The following exercises use the TLA
toolbox for writing and proving PlusCal algorithms. A local
installation of the toolbox is available under `~herbrete/public/TLA/toolbox`.
Add this path to your environment variable `PATH` (in your local
configuration file) and update your environment (applying the `source`
command on the updated configuration file). The TLA toolbox is launched by
entering the command: `toolbox` in a terminal. A PlusCal user's
manuals are available at `~herbrete/public/TLA/c-manual.pdf `and`
~herbrete/public/TLA/pluscal.pdf
`

Aside from the resources provided above, books, tutorials and tools can be downloaded from the TLA webpage.

PlusCal is an algorithmic language. It differs from programming languages since:

- PlusCal algorithms can manipulate arbitrary mathematical objects (graphs, etc). Programming languages require to implement these objects using low-level types (integers, booleans, etc).
- PlusCal algorithms can be non-deterministic. Programs need to be deterministic in order to be executable.
- PlusCal has a well-defined notion of an atomic step. In general, the instructions in a program are not atomic (mechanisms are usually provided to group instructions in atomic steps)
- PlusCal has a formal semantics defined as TLA+ expressions.

The TLA toolbox offers three main features:

- The translation of PlusCal programs into TLA+ expressions.
- The TLC model-checker that allows to find bugs in algorithms, and to prove algorithms with finite resources.
- The TLA prover which is not in the scope of this class.

Launch the TLA toolbox and create a new specification using menu File
> Open Spec > Add New Spec... Enter filename `euclid.tla`

(with full access path) and confirm the creation of the new specification.
An empty module `euclid`

has been created. Copy and paste
Euclid's algorithm below inside the module.

EXTENDS Naturals, TLC CONSTANT MAXINT (* Maximal integer *)In this algorithm:

(* PlusCal options (-termination) *)

(* --algorithm EuclidAlg { variables u \in 1..MAXINT; (* 1st integer *) v \in 1..MAXINT; (* 2nd integer *) { print <<u, v>>; while (u /= 0) { if (u < v) { u := v || v := u }; u := u - v } } } *)

`EXTENDS`

is used to import libraries (here, the natural numbers library and the TLC library).`CONSTANT`

introduces new symbolic names. Here`MAXINT`

is a parameter of the algorithm. Its value is unspecified.- The algorithm itself is placed inside a comment bloc
`(* ... *)`

. Its specification starts with`--algorithm`

followed by a name.

- Two variables
`u`

and`v`

are declared. The declaration`u \in 1..MAXINT`

defines the initial value of variable`u`

. It is non-deterministically chosen in the set`1..MAXINT`

. `print <<u, v>>;`

prints the value of the tuple`<<u, v>>`

- The statement
`u := v || v := u`

is a parallel assignement. It has the semantics of an assignement over vectors: (u v) := (v u).

Use menu File > Parse Module
to check that your algorithm is syntactically correct. Notice that some
errors may not be detected by this check. Then, add the following two
lignes between the closing comment `*)`

and the end of the
module:

\* BEGIN TRANSLATION \* END TRANSLATION

Convert the PlusCal algorithm into a TLA+ specification using menu File
> Translate PlusCal Algorithm. A TLA+ expression equivalent to
the PlusCal algorithm has been output in between the two lignes that have
just been added. The errors that are not detected during module parsing
are detected during the translation. When the PlusCal algorithm is
syntactically correct, the status bar at the bottom of the window is green
(otherwise, it is yellow or red, and error messages are displayed).

Add two new variables `u_init`

and `v_init`

which
are initialized to the values of `u`

and `v`

respectively. Then, add the following statements after the `while`

statement:

print <<u_init, v_init, "have gcd", v>>; assert v = gcd(u_init, v_init);

Define `gcd(x,y)`

between the closing comment `*)`

and `\* BEGIN TRANSLATION`

by copying and pasting the
following TLA+ specification:

`gcd(x,y) == CHOOSE i \in 1..x:`

/\ x % i = 0

/\ y % i = 0

/\ \A j \in 1..x: /\ x % j = 0

/\ y % j = 0

=> i >= j

- Translate the definition of
`gcd(x,y)`

in natural language - The algorithm is one of the two inputs required for verification. What is the other input? How is it specified in this example?
- Create a model using menu
`TLC Model Checker > New Model...`

or open an existing model using`TLC Model Checker > Open Model...`

In panel`Model Overview`

, choose a value for`MAXINT`

by double-clicking on`MAXINT <-`

.`Then click on the green arrow to launch model-checking. What is the result of model-checking?`

- What can you conclude on your algorithm?
- Determine, by successive experimentations, the maximal value of MAXINT for which model-checking can be achieved by TLC checker using reasonable time and space.

Consider the PlusCal algorithm below that performs a binary search of the
value `x` in the array `t`. The algorithm is purposely
incorrect. The goal is to understand the errors issued by the TLC
model-checker and to fix the algorithm using the error traces given by
TLC.

EXTENDS Naturals, TLC CONSTANT N (* Size of arrays *) CONSTANT MAXINT (* Max integer value *) (* PlusCal options (-termination) *) (* --algorithm Binsearch { variables t \in [ 1..N -> 0..MAXINT ]; (* Array of N integers in 0..MAXINT *) x \in 0..MAXINT; (* Value to find *) found = FALSE; l = 1; (* All elements to the left of l are < x *) r = N; (* All elements to the right of r are > x *) p = 1; (* Pivot *) (* Main *) { print <<t, x>>; while ((l <= r) /\ (~ found)) { p := (l + r) \div 2; if (t[p] = x) found := TRUE else if (t[p] < x) l := p-1 else (* t[p] > x *) r := p+1 }; assert( found <=> (\E j \in 1..N : t[j] = x) ) } } *) \* BEGIN TRANSLATION

\* END TRANSLATION

- What are the loop invariant and variant that must hold for the
correctness and termination of the algorithm above?

- Create a new module, copy and paste the algorithm above, then create a
new model and check the Termination property and the assertion for small
instances of the model (e.g.
`N<-2`and`MAXINT<-2`). Analyze the error trace provided by the TLA toolbox. Is it a finite or an infinite path? Is it a counter-example to the termination of the algorithm or to the assertion? Explain why the error trace violates the invariant and/or the variant of loop and fix the algorithm. - Check again the Termination property and the assertion. Analyse the new error trace: is it a finite path ot an infinite path? Is it a counter-example to the termination of the algorithm or to the assertion? Fix the algorithm and justify which part of the specification was violated.
- Check that the algorithm now terminates and that it is now correct.