learning_tla/lamport_video/docs/lecture10-1.md
2025-02-21 18:20:43 +01:00

99 lines
3.4 KiB
Markdown

# 10.1 Implementation with refinement - preliminaries
Implementation as implication like we used until now only works
when ALL the high-level specification variables appear in the low-level spec.
But this is not always the case.
## Recursive definitions
Problem: "define an operator RemoveX that removes all instances of "X" from a sequence of strings"
`RemoveX(<< "Tom", "X", "Dick", "Harry", "X" >>) = << "Tom", "Dick", "Harry" >>`
Let us try to do this with a recursive definition:
```tla+ code fragment
RemoveX(sequence) == ... RemoveX(shorter_sequence) ...
...
== ... RemoveX(<<>>) ...
== <<>>
```
So we have to define two things:
- `RemoveX(<<>>) == <<>>`
- the recursive part, noting that:
- `RemoveX(<<"X", ...>>) == RemoveX(<<...>>)`
- `RemoveX(<<"Tom", ...>>) == <<"Tom">> \o RemoveX(<<...>>)`
```tla+ code fragment
RECURSIVE RemoveX(_) \* Required to allow recursion
RemoveX(seq) ==
IF seq = <<>>
THEN <<>>
ELSE IF Head(seq) = "X"
THEN RemoveX(Tail(seq))
ELSE << Head(seq) >> \o RemoveX(Tail(seq))
```
Think of recursive definitions when implementing the operatior with a program
requires a loop.
## Substitution
### Simple substitution law
"The expression obtained by substituting expression _e_ for the symbol _v_ in expression _f_"
is written: `f WITH v <- e`
Fundamentally in math, for any variable `v` and expressions `e` and `f`,
`v = e IMPLIES f = (f WITH v <- e)`
As a TLA+ theorem: `THEOREM (v = e) => (f = (f WITH v <- e))` (not valid syntax)
L.L. calls this the "simple substitution law", but this is not the usual math naming.
Math variables are the `CONSTANTS` of TLA+; nothing in ordinary math corresponds
to the `VARIABLES` and non-constant operators of TLA+: those belong to _temporal logic_,
a special kind of math, not as simple as ordinary math.
**That theorem is NOT TRUE if `v` is a variable or `e` is a non-constant expression:**
this breaks due to the prime operator:
```tla+ code fragment
\* Substituting v <- y, e <- x + 2, f <- y' in the simple substitution law:
THEOREM (y = x + 2) -> (y' = (x + 2)')
```
- asserts `y = x + 2` in the first start
- asserts `y = x + 2` in the second state too, because that is what the prime operator means,
and that should be true for all behaviors
But that is not true for all behaviors, so the theorem is false.
### Temporal substitution laws
The temporal substitution law is almost the same as the simple substitution law,
but with the _always_ operator added:
`THEOREM [](v = e) => (f = (f WITH v <- e))`
Which reads: for every behavior, if v = e is true in ALL states of the behavior,
then f = (f WITH v <- e) is true on the behavior.
This law is true when the values of `v` and `e` do not depend on the state:
- `v` is a variable and `e` is a state expression.
- `v` is a constant and `e` is a constant expression
There is also a _general temporal substitution law_
- `THEOREM [](v1 = e1) /\ (v2 = e2) /\ ... => (f = (f WITH v1 <- e1, v2 <- e2, ...))`
- With the substitution of all v_i being simultaneous
Otherwise, it would not hold when the expression for one v_i depends on another v_j.
The name "temporal substitution law" is often used for the general version.
## The AB2 protocol
Same as AB, except messages are no longer lost but detectably corrupted.
In the protocol, a corrupted message is represented by a value `Bad` that does
not correspond to any message that can be sent.