TransitionSystems: factorial example finished

This commit is contained in:
Adam Chlipala 2016-02-14 11:41:41 -05:00
parent 9ae318190c
commit ee02d8926a
2 changed files with 88 additions and 54 deletions

View file

@ -5,6 +5,10 @@
Require Import Frap.
Set Implicit Arguments.
(* This command will treat type arguments to functions as implicit, like in
* Haskell or ML. *)
(* Here's a classic recursive, functional program for factorial. *)
Fixpoint fact (n : nat) : nat :=
@ -59,6 +63,8 @@ Theorem trc_trans : forall {A} (R : A -> A -> Prop) x y, trc R x y
-> trc R x z.
Proof.
induct 1; simplify.
(* Note how we pass a *number* to [induct], to ask for induction on
* *the first hypothesis in the theorem statement*. *)
assumption.
(* [assumption]: prove a conclusion that matches some hypothesis exactly. *)
@ -117,28 +123,57 @@ Record trsys state := {
Initial : state -> Prop;
Step : state -> state -> Prop
}.
(* Probably it's intuitively clear what a record type must be.
* See usage examples below to fill in more of the details.
* Note that [state] is a polymorphic type parameter. *)
(* The example of our factorial program: *)
Definition factorial_sys (original_input : nat) : trsys fact_state := {|
Initial := fact_init original_input;
Step := fact_step
|}.
(* To prove that our state machine is correct, we rely on the crucial technique
* of *invariants*. What is an invariant? Here's a general definition, in
* terms of an arbitrary *transition system* defined by a set of states,
* an initial-state relation, and a step relation. *)
Definition invariantFor {state} (sys : trsys state) (invariant : state -> Prop) :=
forall s, sys.(Initial) s
-> forall s', sys.(Step)^* s s'
-> invariant s'.
(* That is, when we begin in an initial state and take any number of steps, the
* place we wind up always satisfies the invariant. *)
Theorem use_invariant : forall {state} (sys : trsys state) (invariant : state -> Prop) s s',
sys.(Step)^* s s'
(* Here's a simple lemma to help us apply an invariant usefully,
* really just restating the definition. *)
Theorem use_invariant : forall {state} (sys : trsys state)
(invariant : state -> Prop) s s',
invariantFor sys invariant
-> sys.(Initial) s
-> invariantFor sys invariant
-> sys.(Step)^* s s'
-> invariant s'.
Proof.
firstorder.
unfold invariantFor.
simplify.
eapply H.
eassumption.
assumption.
Qed.
Theorem invariantFor_monotone : forall {state} (sys : trsys state)
(invariant1 invariant2 : state -> Prop),
(forall s, invariant1 s -> invariant2 s)
-> invariantFor sys invariant1
-> invariantFor sys invariant2.
(* What's the most fundamental way to establish an invariant? Induction! *)
Lemma invariant_induction' : forall {state} (sys : trsys state)
(invariant : state -> Prop),
(forall s, invariant s -> forall s', sys.(Step) s s' -> invariant s')
-> forall s s', sys.(Step)^* s s'
-> invariant s
-> invariant s'.
Proof.
unfold invariantFor; intuition eauto.
induct 2; propositional.
apply IHtrc.
eapply H.
eassumption.
assumption.
Qed.
Theorem invariant_induction : forall {state} (sys : trsys state)
@ -148,53 +183,15 @@ Theorem invariant_induction : forall {state} (sys : trsys state)
-> invariantFor sys invariant.
Proof.
unfold invariantFor; intros.
assert (invariant s) by eauto.
clear H1.
induction H2; eauto.
Qed.
(* To prove that our state machine is correct, we rely on the crucial technique
* of *invariants*. What is an invariant? Here's a general definition, in
* terms of an arbitrary *transition system* defined by a set of states,
* an initial-state relation, and a step relation. *)
Definition invariantFor {state} (initial : state -> Prop) (step : state -> state -> Prop) (invariant : state -> Prop) :=
forall s, initial s
-> forall s', step^* s s'
-> invariant s'.
(* That is, when we begin in an initial state and take any number of steps, the
* place we wind up always satisfied the invariant. *)
(* Here's a simple lemma to help us apply an invariant usefully,
* really just restating the definition. *)
Theorem use_invariant : forall {state} (initial : state -> Prop)
(step : state -> state -> Prop) (invariant : state -> Prop) s s',
step^* s s'
-> initial s
-> invariantFor initial step invariant
-> invariant s'.
Proof.
unfold invariantFor.
simplify.
eapply H1.
eapply invariant_induction'.
eassumption.
eassumption.
apply H.
assumption.
Qed.
(* What's the most fundamental way to establish an invariant? Induction! *)
Theorem invariant_induction : forall {state} (initial : state -> Prop)
(step : state -> state -> Prop) (invariant : state -> Prop),
(forall s, initial s -> invariant s)
-> (forall s, invariant s -> forall s', step s s' -> invariant s')
-> invariantFor initial step invariant.
Proof.
unfold invariantFor; intros.
assert (invariant s) by eauto.
clear H1.
induction H2; eauto.
Qed.
(* Here's a good invariant for factorial, parameterized on the original input
(* That's enough abstract results for now. Let's apply them to our example.
* Here's a good invariant for factorial, parameterized on the original input
* to the program. *)
Definition fact_invariant (original_input : nat) (st : fact_state) : Prop :=
match st with
@ -205,7 +202,7 @@ Definition fact_invariant (original_input : nat) (st : fact_state) : Prop :=
(* We can use [invariant_induction] to prove that it really is a good
* invariant. *)
Theorem fact_invariant_ok : forall original_input,
invariantFor (fact_init original_input) fact_step (fact_invariant original_input).
invariantFor (factorial_sys original_input) (fact_invariant original_input).
Proof.
simplify.
apply invariant_induction; simplify.
@ -235,3 +232,39 @@ Proof.
rewrite H.
ring.
Qed.
(* Therefore, every reachable state satisfies this invariant. *)
Theorem fact_invariant_always : forall original_input s s',
(factorial_sys original_input).(Step)^* s s'
-> (factorial_sys original_input).(Initial) s
-> fact_invariant original_input s'.
Proof.
simplify.
eapply use_invariant.
apply fact_invariant_ok.
eassumption.
assumption.
Qed.
(* Therefore, any final state has the right answer! *)
Lemma fact_ok' : forall original_input s,
fact_final s
-> fact_invariant original_input s
-> s = AnswerIs (fact original_input).
Proof.
invert 1; simplify; equality.
Qed.
Theorem fact_ok : forall original_input s s',
(factorial_sys original_input).(Step)^* s s'
-> (factorial_sys original_input).(Initial) s
-> fact_final s'
-> s' = AnswerIs (fact original_input).
Proof.
simplify.
apply fact_ok'.
assumption.
eapply fact_invariant_always.
eassumption.
assumption.
Qed.

View file

@ -9,3 +9,4 @@ BasicSyntax_template.v
BasicSyntax.v
Interpreters_template.v
Interpreters.v
TransitionSystems.v