I have two hypothesis, and I would like to use forward reasoning to apply a theorem that uses both of them.
My specific I have the hypothes
H0 : a + b = c + d
H1 : e + f = g + h
and I want to apply the theorem from the standard library:
f_equal2_mult
: forall x1 y1 x2 y2 : nat, x1 = y1 -> x2 = y2 -> x1 * x2 = y1 * y2
Now I know I could manually give the values for x1, y1, x2, y2, but I would like Coq to automatically determine those values when it unified with H0 and H1. I have figured out that I can get it to work like so:
eapply f_equal2_mult in H0; try exact H1.
But this feels like a hack, with the broken symmetry and the try. I really would like to be able to say apply f_equals2_mult in H0, H1 or something similarly clear. Is there a way like this?
You could use pose proof to introduce the lemma in the context, and specialize to apply it to other hypotheses.
Lemma f (a b c d : nat) : a = b -> c = d -> False.
intros H1 H2.
pose proof f_equal2_mult as pp.
specialize pp with (1 := H1).
specialize pp with (1 := H2).
(* or *)
specialize pp with (1 := H1) (2 := H2).
Related
From this example:
Example foo : forall (X : Type) (x y z : X) (l j : list X),
x :: y :: l = z :: j ->
y :: l = x :: j ->
x = y.
It can be solved just doing inversion on the second hypothesis:
Proof.
intros X x y z l j eq1 eq2. inversion eq2. reflexivity. Qed.
However, doing inversion also in the first hypothesis, yields apparently contradictory hypothesis:
Proof.
intros X x y z l j eq1 eq2. inversion eq2. inversion eq1. reflexivity. Qed.
Because, in this last proof, the generated hypothesis are:
H0 : y = x
H1 : l = j
H2 : x = z
H3 : y :: l = j
But, if I'm not missing something obvious, it is impossible for both H1 and H3 to be true at the same time.
Can someone explain me what is going on? Is it just that the example is "bad designed" (both hypothesis are contradictory) and that Coq inversion tactic just swallows them? Is it a principle of explosion based on two hypothesis considered together? If so, is it then possible to prove the example just by deriving anything from falsehood? How?
Your example is assuming contradictory hypotheses: they imply that length l + 2 is equal to length l + 1.
Require Import Coq.Lists.List.
Require Import Omega.
Example foo : forall (X : Type) (x y z : X) (l j : list X),
x :: y :: l = z :: j ->
y :: l = x :: j ->
x = y.
Proof.
intros X x y z l j eq1 eq2.
apply (f_equal (#length _)) in eq1.
apply (f_equal (#length _)) in eq2.
simpl in *.
omega.
Qed.
By the principle of explosion, it is not surprising that Coq is able to derive a contradictory context.
Besides this small oddity, there is nothing wrong with the fact that the generated hypotheses are contradictory: such contexts can arise even if the original hypotheses are consistent. Consider the following (admittedly contrived) proof:
Goal forall b c : bool, b = c -> c = b.
Proof.
intros b c e.
destruct b, c.
- reflexivity.
- discriminate.
- discriminate.
- reflexivity.
Qed.
The second and third branches have contradictory hypotheses (true = false and false = true), even if the original hypothesis, b = c, is innocuous. This example is a bit different from the original one, because the contradiction was not obtained by combining hypotheses. Instead, when we call destruct, we promise Coq to prove the conclusion by considering a few subgoals obtained by case analyses. If some of the subgoals happen to be contradictory, even better: there won't be any work to do there.
With an inductive definition like:
Inductive A :=
mkA : nat -> A.
Proving constructors are partial functions can be encoded as:
Lemma constructor_functional :
forall i1 i2, mkA i1 <> mkA i2 -> i1 <> i2.
Although it is trivial to prove, doing so for every defined type sounds weird.
Is there a tactic to encode this property? Or some equivalent in a library? I did not find anything in ssreflect though by searching (_ <> _).
You can state a generic lemma that subsumes this result for every Coq function. Since constructors like your mkA are just functions, the result applies to them as well.
Lemma function_functional :
forall (X Y : Type) (f : X -> Y) (x1 x2 : X),
f x1 <> f x2 -> x1 <> x2.
Proof.
intros X Y f x1 x2 H1 H2.
apply H1.
now rewrite H2.
Qed.
This statement is actually the contrapositive of the following one from the standard library.
Lemma f_equal :
forall (X Y : Type) (f : X -> Y) (x1 x2 : X),
x1 = x2 -> f x1 = f x2.
Often in Coq I find myself doing the following: I have the proof goal, for example:
some_constructor a c d = some_constructor b c d
And I really only need to prove a = b because everything else is identical anyway, so I do:
assert (a = b).
Then prove that subgoal, then
rewrite H.
reflexivity.
finishes the proof.
But it seems to just be unnecessary clutter to have those hanging around at the bottom of my proof.
Is there a general strategy in Coq for taking an equality of constructors and splitting it up into an equality of constructor parameters, kinda like a split but for equalities rather than conjunctions.
You can use Coq's searching capabilities:
Search (?X _ = ?X _).
Search (_ _ = _ _).
Among some noise it reveals a lemma
f_equal: forall (A B : Type) (f : A -> B) (x y : A), x = y -> f x = f y
And its siblings for multi-argument equalities: f_equal2 ... f_equal5 (as of Coq version 8.4).
Here is an example:
Inductive silly : Set :=
| some_constructor : nat -> nat -> nat -> silly
| another_constructor : nat -> nat -> silly.
Goal forall x y,
x = 42 ->
y = 6 * 7 ->
some_constructor x 0 1 = some_constructor y 0 1.
intros x y Hx Hy.
apply f_equal3; try reflexivity.
At this point all you need to prove is x = y.
In particular, standard Coq provides the f_equal tactic.
Inductive u : Type := U : nat -> nat -> nat -> u.
Lemma U1 x y z1 z2 : U x y z1 = U x y z2.
f_equal
Also, ssreflect provides a general-purpose congruence tactic congr.
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 (_=_ -> _+_=_+_).
I have some equalities (=) and unequalities (<>) in the hypotheses such as:
e : x2 = x1
n : x3 <> x1
I want to use tactics like assumption, but sometimes the expected (un)equality in the goal is in the other direction like:
x1 = x2
x1 <> x3
My question is:
Is it possible to automatically introduce the symmetric forms of (un)equality above into the hypotheses?
If not, is it possible to use Notation to write a tactical to do this.
So far, I can do this manually like this:
assert (x1 = x2) by (symmetry in e; assumption).
assert (x1 <> x3) by (unfold not; intro Hnot;
symmetry in Hnot; unfold not in n; apply n in Hnot; inversion Hnot).
But it is really tedious and noisy. I don't know enough about how to automate this or if there is a better way.
Perhaps this tactic can help:
Ltac maybe_intro_sym A B :=
match goal with
|[H:B=A|-_] => fail 1
|[H:A=B|-_] => assert (B=A) by auto
end.
Ltac maybe_intro_sym_neg A B :=
match goal with
|[H:B<>A|-_] => fail 1
|[H:A<>B|-_] => assert (B<>A) by auto
end.
Ltac intro_sym :=
repeat match goal with
|[H:?A=?B|-_] => maybe_intro_sym A B
|[H:?A<>?B|-_] => maybe_intro_sym_neg A B
end.
Here's an example:
Parameters a b c d:nat.
Goal a=b -> c=d -> c<>d -> True.
intros.
intro_sym.
Now the context is
H : a = b
H0 : c = d
H1 : c <> d
H2 : d = c
H3 : b = a
H4 : d <> c
============================
True