1 (**************************************************************************)
4 (* ||A|| A project by Andrea Asperti *)
6 (* ||I|| Developers: *)
7 (* ||T|| The HELM team. *)
8 (* ||A|| http://helm.cs.unibo.it *)
10 (* \ / This file is distributed under the terms of the *)
11 (* v GNU General Public License Version 2 *)
13 (**************************************************************************)
15 set "baseuri" "cic:/matita/nat/generic_iter_p".
17 include "nat/div_and_mod_diseq.ma".
18 include "nat/primes.ma".
21 (*a generic definition of summatory indexed over natural numbers:
22 * n:N is the advanced end in the range of the sommatory
23 * p: N -> bool is a predicate. if (p i) = true, then (g i) is summed, else it isn't
24 * A is the type of the elements of the sum.
25 * g:nat -> A, is the function which associates the nth element of the sum to the nth natural numbers
26 * baseA (of type A) is the neutral element of A for plusA operation
27 * plusA: A -> A -> A is the sum over elements in A.
30 let rec iter_p_gen (n:nat) (p: nat \to bool) (A:Type) (g: nat \to A)
31 (baseA: A) (plusA: A \to A \to A) \def
36 [true \Rightarrow (plusA (g k) (iter_p_gen k p A g baseA plusA))
37 |false \Rightarrow iter_p_gen k p A g baseA plusA]
40 theorem true_to_iter_p_gen_Sn:
41 \forall n:nat. \forall p:nat \to bool. \forall A:Type. \forall g:nat \to A.
42 \forall baseA:A. \forall plusA: A \to A \to A.
43 p n = true \to iter_p_gen (S n) p A g baseA plusA =
44 (plusA (g n) (iter_p_gen n p A g baseA plusA)).
51 theorem false_to_iter_p_gen_Sn:
52 \forall n:nat. \forall p:nat \to bool. \forall A:Type. \forall g:nat \to A.
53 \forall baseA:A. \forall plusA: A \to A \to A.
54 p n = false \to iter_p_gen (S n) p A g baseA plusA = iter_p_gen n p A g baseA plusA.
61 theorem eq_iter_p_gen: \forall p1,p2:nat \to bool. \forall A:Type.
62 \forall g1,g2: nat \to A. \forall baseA: A.
63 \forall plusA: A \to A \to A. \forall n:nat.
64 (\forall x. x < n \to p1 x = p2 x) \to
65 (\forall x. x < n \to g1 x = g2 x) \to
66 iter_p_gen n p1 A g1 baseA plusA = iter_p_gen n p2 A g2 baseA plusA.
70 | apply (bool_elim ? (p1 n1))
72 rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H3).
73 rewrite > true_to_iter_p_gen_Sn
75 [ apply H2.apply le_n.
77 [ intros.apply H1.apply le_S.assumption
78 | intros.apply H2.apply le_S.assumption
81 | rewrite < H3.apply sym_eq.apply H1.apply le_n
84 rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H3).
85 rewrite > false_to_iter_p_gen_Sn
87 [ intros.apply H1.apply le_S.assumption
88 | intros.apply H2.apply le_S.assumption
90 | rewrite < H3.apply sym_eq.apply H1.apply le_n
96 theorem eq_iter_p_gen1: \forall p1,p2:nat \to bool. \forall A:Type.
97 \forall g1,g2: nat \to A. \forall baseA: A.
98 \forall plusA: A \to A \to A.\forall n:nat.
99 (\forall x. x < n \to p1 x = p2 x) \to
100 (\forall x. x < n \to p1 x = true \to g1 x = g2 x) \to
101 iter_p_gen n p1 A g1 baseA plusA = iter_p_gen n p2 A g2 baseA plusA.
105 | apply (bool_elim ? (p1 n1))
107 rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H3).
108 rewrite > true_to_iter_p_gen_Sn
115 [ intros.apply H1.apply le_S.assumption
117 [ apply le_S.assumption
123 apply sym_eq.apply H1.apply le_n
126 rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H3).
127 rewrite > false_to_iter_p_gen_Sn
129 [ intros.apply H1.apply le_S.assumption
131 [ apply le_S.assumption
135 | rewrite < H3.apply sym_eq.
142 theorem iter_p_gen_false: \forall A:Type. \forall g: nat \to A. \forall baseA:A.
143 \forall plusA: A \to A \to A. \forall n.
144 iter_p_gen n (\lambda x.false) A g baseA plusA = baseA.
153 theorem iter_p_gen_plusA: \forall A:Type. \forall n,k:nat.\forall p:nat \to bool.
154 \forall g: nat \to A. \forall baseA:A. \forall plusA: A \to A \to A.
155 (symmetric A plusA) \to (\forall a:A. (plusA a baseA) = a) \to (associative A plusA)
157 iter_p_gen (k + n) p A g baseA plusA
158 = (plusA (iter_p_gen k (\lambda x.p (x+n)) A (\lambda x.g (x+n)) baseA plusA)
159 (iter_p_gen n p A g baseA plusA)).
163 [ rewrite < (plus_n_O n).
165 rewrite > H in \vdash (? ? ? %).
168 | apply (bool_elim ? (p (n1+n)))
170 rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
171 rewrite > (true_to_iter_p_gen_Sn n1 (\lambda x.p (x+n)) ? ? ? ? H4).
172 rewrite > (H2 (g (n1 + n)) ? ?).
176 rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
177 rewrite > (false_to_iter_p_gen_Sn n1 (\lambda x.p (x+n)) ? ? ? ? H4).
183 theorem false_to_eq_iter_p_gen: \forall A:Type. \forall n,m:nat.\forall p:nat \to bool.
184 \forall g: nat \to A. \forall baseA:A. \forall plusA: A \to A \to A.
185 n \le m \to (\forall i:nat. n \le i \to i < m \to p i = false)
186 \to iter_p_gen m p A g baseA plusA = iter_p_gen n p A g baseA plusA.
206 (* a therem slightly more general than the previous one *)
207 theorem or_false_eq_baseA_to_eq_iter_p_gen: \forall A:Type. \forall n,m:nat.\forall p:nat \to bool.
208 \forall g: nat \to A. \forall baseA:A. \forall plusA: A \to A \to A.
209 (\forall a. plusA baseA a = a) \to
210 n \le m \to (\forall i:nat. n \le i \to i < m \to p i = false \lor g i = baseA)
211 \to iter_p_gen m p A g baseA plusA = iter_p_gen n p A g baseA plusA.
215 |apply (bool_elim ? (p n1));intro
218 apply not_eq_true_false.
222 |rewrite > true_to_iter_p_gen_Sn
228 |apply le_S.assumption
235 |rewrite > false_to_iter_p_gen_Sn
239 |apply le_S.assumption
247 theorem iter_p_gen2 :
249 \forall p1,p2:nat \to bool.
251 \forall g: nat \to nat \to A.
253 \forall plusA: A \to A \to A.
254 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a baseA) = a)
257 (\lambda x.andb (p1 (div x m)) (p2 (mod x m)))
259 (\lambda x.g (div x m) (mod x m))
263 (\lambda x.iter_p_gen m p2 A (g x) baseA plusA)
269 | apply (bool_elim ? (p1 n1))
271 rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
272 simplify in \vdash (? ? (? % ? ? ? ? ?) ?).
273 rewrite > iter_p_gen_plusA
276 [ apply eq_iter_p_gen
279 rewrite > (div_plus_times ? ? ? H5).
280 rewrite > (mod_plus_times ? ? ? H5).
286 rewrite > (div_plus_times ? ? ? H5).
287 rewrite > (mod_plus_times ? ? ? H5).
289 simplify.reflexivity.
298 rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
299 simplify in \vdash (? ? (? % ? ? ? ? ?) ?).
300 rewrite > iter_p_gen_plusA
302 apply (trans_eq ? ? (plusA baseA
303 (iter_p_gen n1 p1 A (\lambda x:nat.iter_p_gen m p2 A (g x) baseA plusA) baseA plusA )))
305 [ rewrite > (eq_iter_p_gen ? (\lambda x.false) A ? (\lambda x:nat.g ((x+n1*m)/m) ((x+n1*m)\mod m)))
306 [ apply iter_p_gen_false
309 rewrite > (div_plus_times ? ? ? H5).
310 rewrite > (mod_plus_times ? ? ? H5).
313 | intros.reflexivity.
329 theorem iter_p_gen2':
331 \forall p1: nat \to bool.
332 \forall p2: nat \to nat \to bool.
334 \forall g: nat \to nat \to A.
336 \forall plusA: A \to A \to A.
337 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a baseA) = a)
340 (\lambda x.andb (p1 (div x m)) (p2 (div x m)(mod x m)))
342 (\lambda x.g (div x m) (mod x m))
346 (\lambda x.iter_p_gen m (p2 x) A (g x) baseA plusA)
352 | apply (bool_elim ? (p1 n1))
354 rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
355 simplify in \vdash (? ? (? % ? ? ? ? ?) ?).
356 rewrite > iter_p_gen_plusA
359 [ apply eq_iter_p_gen
362 rewrite > (div_plus_times ? ? ? H5).
363 rewrite > (mod_plus_times ? ? ? H5).
369 rewrite > (div_plus_times ? ? ? H5).
370 rewrite > (mod_plus_times ? ? ? H5).
372 simplify.reflexivity.
381 rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
382 simplify in \vdash (? ? (? % ? ? ? ? ?) ?).
383 rewrite > iter_p_gen_plusA
385 apply (trans_eq ? ? (plusA baseA
386 (iter_p_gen n1 p1 A (\lambda x:nat.iter_p_gen m (p2 x) A (g x) baseA plusA) baseA plusA )))
388 [ rewrite > (eq_iter_p_gen ? (\lambda x.false) A ? (\lambda x:nat.g ((x+n1*m)/m) ((x+n1*m)\mod m)))
389 [ apply iter_p_gen_false
392 rewrite > (div_plus_times ? ? ? H5).
393 rewrite > (mod_plus_times ? ? ? H5).
396 | intros.reflexivity.
414 \forall g: nat \to A.
416 \forall plusA: A \to A \to A.
418 \forall p:nat \to bool.
419 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a baseA) = a)
422 i < n \to p i = true \to
423 (iter_p_gen n p A g baseA plusA) =
424 (plusA (g i) (iter_p_gen n (\lambda x:nat. andb (p x) (notb (eqb x i))) A g baseA plusA)).
428 apply (not_le_Sn_O i).
430 | apply (bool_elim ? (p n1));intro
431 [ elim (le_to_or_lt_eq i n1)
432 [ rewrite > true_to_iter_p_gen_Sn
433 [ rewrite > true_to_iter_p_gen_Sn
434 [ rewrite < (H2 (g i) ? ?).
435 rewrite > (H1 (g i) (g n1)).
436 rewrite > (H2 (g n1) ? ?).
447 | rewrite > H6.simplify.
448 change with (notb (eqb n1 i) = notb false).
450 apply not_eq_to_eqb_false.
452 apply (lt_to_not_eq ? ? H7).
453 apply sym_eq.assumption
457 | rewrite > true_to_iter_p_gen_Sn
461 | rewrite > false_to_iter_p_gen_Sn
462 [ apply eq_iter_p_gen
466 change with (notb false = notb (eqb x n1)).
469 apply not_eq_to_eqb_false.
470 apply (lt_to_not_eq ? ? H8)
477 rewrite > (eq_to_eqb_true ? ? (refl_eq ? n1)).
483 | apply le_S_S_to_le.
486 | rewrite > false_to_iter_p_gen_Sn
487 [ elim (le_to_or_lt_eq i n1)
488 [ rewrite > false_to_iter_p_gen_Sn
496 | rewrite > H6.reflexivity
499 apply not_eq_true_false.
503 | apply le_S_S_to_le.
512 (* invariance under permutation; single sum *)
513 theorem eq_iter_p_gen_gh:
516 \forall plusA: A \to A \to A.
517 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a baseA) = a) \to
518 \forall g: nat \to A.
519 \forall h,h1: nat \to nat.
521 \forall p1,p2:nat \to bool.
522 (\forall i. i < n \to p1 i = true \to p2 (h i) = true) \to
523 (\forall i. i < n \to p1 i = true \to h1 (h i) = i) \to
524 (\forall i. i < n \to p1 i = true \to h i < n1) \to
525 (\forall j. j < n1 \to p2 j = true \to p1 (h1 j) = true) \to
526 (\forall j. j < n1 \to p2 j = true \to h (h1 j) = j) \to
527 (\forall j. j < n1 \to p2 j = true \to h1 j < n) \to
529 iter_p_gen n p1 A (\lambda x.g(h x)) baseA plusA =
530 iter_p_gen n1 p2 A g baseA plusA.
533 [ generalize in match H8.
536 | apply (bool_elim ? (p2 n2));intro
538 apply (not_le_Sn_O (h1 n2)).
543 | rewrite > false_to_iter_p_gen_Sn
555 | apply (bool_elim ? (p1 n1));intro
556 [ rewrite > true_to_iter_p_gen_Sn
557 [ rewrite > (iter_p_gen_gi A g baseA plusA n2 (h n1))
564 change with ((\not eqb (h i) (h n1))= \not false).
566 apply not_eq_to_eqb_false.
569 apply (lt_to_not_eq ? ? H11).
581 | apply le_S.assumption
592 [ apply le_S.assumption
598 | generalize in match H12.
607 | generalize in match H12.
614 elim (le_to_or_lt_eq (h1 j) n1)
616 | generalize in match H12.
626 | apply eqb_false_to_not_eq.
627 generalize in match H14.
629 [ apply sym_eq.assumption
635 apply not_eq_true_false.
636 apply sym_eq.assumption
638 | apply le_S_S_to_le.
641 | generalize in match H12.
664 | rewrite > false_to_iter_p_gen_Sn
667 apply H4[apply le_S.assumption|assumption]
669 apply H5[apply le_S.assumption|assumption]
671 apply H6[apply le_S.assumption|assumption]
673 apply H7[assumption|assumption]
675 apply H8[assumption|assumption]
677 elim (le_to_or_lt_eq (h1 j) n1)
679 | absurd (j = (h n1))
687 apply not_eq_true_false.
696 | apply le_S_S_to_le.
709 theorem eq_iter_p_gen_pred:
712 \forall plusA: A \to A \to A.
715 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a baseA) = a) \to
716 iter_p_gen (S n) (\lambda i.p (pred i)) A (\lambda i.g(pred i)) baseA plusA =
717 plusA (iter_p_gen n p A g baseA plusA) (g O).
720 [rewrite > true_to_iter_p_gen_Sn
724 |apply (bool_elim ? (p n1));intro
725 [rewrite > true_to_iter_p_gen_Sn
726 [rewrite > true_to_iter_p_gen_Sn in ⊢ (? ? ? %)
727 [rewrite > H2 in ⊢ (? ? ? %).
728 apply eq_f.assumption
733 |rewrite > false_to_iter_p_gen_Sn
734 [rewrite > false_to_iter_p_gen_Sn in ⊢ (? ? ? %);assumption
741 definition p_ord_times \def
744 [pair q r \Rightarrow r*m+q].
746 theorem eq_p_ord_times: \forall p,m,x.
747 p_ord_times p m x = (ord_rem x p)*m+(ord x p).
748 intros.unfold p_ord_times. unfold ord_rem.
754 theorem div_p_ord_times:
755 \forall p,m,x. ord x p < m \to p_ord_times p m x / m = ord_rem x p.
756 intros.rewrite > eq_p_ord_times.
757 apply div_plus_times.
761 theorem mod_p_ord_times:
762 \forall p,m,x. ord x p < m \to p_ord_times p m x \mod m = ord x p.
763 intros.rewrite > eq_p_ord_times.
764 apply mod_plus_times.
768 lemma lt_times_to_lt_O: \forall i,n,m:nat. i < n*m \to O < m.
770 elim (le_to_or_lt_eq O ? (le_O_n m))
774 rewrite < times_n_O in H.
775 apply (not_le_Sn_O ? H)
779 theorem iter_p_gen_knm:
782 \forall plusA: A \to A \to A.
783 (symmetric A plusA) \to
784 (associative A plusA) \to
785 (\forall a:A.(plusA a baseA) = a)\to
786 \forall g: nat \to A.
787 \forall h2:nat \to nat \to nat.
788 \forall h11,h12:nat \to nat.
790 \forall p1,p21:nat \to bool.
791 \forall p22:nat \to nat \to bool.
792 (\forall x. x < k \to p1 x = true \to
793 p21 (h11 x) = true \land p22 (h11 x) (h12 x) = true
794 \land h2 (h11 x) (h12 x) = x
795 \land (h11 x) < n \land (h12 x) < m) \to
796 (\forall i,j. i < n \to j < m \to p21 i = true \to p22 i j = true \to
797 p1 (h2 i j) = true \land
798 h11 (h2 i j) = i \land h12 (h2 i j) = j
799 \land h2 i j < k) \to
800 iter_p_gen k p1 A g baseA plusA =
801 iter_p_gen n p21 A (\lambda x:nat.iter_p_gen m (p22 x) A (\lambda y. g (h2 x y)) baseA plusA) baseA plusA.
803 rewrite < (iter_p_gen2' n m p21 p22 ? ? ? ? H H1 H2).
805 apply (eq_iter_p_gen_gh A baseA plusA H H1 H2 g ? (\lambda x.(h11 x)*m+(h12 x)))
807 elim (H4 (i/m) (i \mod m));clear H4
811 |apply (lt_times_to_lt_div ? ? ? H5)
813 apply (lt_times_to_lt_O ? ? ? H5)
814 |apply (andb_true_true ? ? H6)
815 |apply (andb_true_true_r ? ? H6)
818 elim (H4 (i/m) (i \mod m));clear H4
825 apply (lt_times_to_lt_O ? ? ? H5)
826 |apply (lt_times_to_lt_div ? ? ? H5)
828 apply (lt_times_to_lt_O ? ? ? H5)
829 |apply (andb_true_true ? ? H6)
830 |apply (andb_true_true_r ? ? H6)
833 elim (H4 (i/m) (i \mod m));clear H4
837 |apply (lt_times_to_lt_div ? ? ? H5)
839 apply (lt_times_to_lt_O ? ? ? H5)
840 |apply (andb_true_true ? ? H6)
841 |apply (andb_true_true_r ? ? H6)
848 rewrite > div_plus_times
849 [rewrite > mod_plus_times
862 rewrite > div_plus_times
863 [rewrite > mod_plus_times
874 apply (lt_to_le_to_lt ? ((h11 j)*m+m))
875 [apply monotonic_lt_plus_r.
878 change with ((S (h11 j)*m) \le n*m).
879 apply monotonic_le_times_l.
885 theorem iter_p_gen_divides:
888 \forall plusA: A \to A \to A.
889 \forall n,m,p:nat.O < n \to prime p \to Not (divides p n) \to
890 \forall g: nat \to A.
891 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a baseA) = a)
895 iter_p_gen (S (n*(exp p m))) (\lambda x.divides_b x (n*(exp p m))) A g baseA plusA =
896 iter_p_gen (S n) (\lambda x.divides_b x n) A
897 (\lambda x.iter_p_gen (S m) (\lambda y.true) A (\lambda y.g (x*(exp p y))) baseA plusA) baseA plusA.
900 [rewrite < (iter_p_gen2 ? ? ? ? ? ? ? ? H3 H4 H5).
902 (iter_p_gen (S n*S m) (\lambda x:nat.divides_b (x/S m) n) A
903 (\lambda x:nat.g (x/S m*(p)\sup(x\mod S m))) baseA plusA) )
905 apply (eq_iter_p_gen_gh ? ? ? ? ? ? g ? (p_ord_times p (S m)))
910 lapply (divides_b_true_to_lt_O ? ? H H7).
911 apply divides_to_divides_b_true
912 [rewrite > (times_n_O O).
915 |apply lt_O_exp.assumption
918 [apply divides_b_true_to_divides.assumption
919 |apply (witness ? ? (p \sup (m-i \mod (S m)))).
920 rewrite < exp_plus_times.
923 apply plus_minus_m_m.
928 lapply (divides_b_true_to_lt_O ? ? H H7).
930 rewrite > (p_ord_exp1 p ? (i \mod (S m)) (i/S m))
931 [change with ((i/S m)*S m+i \mod S m=i).
938 apply (trans_divides ? (i/ S m))
940 apply divides_b_true_to_divides;assumption]
947 change with ((i/S m) < S n).
948 apply (lt_times_to_lt_l m).
949 apply (le_to_lt_to_lt ? i)
950 [autobatch|assumption]
960 [rewrite > div_p_ord_times
961 [apply divides_to_divides_b_true
964 |apply (divides_b_true_to_lt_O ? ? ? H7).
965 rewrite > (times_n_O O).
967 [assumption|apply lt_O_exp.assumption]
969 |cut (n = ord_rem (n*(exp p m)) p)
971 apply divides_to_divides_ord_rem
972 [apply (divides_b_true_to_lt_O ? ? ? H7).
973 rewrite > (times_n_O O).
975 [assumption|apply lt_O_exp.assumption]
976 |rewrite > (times_n_O O).
978 [assumption|apply lt_O_exp.assumption]
980 |apply divides_b_true_to_divides.
984 rewrite > (p_ord_exp1 p ? m n)
994 |cut (m = ord (n*(exp p m)) p)
997 apply divides_to_le_ord
998 [apply (divides_b_true_to_lt_O ? ? ? H7).
999 rewrite > (times_n_O O).
1001 [assumption|apply lt_O_exp.assumption]
1002 |rewrite > (times_n_O O).
1004 [assumption|apply lt_O_exp.assumption]
1006 |apply divides_b_true_to_divides.
1010 rewrite > (p_ord_exp1 p ? m n)
1020 [rewrite > div_p_ord_times
1021 [rewrite > mod_p_ord_times
1022 [rewrite > sym_times.
1026 |apply (divides_b_true_to_lt_O ? ? ? H7).
1027 rewrite > (times_n_O O).
1029 [assumption|apply lt_O_exp.assumption]
1031 |cut (m = ord (n*(exp p m)) p)
1034 apply divides_to_le_ord
1035 [apply (divides_b_true_to_lt_O ? ? ? H7).
1036 rewrite > (times_n_O O).
1038 [assumption|apply lt_O_exp.assumption]
1039 |rewrite > (times_n_O O).
1041 [assumption|apply lt_O_exp.assumption]
1043 |apply divides_b_true_to_divides.
1047 rewrite > (p_ord_exp1 p ? m n)
1057 |cut (m = ord (n*(exp p m)) p)
1060 apply divides_to_le_ord
1061 [apply (divides_b_true_to_lt_O ? ? ? H7).
1062 rewrite > (times_n_O O).
1064 [assumption|apply lt_O_exp.assumption]
1065 |rewrite > (times_n_O O).
1067 [assumption|apply lt_O_exp.assumption]
1069 |apply divides_b_true_to_divides.
1073 rewrite > (p_ord_exp1 p ? m n)
1082 rewrite > eq_p_ord_times.
1084 apply (lt_to_le_to_lt ? (S m +ord_rem j p*S m))
1087 cut (m = ord (n*(p \sup m)) p)
1089 apply divides_to_le_ord
1090 [apply (divides_b_true_to_lt_O ? ? ? H7).
1091 rewrite > (times_n_O O).
1093 [assumption|apply lt_O_exp.assumption]
1094 |rewrite > (times_n_O O).
1096 [assumption|apply lt_O_exp.assumption]
1098 |apply divides_b_true_to_divides.
1102 rewrite > sym_times.
1103 rewrite > (p_ord_exp1 p ? m n)
1110 |change with (S (ord_rem j p)*S m \le S n*S m).
1113 cut (n = ord_rem (n*(p \sup m)) p)
1118 |rewrite > (times_n_O O).
1120 [assumption|apply lt_O_exp.assumption]
1122 |apply divides_to_divides_ord_rem
1123 [apply (divides_b_true_to_lt_O ? ? ? H7).
1124 rewrite > (times_n_O O).
1126 [assumption|apply lt_O_exp.assumption]
1127 |rewrite > (times_n_O O).
1129 [assumption|apply lt_O_exp.assumption]
1131 |apply divides_b_true_to_divides.
1136 rewrite > sym_times.
1137 rewrite > (p_ord_exp1 p ? m n)
1146 |apply eq_iter_p_gen
1149 elim (divides_b (x/S m) n);reflexivity
1153 |elim H1.apply lt_to_le.assumption
1157 (*distributive property for iter_p_gen*)
1158 theorem distributive_times_plus_iter_p_gen: \forall A:Type.
1159 \forall plusA: A \to A \to A. \forall basePlusA: A.
1160 \forall timesA: A \to A \to A.
1161 \forall n:nat. \forall k:A. \forall p:nat \to bool. \forall g:nat \to A.
1162 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a basePlusA) = a) \to
1163 (symmetric A timesA) \to (distributive A timesA plusA) \to
1164 (\forall a:A. (timesA a basePlusA) = basePlusA)
1168 ((timesA k (iter_p_gen n p A g basePlusA plusA)) =
1169 (iter_p_gen n p A (\lambda i:nat.(timesA k (g i))) basePlusA plusA)).
1174 | cut( (p n1) = true \lor (p n1) = false)
1176 [ rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H7).
1177 rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H7) in \vdash (? ? ? %).
1179 rewrite > (H3 k (g n1)).
1182 | rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H7).
1183 rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H7) in \vdash (? ? ? %).
1196 (* old version - proved without theorem iter_p_gen_knm
1197 theorem iter_p_gen_2_eq:
1200 \forall plusA: A \to A \to A.
1201 (symmetric A plusA) \to
1202 (associative A plusA) \to
1203 (\forall a:A.(plusA a baseA) = a)\to
1204 \forall g: nat \to nat \to A.
1205 \forall h11,h12,h21,h22: nat \to nat \to nat.
1206 \forall n1,m1,n2,m2.
1207 \forall p11,p21:nat \to bool.
1208 \forall p12,p22:nat \to nat \to bool.
1209 (\forall i,j. i < n2 \to j < m2 \to p21 i = true \to p22 i j = true \to
1210 p11 (h11 i j) = true \land p12 (h11 i j) (h12 i j) = true
1211 \land h21 (h11 i j) (h12 i j) = i \land h22 (h11 i j) (h12 i j) = j
1212 \land h11 i j < n1 \land h12 i j < m1) \to
1213 (\forall i,j. i < n1 \to j < m1 \to p11 i = true \to p12 i j = true \to
1214 p21 (h21 i j) = true \land p22 (h21 i j) (h22 i j) = true
1215 \land h11 (h21 i j) (h22 i j) = i \land h12 (h21 i j) (h22 i j) = j
1216 \land (h21 i j) < n2 \land (h22 i j) < m2) \to
1218 (\lambda x:nat .iter_p_gen m1 (p12 x) A (\lambda y. g x y) baseA plusA)
1221 (\lambda x:nat .iter_p_gen m2 (p22 x) A (\lambda y. g (h11 x y) (h12 x y)) baseA plusA )
1224 rewrite < (iter_p_gen2' ? ? ? ? ? ? ? ? H H1 H2).
1225 rewrite < (iter_p_gen2' ? ? ? ? ? ? ? ? H H1 H2).
1227 letin h := (\lambda x.(h11 (x/m2) (x\mod m2))*m1 + (h12 (x/m2) (x\mod m2))).
1228 letin h1 := (\lambda x.(h21 (x/m1) (x\mod m1))*m2 + (h22 (x/m1) (x\mod m1))).
1230 (iter_p_gen (n2*m2) (\lambda x:nat.p21 (x/m2)\land p22 (x/m2) (x\mod m2)) A
1231 (\lambda x:nat.g ((h x)/m1) ((h x)\mod m1)) baseA plusA ))
1233 apply eq_iter_p_gen1
1238 [cut (x \mod m2 < m2)
1239 [elim (and_true ? ? H6).
1240 elim (H3 ? ? Hcut1 Hcut2 H7 H8).
1247 apply div_plus_times.
1250 apply mod_plus_times.
1256 |apply (lt_times_n_to_lt m2)
1258 |apply (le_to_lt_to_lt ? x)
1259 [apply (eq_plus_to_le ? ? (x \mod m2)).
1266 |apply not_le_to_lt.unfold.intro.
1267 generalize in match H5.
1268 apply (le_n_O_elim ? H7).
1269 rewrite < times_n_O.
1274 |apply (eq_iter_p_gen_gh ? ? ? H H1 H2 ? h h1);intros
1277 [cut (i \mod m2 < m2)
1278 [elim (and_true ? ? H6).
1279 elim (H3 ? ? Hcut1 Hcut2 H7 H8).
1284 cut ((h11 (i/m2) (i\mod m2)*m1+h12 (i/m2) (i\mod m2))/m1 =
1285 h11 (i/m2) (i\mod m2))
1286 [cut ((h11 (i/m2) (i\mod m2)*m1+h12 (i/m2) (i\mod m2))\mod m1 =
1287 h12 (i/m2) (i\mod m2))
1293 |apply mod_plus_times.
1296 |apply div_plus_times.
1302 |apply (lt_times_n_to_lt m2)
1304 |apply (le_to_lt_to_lt ? i)
1305 [apply (eq_plus_to_le ? ? (i \mod m2)).
1312 |apply not_le_to_lt.unfold.intro.
1313 generalize in match H5.
1314 apply (le_n_O_elim ? H7).
1315 rewrite < times_n_O.
1321 [cut (i \mod m2 < m2)
1322 [elim (and_true ? ? H6).
1323 elim (H3 ? ? Hcut1 Hcut2 H7 H8).
1328 cut ((h11 (i/m2) (i\mod m2)*m1+h12 (i/m2) (i\mod m2))/m1 =
1329 h11 (i/m2) (i\mod m2))
1330 [cut ((h11 (i/m2) (i\mod m2)*m1+h12 (i/m2) (i\mod m2))\mod m1 =
1331 h12 (i/m2) (i\mod m2))
1339 |apply mod_plus_times.
1342 |apply div_plus_times.
1348 |apply (lt_times_n_to_lt m2)
1350 |apply (le_to_lt_to_lt ? i)
1351 [apply (eq_plus_to_le ? ? (i \mod m2)).
1358 |apply not_le_to_lt.unfold.intro.
1359 generalize in match H5.
1360 apply (le_n_O_elim ? H7).
1361 rewrite < times_n_O.
1367 [cut (i \mod m2 < m2)
1368 [elim (and_true ? ? H6).
1369 elim (H3 ? ? Hcut1 Hcut2 H7 H8).
1374 apply lt_times_plus_times
1375 [assumption|assumption]
1379 |apply (lt_times_n_to_lt m2)
1381 |apply (le_to_lt_to_lt ? i)
1382 [apply (eq_plus_to_le ? ? (i \mod m2)).
1389 |apply not_le_to_lt.unfold.intro.
1390 generalize in match H5.
1391 apply (le_n_O_elim ? H7).
1392 rewrite < times_n_O.
1398 [cut (j \mod m1 < m1)
1399 [elim (and_true ? ? H6).
1400 elim (H4 ? ? Hcut1 Hcut2 H7 H8).
1405 cut ((h21 (j/m1) (j\mod m1)*m2+h22 (j/m1) (j\mod m1))/m2 =
1406 h21 (j/m1) (j\mod m1))
1407 [cut ((h21 (j/m1) (j\mod m1)*m2+h22 (j/m1) (j\mod m1))\mod m2 =
1408 h22 (j/m1) (j\mod m1))
1414 |apply mod_plus_times.
1417 |apply div_plus_times.
1423 |apply (lt_times_n_to_lt m1)
1425 |apply (le_to_lt_to_lt ? j)
1426 [apply (eq_plus_to_le ? ? (j \mod m1)).
1433 |apply not_le_to_lt.unfold.intro.
1434 generalize in match H5.
1435 apply (le_n_O_elim ? H7).
1436 rewrite < times_n_O.
1442 [cut (j \mod m1 < m1)
1443 [elim (and_true ? ? H6).
1444 elim (H4 ? ? Hcut1 Hcut2 H7 H8).
1449 cut ((h21 (j/m1) (j\mod m1)*m2+h22 (j/m1) (j\mod m1))/m2 =
1450 h21 (j/m1) (j\mod m1))
1451 [cut ((h21 (j/m1) (j\mod m1)*m2+h22 (j/m1) (j\mod m1))\mod m2 =
1452 h22 (j/m1) (j\mod m1))
1460 |apply mod_plus_times.
1463 |apply div_plus_times.
1469 |apply (lt_times_n_to_lt m1)
1471 |apply (le_to_lt_to_lt ? j)
1472 [apply (eq_plus_to_le ? ? (j \mod m1)).
1479 |apply not_le_to_lt.unfold.intro.
1480 generalize in match H5.
1481 apply (le_n_O_elim ? H7).
1482 rewrite < times_n_O.
1488 [cut (j \mod m1 < m1)
1489 [elim (and_true ? ? H6).
1490 elim (H4 ? ? Hcut1 Hcut2 H7 H8).
1495 apply (lt_times_plus_times ? ? ? m2)
1496 [assumption|assumption]
1500 |apply (lt_times_n_to_lt m1)
1502 |apply (le_to_lt_to_lt ? j)
1503 [apply (eq_plus_to_le ? ? (j \mod m1)).
1510 |apply not_le_to_lt.unfold.intro.
1511 generalize in match H5.
1512 apply (le_n_O_elim ? H7).
1513 rewrite < times_n_O.
1522 theorem iter_p_gen_2_eq:
1525 \forall plusA: A \to A \to A.
1526 (symmetric A plusA) \to
1527 (associative A plusA) \to
1528 (\forall a:A.(plusA a baseA) = a)\to
1529 \forall g: nat \to nat \to A.
1530 \forall h11,h12,h21,h22: nat \to nat \to nat.
1531 \forall n1,m1,n2,m2.
1532 \forall p11,p21:nat \to bool.
1533 \forall p12,p22:nat \to nat \to bool.
1534 (\forall i,j. i < n2 \to j < m2 \to p21 i = true \to p22 i j = true \to
1535 p11 (h11 i j) = true \land p12 (h11 i j) (h12 i j) = true
1536 \land h21 (h11 i j) (h12 i j) = i \land h22 (h11 i j) (h12 i j) = j
1537 \land h11 i j < n1 \land h12 i j < m1) \to
1538 (\forall i,j. i < n1 \to j < m1 \to p11 i = true \to p12 i j = true \to
1539 p21 (h21 i j) = true \land p22 (h21 i j) (h22 i j) = true
1540 \land h11 (h21 i j) (h22 i j) = i \land h12 (h21 i j) (h22 i j) = j
1541 \land (h21 i j) < n2 \land (h22 i j) < m2) \to
1543 (\lambda x:nat .iter_p_gen m1 (p12 x) A (\lambda y. g x y) baseA plusA)
1546 (\lambda x:nat .iter_p_gen m2 (p22 x) A (\lambda y. g (h11 x y) (h12 x y)) baseA plusA )
1550 rewrite < (iter_p_gen2' ? ? ? ? ? ? ? ? H H1 H2).
1551 letin ha:= (\lambda x,y.(((h11 x y)*m1) + (h12 x y))).
1552 letin ha12:= (\lambda x.(h21 (x/m1) (x \mod m1))).
1553 letin ha22:= (\lambda x.(h22 (x/m1) (x \mod m1))).
1556 (iter_p_gen n2 p21 A (\lambda x:nat. iter_p_gen m2 (p22 x) A
1557 (\lambda y:nat.(g (((h11 x y)*m1+(h12 x y))/m1) (((h11 x y)*m1+(h12 x y))\mod m1))) baseA plusA ) baseA plusA))
1559 apply (iter_p_gen_knm A baseA plusA H H1 H2 (\lambda e. (g (e/m1) (e \mod m1))) ha ha12 ha22);intros
1560 [ elim (and_true ? ? H6).
1563 [ cut((x \mod m1) < m1)
1564 [ elim (H4 ? ? Hcut1 Hcut2 H7 H8).
1589 | apply (lt_times_n_to_lt m1)
1591 | apply (le_to_lt_to_lt ? x)
1592 [ apply (eq_plus_to_le ? ? (x \mod m1)).
1599 | apply not_le_to_lt.unfold.intro.
1600 generalize in match H5.
1601 apply (le_n_O_elim ? H9).
1602 rewrite < times_n_O.
1606 | elim (H3 ? ? H5 H6 H7 H8).
1611 cut(((h11 i j)*m1 + (h12 i j))/m1 = (h11 i j))
1612 [ cut(((h11 i j)*m1 + (h12 i j)) \mod m1 = (h12 i j))
1616 [ apply true_to_true_to_andb_true
1633 [ apply (lt_to_le_to_lt ? ((h11 i j)*m1 + m1) )
1634 [ apply (lt_plus_r).
1636 | rewrite > sym_plus.
1637 rewrite > (sym_times (h11 i j) m1).
1638 rewrite > times_n_Sm.
1639 rewrite > sym_times.
1643 | apply not_le_to_lt.unfold.intro.
1644 generalize in match H12.
1645 apply (le_n_O_elim ? H11).
1649 | apply not_le_to_lt.unfold.intro.
1650 generalize in match H10.
1651 apply (le_n_O_elim ? H11).
1656 | rewrite > (mod_plus_times m1 (h11 i j) (h12 i j)).
1660 | rewrite > (div_plus_times m1 (h11 i j) (h12 i j)).
1665 | apply (eq_iter_p_gen1)
1666 [ intros. reflexivity
1668 apply (eq_iter_p_gen1)
1669 [ intros. reflexivity
1671 rewrite > (div_plus_times)
1672 [ rewrite > (mod_plus_times)
1674 | elim (H3 x x1 H5 H7 H6 H8).
1677 | elim (H3 x x1 H5 H7 H6 H8).
1685 theorem iter_p_gen_iter_p_gen:
1688 \forall plusA: A \to A \to A.
1689 (symmetric A plusA) \to
1690 (associative A plusA) \to
1691 (\forall a:A.(plusA a baseA) = a)\to
1692 \forall g: nat \to nat \to A.
1694 \forall p11,p21:nat \to bool.
1695 \forall p12,p22:nat \to nat \to bool.
1696 (\forall x,y. x < n \to y < m \to
1697 (p11 x \land p12 x y) = (p21 y \land p22 y x)) \to
1699 (\lambda x:nat.iter_p_gen m (p12 x) A (\lambda y. g x y) baseA plusA)
1702 (\lambda y:nat.iter_p_gen n (p22 y) A (\lambda x. g x y) baseA plusA )
1705 apply (iter_p_gen_2_eq A baseA plusA H H1 H2 (\lambda x,y. g x y) (\lambda x,y.y) (\lambda x,y.x) (\lambda x,y.y) (\lambda x,y.x)
1706 n m m n p11 p21 p12 p22)
1712 [apply (andb_true_true ? (p12 j i)).
1714 [rewrite > H6.rewrite > H7.reflexivity
1718 |apply (andb_true_true_r (p11 j)).
1720 [rewrite > H6.rewrite > H7.reflexivity
1738 [apply (andb_true_true ? (p22 j i)).
1740 [rewrite > H6.rewrite > H7.reflexivity
1744 |apply (andb_true_true_r (p21 j)).
1746 [rewrite > H6.rewrite > H7.reflexivity