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