]> matita.cs.unibo.it Git - helm.git/blobdiff - matita/library/nat/euler_theorem.ma
branch for universe
[helm.git] / matita / library / nat / euler_theorem.ma
diff --git a/matita/library/nat/euler_theorem.ma b/matita/library/nat/euler_theorem.ma
new file mode 100644 (file)
index 0000000..9396d44
--- /dev/null
@@ -0,0 +1,409 @@
+(**************************************************************************)
+(*       __                                                               *)
+(*      ||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         *)
+(*                                                                        *)
+(**************************************************************************)
+
+include "nat/map_iter_p.ma".
+include "nat/totient.ma".
+
+(*
+lemma count_card: \forall p.\forall n.
+p O = false \to count (S n) p = card n p.
+intros.elim n
+  [simplify.rewrite > H. reflexivity
+  |simplify.
+   rewrite < plus_n_O.
+   apply eq_f.assumption
+  ]
+qed.
+
+lemma count_card1: \forall p.\forall n.
+p O = false \to p n = false \to count n p = card n p.
+intros 3.apply (nat_case n)
+  [intro.simplify.rewrite > H. reflexivity
+  |intros.rewrite > (count_card ? ? H).
+   simplify.rewrite > H1.reflexivity
+  ]
+qed.
+
+( a reformulation of totient using card insted of count )
+
+lemma totient_card: \forall n. 
+totient n = card n (\lambda i.eqb (gcd i n) (S O)).
+intro.apply (nat_case n)
+  [reflexivity
+  |intro.apply (nat_case m)
+    [reflexivity
+    |intro.apply count_card1
+      [reflexivity
+      |rewrite > gcd_n_n.reflexivity
+      ]
+    ]
+  ]
+qed.
+*)
+
+(*this obvious property is useful because simplify, sometimes,
+  "simplifies too much", and doesn't allow to obtain this simple result.
+ *)
+theorem card_Sn: \forall n:nat. \forall p:nat \to bool.
+card (S n) p = (bool_to_nat (p (S n))) + (card n p).
+intros.
+simplify.
+reflexivity.
+qed.
+
+(* a reformulation of totient using card insted of sigma_p *)
+
+theorem totient_card_aux: \forall n,m: nat.
+m = n \to
+sigma_p (S (S n)) (\lambda m:nat.eqb (gcd m (S (S n))) (S O)) (\lambda x:nat. (S O)) 
+= card (S n) (\lambda m:nat.eqb (gcd m (S (S n))) (S O)).
+intros.
+rewrite < H in \vdash (? ? (? % ? ?) ?).
+rewrite < H in \vdash (? ? ? (? % ?)).
+elim (m)
+[ rewrite > card_Sn.
+  cut ((eqb (gcd (S O)(S (S n))) (S O) ) = true)
+  [ rewrite > Hcut.
+    simplify in \vdash (? ? ? %).
+    rewrite > true_to_sigma_p_Sn
+    [ rewrite > false_to_sigma_p_Sn in \vdash (? ? (? ? %) ?)
+      [ simplify in \vdash (? ? % ?).
+        reflexivity
+      | rewrite > gcd_O_n.
+        apply not_eq_to_eqb_false.
+        apply cic:/matita/nat/nat/not_eq_S.con.                
+        unfold Not.
+        intro.        
+        cut ( (S n) \le O)
+        [ apply (not_le_Sn_n n ?).
+          apply (transitive_le (S n) O n ? ?);
+          [ apply (Hcut1)
+          | apply (le_O_n n)
+          ]
+        | rewrite > H1.
+          apply le_n
+        ]
+      ]
+    | assumption
+    ]
+  | apply eq_to_eqb_true.
+    rewrite > gcd_SO_n.
+    reflexivity   
+  ]
+| cut ((eqb (gcd (S (S n1)) (S (S n))) (S O))  = true 
+    \lor (eqb (gcd (S (S n1)) (S (S n))) (S O))  = false)
+  [ elim Hcut
+    [ rewrite > card_Sn.
+      rewrite > true_to_sigma_p_Sn
+      [ rewrite > H2.
+        simplify in \vdash (? ? ? (? % ?)).
+        apply eq_f.
+        assumption
+      | assumption
+      ]      
+    | rewrite > card_Sn.
+      rewrite > false_to_sigma_p_Sn
+      [ rewrite > H2.
+        simplify in \vdash (? ? ? (? % ?)).
+        rewrite > sym_plus.
+        rewrite < plus_n_O.
+        assumption
+      | assumption  
+      ]
+    ]
+  | elim (eqb (gcd (S (S n1)) (S (S n))) (S O))
+    [ left.
+      reflexivity
+    | right.
+      reflexivity
+    ]
+  ]
+]
+qed.
+  
+lemma totient_card: \forall n.
+totient n = card n (\lambda i.eqb (gcd i n) (S O)).
+intros.
+elim n
+[ simplify.
+  reflexivity
+| elim n1
+  [ simplify.
+    reflexivity
+  |
+    (*unfold card.
+    intros.*)
+    (* here simplify creates problems: it seems it simplifies too much. I had to 
+     * introduce the obvious theorem card_Sn.
+     *)
+    rewrite > card_Sn.
+    rewrite > (gcd_n_n (S (S n2))).
+    cut ((eqb (S (S n2)) (S O)) = false)
+    [ rewrite > Hcut.
+      simplify in \vdash (? ? ? (? % ?)).
+      rewrite > sym_plus.
+      rewrite < (plus_n_O).
+      unfold totient.      
+      apply (totient_card_aux n2 n2).
+      reflexivity    
+    | apply not_eq_to_eqb_false.
+      apply cic:/matita/nat/nat/not_eq_S.con.
+      unfold Not.
+      intro.
+      cut ( (S n2) \le O)
+        [ apply (not_le_Sn_n n2 ?).
+          apply (transitive_le (S n2) O n2 ? ?);
+          [ apply (Hcut)
+          | apply (le_O_n n2)
+          ]
+        | rewrite > H2.
+          apply le_n
+        ]
+    ]
+  ]
+]
+qed.
+  
+theorem gcd_pi_p: \forall n,k. O < k \to k \le n \to
+gcd n (pi_p (\lambda i.eqb (gcd i n) (S O)) k) = (S O).
+intros 3.elim H
+  [rewrite > pi_p_S.
+   cut (eqb (gcd (S O) n) (S O) = true)
+    [rewrite > Hcut.
+     change with ((gcd n (S O)) = (S O)).
+     apply (transitive_eq nat (gcd n (S O)) (gcd (S O) n) (S O) ? ?);
+     [ apply (sym_eq nat (gcd (S O) n) (gcd n (S O)) ?).
+       apply (symmetric_gcd (S O) n).
+     | apply (gcd_SO_n n).
+     ]
+    |apply eq_to_eqb_true.
+     apply (gcd_SO_n n)
+    ]
+  |rewrite > pi_p_S.
+   apply eqb_elim
+    [intro.
+     change with 
+       ((gcd n ((S n1)*(pi_p (\lambda i.eqb (gcd i n) (S O)) n1))) = (S O)).
+     apply eq_gcd_times_SO
+      [unfold.apply le_S.assumption
+      |apply lt_O_pi_p.
+      |rewrite > sym_gcd. assumption.
+      |apply H2.
+       apply (trans_le ? (S n1))[apply le_n_Sn|assumption]
+      ]
+    |intro.
+     change with 
+       (gcd n (pi_p (\lambda i.eqb (gcd i n) (S O)) n1) = (S O)).
+     apply H2.
+     apply (trans_le ? (S n1))[apply le_n_Sn|assumption]
+    ]
+  ]
+qed.
+
+theorem congruent_map_iter_p_times:\forall f:nat \to nat. \forall a,n:nat.
+O < a \to
+congruent
+(map_iter_p n (\lambda i.eqb (gcd i a) (S O)) (\lambda x.f x) (S O) times)
+(map_iter_p n (\lambda i.eqb (gcd i a) (S O)) 
+ (\lambda x.f x \mod a) (S O) times) a.     
+intros.
+elim n
+  [rewrite > map_iter_p_O.
+   apply (congruent_n_n ? a)
+  |apply (eqb_elim (gcd (S n1) a) (S O))
+    [intro.
+     rewrite > map_iter_p_S_true
+      [rewrite > map_iter_p_S_true
+        [apply congruent_times
+          [assumption
+          |apply congruent_n_mod_n.assumption
+          |assumption
+          ]
+        |apply eq_to_eqb_true.assumption
+        ]
+      |apply eq_to_eqb_true.assumption
+      ]
+    |intro. 
+     rewrite > map_iter_p_S_false
+      [rewrite > map_iter_p_S_false
+        [assumption
+        |apply not_eq_to_eqb_false.assumption
+        ]
+      |apply not_eq_to_eqb_false.assumption
+      ]
+    ]
+  ]
+qed.
+
+theorem permut_p_mod: \forall a,n. S O < n \to O < a \to gcd a n = (S O) \to
+permut_p (\lambda x:nat.a*x \mod n) (\lambda i:nat.eqb (gcd i n) (S O)) n.
+intros.
+lapply (lt_S_to_lt ? ? H) as H3.
+unfold permut_p.
+simplify.
+intros.
+split
+  [split
+    [apply lt_to_le.
+     apply lt_mod_m_m.
+     assumption
+    |rewrite > sym_gcd.
+     rewrite > gcd_mod
+      [apply eq_to_eqb_true.
+       rewrite > sym_gcd.
+       apply eq_gcd_times_SO
+        [assumption
+        |apply (gcd_SO_to_lt_O i n H).
+         apply eqb_true_to_eq.
+         assumption
+        |rewrite > sym_gcd.assumption
+        |rewrite > sym_gcd.apply eqb_true_to_eq.
+         assumption
+        ]
+      |assumption
+      ]
+    ]
+  |intros.
+   lapply (gcd_SO_to_lt_n ? ? H H4 (eqb_true_to_eq ? ? H5)) as H9.
+   lapply (gcd_SO_to_lt_n ? ? H H7 (eqb_true_to_eq ? ? H6)) as H10.
+   lapply (gcd_SO_to_lt_O ? ? H (eqb_true_to_eq ? ? H5)) as H11.
+   lapply (gcd_SO_to_lt_O ? ? H (eqb_true_to_eq ? ? H6)) as H12.
+   unfold Not.intro.
+   apply H8.
+   apply (nat_compare_elim i j)
+    [intro.
+     absurd (j < n)
+      [assumption
+      |apply le_to_not_lt.
+       apply (trans_le ? (j -i))
+        [apply divides_to_le
+          [(*fattorizzare*)
+           apply (lt_plus_to_lt_l i).
+           simplify.
+           rewrite < (plus_minus_m_m)
+            [assumption|apply lt_to_le.assumption]
+          |apply (gcd_SO_to_divides_times_to_divides a)
+            [assumption
+            |rewrite > sym_gcd.assumption
+            |apply mod_O_to_divides
+              [assumption
+              |rewrite > distr_times_minus.
+               apply (divides_to_mod_O n (minus (times a j) (times a i)) ? ?);
+               [ apply (H3).
+               | apply (eq_mod_to_divides (times a j) (times a i) n ? ?);
+                [ apply (H3).
+                |apply (sym_eq nat (mod (times a i) n) (mod (times a j) n) ?).
+                 apply (H13).
+                ]
+               ]
+              ]
+            ]
+          ]
+        | apply (le_minus_m j i).
+        ]
+      ]
+    |intro.assumption
+    |intro.
+     absurd (i < n)
+      [assumption
+      |apply le_to_not_lt.
+       apply (trans_le ? (i -j))
+        [apply divides_to_le
+          [(*fattorizzare*)
+           apply (lt_plus_to_lt_l j).
+           simplify.
+           rewrite < (plus_minus_m_m)
+            [assumption|apply lt_to_le.assumption]
+          |apply (gcd_SO_to_divides_times_to_divides a)
+            [assumption
+            |rewrite > sym_gcd.assumption
+            |apply mod_O_to_divides
+              [assumption
+              |rewrite > distr_times_minus.
+               apply (divides_to_mod_O n (minus (times a i) (times a j)) ? ?);
+               [apply (H3).
+               | apply (eq_mod_to_divides (times a i) (times a j) n ? ?);
+                 [apply (H3).
+                 |apply (H13).
+                 ]
+               ]
+              ]
+            ]
+          ]
+        | apply (le_minus_m i j).
+        ]
+      ]
+    ]
+  ]
+qed.
+
+theorem congruent_exp_totient_SO: \forall n,a:nat. (S O) < n \to
+gcd a n = (S O) \to congruent (exp a (totient n)) (S O) n. 
+intros.
+cut (O < a)
+  [ apply divides_to_congruent
+    [apply (trans_lt ? (S O)).apply lt_O_S. assumption
+    |change with (O < exp a (totient n)).apply lt_O_exp.assumption
+    |apply (gcd_SO_to_divides_times_to_divides (pi_p (\lambda i.eqb (gcd i n) (S O)) n))
+      [apply (trans_lt ? (S O)).apply lt_O_S. assumption
+      |apply gcd_pi_p
+        [apply (trans_lt ? (S O)).apply lt_O_S. assumption
+        |apply le_n
+        ]
+      |rewrite < sym_times.
+       rewrite > times_minus_l.
+       rewrite > (sym_times (S O)).
+       rewrite < times_n_SO.
+       rewrite > totient_card.
+       rewrite > a_times_pi_p.
+       apply congruent_to_divides
+        [apply (trans_lt ? (S O)).apply lt_O_S. assumption
+        | apply (transitive_congruent n ? 
+                 (map_iter_p n (\lambda i.eqb (gcd i n) (S O)) (\lambda x.a*x \mod n) (S O) times))
+          [apply (congruent_map_iter_p_times ? n n).
+           apply (trans_lt ? (S O))
+            [apply lt_O_S|assumption]
+            |unfold pi_p.
+             cut ( (map_iter_p n (\lambda i:nat.eqb (gcd i n) (S O)) (\lambda n:nat.n) (S O) times)
+                 = (map_iter_p n (\lambda i:nat.eqb (gcd i n) (S O)) (\lambda x:nat.a*x\mod n) (S O) times))
+              [rewrite < Hcut1.apply congruent_n_n
+              |apply (eq_map_iter_p_permut ? ? ? ? ? (λm.m))
+                [apply assoc_times
+                |apply sym_times
+                |apply (permut_p_mod ? ? H Hcut H1)
+                |simplify.
+                 apply not_eq_to_eqb_false.
+                 unfold.intro.
+                 apply (lt_to_not_eq (S O) n)
+                  [assumption|apply sym_eq.assumption]
+                ]
+              ]
+            ]
+          ]
+        ]
+      ] 
+    |elim (le_to_or_lt_eq O a (le_O_n a)) 
+      [assumption
+      |absurd (gcd a n = S O)
+        [assumption
+        |rewrite < H2.
+         simplify.
+         unfold.intro.
+         apply (lt_to_not_eq (S O) n)
+          [assumption|apply sym_eq.assumption] 
+        ]
+      ]     
+    ]
+qed.