(* Logic in Coq
Version of 2/9/2009
NOTE: This is a preliminary version of Logic.v. Do not submit it.
A full, revised version will be released on Wednesday the 4th.
You'll need to compile the previous files in order to use this one.
*)
Require Export Indsol.
(* ----------------------------------------------------- *)
(* Conjunction *)
Inductive and (A B : Prop) : Prop :=
conj : A -> B -> (and A B).
(* Intuition: To construct evidence for [and A B], we must
provide evidence for [A] and evidence for [B]. *)
(* More familiar syntax: *)
Notation "A /\ B" := (and A B) : type_scope.
(* Exercise: 1 star, optional (and_ind_principle) *)
(* See if you can predict the induction principle for
conjunction. *)
Check and_ind.
Lemma and_example :
(ev 0) /\ (ev 4).
Proof.
apply conj.
Case "left". apply ev_0.
Case "right". apply ev_SS. apply ev_SS. apply ev_0. Qed.
(* [split] is a convenient shorthand for [apply conj]. *)
Lemma and_example' :
(ev 0) /\ (ev 4).
Proof.
split.
Case "left". apply ev_0.
Case "right". apply ev_SS. apply ev_SS. apply ev_0. Qed.
(* Conversely, the [inversion] tactic can be used to
investigate a conjunction hypothesis in the context and
calculate what evidence must have been used to build
it. *)
Lemma and_1 : forall A B : Prop,
A /\ B -> A.
Proof.
intros A B H.
inversion H.
apply H0. Qed.
(* Exercise: 1 star, optional *)
Lemma and_2 : forall A B : Prop,
A /\ B -> B.
Proof.
(* OPTIONAL EXERCISE *) Admitted.
Lemma and_commut : forall A B : Prop,
A /\ B -> B /\ A.
Proof.
intros A B H.
split.
Case "left". apply and_2 with (A:=A). apply H.
Case "right". apply and_1 with (B:=B). apply H. Qed.
(* Exercise: 2 stars *)
Lemma and_assoc : forall A B C : Prop,
A /\ (B /\ C) -> (A /\ B) /\ C.
Proof.
(* FILL IN HERE (and delete "Admitted") *) Admitted.
(* Exercise: 2 stars *)
(* Now we can prove the other direction of the equivalence
of [even] and [ev]. Notice that the left-hand conjunct
here is the statement we are actually interested in;
the right-hand conjunct is needed in order to make the
induction hypothesis strong enough that we can carry
out the reasoning in the inductive step. (To see why
this is needed, try proving the left conjunct by itself
and observe where things get stuck.) *)
Lemma even_ev : forall n : nat,
(even n -> ev n) /\ (even (S n) -> ev (S n)).
Proof.
(* Hint: Use induction on [n]. *)
(* FILL IN HERE (and delete "Admitted") *) Admitted.
(* ------------------------------------------------------ *)
(* Iff *)
Definition iff (A B : Prop) := (A -> B) /\ (B -> A).
Notation "A <-> B" := (iff A B) : type_scope.
Lemma iff_implies : forall A B : Prop,
(A <-> B) -> A -> B.
Proof.
intros A B H.
inversion H. apply H0. Qed.
Lemma iff_sym : forall A B : Prop,
(A <-> B) -> (B <-> A).
Proof.
intros A B H.
inversion H.
split. (* Note that [split] is just a bit smarter than [apply conj],
which would have required an [unfold iff] first. *)
Case "->". apply H1.
Case "<-". apply H0. Qed.
(* Exercise: 1 star, optional *)
Lemma iff_refl : forall A : Prop,
A <-> A.
Proof.
(* OPTIONAL EXERCISE *) Admitted.
(* Exercise: 1 star, optional *)
Lemma iff_trans : forall A B C : Prop,
(A <-> B) -> (B <-> C) -> (A <-> C).
Proof.
(* Hint: If you have an iff hypothesis in the context, you
can use [inversion] to break it into two separate
implications. (Think about why this works.) *)
(* OPTIONAL EXERCISE *) Admitted.
(* Exercise: 2 stars *)
(* Finish the following proof by filling in an
explicit proof object *)
(** <<
Definition MyProp_iff_ev : forall n, MyProp n <-> ev n :=
FILL IN HERE
>> *)
(* ------------------------------------------------------------ *)
(* Disjunction *)
Inductive or (A B : Prop) : Prop :=
| or_introl : A -> or A B
| or_intror : B -> or A B.
Notation "A \/ B" := (or A B) : type_scope.
(* Intuition: There are two ways of giving evidence for [A \/ B]:
- give evidence for [A] (and say that it is [A] you
are giving evidence for! -- this is the function of
the [or_introl] constructor)
- give evidence for [B], tagged with the [or_intror]
constructor. *)
(* Exercise: 1 star, optional (or_ind_principle) *)
(* See if you can predict the induction principle for
disjunction. *)
Check or_ind.
(* Since [A \/ B] has two constructors, doing [inversion] on
a hypothesis of type [A \/ B] yields two subgoals. *)
Lemma or_commut : forall A B : Prop,
A \/ B -> B \/ A.
Proof.
intros A B H.
inversion H.
Case "left". apply or_intror. apply H0.
Case "right". apply or_introl. apply H0. Qed.
(* From here on, we'll use the handy tactics [left] and
[right] in place of [apply or_introl] and [apply
or_intror]. *)
Lemma or_commut' : forall A B : Prop,
A \/ B -> B \/ A.
Proof.
intros A B H.
inversion H.
Case "left". right. apply H0.
Case "right". left. apply H0. Qed.
Lemma or_distributes_over_and_1 : forall A B C : Prop,
A \/ (B /\ C) -> (A \/ B) /\ (A \/ C).
Proof.
intros A B C. intros H. inversion H.
Case "left". split.
SCase "left". left. apply H0.
SCase "right". left. apply H0.
Case "right". split.
SCase "left". right. inversion H0. apply H1.
SCase "right". right. inversion H0. apply H2. Qed.
(* Exercise: 2 stars *)
Lemma or_distributes_over_and_2 : forall A B C : Prop,
(A \/ B) /\ (A \/ C) -> A \/ (B /\ C).
Proof.
(* FILL IN HERE (and delete "Admitted") *) Admitted.
(* Exercise: 1 star, optional *)
Lemma or_distributes_over_and : forall A B C : Prop,
A \/ (B /\ C) <-> (A \/ B) /\ (A \/ C).
Proof.
(* OPTIONAL EXERCISE *) Admitted.
(* --------------------------------------------------- *)
(* Relating /\ and \/ with andb and orb *)
(* Let's record a few useful facts about the relation
between the boolean operations [andb] and [orb] and
their propositional counterparts, which we'll need
later. *)
Lemma andb_true : forall b c,
andb b c = true -> b = true /\ c = true.
Proof.
intros b c H.
destruct b.
destruct c.
apply conj. reflexivity. reflexivity.
inversion H.
inversion H. Qed.
(* Exercise: 1 star, optional *)
Lemma andb_false : forall b c,
andb b c = false -> b = false \/ c = false.
Proof.
(* OPTIONAL EXERCISE *) Admitted.
(* Exercise: 1 star, optional *)
Lemma orb_true : forall b c,
orb b c = true -> b = true \/ c = true.
Proof.
(* OPTIONAL EXERCISE *) Admitted.
(* Exercise: 1 star, optional *)
Lemma orb_false : forall b c,
orb b c = false -> b = false /\ c = false.
Proof.
(* OPTIONAL EXERCISE *) Admitted.
(* --------------------------------------------------- *)
(* Falsehood *)
Inductive False : Prop := .
(* Intuition: [False] is a proposition for which there is no
way to give evidence. *)
(* Exercise: 1 star, optional (False_ind_principle) *)
(* Can you predict the induction principle for falsehood? *)
Check False_ind.
Lemma False_implies_nonsense :
False -> plus 2 2 = 5.
Proof.
intros contra.
inversion contra. Qed.
Lemma nonsense_implies_False :
plus 2 2 = 5 -> False.
Proof.
intros contra.
inversion contra. Qed.
Lemma ex_falso_quodlibet : forall (P:Prop),
False -> P.
Proof.
intros P contra.
inversion contra. Qed.
(* ---------------------------------------------------- *)
(* Truth *)
(* Exercise: 2 stars *)
(* [True] is another inductively defined
proposition. Define it! Hint: the intution is that
[True] should be a proposition for which it is trivial
to give evidence. *)
(* FILL IN HERE *)
(* What induction principle will Coq generate for [True]? *)
(* ---------------------------------------------------- *)
(* Negation *)
Definition not (A:Prop) := A -> False.
(* Intuition: If we could prove [A], then we could prove
[False] (and hence we could prove anything at all). *)
Notation "~ x" := (not x) : type_scope.
Lemma not_False :
~ False.
Proof.
unfold not. intros H. inversion H. Qed.
Lemma contradiction_implies_anything : forall A B : Prop,
(A /\ ~A) -> B.
Proof.
intros A B H. inversion H. unfold not in H1.
apply H1 in H0. inversion H0. Qed.
Lemma double_neg : forall A : Prop,
A -> ~~A.
Proof.
intros A H. unfold not. intros G. apply G. apply H. Qed.
(* Exercise: 2 stars *)
Lemma contrapositive : forall A B : Prop,
(A -> B) -> (~B -> ~A).
Proof.
(* FILL IN HERE (and delete "Admitted") *) Admitted.
(* Exercise: 1 star, optional *)
Lemma not_both_true_and_false : forall A : Prop,
~ (A /\ ~A).
Proof.
(* FILL IN HERE (and delete "Admitted") *) Admitted.
Lemma five_not_even :
~ ev 5.
Proof.
unfold not. intros H. inversion H. inversion H1. inversion H3. Qed.
(* Exercise: 1 star, optional *)
Lemma ev_not_ev_S : forall n,
ev n -> ~ ev (S n).
Proof.
unfold not. intros n H. induction H. (* not n! *)
(* OPTIONAL EXERCISE *) Admitted.
(* Exercise: 3 stars, optional *)
Definition peirce := forall P Q: Prop,
((P->Q)->P)->P.
Definition classic := forall P:Prop,
~~P -> P.
Definition excluded_middle := forall P:Prop,
P \/~P.
Definition de_morgan_not_and_not := forall P Q:Prop,
~(~P/\~Q) -> P\/Q.
Definition implies_to_or := forall P Q:Prop,
(P->Q) -> (~P\/Q).
(* ---------------------------------------------------------- *)
(* Inequality *)
Notation "x <> y" := (~ (x = y)) : type_scope.
(* A useful proof idiom: If you are trying to prove a goal
that is nonsensical, apply the lemma
[ex_falso_quodlibet] to change the goal to [False].
This makes it easier to use assumptions of the form
[~P] that are available in the context. *)
Lemma not_false_then_true : forall b : bool,
b <> false -> b = true.
Proof.
intros b H. destruct b.
Case "b = true". reflexivity.
Case "b = false".
unfold not in H. (* optional step *)
apply ex_falso_quodlibet.
apply H. reflexivity. Qed.
(* Exercise: 2 stars *)
Lemma beq_nat_n_n' : forall n n' : nat,
n <> n'
-> beq_nat n n' = false.
Proof.
(* FILL IN HERE (and delete "Admitted") *) Admitted.
(* Exercise: 4 stars, optional *)
Lemma beq_false_not_eq : forall n m,
false = beq_nat n m -> n <> m.
Proof.
(* OPTIONAL EXERCISE *) Admitted.
(* FIX: This is just a symmetric version of the one above.
We should really delete one of them and just use the
other consistently... *)
Lemma not_eq_false_beq : forall n n' : nat,
n <> n'
-> false = beq_nat n n'.
Proof.
intros n n' H. apply beq_nat_n_n' in H.
rewrite -> H. reflexivity. Qed.
(* ------------------------------------------------------------ *)
(* Existential quantification *)
(* Here is an inductive definition of one more very
important connective: existential quantification. *)
Inductive ex (X : Set) (P : X -> Prop) : Prop :=
ex_intro : forall witness:X, P witness -> ex X P.
(* The intuition is that, in order to give evidence for
the assertion "there is some x for which P holds" we
must actually name a WITNESS -- a specific value x for
which we can give evidence that P holds. *)
(* Let's add some convenient notation for the [ex] type.
The details of how this works are not important: the
critical point is that it allows us to write [exists x,
P] or [exists x:t, P], just as we do with the [forall]
quantifier. *)
Notation "'exists' x , p" := (ex _ (fun x => p))
(at level 200, x ident, right associativity) : type_scope.
Notation "'exists' x : t , p" := (ex _ (fun x:t => p))
(at level 200, x ident, right associativity) : type_scope.
(* We can use the same tactics as always for manipulate
existentials. For example, if to prove an existential,
we [apply] the constructor [ex_intro]. Since the
premise of [ex_intro] involves a variable ([witness])
that does not appear in its conclusion, we need to
explicitly give its value when we use [apply]. *)
Example exists_example_1 : exists n, plus n (mult n n)
= 6.
Proof.
apply ex_intro with (witness:=2).
reflexivity. Qed.
(* Instead of writing [apply ex_intro with e], we can
write the convenient shorthand [exists e]. *)
Example exists_example_1' : exists n,
plus n (mult n n)
= 6.
Proof.
exists 2.
reflexivity. Qed.
(* Conversely, if we have an existential hypothesis in the
context, we can eliminate it with [inversion]. *)
Lemma exists_example_2 : forall n,
(exists m, n = plus 4 m)
-> (exists o, n = plus 2 o).
Proof.
intros n H.
inversion H.
exists (plus 2 witness).
apply H0. Qed.
(* Exercise: 2 stars *)
Lemma dist_exists_or : forall (X:Set) (P Q : X -> Prop),
(exists x, P x \/ Q x) <-> (exists x, P x) \/ (exists x, Q x).
Proof.
(* FILL IN HERE (and delete "Admitted") *) Admitted.
(* Exercise: 1 star, optional *)
Lemma dist_not_exists : forall (X:Set) (P : X -> Prop),
(forall x, P x) -> ~ (exists x, ~ P x).
Proof.
(* OPTIONAL EXERCISE *) Admitted.