Solve for a variable in Coq - 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.)

Related

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.

What's the difference between revert and generalize tactics in Coq?

From the Coq reference manual (8.5p1), my impression is that revert is the inverse of intro, but so is generalize to a certain extent. For example, revert and generalize dependent below seem to be the same.
Goal forall x y: nat, 1 + x = 2 + y -> 1 + x + 5 = 7 + y.
intros x y. revert x y.
intros x y. generalize dependent y. generalize dependent x.
Is it just that generalize is more powerful than revert?
Also, the documentation is a bit circular in explaining things about generalize:
This tactic applies to any goal. It generalizes the conclusion with
respect to some term.
Is generalize similar to the abstraction operator in lambda calculus?
Yes, generalize is more powerful. You've demonstrated it has at least the same power as revert by simulating revert with generalize.
Notice that generalize works on any terms, revert -- only on identifiers.
For example, revert cannot do the example from the manual:
x, y : nat
============================
0 <= x + y + y
Coq < generalize (x + y + y).
1 subgoal
x, y : nat
============================
forall n : nat, 0 <= n
As for "circularity" of the definition, the real explanation is right below the example:
If the goal is G and t is a subterm of type T in the goal, then generalize t replaces the goal by forall x:T, G0 where G0 is obtained from G by replacing all occurrences of t by x.
Essentially, this says generalize wraps your goal in forall, replacing some term with a fresh variable (x).
Of course, generalize should be used with some thought and caution, since one can get a false statement to prove after using it:
Goal forall x y, x > 0 -> 0 < x + y + y.
intros x y H.
generalize dependent (x + y + y).
(* results in this proof state: *)
x, y : nat
H : x > 0
============================
forall n : nat, 0 < n
From what I recall, revert is just a simpler form of generalize, which is usually easier to use for newcomers: it is the opposite of intro. Using a flavor of generalize, you can do much more (especially with dependency between terms and types).

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 (_=_ -> _+_=_+_).

Proving st X + st Y = st Y + (st X - 1) + 1 using Coq

Just like the title says, I'm looking for a way to prove st X + st Y = st Y + (st X - 1) + 1 in Coq. I've been trying applying various combinations of plus_comm, plus_assoc and plus_permute but I haven't been able to make it go through. Any suggestions?
Here is the goal window:
3 subgoal
n : nat
m : nat
st : state
H : st Y + st X = n + m /\ beval st (BNot (BEq (AId X) (ANum 0))) = true
______________________________________(1/3)
st Y + 1 + (st X - 1) = n + m
For integers, either ring or omega should be able to solve such a goal. It can also be done manually. It helps to disable notations so that function names appear (in order use SearchAbout to find useful lemmas). The following is probably not the shortest possible proof, just the first I found:
Require Import ZArith.
Lemma simple: forall x y, (x + y)%Z = (y + (x - 1) + 1)%Z.
intros.
rewrite Z.add_sub_assoc.
replace ((y + x)%Z) with ((x + y)%Z).
Focus 2.
rewrite Z.add_comm.
reflexivity.
set (t := ((x + y)%Z)).
replace (1%Z) with (Z.succ 0).
Focus 2.
symmetry.
apply Z.one_succ.
rewrite Zminus_succ_r.
rewrite Z.add_succ_r.
rewrite <- Zminus_0_l_reverse.
rewrite <- Zplus_0_r_reverse.
rewrite Z.succ_pred.
reflexivity.
Qed.
For those looking to use omega as a quick-fix, here's one way to get the goal into a form where it can be applied:
inversion H.
inversion H1.
rewrite negb_true_iff in H3.
apply beq_nat_false in H3.
omega.
For why omega works after we do this and not when the goal was in the original state, here is a great answer by Github user jaewooklee93:
"You don't need to think about plus_comm or similar lemmas here, because omega can solve those easy problems. Your goals are almost trivial, but the reason why omega hesistates to clear the goals is just because the minus between nat is not the same as the one we already know; 2-5=0, since there is no notion of negative in nat. So if you don't provide the fact that st X is greater than zero, omega cannot clear the goal for you. But you already have that condition in H1. Therefore, the only thing you should do is to simplify H1 and apply lemmas to H1 to make it st X<>0 .Then omega can properly work."

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.