Why is following Coq rewrite not applying on right hand side of assumption? - coq

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.

Related

Cannot rewrite goal with assertion?

I am not sure I understand why in some cases rewriting H works, and in some it doesnt.
Here for example:
Theorem add_assoc2 : forall n m: nat, n + m = m + n.
Proof. intros. rewrite add_comm. reflexivity. Qed.
Theorem plus_4: forall n m p q: nat,
n + (n * p) + m + (m * p) = n + m + (n * p) + (m * p).
Proof.
intros.
assert (H: n * p + m = m + n * p).
{ rewrite <- add_assoc2. reflexivity. }
rewrite H.
Gives:
1 goal
n, m, p, q : nat
H : n * p + m = m + n * p
______________________________________(1/1)
n + n * p + m + m * p = n + m + n * p + m * p
But Coq complains: Found no subterm matching "n * p + m" in the current goal.
Why?
I clearly see one, on the left side. When using induction, rewriting with IHn doesn't pose any problem, even if there are some other terms in front of rewriteable expression.
You can "see" a subterm n * p + m, but this is misleading: Coq doesn't show you the implicit parentheses around all the + expressions.
Use
Set Printing Parentheses.
to make them visible. Your proof state is really:
n, m, p, q : nat
H : ((n * p) + m) = (m + (n * p))
============================
(((n + (n * p)) + m) + (m * p)) = (((n + m) + (n * p)) + (m * p))
Coq was right that there is no subterm that matches H's left hand side expression ((n * p) + m). You need to rewrite using some associativity lemmas to shift the parentheses around.
Also, add_assoc2 is not a good name for a lemma forall n m: nat, n + m = m + n. This is a commutativity property, not associativity.

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

How to show injectivity of a function?

Here's what I'm trying to prove: Theorem add_n_injective : forall n m p, n + m = n + p -> m = p.
The + is notation for plus, defined as in https://softwarefoundations.cis.upenn.edu/lf-current/Basics.html:
Fixpoint plus (n : nat) (m : nat) : nat :=
match n with
| O ⇒ m
| S n' ⇒ S (plus n' m)
end.
In Agda, one can do cong (n + _) to use the fact that n + m = n + p for any n m p.
Coq's built-in tactices injection and congruence both seemed promising, but they only work for constructors.
I tried the following strategy and kept hitting weird errors or getting stuck:
make an inductive type for bundling up a proof of (n + m = s): Sum (n m s)
use the congruence tactic in a lemma that shows Sum (n m s) = Sum (n p s)
use constructing Sums, destruct, and the lemma to show that n + m = n + p
Is there an easier way to prove this? I feel like there must be some built-in tactic I'm missing or some trickery with unfold.
UPDATE
Got it:
Theorem add_n_injective : forall n m p, n + m = n + p -> m = p.
Proof.
intros. induction n.
- exact H.
- apply IHn. (* goal: n + m = n + p *)
simpl in H. (* H: S (n + m) = S (n + p) *)
congruence.
Qed.
Thanks #ejgallego
Injectivity of plus is not an "elementary" statement, given that the plus function could be arbitrary (and non-injective)
I'd say the standard proof does require induction on the left argument, indeed using this method the proof quickly follows.
You will need injection when you arrive to a goal of the form S (n + m) = S (n + p) to derive the inner equality.

even (n + m) -> even n /\ even m \/ odd n /\ odd m

How can I prove this lemma:
Lemma even_plus_split n m :
even (n + m) -> even n /\ even m \/ odd n /\ odd m.
These are the only libraries and definition that can be used:
Require Import Arith.
Require Import Coq.omega.Omega.
Definition even (n: nat) := exists k, n = 2 * k.
Definition odd (n: nat) := exists k, n = 2 * k + 1.
I am new to Coq and confused about it. Can you give me a solution? Thanks in advance!
the code so far:
Lemma even_plus_split n m :
even (n + m) -> even n /\ even m \/ odd n /\ odd m.
Proof.
intros.
unfold even.
unfold even in H.
destruct H as [k H].
unfold odd.
exists (1/2*k).
result so far:
1 subgoal
n, m, k : nat
H : n + m = 2 * k
______________________________________(1/1)
(exists k0 : nat, n = 2 * k0) /\ (exists k0 : nat, m = 2 * k0) \/
(exists k0 : nat, n = 2 * k0 + 1) /\ (exists k0 : nat, m = 2 * k0 + 1)
I just want to make k0 equals to 1/2*k, and therefore I suppose it would make sense, but I can't do that.
I just want to make k0 equals to 1/2*k, and therefore I suppose it would make sense, but I can't do that.
There is a function called Nat.div2, which divides a natural number by 2. Running Search Nat.div2.
Nat.le_div2: forall n : nat, Nat.div2 (S n) <= n
Nat.lt_div2: forall n : nat, 0 < n -> Nat.div2 n < n
Nat.div2_decr: forall a n : nat, a <= S n -> Nat.div2 a <= n
Nat.div2_wd: Morphisms.Proper (Morphisms.respectful eq eq) Nat.div2
Nat.div2_spec: forall a : nat, Nat.div2 a = Nat.shiftr a 1
Nnat.N2Nat.inj_div2: forall a : N, N.to_nat (N.div2 a) = Nat.div2 (N.to_nat a)
Nnat.Nat2N.inj_div2: forall n : nat, N.of_nat (Nat.div2 n) = N.div2 (N.of_nat n)
Nat.div2_double: forall n : nat, Nat.div2 (2 * n) = n
Nat.div2_div: forall a : nat, Nat.div2 a = a / 2
Nat.div2_succ_double: forall n : nat, Nat.div2 (S (2 * n)) = n
Nat.div2_odd: forall a : nat, a = 2 * Nat.div2 a + Nat.b2n (Nat.odd a)
Nat.div2_bitwise:
forall (op : bool -> bool -> bool) (n a b : nat),
Nat.div2 (Nat.bitwise op (S n) a b) = Nat.bitwise op n (Nat.div2 a) (Nat.div2 b)
Of these, the most promising seems to be Nat.div2_odd: forall a : nat, a = 2 * Nat.div2 a + Nat.b2n (Nat.odd a). If you pose proof this lemma, you can destruct (Nat.odd a) and use simpl to get that either a = 2 * Nat.div2 a or a = 2 * Nat.div2 a + 1, for whichever a you choose.
This may not give you a solution directly (I am not convinced that setting k0 to k / 2 is the right decision), but if it does not, you should make sure that you can figure out how to prove this fact on paper before you try it in Coq. Coq is very good at making sure that you don't make any jumps of logic that you're not allowed to make; it's extremely bad at helping you figure out how to prove a fact that you don't yet know how to prove.
Everybody who tries to answer seems to be dancing around the fact that you actually chose a wrong direction for this proof. Here is a example:
if n = 601 and m = 399, then n + m = 2 * 500,
n = 2 * 300 + 1, and m = 2 * 199 + 1.
Between 500, 300, and 199, the 1/2 ratio does not appear anywhere.
Still the statement (even n /\ even m) / (odd n /\ odd m) is definitely true.
So for now, you have more a math problem than a Coq problem.
You have to make a proof for universally quantified numbers n and m, but somehow this proof should also work for specific choices of these numbers. So in a sense you can make the mental exercise of testing your proof on examples.

how to rearrange terms in Coq using plus communtativity and associativity?

I have a general question about how to rearrange terms in Coq. For example, if we have a term m + p + n + p, humans can quickly re-arrange the terms to something like m + n + p + p (implicitly using plus_comm and plus_assoc). How do we do this efficiently in Coq?
For a (silly) example,
Require Import Coq.Arith.Plus.
Require Import Coq.Setoids.Setoid.
Theorem plus_comm_test: forall n m p: nat,
m + p + (n + p) = m + n + 2 * p.
Proof. intros. rewrite plus_assoc. simpl. rewrite <- plus_n_O.
Now, we have
1 subgoals
...
______________________________________(1/1)
m + p + n + p = m + n + (p + p)
My question is:
How do I rewrite the LHS to m + n + p + p effectively?
I tried to use rewrite plus_comm at 2, but it gives an error Nothing to rewrite. Simply using rewrite plus_comm changes the LHS to p + m + n + p.
Any suggestions on effective rewrites are also welcome.
Thanks.
In this particular case (linear arithmetic over the integers), you can just use the omega tactic:
Require Import Omega.
Theorem plus_comm_test: forall n m p: nat,
m + p + (n + p) = m + n + 2 * p.
Proof. intros; omega. Qed.
However, there are situations where omega is not enough. In those cases, the standard rewrite tactic is not very convenient. The Ssreflect library comes with its own version of the rewrite tactic, that works much better for tasks such as rewriting on sub-terms of your goal. For instance:
Require Import Ssreflect.ssreflect Ssreflect.ssrfun Ssreflect.ssrbool.
Require Import Ssreflect.ssrnat.
Theorem plus_comm_test: forall n m p: nat,
m + p + (n + p) = m + n + 2 * p.
Proof.
move=> n m p.
by rewrite -addnA [p + _]addnC -[_ + p]addnA addnn -mul2n addnA.
Qed.
The annotations in square brackets, such as [p + _], provide patterns that help the rewrite tactic figure out where to act. The addn* lemmas and friends are Ssreflect's own version of the standard arithmetic results over the natural numbers.
As Arthur says sometimes omega is not enough, but I sometimes use it for simple steps like this.
Require Import Omega.
Theorem test: forall a b c:nat, a + b + 2 * c = c + b + a + c.
intros.
replace (c + b + a) with (a + b + c) by omega.
replace (a + b + c + c) with (a + b + (c + c)) by omega.
replace (c + c) with (2 * c) by omega.
reflexivity.
Qed.
This is a silly example, because omega would have solved it all in one go, but sometimes you want to rewrite things inside functions that omega can't reach into without a little help...
The ring tactic is able to prove equality of these rearrangements.
Using your example:
Require Import ZArith.
Open Scope Z_scope.
(* Both "ring" and "omega" can prove this. *)
Theorem plus_comm_test : forall n m p : Z,
m + p + (n + p) = m + n + 2 * p.
Proof.
intros.
ring.
Qed.
ring works on the integers, but I don't think it works on the natural numbers.
However, ring is able to prove some identities that omega cannot prove. (The docs say, "Multiplication is handled by omega but only goals where at least one of the two multiplicands of products is a constant are solvable. This is the restriction meant by "Presburger arithmetic".")
For example:
(* "ring" can prove this but "omega" cannot. *)
Theorem rearrange_test : forall a b c : Z,
a * (b + c) = c*a + b*a.
Proof.
intros.
ring.
Qed.