forked from libre-chip/fayalite
Define design safety, and prove it for 1-step and 2-step induction.
This commit is contained in:
parent
4fd4371054
commit
a398f8f185
1 changed files with 216 additions and 2 deletions
|
|
@ -56,9 +56,10 @@ Module simple_register.
|
||||||
apply T. apply A.
|
apply T. apply A.
|
||||||
Qed.
|
Qed.
|
||||||
(* Here we have proven the base case and the inductive case, so we
|
(* Here we have proven the base case and the inductive case, so we
|
||||||
declare success. However, we may want to formalize it from first
|
declare success. However, we want to formalize it from first
|
||||||
principles, something like "All reachable states from an initial
|
principles, something like "All reachable states from an initial
|
||||||
state are valid", and use the above theorems to prove it (TODO). *)
|
state are valid", and use the above theorems to prove it. This will be
|
||||||
|
done later on. *)
|
||||||
|
|
||||||
(* Example: all states reachable in one step from the initial state
|
(* Example: all states reachable in one step from the initial state
|
||||||
are valid. *)
|
are valid. *)
|
||||||
|
|
@ -169,3 +170,216 @@ Module hidden_state.
|
||||||
apply Hi. apply base1. apply Hi. apply T01.
|
apply Hi. apply base1. apply Hi. apply T01.
|
||||||
Qed.
|
Qed.
|
||||||
End hidden_state.
|
End hidden_state.
|
||||||
|
|
||||||
|
(* We now formalize the notion of a safe design, where all reachable states
|
||||||
|
from an initial state are valid. This will allow us to prove that the
|
||||||
|
above designs are truly safe for all time. *)
|
||||||
|
|
||||||
|
Section safety.
|
||||||
|
|
||||||
|
(* define some shortcuts *)
|
||||||
|
Variable S: Type. (* state type *)
|
||||||
|
Variable I: S->Prop. (* initial state *)
|
||||||
|
Variable t: S->S->Prop. (* transition rule *)
|
||||||
|
Variable A: S->Prop. (* assertions *)
|
||||||
|
|
||||||
|
(* Given an initial state and transition rule, recursively construct the
|
||||||
|
"reachable" concept *)
|
||||||
|
Inductive reachable: S->Prop :=
|
||||||
|
(* initial states are reachable *)
|
||||||
|
| r_initial: forall s0: S,
|
||||||
|
I s0 -> reachable s0
|
||||||
|
(* from a given reachable state, we get to another reachable state by
|
||||||
|
following a transition *)
|
||||||
|
| r_step: forall s0 s1: S,
|
||||||
|
reachable s0 -> t s0 s1 -> reachable s1.
|
||||||
|
|
||||||
|
(* example: all states leading from an initial state are reachable *)
|
||||||
|
Example reachable_in_one_step:
|
||||||
|
forall s0 s1: S,
|
||||||
|
I s0 -> t s0 s1 -> reachable s1.
|
||||||
|
Proof.
|
||||||
|
intros s0 s1.
|
||||||
|
intros I0.
|
||||||
|
apply r_step.
|
||||||
|
apply r_initial.
|
||||||
|
exact I0.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* Safety definition: all reachable states are valid (they obey
|
||||||
|
assertions) *)
|
||||||
|
Definition safe: Prop :=
|
||||||
|
forall s: S, reachable s -> A s.
|
||||||
|
|
||||||
|
(* Prove the induction principle for one-step induction: from a base case
|
||||||
|
and an inductive case, we prove full safety. This is enough to handle
|
||||||
|
cases where induction already succeeds in just one step, like the
|
||||||
|
"simple_register" example above. *)
|
||||||
|
Theorem safe1:
|
||||||
|
(* Hypothesis: *)
|
||||||
|
(* 1) base case *)
|
||||||
|
(forall s0: S, I s0 -> A s0) ->
|
||||||
|
(* 2) inductive case *)
|
||||||
|
(forall s0 s1: S, A s0 -> t s0 s1 -> A s1) ->
|
||||||
|
(* Conclusion: safe for all time *)
|
||||||
|
safe.
|
||||||
|
Proof.
|
||||||
|
intros B1 I1.
|
||||||
|
unfold safe.
|
||||||
|
(* Here we take advantage of an induction principle which is automatically
|
||||||
|
generated by Rocq when we defined the "reachable" proposition above. It
|
||||||
|
conveniently matches the base case and inductive cases from the
|
||||||
|
hypothesis *)
|
||||||
|
apply reachable_ind.
|
||||||
|
- exact B1.
|
||||||
|
- intros s0 s1 R0.
|
||||||
|
apply I1.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* Now, we proceed to prove the induction principle to designs that require
|
||||||
|
two steps in induction, like the "hidden_state" design above. *)
|
||||||
|
|
||||||
|
(* The "reachable_ind" induction principle that Rocq generated for us no
|
||||||
|
longer matches the hypothesis for the two-step case. We create another
|
||||||
|
"reachable2" property that does.*)
|
||||||
|
Inductive reachable2: S->Prop :=
|
||||||
|
(* initial states are "reachable2" *)
|
||||||
|
| r2_initial1: forall s0: S,
|
||||||
|
I s0 -> reachable2 s0
|
||||||
|
(* states one transition away from "reachable2" initial states are also
|
||||||
|
"reachable2" *)
|
||||||
|
| r2_initial2: forall s0 s1: S,
|
||||||
|
I s0 -> reachable2 s0 -> t s0 s1 -> reachable2 s1
|
||||||
|
(* from two sequential "reachable2" states, we get another "reachable2"]
|
||||||
|
state by jumping yet another transition. *)
|
||||||
|
| r2_step: forall s0 s1 s2: S,
|
||||||
|
reachable2 s0 -> t s0 s1 -> reachable2 s1 -> t s1 s2 -> reachable2 s2.
|
||||||
|
|
||||||
|
(* example: if, from an initial state, we jump two states, we reach a
|
||||||
|
"reachable2" state *)
|
||||||
|
Example reachable2_in_two_steps:
|
||||||
|
forall (s0 s1 s2: S),
|
||||||
|
I s0 -> t s0 s1 -> t s1 s2 -> reachable2 s2.
|
||||||
|
Proof.
|
||||||
|
intros s0 s1 s2.
|
||||||
|
intros I0 T01.
|
||||||
|
apply r2_step with (s0 := s0).
|
||||||
|
+ apply r2_initial1. apply I0.
|
||||||
|
+ exact T01.
|
||||||
|
+ apply r2_initial2 with (s0:=s0).
|
||||||
|
exact I0. apply r2_initial1. exact I0. exact T01.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* First, we prove the safety property for "reachable2". Later, we will use
|
||||||
|
this result to prove the desired theorem for "reachable" instead *)
|
||||||
|
Lemma safe2':
|
||||||
|
(* Hypothesis: *)
|
||||||
|
(* 1) base case (step 1) *)
|
||||||
|
(forall s0: S, I s0 -> A s0) ->
|
||||||
|
(* 2) base case (step 2) *)
|
||||||
|
(forall s0 s1: S, I s0 -> A s0 -> t s0 s1 -> A s1) ->
|
||||||
|
(* 3) inductive case *)
|
||||||
|
(forall s0 s1 s2: S, A s0 -> t s0 s1 -> A s1 -> t s1 s2 -> A s2) ->
|
||||||
|
(* Conclusion: "reachable2" is safe *)
|
||||||
|
forall s, reachable2 s -> A s.
|
||||||
|
Proof.
|
||||||
|
intros B1 B2 I2.
|
||||||
|
(* With our carefully crafted "reachable2", Rocq generates an induction
|
||||||
|
principle that matches our hypothesis. *)
|
||||||
|
apply reachable2_ind.
|
||||||
|
- exact B1.
|
||||||
|
- intros s0 s1 I0 R0. apply B2. exact I0.
|
||||||
|
- intros s0 s1 s2 R0 A0 T01 R1.
|
||||||
|
apply I2 with (s0 := s0).
|
||||||
|
exact A0. exact T01.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* Now, we proceed to prove the same result for plain "reachable". We first
|
||||||
|
need to prove two auxiliary lemmas. *)
|
||||||
|
|
||||||
|
Lemma reachable2_t:
|
||||||
|
forall s1 s2:S, reachable2 s1 -> t s1 s2 -> reachable2 s2.
|
||||||
|
Proof.
|
||||||
|
intros s1 s2 R1.
|
||||||
|
destruct R1 as [s1 I1| s0 s1 I0 R0 T01|sm1 s0 s1 Rm1 Tm10 R0 T01].
|
||||||
|
- apply r2_initial2. exact I1. apply r2_initial1. exact I1.
|
||||||
|
- apply r2_step with (s0:=s0).
|
||||||
|
+ exact R0.
|
||||||
|
+ exact T01.
|
||||||
|
+ apply r2_initial2 with (s0:=s0). exact I0. exact R0. exact T01.
|
||||||
|
- apply r2_step with (s0 := s0).
|
||||||
|
exact R0. exact T01.
|
||||||
|
apply r2_step with (s1 := s0) (s0 := sm1).
|
||||||
|
exact Rm1. exact Tm10. exact R0. exact T01.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
Lemma reachable1_2:
|
||||||
|
forall s: S, reachable s -> reachable2 s.
|
||||||
|
Proof.
|
||||||
|
intros s R.
|
||||||
|
apply reachable_ind.
|
||||||
|
- exact r2_initial1.
|
||||||
|
- intros s0 s1 R0.
|
||||||
|
apply reachable2_t.
|
||||||
|
- exact R.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* Finally, the main result: safety for 2-step induction. *)
|
||||||
|
Theorem safe2:
|
||||||
|
(* Hypothesis: *)
|
||||||
|
(* 1) base case (step 1) *)
|
||||||
|
(forall s0: S, I s0 -> A s0) ->
|
||||||
|
(* 2) base case (step 2) *)
|
||||||
|
(forall s0 s1: S, I s0 -> A s0 -> t s0 s1 -> A s1) ->
|
||||||
|
(* 3) inductive case *)
|
||||||
|
(forall s0 s1 s2: S, A s0 -> t s0 s1 -> A s1 -> t s1 s2 -> A s2) ->
|
||||||
|
(* Conclusion: safe for all time *)
|
||||||
|
safe.
|
||||||
|
Proof.
|
||||||
|
intros B1 B2 I2.
|
||||||
|
unfold safe.
|
||||||
|
intros s R.
|
||||||
|
apply safe2'.
|
||||||
|
exact B1. exact B2. exact I2.
|
||||||
|
apply reachable1_2. exact R.
|
||||||
|
Qed.
|
||||||
|
|
||||||
|
(* A future step, maybe, would be to prove the safety of n-step induction,
|
||||||
|
for arbitrary n. *)
|
||||||
|
|
||||||
|
End safety.
|
||||||
|
|
||||||
|
(* We use the above results to prove that "simple_register" is indeed safe. *)
|
||||||
|
Module simple_register_safe.
|
||||||
|
Theorem simple_register_is_safe:
|
||||||
|
(* instantiate the safety property for our design *)
|
||||||
|
safe
|
||||||
|
simple_register.S
|
||||||
|
simple_register.initial
|
||||||
|
simple_register.t
|
||||||
|
simple_register.assert.
|
||||||
|
Proof.
|
||||||
|
(* apply the induction principle for 1-step induction *)
|
||||||
|
apply safe1.
|
||||||
|
- exact simple_register.base1.
|
||||||
|
- exact simple_register.induct1.
|
||||||
|
Qed.
|
||||||
|
End simple_register_safe.
|
||||||
|
|
||||||
|
(* Likewise for "hidden_state". *)
|
||||||
|
Module hidden_state_safe.
|
||||||
|
Theorem hidden_state_is_safe:
|
||||||
|
(* instantiate the safety property for our design *)
|
||||||
|
safe
|
||||||
|
hidden_state.S
|
||||||
|
hidden_state.initial
|
||||||
|
hidden_state.t
|
||||||
|
hidden_state.assert.
|
||||||
|
Proof.
|
||||||
|
(* apply the induction principle for 2-step induction *)
|
||||||
|
apply safe2.
|
||||||
|
- exact hidden_state.base1.
|
||||||
|
- exact hidden_state.base2.
|
||||||
|
- exact hidden_state.induct2.
|
||||||
|
Qed.
|
||||||
|
End hidden_state_safe.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue