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 (_ /\ _ -> _).
Related
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.
I have two setoids and bisimilar:
Definition of lang_iff:
Definition lang := str -> Prop.
Definition lang_iff (s1 s2: lang): Prop :=
forall (s: str),
s \in s1 <-> s \in s2.
The setoid lang_setoid:
Add Parametric Relation: lang lang_iff
reflexivity proved by lang_iff_refl
symmetry proved by lang_iff_sym
transitivity proved by lang_iff_trans as lang_setoid.
Definition of bisimilar:
CoInductive bisimilar : lang -> lang -> Prop :=
| bisim : forall (P Q: lang),
...
-> bisimilar P Q.
The bisimilar_setoid:
Add Parametric Relation: lang bisimilar
reflexivity proved by bisimilar_refl
symmetry proved by bisimilar_sym
transitivity proved by bisimilar_trans as bisimilar_setoid.
These are proven to be equivalent:
Theorem bisimilar_is_equivalence:
forall (P Q: lang),
bisimilar P Q <-> lang_iff P Q.
I can manually rewrite between them with some acrobatics, but was wondering if there is a way to help Coq to see that it can rewrite between two setoids and make the following possible without Fail:
Example example_rewriting_using_lang_iff_in_bisimilar:
forall (P Q: lang)
(pq: lang_iff P Q),
bismilar Q P.
Proof.
intros.
Fail rewrite pq.
Fail reflexivity.
Abort.
The reason for this question is that it is useful to take some steps with coinduction in bisimilar and then resolve an equivalence with lang_iff.
A second part of this question is whether we need to preprove all the morphisms from lang_iff in bimisilar or if there is some command to reuse them?
You can register bisimilar as a morphism for lang_iff:
Add Parametric Morphism : bisimilar
with signature lang_iff ==> lang_iff ==> iff as bisimilar_lang_morphism.
Proof.
intros ?? H ?? H'.
apply bisimilar_is_equivalence in H, H'.
split; intro H0.
now rewrite <- H, H0.
now rewrite H, H'.
Qed.
And now rewriting works in your proof script:
Example example_rewriting_using_lang_iff_in_bisimilar:
forall (P Q: lang)
(pq: lang_iff P Q),
bisimilar Q P.
Proof.
intros.
rewrite pq.
reflexivity.
Qed.
I'm not sure how to word my question, because I'm new to coq. I want to use refine with a theorem that includes bi-implication. Example code:
Parameters A B C : Prop.
Theorem t1:
A -> B -> C.
Admitted.
Theorem t2:
A -> B <-> C.
Admitted.
Theorem test1:
A -> B -> C.
Proof.
intros.
refine (t1 _ _).
assumption.
assumption.
Qed.
Theorem test2:
A -> B -> C.
Proof.
intros A B.
refine (t2 _ _).
t1 and t2 are theorems I want to use in refine. t1 works how i expect (shown in test1). But i have a problem with t2. The error I get is:
Ltac call to "refine (uconstr)" failed.
Error: Illegal application (Non-functional construction):
The expression "t2 ?a" of type "Top.B <-> C"
cannot be applied to the term
"?y" : "?T"
Not in proof mode.
What I have tried is something like this:
Theorem test3:
A -> B -> C.
Proof.
intros.
cut (B <-> C).
firstorder.
refine (t2 _).
assumption.
Qed.
But with longer props and proofs, it becomes a bit messy. (Also I have to prove the bi-implication myself). Can I use t2 and get its subgoals in a simpler way?
Thanks
A <-> B is defined as (A -> B) /\ (B -> A) so you can project with proj1, proj2:
Theorem test2:
A -> B -> C.
Proof.
intros A B.
refine (proj1 (t2 _) _).
I am completely new to coq programming and unable to prove below theorem. I need help on steps how to solve below construct?
Theorem PeirceContra: forall (p q:Prop), ~p->~((p ->q) ->p).
I tried the proof below way.
Given axiom as Axiom classic : forall P:Prop, P \/ ~ P.
Theorem PeirceContra: forall (p q:Prop), ~ p -> ~((p -> q) -> p).
Proof.
unfold not.
intros.
apply H.
destruct (classic p) as [ p_true | p_not_true].
- apply p_true.
- elimtype False. apply H.
Qed.
Getting subgoal after using elimtype and apply H as
1 subgoal
p, q : Prop
H : p -> False
H0 : (p -> q) -> p
p_not_true : ~ p
______________________________________(1/1)
p
But now I am stuck here because I am unable to prove P using p_not_true construct of given axiom......Please suggest some help......
I am not clear how to use the given axiom to prove logic................
This lemma can be proved constructively. If you think about what can be done at each step to make progress the lemma proves itself:
Lemma PeirceContra :
forall P Q, ~P -> ~((P -> Q) -> P).
Proof.
intros P Q np.
unfold "~".
intros pq_p.
apply np. (* this is pretty much the only thing we can do at this point *)
apply pq_p. (* this is almost inevitable too *)
(* the rest should be easy *)
(* Qed. *)
I've been going through the Software Foundations course and found the following proof (source link).
Theorem not_exists_dist :
excluded_middle ->
forall (X:Type) (P : X -> Prop),
~ (exists x, ~ P x) -> (forall x, P x).
Proof.
unfold not. intros.
unfold excluded_middle in H.
assert ((P x) \/ ((P x) -> False)) as HP.
apply H with (P:=(P x)).
inversion HP.
apply H1.
apply ex_falso_quodlibet. apply H0. exists x. apply H1.
Qed.
I'm curious, why is there an assertion saying (P x) \/ ((P x) -> False), when if I unfold excluded_middle in H and unfold not in H, I'll get the exact same H : forall P : Prop, P \/ (P -> False) as the assertion, only that there's a universal quantifier.
This is even more obvious as the assertion can be proved just by doing apply H, and the whole reason for this step is to do inversion HP on the newly asserted hypothsesis.
The question is, why isn't it possible to do inversion H at the beginning directly, and spare the extra step of defining an assertion, which just copies one of the assumptions? Is there a better way to do this?
inversion only works on things of inductive type, such as or. forall is not an inductive type constructor, hence one cannot perform inversion on it. One could maybe extend inversion to behave like (e)destruct: if you give it something that is universally quantified, it'll generate additional existentials and proof obligations that you need to fulfill to fill in the missing spots, as well as destructing the conclusion. However, this is not how it works right now...
One could do a more direct proof by just applying H and destructing it directly:
Theorem not_exists_dist :
excluded_middle ->
forall (X:Type) (P : X -> Prop),
~ (exists x, ~ P x) -> (forall x, P x).
Proof.
intros.
destruct (H (P x)).
apply H1.
exfalso. apply H0. exists x. apply H1.
Qed.