Getting Started With TLA+

This post shows how to write your first simple TLA+ specification.

What is a specification?

In software, the behaviour of a system is described as a sequence of states. Mathematically, each state is expressed as a function F(t), which represents the state of a system at time t. To completely specify a system, we write out each state to fully define the systems behaviour.

A simple clock

This example comes from Chapter 2 of the book Specifying Systems by the creator of TLA+, Leslie Lamport. If you are unfamiliar with the math used here, refer to basic math for writing TLA+ article.

This example is a simple clock that shows only the hour of the day. How can we specify this behaviour using TLA+? More abstractly, what are the sequence of states that specify the behaviour of the clock? If the current hour is represented as the variable h, then the behaviour of the clock is to change this variable for each hour:

[h = 1] -> [h = 2] -> [h = 3] -> ...

To define this in TLA+ requires writing an initial predicate for the starting value of h, and a next-state relation describing how the hour changes at each step.

The initial starting point of the clock is somewhat irrelevant, and we can simply set it to any value between 1 and 12. The behaviour of the clock is to, at each step, increment its value by 1, except if the hour is 12, where we will reset the clock to 1 (assuming a 12 hour clock). To completely specify the clock, we would create a single formula combining the initial predicate with the next-state relation using a conjunction:

h ∈ {1, …, 12} ∧ [h = 1] -> [h = 2] -> [h = 3] -> …

Any system that we build that satisfies this formula satisfies our specification for the simple clock. This must be true for all starting steps, and for all possible points in time (all steps).

A simple clock in TLA+

We can express this simple algorithm using TLA+. TLA+ divides partitions into modules; the simple clock can be contained in a single module. Modules are specified using a header, which is a sequence of four or more - characters and the MODULE keyword. The following section begins a TLA+ module:

---- MODULE Clock ----

Arithmetic operators like + are not defined in TLA+. This allows you to write your own + operator that adds matrices or complex numbers, for example. Thankfully, TLA+ provides a standard library that implements some common arithmetic. We can add those libraries to our module using the EXTENDS keyword.

---- MODULE Clock ----
EXTENDS Naturals

Variables in TLA+ need to be defined before use via the VARIABLE keyword. The following section defines a variable h to represent the hour value of the clock:

---- MODULE Clock ----
EXTENDS Naturals

VARIABLE h

Now, to define our initial condition of the clock we need a function. Functions are defined using the == operator, which means is defined to be:

---- MODULE Clock ----
EXTENDS Naturals

VARIABLE h

HCinit == h \in (1 .. 12)

The ∈ operator is written as \in in TLA+, and the .. operator defining a sequence of integers is part of the Naturals library. The next-state relation is similarly written as previously defined:

---- MODULE Clock ----
EXTENDS Naturals

VARIABLE h

HCinit == h \in (1 .. 12)
HCnext == h’ = IF h /= 12 THEN h + 1 ELSE 1

The /= operator means not equal. IF, THEN, ELSE constructs take their usual definitions in programming. h’ represents the new value of h, i.e., the new state of the variable after the function completes.

Lastly, we express the clock itself as the conjunction of the initial state and the next state, for all values of h:

---- MODULE Clock ----
EXTENDS Naturals

VARIABLE h

HCinit == h \in (1 .. 12)
HCnext == h’ = IF h /= 12 THEN h + 1 ELSE 1

HC == HCinit /\ [][HCnext]_h

The only tricky part here is the [][HCnext]_h syntax, which says “this formula is true for all values of h”. To be more precise, the [] operator is the temporal logic operator, which asserts that the formula following the operator is always logically true. The _h allows the formula to make no changes to a state variable, allowing state transitions from [h == 1] -> [h == 1], for example. Or, put another way [][HCnext]_h == [](HCNext \/ (hr’ = hr)).

Finally, we can add a THEOREM to our module. Theorem’s are formulas that follow logically from the definitions in the module, any included library modules, and the rules of TLA+ (set theory and logic).

---- MODULE Clock ----
EXTENDS Naturals

VARIABLE h

HCinit == h \in (1 .. 12)
HCnext == h' = IF h /= 12 THEN h + 1 ELSE 1

HC == HCinit /\ [][HCnext]_h

THEOREM HC => []HCinit

The complete specification of the clock is the formula definition of HC, HCinit, HCnext, the operators .. and + from the Naturals module.

Checking our model with TLC and the TLA+ Toolbox

TLA+ comes with a set of tools for writing and verifying models. To start, download the latest TLA+ Toolbox release for your system from Github. Unzip the folder and you can run the precompiled Java application to start the toolbox. You should be presented with the following welcome screen:

The TLA+ Toolbox Welcome Screen

From here, create a new specification from the file menu. In the following example, I create a new root module and specification called SimpleClock.

Creating a new Specification

Clicking Finish will open up a blank module for you. You can copy in the specification above. The Toolbox is built on top of Eclipse and provides syntax parsing that marks the location of any parsing errors in your code. When you save your file, the box labelled ‘Parsed’ should remain green, showing that there are no syntax errors.

Now, we can create a model that verifies our specification does what it says it does. Models are created through the File -> TLC Model Checker window.

The model checker, TLC, is a program for finding errors in your specification. The model checker is run on a model of your specification, which tells the model checker what it should do. When creating a model you create a behaviour specification, which specifies the set of allowed behaviours of the system being specified. We also include explicitly what the model checker should check, and any initial values to substitute for parameters.

TLC works with formulas expressed as F == Init /\ [][Next]_var, which is an initial state combined with a next-state relation. The next-state relation can be built up from other formulas, but the entire specification should be reduced to such a formula for checking via TLC. Together, the initial state and the next-state are called the behaviour spec. TLC will check this behaviour spec.

Choosing the Behaviour Spec

You can now run the model checker to verify that our specification does not contain any errors. The model checker is especially useful for checking concurrent algorithms for liveness or deadlock errors.


In this article, we have explored how to write a simple specification, and how to create and run a simple model check. In future articles we will look more closely at how to use the TLC model checker to verify more complex specifications.

Like this post? Subscribe via RSS or email to never miss an update.