How to prove x + y - z = x + (y - z) in Coq - 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.

Related

How to improve this proof?

I work on mereology and I wanted to prove that a given theorem (Extensionality) follows from the four axioms I had.
This is my code:
Require Import Classical.
Parameter Entity: Set.
Parameter P : Entity -> Entity -> Prop.
Axiom P_refl : forall x, P x x.
Axiom P_trans : forall x y z,
P x y -> P y z -> P x z.
Axiom P_antisym : forall x y,
P x y -> P y x -> x = y.
Definition PP x y := P x y /\ x <> y.
Definition O x y := exists z, P z x /\ P z y.
Axiom strong_supp : forall x y,
~ P y x -> exists z, P z y /\ ~ O z x.
And this is my proof:
Theorem extension : forall x y,
(exists z, PP z x) -> (forall z, PP z x <-> PP z y) -> x = y.
Proof.
intros x y [w PPwx] H.
apply Peirce.
intros Hcontra.
destruct (classic (P y x)) as [yesP|notP].
- pose proof (H y) as [].
destruct H0.
split; auto.
contradiction.
- pose proof (strong_supp x y notP) as [z []].
assert (y = z).
apply Peirce.
intros Hcontra'.
pose proof (H z) as [].
destruct H3.
split; auto.
destruct H1.
exists z.
split.
apply P_refl.
assumption.
rewrite <- H2 in H1.
pose proof (H w) as [].
pose proof (H3 PPwx).
destruct PPwx.
destruct H5.
destruct H1.
exists w.
split; assumption.
Qed.
I’m happy with the fact that I completed this proof. However, I find it quite messy. And I don’t know how to improve it. (The only thing I think of is to use patterns instead of destruct.) It is possible to improve this proof? If so, please do not use super complex tactics: I would like to understand the upgrades you will propose.
Here is a refactoring of your proof:
Require Import Classical.
Parameter Entity: Set.
Parameter P : Entity -> Entity -> Prop.
Axiom P_refl : forall x, P x x.
Axiom P_trans : forall x y z,
P x y -> P y z -> P x z.
Axiom P_antisym : forall x y,
P x y -> P y x -> x = y.
Definition PP x y := P x y /\ x <> y.
Definition O x y := exists z, P z x /\ P z y.
Axiom strong_supp : forall x y,
~ P y x -> exists z, P z y /\ ~ O z x.
Theorem extension : forall x y,
(exists z, PP z x) -> (forall z, PP z x <-> PP z y) -> x = y.
Proof.
intros x y [w PPwx] x_equiv_y.
apply NNPP. intros x_ne_y.
assert (~ P y x) as NPyx.
{ intros Pxy.
enough (PP y y) as [_ y_ne_y] by congruence.
rewrite <- x_equiv_y. split; congruence. }
destruct (strong_supp x y NPyx) as (z & Pzy & NOzx).
assert (y <> z) as y_ne_z.
{ intros <-. (* Substitute z right away. *)
assert (PP w y) as [Pwy NEwy] by (rewrite <- x_equiv_y; trivial).
destruct PPwx as [Pwx NEwx].
apply NOzx.
now exists w. }
assert (PP z x) as [Pzx _].
{ rewrite x_equiv_y. split; congruence. }
apply NOzx. exists z. split; trivial.
apply P_refl.
Qed.
The main changes are:
Give explicit and informative names to all the intermediate hypotheses (i.e., avoid doing destruct foo as [x []])
Use curly braces to separate the proofs of the intermediate assertions from the main proof.
Use the congruence tactic to automate some of the low-level equality reasoning. Roughly speaking, this tactic solves goals that can be established just by rewriting with equalities and pruning subgoals with contradictory statements like x <> x.
Condense trivial proof steps using the assert ... by tactic, which does not generate new subgoals.
Use the (a & b & c) destruct patterns rather than [a [b c]], which are harder to read.
Rewrite with x_equiv_y to avoid doing sequences such as specialize... destruct... apply H0 in H1
Avoid some unnecessary uses of classical reasoning.

Relations with dependent types in Coq

I want to define a relation over two type families in Coq and have come up with the following definition dep_rel and the identity relation dep_rel_id:
Require Import Coq.Logic.JMeq.
Require Import Coq.Program.Equality.
Require Import Classical_Prop.
Definition dep_rel (X Y: Type -> Type) :=
forall i, X i -> forall j, Y j -> Prop.
Inductive dep_rel_id {X} : dep_rel X X :=
| dep_rel_id_intro i x: dep_rel_id i x i x.
However, I got stuck when I tried to prove the following lemma:
Lemma dep_rel_id_inv {E} i x j y:
#dep_rel_id E i x j y -> existT _ i x = existT _ j y.
Proof.
intros H. inversion H. subst.
Abort.
inversion H seems to ignore the fact that the two xs in dep_rel_id i x i x are the same. I end up with the proof state:
E : Type -> Type
j : Type
x, y, x0 : E j
H2 : existT (fun x : Type => E x) j x0 = existT (fun x : Type => E x) j x
H : dep_rel_id j x j y
x1 : E j
H5 : existT (fun x : Type => E x) j x1 = existT (fun x : Type => E x) j y
x2 : E j
H4 : j = j
============================
existT E j x = existT E j x1
I don't think the goal can be proved in this way. Are there any tactics for situation like this that I'm not aware of?
By the way, I was able to prove the lemma with a somehow tweaked definition like below:
Inductive dep_rel_id' {X} : dep_rel X X :=
| dep_rel_id_intro' i x j y:
i = j -> x ~= y -> dep_rel_id' i x j y.
Lemma dep_rel_id_inv' {E} i x j y:
#dep_rel_id' E i x j y -> existT _ i x = existT _ j y.
Proof.
intros H. inversion H. subst.
apply inj_pair2 in H0.
apply inj_pair2 in H1. subst.
reflexivity.
Qed.
But I'm still curious whether this can be done in a simpler way (without using JMeq probably?). I'd be grateful for your suggestions.
Not sure what the issue is with inversion, indeed it seems like it has lost track of an important equality. However, using case H instead of inversion H seems to work just fine:
Lemma dep_rel_id_inv {E} i x j y:
#dep_rel_id E i x j y -> existT _ i x = existT _ j y.
Proof.
intros H.
case H.
reflexivity.
Qed.
But having case or destruct do the job where inversion couldn’t is very suprising to me. I suspect some kind of bug/wrong simplification by inversion, as simple inversion also gives a hypothesis from which one can prove the goal.

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.)

Coq how to pretty-print a term constructed using tactics?

I'm new to Coq and am doing some exercises to get more familiar with it.
My understanding is that proving a proposition in Coq "really" is writing down a type in Gallina and then showing that it's inhabited using tactics to combine terms together in deterministic ways.
I'm wondering if there's a way to get a pretty-printed representation of the actual term, with all the tactics removed.
In the example below, an anonymous term of type plus_comm (x y : N) : plus x y = plus y x is ultimately produced... I think. What should I do if I want to look at it? In a certain sense, I'm curious what the tactics "desugar" to.
Here's the code in question, lifted essentially verbatim from a tutorial on YouTube https://www.youtube.com/watch?v=OaIn7g8BAIc.
Inductive N : Type :=
| O : N
| S : N -> N
.
Fixpoint plus (x y : N) : N :=
match x with
| O => y
| S x' => S (plus x' y)
end.
Lemma plus_0 (x : N) : plus x O = x.
Proof.
induction x.
- simpl. reflexivity.
- simpl. rewrite IHx. reflexivity.
Qed.
Lemma plus_S (x y : N) : plus x (S y) = S(plus x y).
Proof.
induction x.
- simpl. reflexivity.
- simpl. rewrite IHx. reflexivity.
Qed.
Lemma plus_comm (x y : N) : plus x y = plus y x.
Proof.
induction x.
- simpl. rewrite plus_0. reflexivity.
- simpl. rewrite IHx. rewrite plus_S. reflexivity.
Qed.
First of all, plus_comm is not a part of the type. You get a term named plus_comm of type forall x y : N, plus x y = plus y x. You can check it using the following command
Check plus_comm.
So, an alternative way of defining the plus_comm lemma is
Lemma plus_comm : forall x y : N, plus x y = plus y x.
As a side note: in this case you'll need to add intros x y. (or just intros.) after the Proof. part.
Tactics (and the means to glue them together) are a metalanguage called Ltac, because they are used to produce terms of another language, called Gallina, which is the specification language of Coq.
For example, forall x y : N, plus x y = plus y x is an instance of Gallina sentence as well as the body of the plus function. To obtain the term attached to plus_comm use the Print command:
Print plus_comm.
plus_comm =
fun x y : N =>
N_ind (fun x0 : N => plus x0 y = plus y x0)
(eq_ind_r (fun n : N => y = n) eq_refl (plus_0 y))
(fun (x0 : N) (IHx : plus x0 y = plus y x0) =>
eq_ind_r (fun n : N => S n = plus y (S x0))
(eq_ind_r (fun n : N => S (plus y x0) = n) eq_refl (plus_S y x0))
IHx) x
: forall x y : N, plus x y = plus y x
It is not an easy read, but with some experience you'll be able to understand it.
Incidentally, here is how we could have proved the lemma not using tactics:
Definition plus_comm : forall x y : N, plus x y = plus y x :=
fix IH (x y : N) :=
match x return plus x y = plus y x with
| O => eq_sym (plus_0 y)
| S x => eq_ind _ (fun p => S p = plus y (S x)) (eq_sym (plus_S y x)) _ (eq_sym (IH x y))
end.
To explain a few things: fix is the means of defining recursive functions, eq_sym is used to change x = y into y = x, and eq_ind corresponds to the rewrite tactic.

How to add to both sides of an equality in Coq

This seems like a really simple question, but I wasn't able to find anything useful.
I have the statement
n - x = n
and would like to prove
(n - x) + x = n + x
I haven't been able to find what theorem allows for this.
You should have a look at the rewrite tactic (and then maybe reflexivity).
EDIT: more info about rewrite:
You can rewrite H rewrite -> H to rewrite from left to right
You can rewrite <- H to rewrite from right to left
You can use the pattern tactic to only select specific instances of the goal to rewrite. For example, to only rewrite the second n, you can perform the following steps
pattern n at 2.
rewrite <- H.
In your case, the solution is much simpler.
Building on #gallais' suggestion on using f_equal. We start in the following state:
n : nat
x : nat
H : n - x = n
============================
n - x + x = n + x
(1) First variant via "forward" reasoning (where one applies theorems to hypotheses) using the f_equal lemma.
Check f_equal.
f_equal
: forall (A B : Type) (f : A -> B) (x y : A), x = y -> f x = f y
It needs the function f, so
apply f_equal with (f := fun t => t + x) in H.
This will give you:
H : n - x + x = n + x
This can be solved via apply H. or exact H. or assumption. or auto. ... or some other way which suits you the most.
(2) Or you can use "backward" reasoning (where one applies theorems to the goal).
There is also the f_equal2 lemma:
Check f_equal2.
f_equal2
: forall (A1 A2 B : Type) (f : A1 -> A2 -> B)
(x1 y1 : A1) (x2 y2 : A2),
x1 = y1 -> x2 = y2 -> f x1 x2 = f y1 y2
We just apply it to the goal, which results in two trivial subgoals.
apply f_equal2. assumption. reflexivity.
or just
apply f_equal2; trivial.
(3) There is also the more specialized lemma f_equal2_plus:
Check f_equal2_plus.
(*
f_equal2_plus
: forall x1 y1 x2 y2 : nat,
x1 = y1 -> x2 = y2 -> x1 + x2 = y1 + y2
*)
Using this lemma we are able to solve the goal with the following one-liner:
apply (f_equal2_plus _ _ _ _ H eq_refl).
There is a powerful search engine in Coq using patterns. You can try for example:
Search (_=_ -> _+_=_+_).