Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From Coq Require Import Arith.
- From Coq Require Import Wf_nat.
- From Coq Require Import ZArith.
- From Coq Require Import Peano_dec.
- From Coq Require Import ZArith_dec.
- From Coqprime Require Import NatAux ZCAux ZCmisc ZSum Pmod Ppow.
- (** * Compatibility lemmas (provisional) *)
- (** more general than [NatAux] lemma *)
- Definition CoPrime (a b : nat) := (* done *)
- Zis_gcd (Z.of_nat a) (Z.of_nat b) 1%Z.
- Lemma coPrimeSym (* done *) : forall a b : nat, CoPrime a b -> CoPrime b a.
- Proof. intros. now apply Zis_gcd_sym. Qed.
- Definition LinComb (c x y: Z) := exists a b: Z, c = x * a + y * b.
- Lemma gcd_lincomb_nat:
- forall (x y d : nat),
- (x > 0)%nat ->
- Zis_gcd (Z_of_nat x) (Z_of_nat y) (Z_of_nat d) ->
- LinComb (Z_of_nat d) (Z_of_nat x) (Z_of_nat y).
- Proof.
- Admitted.
- Lemma coPrimeMult : (* done *)
- forall a b c : nat, CoPrime a b -> divide a (b * c) -> divide a c.
- Proof.
- intros ? ? ? H H0; unfold CoPrime in H.
- induction a as [| a _].
- - (* a = 0 *)
- induction H0 as (x, H0).
- cbn in H0. rewrite Nat.eq_mul_0 in H0. (* b = O \/ c = O *)
- destruct H0 as [H1 | H1].
- + rewrite H1 in H. simpl in H.
- inversion H. clear H H0 H1 H2.
- assert (2 | 0). { exists 0. auto. }
- destruct (H3 _ H H). nia.
- + rewrite H1. exists 0%nat. auto.
- - assert (H1: (S a > 0)%nat) by apply gt_Sn_O.
- destruct (gcd_lincomb_nat _ _ 1 H1 H) as [x [x0 H2]].
- destruct H0 as [x1 H0].
- assert (1 * Z.of_nat c = Z_of_nat (S a) * (x * Z.of_nat c + Z.of_nat x1 * x0)).
- { rewrite (Z.mul_comm (Z.of_nat (S a))).
- rewrite Z.mul_add_distr_r.
- rewrite (Z.mul_comm (x * Z.of_nat c)).
- rewrite (Z.mul_comm (Z.of_nat x1 * x0)).
- repeat rewrite Z.mul_assoc.
- rewrite <- Znat.inj_mult.
- rewrite <- H0.
- rewrite Znat.inj_mult.
- rewrite (Z.mul_comm (Z.of_nat b)).
- rewrite <- (Z.mul_assoc (Z.of_nat c)).
- rewrite (Z.mul_comm (Z.of_nat c)).
- rewrite <- Z.mul_add_distr_r.
- now rewrite <- H2. }
- rewrite Zmult_1_l in H3.
- assert (Z.divide (Z.of_nat (S a)) (Z.of_nat c)).
- { exists (x * Z.of_nat c + Z.of_nat x1 * x0).
- now rewrite Z.mul_comm at 1. }
- clear H2 H3 x x0.
- rewrite <- (Znat.Zabs2Nat.id (S a)).
- rewrite <- (Znat.Zabs2Nat.id c).
- repeat rewrite Zabs2Nat.id. destruct H4. exists (Z.to_nat x). lia.
- Qed.
- Lemma coPrimeMult2 : (* done *)
- forall a b c : nat,
- CoPrime a b -> divide a c -> divide b c -> divide (a * b) c.
- Proof.
- intros a b c H H0 [x H1].
- assert (divide a x).
- { eapply coPrimeMult with (1:= H); now rewrite <- H1. }
- destruct H2 as [x0 H2]; exists x0; subst; ring.
- Qed.
- Lemma ltgt1 (* done *): forall a b : nat, (a < b -> b > 0)%nat. (* done *)
- Proof. lia. Qed.
- Lemma minus1 (* done *) : forall a b c : Z, (a - c)%Z = (b - c)%Z -> a = b.
- Proof. lia. Qed.
- Lemma chRem2 : (* done *)
- forall b1 r1 b2 r2 q : Z,
- (0 <= r1)%Z ->
- (0 <= r2)%Z ->
- (r1 < q)%Z -> (r2 < q)%Z -> (b1 * q + r1)%Z = (b2 * q + r2)%Z ->
- r1 = r2.
- Proof.
- intros * H H0 H1 H2 H3.
- assert (H4: ((b1 - b2) * q)%Z = (r2 - r1)%Z) by
- (rewrite Z.mul_sub_distr_r; lia).
- induction (Zle_or_lt 0 (b1 - b2)) as [H5 | H5].
- induction (Zle_lt_or_eq _ _ H5) as [H6 | H6].
- assert (H7: (1 <= b1 - b2)%Z).
- { replace 1%Z with (Z.succ 0).
- apply Zlt_le_succ.
- assumption.
- auto.
- }
- assert (H8:(q <= r2 - r1)%Z).
- { replace q with (1 * q)%Z.
- rewrite <- H4.
- apply Zmult_le_compat_r.
- assumption.
- eapply Z.le_trans.
- apply H.
- apply Zlt_le_weak.
- assumption.
- apply Zmult_1_l.
- }
- set (A1 := Zplus_lt_le_compat r2 q (- r1) 0 H2) in *.
- assert (H9:(r2 - r1 < q)%Z).
- { replace q with (q + 0)%Z.
- unfold Zminus in |- *.
- apply A1.
- eapply (fun a b : Z => Zplus_le_reg_l a b r1).
- rewrite Zplus_opp_r.
- rewrite <- Zplus_0_r_reverse.
- assumption.
- rewrite <- Zplus_0_r_reverse.
- reflexivity.
- }
- elim (Zle_not_lt q (r2 - r1)).
- assumption.
- assumption.
- rewrite <- H6 in H4.
- rewrite Z.mul_comm in H4.
- rewrite <- Zmult_0_r_reverse in H4.
- rewrite <- (Zplus_opp_r r2) in H4.
- unfold Zminus in H4.
- apply Z.opp_inj.
- symmetry in |- *.
- eapply Zplus_reg_l.
- apply H4.
- assert (H6:(1 <= b2 - b1)%Z).
- { replace 1%Z with (Z.succ 0).
- apply Zlt_le_succ.
- apply (Zplus_lt_reg_l 0 (b2 - b1) b1).
- rewrite Zplus_minus.
- rewrite <- Zplus_0_r_reverse.
- apply (Zplus_lt_reg_l b1 b2 (- b2)).
- rewrite Zplus_opp_l.
- rewrite Zplus_comm.
- unfold Zminus in H5.
- assumption.
- auto.
- }
- assert (H7: ((b2 - b1) * q)%Z = (r1 - r2)%Z) by
- ( rewrite Z.mul_sub_distr_r ; lia ).
- assert (H8:(q <= r1 - r2)%Z).
- { replace q with (1 * q)%Z.
- rewrite <- H7.
- apply Zmult_le_compat_r.
- assumption.
- eapply Z.le_trans.
- apply H.
- apply Zlt_le_weak.
- assumption.
- apply Zmult_1_l.
- }
- set (A1 := Zplus_lt_le_compat r1 q (- r2) 0 H1) in *.
- assert (H9:(r1 - r2 < q)%Z).
- { replace q with (q + 0)%Z.
- unfold Zminus in |- *.
- apply A1.
- eapply (fun a b : Z => Zplus_le_reg_l a b r2).
- rewrite Zplus_opp_r.
- rewrite <- Zplus_0_r_reverse.
- assumption.
- rewrite <- Zplus_0_r_reverse.
- reflexivity.
- }
- elim (Zle_not_lt q (r1 - r2)).
- assumption.
- assumption.
- Qed.
- Open Scope nat_scope.
- Lemma uniqueRem : (* done *)
- forall r1 r2 b : nat,
- b > 0 ->
- forall a : nat,
- (exists q : nat, a = q * b + r1 /\ b > r1) ->
- (exists q : nat, a = q * b + r2 /\ b > r2) -> r1 = r2.
- Proof.
- intros ? ? ? H a [x [H0 H2]] [x0 [H1 H3]].
- assert (x = x0). { nia. } nia.
- Qed.
- Lemma modulo :
- forall b : nat, b > 0 ->
- forall a : nat, {p : nat * nat | a = fst p * b + snd p /\ b > snd p}.
- Proof.
- intros b H a; apply (gt_wf_rec a).
- intros n H0 .
- destruct (le_lt_dec b n) as [Hle | Hlt].
- - assert (n > n - b).
- { unfold gt in |- *; apply lt_minus; assumption. }
- destruct (H0 _ H1) as [[a1 b0] p].
- simpl in p; exists (S a1, b0); simpl in |- *.
- destruct p as (H2, H3).
- split.
- + rewrite <- Nat.add_assoc, <- H2.
- now apply le_plus_minus.
- + assumption.
- - exists (0, n); simpl in |- *; now split.
- Qed.
- Lemma chRem1 : (* done *)
- forall b : nat, b > 0 -> forall a : Z,
- {p : Z * nat | snd p < b /\
- Z.of_nat (snd p) = (fst p * Z.of_nat b + a)%Z}.
- Proof.
- intros b H a.
- assert
- (H0: forall a' : Z,
- (a' >= 0)%Z ->
- {p : Z * nat | snd p < b /\
- Z.of_nat (snd p) =
- (fst p * Z.of_nat b + a')%Z}).
- { intros a' H0; set (A := Z.to_nat a') in *.
- induction (modulo b H A) as [x p].
- destruct x as (a0, b0).
- exists ((- Z.of_nat a0)%Z, b0).
- destruct p as (H1, H2).
- split.
- - apply H2.
- - rewrite <- (Z2Nat.id a').
- + simpl fst ; simpl snd.
- rewrite Zopp_mult_distr_l_reverse.
- rewrite Z.add_comm.
- fold (Z.of_nat (Z.to_nat a') - Z.of_nat a0 * Z.of_nat b)%Z
- in |- *.
- apply Zplus_minus_eq.
- rewrite <- Znat.inj_mult.
- rewrite <- Znat.inj_plus.
- apply Znat.inj_eq.
- apply H1.
- + auto.
- now rewrite <- Z.ge_le_iff.
- }
- destruct (Z_ge_lt_dec a 0).
- + apply H0; assumption.
- + assert (a + Z.of_nat b * - a >= 0)%Z.
- induction b as [| b Hrecb].
- * elim (lt_irrefl _ H).
- * rewrite Znat.inj_S.
- rewrite Z.mul_comm.
- rewrite <- Zmult_succ_r_reverse.
- fold (- a * Z.of_nat b - a)%Z in |- *.
- rewrite Zplus_minus.
- replace 0%Z with (0 * Z.of_nat b)%Z.
- apply Zmult_ge_compat_r.
- rewrite (Zminus_diag_reverse a).
- rewrite <- (Zplus_0_l (- a)).
- unfold Zminus in |- *.
- apply Z.le_ge.
- apply Zplus_le_compat_r.
- apply Zlt_le_weak.
- assumption.
- replace 0%Z with (Z.of_nat 0).
- apply Znat.inj_ge.
- unfold ge in |- *.
- apply le_O_n.
- auto.
- auto.
- * induction (H0 _ H1) as [x [H2 H3]].
- induction x as (a0, b1).
- exists ((a0 - a)%Z, b1).
- split.
- -- simpl in |- *; apply H2.
- -- cbv beta iota zeta delta [fst snd] in |- *.
- cbv beta iota zeta delta [fst snd] in H3.
- rewrite H3.
- rewrite (Zplus_comm a).
- rewrite Zplus_assoc.
- apply Zplus_eq_compat.
- rewrite Zmult_minus_distr_r.
- unfold Zminus in |- *.
- apply Zplus_eq_compat.
- reflexivity.
- rewrite Z.mul_comm.
- apply Zopp_mult_distr_l_reverse.
- reflexivity.
- Qed.
- Lemma euclid_gcd1 :
- forall (d : nat) (x y q r : Z), Zis_gcd x y (Z.of_nat d) -> x = (q * y + r)%Z -> Zis_gcd r y (Z.of_nat d).
- Proof.
- intros. rewrite H0 in H. clear H0 x.
- replace (q * y + r)%Z with (r - (- q) * y)%Z in H by lia.
- apply Zis_gcd_sym in H. apply Zis_gcd_for_euclid in H. auto.
- Qed.
- Lemma euclid_gcd :
- forall (d1 d2 : nat) (x y q r : Z),
- x = (q * y + r)%Z -> Zis_gcd x y (Z.of_nat d1) -> Zis_gcd r y (Z.of_nat d2) -> d1 = d2.
- Proof.
- intros. pose proof (euclid_gcd1 d1 x y q r H0 H).
- pose proof (Zis_gcd_unique r y _ _ H2 H1). lia.
- Qed.
- Lemma gcd_lincomb_nat_dec :
- forall x y d : nat,
- x > 0 ->
- Zis_gcd (Z.of_nat x) (Z.of_nat y) (Z.of_nat d) ->
- {a : Z * Z |
- Z.of_nat d = (Z.of_nat x * fst a + Z.of_nat y * snd a)%Z}.
- Proof.
- intro x; apply (lt_wf_rec x); intros X IH. intros y d H H0.
- elim (modulo X H y).
- intro z; elim z.
- intros q r; clear z; simpl in |- *.
- case r.
- (* case r = 0 *)
- - intros; induction p as (H1, H2).
- rewrite <- plus_n_O in H1.
- exists (1%Z, 0%Z).
- simpl fst; simpl snd.
- rewrite <- Zmult_0_r_reverse; rewrite <- Zplus_0_r_reverse.
- rewrite Z.mul_comm. rewrite Zmult_1_l.
- apply Znat.inj_eq.
- apply (euclid_gcd d X (Z.of_nat y) (Z.of_nat X) (Z.of_nat q) 0).
- rewrite <- Zplus_0_r_reverse; rewrite <- Znat.inj_mult;
- apply Znat.inj_eq; assumption.
- apply Zis_gcd_sym; assumption.
- constructor.
- + exists 0%Z. auto.
- + exists 1%Z. lia.
- + auto.
- - (* case r > 0 *)
- intros r1 [H1 H2].
- elim (IH (S r1) H2 X d).
- + intro z; elim z.
- intros delta gamma; clear z.
- simpl fst; simpl snd.
- intros p.
- exists ((gamma - Z.of_nat q * delta)%Z, delta).
- simpl fst; simpl snd.
- rewrite p, H1.
- unfold Zminus in |- *; rewrite Zmult_plus_distr_r.
- rewrite Znat.inj_plus; rewrite Zmult_plus_distr_l.
- rewrite Znat.inj_mult; rewrite <- Zopp_mult_distr_l_reverse.
- rewrite (Z.mul_assoc (Z.of_nat X)).
- rewrite (Z.mul_comm (Z.of_nat X) (- Z.of_nat q)).
- rewrite Zopp_mult_distr_l_reverse.
- rewrite Zopp_mult_distr_l_reverse.
- rewrite <- (Z.add_assoc (Z.of_nat X * gamma)).
- rewrite <- Znat.inj_mult.
- rewrite (Z.add_assoc (- (Z.of_nat (q * X) * delta))).
- rewrite Zplus_opp_l. simpl in |- *. apply Z.add_comm.
- + auto with arith.
- + apply (euclid_gcd1 d (Z.of_nat y) (Z.of_nat X) (Z.of_nat q) (Z.of_nat (S r1))).
- * apply Zis_gcd_sym; assumption.
- * rewrite <- Znat.inj_mult; rewrite <- Znat.inj_plus;
- apply Znat.inj_eq; assumption.
- Qed.
- Lemma chineseRemainderTheoremHelp :
- forall x1 x2 : nat,
- CoPrime x1 x2 ->
- forall (a b : nat) (pa : a < x1) (pb : b < x2),
- a <= b ->
- {y : nat |
- y < x1 * x2 /\
- a = snd (proj1_sig (modulo x1 (ltgt1 _ _ pa) y)) /\
- b = snd (proj1_sig (modulo x2 (ltgt1 _ _ pb) y))}.
- Proof.
- intros ? ? H a b pa pb H0. unfold CoPrime in H.
- replace 1%Z with (Z.of_nat 1) in H by auto.
- destruct (gcd_lincomb_nat_dec _ _ _ (ltgt1 _ _ pa) H)
- as [(a0,b0) p].
- set (A := Z.of_nat a) in *.
- set (B := Z.of_nat b) in *.
- set (X1 := Z.of_nat x1) in *.
- set (X2 := Z.of_nat x2) in *.
- set (y := (a0 * (B - A))%Z) in *.
- set (z := (b0 * (A - B))%Z) in *.
- set (d := (A + X1 * y)%Z) in *.
- assert (d = (B + X2 * z)%Z).
- unfold d in |- *; simpl in p.
- apply minus1 with (X2 * z)%Z.
- rewrite (Z.add_comm B).
- rewrite Zminus_plus.
- unfold z in |- *.
- replace (A - B)%Z with (- (B - A))%Z.
- unfold Zminus in |- *.
- rewrite (Z.mul_comm b0).
- rewrite Zopp_mult_distr_l_reverse.
- rewrite (Z.mul_comm X2).
- rewrite Zopp_mult_distr_l_reverse.
- rewrite Z.opp_involutive.
- unfold y in |- *.
- rewrite <- (Z.mul_assoc (B + - A)).
- rewrite (Z.mul_comm (B + - A)).
- rewrite (Z.mul_assoc X1).
- rewrite (Z.mul_comm b0).
- rewrite <- Z.add_assoc.
- rewrite <- Zmult_plus_distr_l.
- rewrite <- p.
- rewrite Z.mul_1_l.
- fold (B - A)%Z in |- *.
- apply Zplus_minus.
- unfold Zminus in |- *.
- rewrite Zopp_plus_distr.
- rewrite Z.add_comm.
- rewrite Z.opp_involutive.
- reflexivity.
- assert (H2: x1 * x2 > 0).
- replace 0 with (0 * x2).
- unfold gt in |- *.
- rewrite Nat.mul_comm.
- rewrite (Nat.mul_comm x1).
- induction x2 as [| x2 Hrecx2].
- elim (lt_n_O _ pb).
- apply mult_S_lt_compat_l.
- fold (x1 > 0) in |- *.
- eapply ltgt1.
- apply pa.
- auto.
- destruct (chRem1 _ H2 d) as [(a1, b1) [H3 H4]].
- exists b1; split.
- apply H3.
- cbv beta iota zeta delta [snd fst] in H4, p.
- split.
- induction (modulo x1 (ltgt1 a x1 pa) b1).
- induction x as (a2, b2).
- simpl in |- *.
- induction p0 as (H5, H6).
- cbv beta iota zeta delta [snd fst] in H5.
- rewrite H5 in H4.
- unfold d in H4.
- unfold A, X1 in H4.
- assert (Z.of_nat a = Z.of_nat b2).
- { eapply chRem2; try lia.
- + apply Znat.inj_lt.
- apply pa.
- + apply Znat.inj_lt.
- apply H6.
- + rewrite Znat.inj_plus in H4.
- repeat rewrite Znat.inj_mult in H4.
- symmetry in |- *.
- rewrite (Z.add_comm (Z.of_nat a)) in H4.
- rewrite Z.add_assoc in H4.
- rewrite Z.mul_assoc in H4.
- rewrite (Z.mul_comm a1) in H4.
- rewrite <- (Z.mul_assoc (Z.of_nat x1)) in H4.
- rewrite <- Zmult_plus_distr_r in H4.
- rewrite (Z.mul_comm (Z.of_nat x1)) in H4.
- apply H4. }
- lia.
- induction (modulo x2 (ltgt1 b x2 pb) b1).
- simpl in |- *.
- induction x as (a2, b2).
- cbv beta iota zeta delta [snd fst] in p0.
- induction p0 as (H5, H6).
- rewrite H5 in H4.
- rewrite H1 in H4.
- unfold B, X2 in H4.
- simpl. assert (Z.of_nat b = Z.of_nat b2).
- { eapply chRem2; try lia.
- + apply Znat.inj_lt.
- apply pb.
- + apply Znat.inj_lt.
- apply H6.
- + rewrite Znat.inj_plus in H4.
- repeat rewrite Znat.inj_mult in H4.
- symmetry in |- *.
- rewrite (Z.add_comm (Z.of_nat b)) in H4.
- rewrite Z.mul_assoc in H4.
- rewrite Z.add_assoc in H4.
- rewrite (Z.mul_comm a1) in H4.
- rewrite (Z.mul_comm (Z.of_nat x2)) in H4.
- rewrite <- Zmult_plus_distr_l in H4.
- apply H4. }
- lia.
- Qed.
- Lemma chineseRemainderTheorem :
- forall x1 x2 : nat,
- CoPrime x1 x2 ->
- forall (a b : nat) (pa : a < x1) (pb : b < x2),
- {y : nat |
- y < x1 * x2 /\
- a = snd (proj1_sig (modulo x1 (ltgt1 _ _ pa) y)) /\
- b = snd (proj1_sig (modulo x2 (ltgt1 _ _ pb) y))}.
- Proof.
- intros ? ? H a b pa pb.
- destruct (le_lt_dec a b).
- - apply chineseRemainderTheoremHelp; assumption.
- - assert (H0: b <= a) by (now apply lt_le_weak).
- assert (H1: CoPrime x2 x1) by (now apply coPrimeSym).
- induction (chineseRemainderTheoremHelp _ _ H1 b a pb pa H0)
- as [x [H2 [H3 H4]]].
- exists x.
- split.
- + now rewrite Nat.mul_comm.
- + split; assumption.
- Qed.
- Fixpoint prod (n:nat) (x: nat -> nat) :=
- match n with
- O => 1%nat
- | S p => x p * prod p x
- end.
- Definition factorial (n : nat) : nat := prod n S.
- Lemma coPrime1 : forall a : nat, CoPrime 1 a.
- Proof.
- split.
- - simpl. exists 1%Z. auto.
- - exists (Z.of_nat a); lia.
- - intros e [H H0] [H1 H2].
- simpl in H0. symmetry in H0.
- assert (H >= 0 \/ H <= 0)%Z by lia. destruct H3.
- + pose proof (Zmult_one _ _ H3 H0). subst. exists 1%Z. lia.
- + assert (- H >= 0)%Z by lia.
- replace (H * e)%Z with ((- H) * (- e))%Z in H0 by lia.
- pose proof (Zmult_one _ _ H4 H0). rewrite H5 in H0.
- exists (-1)%Z. lia.
- Qed.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement