]> matita.cs.unibo.it Git - helm.git/blob - matita/library/nat/generic_iter_p.ma
c424f82e0318064b1a31ee6c406d4f8b55089327
[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