Coq proof tactics - coq

I am a beginner at Coq proof system (about 4 days). I've tried hard, but I am not able to prove the following.
forall a b c : nat, S (S (a + b)) = S (S (a + c)) -> b = c.
As far as I know, we need to prove the bijectivity of +, so that we can somehow use f(b) = f(c) -> b = c. How do I do this ?

As pointed out in Vinz's answer, you can find the bijectivity theorem about plus directly in the Coq standard library. You can also prove it directly using primitive tactics and mathematical induction on a as follows.
Theorem plus_l_bij: forall a b c : nat, a + b = a + c -> b = c.
Proof.
induction a as [|a'].
intros b c H. apply H.
intros b c H. simpl plus in H. inversion H. apply IHa' in H1. apply H1.
Qed.
After induction a, the base case a = 0 is trivial.
The proof for the second case a = S a', rearranges
S a' + b = S a' + c
to
S (a' + b) = S (a' + c)
and then removes the constructor S using its bijectivity. Finally, the induction hypothesis can be applied to finish the proof.

Using SearchAbout plus or SearchPattern (_ + _ = _ + _ -> _) you could check the available lemmas about +. But if you didn't import the correct modules, that could be useless. What I usually do is that I go look at the online documentation. Here is the documentation for plus and you could have a particular look to plus_reg_l and plus_reg_r.

Related

Coq: prove while is equivalent to repeat

I'm new to Coq and to learn formal semantics I'm following the book Software Foundations.
Currently I'm in the chapter: https://softwarefoundations.cis.upenn.edu/lf-current/Imp.html. Where it defines the commands for a simple imperative language. As an exercise I've tried to add a repeat command to the language defined as follows:
Inductive ceval : com -> state -> state -> Prop :=
(* ...same as in the book *)
| E_RepeatTrue : forall st st' b c,
[ c, st ] ~> st' ->
beval st' b = true ->
[ repeat c until b end, st ] ~> st'
| E_RepeatFalse : forall st st' st'' b c,
[ c, st ] ~> st'' ->
beval st'' b = false ->
[ repeat c until b end, st'' ] ~> st' ->
[ repeat c until b end, st ] ~> st'
where "'[' c ',' st ']' '~>' st'" := (ceval c st st').
But I'm stuck trying to prove that the command repeat c until b end is equivalent to c; while ~b do c end, in the following sense:
Definition cequiv (c1 c2 : com) : Prop :=
forall (st st' : state),
([ c1, st ] ~> st') <-> ([ c2, st ] ~> st').
I defined the theorem in Coq as follows:
Theorem repeat_equiv_while : forall b c,
cequiv <{repeat c until b end}> <{c; while ~b do c end}>.
Proof.
intros.
split; intros.
- inversion H; subst.
+ apply E_Concat with st'. assumption.
apply E_WhileFalse. apply bev_not_true_iff_false.
rewrite <- H5. apply bev_negb_involutive.
+ (* infinite loop? *)
admit.
- inversion H. subst.
inversion H5. subst.
+ apply E_RepeatTrue. assumption.
apply bev_not_true_iff_false in H6.
rewrite <- H6. symmetry.
apply bev_negb_involutive.
+ admit.
Admitted.
I've managed to prove the cases where the evaluation ends in the next step but when I try to prove the other case I get stuck in a loop. I would like to apply the induction hypothesis to solve it, but I don't know how to do it. I think maybe dependent induction can help me but I couldn't manage to prove it either using it.
You have solved the easy case, in which both loops terminate. In the more interesting case that they don't, you need to use an inductive hypothesis that will claim that the loops are equivalent for the remaining iterations. This induction is well founded because the remaining iterations are fewer by one than the ones we started with. Therefore, in principle, you need to do induction on the number of iterations that the loops will make.
Now, a problem that is inherent in big-step semantics is that this number of iterations is not explicit. Therefore, the easiest way to prove your theorem is by induction on the derivation of your big-step semantics. This has to be done carefully; it has to be a dependent induction in Coq, as otherwise you will miss information in the proofs. Furthermore, in the proof of the inverse, you need to carefully generalize your goal after the inversion, otherwise the inductive hypothesis will not be strong enough to be applied.
I'm writing down the skeleton, which shows the Coq technicalities, but I'm leaving the rest admitted because I don't want to spoil the exercise. Happy proving!
Theorem repeat_equiv_while_fixed : forall b c,
cequiv <{repeat c until b end}> <{c; while ~b do c end}>.
Proof.
intros; split; intros.
- dependent induction H.
+ admit.
+ admit.
- inversion H; subst; clear H.
generalize st H2; clear st H2.
dependent induction H5; intros st0 H2.
+ admit.
+ admit.
Qed.

How to do induction on the length of a list in Coq?

When reasoning on paper, I often use arguments by induction on the length of some list. I want to formalized these arguments in Coq, but there doesn't seem to be any built in way to do induction on the length of a list.
How should I perform such an induction?
More concretely, I am trying to prove this theorem. On paper, I proved it by induction on the length of w. My goal is to formalize this proof in Coq.
There are many general patterns of induction like this one that can be covered
by the existing library on well founded induction. In this case, you can prove
any property P by induction on length of lists by using well_founded_induction, wf_inverse_image, and PeanoNat.Nat.lt_wf_0, as in the following comand:
induction l using (well_founded_induction
(wf_inverse_image _ nat _ (#length _)
PeanoNat.Nat.lt_wf_0)).
if you are working with lists of type T and proving a goal P l, this generates an
hypothesis of the form
H : forall y : list T, length y < length l -> P y
This will apply to any other datatype (like trees for instance) as long as you can map that other datatype to nat using any size function from that datatype to nat instead of length.
Note that you need to add Require Import Wellfounded. at the head of your development for this to work.
Here is how to prove a general list-length induction principle.
Require Import List Omega.
Section list_length_ind.
Variable A : Type.
Variable P : list A -> Prop.
Hypothesis H : forall xs, (forall l, length l < length xs -> P l) -> P xs.
Theorem list_length_ind : forall xs, P xs.
Proof.
assert (forall xs l : list A, length l <= length xs -> P l) as H_ind.
{ induction xs; intros l Hlen; apply H; intros l0 H0.
- inversion Hlen. omega.
- apply IHxs. simpl in Hlen. omega.
}
intros xs.
apply H_ind with (xs := xs).
omega.
Qed.
End list_length_ind.
You can use it like this
Theorem foo : forall l : list nat, ...
Proof.
induction l using list_length_ind.
...
That said, your concrete example example does not necessarily need induction on the length. You just need a sufficiently general induction hypothesis.
Import ListNotations.
(* ... some definitions elided here ... *)
Definition flip_state (s : state) :=
match s with
| A => B
| B => A
end.
Definition delta (s : state) (n : input) : state :=
match n with
| zero => s
| one => flip_state s
end.
(* ...some more definitions elided here ...*)
Theorem automata221: forall (w : list input),
extend_delta A w = B <-> Nat.odd (one_num w) = true.
Proof.
assert (forall w s, extend_delta s w = if Nat.odd (one_num w) then flip_state s else s).
{ induction w as [|i w]; intros s; simpl.
- reflexivity.
- rewrite IHw.
destruct i; simpl.
+ reflexivity.
+ rewrite <- Nat.negb_even, Nat.odd_succ.
destruct (Nat.even (one_num w)), s; reflexivity.
}
intros w.
rewrite H; simpl.
destruct (Nat.odd (one_num w)); intuition congruence.
Qed.
In case like this, it is often faster to generalize your lemma directly:
From mathcomp Require Import all_ssreflect.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Section SO.
Variable T : Type.
Implicit Types (s : seq T) (P : seq T -> Prop).
Lemma test P s : P s.
Proof.
move: {2}(size _) (leqnn (size s)) => ss; elim: ss s => [|ss ihss] s hs.
Just introduce a fresh nat for the size of the list, and regular induction will work.

Proving Gauss' theorem for nat in Coq

I'd like to prove Gauss' theorem for nat.
In plain (non-precise) language it says: if a divides b*c and none of a's factors are in b then they must all be in c.
Require Import NPeano.
Theorem Gauss_nat: forall (a b c:nat), gcd a b = 1 -> (a | (b*c)) -> (a | c).
The theorem is already defined for integers Z, see here in the Coq manual. But I need it for nat. The recommendations I have gotten so far is to use Bezout's lemma which states that
Lemma Bezout: forall (a b c:Z), Z.gcd a b = c -> exists u v, u*a+v*b=c.
However, I can't use it directly for nats since the coefficients u and v might be negative and thus it doesn't hold for nat.
Is there another proof that does not use integers in the proof?
EDIT:
As was pointed out in a comment by Mark Dickinson, the theorem and lemma are already in Coq's library. They are in NPeano, named Nat.gcd_bezout and Nat.gauss.
If you just want to obtain the result for nat, and not really avoid the use of Z, you can just reuse the proof in the standard library. Here's a sketch of how you could proceed, relying on two auxiliary lemmas:
Require Import NPeano.
Require Import ZArith.
Require Import ZArith.Znumtheory.
Require Import Omega.
Close Scope Z_scope.
Lemma Zdiv_Ndiv a b : (a | b) <-> (Z.of_nat a | Z.of_nat b)%Z.
Proof. Admitted.
Lemma Zgcd_Ngcd a b : Z.of_nat (gcd a b) = Z.gcd (Z.of_nat a) (Z.of_nat b).
Proof. Admitted.
Theorem Gauss_nat a b c : gcd a b = 1 -> (a | (b*c)) -> (a | c).
Proof.
rewrite Zdiv_Ndiv, Zdiv_Ndiv, Nat2Z.inj_mul.
intros H1 H2.
assert (H3 : Z.of_nat (gcd a b) = 1%Z) by (rewrite H1; reflexivity).
rewrite Zgcd_Ngcd in H3.
apply (Gauss _ _ _ H2).
now rewrite <- Zgcd_1_rel_prime.
Qed.

Coq proof of forall a b c: nat, b >= c -> a + b - c = a + (b - c)

Does anybody know of a proof in any of the standard libraries of Coq of the following theorem? If there is one, I couldnĀ“t find it.
forall a b c: nat, b >= c -> a + b - c = a + (b - c)
Thanks in advance,
Marcus.
It is unlikely that somewhat specific formulations would be in the standard library. In particular, for regular Presburger arithmetic, there is a powerful tactic that is complete, namely omega:
Require Import Omega.
Theorem t : forall a b c: nat, b >= c -> a + b - c = a + (b - c).
Proof.
intros. omega.
Qed.
There is a very similar lemma in the Coq standard library (checked with version 8.5pl3), it's called
Nat.add_sub_assoc
: forall n m p : nat, p <= m -> n + (m - p) = n + m - p
Here is how it can be used:
Require Import Coq.Arith.Arith.
Goal forall a b c: nat, b >= c -> a + b - c = a + (b - c).
intros a b c H.
apply (eq_sym (Nat.add_sub_assoc _ _ _ H)).
Qed.
You can use Coq's search facilities to discover it:
Require Import Coq.Arith.Arith.
Search (_ + _ - _).

apply argument to equal functions in Coq

Suppose I have two functions f and g and I know f = g. Is there a forward reasoning 'function application' tactic that will allow me to add f a = g a to the context for some a in their common domain? In this contrived example, I could use assert (f a = g a) followed by f_equal. But I want to do something like this in more complex situations; e.g.,
Lemma fapp : forall (A B : Type) (P Q : A -> B) (a : A),
(fun (a : A) => P a) = (fun (a : A) => Q a) ->
P a = Q a.
I think I can't correctly infer the general problem that you have, given your description and example.
If you already know H : f = g, you can use that to rewrite H wherever you want to show something about f and g, or just elim H to rewrite everything at once. You don't need to assert a helper theorem and if you do, you'll obviously need something like assert or pose proof.
If that equality is hidden underneath some eta-expansion, like in your example, remove that layer and then proceed as above. Here are two (out of many) possible ways of doing that:
intros A B P Q a H. assert (P = Q) as H0 by apply H. rewrite H0; reflexivity.
This solves your example proof by asserting the equality, then rewriting. Another possibility is to define eta reduction helpers (haven't found predefined ones) and using these. That will be more verbose, but might work in more complex cases.
If you define
Lemma eta_reduce : forall (A B : Type) (f : A -> B),
(fun x => f x) = f.
intros. reflexivity.
Defined.
Tactic Notation "eta" constr(f) "in" ident(H) :=
pattern (fun x => f x) in H;
rewrite -> eta_reduce in H.
you can do the following:
intros A B P Q a H. eta P in H. eta Q in H. rewrite H; reflexivity.
(That notation is a bit of a loose cannon and might rewrite in the wrong places. Don't rely on it and in case of anomalies do the pattern and rewrite manually.)
I don't have a lot of experience with Coq or its tactics, but why not just use an auxiliary theorem?
Theorem fapp': forall (t0 t1: Type) (f0 f1: t0 -> t1),
f0 = f1 -> forall (x0: t0), f0 x0 = f1 x0.
Proof.
intros.
rewrite H.
trivial.
Qed.
Lemma fapp : forall (A B : Type) (P Q : A -> B) (a : A),
(fun (a : A) => P a) = (fun (a : A) => Q a) ->
P a = Q a.
Proof.
intros.
apply fapp' with (x0 := a) in H.
trivial.
Qed.