learning_tla/lamport_video/docs/lecture08-1.md
2025-02-17 18:08:25 +01:00

157 lines
6.1 KiB
Markdown

# 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 + v` is module-complete if `x` is a declared variable
- but the subexpression `x' = x + v` is not, because `v` is neither in it, nor declared
A _module-closed_ formula is a boolean module-closed expression:
- `(x \in 1..42) /\ (y' = x + 1)` is a module-closed formula if both `x` and `y` are 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. `'` and `UNCHANGED`)
- Example: `foo \cup { n \in 1..22 : n^2 > m}` depends only on constants `foo` and `m`
- 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
- `TPInit` is true on state s1
- `TPNext` is 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 `INIT` and `NEXT` in 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](../specs/TwoPhase.tla)
```tla+ code fragment
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 `[]TPTypeOK` is true on a behavior iff `TPTypeOK` is true on all steps of the behavior.
- The _state formula_ `TPTypeOK` is an action whose value depends only on `s_i`,
because it contains no primed variables
- So `[]TPTypeOK` is true on a behavior iff `TPTypeOK` is true on all states (vs steps) of the behavior
- This is written `[]TPTypeOK` without adding the `[ ]_<<var_1, ...var_n>>`,
because it is a `state formula`, not just an `action 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 `TPSpec` is true on the behavior, which means that the behavior satisfies `TPSpec`,
- then _always_ `[]TPTypeOK` is true on the behavior
- which means `TPTypeOK` is true on every state of the behavior
- Meaning that the theorem asserts that `TPTypeOK` is an `INVARIANT` of `TPSpec`
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 `[]TPTypeOK` to the properties for a model with behavior spec `TPSpec`
- or add `TPTypeOK` to the invariants for the model
- In TLC
- add `PROPERTY []TPTypeOK` to the CFG file
- or add `INVARIANT TPTypeOK` to the CFG file