RelProperties of Relations
Set Warnings "-notation-overridden,-parsing,-deprecated-hint-without-locality".
From LF Require Export IndProp.
From LF Require Export IndProp.
Relations
Definition relation (X: Type) := X → X → Prop.
An example relation on nat is le, the less-than-or-equal-to
relation, which we usually write n1 ≤ n2.
Print le.
(* ====> Inductive le (n : nat) : nat -> Prop :=
le_n : n <= n
| le_S : forall m : nat, n <= m -> n <= S m *)
Check le : nat → nat → Prop.
Check le : relation nat.
(* ====> Inductive le (n : nat) : nat -> Prop :=
le_n : n <= n
| le_S : forall m : nat, n <= m -> n <= S m *)
Check le : nat → nat → Prop.
Check le : relation nat.
(Why did we write it this way instead of starting with Inductive
le : relation nat...? Because we wanted to put the first nat
to the left of the :, which makes Coq generate a somewhat nicer
induction principle for reasoning about ≤.)
Basic Properties
Partial Functions
Definition partial_function {X: Type} (R: relation X) :=
∀ x y1 y2 : X, R x y1 → R x y2 → y1 = y2.
∀ x y1 y2 : X, R x y1 → R x y2 → y1 = y2.
For example, the next_nat relation is a partial function.
Inductive next_nat : nat → nat → Prop :=
| nn n : next_nat n (S n).
Check next_nat : relation nat.
Theorem next_nat_partial_function :
partial_function next_nat.
| nn n : next_nat n (S n).
Check next_nat : relation nat.
Theorem next_nat_partial_function :
partial_function next_nat.
Proof.
unfold partial_function.
intros x y1 y2 H1 H2.
inversion H1. inversion H2.
reflexivity. Qed.
unfold partial_function.
intros x y1 y2 H1 H2.
inversion H1. inversion H2.
reflexivity. Qed.
However, the ≤ relation on numbers is not a partial
function. (Assume, for a contradiction, that ≤ is a partial
function. But then, since 0 ≤ 0 and 0 ≤ 1, it follows that
0 = 1. This is nonsense, so our assumption was
contradictory.)
Theorem le_not_a_partial_function :
¬(partial_function le).
¬(partial_function le).
Proof.
unfold not. unfold partial_function. intros Hc.
assert (0 = 1) as Nonsense. {
apply Hc with (x := 0).
- apply le_n.
- apply le_S. apply le_n. }
discriminate Nonsense. Qed.
unfold not. unfold partial_function. intros Hc.
assert (0 = 1) as Nonsense. {
apply Hc with (x := 0).
- apply le_n.
- apply le_S. apply le_n. }
discriminate Nonsense. Qed.
Reflexive Relations
Definition reflexive {X: Type} (R: relation X) :=
∀ a : X, R a a.
Theorem le_reflexive :
reflexive le.
∀ a : X, R a a.
Theorem le_reflexive :
reflexive le.
Proof.
unfold reflexive. intros n. apply le_n. Qed.
unfold reflexive. intros n. apply le_n. Qed.
Definition transitive {X: Type} (R: relation X) :=
∀ a b c : X, (R a b) → (R b c) → (R a c).
Theorem le_trans :
transitive le.
∀ a b c : X, (R a b) → (R b c) → (R a c).
Theorem le_trans :
transitive le.
Proof.
intros n m o Hnm Hmo.
induction Hmo.
- (* le_n *) apply Hnm.
- (* le_S *) apply le_S. apply IHHmo. Qed.
intros n m o Hnm Hmo.
induction Hmo.
- (* le_n *) apply Hnm.
- (* le_S *) apply le_S. apply IHHmo. Qed.
Reflexivity and transitivity are the main concepts we'll need for
later chapters, but, for a bit of additional practice working with
relations in Coq, let's look at a few other common ones...
A relation R is symmetric if R a b implies R b a.
Symmetric and Antisymmetric Relations
Definition symmetric {X: Type} (R: relation X) :=
∀ a b : X, (R a b) → (R b a).
∀ a b : X, (R a b) → (R b a).
A relation R is antisymmetric if R a b and R b a together
imply a = b -- that is, if the only "cycles" in R are trivial
ones.
Definition antisymmetric {X: Type} (R: relation X) :=
∀ a b : X, (R a b) → (R b a) → a = b.
∀ a b : X, (R a b) → (R b a) → a = b.
Definition equivalence {X:Type} (R: relation X) :=
(reflexive R) ∧ (symmetric R) ∧ (transitive R).
(reflexive R) ∧ (symmetric R) ∧ (transitive R).
Partial Orders and Preorders
Definition order {X:Type} (R: relation X) :=
(reflexive R) ∧ (antisymmetric R) ∧ (transitive R).
(reflexive R) ∧ (antisymmetric R) ∧ (transitive R).
A preorder is almost like a partial order, but doesn't have to be
antisymmetric.
Definition preorder {X:Type} (R: relation X) :=
(reflexive R) ∧ (transitive R).
(reflexive R) ∧ (transitive R).
Reflexive, Transitive Closure
Inductive clos_refl_trans {A: Type} (R: relation A) : relation A :=
| rt_step x y (H : R x y) : clos_refl_trans R x y
| rt_refl x : clos_refl_trans R x x
| rt_trans x y z
(Hxy : clos_refl_trans R x y)
(Hyz : clos_refl_trans R y z) :
clos_refl_trans R x z.
| rt_step x y (H : R x y) : clos_refl_trans R x y
| rt_refl x : clos_refl_trans R x x
| rt_trans x y z
(Hxy : clos_refl_trans R x y)
(Hyz : clos_refl_trans R y z) :
clos_refl_trans R x z.
For example, the reflexive and transitive closure of the
next_nat relation coincides with the le relation.
Theorem next_nat_closure_is_le : ∀ n m,
(n ≤ m) ↔ ((clos_refl_trans next_nat) n m).
(n ≤ m) ↔ ((clos_refl_trans next_nat) n m).
Proof.
intros n m. split.
- (* -> *)
intro H. induction H.
+ (* le_n *) apply rt_refl.
+ (* le_S *)
apply rt_trans with m. apply IHle. apply rt_step.
apply nn.
- (* <- *)
intro H. induction H.
+ (* rt_step *) inversion H. apply le_S. apply le_n.
+ (* rt_refl *) apply le_n.
+ (* rt_trans *)
apply le_trans with y.
apply IHclos_refl_trans1.
apply IHclos_refl_trans2. Qed.
intros n m. split.
- (* -> *)
intro H. induction H.
+ (* le_n *) apply rt_refl.
+ (* le_S *)
apply rt_trans with m. apply IHle. apply rt_step.
apply nn.
- (* <- *)
intro H. induction H.
+ (* rt_step *) inversion H. apply le_S. apply le_n.
+ (* rt_refl *) apply le_n.
+ (* rt_trans *)
apply le_trans with y.
apply IHclos_refl_trans1.
apply IHclos_refl_trans2. Qed.
The above definition of reflexive, transitive closure is natural:
it says, explicitly, that the reflexive and transitive closure of
R is the least relation that includes R and that is closed
under rules of reflexivity and transitivity. But it turns out
that this definition is not very convenient for doing proofs,
since the "nondeterminism" of the rt_trans rule can sometimes
lead to tricky inductions. Here is a more useful definition:
Inductive clos_refl_trans_1n {A : Type}
(R : relation A) (x : A)
: A → Prop :=
| rt1n_refl : clos_refl_trans_1n R x x
| rt1n_trans (y z : A)
(Hxy : R x y) (Hrest : clos_refl_trans_1n R y z) :
clos_refl_trans_1n R x z.
(R : relation A) (x : A)
: A → Prop :=
| rt1n_refl : clos_refl_trans_1n R x x
| rt1n_trans (y z : A)
(Hxy : R x y) (Hrest : clos_refl_trans_1n R y z) :
clos_refl_trans_1n R x z.
Our new definition of reflexive, transitive closure "bundles"
the rt_step and rt_trans rules into the single rule step.
The left-hand premise of this step is a single use of R,
leading to a much simpler induction principle.
Before we go on, we should check that the two definitions do
indeed define the same relation...
First, we prove two lemmas showing that clos_refl_trans_1n mimics
the behavior of the two "missing" clos_refl_trans
constructors.
Lemma rsc_R : ∀ (X:Type) (R:relation X) (x y : X),
R x y → clos_refl_trans_1n R x y.
R x y → clos_refl_trans_1n R x y.
Proof.
intros X R x y H.
apply rt1n_trans with y. apply H. apply rt1n_refl. Qed.
intros X R x y H.
apply rt1n_trans with y. apply H. apply rt1n_refl. Qed.
Lemma rsc_trans :
∀ (X:Type) (R: relation X) (x y z : X),
clos_refl_trans_1n R x y →
clos_refl_trans_1n R y z →
clos_refl_trans_1n R x z.
Proof.
(* FILL IN HERE *) Admitted.
☐
∀ (X:Type) (R: relation X) (x y z : X),
clos_refl_trans_1n R x y →
clos_refl_trans_1n R y z →
clos_refl_trans_1n R x z.
Proof.
(* FILL IN HERE *) Admitted.
☐
Exercise: 3 stars, standard, optional (rtc_rsc_coincide)
Theorem rtc_rsc_coincide :
∀ (X:Type) (R: relation X) (x y : X),
clos_refl_trans R x y ↔ clos_refl_trans_1n R x y.
Proof.
(* FILL IN HERE *) Admitted.
☐
∀ (X:Type) (R: relation X) (x y : X),
clos_refl_trans R x y ↔ clos_refl_trans_1n R x y.
Proof.
(* FILL IN HERE *) Admitted.
☐