Upload
ignacio-truitt
View
213
Download
0
Embed Size (px)
Citation preview
Model-based reasoning meetscode verification
Michael Butler21 May 2014
WG 2.3 Meeting 55, Orlando
Talk is about
• Distinguish algorithm from its implementation
• Use of patterns / ghost elements for– Verification of algorithm wrt its spec
independently from its implementation– Verification of implementation wrt algorithm– Mechanised verification by linking existing
verification systems• Dafny & Event-B/Rodin
Model of a transition system
SETS STATE
CONSTANTS init, tr, inv, reach
tr ∈ STATE ↔ STATE // transition relation
inv STATE ⊆ // states satisfying invariant
init inv⊆ // initial states (satisfy inv)
reach = tr*[init] // set of reachable states
Algorithm Specification
IF reach inv⊆
THEN result := SAFE
ELSE result := UNSAFE
END
Representing the transition system in Dafny
class STATE {};
method initStates returns ( res: seq<STATE> )ensures res == initial states of system;
method get_successors( s:STATE ) returns ( succ: seq<STATE> )ensures succ == “all successors of s”
method check_inv(s: STATE) returns ( ok:bool )ensures ok == “s satisfies invariant”
Implementation of algorithmmethod CheckReach() returns ( pass: bool ){ var safe : seq<STATE> := initStates() ;
var err: seq<STATE> := [] ; var i := 0 ;while ( i < |safe| && err == [] ) {
var j := 0; s1 := safe[i]; succ := get_successors(s1);while ( j < |succ| && err == [] ) {
var s2 := succ[j];if ( s2 !in safe && s2 !in err ) {
if ( check_inv(s2) ) {safe := safe + [s2]; } else { err := err + [s2]; } } ;
j := j + 1;} ;i := i + 1;
} ;if ( err == [] ) { pass := true; } else { pass := false; }
}
7
FindOk NoFind
Search
StartFind Pass(i) FindOk
some i
StartFind Fail(i) NoFind
all i
Search algorithm pattern
• FindOk: ∃x∈S • P(x)or• NoFind: ∀x∈S • ¬P(x)
xor
8
Could merge to form a (less abstract) sequential algorithm
StartFind ;for i in S do
Fail(i) []
Pass(i) ; exit od ; if exit then FindOk else NoFind fi
9
FindOk
StartFind
Pass(p,i)
FindOksome i:S[p]
Alternatively refine to parallel model
• Partition S so that search is farmed out to multiple processors p ∈ P
• This is a simple refinement step in Event-B
some p:P
10
What’s in a refinement pattern?
• Determining the refined events is relatively easy once we decide on the appropriate abstract program structure to use
• But determining the right gluing invariants can be difficult
• Patterns: from a certain specification structure– determine refined events– gluing invariants– convergence variants
11
“All Condition” Pattern
CondAll ≙ when
∀i ∈ S • Cond(i)then
actionend
Search Fail: Cond(i) ≙ ¬Property(i)
12
Refinement of CondAllStep ≙
any i where Cond(i) ∧ s oStep∉thenoStep := oStep ∪ {i}end
CondAll≙ whenoStep = Sthen
actionend
CondAll
Step(i) CondAll
all i:S
invariant ∀i ∈ oStep • Cond(i)
i ∈ oStep iff Step(i) event has occurred
13
“Some Condition” Pattern
CondSome ≙ when
∃i . i ∈ S ∧ Cond(i)then
actionend
CondSome ≙ any i where
i ∈ S Cond(i)
thenaction(i)
end
14
Refinement of CondSomeStep ≙
any i where Cond(i) ∧ s oStep∉thenoStep := oStep ∪ {i}end
CondSome ≙ any i where i ∈ oStepthenaction(i)end
CondSome
Step(i) CondSome
some i:S
invariant ∀i ∈ oStep • Cond(i)
15
FindOk NoFind
Search
StartFind Pass(i) FindOk
some i
StartFind Fail(i) NoFind
all i
Refinement invariants for search
• Invariant: oPass S∩P⊆• Invariant: oFail S \ P⊆
xor
16
FindOk NoFind
Search
StartFind Pass(i) FindOk
some i
StartFind Fail(i) NoFind
all i
Convergence variant for search
• Variant: S \ ( oPass oFail )∪• Invariant: finite(S)
xor
Event-B spec of reachabilityPass ≙ WHEN
reach inv⊆ THEN
result := SAFEEND
Fail ≙ ANY e WHERE
e ∈ reach e ∉ inv
THEN result := UNSAFE error_state := e
END
• reach is a ghost constant and it needs to be removed in the implementation
• Refine the model to one that computes the reachable states step-by-step
18
Fail Pass
Reach
Start Error(s) Fail
Some s
Start Ok(s) Pass
All s
Guards for reachability events
• Fail: ∃s∈reach • ¬Inv(s)or• Pass: ∀s∈reach • Inv(s)
xor
19
Fail Pass
Reach
Start Error(s) Fail
Some s
Start Safe(s) Pass
All s
Invariants for reachability refinement
• Invariant: oSafe reach ∩ inv⊆• Invariant: oError reach \ inv⊆
xor
Spec of Safe event
Event Safe // add a new successor state that satisfies invariant to oSafe
ANYs WHEREs reach ∈s inv∈s oSafe∉THENoSafe := oSafe {s}∪END
Convergence of Safe and Error events
• Variant: S \ ( oSafe ∪ oFail )• Invariant: finite(S)
Refining the Fail eventAbstract Fail ≙ ANY e WHERE
e ∈ reache ∉ inv
THEN result := FAIL error_state := e
END
Refined Fail ≙ ANY e WHERE
e ∈ oErrorTHEN
result := FAIL error_state := e
END
Invariant:oError reach inv ⊆ ∖
Prove guard strengthening
refined guard=
e ∈ oError ⇒ “invariant”e ∈ reach inv ∖
=abstract guard
Refining the Pass eventAbstract Pass ≙ WHEN
reach inv⊆ THEN
result := OKEND
Refined Pass ≙ WHEN
oSafe = reach THEN
result := OKEND
Invariant:oSafe reach ∩ inv ⊆
Prove guard strengthening
oSafe = reach ⇒ “invariant”reach reach ∩ inv⊆
⇒ “set theory”reach inv⊆
The specter of reach remains
• Fail events do not refer to reach so no further refinement required
• Pass events still do refer to reach, so further refinement required
• Refine the guard of the Safe(s) event:s reach ∈
⇐ “reach is a fixed point”∃s1 • s1 reach ∈ ∧s1 s tr ↦ ∈
⇐ “oSafe reach”⊆∃s1 • s1 oSafe ∈ ∧ s1 s tr ↦ ∈
Add new parameter to Safe event
Event SafeANY
s, s1 WHERE
s1 oSafe∈
s1 s tr ↦ ∈s inv∈s oSafe∉
THENoSafe := oSafe {s}∪
END
26
Extra parameter gives nested iteration
Pass
Safe(s) Pass
all s
Pass
Safe(s1,s) Pass
all s1
all s
Further refinement: tracking the explored states
• A state is explored if it is in safe and all its successors are reached
• Invariant: tr[ explored ] ( oSafe oError )⊆ ∪
• Introduce new event:Event Mark_explored
ANY s WHEREs rac ∈s explored∉tr[{s}] ( oSafe oError ) ⊆ ∪
THENexplored := explored {s} ∪
END
Refining the Pass eventPass ≙ WHEN
oSafe = reach THEN
result := OKEND
Refined Pass ≙ WHEN
explored = oSafe oError = {}
THEN result := OK
END
Invariant:tr[ explored ] ( oSafe ⊆ ∪
oError )
Prove guard strengthening
explored = oSafe oError = {} ∧ ⇒ “invariant”
tr[ oSafe ] oSafe⊆⇒ “reach is least fixed
point”reach oSafe⊆
What to verify in Dafny?
• Verify that the Dafny code is a correct refinement of the final Event-B model
• Event-B variables become ghost variables in Dafny• Gluing invariants in Dafny:
invariant oSafe == seqElems(safe);invariant oError == seqElems(err);invariant explored == seqElems(safe[0..i]);
• Embed the events into the Dafny code
Embed events in the Dafnymethod CheckReach() returns ( pass: bool ){ … Init
while ( i < |safe| && err == [] ) {var j := 0; s1 := safe[i]; succ := get_successors(s1);while ( j < |succ| && err == [] ) {
var s2 := succ[j];if ( s2 !in safe && s2 !in err ) {
if ( check_inv(s2) ) {safe := safe + [s2]; Safe(s1,s2); };
else { err := err + [s2]; Error(s2); } } ;j := j + 1;
} ; Mark_Explored ;i := i + 1;
} ;if ( err == [] ) { pass := true; Pass ; }else { pass := false; Fail ; }
}
Ghost busters
• Guarded event:when G then A end == (assume G) ; A
• Eliminating guards with assertions(assert G) ; (assume G) ; A A ⊑
• Once guards are removed, ghost variables no longer influence the program so can be eliminated
Concluding
• Correctness of algorithm is proved independently of Dafny (with help from patterns)
• At Dafny level we prove that the code is a correct implementation of the algorithm– Avoided any duplication in proof except for Dafny
variants• NB: proposed “embeddding” method for proving
Dafny refines the algorithm only works if code is deterministic