0% found this document useful (0 votes)
5 views

fsv slide

Uploaded by

maseattonima
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

fsv slide

Uploaded by

maseattonima
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 104

Formal Specification and Verification

Martin Kappes
Frankfurt University of Applied Sciences

September 15, 2023


Contents

1 Introduction 3
1.1 The Idea of Model Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Practical Examples for Model Checking . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Formalisms for Model Checking . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.1 System Specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.2 Requirements Specification . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.3 Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4 Outline of this course . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.5 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2 Installing and Running Spin 11


2.1 Minimal Installation Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2 Optional Tool iSpin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3 Simulating Promela Models with Spin . . . . . . . . . . . . . . . . . . . . . . . 12
2.4 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

3 Promela Language Basics 13


3.1 Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2 Promela in a Nutshell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.3 Lexical Conventions, Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.4 Data Types for Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.5 Control Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.6 Process Creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.7 Message Channels and Message Passing . . . . . . . . . . . . . . . . . . . . . . 21
3.8 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4 Simple Promela Model Tasks 25


4.1 Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4.2 Nondeterminism in a Single Process . . . . . . . . . . . . . . . . . . . . . . . . 25
4.3 Nondeterminism between Processes . . . . . . . . . . . . . . . . . . . . . . . . 26
4.4 Simple Channel Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.5 Further Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

5 Advanced Promela Model Tasks 31


5.1 Modeling Procedures and Recursion [14] . . . . . . . . . . . . . . . . . . . . . 31
5.2 Prisoner’s Dilemma (Ruth Schorr) . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.3 Elaaden Vault by Enrico Magnago . . . . . . . . . . . . . . . . . . . . . . . . . 32
II Contents

5.4 Semaphore by Rendezvous Channel (from [14]) . . . . . . . . . . . . . . . . . . 32


5.5 Sieve of Eratosthenes (from Spinlab) . . . . . . . . . . . . . . . . . . . . . . . . 32
5.6 SAT Problem (from Spinlab) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.7 Traveling Salesman from (Spinlab) . . . . . . . . . . . . . . . . . . . . . . . . . 33
5.8 Undecidable Problems: Dead Code . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.9 Dining Philosophers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

6 Spin 37
6.1 Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.2 Running Simulations in Spin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.3 Simulation Options for Spin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
6.4 Verifying a Model with Spin . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
6.5 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

7 Modeling Mutual Exclusion of Processes 43


7.1 Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
7.2 A Failed Attempt for Mutual Exclusion . . . . . . . . . . . . . . . . . . . . . . 46
7.3 Mutual Exclusion with Deadlock . . . . . . . . . . . . . . . . . . . . . . . . . . 48
7.4 A Probabilistic Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.5 Peterson’s Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.6 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

8 Transition Systems 59
8.1 Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
8.2 Modeling Concurrent Processes as Transition Systems . . . . . . . . . . . . . . 60
8.3 Traces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

9 Finite Automata 61
9.1 Mathematical Preliminaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
9.1.1 General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
9.1.2 Alphabets, Words, Languages . . . . . . . . . . . . . . . . . . . . . . . 62
9.2 Automata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
9.3 Closure Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
9.4 Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
9.5 Modeling Automata in Promela . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.6 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

10 Büchi Automata 77
10.1 Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
10.2 ω-Regular Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
10.3 Generalized Büchi-Automata . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
10.4 Safety Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
10.5 Liveness Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
10.6 Characterizing Safety and Liveness . . . . . . . . . . . . . . . . . . . . . . . . . 84
Contents III

10.7 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

11 Linear Temporal Logic 87


11.1 Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
11.2 Model Checking with Büchi Automata and LTL . . . . . . . . . . . . . . . . . . 90
11.3 Fairness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
11.4 Büchi-Automata and LTL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
11.5 Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

Bibliography 97
Reading Instructions
These are the lecture notes for the course “Formal Specification and Verification”. Please note
that these notes do neither cover the complete material presented in lectures and/or exercises nor
are meant for self-study. Moreover, this class is based on textbooks. These notes are comple-
mentary to studying the literature and do not replace it.
1 Introduction

Required Reading before Proceeding


• [1], pp. 1–16

1.1 The Idea of Model Checking


The reliability of software and hardware is a required feature for software and hardware systems,
particularly for high integrity systems. With the ever-increasing complexity and size of software
systems, methods to improve the reliability of such systems have been in the focus of researchers
and practitioners in Computer Science for decades.
Unsurprisingly, Computer Scientists strive to find automated solutions which, given a software
and a formalization of the desired properties of the software, automatically check whether the
software meets the formalized properties or not, i.e. whether the software is correct or not. In
other words, they aim for an algorithm which performs these checks. Ideally, given a software
and its required features, the algorithm would either verifiy the correctness of the software or
show that the software does not meet requirements and what needs to be fixed.
Unfortunately, already in 1936, Alan Turing showed mathematically that there are problems
which cannot be solved algorithmically using his formalization of software called Turing-Machine,
and Rice’s Theorem in fact established that any non-trivial semantic properties of a program is
undecidable, i.e., it cannot be algorithmically determined. This also implies that

• no algorithm exists which can check two programs for equivalence and

• no algorithm exists to check whether a given program has any nontrivial property stated in
any form of specification.

Thus, the correctness of programs can, in general, not be algorithmically determined. Cor-
rectness of programs is of course one building block for establishing the reliability of software,
however, there is also no algorithm to compute, either precisely or approximately, the reliability
of an arbitrary software system, even if the reliabilities of the components in that system or the
reliabilities of the operations in the components are known [7].
While all nontrivial properties of software as represented by Turing-Machines, i.e., automata
with an infinite tape, are undecidable, it is well known that many relevant properties for the much
simpler class of Finite Automata can be determined by algorithms even with polynomial runtime.
Finite Automata are basically Turing Machines without a tape which can only process their input
in one direction. Thus, if it is possible to abstract relevant aspects of software into a finite state
model, many interesting properties of the model can be studied and determined algorithmically.
4 1 Introduction

Figure 1.1: Model Checking Workflow, depiction from [1].

Moreover, there are formalisms which allow to specify requirements for finite automata in a
manner such that these requirements can be algorithmically checked for a finite state model, in
particluar certain types of logic. It should be noted that these logics are not very expressive in
the sense that quite a few interesting properties for finite automata cannot be formulated within
such logic formalism. So, only certain properties can be checked. However, analogously to
Turing Machines, for more expressive logic formalisms nontrivial properties cannot be checked
algorithmically either. This is known as Gödel’s Incompleteness Theorem.
It has turned out that, while there are quite a few pitfalls an fallacies, using algorithmic meth-
ods based on simple formalisms can be still be quite useful in improving the correctness and
reliablilty of software (and especially also hardware). This is particularly the case for software
for which meaningful aspects can be abstracted into a finite automaton such as, e.g, communi-
cation protocols between multiple processes and other software which is not data-centric. Also,
relevant requirements for such systems can be formulated in simple logical formalisms and thus
automatically checked.
This overall process is called model checking. “Model checking is an automated technique
that, given a finite-state model of a system and a formal property, systematically checks whether
this property holds for (a given state in) that model” [1].
The overall workflow of model checking is shown in Figure 1.1: The system under consid-
eration is modeled in a formalism through which a system model is obtained. The model is an
abstraction from the actual system and includes the relevant aspects which are to be checked.
Also, the requirements for the system are specified in another formalism. Both the system ab-
straction and the properties are described in formalisms which then allow for automated model
checking of the properties against the system description. The model checking may have as out-
come that the properties hold in the model, i.e. the desired properties are satisfied. Also, it is
possible that model checking finds that the model violates the properties. In this case, a counter
1.2 Practical Examples for Model Checking 5

example is produced in which can be further examined through simulations of the system such
that the error can be found. However, there is a third possible outcome. Model checking essen-
tially works by exploring all possible outcomes of the model by an exhaustive search. If, during
this search, a counterexample is produced, the process will stop. However, the correctness of the
model is established by not finding any counterexample in any possible execution of the model.
In general, exhaustive search leads to exponential increases in runtime and memory use, so the
run of the model checker may yield an inconclusive result. In this case, the model needs to be
adapted.
As model checking checks any possible execution, it is not “biased towards the most probable
scenarios”, but will check any scenario. Hence, errors in very unlikely scenarios will also get
caught if a conclusive result is obtained. Clearly, one might also ask the question whether it
would not be better to focus on the very likely scenarios if an exhaustive check of the model is
impossible.
In summary, model checking has the following advantages:
• It is based on a formal foundation and the applied techniques are mathematically proven
to work.
• It allows for a partially automated verification which can be implemented in a tool.
• In case of property violations, it provides counterexamples which can be used to debug the
system model.
• It has relevant applications (protocols, hardware, control software).
However, there are quite a few disadvantages as well:
• The used formalisms have a very limited expressiveness and can only model certain as-
pects.
• The accuracy of the results depends on the quality of the used model and the formally
specified requirements which both may not be correct for the actual system under consid-
eration.
• Even for the limited formalisms, an automatic verification may fail due to exponential use
of time and space.

1.2 Practical Examples for Model Checking


Practical examples where model checking has been successfully applied can be fond in the liter-
ature.
Model Checking is a technology that is often applied in additon with other techniques to im-
prove software correctness, particularly for safety critical applications. Apart from its automation
aspects, Computer Scientists working on ensuring the correctness and reliability of software of-
ten can apply the formal foundations of model checking for their work. In particularly, is is
indispensable to be able to model a system in a meaningful way and to formally state proper-
ties of the sysem under consideration not only when applying model checking, but also when
examining software systems with other technologies.
6 1 Introduction

1.3 Formalisms for Model Checking


As outlined above, model checking pertains to formally specifying a system model and then to
automatically check it against a requirements specification. In the following, we will briefly
present which formalisms are typically used.

1.3.1 System Specification


As mentioned before, the system which is actually to be checked needs to be modeled in a for-
malism which allows for some form of automated checking. In practice, all system models which
are considered are variants of finite automata. Finite automata are one of the most fundamental
and basic structures in Theoretical Computer Science. The variants considered in Model Check-
ing are Program Graphs, Transition Systems and finite automata over infinite words, so-called
Büchi Automata. We will discuss these structures in more detail later. The essence however is
that all of these system models carry all information and data held in the system at a particular
time in one out of finitely many states of the structure, i.e., there is no additonal memory. Thus,
if a program is modeled, all information about the program at a given point in time, i.e., which
instruction is currently executed, all data held in variables and any other information, is repre-
sented through the state. Again, this is a severe limitation. It also only allows for certain type of
variables to be modeled, and all variables need to have a finite domain.
In practice, we will specify our system models in a language called Promela. This is a model-
ing language with stringent restrictions to keep these requirements. Among them are no function
calls, only variables with finite domains, and a limited number of processes.

1.3.2 Requirements Specification


For formalizing requirements, similar restricted mechanisms need to be used. In most cases,
logics are used which are limited in their expressiveness. Here, we will consider linear temporal
logic (LTL). Other formalisms such as, e.g., Computation Tree Logic also exist. The properties
specified in LTL can also be specified using Büchi-Automata. Some desirable properties can also
be formulated as finite automata, i.e. regular languages.

1.3.3 Checking
Thus, requirements R and system model M are specified as finite automata of sorts. Since
finite automata are closed under complementation and intersection and the constructions can
be done in an automated way, it is possible to check algorithmically whether the intersection
of the behavior of the model T (M) with the complement of the requirements T (R) is empty
or not, T (M) ∩ T (R) = 0.
/ If so, the model meets the requirements, if not, a counterexample
w ∈ T (M) ∩ T (R) is given - at least if the computational demands of the model and the require-
ments allow for it. The reason that the process may fail is that the system model can become
quite large (“state explosion”), and the negation of the requirements under consideration may
also lead to an exponential increase. Thus, model checking, even with such limited formalisms,
may fail.
1.4 Outline of this course 7

1.4 Outline of this course


The aims of this couse are:

• Understanding the principles of formal specification and verification.

• Understanding the theory (models and logics) used in model checking.

• Reasoning about safety, liveness and fairness properties in concurrent systems.

• Specifying safety and liveness properties of concurrent systems using temporal logic and/or
computational tree logic.

• Verifying that a concurrent system satisfies certain safety and liveness properties using
model checking algorithms.

• Obtaining practical skills in using a Model Checking Tool .

• Understanding the limitations of model checking.

1.5 Tasks
Task 1.1:
Describe the process of model checking.

Task 1.2:
Explain advantages and disadvantages of model checking.

Appendix: A Simple Proof for Rice’s Theorem


Definition 1.1 (Halting Problem) The halting problem is defined as follows:
Input: A program P and an input w for the program.
Output: "yes", if P terminates on input w, "no" otherwise.

Theorem 1.2 There is no algorithm solving the halting problem, i.e. the halting problem is
undecidable

Proof. Suppose, for the sake of contradiction, there was an algorithm HALT() solving the halting
problem:

typedef char* Program;


typedef char* Input;

bool HALT(Program P, Input w){


8 1 Introduction

bool result;
// we have no idea of halt’s inner workings but assume
// it will stop and output ’yes’ iff P halts on w and
// no otherwise.
// (...)
//
//
return result; // 0 == no, 1 == yes.
}

We construct a program absurd() as follows:

bool absurd(Program P){


bool a;
a = HALT(P,P);
if (a){ // If HALT(P,P) = yes, then
for (;;) {;} // (*) infinite loop
}
else{ // If HALT(P,P)= no, then
return 0; // (**) absurd halts.
};
}

absurd() takes a program P as input and calls HALT(P,P). Therefore, HALT() computes
whether program P terminates when called with itself as input. If P terminates with itself as
input, then absurd() will get stuck in an infinite loop and will not terminate, if P does not
terminate with itself as input, then absurd() will terminate. Thus, absurd() always does the
opposite of P(P), we have

does not terminate if P terminates on P,
absurd(P) =
terminates fif P does not terminate on P.

Consider calling absurd() with itself as input. There are two possibilities. Either absurd()
terminates with itself as input or not.
Suppose absurd(absurd) terminates. We have HALT(absurd,absurd)=yes. In this case
absurd() will execute (*) and get stuck in an infinite loop and thus not terminate. On the
other hand, if absurd(absurd) does not terminate, we obtain HALT(absurd,absurd)=no and
absurd() will execute (**) and terminate. In summary, we have

does not terminate if absurd(absurd) does terminate,
absurd(absurd) =
terminates if absurd(absurd) does not terminate,

This is a contradiction. We conclude our assumption was wrong and that there is no algorithm
HALT(). □
1.5 Tasks 9

Theorem 1.3 (Rice’s Theorem for Recursive Sets) Let M be a program with output “yes” or
“no” when terminating and denote by T (M) the set of all inputs for which the program outputs
“yes”. Any nontrivial property ot T (M) is undecidable.

Proof. We prove that we could decide the Halting Problem if there was an an algorithm to decide
a nontrivial property.
Suppose there was a nontrivial property (i.e. a property which is not fulfilled or fulfilled for
any program) prop for which there was an algorithm which takes as input a program P and
outputs “yes” if P fulfills prop and “no” otherwise.:

typedef char* Program;

bool Prop(Program P){


bool result;
// we have no idea of Prop’s inner workings but assume
// it will stop and output ’yes’ iff P fulfills prop and
// no otherwise.
// (...)
//
//
return result; // 0 == no, 1 == yes.
}

Since the property is nontrivial, there is at least one program Q such that T (Q) fulfills the
property. Without loss of generality we also assume that 0/ (a program which never outputs “yes”
for any input) does not fulfil prop (otherwise we consider the complement of prop). For any
given program P and input w we construct the following program:

bool Q2(input x){


bool result;
P(w);
result=Q(x);
return result;
}

Clearly, we have 
T (Q) if P terminates on w,
T(Q2) =
0/ if P does not terminate on w.
Thus, 
1 if P terminates on w,
Prop(Q2) =
0 if P does not terminate on w.
Thus, we can construct an algorithm solving the halting problem as follows:

typedef char* Program;


typedef char* Input;
10 1 Introduction

bool HALT(Program P, Input w){


bool result;
Program Q2=construct(P,w) // constructs Q2 as specified above
return Prop(Q2);
}

This is a contradiction. We conclude our assumption was wrong and that there is no algorithm
deciding the property. □

Thus, is is clear that we cannot algorithmically verify general programs and must restrict
ourselves to much simpler finite automata models.
2 Installing and Running Spin

2.1 Minimal Installation Instructions


In this course, we will use the open-source software verification tool Spin for practical exercises.
Therefore, you need to install Spin on your computer. Detailed instructions, including the instal-
lation of additional tools, can be found at https://spinroot.com/spin/Man/README.html.
Here, we will present the essentials.
We assume you install Spin on a Linux-Machine. Here, we will outline an installation pro-
cedure which has been tested under Ubuntu 22.04. However, any other Linux-Distribution can
be used as well. In case you are using Windows, it is recommended to install Spin on a Virtual
Linux Machine on your system.
In general, processing power and memory are essential for model checking. However, for our
purposes, an installation in a virtual machine with moderate resources should be sufficient.
For running Spin, the build-tools and yacc must be installed on your system, installing git is
also required for the below instructions but may also be omitted if you choose to install Spin
differently.
sudo apt install build-essential
sudo apt install yacc
suto apt install git
The most recent Spin distribution can be found at https://github.com/nimble-code/
Spin. In order to clone the git-repository, use the command
git clone https://github.com/nimble-code/Spin.git
The code is in the subdirectory Spin of the current directory (we assume it is in /home/labor/Spin.
In this directory, call make to compile Spin. The resulting executable can be found at
/home/labor/Spin/Src/spin.
Feel free to adjust your path to execute this binary, create an alias or put it somewhere into
your path for simple execution. In order to avoid any configuration of optional tools, it can, e.g.,
be placed in /usr/bin. In the following, we will simply refer to spin as command for executing
it. Test Spin by checking which version you just installed.
spin -V
Spin Version 6.5.2 -- 9 June 2022

2.2 Optional Tool iSpin


iSpin is an IDE for Spin with a GUI. We will not pursue the use of iSpin in this course and
only use spin. However, in case you want to use iSpin, it can also easily be used as it is already
12 2 Installing and Running Spin

included in the spin-distribution.


iSpin requires tck, tk and the graphviz-package:

sudo apt install tcl tk


sudo apt install graphviz

To run iSpin, execute the file Spin/optional gui/ispin.tcl. More detailed instructions
and a Getting Started guide can be found at https://spinroot.com/spin/Man/3_SpinGUI.
html.

2.3 Simulating Promela Models with Spin


Spin is a tool for simulating and analyzing models specified in a modeling language called
Promela which we will outline in the next chapters. For a Promela model, Spin can perform
random, interactive or guided simulations of the model. It also can be used for analysis and
verificationWe will outline some more details on Spin, particularly the verification features, in
Chapter 6.
Promela models contain nondeterminism both in form of nondeterministic instructions as well
as due to concurrency and parallelism between processes. Spin can perform a simulation of
the Promela model, i.e. an execution where one out of the possible nondterministic choices is
selected at any time nondeterminism occurs.
In order to randomly simulate a Promela model given in filename.pml (.pml is the usual
file extension for Promela), the command spin filename.pml can be used. Spin will then
randomly select which choice is made in case of nondeterminism. It is also possible to have the
user interactively select what to do in every such situatioon by running Spin in interactive mode,
spin -i filename.pml. Then, the user will be prompted with all available options.

2.4 Tasks
Task 2.1:
Install Spin on a Machine and run it.

Task 2.2:
Install the required packages to run iSpin on a Machine and start it.

Task 2.3:
What are advantages and disadvantages of installing Spin in a Virtual Machine as opposed to
directly on a system?
3 Promela Language Basics

Required Reading before Proceeding


• [11]

• [4]

• [12]

3.1 Fundamentals
In this course, we will use the modeling language Promela (PROcess MEta LAnguage) [11] in
conjunction with Spin, a tool for randomly or interactively simulating and analyzing systems, in
particular concurrent systems. Spin uses three types of objects: processes, variables and message
channels. It also allows for the checking of the defined models using assertions, logical formula
and so-called never claims. We will deal with these features in a later chapter. Here, we focus on
the basic language constructs and features.
Promela is intended for modeling a system with a finite number of processes (256 max). A
run of a Promela model does not require any input. The processes may run synchronous or
asynchronous and may communicate via channels or (shared) global variables. As processes run
interleaved in any arbitrary possible order, the system may be nondeterministic, i.e. two different
runs of the system may yield different results. Also, Promela allows for nondeterminism within
a single process. Its semantics are intended for using the model for verification through Model
Checking.
Promela is quite restricted in the sense that it does not have any libraries, pointers, ability to
define functions and floating-point variables. All structures are finite and bound.

3.2 Promela in a Nutshell


Promela’s core feature as compared to normal programming languages is nondeterminism which,
in other languages, mostly occurs unintended due to the use of multi-threaded processes or con-
current processes. Thus, nondeterminism is an important feature to verify and check concurrent
systems.
Nondeterminism in Promela may be introduced by concurrency between processes as the next
statement to be executed is randomly chosen from all active processes unless special provisions
are taken (i.e. atomicity). For example,
14 3 Promela Language Basics

1 int shared = 0
2

3 active proctype A() {


4 shared = 1
5 printf("A:␣%d\n", shared)
6 }
7

8 active proctype B() {


9 shared = 2
10 printf("B:␣%d\n", shared)
11 }

may be executed in the following order (line numbers of statements):


4 5 9 10
4 9 5 10
4 9 10 5
9 10 4 5
9 4 10 5
9 4 5 10
Clearly, the value finally stored in shared is also nondeterministic, potentially leading to prob-
lems or the incorrectness of the code.
Another source of nondeterminism are nondeterministic instructions within a process. As an
example, when running this promela model,
1 int myvar = 5;
2 int assigned = 0;
3

4 init {
5

6 if
7 :: (myvar < 10) -> assigned = 1
8 :: (myvar < 20) -> assigned = 2
9 :: (myvar == 10) -> assigned = 3
10 :: true -> break
11 fi
12 }

the value of assigned may be 1, 2, 3 or even 0. We will explain details later.


Another very distincive feature of Promela is that a statement can only run if it is executable.
Some statements may always be executable, e.g., an assignment like a=1. However, a logical
expression like a==1 is only executable if it is true. If a process encounters the expression a==1
and the value of a is 0, it will block until the value of a changes to 1 which may only happen by
the workings of another process.
3.3 Lexical Conventions, Syntax 15

3.3 Lexical Conventions, Syntax


The lexical conventions of Promela can be found in [4].Promela has five classes of tokens: iden-
tifiers (names), keywords, constants, operators and statement separators. Blanks, tabs, newlines,
formfeeds and comments serve only to separate tokens.
Similar to c, comments either start with /* and end with */ or are the suffix of a single line
after //.
Identifiers (names) in Promela start with a single letter (uppercase or lowercase) or underscore
followed by zero or more letters or numbers. The following names are used for keywords and
may not be used as identifiers:

active assert atomic bit


boot break byte chan
d step D proctype do else
empty enabled fi full
goto hidden if init
int len mtype nempty
never nfull od of
pc value printf priority proctype
provided run short skip
timeout typedef unless unsigned
xr xs
Constants in Promela are defined as for the c-preprocessor. For instance,
#define N 5
sets the constant N to 5.
Another possibility is the use of mtype which allows to assign symbolic names of numeric
constants which might be helpful in simulations. Variables of type mtype may carry these sym-
bolic names which might be directly used in the Promela code. The constants range from 1 to
255, thus uninitialized variables are not set (value 0). The use of subtypes is also possible from
Spin version 6.4.8 on. Further details can be found in [12]. Listing 3.1 presents an example also
containing subtypes from [12].
Listing 3.1: Example for mtype from [12]
1 // requires Spin Version 6.4.8 or later
2 mtype { one, two, three }
3 mtype:fruit = { appel, pear, banana }
4 mtype:sizes = { small, medium, large }
5 chan q = [0] of { mtype, mtype:fruit, mtype:sizes, int }
6 proctype recipient(mtype:fruit z; mtype y)
7 { mtype a
8 mtype:fruit b
9 mtype:sizes c
16 3 Promela Language Basics

10 atomic {
11 printf("z:␣"); printm(z); printf("\n");
12 printf("y:␣"); printm(y); printf("\n");
13 }
14 q?a,b,c,_
15 atomic {
16 printm(a) printm(b) printm(c) printf("\n")
17 }
18 q?c,a,b,_ // flagged as type error
19 atomic {
20 printm(a) printm(b) printm(c) printf("\n")
21 }
22 }
23

24 init
25 { mtype numbers, nn;
26 mtype:fruit snack, ss;
27 mtype:sizes package, pp;
28 run recipient(pear, two)
29 //run recipient(small, two) // type error
30 //package = pear // type error
31 numbers = one
32 snack = pear
33 package = large
34 printm(numbers)
35 printm(snack)
36 printm(package)
37 printf("\n")
38 q!numbers,snack,large,9
39 //q!large,ss,pp,3 // type error
40 }

Table 3.1 shows the operators and precedence rules from the Promela Reference Pages [12].

3.4 Data Types for Variables

Promela features seven integer-type variables:


3.4 Data Types for Variables 17

Operators Associativity Comment


() [] . left to right parentheses, array brackets (highest precedence)
! ∼ ++ - - right to left negation, complement, increment, decrement
* / % left to right multiplication, division, modulo
+ - left to right addition, subtraction
« » left to right left and right shift
< <= > >= left to right relational operators
== != left to right equal, unequal
& left to right bitwise and
ˆ left to right bitwise exclusive or
| left to right bitwise or
&& left to right logical and
|| left to right logical or
-> : right to left conditional expression operators
= right to left assignment (lowest precedence)

Table 3.1: Operators and Precedence in Promela from [12]

Type Size (in bit) Domain


bit, bool 1 0,1
byte 8 0,1,. . .,255
short 16 −215 − 1,. . .,215 − 1
int 32 −231 − 1,. . .,231 − 1
unsigned i 0, . . .,2i−1
pid used for Process IDs

Variables need to be declared and are strictly typed. They may be global or local to a process
depending on where they are declared (globally or in the process). The declaration of (one-
dimensional) arrays is possible. User-defined data types can be created with typedef. Listing
3.2 shows examples of the declaration and the use of variables.
Listing 3.2: Examples for Variable Declarations
1 #define N 5 // definition of a constant as preprocessor option
2 // declaration of global variables:
3 unsigned h : 4 // declaration of an unsigned with 4 bit
4 // initial value 0 if not specified
5 unsigned i : 5 = 8 // unsigned with 5 bit, initial value 8
6 byte z[N] // declaration of array of N bytes
7 // indices from 0 to N-1
8

9 mtype = { ack, nak, err, next, accept } // mtype


18 3 Promela Language Basics

10 mtype a // declaration of mtype variable


11 mtype p[4] = nak // another mtype, all fields initialized with nak
12

13 typedef CORD{ // definition of type CORD


14 byte x;
15 byte y
16 }
17 CORD h[4] // declaration of array of 4 CORD-types
18 proctype myprocess {
19 // declaration of local variables
20 short d = 7 // declaration of a short with initial value 7
21 }

The syntax of Promela is c-like. A complete grammar specification can be found in [10].
Statements in Promela may either be executable or not. The statement a==b is only executable
if a == b, otherwise execution blocks until it holds. Thus, executablilty of statements is one of
the main means for synchronization.

3.5 Control Flow


We will now discuss the basic control flow in Promela. Contatenated statements in Promela will
be executed sequentially. However, if multiple processes are running, processes may run arbitrar-
ily interleaved. In case statements of a process must happen uninterrupted, Prefixing a sequence
of statements with the keyword atomic indicates that the following statements enclosed in curly
braces must be executed without interruption and uninterleaved with other processes. However,
if a process blocks, the atomicity is lost and may only be regained once the blocking statement
becomes executable. Then, the atomicity will be gained again once the process resumes exe-
cution which may however not happen intermediately after the blocking finishes. Consider the
example in Listing 3.3. Processes A and B will always terminate and stateA and stateB will
be one, even if Process B is executed first.

Listing 3.3: Examples Atomicity


1 byte turn = 1;
2 byte stateA = 0;
3 byte stateB = 0;
4

5 proctype A()
6 { atomic {turn == 1;
7 turn = 0; // Necessary for B to not block on turn==0
8 stateA == 1; // B must first execute stateA=1
9 stateB = 1;
10 }
11 }
3.5 Control Flow 19

12

13 proctype B()
14 { atomic {turn == 0; // If B is executed first, it will block here
15 stateB == 0; // A must first execute stateB=1
16 stateA = 1;
17 }
18 }
19 init
20 { atomic{run A();run B()};
21 }

Promela also features case selection, repetition and uncondituonal jumps. A case selection is
enclosed by the keywords if and fi.

if
:: (a != b) -> option1
:: (a == b) -> option2
fi

Moreover, each possible selection starts with ::, followed by a guard statement, -> and a se-
quence of statements (named option1 and option 2 in the example) which can get executed if the
guard statement is true. Please note that the guard statements may not me mutually exclusive.
In this case, the execution of the case selection is nondeterministc and any options for which the
guard-statement is true may get selected. If none of the guards of the possible selections is true,
the statement will block until one or more become available. It is also possible to use else as
guard. The option following else is executed if all other guards are false.
Note that using -> above is optional, the statement separator ; may also be used and is seman-
tically identical. The use of -> soley may simplify reading the code. Moreover, guard statements
need not be followed by any options.
Repetition is an extension to case selection and enclosed by the keywords do and od. The
syntax of the repetition structure is more or less identical to the selection structure. The repetition
may be ended by the break statement. The following shows a conter that is nondeterministically
increased or decreased. If its value is 3, the repetition may be stopped or the counter may be
increased or decreased. do will also block if none of the guards is true.

do
:: counter++
:: counter--
:: (counter == 3) -> break
od

Unconditional jumps can be facilitated by defining a label. The label is defined and placed in
the code with a colon and may be the target of a jump sttement. Labels must be unique and may
be used only within the same process. Label are not allowed in front of guards. The following
code shows a process fragment where counter is increased from 0 in increments of 1 to 10.
20 3 Promela Language Basics

counter = 0
label1:
if
:: counter < 10 -> counter ++; goto label1
:: else -> skip
fi

Promela also features a select-statement which non-deterministically assigns a value out of


a given value range to a variable. The statement

byte cc
select(cc: 5 .. 22)

will assign cc a value between 5 and 22. The boundaries may also be given by expressions.

3.6 Process Creation


Processes can be declared using the proctype keyword. They will initialized when running the
model if the active keyword is used. Processes may also be started in other processes using
run. With run, basic data types can be passed as parameters to processes. Multiple instances of
a single proctype-declaration may be instantiated. The process specified as init will always be
executed. Active processes and init should not have parameters, if they do they will default to 0.
A system specified in Promela can be simulated randomly or interactively by spin. However,
the main feature of spin is the possibility to conduct an exhaustive verification of the system
state space and can check it against user-specified system invariants. Some examples are given
in Listing 3.4.

Listing 3.4: Examples for Process Declarations


1 proctype A()
2 {
3 skip
4 }
5

6 active proctype B()


7 {
8 skip
9 }
10

11 proctype C(byte state; short someval)


12 {
13 skip
14 }
15

16 init
3.7 Message Channels and Message Passing 21

17 {
18 run A()
19 run C(2,55)
20 }

Processes run concurrently, so the order of execution may be nondeterministic and a process
may not immediately start after creation.
Each process carries a specific pid which is stored in the predefined global variable pid.
The number of active processes is stored in nr pr. At most 255 processes can be running
simultaneously. Another useful predefined variable particularly for verification is lastand
holds the instantiation number of the process that performed the last step in the current execution
sequence.

3.7 Message Channels and Message Passing


The transfer of data between processes may occur through global variables. An alternative and
much better means of passing data are message channels. They might be declared globally or
locally. The statement

chan mychannel = [8] of { byte }

declares a channel which may hold up to 8 messages of type byte. The names of channels may
be passed as parameters in the process instantiaton or through channels as well.
Messages in a channel may consist of more than a single field and elements of different types.

chan mysecondchannel = [16] of { byte, short, chan }

declares a channel which may hold up to 16 messages each of which contains a byte, a short and
a channel.
The statement mychannel!expr sends the value of expression expr to mychannel. Receiving
a message from the channel can be facilitated via mychannel?myvar and stores the value in
myvar. Also, the message is deleted from the channel. Reading without deletion is possible with
mychannel?<myvar>. Channels operate first-in-first-out. Statements to read from or write to a
channel which is empty or full respectively are blocking until one message is written to or read
from the channel. Writing to and reading from channels with more than a single field is done via
a comma-separated list, e.g., mysecondchannel!expr1,expr2,expr3.

Listing 3.5: Channel Example from [11]


1 proctype A(chan q1)
2 {chan q2;
3 q1?q2;
4 q2!123
5 }
6

7 proctype B(chan qforb)


22 3 Promela Language Basics

8 {int x;
9 qforb?x;
10 printf("x␣=␣%d\n", x)
11 }
12

13 init {
14 chan qname = [1] of { chan };
15 chan qforb = [1] of { int };
16 run A(qname);
17 run B(qforb);
18 qname!qforb
19 }

Listing 3.6 presents an example from [11] which shows the passing of channel names. The
value printed will be 123.
For every channel, the predefined function len(mychannel) gives the number of messages
stored in the channel. This function may also be used as statement in which case it blocks if the
number of messages is zero.
Also, there are the functions full(mychannel), nfull(mychannel), empty(mychannel)
and nempty(mychannel) which return true or false and can be seen as special cases of len.
Channels of size 0 are so-called rendez-vous channels as communication is synchronous (send-
ing process blocks until message is read by a process and vice-versa).
Also, it is possible on the receiving side to use a constant as parameter when receiving a mes-
sage. In this case, the message will only be read if the constant matches the value in the message.
Similarly, eval(var) will only retrieve the message in the channel if the value of var matches
the respective message field. Functionally equivalent to mysecondchannel?eval(arg1),arg2
is the command mysecondchannel?arg1(arg2).
Furthermore, mysecondchannel?? arguments will retrieve (and delete) the first message
in the channel that matches constants specified in the arguments. For example, mysecondchannel??
1, ... will retrieve the first message where the first argument is 1. The non-deleting variant
mysecondchannel?? <1, ...> also exists.
Writing to a channel may also be done via mychannel!!expr. In this case, the message will
be lexicographically sorted into the channel, i.e. no first in. first out.
A simple example for the use of a channel is given in Listing 3.6.

Listing 3.6: Another Channel Example


1 proctype A (byte num; chan channel)
2 { byte ignored
3 byte what
4 do
5 :: channel?ignored,what -> printf("Process␣%d␣answers␣%d␣\n",num,what)
6 od
7

8 }
3.8 Tasks 23

10 init { byte where


11 chan channel = [8] of {byte,byte}
12 run A(1,channel);
13 run A(2,channel);
14 run A(3,channel);
15 do
16 :: select (where: 1..3); channel!where,where;
17 od
18 }

Three processes are created which randomly take messages out of the channel. If line 5 is
changed from channel?ignored,what to channel?eval(num),what, processes will only
take messages with their value of num in the first position. Consequently, changing the select
(where 1..3) statement in line 16 to select (where:1..4) will eventually lead to a timeout
as no messages with value 4 are being processed.

3.8 Tasks
Task 3.1:
Use len to implement the functions full, nfull, empty and nempty

Task 3.2:
Promela also features the expression channel?[variable]. Find out what this expression is
doing and give an example how it might be used.

Task 3.3:
In Listing 3.1, the variable is used. Explain what this variable is doing and where it is defined.

Task 3.4:
In the Promela Manual, it is stated that

mtype = { ack, nak, err, next, accept }

is functionally equivalent to

#define ack 5
#define nak 4
#define err 3
#define next 2
#define accept 1
24 3 Promela Language Basics

Explain why mtype is useful and what its advantages are.

Task 3.5:
Consider the following Promela code snippet:

#define LOW 0
#define HIGH 15
byte range = LOW;
do
:: range < HIGH -> range++
:: break
od

Assuming that the probability of choosing a guard which is true is uniformly distributed, what is
the probability of generating value i?
Does this behavour matter in simulations and verification or not?
4 Simple Promela Model Tasks
In this chapter, we will present some simple examples for models in promela by different authors
in order to also show various programming styles. They are formulated as task for the reader to
program themselves.

4.1 Hello World


Task 4.1:
Write a “hello world”-model in Promela and simulate it with Spin.

Task 4.2:
Write a revisited hello world program which starts another process that adds “revisited” behind
hello world.

4.2 Nondeterminism in a Single Process


Promela and Spin are intended for studying concurrent distributed systems in which nondeter-
ministic behavior occurs due to race conditions. As Promela models do not have any input, the
outcome of such a model for a single process is always identical unless nondeterminism is used,
either explicitly or implicitly.

Task 4.3:
Consider the following Promela code fragment;
1 active proctype P(){
2 int value;
3 do
4 /* code to be added here */
5 printf("value␣is:␣%d\n", value)
6 od
7 }

1. Add code such that value is set to either 0, 1 or 2 using the select-statement. Simulate
your model with Spin using random mode and interactive mode.
26 4 Simple Promela Model Tasks

2. Add code such that value is set to either 0, 1 or 2 using an if-construction.


3. Add code such that value is set to either 0, 1 or 2 using an repetitive do-construction.

Task 4.4:
Consider the following Promela code fragment:
1 #define N 10
2 active proctype P() {
3 int value[N];
4 int product = 1;
5

6 /* to be added */
7

8 }

1. Add code such that all elements of the array are initialized with the values 1 or 2.
2. Add code to calculate the product of all elements of the array and print it out.
3. Simulate your model with Spin in random and interactive mode and present example runs.
4. Determine and prove which values product can have. Valitate your assumptions by using
Spin in interactive mode.
5. Assuming an equal probability for all values to be 1 or 2, give a formula for the likelihood
of value to be x.

Task 4.5:
Write a Promela model which prints the first 20 natural numbers in random order. “Random” is
synonymous to any permutation of the numbers in the output is possible, likeliness disregarded.

4.3 Nondeterminism between Processes


Task 4.6:
Consider the following Promela model:
1 #define N 2
2 proctype P(){
3 int counter = 0
4 do
5 :: counter<N -> printf("P␣"); counter++
4.3 Nondeterminism between Processes 27

6 :: else -> break


7 od
8 }
9

10 proctype Q(){
11 int counter = 0
12 do
13 :: counter<N -> printf("Q␣"); counter++
14 :: else -> break
15 od
16 }
17

18 init {
19 atomic{run P();
20 run Q();}
21 }

1. Run the model in random and interactive mode. How many interleaving possibilities does
the program have and which?
2. How many possibilities are there for arbitrary values of N?

Task 4.7:
Consider the following Promela model:
1 int x = 8;
2 int y = 6;
3 int z = 0;
4

5 active proctype P() {


6 if
7 :: x < y -> z = 100
8 :: else -> z = 200
9 fi
10 printf("%d",z)
11 }
12

13 active proctype Q() {


14 x=1
15 }
16

17 active proctype R() {


18 z=300
19 }
28 4 Simple Promela Model Tasks

1. How many interleaving possibilities does this model have?

4.4 Simple Channel Examples


Task 4.8:
Consider the following Promela code:
1 #define N 10
2 #define M 0
3 chan ourchannel = [M] of { int }
4 active proctype P() {
5 /* code to be added */
6 }
7

8 active proctype Q() {


9 /* code to be added */
10 }

1. Complete the code such that process P writes all natural numbers up to N in ascending
order into the channel while process Q reads the numbers and prints them out. Both pro-
cesses shall terminate once the number N is sent/received.

2. How many interleaving possibilities exist?

3. Change M to 10 and run simulations of the model. Which changes can be observed?

4. How many interleaving possibilities exist for M = 10?

4.5 Further Tasks


Task 4.9:

1. Name all possible values for myvalue after executing the following Promela code:

byte myvalue=50
if
:: myvalue = 100
:: myvalue = 200
fi
4.5 Further Tasks 29

2. Name all possible values for myvalue after executing the following Promela code:

byte myvalue=50
int a = 5
if
:: a<5 -> myvalue = 100
:: else -> myvalue = 200
fi

3. Name all possible values for myvalue after executing the following Promela code:

byte myvalue=50
int a = 5
if
:: a<5 -> myvalue = 100
:: a<3 -> myvalue = 200
fi

4. Name all possible values for myvalue after executing the following Promela code:

byte myvalue=50
int a = 5
if
:: a<5 -> a=2
:: a=2 -> myvalue = 200
fi

5. Name all possible values for mybyte after executing the following Promela code:

byte mybyte=10

active proctype P(){ mybyte=mybyte*2 }


active proctype Q(){ mybyte=50 }

6. Name all possible values for mybyte after executing the following Promela code:

byte mybyte=10

active proctype P(){ mybyte=mybyte*2 }


active proctype Q(){ mybyte=50 }
active proctype R(){byte x
x = mybyte
mybyte = x
}
30 4 Simple Promela Model Tasks

7. Name all possible values for value after executing the following Promela code:

active proctype P(){


int value;
do
:: value<2 -> value++
:: break
od;
printf("value␣is:␣%d\n", value);
}
5 Advanced Promela Model Tasks
In this chapter, we will present some more advanced examples for models in promela by different
authors in order to also show various programming styles. They are formulated as task for the
reader to program themselves.

5.1 Modeling Procedures and Recursion [14]


Procedures can be modeled as processes, even recursive ones. The return value can be passed
back to the calling process via a global variable, or via a message.
Task 5.1:
Write a program to recursively calculate the factorial of a number n.

Task 5.2:
The Fibonacci Numbers are defined as follows: F(0) = 0, F(1) = 1 and F(n) = F(n − 1) +
F(n − 2) for all natural numbers n ≥ 2.

1. Write a Promela model which computes the Fibonacci numbers recursively.

2. What is the maximum Fibonacci Number which can be computed and why?

3. Improve your program to calculate the highest Fibonacci number possible in Promela.

5.2 Prisoner’s Dilemma (Ruth Schorr)


Task 5.3:
“Two prisoners are held in separate cells for a serious crime that they did, in fact, commit. The
police, however, have only enough hard evidence to convict them of a minor offense, for which
the penalty is a year in jail. Each prisoner is told that if one confesses while the other denies, the
confessor will go scot free while the other spends 20 years in prison. If both confess, they will
get an intermediate sentence, say five years.”
Write a model containing three processes, one for each prisoner and a policeman-process.
“The two prisoner processes independently send a CONFESS or DENY message through a
pair of synchronous channels to the policeman process. Each prisoner chooses the content of
his message in a random fashion and independently from the other. The policeman receives the
messages, decides an adequate penalty and sends back to each prisoner a SENTENCE message
32 5 Advanced Promela Model Tasks

with the number of years he is supposed to spend in detention, using the same channel from
which he received the initial message.”

5.3 Elaaden Vault by Enrico Magnago


Task 5.4:
“Five ControlPillars, numbered from 0 to 4, control the gate of an ancient vault. Initially, pil-
lars 1, 3 and 4 are in ON state, while 0 and 2 are OFF . The gate opens when all pillars are
contemporarily set to ON.

• Each ControlPillar waits for input commands sent through their input channel ctl. When-
ever a pillar receives a command, it atomically changes its own state –and the state of its
immediate left and right neighbours– to the opposite value. To this extent, pillars 0 and 4
must be considered neighbours of each other.

• A spaceship Commander keeps sending command messages to randomly chosen control


pillars, up until the gate opens.”

5.4 Semaphore by Rendezvous Channel (from [14])


Task 5.5:
We will address problems with race conditions and concurrency between processes in more detail
later in this lecture. One fundamental solution to handling race conditions is to ensure mutual
exclusion of processes in so-called critical sections [16]. A well-known solution to achieve this
are semaphores as proposed by Dijkstra [3]. Semaphores are originally based on so-called TSL
(Test Set Lock)-Instructions. In Promela, one way to model semaphores is the use of rendezvous
channels. Write an implementation of Semaphores using rendezvous channels.

5.5 Sieve of Eratosthenes (from Spinlab)


Task 5.6:
The Sieve of Erathostenes is an algorithm to find all prime numbers up to a certain number
N. Write a promela model which implements this algorithm by starting a new process for each
prime which eliminates all numbers divisible by it and starts a new process for the first new prime
found.
5.6 SAT Problem (from Spinlab) 33

5.6 SAT Problem (from Spinlab)


Promela allows the use of nondeterminism in its code. Recall that the class NPcontains problems
which can be solved in polynomial time, but it is unknown whether polynomial-time algorithms
for these problems exist. Even NP-complete problems can be modeled in Promela. Consequently,
a verification of the model for an instance of such a problem may take exponential time, hinting
again once more at the limits of model checking. We will illustrate this with the SAT Problem.
Listing 5.1: SAT Problem from Spinlab
1 active proctype P() {
2 bool a, b, c
3

4 select(a: 0..1)
5 select(b: 0..1)
6 select(c: 0..1)
7

8 assert(!((a || c) && (!a || !c) &&


9 (a || !b) && (!a || b) &&
10 (b || !c) && (!b || !c)))
11 }

5.7 Traveling Salesman from (Spinlab)

Listing 5.2: Traveling Salesman from Spinlab


1 #define N 4
2 #ifndef MAX
3 #define MAX 97
4 #endif
5

6 byte distance[N*N];
7 byte city, dest, tour, seen;
8 byte visited[N]; // shortest tour so far
9

10 #define Dist(a,b) distance[((a)*N)+(b)]


11

12 // (0) -- (1)
13 // | \__/ |
14 // | / \ |
15 // (2) -- (3)
16

17 inline travel2(dest) {
18
34 5 Advanced Promela Model Tasks

19 (city != dest && tour <= MAX &&


20 (visited[dest] == 0 || tour + Dist(city,dest) < visited[dest])) ->
21

22 tour = tour + Dist(city,dest)


23 city = dest
24 if
25 :: !visited[city] ->
26 visited[city] = tour
27 printf("visit␣%d␣--␣tour␣%d\n", city, tour)
28 seen++
29 :: else
30 fi
31 }
32

33 init {
34 Dist(0,1) = 20; Dist(1,0) = 20
35 Dist(0,2) = 42; Dist(1,2) = 30
36 Dist(0,3) = 35; Dist(1,3) = 34
37

38 Dist(2,0) = 42; Dist(3,0) = 35


39 Dist(2,1) = 30; Dist(3,1) = 34
40 Dist(2,3) = 12; Dist(3,2) = 12
41

42 // find shortest route to visit all nodes starting and ending at 0


43 do
44 :: select(dest : 0 .. (N-1)) -> travel2(dest)
45 od
46

47 }
48

49 ltl p { [] ((seen < N) || (tour > MAX)) }


50

51 // exercises:
52 // 1. change it so that the distance going from a higher
53 // city number to a lower number is half that of going
54 // the other way (downhill/uphill)
55 // 2. change it to find the longest iso shortest tour

5.8 Undecidable Problems: Dead Code


Promela models may not only be built for NP-complete problems, but also for undecidable prob-
lems. Recall that any nontrivial property of a program at runtime cannot be decided algorithmi-
5.9 Dining Philosophers 35

cally. One of these problems is the discovery of dead code, i.e., code that will never be executed
in any run of the program.

5.9 Dining Philosophers


Task 5.7:
N philosophers dine together at a round table. Each philosopher has their own place at the table
with a plate in front. There is a fork between each plate, i.e. there are N forks, one to the left and
right of each philosopher. Each philosopher alternately thinks and then eats. When a philosopher
wants to eat, they need their left and right fork to eat which have to be picked up one fork at a
time. After an individual philosopher finishes eating, they will put down both forks.
The Dining Philosophers problem is a famous synchronizaton problem as a deadlocks may
occur in wrong implementations (e.g., when every philosopher wants to start eating at the same
time and they all pick up their left fork).
Implement the Dining Philosopher Problem in Promela.
6 Spin

Required Reading before Proceeding


• [14]
• [15]

6.1 Fundamentals
The tool for simulating and analyzing Promela models is called Spin. It is particilarly suitable
for asynchronous distributed software systems and communication protocols, nevertheless it can
also be used for single processes. For the analysis of the models, correctness properties can be
specified in multiple ways.
For a Promela model, Spin can perform random, interactive or guided simulations of the
model. For analysis, Spin creates c-code from the model (pan.c) which can be compiled and
then be used to analyze it.

6.2 Running Simulations in Spin


Consider the simple example simple.pml as specified in listing 6.1 which will nondeterminis-
tically assign mybyte either the value 100 or 200. The only instruction worth mentioning in the
program is the instruction assert(mybyte<200) in Line 8. assert() is for specitying simple
(safety) properties of a model. It takes any expression as argument. When the statement is en-
countered, the expression will be evaluated. If the result of the evaluation is true, the execution

Listing 6.1: Simple Example for Spin


1 byte myvalue
2 init
3 { if
4 :: myvalue = 100
5 :: myvalue = 200
6 fi
7 printf("myvalue␣=␣%d␣\n",myvalue)
8 assert(myvalue<200)
9 }
38 6 Spin

of the model will continue. If it is false (i.e. 0), the assertion violation will be reported and the
execution of the model will also continue. As we will see, assertions are mainly useful when
analyzing the model.
For now, we first start with a random simulation of the model which can be performed by
running Spin without options. We either obtain

~> spin simple.pml


myvalue = 100
1 process created

or

~> spin simple.pml


myvalue = 200
spin: simple.pml:9, Error: assertion violated
spin: text of failed assertion: assert((myvalue<200))
#processes: 1
myvalue = 200
4: proc 0 (:init::1) simple.pml:9 (state 6)
1 process created

as output. For now, we can ignore the details of the assertion. Clearly, the result of the sim-
ulation depends on the nondeterministic choice in the respective simulation which is randomly
performed by Spin.
We can also use interactive mode. By using the option -i, the user is prompted every time
a nondeterministic choice can be made and can select which of the alternatives to choose. For
example, we take choice 1 and obtain

~> spin -i simple.pml


Select stmnt (proc 0 (:init::1) )
choice 1: myvalue = 100
choice 2: myvalue = 200
Select [0-2]: 1
myvalue = 100
1 process created

It is also possible to run a simulation where the nondeterministic choices are selected according
to a recorded execution trail specified in simple.pml.trail. This option can be invoked by
using the option -t, i.e. spin -t simple.pml. It is particularly useful when examining an
error trail obtained from the analysis of a promela model. We will discuss this feature later.

6.3 Simulation Options for Spin


Spin also features further options which are useful when studying a simulation run in more detail.
[14] summarizes them as follows:
6.4 Verifying a Model with Spin 39

• “-p: Shows the state changes of the Promela processes at every time step.

• -g: Shows the current value of global variables at every time step.

• -l: Shows the current value of local variables, after the process that owns them has
changed state.

• -r: Shows all message receive events. It shows the process performing the receive, its
name and number, the source line number, the message parameter number (there is one
line for each parameter), the message type and the message channel number and name.

• -s: Shows all message send events.”

Spin also offers quite a few more run-time options which can be foind in [15].

6.4 Verifying a Model with Spin


Let us proceed by analyzing the model from Listing 6.1 with Spin. Spin can create c-code for an
analyzer which performs an exhaustive verification of the system state space. The system state
space can be verified against properties which can be defined in various ways one of which is the
assert()-statement which we put in our simple example.
In order to create the c-code, we run Spin with the option -a, i.e. spin -a simple.pml. This
produces a variety of files with the names pan.[cbhmt]. Running a c-compiler gcc pan.c -o
pan then produces the analyzer named pan. Running it for our example yields the following
output:

pan:1: assertion violated (myvalue<200) (at depth 2)


pan: wrote simple.pml.trail

(Spin Version 6.5.2 -- 9 June 2022)


Warning: Search not completed
+ Partial Order Reduction

Full statespace search for:


never claim - (none specified)
assertion violations +
acceptance cycles - (not selected)
invalid end states +

State-vector 20 byte, depth reached 4, errors: 1


7 states, stored
0 states, matched
7 transitions (= stored+matched)
0 atomic steps
hash conflicts: 0 (resolved)
40 6 Spin

Stats on memory usage (in Megabytes):


0.000 equivalent memory usage for states (stored*(State-vector + overhead))
0.292 actual memory usage for states
128.000 memory used for hash table (-w24)
0.534 memory used for DFS stack (-m10000)
128.730 total actual memory usage

pan: elapsed time 0.02 seconds


pan: rate 350 states/second
Let us for now focus on the verification of the model. pan found a violation of our assertion
and produced a trail of a run which violated the assertion. We may now run spin with the -t-
option in conjunction with other options to find out what is wrong with our model.
In this toy example, the violation of the assertion is not surprising at all and studying the trail
merely presents a run where the nondeterministic option to assign 200 to mybyte is chosen, but
in more complex models, even subtile errors can be found.
Pan offers a variety of options at compile-time and run-time, see [9] for details. This reference
also gives a detailed overview of Pan’s output which will be omitted here.

6.5 Tasks
Task 6.1:
Consider the Promela-model created in Section 4.2 for computing the product of N random
numbers with values either 1 or 2. For N = 10, Use an assert-statement and find a run where
the product is 1024 using verification.

Task 6.2:
Consider the following Promela model “Double”:
Listing 6.2: Promela Model “Double”
1 byte a,b,x
2

3 proctype proc(byte number)


4 { do
5 :: x<=16 -> a = x;
6 b = x;
7 x = a + b
8 :: else -> break;
9 od
10 }
6.5 Tasks 41

11

12 init
13 { x = 1
14 run proc(1)
15 run proc(2)
16 printf ("x␣=␣%d␣\n",x);
17 }

1. Explain what the model is doing.

2. Use Spin to find all potential values which can be printed for x.

Task 6.3:
Consider the following Promela model:

Listing 6.3: Promela Model


1 byte flag = 0;
2 short count = 0;
3 bool ende = false
4 active proctype P() {
5 if
6 :: flag = 1
7 :: flag = 2
8 fi;
9 if
10 :: flag == 1 ->
11 do
12 :: (count == 0) -> break
13 :: count++
14 :: count--
15 od
16 :: else ->
17 do
18 :: (count == 0) -> break
19 :: (count != 0) -> if
20 :: count++
21 :: count--
22 fi
23 od
24 fi;
25 ende = true
26 }
42 6 Spin

and consider the following properties:

1. Whenever flagg is 1, ende will become true at some point thereafter.

2. Whenever flagg is 2, ende will become true at some point thereafter.

3. If count is infinitely often 5, then it is infinitely often 4 or infinitely often 6.

4. If count is 5, it will have the value 4 or 6 in the next step.

5. count can only finitely often be 0.

For each property, state and explain whether the property is true or false. Present LTL-formulae
in Promela to automatically verify these claims and present the automatic verification.
7 Modeling Mutual Exclusion of Processes

Required Reading before Proceeding


• [2], pp. 38–54

7.1 Fundamentals
A general problem in interprocess communication are race conditions between processes (see
[16], pp. 119–148). This term refers to situatios in which processes access shared data and the
outcome depends on which process exactly runs when. Race conditions are in general unwanted
and need to be avoided.
Listing 7.1 shows an example for race conditions from [2]. If both processes (let us call them
A and B) are executed sequentially, the final value of n will be 20. However, if both processes
store the value of n in temp before the respective other process has saved its increment back,

Listing 7.1: Race Condition Example from [2]


1 byte n = 0;
2

3 proctype P() {
4 byte temp, i;
5 for (i : 1..10)
6 {
7 temp = n;
8 n = temp + 1
9 }
10 }
11

12 init {
13 atomic {
14 run P();
15 run P()
16 }
17 (_nr_pr == 1);
18 printf("The␣value␣is␣%d\n", n);
19 }
44 7 Modeling Mutual Exclusion of Processes

the increment is lost resulting in a final value of n lower than 20.The minimal value for n after a
competion of the two processes may even be as low as 2 if, e.g., processes A stores 0 in temp,
then process B runs uninterrupted until n is set to 9. At this point process A runs once setting
n back to 1. Then, process B stores 1 in temp after which A runs uninterrupted until it finishes.
Then B finally sets n to 2.
With the Promela model at hand, we can use Spin to find this particular execution of the model.
We append an assertion before the printf-statement assert(n>2) and run the commands

spin -a filename.pml
gcc pan.c -o pan
pan

and obtain a trail of a run violating the condition. We now look into this trail by running spin
-t -p -l -g filename.pml. The behavior outlined above can also clearlz be found in the
trail (boring parts are omitted):

Starting P with pid 1


1: proc 0 (:init::1) nondet.pml:16 (state 1) [(run P())]
Starting P with pid 2
2: proc 0 (:init::1) nondet.pml:17 (state 2) [(run P())]
3: proc 2 (P:1) nondet.pml:7 (state 1) [i = 1]
P(2):i = 1
4: proc 2 (P:1) nondet.pml:7 (state 2) [((i<=10))]
5: proc 1 (P:1) nondet.pml:7 (state 1) [i = 1]
P(1):i = 1
6: proc 1 (P:1) nondet.pml:7 (state 2) [((i<=10))]
7: proc 2 (P:1) nondet.pml:9 (state 3) [temp = n]
P(2):temp = 0
8: proc 1 (P:1) nondet.pml:9 (state 3) [temp = n]
P(1):temp = 0
9: proc 2 (P:1) nondet.pml:10 (state 4) [n = (temp+1)]
n = 1
(...)
41: proc 2 (P:1) nondet.pml:10 (state 4) [n = (temp+1)]
n = 9
42: proc 2 (P:1) nondet.pml:7 (state 5) [i = (i+1)]
P(2):i = 10
43: proc 2 (P:1) nondet.pml:7 (state 2) [((i<=10))]
44: proc 1 (P:1) nondet.pml:10 (state 4) [n = (temp+1)]
n = 1
45: proc 1 (P:1) nondet.pml:7 (state 5) [i = (i+1)]
P(1):i = 2
46: proc 1 (P:1) nondet.pml:7 (state 2) [((i<=10))]
47: proc 2 (P:1) nondet.pml:9 (state 3) [temp = n]
P(2):temp = 1
7.1 Fundamentals 45

48: proc 1 (P:1) nondet.pml:9 (state 3) [temp = n]


P(1):temp = 1
49: proc 1 (P:1) nondet.pml:10 (state 4) [n = (temp+1)]
n = 2
(...)
proc 1 (P:1) nondet.pml:10 (state 4) [n = (temp+1)]
n = 10
82: proc 1 (P:1) nondet.pml:7 (state 5) [i = (i+1)]
P(1):i = 11
83: proc 1 (P:1) nondet.pml:11 (state 6) [else]
84: proc 2 (P:1) nondet.pml:10 (state 4) [n = (temp+1)]
n = 2
85: proc 2 (P:1) nondet.pml:7 (state 5) [i = (i+1)]
P(2):i = 11
86: proc 2 (P:1) nondet.pml:11 (state 6) [else]
87: proc 2 terminates
88: proc 1 terminates
(...)
spin: nondet.pml:22, Error: assertion violated

Thus, we have already analysed a race condition by using an assertion.


Back to the problem itself. The key to avoiding race conditions is the introduction of critical
regions which only a single process may enter at any time. This is referred to as mutual exclusion.
If a process is in a critical region, other processes have to wait until the process leaves the critical
region.
In our above example, lines 7 and 8 can be considered a critical region. In other words,
no other process shall access n before the increment was written back. Promela offers a very
simple method for modeling a simple critical section using the atomic-keyword. The sequence
in the atomic-statement is executed indivisibly and non-interleaved with other processes (see
atomic at [11]) ”If any statement within the atomic sequence blocks, atomicity is lost, and other
processes are then allowed to start executing statements. When the blocked statement becomes
executable again, the execution of the atomic sequence can be resumed at any time, but not
necessarily immediately. Before the process can resume the atomic execution of the remainder
of the sequence, the process must first compete with all other active processes in the system to
regain control, that is, it must first be scheduled for execution.”
In Listing 7.2, the race condition between the two processes is eliminated and the final value
of n is always 20. Please note that this straightforward use of atomic to model a critical section
(i.e. by making the critical section atomic) fails in nontrivial scenarios. However, atomic can be
used to model access criteria to critical sections which allow for more elaborate models as will
be demonstrated shortly.
46 7 Modeling Mutual Exclusion of Processes

Listing 7.2: Example from [2] without race condition.


1 byte n = 0;
2

3 proctype P() {
4 byte temp, i;
5 for (i : 1..10)
6 { atomic{
7 temp = n;
8 n = temp + 1
9 }}
10 }
11

12 init {
13 atomic {
14 run P();
15 run P()
16 }
17 (_nr_pr == 1);
18 printf("The␣value␣is␣%d\n", n);
19 }

7.2 A Failed Attempt for Mutual Exclusion


In the following, we want to investigate a model striving to model mutual exclusion. by means
of using a global variable critical. The code for this attempt is given in Listing 7.3
The problem with this approach is that both processes may check the value of critical,
immediately after one another finding it to be 0, before the processes increase the value. Using
Spin in interactive mode can already show this:

Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:15 (state 8) [printf(’Q noncritical \\n’)]
choice 2: proc 0 (P:1) notmutex.pml:4 (state 8) [printf(’P noncritical \\n’)]
Select [1-2]: 1
Q noncritical
Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:17 (state 6) [((critical==0))]
choice 2: proc 0 (P:1) notmutex.pml:4 (state 8) [printf(’P noncritical \\n’)]
Select [1-2]: 2
P noncritical
Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:17 (state 6) [((critical==0))]
choice 2: proc 0 (P:1) notmutex.pml:6 (state 6) [((critical==0))]
7.2 A Failed Attempt for Mutual Exclusion 47

Listing 7.3: Failed Attempt for Mutual Exclusion.


1 byte critical = 0
2

3 active proctype P(){


4 do
5 :: printf("P␣noncritical␣\n");
6 if
7 :: critical == 0 -> critical=1;
8 printf("P␣critical␣\n");
9 critical=0;
10 fi
11 od
12

13 }
14 active proctype Q(){
15 do
16 :: printf("Q␣noncritical␣\n");
17 if
18 :: critical == 0 -> critical=1;
19 printf("Q␣critical␣\n");
20 critical=0;
21 fi
22 od
23

24 }

Select [1-2]: 1
Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:18 (state 3) [critical = 1]
choice 2: proc 0 (P:1) notmutex.pml:6 (state 6) [((critical==0))]
Select [1-2]: 2
Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:18 (state 3) [critical = 1]
choice 2: proc 0 (P:1) notmutex.pml:7 (state 3) [critical = 1]
Select [1-2]: 1
Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:19 (state 4) [printf(’Q critical \\n’)]
choice 2: proc 0 (P:1) notmutex.pml:7 (state 3) [critical = 1]
Select [1-2]: 2
Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:19 (state 4) [printf(’Q critical \\n’)]
48 7 Modeling Mutual Exclusion of Processes

choice 2: proc 0 (P:1) notmutex.pml:8 (state 4) [printf(’P critical \\n’)]


Select [1-2]: 1
Q critical
Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:20 (state 5) [critical = 0]
choice 2: proc 0 (P:1) notmutex.pml:8 (state 4) [printf(’P critical \\n’)]
Select [1-2]: 2
P critical
Select a statement
choice 1: proc 1 (Q:1) notmutex.pml:20 (state 5) [critical = 0]
choice 2: proc 0 (P:1) notmutex.pml:9 (state 5) [critical = 0]

However, let us try to find this error using Spin’s verification features. The first possibility is
to introduce a variable which is not part of the model, but only used for verification purposes.
Such a variable is called ghost variable. We introduce a ghost variable which starts with value 0
is increased by one of a processe is in the critical section, and then decreased. If only one process
at a time is in the critical section, this variable should never reach the value 2. We then check this
with a corresponding assertion. The modified listing is shown in 7.4.
When verifying this model, a violation of the assertion is found and the respectve trail can be
studied. Clearly, this is a more systematic approach.
Another means of checking for the same property is the use of linear temporal logic. While
we will discuss this formalism in more detail in Chapter 11. The modified listing is shown in
Listing 7.5.
We have introduced two boolean ghost variables pcrit and qcrit which indicate whether the
respective processes are in their critical section. Clearly, in order to have mutual exclusion, both
variables should never be true at the same point in time at any point in time. In LTL, at any point
in time (or “always”) can be expressed by the □-operator, and the formula for not both variables
true is of course ¬(pcrit ∧ qcrit), which yields us the LTL-formula

□¬(pcrit ∧ qcrit) “always not pcrit and qcrit”

In Promela, an LTL-foumla can be specified by providing the lexem ltl, a name for the for-
mula (here mutex) and the formula enclosed in curly brackets. The operators are translated into
Promelas syntax straightforward and leaves us with []!(pcrit && qcrit).
The usual steps and running pan give us again a trail of an execution where both processes are
in the critical region at the same time.

7.3 Mutual Exclusion with Deadlock


So, let us try another solution to the problem. Listing 7.6 shows another attempt. We now use
two boolean variables pwant and qwant to signal the wish to enter the critical region to the
respective other process. If P wants to enter the critical region, it sets pwant=1. After setting this
flag, the process checks if the other process also has set the flag, qwant==1. If so, it is assumed
7.3 Mutual Exclusion with Deadlock 49

Listing 7.4: Failed Attempt for Mutual Exclusion for Verification.


1 byte critical = 0
2 byte ghostcounter = 0;
3

4 active proctype P(){


5 do
6 :: printf("P␣noncritical␣\n");
7 if
8 :: critical == 0 -> critical=1;
9 printf("P␣critical␣\n");
10 ghostcounter++;
11 assert (ghostcounter<2);
12 ghostcounter--;
13 critical=0;
14 fi
15 od
16

17 }
18 active proctype Q(){
19 do
20 :: printf("Q␣noncritical␣\n");
21 if
22 :: critical == 0 -> critical=1;
23 printf("Q␣critical␣\n");
24 ghostcounter++;
25 ghostcounter--;
26 critical=0;
27 fi
28 od
29

30 }

that process Q is in the critical region and the process blocks and will get unblocked once Q leaves
the critica region and sets qwant to 0.
The code shown in the listing still contains our code for verifying mutual exclusion, and we
now use Spin to check whether mutual exclusion holds. And, indeed, pan does not come back
with an error trial, so this model indeed guarantees mutual exclusion.
However, it contains another glitch which may lead to a deadlock. A deadlock in general refers
to a set of processes which are blocked waiting for an event which would also be triggered by
a process in the same set. As all processes are blocked, no process will trigger an event and all
processes will not resume forever.
50 7 Modeling Mutual Exclusion of Processes

Listing 7.5: Failed Attempt for Mutual Exclusion for Verification with LTL.
1 byte critical = 0
2 bool pcrit = 0;
3 bool qcrit = 0;
4 ltl mutex{[]!(pcrit && qcrit)}
5

7 active proctype P(){


8 do
9 :: printf("P␣noncritical␣\n");
10 if
11 :: critical == 0 -> critical=1;
12 printf("P␣critical␣\n");
13 pcrit=1;
14 pcrit=0;
15 critical=0;
16 fi
17 od
18

19 }
20 active proctype Q(){
21 do
22 :: printf("Q␣noncritical␣\n");
23 if
24 :: critical == 0 -> critical=1;
25 printf("Q␣critical␣\n");
26 qcrit=1;
27 qcrit=0;
28 critical=0;
29 fi
30 od
31

32 }

In our case, a deadlock will occur if P and Q set their flags immediately after one another before
then checking the flag of the other process. Spin in interactive mode can reach this situation as
follows:

Select a statement
choice 1: proc 1 (Q:1) notmutexver.pml:22 (state 10) [printf(’Q noncritical \\n’)]
choice 2: proc 0 (P:1) notmutexver.pml:9 (state 10) [printf(’P noncritical \\n’)]
Select [1-2]: 1
7.3 Mutual Exclusion with Deadlock 51

Listing 7.6: Mutual Exclusion with Deadlock.


1 bool pcrit = 0
2 bool qcrit = 0
3 bool pwant = 0
4 bool qwant = 0;
5 ltl mutex{[]!(pcrit && qcrit)}
6

8 active proctype P(){


9 do
10 :: printf("P␣noncritical␣\n");
11 pwant=true;
12 if :: qwant==false ->
13 printf("P␣critical␣\n");
14 pcrit=1;
15 pcrit=0;
16 pwant=false;
17 fi
18 od
19

20 }
21 active proctype Q(){
22 do
23 :: printf("Q␣noncritical␣\n");
24 qwant=true;
25 if :: pwant==false ->
26 printf("Q␣critical␣\n");
27 qcrit=1;
28 qcrit=0;
29 qwant=false;
30 fi
31 od
32

33 }

Q noncritical
Select a statement
choice 1: proc 1 (Q:1) notmutexver.pml:24 (state 2) [qwant = 1]
choice 2: proc 0 (P:1) notmutexver.pml:9 (state 10) [printf(’P noncritical \\n’)]
Select [1-2]: 2
P noncritical
52 7 Modeling Mutual Exclusion of Processes

Select a statement
choice 1: proc 1 (Q:1) notmutexver.pml:24 (state 2) [qwant = 1]
choice 2: proc 0 (P:1) notmutexver.pml:11 (state 2) [pwant = 1]
Select [1-2]: 1
Select a statement
choice 1: proc 1 (Q:1) notmutexver.pml:25 (state 8) [((pwant==0))]
choice 2: proc 0 (P:1) notmutexver.pml:11 (state 2) [pwant = 1]
Select [1-2]: 2
Select a statement
no executable choices
Let us now also use Spin’s verification feature to detect the deadlock. What we want is that
always at some time Q or P enter their critical section. However, there may be a time when none
of the processes is in the critical section, but eventually one of them enters. Something which
eventually happens can be specified in LTL using the ♢-operator. So, for “always eventually qcrit
or pcrit” we obtain
□♢(pcrit ∨ qcrit),
or in Promela’s syntax []<>(pcrit || qcrit).
We replace our original LTL-formula with this formula (named deadlock and again run our
verifier (pan -a). We obtain a trail of a violation of the condition as follows:
spin -t -p -l -g notmutexver.pml
ltl deadlock: [] (<> ((pcrit) || (qcrit)))
starting claim 2
Never claim moves to line 3 [(!((pcrit||qcrit)))]
Q noncritical
2: proc 1 (Q:1) notmutexver.pml:22 (state 1) [printf(’Q noncritical \\n’)]
Never claim moves to line 8 [(!((pcrit||qcrit)))]
P noncritical
4: proc 0 (P:1) notmutexver.pml:9 (state 1) [printf(’P noncritical \\n’)]
6: proc 1 (Q:1) notmutexver.pml:23 (state 2) [qwant = 1]
qwant = 1
8: proc 0 (P:1) notmutexver.pml:10 (state 2) [pwant = 1]
pwant = 1
<<<<<START OF CYCLE>>>>>
spin: trail ends after 10 steps
#processes: 2
pcrit = 0
qcrit = 0
pwant = 1
qwant = 1
10: proc 1 (Q:1) notmutexver.pml:24 (state 8)
10: proc 0 (P:1) notmutexver.pml:11 (state 8)
10: proc - (deadlock:1) _spin_nvr.tmp:7 (state 10)
2 processes created
7.4 A Probabilistic Solution 53

Listing 7.7: Mutual Exclusion with Probabilistic Resolvement.


1 bool pcrit = 0
2 bool qcrit = 0
3 bool pwant = 0
4 bool qwant = 0;
5 ltl deadlock{[](<> (pcrit || qcrit))}
6

7 active proctype P(){


8 do
9 :: printf("P␣noncritical␣\n");
10 pwant=true;
11 if :: qwant==false ->
12 printf("P␣critical␣\n");
13 pcrit=1;
14 pcrit=0;
15 pwant=false;
16 :: else -> pwant=false;
17 fi
18 od
19

20 }
21 active proctype Q(){
22 do
23 :: printf("Q␣noncritical␣\n");
24 qwant=true;
25 if :: pwant==false ->
26 printf("Q␣critical␣\n");
27 qcrit=1;
28 qcrit=0;
29 qwant=false;
30 :: else -> qwant=false;
31 fi
32 od
33

34 }

7.4 A Probabilistic Solution


Consider the modification of the program in Listing 7.6 as presented in Listing 7.7. The dif-
ference is that, if the other process has also signaled its interest to enter the critical section, the
respective process will defer its access and return to noncritical (and thus try later). Thus, mutual
54 7 Modeling Mutual Exclusion of Processes

exclusion is achieved while, also, no deadlock seems to occur. If we run a simulation of the
model, we can clearly observe this behavior:

spin deadlockprob.pml
ltl deadlock: [] (<> ((pcrit) || (qcrit)))
Q noncritical
P noncritical
P noncritical
Q critical
P noncritical
Q noncritical
Q critical
P critical
Q noncritical
P noncritical
P noncritical
Q critical
P noncritical
P noncritical
Q noncritical
P critical
Q noncritical
P noncritical
P noncritical
Q noncritical
Q critical
P noncritical
P critical
Q noncritical
Q critical
(...)

However, if we run pan -a on the analysis code, we obtain an error with the following trail
of the violation:

spin -t -p -l -g deadlockprob.pml
ltl deadlock: [] (<> ((pcrit) || (qcrit)))
starting claim 2
Never claim moves to line 3 [(!((pcrit||qcrit)))]
Q noncritical
2: proc 1 (Q:1) deadlockprob.pml:23 (state 1) [printf(’Q noncritical \\n’)]
Never claim moves to line 8 [(!((pcrit||qcrit)))]
P noncritical
4: proc 0 (P:1) deadlockprob.pml:9 (state 1) [printf(’P noncritical \\n’)]
6: proc 1 (Q:1) deadlockprob.pml:24 (state 2) [qwant = 1]
7.4 A Probabilistic Solution 55

qwant = 1
8: proc 1 (Q:1) deadlockprob.pml:25 (state 3) [((pwant==0))]
Q critical
10: proc 1 (Q:1) deadlockprob.pml:26 (state 4) [printf(’Q critical \\n’)]
<<<<<START OF CYCLE>>>>>
12: proc 0 (P:1) deadlockprob.pml:10 (state 2) [pwant = 1]
pwant = 1
14: proc 0 (P:1) deadlockprob.pml:16 (state 8) [else]
16: proc 0 (P:1) deadlockprob.pml:16 (state 9) [pwant = 0]
pwant = 0
P noncritical
18: proc 0 (P:1) deadlockprob.pml:9 (state 1) [printf(’P noncritical \\n’)]
spin: trail ends after 18 steps
#processes: 2
pcrit = 0
qcrit = 0
pwant = 0
qwant = 1
18: proc 1 (Q:1) deadlockprob.pml:27 (state 5)
18: proc 0 (P:1) deadlockprob.pml:10 (state 2)
18: proc - (deadlock:1) _spin_nvr.tmp:7 (state 10)
2 processes created
As can be seen, the trail shows an execution of the model violating our LTL-statement where
process P keeps looping while Q remains in the critical section and is not further executed!
While such an execution cannot be ruled out, it is on one hand practically arbitrarily unlikely as,
assuming a constant distribution of probalilities that p that P runs and (1 − p) that Q runs, the
probability for this behavior is pn after n executions of the model and converges to 0 for n → ∞.
The non-execution of a process which is reaty to run is also called starvation.
Spin also offers a feature to only consider executions of the model which are (weakly) fair.
This can be achieved by using the option -f (please note that spin is somewhat experimental and
the feature not well-documented, thus different behaviour may also be observed, caution should
be used). However, by running pan -a -f we still obtain a violation with the following trail:
spin -t -p -l -g deadlockprob.pml
ltl deadlock: [] (<> ((pcrit) || (qcrit)))
starting claim 2
Never claim moves to line 3 [(!((pcrit||qcrit)))]
Q noncritical
2: proc 1 (Q:1) deadlockprob.pml:23 (state 1) [printf(’Q noncritical \\n’)]
Never claim moves to line 8 [(!((pcrit||qcrit)))]
P noncritical
4: proc 0 (P:1) deadlockprob.pml:9 (state 1) [printf(’P noncritical \\n’)]
6: proc 1 (Q:1) deadlockprob.pml:24 (state 2) [qwant = 1]
qwant = 1
56 7 Modeling Mutual Exclusion of Processes

8: proc 0 (P:1) deadlockprob.pml:10 (state 2) [pwant = 1]


pwant = 1
10: proc 1 (Q:1) deadlockprob.pml:30 (state 8) [else]
12: proc 1 (Q:1) deadlockprob.pml:30 (state 9) [qwant = 0]
qwant = 0
Q noncritical
14: proc 1 (Q:1) deadlockprob.pml:23 (state 1) [printf(’Q noncritical \\n’)]
16: proc 1 (Q:1) deadlockprob.pml:24 (state 2) [qwant = 1]
qwant = 1
18: proc 0 (P:1) deadlockprob.pml:16 (state 8) [else]
20: proc 1 (Q:1) deadlockprob.pml:30 (state 8) [else]
22: proc 1 (Q:1) deadlockprob.pml:30 (state 9) [qwant = 0]
qwant = 0
Q noncritical
24: proc 1 (Q:1) deadlockprob.pml:23 (state 1) [printf(’Q noncritical \\n’)]
26: proc 1 (Q:1) deadlockprob.pml:24 (state 2) [qwant = 1]
qwant = 1
28: proc 0 (P:1) deadlockprob.pml:16 (state 9) [pwant = 0]
pwant = 0
<<<<<START OF CYCLE>>>>>
P noncritical
30: proc 0 (P:1) deadlockprob.pml:9 (state 1) [printf(’P noncritical \\n’)]
32: proc 0 (P:1) deadlockprob.pml:10 (state 2) [pwant = 1]
pwant = 1
34: proc 1 (Q:1) deadlockprob.pml:30 (state 8) [else]
36: proc 1 (Q:1) deadlockprob.pml:30 (state 9) [qwant = 0]
qwant = 0
Q noncritical
38: proc 1 (Q:1) deadlockprob.pml:23 (state 1) [printf(’Q noncritical \\n’)]
40: proc 1 (Q:1) deadlockprob.pml:24 (state 2) [qwant = 1]
qwant = 1
42: proc 0 (P:1) deadlockprob.pml:16 (state 8) [else]
44: proc 1 (Q:1) deadlockprob.pml:30 (state 8) [else]
46: proc 1 (Q:1) deadlockprob.pml:30 (state 9) [qwant = 0]
qwant = 0
Q noncritical
48: proc 1 (Q:1) deadlockprob.pml:23 (state 1) [printf(’Q noncritical \\n’)]
50: proc 1 (Q:1) deadlockprob.pml:24 (state 2) [qwant = 1]
qwant = 1
52: proc 0 (P:1) deadlockprob.pml:16 (state 9) [pwant = 0]
pwant = 0
spin: trail ends after 52 steps
#processes: 2
pcrit = 0
7.5 Peterson’s Solution 57

qcrit = 0
pwant = 0
qwant = 1
52: proc 1 (Q:1) deadlockprob.pml:25 (state 10)
52: proc 0 (P:1) deadlockprob.pml:8 (state 12)
52: proc - (deadlock:1) _spin_nvr.tmp:7 (state 10)
2 processes created

Here, the unproductive cycle is due to the fact that neither P or Q enter the critical section, but
both defer access indefinetely. Regarding the likelihood for this behaviour, similar considerations
as above yield the result that it is arbitrarily unlikely. However, there are no built-in options to
only consider practically really relevant scenarios for this case.

7.5 Peterson’s Solution


Of course, there are solutions to mutual exclusion which neither violate the condition that only
one process at a time is in the critical section and are also deadlock-free.
One such software solution for mutual exclusion of two processes is Peterson’s solution (see
[16] pp. 124-125).
In short, race conditions are resolved as a process defers access to the critical region in case it
has overwritten the turn-variable set before by the other process which is also either interested in
accessing the critical region or already in the critical region.
The implememtatiom of the algorithm in Promela and its verification are left as exercise.

7.6 Tasks
Task 7.1:
Assume we modify Listing 7.1 to run P three times. What would be the possible value range for
n?

Task 7.2:
Verify for Listing 7.2 that the final value of n is always 20 using Spin.

Task 7.3:
Create a Promela model for Peterson’s algorithm. Verify mutual exclusion and deadlock-freeness
with Spin.

Task 7.4:
Create a Promela model using Peterson’s algorithm instead of atomicity to resolve the race con-
dition from Listing 7.1
8 Transition Systems

Required Reading before Proceeding


• [1] Chapter 2

8.1 Fundamentals
A powerful modeling tool for modeling processes in Computer Science are Transition Systems:

Definition 8.1 (TS) A Transition System (TS) T is a tuple

T = (Q, Σ, δ , Q0 , AP, L)

where

Q is a set of states
Σ is a set of actions
Q0 ⊆ Q is the set of initial states
Q
δ : Q×Σ → 2 the transition relation
AP is a set of labels
L : Q → 2AP ⊆ Q is the labelling function.

The transition relation →⊆ Q × Σ × Q is induced by (q, σ , p) ∈→ if p ∈ δ (q, σ ), for conve-


σ
nience, we also use the notation p → q.
For every σ ∈ Σ and q ∈ Q, the direct successors and predecessors are denoted by Post(q, σ ) =
δ (q, σ ), Post(q) = ∪σ ∈Σ Post(q, σ ), Pre(q, σ ) = {p ∈ Q | q ∈ δ (p, σ )}, Post(q) = ∪σ ∈Σ Pre(q, σ ),
We extend this notation canonically to sets of states. A state q ∈ Q is called terminal if Post(q) =
0.
/
Note that, in contrast to finite automata, transition systems have no final states and are thus not
accepting any inputs. Moreover, they may have countably infinite sets of states and actions.

Definition 8.2 Let T = (Q, Σ, δ , Q0 , AP, L) be a transition system. An execution fragment ρ ∈


(Q × Σ)ω ∪ (Q × Σ)+ is an (infinite) alternating sequence of states and actions

ρ = q0 σ1 q1 σ2 q2 . . . such that qi+1 ∈ δ (qi , σi+1 ) for alli ≥ 0

ρ is called maximal if it is infinite or ending in a terminal state. ρ is called initial if q0 ∈ Q0 . A


maximal, initial execution fragment is called execution.
60 8 Transition Systems

8.2 Modeling Concurrent Processes as Transition Systems


While [1], Chapter 2 extensively studies how serial processes with nondeterminsm can be mod-
eled as a program graph which in turn can be unfolded into an eqivalent transition system and
how synchronized and unsynchronized concurrent transition systems can be interleaved into one
system, we will not study these constructions in detail here, but rather state the following:
If the domain of all variables of a process is finite, a semantically equivalent transition system
can be generated by memorizing all variables in the state of the transition system as well as the
current instruction (program cunter). Transitions from one state into another state are modeled
in the canonical way. This also holds true for multiple processes.

8.3 Traces
Definition 8.3 Let T = (Q, Σ, δ , Q0 , AP, L) be a transition system without terminal states. The
trace of an execution ρ = q0 σ1 q1 σ2 q2 . . . is given by

trace(ρ) = L(q0 )L(q1 )L(q2 ) ∈ (2AP )ω

Furthermore,
trace(T ) = {trace(ρ) | ρ is an execution of T }

Theorem 8.4 Let T = T = (Q, Σ, δ , Q0 , AP, L) be a transition system without terminal states with
a finite number of states over a finite set of actions. Then there is a Büchi-Automaton M with
Tω (M) = trace(T ).

Proof. Without loss of generality, we assume T has only one initial state, {q0 } = Q0 . We define
the B"uchi-Automaton M = (Q, 2AP , δ ′ , q0 , Q) where for all σ ∈ 2AP

δ ′ (q, σ ) := {p ∈ Q | p ∈ Post(q) and L(q) = σ }.

It is easy to prove T (M) = traces(T ). □


9 Finite Automata

9.1 Mathematical Preliminaries


9.1.1 General
A set is a collection of distinguishable elements. For a set A, |A| denotes the cardinality of the set.
The set of all subsets of A is denoted by 2A . A (not neccessarily) proper inclusion is denoted by
⊂ (⊆); the difference between two sets is denoted by −. The inclusion of an element in a set is
expressed by ∈. Furthermore, A|i for 1 ≤ i ≤ |A| denotes the ith element of A (an according order
of the elements in the set is always assumed), thus, we have 1≤i≤|A| {A|i } = A and A|i ̸= A| j for
S

i ̸= j. We also put A|i = 0/ for all i > |A|.

Example 9.1 Consider the set A = {p, q, r}. We have |A| = 3 and

2A = {0,
/ {p}, {q}, {r}, {p, q}, {p, r}, {q, r}, {p, q, r}}.

Also, {p} ⊆ {p, q}, p ∈ A and {p, q} − {p} = {q}.

Definition 9.2 Let A and B be two sets. The product between A and B, A × B, is the set

A × B = {(a, b) |a ∈ A, b ∈ B}.

Definition 9.3 A binary relation R on a set A is a subset of the product of A with itself, R ⊆ A ×A.
For such a relation we put R0 := {(a, a) ∈ A × A | a ∈ A} and Rk := {(a, c) ∈ A × A | there is a b ∈
A, such that (a, b) ∈ R and (b, c) ∈ Rk−1 }. The transitive closure of R is R+ := ∪i≥1 Ri , the reflex-
ive transitive closure R∗ := ∪i≥0 Ri .
For binary relations we use aRb synomynously for (a, b) ∈ R.
A relation R ⊆ A × A is called

• reflexive if for all a ∈ A aRa holds,

• transitive, if for all a, b, c ∈ A we have: If aRb and bRc, then aRc holds,

• symmetrical, if for all a, b ∈ A we have: If aRb, then bRa holds.

A reflexive, transitive and symmetrical relation R ⊆ A × A, is called equivalence relation. For


each a ∈ A ⟨a⟩R denote the equivalence class of a regarding R, ⟨a⟩R := {b ∈ A | (a, b) ∈ R}. The
equivalence classes constitute a partitioning of the set A.
The index of an equivalence relation is the maximal number of pairwise disjoint equivalence
classes.
62 9 Finite Automata

9.1.2 Alphabets, Words, Languages


An alphabet is a non-empty finite set of symbols Σ. Every element of an alphabet σ ∈ Σ is called
symbol.

Example 9.4 Consider the latin alphabet A = {a, b, c, . . . , z} and the binary alphabet B = {0, 1}.

Words over an alphabet are constructed by concatenating symbols of the alphabet. For an
alphabet Σ, Σ∗ denotes the set of all words over the alphabet including the empty word ε. The set
of all non-empty words is Σ+ := Σ∗ − {ε}. The length |w| of a word w is the number of symbols
it constructed of, |ε| = 0. The set of all non-empty words of length k is Σk := {w ∈ Σ+ | |w| = k},
Accordingly, Σ⋄k := {w ∈ Σ+ | |w| ⋄ k} for ⋄ ∈ {<, ≤, >, ≥}. A word v ∈ Σ∗ is called (proper)
substring of x ∈ Σ∗ if there is a partitioning x = uvw such that u, w ∈ Σ∗ (and |uw| > 0). If |u| = 0
(|w| = 0), v is called prefix (suffix) of x. For two words x = σ1 . . . σm and y = τ1 . . . τn ∈ Σ∗ ,
σi ∈ Σ, 1 ≤ i ≤ m, τi ∈ Σ, 1 ≤ i ≤ n the concatenation xy of x and y, i.e. the word consistin of the
m + n symbols xy = σ1 . . . σm τ1 . . . τn .

Example 9.5 For the alphabets A and B as above, we have 01101 ∈ B∗ and test ∈ A∗ . Also,
|01101| = 5 and |test| = 4. Furthermore,
B∗ = {ε, 0, 1, 00, 01, 10, 11, 000, 001, 010, 011, 100, 101, 110, 111, 0000, . . .}
and
A∗ = {ε, a, b, . . . , z, aa, . . . , az, ba, . . .}.
The set of all words of length 3 over B is
B3 = {000, 001, 010, 011, 100, 101, 110, 111}.
For x = 01001 and y = 10010110 we have xy = 0100110010110.

Formal languages consist of a (not necessarily empty) set of words over an alphabet Σ. Any
subset L ⊆ Σ∗ is called formal language.

Example 9.6 Again, consider B as above. Examples for formal languages over B are
L1 = {ε, 0, 00, 000, 0000, 00000, 000000, . . .}
L2 = {w ∈ B∗ | the number of ones in w is even}
L3 = 0/
L4n = {x1y ∈ B∗ | x ∈ B∗ , y ∈ Bn−1 }.
L1 ist the set of all words over B which do not contain a one. L4 is the set of all worfs over B
where the nth position from the end is a one.

If not explicitly stated, w denotes a (possibly empty) word w ∈ Σ∗ and σ an input symbol
σ ∈ Σ.
Let L ⊆ Σ∗ . The complement of L is definde as L = Σ∗ − L. Hence, for every w ∈ Σ∗ we have
eitherL or L; L is partitioning Σ∗ in two parts.
For a subset Γ ⊆ Σ |w|Γ is the number of occurences of symbols from Γ in w. for singleton
sets, we use the notation |w|a instead of |w|{a} .
9.2 Automata 63

9.2 Automata
Definition 9.7 (NFA) A Nondeterministic Finite Automaton (NFA) M is a tuple
M = (Q, Σ, δ , q0 , F)
where
Q is a non-empty finite set of states
Σ is a non-empty finite set of symbols
q0 ∈ Q is the initial state
F ⊆Q is a set of final states
δ : Q × Σ → 2Q the transition function.
Σ∗ denotes the set of all inputs for M including the empty word ε. The set of all non-empty inputs
is denoted by Σ+ := Σ∗ − {ε}. The length of an input |w| is the number of symbols it consists of,
we have |ε| = 0. If not mentioned differently, w denotes a (potentially empty) input w ∈ Σ∗ and
σ denotes a symbol σ ∈ Σ. Furthermore i, j, k, m and n denote natural numbers (including 0). We
also use the notation a ≤ i ≤ b for i ∈ {a, a + 1, . . . , b}. For a set A, |A| denotes the cardinality
of the set and the set of all subsets is given by 2A . Sometimes, the alphabet symbols for the
automata under consideration are sets over a finite set of atomic propositions of a propositional
logic AP, i.e. Σ = 2AP .. In this case, we also use the symbolic notation for transitions of the
automata, particular in depictions. For a formula φ over AP, φ refers to the set of sets of atomic
propistions which satisfy φ = {A ∈ 2AP | A |= φ }.
Definition 9.8 (Extended δ -function) Let M = (Q, Σ, δ , q0 , F) an NFA with δ : Q × Σ → 2Q . We
define
δ̂ : 2Q × Σ∗ → 2Q
as follows:
δ̂ (A, ε) := A for all A ∈ 2Q
for all A ∈ 2Q , w ∈ Σ∗ , σ ∈ Σ.
S
δ̂ (A, wσ ) := δ (q, σ )
q∈δ̂ (A,w)

For subsets of Q consisting of a single element, we also may drop the brackets in the notation.
Also, we will refer to δ̂ simply by δ .
Definition 9.9 The language T (M) accepted by an NFA M = (Q, Σ, δ , q0 , F) is defined as
T (M) := {w ∈ Σ∗ | δ (q0 , w) ∩ F ̸= 0}.
/
Two automata M and M ′ are called equivalent if T (M) = T (M ′ ). The set of all languages
which can be accepted by an NFA is called regular languages. The set of regular languages is
closed under concatenation, intersection, union, Kleene-∗, homomorphims and inverse homo-
morphisms. We will look into some of these operations in detail later.
Automata are often specified using a table for the specification of the δ -function. Moreover,
they can be represented by a transition diagram (see Tasks).
64 9 Finite Automata

a,b

a a,b a,b a,b


start q0 q1 q2 ··· qn

Figure 9.1: NFA with n + 1 states for which each equivalent DFA has at least 2n states.

Definition 9.10 (DFA) A finite automaton M = (Q, Σ, δ , q0 , F) is called Deterministic Finite Au-
tomaton (DFA) if

|δ (q, σ )| = 1 for all q ∈ Q, σ ∈ Σ.

For a DFA, we have |δ (q, w)| = 1 for all q ∈ Q and w ∈ Σ∗ . Consequently, we can use an extended
δ -function δ̌ : Q × Σ∗ → Q which we also refer to as δ .

Theorem 9.11 For every NFA M with n states there is a DFA M ′ with 2n states and T (M ′ ) =
T (M).

Proof. Let M = (Q, Σ, δ , q0 , F) be an NFA with |Q| = n. We construct a DFA M ′ := (Q′ , Σ, δ ′ , [q0 ], F ′ )
via the so-called power set construction:

Q′ := {[A] | A ∈ 2Q }
F′ := {[A] ∈ Q′ | A ∩ F ̸= 0}
/
δ ′ ([A], σ ) := [δ (A, σ )] for all A ∈ 2Q , σ ∈ Σ.

States in M ′ are all sets of states from M. We can prove by induction: For all w ∈ Σ∗ we have:

δ (q0 , w) = A ⇔ δ ′ ([q0 ], w) = [A],

Thus we have

w ∈ T (M) ⇔ δ (q0 , w) = A ∧ A ∩ F ̸= 0/
⇔ δ ([q0 ], w) = [A] ∧ [A] ∈ F ′

⇔ w ∈ T (M ′ ).

We have T (M ′ ) = T (M) and M ′ has 2n states. □

In the above construction, each NFA with n states is converted into a DFA with 2n states, i.e.
there is an exponential blow-up in the number of states. While this construction may sometimes
yield an DFA for which equivalent smaller DFA exist, there are cases in which the construction
yields a minimal DFA:
Fact 9.12 There exists an infinite sequence of languages Li , i ≥ 1 such that there is an NFA Mi
for Li with n states but every equivalent DFA needs at least 2n states.
9.3 Closure Properties 65

While we will just state this as fact, we will now consider an example for which we almost
achieve such an exponential blow-up in the number of states.

Example 9.13 Consider the NFA with n states in Figure 9.1 which operates over Σ = {a, b}.
It operates as follows: In the initial state q0 , the automaton has the choice to remain in q0 for
arbitrary symbols or -in case the input symbol is an a, to proceed to q1 . From qi , 1 ≤ i < n the
automaton proceeds to qi+1 for any input symbol. qn is accepting and has no transition to other
states. In other words, the automaton accepts an input if the n-th position from the end of the
input is an a,

T (M) = {w ∈ Σ∗ |w = w0 aw1 where w0 , w1 ∈ Σ∗ and |w1 | = n − 1}.

The NFA ”guesses” if an a it sees is at the nth position before the end or not. If not, it remains

in q0 , if yes, it moves to q1 .
Every DFA for T (M) need at least 2n states. Suppose for the sake of contradiction that there
was a DFA M = (Q, Σ, δ , q0 , F) with less than 2n states. Then, there are two x, y ∈ Σn , x ̸= y.
where δ (q0 , x) = δ (q0 , y) (since there are 2n such words). Since x and y are different, they dif-
fer in at least one position. W.l.o.g. we may assume that x = x1 az and y = y1 bz, |x1 | = |y1 | =
n − 1 − |z|. As xan−1−|z| is in L, we have δ (q0 , xan−1−|z| ) ∈ F. However, δ (q0 , xan−1−|z| ) =
δ (δ (q0 , x), an−1−|z| ) = δ (δ (q0 , y), an−1−|z| ) = δ (q0 , yan−1−|z| ). Therefore, yan−1−|z| will be ac-
cepted by M. However, yan−1−|z| ) ∈ / L, contradiction.

9.3 Closure Properties


Definition 9.14 Let L, L1 , L2 ⊆ Σ∗ be languages over Σ. The concatenation of L1 with L2 , L1 L2
is defined by
L1 L2 := {xy ∈ Σ∗ | x ∈ L1 and y ∈ L2 }.
Define L0 := {ε} and Li := LLi−1 . The Kleene-closure of L, notation L∗ , ist defined as

L∗ :=
[
Li .
0≤i≤∞

The positive closure L+ of L is


L+ :=
[
Li .
1≤i≤∞

Lemma 9.15 Let L1 and L2 be regular languages. Then L1 L2 is a regular language

Proof. Let L1 ⊆ Σ∗ and L2 ⊆ Σ∗ be two regular languages. Then, there are two NFA M1 =
(Q1 , Σ, δ1 , q10 , F1 ) and M2 = (Q2 , Σ, δ2 , q20 , F2 ) with T (M1 ) = L1 and T (M2 ) = L2 . Without loss of
generality we assume Q1 ∩ Q2 = 0. / We construct M = (Q1 ∪ Q2 , Σ, δ , q10 , F) where

 δ1 (q, σ ) if q ∈ Q1 − F1
δ (q, σ ) := δ1 (q, σ ) ∪ δ (q20 , σ ) if q ∈ F1

δ2 (q, σ ) if q ∈ Q2
66 9 Finite Automata

for all q ∈ Q, σ ∈ Σ and 


F2 if ε ∈
/ T (M2 )
F :=
F1 ∪ F2 if ε ∈ T (M2 )
By induction on |w| we can prove for all w ∈ Σ+ :

p ∈ δ (q10 , w) ⇐⇒ p ∈ δ1 (q10 , w) or there is a partitioning w = w1 w2 , w2 ∈ Σ+


and an f ∈ F1 with f ∈ δ1 (q10 , w1 )
and p ∈ δ2 (q20 , w2 ).

It is thus not difficult to prove T (M) = T (M1 )T (M2 ) = L1 L2 . □

Lemma 9.16 Let L1 and L2 be regluar languages. Then, L1 ∪ L2 is a regular language.

Proof. Let L1 ⊆ Σ∗ and L2 ⊆ Σ∗ be two regular languages. Then, there are two NFA M1 =
(Q1 , Σ, δ1 , q10 , F1 ) and M2 = (Q2 , Σ, δ2 , q20 , F2 ) with T (M1 ) = L1 und T (M2 ) = L2 . Without loss of
generality we assume Q1 ∩ Q2 = 0/ and q0 ∈ / Q1 ∪ Q2 a new state. We construct M = (Q1 ∪ Q2 ∪
{q0 }, Σ, δ , q0 , F) with

 δ1 (q, σ ) if q ∈ Q1
δ (q, σ ) := δ2 (q, σ ) if q ∈ Q2
δ1 (q10 , σ , ) ∪ δ2 (q20 , σ ) if q = q0

for all q ∈ Q, σ ∈ Σ and



{q0 } ∪ F1 ∪ F2 if ε ∈ T (M1 ) ∪ T (M2 )
F :=
F1 ∪ F2 else
for all q ∈ Q.
By induction on |w| we can prove: For all w ∈ Σ+ we have

p ∈ δ (q0 , w) ⇐⇒ p ∈ δ1 (q10 , w) or p ∈ δ2 (q20 , w)

Thus, it is not difficult to prove T (M) = T (M1 ) ∪ T (M2 ) = L1 ∪ L2 . □

Lemma 9.17 If L is a regular language, then L∗ is a regular language.

Proof. Let L ⊆ Σ∗ be a regular language. Then, there is an NFA M = (Q, Σ, δ , q0 , F) with


T (M) = L. Let q′0 ∈
/ Q be a new state. We construct an NFG M ′ = (Q ∪ {q′0 }, Σ, δ ′ , q′0 , F ′ ∪ {q′0 })
with 
 δ (q, σ ) if q ∈ Q − F
δ ′ (q, σ ) := δ (q, σ ) ∪ δ (q0 , σ ) if q ∈ F
δ (q0 , σ ) if q = q′0

for all q ∈ Q, σ ∈ Σ.
9.4 Regular Expressions 67

By induction over |w| it is possible to prove: For all w ∈ Σ+ we have


p ∈ δ (q′0 , w) ⇐⇒ there is an m ≥ 1 such that
w = w1 . . . wm , wi ∈ Σ+ 1 ≤ i ≤ m, fi ∈ F, 1 ≤ i < m
with fi ∈ δ (q0 , wi ), 1 ≤ i ≤ m and p ∈ δ (q0 , wm ).
It is not difficult to show T (M ′ ) = T (M)∗ = L∗ . □

Lemma 9.18 Let L1 and L2 be regular languages. Then, L1 ∩ L2 is a regular language.


Proof. Let L1 ⊆ Σ∗ and L2 ⊆ Σ∗ be two regular languages. Then, there are two DFA M1 =
(Q1 , Σ, δ1 , q10 , F1 ) and M2 = (Q2 , Σ, δ2 , q20 , F2 ) with T (M1 ) = L1 und T (M2 ) = L2 . We construct
M = (Q1 × Q2 , Σ, δ , (q10 , q20 ), F) with
δ ((p, q), σ ) := (δ1 (p, σ ), δ2 (q, σ )) for all σ ∈ Σ, p ∈ Q1 and q ∈ Q2
and
F := {(p, q) ∈ Q | p ∈ F1 and q ∈ F2 }.
By induction on |w| we can prove: For all w ∈ Σ∗ we have
(p, q) = δ ((q10 , q20 ), w) ⇐⇒ p = δ1 (q10 , w) and q = δ2 (q20 , w)
Thus, it is not difficult to prove T (M) = T (M1 ) ∩ T (M2 ) = L1 ∩ L2 . □

9.4 Regular Expressions


Regular languages can also be expressed by regular expressions:
Definition 9.19 Let Σ be an alphabet. The set of all regular expressions over Σ is defined as
follows:
• 0/ is a regular expression
• ε is a regular expression
• a is a regular expression for all a ∈ Σ
• if α and β are regular expressions, then (α ∗ ), (α + β ) and (αβ ) are regular expressions.
According to the following definitions, every regular expression γ is associated to a language
over Σ as follows:


 0/ if γ = 0/




 {ε} if γ = ε
{a} if γ = a for an a ∈ Σ

L(γ) :=

 L(α)∗ if γ = (α ∗ ) for a regular expression α




 L(α) ∪ L(β ) if γ = (α + β ) for regular expressions α, β
L(α)L(β ) if γ = (αβ ) for regular expressions α, β .

68 9 Finite Automata

Regular expressions are for reasons of distinction often printed in bold. The language associated
with a regular expression is uniquely defined due to the bracketing. The following precedeces
are used to simplify regular expressions: ∗ before concatenation and concatenation before +.
Hence, the regular expression ((((ab)b)∗ ) + (b(a∗ ))) can be simplified to (abb)∗ + ba∗ . For a
regular expression αα ∗ , we also use the simplification α + . We also use a regular expression γ
synonymously for L(γ).

Example 9.20 Here are a few examples for regular expressions:


• L = {ab}. The word ab: ab
• L = {xay ∈ {a, b} | x, y ∈ {a, b}∗ }. The set of all words over {a, b} containing at least one
a: (a + b)∗ a(a + b)∗
• L = {am bn c | m ≥ 1, n ≥ 0}. The set of all words over {a, b, c}, which contain at first a
sequence of (at least one) a, then a sequence of bs or no b and then exactly one c:a+ b∗ c

Lemma 9.21 Let γ be a regular expression. Then L(γ) is a regular language.


Proof. Proof by induction over the number of operators in γ.
/ ε or a for an a ∈ Σ. It is
Basis for induction (no operators). The regular expression is either 0,
easy to construct an NFAM with T (M) = 0, / T (M) = ε or T (M) = {a}. Thus, L(γ) is regular.
Induction step: Assume the the statement is true for regular expressions with n operators.and
γ is a regular expression with n + 1 operators. There are three cases:
1. γ = α ∗ for a regular expression α with n operators. We have L(γ) = L(α)∗ . According to
the inductive hypothesis L(α) is a regular language. According to Lemma 9.17 L(α)∗ =
L(γ) is also regular.
2. γ = (α + β ). Then α, β are regular expressions with at most n operators and we have
L(γ) = L(α) ∪ L(β ). According to the inductive hypothesis L(α) and L(β ) are regular
languages. According to Lemma 9.16 L(γ) = L(α) ∪ L(β ) is also regular.
3. γ = (αβ ). α, β are regular expressions with at most n Operators and we have L(γ) =
L(α)L(β ). According to the inductive hypothesis L(α) and L(β ) are regular languages.
According to Lemma 9.15 L(γ) = L(α)L(β ) is also regular.

Lemma 9.22 Let L be a regular language. Then, there is a regular expression γ with L = L(γ).
Proof. Let L be regular. Then, there is a DFA M = (Q, Σ, δ , q1 , F) mit T (M) = L. Without loss
of generality we assume the states in M to be numbered from 1 to n: Q = {q1 , . . . , qn }. We define
(k)
Ri, j := {w ∈ Σ∗ | δ (qi , w) = q j and for all ql ∈ Q and w1 , w2 ∈ Σ+
with w = w1 w2 and δ (qi , w1 ) = ql
we have l ≤ k}.
9.4 Regular Expressions 69

(k)
Intuitively, Ri, j consists of the set of all words over Σ, with which one in M gets from state qi to
state q j without going over intermediate states with an index number higher than k.
S (n)
It is not difficult to show T (M) = qr ∈F R1,r .
(k) (k)
We now prove by induction over k: There is a regular expression ri, j with L(ri, j ) = Rki, j .
Basis for Induction k = 0. For k = 0 no intermediate states at all can be present. Thus, we have

(0)
Ri, j = {a ∈ Σ | δ (qi , a) = q j } ∪ {ε | i = j}.

(0)
It is easy to construct a regular expression for Ri, j .
(k+1)
Suppose the inductive hypothesis is valid for k < n. We consider Ri, j . We have

(k+1) (k) (k) (k) (k)


Ri, j = Ri, j ∪ Ri,k+1 (Rk+1,k+1 )∗ Rk+1, j ,

(k+1) (k)
as every w ∈ Ri, j either does not pass through stateqk+1 and is already contained inRi, j or state
(k) (k) (k)
k + 1 is passed once or multiple times, in which case w is contained in Ri,k+1 (Rk+1,k+1 )∗ Rk+1, j .
(k) (k) (k) (k)
Due to the inductive hypothesis, there are regular expressions ri, j , ri,k+1 , rk+1,k+1 and rk+1, j with
(k) (k) (k) (k) (k) (k) (k) (k)
L(ri, j ) = Ri, j , L(ri,k+1 ) = Ri,k+1 , L(rk+1,k+1 ) = Rk+1,k+1 and L(rk+1, j ) = Rk+1, j .
Thus, we have for the regular expression

(k+1) (k) (k) (k) (k)


ri, j := ri, j + ri,k+1 (rk+1,k+1 )∗ rk+1, j

(k+1) (k+1)
L(ri, j = Ri, j .
(n)
A regular expression for T (M) can be constructed by building the union over r1, j for all q j ∈ F
(plus-operator). □

Example 9.23 Consider the following DFA:

Start q a q a q
1 2 3

b
a,b
70 9 Finite Automata

We have
(0)
r1,1 = ε +b
(0)
r1,2 = a
(0)
r1,3 = 0/
(0)
r2,1 = b
(0)
r2,2 = ε
(0)
r2,3 = a
(0)
r3,1 = a+b
(0)
r3,2 = 0/
(0)
r3,3 = ε

(1) (0) (0) (0) (0)


r1,1 = r1,1 + r1,1 (r1,1 )∗ r1,1 = ε + b + (ε + b)(ε + b)∗ (ε + b) = b∗
(1) (0) (0) (0) (0)
r1,2 = r1,2 + r1,1 (r1,1 )∗ r1,2 = a + (ε + b)(ε + b)∗ a = b∗ a
(1) (0) (0) (0) (0)
r1,3 = r1,3 + r1,1 (r1,1 )∗ r1,3 = 0/ + (ε + b)(ε + b)∗ 0/ = 0/
(1) (0) (0) (0) (0)
r2,1 = r2,1 + r2,1 (r1,1 )∗ r1,1 = b + b(ε + b)∗ (ε + b) = b+
(1) (0) (0) (0) (0)
r2,2 = r2,2 + r2,1 (r1,1 )∗ r1,2 = ε + b(ε + b)∗ a = ε + b+ a
(1) (0) (0) (0) (0)
r2,3 = r2,3 + r2,1 (r1,1 )∗ r1,3 = a + b(ε + b)∗ 0/ = a
(1) (0) (0) (0) (0)
r3,1 = r3,1 + r3,1 (r1,1 )∗ r1,1 = a + b + (a + b)(ε + b)∗ (ε + b) = (a + b)b∗
(1) (0) (0) (0) (0)
r3,2 = r3,2 + r3,1 (r1,1 )∗ r1,2 = 0/ + (a + b)(ε + b)∗ a = (a + b)b∗ a
(1) (0) (0) (0) ∗ (0)
r3,3 = r3,3 + r3,1 (r1,1 ) r1,3 = ε + (a + b)(ε + b)∗ 0/ = ε

(2) (1) (1) (1) (1)


r1,1 = r1,1 + r1,2 (r2,2 )∗ r2,1 = b∗ + (b∗ a)(ε + b+ a)∗ b+ = b∗ + b∗ a(b+ a)∗ b+
(2) (1) (1) (1) (1)
r1,2 = r1,2 + r1,2 (r2,2 )∗ r2,2 = b∗ a + (b∗ a)(ε + b+ a)∗ (ε + b+ a) = b∗ a + b∗ a(b+ a)∗
(2) (1) (1) (1) (1)
r1,3 = r1,3 + r1,2 (r2,2 )∗ r2,3 = 0/ + (b∗ a)(ε + b+ a)∗ a = b∗ a(b+ a)∗ a
(2) (1) (1) (1) (1)
r2,1 = r2,1 + r2,2 (r2,2 )∗ r2,1 = b+ + (ε + b+ a)(ε + b+ a)∗ b+ = (b+ a)∗ b+
(2) (1) (1) (1) (1)
r2,2 = r2,2 + r2,2 (r2,2 )∗ r2,2 = ε + b+ a + (ε + b+ a)(ε + b+ a)∗ (ε + b+ a) = (b+ a)∗
(2) (1) (1) (1) (1)
r2,3 = r2,3 + r2,2 (r2,2 )∗ r2,3 = a + (ε + b+ a)(ε + b+ a)∗ a = (b+ a)∗ a
(2) (1) (1) (1) ∗ (1)
r3,1 = r3,1 + r3,2 (r2,2 ) r2,1 = (a + b)b∗ + ((a + b)b∗ a)(ε + b+ a)∗ b+
= (a + b)b∗ + (a + b)b∗ a(b+ a)∗ b+
(2) (1) (1) (1) (1)
r3,2 = r3,2 + r3,2 (r2,2 )∗ r2,2 = (a + b)b∗ a + ((a + b)b∗ a)(ε + b+ a)∗ (ε + b+ a)
= (a + b)b∗ a(b+ a)∗
(2) (1) (1) (1) (1)
r3,3 = r3,3 + r3,2 (r2,2 )∗ r2,3 = ε + ((a + b)b∗ a)(ε + b+ a)∗ a
= ε + (a + b)b∗ a(b+ a)∗ a

(3) (3)
For ri, j we only calulate r1,3 , as q3 is the only accepting state.
9.5 Modeling Automata in Promela 71

(3) (2) (2) (2) (2)


r1,3 = r1,3 + r1,3 (r3,3 )∗ r3,3
= b∗ a(b+ a)∗ a + b∗ a(b+ a)∗ a(ε + (a + b)b∗ a(b+ a)∗ a)∗ (ε + (a + b)b∗ a(b+ a)∗ a)
= b∗ a(b+ a)∗ a((a + b)b∗ a(b+ a)∗ a)∗
3 ).
We have T (M) = L(r1,3

9.5 Modeling Automata in Promela


Finite automata can be easiliy implemented in Promela. In contrast to programming languages
and due to its nondeterministic features, this also holds for NFAs.

Example 9.24 Consider the DFA from 9.23. An example for a Promela model for the automaton
is as follows (we use 0 for a and 1 for b for simplification):
Listing 9.1: NFA from Figure 9.23 in Promela.
1 # define N 10
2 byte input[N+1] = { 0, 1, 1, 0, 1, 0, 1, 0, 1, 2 }
3 byte state = 1
4 active proctype automaton() {
5 int ctr = 0
6 byte what
7 do
8 :: atomic { what = input[ctr]-> ctr++;
9 if ::(what == 0 && state == 1) -> state = 2; printf("|q1|␣-a->")
10 ::(what == 1 && state == 1) -> state = 1; printf("|q1|␣-b->")
11 ::(what == 0 && state == 2) -> state = 3; printf("|q2|␣-a->")
12 ::(what == 1 && state == 2) -> state = 1; printf("|q2|␣-b->")
13 ::(what == 0 && state == 3) -> state = 1; printf("|q3|␣-a->")
14 ::(what == 1 && state == 3) -> state = 1; printf("|q3|␣-b->")
15 ::(what == 2 && state != 3) -> printf("|q3|.");goto reject
16 ::(what == 2 && state == 3) -> printf("|q%d.",what);goto accept
17 fi
18 }
19 od
20

21 accept:
22 printf("Input␣accepted.\n")
23 assert(false)
24 goto end
25

26 reject:
72 9 Finite Automata

27 printf("Input␣rejected.\n")
28

29 end:
30 printf("The␣End\n")
31 }

Thus, finite automata can be used in Promela to specify program features for verification. In
most cases however, the automata for checking properties are created automatically, not manu-
ally.

9.6 Tasks
Task 9.1:
Consider the following automaton:
b b

start q0 q1
a

a a

q3 a q2

b b

1. Describe the automaton formally. Is it an NFA or DFA?

2. Explain what the automaton is doing.

3. Specify the language it accepts as formally as possible.

4. What would change if F = {q1 } or F = {q0 , q2 }? Also give formal definitions for the
languages.

Task 9.2:
Consider L = {0, 10, 110}.
1. Write down L0 , L1 , L2 and L3 .

2. Write down L∗ .

3. Which of the following words are not in L∗ ? and why?


9.6 Tasks 73

• ε
• 0000100001100000
• 11011010010
• 00111010010010110
• 00000000001110010
• 00000000101100000110

Task 9.3:
Consider L = {ε, ab, baa, aabaa}.

1. Calculate L0 , L1 and L2 .

2. Calculate L∗ and L+ .

3. What changes for L0 , L1 , L2 , L∗ and L+ , respecively if you consider L − {ε}?

Task 9.4:

1. Construct an NFA M1 with

T (M1 ) = {w ∈ {a, b}∗ | the number of as in w is even}

and an NFA M2 with

T (M2 ) = {w ∈ {a, b}∗ | the number of bs in w is odd}.

Formally define both automata and draw their transition diagrams.

2. Using the construction from Lemma 9.15, construct an automaton M ′ with T (M ′ ) = T (M1 )T (M2 ).
Give a formal definition for the automata and draw its transition diagram.

3. Using the construction from Lemma 9.15, construct an automaton M ′′ with T (M ′′ ) =


T (M1 ) ∪ T (M2 ). Give a formal definition for the automata and draw its transition diagram.

4. Construct an automaton for T (M1 ) ∩ T (M2 ).

Task 9.5:
Let L ⊆ Σ∗ be language. When does L∗ = L+ ? hold? Prove your solution.

Task 9.6:
Give Regular Expressions for the following languages:
74 9 Finite Automata

1. The set of all words over the alphabet {a, b, c}, in which there is at least one a and at least
one b.

2. The set of all words over the alphabet {a, b, c}, in which there is at most one c.

3. The set of all words over the alphabet {0, 1}, in which at least two consecutive 1s occur.

4. The set of all words over the alphabet {0, 1}, in which exactly two consecutive 1s occur.

5. The set of all words over the alphabet {0, 1}, in which the number of 0 is even.

Task 9.7:
Construct a DFA M for

T (M) = {w ∈ Σ∗ |w = w0 aw1 where w0 , w1 ∈ Σ∗ and |w1 | = n − 1}.

and prove its correctness.

Task 9.8:
Consider an NFA M = (Q, 2AP , δ , q0 , F) with AP = {a, b, c}. For the following propositional
formulae, specify the set of input symbols which are represented by the following propositional
formulae:

1. true

2. f alse

3. ¬a

4. a ∧ ¬b

5. ¬a ∧ b ∧ ¬c

6. ¬a ∧ ¬b ∧ ¬c

7. ¬a ∧ b ∧ ¬c if AP = {a, b, c, d}

Task 9.9:
Prove or disprove the following for two regular expressions: r and s.

1. r + s = s + r

2. (r + s)∗ = r∗ + s∗

3. 0/ ∗ = ε

4. s(rs + s)∗ r = rr∗ s(rr∗ s)∗


9.6 Tasks 75

5. (r∗ s∗ )∗ = (r + s)∗

Task 9.10:
Consider the NFA from Figure 9.1. Implement the FA as Promela model for n = 50 in the
following template
1 # define N 50
2 byte state = 0 // holds state number
3 byte input[N+1] // holds input symbols from 0 to N-1 and end delimiter at N
4

5 active proctype automaton{


6

7 /* code to be added */
8

9 }

Task 9.11:
In the following, we consider Σ = {a, b}.

1. Construct a DFA M1 such that

T (M1 ) = {w ∈ Σ∗ | |w|a is not divisible by 3}.

2. Construct a DFA M2 such that

T (M2 ) = {w ∈ Σ∗ | |w|a is divisible by 2}.

3. Construct an NFA M such that T (M) = T (M1 ) ∪ T (M2 ).

4. Construct a DFA M such that T (M) = T (M1 ) ∩ T (M2 ).


10 Büchi Automata

Required Reading before Proceeding


• [19]

10.1 Fundamentals
For ω-languages, various finite state automata models have been proposed (see e.g., [22, 24,
26]). Here, we focus on “Büchi-Automata” [20] as they are the most elementary automaton
model for infinite languages. Büchi Automata resemble Finite Automata but use a different
acceptance condition. “Büchi-Automata” resemble “regular” (deterministic or nondeterministic)
FAs as defined in the previous with an altered acceptance criterion. Throughout this paper, we
refer to NFAs used to accept infinite languages as NBA (or DBA if |δ (q, σ )| ≤ 1 for all states
and input symbols). Let Σω denote the set of all words over Σ having infinite length.
Definition 10.1 A run of an NBA M = (Q, Σ, δ , q0 , F) on an ω-word x = x0 x1 · · · ∈ Σω is a se-
quence of states of M ρ(x) = ρ0 ρ1 . . . such that ρ0 = q0 and ρi+1 ∈ δ (ρi , xi ) for i ≥ 0. We define
Inf (ρ(x)) = {q ∈ Q | there exist infinitely many i such that ρi = q} as the set of states that occur
infinitely often in the computation ρ(x) of M on x. We call ρ(x) successful if Inf (ρ(x)) ∩ F ̸= 0, /
i.e., if there is at least one state q ∈ F that appears infinitely often in ρ(x). A string x ∈ Σω is
accepted by M if there is a successful run of M on x. The ω-language recognized by M is defined
by Tω (M) = {x ∈ Σω | M accepts x}.
Two BA M and M ′ are considered equivalent iff Tω (M) = Tω (M ′ ).
A Büchi-Automaton is called reduced if from every state there is a path to an accepting state
(i.e. no trap states). For any Büchi-Automaton M it is possible to construct an equivalent reduced
Büchi-Automaton M ′ accepting the same languate by simply deleting every state from which no
accepting state is reachable.
The set of languages which are recognizable by an NBA is the set of regular ω-languages. An
NBA M is called deterministic (DBA) if |δ (q, σ )| ≤ 1 for all states and input symbols. Since for
Σ = {a} the language accepted by an NBA is either empty or aω , we assume that all automata
operate over an at least binary alphabet, |Σ| ≥ 2.
Let L ⊆ Σ∗ be a language. The Eilenberg-limit of L is defined by lim(L) = {w ∈ Σω | there
exist infinitely many prefixes x of w, such that x ∈ L} [21].
It is known that the language Tω (M) of an ω-DFA M is exactly the Eilenberg-limit of the
regular language that is accepted by M when it is interpreted as a traditional DFA, i.e., Tω (M) =
lim(T (M)). Thus, for two DFA M,M ′ with T (M) = T (M ′ ) we have Tω (M) = Tω (M ′ ).
However, we need to be careful when considering eqiivalence of automata as, in general,
equivalence in the case of infinite languagages does not imply equivalence for regular languages
78 10 Büchi Automata

a,b b

start q0 q1
b

Figure 10.1: NBA with Tω (M) = (a + b)∗ bω .

and vice-versa: There are nondeterministic automata M and M ′ such that T (M) = T (M ′ ) but
Tω (M) ̸= Tω (M ′ ) (even already over a unary alphabet). Consider, e.g., the following Automata
M on the left and M ′ on the right hand side:

a a

start q0 q1 start q0 q1
a a

for which we have T (M) = T (M ′ ) = {an | n ≥ 1} but Tω (M) = {aω } ̸= 0/ = Tω (M ′ ).


Also, there are even deterministic automata (and even over unarry alphabet) with Tω (M) =
Tω (M ′ ) but T (M) ̸= T (M ′ ). Consider M on the left hand side and M ′ on the right:

a a
start q0 q1 start q0 q1
a a

We have Tω (M) = Tω (M ′ ) = {aω } but T (M) = {a2n+1 |n ≥ 0} and T (M ′ ) = {a2n |n ≥ 0}


While the descriptive power of nondeterminisic and deterministic finite automata is equivalent,
this is not the case for Büchi automata:

Theorem 10.2 There is a language L which can be accepted by an NBA while there is no DBA
accepting L.

Proof. Consider the Language L = (a + b)∗ bω . There is a nondeterministic Büchi Automation


with two states accepting L which is shown in Figure 10.1. Suppose there was a deterministig
Büchi-Automaton M = (Q, Σ, δ , qo , F) accepting L.
Since bω ∈ L, there is some prefix w0 = bi0 of bω with 1 ≤ i0 ≤ n such that we have δ (q0 , w0 ) =
p0 ∈ F. As w0 abω ∈ L, we also can find a prefix w1 = abi1 for some 1 ≤ i0 ≤ n such that
δ (q0 , w0 w1 = p1 ∈ F . Continuing this argument, we can find prefixes w j = abi j for some
1 ≤ i j ≤ n and all j ≥ 2 such that δ (q0 , w0 w1 . . . w j ) = p j ∈ F. Consider the n + 1 prefixes
w0 , w0 w1 , . . . , w0 w1 . . . wn As M has only n states, there are 0 ≤ i < j ≤ n such that

δ (q0 , w0 w1 . . . wi ) = pi = p j = δ (q0 , w0 w1 . . . w j ).
10.2 ω-Regular Expressions 79

Thus, we have δ (pi , wi+1 . . . w j ) = pi , and we find w0 . . . wi (wi+1 . . . w j )ω ∈ Tω (M), a contra-


diction as this word contains infinitely many as. □

The following theorem states that Büchi-Automata are closed under intersection:

Theorem 10.3 Let M1 = (Q1 , Σ, δ1 , q10 , F1 ) and M2 = (Q2 , Σ, δ2 , q20 , F2 be two Büchi-Automata.
Then, there is a Büchi-Automaton M with Tω (M) = Tω (M1 ) ∩ Tω (M2 ).

Proof. We define M = (Q, Σ, δ , [q10 , q20 , 1], F) where

Q = Q1 × Q2 × {1, 2}
F = Q1 × F2 × {2}

and for all σ ∈ Σ, q1 ∈ Q1 , q2 ∈ Q2 , δ is given by



{[p1 , p2 , 1] | p1 ∈ δ1 (q1 , σ ), p2 ∈ δ2 (q2 , σ ) and p1 ∈
/ F1 }
δ ([q1 , q2 , 1], σ ) =
{[p1 , p2 , 2] | p1 ∈ δ1 (q1 , σ ), p2 ∈ δ2 (q2 , σ ) and p1 ∈ F1 }

{[p1 , p2 , 2] | p1 ∈ δ1 (q1 , σ ), p2 ∈ δ2 (q2 , σ ) and p2 ∈
/ F2 }
δ ([q1 , q2 , 2], σ ) =
{[p1 , p2 , 1] | p1 ∈ δ1 (q1 , σ ), p2 ∈ δ2 (q2 , σ ) and p2 ∈ F2 }

We can prove by induction: Let w ∈ Σω be an infinite word. If ρ = (q10 , q20 , i0 )(q11 , q21 , i1 )(q12 , q22 , i2 ) . . .
is a run on w in M, then ρ1 := q10 , q11 , q12 . . . is a run on w in M1 and ρ2 := q20 , q21 , q22 . . . is a run on w
in M2 . Moreover, ρ1 and ρ2 are successful if ρ is successful. Thus, Tω (M) ⊆ Tω (M1 ) ∩ Tω (M2 ).
Also we can prove by induction: If ρ1 and ρ2 are successful runs on w in M1 and M2 respec-
tively, then there is an accepting run ρ on w in M, hence we have Tω (M1 ) ∩ Tω (M2 ) ⊆ Tω (M),
and Tω (M1 ) ∩ Tω (M2 ) = Tω (M) follows. □

10.2 ω-Regular Expressions


Definition 10.4 Let L be a language. Then, Lω denotes the set of all infinite words consisting of
concatenations of words from L,

Lω := {w1 w2 w3 . . . |, wi ∈ L, i ≥ i}

Definition 10.5 An ω-regular expression is defined as follows:

• For two regular expressions A and B with ε ∈


/ B, ABω is an ω-regular expression

• For two ω-regular expressions C and D, C + D is an ω-regular expression.

The language associated with an ω-regular expresssion is L(A)L(B)ω or L(C) ∪ L(D), respec-
tively.
80 10 Büchi Automata

Thus, all ω-regular expressions are of the form

A1 Bω ω ω
1 + A2 B2 + . . . + An Bn

for regular expressions Ai , Bi , 1 ≤ i ≤ n and ε ∈


/ Bi 1 ≤ i ≤ n.

Fact 10.6 For every ω-regular expression there is a Büchi-automaton accepting the same lan-
guage and vice-versa.

10.3 Generalized Büchi-Automata


Definition 10.7 A generalized (nondeterministic) Büchi-Automaton (GNBA) M is a tuple

M = (Q, Σ, δ , q0 , F )

where

Q is a non-empty finite set of states


Σ is a non-empty finite set of symbols
q0 ∈ Q is the initial state
F ⊆ 2Q is a nonempty set of sets of final states
Q
δ : Q×Σ → 2 the transition function.

A run ρ(x) on an x ∈ Σω is called successful if for all F ∈ F we have Inf (ρ(x)) ∩ F ̸= 0,


/ i.e.,
if for all F ∈ F there is at least one state q ∈ F that appears infinitely often in ρ(x). A string
x ∈ Σω is accepted by M if there is a successful run of M on x. The ω-language recognized by M
is defined by Tω (M) = {x ∈ Σω | M accepts x}.

In other words, a generalized Büchi-Automaton consists of a set sets of accepting states F =


{F1 , . . . , Fk }, Fi ⊆ Q, 1 ≤ i ≤ k and, in an accepting run, for all these Fi at least q ∈ Fi is reached
infinetely often.

Theorem 10.8 For every GNBA M = (Q, Σ, δ , q0 , F ) there is a NBA M ′ = (Q′ , Σ, δ ′ , q′0 , F) such
that Tω (M) = Tω (M ′ )

Proof. Let M = (Q, Σ, δ , q0 , F ) be a GNBA. Then, F = {F1 , F2 , . . . , Fk } for some finite 1 ≤ k ≤


|Q|
22 . Define the k NBA Mi = (Q, Σ, δ , q0 , Fi ). It is not difficult to show that
\
Tω (M) = Tω (Mi ).
1≤i≤k

Thus, the claim follows from Theorem 10.3. □

However, an NBA for Tω (M) can also be directly constructed by defining

M ′ := (Q′ , Σ, δ ′ , [q0 , 1], F ′ )


10.4 Safety Properties 81

where

Q′ := {[q, i] | q ∈ Q, i ∈ {1, 2, . . . , k}}



{[q, i] | q ∈ δ (p, a)} if q ∈
/ Fi
δ ′ ([p, i], a) :=
{[q, (i mod k) + 1] | q ∈ δ (p, a)} if q ∈ Fi
F′ := {[q, 1] | q ∈ F1 }

It is not difficult to prove Tω (M) = Tω (M ′ ) using similar arguments as in Theorem 10.3.

10.4 Safety Properties


[19]

Definition 10.9 (Property) A property P is a set of infinite sequences of program states. For an
infinite sequence σ , write σ |= P if σ is in property P.

Now we will define safety properies. Informally, a safety property is a property which stipu-
lates that something “bad” does not happen. The safety propery is fulfilled as long as this bad
thing does not happen. If it happens, it must happen after some finite prefix and once this “bad
thing” occurs, the property can no longer be fulfilled. In other words, if an infinite word fulfills
the property, something “bad” never happens. Formally, this means that for any finite prefix of
this infinite word it must be possible to cconcatenate this prefix with an infinite word such that
the resulting word also fulfills the property.

Definition 10.10 (Safety Property) A property is a called a safety property if for all σ ∈ Σω we
have σ |= P if and only if for all i ≥ 1 there is a β ∈ Σω such that σ [..i]β |= P. σ [..i] denotes the
prefix of length i from σ .

or, equivalently
Definition 10.11 (Safety Property Alt) A property is a called a safety property if for all σ ∈ Σω
we have σ ̸|= P if and only if there is an i ≥ 1 such that for all β ∈ Σω we have σ [..i]β ̸|= P.
Consider

Example 10.12 The language (a + b)∗ bω can be accepted by a NBA as depicted in Figure 10.1.
Consider aω ∈/ (a + b)∗ bω . However, for every n ≥ 1 we have an bω ∈ (a + b)∗ bω , thus (a + b)∗ bω
does not specify a safety property.

Definition 10.13 For every reduced Büchi-Automaton M = (Q, Σ, δ , q0 , F), we define the closure
of M as cl(M) = (Q, Σ, δ , q0 , Q), i.e., every state is turned into an accepting state.

Theorem 10.14 A reduced Büchi-Automaton specifies a safety property if and only if Tω (M) =
Tω (cl(M))
82 10 Büchi Automata

Proof. See [19]. □

Thus, the Büchi-Automaton only has accepting states. In other words, inputs which do not
have any accepting run and this violate the safety property, will, at some point, not have any con-
tinuation in the reduced Büchi-Automaton. If we apply the powerset construction to this reduced
Büchi-Automaton, this corresponds with all inputs which eventually reach the state representing
0.
/ Since all states are accepting, this automaton is a deterministic B"uchi-Automaton accepting
the same language. As all states of a Büchi-Automaton specifying a safety property can be made
accepting, the following follows:

Fact 10.15 Let P be a safety property over Σω which can be represented by a Büchi-Automaton
M, Tω (M) = P. Then, there is an equivalent DBA M ′ such that Tω (M) = Tω (M ′ ).

This automaton can be obtained by applying the power set construction to the reduced version of
the NBA. See, e.g., [29] for proof.
If we complement this DBA, making only the state representing 0/ accepting and all other states
non-accepting, we get a finite automaton which accepts the set of all bad prefixes of the property
the original Büchi-Automaton. Please note that these DFA have a special structure in that they
only have one accepting state which is never left for any input symbol. Intuitively, this state is
reached once the “bad thing” has happened.
This is also quite important for our model checking approaches: If a safety property is violated,
a finite counterexample of a run of the model may be given which clearly shows the violation of
the safety property.
We will summarize this now:

Definition 10.16 Let P be a safety property over Σω . The set of all bad prefixes of P, BadPre f (P) ⊆
Σ∗ is given by
BadPre f (P) = {α ∈ Σ∗ | ασ ̸∈ P for any σ ∈ Σω }.

Fact 10.17 Let P be a safety property over Σω which can be represented by a Büchi-Automaton
M, Tω (M) = P. Then, there is a DFA M ′ such that T (M ′ ) = BadPre f (Tω (M)).

Consider

Example 10.18 Let us for example consider the specification on mutual exclusion of two pro-
cesses A and B. We specify the properties csa and csb specifying that a and be are in their critical
section, respectively, and specify a Büchi-Automaton over the Alphabet Σ = {0, / {csA }, {csB }, {csA , csB }}
as depicted in Figure 10.2.
The Büchi-Automaton accepts the language {0, / {csA }, {csB }}ω . As DFA for BadPre f (Tω (M))
when applying the outlined construction from above, we obtain the DFA shown in Figure 10.3
which accepts the language {0, / {csA }, {csB }}∗ {csA , csB }{0,
/ {csA }, {csB }, {csA , csB }}∗ .

A special case of a safety property is an invariant. Intuitively, an invariant specifies a safety


property for which the “bad thing” can be identified regardless of the state the automaton has
reached, i.e. just by looking at the input symbols. Formally:
10.4 Safety Properties 83

¬(csa ∧ csb )

start q0

Figure 10.2: Büchi-Automaton for Mutual Exclusion of two processes A and B.

¬(csa ∧ csb )
true

start {q0 } {0}


/
csa ∧ csb

Figure 10.3: DFA for BadPre f for Mutual Exclusion of two processes A and B.

Definition 10.19 Let Σ be an alphabet. A property is called invariant if there is a ∆ ⊆ Σ and


P = ∆ω .

An invariant can be accepted by a reduced DBA with a single state as depicted in Figure 10.4.
The DBA loops in this state for all symbols σ ∈ ∆ and has no subsequent state for all σ ∈ Σ − ∆.
Clearly, the language accepted by this automaton is a safety property due to Theorem 10.14
as M = cl(M) and Tω (M) = Tω (cl(M)) holds. The example presented in 10.18 is, in fact, an
invariant.
Invariants are a special simple case of safety properties. There are also safety properties which
are not invariants and more complex. An example is the safety property (aaa∗ + b)ω in which
the “bad event” happens if less than two as occur . This property cannot be determined by just
looking at every single input symbol.

start q0

Figure 10.4: Büchi-Automaton for an Invariant.


84 10 Büchi Automata

true P

start q0 q1
P

Figure 10.5: NBA for Liveness Property

10.5 Liveness Properties


Definition 10.20 For a language L ⊆ Σ∗ or L ⊆ Σω , let pre(L) denote the set of all prefixes of
all words in L. We call Tω (M) a liveness language if pre(Tω (M)) = Σ∗ [18].

This definition is equivalent to the following characterization:

Definition 10.21 A property P is a called a liveness property if for all α ∈ Σ∗ there exists a β ∈
Σω such that αβ |= P.

Theorem 10.22 A reduced Büchi-Automaton specifies a liveness property if and only if Tω (cl(M)) =
Σω

Proof. See [19]. □

From the definition of liveness, important aspects for verification also follow. If a liveness
property is specified by a Büchi-automaton and violated by a program, there is no counterex-
ample in the sense of a single input which violates it. A counterexample is rather given by the
fact that there is an (infinite) run of the program which does not have any accepting run in the
automaton. Equivalently, there is an infinite run for a run of the program which does get accepted
by a Büchi-automaton accepting the complement of the liveness-property.

Example 10.23 Let us for example consider a Büchi-automaton assuring that a property P will
eventually hold forever (which is in fact the Automaton from Figure 10.1 with different labels)
in Figure 10.5. Clearly, it specifies a liveness property.

10.6 Characterizing Safety and Liveness


Theorem 10.24 For every reduced Büchi-Automaton M we can construct Büchi-Automata M1
and M2 such that M1 specifies a safety property, M2 specifies a liveness property, and Tω (M) =
Tω (M1 ) ∩ Tω (M2 )

Proof. see [19] □

Also, we have
10.7 Tasks 85

All Linear Time Properties

Safety

Invariants Liveness

Σω

Figure 10.6: Linear Time Properties.

Fact 10.25 The only property over Σ which is a safety and a liveness property is Σω .

This is easy to prove for Büchi-Automata: Let M be a reduced Büchi-Automaton specifying a


safety and a liveness property. Since M specifies a safety property, we have Tω (M) = Tω (cl(M))
according to Theorem 10.14. Since M specifies a liveness property, we have Tω (cl(M)) = Σω
according to Theorem 10.22. Thus,

Tω (M) = Tω (cl(M)) = Σω

A general proof would require an extended definition of the closure operation but is otherwise
identical.
Summarizing these results, we obtain the Venn diagram in Figure 10.6 of the linear time
properties discussed here.

10.7 Tasks
Task 10.1:

1. Give a definition for a Büchi-Automaton accepting all inputs with an infinite number of as
immediately followed by a b.

2. Present a Büchi-Automaton for (a + b)∗ aω + (a + b)∗ bω .

3. Present a definition for a Büchi-Automaton accepting all inputs over a, b with an infinite
number of six consecutive as.
86 10 Büchi Automata

Task 10.2:
Let Σ = {a, b, c}. Provide ω-regular expressions and a Büchi-Automaton for the following lan-
guages:

1. From some point on there is only c.

2. There are only finitely many a.

3. There are infinitely many b.

4. There is an a, which is eventually followed by a b.

5. Every a is eventually followed by a b

Task 10.3:
Specify the language the following Büchi-automaton acccepts:

a b

start q0 q1
b
a
a

q2

Task 10.4:
Prove that for every Büchi-Automaton there is a reduced Büchi-Automaton accepting the same
language.
11 Linear Temporal Logic

Required Reading before Proceeding


• [1], Chapter 5 pp. 225-294

11.1 Fundamentals
Definition 11.1 (LTL) Let AP be atomic propositions (symbols). A linear temporal logic for-
mula φ over AP is definded by:

• for all a ∈ AP, a is an LTL-formula,

• if φ is an LTL-formula, then ¬φ is an LTL-formula,

• if φ and ψ are LTL-formulae, φ ∧ ψ is an LTL-formula

• if φ is an LTL-formula, ⃝φ is an LTL-formula

• if φ and ψ are LTL-formulae, φ ∪ ψ is an LTL-formula.

The semantics is given as follows: Let σ = A0 A1 A2 A3 . . . ∈ (2AP )ω be an infinite word over


2APand φ be an LTL formula. We say that σ |= φ if

• φ = a for some a ∈ AP and a ∈ A0 ,

• φ = ¬φ1 and σ ̸|= φ1 ,

• φ = φ1 ∧ φ1 and σ |= φ1 and σ |= φ2

• φ = ⃝φ1 and σ1 |= φ1

• φ = φ1 ∪ φ2 and there is an j ≥ 0 such that for all 0 ≤ i < j we have σi |= φ1 and σ j |= φ2 ,

where σi denotes the suffix of σ starting with Ai , σi := Ai Ai+1 Ai+2 . . .


Let φ be an LTL-formula over the atomic propositions AP, we define

Words(φ ) = {σ ∈ (2AP )ω } | σ |= φ }.

Two formula φ and ψ are called eqivalent, notation φ = ψ, if Words(φ ) = Words(ψ). For a
set α ⊆ (2AP )ω we define α |= φ if and only if α ⊆ Words(φ ).
88 11 Linear Temporal Logic

Please note that σ |= φ ψ if σ |= ψ (special case j = 0 in the definition). Thus, intuitively


S

φ has to hold until ψ holds at a future position or the current one. Moreover, while σ |= φ ψ
S

implies that there is a minimal i ≥ 0 such that σi |= psi, the -operator does not necessarily refer
S

to the first position. For example, for AP = {a, b}, {a}{a}{b}(2AP )ω ∈ Words(true a ⃝ b).
S

Definition 11.2 (Derived Operators) Let φ and ψ be two LTL-formulae. For shortening LTL-
formulae, we use the following derived operators:

φ ∨ψ := ¬(¬φ ∧ ¬ψ) or
φ ⇒ψ := ¬φ ∨ ψ implication
φ ⇔ψ := (φ ⇒ ψ) ∧ (ψ ⇒ φ ) equivalence
φ ⊕ψ := (φ ∧ =
̸ ψ) ∨ (¬φ ∧ ψ) xor
true := φ ∨ ¬φ
f alse := ¬true
♢φ := true ∪ φ some time in the future
□φ := ¬♢¬φ from now on always

Convention: Unary operators take precedence over binary.

The operators ⃝, , ♢, □ are called temporal operators. A formula which does not use any
S

temporal operators is also called propositonal formula as definition and semantics coincide with
to so-called propositional logic.
Intuitively, the semantics of the temporal aspects can be depicted as follows:

• Atomic proposition a:

a arbitrary arbitrary arbitrary arbitrary

···

• ⃝φ :

arbitrary φ arbitrary arbitrary arbitrary

···

• φ ∪ ψ:

φ ∧ ¬ψ φ ∧ ¬ψ φ ∧ ¬ψ ψ arbitrary

···

also:
11.1 Fundamentals 89

ψ arbitrary arbitrary arbitrary arbitrary

···

• ♢φ :

¬φ ¬φ ¬φ φ arbitrary

···

also:

φ arbitrary arbitrary arbitrary arbitrary

···

• □φ :

φ φ φ φ φ

···

Fact 11.3 Let φ , ψ and χ be LTL-formulae. The following equivalences hold:

• Idempotence: φ ∨ φ = φ = φ ∧ φ

• Commutativity: φ ∨ ψ = ψ ∨ φ and φ ∧ ψ = ψ ∧ φ

• Associativity: φ ∨ (ψ ∨ χ) = (φ ∨ ψ) ∨ χ and φ ∧ (ψ ∧ χ) = (φ ∧ ψ) ∧ χ

• Distributivity: φ ∧ (ψ ∨ χ) = (φ ∧ ψ) ∨ (φ ∧ χ) and φ ∨ (ψ ∧ χ) = (φ ∨ ψ) ∧ (φ ∨ χ)

• Absorption: φ ∨ (φ ∧ ψ) = φ and φ ∧ (φ ∨ ψ) = φ

• Negation: ¬¬φ = φ

• De Morgan: ¬(φ ∨ ψ) = ¬φ ∧ ¬ψ and ¬(φ ∧ ψ) = ¬φ ∨ ¬ψ

• Identity: f alse ∨ φ = φ = φ ∨ f alse and true ∧ φ = φ = φ ∧ true

• Inverse: φ ∨ ¬φ = true and φ ∧ ¬φ = f alse

• Domination: φ ∨ true = true and φ ∧ f alse = f alse

• Duality: ¬ ⃝ φ = ⃝¬φ , ¬♢φ = □¬φ , ¬□φ = ♢¬φ


90 11 Linear Temporal Logic

• Temporal Idempotence: ♢♢φ = ♢φ ,□□φ = □φ , φ ∪ (φ ∪ ψ) = φ ∪ ψ = (φ ∪ ψ) ∪ ψ


• Temporal Absorption: ♢□♢φ = □♢φ , □♢□φ = ♢□φ .
• Temporal Expansion: φ ∪ ψ = ψ ∨ (φ ⃝ (φ ∪ ψ), ♢φ = φ ∨ ⃝♢φ and □φ = φ ∧ ⃝□φ
• Temporal Distributivity: ⃝(φ ∪ ψ) = (⃝φ ) ∪ (⃝(ψ), ♢(φ ∨ ψ) = ♢φ ∨ ♢ψ □(φ ∧ ψ) =
□φ ∧ □ψ
Please note that ♢(φ ∪ ψ) ̸= (♢φ ) ∪ (♢ψ), ♢(φ ∧ ψ) ̸= (♢φ ) ∧ (♢ψ) and □(φ ∧ ψ) ̸= (♢φ ) ∨
(♢ψ)

11.2 Model Checking with Büchi Automata and LTL


As we know from Theorem 8.4, for every transition system, there is a Büchi automaton accepting
the infinite traces of the transition system.
Definition 11.4 A Büchi automaton M operating over 2AP satisfies an LTL-formula φ over AP,
notation M |= φ , iff Tω (M) ⊆ Words(φ ).
Fact 11.5 For any LTL-Formula φ over AP, we have Words(¬φ ) = 2AP −Words(φ ).
Fact 11.6 We have M |= φ ⇐⇒ Tω (M) ∩Words(¬φ ) = 0.
/
Fact 11.7 For any w ∈ (2AP )ω we have
w |= φ ⇔ w ̸|= ¬φ
Fact 11.8 For any Büchi-Automaton M working over 2AP with Tω (M) ̸= 0/ and LTL-formula φ
over AP we have
Tω (M) |= φ ⇒ Tω (M) ̸|= ¬φ
This can be seen as follows: Since there is at least one w ∈ Tω (M) , we have w |= φ and thus
w ∈ Words(φ ) and hence w ∈ / 2AP − Words(φ ) = Words(¬φ ) implying Tω (M) ̸⊆ Words(¬φ )
hence Tω (M) ̸|= ¬φ .
However, we have
Fact 11.9 There are Büchi-Automata M working over 2AP with Tω (M) ̸= 0/ and LTL formula φ
over AP such that
Tω (M) ̸|= ¬φ
holds but

Tω (M) |= φ
does not hold.
Consider a Büchi-Automaton accepting aω + bω (the construction is left to the reader) and con-
sider the LTL formula ♢a. Clearly, aω + bω ̸|= ♢a as bω does not fulfill the formula. However,
aω + bω ̸|= ¬♢a as aω does not fulfill it.
Trivially stated, just because some set A1 ⊆ A is not a subset of a set A2 ⊆ A it does not imply
that A1 ⊆ A − A2 as A1 . This is wrong if A1 contains at least one element of A2 .
11.3 Fairness 91

11.3 Fairness
Definition 11.10 Let φ and ψ be propositional formulae over AP.

• An unconditional LTL fairness constraint is an LTL formula of the form

□♢φ

• A strong LTL fairness constraint is an LTL formula of the form

□♢ψ ⇒ □♢φ

• A weak LTL fairness constraint is an LTL formula of the form

♢□ψ ⇒ □♢φ

Intuitively, ψ stands for is enabled and φ stands for is taken. So, an unconditional fairness
constraint specifies that φ holds infinitely often. A strong fairness constraint specifies that φ
holds infinitely often if ψ holds infinitely often. A weak constraint stands for the situation that if
ψ eventually holds forever, then φ holds infinetely often.
Clearly, unconditionally fairness implies strong fairness implies weak fairness.

Definition 11.11 An LTL fairness assumption f air is the conjunction of fairness constraints.
For set α of infinite words over 2AP , we define α α |= f air φ if and only if α |= ( f air ⇒ φ ), i.e φ
holds in case the fairness condition is satisfied. Please note that words which violate the fairness
constraints are not considered.

11.4 Büchi-Automata and LTL


Fact 11.12 For every LTL formula φ , there is a Büchi-Automaton M such that Tω (M) = Words(φ ).

Fact 11.13 There is a Büchi automaton M such that there is no LTL formula φ with Words(φ ) =
Tω (M).

An example for such a language is L = {w = A0 A1 A2 A3 . . . ∈ 2{a,b} | a ∈ Ai if i is even} which


can be accepted by the following Büchi-Automaton:

a
start q0 q1
true
92 11 Linear Temporal Logic

11.5 Tasks
Task 11.1:
Let φ ,be an LTL-formula. Prove the following properties:

1. ¬♢φ = □¬φ

2. ¬□φ = ♢¬φ .

Task 11.2:
Let φ , ψ and χ be LTL-formulae. Prove the following properties:

1. χ ∪ (φ ∨ ψ) = (χ ∪ φ ) ∨ (χ ∪ ψ)

2. ♢(φ ∨ ψ) = ♢φ ∨ ♢ψ

3. □(φ ∧ ψ) = □φ ∧ □ψ.

You can assume Morgan’s Law as given.

Task 11.3:
Prove or disprove:


Words(♢(φ ∪ ψ)) ⊂ Words((♢φ ) ∪ (♢ψ))


Words(□(φ ∧ ψ) ⊃ Words(♢φ ) ∨ (♢ψ)

Task 11.4:
Give equivalent Büchi-Automata for the following LTL-Formulae:

1. □P

2. ♢P
S
3. Q P

Task 11.5:
Give eqivalent LTL-Formulae for the following Büchi-Automata:

1. Automaton from Figure 10.5:


11.5 Tasks 93

true P

start q0 q1
P

2. Automaton

¬P P

start q0 q1
P

3. Automaton

¬P P
P
start q0 q1

¬P

4. Automaton

true P
P
start q0 q1

¬P

5. Automaton

true P
P
start q0 q1
true

6. Automaton

b, c a, c
a
start q0 q1

b
94 11 Linear Temporal Logic

7. Automaton over Σ = {a, b}

b a,b

start q0 q1 q2 qF
a a,b a,b

8. Automaton over 2AP and some propositional logic formulae p, q over AP

q p∧q

start q0 q1 q2 qF
p p∧q p∨q

9. Automaton over Σ = 2AP for AP = {p, q}.

¬p ∨ q p ∧ ¬q ¬q

start q0 q1

Task 11.6:
Let AP = {a, b} and Σ = 2AP . Give LTL formulae defining the following languages:

1. {a, b}0Σ
/ ω

2. Σ∗ {a}ω

3. Σ∗ ({a} + {a, b})Σ∗ {a}Σω

4. {a}∗ {b}∗ 0/ ω

Task 11.7:
Provide a Büchi-Automaton equivalent to the following LTL-Formula over the atomic proposi-
tions a and b:

1. □(a ⇔ b)

2. ♢a
11.5 Tasks 95

3. (□(a ⇔ b)) ∨ (♢a)


4. □(a ∨ ¬ ⃝ b)
5. □♢(a ⇔ b)
6. ⃝ ⃝ (a ∨ ♢□b)

Task 11.8:
Consider the Dining Philosopher’s Problem as presented in Section 5.9 and the atomic proposi-
tons hi : Philospher i is hungry, ei : Philosopher i is eating. Express the following properties as
LTL formulae:
1. An eating philosopher prevents his/her neighbours from eating.
2. An eating philosopher eats until he/she is no longer hungry.
3. Every hungry philosopher eats eventually.
4. An eating philosopher eventually loses his/her appetite.

Task 11.9:

1. Give an ω-regular expression equivalent to ⃝ ⃝ a.


2. Present a Büchi-Automaton for ⃝ ⃝ (a b).
S

3. Simplify the LTL-formula φ ∨ ((¬φ ) ⃝ (♢true)) as much as possible, present your calcu-
lation.

Task 11.10:
Consider the LTL-formula
φ = (♢x) ⇒ ♢(y ∧ z) over {x, y, z}.
Which of the following words satisfies φ ? Explain your calculation and answer.
1. 0/ ω
2. {x, y, z}ω
3. {x}ω
4. {y, z}, {x}{z}ω
5. ({x}{y}{z})ω
6. {y}ω
7. {y}{x}{y}ω
Bibliography
[1] C. Baier, J.-P. Katoen, Principles of Model Checking, MIT Press, London, UK, 2007.
[2] M. Ben-Ari, Principles of the Spin Model Checker, Springer London, UK, 2008.
[3] E.W. Dijkstra, Solution to a problem in concurrent programming control, CACM 8, 9
(1965), 569.
[4] R. Garth, Concise Promela Reference, available online at https://spinroot.com/
spin/Man/Quick.html
[5] M.R. Garey, D.S. Johnson, Computers and Intractability - A Guide to the Theory of
NP-Completeness, W.H. Freeman and Company, New York NY, 1978.
[6] J.E. Hopcroft, J.D. Ullman, Introduction to Automata Theory, Languages and Com-
putation, Addison-Wesley, Reading MA, 1979.
[7] M. Kappes, R. P. Klemm, C. M. R. Kintala, Formal Limits on Determining Reliabil-
ities of Component-Based Software Systems, Proceedings 11th International Sympo-
sium on Software Reliability Engineering (ISSRE), 2000.
[8] C.H. Papadimitriou, Computational Complexity, Addison-Wesley, Reading MA,
1994.
[9] Pan Verification Options Overview available online at https://spinroot.com/
spin/Man/Pan.html
[10] Spin Version 6 - Promela Grammar, available online at https://spinroot.com/
spin/Man/grammar.html
[11] Promela Reference Manual, available online at https://spinroot.com/spin/
Man/Intro.html
[12] Promela Reference Pages, available online at https://spinroot.com/spin/Man/
promela.html
[13] C.H. Papadimitriou, K. Steiglitz, Combinatorial Optimization : Algorithms and Com-
plexity, Prentice Hall, Englewood Cliffs NJ, 1982.
[14] Basic Spin Manual, available online at https://spinroot.com/spin/Man/
Manual.html
[15] Spin Run-Time Options Overview, available online at https://spinroot.com/
spin/Man/Spin.html
98 Bibliography

[16] A.S. Tanenbaum, H. Bos, Modern Operating Systems, Fourth Edition, Pearson, Essex,
UK, 2015.

[17] A. Salomaa and M. Soittola, Automata-Theoretic Aspects of Formal Power Series,


Springer-Verlag, 1978.

[18] B. Alpern and F.B. Schneider, Defining Liveness, Information Processing Letters,
21(4), pp 181-185, 1985.

[19] B. Alpern and F.B. Schneider, Recognizing Safety and Liveness, Distributed Comput-
ing, 2, pp 117-126, 1987.

[20] J.R. Büchi, On a Decision Method in Restricted Second Order Arithmetic. In E. Nagel
et al., editors, Proceedings of the International Congress on Logic, Methodology and
Philosophy of Science 1960, pp 1-11. Stanford University Press, 1962.

[21] S. Eilenberg, Automata, Languages and Machines, volume A, Academic Press, New
York, 1974.

[22] L.H. Landweber, Decision problems for ω-automata, Mathematical System Theory 4,
pp 376-384, 1969

[23] M. Lyu, editor, Handbook of Software Reliability Engineering, McGraw-Hill, New


York, 1995.

[24] D.E. Muller, Infinite Sequences and Finite Machines, in Proceedings of the 4th IEEE
Symposium on Switching Circuit Theory and Logical Design, pp 3-16, 1963.

[25] M. P. Schützenberger, Finite Counting Automata, Information and Control,5, pp 91-


107, 1962.

[26] W. Thomas, Languages, Automata and Logic, Handbook of Formal Language Theory,
volume III, Springer-Verlag 1997, pp 389-455.

[27] M.Y. Vardi and P. Wolper, Automata-theoretic Techniques for Modal Logics of Pro-
grams, Journal of Computer and System Sciences, 32, pp 182-211, 1986.

[28] M.Y. Vardi and P. Wolper, Reasoning About Infinite Computations, Information and
Computation, 115, pp 1-37, 1994.

[29] Z. Manna, A. Pnueli, A hierarchy of temporal properties, in: Proceedings of the 9th
Annual ACM Symposium on Principles of Distributed Computing, ACM Press, 1990,
pp. 377–408.

You might also like