Coq unable to unify -- how to change hypothesis? - coq

Coq beginner here.
I have the following silly theorems:
Theorem plus_same : forall a b c : nat,
a+b=a+c -> b=c.
Proof. Admitted.
Theorem advanced_commutivity:
forall x y z w : nat, x + y + (z+w) = x + z + (y + w).
Proof.
intros x y z w.
apply (plus_same x (y + (z+w)) (z + (y + w))).
However, when I try to run the apply line, I get an error:
Unable to unify "y + (z + w) = z + (y + w)" with
"x + y + (z + w) = x + z + (y + w)".
Do I need to change my hypothesis here? How can I apply plus_same here to the arguments in advanced_commutivity proof?

You are misreading your goal: x + y + (z + w) stands for (x + y) + (z + w), because + is registered as left-associative, which is different from x + (y + (z + w)).
So in order to apply your lemma, you should first reassociate your + by rewriting with another Lemma plus_assoc : forall x y z, x + y + z = x + (y + z).

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.

computation theory in coq

2 subgoals
x, y : nat
H : x + 0 = y + 0
but after that I don't know how to to get rid of 0 in H.
It's true that on paper you would simply conclude because x + 0 = x. Well, in Coq you have to prove it because addition is left-biased (it computes by looking up its first argument).
I would suggest proving first that
forall n, n + 0 = n
I would go with something like this:
Theorem ex9: forall x y n, x + n = y + n -> x = y.
Proof.
intros.
induction n as [| n' IH].
- rewrite add_0_r in H. (* replace x + 0 with x *)
rewrite add_0_r in H. (* replace y + 0 with y *)
assumption.
- apply IH. (* replace x=y with x+n' = y+n' *)
rewrite <- plus_n_Sm in H. (* replace x + S n' with S (x + n') *)
rewrite <- plus_n_Sm in H. (* replace y + S n' with S (y + n') *)
apply S_injective in H. (* drop both S constructors *)
assumption.
Qed.

Solve for a variable in Coq

Is there a way to solve for a variable in Coq? Given:
From Coq Require Import Reals.Reals.
Definition f_of_x (x : R) : R := x + 1.
Definition f_of_y (y : R) : R := y + 2.
I want to express
Definition x_of_y (y : R) : R :=
as something like solve for x in f_of_x = f_of_y. I expect to use the tactic language to then shuffle terms about. I ultimately want to end up with the correct usable definition of y + 1. I think want to use my definiton:
Compute x_of_y 2. (* This would yield 3 if R was tractable or if I was using nat *)
The alternative is to do it by hand with pencil/paper and then only check my work with Coq. Is this the only way?
If I understand correctly, what you want to express is the existence of a solution to the equation
x + 3 = x + 2
If so you can state it in coq as
Lemma solution :
exists x, x + 3 = x + 2.
If it was something solvable like x + 2 = 2 * x then you could solve it as
Lemma solution :
exists x, x + 2 = 2 * x.
Proof.
exists 2. reflexivity.
Qed.
But then of course there are no solutions to x + 3 = x + 2.
If you want instead a solution, with y fixed to
x + 3 = y + 2
you have to quantify over y:
Lemma solution :
forall y, exists x, x + 1 = y + 2.
Proof.
intro y.
eexists. (* Here I'm saying I want to prove the equality and fill in the x later *)
eapply plus_S_inj.
rewrite plus_0.
reflexivity.
Defined.
Print solution. (* You will see the y + 1 here *)
Here I assume some lemmata that help me manipulate numbers:
Lemma plus_S_inj :
forall x y z t,
x + z = y + t ->
x + (S z) = y + (S t).
Admitted.
Lemma plus_0 :
forall x,
x + 0 = x.
Admitted.
You probably have similar lemmata for your notion of R (I don't know which it is so I cannot go any further.)

Why is following Coq rewrite not applying on right hand side of assumption?

I have following Coq env.
1 subgoals
m : nat
IHm : forall n : nat, n + n = m + m -> n = m
n : nat
H : S (n + S n) = S (m + S m)
ll := ll : forall k : nat, k + S k = S k + k
Doing rewrite ll in H, only changes the LHS S (n + S n) to S (S n + n) but not the RHS S (m + S m). ll should be applicable on all variables of type nat. What is wrong here?
Expanding on Emilio's comment, rewrite H and rewrite H in H' will first find an instantiation for all (dependently) quantified variables of H, and then replace all occurrences* of that instantiated LHS with the RHS. I believe it finds the topmost/leftmost instantiation in the syntax tree. So, for example, if you do this:
Goal forall a b, (forall x, x + 0 = x) -> (a + 0) * (a + 0) * (b + 0) = a * a * b.
intros a b H.
rewrite H.
the rewrite H will choose to instantiate x with a, and the resulting goal will be a * a * (b + 0) = a * a * b. You can prefix the lemma with ! (as in rewrite !H) to mean "rewrite everywhere, picking as many instantiations as you can", or with ? (as in rewrite ?H) to mean try rewrite !H, i.e., you can pick multiple instantiations, and also don't fail if you can't find any.
*There's actually a bit more nuance, which is that the replacement is done in a single pass with rewrite H and in multiple passes with rewrite ?H and rewrite !H. This only shows up when the first replacement(s) expose other replacement locations that weren't previously available. This shows up, for example, if you rewrite with a + 0 = a in the goal (a + 0) + 0 = a; rewrite H leaves the goal a + 0 = 0.

How to prove x + y - z = x + (y - z) in Coq

I want to prove this :
1 subgoals
x : nat
y : nat
z : nat
______________________________________(1/1)
x + y - z = x + (y - z)
It looks trivial, but it confuse me a lot, and I need it for another proof.
Thanks.
What you're trying to prove doesn't hold if y <= z, because with nat a-b is zero if a <= b.
Omega is a useful tactic to use for inequalities and simple arithmetic over nat.
Require Import Omega.
Theorem foo:
forall x y z:nat, (x = 0 \/ z <= y) <-> x + y - z = x + (y - z).
intros; omega.
Qed.
However, your identity of course holds for the integers Z.
Require Import ZArith.
Open Scope Z.
Theorem fooZ:
forall x y z:Z, x + y - z = x + (y - z).
intros; omega.
Qed.