On Building PVS Interfaces for Abstraction Proofs Extending TAME for Refinements Sayan Mitra...
-
Upload
joan-gaines -
Category
Documents
-
view
227 -
download
1
Transcript of On Building PVS Interfaces for Abstraction Proofs Extending TAME for Refinements Sayan Mitra...
On Building PVS Interfaces for Abstraction Proofs
Extending TAME for Refinements
Sayan [email protected]
Myla [email protected]
1. Motivation
• Why a theorem prover interface ?– Simpler to use
• Strict rules for specification• Fewer proof steps
– Provides a more tamed environment, for special purposes.– Less effort
• Strategies exploit common proof patterns
– Generate human readable proofs• How does it work ?
– Example: TAME• Template for specifying Timed I/O Automata• Specialized Strategies for Inductive Invariant Proofs.
• We want to extend this idea to other kinds of proofs– Abstractions– Termination– Liveness
Talk Outline
1. Motivation
2. Background
A quick tour of TAME
PVS strategies
• Interface for Abstraction proofs
Abstraction relations
Design using PVS
theory interpretations
• The Examples
• Strategy for proving Refinement
Results
• Conclusions
ToDo’s & Future work
2. Timed Automaton Modeling Environment
• Provides a template for specifying timed automata• States• Actions : Visibility, Preconditions, and Transitions• Start states
– Reachable states of the automaton– Equivalence of states
• Strategies for proving Invariants– AUTO_INDUCT– DIRECT_PROOF– TRY_SIMP– APPLY_GENERAL_PRECOND– APPLY_SPECIFIC_PRECOND– APPLY_IND_HYP– APPLY_INV_LEMMA
2.1 TAME: Theory Tree
TESLA_decls
states machine time
TESLA_unique_aux TESLA_rewrite_1_aux TESLA_rewrite_2_aux
TESLA_invariants
stateactionspreconditionstransitionsstart state
2.2 PVS Strategies
• PVS prover commands are either rules or strategies– A rule executes as a single step, e.g. skolem, flatten, etc.
– A strategy is created using • PVS strategy building commands (strategicals), e.g., then, branch,
try, let, if, etc.
• Rule applications
• Other strategies
• Examples of simple strategies– (TRY (THEN (LIFT-IF) (PROP) (ASSERT)) (FAIL) (SKIP))
– (APPLY (THEN (LIFT-IF) (PROP (ASSERT))
• let, if strategicals allow the use of Lisp code in strategies
• Lisp is used to probe the current proof state and create prover commands.
2.3 Probing the Proof State in PVS
The following slots have :instance allocation:
label "weak_refinement_thm.1"
current-goal {-1} "rel_mem_visible(rel_nu(rel_nu1_var!1))"
{-2} "rel_mem_reachable(s1)“
{3} "rel_mem_enabled(rel_nu(rel_nu1_var!1), s1)"
|-------
{1} "mem_enabled_general(amap(rel_nu(rel_nu1_var!1)),r(s1))"
current-xrule …
(lisp (describe *ps* ))
2.3 Probing the Proof State in PVS
The following slots have :instance allocation:
s-forms (mem_enabled_general(amap(rel_nu(rel_nu1_var!1)), r(s1))
NOT rel_mem_visible(rel_nu(rel_nu1_var!1))
NOT rel_mem_reachable(s1)
NOT rel_mem_enabled(rel_nu(rel_nu1_var!1), s1))
p-sforms (mem_enabled_general(amap(rel_nu(rel_nu1_var!1)), r(s1)))
n-sforms (NOT rel_mem_visible(rel_nu(rel_nu1_var!1))
NOT rel_mem_reachable(s1)
NOT rel_mem_enabled(rel_nu(rel_nu1_var!1), s1))
(lisp (describe (current-goal *ps* )))
2.3 Probing the Proof State in PVS
(mem_enabled_general(amap(rel_nu(rel_nu1_var!1)), r(s1))
NOT rel_mem_visible(rel_nu(rel_nu1_var!1))
NOT rel_mem_reachable(s1)
NOT rel_mem_enabled(rel_nu(rel_nu1_var!1), s1)) is a cons.
(lisp (describe (s-forms (current-goal *ps* ))))
(lisp (describe (car (s-forms (current-goal *ps* )))))
newline-comment nil parens 0
type bool free-variables nil
free-parameters unbound from-macro nil
operator mem_enabled_general
argument (amap(rel_nu(rel_nu1_var!1)), r(s1)) nil
A Typical defstep in a Strategy
(defstep ref_induct_steps ()
(let ((sforms (s-forms (current-coal *ps*)))
(refStepName (string (id (formula (car sforms)))))
(cmd `(then (expand , refStepName)
(skolem 1 “s1”)))
cmd)
“Expands induction step and skolemizes top level”
“Expand” )
3 Abstraction Relations: Refinements
• A refinement from A to B is a function r from states of A to states of B, such that:– s є start(A) implies r(s) є start(B), and
– s aA s’ implies r(s)a
Br(s’).
• A weak refinement from A to B is a function r from states of A to states of B, such that:– s є start(A) implies r(s) є start(B), and
– for every reachable state s, and transition s aA s’, if a is a
visible action then r(s)aBr(s’), otherwise r(s) = r(s’).
• Thm: (Weak) Refinement is sound. A ≤r B implies A ≤T B
• Thm: Invariance:If A ≤r B, IA is invariant for A, and IB = r(IA)= {r(s) | s є IA}, then is IB an invariant for B ?
3.1 More on Refinements
• No, IB as defined above is not an invariant for B.
– start(B) not contained in IB.
• Suppose IB is an invariant for B
• We define IA = {s | r(s) є IB}
• Then IA is an invariant for A.
3.1 Abstraction Relations: Simulations
• A forward simulation from A to B is a function f from states of A to states of B, such that:– s є start(A) implies f(s) ∩ start(B) ≠ Ø, and
– if s is a reachable state of A, s aA s’, and u є f(s), then there
exists u’ є f(s’), such that uaBu’.
• Thm: refinement implies forward simulation.
• Thm: Soundness A ≤f B implies A ≤T B
3.2 Interface for Abstraction Proofs: The Plan
• PVS 3 is supposed to support theory interpretations
• We define a generic automaton theory
• An abstraction theory defines the
relation between two automata
automaton:THEORY BEGIN actions: TYPE+; visible:[actions->bool]; states: TYPE+ enabled:[actions,states -> bool]; trans:[actions, states ->states]; equivalent:[states, states ->bool]; reachable:[states->bool]; start:[states -> bool] END automaton
refinement[ A, B : THEORY automaton, r:[A.states -> B.states] , amap: [A.actions -> B.actions]] : THEORY
• A common theory imports the specification of both the abstract and concrete automata and imports the abstraction theory
IMPORTING abstractions_lib@refinement[tip_decls, spec_decls, r, amap]
3.3 Problems
• The previous scheme requires– PVS theory interpretations, and
– Passing theories as parameters by name
• We have collapsed all the theories into a single theory – Abstract and concrete automata specifications
– The invariants
– The abstraction relation and the corresponding theorem
• To distinguish the components of each automaton– Cannot rely on standard naming
not implemented presentlydoes not work!!
We are here
1. Motivation
2. A quick tour of TAME
PVS strategies
3. Interface for Abstraction proofs
Abstraction relations
Design using PVS theory
Problems
• The Examples
• Strategy for proving Refinement
Results
• Conclusions
ToDo’s & Future work
4 Example 1: TipVERTICES: TYPE+; Link: TYPE=[Vertices, Vertices]; Edges: TYPE = {l:Link | not(proj_1(l)=proj_2(l))};
% source, target functions and definition of connectness
tip_actions: DATATYPE nu(timeof:(fintime?)): nu? add_child(addE: Edges): add_child? children_known(childV: Vertices): children_known? ack(ackE: Edges): ack? resolve_contention(resE: Edges): resolve_contention? root(rootV: Vertices): root? noop:noop?
tip_visible(a:tip_actions):bool
tip_MMTstates: TYPE = [# init: [Vertices -> Bool], contention: [Vertices -> Bool], root: [Vertices -> Bool], child: [Edges -> Bool], mq:[Edges -> BoolStar] #]
IMPORTING states[tip_actions,tip_MMTstates,time,fintime?]
% this should not be necessary if % tip_states:TYPE = states
tip_enabled_general (a:tip_actions, s:tip_states):bool = now(s) >= first(s)(a) & now(s) <= last(s)(a);
tip_enabled_specific (a:tip_actions, s:tip_states):bool = nu(delta_t): delta_t > zero, add_child(e): children_known(v): ack(e): resolve_contention(e): root(v): not(init(v,s)) & not(contention(v,s)) & not(root(v,s)) & (forall (e:tov(v)): child(e,s)), noop:true
tip_enabled (a:tip_actions, s:tip_states):bool = tip_enabled_general(a,s) & tip_enabled_specific(a,s)
IMPORTING machine[tip_states, tip_actions, tip_enabled, tip_trans, tip_start, tip_visible]
4.1 Tip continued (Transitions)tip_trans (a:tip_actions, s:tip_states):tip_states = nu(delta_t): s WITH [now := now(s) + delta_t],
add_child(e): if not(mq(e,s)=null) then s WITH [basic:= basic(s) with
[child := child(basic(s)) with [(e):=true], mq := mq(basic(s)) with [(e):= cdr(mq(e,s))]]]
else s endif,children_known(v): ….ack(e):… resolve_contention(e):…root(v): s WITH [basic:= basic(s) with [root:= root(basic(s)) with [(v):= true]]],noop: s
tip_start (s:tip_states):bool = s = (# basic := basic(s) with ….
4.2 The Spec
spec_actions: DATATYPEspec_root(rootV: Vertices): spec_root?spec_nu(timeof:(fintime?)): spec_nu?spec_noop: spec_noop?
spec_MMTstates: TYPE = [# done:bool #]
IMPORTING states[spec_actions,spec_MMTstates,time,fintime?]
spec_enabled_general (a:spec_actions, s:spec_states):bool = now(s) >= first(s)(a) & now(s) <= last(s)(a);
spec_enabled_specific (a:spec_actions, s:spec_states):bool = spec_nu(delta_t): delta_t > zero,spec_root(v): not(done(s)),spec_noop: true
spec_trans (a:spec_actions, s:spec_states):spec_states =spec_nu(delta_t): s WITH [now := now(s) + delta_t],spec_root(v): s WITH [basic:= basic(s) with [done := true]],spec_noop : s
spec_enabled (a:spec_actions, s:spec_states):bool = spec_enabled_general(a,s) & spec_enabled_specific(a,s)
spec_start: [spec_states -> bool] = LAMBDA(s:spec_states):s = (# basic := basic(s) with [done:= false], now := zero, first := (LAMBDA (a:spec_actions): zero),
last := (LAMBDA (a:spec_actions): infinity) #);
IMPORTING machine[spec_states, spec_actions, spec_enabled, spec_trans, spec_start, spec_visible]
4.3 Action and State maps for Tip
amap(aA: tip_actions): spec_actions = nu(t): spec_nu(t), add_child(e): spec_noop, children_known(c): spec_noop, ack(a): spec_noop, resolve_contention(r):spec_noop, root(v): spec_root(v), noop: spec_noop
r(sA: tip_states): spec_states = (# basic :=
(# done := EXISTS (v:Vertices): root(v,sA) #), now := now(sA), first := (LAMBDA(a:spec_actions): zero), last := (LAMBDA(a:spec_actions): infinity) #)
4.4 Tip Invariants and Refinement Theorem
Thm_200: THEOREM (FORALL (s:tip_states): tip_reachable(s) => spec_reachable(r(s)));
refinement_base: bool = (FORALL (sA:tip_states): tip_start(sA) => spec_start(r(sA)));
weak_alt_refinement_step: bool = (FORALL (sA:tip_states, aA:tip_actions): tip_reachable(sA) & tip_enabled(aA,sA) =>
IF tip_visible(aA) THEN (spec_enabled(amap(aA),r(sA)) & r(tip_trans(aA,sA))= spec_trans(amap(aA),r(sA)))
ELSE (r(sA) = r(tip_trans(aA,sA))) ENDIF)
weak_refinement_step : bool = (FORALL (sA:tip_states): FORALL (aA:tip_actions): tip_reachable(sA) & tip_enabled(aA,sA) => (tip_visible(aA)
(spec_enabled(amap(aA),r(sA)) & r(tip_trans(aA,sA))= spec_trans(amap(aA),r(sA)))) &
(NOT tip_visible(aA)
((r(sA) = r(tip_trans(aA,sA))) OR (r(tip_trans(aA,sA))= spec_trans(amap(aA),r(sA))))))
weak_refinement : bool = refinement_base & weak_refinement_step
weak_refinement_thm : THEOREM weak_refinement
correspondence
equality
4.5 Example 2: Memory : The Specfind:[Locs, Memory -> MemVals]change:[Locs, Vals, Memory -> Memory]
find_Ax: AXIOM FORALL(l,m): IF memloc(l) THEN find(l,m) = m(l) ELSE find(l,m) = InitVal ENDIF
change_Ax: AXIOM FORALL(l,v,m): IF memloc(l) AND memval(v) THEN change(l,v,m) = m WITH [(l) := v] ELSE change(l,v,m) = m ENDIF
mem_actions: DATATYPE nu(timeof:(fintime?)): nu? read(proc:Process, loc:Locs):read? write(proc:Process, loc:Locs, val: Vals):write? return(proc:Process, ack:Ack):return? bad_arg(proc:Process):bad_arg? mem_failure(proc:Process):mem_failure? get(proc:Process):get? put(proc:Process):put? noop:noop?
mem_MMTstates: TYPE = [# pc:[Process->Mpc], loc:[Process->Locs], val:[Process->Vals], memory:Memory, performed:[Process->bool], legal:[Process->bool] #]
mem_enabled_specific (a:mem_actions, s:mem_states):bool = nu(delta_t): delta_t > zero,
read(p,l):true,write(p,l,v):true,return(p,ack):
bad_arg(p): ( Read?(pc(s,p)) OR Write?(pc(s,p)) ) AND NOT legal(s,p),mem_failure(p):( Read?(pc(s,p)) OR Write?(pc(s,p)) ),get(p): Read?(pc(s,p)) AND legal(s,p) AND (NOT performed(s,p)),
put(p): Write?(pc(s,p)) AND legal(s,p), noop:true
4.6 Reliable Memory
Identical to mem specs, except, does not have the mem_failure action.
r and amap are identity functions.
amap(aA: rel_mem_actions): mem_actions = rel_nu(t): nu(t), rel_read(p,l): read(p,l), rel_write(p, l, v): write(p,l,v), rel_return(p, ack): return(p,ack), rel_bad_arg(p): bad_arg(p), rel_get(p): get(p), rel_put(p): put(p),
rel_noop: noop
r(sA: rel_mem_states): mem_states = (# basic := (# pc := pc(sA), loc := loc(sA), val := val(sA), performed := performed(sA), memory := memory(sA), legal := legal(sA) #),
now := now(sA),first := (LAMBDA(a:mem_actions): zero),last := (LAMBDA(a:mem_actions): infinity) #)
5 Strategy for Refinement Proofs
• Structure of refinement proofs : (refinement_strat)
• Expands and splits theorem into base case and induction step
– Base case proved by skolemizing and expanding r and expanding tip_start and spec_start.
– Induction step:• Induct on the action name, this generates as many subgoals as there are
actions
• For each visible action 2 new subgoals are generated
– Corresponding visible action is enabled
– Correspondence for the resulting post state
• For each invisible action prove either of the following
– Equality
– Correspondence
• If this does not complete the proof for a particular action then invariants are required, and the user will be prompted to choose the appropriate invariant
5.1 Results
• RPC-MEM– Proof completes without any user assistance
– Run time = 4.25 secs Real time 38.74 secs• Can improve using rewrite instead of grind.
• Tip – Used invariant 15 and invariant 13 manually for the branch
which required maximum work in the full manual proof.
5.2 Summary
• Strategy for proving refinements. Two examples.– Rewrites instead of grind
– Add comments
– Careful back-tracking to handover the proof to the user in the best possible proof state
– Another example
• Template theory for proving other abstractions using PVS theory interpretations and passing theories by name.
• Automatic generation of auxiliary theories.
• Learnt quite a bit about writing PVS strategies.
Future Work
• Strategies other structured proofs– Abstraction Proofs
• Simulation Proofs
– Termination Proofs
– Liveness (?)
• Porting the system to new and enhanced PVS
• Interface for HIOA
Thank you all very much. It has been a fun summer..
so far