|
| 1 | +Require Import Primes Arith Psatz List Nat Misc Primisc Prod Bool. |
| 2 | + |
| 3 | +Local Open Scope nat_scope. |
| 4 | + |
| 5 | +(* TODO: Develop this, use Prime as main definition of primality. |
| 6 | + Prime shouldn't be defined in terms of a prima lity checker. -RNR *) |
| 7 | + |
| 8 | +Definition Prime (p : nat) := p > 1 /\ forall a, Nat.divide a p -> a = 1 \/ a = p. |
| 9 | + |
| 10 | +Definition Composite (n : nat) := exists a b, a > 1 /\ b > 1 /\ a * b = n. |
| 11 | + |
| 12 | +Lemma NatOdd2x : |
| 13 | + forall x, ~ Nat.Odd (x * 2). |
| 14 | +Proof. |
| 15 | + induction x. simpl. intro. inversion H. lia. |
| 16 | + intro. simpl in *. rewrite Nat.Odd_succ_succ in H. easy. |
| 17 | +Qed. |
| 18 | + |
| 19 | +Definition coprime (a b : nat) : Prop := Nat.gcd a b = 1%nat. |
| 20 | + |
| 21 | +Lemma pow_coprime : |
| 22 | + forall a p k, |
| 23 | + Nat.gcd a p = 1 -> Nat.gcd a (p^k) = 1. |
| 24 | +Proof. |
| 25 | + intros. induction k. simpl. apply Nat.gcd_1_r. |
| 26 | + simpl. apply Nat_gcd_1_mul_r; easy. |
| 27 | +Qed. |
| 28 | + |
| 29 | +Lemma coprime_list_prod : |
| 30 | + forall p l f, |
| 31 | + (forall q, In q l -> Nat.gcd p q = 1) -> |
| 32 | + Nat.gcd p (fold_left Nat.mul (map (fun x : nat => x ^ f x) l) 1) = 1. |
| 33 | +Proof. |
| 34 | + intros. induction l. |
| 35 | + simpl. apply Nat.gcd_1_r. |
| 36 | + simpl. replace (a ^ f a + 0) with (1 * (a ^ f a)) by lia. |
| 37 | + rewrite <- Misc.List_fold_left_mul_assoc. |
| 38 | + apply Misc.Nat_gcd_1_mul_r. |
| 39 | + apply IHl. intros. apply H. apply in_cons. easy. |
| 40 | + apply pow_coprime. apply H. constructor. easy. |
| 41 | +Qed. |
| 42 | + |
| 43 | +(* A bit of useful reflection from Software Foundations Vol 3 *) |
| 44 | + |
| 45 | +Lemma beq_reflect : forall x y, reflect (x = y) (x =? y). |
| 46 | +Proof. |
| 47 | + intros x y. |
| 48 | + apply iff_reflect. symmetry. apply beq_nat_true_iff. |
| 49 | +Qed. |
| 50 | + |
| 51 | +Lemma blt_reflect : forall x y, reflect (x < y) (x <? y). |
| 52 | +Proof. |
| 53 | + intros x y. |
| 54 | + apply iff_reflect. symmetry. apply Nat.ltb_lt. |
| 55 | +Qed. |
| 56 | + |
| 57 | +Lemma ble_reflect : forall x y, reflect (x <= y) (x <=? y). |
| 58 | +Proof. |
| 59 | + intros x y. |
| 60 | + apply iff_reflect. symmetry. apply Nat.leb_le. |
| 61 | +Qed. |
| 62 | + |
| 63 | +Hint Resolve blt_reflect ble_reflect beq_reflect : bdestruct. |
| 64 | + |
| 65 | +Ltac bdestruct X := |
| 66 | + let H := fresh in let e := fresh "e" in |
| 67 | + evar (e: Prop); |
| 68 | + assert (H: reflect e X); subst e; |
| 69 | + [eauto with bdestruct |
| 70 | + | destruct H as [H|H]; |
| 71 | + [ | try first [apply not_lt in H | apply not_le in H]]]. |
| 72 | + |
| 73 | +Lemma simplify_primality : forall N, |
| 74 | + ~ (prime N) -> Nat.Odd N -> (forall p k, prime p -> N <> p ^ k) -> |
| 75 | + (exists p k q, (k <> 0) /\ prime p /\ (p > 2) /\ (q > 2) /\ coprime (p ^ k) q /\ N = p ^ k * q)%nat. |
| 76 | +Proof. |
| 77 | + intros. |
| 78 | + assert (GN : N > 1). |
| 79 | + { destruct H0. specialize (H1 2 0 eq_refl). simpl in *. lia. } |
| 80 | + destruct (prime_divisors N) as [| p [| q l]] eqn:E. |
| 81 | + - apply Primisc.prime_divisors_nil_iff in E. lia. |
| 82 | + - assert (Hp: In p (prime_divisors N)) by (rewrite E; constructor; easy). |
| 83 | + apply Prod.prime_divisors_aux in Hp. destruct Hp as [Hp Hpn]. |
| 84 | + assert (HN0: N <> 0) by lia. |
| 85 | + specialize (Prod.prime_divisor_pow_prod N HN0) as G. |
| 86 | + rewrite E in G. simpl in G. |
| 87 | + specialize (H1 p (Prod.pow_in_n N p) Hp). |
| 88 | + remember (p ^ Prod.pow_in_n N p) as pk. |
| 89 | + rewrite <- G in H1. lia. |
| 90 | + - assert (Hp: In p (prime_divisors N)) by (rewrite E; constructor; easy). |
| 91 | + assert (Hq: In q (prime_divisors N)) by (rewrite E; constructor; constructor; easy). |
| 92 | + assert (Hp': In p (prime_decomp N)) by (apply Primisc.prime_divisors_decomp; easy). |
| 93 | + assert (Hq': In q (prime_decomp N)) by (apply Primisc.prime_divisors_decomp; easy). |
| 94 | + apply in_prime_decomp_divide in Hp'. apply in_prime_decomp_divide in Hq'. |
| 95 | + apply Prod.prime_divisors_aux in Hp. destruct Hp as [Hp Hpn]. |
| 96 | + apply Prod.prime_divisors_aux in Hq. destruct Hq as [Hq Hqn]. |
| 97 | + remember (q :: l) as lq. |
| 98 | + assert (HN0: N <> 0) by lia. |
| 99 | + specialize (Prod.prime_divisor_pow_prod N HN0) as G. |
| 100 | + rewrite E in G. simpl in G. |
| 101 | + replace (p ^ Prod.pow_in_n N p + 0) with (1 * (p ^ Prod.pow_in_n N p)) in G by lia. |
| 102 | + rewrite <- Misc.List_fold_left_mul_assoc in G. |
| 103 | + remember (Prod.prod (map (fun x : nat => x ^ Prod.pow_in_n N x) lq)) as Plq. |
| 104 | + exists p, (Prod.pow_in_n N p), Plq. |
| 105 | + split. lia. split. easy. |
| 106 | + split. assert (2 <= p) by (apply prime_ge_2; easy). |
| 107 | + bdestruct (2 =? p). rewrite <- H3 in Hp'. destruct Hp'. rewrite H4 in H0. apply NatOdd2x in H0. easy. lia. |
| 108 | + assert (HeqPlq' := HeqPlq). |
| 109 | + simpl in HeqPlq'. rewrite <- HeqPlq' in G. |
| 110 | + rewrite Heqlq in HeqPlq. |
| 111 | + rewrite map_cons, Prod.prod_extend in HeqPlq. |
| 112 | + split. |
| 113 | + bdestruct (Plq =? 0). rewrite H2 in G. lia. |
| 114 | + bdestruct (Plq =? 1). |
| 115 | + assert (2 <= q) by (apply prime_ge_2; easy). |
| 116 | + assert (Prod.pow_in_n N q < q ^ Prod.pow_in_n N q) by (apply Nat.pow_gt_lin_r; lia). |
| 117 | + assert (2 <= q ^ Prod.pow_in_n N q) by lia. |
| 118 | + destruct (Prod.prod (map (fun x : nat => x ^ Prod.pow_in_n N x) l)); lia. |
| 119 | + bdestruct (Plq =? 2). rewrite H4 in G. rewrite <- G in H0. rewrite Nat.mul_comm in H0. apply NatOdd2x in H0. easy. |
| 120 | + lia. |
| 121 | + split. unfold coprime. apply Prod.Nat_gcd_1_pow_l. |
| 122 | + rewrite HeqPlq'. apply coprime_list_prod. |
| 123 | + intros. assert (In q0 (prime_divisors N)) by (rewrite E; apply in_cons; easy). |
| 124 | + assert (p <> q0). |
| 125 | + { specialize (Prod.prime_divisors_distinct N) as T. rewrite E in T. |
| 126 | + inversion T. intro. subst. easy. |
| 127 | + } |
| 128 | + apply Prod.prime_divisors_aux in H3. destruct H3 as [Hq0 Hq0n]. |
| 129 | + apply eq_primes_gcd_1; easy. |
| 130 | + lia. |
| 131 | +Qed. |
| 132 | + |
| 133 | +Theorem Prime_prime : |
| 134 | + forall n, Prime n <-> prime n. |
| 135 | +Proof. |
| 136 | + intros. split; intro. |
| 137 | + - destruct H. |
| 138 | + unfold prime, is_prime. |
| 139 | + do 2 (destruct n; try lia). |
| 140 | + apply prev_not_div_prime_test_true; try lia. |
| 141 | + intros. intro. apply Nat.mod_divide in H2; try lia. |
| 142 | + specialize (H0 e H2). |
| 143 | + lia. |
| 144 | + - unfold Prime. |
| 145 | + assert (2 <= n) by (apply prime_ge_2; easy). |
| 146 | + split. lia. |
| 147 | + intros. |
| 148 | + apply prime_only_divisors; easy. |
| 149 | +Qed. |
0 commit comments