Annotate while with invariants in the language

This commit is contained in:
Théophile Bastian 2017-12-07 20:26:25 +01:00
parent 4f15160760
commit 3888b62c6a

94
wp.v
View file

@ -11,13 +11,26 @@ Definition Var := nat.
Definition Mem := Var -> Z. Definition Mem := Var -> Z.
Definition Expr:= Mem -> Z. Definition Expr:= Mem -> Z.
Inductive SynAssert : Type:=
| ATop: SynAssert
| ABot: SynAssert
| ANeg: SynAssert -> SynAssert
| AAnd: SynAssert -> SynAssert -> SynAssert
| AOr: SynAssert -> SynAssert -> SynAssert
| AImplies: SynAssert -> SynAssert -> SynAssert
| AExpr: Expr -> SynAssert
| AForall: Var -> SynAssert -> SynAssert
| AExists: Var -> SynAssert -> SynAssert
| ASubstZ: Var -> Z -> SynAssert -> SynAssert
| ASubstE: Var -> Expr -> SynAssert -> SynAssert.
Inductive Instr : Type := Inductive Instr : Type :=
| skip: Instr | skip: Instr
| abort: Instr | abort: Instr
| assign: Var -> Expr -> Instr | assign: Var -> Expr -> Instr
| seq: Instr -> Instr -> Instr | seq: Instr -> Instr -> Instr
| ifelse: Expr -> Instr -> Instr -> Instr | ifelse: Expr -> Instr -> Instr -> Instr
| while: Expr -> Instr -> Instr. | while: SynAssert -> Expr -> Instr -> Instr.
Definition ifonly (exp: Expr) (inst: Instr) : Instr := Definition ifonly (exp: Expr) (inst: Instr) : Instr :=
ifelse exp inst skip. ifelse exp inst skip.
@ -87,7 +100,7 @@ Fixpoint interp (inst: Instr) (mem: MemCpo) : MemCpo :=
if ((guard mem0) =? 0) % Z if ((guard mem0) =? 0) % Z
then interp instrElse mem then interp instrElse mem
else interp instrIf mem else interp instrIf mem
| while guard body => | while _ guard body =>
let fix while_chain (mem: MemCpo) (n: nat): MemCpo := let fix while_chain (mem: MemCpo) (n: nat): MemCpo :=
match n with match n with
| 0 => mem | 0 => mem
@ -129,16 +142,16 @@ Definition expr_neg (expr: Expr) : Expr :=
| _ => 0%Z | _ => 0%Z
end. end.
Lemma certain_termination_exists body guard mem : Lemma certain_termination_exists assert body guard mem :
interp (while guard body) mem <> MemError -> interp (while assert guard body) mem <> MemError ->
exists n: nat, exists n: nat,
interp (nth_iterate (ifonly guard body) n) mem |=e expr_neg guard. interp (nth_iterate (ifonly guard body) n) mem |=e expr_neg guard.
Proof. Proof.
intros noError. intros noError.
Admitted. Admitted.
Lemma certain_termination_exists_minimal body guard mem : Lemma certain_termination_exists_minimal assert body guard mem :
interp (while guard body) mem <> MemError -> interp (while assert guard body) mem <> MemError ->
exists n: nat, exists n: nat,
(forall p: nat, p < n -> (forall p: nat, p < n ->
interp (nth_iterate (ifonly guard body) p) mem |=e guard) interp (nth_iterate (ifonly guard body) p) mem |=e guard)
@ -147,15 +160,15 @@ Proof.
intros not_error. intros not_error.
Admitted. Admitted.
Lemma certain_termination body guard mem : Lemma certain_termination assert body guard mem :
interp (while guard body) mem <> MemError -> interp (while assert guard body) mem <> MemError ->
exists n: nat, exists n: nat,
(interp (nth_iterate body n) mem) |=e (expr_neg guard) (interp (nth_iterate body n) mem) |=e (expr_neg guard)
/\ (forall p, p < n -> (interp (nth_iterate body p) mem) |=e guard) /\ (forall p, p < n -> (interp (nth_iterate body p) mem) |=e guard)
/\ interp (while guard body) mem = interp (nth_iterate body n) mem. /\ interp (while assert guard body) mem = interp (nth_iterate body n) mem.
Proof. Proof.
intros notError. intros notError.
elim (certain_termination_exists_minimal body guard mem). elim (certain_termination_exists_minimal assert body guard mem).
intros n. intros [notBeforeN atN]. exists n. intros n. intros [notBeforeN atN]. exists n.
split. split.
Admitted. Admitted.
@ -240,9 +253,9 @@ Inductive hoare_provability : Assert -> Instr -> Assert -> Prop :=
(|- [| pre /\ ~(assertOfExpr expr) |] sElse [| post |]) % assert -> (|- [| pre /\ ~(assertOfExpr expr) |] sElse [| post |]) % assert ->
(|- [| pre |] (ifelse expr sIf sElse) [| post |]) % assert (|- [| pre |] (ifelse expr sIf sElse) [| post |]) % assert
| H_while: | H_while:
forall inv, forall expr, forall sBody, forall inv assert expr sBody,
(|- [| inv /\ (assertOfExpr expr) |] sBody [| inv |]) % assert -> (|- [| inv /\ (assertOfExpr expr) |] sBody [| inv |]) % assert ->
(|- [| inv |] (while expr sBody) (|- [| inv |] (while assert expr sBody)
[| inv /\ ~ (assertOfExpr expr) |]) % assert [| inv /\ ~ (assertOfExpr expr) |]) % assert
where "|- [| pre |] instr [| post |]" := where "|- [| pre |] instr [| post |]" :=
(hoare_provability pre instr post) : assert. (hoare_provability pre instr post) : assert.
@ -390,9 +403,9 @@ Proof.
+ assumption. + assumption.
+ rewrite <- Z.eqb_eq. congruence. + rewrite <- Z.eqb_eq. congruence.
- unfold conseq_or_bottom. - unfold conseq_or_bottom.
destruct (interp (while expr sBody) (MemElem mem)) eqn:interpRel. destruct (interp (while assert expr sBody) (MemElem mem)) eqn:interpRel.
* trivial. * trivial.
* elim (certain_termination sBody expr (MemElem mem)). * elim (certain_termination assert sBody expr (MemElem mem)).
intros n [lastIter [notLastIter isWhile] ]. intros n [lastIter [notLastIter isWhile] ].
rewrite isWhile in interpRel. rewrite isWhile in interpRel.
destruct n. destruct n.
@ -440,6 +453,23 @@ Proof.
+ rewrite interpRel; unfold MemError; congruence. + rewrite interpRel; unfold MemError; congruence.
Qed. Qed.
(***** Syntactic assertion interpretation ************************************)
Fixpoint aInterp (src: SynAssert): Assert :=
fun (mem: Mem) => match src with
| ATop => True
| ABot => False
| ANeg x => ~ (aInterp x mem)
| AAnd x y => (aInterp x mem) /\ (aInterp y mem)
| AOr x y => (aInterp x mem) \/ (aInterp y mem)
| AImplies x y => (~ (aInterp x mem)) \/ (aInterp y mem)
| AExpr exp => exp mem <> 0%Z
| AForall v x => forall (z: Z), aInterp x (mem [v <- z])
| AExists v x => exists (z: Z), aInterp x (mem [v <- z])
| ASubstZ v z x => aInterp x (mem [v <- z])
| ASubstE v e x => aInterp x (mem [v <- (e mem)])
end.
(***** Weakest precondition **************************************************) (***** Weakest precondition **************************************************)
Fixpoint wp (instr: Instr) (cond: Assert) : Assert := match instr with Fixpoint wp (instr: Instr) (cond: Assert) : Assert := match instr with
@ -450,7 +480,7 @@ Fixpoint wp (instr: Instr) (cond: Assert) : Assert := match instr with
| ifelse guard sIf sElse => | ifelse guard sIf sElse =>
((assertOfExpr guard -> wp sIf cond) ((assertOfExpr guard -> wp sIf cond)
/\ (~ (assertOfExpr guard) -> wp sElse cond)) % assert /\ (~ (assertOfExpr guard) -> wp sElse cond)) % assert
| while guard body => assertBot | while assert guard body => assertBot
end. end.
Lemma assertImplElim {a b: Assert} : Lemma assertImplElim {a b: Assert} :
@ -527,7 +557,7 @@ Proof.
* apply (H_conseq * apply (H_conseq
assertBot post assertBot post
assertBot (assertBot /\ ~ (assertOfExpr e))%assert). assertBot (assertBot /\ ~ (assertOfExpr e))%assert).
- apply (H_while assertBot e instr). - apply (H_while assertBot s e instr).
apply (H_conseq apply (H_conseq
(assertBot /\ assertOfExpr e)%assert assertBot (assertBot /\ assertOfExpr e)%assert assertBot
assertBot assertBot). assertBot assertBot).
@ -585,35 +615,7 @@ Proof.
apply wp_correctness_provable. apply wp_correctness_provable.
Qed. Qed.
(***** Assertions syntaxiques******** ****************************************) (***** Assertions syntaxiques -- proprietes **********************************)
Inductive SynAssert : Type:=
| ATop: SynAssert
| ABot: SynAssert
| ANeg: SynAssert -> SynAssert
| AAnd: SynAssert -> SynAssert -> SynAssert
| AOr: SynAssert -> SynAssert -> SynAssert
| AImplies: SynAssert -> SynAssert -> SynAssert
| AExpr: Expr -> SynAssert
| AForall: Var -> SynAssert -> SynAssert
| AExists: Var -> SynAssert -> SynAssert
| ASubstZ: Var -> Z -> SynAssert -> SynAssert
| ASubstE: Var -> Expr -> SynAssert -> SynAssert.
Fixpoint aInterp (src: SynAssert): Assert :=
fun (mem: Mem) => match src with
| ATop => True
| ABot => False
| ANeg x => ~ (aInterp x mem)
| AAnd x y => (aInterp x mem) /\ (aInterp y mem)
| AOr x y => (aInterp x mem) \/ (aInterp y mem)
| AImplies x y => (~ (aInterp x mem)) \/ (aInterp y mem)
| AExpr exp => exp mem <> 0%Z
| AForall v x => forall (z: Z), aInterp x (mem [v <- z])
| AExists v x => exists (z: Z), aInterp x (mem [v <- z])
| ASubstZ v z x => aInterp x (mem [v <- z])
| ASubstE v e x => aInterp x (mem [v <- (e mem)])
end.
Fixpoint wps (instr: Instr) (asser: SynAssert) : SynAssert := match instr with Fixpoint wps (instr: Instr) (asser: SynAssert) : SynAssert := match instr with
| skip => asser | skip => asser
@ -624,7 +626,7 @@ Fixpoint wps (instr: Instr) (asser: SynAssert) : SynAssert := match instr with
AAnd AAnd
(AImplies (AExpr guard) (wps sIf asser)) (AImplies (AExpr guard) (wps sIf asser))
(AImplies (ANeg (AExpr guard)) (wps sElse asser)) (AImplies (ANeg (AExpr guard)) (wps sElse asser))
| while guard body => ABot | while assert guard body => ABot
end. end.
Lemma aInterpConsistent (instr: Instr): Lemma aInterpConsistent (instr: Instr):