6.1 KiB
8.1 Implementation - preliminaries
Implies
A specification can be written as a single temporal formula.
P => Q reads P implies Q. Unlike everyday speech, implies does NOT assert causality,
only correlation.
Definitions
Module-closed formulas
A module-closed expression, after resolution, contains only:
- built-in TLA+ operators and constructs
- numbers and strings
- declared constants and variables
- identifiers declared locally within the expression, including those
- in \A and \E
- in function
[]and set{}constructors
\E v \in Nat: x' = x + vis module-complete ifxis a declared variable- but the subexpression
x' = x + vis not, becausevis neither in it, nor declared
- but the subexpression
A module-closed formula is a boolean module-closed expression:
(x \in 1..42) /\ (y' = x + 1)is a module-closed formula if bothxandyare declared variables
Only in this lecture, expression/formula will only consider those which are module-closed.
Constant formulas
A constant expression is a (module-complete) expression that
- has no declared variables
- has no non-constant operators (e.g.
'andUNCHANGED) - Example:
foo \cup { n \in 1..22 : n^2 > m}depends only on constantsfooandm - It is also a state expression that has the same value on all states
An assumption, introduced by an ASSUME statement, must be a constant formula.
State expressions
A state expression can contain anything in a constant expression, as well as variables
declared in a VARIABLES statement. Example, if foo is a declared constant,
and x and y are declared variables: x + y[foo].
- It has value on a s state: states assign values to variables.
- It is an action expression whose value only depends on the first state of the step.
A state formula is a boolean state expression.
Action expressions
An action expression can contain anything a state expression can, as well as ' and UNCHANGED.
It has value on a step or pair of states.
The prime operator ' does not only apply to variables, but to any state expression.
For a state expression se, the value of se' on step s -> t is the value
of se on state t.
This defines: UNCHAGED e equals e' = e, so
UNCHANGED <<x, y, z>> equals <<x, y, z>>' = <<x, y, z>>
equals <<x', y', z'>> = <<x, y, z>>
equals (x' = x) /\ (y' = y) /\ (z' = z)
Temporal formulas
Definition
A temporal formula has a boolean value (formula) on a sequence of states, which is what we've been calling a behavior.
We can write any specification as a temporal formula, whose value is true
on the behaviors allowed by the spec.
For example, let's call TPSpec the specification of the two-phase commit protocol.
Since the two-phase commit spec has
- initial formula:
TPInit - next-state formula:
TPNext
Then, TPSpec should be true on s(1) -> s(2) -> ... iff
TPInitis true on state s1TPNextis true on all steps s(i) -> s(i+1) for all i.
Considering the state expression TPInit as an action, its value is the one it has on
the initial state of the step, that is true on s(1).
If we consider it as a temporal formula, the state it has on the first state of the behavior is true.
Similarly, TPNext is true on a behavior iff it is true on the first state of the behavior.
If we allow it to stutter indefinitely with the always temporal operator, we get []TPNExt,
which is true on a behavior iff TPNExt is true on all first states of the behavior.
So TPSpec == TPInit /\ []TPNext
That is really is too simple. It really is:
TPSpec == TPInit /\ [][TPNext]_<<rmState, tmState, tmPrepared, msgs>>
In general, the specification with initial formula Init, next-state formula Next,
and declared variables v_1, ..., v_n is expressed by the temporal formula:
Init /\ [][Next]_<<v_1, ..., v_n>>
But for now, ignore that last part.
We can tell TLC that the spec is this, we can d
- In the toolbox:
- either define Initial predicate and next-state relation
- or give it the complete temporal formula, even using its name if it is in the spec
- define
INITandNEXTin a CFG file.
Applying [] to a state formula
For action A, []A is true on a behavior iff A is true on all steps of the behavior.
Consider TPTypeOK in two-phase commit
TPTypeOK ==
(*************************************************************************)
(* The type-correctness invariant *)
(*************************************************************************)
/\ rmState \in [RM -> {"working", "prepared", "committed", "aborted"}]
/\ tmState \in {"init", "done"}
/\ tmPrepared \subseteq RM
/\ msgs \subseteq Messages
- It is an action, so
[]TPTypeOKis true on a behavior iffTPTypeOKis true on all steps of the behavior. - The state formula
TPTypeOKis an action whose value depends only ons_i, because it contains no primed variables - So
[]TPTypeOKis true on a behavior iffTPTypeOKis true on all states (vs steps) of the behavior - This is written
[]TPTypeOKwithout adding the[ ]_<<var_1, ...var_n>>, because it is astate formula, not just anaction formula.
Theorems
If TF is a temporal formula, THEOREM TF asserts that TF is true on
- every possible behavior
- not just behaviors satisfying some spec
THEOREM TPSpec => []TPTypeOK asserts that for every behavior:
- if
TPSpecis true on the behavior, which means that the behavior satisfiesTPSpec,- then always
[]TPTypeOKis true on the behavior - which means
TPTypeOKis true on every state of the behavior
- then always
- Meaning that the theorem asserts that
TPTypeOKis anINVARIANTofTPSpec
TLC does NOT automatically check theorems: we add them in the specs to tell the reader what the author expects to be true.
To force checking the theorem,
- In the toolbox,
- add
[]TPTypeOKto the properties for a model with behavior specTPSpec - or add
TPTypeOKto the invariants for the model
- add
- In TLC
- add
PROPERTY []TPTypeOKto the CFG file - or add
INVARIANT TPTypeOKto the CFG file
- add