I am interested in how does dependent-typed theorem provers do substitution on the context. I find a thing called "intro ->" in Coq, as described in:
https://coq.inria.fr/refman/proof-engine/tactics.html#intropattern-rarrow-ex
In the example, it says the goal:
x, y, z : nat
H : x = y
y = z -> x = z
will become
x, z : nat
H : x = z
x = z
after an application of "intros ->".
I am not sure how is the step of substituting H:x = y into H:x = z be done, what is the rule of the logic of Coq is this step according to? It seems like a step of rewriting, and according to my current knowledge most of these rewriting are according to equalities, so the replacement from H:x = y into H:x = z should come from an equality like (H:x = y) = (H:x= z) ($\diamond$), but such an equality is ill-formed because, in principle, we require the LHS and RHS of an equality to have the same type, so the well-formedness of such equality ($\diamond$) depends on the assumption that y = z.
Could someone please help explaining how does "intro ->" work here? Do we need to get "equalities" like ($\diamond$) involved?
In Coq, rewriting on the context is a derived notion. The tactic intros -> in this case is roughly equivalent to the following tactics:
intros H'. rewrite H' in H. clear y H'.
The tactic rewrite H' in H., in turn, is roughly equivalent to
revert H. rewrite H'. intros H.
In words, to rewrite on the context, Coq first transfers all the relevant hypotheses to the goal, rewrites the goal and then brings the hypotheses back to the context.
Rewriting the goal uses the following elimination principle for the equality type:
forall [A : Type] [a : A] (P : A -> Prop), P a -> forall b : A, b = a -> P b
For rewriting H' above, we would have:
A := T
a := z
P := fun c => x = c -> x = z
b := y
so,
P b == x = y -> x = z
P a == x = z -> x = z
Indeed, ignoring the move steps to and from the context, Coq went from P b to P a when you performed the rewrite.
Related
What effect does the following tactic have on the goal and the assumptions?
I know what induction on variables and named hypothesis do, but am unclear about induction on a number.
Induction 1
From the Coq Reference Manual: https://coq.inria.fr/distrib/current/refman/proof-engine/tactics.html#coq:tacn.induction
(...) induction num behaves as intros until num followed by induction applied to the last introduced hypothesis.
And for intros until num: https://coq.inria.fr/distrib/current/refman/proof-engine/tactics.html#coq:tacv.intros
intros until num: This repeats intro until the num-th non-dependent product.
Example
On the subgoal forall x y : nat, x = y -> y = x the tactic intros until 1 is equivalent to intros x y H, as x = y -> y = x is the first non-dependent product.
On the subgoal forall x y z : nat, x = y -> y = x the tactic intros until 1 is equivalent to intros x y z as the product on z can be rewritten as a non-dependent product: forall x y : nat, nat -> x = y -> y = x.
For reference, there is an index of standard tactics in the Manual where those can easily be looked up: https://coq.inria.fr/distrib/current/refman/coq-tacindex.html
(There are other indices in there that you may find interesting as well.)
I am trying to prove that every group has an inverse function.
I have defined a group as follows:
Record Group:Type := {
G:Set;
mult:G->G->G;
e:G;
assoc:forall x y z:G, mult x (mult y z)=mult (mult x y) z;
neut:forall x:G, mult e x=x /\ mult x e=x;
inverse:forall x:G,exists y:G, mult x y = e
}.
I am aware that it is better to just replace the inverse axiom by inverse:forall x:G, {y: mult x y = e}., or even inverse:G->G. is_inverse:forall x:G, mult x (inverse x)=e., but I prefer my definition, mainly because I want the definition to be identical to the one given in a classroom.
So I have included a suitable version of the axiom of choice:
Axiom indefinite_description : forall (A : Type) (P: A->Prop), ex P -> sig P.
Axiom functional_choice : forall A B (R:A->B->Prop), (forall x, exists y, R x y) -> (exists f, forall x, R x (f x)).
Now I can prove my claim:
Lemma inv_func_exists(H:Group):exists inv_func:G H->G H, (forall x:G H, mult H x (inv_func(x))=e H).
generalize (inverse H).
apply functional_choice.
Qed.
Now that I have proved the existence, I would like to define an actual function. Here I feel that things start to go messy. The following definition creates an actual function, but seems to ugly and complicated:
Definition inv_func(H:Group):G H->G H.
pose (inv_func_exists H).
pose indefinite_description.
generalize e0 s.
trivial.
Qed.
Lastly, I would like to prove that inv_func is actually an inverse function:
Lemma inv_func_is_inverse:forall (H:Group), forall x:(G H), mult H x (inv_func H x)=e H.
I can see that Coq knows how inv_func was defined (e.g. Print inv_func), but I have no idea how to formally prove the lemma.
To conclude, I would appreciate suggestions as to how to prove the last lemma, and of better ways to define inv_func (but under my definition of group, without including the existence of such a function in the group definition. I believe the question could be relevant in many other situations when one can prove some correspondence for each element and needs to build this correspondence as a function).
There are quite a few questions inside your question. I'll try to address all of them:
First, there is no reason to prefer exists x, P + description over {x | P}, indeed, it seems weird you do so. {x | P} is perfectly valid as "there exists a x that can be computed" and I would rather use that definition with your groups.
Secondly, when creating definitions using tactics, you should end the proof with the command Defined. Using Qed will declare the definition "Opaque", which means it cannot be expanded, then preventing you proof.
The way to extract the witness from your definition is by using a projection. In this case, proj1_sig.
Using all the above we arrive at:
Definition inv_func' (H:Group) (x : G H) : G H.
Proof.
destruct (inverse H x) as [y _].
exact y.
Defined.
Definition inv_func (H:Group) (x : G H) : G H := proj1_sig (inverse H x).
Lemma inv_func_is_inverse (H:Group) (x: G H) : mult H x (inv_func H x) = e H.
Proof. now unfold inv_func; destruct (inverse H x). Qed.
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 (_=_ -> _+_=_+_).
If I'm in Coq and I find myself in a situation with a goal like so:
==================
x = y -> y = x
Is there a tactic that can can take care of this in one swoop? As it is, I'm writing
intros H. rewrite -> H. reflexivity.
But it's a bit clunky.
To "flip" an equality H: x = y you can use symmetry in H. If you want to flip the goal, simply use symmetry.
If you're looking for a single tactic, then the easy tactic handles this one immediately:
Coq < Parameter x y : nat.
x is assumed
y is assumed
Coq < Lemma sym : x = y -> y = x.
1 subgoal
============================
x = y -> y = x
sym < easy.
No more subgoals.
If you take a look at the proof that the easy tactic found, the key part is an application of eq_sym:
sym < Show Proof.
(fun H : x = y => eq_sym H)
The heavier-weight auto tactic will also handle this goal in a single step. For a slightly lower-level proof that produces exactly the same proof term, you can use the symmetry tactic (which also automatically does the necessary intro for you):
sym < Restart.
1 subgoal
============================
x = y -> y = x
sym < symmetry.
1 subgoal
H : x = y
============================
x = y
sym < assumption.
No more subgoals.
sym < Show Proof.
(fun H : x = y => eq_sym H)