Naval Research Laboratory Reusable PVS Proof Strategies for Proving Abstraction Properties of I/O Automata Sayan Mitra MIT Computer Sc. and AI Lab mitras@csail.mit.edu Myla Archer Code 5546 Naval Research Laboratory archer@itd.nrl.navy.mil
Outline Background Design Strategy for weak refinement I/O Automata TAME Design Class ‘automaton’ Property theories Template for abstraction properties Strategy for weak refinement Experimental results Conclusions
Background: I/O Automata Basic I/O automaton model (IOA) Discrete events (no timing or probability) Parallel composition Levels of abstractions Automaton [MMT ’91] X: set of state variables now є X: a special ‘real time’ variable Q: states, a set of valuations of X Q: start states A = I O H: input, output, invisible actions nu є A: a special time passage action D Q A Q: discrete transitions visible actions
I/O Automaton Executions and Invariants Alternating sequence s0 a1 s1 a2 s2 …, where: Each (si, ai , si+1) is a discrete step Beginning in a start state, s0 є Trace (external behavior): execution restricted to external actions Invariant properties (true in all reachable states): base case: induction step:
TAME TAME [Archer ’02] provides a set of strategies that exploit the above proof structure to partially automate invariant proofs. Templates Specifying IOA as PVS theories Invariant properties as theorems Generic strategies for proving invariants Reusable : independent of particular IOA Relies on IOA template, and structure of invariant theorems. SUPPOSE p Splits proof goal into cases based on predicate p. APPLY_SPECIFIC_PRECOND Appeal to precondition of an action AUTO_INDUCT Split into base case and induction step and do action based case analysis for induction step. APPLY_INVARIANT_LEMMA m, i Introduce invariant lemma m, instantiating the universally quantified variables as i in proof goal. TRY_SIMP Apply propositional, equational, datatype simplifications.
I/O Automata Traces and Implementation relations Some properties cannot be formalized as invariants A implements B if they have the same set of external actions and traces(A) traces(B). Abstraction properties Homomorphism Refinement, weak refinement Forward and backward simulation
Case Study : TIP Tree Identification Phase of IEEE 1394: leader election algorithm. Algorithm starts after a reset which clears all topology information except local information Leaf nodes send parent request (PR) message to neighbors When a node receives PR from all but one of its neighbors then it sends a PR to the remaining neighbor. PRs are ACKed Tree grows from leaf to root Node receiving an ACK terminates as a non-root. Node receiving PR from all its neighbors is root --- leader. Root contentions are broken by back-off and random retransmit. Correctness # leaders always <= 1 Eventually, # leaders = 1
actions: DATATYPE. nu(t). add_child(edge). children_known(vertices) actions: DATATYPE nu(t) add_child(edge) children_known(vertices) ack(edges) resolve_contention(edges) root(vertices) noop:noop? visible(a):bool = root?(a) or nu?(a) states: TYPE = [# init: [Vertices -> Bool], contention: [Vertices -> Bool], root:[Vertices->Bool], child: [Edges -> Bool], mq:[Edges -> BoolStar] #] enabled_general (a, s):Bool = true enabled_specific (a, s):Bool = nu(t):t > zero, add_child(e): init(target(e),s) & not(mq(e,s)=null), … root(v): not(init(v,s)) & not(contention(v,s)) & not(root(v,s)) & (forall (e:tov(v)):child(e,s)), noop:true enabled (a, s):Bool= enabled_general(a,s) & enabled_specific(a,s) trans (a, s):states = nu(t): s WITH [now := now(s) + t], add_child(e):… … root(v): s WITH [basic:= basic(s) with [root:= root(basic(s)) with [(v):= true]]], noop: s start (s):Bool = s = (# basic := basic(s) with …. What is mq ? How does tip work ?
SPEC actions: DATATYPE root(vertices) nu(t) noop states: TYPE = [# done:bool #] enabled_general (a, s):bool = true; enabled_specific (a, s):bool = nu(t): t > zero, root(v): not(done(s)), noop: true enabled (a, s):bool = enabled_general(a,s) & enabled_specific(a,s) trans (a, s):states = nu(t): s WITH [now := now(s) + t], root(v): s WITH [basic:= basic(s) with [done := true]], noop : s start: [states -> bool] = LAMBDA(s):s = (# basic := basic(s) with [done:= false], now := zero, first := (LAMBDA (a:spec_actions): zero), last := (LAMBDA (a:spec_actions): infinity) #);
2. Design Issues How to define abstraction properties (say, refinement) without referring to particular automata? Cannot define a type "automaton" in PVS How quantify over two automata? Adapt the notion of an automaton object A PVS theory with special structure A automaton declaration written with TAME template is interpreted as an automaton object The object can carry extra information: visible, reachable, etc. for property definitions Introduce a template for importing automata definitions and defining a refinement relation between them Essentially user has to rewrite the definition of refinement for every pair of automata User has to be familiar with PVS naming conventions Introduce a generic refinement theory which is imported in the context of the two automata to state the refinement relation User has to write a new theory that matches the elements of the automata theories to elements of the generic theory
Design Issues (contd.) Instead, parameterize generic refinement theory on automaton objects Pass automata theories interpreted as automaton objects as parameters to a generic refinement theory Automatic matching by name of theory elements to elements of automaton object This matching is made possible by recent PVS enhancements, making it easier to pass theory parameters. How to distinguish between analogous objects (e.g. A.states vs B.states) from two automata when communicating with the prover? Formal theory-parameter names can be used as prefixes on objects from the actual theories
3. Pieces in PVS Specification of an Abstraction property Automaton Class A Template for Abstraction properties Interpretation i MA iii Theorem: MA implements MB import B Interpretation MB Abstraction Property ii
Rest of the Talk Background Previous barriers Pieces in PVS specification Class ‘automaton’ Property theories Template for abstraction properties Strategy for weak refinement Experimental results Conclusions
i. Class automaton automaton : THEORY BEGIN actions : TYPE+ states : TYPE+ visible (a: actions) : bool start (s: states) : bool enabled (a: actions, s: states) : bool trans (a: actions, s: states): states reachable (s: states): bool converts (s1 , s2 : states) : bool END automaton
ii. Property Theories : Forward Simulation fwd_sim_base: FORALL sA, If A.start(sA) then EXISTS sB, B.start(sB) and r(sA,sB); fwd_sim_step FORALL sA, sA’, sB, aA, r(sA,sB) & A.enabled(aA,sA) & sA’ = A.trans(aA,sA) implies If A.visible(aA) then EXISTS sB1, sB2, sB3, converts(sB,sB1) & converts(sB2,sB2) & r(sA’, sB3) & B.enabled(actmap(aA), sB1) & B.trans(actmap(aA),sB1) = sB2) else EXISTS sB3, converts(sB, sB3) & r(sA’, sB3) sB sB1 sB2 sB3 sB sB3 actmap r r r r aA aA sA sA’ sA sA’ Visible Invisible
ii. Property Theories : Weak Refinement weak_refinement_base FORALL sA:A.states, if A.start(sA) then B.start(r(sA)) weak_refinement_step FORALL sA, aA, A.reachable(sA) & A.enabled(aA,sA) implies if A.visible(aA) then B.enabled(actmap(aA),r(sA)) and r(A.trans(aA,sA)) = B.trans(actmap(aA),r(sA)) else r(sA) = r(A.trans(aA,sA)) or r(A.trans(aA,sA)) = B.trans(actmap(aA),r(sA)) weak_refinement THEOREM weak_refinement_base and weak_refinement_step
iii. Template for Abstraction Properties Initial theory imports for TIP and SPEC MA : THEORY = automaton :-> tip_decls MB : THEORY = automaton :-> spec_decls amap(aA: MA.actions): MB.actions = CASES aA OF nu(t): nu(t), add_child(e):noop, children_known(c): noop, ack(a): noop, resolve_contention(r): noop, root(v): root(v), noop:noop ENDCASES ref(sC: MC.states): MA.states = (# basic := (# done := EXISTS (v:Vertices): root(v,s_C) #), now := now(s_C) #) IMPORTING weak_refinement[MA,MC, amap, ref] weak_refinement_theorem: THEOREM refinement
PROVE_REFINEMENT PROVE_REFINEMENT SETUP_REF_BASE SETUP_REF_INDUCT_CASES START_REF_INDUCTION_BRANCH START_REF_INDUCTION_BRANCH DO_TRANS DO_TRANS START_ENABLEMENT_PROOF APPLY_GENERAL_PRECOND APPLY_SPECIFIC_PRECOND
PROVE_REFINEMENT Strategy SETUP_REF_BASE SETUP_REF_INDUCT_CASES START_REF_INDUCTION_BRANCH START_REF_INDUCTION_BRANCH DO_TRANS START_ENABLEMENT_PROOF DO_TRANS APPLY_GENERAL_PRECOND APPLY_SPECIFIC_PRECOND weak_refinement : weak_refinement_base & weak_refinement_step weak_refinement_base : FORALL sc:A.states, if A.start(sc) then B.start(r(sc)) weak_refinement_step : FORALL sc, ac, A.reachable(sC) & A.enabled(aC,sC) implies if A.visible(aC) then B.enabled(actmap(aC),r(sC)) and r(A.trans(aC,sC)) = B.trans(actmap(aC),r(sC)) else r(sC) = r(A.trans(aC,sC)) or r(A.trans(aC,sC)) = B.trans(actmap(aC),r(sC))
SETUP_REF_BASE (defstep setup_ref_base (concsimpstrat abssimpstrat) (then (expand "refinement_base") (skolem 1 "sC_1") (flatten) (expand "start") (expand "ref") concsimpstrat abssimpstrat)"" "") PROVE_REFINEMENT SETUP_REF_BASE SETUP_REF_INDUCT_CASES START_REF_INDUCTION_BRANCH START_ENABLEMENT_PROOF DO_TRANS APPLY_GENERAL_PRECOND APPLY_SPECIFIC_PRECOND
START_ENABLEMENT_PROOF (defstep start_enablement_proof (comment-string) (let ((gencomcmd (setq *gencomcmd* `(comment ,(format nil "~a~a" comment-string "general enablement")))) (speccomcmd (setq *speccomcmd* `(comment ,(format nil "~a~a" comment-string "specific enablement"))))) (then (expand "enabled" "enabled C.action" :assert? NONE) (with-labels (flatten) (("C.general-precondition" "C.specific-precondition"))) (expand "enabled" "enabled A.action" :assert? NONE) (branch (with-labels (split) (("A.general-precondition" "A.specific-precondition"))) ((then (apply_general_precond) gencomcmd (time_simp) (postpone)) (then (apply_specific_precond) speccomcmd (postpone)))))) "" "") PROVE_REFINEMENT SETUP_REF_BASE SETUP_REF_INDUCT_CASES START_REF_INDUCTION_BRANCH START_ENABLEMENT_PROOF DO_TRANS APPLY_GENERAL_PRECOND APPLY_SPECIFIC_PRECOND
TIP Walkthrough: Proof Stages weak_refinement : |------- {1} refinement Rule? (PROVE_REFINEMENT) {-1,(base-case)} s_C!1 = (# basic := basic(s_C!1) WITH [init := LAMBDA (v: Vertices): TRUE, contention := LAMBDA (v: Vertices): FALSE, root := LAMBDA (v: Vertices): FALSE, child := LAMBDA (e: Edges): FALSE, mq := LAMBDA (e: Edges): null], now := zero, first := (LAMBDA (a: actions): zero), last := (LAMBDA (a: actions): infinity) #) |------- {1,(base-case)} NOT (EXISTS (v: Vertices): root(v, s_C!1)) AND now(s_C!1) = zero Rule? (SETUP_REF_BASE)
TIP Walkthrough: Proof Stages ;;; Case nu(timeof_C_action) enablement [-1,(reachable C.prestate)] reachable(s_C_theorem) [-2,(enabled C.action)] enabled(nu(timeof_C_action), s_C_theorem) |------- [1,(enabled A.action)] tip_spec_decls.enabled (nu(timeof_C_action), (# basic := (# done := EXISTS (v: Vertices): root(v, s_C_theorem) #), now := now(s_C_theorem), first := (LAMBDA (a: MA.actions): zero), last := (LAMBDA (a: MA.actions): infinity) #))
TIP Walkthrough: Proof Stages ;;; Transitions correspond for nu {-1,(enabled A.action)} tip_spec_decls.enabled(nu(timeof_C_action), (# basic := (# done := EXISTS (v: Vertices): root(v, s_C_theorem) #), now := now(s_C_theorem), first := (LAMBDA (a: MA.actions): zero), last := (LAMBDA (a: MA.actions): infinity) #)) [-2,(reachable C.prestate)] reachable(s_C_theorem) [-3,(enabled C.action)] enabled(nu(timeof_C_action), s_C_theorem) |------- {1,(congruence)} ((# basic := (# done := EXISTS (v: Vertices): root(v, trans(nu(timeof_C_action), s_C_theorem)) #), now := now(trans(nu(timeof_C_action), s_C_theorem)), last := (LAMBDA (a: MA.actions): infinity) #) = tip_spec_decls.trans(nu(timeof_C_action), last := (LAMBDA (a: MA.actions): infinity) #)))
Tip Proof ("" (prove_refinement) (("1" ;; Case root(rootV_C_action) specific enablement case (skolem_in "A.specific-precondition" "v_1") (apply_inv_lemma "15" "s_C_theorem") ;; Applying the lemma ;; (EXISTS (v: Vertices): FORALL (e: tov(v)): child(e, s_C_theorem)) => ;; ((EXISTS (v: Vertices): FORALL (e: tov(v)): child(e, s_C_theorem)) & ;; (FORALL (v, w: Vertices): ;; (((FORALL (e: tov(v)): child(e, s_C_theorem)) & ;; (FORALL (e: tov(w)): child(e, s_C_theorem))) => v = w))) (inst_in "lemma_15" "rootV_C_action") (inst_in "lemma_15" "v_1" "rootV_C_action") (inst_in "lemma_15" "v_1" "rootV_C_action") (skolem_in "lemma_15" "e_1") (apply_inv_lemma "13" "s_C_theorem" "e_1")) ;; Applying the lemma ;; FORALL (e: Edges): root(target(e), s_C_theorem) +> child(e, s_C_theorem) (try_simp) (“2" ;; Case root(rootV_C_action) congruence (inst "congruence" "rootV_C_action") (try_simp))))
5. Other Case Studies Specification and implementation of failure prone memory component[ Romijn 1996] REL_MEM: concrete automaton MEM: Abstract automaton, same as MEM without fail action The refinement relation ref is a bijection The action map amap is an injection Trace inclusion proved by weak refinement Proved completely automatically using (prove_refinement)
Forward Simulation Concrete automaton: composition of P C T [Kaynar, et. al. 2004 ] Send process P sends a message every u1 time until fail action occurs Channel C delivers message with a max delay b Timeout process T times out if it does not receive a message for more than u2 time, and suspects P to be failed Property to check: If u2 > u1 + b then suspects failed Abstract automaton: A fail action is followed by timeout in u2 + b time Trace inclusion proved by forward simulation in PVS Developing strategy PROVE_FWD_SIM Initial proof steps are similar to PROVE_REFINEMENT Needs addition TAME sub strategies
Conclusions Specification of abstraction properties in PVS/ TAME Automaton object / theory Library of abstraction property theories Template for stating abstraction properties as theorems Reusable strategy for proving weak refinement in TAME User friendly interactive proving Template for developing strategies for proving other abstraction relations Add other abstraction relations to library Develop PROVE_FWD_SIM and others Integrate with TIOA tools