How do I prove the simplified Chinese Remainder Theorem? - coq

I've managed to prove
Theorem modulo_inv : forall m n : Z, rel_prime m n -> exists x : Z, (m * x == 1 [n]). Admitted.
My question is how to finish the following proof (maybe using the modulo_inv theorem?):
Variables m n : Z.
Hypothesis co_prime : rel_prime m n.
Theorem SimpleChineseRemainder :
forall a b : Z, exists x : Z, (x == a [m]) /\ (x == b [n]).
Here is what I tried, but I don't know whether it is correct or not.
Proof.
intros a b.
exists ((a * n) * (n ^ (-1) mod m) + (b * m) * (m ^ (-1) mod n)).
refine (conj _ _).
(* case : ((a * n) * (n ^ (-1) mod m) + (b * m) * (m ^ (-1) mod n) == a [m]) *)
red.
rewrite Z.add_sub_swap.
apply Z.divide_add_r.
(* case : ((a * n) * (n ^ (-1) mod m) + (b * m) * (m ^ (-1) mod n) == b [n]) *)
Can anybody provide any suggestions?

Code-golfing Anton's answer, I was hoping that ring would be clever enough to use the Eq information, and that the proof would simply be
Theorem SimpleChineseRemainder' a b : exists x : Z, (x == a [m]) /\ (x == b [n]).
Proof.
destruct (rel_prime_bezout _ _ co_prime) as [u v Eq];
exists (a * v * n + b * u * m); split ; [ exists ((b-a)*u) | exists ((a-b)*v)]; ring.
Qed.
Unfortunately it didn't automatically exploit that u * m + v * n = 1 -> u * m = 1 - v * n. So until we have a stronger tactic, I guess that has to be added manually, like so:
Theorem SimpleChineseRemainder' a b : exists x : Z, (x == a [m]) /\ (x == b [n]).
Proof.
destruct (rel_prime_bezout _ _ co_prime) as [u v Eq].
exists (a * (v * n) + b * (u * m)); split ; [ exists ((b-a)*u) | exists ((a-b)*v)].
- replace (v*n) with (1-u*m) by (rewrite <- Eq; ring); ring.
- replace (u*m) with (1-v*n) by (rewrite <- Eq; ring); ring.
Qed.
EDIT: The nsatz tactic is able to solve the equation system. However, it introduces a notation for [ ... ] that conflicts with the notation introduced above, and I don't know how to handle that. However, by changing the notation to i.e. [[ ... ]], the proof becomes just two lines:
Require Import Nsatz.
Theorem SimpleChineseRemainder' a b :
exists x : Z, (x == a [[m]]) /\ (x == b [[n]]).
Proof.
destruct (rel_prime_bezout _ _ co_prime) as [u v Eq];
exists (a * v * n + b * u * m); split ; [ exists ((b-a)*u) | exists ((a-b)*v)]; nsatz.
Qed.

Reusing the proof from Wikipedia which is based on Bézout's lemma, we get the following:
From Coq Require Import ZArith Znumtheory.
Import Z.
Definition modulo (a b n : Z) : Prop := (n | (a - b)).
Notation "a == b [ n ]" := (modulo a b n) (at level 50).
Section SimpleChineseRemainder.
Variables m n : Z.
Hypothesis co_prime : rel_prime m n.
Theorem SimpleChineseRemainder a b : exists x : Z, (x == a [[m]]) /\ (x == b [[n]]).
Proof.
destruct (rel_prime_bezout _ _ co_prime) as [u v Eq].
exists (a * v * n + b * u * m); split; [| rewrite add_comm in *];
match goal with |- _ == ?c [_] => replace c with (c * 1) at 2 by apply mul_1_r end;
rewrite <-Eq, mul_add_distr_l, !mul_assoc;
now eexists; rewrite add_add_simpl_l_r, <-mul_sub_distr_r.
Qed.
End SimpleChineseRemainder.

Related

How to prove all proofs of le equal?

I'm basically trying to prove
Theorem le_unique {x y : nat} (p q : x <= y) : p = q.
without assuming any axioms (e.g. proof irrelevance). In particular, I've tried to get through le_unique by induction and inversion, but it never seems to get far
Theorem le_unique (x y : nat) (p q : x <= y) : p = q.
Proof.
revert p q.
induction x as [ | x rec_x]. (* induction on y similarly fruitless; induction on p, q fails *)
- destruct p as [ | y p].
+ inversion q as [ | ]. (* destruct q fails and inversion q makes no progress *)
admit.
+ admit.
- admit.
Admitted.
In the standard library, this lemma can be found as Peano_dec.le_unique in the module Coq.Arith.Peano_dec.
As for a relatively simple direct proof, I like to go by induction on p itself.
After proving by hand a few induction principles that Coq doesn't automatically generate, and remembering that proofs of equality on nat are unique, the proof is a relatively straightforward induction on p followed by cases on q, giving four cases two of which are absurd.
Below is a complete Coq file proving le_unique.
Import EqNotations.
Require Eqdep_dec PeanoNat.
Lemma nat_uip {x y : nat} (p q : x = y) : p = q.
apply Eqdep_dec.UIP_dec.
exact PeanoNat.Nat.eq_dec.
Qed.
(* Generalize le_ind to prove things about the proof *)
Lemma le_ind_dependent :
forall (n : nat) (P : forall m : nat, n <= m -> Prop),
P n (le_n n) ->
(forall (m : nat) (p : n <= m), P m p -> P (S m) (le_S n m p)) ->
forall (m : nat) (p : n <= m), P m p.
exact (fun n P Hn HS => fix ind m p : P m p := match p with
| le_n _ => Hn | le_S _ m p => HS m p (ind m p) end).
Qed.
(*
Here we give an proof-by-cases principle for <= which keeps both the left
and right hand sides fixed.
*)
Lemma le_case_remember (x y : nat) (P : x <= y -> Prop)
(IHn : forall (e : y = x), P (rew <- e in le_n x))
(IHS : forall y' (q' : x <= y') (e : y = S y'), P (rew <- e in le_S x y' q'))
: forall (p : x <= y), P p.
exact (fun p => match p with le_n _ => IHn | le_S _ y' q' => IHS y' q' end eq_refl).
Qed.
Theorem le_unique {x y : nat} (p q : x <= y) : p = q.
revert q.
induction p as [|y p IHp] using le_ind_dependent;
intro q;
case q as [e|x' q' e] using le_case_remember.
- rewrite (nat_uip e eq_refl).
reflexivity.
- (* x = S x' but x <= x', so S x' <= x', which is a contradiction *)
exfalso.
rewrite e in q'.
exact (PeanoNat.Nat.nle_succ_diag_l _ q').
- (* S y' = x but x <= y', so S y' <= y', which is a contradiction *)
exfalso; clear IHp.
rewrite <- e in p.
exact (PeanoNat.Nat.nle_succ_diag_l _ p).
- injection e as e'.
(* We now get rid of e as equal to (f_equal S e'), and then destruct e'
now that it is an equation between variables. *)
assert (f_equal S e' = e).
+ apply nat_uip.
+ destruct H.
destruct e'.
change (le_S x y p = le_S x y q').
f_equal.
apply IHp.
Qed.
Inspired by Eqdep_dec (and with a lemma from it), I've been able to cook this proof up. The idea is that x <= y can be converted to exists k, y = k + x, and roundtripping through this conversion produces a x <= y that is indeed = to the original.
(* Existing lemmas (e.g. Nat.le_exists_sub) seem unusable (declared opaque) *)
Fixpoint le_to_add {x y : nat} (prf : x <= y) : exists k, y = k + x :=
match prf in _ <= y return exists k, y = k + x with
| le_n _ => ex_intro _ 0 eq_refl
| le_S _ y prf =>
match le_to_add prf with
| ex_intro _ k rec =>
ex_intro
_ (S k)
match rec in _ = z return S y = S z with eq_refl => eq_refl end
end
end.
Fixpoint add_to_le (x k : nat) : x <= k + x :=
match k with
| O => le_n x
| S k => le_S x (k + x) (add_to_le x k)
end.
Theorem rebuild_le
{x y : nat} (prf : x <= y)
: match le_to_add prf return x <= y with
| ex_intro _ k prf =>
match prf in _ = z return x <= z -> x <= y with
| eq_refl => fun p => p
end (add_to_le x k)
end = prf.
Proof.
revert y prf.
fix rec 2. (* induction is not enough *)
destruct prf as [ | y prf].
- reflexivity.
- specialize (rec y prf).
simpl in *.
destruct (le_to_add prf) as [k ->].
subst prf.
reflexivity.
Defined.
Then, any two x <= ys will produce the same k, by injectivity of +. The decidability of = on nat tells us that the produced equalities are also equal. Thus, the x <= ys map to the same exists k, y = k + x, and mapping that equality back tells us the x <= ys were also equal.
Theorem le_unique (x y : nat) (p q : x <= y) : p = q.
Proof.
rewrite <- (rebuild_le p), <- (rebuild_le q).
destruct (le_to_add p) as [k ->], (le_to_add q) as [l prf].
pose proof (f_equal (fun n => n - x) prf) as prf'.
simpl in prf'.
rewrite ?Nat.add_sub in prf'.
subst l.
apply K_dec with (p := prf).
+ decide equality.
+ reflexivity.
Defined.
I'm still hoping there's a better (i.e. shorter) proof available.

How to prove a*b*c=a*(b*c) in Coq?

Im trying to prove the above question. I have been given a definition of an induction:
Definition nat_ind
(p : nat -> Prop)
(basis : p 0)
(step : forall n, p n -> p (S n)) :
forall n, p n := fix f n :=
match n return p n with
| 0 => basis
| S n => step n (f n)
end.
This is my attempt, but don't know how to finish
Goal forall a b c, a * b * c = a * (b * c).
Proof.
apply nat_ind.
- intros a b c. revert a.
apply (nat_ind (fun a => a * b * c = a * (b * c))); simpl.
+ reflexivity.
+ intros. f_equal. intros.
After your very first nat_ind invocation, if you look at your goal, you see that Coq did not do the right thing at all!
______________________________________(1/3)
forall a b c : nat, a * b * c = a * (b * c)
______________________________________(2/3)
nat ->
(forall a b c : nat, a * b * c = a * (b * c)) ->
forall a b c : nat, a * b * c = a * (b * c)
______________________________________(3/3)
nat
What happened here is that it made a guess for your motive p, and decided to unify it with fun (_ : nat) => <YOUR_WHOLE_GOAL>, a function which given any nat would give your goal... Yes, this is silly!
One way to nudge it into doing the induction on a is by explicitly forcing it to do so, with:
apply nat_ind with (n := a)
(where the n matches the name used in your definition of nat_ind)
After this, you get the much more reasonable goals:
______________________________________(1/2)
forall b c : nat, 0 * b * c = 0 * (b * c)
______________________________________(2/2)
forall n : nat,
(forall b c : nat, n * b * c = n * (b * c)) ->
forall b c : nat, S n * b * c = S n * (b * c)
where indeed a has been replaced by 0 and S n respectively.
[EDIT: I guess this does not quite answer your question as you had gotten your way to the same point with the second induction call...]
To solve your goal, it will help a lot to have a property about distributivity of multiplication over addition:
forall n m p, (n + m) * p = n * p + m * p
All of these, as well as what you're trying to prove, already exists in Coq. Is this homework? Are you just training?

Well-founded induction for a counting predicate

Here is the definition for the Count predicate. It uses 2 indices to denote starting and ending elements, "check" predicate to count/skip the "current" element and the last argument "sum" to keep track the number of elements that satisfy check predicate between these boundary indices.
Require Import ZArith.
Open Scope Z_scope.
Inductive Count : Z -> Z -> (Z -> Prop) -> Z -> Prop :=
| Q_Nil:
forall (m n : Z),
forall (check : Z -> Prop),
(n <= m) ->
(Count m n check 0)
| Q_Hit:
forall (m n sum : Z),
forall (check : Z -> Prop),
let x := (n - 1) in
(m < n) ->
(check x) ->
(Count m x check sum) ->
(Count m n check (1 + sum))
| Q_Miss:
forall (m n sum : Z),
forall (check : Z -> Prop),
let x := (n - 1) in
(m < n) ->
~(check x) ->
(Count m x check sum) ->
(Count m n check sum).
It is required to prove that the number of counted elements "sum" is non-negative.
Goal
forall (m n sum : Z),
forall (check : Z -> Prop),
(Count m n check sum) -> (0 <= sum).
Proof.
Obviously, the induction could be applied here. However, schemes like natlike_rec3 are not applicable because of the Q_Hit|Q_Miss difference in sum element (i.e. +1 in Q_Hit).
Here is my proof attempt till the step where an induction should be applied.
Proof.
Require Import Psatz.
intros m n sum check.
assert (X: n <= m \/ n > m) by lia.
destruct X as [le|gt].
+ intro.
inversion H; subst; intuition.
+ pose (p := (n - m)).
assert (PZ: p > 0). { subst p. auto with zarith. }
replace n with (m + p) in * by (subst p; auto with zarith).
1 subgoal
m, n, sum : Z
check : Z -> Prop
p := n - m : Z
gt : m + p > m
PZ : p > 0
______________________________________(1/1)
Count m (m + p) check sum -> 0 <= sum
I think that maybe well_founded_induction_type_2 could be used further with relation on sum and p: sum <= p.
You can use induction on the Count hypothesis (in a way, that's the main point of Inductive types).
Proof.
intros.
induction H.
all: omega.
(* or, as a single sequence: intros; induction H; omega. *)
(* lia also works instead of omega, and should probably be preferred nowadays (Require Import Lia.) *)
Qed.

even (n + m) -> even n /\ even m \/ odd n /\ odd m

How can I prove this lemma:
Lemma even_plus_split n m :
even (n + m) -> even n /\ even m \/ odd n /\ odd m.
These are the only libraries and definition that can be used:
Require Import Arith.
Require Import Coq.omega.Omega.
Definition even (n: nat) := exists k, n = 2 * k.
Definition odd (n: nat) := exists k, n = 2 * k + 1.
I am new to Coq and confused about it. Can you give me a solution? Thanks in advance!
the code so far:
Lemma even_plus_split n m :
even (n + m) -> even n /\ even m \/ odd n /\ odd m.
Proof.
intros.
unfold even.
unfold even in H.
destruct H as [k H].
unfold odd.
exists (1/2*k).
result so far:
1 subgoal
n, m, k : nat
H : n + m = 2 * k
______________________________________(1/1)
(exists k0 : nat, n = 2 * k0) /\ (exists k0 : nat, m = 2 * k0) \/
(exists k0 : nat, n = 2 * k0 + 1) /\ (exists k0 : nat, m = 2 * k0 + 1)
I just want to make k0 equals to 1/2*k, and therefore I suppose it would make sense, but I can't do that.
I just want to make k0 equals to 1/2*k, and therefore I suppose it would make sense, but I can't do that.
There is a function called Nat.div2, which divides a natural number by 2. Running Search Nat.div2.
Nat.le_div2: forall n : nat, Nat.div2 (S n) <= n
Nat.lt_div2: forall n : nat, 0 < n -> Nat.div2 n < n
Nat.div2_decr: forall a n : nat, a <= S n -> Nat.div2 a <= n
Nat.div2_wd: Morphisms.Proper (Morphisms.respectful eq eq) Nat.div2
Nat.div2_spec: forall a : nat, Nat.div2 a = Nat.shiftr a 1
Nnat.N2Nat.inj_div2: forall a : N, N.to_nat (N.div2 a) = Nat.div2 (N.to_nat a)
Nnat.Nat2N.inj_div2: forall n : nat, N.of_nat (Nat.div2 n) = N.div2 (N.of_nat n)
Nat.div2_double: forall n : nat, Nat.div2 (2 * n) = n
Nat.div2_div: forall a : nat, Nat.div2 a = a / 2
Nat.div2_succ_double: forall n : nat, Nat.div2 (S (2 * n)) = n
Nat.div2_odd: forall a : nat, a = 2 * Nat.div2 a + Nat.b2n (Nat.odd a)
Nat.div2_bitwise:
forall (op : bool -> bool -> bool) (n a b : nat),
Nat.div2 (Nat.bitwise op (S n) a b) = Nat.bitwise op n (Nat.div2 a) (Nat.div2 b)
Of these, the most promising seems to be Nat.div2_odd: forall a : nat, a = 2 * Nat.div2 a + Nat.b2n (Nat.odd a). If you pose proof this lemma, you can destruct (Nat.odd a) and use simpl to get that either a = 2 * Nat.div2 a or a = 2 * Nat.div2 a + 1, for whichever a you choose.
This may not give you a solution directly (I am not convinced that setting k0 to k / 2 is the right decision), but if it does not, you should make sure that you can figure out how to prove this fact on paper before you try it in Coq. Coq is very good at making sure that you don't make any jumps of logic that you're not allowed to make; it's extremely bad at helping you figure out how to prove a fact that you don't yet know how to prove.
Everybody who tries to answer seems to be dancing around the fact that you actually chose a wrong direction for this proof. Here is a example:
if n = 601 and m = 399, then n + m = 2 * 500,
n = 2 * 300 + 1, and m = 2 * 199 + 1.
Between 500, 300, and 199, the 1/2 ratio does not appear anywhere.
Still the statement (even n /\ even m) / (odd n /\ odd m) is definitely true.
So for now, you have more a math problem than a Coq problem.
You have to make a proof for universally quantified numbers n and m, but somehow this proof should also work for specific choices of these numbers. So in a sense you can make the mental exercise of testing your proof on examples.

How to apply Z.divide_add_r in a hypothesis?

I have the following code:
Require Import Znumtheory.
Require Import Zdiv.
Require Import ZArith.
Import Z.
Definition modulo (a b n : Z) : Prop := (n | (a - b)).
Notation "( a == b [ n ])" := (modulo a b n).
This is a lemma I'm trying to prove:
Lemma modulo_plus_eq : forall a b c m n : Z,
(a * m + b * n == c [ n ]) -> (a * m == c [ n ]).
Here is what I tried so far:
Proof.
intros a b c m n Hab.
red in Hab |- *.
unfold Zminus in Hab.
rewrite Zplus_comm in Hab.
rewrite Zplus_assoc in Hab.
cut (n | b * n).
intros Hbn.
How do I finish the proof?
Here is a follow-up question: Chinese Remainder Theorem
Let me give you a couple of hints first: if you open scope Z some things will be easier, you can also get rid of parentheses in your _ == _ [ _ ] notation (but this is subjective, of course).
Open Scope Z.
Notation "a == b [ n ]" := (modulo a b n) (at level 50).
You have all the lemmas in the standard library to make the proof simpler:
Lemma modulo_plus_eq a b c m n :
a * m + b * n == c [ n ] -> a * m == c [ n ].
Proof.
intros H.
apply divide_add_cancel_r with (m := b * n).
- apply divide_factor_r.
- now rewrite add_sub_assoc, add_comm.
Qed.
We can also make the proof of modulo_plus_extension a bit simpler:
Lemma modulo_plus_extension a b c m n :
a * m == c [ n ] -> a * m + b * n == c [ n ].
Proof.
intros Ham; red in Ham |- *.
rewrite add_sub_swap.
apply divide_add_r; [assumption | apply divide_factor_r].
Qed.
You can use the Search command to find lemmas in the standard library which can do what you want in one or two steps. You just need to state what you want explicitly:
Search (?x + ?y - ?z = ?x - ?z + ?y).
And sometimes one can unfold notations, like so: unfold "_ == _ [ _ ]" in *., which is a bit more explicit than red in Ham |- *..
There is good support for linear integer arithmetic in the Psatz module with the lia tactic. (There is also an lra tactic for linear real arithmetic.)
See the ref man.
With it you can solve your goals with one line.
Require Import Psatz.
Lemma modulo_plus_extension :
forall a b c m n: Z, (a * m == c [ n ]) -> (a * m + b * n == c [ n ]).
Proof. unfold modulo, divide; destruct 1 as [z H]; exists (z+b); lia. Qed.
Lemma modulo_plus_eq :
forall a b c m n : Z, (a * m + b * n == c [ n ]) -> (a * m == c [ n ]).
Proof. unfold modulo, divide; destruct 1 as [z H]; exists (z-b); lia. Qed.
The goal that lia has to solve is
a, b, c, m, n, z : Z
H : a * m + b * n - c = z * n
============================
a * m - c = (z - b) * n
which you can solve yourself with a lot of appeals to commutativity, distributivity, etc. It is good to be able to do it by hand, but after a while it gets tedious, and then it is good to have a tactic that lets you focus on the interesting parts of the proof.
What you're trying to do isn't actually true. Z.divide_add_r says if you already know (n | m) and (n | p), then (n | m + p). You have a hypothesis of the form (n | m + p) and want (n | m) and (n | p), which is the converse of Z.divide_add_r, but that fact isn't true: for example, 3 | 3 but neither 3 | 1 nor 3 | 2 are true.