(** * MoreProp: More about Propositions and Evidence *)
Require Export "Prop".
(* ####################################################### *)
(** * Relations *)
(** A proposition parameterized by a number (such as [ev] or
[beautiful]) can be thought of as a _property_ -- i.e., it defines
a subset of [nat], namely those numbers for which the proposition
is provable. In the same way, a two-argument proposition can be
thought of as a _relation_ -- i.e., it defines a set of pairs for
which the proposition is provable. *)
Module LeModule.
(** One useful example is the "less than or equal to"
relation on numbers. *)
(** The following definition should be fairly intuitive. It
says that there are two ways to give evidence that one number is
less than or equal to another: either observe that they are the
same number, or give evidence that the first is less than or equal
to the predecessor of the second. *)
Inductive le : nat -> nat -> Prop :=
| le_n : forall n, le n n
| le_S : forall n m, (le n m) -> (le n (S m)).
Notation "m <= n" := (le m n).
(** Proofs of facts about [<=] using the constructors [le_n] and
[le_S] follow the same patterns as proofs about properties, like
[ev] in chapter [Prop]. We can [apply] the constructors to prove [<=]
goals (e.g., to show that [3<=3] or [3<=6]), and we can use
tactics like [inversion] to extract information from [<=]
hypotheses in the context (e.g., to prove that [(2 <= 1) -> 2+2=5].) *)
(** Here are some sanity checks on the definition. (Notice that,
although these are the same kind of simple "unit tests" as we gave
for the testing functions we wrote in the first few lectures, we
must construct their proofs explicitly -- [simpl] and
[reflexivity] don't do the job, because the proofs aren't just a
matter of simplifying computations.) *)
Theorem test_le1 :
3 <= 3.
Proof.
(* WORKED IN CLASS *)
apply le_n. Qed.
Theorem test_le2 :
3 <= 6.
Proof.
(* WORKED IN CLASS *)
apply le_S. apply le_S. apply le_S. apply le_n. Qed.
Theorem test_le3 :
(2 <= 1) -> 2 + 2 = 5.
Proof.
(* WORKED IN CLASS *)
intros H. inversion H. inversion H2. Qed.
(** The "strictly less than" relation [n < m] can now be defined
in terms of [le]. *)
End LeModule.
Definition lt (n m:nat) := le (S n) m.
Notation "m < n" := (lt m n).
(** Here are a few more simple relations on numbers: *)
Inductive square_of : nat -> nat -> Prop :=
sq : forall n:nat, square_of n (n * n).
Inductive next_nat (n:nat) : nat -> Prop :=
| nn : next_nat n (S n).
Inductive next_even (n:nat) : nat -> Prop :=
| ne_1 : ev (S n) -> next_even n (S n)
| ne_2 : ev (S (S n)) -> next_even n (S (S n)).
(** **** Exercise: 2 stars (total_relation) *)
(** Define an inductive binary relation [total_relation] that holds
between every pair of natural numbers. *)
(* FILL IN HERE *)
(** [] *)
(** **** Exercise: 2 stars (empty_relation) *)
(** Define an inductive binary relation [empty_relation] (on numbers)
that never holds. *)
(* FILL IN HERE *)
(** [] *)
(** **** Exercise: 2 stars, optional (le_exercises) *)
(** Here are a number of facts about the [<=] and [<] relations that
we are going to need later in the course. The proofs make good
practice exercises. *)
Lemma le_trans : forall m n o, m <= n -> n <= o -> m <= o.
Proof.
(* FILL IN HERE *) Admitted.
Theorem O_le_n : forall n,
0 <= n.
Proof.
(* FILL IN HERE *) Admitted.
Theorem n_le_m__Sn_le_Sm : forall n m,
n <= m -> S n <= S m.
Proof.
(* FILL IN HERE *) Admitted.
Theorem Sn_le_Sm__n_le_m : forall n m,
S n <= S m -> n <= m.
Proof.
(* FILL IN HERE *) Admitted.
Theorem le_plus_l : forall a b,
a <= a + b.
Proof.
(* FILL IN HERE *) Admitted.
Theorem plus_lt : forall n1 n2 m,
n1 + n2 < m ->
n1 < m /\ n2 < m.
Proof.
unfold lt.
(* FILL IN HERE *) Admitted.
Theorem lt_S : forall n m,
n < m ->
n < S m.
Proof.
(* FILL IN HERE *) Admitted.
Theorem ble_nat_true : forall n m,
ble_nat n m = true -> n <= m.
Proof.
(* FILL IN HERE *) Admitted.
Theorem le_ble_nat : forall n m,
n <= m ->
ble_nat n m = true.
Proof.
(* Hint: This may be easiest to prove by induction on [m]. *)
(* FILL IN HERE *) Admitted.
Theorem ble_nat_true_trans : forall n m o,
ble_nat n m = true -> ble_nat m o = true -> ble_nat n o = true.
Proof.
(* Hint: This theorem can be easily proved without using [induction]. *)
(* FILL IN HERE *) Admitted.
(** **** Exercise: 3 stars (R_provability) *)
Module R.
(** We can define three-place relations, four-place relations,
etc., in just the same way as binary relations. For example,
consider the following three-place relation on numbers: *)
Inductive R : nat -> nat -> nat -> Prop :=
| c1 : R 0 0 0
| c2 : forall m n o, R m n o -> R (S m) n (S o)
| c3 : forall m n o, R m n o -> R m (S n) (S o)
| c4 : forall m n o, R (S m) (S n) (S (S o)) -> R m n o
| c5 : forall m n o, R m n o -> R n m o.
(** - Which of the following propositions are provable?
- [R 1 1 2]
- [R 2 2 6]
- If we dropped constructor [c5] from the definition of [R],
would the set of provable propositions change? Briefly (1
sentence) explain your answer.
- If we dropped constructor [c4] from the definition of [R],
would the set of provable propositions change? Briefly (1
sentence) explain your answer.
(* FILL IN HERE *)
[]
*)
(** **** Exercise: 3 stars, optional (R_fact) *)
(** Relation [R] actually encodes a familiar function. State and prove two
theorems that formally connects the relation and the function.
That is, if [R m n o] is true, what can we say about [m],
[n], and [o], and vice versa?
*)
(* FILL IN HERE *)
(** [] *)
End R.
(* ##################################################### *)
(** * Programming with Propositions *)
(** A _proposition_ is a statement expressing a factual claim,
like "two plus two equals four." In Coq, propositions are written
as expressions of type [Prop]. Although we haven't discussed this
explicitly, we have already seen numerous examples. *)
Check (2 + 2 = 4).
(* ===> 2 + 2 = 4 : Prop *)
Check (ble_nat 3 2 = false).
(* ===> ble_nat 3 2 = false : Prop *)
Check (beautiful 8).
(* ===> beautiful 8 : Prop *)
(** Both provable and unprovable claims are perfectly good
propositions. Simply _being_ a proposition is one thing; being
_provable_ is something else! *)
Check (2 + 2 = 5).
(* ===> 2 + 2 = 5 : Prop *)
Check (beautiful 4).
(* ===> beautiful 4 : Prop *)
(** Both [2 + 2 = 4] and [2 + 2 = 5] are legal expressions
of type [Prop]. *)
(** We've mainly seen one place that propositions can appear in Coq: in
[Theorem] (and [Lemma] and [Example]) declarations. *)
Theorem plus_2_2_is_4 :
2 + 2 = 4.
Proof. reflexivity. Qed.
(** But they can be used in many other ways. For example, we have also seen that
we can give a name to a proposition using a [Definition], just as we have
given names to expressions of other sorts. *)
Definition plus_fact : Prop := 2 + 2 = 4.
Check plus_fact.
(* ===> plus_fact : Prop *)
(** We can later use this name in any situation where a proposition is
expected -- for example, as the claim in a [Theorem] declaration. *)
Theorem plus_fact_is_true :
plus_fact.
Proof. reflexivity. Qed.
(** We've seen several ways of constructing propositions.
- We can define a new proposition primitively using [Inductive].
- Given two expressions [e1] and [e2] of the same type, we can
form the proposition [e1 = e2], which states that their
values are equal.
- We can combine propositions using implication and
quantification. *)
(** We have also seen _parameterized propositions_, such as [even] and
[beautiful]. *)
Check (even 4).
(* ===> even 4 : Prop *)
Check (even 3).
(* ===> even 3 : Prop *)
Check even.
(* ===> even : nat -> Prop *)
(** The type of [even], i.e., [nat->Prop], can be pronounced in
three equivalent ways: (1) "[even] is a _function_ from numbers to
propositions," (2) "[even] is a _family_ of propositions, indexed
by a number [n]," or (3) "[even] is a _property_ of numbers." *)
(** Propositions -- including parameterized propositions -- are
first-class citizens in Coq. For example, we can define functions
from numbers to propositions... *)
Definition between (n m o: nat) : Prop :=
andb (ble_nat n o) (ble_nat o m) = true.
(** ... and then partially apply them: *)
Definition teen : nat->Prop := between 13 19.
(** We can even pass propositions -- including parameterized
propositions -- as arguments to functions: *)
Definition true_for_zero (P:nat->Prop) : Prop :=
P 0.
(** Here are two more examples of passing parameterized propositions
as arguments to a function.
The first function, [true_for_all_numbers], takes a proposition
[P] as argument and builds the proposition that [P] is true for
all natural numbers. *)
Definition true_for_all_numbers (P:nat->Prop) : Prop :=
forall n, P n.
(** The second, [preserved_by_S], takes [P] and builds the proposition
that, if [P] is true for some natural number [n'], then it is also
true by the successor of [n'] -- i.e. that [P] is _preserved by
successor_: *)
Definition preserved_by_S (P:nat->Prop) : Prop :=
forall n', P n' -> P (S n').
(** Finally, we can put these ingredients together to define
a proposition stating that induction is valid for natural numbers: *)
Definition natural_number_induction_valid : Prop :=
forall (P:nat->Prop),
true_for_zero P ->
preserved_by_S P ->
true_for_all_numbers P.
(** **** Exercise: 3 stars (combine_odd_even) *)
(** Complete the definition of the [combine_odd_even] function
below. It takes as arguments two properties of numbers [Podd] and
[Peven]. As its result, it should return a new property [P] such
that [P n] is equivalent to [Podd n] when [n] is odd, and
equivalent to [Peven n] otherwise. *)
Definition combine_odd_even (Podd Peven : nat -> Prop) : nat -> Prop :=
(* FILL IN HERE *) admit.
(** To test your definition, see whether you can prove the following
facts: *)
Theorem combine_odd_even_intro :
forall (Podd Peven : nat -> Prop) (n : nat),
(oddb n = true -> Podd n) ->
(oddb n = false -> Peven n) ->
combine_odd_even Podd Peven n.
Proof.
(* FILL IN HERE *) Admitted.
Theorem combine_odd_even_elim_odd :
forall (Podd Peven : nat -> Prop) (n : nat),
combine_odd_even Podd Peven n ->
oddb n = true ->
Podd n.
Proof.
(* FILL IN HERE *) Admitted.
Theorem combine_odd_even_elim_even :
forall (Podd Peven : nat -> Prop) (n : nat),
combine_odd_even Podd Peven n ->
oddb n = false ->
Peven n.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
(* ##################################################### *)
(** One more quick digression, for adventurous souls: if we can define
parameterized propositions using [Definition], then can we also
define them using [Fixpoint]? Of course we can! However, this
kind of "recursive parameterization" doesn't correspond to
anything very familiar from everyday mathematics. The following
exercise gives a slightly contrived example. *)
(** **** Exercise: 4 stars, optional (true_upto_n__true_everywhere) *)
(** Define a recursive function
[true_upto_n__true_everywhere] that makes
[true_upto_n_example] work. *)
(*
Fixpoint true_upto_n__true_everywhere
(* FILL IN HERE *)
Example true_upto_n_example :
(true_upto_n__true_everywhere 3 (fun n => even n))
= (even 3 -> even 2 -> even 1 -> forall m : nat, even m).
Proof. reflexivity. Qed.
*)
(** [] *)
(* $Date: 2013-07-17 16:19:11 -0400 (Wed, 17 Jul 2013) $ *)