99 lines
3.4 KiB
Markdown
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.
|