]> matita.cs.unibo.it Git - helm.git/blobdiff - matita/contribs/library_auto/auto/nat/fermat_little_theorem.ma
branch for universe
[helm.git] / matita / contribs / library_auto / auto / nat / fermat_little_theorem.ma
diff --git a/matita/contribs/library_auto/auto/nat/fermat_little_theorem.ma b/matita/contribs/library_auto/auto/nat/fermat_little_theorem.ma
new file mode 100644 (file)
index 0000000..a04adaa
--- /dev/null
@@ -0,0 +1,448 @@
+(**************************************************************************)
+(*       ___                                                             *)
+(*      ||M||                                                             *)
+(*      ||A||       A project by Andrea Asperti                           *)
+(*      ||T||                                                             *)
+(*      ||I||       Developers:                                           *)
+(*      ||T||       A.Asperti, C.Sacerdoti Coen,                          *)
+(*      ||A||       E.Tassi, S.Zacchiroli                                 *)
+(*      \   /                                                             *)
+(*       \ /        This file is distributed under the terms of the       *)
+(*        v         GNU Lesser General Public License Version 2.1         *)
+(*                                                                        *)
+(**************************************************************************)
+
+set "baseuri" "cic:/matita/library_autobatch/nat/fermat_little_theorem".
+
+include "auto/nat/exp.ma".
+include "auto/nat/gcd.ma".
+include "auto/nat/permutation.ma".
+include "auto/nat/congruence.ma".
+
+theorem permut_S_mod: \forall n:nat. permut (S_mod (S n)) n.
+intro.
+unfold permut.
+split
+[ intros.
+  unfold S_mod.
+  autobatch
+  (*apply le_S_S_to_le.
+  change with ((S i) \mod (S n) < S n).
+  apply lt_mod_m_m.
+  unfold lt.
+  apply le_S_S.
+  apply le_O_n*)
+| unfold injn.
+  intros.
+  apply inj_S.
+  rewrite < (lt_to_eq_mod i (S n))
+  [ rewrite < (lt_to_eq_mod j (S n))
+    [ cut (i < n \lor i = n)
+      [ cut (j < n \lor j = n)
+        [ elim Hcut
+          [ elim Hcut1
+            [ (* i < n, j< n *)
+              rewrite < mod_S
+              [ rewrite < mod_S
+                [ (*qui autobatch non chiude il goal, chiuso invece dalla tattica
+                   * apply H2
+                   *)
+                  apply H2                
+                | autobatch
+                  (*unfold lt.
+                  apply le_S_S.
+                  apply le_O_n*)
+                | rewrite > lt_to_eq_mod;
+                    unfold lt;autobatch.(*apply le_S_S;assumption*)                  
+                ]
+              | autobatch
+                (*unfold lt.
+                apply le_S_S.
+                apply le_O_n*)              
+              | rewrite > lt_to_eq_mod
+                [ unfold lt.autobatch
+                  (*apply le_S_S.
+                  assumption*)
+                | unfold lt.autobatch
+                  (*apply le_S_S.
+                  assumption*)
+                ]
+              ]
+            | (* i < n, j=n *)
+              unfold S_mod in H2.
+              simplify.
+              apply False_ind.
+              apply (not_eq_O_S (i \mod (S n))).
+              apply sym_eq.
+              rewrite < (mod_n_n (S n))
+              [ rewrite < H4 in \vdash (? ? ? (? %?)).
+                rewrite < mod_S
+                [ assumption
+                | unfold lt.autobatch
+                  (*apply le_S_S.
+                  apply le_O_n*)
+                | rewrite > lt_to_eq_mod;
+                    unfold lt;autobatch;(*apply le_S_S;assumption*)                
+                ]
+              | unfold lt.autobatch
+                (*apply le_S_S.
+                apply le_O_n*)
+              ]
+            ]
+          | (* i = n, j < n *)
+            elim Hcut1
+            [ apply False_ind.
+              apply (not_eq_O_S (j \mod (S n))).
+              rewrite < (mod_n_n (S n))
+              [ rewrite < H3 in \vdash (? ? (? %?) ?).
+                rewrite < mod_S
+                [ assumption
+                | unfold lt.autobatch
+                  (*apply le_S_S.
+                  apply le_O_n*)
+                | rewrite > lt_to_eq_mod;
+                    unfold lt;autobatch(*apply le_S_S;assumption*)                  
+                ]
+              | unfold lt.autobatch
+                (*apply le_S_S.
+                apply le_O_n*)
+              ]
+            |(* i = n, j= n*)
+              autobatch
+              (*rewrite > H3.
+              rewrite > H4.
+              reflexivity*)
+            ]
+          ]
+        | autobatch
+          (*apply le_to_or_lt_eq.
+          assumption*)
+        ]
+      | autobatch
+        (*apply le_to_or_lt_eq.
+        assumption*)
+      ]                  
+    | unfold lt.autobatch
+      (*apply le_S_S.
+      assumption*)
+    ]
+  | unfold lt.autobatch
+    (*apply le_S_S.
+    assumption*)
+  ]
+]
+qed.
+
+(*
+theorem eq_fact_pi: \forall n,m:nat. n < m \to n! = pi n (S_mod m).
+intro.elim n.
+simplify.reflexivity.
+change with (S n1)*n1!=(S_mod m n1)*(pi n1 (S_mod m)).
+unfold S_mod in \vdash (? ? ? (? % ?)). 
+rewrite > lt_to_eq_mod.
+apply eq_f.apply H.apply (trans_lt ? (S n1)).
+simplify. apply le_n.assumption.assumption.
+qed.
+*)
+
+theorem prime_to_not_divides_fact: \forall p:nat. prime p \to \forall n:nat.
+n \lt p \to \not divides p n!.
+intros 3.
+elim n
+[ unfold Not.
+  intros.
+  apply (lt_to_not_le (S O) p)
+  [ unfold prime in H.
+    elim H.
+    assumption
+  | autobatch
+    (*apply divides_to_le.
+    unfold lt.
+    apply le_n.
+    assumption*)
+  ]
+| change with (divides p ((S n1)*n1!) \to False).
+  intro.
+  cut (divides p (S n1) \lor divides p n1!)
+  [ elim Hcut
+    [ apply (lt_to_not_le (S n1) p)
+      [ assumption
+      | autobatch
+        (*apply divides_to_le
+        [ unfold lt.
+          apply le_S_S.
+          apply le_O_n
+        | assumption
+        ]*)
+      ]
+    | autobatch
+      (*apply H1
+      [ apply (trans_lt ? (S n1))
+        [ unfold lt. 
+          apply le_n
+        | assumption
+        ]
+      | assumption
+      ]*)
+    ]
+  | autobatch
+    (*apply divides_times_to_divides;
+      assumption*)
+  ]
+]
+qed.
+
+theorem permut_mod: \forall p,a:nat. prime p \to
+\lnot divides p a\to permut (\lambda n.(mod (a*n) p)) (pred p).
+unfold permut.
+intros.
+split
+[ intros.
+  apply le_S_S_to_le.
+  apply (trans_le ? p)
+  [ change with (mod (a*i) p < p).
+    apply lt_mod_m_m.
+    unfold prime in H.
+    elim H.
+    autobatch
+    (*unfold lt.
+    apply (trans_le ? (S (S O)))
+    [ apply le_n_Sn
+    | assumption
+    ]*)
+  | rewrite < S_pred
+    [ apply le_n
+    | unfold prime in H.
+      elim H.
+      autobatch
+      (*apply (trans_lt ? (S O))
+      [ unfold lt.
+        apply le_n
+      | assumption
+      ]*)
+    ]
+  ]
+| unfold injn.
+  intros.
+  apply (nat_compare_elim i j)
+  [ (* i < j *)
+    intro.
+    absurd (j-i \lt p)
+    [ unfold lt.
+      rewrite > (S_pred p)
+      [ autobatch
+        (*apply le_S_S.
+        apply le_plus_to_minus.
+        apply (trans_le ? (pred p))
+        [ assumption
+        | rewrite > sym_plus.
+          apply le_plus_n
+        ]*)
+      | unfold prime in H. elim H. autobatch.
+        (*
+        apply (trans_lt ? (S O))
+        [ unfold lt.
+          apply le_n
+        | assumption
+        ]*)
+      ]
+    | apply (le_to_not_lt p (j-i)).
+      apply divides_to_le
+      [ unfold lt.autobatch
+        (*apply le_SO_minus.
+        assumption*)
+      | cut (divides p a \lor divides p (j-i))
+        [ elim Hcut
+          [ apply False_ind.
+            autobatch
+            (*apply H1.
+            assumption*)
+          | assumption
+          ]
+        | apply divides_times_to_divides
+          [ assumption
+          | rewrite > distr_times_minus.
+            apply eq_mod_to_divides
+            [ unfold prime in H.elim H.autobatch
+              (*apply (trans_lt ? (S O))
+              [ unfold lt.
+                apply le_n
+              | assumption
+              ]*)
+            | autobatch
+              (*apply sym_eq.
+              apply H4*)
+            ]
+          ]
+        ]
+      ]
+    ]
+  |(* i = j *)
+    autobatch
+    (*intro. 
+    assumption*)
+  | (* j < i *)
+    intro.
+    absurd (i-j \lt p)
+    [ unfold lt.
+      rewrite > (S_pred p)
+      [ autobatch
+        (*apply le_S_S.
+        apply le_plus_to_minus.
+        apply (trans_le ? (pred p))
+        [ assumption
+        | rewrite > sym_plus.
+          apply le_plus_n
+        ]*)
+      | unfold prime in H.elim H.autobatch.
+        (*
+        apply (trans_lt ? (S O))
+        [ unfold lt.
+          apply le_n
+        | assumption
+        ]*)
+      ]
+    | apply (le_to_not_lt p (i-j)).
+      apply divides_to_le
+      [ unfold lt.autobatch
+        (*apply le_SO_minus.
+        assumption*)
+      | cut (divides p a \lor divides p (i-j))
+        [ elim Hcut
+          [ apply False_ind.
+            autobatch
+            (*apply H1.
+            assumption*)
+          | assumption
+          ]
+        | apply divides_times_to_divides
+          [ assumption
+          | rewrite > distr_times_minus.
+            apply eq_mod_to_divides
+            [ unfold prime in H.elim H.autobatch.
+              (*
+              apply (trans_lt ? (S O))
+              [ unfold lt.
+                apply le_n
+              | assumption
+              ]*)
+            | apply H4
+            ]
+          ]
+        ]
+      ]
+    ]
+  ]
+]
+qed.
+
+theorem congruent_exp_pred_SO: \forall p,a:nat. prime p \to \lnot divides p a \to
+congruent (exp a (pred p)) (S O) p. 
+intros.
+cut (O < a)
+[ cut (O < p)
+  [ cut (O < pred p)
+    [ apply divides_to_congruent
+      [ assumption
+      | autobatch
+        (*change with (O < exp a (pred p)).
+        apply lt_O_exp.
+        assumption*)
+      | cut (divides p (exp a (pred p)-(S O)) \lor divides p (pred p)!)
+        [ elim Hcut3
+          [ assumption
+          | apply False_ind.
+            apply (prime_to_not_divides_fact p H (pred p))
+            [ unfold lt.
+              autobatch
+              (*rewrite < (S_pred ? Hcut1).
+              apply le_n*)
+            | assumption
+            ]
+          ]
+        | apply divides_times_to_divides
+          [ assumption
+          | rewrite > times_minus_l.
+            rewrite > (sym_times (S O)).
+            rewrite < times_n_SO.
+            rewrite > (S_pred (pred p) Hcut2).
+            rewrite > eq_fact_pi.
+            rewrite > exp_pi_l.
+            apply congruent_to_divides
+            [ assumption
+            | apply (transitive_congruent p ? 
+                  (pi (pred (pred p)) (\lambda m. a*m \mod p) (S O)))
+              [ apply (congruent_pi (\lambda m. a*m)).
+                assumption
+              | cut (pi (pred(pred p)) (\lambda m.m) (S O)
+                     = pi (pred(pred p)) (\lambda m.a*m \mod p) (S O))
+                [ rewrite > Hcut3.
+                  apply congruent_n_n
+                | rewrite < eq_map_iter_i_pi.
+                  rewrite < eq_map_iter_i_pi.
+                  apply (permut_to_eq_map_iter_i ? ? ? ? ? (λm.m))
+                  [ apply assoc_times
+                  | (*NB qui autobatch non chiude il goal, chiuso invece dalla sola
+                     ( tattica apply sys_times
+                     *)
+                    apply sym_times
+                  | rewrite < plus_n_Sm.
+                    rewrite < plus_n_O.
+                    rewrite < (S_pred ? Hcut2).
+                    autobatch
+                    (*apply permut_mod
+                    [ assumption
+                    | assumption
+                    ]*)
+                  | intros.
+                    cut (m=O)
+                    [ autobatch
+                      (*rewrite > Hcut3.
+                      rewrite < times_n_O.
+                      apply mod_O_n.*)
+                    | autobatch
+                      (*apply sym_eq.
+                      apply le_n_O_to_eq.
+                      apply le_S_S_to_le.
+                      assumption*)
+                    ]
+                  ]
+                ]
+              ]
+            ]
+          ]
+        ]
+      ]
+    | unfold lt.
+      apply le_S_S_to_le.
+      rewrite < (S_pred ? Hcut1).
+      unfold prime in H.      
+      elim H.
+      assumption
+    ]
+  | unfold prime in H.
+    elim H.
+    autobatch
+    (*apply (trans_lt ? (S O))
+    [ unfold lt.
+      apply le_n
+    | assumption
+    ]*)
+  ]
+| cut (O < a \lor O = a)
+  [ elim Hcut
+    [ assumption
+    | apply False_ind.
+      apply H1.
+      rewrite < H2.
+      autobatch
+      (*apply (witness ? ? O).
+      apply times_n_O*)
+    ]
+  | autobatch
+    (*apply le_to_or_lt_eq.
+    apply le_O_n*)
+  ]
+]
+qed.
+