Lecture notes 20190412
Small Step Semantics 1
Remark. Some material in this lecture is from << Software Foundation >>
volume 1 and volume 2.
Require Import PL.Imp6.
Require Coq.Relations.Relation_Operators.
Require Coq.Relations.Relation_Definitions.
Require Coq.Relations.Relation_Operators.
Require Coq.Relations.Relation_Definitions.
General Idea: Small Step
2 + 2 + 3 * 4,
denotational semantics says:
2 + 2 + 3 * 4 ==> 16
while small step operational semantics says:
2 + 2 + 3 * 4
--> 4 + 3 * 4
--> 4 + 12
--> 16.
--> 4 + 3 * 4
--> 4 + 12
--> 16.
Small Step Semantics for Expression Evaluation
- At any moment, the state of the machine is an integer
expression.
- A step of this machine is an atomic unit of computation —
here, a single arithmetic operation or loading program variable's
value.
- The halting states of the machine are ones where there is no more computation to be done.
- Take a as the starting state of the machine.
- Repeatedly use the step relation to find a sequence of
machine states, starting with a, where each state steps to
the next.
- When no more forward step is possible, "read out" the final state of the machine as the result of computation.
Inductive aexp_halt: aexp → Prop :=
| AH_num : ∀n, aexp_halt (ANum n).
| AH_num : ∀n, aexp_halt (ANum n).
Of course, we could define it using a Coq function instead of an inductive
predicate. Here is this alternative (but equivalent approach) approach.
Module Playground.
Definition aexp_halt (a: aexp): Prop :=
match a with
| ANum _ ⇒ True
| _ ⇒ False
end.
End Playground.
Definition aexp_halt (a: aexp): Prop :=
match a with
| ANum _ ⇒ True
| _ ⇒ False
end.
End Playground.
Then we define our step relation.
Inductive astep : state → aexp → aexp → Prop :=
| AS_Id : ∀st X,
astep st
(AId X) (ANum (st X))
| AS_Plus1 : ∀st a1 a1' a2,
astep st
a1 a1' →
astep st
(APlus a1 a2) (APlus a1' a2)
| AS_Plus2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
astep st
(APlus a1 a2) (APlus a1 a2')
| AS_Plus : ∀st n1 n2,
astep st
(APlus (ANum n1) (ANum n2)) (ANum (n1 + n2))
| AS_Minus1 : ∀st a1 a1' a2,
astep st
a1 a1' →
astep st
(AMinus a1 a2) (AMinus a1' a2)
| AS_Minus2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
astep st
(AMinus a1 a2) (AMinus a1 a2')
| AS_Minus : ∀st n1 n2,
astep st
(AMinus (ANum n1) (ANum n2)) (ANum (n1 - n2))
| AS_Mult1 : ∀st a1 a1' a2,
astep st
a1 a1' →
astep st
(AMult a1 a2) (AMult a1' a2)
| AS_Mult2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
astep st
(AMult a1 a2) (AMult a1 a2')
| AS_Mult : ∀st n1 n2,
astep st
(AMult (ANum n1) (ANum n2)) (ANum (n1 * n2)).
| AS_Id : ∀st X,
astep st
(AId X) (ANum (st X))
| AS_Plus1 : ∀st a1 a1' a2,
astep st
a1 a1' →
astep st
(APlus a1 a2) (APlus a1' a2)
| AS_Plus2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
astep st
(APlus a1 a2) (APlus a1 a2')
| AS_Plus : ∀st n1 n2,
astep st
(APlus (ANum n1) (ANum n2)) (ANum (n1 + n2))
| AS_Minus1 : ∀st a1 a1' a2,
astep st
a1 a1' →
astep st
(AMinus a1 a2) (AMinus a1' a2)
| AS_Minus2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
astep st
(AMinus a1 a2) (AMinus a1 a2')
| AS_Minus : ∀st n1 n2,
astep st
(AMinus (ANum n1) (ANum n2)) (ANum (n1 - n2))
| AS_Mult1 : ∀st a1 a1' a2,
astep st
a1 a1' →
astep st
(AMult a1 a2) (AMult a1' a2)
| AS_Mult2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
astep st
(AMult a1 a2) (AMult a1 a2')
| AS_Mult : ∀st n1 n2,
astep st
(AMult (ANum n1) (ANum n2)) (ANum (n1 * n2)).
This definition seems to be super long. Let's read it part by part. But
please keep in mind that what we define here is only a single step evaluation
relation.
The first part of this definition talks about the value of a program variable:
The second part of this definition talks about how the sum of two
subexpressions are computed.
Combining these two parts together, we are already able to describe the
evaluation process of some nontrivial examples. For example, when X's value
is 1 and Y's value is 2, X + (3 + Y) will be evaluated by the following
steps:
astep st
(AId X) (ANum (st X)).
In short, it says: a program variable X's variable is X's variable and this
evaluation process has only one step.
(AId X) (ANum (st X)).
| AS_Plus1 : ∀st a1 a1' a2,
astep st
a1 a1' →
astep st
(APlus a1 a2) (APlus a1' a2)
| AS_Plus2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
astep st
(APlus a1 a2) (APlus a1 a2')
| AS_Plus : ∀st n1 n2,
astep st
(APlus (ANum n1) (ANum n2)) (ANum (n1 + n2))
It says, the left side is computed first, then the right side. When both sides
are computed, the sum of them can be computed in another step.
astep st
a1 a1' →
astep st
(APlus a1 a2) (APlus a1' a2)
| AS_Plus2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
astep st
(APlus a1 a2) (APlus a1 a2')
| AS_Plus : ∀st n1 n2,
astep st
(APlus (ANum n1) (ANum n2)) (ANum (n1 + n2))
X + (3 + Y)
--> 1 + (3 + Y)
--> 1 + (3 + 2)
--> 1 + 5
--> 6.
We can prove this in Coq.
--> 1 + (3 + Y)
--> 1 + (3 + 2)
--> 1 + 5
--> 6.
Module Step_Example1.
Import Abstract_Pretty_Printing.
Example step_1: ∀(X Y: var) (st: state),
st X = 1 →
astep st (X + (3 + Y)) (1 + (3 +Y)).
Proof.
intros.
apply AS_Plus1.
rewrite <- H.
apply AS_Id.
Qed.
Example step_2: ∀(Y: var) (st: state),
st Y = 2 →
astep st (1 + (3 +Y)) (1 + (3 + 2)).
Proof.
intros.
apply AS_Plus2.
{ apply AH_num. }
apply AS_Plus2.
{ apply AH_num. }
rewrite <- H.
apply AS_Id.
Qed.
Example step_3: ∀(st: state),
astep st (1 + (3 + 2)) (1 + 5).
Proof.
intros.
apply AS_Plus2.
{ apply AH_num. }
apply AS_Plus.
Qed.
Example step_4: ∀(st: state),
astep st (1 + 5) 6.
Proof.
intros.
apply AS_Plus.
Qed.
End Step_Example1.
Import Abstract_Pretty_Printing.
Example step_1: ∀(X Y: var) (st: state),
st X = 1 →
astep st (X + (3 + Y)) (1 + (3 +Y)).
Proof.
intros.
apply AS_Plus1.
rewrite <- H.
apply AS_Id.
Qed.
Example step_2: ∀(Y: var) (st: state),
st Y = 2 →
astep st (1 + (3 +Y)) (1 + (3 + 2)).
Proof.
intros.
apply AS_Plus2.
{ apply AH_num. }
apply AS_Plus2.
{ apply AH_num. }
rewrite <- H.
apply AS_Id.
Qed.
Example step_3: ∀(st: state),
astep st (1 + (3 + 2)) (1 + 5).
Proof.
intros.
apply AS_Plus2.
{ apply AH_num. }
apply AS_Plus.
Qed.
Example step_4: ∀(st: state),
astep st (1 + 5) 6.
Proof.
intros.
apply AS_Plus.
Qed.
End Step_Example1.
The small step semantics for "minus" and "multiplication" are defined in
very similar way. And we can also define bool expression's evaluation as
follows. If you forget details about bexp's inductive definition, just use
Print bexp as a cheat sheet.
(* Print bexp. *)
Inductive bexp_halt: bexp → Prop :=
| BH_True : bexp_halt BTrue
| BH_False : bexp_halt BFalse.
Inductive bstep : state → bexp → bexp → Prop :=
| BS_Eq1 : ∀st a1 a1' a2,
astep st
a1 a1' →
bstep st
(BEq a1 a2) (BEq a1' a2)
| BS_Eq2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
bstep st
(BEq a1 a2) (BEq a1 a2')
| BS_Eq_True : ∀st n1 n2,
n1 = n2 →
bstep st
(BEq (ANum n1) (ANum n2)) BTrue
| BS_Eq_False : ∀st n1 n2,
n1 ≠ n2 →
bstep st
(BEq (ANum n1) (ANum n2)) BFalse
| BS_Le1 : ∀st a1 a1' a2,
astep st
a1 a1' →
bstep st
(BLe a1 a2) (BLe a1' a2)
| BS_Le2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
bstep st
(BLe a1 a2) (BLe a1 a2')
| BS_Le_True : ∀st n1 n2,
n1 ≤ n2 →
bstep st
(BLe (ANum n1) (ANum n2)) BTrue
| BS_Le_False : ∀st n1 n2,
n1 > n2 →
bstep st
(BLe (ANum n1) (ANum n2)) BFalse
| BS_NotStep : ∀st b1 b1',
bstep st
b1 b1' →
bstep st
(BNot b1) (BNot b1')
| BS_NotTrue : ∀st,
bstep st
(BNot BTrue) BFalse
| BS_NotFalse : ∀st,
bstep st
(BNot BTrue) BTrue
| BS_AndStep : ∀st b1 b1' b2,
bstep st
b1 b1' →
bstep st
(BAnd b1 b2) (BAnd b1' b2)
| BS_AndTrue : ∀st b,
bstep st
(BAnd BTrue b) b
| BS_AndFalse : ∀st b,
bstep st
(BAnd BFalse b) BFalse.
Inductive bexp_halt: bexp → Prop :=
| BH_True : bexp_halt BTrue
| BH_False : bexp_halt BFalse.
Inductive bstep : state → bexp → bexp → Prop :=
| BS_Eq1 : ∀st a1 a1' a2,
astep st
a1 a1' →
bstep st
(BEq a1 a2) (BEq a1' a2)
| BS_Eq2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
bstep st
(BEq a1 a2) (BEq a1 a2')
| BS_Eq_True : ∀st n1 n2,
n1 = n2 →
bstep st
(BEq (ANum n1) (ANum n2)) BTrue
| BS_Eq_False : ∀st n1 n2,
n1 ≠ n2 →
bstep st
(BEq (ANum n1) (ANum n2)) BFalse
| BS_Le1 : ∀st a1 a1' a2,
astep st
a1 a1' →
bstep st
(BLe a1 a2) (BLe a1' a2)
| BS_Le2 : ∀st a1 a2 a2',
aexp_halt a1 →
astep st
a2 a2' →
bstep st
(BLe a1 a2) (BLe a1 a2')
| BS_Le_True : ∀st n1 n2,
n1 ≤ n2 →
bstep st
(BLe (ANum n1) (ANum n2)) BTrue
| BS_Le_False : ∀st n1 n2,
n1 > n2 →
bstep st
(BLe (ANum n1) (ANum n2)) BFalse
| BS_NotStep : ∀st b1 b1',
bstep st
b1 b1' →
bstep st
(BNot b1) (BNot b1')
| BS_NotTrue : ∀st,
bstep st
(BNot BTrue) BFalse
| BS_NotFalse : ∀st,
bstep st
(BNot BTrue) BTrue
| BS_AndStep : ∀st b1 b1' b2,
bstep st
b1 b1' →
bstep st
(BAnd b1 b2) (BAnd b1' b2)
| BS_AndTrue : ∀st b,
bstep st
(BAnd BTrue b) b
| BS_AndFalse : ∀st b,
bstep st
(BAnd BFalse b) BFalse.
Remark: when evaluating a conjunction of two boolean expression, we use
short circuit evaluation. That is, the right hand side will not be evaluated if
the left hand side is false. For example, when X's value is 1,
X ≤ 0 && 0 < X + 10 will be evaluated by the following steps:
X ≤ 0 && 0 ≤ X + 10
--> 1 ≤ 0 && 0 ≤ X + 10
--> False && 0 ≤ X + 10
--> False.
--> 1 ≤ 0 && 0 ≤ X + 10
--> False && 0 ≤ X + 10
--> False.
Module Step_Example2.
Import Abstract_Pretty_Printing.
Example step_1: ∀(X: var) (st: state),
st X = 1 →
bstep st ((X ≤ 0) && (0 ≤ X + 10)) ((1 ≤ 0) && (0 ≤ X + 10)).
Proof.
intros.
apply BS_AndStep.
apply BS_Le1.
rewrite <- H.
apply AS_Id.
Qed.
Example step_2: ∀(X: var) (st: state),
bstep st ((1 ≤ 0) && (0 ≤ X + 10)) (BFalse && (0 ≤ X + 10)).
Proof.
intros.
apply BS_AndStep.
apply BS_Le_False.
omega.
Qed.
Example step_3: ∀(X: var) (st: state),
bstep st (BFalse && (0 ≤ X + 10)) BFalse.
Proof.
intros.
apply BS_AndFalse.
Qed.
End Step_Example2.
Import Abstract_Pretty_Printing.
Example step_1: ∀(X: var) (st: state),
st X = 1 →
bstep st ((X ≤ 0) && (0 ≤ X + 10)) ((1 ≤ 0) && (0 ≤ X + 10)).
Proof.
intros.
apply BS_AndStep.
apply BS_Le1.
rewrite <- H.
apply AS_Id.
Qed.
Example step_2: ∀(X: var) (st: state),
bstep st ((1 ≤ 0) && (0 ≤ X + 10)) (BFalse && (0 ≤ X + 10)).
Proof.
intros.
apply BS_AndStep.
apply BS_Le_False.
omega.
Qed.
Example step_3: ∀(X: var) (st: state),
bstep st (BFalse && (0 ≤ X + 10)) BFalse.
Proof.
intros.
apply BS_AndFalse.
Qed.
End Step_Example2.
Reflexive, Transive Closure
- (Def A1) the smallest relation that contains R and that is both reflexive and transitive.
- (Def A2) the result of expanding R by reflexivity and transitivity;
- (Def B1) the smallest reflexive relation which is closed under right-concatenating R;
- (Def B2) the result of expanding the identity relation by right-concatenating R repeatedly;
- (Def C1) the smallest reflexive relation which is closed under left-concatenating R;
- (Def C2) the result of expanding the identity relation by left-concatenating R repeatedly;
- (Def D) the union of the following relations: the identity relation, the relation R, the concatenation of two Rs, the concatenation of three R's, etc.
Module Relation_Definitions.
Identity relation.
Definition id {A: Type}: A → A → Prop :=
fun a b ⇒ a = b.
fun a b ⇒ a = b.
Concatenation of two relations.
Definition concat {A B C: Type} (R1: A → B → Prop) (R2: B → C → Prop): A → C → Prop:=
fun a c ⇒ ∃b, R1 a b ∧ R2 b c.
fun a c ⇒ ∃b, R1 a b ∧ R2 b c.
The union of countably many relations.
Definition omega_union {A B: Type} (Rs: nat → A → B → Prop): A → B → Prop :=
fun a b ⇒ ∃n, Rs n a b.
fun a b ⇒ ∃n, Rs n a b.
Then we have some new definitions. Reflexivity is a property of relations.
Definition Reflexive {A: Type} (R: A → A → Prop): Prop :=
∀x, R x x.
∀x, R x x.
Transitivity is another property of relations.
Definition Transitive {A: Type} (R: A → A → Prop): Prop :=
∀x y z, R x y → R y z → R x z.
∀x y z, R x y → R y z → R x z.
We say that a relation R1 is a subrelation of R2 if every pair of
elements in R1 is in R2. In some sense, subrelation can be treated as a
property of pairs of relations.
Definition subrelation {A B: Type} (R R': A → B → Prop): Prop:=
∀(x : A) (y : B), R x y → R' x y.
∀(x : A) (y : B), R x y → R' x y.
Furthermore, for any property Pr of relations, when we say "R is the
smallest relation satisfying Pr", we mean "R satisfies Pr and for any
other R', if R' satisfies Pr, then R is a subrelation of R'".
Definition is_smallest_relation {A B: Type} (Pr: (A → B → Prop) → Prop) (R: A → B → Prop) :=
Pr R ∧ ∀R', Pr R' → subrelation R R'.
End Relation_Definitions.
Pr R ∧ ∀R', Pr R' → subrelation R R'.
End Relation_Definitions.
Now, we are ready to formulate those equivalent definitions of reflexive,
transitive closure.
Module A1.
Import Relation_Definitions.
Import Relation_Definitions.
The following definition says: Rc is R's reflexive, transitive closure
if and only if it is the smallest relation that contains R and that is both
reflexive and transitive.
Definition is_clos_refl_trans {A: Type} (R Rc: A → A → Prop): Prop :=
is_smallest_relation
(fun Rc' ⇒ subrelation R Rc' ∧
Reflexive Rc' ∧
Transitive Rc')
Rc.
is_smallest_relation
(fun Rc' ⇒ subrelation R Rc' ∧
Reflexive Rc' ∧
Transitive Rc')
Rc.
This definition does not say that any relation has a reflexive, transitive
closure. We have to prove it later.
End A1.
Module A2.
Import Relation_Definitions.
Module A2.
Import Relation_Definitions.
The following definition says: Rc is R's reflexive, transitive closure
if and only if it is the result of expanding R by reflexivity and
transitivity. Here, expansion can be defined by Coq's inductive predicate.
Inductive clos_refl_trans {A: Type} (R: A → A → Prop) : A → A → Prop :=
| 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.
In short, for any relation R, we define clos_refl_trans R to be its
reflexive, transitive closure. Now, let's read this Coq definition line-by-line
and make sure that we understand it.
rt_step x y (H : R x y) : clos_refl_trans R x y
This first constructor rt_step says: we start from R to defined
clos_refl_trans R, i.e. for any x and y, clos_refl_trans R x y holds
if R x y is true.
rt_refl x : clos_refl_trans R x x
This second constructor rt_refl says: we expand clos_refl_trans R by
reflexivity.
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.
And most interestingly, we expand clos_refl_trans R x y by transitivity using
this constructor rt_trans. The intuition is that we keep adding new pairs
(x, z) into the expansion result until no more updates can be made.
(Hxy : clos_refl_trans R x y)
(Hyz : clos_refl_trans R y z) :
clos_refl_trans R x z.
Module Example.
Local Open Scope nat.
Local Open Scope nat.
For example, using this definition, we can prove that the reflexive and
transitive closure of the next_nat relation coincides with the le relation.
Inductive next_nat (n : nat) : nat → Prop :=
nn : next_nat n (S n).
Theorem next_nat_closure_is_le : ∀n m: nat,
(n ≤ m) ↔ ((clos_refl_trans next_nat) n m).
End Example.
End A2.
Module A1_vs_A2.
Import Relation_Definitions.
nn : next_nat n (S n).
Theorem next_nat_closure_is_le : ∀n m: nat,
(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.
End Example.
End A2.
Module A1_vs_A2.
Import Relation_Definitions.
We mentioned that definition A1 and definition A2 are equivalent. Now,
let's prove their equivalence. That is, we will show that the reflexive,
transitive closure defined by A2 does satisfy the criterion defined by A1.
Theorem def_equiv: ∀(A: Type) (R: A → A → Prop),
A1.is_clos_refl_trans R (A2.clos_refl_trans R).
Proof.
intros.
unfold A1.is_clos_refl_trans.
unfold is_smallest_relation.
split.
A1.is_clos_refl_trans R (A2.clos_refl_trans R).
Proof.
intros.
unfold A1.is_clos_refl_trans.
unfold is_smallest_relation.
split.
We first prove that A2.clos_refl_trans R is actually reflexive and
transitive, and it does contain R. We then prove that it is the smallest
relation that satisfies all these three properties.
+ assert (subrelation R (A2.clos_refl_trans R)).
{
unfold subrelation.
intros.
apply A2.rt_step.
exact H.
}
assert (Reflexive (A2.clos_refl_trans R)).
{
unfold Reflexive.
intros.
apply A2.rt_refl.
}
assert (Transitive (A2.clos_refl_trans R)).
{
unfold Transitive.
intros.
apply A2.rt_trans with y.
+ exact H1.
+ exact H2.
}
tauto.
+ intros.
destruct H as [? [? ?]].
{
unfold subrelation.
intros.
apply A2.rt_step.
exact H.
}
assert (Reflexive (A2.clos_refl_trans R)).
{
unfold Reflexive.
intros.
apply A2.rt_refl.
}
assert (Transitive (A2.clos_refl_trans R)).
{
unfold Transitive.
intros.
apply A2.rt_trans with y.
+ exact H1.
+ exact H2.
}
tauto.
+ intros.
destruct H as [? [? ?]].
Now, we suppose that R' is a relation that contains R and is both
reflexive and transitive. We are going to prove that it is larger than
A2.clos_refl_trans R.
unfold subrelation.
intros.
induction H2.
- (* rt_step case *)
unfold subrelation in H.
specialize (H x y H2).
exact H.
- (* rt_refl case *)
unfold Reflexive in H0.
apply H0.
- (* rt_trans case *)
unfold Transitive in H1.
specialize (H1 x y z).
tauto.
Qed.
End A1_vs_A2.
(* Among these two definitions, A2 is obviously easier to use in Coq. This
definition is also part of Coq's standard library. *)
Import Coq.Relations.Relation_Operators.
Import Coq.Relations.Relation_Definitions.
Print clos_refl_trans.
(* Inductive clos_refl_trans (A : Type) (R : relation A) (x : A) : A -> Prop :=
rt_step : forall y : A, R x y -> clos_refl_trans A R x y
| rt_refl : clos_refl_trans A R x x
| rt_trans : forall y z : A,
clos_refl_trans A R x y ->
clos_refl_trans A R y z ->
clos_refl_trans A R x z *)
Print relation.
(* relation = fun A : Type => A -> A -> Prop
: Type -> Type *)
intros.
induction H2.
- (* rt_step case *)
unfold subrelation in H.
specialize (H x y H2).
exact H.
- (* rt_refl case *)
unfold Reflexive in H0.
apply H0.
- (* rt_trans case *)
unfold Transitive in H1.
specialize (H1 x y z).
tauto.
Qed.
End A1_vs_A2.
(* Among these two definitions, A2 is obviously easier to use in Coq. This
definition is also part of Coq's standard library. *)
Import Coq.Relations.Relation_Operators.
Import Coq.Relations.Relation_Definitions.
Print clos_refl_trans.
(* Inductive clos_refl_trans (A : Type) (R : relation A) (x : A) : A -> Prop :=
rt_step : forall y : A, R x y -> clos_refl_trans A R x y
| rt_refl : clos_refl_trans A R x x
| rt_trans : forall y z : A,
clos_refl_trans A R x y ->
clos_refl_trans A R y z ->
clos_refl_trans A R x z *)
Print relation.
(* relation = fun A : Type => A -> A -> Prop
: Type -> Type *)
In the beginning of this part, we also mentioned other definitions of
reflexive, transitive closure. Definition B2 and C2 are also included in Coq
standard library.
Print clos_refl_trans_n1.
(* Inductive clos_refl_trans_n1 (A : Type) (R : relation A) (x : A) : A -> Prop :=
rtn1_refl : clos_refl_trans_n1 A R x x
| rtn1_trans : forall y z : A,
R y z ->
clos_refl_trans_n1 A R x y ->
clos_refl_trans_n1 A R x z *)
Print clos_refl_trans_1n.
(* Inductive clos_refl_trans_1n (A : Type) (R : relation A) (x : A) : A -> Prop :=
rt1n_refl : clos_refl_trans_1n A R x x
| rt1n_trans : forall y z : A,
R x y ->
clos_refl_trans_1n A R y z ->
clos_refl_trans_1n A R x z *)
(* Inductive clos_refl_trans_n1 (A : Type) (R : relation A) (x : A) : A -> Prop :=
rtn1_refl : clos_refl_trans_n1 A R x x
| rtn1_trans : forall y z : A,
R y z ->
clos_refl_trans_n1 A R x y ->
clos_refl_trans_n1 A R x z *)
Print clos_refl_trans_1n.
(* Inductive clos_refl_trans_1n (A : Type) (R : relation A) (x : A) : A -> Prop :=
rt1n_refl : clos_refl_trans_1n A R x x
| rt1n_trans : forall y z : A,
R x y ->
clos_refl_trans_1n A R y z ->
clos_refl_trans_1n A R x z *)
All these definitions are proved equivalent with each other in the standard
library. You, students of the course, can try to write down other definitions
(B1, C1 and D) and understand their equivalence.
(* Thu Apr 11 14:39:22 UTC 2019 *)