Consider the following toy exercise:
Theorem swap_id: forall (m n : nat), m = n -> (m, n) = (n, m).
Proof.
intros m n H.
At this point I have the following:
1 subgoal
m, n : nat
H : m = n
______________________________________(1/1)
(m, n) = (n, m)
I would like to split the goal into two subgoals, m = n and n = m. Is there a tactic which does that?
Solve using the f_equal tactic:
Theorem test: forall (m n : nat), m = n -> (m, n) = (n, m).
Proof.
intros m n H. f_equal.
With state:
2 subgoals
m, n : nat
H : m = n
______________________________________(1/2)
m = n
______________________________________(2/2)
n = m
Related
Yesterday I asked a question here about a proof in Coq and the answer helped me a lot, I was able to solve many exercises alone and discover new features. Today I have another exercise, which states that For all m, n, if m <= n then max(m,n) = n. I tried to do induction after m, but I got stuck. Any help would be appreciated!
Fixpoint max (m n : Nat) : Nat :=
match m with
| O => n
| S m' => match n with
| O => m
| S n' => S (max m' n')
end
end.
Fixpoint le_Nat (m n : Nat) : bool :=
match m with
| O => true
| S m' => match n with
| O => false
| S n' => (le_Nat m' n')
end
end.
Lemma:
Lemma le_max_true :
forall m n,
le_Nat m n = true ->
max m n = n.
Proof.
...
Qed.
Let's consider the 4th sub-goal.
1 goal (ID 39)
m : nat
IHm : forall n : nat, le_nat m n = true -> max m n = n
n : nat
============================
le_nat m n = true -> S (max m n) = S n
rewrite IHm is able to replace (max m N) with N(for any N), under the condition le_nat m N = true.
By an intro H, you push an hypothesis of type le_nat m n = true into the context. Then your rewrite IHm generates two (trivial) sub-goals.
In short, in order to solve the 4th sub-goal, you may start with intro H; rewrite IHm.
If you forget the intro H, you get an unsolvable goal:
m : Nat
IHm : forall n : Nat, le_Nat m n = true -> max m n = n
n : Nat
============================
le_Nat m n = true
You need to do induction on both m and n (m and then n). After that, the goal is relatively straightforward.
Trying to solve eqb_trans I became stuck:
Theorem eqb_trans : forall n m p,
n =? m = true ->
m =? p = true ->
n =? p = true.
Obviously, we should use eqb_true to solve it:
Theorem eqb_true : forall n m,
n =? m = true -> n = m.
--------------------------------------------
Proof.
intros n m p H1 H2. apply eqb_true in H1.
apply eqb_true with (n:=m)(m:=p) in H2.
At this point we have:
n, m, p : nat
H1 : n = m
H2 : m = p
============================
(n =? p) = true
Now I wanted to use eqb_true upon the goal:
apply eqb_true with (m:=p).
But here we get an error:
Unable to unify "?M1056 = p" with "(n =? p) = true".
Why doesn't it work? How to fix?
When you apply a lemma to the goal, it is the conclusion of the lemma that must unify with the goal rather than its premise. The conclusion of this lemma is of the form _ = _, while your goal is (_ =? _) = true. These two cannot be unified, which leads to the error you see.
To prove eqb_trans, you need the converse of eqb_true, namely
forall n m, n = m -> (n =? m) = true,
which, after some simplification, is equivalent to
forall n, (n =? n) = true.
Theorem eqb_trans : forall n m p,
n =? m = true ->
m =? p = true ->
n =? p = true.
Proof.
intros n m p.
repeat rewrite Nat.eqb_eq.
intros.
rewrite H.
exact H0.
Qed.
-- Check Nat.eqb_eq.
Nat.eqb_eq
: forall n m : nat, (n =? m) = true <-> n = m
Consider the following partial proof:
Theorem test : forall (n m : nat),
n = m -> S n = S m.
Proof.
intros n m H.
Executing until this point gives me the following:
1 subgoal
n, m : nat
H : n = m
______________________________________(1/1)
S n = S m
I would like to remove the Ss from the goal, obtaining the goal n = m. Is there a tactic that does this?
You are looking for the f_equal tactic.
When using induction, I'd like to have hypotheses n = 0 and n = S n' to separate the cases.
Section x.
Variable P : nat -> Prop.
Axiom P0: P 0.
Axiom PSn : forall n, P n -> P (S n).
Theorem Pn: forall n:nat, P n.
Proof. intros n. induction n.
- (* = 0 *)
apply P0.
- (* = S n *)
apply PSn. assumption.
Qed.
In theory I could do this with induction n eqn: Hn, but that seems to mess up the inductive hypothesis:
Theorem Pn2: forall n:nat, P n.
Proof. intros n. induction n eqn: Hn.
- (* Hn : n = 0 *)
apply P0.
- (* Hn : n = S n0 *)
(*** 1 subgoals
P : nat -> Prop
n : nat
n0 : nat
Hn : n = S n0
IHn0 : n = n0 -> P n0
______________________________________(1/1)
P (S n0)
****)
Abort.
End x.
Is there an easy way to get what I want here?
Matt was almost right, you just forgot to generalize a bit your goal by reverting the remembered n:
Theorem Pn2: forall n:nat, P n.
Proof. intros n. remember n. revert n0 Heqn0.
induction n as [ | p hi]; intros m heq.
- (* heq : n = 0 *) subst. apply P0.
- (* heq : n = S n0 *)
(*
1 subgoal
P : nat -> Prop
p : nat
hi : forall n0 : nat, n0 = p -> P n0
m : nat
heq : m = S p
______________________________________(1/1)
P m
*) subst; apply (PSn p). apply hi. reflexivity.
Ooo, I think I figured it out!
Applying the inductive hypothesis changes your goal from (P n) to (P (constructor n')), so I think in general you can just match against the goal to create the equation n = construct n'.
Here's a tactic that I think does this:
(* like set (a:=b) except introduces a name and hypothesis *)
Tactic Notation
"provide_name" ident(n) "=" constr(v)
"as" simple_intropattern(H) :=
assert (exists n, n = v) as [n H] by (exists v; reflexivity).
Tactic Notation
"induction_eqn" ident(n) "as" simple_intropattern(HNS)
"eqn:" ident(Hn) :=
let PROP := fresh in (
pattern n;
match goal with [ |- ?FP _ ] => set ( PROP := FP ) end;
induction n as HNS;
match goal with [ |- PROP ?nnn ] => provide_name n = nnn as Hn end;
unfold PROP in *; clear PROP
).
It works for my example:
Theorem Pn_3: forall n:nat, P n.
Proof.
intros n.
induction_eqn n as [|n'] eqn: Hn.
- (* n: nat, Hn: n = 0; Goal: P 0 *)
apply P0.
- (* n': nat, IHn': P n';
n: nat, Hn: n = S n'
Goal: P (S n') *)
apply PSn. exact IHn'.
Qed.
I'm not sure if this is any easier, than what you have done in your second attempt, but you can first "remember" n.
Theorem Pn: forall n:nat, P n.
Proof. intro n. remember n. induction n.
- (*P : nat -> Prop
n0 : nat
Heqn0 : n0 = 0
============================
P n0
*)
subst. apply P0.
- (* P : nat -> Prop
n : nat
n0 : nat
Heqn0 : n0 = S n
IHn : n0 = n -> P n0
============================
P n0
*)
How to prove forall n m : nat, (n <? m) = false -> m <= n in Coq?
I got as far as turning the conclusion into ~ n < m using by apply Nat.nlt_ge.
Doing SearchAbout ltb yields ltb_lt: forall n m : nat, (n <? m) = true <-> n < m, but I don't know how to apply this since it only deals with (n <? m) = true, not (n <? m) = false.
Here is a proof that uses induction on n.
Require Import NPeano.
Theorem my_thm: forall n m, (n <? m) = false -> m <= n.
induction n; destruct m; intros ; auto using (Le.le_n_S); discriminate.
Qed.