How to prove a*b*c=a*(b*c) in Coq? - 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?

Related

Cannot rewrite goal with assertion?

I am not sure I understand why in some cases rewriting H works, and in some it doesnt.
Here for example:
Theorem add_assoc2 : forall n m: nat, n + m = m + n.
Proof. intros. rewrite add_comm. reflexivity. Qed.
Theorem plus_4: forall n m p q: nat,
n + (n * p) + m + (m * p) = n + m + (n * p) + (m * p).
Proof.
intros.
assert (H: n * p + m = m + n * p).
{ rewrite <- add_assoc2. reflexivity. }
rewrite H.
Gives:
1 goal
n, m, p, q : nat
H : n * p + m = m + n * p
______________________________________(1/1)
n + n * p + m + m * p = n + m + n * p + m * p
But Coq complains: Found no subterm matching "n * p + m" in the current goal.
Why?
I clearly see one, on the left side. When using induction, rewriting with IHn doesn't pose any problem, even if there are some other terms in front of rewriteable expression.
You can "see" a subterm n * p + m, but this is misleading: Coq doesn't show you the implicit parentheses around all the + expressions.
Use
Set Printing Parentheses.
to make them visible. Your proof state is really:
n, m, p, q : nat
H : ((n * p) + m) = (m + (n * p))
============================
(((n + (n * p)) + m) + (m * p)) = (((n + m) + (n * p)) + (m * p))
Coq was right that there is no subterm that matches H's left hand side expression ((n * p) + m). You need to rewrite using some associativity lemmas to shift the parentheses around.
Also, add_assoc2 is not a good name for a lemma forall n m: nat, n + m = m + n. This is a commutativity property, not associativity.

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 do I prove the simplified Chinese Remainder Theorem?

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.

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.

Coq: Insufficient Justification error

I am new to Coq and am getting an Insufficient Justification error for hypothesis H3. I tried rewriting it several times but the error persists. Could someone please explain why? Thanks.
Section GroupTheory.
Variable G: Set.
Variable operation: G -> G -> G.
Variable e : G.
Variable inv : G -> G.
Infix "*" := operation.
Hypothesis associativity : forall x y z : G, (x * y) * z = x * (y * z).
Hypothesis identity : forall x : G, exists e : G, (x * e = x) /\ (e * x = x).
Hypothesis inverse : forall x : G, (x * inv x = e) /\ (inv x * x = e).
Theorem latin_square_property :
forall a b : G, exists x : G, a * x = b.
proof.
let a : G, b : G.
take (inv a * b).
have H1:(a * (inv a * b) = (a * inv a) * b) by associativity.
have H2:(a * inv a = e) by inverse.
have H3:(e * b = b) by identity.
have (a * (inv a * b) = (a * inv a) * b) by H1.
~= (e * b) by H2.
~= (b) by H3.
hence thesis.
end proof.
Qed.
End GroupTheory.
The reason is that your identity axiom is independent of the unit e, defined in the section, because you've bound e with the existential quantifier in the definition of the identity axiom.
We can amend identity, getting rid of exists e in the definition:
Hypothesis identity : forall x : G, (x * e = x) /\ (e * x = x).
After that you'll be able to finish your proof.