]> matita.cs.unibo.it Git - helm.git/blob - matita/library/nat/generic_iter_p.ma
3a9adc231262f58a9bfc5da65783cf790b4e9a89
[helm.git] / matita / library / nat / generic_iter_p.ma
1 (**************************************************************************)
2 (*       ___                                                              *)
3 (*      ||M||                                                             *)
4 (*      ||A||       A project by Andrea Asperti                           *)
5 (*      ||T||                                                             *)
6 (*      ||I||       Developers:                                           *)
7 (*      ||T||         The HELM team.                                      *)
8 (*      ||A||         http://helm.cs.unibo.it                             *)
9 (*      \   /                                                             *)
10 (*       \ /        This file is distributed under the terms of the       *)
11 (*        v         GNU General Public License Version 2                  *)
12 (*                                                                        *)
13 (**************************************************************************)
14
15 set "baseuri" "cic:/matita/nat/generic_iter_p".
16
17 include "nat/primes.ma".
18 include "nat/ord.ma".
19
20 (*a generic definition of summatory indexed over natural numbers:
21  * n:N is the advanced end in the range of the sommatory 
22  * p: N -> bool is a predicate. if (p i) = true, then (g i) is summed, else it isn't 
23  * A is the type of the elements of the sum.
24  * g:nat -> A, is the function which associates the nth element of the sum to the nth natural numbers 
25  * baseA (of type A) is the neutral element of A for plusA operation
26  * plusA: A -> A -> A is the sum over elements in A. 
27  *)
28  
29 let rec iter_p_gen (n:nat) (p: nat \to bool) (A:Type) (g: nat \to A) 
30    (baseA: A) (plusA: A \to A \to A)  \def
31   match n with
32    [ O \Rightarrow baseA
33    | (S k) \Rightarrow 
34       match p k with
35       [true \Rightarrow (plusA (g k) (iter_p_gen k p A g baseA plusA))
36       |false \Rightarrow iter_p_gen k p A g baseA plusA]
37    ].
38    
39 theorem true_to_iter_p_gen_Sn: 
40 \forall n:nat. \forall p:nat \to bool. \forall A:Type. \forall g:nat \to A.
41 \forall baseA:A. \forall plusA: A \to A \to A.
42 p n = true \to iter_p_gen (S n) p A g baseA plusA = 
43 (plusA (g n) (iter_p_gen n p A g baseA plusA)).
44 intros.
45 simplify.
46 rewrite > H.
47 reflexivity.
48 qed.
49
50
51
52 theorem false_to_iter_p_gen_Sn: 
53 \forall n:nat. \forall p:nat \to bool. \forall A:Type. \forall g:nat \to A.
54 \forall baseA:A. \forall plusA: A \to A \to A.
55 p n = false \to iter_p_gen (S n) p A g baseA plusA = iter_p_gen n p A g baseA plusA.
56 intros.
57 simplify.
58 rewrite > H.
59 reflexivity.
60 qed.
61
62
63 theorem eq_iter_p_gen: \forall p1,p2:nat \to bool. \forall A:Type.
64 \forall g1,g2: nat \to A. \forall baseA: A. 
65 \forall plusA: A \to A \to A. \forall n:nat.
66 (\forall x.  x < n \to p1 x = p2 x) \to
67 (\forall x.  x < n \to g1 x = g2 x) \to
68 iter_p_gen n p1 A g1 baseA plusA = iter_p_gen n p2 A g2 baseA plusA.
69 intros 8.
70 elim n
71 [ reflexivity
72 | apply (bool_elim ? (p1 n1))
73   [ intro.
74     rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H3).
75     rewrite > true_to_iter_p_gen_Sn     
76     [ apply eq_f2
77       [ apply H2.apply le_n.
78       | apply H
79         [ intros.apply H1.apply le_S.assumption
80         | intros.apply H2.apply le_S.assumption
81         ]
82       ]
83     | rewrite < H3.apply sym_eq.apply H1.apply le_n
84     ]
85   | intro.
86     rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H3).
87     rewrite > false_to_iter_p_gen_Sn
88     [ apply H
89       [ intros.apply H1.apply le_S.assumption
90       | intros.apply H2.apply le_S.assumption
91       ]
92     | rewrite < H3.apply sym_eq.apply H1.apply le_n
93     ]
94   ]
95 ]
96 qed.
97
98 theorem eq_iter_p_gen1: \forall p1,p2:nat \to bool. \forall A:Type.
99 \forall g1,g2: nat \to A. \forall baseA: A. 
100 \forall plusA: A \to A \to A.\forall n:nat.
101 (\forall x.  x < n \to p1 x = p2 x) \to
102 (\forall x.  x < n \to p1 x = true \to g1 x = g2 x) \to
103 iter_p_gen n p1 A g1 baseA plusA = iter_p_gen n p2 A g2 baseA plusA.
104 intros 8.
105 elim n
106 [ reflexivity
107 | apply (bool_elim ? (p1 n1))
108   [ intro.
109     rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H3).
110     rewrite > true_to_iter_p_gen_Sn
111     [ apply eq_f2
112       [ apply H2
113         [ apply le_n
114         | assumption
115         ]
116       | apply H
117         [ intros.apply H1.apply le_S.assumption
118         | intros.apply H2
119           [ apply le_S.assumption
120           | assumption
121           ]
122         ]
123       ]
124     | rewrite < H3.
125       apply sym_eq.apply H1.apply le_n
126     ]
127   | intro.
128     rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H3).
129     rewrite > false_to_iter_p_gen_Sn
130     [ apply H
131       [ intros.apply H1.apply le_S.assumption
132       | intros.apply H2
133         [ apply le_S.assumption
134         | assumption
135         ]
136       ]
137     | rewrite < H3.apply sym_eq.
138       apply H1.apply le_n
139     ]
140   ]
141 ]
142 qed.
143
144 theorem iter_p_gen_false: \forall A:Type. \forall g: nat \to A. \forall baseA:A.
145 \forall plusA: A \to A \to A. \forall n.
146 iter_p_gen n (\lambda x.false) A g baseA plusA = baseA.
147 intros.
148 elim n
149 [ reflexivity
150 | simplify.
151   assumption
152 ]
153 qed.
154
155 theorem iter_p_gen_plusA: \forall A:Type. \forall n,k:nat.\forall p:nat \to bool.
156 \forall g: nat \to A. \forall baseA:A. \forall plusA: A \to A \to A.
157 (symmetric A plusA) \to (\forall a:A. (plusA a baseA) = a) \to (associative A plusA)
158 \to
159 iter_p_gen (k + n) p A g baseA plusA 
160 = (plusA (iter_p_gen k (\lambda x.p (x+n)) A (\lambda x.g (x+n)) baseA plusA)
161          (iter_p_gen n p A g baseA plusA)).
162 intros.
163
164 elim k
165 [ rewrite < (plus_n_O n).
166   simplify.
167   rewrite > H in \vdash (? ? ? %).
168   rewrite > (H1 ?).
169   reflexivity
170 | apply (bool_elim ? (p (n1+n)))
171   [ intro.     
172     rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
173     rewrite > (true_to_iter_p_gen_Sn n1 (\lambda x.p (x+n)) ? ? ? ? H4).
174     rewrite > (H2 (g (n1 + n)) ? ?).
175     rewrite < H3.
176     reflexivity
177   | intro.
178     rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
179     rewrite > (false_to_iter_p_gen_Sn n1 (\lambda x.p (x+n)) ? ? ? ? H4).
180     assumption
181   ]
182 ]
183 qed.
184
185 theorem false_to_eq_iter_p_gen: \forall A:Type. \forall n,m:nat.\forall p:nat \to bool.
186 \forall g: nat \to A. \forall baseA:A. \forall plusA: A \to A \to A. 
187 n \le m \to (\forall i:nat. n \le i \to i < m \to p i = false)
188 \to iter_p_gen m p A g baseA plusA = iter_p_gen n p A g baseA plusA.
189 intros 8.
190 elim H
191 [ reflexivity
192 | simplify.
193   rewrite > H3
194   [ simplify.
195     apply H2.
196     intros.
197     apply H3
198     [ apply H4
199     | apply le_S.
200       assumption
201     ]
202   | assumption
203   |apply le_n
204   ]
205 ]
206 qed.
207
208 theorem iter_p_gen2 : 
209 \forall n,m:nat.
210 \forall p1,p2:nat \to bool.
211 \forall A:Type.
212 \forall g: nat \to nat \to A.
213 \forall baseA: A.
214 \forall plusA: A \to A \to A.
215 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a  baseA) = a)
216 \to
217 iter_p_gen (n*m) 
218   (\lambda x.andb (p1 (div x m)) (p2 (mod x m)))
219   A 
220   (\lambda x.g (div x m) (mod x m)) 
221   baseA
222   plusA  =
223 iter_p_gen n p1 A
224   (\lambda x.iter_p_gen m p2 A (g x) baseA plusA)
225   baseA plusA.
226 intros.
227 elim n
228 [ simplify.
229   reflexivity
230 | apply (bool_elim ? (p1 n1))
231   [ intro.
232     rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
233     simplify in \vdash (? ? (? % ? ? ? ? ?) ?).
234     rewrite > iter_p_gen_plusA
235     [ rewrite < H3.
236       apply eq_f2
237       [ apply eq_iter_p_gen
238         [ intros.
239           rewrite > sym_plus.
240           rewrite > (div_plus_times ? ? ? H5).
241           rewrite > (mod_plus_times ? ? ? H5).
242           rewrite > H4.
243           simplify.
244           reflexivity
245         | intros.
246           rewrite > sym_plus.
247           rewrite > (div_plus_times ? ? ? H5).
248           rewrite > (mod_plus_times ? ? ? H5).
249           rewrite > H4.
250           simplify.reflexivity.   
251         ]
252       | reflexivity
253       ]
254     | assumption
255     | assumption
256     | assumption
257     ]
258   | intro.
259     rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
260     simplify in \vdash (? ? (? % ? ? ? ? ?) ?).
261     rewrite > iter_p_gen_plusA
262     [ rewrite > H3.
263       apply (trans_eq ? ? (plusA baseA
264            (iter_p_gen n1 p1 A (\lambda x:nat.iter_p_gen m p2 A (g x) baseA plusA) baseA plusA )))
265       [ apply eq_f2
266         [ rewrite > (eq_iter_p_gen ? (\lambda x.false) A ? (\lambda x:nat.g ((x+n1*m)/m) ((x+n1*m)\mod m)))
267           [ apply iter_p_gen_false
268           | intros.
269             rewrite > sym_plus.
270             rewrite > (div_plus_times ? ? ? H5).
271             rewrite > (mod_plus_times ? ? ? H5).
272             rewrite > H4.
273             simplify.reflexivity
274           | intros.reflexivity.
275           ]
276         | reflexivity
277         ]
278       | rewrite < H.
279         rewrite > H2.
280         reflexivity.  
281       ]
282     | assumption
283     | assumption
284     | assumption
285     ]
286   ]
287 ]
288 qed.
289
290 theorem iter_p_gen2': 
291 \forall n,m:nat.
292 \forall p1: nat \to bool.
293 \forall p2: nat \to nat \to bool.
294 \forall A:Type.
295 \forall g: nat \to nat \to A.
296 \forall baseA: A.
297 \forall plusA: A \to A \to A.
298 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a  baseA) = a)
299 \to
300 iter_p_gen (n*m) 
301   (\lambda x.andb (p1 (div x m)) (p2 (div x m)(mod x m)))
302   A 
303   (\lambda x.g (div x m) (mod x m)) 
304   baseA
305   plusA  =
306 iter_p_gen n p1 A
307   (\lambda x.iter_p_gen m (p2 x) A (g x) baseA plusA)
308   baseA plusA.
309 intros.
310 elim n
311 [ simplify.
312   reflexivity
313 | apply (bool_elim ? (p1 n1))
314   [ intro.
315     rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
316     simplify in \vdash (? ? (? % ? ? ? ? ?) ?).
317     rewrite > iter_p_gen_plusA
318     [ rewrite < H3.
319       apply eq_f2
320       [ apply eq_iter_p_gen
321         [ intros.
322           rewrite > sym_plus.
323           rewrite > (div_plus_times ? ? ? H5).
324           rewrite > (mod_plus_times ? ? ? H5).
325           rewrite > H4.
326           simplify.
327           reflexivity
328         | intros.
329           rewrite > sym_plus.
330           rewrite > (div_plus_times ? ? ? H5).
331           rewrite > (mod_plus_times ? ? ? H5).
332           rewrite > H4.
333           simplify.reflexivity.   
334         ]
335       | reflexivity
336       ]
337     | assumption
338     | assumption
339     | assumption
340     ]
341   | intro.
342     rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H4).
343     simplify in \vdash (? ? (? % ? ? ? ? ?) ?).
344     rewrite > iter_p_gen_plusA
345     [ rewrite > H3.
346       apply (trans_eq ? ? (plusA baseA
347            (iter_p_gen n1 p1 A (\lambda x:nat.iter_p_gen m (p2 x) A (g x) baseA plusA) baseA plusA )))
348       [ apply eq_f2
349         [ rewrite > (eq_iter_p_gen ? (\lambda x.false) A ? (\lambda x:nat.g ((x+n1*m)/m) ((x+n1*m)\mod m)))
350           [ apply iter_p_gen_false
351           | intros.
352             rewrite > sym_plus.
353             rewrite > (div_plus_times ? ? ? H5).
354             rewrite > (mod_plus_times ? ? ? H5).
355             rewrite > H4.
356             simplify.reflexivity
357           | intros.reflexivity.
358           ]
359         | reflexivity
360         ]
361       | rewrite < H.
362         rewrite > H2.
363         reflexivity.  
364       ]
365     | assumption
366     | assumption
367     | assumption
368     ]
369   ]
370 ]
371 qed.
372
373 lemma iter_p_gen_gi: 
374 \forall A:Type.
375 \forall g: nat \to A.
376 \forall baseA:A.
377 \forall plusA: A \to A \to A.
378 \forall n,i:nat.
379 \forall p:nat \to bool.
380 (symmetric A plusA) \to  (associative A plusA) \to (\forall a:A.(plusA a  baseA) = a) 
381   \to 
382   
383 i < n \to p i = true \to
384 (iter_p_gen n p A g baseA plusA) = 
385 (plusA (g i) (iter_p_gen n (\lambda x:nat. andb (p x) (notb (eqb x i))) A g baseA plusA)).
386 intros 5.
387 elim n
388 [ apply False_ind.
389   apply (not_le_Sn_O i).
390   assumption
391 | apply (bool_elim ? (p n1));intro
392   [ elim (le_to_or_lt_eq i n1)
393     [ rewrite > true_to_iter_p_gen_Sn
394       [ rewrite > true_to_iter_p_gen_Sn
395         [ rewrite < (H2 (g i) ? ?).
396           rewrite > (H1 (g i) (g n1)).
397           rewrite > (H2 (g n1) ? ?).
398           apply eq_f2
399           [ reflexivity
400           | apply H
401             [ assumption
402             | assumption
403             | assumption 
404             | assumption
405             | assumption
406             ]
407           ]
408         | rewrite > H6.simplify.
409           change with (notb (eqb n1 i) = notb false).
410           apply eq_f.
411           apply not_eq_to_eqb_false.
412           unfold Not.intro.
413           apply (lt_to_not_eq ? ? H7).
414           apply sym_eq.assumption
415         ]
416       | assumption
417       ]
418     | rewrite > true_to_iter_p_gen_Sn
419       [ rewrite > H7.
420         apply eq_f2
421         [ reflexivity
422         | rewrite > false_to_iter_p_gen_Sn
423           [ apply eq_iter_p_gen
424             [ intros.
425               elim (p x)
426               [ simplify.
427                 change with (notb false = notb (eqb x n1)).
428                 apply eq_f.
429                 apply sym_eq. 
430                 apply not_eq_to_eqb_false.
431                 apply (lt_to_not_eq ? ? H8)
432               | reflexivity
433               ]
434             | intros.
435               reflexivity
436             ]
437           | rewrite > H6.
438             rewrite > (eq_to_eqb_true ? ? (refl_eq ? n1)).
439             reflexivity
440           ]
441         ]
442       | assumption
443       ]
444     | apply le_S_S_to_le.
445       assumption
446     ]
447   | rewrite > false_to_iter_p_gen_Sn
448     [ elim (le_to_or_lt_eq i n1)
449       [ rewrite > false_to_iter_p_gen_Sn
450         [ apply H
451           [ assumption
452           | assumption
453           | assumption
454           | assumption
455           | assumption
456           ]
457         | rewrite > H6.reflexivity
458         ]
459       | apply False_ind. 
460         apply not_eq_true_false.
461         rewrite < H5.
462         rewrite > H7.
463         assumption
464       | apply le_S_S_to_le.
465         assumption
466       ]
467     | assumption
468     ]
469   ] 
470
471 qed.
472
473 (* invariance under permutation; single sum *)
474 theorem eq_iter_p_gen_gh: 
475 \forall A:Type.
476 \forall baseA: A.
477 \forall plusA: A \to A \to A.
478 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a  baseA) = a) \to
479 \forall g: nat \to A.
480 \forall h,h1: nat \to nat.
481 \forall n,n1:nat.
482 \forall p1,p2:nat \to bool.
483 (\forall i. i < n \to p1 i = true \to p2 (h i) = true) \to
484 (\forall i. i < n \to p1 i = true \to h1 (h i) = i) \to 
485 (\forall i. i < n \to p1 i = true \to h i < n1) \to 
486 (\forall j. j < n1 \to p2 j = true \to p1 (h1 j) = true) \to
487 (\forall j. j < n1 \to p2 j = true \to h (h1 j) = j) \to 
488 (\forall j. j < n1 \to p2 j = true \to h1 j < n) \to 
489
490 iter_p_gen n p1 A (\lambda x.g(h x)) baseA plusA = 
491 iter_p_gen n1 p2 A g baseA plusA.
492 intros 10.
493 elim n
494 [ generalize in match H8.
495   elim n1
496   [ reflexivity
497   | apply (bool_elim ? (p2 n2));intro
498     [ apply False_ind.
499       apply (not_le_Sn_O (h1 n2)).
500       apply H10
501       [ apply le_n
502       | assumption
503       ]
504     | rewrite > false_to_iter_p_gen_Sn
505       [ apply H9.
506         intros.  
507         apply H10
508         [ apply le_S.
509           apply H12
510         | assumption
511         ]
512       | assumption
513       ]
514     ]
515   ]
516 | apply (bool_elim ? (p1 n1));intro
517   [ rewrite > true_to_iter_p_gen_Sn
518     [ rewrite > (iter_p_gen_gi A g baseA plusA n2 (h n1))
519       [ apply eq_f2
520         [ reflexivity
521         | apply H3
522           [ intros.
523             rewrite > H4
524             [ simplify.
525               change with ((\not eqb (h i) (h n1))= \not false).
526               apply eq_f.
527               apply not_eq_to_eqb_false.
528               unfold Not.
529               intro.
530               apply (lt_to_not_eq ? ? H11).
531               rewrite < H5
532               [ rewrite < (H5 n1)
533                 [ apply eq_f.
534                   assumption
535                 | apply le_n
536                 | assumption
537                 ]
538               | apply le_S.
539                 assumption
540               | assumption
541               ]
542             | apply le_S.assumption
543             | assumption
544             ]
545           | intros.
546             apply H5
547             [ apply le_S.
548               assumption
549             | assumption
550             ]
551           | intros.
552             apply H6
553             [ apply le_S.assumption
554             | assumption
555             ]
556           | intros.
557             apply H7
558             [ assumption
559             | generalize in match H12.
560               elim (p2 j)
561               [ reflexivity
562               | assumption
563               ]
564             ]
565           | intros.
566             apply H8
567             [ assumption
568             | generalize in match H12.
569               elim (p2 j)
570               [ reflexivity
571               | assumption
572               ]
573             ]
574           | intros.
575             elim (le_to_or_lt_eq (h1 j) n1)
576             [ assumption
577             | generalize in match H12.
578               elim (p2 j)
579               [ simplify in H13.
580                 absurd (j = (h n1))
581                 [ rewrite < H13.
582                   rewrite > H8
583                   [ reflexivity
584                   | assumption
585                   | autobatch
586                   ]
587                 | apply eqb_false_to_not_eq.
588                   generalize in match H14.
589                   elim (eqb j (h n1))
590                   [ apply sym_eq.assumption
591                   | reflexivity
592                   ]
593                 ]
594               | simplify in H14.
595                 apply False_ind.
596                 apply not_eq_true_false.
597                 apply sym_eq.assumption
598               ]
599             | apply le_S_S_to_le.
600               apply H9
601               [ assumption
602               | generalize in match H12.
603                 elim (p2 j)
604                 [ reflexivity
605                 | assumption
606                 ]
607               ]
608             ]
609           ]
610         ]
611       | assumption  
612       | assumption
613       | assumption  
614       | apply H6
615         [ apply le_n
616         | assumption
617         ]
618       | apply H4
619         [ apply le_n
620         | assumption
621         ]
622       ]
623     | assumption
624     ]
625   | rewrite > false_to_iter_p_gen_Sn
626     [ apply H3
627       [ intros.
628         apply H4[apply le_S.assumption|assumption]
629       | intros.
630         apply H5[apply le_S.assumption|assumption]
631       | intros.
632         apply H6[apply le_S.assumption|assumption]
633       | intros.
634         apply H7[assumption|assumption]
635       | intros.
636         apply H8[assumption|assumption]
637       | intros.
638         elim (le_to_or_lt_eq (h1 j) n1)
639         [ assumption
640         | absurd (j = (h n1))
641           [ rewrite < H13.
642             rewrite > H8
643             [ reflexivity
644             | assumption
645             | assumption
646             ]
647           | unfold Not.intro.
648             apply not_eq_true_false.
649             rewrite < H10.
650             rewrite < H13.
651             rewrite > H7
652             [ reflexivity
653             | assumption
654             | assumption
655             ]
656           ]
657         | apply le_S_S_to_le.
658           apply H9
659           [ assumption
660           | assumption
661           ]
662         ]
663       ]
664     | assumption
665     ]
666   ]
667 ]
668 qed.
669
670
671 (* da spostare *)
672
673 definition p_ord_times \def
674 \lambda p,m,x.
675   match p_ord x p with
676   [pair q r \Rightarrow r*m+q].
677   
678 theorem  eq_p_ord_times: \forall p,m,x.
679 p_ord_times p m x = (ord_rem x p)*m+(ord x p).
680 intros.unfold p_ord_times. unfold ord_rem.
681 unfold ord.
682 elim (p_ord x p).
683 reflexivity.
684 qed.
685
686 theorem div_p_ord_times: 
687 \forall p,m,x. ord x p < m \to p_ord_times p m x / m = ord_rem x p.
688 intros.rewrite > eq_p_ord_times.
689 apply div_plus_times.
690 assumption.
691 qed.
692
693 theorem mod_p_ord_times: 
694 \forall p,m,x. ord x p < m \to p_ord_times p m x \mod m = ord x p.
695 intros.rewrite > eq_p_ord_times.
696 apply mod_plus_times.
697 assumption.
698 qed.
699
700 lemma lt_times_to_lt_O: \forall i,n,m:nat. i < n*m \to O < m.
701 intros.
702 elim (le_to_or_lt_eq O ? (le_O_n m))
703   [assumption
704   |apply False_ind.
705    rewrite < H1 in H.
706    rewrite < times_n_O in H.
707    apply (not_le_Sn_O ? H)
708   ]
709 qed.
710
711 (* lemmino da postare *)
712 theorem lt_times_to_lt_div: \forall i,n,m. i < n*m \to i/m < n.
713 intros.
714 cut (O < m)
715   [apply (lt_times_n_to_lt m)
716     [assumption
717     |apply (le_to_lt_to_lt ? i)
718       [rewrite > (div_mod i m) in \vdash (? ? %).
719        apply le_plus_n_r.
720        assumption
721       |assumption
722       ]
723     ]
724   |apply (lt_times_to_lt_O ? ? ? H)
725   ]
726 qed.
727
728 theorem iter_p_gen_knm:
729 \forall A:Type.
730 \forall baseA: A.
731 \forall plusA: A \to A \to A. 
732 (symmetric A plusA) \to 
733 (associative A plusA) \to 
734 (\forall a:A.(plusA a  baseA) = a)\to
735 \forall g: nat \to A.
736 \forall h2:nat \to nat \to nat.
737 \forall h11,h12:nat \to nat. 
738 \forall k,n,m.
739 \forall p1,p21:nat \to bool.
740 \forall p22:nat \to nat \to bool.
741 (\forall x. x < k \to p1 x = true \to 
742 p21 (h11 x) = true \land p22 (h11 x) (h12 x) = true
743 \land h2 (h11 x) (h12 x) = x 
744 \land (h11 x) < n \land (h12 x) < m) \to
745 (\forall i,j. i < n \to j < m \to p21 i = true \to p22 i j = true \to 
746 p1 (h2 i j) = true \land 
747 h11 (h2 i j) = i \land h12 (h2 i j) = j
748 \land h2 i j < k) \to
749 iter_p_gen k p1 A g baseA plusA =
750 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.
751 intros.
752 rewrite < (iter_p_gen2' n m p21 p22 ? ? ? ? H H1 H2).
753 apply sym_eq.
754 apply (eq_iter_p_gen_gh A baseA plusA H H1 H2 g ? (\lambda x.(h11 x)*m+(h12 x)))
755  [intros.
756   elim (H4 (i/m) (i \mod m));clear H4
757    [elim H7.clear H7.
758     elim H4.clear H4.
759     assumption
760    |apply (lt_times_to_lt_div ? ? ? H5)
761    |apply lt_mod_m_m.
762     apply (lt_times_to_lt_O ? ? ? H5)
763    |apply (andb_true_true ? ? H6)
764    |apply (andb_true_true_r ? ? H6)
765    ]
766  |intros.
767   elim (H4 (i/m) (i \mod m));clear H4
768    [elim H7.clear H7.
769     elim H4.clear H4.
770     rewrite > H10.
771     rewrite > H9.
772     apply sym_eq.
773     apply div_mod.
774     apply (lt_times_to_lt_O ? ? ? H5)
775    |apply (lt_times_to_lt_div ? ? ? H5)
776    |apply lt_mod_m_m.
777     apply (lt_times_to_lt_O ? ? ? H5)  
778    |apply (andb_true_true ? ? H6)
779    |apply (andb_true_true_r ? ? H6)
780    ]
781  |intros.
782   elim (H4 (i/m) (i \mod m));clear H4
783    [elim H7.clear H7.
784     elim H4.clear H4.
785     assumption
786    |apply (lt_times_to_lt_div ? ? ? H5)
787    |apply lt_mod_m_m.
788     apply (lt_times_to_lt_O ? ? ? H5)
789    |apply (andb_true_true ? ? H6)
790    |apply (andb_true_true_r ? ? H6)
791    ]
792  |intros.
793   elim (H3 j H5 H6).
794   elim H7.clear H7.
795   elim H9.clear H9.
796   elim H7.clear H7.
797   rewrite > div_plus_times
798    [rewrite > mod_plus_times
799      [rewrite > H9.
800       rewrite > H12.
801       reflexivity.
802      |assumption
803      ]
804    |assumption
805    ]
806  |intros.
807   elim (H3 j H5 H6).
808   elim H7.clear H7.
809   elim H9.clear H9.
810   elim H7.clear H7. 
811   rewrite > div_plus_times
812    [rewrite > mod_plus_times
813      [assumption
814      |assumption
815      ]
816    |assumption
817    ]
818  |intros.
819   elim (H3 j H5 H6).
820   elim H7.clear H7.
821   elim H9.clear H9.
822   elim H7.clear H7. 
823   apply (lt_to_le_to_lt ? ((h11 j)*m+m))
824    [apply monotonic_lt_plus_r.
825     assumption
826    |rewrite > sym_plus.
827     change with ((S (h11 j)*m) \le n*m).
828     apply monotonic_le_times_l.
829     assumption
830    ]
831  ]
832 qed.
833
834 theorem iter_p_gen_divides:
835 \forall A:Type.
836 \forall baseA: A.
837 \forall plusA: A \to A \to A. 
838 \forall n,m,p:nat.O < n \to prime p \to Not (divides p n) \to 
839 \forall g: nat \to A.
840 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a  baseA) = a)
841
842 \to
843
844 iter_p_gen (S (n*(exp p m))) (\lambda x.divides_b x (n*(exp p m))) A g baseA plusA =
845 iter_p_gen (S n) (\lambda x.divides_b x n) A
846   (\lambda x.iter_p_gen (S m) (\lambda y.true) A (\lambda y.g (x*(exp p y))) baseA plusA) baseA plusA.
847 intros.
848 cut (O < p)
849   [rewrite < (iter_p_gen2 ? ? ? ? ? ? ? ? H3 H4 H5).
850    apply (trans_eq ? ? 
851     (iter_p_gen (S n*S m) (\lambda x:nat.divides_b (x/S m) n) A
852        (\lambda x:nat.g (x/S m*(p)\sup(x\mod S m)))  baseA plusA) )
853     [apply sym_eq.
854      apply (eq_iter_p_gen_gh ? ? ? ? ? ? g ? (p_ord_times p (S m)))
855       [ assumption
856       | assumption
857       | assumption
858       |intros.
859        lapply (divides_b_true_to_lt_O ? ? H H7).
860        apply divides_to_divides_b_true
861         [rewrite > (times_n_O O).
862          apply lt_times
863           [assumption
864           |apply lt_O_exp.assumption
865           ]
866         |apply divides_times
867           [apply divides_b_true_to_divides.assumption
868           |apply (witness ? ? (p \sup (m-i \mod (S m)))).
869            rewrite < exp_plus_times.
870            apply eq_f.
871            rewrite > sym_plus.
872            apply plus_minus_m_m.
873            autobatch
874           ]
875         ]
876       |intros.
877        lapply (divides_b_true_to_lt_O ? ? H H7).
878        unfold p_ord_times.
879        rewrite > (p_ord_exp1 p ? (i \mod (S m)) (i/S m))
880         [change with ((i/S m)*S m+i \mod S m=i).
881          apply sym_eq.
882          apply div_mod.
883          apply lt_O_S
884         |assumption
885         |unfold Not.intro.
886          apply H2.
887          apply (trans_divides ? (i/ S m))
888           [assumption|
889            apply divides_b_true_to_divides;assumption]
890         |apply sym_times.
891         ]
892       |intros.
893        apply le_S_S.
894        apply le_times
895         [apply le_S_S_to_le.
896          change with ((i/S m) < S n).
897          apply (lt_times_to_lt_l m).
898          apply (le_to_lt_to_lt ? i)
899           [autobatch|assumption]
900         |apply le_exp
901           [assumption
902           |apply le_S_S_to_le.
903            apply lt_mod_m_m.
904            apply lt_O_S
905           ]
906         ]
907       |intros.
908        cut (ord j p < S m)
909         [rewrite > div_p_ord_times
910           [apply divides_to_divides_b_true
911             [apply lt_O_ord_rem
912              [elim H1.assumption
913              |apply (divides_b_true_to_lt_O ? ? ? H7).
914                rewrite > (times_n_O O).
915                apply lt_times
916                [assumption|apply lt_O_exp.assumption]
917              ]
918            |cut (n = ord_rem (n*(exp p m)) p)
919               [rewrite > Hcut2.
920                apply divides_to_divides_ord_rem
921                 [apply (divides_b_true_to_lt_O ? ? ? H7).
922                  rewrite > (times_n_O O).
923                  apply lt_times
924                  [assumption|apply lt_O_exp.assumption]
925                  |rewrite > (times_n_O O).
926                    apply lt_times
927                   [assumption|apply lt_O_exp.assumption]
928                |assumption
929                |apply divides_b_true_to_divides.
930                 assumption
931                ]
932               |unfold ord_rem.
933               rewrite > (p_ord_exp1 p ? m n)
934                 [reflexivity
935                |assumption
936                 |assumption
937                |apply sym_times
938                ]
939              ]
940             ]
941           |assumption
942           ]
943         |cut (m = ord (n*(exp p m)) p)
944           [apply le_S_S.
945            rewrite > Hcut1.
946            apply divides_to_le_ord
947             [apply (divides_b_true_to_lt_O ? ? ? H7).
948              rewrite > (times_n_O O).
949              apply lt_times
950               [assumption|apply lt_O_exp.assumption]
951             |rewrite > (times_n_O O).
952              apply lt_times
953               [assumption|apply lt_O_exp.assumption]
954             |assumption
955             |apply divides_b_true_to_divides.
956              assumption
957             ]
958           |unfold ord.
959            rewrite > (p_ord_exp1 p ? m n)
960             [reflexivity
961             |assumption
962             |assumption
963             |apply sym_times
964             ]
965           ]
966         ]
967       |intros.
968        cut (ord j p < S m)
969         [rewrite > div_p_ord_times
970           [rewrite > mod_p_ord_times
971             [rewrite > sym_times.
972              apply sym_eq.
973              apply exp_ord
974               [elim H1.assumption
975               |apply (divides_b_true_to_lt_O ? ? ? H7).
976                rewrite > (times_n_O O).
977                apply lt_times
978                 [assumption|apply lt_O_exp.assumption]
979               ]
980            |cut (m = ord (n*(exp p m)) p)
981              [apply le_S_S.
982               rewrite > Hcut2.
983               apply divides_to_le_ord
984                [apply (divides_b_true_to_lt_O ? ? ? H7).
985                 rewrite > (times_n_O O).
986                 apply lt_times
987                  [assumption|apply lt_O_exp.assumption]
988                |rewrite > (times_n_O O).
989                 apply lt_times
990                  [assumption|apply lt_O_exp.assumption]
991                |assumption
992                |apply divides_b_true_to_divides.
993                 assumption
994                ]
995              |unfold ord.
996               rewrite > (p_ord_exp1 p ? m n)
997                 [reflexivity
998                 |assumption
999                 |assumption
1000                 |apply sym_times
1001                 ]
1002               ]
1003             ]
1004           |assumption
1005           ]
1006         |cut (m = ord (n*(exp p m)) p)
1007           [apply le_S_S.
1008            rewrite > Hcut1.
1009            apply divides_to_le_ord
1010             [apply (divides_b_true_to_lt_O ? ? ? H7).
1011              rewrite > (times_n_O O).
1012              apply lt_times
1013               [assumption|apply lt_O_exp.assumption]
1014             |rewrite > (times_n_O O).
1015              apply lt_times
1016               [assumption|apply lt_O_exp.assumption]
1017             |assumption
1018             |apply divides_b_true_to_divides.
1019              assumption
1020             ]
1021           |unfold ord.
1022            rewrite > (p_ord_exp1 p ? m n)
1023             [reflexivity
1024             |assumption
1025             |assumption
1026             |apply sym_times
1027             ]
1028           ]
1029         ]
1030       |intros.
1031        rewrite > eq_p_ord_times.
1032        rewrite > sym_plus.
1033        apply (lt_to_le_to_lt ? (S m +ord_rem j p*S m))
1034         [apply lt_plus_l.
1035          apply le_S_S.
1036          cut (m = ord (n*(p \sup m)) p)
1037           [rewrite > Hcut1.
1038            apply divides_to_le_ord
1039             [apply (divides_b_true_to_lt_O ? ? ? H7).
1040              rewrite > (times_n_O O).
1041              apply lt_times
1042               [assumption|apply lt_O_exp.assumption]
1043             |rewrite > (times_n_O O).
1044              apply lt_times
1045               [assumption|apply lt_O_exp.assumption]
1046             |assumption
1047             |apply divides_b_true_to_divides.
1048              assumption
1049             ]
1050           |unfold ord.
1051            rewrite > sym_times.
1052            rewrite > (p_ord_exp1 p ? m n)
1053             [reflexivity
1054             |assumption
1055             |assumption
1056             |reflexivity
1057             ]
1058           ]
1059         |change with (S (ord_rem j p)*S m \le S n*S m).
1060          apply le_times_l.
1061          apply le_S_S.
1062          cut (n = ord_rem (n*(p \sup m)) p)
1063           [rewrite > Hcut1.
1064            apply divides_to_le
1065             [apply lt_O_ord_rem
1066               [elim H1.assumption
1067               |rewrite > (times_n_O O).
1068                apply lt_times
1069                 [assumption|apply lt_O_exp.assumption]
1070               ]
1071             |apply divides_to_divides_ord_rem
1072               [apply (divides_b_true_to_lt_O ? ? ? H7).
1073                rewrite > (times_n_O O).
1074                apply lt_times
1075                 [assumption|apply lt_O_exp.assumption]
1076               |rewrite > (times_n_O O).
1077                apply lt_times
1078                 [assumption|apply lt_O_exp.assumption]
1079               |assumption
1080               |apply divides_b_true_to_divides.
1081                assumption
1082               ]
1083             ]
1084         |unfold ord_rem.
1085          rewrite > sym_times.
1086          rewrite > (p_ord_exp1 p ? m n)
1087           [reflexivity
1088           |assumption
1089           |assumption
1090           |reflexivity
1091           ]
1092         ]
1093       ]
1094     ]
1095   |apply eq_iter_p_gen
1096   
1097     [intros.
1098      elim (divides_b (x/S m) n);reflexivity
1099     |intros.reflexivity
1100     ]
1101   ]
1102 |elim H1.apply lt_to_le.assumption
1103 ]
1104 qed.
1105     
1106 (*distributive property for iter_p_gen*)
1107 theorem distributive_times_plus_iter_p_gen: \forall A:Type.
1108 \forall plusA: A \to A \to A. \forall basePlusA: A.
1109 \forall timesA: A \to A \to A. 
1110 \forall n:nat. \forall k:A. \forall p:nat \to bool. \forall g:nat \to A.
1111 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a  basePlusA) = a) \to
1112 (symmetric A timesA) \to (distributive A timesA plusA) \to
1113 (\forall a:A. (timesA a basePlusA) = basePlusA)
1114  
1115   \to
1116
1117 ((timesA k (iter_p_gen n p A g basePlusA plusA)) = 
1118  (iter_p_gen n p A (\lambda i:nat.(timesA k (g i))) basePlusA plusA)).
1119 intros.
1120 elim n
1121 [ simplify.
1122   apply H5
1123 | cut( (p n1) = true \lor (p n1) = false)
1124   [ elim Hcut
1125     [ rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H7).
1126       rewrite > (true_to_iter_p_gen_Sn ? ? ? ? ? ? H7) in \vdash (? ? ? %).
1127       rewrite > (H4).
1128       rewrite > (H3 k (g n1)).
1129       apply eq_f.
1130       assumption
1131     | rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H7).
1132       rewrite > (false_to_iter_p_gen_Sn ? ? ? ? ? ? H7) in \vdash (? ? ? %).
1133       assumption
1134     ]
1135   | elim ((p n1))
1136     [ left.
1137       reflexivity
1138     | right.
1139       reflexivity
1140     ]
1141   ]
1142 ]
1143 qed.
1144
1145 (* old version - proved without theorem iter_p_gen_knm
1146 theorem iter_p_gen_2_eq: 
1147 \forall A:Type.
1148 \forall baseA: A.
1149 \forall plusA: A \to A \to A. 
1150 (symmetric A plusA) \to 
1151 (associative A plusA) \to 
1152 (\forall a:A.(plusA a  baseA) = a)\to
1153 \forall g: nat \to nat \to A.
1154 \forall h11,h12,h21,h22: nat \to nat \to nat. 
1155 \forall n1,m1,n2,m2.
1156 \forall p11,p21:nat \to bool.
1157 \forall p12,p22:nat \to nat \to bool.
1158 (\forall i,j. i < n2 \to j < m2 \to p21 i = true \to p22 i j = true \to 
1159 p11 (h11 i j) = true \land p12 (h11 i j) (h12 i j) = true
1160 \land h21 (h11 i j) (h12 i j) = i \land h22 (h11 i j) (h12 i j) = j
1161 \land h11 i j < n1 \land h12 i j < m1) \to
1162 (\forall i,j. i < n1 \to j < m1 \to p11 i = true \to p12 i j = true \to 
1163 p21 (h21 i j) = true \land p22 (h21 i j) (h22 i j) = true
1164 \land h11 (h21 i j) (h22 i j) = i \land h12 (h21 i j) (h22 i j) = j
1165 \land (h21 i j) < n2 \land (h22 i j) < m2) \to
1166 iter_p_gen n1 p11 A 
1167      (\lambda x:nat .iter_p_gen m1 (p12 x) A (\lambda y. g x y) baseA plusA) 
1168      baseA plusA =
1169 iter_p_gen n2 p21 A 
1170     (\lambda x:nat .iter_p_gen m2 (p22 x) A  (\lambda y. g (h11 x y) (h12 x y)) baseA plusA )
1171     baseA plusA.
1172 intros.
1173 rewrite < (iter_p_gen2' ? ? ? ? ? ? ? ? H H1 H2).
1174 rewrite < (iter_p_gen2' ? ? ? ? ? ? ? ? H H1 H2).
1175 apply sym_eq.
1176 letin h := (\lambda x.(h11 (x/m2) (x\mod m2))*m1 + (h12 (x/m2) (x\mod m2))).
1177 letin h1 := (\lambda x.(h21 (x/m1) (x\mod m1))*m2 + (h22 (x/m1) (x\mod m1))).
1178 apply (trans_eq ? ? 
1179   (iter_p_gen (n2*m2) (\lambda x:nat.p21 (x/m2)\land p22 (x/m2) (x\mod m2)) A
1180   (\lambda x:nat.g ((h x)/m1) ((h x)\mod m1)) baseA plusA ))
1181   [clear h.clear h1.
1182    apply eq_iter_p_gen1
1183     [intros.reflexivity
1184     |intros.
1185      cut (O < m2)
1186       [cut (x/m2 < n2)
1187         [cut (x \mod m2 < m2)
1188           [elim (and_true ? ? H6).
1189            elim (H3 ? ? Hcut1 Hcut2 H7 H8).
1190            elim H9.clear H9.
1191            elim H11.clear H11.
1192            elim H9.clear H9.
1193            elim H11.clear H11.
1194            apply eq_f2
1195             [apply sym_eq.
1196              apply div_plus_times.
1197              assumption
1198             | apply sym_eq.
1199               apply mod_plus_times.
1200               assumption
1201             ]
1202           |apply lt_mod_m_m.
1203            assumption
1204           ]
1205         |apply (lt_times_n_to_lt m2)
1206           [assumption
1207           |apply (le_to_lt_to_lt ? x)
1208             [apply (eq_plus_to_le ? ? (x \mod m2)).
1209              apply div_mod.
1210              assumption
1211             |assumption
1212             ]
1213           ]
1214         ]
1215       |apply not_le_to_lt.unfold.intro.
1216        generalize in match H5.
1217        apply (le_n_O_elim ? H7).
1218        rewrite < times_n_O.
1219        apply le_to_not_lt.
1220        apply le_O_n  
1221       ]      
1222     ]
1223   |apply (eq_iter_p_gen_gh ? ? ? H H1 H2 ? h h1);intros
1224     [cut (O < m2)
1225       [cut (i/m2 < n2)
1226         [cut (i \mod m2 < m2)
1227           [elim (and_true ? ? H6).
1228            elim (H3 ? ? Hcut1 Hcut2 H7 H8).
1229            elim H9.clear H9.
1230            elim H11.clear H11.
1231            elim H9.clear H9.
1232            elim H11.clear H11.
1233            cut ((h11 (i/m2) (i\mod m2)*m1+h12 (i/m2) (i\mod m2))/m1 = 
1234                  h11 (i/m2) (i\mod m2))
1235             [cut ((h11 (i/m2) (i\mod m2)*m1+h12 (i/m2) (i\mod m2))\mod m1 =
1236                   h12 (i/m2) (i\mod m2))
1237               [rewrite > Hcut3.
1238                rewrite > Hcut4.
1239                rewrite > H9.
1240                rewrite > H15.
1241                reflexivity
1242               |apply mod_plus_times. 
1243                assumption
1244               ]
1245             |apply div_plus_times.
1246              assumption
1247             ]
1248           |apply lt_mod_m_m.
1249            assumption
1250           ]
1251         |apply (lt_times_n_to_lt m2)
1252           [assumption
1253           |apply (le_to_lt_to_lt ? i)
1254             [apply (eq_plus_to_le ? ? (i \mod m2)).
1255              apply div_mod.
1256              assumption
1257             |assumption
1258             ]
1259           ]
1260         ]
1261       |apply not_le_to_lt.unfold.intro.
1262        generalize in match H5.
1263        apply (le_n_O_elim ? H7).
1264        rewrite < times_n_O.
1265        apply le_to_not_lt.
1266        apply le_O_n  
1267       ]      
1268     |cut (O < m2)
1269       [cut (i/m2 < n2)
1270         [cut (i \mod m2 < m2)
1271           [elim (and_true ? ? H6).
1272            elim (H3 ? ? Hcut1 Hcut2 H7 H8).
1273            elim H9.clear H9.
1274            elim H11.clear H11.
1275            elim H9.clear H9.
1276            elim H11.clear H11.
1277            cut ((h11 (i/m2) (i\mod m2)*m1+h12 (i/m2) (i\mod m2))/m1 = 
1278                  h11 (i/m2) (i\mod m2))
1279             [cut ((h11 (i/m2) (i\mod m2)*m1+h12 (i/m2) (i\mod m2))\mod m1 =
1280                   h12 (i/m2) (i\mod m2))
1281               [rewrite > Hcut3.
1282                rewrite > Hcut4.
1283                rewrite > H13.
1284                rewrite > H14.
1285                apply sym_eq.
1286                apply div_mod.
1287                assumption
1288               |apply mod_plus_times. 
1289                assumption
1290               ]
1291             |apply div_plus_times.
1292              assumption
1293             ]
1294           |apply lt_mod_m_m.
1295            assumption
1296           ]
1297         |apply (lt_times_n_to_lt m2)
1298           [assumption
1299           |apply (le_to_lt_to_lt ? i)
1300             [apply (eq_plus_to_le ? ? (i \mod m2)).
1301              apply div_mod.
1302              assumption
1303             |assumption
1304             ]
1305           ]
1306         ]
1307       |apply not_le_to_lt.unfold.intro.
1308        generalize in match H5.
1309        apply (le_n_O_elim ? H7).
1310        rewrite < times_n_O.
1311        apply le_to_not_lt.
1312        apply le_O_n  
1313       ]      
1314     |cut (O < m2)
1315       [cut (i/m2 < n2)
1316         [cut (i \mod m2 < m2)
1317           [elim (and_true ? ? H6).
1318            elim (H3 ? ? Hcut1 Hcut2 H7 H8).
1319            elim H9.clear H9.
1320            elim H11.clear H11.
1321            elim H9.clear H9.
1322            elim H11.clear H11.
1323            apply lt_times_plus_times
1324             [assumption|assumption]
1325           |apply lt_mod_m_m.
1326            assumption
1327           ]
1328         |apply (lt_times_n_to_lt m2)
1329           [assumption
1330           |apply (le_to_lt_to_lt ? i)
1331             [apply (eq_plus_to_le ? ? (i \mod m2)).
1332              apply div_mod.
1333              assumption
1334             |assumption
1335             ]
1336           ]
1337         ]
1338       |apply not_le_to_lt.unfold.intro.
1339        generalize in match H5.
1340        apply (le_n_O_elim ? H7).
1341        rewrite < times_n_O.
1342        apply le_to_not_lt.
1343        apply le_O_n  
1344       ]
1345     |cut (O < m1)
1346       [cut (j/m1 < n1)
1347         [cut (j \mod m1 < m1)
1348           [elim (and_true ? ? H6).
1349            elim (H4 ? ? Hcut1 Hcut2 H7 H8).
1350            elim H9.clear H9.
1351            elim H11.clear H11.
1352            elim H9.clear H9.
1353            elim H11.clear H11.
1354            cut ((h21 (j/m1) (j\mod m1)*m2+h22 (j/m1) (j\mod m1))/m2 = 
1355                  h21 (j/m1) (j\mod m1))
1356             [cut ((h21 (j/m1) (j\mod m1)*m2+h22 (j/m1) (j\mod m1))\mod m2 =
1357                   h22 (j/m1) (j\mod m1))
1358               [rewrite > Hcut3.
1359                rewrite > Hcut4.
1360                rewrite > H9.
1361                rewrite > H15.
1362                reflexivity
1363               |apply mod_plus_times. 
1364                assumption
1365               ]
1366             |apply div_plus_times.
1367              assumption
1368             ]
1369           |apply lt_mod_m_m.
1370            assumption
1371           ] 
1372         |apply (lt_times_n_to_lt m1)
1373           [assumption
1374           |apply (le_to_lt_to_lt ? j)
1375             [apply (eq_plus_to_le ? ? (j \mod m1)).
1376              apply div_mod.
1377              assumption
1378             |assumption
1379             ]
1380           ]
1381         ]
1382       |apply not_le_to_lt.unfold.intro.
1383        generalize in match H5.
1384        apply (le_n_O_elim ? H7).
1385        rewrite < times_n_O.
1386        apply le_to_not_lt.
1387        apply le_O_n  
1388       ] 
1389     |cut (O < m1)
1390       [cut (j/m1 < n1)
1391         [cut (j \mod m1 < m1)
1392           [elim (and_true ? ? H6).
1393            elim (H4 ? ? Hcut1 Hcut2 H7 H8).
1394            elim H9.clear H9.
1395            elim H11.clear H11.
1396            elim H9.clear H9.
1397            elim H11.clear H11.
1398            cut ((h21 (j/m1) (j\mod m1)*m2+h22 (j/m1) (j\mod m1))/m2 = 
1399                  h21 (j/m1) (j\mod m1))
1400             [cut ((h21 (j/m1) (j\mod m1)*m2+h22 (j/m1) (j\mod m1))\mod m2 =
1401                   h22 (j/m1) (j\mod m1))
1402               [rewrite > Hcut3.
1403                rewrite > Hcut4.               
1404                rewrite > H13.
1405                rewrite > H14.
1406                apply sym_eq.
1407                apply div_mod.
1408                assumption
1409               |apply mod_plus_times. 
1410                assumption
1411               ]
1412             |apply div_plus_times.
1413              assumption
1414             ]
1415           |apply lt_mod_m_m.
1416            assumption
1417           ] 
1418         |apply (lt_times_n_to_lt m1)
1419           [assumption
1420           |apply (le_to_lt_to_lt ? j)
1421             [apply (eq_plus_to_le ? ? (j \mod m1)).
1422              apply div_mod.
1423              assumption
1424             |assumption
1425             ]
1426           ]
1427         ]
1428       |apply not_le_to_lt.unfold.intro.
1429        generalize in match H5.
1430        apply (le_n_O_elim ? H7).
1431        rewrite < times_n_O.
1432        apply le_to_not_lt.
1433        apply le_O_n  
1434       ] 
1435     |cut (O < m1)
1436       [cut (j/m1 < n1)
1437         [cut (j \mod m1 < m1)
1438           [elim (and_true ? ? H6).
1439            elim (H4 ? ? Hcut1 Hcut2 H7 H8).
1440            elim H9.clear H9.
1441            elim H11.clear H11.
1442            elim H9.clear H9.
1443            elim H11.clear H11.
1444            apply (lt_times_plus_times ? ? ? m2)
1445             [assumption|assumption]
1446           |apply lt_mod_m_m.
1447            assumption
1448           ] 
1449         |apply (lt_times_n_to_lt m1)
1450           [assumption
1451           |apply (le_to_lt_to_lt ? j)
1452             [apply (eq_plus_to_le ? ? (j \mod m1)).
1453              apply div_mod.
1454              assumption
1455             |assumption
1456             ]
1457           ]
1458         ]
1459       |apply not_le_to_lt.unfold.intro.
1460        generalize in match H5.
1461        apply (le_n_O_elim ? H7).
1462        rewrite < times_n_O.
1463        apply le_to_not_lt.
1464        apply le_O_n  
1465       ]
1466     ]
1467   ]
1468 qed.*)
1469
1470
1471 theorem iter_p_gen_2_eq: 
1472 \forall A:Type.
1473 \forall baseA: A.
1474 \forall plusA: A \to A \to A. 
1475 (symmetric A plusA) \to 
1476 (associative A plusA) \to 
1477 (\forall a:A.(plusA a  baseA) = a)\to
1478 \forall g: nat \to nat \to A.
1479 \forall h11,h12,h21,h22: nat \to nat \to nat. 
1480 \forall n1,m1,n2,m2.
1481 \forall p11,p21:nat \to bool.
1482 \forall p12,p22:nat \to nat \to bool.
1483 (\forall i,j. i < n2 \to j < m2 \to p21 i = true \to p22 i j = true \to 
1484 p11 (h11 i j) = true \land p12 (h11 i j) (h12 i j) = true
1485 \land h21 (h11 i j) (h12 i j) = i \land h22 (h11 i j) (h12 i j) = j
1486 \land h11 i j < n1 \land h12 i j < m1) \to
1487 (\forall i,j. i < n1 \to j < m1 \to p11 i = true \to p12 i j = true \to 
1488 p21 (h21 i j) = true \land p22 (h21 i j) (h22 i j) = true
1489 \land h11 (h21 i j) (h22 i j) = i \land h12 (h21 i j) (h22 i j) = j
1490 \land (h21 i j) < n2 \land (h22 i j) < m2) \to
1491 iter_p_gen n1 p11 A 
1492      (\lambda x:nat .iter_p_gen m1 (p12 x) A (\lambda y. g x y) baseA plusA) 
1493      baseA plusA =
1494 iter_p_gen n2 p21 A 
1495     (\lambda x:nat .iter_p_gen m2 (p22 x) A  (\lambda y. g (h11 x y) (h12 x y)) baseA plusA )
1496     baseA plusA.
1497
1498 intros.
1499 rewrite < (iter_p_gen2' ? ? ? ? ? ? ? ? H H1 H2).
1500 letin ha:= (\lambda x,y.(((h11 x y)*m1) + (h12 x y))).
1501 letin ha12:= (\lambda x.(h21 (x/m1) (x \mod m1))).
1502 letin ha22:= (\lambda x.(h22 (x/m1) (x \mod m1))).
1503
1504 apply (trans_eq ? ? 
1505 (iter_p_gen n2 p21 A (\lambda x:nat. iter_p_gen m2 (p22 x) A
1506  (\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))
1507 [
1508   apply (iter_p_gen_knm A baseA plusA H H1 H2 (\lambda e. (g (e/m1) (e \mod m1))) ha ha12 ha22);intros
1509   [ elim (and_true ? ? H6).
1510     cut(O \lt m1)
1511     [ cut(x/m1 < n1)
1512       [ cut((x \mod m1) < m1)
1513         [ elim (H4 ? ? Hcut1 Hcut2 H7 H8).
1514           elim H9.clear H9.
1515           elim H11.clear H11.
1516           elim H9.clear H9.
1517           elim H11.clear H11.
1518           split
1519           [ split
1520             [ split
1521               [ split
1522                 [ assumption
1523                 | assumption
1524                 ]
1525               | rewrite > H14.
1526                 rewrite > H13.
1527                 apply sym_eq.
1528                 apply div_mod.
1529                 assumption
1530               ]
1531             | assumption
1532             ]
1533           | assumption
1534           ]
1535         | apply lt_mod_m_m.
1536           assumption
1537         ]
1538       | apply (lt_times_n_to_lt m1)
1539         [ assumption
1540         | apply (le_to_lt_to_lt ? x)
1541           [ apply (eq_plus_to_le ? ? (x \mod m1)).
1542             apply div_mod.
1543             assumption
1544           | assumption
1545         ]
1546       ]  
1547     ]
1548     | apply not_le_to_lt.unfold.intro.
1549       generalize in match H5.
1550       apply (le_n_O_elim ? H9).
1551       rewrite < times_n_O.
1552       apply le_to_not_lt.
1553       apply le_O_n.              
1554     ]
1555   | elim (H3 ? ? H5 H6 H7 H8).
1556     elim H9.clear H9.
1557     elim H11.clear H11.
1558     elim H9.clear H9.
1559     elim H11.clear H11.
1560     cut(((h11 i j)*m1 + (h12 i j))/m1 = (h11 i j))
1561     [ cut(((h11 i j)*m1 + (h12 i j)) \mod m1 = (h12 i j))
1562       [ split
1563         [ split
1564           [ split
1565             [ apply true_to_true_to_andb_true
1566               [ rewrite > Hcut.
1567                 assumption
1568               | rewrite > Hcut1.
1569                 rewrite > Hcut.
1570                 assumption
1571               ] 
1572             | rewrite > Hcut1.
1573               rewrite > Hcut.
1574               assumption
1575             ]
1576           | rewrite > Hcut1.
1577             rewrite > Hcut.
1578             assumption            
1579           ]
1580         | cut(O \lt m1)
1581           [ cut(O \lt n1)      
1582             [ apply (lt_to_le_to_lt ? ((h11 i j)*m1 + m1) )
1583               [ apply (lt_plus_r).
1584                 assumption
1585               | rewrite > sym_plus.
1586                 rewrite > (sym_times (h11 i j) m1).
1587                 rewrite > times_n_Sm.
1588                 rewrite > sym_times.
1589                 apply (le_times_l).
1590                 assumption  
1591               ]
1592             | apply not_le_to_lt.unfold.intro.
1593               generalize in match H12.
1594               apply (le_n_O_elim ? H11).       
1595               apply le_to_not_lt.
1596               apply le_O_n
1597             ]
1598           | apply not_le_to_lt.unfold.intro.
1599             generalize in match H10.
1600             apply (le_n_O_elim ? H11).       
1601             apply le_to_not_lt.
1602             apply le_O_n
1603           ]  
1604         ]
1605       | rewrite > (mod_plus_times m1 (h11 i j) (h12 i j)).
1606         reflexivity.
1607         assumption
1608       ]     
1609     | rewrite > (div_plus_times m1 (h11 i j) (h12 i j)).
1610       reflexivity.
1611       assumption
1612     ]
1613   ]
1614 | apply (eq_iter_p_gen1)
1615   [ intros. reflexivity 
1616   | intros.
1617     apply (eq_iter_p_gen1)
1618     [ intros. reflexivity
1619     | intros.
1620       rewrite > (div_plus_times)
1621       [ rewrite > (mod_plus_times)
1622         [ reflexivity
1623         | elim (H3 x x1 H5 H7 H6 H8).
1624           assumption
1625         ]
1626       | elim (H3 x x1 H5 H7 H6 H8).       
1627         assumption
1628       ]
1629     ]
1630   ]
1631 ]
1632 qed.
1633
1634
1635
1636
1637