forked from coq-community/corn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlagrange.v
4834 lines (4625 loc) · 120 KB
/
lagrange.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Require Import ssreflect CSetoids CSetoidFun
CFields CPolynomials Program
Omega Equivalence Morphisms
Wf Morphisms CRings
CRing_Homomorphisms Rational Setoid
CPoly_NthCoeff CPoly_Degree CReals Intervals
CauchySeq IntervalFunct MoreIntervals
MoreFunctions Composition.
Require Import seq.
Open Scope program_scope.
(**
* The sq(uash) and unsq(uash) tricks are just
* hacks because we are dealing with a flaw in
* the Program Fixpoint construct. Bas and other
* people are working on this. It is assumed that
* this construct will not be required in the
* final version of this proof.
*)
Inductive sq (A : Type) : Prop :=
insq : A -> (sq A).
Axiom unsq : forall A : Type, (sq A) -> A.
(**
* A 'fresh' sequence is a sequence where no two
* elements are the same. Therefore, we know that
* for elements a, b in such a sequence it holds
* that a - b =/= 0. The following section deals
* with fresh sequences.
*)
Section FreshSeq.
Variable A : CSetoid.
(**
* Freshness of a sequence relative to one
* element.
*)
Lemma fresh (s : seq A) : A -> Type.
intro s.
induction s as [a|b s fresh_s].
exact (fun _ => True).
exact (fun a => (b [#] a) and (fresh_s a)).
Defined.
(**
* 'Squashed' version of the freshness property.
* For more information, read the Type vs. Prop
* discussion above.
*)
Definition sqfresh (s : seq A) (a : A) :=
(sq (fresh s a)).
(**
* A fresh sequence is a sequence where every
* two elements lie apart. It is similar to the
* normal sequence type.
*)
Inductive fresh_seq : seq A -> Prop :=
| fresh_nil : fresh_seq nil
| fresh_cons : forall x s,
sqfresh s x -> fresh_seq s ->
fresh_seq (x :: s).
(**
* If we an element a is fresh (relative to a
* sequence s), then a is also fresh relative
* to any subsequence of s.
*)
Lemma take_fresh : forall (n : nat)
(s : seq A) (a : A), fresh s a ->
fresh (take n s) a.
Proof.
intro n; induction n.
intros s a H; rewrite take0; simpl; auto.
intros s a H; destruct s; simpl; auto.
simpl; split.
by inversion H.
apply IHn; by inversion H.
Defined.
(**
* Any subsequence we take from the beginning of a fresh
* sequence is still fresh.
*)
Lemma take_fresh_seq : forall (n : nat)
(s : seq A), fresh_seq s ->
fresh_seq (take n s).
Proof.
intro n; induction n.
intros s H; simpl; rewrite take0; exact fresh_nil.
intros s H; destruct s; simpl; auto.
simpl; apply fresh_cons.
unfold sqfresh; apply insq; apply take_fresh.
apply unsq; by inversion H.
apply IHn; by inversion H.
Defined.
(**
* If an element is fresh with respect to a certain
* sequence, it results in a fresh sequence if we add
* this element to the rear of this sequence.
*)
Lemma rcons_fresh : forall (s : seq A)
(a t : A), fresh (t :: s) a -> fresh (rcons s t) a.
Proof.
intros s a t H; induction s.
simpl; by inversion H.
simpl; inversion H; inversion X0; split.
auto.
apply IHs; simpl; by split.
Defined.
(**
* The inverse of the previous theorem. If an element
* added to the rear of a sequence results in a fresh
* sequence, we might instead add this element in the
* front and still come up with a fresh sequence.
*)
Lemma fresh_rcons : forall (s : seq A)
(a t : A), fresh (rcons s t) a -> fresh (t :: s) a.
Proof.
intros s a t H; induction s.
simpl; by inversion H.
simpl; simpl in H; split.
apply IHs; by inversion H.
split.
by inversion H.
apply IHs; by inversion H.
Defined.
(**
* Freshness remains if we reverse a sequence.
*)
Lemma rev_fresh : forall (s : seq A) (a : A),
fresh s a -> fresh (rev s) a.
Proof.
intros s a H; induction s.
auto.
rewrite rev_cons; apply rcons_fresh; simpl; split.
by inversion H.
apply IHs; by inversion H.
Defined.
(**
* If we have a fresh sequence with one element on front,
* the sequence remains fresh if we add this element to
* the rear.
*)
Lemma rcons_fresh_seq : forall (s : seq A)
(a : A), fresh_seq (a :: s) ->
fresh_seq (rcons s a).
Proof.
intros s a H; induction s.
auto.
simpl; apply fresh_cons.
unfold sqfresh; inversion H; apply insq.
apply rcons_fresh; simpl; unfold sqfresh in H2.
assert (fresh (t :: s) a).
by apply unsq.
inversion X.
split.
algebra.
assert (sq (fresh s t)).
inversion H3; auto.
by apply unsq in H4.
apply IHs; inversion H; apply fresh_cons.
inversion H2; inversion X; unfold sqfresh; by apply insq.
by inversion H3.
Defined.
(**
* If a sequence with a specific element on its rear is
* fresh, the sequence is still fresh if we would have
* added this element in the front.
*)
Lemma fresh_seq_rcons : forall (s : seq A)
(a : A), fresh_seq (rcons s a) ->
fresh_seq (a :: s).
Proof.
intros; induction s. auto.
simpl in H; inversion H; apply fresh_cons.
unfold sqfresh; apply insq.
assert (fresh (a :: s) t); apply fresh_rcons.
unfold sqfresh in H2; by apply unsq in H2.
simpl; simpl in X; inversion X; apply unsq; inversion H.
assert (fresh_seq (a :: s)).
by apply IHs.
apply insq; apply rcons_fresh; simpl; split.
algebra.
apply unsq; inversion H8.
unfold sqfresh in H11; apply unsq in H11; by apply insq.
apply fresh_cons; unfold sqfresh in H2; apply unsq in H2.
apply fresh_rcons in H2; inversion H2; unfold sqfresh.
by apply insq.
assert (fresh_seq (a :: s)).
by apply IHs.
by inversion H4.
Defined.
(**
* If a sequence is fresh, it remains fresh if we completely
* reverse it.
*)
Lemma rev_fresh_seq : forall (s : seq A),
fresh_seq s -> fresh_seq (rev s).
Proof.
intros; induction s. auto.
rewrite rev_cons; apply rcons_fresh_seq; apply fresh_cons.
inversion H; unfold sqfresh; apply insq; apply rev_fresh.
unfold sqfresh in H2; by apply unsq.
apply IHs; by inversion H.
Defined.
Hint Constructors fresh_seq.
End FreshSeq.
(**
* The definitions and lemmas for Newton
* polynomials hold for polynomials over an
* arbitrary field K. We will later confine
* this K to the real numbers R.
*)
Section NewtonPolynomials.
Variable K : CField.
Variable f : K -> K.
(**
* The definition of the divided differences
* follows here. This is the function f [..]
* as described in the paper written by Bas.
* To avoid any confusion, the notation f ()
* is used for the polynomial subject to
* interpolation.
*)
Program Fixpoint dd (s : seq K) (P : fresh_seq K s)
{measure (size s)} : K :=
match s with
| nil => Zero
| (a :: nil) => (f a)
| (a :: b :: s') =>
((dd (a :: s') _) [-] (dd (b :: s') _) [/]
(a [-] b) [//] _)
end.
Next Obligation.
apply fresh_cons; inversion P; inversion H1.
inversion X; unfold sqfresh; by apply insq.
inversion P; by inversion H2.
Qed.
Next Obligation.
by inversion P.
Qed.
Next Obligation.
apply minus_ap_zero; apply unsq; inversion P; inversion H1.
inversion X; apply insq; algebra.
Qed.
(**
* Now that we have solved all obligations for
* the definition of divided differences, we
* continue with our definitions of the functions
* N, alpha and eta.
*)
Variable s : seq K.
Variable k : nat.
Hypothesis fresh_s : fresh_seq K s.
(**
* This definition still uses the bigopsClass, but it will be
* replaced by a fold until the problems in bigopsClass are
* resolved. This definition of eta corresponds to the
* definition of n_j(x) in the paper written by Bas.
*
* TODO: Replace bigopsClass definitions by folds
*)
Require Export bigopsClass.
Definition eta (j : nat) : cpoly_cring K :=
\big[(cpoly_mult_cs K)/(cpoly_one K)]_(x_i <- take j s)
(cpoly_linear _ ([--] x_i) (cpoly_one _)).
(**
* This definition corresponds to the definition of a_j in
* the paper. It is basically a direct call to the definition
* of divided differences using the vector x_j, ..., x_0.
*)
Definition alpha (j : nat) : K :=
dd (rev (take (j + 1) s))
((rev_fresh_seq K (take (j + 1) s))
(take_fresh_seq K (j + 1) s fresh_s)).
(**
* This is the definition of N from the paper. The mkseq
* construct creates an increasing sequence.
*
* TODO: Replace bigopsClass definitions by folds.
*)
Definition N : cpoly_cring K :=
\big[cpoly_plus_cs K/(cpoly_zero K)]_(j <-
(mkseq (fun x => x) (k + 1)) | (fun x => true) j)
(_C_ (alpha j) [*] (eta j)).
End NewtonPolynomials.
Section BigopsTheory.
Variable K : CField.
Variable f : K -> K.
(**
* This is proof independence of divided differences with
* respect to freshness.
*)
Lemma dd_indep : forall (l1 l2 : seq K) (P1 : fresh_seq K l1)
(P2 : fresh_seq K l2), l1 = l2 ->
dd K f l1 P1 [=] dd K f l2 P2.
Proof.
intros.
unfold dd.
replace (existT (fun s : seq K => fresh_seq K s) l2 P2) with
(existT (fun s : seq K => fresh_seq K s) l1 P1).
reflexivity.
by apply subsetT_eq_compat.
Qed.
(**
* Equality of CPolynomials over a field K is reflexive,
* symmetric and transitive according to the following
* three type class instances.
*)
Instance cpoly_eq_refl : Reflexive (cpoly_eq K).
unfold Reflexive; by reflexivity. Qed.
Instance cpoly_eq_symm : Symmetric (cpoly_eq K).
unfold Symmetric; by symmetry. Qed.
Instance cpoly_eq_trans : Transitive (cpoly_eq K).
unfold Transitive; intros x y z; by transitivity y. Qed.
Instance eqv_cpoly : Equivalence (cpoly_eq K).
Instance eqv_K : Equivalence (@st_eq K).
(**
* TODO: This definition is not required because we have
* an equivalent construct in the type class system.
*)
Add Parametric Relation : (cpoly_cring K) (cpoly_eq K)
reflexivity proved by cpoly_eq_refl
symmetry proved by cpoly_eq_symm
transitivity proved by cpoly_eq_trans
as cpeq.
(**
* This is meant to prove that addition of polynomials
* is a morphism with respect to equality. However, I
* cannot complete the proof because it somehow seems
* that this exact morphism is required to finish the
* proof.
*
* TODO: Fix this proof.
*)
Instance morph_cpoly : Proper ((cpoly_eq K) ==> (cpoly_eq K) ==>
(cpoly_eq K)) (cpoly_plus_cs K).
Admitted.
(**
* Multiplication of polynomials is also a morphism with
* respect to equality. However, the same problem as in
* the previous proof arises here.
*
* TODO: Complete this proof.
*)
Instance morph_cpoly_mult : Proper ((cpoly_eq K) ==> (cpoly_eq K) ==>
(cpoly_eq K)) (cpoly_mult_cs K).
Admitted.
(**
* Multiplication in an arbitrary field K is a morphism with
* respect to the standard equality defined in K.
*
* TODO: Are definitions like these really required? Aren't
* they already defined in the CoRN libraries?
*)
Instance morph_K_mult : Proper ((@st_eq K) ==> (@st_eq K) ==> (@st_eq K))
cr_mult.
unfold Proper; unfold respectful.
intros x y H x0 y0 H0; rewrite H H0; reflexivity.
Qed.
(**
* Addition in a field K is a morphism with respect to the
* standard equality defined on K.
*)
Instance morph_K_plus : Proper ((@st_eq K) ==> (@st_eq K) ==> (@st_eq K))
csg_op.
unfold Proper; unfold respectful.
intros x y H x0 y0 H0; rewrite H H0; reflexivity.
Qed.
(**
* Addition of polynomials is associative.
*
* TODO: As OperationClasses is no longer compiling, this
* has to be replaced with another construct.
*)
Instance assoc_cpoly : @OperationClasses.associative (cpoly_cring K)
(cpoly_eq K) eqv_cpoly (cpoly_plus_cs K).
unfold OperationClasses.associative.
intros x y z; red.
set cpoly_plus_associative.
unfold associative in a; simpl in a; apply a.
Qed.
(**
* Multiplication of polynomials is associatve.
*
* TODO: Fix usage of OperationClasses.
*)
Instance assoc_cpoly_mult : @OperationClasses.associative (cpoly_cring K)
(cpoly_eq K) eqv_cpoly (cpoly_mult_cs K).
unfold OperationClasses.associative.
intros x y z; red.
set cpoly_mult_assoc.
unfold associative in a; simpl in a; apply a.
Qed.
(**
* Multiplication is associative in any field K
*
* TODO: This should be replaced by a standard lemma from
* the CoRN libraries.
*)
Instance assoc_K_mult : @OperationClasses.associative K
(@st_eq K) eqv_K cr_mult.
unfold OperationClasses.associative.
intros x y z; red; algebra.
Qed.
(**
* Addition is associative in any field K
*
* TODO: This is very probably already somewhere in the
* libraries.
*)
Instance assoc_K_plus : @OperationClasses.associative K
(@st_eq K) eqv_K csg_op.
unfold OperationClasses.associative.
intros x y z; red; algebra.
Qed.
(**
* The zero-polynomial is a left-unit element with respect
* to addition.
*
* TODO: Fix OperationClasses usage.
*)
Instance left_unit_cpoly : @OperationClasses.left_unit (cpoly_cring K)
(cpoly_eq K) eqv_cpoly (cpoly_plus_cs K) (cpoly_zero K).
intro x; red.
simpl; reflexivity.
Qed.
(**
* The one-polynomial is a left-unit element with respect
* to multiplication.
*
* TODO: Fix OperationClasses usage.
*)
Instance left_unit_cpoly_mult : @OperationClasses.left_unit (cpoly_cring K)
(cpoly_eq K) eqv_cpoly (cpoly_mult_cs K) (cpoly_one K).
intro x; red.
rewrite cpoly_mult_commutative.
rewrite cpoly_mult_one.
reflexivity.
Qed.
(**
* TODO: Deprecated, do not use OperationClasses.
*)
Instance left_unit_K_mult : @OperationClasses.left_unit K
(@st_eq K) eqv_K cr_mult (One:K).
intro x; red; algebra.
Qed.
(**
* TODO: Deprecated, do not use Operationclasses.
*)
Instance left_unit_K_plus : @OperationClasses.left_unit K
(@st_eq K) eqv_K csg_op (Zero:K).
intro x; red; algebra.
Qed.
(**
* The zero-polynomial is a right-unit element with respect
* to to addition of polynomials.
*
* TODO: Get rid of OperationClasses code.
*)
Instance right_unit_cpoly : @OperationClasses.right_unit (cpoly_cring K)
(cpoly_eq K) eqv_cpoly (cpoly_plus_cs K) (cpoly_zero K).
intro x; red.
rewrite cpoly_plus_commutative; simpl; reflexivity.
Qed.
(**
* The one-polynomial is a right-unit element with respect
* to multiplication of polynomials.
*
* TODO: Get rid of OperationClasses code.
*)
Instance right_unit_cpoly_mult : @OperationClasses.right_unit (cpoly_cring K)
(cpoly_eq K) eqv_cpoly (cpoly_mult_cs K) (cpoly_one K).
intro x; red.
rewrite cpoly_mult_one; reflexivity.
Qed.
(**
* TODO: Deprecated, do not use OperationClasses code.
*)
Instance right_unit_K_mult : @OperationClasses.right_unit K
(@st_eq K) eqv_K cr_mult (One:K).
intro x; red; algebra.
Qed.
(**
* TODO: Deprecated, do not use OperationClasses code.
*)
Instance right_unit_K_plus : @OperationClasses.right_unit K
(@st_eq K) eqv_K csg_op (Zero:K).
intro x; red; algebra.
Qed.
(**
* Application of polynomials (over K) is a morphism with
* respect to the standard equality defined on K.
*
* TODO: Fix this proof. To be honest, I have no clue why
* this cannot be done. Will take a look at it later.
*)
Add Parametric Morphism : (@cpoly_apply K) with
signature (@cpoly_eq K) ==> (@st_eq K) ==> (@st_eq K) as cpoly_apply_mor.
Admitted.
(**
* Multiplication of polynomials is a morphism with respect
* to the equality defined on polynomials.
*
* TODO: Replace with type class instance.
*)
Add Parametric Morphism : (@cpoly_mult_cs K) with
signature (@cpoly_eq K) ==> (@cpoly_eq K) ==> (@cpoly_eq K) as cpoly_mult_mor.
intros x y H x0 y0 H0.
rewrite H; rewrite H0; reflexivity.
Qed.
(**
* TODO: Replace with type class instance.
*)
Add Parametric Morphism : (@polyconst K) with
signature (@st_eq K) ==> (@cpoly_eq K) as cpoly_const_mor.
intros x y H; rewrite H; reflexivity.
Qed.
(**
* Multiplication of a polynomial (over any field K) and an
* element from K is invariant under both equality over poly(K)
* and K.
*
* TODO: Fix this proof. Seems to mutually depend on a previous
* morphism for polynomial-multiplication.
*)
Add Parametric Morphism : (@cpoly_mult_cr_cs K) with
signature (@cpoly_eq K) ==> (@st_eq K) ==> (cpoly_eq K) as cpoly_mult_cr_mor.
intros x y H x0 y0 H0.
Admitted.
(**
* TODO: Replace with corresponding type class instance.
*)
Add Parametric Morphism : (@cg_minus K) with
signature (@st_eq K) ==> (@st_eq K) ==> (@st_eq K) as cg_minus_mor.
intros x y H x0 y0 H0; rewrite H; rewrite H0; reflexivity.
Qed.
(**
* Getting the nth coefficient of a polynomial is a morphism
* with respect to equality over nat.
*
* TODO: Fix this proof. Should not be very difficult. Will
* take a look at it later.
*)
Add Parametric Morphism : (@nth_coeff K) with
signature (@eq nat) ==> (@cpoly_eq K) ==> (@st_eq K) as nth_coeff_mor.
intros y x y0 H.
Admitted.
(**
* TODO: Replace with corresponding type class instance
*)
Add Parametric Morphism : (@csg_op K) with
signature (@st_eq K) ==> (@st_eq K) ==> (@st_eq K) as csg_op_mor.
intros x y H x0 y0 H0; rewrite H H0; reflexivity.
Qed.
(**
* TODO: Replace with corresponding type class instance
*)
Add Parametric Morphism : (@cg_inv K) with
signature (@st_eq K) ==> (@st_eq K) as cg_inv_mor.
intros x y H; rewrite H; reflexivity.
Qed.
(**
* The equality on K can be continued to an equality on
* polynomials. However, it was not immediately clear how
* to prove this.
*
* TODO: Replace with corresponding definition from the
* CoRN libraries.
*)
Add Parametric Morphism : (@cpoly_linear K) with
signature (@st_eq K) ==> (@cpoly_eq K) ==> (@cpoly_eq K) as cpoly_lin_mor.
intros x y H x0 y0 H0.
Admitted.
(**
* I have not been able to get rings to work for polynomials.
*
* TODO: Fix this because it makes many proofs easier to
* understand.
*
* Add Ring cpolyk_th : (CRing_Ring (cpoly_cring K)).
* Add Ring cring_K : (CRing_Ring K).
*
*)
(**
* If a bigops-expression results in a polynomial, and if
* this expression is therefore applied to a particular
* value, the application results in the same value as if
* the application was done inside the bigops-expression.
*
* TODO: This should be more general.
* TODO: Replace the bigops expression with a corresponding
* fold.
*)
Lemma apply_bigops : forall (r : seq K) F x,
(\big[cpoly_mult_cs K/cpoly_one K]_(i <- r) F i) ! x [=]
\big[cr_mult/(One:K)]_(i <- r) ((F i) ! x).
Proof.
intros r F x; destruct r; simpl.
rewrite cring_mult_zero; algebra.
induction r.
simpl; rewrite mult_one; rewrite cpoly_mult_one.
reflexivity.
repeat rewrite big_cons; simpl in IHr; rewrite mult_assoc.
rewrite (mult_commutes K (cpoly_apply K (F s) x)
(cpoly_apply K (F t) x)).
rewrite <- mult_assoc; rewrite <- IHr.
set (@mult_apply); simpl in s0; rewrite <- s0.
rewrite cpoly_mult_fast_equiv.
set (@cpoly_mult_assoc); unfold CSetoids.associative in a.
simpl in a; repeat rewrite a.
rewrite (cpoly_mult_commutative K (F s) (F t)).
reflexivity.
Qed.
(**
* If we take a subsequence from (the start of)
* another sequence, it does not matter if this
* sequence was already the result of a 'take' operation.
*)
Lemma take_nest_redun : forall (n m : nat)
(s : seq K), m <= n -> m <= size s ->
take m (take n s) = take m s.
Proof.
intro n; induction n.
intros m s H H0; rewrite take0; inversion H.
repeat rewrite take0; reflexivity.
intros m s H H0. destruct s. simpl; reflexivity.
assert (take (S n) (s :: s0) = s :: take n s0) by auto.
rewrite H1; destruct m. simpl; reflexivity.
simpl; rewrite IHn. reflexivity. omega.
inversion H0. auto. omega.
Qed.
(**
* This lemma effectively says that:
*
* x_0, x_1, ..., x_(k+1) = x_0, x_1, ..., x_i, x_(i+1),
* ..., x_(k+1)
*
* TODO: Perhaps all these takes, nths and drops can be
* set up a bit more clearer.
*)
Lemma take_nth_drop : forall (i k : nat) (s : seq K),
i <= k -> k < size s ->
take (S k) s = take i s ++ (nth Zero s i) ::
(take (k - i) (drop (i + 1) s)).
Proof.
intro i; induction i.
intros k s H H0; destruct s.
inversion H0; simpl.
replace (k - 0) with k by omega; simpl.
rewrite drop0; reflexivity.
intros k s H H0; destruct s.
inversion H0; simpl.
replace (k - S i) with ((k - 1) - i) by omega.
simpl; rewrite <- IHi.
replace (S (k - 1)) with k by omega; reflexivity.
omega. inversion H0.
assert (1 <= k) by omega; omega.
assert (1 <= k) by omega; omega.
Qed.
(**
* This lemma asserts that the repeated multiplication
* of an expression (-x_i) + x_i is equal to zero.
*)
Lemma lem11a : forall i s k,
size s > 1 -> k < size s -> i <= k ->
\big[cr_mult/(One:K)]_(x_i <- take (S k) s)
(cpoly_linear K [--]x_i (cpoly_one K)) ! (nth Zero s i) [=] Zero.
Proof.
intros.
rewrite (@eq_big_idx_seq K (@st_eq K)
eqv_K (cr_mult) (One:K) morph_K_mult
right_unit_K_mult (One:K) K
(take (S k) s) _
(fun x : K => (cpoly_linear K [--]x (cpoly_one K)) !
(nth Zero s i)) right_unit_K_mult).
assert (take (S k) s = (take i s) ++ ((nth Zero s i) ::
(take (k - i) (drop (i + 1) s)))).
apply take_nth_drop.
omega.
exact H0.
rewrite H2.
rewrite (@big_cat K (@st_eq K) eqv_K
cr_mult (One:K) morph_K_mult
assoc_K_mult left_unit_K_mult
K (take i s) (nth Zero s i :: take (k - i) (drop (i + 1) s))
(fun x : K => true)).
rewrite big_cons.
assert ((cpoly_linear K [--](nth Zero s i) (cpoly_one K)) !
(nth Zero s i) [=] Zero).
simpl.
rewrite cring_mult_zero.
rewrite cm_rht_unit_unfolded.
rewrite mult_one.
rewrite cg_lft_inv_unfolded.
reflexivity.
rewrite H3.
rewrite mult_assoc.
rewrite cring_mult_zero.
rewrite mult_commutes.
rewrite cring_mult_zero.
reflexivity.
destruct s.
inversion H.
simpl; auto.
Qed.
(**
* If we have a fresh sequence s, it is clear that the kth
* element is fresh with respect to a subsequence of s.
*)
Lemma nth_fresh : forall (s : seq K) (k c : nat),
k < size s -> fresh_seq K s ->
fresh K (take (k - c) s) (nth Zero s k).
Proof.
intros.
induction c.
assert (k - 0 = k) by omega.
rewrite H1.
assert (fresh_seq K (take (k + 1) s)).
apply take_fresh_seq.
exact H0.
cut (take (k + 1) s = take k s ++ [:: nth Zero s k]).
intro.
rewrite H3 in H2.
assert (fresh_seq K ((nth Zero s k) ::
take k s)).
apply fresh_seq_rcons.
rewrite <- cat_rcons in H2.
rewrite cats0 in H2.
exact H2.
apply unsq.
inversion H4.
unfold sqfresh in H7.
exact H7.
rewrite <- cat_rcons.
rewrite cats0.
rewrite <- take_nth.
replace (S k) with (k + 1) by omega.
reflexivity.
apply (ssrbool.introT (P := S k <= size s)).
apply ssrnat.leP.
omega.
cut (take (k - S c) s = take (k - S c)
(take (k - c) s)).
intro.
rewrite H1.
apply take_fresh.
exact IHc.
rewrite take_nest_redun.
reflexivity.
omega.
omega.
Qed.
(**
* If a sequence of elements is fresh, than any two
* elements from this sequence lie apart. This is not
* immediately clear from the definition (although it
* seems so) because of difficulty with the definition
* of nth.
*
* TODO: This proof can be made a bit shorter.
*)
Lemma ap_fresh_nth : forall (s : seq K)
(k c : nat), 0 < k -> c < k -> k < size s ->
fresh_seq K s ->
(nth Zero s k) [-] (nth Zero s (k - S c)) [#] Zero.
Proof.
intros.
apply minus_ap_zero.
assert (fresh K (take (k - c) s) (nth Zero s k)).
apply nth_fresh.
exact H1.
exact H2.
assert (take (k - c) s = take (k - S c) s ++
[:: nth Zero s (k - S c)]).
rewrite <- cat_rcons.
rewrite <- take_nth.
replace (S (k - S c)) with (k - c) by omega.
rewrite cats0.
reflexivity.
apply (ssrbool.introT (P := S (k - S c) <= size s)).
apply ssrnat.leP.
omega.
rewrite H3 in X.
rewrite <- cat_rcons in X.
rewrite cats0 in X.
apply fresh_rcons in X.
inversion X.
algebra.
Qed.
(**
* This lemma is essentially a one-step reduction in the
* definition of divided differences. However, it is not
* as straightforwardly provable as it might seem.
*
* TODO: Fix this proof.
*)
Lemma dd_reduce : forall (s : seq K) (a b : K)
(P1 : fresh_seq K (a :: b :: s))
(P2 : fresh_seq K (a :: s))
(P3 : fresh_seq K (b :: s))
(P4 : a [-] b [#] Zero),
(dd K f (a :: b :: s) P1) =
(((dd K f (a :: s) P2) [-] (dd K f (b :: s) P3))
[/] (a [-] b) [//] P4).
Proof.
intros.
Admitted.
(**
* This rather complicated lemma states that if we have a
* one-step reduction for divided differences, we also have
* an n-step reduction according to a specific pattern.
*
* TODO: This lemma is very unreadable. Perhaps this can be
* made more clear using appropriate syntax elements.
*)
Lemma dd_reduce_nth : forall (s : seq K) (k c : nat)
(P : fresh_seq K
(nth Zero s k :: rev (take (k - c) s)))
(Q : fresh_seq K
(nth Zero s k :: rev (take (k - S c) s)))
(R : fresh_seq K (rev (take (k - c) s)))
(X : (nth Zero s k) [-] (nth Zero s (k - S c))
[#] Zero),
0 < k -> c < k -> k < size s -> fresh_seq K s ->
(dd K f (nth Zero s k :: rev (take (k - c) s)) P) [=]
((dd K f (nth Zero s k :: rev (take (k - S c) s)) Q)[-]
(dd K f (rev (take (k - c) s)) R)[/]
(nth Zero s k[-]nth Zero s (k - S c))[//]X).
Proof.
intros.
assert (fresh_seq K
(nth Zero s k :: nth Zero s (k - S c) ::
rev (take (k - S c) s))).
apply fresh_cons.
unfold sqfresh.
apply insq.
simpl.
split.
apply zero_minus_apart.
algebra.
apply rev_fresh.
apply nth_fresh.
exact H1.
exact H2.
apply fresh_cons.
unfold sqfresh.
apply insq.
assert (forall k, k < size s ->
fresh K (rev (take k s))
(nth Zero s k)).
intros.
apply rev_fresh.
assert (take k0 s = take (k0 - 0) s).
replace (k0 - 0) with k0 by omega; reflexivity.
rewrite H4.
apply nth_fresh.
exact H3.
exact H2.
apply X0.
omega.
apply rev_fresh_seq.
apply take_fresh_seq.
exact H2.
assert (rev (take (k - c) s) =
nth Zero s (k - S c) :: rev (take (k - S c) s)).
assert (k - c = (S (k - S c))) by omega.
rewrite H4.
set (@take_nth).
rewrite (@take_nth K Zero (k - S c) s).
rewrite rev_rcons; reflexivity.
apply (ssrbool.introT (P := S (k - S c) <= size s)).
apply ssrnat.leP.
omega.
assert ((dd K f (nth Zero s k :: rev (take (k - c) s)) P) [=]
(dd K f [:: nth Zero s k, nth Zero s (k - S c) &
rev (take (k - S c) s)] H3)).
apply dd_indep.
rewrite H4; reflexivity.
rewrite H5.
assert (fresh_seq K ((nth Zero s (k - S c)) ::
rev (take (k - S c) s))).
inversion H3.
exact H9.
assert ((dd K f (rev (take (k - c) s)) R) [=]
(dd K f (nth Zero s (k - S c) :: rev (take (k - S c) s)) H6)).
apply dd_indep.
rewrite H4; reflexivity.
unfold cf_div.
rewrite H7.
set (dd_reduce (rev (take (k - S c) s))
(nth Zero s k) (nth Zero s (k - S c))
H3 Q H6 X).
unfold cf_div in e.
rewrite e.
reflexivity.
Qed.
(**
* The Newton polynomial coincides with the Lagrange
* polynomial. This lemma essentially proves this.
*
* TODO: Replace bigopsClass operators with corresponding
* folds.
*)
Lemma lem11b : forall (k c : nat) (s : seq K)
(Q : fresh_seq K s)
(R : fresh_seq K ((nth Zero s k) ::
(rev (take (k - c) s)))),
0 < k -> c <= k -> k < size s ->
(N K f s k Q) ! (nth Zero s k) [=]
(\big[(cpoly_plus_cs K)/(cpoly_zero K)]_(j <- (mkseq (fun x => x) (k - c)) | (fun x => true) j)
(_C_ (alpha K f s Q j) [*] (eta K s j)))
! (nth Zero s k) [+]
(dd K f ((nth Zero s k) ::
(rev (take (k - c) s))) R) [*]
(eta K s (k - c)) ! (nth Zero s k).
Proof.
intros.
induction c.
assert (k - 0 = k) by omega.
assert (mkseq ssrfun.id (k - 0) =
mkseq ssrfun.id k).
rewrite H2; reflexivity.
rewrite H3.
clear H2 H3.
assert (fresh_seq K (rev (take k s))).
apply rev_fresh_seq.
apply take_fresh_seq.
exact Q.
assert (dd K f (nth Zero s k ::
rev (take (k - 0) s)) R [=]