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

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 + 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

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