I can figure out how to prove my "degree_descent" Theorem below if I really need to:
Variable X : Type.
Variable degree : X -> nat.
Variable P : X -> Prop.
Axiom inductive_by_degree : forall n, (forall x, S (degree x) = n -> P x) -> (forall x, degree x = n -> P x).
Lemma hacky_rephrasing : forall n, forall x, degree x = n -> P x.
Proof. induction n; intros.
- apply (inductive_by_degree 0). discriminate. exact H.
- apply (inductive_by_degree (S n)); try exact H. intros y K. apply IHn. injection K; auto.
Qed.
Theorem degree_descent : forall x, P x.
Proof. intro. apply (hacky_rephrasing (degree x)); reflexivity.
Qed.
but this "hacky_rephrasing" Lemma is an ugly and unintuitive pattern to me. Is there a better way to prove degree_descent all by itself? For example, using set or pose to introduce n := degree x and then invoking induction n isn't working because it annihilates the hypothesis from the subsequent contexts (if someone could explain why this occurs, too, that would be helpful!). I can't figure out how to get generalize to work with me here, either.
PS: This is just weak induction for simplicity, but ideally I would like the solution to work with custom induction schemes via induction ... using ....
It looks like you would like to use the remember tactic:
Variable X : Type.
Variable degree : X -> nat.
Variable P : X -> Prop.
Axiom inductive_by_degree : forall n, (forall x, S (degree x) = n -> P x) -> (forall x, degree x = n -> P x).
Theorem degree_descent : forall x, P x.
Proof.
intro x. remember (degree x) as n eqn:E.
symmetry in E. revert x E.
(* Goal: forall x : X, degree x = n -> P x *)
Restart. From Coq Require Import ssreflect.
(* Or ssreflect style *)
move=> x; move: {2}(degree x) (eq_refl : degree x = _)=> n.
(* ... *)
Related
I work on mereology and I wanted to prove that a given theorem (Extensionality) follows from the four axioms I had.
This is my code:
Require Import Classical.
Parameter Entity: Set.
Parameter P : Entity -> Entity -> Prop.
Axiom P_refl : forall x, P x x.
Axiom P_trans : forall x y z,
P x y -> P y z -> P x z.
Axiom P_antisym : forall x y,
P x y -> P y x -> x = y.
Definition PP x y := P x y /\ x <> y.
Definition O x y := exists z, P z x /\ P z y.
Axiom strong_supp : forall x y,
~ P y x -> exists z, P z y /\ ~ O z x.
And this is my proof:
Theorem extension : forall x y,
(exists z, PP z x) -> (forall z, PP z x <-> PP z y) -> x = y.
Proof.
intros x y [w PPwx] H.
apply Peirce.
intros Hcontra.
destruct (classic (P y x)) as [yesP|notP].
- pose proof (H y) as [].
destruct H0.
split; auto.
contradiction.
- pose proof (strong_supp x y notP) as [z []].
assert (y = z).
apply Peirce.
intros Hcontra'.
pose proof (H z) as [].
destruct H3.
split; auto.
destruct H1.
exists z.
split.
apply P_refl.
assumption.
rewrite <- H2 in H1.
pose proof (H w) as [].
pose proof (H3 PPwx).
destruct PPwx.
destruct H5.
destruct H1.
exists w.
split; assumption.
Qed.
I’m happy with the fact that I completed this proof. However, I find it quite messy. And I don’t know how to improve it. (The only thing I think of is to use patterns instead of destruct.) It is possible to improve this proof? If so, please do not use super complex tactics: I would like to understand the upgrades you will propose.
Here is a refactoring of your proof:
Require Import Classical.
Parameter Entity: Set.
Parameter P : Entity -> Entity -> Prop.
Axiom P_refl : forall x, P x x.
Axiom P_trans : forall x y z,
P x y -> P y z -> P x z.
Axiom P_antisym : forall x y,
P x y -> P y x -> x = y.
Definition PP x y := P x y /\ x <> y.
Definition O x y := exists z, P z x /\ P z y.
Axiom strong_supp : forall x y,
~ P y x -> exists z, P z y /\ ~ O z x.
Theorem extension : forall x y,
(exists z, PP z x) -> (forall z, PP z x <-> PP z y) -> x = y.
Proof.
intros x y [w PPwx] x_equiv_y.
apply NNPP. intros x_ne_y.
assert (~ P y x) as NPyx.
{ intros Pxy.
enough (PP y y) as [_ y_ne_y] by congruence.
rewrite <- x_equiv_y. split; congruence. }
destruct (strong_supp x y NPyx) as (z & Pzy & NOzx).
assert (y <> z) as y_ne_z.
{ intros <-. (* Substitute z right away. *)
assert (PP w y) as [Pwy NEwy] by (rewrite <- x_equiv_y; trivial).
destruct PPwx as [Pwx NEwx].
apply NOzx.
now exists w. }
assert (PP z x) as [Pzx _].
{ rewrite x_equiv_y. split; congruence. }
apply NOzx. exists z. split; trivial.
apply P_refl.
Qed.
The main changes are:
Give explicit and informative names to all the intermediate hypotheses (i.e., avoid doing destruct foo as [x []])
Use curly braces to separate the proofs of the intermediate assertions from the main proof.
Use the congruence tactic to automate some of the low-level equality reasoning. Roughly speaking, this tactic solves goals that can be established just by rewriting with equalities and pruning subgoals with contradictory statements like x <> x.
Condense trivial proof steps using the assert ... by tactic, which does not generate new subgoals.
Use the (a & b & c) destruct patterns rather than [a [b c]], which are harder to read.
Rewrite with x_equiv_y to avoid doing sequences such as specialize... destruct... apply H0 in H1
Avoid some unnecessary uses of classical reasoning.
I've been trying to prove a Lemma in Coq that like this,
Goal forall (X : Type) (p : X -> Prop),
(exists x, ~ p x) <-> ~ (forall x, p x).
This is my attempt at it,
Proof.
intros X p. split.
- intros [x B] C. apply B. apply C.
- simpl. intros H.
I got stuck, with this.
1 subgoal
X : Type
p : X -> Prop
H : ~ (forall x : X, p x)
______________________________________(1/1)
exists x : X, ~ p x
And now, my thinking is that maybe i could destruct H in a certain way to progress. Or maybe there's a better way of finishing this? Please help, thanks in advance!
yep, you need an extra axiom
If you do :
Require Import Classical.
Check classic.
now using classic, you can do the proof.
My goal is like below. Are there any tactics to solve these trivial goals?
Goal forall A (x : A) P Q,
(forall y, P y /\ Q y) ->
Q x.
Proof.
intros. intuition. auto.
Abort.
(* a more complex version *)
Goal forall A (x : A) P Q R,
(forall y, R -> P y /\ Q y) ->
R ->
Q x.
Proof.
intros. intuition. auto.
Abort.
The tactic intuition does not work because that tactic is designed for propositional logic (i.e. it dos not the quantifier in forall y, R -> ... There is another tactic for this, it is called firstorder. Try it!
I'm new to inductive predicates in Coq. I have learned how to define simple inductive predicates such as "even" (as in adam.chlipala.net/cpdt/html/Predicates.html) or "last" (as in http://www.cse.chalmers.se/research/group/logic/TypesSS05/resources/coq/CoqArt/inductive-prop-chap/SRC/last.v).
Now I wanted to try something slightly more complicated: to define addition as an inductive predicate, but I got stuck. I did the following:
Inductive N : Type :=
| z : N (* zero *)
| s : N -> N. (* successor *)
Inductive Add: N -> N -> N -> Prop :=
| add_z: forall n, (Add n z n)
| add_s: forall m n r, (Add m n r) -> (Add m (s n) (s r)).
Fixpoint plus (x y : N) :=
match y with
| z => x
| (s n) => (s (plus x n))
end.
And I would like to prove a simple theorem (analogously to what has been done for last and last_fun in www.cse.chalmers.se/research/group/logic/TypesSS05/resources/coq/CoqArt/inductive-prop-chap/SRC/last.v):
Theorem T1: forall x y r, (plus x y) = r -> (Add x y r).
Proof.
intros x y r. induction y.
simpl. intro H. rewrite H. apply add_z.
case r.
simpl. intro H. discriminate H.
???
But then I get stuck. The induction hypothesis seems strange. I don't know if I defined Add wrongly, or if I am just using wrong tactics. Could you please help me, by either correcting my inductive Add or telling me how to complete this proof?
You introduced r before using induction on y. In general you'll want to use induction before introducing anything so the induction hypothesis is as general as possible.
Conjecture injectivity : forall n m, s n = s m -> n = m.
Theorem T1: forall x y r, (plus x y) = r -> (Add x y r).
Proof.
intros x y. induction y.
simpl. intros r H. rewrite H. apply add_z.
intro r. case r.
simpl. intro H. discriminate H.
simpl. intros n H. apply add_s. apply IHy. apply injectivity. apply H.
Qed.
Is it possible to give a counterexample for a statement which doesn't hold in general? Like, for example that the all quantor does not distribute over the connective "or". How would you state that to begin with?
Parameter X : Set.
Parameter P : X -> Prop.
Parameter Q : X -> Prop.
(* This holds in general *)
Theorem forall_distributes_over_and
: (forall x:X, P x /\ Q x) -> ((forall x:X, P x) /\ (forall x:X, Q x)).
Proof.
intro H. split. apply H. apply H.
Qed.
(* This doesn't hold in general *)
Theorem forall_doesnt_distributes_over_or
: (forall x:X, P x \/ Q x) -> ((forall x:X, P x) \/ (forall x:X, Q x)).
Abort.
Here is a quick and dirty way to prove something similar to what you want:
Theorem forall_doesnt_distributes_over_or:
~ (forall X P Q, (forall x:X, P x \/ Q x) -> ((forall x:X, P x) \/ (forall x:X, Q x))).
Proof.
intros H.
assert (X : forall x : bool, x = true \/ x = false).
destruct x; intuition.
specialize (H _ (fun b => b = true) (fun b => b = false) X).
destruct H as [H|H].
now specialize (H false).
now specialize (H true).
Qed.
I have to quantify X P and Q inside the negation in order to be able to provide the one I want. You couldn't quite do that with your Parameters as they somehow fixed an abstract X, P and Q, thus making your theorem potentially true.
In general, if you want to produce a counterexample, you can state the negation of the formula and then prove that this negation is satisfied.