Coq: prove while is equivalent to repeat - coq

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.

Related

how do I prove forall P Q : Prop, ((((P -> Q) -> P) -> P) -> Q) ->Q. in coq?

I am very new to coq so if you only say intros. I don't know what to introduce. So being specific like (Ex. intros p q.) would be very helpful.
Fortunately, your goal can be automatically solved by the auto tactic.
If you use its variant info_auto, Coq tells you which steps lead to the solution .
Goal forall P Q : Prop, ((((P -> Q) -> P) -> P) -> Q) -> Q.
info_auto.
Then, you may replay the proof by yourself, and add comments and explicit variables names to the introstactics, and you will understand the
strategy used by auto (what to do when the conclusion is a forall or an implication, or an atomic proposition).
Restart.
intros P Q H.
apply H (* no-choice ! *).
intro H0.
apply H0. (* no other possibility ! *)
intro p.
apply H. (* no alternative ! *)
intros _.
assumption.
Qed.

Weak Excluded Middle Implies Morgan law for conjunction

I am currently following the book Computational Type Theory and Interactive Theorem Proving with Coq by Gert Smolka and on page 75, there is exercise 9.3.14.b asking me to prove that the 'weak law of excluded middle' defined as:
Definition WXM : Prop := forall (X:Prop), ~X \/ ~~X.
implies the Morgan law for conjunction:
Definition MGC : Prop := forall (X Y:Prop), ~(X/\Y) -> ~X \/ ~Y. (* <- always true *)
i.e.
Lemma L1 : WXM -> MGC
Proof.
Admitted.
I have been trying for solve this for a while now, but with no success. Assuming WXM
and ~(X/\Y) for some Prop X Y, faced with the goal ~X \/ ~Y, I did a case
analysis (applying WXM on X and Y). Out of the 4 cases, 3 are immediately dispatched but I am left with a 4th cases with additional assumptions ~~X and ~~Y.
Intuitively ~~X and ~~Y are saying that X and Y are 'weakly true' and you would hope to conclude that X /\ Y is also weakly true (i.e. show ~~(X/\Y) leading to a contradiction thanks to the assumption ~(X/\Y)). However, I am not able to conclude.
I don't want to give up but would also like to move on with the book. Does anyone have the answer to this?.
One does not need to consider the four cases here, because one has negated disjuncts in the goal giving some terms to work with when one chooses which disjunct to prove. Getting e.g. ~ Q and ~ ~ Q cases is enough to prove the lemma.
I'm not sure how to explain this intuition further without just showing the solution.
Goal
(forall P : Prop, ~ P \/ ~ ~ P) ->
(forall P Q : Prop, ~ (P /\ Q) -> ~ P \/ ~ Q).
Proof.
intros wlem P Q npq.
destruct (wlem Q) as [nq | nnq].
- right; trivial.
- left; intros p.
apply nnq; intros q.
apply npq; split; trivial.
Qed.

Disjunctive Syllogism tactic in Coq?

I am learning propositional logic and the rules of inference. The Disjunctive Syllogism rule states that if we have in our premises (P or Q), and also (not P); then we can reach Q.
I can not for the life of me figure out how to do this in Coq. Let's say I have :
H : A \/ B
H0 : ~ A
______________________________________(1/1)
What tactic should I use to reach
H1 : B.
As an extra, I would be glad if someone could share with me the Coq tactic equivalents of basic inference rules, like modus tollens, or disjunctive introduction etc. Is there maybe a plugin I can use?
Coq does not have this tactic built-in, but fortunately you can define your own tactics. Notice that
destruct H as [H1 | H1]; [contradiction |].
puts H1 : B in the context, just as you asked. So you can create an alias for this combined tactic:
Ltac disj_syllogism AorB notA B :=
destruct AorB as [? | B]; [contradiction |].
Now we can easily imitate the disjunctive syllogism rule like so:
Section Foo.
Context (A B : Prop) (H : A \/ B) (H0 : ~ A).
Goal True.
disj_syllogism H H0 H1.
End Foo.
Let me show a couple less automated approaches:
Ltac disj_syllogism AorB notA B :=
let A := fresh "A" in
destruct AorB as [A | B]; [contradiction (notA A) |].
This approach does not ask Coq to find a contradiction, it provides it directly to the contradiction tactic (notA A term). Or we could have used an explicit term with the pose proof tactic:
Ltac disj_syllogism AorB notA B :=
pose proof (match AorB with
| or_introl a => False_ind _ (notA a)
| or_intror b => b
end) as B.
I hope this helps. I'm not sure if some extra explanation is needed -- feel free to ask for clarification and I'll update my answer.
I think you maybe have the wrong expectations on how Coq works? The general way of proving this is essentially a truth-table on the different possibilities:
Lemma it: forall a b, (a \/ b) /\ ~a -> b.
Proof.
intuition.
Show Proof.
Qed.
(fun (a b : Prop) (H : (a \/ b) /\ ~ a) =>
and_ind
(fun (H0 : a \/ b) (H1 : ~ a) =>
or_ind (fun H2 : a => let H3 : False := H1 H2 in False_ind b H3)
(fun H2 : b => H2) H0) H)
If you look at the resulting proof-term, you see the Coq is essentially taking apart the boolean the constructors. We can do this manually and get the same proof-term:
Lemma it: forall a b, (a \/ b) /\ ~a -> b.
Proof.
intros a b H.
induction H.
induction H.
contradict H. exact H0.
exact H.
Qed.
Whereas e.g. modus ponens corresponds to an apply in Coq, I don't think this is "built in" in any direct way.
Afterwards, you can use this lemma (and I'm sure there's a corresponding version somewhere in the standard library) to derive your additional hypothesis through apply.

How does `auto` interract with biconditional (iff)

I noticed, that auto is ignoring biconditionals. Here is a simplified example:
Parameter A B : Prop.
Parameter A_iff_B : A <-> B.
Theorem foo1: A -> B.
Proof.
intros H. apply A_iff_B. assumption.
Qed.
Theorem bar1: B -> A.
Proof.
intros H. apply A_iff_B. assumption.
Qed.
Theorem foo2_failing: A -> B.
Proof.
intros H. auto using A_iff_B.
Abort.
Theorem bar2_failing: B -> A.
Proof.
intros H. auto using A_iff_B.
Abort.
Now, I know that A <-> B is a syntactic sugar for A -> B /\ B -> A so I wrote two theorems to extract one or the other:
Theorem iff_forward : forall {P Q : Prop},
(P <-> Q) -> P -> Q.
Proof.
intros P Q H. apply H.
Qed.
Theorem iff_backward : forall {P Q : Prop},
(P <-> Q) -> Q -> P.
Proof.
intros P Q H. apply H.
Qed.
Theorem foo3: A -> B.
Proof.
intros H.
auto using (iff_forward A_iff_B).
Qed.
Theorem bar3: B -> A.
Proof.
intros H.
auto using (iff_backward A_iff_B).
Qed.
How come apply A_iff_B works and auto using A_iff_B does not? I
thought that auto n is performing an exhaustive search of all
possible sequences of apply of length <= n using the hypotheses
and all theorems in a given database.
Is there a standard trick for working with biconditionals or are
those two projection functions the usual solution?
Are such projection functions somewhere in the standard library? I
could not found them.
How come apply A_iff_B works and auto using A_iff_B does not?
auto generally uses simple apply instead of apply and this restricted version of apply does not handle biconditionals.
Is there a standard trick for working with biconditionals or are those two projection functions the usual solution?
You can use Hint Resolve -> (<-) feature for that:
Hint Resolve -> A_iff_B.
Hint Resolve <- A_iff_B. (* if you remove this one, then `auto` won't be able to prove the `bar3` theorem *)
Theorem foo3: A -> B.
Proof. info_auto. Qed. (* look at the output *)
Are such projection functions somewhere in the standard library?
Yes, they are called: proj1 and proj2. Here is how you can find them:
Search (?A /\ ?B -> ?A).
Or a bit easier to type, but finds a tad more stuff than we need:
Search (_ /\ _ -> _).

Coq proof tactics

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.