1 (**************************************************************************)
4 (* ||A|| A project by Andrea Asperti *)
6 (* ||I|| Developers: *)
7 (* ||T|| A.Asperti, C.Sacerdoti Coen, *)
8 (* ||A|| E.Tassi, S.Zacchiroli *)
10 (* \ / Matita is distributed under the terms of the *)
11 (* v GNU Lesser General Public License Version 2.1 *)
13 (**************************************************************************)
15 set "baseuri" "cic:/matita/library_auto/nat/gcd".
17 include "auto/nat/primes.ma".
19 let rec gcd_aux p m n: nat \def
20 match divides_b n m with
25 |(S q) \Rightarrow gcd_aux q n (m \mod n)]].
27 definition gcd : nat \to nat \to nat \def
33 | (S p) \Rightarrow gcd_aux (S p) m (S p) ]
37 | (S p) \Rightarrow gcd_aux (S p) n (S p) ]].
39 theorem divides_mod: \forall p,m,n:nat. O < n \to p \divides m \to p \divides n \to
40 p \divides (m \mod n).
41 intros.elim H1.elim H2.
42 apply (witness ? ? (n2 - n1*(m / n))).
44 rewrite > distr_times_minus.
45 rewrite < H3 in \vdash (? ? ? (? % ?)).
46 rewrite < assoc_times.
47 rewrite < H4 in \vdash (? ? ? (? ? (? % ?))).
53 rewrite < (div_mod ? ? H).
58 theorem divides_mod_to_divides: \forall p,m,n:nat. O < n \to
59 p \divides (m \mod n) \to p \divides n \to p \divides m.
63 apply (witness p m ((n1*(m / n))+n2)).
64 rewrite > distr_times_plus.
66 rewrite < assoc_times.
75 theorem divides_gcd_aux_mn: \forall p,m,n. O < n \to n \le m \to n \le p \to
76 gcd_aux p m n \divides m \land gcd_aux p m n \divides n.
84 | cut ((n1 \divides m) \lor (n1 \ndivides m))
87 [ rewrite > divides_to_divides_b_true
92 | apply (witness n1 n1 (S O)).
98 | rewrite > not_divides_to_divides_b_false
100 cut (gcd_aux n n1 (m \mod n1) \divides n1 \land
101 gcd_aux n n1 (m \mod n1) \divides mod m n1)
105 [ apply (divides_mod_to_divides ? ? n1);assumption
109 [ cut (O \lt m \mod n1 \lor O = mod m n1)
115 apply mod_O_to_divides
122 (*apply le_to_or_lt_eq.
129 | apply le_S_S_to_le.
130 apply (trans_le ? n1);auto
131 (*[ auto.change with (m \mod n1 < n1).
143 (*apply (decidable_divides n1 m).
149 theorem divides_gcd_nm: \forall n,m.
150 gcd n m \divides m \land gcd n m \divides n.
152 (*CSC: simplify simplifies too much because of a redex in gcd *)
158 | (S p) \Rightarrow gcd_aux (S p) m (S p) ]
162 | (S p) \Rightarrow gcd_aux (S p) n (S p) ] ] \divides m
168 | (S p) \Rightarrow gcd_aux (S p) m (S p) ]
172 | (S p) \Rightarrow gcd_aux (S p) n (S p) ] ] \divides n).
174 [ apply (nat_case1 n)
179 [ apply (witness m m (S O)).
181 | apply (witness m O O).
186 (gcd_aux (S m1) m (S m1) \divides m
188 gcd_aux (S m1) m (S m1) \divides (S m1)).
190 (*apply divides_gcd_aux_mn
205 [ apply (witness n O O).
207 | apply (witness n n (S O)).
212 (gcd_aux (S m1) n (S m1) \divides (S m1)
214 gcd_aux (S m1) n (S m1) \divides n).
215 cut (gcd_aux (S m1) n (S m1) \divides n
217 gcd_aux (S m1) n (S m1) \divides S m1)
221 | apply divides_gcd_aux_mn
226 | apply not_lt_to_le.
233 (*apply (trans_le ? (S n))
244 theorem divides_gcd_n: \forall n,m. gcd n m \divides n.
246 exact (proj2 ? ? (divides_gcd_nm n m)). (*auto non termina la dimostrazione*)
249 theorem divides_gcd_m: \forall n,m. gcd n m \divides m.
251 exact (proj1 ? ? (divides_gcd_nm n m)). (*auto non termina la dimostrazione*)
254 theorem divides_gcd_aux: \forall p,m,n,d. O < n \to n \le m \to n \le p \to
255 d \divides m \to d \divides n \to d \divides gcd_aux p m n.
258 [ absurd (O < n);auto
260 | apply le_to_not_lt.
264 cut (n1 \divides m \lor n1 \ndivides m)
266 rewrite > divides_to_divides_b_true;
273 rewrite > not_divides_to_divides_b_false
276 [ cut (O \lt m \mod n1 \lor O = m \mod n1)
280 absurd (n1 \divides m);auto
281 (*[ apply mod_O_to_divides
283 | apply sym_eq.assumption.
289 (*apply le_to_or_lt_eq.
296 | apply le_S_S_to_le.
298 (*apply (trans_le ? n1)
299 [ change with (m \mod n1 < n1).
313 (*apply (decidable_divides n1 m).
318 theorem divides_d_gcd: \forall m,n,d.
319 d \divides m \to d \divides n \to d \divides gcd n m.
321 (*CSC: here simplify simplifies too much because of a redex in gcd *)
328 | (S p) \Rightarrow gcd_aux (S p) m (S p) ]
332 | (S p) \Rightarrow gcd_aux (S p) n (S p) ]]).
334 [ apply (nat_case1 n)
339 change with (d \divides gcd_aux (S m1) m (S m1)).
340 apply divides_gcd_aux
345 | apply le_n. (*chiude il goal anche con auto*)
351 | apply (nat_case1 m)
356 change with (d \divides gcd_aux (S m1) n (S m1)).
357 apply divides_gcd_aux
365 | apply le_n (*chiude il goal anche con auto*)
374 theorem eq_minus_gcd_aux: \forall p,m,n.O < n \to n \le m \to n \le p \to
375 \exists a,b. a*n - b*m = gcd_aux p m n \lor b*m - a*n = gcd_aux p m n.
378 [ absurd (O < n);auto
384 [ cut (n1 \divides m \lor n1 \ndivides m)
387 [ rewrite > divides_to_divides_b_true
389 apply (ex_intro ? ? (S O)).
390 apply (ex_intro ? ? O).
395 apply sym_eq.apply minus_n_O*)
399 | rewrite > not_divides_to_divides_b_false
402 a*n1 - b*m = gcd_aux n n1 (m \mod n1)
404 b*m - a*n1 = gcd_aux n n1 (m \mod n1)).
407 a*(m \mod n1) - b*n1= gcd_aux n n1 (m \mod n1)
409 b*n1 - a*(m \mod n1) = gcd_aux n n1 (m \mod n1))
415 apply (ex_intro ? ? (a1+a*(m / n1))).
416 apply (ex_intro ? ? a).
419 rewrite < (sym_times n1).
420 rewrite > distr_times_plus.
421 rewrite > (sym_times n1).
422 rewrite > (sym_times n1).
423 rewrite > (div_mod m n1) in \vdash (? ? (? % ?) ?);auto
424 (*[ rewrite > assoc_times.
426 rewrite > distr_times_plus.
427 rewrite < eq_minus_minus_minus_plus.
428 rewrite < sym_plus.auto.
430 [ rewrite < minus_n_n.
438 apply (ex_intro ? ? (a1+a*(m / n1))).
439 apply (ex_intro ? ? a).
441 (* clear Hcut2.clear H5.clear H6.clear H. *)
443 rewrite > distr_times_plus.
445 rewrite > (sym_times n1).
446 rewrite > (div_mod m n1) in \vdash (? ? (? ? %) ?)
447 [ rewrite > distr_times_plus.
448 rewrite > assoc_times.
449 rewrite < eq_minus_minus_minus_plus.
451 (*rewrite < sym_plus.
453 [ rewrite < minus_n_n.
460 | apply (H n1 (m \mod n1))
461 [ cut (O \lt m \mod n1 \lor O = m \mod n1)
464 | absurd (n1 \divides m);auto
465 (*[ apply mod_O_to_divides
474 (*apply le_to_or_lt_eq.
481 | apply le_S_S_to_le.
483 (*apply (trans_le ? n1)
484 [ change with (m \mod n1 < n1).
496 (*apply (decidable_divides n1 m).
500 (*apply (lt_to_le_to_lt ? n1);assumption *)
505 theorem eq_minus_gcd:
506 \forall m,n.\exists a,b.a*n - b*m = (gcd n m) \lor b*m - a*n = (gcd n m).
510 [ apply (nat_case1 n)
513 apply (ex_intro ? ? O).
514 apply (ex_intro ? ? (S O)).
523 a*(S m1) - b*m = (gcd_aux (S m1) m (S m1))
524 \lor b*m - a*(S m1) = (gcd_aux (S m1) m (S m1))).
526 (*apply eq_minus_gcd_aux
534 | apply (nat_case1 m)
537 apply (ex_intro ? ? (S O)).
538 apply (ex_intro ? ? O).
547 a*n - b*(S m1) = (gcd_aux (S m1) n (S m1))
548 \lor b*(S m1) - a*n = (gcd_aux (S m1) n (S m1))).
551 a*(S m1) - b*n = (gcd_aux (S m1) n (S m1))
553 b*n - a*(S m1) = (gcd_aux (S m1) n (S m1)))
556 elim H3;apply (ex_intro ? ? a1);auto
557 (*[ apply (ex_intro ? ? a1).
558 apply (ex_intro ? ? a).
561 | apply (ex_intro ? ? a1).
562 apply (ex_intro ? ? a).
566 | apply eq_minus_gcd_aux;auto
570 | auto.apply lt_to_le.
580 (* some properties of gcd *)
582 theorem gcd_O_n: \forall n:nat. gcd O n = n.
584 (*intro.simplify.reflexivity.*)
587 theorem gcd_O_to_eq_O:\forall m,n:nat. (gcd m n) = O \to
590 cut (O \divides n \land O \divides m)
595 [ apply antisymmetric_divides
599 | apply antisymmetric_divides
609 theorem lt_O_gcd:\forall m,n:nat. O < n \to O < gcd m n.
613 apply (divides_to_lt_O (gcd m n) n ? ?);
615 |apply (divides_gcd_m m n).
620 theorem gcd_n_n: \forall n.gcd n n = n.
624 apply (antisymmetric_divides (gcd n n) n ? ?);
625 [apply (divides_gcd_n n n).
626 |apply (divides_d_gcd n n n ? ?);
627 [apply (reflexive_divides n).
628 |apply (reflexive_divides n).
634 theorem gcd_SO_to_lt_O: \forall i,n. (S O) < n \to gcd i n = (S O) \to
637 elim (le_to_or_lt_eq ? ? (le_O_n i))
639 | absurd ((gcd i n) = (S O))
645 apply (lt_to_not_eq (S O) n H).
653 theorem gcd_SO_to_lt_n: \forall i,n. (S O) < n \to i \le n \to gcd i n = (S O) \to
656 elim (le_to_or_lt_eq ? ? H1)
658 |absurd ((gcd i n) = (S O))
663 apply (lt_to_not_eq (S O) n H).
664 apply sym_eq.assumption
669 theorem gcd_n_times_nm: \forall n,m. O < m \to gcd n (n*m) = n.
670 intro.apply (nat_case n)
675 [apply lt_O_S|apply divides_gcd_n]
677 [apply lt_O_gcd.rewrite > (times_n_O O).
678 apply lt_times[apply lt_O_S|assumption]
680 [apply (witness ? ? m1).reflexivity
688 theorem symmetric_gcd: symmetric nat gcd.
689 (*CSC: bug here: unfold symmetric does not work *)
691 (\forall n,m:nat. gcd n m = gcd m n).
695 apply (antisymmetric_divides (gcd n m) (gcd m n) ? ?);
696 [apply (divides_d_gcd n m (gcd n m) ? ?);
697 [apply (divides_gcd_n n m).
698 |apply (divides_gcd_m n m).
700 |apply (divides_d_gcd m n (gcd m n) ? ?);
701 [apply (divides_gcd_n m n).
702 |apply (divides_gcd_m m n).
708 variant sym_gcd: \forall n,m:nat. gcd n m = gcd m n \def
711 theorem le_gcd_times: \forall m,n,p:nat. O< p \to gcd m n \le gcd m (n*p).
719 (*rewrite > (times_n_O O).
726 | apply divides_d_gcd;auto
727 (*[ apply (transitive_divides ? (S m1))
728 [ apply divides_gcd_m
729 | apply (witness ? ? p).
732 | apply divides_gcd_n
738 theorem gcd_times_SO_to_gcd_SO: \forall m,n,p:nat. O < n \to O < p \to
739 gcd m (n*p) = (S O) \to gcd m n = (S O).
741 apply antisymmetric_le
744 (*apply le_gcd_times.
747 (*change with (O < gcd m n).
753 (* for the "converse" of the previous result see the end of this development *)
755 theorem eq_gcd_SO_to_not_divides: \forall n,m. (S O) < n \to
756 (gcd n m) = (S O) \to \lnot (divides n m).
759 generalize in match H1.
763 [ elim (gcd_times_SO_to_gcd_SO n n n2 ? ? H4)
764 [ cut (gcd n (n*n2) = n);auto
765 (*[ auto.apply (lt_to_not_eq (S O) n)
770 | apply gcd_n_times_nm.
774 (*apply (trans_lt ? (S O))
780 | elim (le_to_or_lt_eq O n2 (le_O_n n2))
783 apply (le_to_not_lt n (S O))
785 apply divides_to_le;auto
788 | apply divides_d_gcd
789 [ apply (witness ? ? n2).
800 theorem gcd_SO_n: \forall n:nat. gcd (S O) n = (S O).
804 apply (symmetric_eq nat (S O) (gcd (S O) n) ?).
805 apply (antisymmetric_divides (S O) (gcd (S O) n) ? ?);
806 [apply (divides_SO_n (gcd (S O) n)).
807 |apply (divides_gcd_n (S O) n).
812 theorem divides_gcd_mod: \forall m,n:nat. O < n \to
813 divides (gcd m n) (gcd n (m \mod n)).
816 (*apply divides_d_gcd
819 | apply divides_gcd_n
820 | apply divides_gcd_m
822 | apply divides_gcd_m.
826 theorem divides_mod_gcd: \forall m,n:nat. O < n \to
827 divides (gcd n (m \mod n)) (gcd m n) .
830 (*apply divides_d_gcd
831 [ apply divides_gcd_n
832 | apply (divides_mod_to_divides ? ? n)
834 | apply divides_gcd_m
835 | apply divides_gcd_n
840 theorem gcd_mod: \forall m,n:nat. O < n \to
841 (gcd n (m \mod n)) = (gcd m n) .
844 (*apply antisymmetric_divides
845 [ apply divides_mod_gcd.
847 | apply divides_gcd_mod.
854 theorem prime_to_gcd_SO: \forall n,m:nat. prime n \to n \ndivides m \to
856 intros.unfold prime in H.
859 [ apply not_lt_to_le.unfold Not.unfold lt.
862 rewrite < (H3 (gcd n m));
863 [auto|auto| unfold lt; auto]
864 (*[ apply divides_gcd_m
865 | apply divides_gcd_n
868 | cut (O < gcd n m \lor O = gcd n m)
872 apply (not_le_Sn_O (S O)).
875 rewrite < H5 in \vdash (? ? %).
878 (*apply gcd_O_to_eq_O.
884 (*apply le_to_or_lt_eq.
890 theorem divides_times_to_divides: \forall n,p,q:nat.prime n \to n \divides p*q \to
891 n \divides p \lor n \divides q.
893 cut (n \divides p \lor n \ndivides p)
897 cut (\exists a,b. a*n - b*p = (S O) \lor b*p - a*n = (S O))
898 [elim Hcut1.elim H3.elim H4
900 rewrite > (times_n_SO q).rewrite < H5.
901 rewrite > distr_times_minus.
902 rewrite > (sym_times q (a1*p)).
903 rewrite > (assoc_times a1).
907 applyS (witness n (n*(q*a-a1*n2)) (q*a-a1*n2))
909 applyS (witness n ? ? (refl_eq ? ?)) (* timeout=50 *)
911 rewrite < (sym_times n).rewrite < assoc_times.
912 rewrite > (sym_times q).rewrite > assoc_times.
913 rewrite < (assoc_times a1).rewrite < (sym_times n).
914 rewrite > (assoc_times n).
915 rewrite < distr_times_minus.
916 apply (witness ? ? (q*a-a1*n2)).reflexivity
919 rewrite > (times_n_SO q).rewrite < H5.
920 rewrite > distr_times_minus.
921 rewrite > (sym_times q (a1*p)).
922 rewrite > (assoc_times a1).
926 rewrite < sym_times.rewrite > assoc_times.
927 rewrite < (assoc_times q).
928 rewrite < (sym_times n).
929 rewrite < distr_times_minus.
930 apply (witness ? ? (n2*a1-q*a)).
932 ](* end second case *)
933 | rewrite < (prime_to_gcd_SO n p);auto
934 (* [ apply eq_minus_gcd
940 | apply (decidable_divides n p).
941 apply (trans_lt ? (S O))
952 theorem eq_gcd_times_SO: \forall m,n,p:nat. O < n \to O < p \to
953 gcd m n = (S O) \to gcd m p = (S O) \to gcd m (n*p) = (S O).
955 apply antisymmetric_le
956 [ apply not_lt_to_le.
958 cut (divides (smallest_factor (gcd m (n*p))) n \lor
959 divides (smallest_factor (gcd m (n*p))) p)
961 [ apply (not_le_Sn_n (S O)).
962 change with ((S O) < (S O)).
963 rewrite < H2 in \vdash (? ? %).
964 apply (lt_to_le_to_lt ? (smallest_factor (gcd m (n*p))))
966 (*apply lt_SO_smallest_factor.
968 | apply divides_to_le;
972 | apply (transitive_divides ? (gcd m (n*p)))
981 | apply divides_d_gcd
983 | apply (transitive_divides ? (gcd m (n*p)))
984 [ apply divides_smallest_factor_n.
985 apply (trans_lt ? (S O))
990 | apply divides_gcd_n
995 | apply (not_le_Sn_n (S O)).
996 change with ((S O) < (S O)).
997 rewrite < H3 in \vdash (? ? %).
998 apply (lt_to_le_to_lt ? (smallest_factor (gcd m (n*p))))
999 [ apply lt_SO_smallest_factor.
1001 | apply divides_to_le;
1005 | apply (transitive_divides ? (gcd m (n*p)))
1014 | apply divides_d_gcd
1016 | apply (transitive_divides ? (gcd m (n*p)))
1017 [ apply divides_smallest_factor_n.
1018 apply (trans_lt ? (S O))
1023 | apply divides_gcd_n
1029 | apply divides_times_to_divides;
1031 apply (transitive_divides ? (gcd m (n*p)))
1037 (*[ apply prime_smallest_factor_n.
1039 | auto.apply (transitive_divides ? (gcd m (n*p)))
1040 [ apply divides_smallest_factor_n.
1041 apply (trans_lt ? (S O))
1046 | apply divides_gcd_m
1050 (*change with (O < gcd m (n*p)).
1052 rewrite > (times_n_O O).
1053 apply lt_times;assumption.*)
1057 theorem gcd_SO_to_divides_times_to_divides: \forall m,n,p:nat. O < n \to
1058 gcd n m = (S O) \to n \divides (m*p) \to n \divides p.
1060 cut (n \divides p \lor n \ndivides p)
1063 | cut (\exists a,b. a*n - b*m = (S O) \lor b*m - a*n = (S O))
1064 [ elim Hcut1.elim H4.elim H5
1066 rewrite > (times_n_SO p).rewrite < H6.
1067 rewrite > distr_times_minus.
1068 rewrite > (sym_times p (a1*m)).
1069 rewrite > (assoc_times a1).
1071 applyS (witness n ? ? (refl_eq ? ?)) (* timeout=50 *).
1073 rewrite > (times_n_SO p).rewrite < H6.
1074 rewrite > distr_times_minus.
1075 rewrite > (sym_times p (a1*m)).
1076 rewrite > (assoc_times a1).
1078 applyS (witness n ? ? (refl_eq ? ?)).
1079 ](* end second case *)
1085 (*apply (decidable_divides n p).