Tactics: stuck in eqb_trans - coq

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

Related

Coq - How to prove eqb_neq?

I'm trying to prove eqb_neq:
Theorem eqb_neq : forall x y : nat,
x =? y = false <-> x <> y.
This is my current proof status:
During the proof I reached a final step where I just need to prove the additional helper theorem:
Theorem eqb_false_helper : forall n m : nat,
n <> m -> S n <> S m.
I've tried multiple strategies but now I'm not even sure it's possible to prove this helper theorem.
I'm not sure how to prove the base case using induction:
What else can I try? Any tips for eqb_neq or the helper theorem?
Thanks
It is actually quite simple for your helper theorem if you just unfold not :
Theorem eqb_false_helper : forall n m : nat,
n <> m -> S n <> S m.
Proof.
unfold not; intros.
apply H; injection H0; intro; assumption.
Qed.
You actually just need to prove that S n = S m -> False, you assume that n = m -> False, thus you can prove that S n = S m -> n = m, which is done injecting hypothesis S n = S m.

how to simplify a equality statement

In hypothesis, I have a natural number that cannot be zero.When we add this number
to an another function,whose output is also natural number. I have to prove that result of addition of these two values equal to zero is false. I should not dig about f,because addition of anything in non zero term ,become equal to zero is false statement.
`H : (m =? 0) = false
(f+ m =? 0) = false`
Short answer:
Require Import Lia.
rewrite !Nat.eqb_neq; lia.
Long answer:
I feel sorry that this question arises. Historically, most of the reasoning in Coq about equality is done with the eq concept, with the notation m = n, not with the boolean equality, on which you rely here. It is also important to know that Coq has a specific notation for "disequality" or "non-equality" : m <> n stands for ~ (m = n).
So if you add typed the following statement instead, there would be an easy solution:
Require Import Arith Lia.
Lemma example1 f m : m <> 0 -> f + m <> 0.
Proof. lia. Qed.
Unfortunately, this does not work for the way you express your statement:
Lemma example2 f m : (m =? 0) = false -> (f + m =? 0) = false.
Proof.
Fail lia.
If you call Search with the following pattern, you see that the boolean comparison expression is logically equivalent to basic equality, but only if you use specific theorems to express this:
Search (_ =? _).
Nat.eqb_refl: forall x : nat, (x =? x) = true
beq_nat_refl: forall n : nat, true = (n =? n)
Nat.eqb_sym: forall x y : nat, (x =? y) = (y =? x)
Nat.eqb_spec: forall x y : nat, Bool.reflect (x = y) (x =? y)
beq_nat_eq: forall n m : nat, true = (n =? m) -> n = m
beq_nat_true: forall n m : nat, (n =? m) = true -> n = m
Nat.eqb_eq: forall n m : nat, (n =? m) = true <-> n = m
beq_nat_false: forall n m : nat, (n =? m) = false -> n <> m
Nat.eqb_neq: forall x y : nat, (x =? y) = false <-> x <> y
Nat.pow2_bits_eqb: forall n m : nat, Nat.testbit (2 ^ n) m = (n =? m)
Nat.bit0_eqb: forall a : nat, Nat.testbit a 0 = (a mod 2 =? 1)
Nat.eqb_compare:
forall x y : nat, (x =? y) = match x ?= y with
| Eq => true
| _ => false
end
Nat.setbit_eqb:
forall a n m : nat,
Nat.testbit (Nat.setbit a n) m = ((n =? m) || Nat.testbit a m)%bool
Nat.clearbit_eqb:
forall a n m : nat,
Nat.testbit (Nat.clearbit a n) m = (Nat.testbit a m && negb (n =? m))%bool
Nat.testbit_eqb: forall a n : nat, Nat.testbit a n = ((a / 2 ^ n) mod 2 =? 1)
But there is no theorem that expresses the interaction of addition with equality to 0. You can also see this using a more precise pattern.
Search (_ =? _) 0 (_ + _).
This returns nothing.
On the other hand, if you type
Search (_ = _) 0 (_ + _).
You see many theorems, one of which is relevant to your problem.
Nat.eq_add_0: forall n m : nat, n + m = 0 <-> n = 0 /\ m = 0
And this one is enough to solve the problem, if it is expressed with _ = _ instead of _ =? _. So to solve your specific problem, we need first to transform comparisons using _ =? _ into equality statements,and then do logical reasoning using the available theorems. In the first search result, we have the theorem Nat.eqb_neq that is adapted to your situation. Continuing on the proof of example2 above, we can write:
Rewrite !Nat.eqb_neq.
The goal becomes:
f, m : nat
============================
m <> 0 -> f + m <> 0
Now, we could do logical reasoning using the theorem Nat.eq_add_0.
rewrite Nat.eq_add_0.
We can finish the proof by small step like this.
intros mn0 [fis0 mis0]; case mn0; assumption.
we can also ask an automatic tool to finish the proof for us:
tauto.
But going a little backward in time, we can also observe the statement after rewriting with Nat.eqb_neq. This is a statement in linear arithmetic (it contains comparisons, natural numbers, and no product between variables). This statement is in the scope of a tactic for this theory, the one used most often now is lia.

Coq: remove constructor from both sides of goal

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.

Split conjunction goal into subgoals

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

Is it possible to rewrite the silly2 example from the Tactics chapter of the SF book using 'rewrite' instead of 'apply'?

Theorem silly2 : forall(n m o p : nat),
n = m ->
(forall (q r : nat), q = r -> [q;o] = [r;p]) ->
[n;o] = [m;p].
Proof.
intros n m o p eq1 eq2.
apply eq2.
apply eq1.
Qed.
The SF book implies that it would be possible to do the above using rewrite, but I just do not see how. Any idea how it would be possible to do that?
You should be able to prove it with rewrite (eq2 ? ? ?) if you properly fill the ?. Be sure to understand what is going on in order to improve your understanding of Coq.
[Hint: try pose proof (eq2 o) and see what it does]
Here are 3 different versions of this. The first one I figured out on my own before seeing the reply by ejgallego in a different context once I realized what the rewrite error messages meant.
Theorem silly2 : forall(n m o p : nat),
n = m ->
(forall (q r : nat), q = r -> [q;o] = [r;p]) ->
[n;o] = [m;p].
Proof.
intros n m o p eq1 eq2.
rewrite eq2 with (r := m).
- reflexivity.
- rewrite eq1. reflexivity.
Qed.
The second one seem to be a rewrite with a function application as per ejgallego's suggestion.
Theorem silly2' : forall(n m o p : nat),
n = m ->
(forall (q r : nat), q = r -> [q;o] = [r;p]) ->
[n;o] = [m;p].
Proof.
intros n m o p eq1 eq2.
rewrite (eq2 n m).
- reflexivity.
- rewrite eq1. reflexivity.
Qed.
The third one uses pose proof which seem to be doing function application on the hypothesis without rewriting the goal as in the above.
Theorem silly2'' : forall(n m o p : nat),
n = m ->
(forall (q r : nat), q = r -> [q;o] = [r;p]) ->
[n;o] = [m;p].
Proof.
intros n m o p eq1 eq2.
pose proof (eq2 n m).
apply H.
apply eq1.
Qed.