Summary

Lamport's "Temporal Logic of Actions" is a temporal logic that includes actions — i.e. transitions between states. The conventional Tableau technique of Clarke and Emmerson [1981], used to verify temporal formulas, does not handle actions. We present the Action Tableau technique, which does handle actions. The technique was partly developed and implemented during a summer internship at Compaq Systems Research Center.

Lucian Wischik,

Leslie Lamport, Yuan Yu (supervisors)
TLA Temporal Logic of Actions - uses the same logical notation for both specification and checks
Lamport et al
TLC Model checker for TLA
Lamport, Yu et al
SPIN Model-checker - write specifications in PROMELA, use Buchi automata to verify temporal formulas.
Vardi, Wolper, Holzmann et al
Clark & Emerson [1981] "Design and synthesis of synchronization skeletons using branching time temporal logic."
The Tableau method.
STeP Stanford Temporal Prover - write in SPL, use Tableau method to verify arbitrary temporal formulas.
Manna, Pnueli et al.
Book "Temporal Verification of Reactive Systems".

TLA is a logic for describing systems that go from state to state.

You can write properties about states
x = 3

You can write how a system moves from one state to another - transitions - actions x' = x+1

You can use temporal operators
[] (always), <> (eventually), ~> (leads-to), O (next) * actually, not this one... [] x<4
x=2 ~> x=3
O([] x<4)

previous Actually, there is no Next operator O in TLA, because its inclusion would lead to problems. It is however needed to construct a tableau, which is why we introduced it here.

Conventional model-checkers:

if (x==3) {noncritical; x=1;}
else {critical; x=x+1;}

TLA says:

with actions:     without:
 x'=x+1            Exists y: x=y /\ O(x=y+1)
  solvable          unsolvable in general
                    also, O not in TLA

Model: a possible execution trace of Spec
Model-checker: program to verify that all models satisfy Check

(simplistic) Check "always" formulas about states. * surprisingly useful...

"always, the state will be such with no dangling pointers"
"always, the state will have no more than ten items in the buffer"

(tableau) Check arbitrary temporal formulas about states.

"if I put a datum into my reliable-transport-protocol, then the datum will eventually come out the other end"

previous

To check "always" formulas about states is easy: just go through every possible state, and see if the formula holds. This is what TLC did, before the project.

Although it sounds simplistic, it is still useful! For example, TLC found some problems in the cache-coherency protocol of an Alpha chip currently in design. Paper available.)

Action tableau: new technique to handle arbitrary TLA formulas

  • in specifications and as checks
  • freely using the temporal operators [], <>
  • about transitions as well as states

    "although this wire may be lossy, it will not do 'fail' transitions from now to eternity"
    "if the event gets signalled, then my process will eventually wake up"

    In fact we can turn specification and check into one giant formula.
    Model: a model of the formula Spec /\ -Check
    Model-checker: check whether a model exists

  • state graph for a mod-3 counter
    "If the transition becomes takeable infinitely often, it must be taken infinitely often"

    []<>Enabled(NextUp) => []<>Taken(NextUp)

    equivalently, SF(NextUp).

    "Strong Fairness". * what is weak fairness?

    previous Strong and weak fairness

    state graph illustrating SF vs WF
    "Strong Fairness: if Next is enabled infinitely often, then it must be taken infinitely often"

    s1,s2,s1,s2,... is illegal under SF(Next)

    "Weak Fairness: if we get in a state where Next is perpetually enabled, it must eventually be taken"

    s1,s2,s1,s2,... is legal under WF(Next)

    So that we can replace a bit of code,
    we always allow stutter-steps.

    hclock hmclock (m) hmclock
    hour clock hour+minute clock hour+minute clock, hiding the minutes

    [] (tick \/ stutter)

    SF(tick)

    (In fact TLA always implicitly allows stutter-steps as part of its very syntax).

        Init:  x=1
      NextUp:  x<3  /\  x'=x+1
    NextFlip:  x=3  /\  x'=1
    LiveSpec:  SF(NextUp)
    
        Spec:  /\ Init
               /\ [] (NextUp \/ NextFlip \/ stutter)
               /\ LiveSpec
    
       Check:  /\ (x=3) ~> (x=1)
               /\ SF(NextFlip)
               /\ [] x<4

    The user asks: does Spec => Check ?

    In answer, we will attempt to find a counter-example.
    i.e. a case where Spec and Not(Check) hold.

    things solved by existing model-checked

    Existing model-checkers:

    (TLC only checked "always state" properties, before.)

    things solved with action tableaux

    New Technique 1: Action Tableau

    things solved with DNF

    New Technique 2: Disjunctive Normal Form

    tableau for x=3 not leading to x=1

    Turn a temporal formula on states
    into a finite-state machine,
    which accepts only those execution traces that satisfy the formula.

    We want a counter-example to Spec=>Check: = Not(Check)
    = Not(x=3 ~> x=1)
    = <>(x=3 /\ []x≠1)

    Only consider fulfilling cycles. The green cycle is not fulfilling: it makes the promise <>..., but does not deliver.

    behaviour graph for mod-3 counter

    Do cross-product: state * tableau

  • all paths in it are consistent with the state graph:
    Init /\ []Next
  • all paths in it are consistent with the tableau:
    Not(Check)
  • Goal: to find cycle* component that

  • is fair (if red is takeable, take it eventually)
  • fulfills its promises (don't stay on greens)
  • Answer: (1n2n3n)n3ω

    previous Goal: to find a component

    A strongly connected component in a graph is a maximal subset of nodes and edges such that every node is reachable from every other node.

    There are an infinite number of cycles, but they always end up contained within a component. Components completely capture every possible cycle.

    There are standard algorithms for finding components. We use Targan [1972]. A neat online reference is by Prof. Eppstein as course-notes for his algorithms class. Once the components are found, we check that they are fair and fulfilling:

    An eventually-always formula <>[]a means: remove all edges from the component that do not satisfy a, and find components in what is left.

    An always-eventually formula []<>a means: that a must be present somewhere in the component that's left.

    (You see why fairness the conditions eventually-always and always-eventually are so significant: they are temporal formulas which have no need of tableaux, because they merely describe properties of the final within-component loop of a cycle.)

    Fulfilling: if we have <>p, which promises p, then we need in the component at least one node which either doesn't have <>p, or which does have p. You need to think subtly to figure out why this is correct. Hint: by construction of the tableau, the only way to get from a <>p to something without <>p is by actually fulfilling it! Incidentally, although it is true that Not([]p) promises Not(p), we don't consider it: since our disjunctive normal form pushed all negations inside.

    If a component passes all these tests, then it is a valid counter-example and we are finished. If no component passes all tests, then there are no counter-examples.

    The reference we used for all this is Temporal Verification of Reactive Systems: Safety by Manna and Pnueli, but we treat eventually-always and always-eventually a little more generally.

    an action tableau

    Basic idea: put actions into the tableau graph.

    Subject of ongoing work.

    action tableau and state space

    In fact, can express all of Spec/\-Check as a single formula, in a single action tableau.

    Before, we used to cross tableau with state-transition graph of Spec. But now, Spec has been merged into the tableau...

    We cross action-tableau with the trivial universal state transition graph (fragment shown in green; needs no explicit storage; every state connects to every other state).

       NextUp:  x<3  /\  x'=x+1
     NextFlip:  x=3  /\  x'=1
    NextStutt:  x'=x
    
      Formula:  /\ x=1
                /\ [] (\/ NextUp
                       \/ NextFlip
                       \/ NextStutt)
    action-tableau behaviour graph

    Advantages of action-tableaux:

    Not( SF(NextUp) => SF(NextFlip) /\ 3~>1 )

    Optimization to reduce cost for fairness validation.
    Express formula in disjunctive normal form. (preserves meaning)
    Then look for cycles, as before.

    disjunctive normal form

    (Sorry! TLC not yet publically released, so no interactive version available.)

    tlclive egtalk
    TLC Version 1.0 of 3 Jun 1999
    Running Random Simulation with seed 7395095282892744306.
     
    Found a counter-example!
    The counter-example satisfies these parts from the spec:
    <>[]- (state:LiveSpec.fair_enabled)
    The counter-example satisfies this temporal formula:
    <>(LiveCheck.conj0.cause) /\ []-(LiveCheck.conj0.effect)
    And these are the states from which counter-example
    cycles might be constructed:
    * Behaviour-graph-node 5
    particle formulas:  []-(state:LiveCheck.conj0.effect), 
    State fingerprint: -4900539538744082733
    /\ x = 3
    Here endeth the counter-example.
     
    [and there's a second counter-example...]
     
    Finished checking.