Lecture Notes in Computer Science
Commenced Publication in 1973
Founding and Former Series Editors:
Gerhard Goos, Juris Hartmanis, and Jan van Leeuwen
Editorial Board
David Hutchison
Lancaster University, UK
Takeo Kanade
Carnegie Mellon University, Pittsburgh, PA, USA
Josef Kittler
University of Surrey, Guildford, UK
Jon M. Kleinberg
Cornell University, Ithaca, NY, USA
Friedemann Mattern
ETH Zurich, Switzerland
John C. Mitchell
Stanford University, CA, USA
Moni Naor
Weizmann Institute of Science, Rehovot, Israel
Oscar Nierstrasz
University of Bern, Switzerland
C. Pandu Rangan
Indian Institute of Technology, Madras, India
Bernhard Steffen
University of Dortmund, Germany
Madhu Sudan
Massachusetts Institute of Technology, MA, USA
Demetri Terzopoulos
University of California, Los Angeles, CA, USA
Doug Tygar
University of California, Berkeley, CA, USA
Moshe Y. Vardi
Rice University, Houston, TX, USA
Gerhard Weikum
Max-Planck Institute of Computer Science, Saarbruecken, Germany
4591
Jim Davies Jeremy Gibbons (Eds.)
Integrated
Formal Methods
6th International Conference, IFM 2007
Oxford, UK, July 2-5, 2007
Proceedings
13
Volume Editors
Jim Davies
Oxford University Computing Laboratory
Wolfson Building
Oxford OX1 3QD, UK
E-mail: Jim.Davies@camlab.ox.ac.uk
Jeremy Gibbons
Oxford University Computing Laboratory
Wolfson Building
Oxford OX1 3QD, UK
E-mail: jeremy.gibbons@comlab.ox.ac.uk
Library of Congress Control Number: 2007928796
CR Subject Classification (1998): F.3, D.3, D.2, D.1
LNCS Sublibrary: SL 2 – Programming and Software Engineering
ISSN
ISBN-10
ISBN-13
0302-9743
3-540-73209-8 Springer Berlin Heidelberg New York
978-3-540-73209-9 Springer Berlin Heidelberg New York
This work is subject to copyright. All rights are reserved, whether the whole or part of the material is
concerned, specifically the rights of translation, reprinting, re-use of illustrations, recitation, broadcasting,
reproduction on microfilms or in any other way, and storage in data banks. Duplication of this publication
or parts thereof is permitted only under the provisions of the German Copyright Law of September 9, 1965,
in its current version, and permission for use must always be obtained from Springer. Violations are liable
to prosecution under the German Copyright Law.
Springer is a part of Springer Science+Business Media
springer.com
© Springer-Verlag Berlin Heidelberg 2007
Printed in Germany
Typesetting: Camera-ready by author, data conversion by Scientific Publishing Services, Chennai, India
Printed on acid-free paper
SPIN: 12080328
06/3180
543210
Preface
The design and analysis of computing systems presents a significant challenge:
systems need to be understood at many different levels of abstraction, and examined from many different perspectives. Formal methods—languages, tools, and
techniques with a sound, mathematical basis—can be used to develop a thorough
understanding and to support rigorous examination.
Further research into effective integration is required if these methods are
to have a significant impact outside academia. The Integrated Formal Methods
(IFM) series of conferences seeks to promote this research, to bring together the
researchers carrying it out, and to disseminate the results of this research among
the wider academic and industrial community.
Earlier meetings in the series were held at: York (1999); Dagstuhl (2000);
Turku (2002); Kent (2004); Eindhoven (2005). IFM 2007 was the largest to date,
with 32 technical papers (from 85 submissions), 3 invited talks, 3 workshops, and
a tutorial. The success of the series reflects the enthusiasm and efforts of the IFM
community, and the organizers would like to thank the speakers, the committee,
and the reviewers for their contributions.
April 2007
Jim Davies
Jeremy Gibbons
Organization
Chair
Jim Davies
Co-chairs
Jin Song Dong, Jeremy Gibbons, Judi Romijn, Wolfram Schulte
Workshops and Tutorials
Richard Paige
Local Arrangements
Jackie Jordan, James Welch
Special Sessions
Yifeng Chen, Eerke Boiten, Phil Brooke, John Derrick, Graeme Smith
Programme Committee
Didier Bert, Eerke Boiten, Jonathan Bowen, Phil Brooke, Michael Butler,
Yifeng Chen, Paul Curzon, Jim Davies, John Derrick, Jin Song Dong,
Steve Dunne, Andy Galloway, Chris George, Jeremy Gibbons,
Wolfgang Grieskamp, Henri Habrias, Maritta Heisel, Soon-Kyeong Kim,
Michel Lemoine, Shaoying Liu, Dominique Mery, Stephan Merz,
Colin O’Halloran, Richard Paige, Luigia Petre, Jaco van de Pol,
Judi Romijn, Thomas Santen, Steve Schneider, Wolfram Schulte,
Kaisa Sere, Jane Sinclair, Graeme Smith, Bill Stoddart, Kenji Taguchi,
Helen Treharne, Heike Wehrheim, Kirsten Winter, Jim Woodcock
Additional Reviewers
Pascal Andre, Christian Attiogbé, Pavel Avgustinov, Luis Barbosa,
Alessandra Cavarra, Orieta Celiku, Yuting Chen, Chunqing Chen,
John Colley, Robert Colvin, Neil Evans, Yuan Fang Li, Berndt Farwer,
Diego Garbervetsky, Lars Grunske, Stefan Hallerstede, Dubravka Ilic,
Yoshinao Isobe, Jon Jacky, Ehtesham Jam, Linas Laibinis, Antonia Lopes,
Eduardo Lopez-Ruiz, Hidehiko Masuhara, Tim McComb, Larissa Meinicke,
Bernhard Moeller, Leonardo de Moura, Ivan Porres, Viorel Preoteasa,
Franco Raimondi, Jean-Luc Richier, Rimvydas Ruksenas, Ondrej Rypacek,
Holger Schmidt, Cristina Seceleanu, Paul Strooper, Georg Struth, Jun Sun,
Jörn Guy Süß, Yoshinori Tanabe, Nikolai Tillmann, Jan Tobias Muehlberg,
Niki Trigoni, Margus Veanes, Meng Wang, Geoffrey Watson, James Welch,
Luke Wildman, Divakar Yadav, Lu Yan, Huibiao Zhu
Table of Contents
Verifying Temporal Properties of CommUnity Designs . . . . . . . . . . . . . . . .
Nazareno Aguirre, Germán Regis, and Tom Maibaum
1
Precise Scenarios – A Customer-Friendly Foundation for Formal
Specifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Oliver Au, Roger Stone, and John Cooke
21
Automated Verification of Security Policies in Mobile Code . . . . . . . . . . . .
Chiara Braghin, Natasha Sharygina, and Katerina Barone-Adesi
37
Slicing Concurrent Real-Time System Specications for Verification . . . . .
Ingo Brückner
54
Slotted-Circus: A UTP-Family of Reactive Theories . . . . . . . . . . . . . . . . . .
Andrew Butterfield, Adnan Sherif, and Jim Woodcock
75
Bug Hunting with False Negatives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Jens Calamé, Natalia Ioustinova, Jaco van de Pol and
Natalia Sidorova
98
Behavioural Specifications from Class Models . . . . . . . . . . . . . . . . . . . . . . . .
Alessandra Cavarra and James Welch
118
Inheriting Laws for Processes with States . . . . . . . . . . . . . . . . . . . . . . . . . . .
Yifeng Chen
138
Probabilistic Timed Behavior Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Robert Colvin, Lars Grunske, and Kirsten Winter
156
Guiding the Correction of Parameterized Specifications . . . . . . . . . . . . . . .
Jean-François Couchot and Frédéric Dadeau
176
Proving Linearizability Via Non-atomic Refinement . . . . . . . . . . . . . . . . . .
John Derrick, Gerhard Schellhorn, and Heike Wehrheim
195
Lifting General Correctness into Partial Correctness is ok . . . . . . . . . . . . .
Steve Dunne and Andy Galloway
215
Verifying CSP-OZ-DC Specifications with Complex Data Types and
Timing Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Johannes Faber, Swen Jacobs, and Viorica Sofronie-Stokkermans
233
Modelling and Verification of the LMAC Protocol for Wireless Sensor
Networks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ansgar Fehnker, Lodewijk van Hoesel, and Angelika Mader
253
VIII
Table of Contents
Finding State Solutions to Temporal Logic Queries . . . . . . . . . . . . . . . . . . .
Mihaela Gheorghiu, Arie Gurfinkel, and Marsha Chechik
273
Qualitative Probabilistic Modelling in Event-B . . . . . . . . . . . . . . . . . . . . . . .
Stefan Hallerstede and Thai Son Hoang
293
Verifying Smart Card Applications: An ASM Approach . . . . . . . . . . . . . . .
Dominik Haneberg, Holger Grandy, Wolfgang Reif, and
Gerhard Schellhorn
313
Verification of Probabilistic Properties in HOL Using the Cumulative
Distribution Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Osman Hasan and Sofiène Tahar
333
UTP Semantics for Web Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
He Jifeng
353
Combining Mobility with State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Damien Karkinsky, Steve Schneider, and Helen Treharne
373
Algebraic Approaches to Formal Analysis of the Mondex Electronic
Purse System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Weiqiang Kong, Kazuhiro Ogata, and Kokichi Futatsugi
393
Capturing Conflict and Confusion in CSP . . . . . . . . . . . . . . . . . . . . . . . . . . .
Christie Marr (née Bolton)
413
A Stepwise Development Process for Reasoning About the Reliability
of Real-Time Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Larissa Meinicke and Graeme Smith
439
Decomposing Integrated Specifications for Verification . . . . . . . . . . . . . . . .
Björn Metzler
459
Validating Z Specifications Using the ProB Animator and Model
Checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Daniel Plagge and Michael Leuschel
480
Verification of Multi-agent Negotiations Using the Alloy Analyzer . . . . . .
Rodion Podorozhny, Sarfraz Khurshid, Dewayne Perry, and
Xiaoqin Zhang
501
Integrated Static Analysis for Linux Device Driver Verification . . . . . . . . .
Hendrik Post and Wolfgang Küchlin
518
Integrating Verification, Testing, and Learning for Cryptographic
Protocols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Martijn Oostdijk, Vlad Rusu, Jan Tretmans, R.G. de Vries, and
T.A.C. Willemse
538
Table of Contents
IX
Translating FSP into LOTOS and Networks of Automata . . . . . . . . . . . . .
Gwen Salaün, Jeff Kramer, Frédéric Lang, and Jeff Magee
558
Common Semantics for Use Cases and Task Models . . . . . . . . . . . . . . . . . .
Daniel Sinnig, Patrice Chalin, and Ferhat Khendek
579
Unifying Theories of Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Michael Anthony Smith and Jeremy Gibbons
599
Non-interference Properties for Data-Type Reduction of Communicating
Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Tobe Toben
619
Co-simulation of Distributed Embedded Real-Time Control Systems . . . .
Marcel Verhoef, Peter Visser, Jozef Hooman, and Jan Broenink
639
Author Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
659
Verifying Temporal Properties of CommUnity
Designs
Nazareno Aguirre1 , Germán Regis1 , and Tom Maibaum2
1
Departamento de Computación, FCEFQyN, Universidad Nacional de Rı́o Cuarto
and CONICET, Ruta 36 Km. 601, Rı́o Cuarto (5800), Córdoba, Argentina
{naguirre,gregis}@dc.exa.unrc.edu.ar
2
Department of Computing & Software, McMaster University,
1280 Main St. West, Hamilton, Ontario, Canada L8S 4K1
tom@maibaum.org
Abstract. We study the use of some verification techniques for reasoning about temporal properties of CommUnity designs. We concentrate on
the verification of temporal properties in the context of branching-time
temporal logic using the SMV tool.
We also discuss ways of modularising the temporal reasoning, by exploiting the various kinds of morphisms between designs available in
CommUnity. Moreover, we combine SMV verification with some abstract
interpretation mechanisms to overcome a limitation, with respect to the
use of structure for simplification of verification, of CommUnity’s refinement morphisms, the lack of support for data refinement.
1
Introduction
The constant increase in the complexity of software systems demands a continuous search for more and better modularisation mechanisms in software development processes, covering not only implementation, but also earlier stages, such
as analysis and design. Indeed, many new modularisation mechanisms influence
not only programming language constructs, but also their associated development
methodologies. Modularisation mechanisms are also of a crucial importance for
formal methods, and in particular for formal specification. Appropriate modularisation mechanisms allow us to structure our specifications, dividing the usually
large specifications (due to the degree of detail that formal models demand) into
manageable parts. Also, many modern software systems have an inherent structural nature, and for these, structured specifications are better suited. Finally,
and more importantly for this paper, modularisation mechanisms allow us to apply some modularity principles to analyses of properties, taking advantage of the
structure of the design itself, and making some automated and semi-automated
verification techniques scale up and be applicable to larger systems specifications.
There exist many formal specification languages which put an emphasis on the
way systems are built out of components (e.g., those reported in [15,6,20,14]),
thus aiding the modularisation of specifications and designs. CommUnity is one
of these languages; it is a formal program design language which puts special emphasis on ways of composing specifications of components to form specifications
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 1–20, 2007.
c Springer-Verlag Berlin Heidelberg 2007
2
N. Aguirre, G. Regis, and T. Maibaum
of systems [4]. CommUnity is based on Unity [1] and IP [5], and its foundations
lie in the categorical approach to systems design [7]. Its mechanisms for composing specifications have a formal interpretation in terms of category theory
constructs [4]. Moreover, CommUnity’s composition mechanisms combine nicely
with a sophisticated notion of refinement, which involves separate concepts of
action blocking and action progress. CommUnity also has some tool support, the
CommUnity Workbench [23]. The CommUnity Workbench supports the editing,
compilation, colimit generation (as explained below, colimits represent the joint
behaviour of interacting components in CommUnity) and execution of CommUnity programs. However, it currently does not support the verification of logical
properties of designs. For this purpose, we propose the use of well known model
checking tools, in order to verify temporal properties of designs. More precisely,
and due to some particular characteristics of CommUnity, we propose the use
of CTL based model checking to analyse temporal properties of CommUnity
designs. We start by defining a translation from CommUnity designs into SMV
specifications in a semantics preserving way; since our goal is to verify temporal
properties of designs, we have to consider a semantics for CommUnity designs
that is more restrictive than (but compatible with) the semantics of open CommUnity designs described in [12]. We then attempt to modularise the verification
activities via the superposition and refinement morphisms available in CommUnity, as indicated in [13]. This is very important, since it allows us to exploit the
structure of CommUnity designs for verification, a task that is crucial for the
successful use of model checking and other automated analysis techniques. The
idea is to check properties required of a component from the specification of that
component, thus exponentially reducing the search space associated with these
checks, as compared to the search space associated with the much larger specification of the system. Although not all properties are necessarily preserved by
including a component in a system, by means of some structuring relationship,
important categories of properties are. Thus economies of scale might be achieved
by using this structuring information to structure verifications. We concentrate
on the information supplied by superposition relationships, used in structuring
designs, but also discuss refinements. Finally, we combine model checking with
predicate abstraction [8] in order to overcome a limitation (with respect to the
modularisation of verification) of CommUnity refinements, namely the lack of
support for data refinement [13].
The paper proceeds as follows. In section 2 we describe CommUnity and the
concepts of designs and programs, including the structuring principles used to
build systems from components. We also summarise the transition systems semantics of designs. Then in section 3, we discuss the verification of CommUnity
designs using SMV, how the required translation is defined, and how the verification can be modularised, in some cases, by using the structure defined by the
superposition morphisms used in structuring the design. We also discuss the relationship between refinement morphisms and temporal properties, and describe
how we complement the CTL model checking with predicate abstraction, which
is necessary due to the fact that refinement morphisms do not allow for data
Verifying Temporal Properties of CommUnity Designs
3
refinement. We conclude with a discussion of results and future research. In order to illustrate the main ideas of the paper, we develop a case study based on a
modular specification of a processor with a simple process scheduling mechanism.
2
CommUnity Designs
In this section, we introduce the reader to the CommUnity design language and
its main features, by means of an example. The computational units of a system
are specified in CommUnity through designs. Designs are abstract programs, in
the sense that they describe a class of programs (more precisely, the class of all
the programs one might obtain from the design by refinement), rather than a
single program. In fact, when a design does not admit any further refinement, it
is called a program [22].
Before describing in some detail the refinement and composition mechanisms
of CommUnity, let us describe the main constituents of a CommUnity design.
Assume that we have a fixed set ADT of datatypes, specified as usual via a
first-order specification. A CommUnity design is composed of:
– A set V of channels, typed with sorts in ADT . V is partitioned into three
subsets Vin , Vprv and Vout , corresponding to input, private and output channels, respectively. Input channels are the ones controlled, from the point of
view of the component, by the environment. Private and output channels are
the local channels of the component. The difference between these is that
output channels can be read by the environment, whereas private channels
cannot.
– A first-order sentence Init(V ), describing the initial states of the design1 .
– A set Γ of actions, partitioned into private actions Γprv and public actions
Γpub . Each action g ∈ Γ is of the form:
g[D(g)] : L(g), U (g) → R(g)
where D(g) ⊆ Vprv ∪ Vout is the (write) frame of g (the local channels that
g modifies), L(g) and U (g) are two first-order sentences such that U (g) ⇒
L(g), called the lower and upper bound guards, respectively, and R(g) is a
first-order sentence α(V ∪ D(g) ), indicating how the action g modifies the
values of the variables in its frame (D(g) is a set of channels and D(g) is the
corresponding set of “primed” versions of the channels in D(g), representing
the new values of the channels after the execution of the action g.)
The two guards L(g) and U (g) associated with an action g are related to refinement, in the sense that the actual guard of an action gr implementing the
abstract action g, must lie between L(g) and U (g). As explained in [13], the
negation of L(g) establishes a blocking condition (L(g) can be seen as a lower
1
Some versions of CommUnity, such as the one presented in [13], do not include an
initialisation constraint.
4
N. Aguirre, G. Regis, and T. Maibaum
bound on the actual guard of an action implementing g), whereas U (g) establishes a progress condition (i.e., an upper bound on the actual guard of an action
implementing g).
Of course, R(g) might not uniquely determine values for the variables D(g) .
As explained in [13], R(g) is typically composed of a conjunction of implications
pre ⇒ post , where pre is a precondition and post defines a multiple assignment.
To clarify the definition of CommUnity designs, let us suppose that we would
like to model a processor. We will abstract away from the actual code of the
processes, and represent them simply by an ordered pair of non negative integers
(denoted by nat), where the first integer represents a label for identifying the
process and the second one the number of seconds of execution remaining. Then,
a processor is a simple CommUnity design composed of:
– A local channel curr proc:nat, nat, representing the current process accessing the processor. We use a dummy value (0, 0) for indicating that the
processor is idle.
– an input channel in proc:nat, nat, for obtaining a new process (from
the environment, in an abstract sense) to be run by the processor.
– An action load, which loads a new process into the processor (reading the
corresponding values from the input variable in proc).
– An action run, that executes the current process for a second.
– An action kill, that removes the current process, replacing it by the dummy
(0, 0).
– An action switch, which, if the current process is not the dummy (0, 0),
replaces it by the incoming process in proc.
The CommUnity design corresponding to this component is shown in Figure 1.
Design Processor
in
in proc: <nat, nat>
out
curr proc: <nat, nat>
init
curr proc = (0,0)
do
load[ curr proc ] : in proc. snd > 0 ∧ in proc. fst = 0 ∧ curr proc=(0,0)
−→ curr proc’=in proc
[] prv run[ curr proc ] : curr proc. snd > 0, curr proc. snd > 0
−→ curr proc’=(curr proc.fst , curr proc. snd−1)
[]
kill [ curr proc ] : curr proc. fst = 0, false −→ curr proc’=(0,0)
[]
switch[ curr proc ] : in proc. snd > 0 ∧ in proc. fst = 0 ∧
curr proc. snd >0, false
−→ curr proc’=in proc
Fig. 1. An abstract CommUnity design for a simple processor
Verifying Temporal Properties of CommUnity Designs
5
In Fig. 1, one can see the different kinds of guards that an action might have.
For instance, action kill has safety and progress guards (curr proc.fst = 0
and false, respectively). Since the progress guard for this action is false, the
component is not obliged to execute the action when the environment requires
it to do so.
Another important point to notice in the processor design is the apparent
behaviour of action switch. After a switch, the previous value of curr proc
seems to be missing, since the component does not store it anywhere else, nor
“sends” it to another component. It will become clearer later on that it will
be the responsibility of other components in the architecture to “extract” the
current process and store it when a switch takes place. This is basically due
to the fact that communication between components is achieved by means of
coordination, rather than by explicit invocation.
To complete the picture, let us introduce some further designs. One is a
bounded queue of processes, with the traditional enqueue (enq) and dequeue
(deq) operations, implemented over an array. The other is a process generator, a
design that generates new processes to feed the system. These designs are shown
in Figures 2 and 3, respectively.
Design Process Queue
in
in proc: <nat, nat>
out
out proc: <nat, nat>
local
queue: array(10,<nat, nat>)
low, up, count: nat
init
out proc = (0,0) ∧ ∀ x ∈ [1..10] :
queue[x] = (0,0) ∧ low = 1 ∧ up = 1 ∧ count = 0
do
enq[ queue,out proc,count,up ] : count<10 ∧ in proc. fst = 0
−→ queue’[up] = in proc ∧ up’ = (up mod 10)+1 ∧
out proc’ = if (count=0,in proc,queue[low]) ∧ count’=count+1
[]
deq[ queue,out proc,count,low ] : count>0 , count>5
−→ queue’[low] = (0,0) ∧ low’ = (low mod 10)+1 ∧
out proc’ = queue[(low mod 10)+1] ∧count’=count−1
Fig. 2. An abstract CommUnity design for a process queue
the definition of action enq makes use of an if-then-else expression, in the syntax
of the CommUnity Workbench. Notice that the progress guard for action load of
the processor coincides with its blocking guard, which is too weak to guarantee
a scheduling policy. Stronger progress guards for actions related to load will
arise as a result of composing the processor with other components, to achieve
6
N. Aguirre, G. Regis, and T. Maibaum
Design Process Generator
out
out proc: <nat, nat>
local
curr id : nat
init
curr id = 1 ∧ out proc = (0,0)
do
prv gen[ out proc ] : out proc.fst = curr id
−→ out proc’. fst = curr id ∧ out proc’. snd > 0
[]
send[ out proc, curr id ] : out proc.fst = curr id
−→ out proc’=(0,0) ∧ curr id ’ = curr id+1
Fig. 3. An abstract CommUnity design for a process generator
a proper scheduling policy. In our case, for example, we require the dequeing of
processes to be ready whenever the number of processes in the queue exceeds
half the queue capacity (see the progress guard of action deq).
2.1
Component Composition
In order to build a system out of the above components, we need a mechanism
for composition. The mechanism for composing designs in Community is based
on action synchronisation and the “connection” of output channels to input
channels (shared memory). Since our intention is to connect both the process
generator and the processor to the queue (since processes to be enqueued might
be generated by the generator, or come from a processor’s currently executing
process being “switched out”), and the queue has a single “incoming interface”,
we have a kind of architectural mismatch. In order to overcome it, we can use a
duplexer, as specified in Figure 4. The duplexer enables us to design a system in
which independent use of the operations of the queue can be made by components
that are clients of the queue. Using this duplexer, we can form the architecture
shown in Figure 5. In Fig. 5, the architecture is shown using the CommUnity
Workbench graphical notation. In this notation, boxes represent designs, with
its channels and actions, and lines represent the interactions (“cables” in the
sense of [13]), indicating how input channels are connected to output channels,
and which actions are synchronised.
2.2
Semantics of Architectures
CommUnity designs have a semantics based on (labelled) transition systems.
Architectural configurations, of the kind shown in Fig. 5, also have a precise
semantics; they are interpreted as categorical diagrams, representing the architecture [13]. The category has designs as objects and the morphisms are superposition relationships. A superposition morphism between two designs A and B
Verifying Temporal Properties of CommUnity Designs
7
Design Duplexer
in
in 1 : <nat, nat>
in 2 : <nat, nat>
out
out proc: <nat, nat>
do
read1[ out proc ] : in 1 = (0,0) ∧ out proc= (0,0) −→ out proc’=in 1
[]
read2[ out proc ] : in 2 = (0,0) ∧ out proc= (0,0) −→ out proc’=in 2
[]
send: out proc = (0,0) −→ out proc’=(0,0)
Fig. 4. An abstract CommUnity design for a simple duplexer
Fig. 5. A graphical view of the architecture of the system
indicates, in a formal way, that B contains A, and uses it while respecting the
encapsulation of A (regulative superposition). The interesting fact is that the
joint behaviour of the system can be obtained by taking the colimit of the categorical diagram corresponding to the architecture [4]. Therefore, one can obtain
a single design (the colimit object), capturing the behaviour of the whole system.
2.3
Semantics for Abstract CommUnity Designs
In [13], the authors state that designs have an operational semantics when they
are closed (i.e., they do not have input channels), the safety and progress guards
for each action coincide, and the assignment for each action fully determines the
value for each v , where v is in the frame of the action. For abstract CommUnity
designs (i.e., not programs), it is not difficult to define a transition system semantics, by assuming that input channels can change arbitrarily and that, when
no action occurs, the values of the local variables are preserved. This is exactly
the idea followed in the definition of a denotational semantics for abstract CommUnity designs given in [12]. The semantics defined therein is, however, not
8
N. Aguirre, G. Regis, and T. Maibaum
completely adequate for our purposes, since many labelled transition systems
might correspond to an open design. Since we want to verify temporal properties of designs, we are forced to interpret these, when they are opened, in a
particular way; we have been careful to do so in a way that is compatible with
the semantics of open CommUnity designs given in [12] (i.e., we interpret designs
as particular transition systems within the possible interpretations as described
in [12]). Moreover, when a design is a program, the interpretation coincides with
the operational semantics of these, as described in [13]. The semantics described
below, which is a specialisation of that defined in [12], will allow us to establish
a direct connection between arbitrary CommUnity designs (including programs)
and temporal logic, with the aim of verifying temporal properties of designs.
Let LADT , Φ be a first-order specification of datatypes, UADT a model of
LADT , Φ and P = Vf , G a CommUnity design. Then, P defines a transition
system TP = Vf , θ, T over LADT and UADT , where:
– the set of flexible variables is the set Vf of channels of P ,
– the initialisation condition θ is the initialisation Init of P ,
– for each action g ∈ G, we include a transition tg in T , whose transition
relation is the following:
ρtg : L(g) ∧ R(g) ∧ ST (D(g))
where ST (D(g)) is the formula v∈(Loc (Vf −D(g)) (v = v ) (stuttering of the
local variables not in the frame of g),
– T includes a stuttering transition tI ,
– T also includes a local stuttering transition id , whose transition relation is
the following:
v = v
ρid :
v∈Loc (Vf )
The first two points in the above construction of the transition system TP are
easy to understand. The third point indicates that the actions of P correspond to
transitions of TP , as one might have expected. Notice that both the safety guard
and the precondition for an action g (the first captured by the conjunct L(g)
and the second is embedded in R(g)) are considered in the transition; moreover,
the corresponding assignment has to take place and the values of those local
variables not in the frame of g are required to be preserved. The fourth and
fifth points characterise the steps in which the design P is not actively involved
(computation steps of the environment); note that input channels are allowed to
change in a stuttering step of the design P .
The reader might notice that several constructs of CommUnity designs are
ignored in the above described construction of transition systems. The most notable case is that of progress guards. Progress guards are not taken into account
in the construction of transition systems for designs, because they represent
“readiness” constraints which are not part of the transition system definition,
but restrictions on the allowed models. For the particular models that we have
chosen as the interpretations for CommUnity designs, these trivially hold, as
Verifying Temporal Properties of CommUnity Designs
9
long as the progress guards of actions are stronger than the corresponding safety
ones. More precisely, when the progress guard U (g) of an action g holds, g must
be “available” to be executed (more formally, any state s in a computation of a
design P in which U (g) holds must have a tg -successor state s ); since the enabling condition for actions, according to our interpretation, is the safety guard,
whenever L(g) is true the action is available, thus guaranteeing that U (g) implies
the availability of g. Clearly, the logical characterisation of progress constraints
requires the use of path quantifiers. The reason for adopting a branching time
temporal logic is to be able to express such constraints. These are useful, since
the user might want to manually strengthen the enabling guards of actions,
which is a sound activity (with respect to [12]) as long as they are not strengthened “beyond” the corresponding progress guards. Finally, according to [12],
one must restrict runs of a transition system TP for a design P to strongly fair
runs with respect to private actions, taking as their enabling conditions their
corresponding safety guards.
Notice also that the difference between private and shared actions does not
have an impact in the construction of transition systems for designs. This is due
to the fact that, as explained in [13], the difference between private and shared
actions only has to do with the allowed forms of interaction between designs.
3
3.1
Verifying Temporal Properties of Designs
The SMV System
SMV (Symbolic Model Verifier) is one of the most widely used model checking
tools. Originally developed at Carnegie Mellon [18], SMV was the first model
checking tool that used a symbolic representation of transition systems based on
binary decision diagrams, which allowed for the application of model checking
techniques to larger finite state systems. SMV comprises a modular notation for
describing transition systems, as well as a notation for describing properties of
these, in the CTL temporal logic. We will not give a full description of SMV,
but just a brief overview of the notation, so that the reader not familiar with it
can straightforwardly follow our descriptions.
The SMV description of a system is organised in modules. Each module describes a portion of a finite state system, and its specification is given in terms
of typed variables, initialisation constraints and a transition relation. More precisely, a module description starts with declarations, which are essentially given
as a list of typed variables. These types for variables must be bounded. The
variables in declarations can be accompanied by a declaration of new types or
aliases of types, for variable typing. The state space associated with a module
will then be given by all the combinations of values of the corresponding types
for the declared variables. The transition system associated with the system
corresponding to a module is defined in terms of:
– a definition of the initial state, declared as initial values for each of the
declared variables, and
10
N. Aguirre, G. Regis, and T. Maibaum
– a definition of the transition relation, typically given as a “case” expression
for the next value to be assumed for each of the declared variables.
Let us provide, as a simple example, the following module definition, which
corrresponds to a manual translation of the simplest CommUnity design of our
example, the process generator: In our SMV models, MAXINT is a user provided
MODULE Process Generator() {
out proc: array 0..1 of 0.. MAXINT;
curr id : array 0..1 of 0.. MAXINT;
init(out proc):= [0,0];
init(curr id ):= 1;
next(curr id):= case {
out proc[0] = curr id: curr id +1; −− action send
out proc[0] ˜= curr id: curr id ; −− action gen
};
}
next(out proc):= case {
out proc[0] = curr id: [0,0];
−− action send
out proc[0] ˜= curr id: [ curr id ,1.. MAXINT]; −− action gen
};
positive constant, representing the maximum positive integer we consider. Notice
also that it is possible to represent nondeterministic assignment: in the above
example, the second component of the out proc variable is nondeterministically
assigned a positive value, in the definition of its next value associated with action
gen.
3.2
Translating CommUnity Designs into SMV
We now describe our general characterisation of CommUnity designs in the language of the SMV tool. We will illustrate the translation from CommUnity into
SMV by means of a detailed example. It is worth mentioning that we have chosen
Cadence SMV [19] because of its richer language, which allows us to describe
transitions involving structured-typed variables, such as arrays, in a more concise
way.
The translation we describe only involves designs and not architectural configurations. As explained before, any valid configuration is a representation of a
single design (the colimit of the categorical diagram corresponding to the architecture), so we do not lose generality.
The simplest part is the characterisation of channels. These are simply translated as variables in SMV, and for obvious reasons we limit ourselves to the types
supported by Cadence SMV. For our simple Processor design described before,
the channels are represented as follows:
Verifying Temporal Properties of CommUnity Designs
in proc : array 0..1 of 0.. MAXINT; −−
curr proc : array 0..1 of 0.. MAXINT;
11
Input variable
The initialisation of channels is translated into “init” specifications for the
corresponding variables in SMV, as one might expect:
−− Initialisation
of variables
init(in proc) := [0.. MAXINT,0..MAXINT];
init(curr proc):= [0,0];
−−Input variable
The slightly more complicated part is the characterisation of actions. These
need to be encoded into the “next” relationships for the variables. Since we need
to simulate a scheduler for actions, which chooses nondeterministically one of
the available actions, we introduce a “random variable”. This variable randomly
takes a numeric value corresponding to an action (including skip) to be executed
in the next step as long as its safety guard is satisfied; if the safety guard of the
chosen action is not true, then the action executed will be skip. For the Processor
design, the scheduling of the actions is represented in the following way:
−− Definition of Scheduler
−− Generation of random values used to schedule actions
init(rnd) := 0;
next(rnd) := 0..4;
init(curr action ) := skip;
next(curr action) := case{
rnd = 0 : skip;
rnd = 1 & (next(in proc[1]) > 0 & next(in proc[0]) ˜= 0 &
next(curr proc) = [0,0] ) : load;
rnd = 2 & (next(curr proc[1]) > 0): run;
rnd = 3 & true : kill ;
rnd = 4 & (next(in proc[1]) > 0 & next(in proc[0]) ˜= 0 &
next(curr proc[1]) > 0) : switch;
1: skip;
};
A point worth noticing is that the execution of the system in the SMV representation of a design P starts with a skip. This simplifies the specification of
the initialisation statement in the translation, since otherwise we would need
to take into account the initialisation constraints in P for the scheduling of the
first action to be executed. Our alternative does not restrict the executions of
the system, which from the second instant onwards will evolve by randomly chosen (available) actions. Notice that safety guards are part of the scheduling. The
assignments of the actions, on the other hand, appear on the “next” definitions
for the channels, which are formed by a “case” expression which depends on the
action executed:
12
N. Aguirre, G. Regis, and T. Maibaum
−− Definition of next value of variables
next(in proc) := [0.. MAXINT,0..MAXINT];
next(curr):=
curr action
curr action
curr action
curr action
curr action
curr action
};
−−Input variable
case{
= skip : curr proc;
= load : in proc;
= run : [ curr proc[0], curr proc[1] − 1];
= kill & curr proc[0] = 0 : curr proc;
= kill & curr proc[0] ˜= 0 : [0,0];
= switch : in proc;
Notice that, since in proc is an input variable, it can change arbitrarily in each
step.
Finally, we need to represent the constraints corresponding to progress guards
and strong fairness for private actions. These are easily characterised in CTL,
using an ASSUME clause for progress guards constraints and a FAIRNESS clause
for strong fairness on private actions:
−− Fairness for private actions
FAIRNESS
curr action = {run};
−− Specification of progress guards as CTL formulae
ASSUME progress switch;
progress switch : SPEC AG ((curr proc[1] > 4 & in proc ˜= [0,0])
→ EX( curr action = switch ));
Notice that progress guards are interpreted as (redundant) ASSUME clauses. If
the user decides to strengthen some guards of actions in order to obtain more restrictive interpretations of a design, these must not go beyond the corresponding
progress guards, in order not to make the SMV specification inconsistent.
Now we only need to provide the CTL formulae to be verified. For instance,
we might want to check that if the id of the current process is 0 then it is the
dummy process (i.e., the number of seconds remaining is also 0):
−− Properties to be verified
NoInvalidProccess :SPEC AG (curr proc[1] >0 →curr proc[0]>0);
3.3
Modularising the Verification Through Morphisms
As put forward in [4] and later work, different notions of component relationships
can be captured by morphisms, in the sense of category theory. We now exploit
these morphisms in order to modularise the SMV-based verification, in the way
indicated in [13].
Verifying Temporal Properties of CommUnity Designs
13
Superposition Morphisms. We start by describing how superposition morphisms, which are used in the composition of CommUnity designs, are exploited.
Let us first recall the formal notion of superposition morphism. A superposition
morphism σ : A → B is a pair of mappings σch , σact such that: (i) σch is a
total mapping from channels in A to channels in B, respecting the type and
kind2 of channels (except that input channels can be mapped to input or output channels), (ii) σact is a partial mapping from actions of B to actions of A,
which preserves the kind (shared or private) of actions, does not reduce the write
frame of actions of A, and the lower bound, upper bound and assignment for
each action of A is strengthened in the corresponding actions of B; moreover,
the encapsulation of A must be preserved, meaning that every action of B that
modifies a channel v of ran(σch ) must “invoke” an action of A that includes
−1
σch
(v) in its write frame.
Basically, σch indicates how the channels of A are embedded as channels of
B. The mapping σact , on the other hand, indicates, for each action a of A, all
−1
the actions that use it in B (through σact
(a)).
The main result that enables us to modularise the verification via superposition morphisms is reported in [12]. Therein, the authors indicate that superposition morphisms preserve invariants, the effect of actions on channels and the
restrictions to the occurrence of actions. More generally, we can affirm that superposition morphisms preserve safety properties, which is a direct consequence
of the following theorem:
Theorem 1. Let A and B be CommUnity designs, and σch , σact : A → B a
superposition morphism. Let s be a computation of B, according to the above
defined semantics of designs, and defined over an interpretation U for datatypes.
The computation sA , defined as the restriction of states in s to channels in
σch (VA ), is a computation of A.
Applied to our example, this means that we can reason locally about safety
properties of the components of a system. We have some examples below in
which we show the improvement that local verification of safety properties for
our case study constitutes. Of course, as is well known, this does not hold for
liveness properties, which are not necessarily preserved by superposition (it is
well known that, when a component is put to interact with others, some of its
liveness properties might be lost).
Notice also that, among all possible interpretations of an open CommUnity
design, we choose the less restrictive one, i.e., that in which the actions are
enabled under the weakest possible conditions. This has as a consequence that
the safety properties of the design that are verified using our SMV translation
are indeed properties of all the valid transition system interpretations (according
to [12]) of the design.
2
By the type of the channel we mean the sort with which it is associated; by the kind
of a channel we mean its “input”, “output” or “private” constraint.
14
N. Aguirre, G. Regis, and T. Maibaum
Refinement Morphisms. An important relationship between designs is refinement. Refinement, besides relating abstract designs with more concrete “implementations”, is also useful for characterising parametrisation and parameter
instantiation. In [13], the authors present a characterisation of refinement in
terms of category theory constructions. Essentially, they demonstrate that CommUnity designs and morphisms capturing the notion of refinement constitute a
category. As defined in [13], a refinement σ between designs A and B is a pair
of mappings σch , σact , such that (i) σch is a total mapping from channels in
A to channels in B, respecting the type and kind of channels, and injectively
mapping different output and input channels of A to different output and input
channels of B; (ii) σact is a partial mapping from actions of B to actions of A,
which preserves the kind of actions, does not reduce the frame of actions of A,
the lower bound and assignment for each action of A is strengthened in the corresponding actions of B; moreover, the upper bound of each action a of A must
be weakened by the disjunction of the upper bounds of all actions in B refining
a, meaning that every action of B that modifies a channel v of ran(σch ) must
−1
“invoke” an action of A that includes σch
(v) in its frame. Also, shared actions
of A must have at least one corresponding action in B, and all new actions of B
do not modify the local channels of A.
Notice that, with respect to the assignment and lower bounds of actions, the
refinement morphisms make them stronger when refining a design. Therefore,
we again can affirm, as for superposition morphisms, that, if σ is a refinement
morphism between designs A and B, then every execution trace of B, restricted
to the channels originating in A, is an execution of A, and therefore safety properties are preserved along refinement morphisms. Moreover, as shown in [13],
refinement morphisms also preserve properties expressing the readiness of actions (called co-properties in [13]). This does not mean, however, that refinement
morphisms are theorem preserving morphisms, with respect to the logic CTL.
Many liveness properties expressible in CTL, for example, are not necessarily
preserved along refinement morphisms. Consider, as a trivial example, a design
containing, among other things, a private action a:
Design P
...
out
x : int
...
init
x = 0 ∧ ...
do
prv a[ x ] : true, false −→ x’ = x + 1
...
where the variable x can only be modified by action a. Consider a refinement of
this design, in which all actions and channels are maintained without modifications, except for a, which is refined as follows:
Verifying Temporal Properties of CommUnity Designs
15
Design P’
...
out
x : int
...
init
x = 0 ∧ ...
do
prv a[ x ] : false , false −→ x’ = x + 1
...
It is easy to see that, due to the strong fairness constraints imposed on private
actions, the CTL liveness property AF (x = 1) holds for the original design, but
it does not hold for its described refinement.
One might be interested in exploiting refinement morphisms for simplifying
the verification of properties of designs, since some safety and readiness properties might be easier to verify in more abstract designs, i.e., designs with fewer
and simpler actions. However, the simplification one might obtain by moving
from a design to more abstract (i.e., less refined) ones is limited, since refinement morphisms do not allow for data refinement (the types of channels must be
preserved by refinement). This means, basically, that the state space of designs
does not change through refinement morphisms. Thus, refinement morphisms
are quite restricted for the simplification of verification, especially in the context
of automated verification, where data abstraction is known to have a big impact
on the verification times. For this reason, we complement below CommUnity’s
morphisms with abstraction mechanisms.
Abstraction. As we mentioned, abstraction is known to have a big impact
in automated verification, especially for model checking [2]. Since refinement
morphisms do not support data refinement, we considered the use of predicate
abstraction [8], as a way of improving the SMV-based verification of CommUnity
designs. Essentially, predicate abstraction consists of, given a (possibly infinite
state) transition system, constructing an abstract version of it, whose abstract
state space is determined by a number of predicates on the original state space.
Basically, the state space of the abstract transition system is composed of equivalence classes of the original states, according to the provided (abstraction) predicates [8]. The more complex part is the construction of abstract transitions
corresponding to the concrete ones, which requires checking to which of the
equivalence class(es) the source and target states of each transition correspond.
This can be computed automatically in many cases, and its complexity (not from
a computational point of view) greatly depends on the provided predicates.
We used predicate abstraction in order to improve the verification for our
example. For instance, we can concentrate on the processor design, and consider
the following predicates to do the abstraction:
– the number of seconds remaining for curr proc is 0,
– the process id for curr proc is 0.
16
N. Aguirre, G. Regis, and T. Maibaum
This leads us to the following four possibilities for curr proc:
– dummy, if the number of seconds remaining is 0 and the process id is 0,
– finished, if the number of seconds remaining is 0 and the process id is not 0,
– unfinished, if the number of seconds remaining is not 0 and the process id is
not 0,
– invalid, otherwise.
We can reproduce this abstraction for the in proc variable, which leads us to a
version of the SMV specification for the processor in which we do not distinguish
the actual values of curr proc and in proc, but only whether their ids and
remaining seconds are nil or not, which obviously makes the transition system
for the design much smaller.
The corresponding abstract version of the SMV Processor module is the following:
typedef PROCCESS {dummy,finished,unfinished,invalid};
MODULE main (){
rnd : 0..4; −− used to schedule actions randomly
curr action : {skip, load, run, kill , switch1 };
−− Definition of the variables
in proc : PROCCESS; −−Input
curr proc : PROCCESS;
variable
−− Definition of Scheduler
init(rnd) := 0;
next(rnd) := 0..4;
init(curr action ) := skip;
next(curr action) := case{
rnd = 0 : skip;
rnd = 1 & (next(in proc) = unfinished & next(curr proc) = dummy ) : load;
rnd = 2 & (next(curr proc) = unfinished) : run;
rnd = 3 & true : kill ;
rnd = 4 & (next(in proc) = unfinished & next(curr proc) = unfinished ) :
switch1;
1: skip; };
−− Initialisation
of variables
init(in proc) := { dummy,finished,unfinished,invalid};
init(curr proc):= dummy;
−− Definition of next value of variables
next(in proc) := { dummy,finished,unfinished,invalid}; −−Input variable
next(curr proc):= case{
curr action = skip : curr proc;
curr action = load : in proc;
curr action = run : {unfinished , finished } ;
curr action = kill & (curr proc = dummy | curr proc = invalid) : curr proc;
curr action = kill & (curr proc = unfinished | curr proc = finished ) : dummy;
curr action = switch1 : in proc; };
−− Fairness for private actions
FAIRNESS curr action = {run};
Verifying Temporal Properties of CommUnity Designs
17
−− Specification of progress guards as CTL formulae
}
ASSUME progress switch1;
progress switch1 : SPEC AG ((curr p = unfinished & in p ˜= dummy)
→ EX( curr action = switch1 ));
We can verify the property that if the id of the current process is 0 then it is
the dummy process, whose concrete and abstract versions are the following:
NoInvalidProccess :SPEC AG (curr proc[1] >0 →curr proc[0]>0);
NoInvalidProccess :SPEC AG (curr proc ˜= invalid);
The validity of the abstract version of this property implies the validity of
its concrete version [2]. Since this is a safety property, it is guaranteed that it
will also hold for the complete system (since superposition morphisms preserve
safety properties).
A point regarding abstraction and readiness is worth noticing. As indicated
in [2], all CTL formulae not involving existential path quantifiers are preserved
through abstraction. Readiness assertions require existential path quantifiers to
be expressed in CTL, and therefore these (expressing required non determinism
of components) might not be preserved through abstractions.
3.4
Some Sample Properties
To end this section, we provide some sample properties we have been able to
verify using our translation into SMV:
“Variables up and low are always valid positions of queue”
Bounds:SPEC AG(low 2 >= 1 & low 2 <= SIZE & up 2 >= 1 & up 2 <= SIZE);
“Variable count ranges from 0 (empty queue) to SIZE-1 (full queue)”
Count:SPEC AG(count 2 >= 0 & count 2 <= SIZE−1);
“Variable out proc of the duplexer always holds a dummy process or a valid
process (a positive process id and a positive number of seconds)”
NoInvalidDuplexerOut:SPEC AG(out p 0 = [0,0] | (out p 0[0] >0 & out p 0[1] >0))
“All processes held in queue have a positive number of seconds remaining to
be run”
18
N. Aguirre, G. Regis, and T. Maibaum
for (i =1;i<=SIZE;i=i+1){NoFinished[i]:SPEC AG(q 2[i][0] >0 →q 2[i][1]>0);}
“All live processes (in the processor) eventually finish”
for (i =1;i<=MAXINT;i=i+1){Proccessed[i]:
SPEC AG(curr p 3[0]=i & curr p 3[1] >0 →AF (curr p 3[0]=i & curr p 3[1]=0));}
Some of these properties can be verified locally within one component’s design
(for instance, the first two properties above are properties of the queue). This
is so thanks to the fact that safety properties of designs are preserved through
superposition morphisms. Other properties, such as the third one above, are
emergent properties, in the sense of [3], i.e., they are properties of a design that
emerge due to the interaction of it with other designs of the system.
4
Conclusions
We have presented a characterisation of CommUnity designs in SMV, defined
with the aim of verifying temporal properties of these designs. We have experimented with the modularisation of the verification activities in SMV by exploiting Community’s superposition morphisms, in the way indicated in [13]. We
also observed that refinement morphisms, related to abstraction, are not powerful enough with respect to the improvement of automated verification, since
they do not allow for data refinement. In order to overcome this limitation, we
used an abstract interpretation mechanism known as predicate abstraction [8].
We also observed that, although predicate abstraction preserves a wide range
of properties of designs, it does not necessarily preserve readiness properties of
actions, related to the required non determinism of components. We developed a
case study based on a modular specification of a processor with a simple process
scheduling mechanism, and verified several temporal properties, including safety
and liveness properties. Some of these were verified modularly, using abstraction
and superposition morphisms.
We believe that CommUnity is an interesting language that deserves more attention. As we mentioned, it is a language that puts special emphasis on ways of
composing specifications of components via their coordination, and clearly distinguishes action availability from action readiness. Moreover, there have been
recently some extensions of it in order to capture complex notions such as mobility and dynamic reconfiguration. Of course, having appropriate tool support
would improve the use of the language, and the work we report here is an initial
attempt in this direction.
We are implementing a tool for verifying temporal properties of CommUnity designs. This tool is, at the moment, just a compiler that implements the
translation of CommUnity designs into SMV. We are using the colimit generation procedure available in the CommUnity Workbench, and using a SAT solver
to check the proof obligations associated to the construction of the abstract
Verifying Temporal Properties of CommUnity Designs
19
transition systems related to predicate abstraction. This is done manually, at
the moment, but we plan to incorporate the generation and verification of these
proof obligations to the tool. We also plan to exploit the hierarchical structure of
SMV specifications in our translation (at the moment, our translations generate
unstructured SMV specifications).
As work in progress, we are trying to characterise the abstraction associated
with predicate abstraction in a categorical way (via an appropriate morphism
capturing data refinement). We are also studying the verification of temporal
properties of CommUnity’s dynamic software architectures [22], i.e., architectural
configuration that might change at run time (e.g., via the deletion or creation of
components, and the deletion and creation of connectors between components).
Reasoning about temporal properties of dynamic architectures is notably more
complex, since it is necessary to characterise the architectural configuration of the
system as part of the state of the system. We are also looking at how aspects, in the
sense of [10], can be applied to CommUnity designs. Aspects, as already observed
in [9] and later work, can be implemented via combinations of superimpositions.
In [11], the authors show how several aspects can be successfully characterised and
combined in an organised way in CommUnity, via the use of higher-order architectural connectors (aspect weaving would correspond to colimit construction).
In fact, we believe that most aspects can be characterised as architectural transformation patterns, replacing some part of a system design, defined by a pattern
of components and connectors, by another pattern of components and connectors. However, for this approach to be powerful enough, we believe it is necessary to use an additional kind of superposition, so called invasive superpositions,
that can break encapsulation and weakens lower and upper guards, and generalise
CommUnity’s designs to allow the design of hierarchical, reconfigurable systems.
Aspect “weaving” would still be realised by the colimit construction.
Acknowledgements
The first author was partially supported by the Argentinian Agency for Scientific
and Technological Promotion (ANPCyT) and the Agencia Córdoba Ciencia, and
his visits to McMaster University that contributed to this work were supported
by McMaster University and the Canada Research Chair programme. The second
author was partially supported by CONICET and the Agencia Córdoba Ciencia.
The third author was partially supported by McMaster University, the Canada
Research Chair programme, and the Natural Sciences and Engineering Council of
Canada.
References
1. Chandy, K., Misra, J.: Parallel Program Design - A Foundation. Addison-Wesley,
Reading (1988)
2. Clarke, E., Grumberg, O., Long, D.: Model Checking and Abstraction. In: ACM
Trans. on Programming Languages and Systems, vol. 16(5), ACM Press, New York
(1994)
20
N. Aguirre, G. Regis, and T. Maibaum
3. Fiadeiro, J.: On the Emergence of Properties in Component-Based Systems. In:
Nivat, M., Wirsing, M. (eds.) AMAST 1996. LNCS, vol. 1101, Springer, Heidelberg
(1996)
4. Fiadeiro, J., Maibaum, T.: Categorical Semantics of Parallel Program Design. In:
Science of Computer Programming, vol. 28(2-3), Elsevier, Amsterdam (1997)
5. Francez, N., Forman, I.: Interacting Processes. Addison-Wesley, Reading (1996)
6. Garlan, D., Monroe, R., Wile, D.: ACME: An Architecture Description Interchange
Language. In: Proc. of CASCON’97, Toronto, Ontario (1997)
7. Goguen, J.: Categorical Foundations for General System Theory. In: Advances in
Cybernetics anda Systems Research, Transcripta Books (1973)
8. Graf, S., Saidi, H.: Construction of abstract state graphs with PVS. In: Grumberg,
O. (ed.) CAV 1997. LNCS, vol. 1254, Springer, Heidelberg (1997)
9. Katz, S., Gil, J.: Aspects and Superimpositions. In: Moreira, A.M.D., Demeyer,
S. (eds.) Object-Oriented Technology. ECOOP’99 Workshop Reader. LNCS,
vol. 1743, Springer, Heidelberg (1999)
10. Kiczales, G., Lamping, J., Mendhekar, A., Maeda, C., Lopes, C.V., Loingtier, J.M., Irwin, J.: Aspect-Oriented Programming. In: Aksit, M., Matsuoka, S. (eds.)
ECOOP 1997. LNCS, vol. 1241, Springer, Heidelberg (1997)
11. Lopes, A., Wermelinger, M., Fiadeiro, J.: Higher-Order Architectural Connectors.
ACM Trans. on Software Engineering and Methodology, vol. 12(1). ACM Press,
New York (2003)
12. Lopes, A., Fiadeiro, J.: Using Explicit State to Describe Architectures. In: Finance,
J.-P. (ed.) ETAPS 1999 and FASE 1999. LNCS, vol. 1577, Springer, Heidelberg (1999)
13. Lopes, A., Fiadeiro, J.: Superposition: Composition vs. Refinement of NonDeterministic, Action-Based Systems. In: Formal Aspects of Computing, vol. 16(1),
Springer, Heidelberg (2004)
14. Luckham, D., Kenney, J., Augustin, L., Vera, J., Bryan, D., Mann, W.: Specification and Analysis of System Architecture Using Rapide. IEEE Trans. on Software
Engineering. IEEE Press, New York (1995)
15. Magee, J., Dulay, N., Eisenbach, S., Kramer, J.: Specifying Distributed Software
Architectures. In: Botella, P., Schäfer, W. (eds.) ESEC 1995. LNCS, vol. 989,
Springer, Heidelberg (1995)
16. Manna, Z., Pnueli, A.: The Temporal Logic of Reactive and Concurrent Systems Specification. Springer, Heidelberg (1991)
17. Manna, Z., Pnueli, A.: Temporal Verification of Reactive Systems - Safety. Springer,
Heidelberg (1995)
18. McMillan, K.: Symbolic Model Checking - An Approach to the State Explosion
Problem, PhD thesis, SCS, Carnegie Mellon University (1992)
19. McMillan, K.: The SMV Language, Cadence Berkeley Labs, Cadence Design Systems (1998)
20. Medvidovic, N., Oreizy, P., Robbins, J., Taylor, R.: Using Object-Oriented Typing
to Support Architectural Design in the C2 Style. In: Proc. of ACM SIGSOFT ’96,
San Francisco, CA, ACM Press, New York (1996)
21. Wermelinger, M., Lopes, A., Fiadeiro, J.: Superposing Connectors. In: Proc. of the
10th International Workshop on Software Specification and Design, IEEE Press,
Los Alamitos (2000)
22. Wermelinger, M., Lopes, A., Fiadeiro, J.: A Graph Based Architectural
(Re)configuration Language. In: Proc. of ESEC/FSE’01, ACM Press, New York
(2001)
23. Wermelinger, M., Oliveira, C.: The CommUnity Workbench. In: Proc. of ICSE
2002, Orlando (FL), USA, ACM Press, New York (2002)
Precise Scenarios – A Customer-Friendly
Foundation for Formal Specifications
Oliver Au, Roger Stone, and John Cooke
Loughborough University, England
{o.t.s.au,r.g.stone,d.j.cooke}@lboro.ac.uk
Abstract. A formal specification, written in a mathematical notation, is
beyond the comprehension of the average software customer. As a result,
the customer cannot provide useful feedback regarding its correctness
and completeness. To address this problem, we suggest the formalism
expert to work with the customer to create precise scenarios. With only
a few simple Z concepts, a precise scenario describes an operation by its
effects on the system state. The customer would find a concrete precise
scenario easier to understand than its corresponding abstract schema.
The Z expert derives schemas based on the precise scenarios. Precise
scenarios afford user involvement that improves the odds of a formal
specification fully capturing the user requirements.
Keywords: precise scenario, formal method, requirements specification,
use case, Z notation.
1
Introduction
The most important software project success factor is user involvement [1]. Specifications in mathematical notations are difficult for users to read and provide
meaningful feedback [2]. Thus a formal specification may not truly reflect their
requirements. This could explain the limited adoption of formal methods [3].
We hope to broaden the appeal of formal specification by integrating into it the
intuitive scenarios. The result is increased user involvement in the application
of formal methods.
Use cases and scenarios can involve customers in requirements elicitation.
There should be a use case for each user task. A use case consists of several
scenarios, one scenario for a situation. The most common way to describe the
details of a scenario is by listing a sequence of steps. Each step names an actor
and describes its action in a natural language. Due to the inherited ambiguity,
the scenario descriptions are not a reliable basis for the formal specification.
We propose to describe a scenario by its precise effects on a state. A state is
represented by its actual data expressed in a small subset of the specification language Z. For the layman, actual data are easier to understand than their abstract
descriptions. A small number of Z symbols used in the precise scenarios make
them easier to understand than the corresponding schemas. The customers can
participate in the creation of the precise scenarios. But scenarios only partially
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 21–36, 2007.
c Springer-Verlag Berlin Heidelberg 2007
22
O. Au, R. Stone, and J. Cooke
describe the infinite behaviour of a software application. A Z expert will need
to generalise the scenarios into schemas that form a complete Z specification.
We could have demonstrated precise scenarios with another state-based specification language such as VDM-SL. However we find the schema operators in Z,
for example, conjunction and disjunction, particular useful in the incremental
development of a formal specification.
The idea of creating formal specifications from scenarios is not new. Amyot et
al. express scenarios in Use Case Maps (UCM) and translate them into high-level
LOTOS specifications [4]. Whittle and Schumann create statechart diagrams
from UML sequence diagrams [5]. Uchitel et al. [6] and Damas et al. [7] use
message sequence charts (MSC) to synthesize labeled transition system (LTS).
System behaviour in the above research is limited to sequences of events. Being
based on Z, precise scenarios can represent general computation beyond events.
In another strand of research, Grieskamp and Lepper combine use cases with Z
[8]. Use cases relate operations of a Z specification in actual usage. Test dialogues,
built with nondeterministic choice, repetition and interruption, are executed in
ZETA [9]. In contrast to our research goal, their focus on black-box testing
worsens the accessibility by software customers.
Structured-Object-based-Formal Language (SOFL) integrates structured
methods, object-oriented methods and formal methods. Condition data flow
diagrams are created with structured methods. Details are added with objectoriented methods. The formal part in VDM only provides partial constraints
to the final specification [10, section 2]. Reviews, inspections and testing take
the place of formal proofs. SOFL may be more appropriately considered a semiformal methodology. SOFL overhauls the entire software development life cycle
while precise scenarios only directly affect the specification activities.
Test First Design (TFD) or Test Driven Development (TDD) is a required
practice of Extreme Progamming (XP) [11]. TDD is an iterative development
approach with each iteration consists of five small steps: write a test, make it
compile, run it to see that it fails, modify the code until the test succeeds, and
refactor the code to remove any duplication introduced [12]. Tests, examples
in disguise, are used to guide programming. We use precise scenarios to guide
specification writing.
Framework for Integrated Tests (Fit) is a tool for enhancing collaboration
among customers, programmers and testers [13]. Customers document sample
computations in table form with HTML files. A row on a table, with specific
input and output values, denotes an example. Programmers create classes called
fixture to perform the necessary computing. The customer, programmer or tester
can run the fixture against the table within the framework. It creates a similar
table that highlights unexpected output values. New tests or examples can be
easily added to the table for a rerun. A potential drawback in Fit is that only
simple values are allowed in table cells. Though unnecessary for precise scenarios,
we have presented them in this paper using table form. We allow a table cell to
hold expressive data structures, for example, a set of relations.
Precise Scenarios – A Customer-Friendly Foundation
23
We use a simple ordering problem to demonstrate our approach [14]. Section
2 describes the problem and a representation of the state space in Z. Each of
sections 3 to 6 describes a user task, its precise scenarios and their use in the
derivation of schemas. Section 7 discusses validation, underspecification, overspecification, nondeterminism, testing and tool support. Our conclusions are
stated in section 8.
2
Ordering Problem and State Space
There are four user tasks in our ordering problem: create a new order, invoice an
order, cancel an order and refill the stock. The following statement introduces
basic types OrderId and Product for the identification of individual orders and
products. Once defined, we can use them in the specification without worrying
about their implementation.
[OrderId , Product ]
When an order is newly created, it will be in the state pending. After the
order has left the warehouse, its state changes to invoiced . These are the only
two order states that concern us regarding the scenarios to be discussed. The
following definition could be modified by adding the new state paid to deal with
payment scenarios in an iterative development process which is beyond the scope
of this paper.
OrderState ::= pending | invoiced
We declare the state space with schema OrderSystem which has four variables,
and after a horizontal dividing line, two invariants.
OrderSystem
stock : bag Product
orders : OrderId →
bag Product
orderStatus : OrderId →
OrderState
freeIds : P OrderId
dom orders
= dom orderStatus
dom orders freeIds = ∅
A bag of Product is equivalent to a partial function from Product to the
set of positive natural numbers N1 . We use the function to keep track of a
product’s quantity in stock or in an order. The symbols →
and P represent partial
function and power set respectively. The keyword dom stands for domain. The
first invariant ensures that an order id in use must appear in both orders and
orderStatus for an order cannot exist without its status. The second invariant
prevents an order id from being used and at the same time available for new
orders. Often, we don’t know all the constraints until we have explored the
scenarios. After an operation, we want to report whether it was successful.
24
O. Au, R. Stone, and J. Cooke
Report ::= OK | no more ids | order not pending
| id not found | not enough stock
In an arbitrary state, we have 5 nuts and 6 bolts in stock. Order 1 was placed
for 2 nuts and 2 bolts. Order 2 was placed for 3 bolts. Order 1 has been invoiced
and order 2 is still pending. Ids 3 and 4 are free for future use. The state could
be expressed with the following values in the variables of schema OrderSystem.
stock = {nut → 5, bolt → 6}
orders = {1 → {nut → 2, bolt → 2}, 2 → {bolt → 3}}
orderStatus = {1 → invoiced , 2 → pending}
freeIds = {3, 4}
3
New Order
The scenario NewOrder documents a successful order creation using four Z concepts. They are input with the symbol ?, output with !, maplet with →, and set
with { } and commas. The input parameter order ? places a new order for 4 nuts
and 4 bolts. Below the table headings are the pre-state followed by the post-state.
In the post-state, the 3-dot symbol . . . is used to denote the unchanged function
stock . Functions orders and orderStatus are extended by a map for OrderId 3.
The element 3 is removed from the set freeIds. The output parameters id ! and
report ! return 3 and OK respectively.
scenario NewOrder
order ? = {nuta → 4b , boltc → 4d }
stock
orders
orderStatus
freeIds
{nut → 5, {1 → {nut → 2, bolt → 2},
{1 → invoiced , {3e , 4}
bolt → 6} 2 → {bolt → 3}}
2 → invoiced }
...
{1 → {nut → 2, bolt → 2},
{1 → invoiced , {4}
2 → {bolt → 3},
2 → invoiced ,
3e → {nuta → 4b , boltc → 4d }} 3e → pending}
id ! = 3e , report ! = OK
Values referred in input/output parameters are subscripted allowing us to
relate them to the state. When two pieces of data have the same subscript, for
example, 3e in the post-state of orders and orderStatus, they must be identical.
If two pieces of data have identical value but different subscripts, for example
4b and 4d , their equality is merely a coincidence. Value 4d could have been 5d
throughout the scenario. The values allowed in a scenario are confined by earlier
declarations in schema OrderSystem. For example, 4b and 4d must be taken from
the set of positive natural numbers N1 .
To generalise the above scenario to an operation schema, we need a type for
the new order that maps Product to a positive integer.
Order == {order : bag Product | order = ∅}
Precise Scenarios – A Customer-Friendly Foundation
25
The scenario NewOrder can be converted to the equivalent Z schema below.
The declaration part declares the variables, input/output parameters and their
types. The symbol Δ alerts us that the state of OrderSystem is changed by
this operation. The predicate part lists the constraints on the variables and
parameters. The trailing symbol is used to denote a value after the operation.
NewOrderScenario
ΔOrderSystem
order ? : Order
id ! : OrderId
report ! : Report
order ? = {nuta → 4b , boltc → 4d }
3e ∈ freeIds
stock = stock
orders = orders ∪ {3e → {nuta → 4b , boltc → 4d }}
orderStatus = orderStatus ∪ {3e → pending}
freeIds = freeIds \ {3e }
id ! = 3e
report ! = OK
The first predicate specifies the value of the input parameter order ?. The
membership of 3e in set freeIds gives rise to the second predicate. The third
predicate states that stock is unchanged after the operation. The new maplets
for 3e , adding to orders and orderStatus, are captured in the fourth and fifth
predicates. The removal of 3e from the set freeIds is expressed next. The values
for the output parameters are specified by the last two predicates.
Subscripted values, used to represent input/output parameters, are not fixed.
For example, instead of picking 3e in the pre-state, we could have picked 4e . We
may therefore replace the subscripted values with the input/output variables,
NewOrderGeneralised
ΔOrderSystem
order ? : Order
id ! : OrderId
report ! : Report
order ? = order ?
id ! ∈ freeIds
stock = stock
orders = orders ∪ {id ! → order ?}
orderStatus = orderStatus ∪ {id ! → pending}
freeIds = freeIds \ {id !}
id ! = id !
report ! = OK
26
O. Au, R. Stone, and J. Cooke
for example, “3e ” with “id !” and “{nuta → 4b , boltc → 4d }” with “order ?”, to
have the generalised schema.
The generalised version of the Z schema can be simplified by removing the
two identity predicates that always evaluate to true.
NewOrder
ΔOrderSystem
order ? : Order
id ! : OrderId
report ! : Report
id ! ∈ freeIds
stock = stock
orders = orders ∪ {id ! → order ?}
orderStatus = orderStatus ∪ {id ! → pending}
freeIds = freeIds \ {id !}
report ! = OK
We now turn our attention to an unsuccessful attempt to create a new order. A
separate post-state is not shown in the scenario because the state is unchanged.
No subscripts are used because the input/output parameters do not relate to
any data in the state. The precondition is an empty set freeIds.
scenario NoMoreIdsError
order ? = {nut → 7}
stock
orders
orderStatus
freeIds
{nut → 5, {1 → {nut → 2, bolt → 2}, {1 → invoiced , { }
bolt → 6} 2 → {bolt → 3},
2 → invoiced ,
3 → {nut → 4, bolt → 4}, 3 → pending,
4 → {bolt → 8}}
4 → pending}
report ! = no more ids
The symbol Ξ indicates that the state OrderSystem is unchanged by the
schema.
NoMoreIdsError
ΞOrderSystem
order ? : Order
report ! : Report
freeIds = ∅
report ! = no more ids
Precise Scenarios – A Customer-Friendly Foundation
27
The precondition of NewOrder is that there is some element in freeIds. Conversely, the precondition of NoMoreIdsError is that the set freeIds is empty. The
disjunction of the two preconditions is true. Therefore operation NewOrderOp
can handle all situations.
NewOrderOp == NewOrder ∨ NoMoreIdsError
4
Invoice Order
The invoicing operation updates the order status from pending to invoiced and
reduces the stock accordingly. The two preconditions, shown before the table,
require the state to have sufficient stock to fill the order. The two postconditions,
shown after the table, determine the updated stock quantities.
scenario InvoiceOrder
id ? = 2a , 4f ≤ 5c , 3h ≤ 9e
stock
orders
orderStatus
freeIds
{nutb → 5c , {1 → {nut → 2},
{1 → invoiced , {3, 4}
boltd → 9e } 2a → {nutb → 4f , boltd → 3h }} 2a → pending}
{nutb → 1i , . . .
{1 → invoiced , . . .
boltd → 6j }
2a → invoiced }
report ! = OK , 1i = 5c − 4f , 6j = 9e − 3h
The Z mathematical toolkit provides the sub-bag symbol that concisely expresses multiple ≤ relationships between corresponding quantities in two bags.
− expresses multiple pairwise subtractions.
Likewise, the bag difference symbol ∪
The updating of the order status to invoiced is expressed with the override symbol ⊕. Round brackets represent function application, for example, orders(2a )
returns {nutb → 4f , boltd → 3h }.
InvoiceOrderScenario
ΔOrderSystem
id ? : OrderId
report ! : Report
id ? = 2a
orders(2a ) stock
orderStatus(2a ) = pending
− orders(2 )
stock = stock ∪
a
orders = orders
orderStatus = orderStatus ⊕ {2a → invoiced }
freeIds = freeIds
report ! = OK
After substitution and simplification, we have the following Z schema.
28
O. Au, R. Stone, and J. Cooke
InvoiceOrder
ΔOrderSystem
id ? : OrderId
report ! : Report
orders(id ?) stock
orderStatus(id ?) = pending
− orders(id ?)
stock = stock ∪
orders = orders
orderStatus = orderStatus ⊕ {id ? → invoiced }
freeIds = freeIds
report ! = OK
We have three unsuccessful scenarios for this operation. Explanations and
intermediate steps are skimmed here due to their similarities to earlier scenarios.
scenario IdNotFoundError
id ? = 3a , 3a = 1b , 3a = 2c
stock
orders
orderStatus
freeIds
{nut → 5, {1 → {nut → 2, bolt → 2}, {1b → invoiced , {3, 4}
bolt → 9} 2 → {bolt → 3}}
2c → pending}
report ! = id not found
IdNotFoundErrorScenario
ΞState
id ? : OrderId
report ! : Report
id ? = 3a
3a ∈
/ {1b , 2c }
report ! = id not found
IdNotFoundError
ΞState
id ? : OrderId
report ! : Report
id ? ∈
/ dom orderStatus
report ! = id not found
scenario OrderNotPendingError
id ? = 1a , invoicedb = pending
stock
orders
orderStatus
freeIds
{nut → 5, {1 → {nut → 2, bolt → 2}, {1a → invoicedb , {3, 4}
bolt → 9} 2 → {bolt → 3}}
2 → pending}
report ! = order not pending
Precise Scenarios – A Customer-Friendly Foundation
29
OrderNotPendingError
ΞState
id ? : OrderId
report ! : Report
orderStatus(id ?) = pending
report ! = order not pending
scenario NotEnoughStockError
id ? = 2a , 77c > 9b
stock
orders
orderStatus
freeIds
{nut → 5, {1 → {nut → 2, bolt → 2}, {1 → invoiced , {3, 4}
boltd → 9b } 2a → {boltd → 77c }}
2 → pending}
report ! = not enough stock
NotEnoughStockError
ΞState
id ? : OrderId
report ! : Report
¬(orders(id ?) stock )
report ! = not enough stock
We define operation InvoiceOrderOp to deal with all situations. When multiple errors happen at the same time, the definition is unspecific about which
error report to return. We will discuss nondeterminism in section 7.3.
InvoiceOrderOp == InvoiceOrder ∨ IdNotFoundError ∨
OrderNotPendingError ∨ NotEnoughStockError
5
Cancel Order
A pending order may be cancelled. Its order id is returned to the pool of free
id’s for future use.
scenario CancelOrder
id ? = 2a
stock
orders
orderStatus
freeIds
{nut → 5, {1 → {nut → 2, bolt → 2}, {1 → invoiced , {3, 4}
bolt → 6} 2a → {bolt → 3}}
2a → pendingb }
...
{1 → {nut → 2, bolt → 2}} {1 → invoiced } {2a , 3, 4}
report ! = OK
30
O. Au, R. Stone, and J. Cooke
The domain anti-restriction symbol −
is used to remove maplets for order id
2a from orders and orderStatus.
CancelOrderScenario
ΔOrderSystem
id ? : OrderId
report ! : Report
id ? = 2a
orderStatus(2a ) = pending
stock = stock
orders = {2a } −
orders
orderStatus = {2a } −
orderStatus
freeIds = {2a } ∪ freeIds
report ! = OK
We generalise the scenario schema by replacing 2a with id ?. After simplification, we have schema CancelOrder .
CancelOrder
ΔOrderSystem
id ? : OrderId
report ! : Report
orderStatus(id ?) = pending
stock = stock
orders = {id ?} −
orders
orderStatus = {id ?} −
orderStatus
freeIds = {id ?} ∪ freeIds
report ! = OK
It is an error trying to cancel an order that does not exist or have already
been invoiced . We can reuse error detecting schemas to handle all situations.
CancelOrderOp == CancelOrder ∨ IdNotFoundError ∨
OrderNotPendingError
6
Enter Stock
Entering stock is the task of replenishing depleted stock. By assuming that there
is always sufficient storage space, we don’t worry about detecting an error for this
task. The postconditions concerning the updated stock quantities are expressed
with the bag addition symbol .
Precise Scenarios – A Customer-Friendly Foundation
31
scenario EnterStock
newStock ? = {nuta → 80b , boltc → 70d }
stock
orders
orderStatus
freeIds
{nuta → 5e , {1 → {nut → 2, bolt → 2}, {1 → invoiced , {3, 4}
boltc → 9f } 2 → {bolt → 3}}
2 → pending}
{nuta → 85g , . . .
...
...
boltc → 79h }
report ! = OK , 85g = 5e + 80b , 79h = 9f + 70d
EnterStockScenario
ΔOrderSystem
newStock ? : Order
report ! : Report
newStock ? = {nuta → 80b , boltc → 70d }
stock = stock {nuta → 80b , boltc → 70d }
orders = orders
orderStatus = orderStatus
freeIds = freeIds
report ! = OK
EnterStock
ΔOrderSystem
newStock ? : Order
report ! : Report
stock = stock newStock ?
orders = orders
orderStatus = orderStatus
freeIds = freeIds
report ! = OK
7
Validation
We can apply the values of input parameters and pre-states in a scenario to its
operation schema. If the post-state and output parameters obtained are the same
as in the original scenario, we know that the operation schema works correctly
for the scenario.
Another type of validation we can perform is to apply new input parameters
and pre-state values to an operation schema. This exercise in essence creates
new scenarios. If the customer is satisfied with the newly created post-states
and output parameters, we gain confidence that our Z schemas meet the user
requirements. For instance, we can validate schema InvoiceOrder with the following input parameter and pre-state different from earlier scenarios.
32
O. Au, R. Stone, and J. Cooke
id ? = 3
stock = { nut → 5, bolt → 9}
orders = { 1 → {nut → 2},
2 → {nut → 4, bolt → 3},
3 → {nut → 5, bolt → 6}}
orderStatus = { 1 → invoiced , 2 → invoiced , 3 → pending}
freeIds = {4}
The first two predicates in schema InvoiceOrder specify its preconditions.
They both evaluate to true with the above data. The next four predicates specify
the resulting values of the four variables. The last predicate specifies the output
parameter. To save space, we only show the evaluation of two predicates.
orders(id ?) stock
orders(3) {nut → 5, bolt → 9}
{nut → 5, bolt → 6} {nut → 5, bolt → 9}
true
− orders(id ?)
stock = stock ∪
− {nut → 5, bolt → 6}
stock = {nut → 5, bolt → 9} ∪
3}
stock = {bolt →
After evaluating the schema predicates, we have a new scenario. Though without subscripts, preconditions and postconditions, there is enough information for
the customer to decide if it matches his or her expectation.
scenario InvoiceOrderNew
id ? = 3
stock
orders
orderStatus
ids
{nut → 5, {1 → {nut → 2},
{1 → invoiced , {4}
bolt → 9} 2 → {nut → 4, bolt → 3} 2 → invoiced ,
3 → {bolt → 5, bolt → 6}} 3 → pending}
{bolt → 3} . . .
{1 → invoiced , . . .
2 → invoiced ,
3 → invoiced }
report ! = OK
7.1
Underspecification
Underspecification happens when a required condition is missing. Suppose we
had omitted the following precondition of checking for sufficient stock in schema
InvoiceOrder.
orders(id ?)
stock
When we validate the incorrect schema with an excessive ordered quantity,
the operation may still succeed and yield a negative stock quantity which can
easily be spotted by the customer as an error.
Precise Scenarios – A Customer-Friendly Foundation
7.2
33
Overspecification
Overspecification happens when unnecessary conditions are included in a scenario. Recall scenario NewOrder. The quantities of the nuts and bolts in the
input parameter were both 4 by coincidence. In our original scenario, they have
different subscripts b and d to indicate that they need not be the same. Suppose
we had made a mistake by using the same subscript b on both occurrences of 4.
We would have a slightly different scenario.
scenario OverSpecifiedNewOrder
order ? = {nuta → 4b , boltc → 4b }
stock
orders
orderStatus
freeIds
{nut → 5, {1 → {nut → 2, bolt → 2},
{1 → invoiced , {3e , 4}
bolt → 6} 2 → {bolt → 3}}
2 → invoiced }
...
{1 → {nut → 2, bolt → 2},
{1 → invoiced , {4}
2 → {bolt → 3},
2 → invoiced ,
3e → {nuta → 4b , boltc → 4b }} 3e → pending}
id ! = 3e , report ! = OK
The equality implied by the identical subscripts gives rise to the first predicate
in the following schema. When we validate the schema with order ? = {nut →
7, bolt → 9}, the new predicate would evaluate to false. Overspecification is
caught when the operation fails on legitimate input and pre-state.
OverSpecifiedNewOrder
ΔOrderSystem
order ? : Order
id ! : OrderId
report ! : Report
∀ p, q : Product | p ∈ dom order ? ∧ q ∈ dom order ? •
order ?(p) = order ?(q)
id ! ∈ freeIds
stock = stock
orders = orders ∪ {id ! → order ?}
orderStatus = orderStatus ∪ {id ! → pending}
freeIds = freeIds \ {id !}
report ! = OK
7.3
Nondeterminism
Recall that we have defined InvoiceOrderOp to catch errors.
InvoiceOrderOp == InvoiceOrder ∨ IdNotFoundError ∨
OrderNotPendingError ∨ NotEnoughStockError
If the preconditions of OrderNotPendingError and NotEnoughStockError are
true at the same time, which error report are we going to get? In this nondeterministic definition of InvoiceOrderOp, we could get either one. If it is necessary
34
O. Au, R. Stone, and J. Cooke
to distinguish the two errors, we can eliminate nondeterminism by strengthening
their preconditions so that their conjunction is false.
There are times that nondeterminism is a sign of error. In section 7.1, we
discussed a situation where the checking for sufficient stock was omitted from
schema InvoiceOrder . The omission causes nondeterminism between
InvoiceOrder and NotEnoughStockError . Adding back the omitted predicate
strengthens the preconditions of the incorrect version of schema InvoiceOrder .
The conjunction of corrected InvoiceOrder and NotEnoughStockError is false
and thus nondeterminism between them is removed. In general, we can detect
nondeterminism by performing pairwise conjunction on the disjuncts used to
define an operation. A non-false conjunction suggests nondeterminism.
7.4
Testing
The use of precise scenarios for the development and validation of schemas relates
to a software testing technique called equivalence partitioning [15]. The technique
ensures that a scenario is selected from every class of similar situations. For
example, the operation InvoiceOrder can be partitioned into at least two classes
of situations, one for ordered quantities being a sub-bag of stock quantities and
one for otherwise. If necessary, we can divide them into more partitions. For
example, we can add a class of situations where the ordered quantities equal to
the stock quantities.
The research community has long held the attitude that formal methods reduce or eliminate the need for testing. But how do we know the formal specification is complete in the first place? Even for toy problems, it is hard to be
certain that a formal specification is complete. Though the use of precise scenarios cannot guarantee completeness, the improved customer involvement will
definitely help.
7.5
Tool Support Required
The success of a methodology relies heavily on the availability of good tools.
There are many tools around, for example, CADiZ [16], CZT (Community Z
Tools) [17] and Z/EVES [18], useful for checking type consistency and proving
theorems of a Z specification. In this paper, we have manually validated operation
schemas against precise scenarios. Existing Z tools can improve the efficiency
and reliability of the manual validation exercise by running an operation schema
through test cases [18, section 3.2.5]. Specific input values are used to see if they
can generate expected values in the state variables.
We need a tool to manage the operation schemas with their related scenarios.
When a scenario is changed, we need to identify the affected operation schema
to see if it still meets the new requirement described in the updated scenario.
Conversely, when we decide to update an operation schema, we need to identify
all the affected scenarios. If too many scenarios are affected, we may be better
off creating a new operation schema than to update an existing one. A tool with
such capabilities does not yet exist.
Precise Scenarios – A Customer-Friendly Foundation
8
35
Conclusions
The Z specification we derived in this paper is almost identical to the one found
in [14]. One notable difference is that our specification catches more errors.
It is premature to conclude how the use of precise scenarios would shape a Z
specification. However we do not seem to have lost any capability to create a
generic Z specification.
Are precise scenarios more comprehensible than Z specifications by customers?
Precise scenarios describe states with actual data; a few simple Z concepts are sufficient. On the other hand Z schemas describe operations with variables; additional
Z concepts are needed. The example in this paper and our unpublished work on numerical computation, sorting and telephone system confirm that precise scenarios
require fewer simpler concepts to describe than formal specifications. In addition,
biologists and educationists suggest that understanding begins with concrete examples [19]. Every customer is unique. In the extreme case where the customer is a
Z expert, he or she may actually prefer to reason directly in Z specification. But we
think, as long as precise scenarios are not exceedingly lengthy, customers in general
will have an easier time understanding them than formal specifications. As we continue to search for a better notation to write precise scenarios and gain experience
in using it on real or toy problems, it will take some time before we learn the true
value of precise scenarios in requirements elicitation.
In a real development project, there will be a great many precise scenarios
because we need a few of them for each operation schema. However we should not
be discouraged to use precise scenarios. With appropriate tool support, they are
no harder to manage than test cases. In fact, the content that goes into a precise
scenario is comparable to what goes into a test case. They differ in the time
of creation and purpose. Precise scenarios are created earlier for requirements
elicitation. They can be reused as test cases to reduce development costs.
Mistakes are not uncommon during the generalisation of precise scenarios to operation schemas. However underspecification and overspecification will be caught
by appropriately written scenarios. The current paper shows only scenarios with
pre- and post-states. Work in progress includes longer scenarios with intermediate
states. We are also working on the use of precise scenarios with other languages.
Eventually, we would like to field-test the approach with suitable tool support.
We propose to use precise scenarios as the foundation for formal specifications
because they are simple enough for the customers to understand and yet precise
enough for the validation of an implementation. While scenarios have been in use
for long, the novelty of precise scenarios is precision without sacrificing simplicity
and generality.
References
1. The Standish Group: The CHAOS Report, 5 (1994)
2. Zimmerman, M.K., Lundqvist, K., Leveson, N.: Investigating the Readability of
State-Based Formal Requirements Specification Languages. ICSE’02: 24th International Conference on Software Engineering, May 2002, pp. 33–43 (2002)
36
O. Au, R. Stone, and J. Cooke
3. Glass, R.L.: The Mystery of Formal Methods Disuse. Communications of the
ACM 47(8), 15–17 (2004)
4. Amyot, D., Logrippo, L., Buhr, R.J.A., Gray, T.: Use Case Maps for the Capture
and Validation of Distributed Systems Requirements. RE’99: 4th IEEE International Symposium on Requirements Engineering, June 1999, pp. 44–54 (1999)
5. Whittle, J., Schumann, J.: Generating Statechart Designs from Scenarios. ICSE’00:
22nd International Conference on Software Engineering, June 2000, pp. 314–323
(2000)
6. Uchitel, S., Kramer, J., Magee, J.: Synthesis of Behavioral Models from Scenarios.
IEEE Transactions on Software Engineering 29(2), 99–115 (2003)
7. Damas, C., Lambeau, B., Dupont, P., van Lamsweerde, A.: Generating Annotated
Behaviour Models from End-User Scenarios. IEEE Transactions on Software Engineering 31(12), 1056–1073 (2005)
8. Grieskamp, W., Lepper, M.: Using Use Cases. In: Executable, Z., Liu, S., McDermid, J.A., Hinchey, M.G. (eds.) ICFEM 2000: 3rd IEEE International Conference
on Formal Engineering Methods, September 2000, pp. 111–119 (2000)
9. Büssow, R., Grieskamp, W.: A Modular Framework for the Integration of Heterogeneous Notations and Tools. In: Araki, K., Galloway, A., Taguchi, K. (eds.)
IFM99: 1st International Conference on Integrated Formal Methods, June 1999,
pp. 211–230 (1999)
10. Liu, S., Offutt, A.J., Ho-Stuart, C., Sun, Y., Ohba, M.: SOFL: A Formal Engineering Methodology for Industrial Applications. IEEE Transactions on Software
Engineering 24(1), 24–45 (1998)
11. Beck, K.: Extreme Programming Explained: Embrace Change. Addison-Wesley,
Reading (2000)
12. Beck, K.: Test-Driven Development: By Example, p. 24. Addison-Wesley, Reading
(2003)
13. Mugridge, R., Cunningham, W.: Fit for Developing Software: Framework for Integrated Tests. Prentice-Hall, Englewood Cliffs (2005)
14. Bowen, J.P.: Chapter 1 - Z. In: Habrias, H., Frappier, M. (eds.) Software Specification Methods, ISTE, pp. 3–20 (2006)
15. Sommerville, I.: Software Engineering, 6th edn., pp. 444–447. Addison-Wesley,
Reading (2001)
16. Toyn, I., McDermid, J.A.: CADiZ: An Architecture for Z Tools and its Implementation. Software – Practice and Experience 25(3), 305–330 (1995)
17. Malik, P., Utting, M.: CZT: A Framework for Z Tools. ZB2005: 4th International
Conference of B and Z Users, April 2005, pp. 65–84 (2005)
18. Saaltink, M.: The Z/EVES 2.0 User’s Guide, ORA Canada, pp. 31–32 (1999)
19. Zull, J.E.: The Art of Changing the Brain, pp. 102–103. Stylus Publishing (2002)
Automated Verification of Security Policies
in Mobile Code
Chiara Braghin1, Natasha Sharygina2,3, and Katerina Barone-Adesi2
1
2
DTI, Università Statale di Milano, Crema, Italy
Faculty of Informatics, Università della Svizzera Italiana, Lugano, Switzerland
3
School of Computer Science, Carnegie Mellon University, Pittsburgh, USA
Abstract. This paper describes an approach for the automated verification of
mobile programs. Mobile systems are characterized by the explicit notion of locations (e.g., sites where they run) and the ability to execute at different locations,
yielding a number of security issues. We give formal semantics to mobile systems
as Labeled Kripke Structures, which encapsulate the notion of the location net.
The location net summarizes the hierarchical nesting of threads constituting a
mobile program and enables specifying security policies. We formalize a language for specifying security policies and show how mobile programs can be
exhaustively analyzed against any given security policy by using model checking
techniques.
We developed and experimented with a prototype framework for analysis of
mobile code, using the SATABS model checker. Our approach relies on SATABS’s support for unbounded thread creation and enhances it with location net
abstractions, which are essential for verifying large mobile programs. Our experimental results on various benchmarks are encouraging and demonstrate advantages of the model checking-based approach, which combines the validation of
security properties with other checks, such as for buffer overflows.
1 Introduction
Despite the promising applications of mobile code technologies, such as web services
and applet models for smart cards, they have not yet been widely deployed. A major
problem is security: without appropriate security measures, a malicious applet could
mount a variety of attacks against the local computer, such as destroying data (e.g.,
reformatting the disk), modifying sensitive data (e.g., registering a bank transfer via a
home-banking software), divulging personal information over the network, or modifying other programs.
Moreover, programming over a wide area network such as the Internet introduces
new issues to the field of multi-threaded programming and analysis. For example, during the execution of a mobile program, a given thread may stop executing at a site, and
continue executing at another site. That is, threads may jump from site to site while retaining their conceptual identity. The following issues distinguish mobile systems from
a more general case of multi-threaded programs:
This work was done when the first author was staying at the Faculty of Informatics, Università
della Svizzera Italiana, Lugano, Switzerland.
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 37–53, 2007.
c Springer-Verlag Berlin Heidelberg 2007
38
C. Braghin, N. Sharygina, and K. Barone-Adesi
– threads may run in different locations (e.g., administrative domains, hosts, physical
locations, etc.);
– communication among threads and threads migration take into account their geographical distribution (e.g., migration can only occur between directly linked net
locations).
To protect mobile systems against security leaks, security policies are defined, i.e., rules
or conditions that state which actions are permitted and which are prohibited in the system. The rules may concern access control or information flow, and are usually verified
on the fly during the system execution. The dynamic approach has several drawbacks:
it slows down the system execution, there is no formal proof that the dynamic checks
are done properly, and the checks are not exhaustive.
This paper describes an approach for modeling and verifying mobile programs. We
give formal semantics to mobile systems as Labeled Kripke Structures (LKSs), which
encapsulate the notion of location and unbounded thread creation typical to mobile
systems. We define the semantics of mobile programs where thread locations are hierarchically structured, where threads are always confined to locations and where threads
may move within the Internet. The LKS notation allows modeling both data and communication structures of the multi-threaded systems. Consequently, it outperforms the
traditional process algebra approach that captures only the communication behavior.
We formalize a language for specifying general-purpose and application-dependent
security policies, and we show how mobile programs can be statically and exhaustively
analyzed against those security policies by using model checking techniques. A policy
configuration file, specifying what permissions (i.e., which types of system resource
access) to deny, is given as an input to the model checker together with the program
to be verified. To support features of mobile systems, the policy specification language
defines rules for expressing and manipulating the code location.
We implemented a prototype framework for modeling and verifying mobile programs written in C. In our approach, a mobile program is annotated with information
related to the security policy in such a way that if and when the security policy is violated, the model checker returns a counter-example that led to such an error. In such a
way, we are able to discover both implementation and malicious errors. Our framework
uses the SATABS model checker [1], which implements a SAT-based counterexampleguided abstraction refinement framework (CEGAR for short) for ANSI-C programs.
To cope with the computational complexity of verifying mobile programs, we define
projection abstractions. Given a path of a multi-threaded program, one can construct
projections by restricting the path to actions or states satisfying certain conditions. We
exploit the explicit notion of locations and define location-based projections, which
allow efficient verification of location-specific security policies.
In summary, our approach to modeling and verifying mobile programs has several
advantageous features:
– it explicitly models thread location, location distribution and thread moving operations, which are essential elements of mobile programs;
– it preserves both data and communication structures of mobile systems;
– it defines a specification language for specifying security policies of mobile code;
Automated Verification of Security Policies in Mobile Code
39
– it integrates model checking technologies to support exhaustive analysis of security
policies;
– it defines location-specific abstractions which enable the efficient verification of
large mobile code applications.
We experimented with a number of mobile code benchmarks by verifying various security policies. The results of verifying security policies, dealing with both access permissions of system actions and tracing the location net with respect to permissible location
configurations, were encouraging.
2 Related Work
The use of mobile systems raises a number of security issues, including access control
(is the use of the resource permitted?), user authentication (to identify the valid users),
data integrity (to ensure data is delivered intact), data confidentiality (to protect sensitive
data), and auditing (to track uses of mobile resources). All but the first category are
closely coupled with research in cryptography and are outside of the scope of this paper.
Our techniques assume that the appropriate integrity checking and signature validation
are completed before the security access policies are checked.
Trust management systems (TMS) [2] address the access control problem by requiring that security policies are defined explicitly in a specification language, and relying
on an algorithm to determine when a specific request can be allowed. An extensive survey of trust management systems and various authorization problems can be found in
[3,4,5]. The major difference from our work is that these techniques rely on encryption techniques or proof-carrying code certification. For example, in the SPKI/SDSI
framework, all principals are represented by their public keys, and access control is
established by checking the validity of the corresponding public keys. In contrast, our
security analysis reduces access control problems to static reachability analysis.
Certified code [6] is a general mechanism for enforcing security properties. In this
paradigm, untrusted mobile code carries annotations that allow a host to verify its trustworthiness. Before running the agent, the host checks the annotations and proves that
they imply the host’s security policy. Despite the flexibility of this scheme, so far, compilers that generate certified code have focused on simple type safety properties rather than
more general security policies. The main difficulty is that automated theorem provers are
not powerful enough to infer properties of arbitrary programs and constructing proofs by
hand is prohibitively expensive. Unable to prove security properties statically, real-world
security systems such as the Java Virtual Machine (JVM) have fallen back on run-time
checking. Dynamic security checks are scattered throughout the Java libraries and are
intended to ensure that applets do not access protected resources inappropriately. However, this situation is unsatisfying for a number of reasons: 1) dynamic checks are not
exhaustive; 2) tests rely on the implementation of monitors which are error-prone; and
3) system execution is delayed during the execution of the monitor.
Modeling of Mobile Systems. The most common approach to modeling mobile programs is the process algebra-based approach. Various location-aware calculi, with an
explicit notion of location, have arisen in the literature to directly model phenomena
40
C. Braghin, N. Sharygina, and K. Barone-Adesi
such as the distribution of processes within different localities, their migrations, or their
failures [7,8,9,10].
The π calculus [11] is often referred to as mobile because it features the ability to
dynamically create and exchange channel names. While it is a de facto standard for
modeling concurrent systems, the mobility it supports encompasses only part of all the
abstractions meaningful in a distributed system. In fact, it does not directly and explicitly model phenomena such as the distribution of processes within different localities,
their migrations, or their failures. Moreover, mobility is not expressed in a sufficiently
explicit manner since it basically allows processes only to change their interconnection
structures, even if dynamically. Indeed, name mobility is often referred to as a model
of labile processes or as link mobility, characterized by a dynamic interaction structure,
and distinguished from calculi of mobile processes which exhibit explicit movement.
Seal [12] is one of the many variants spawned by π calculus. The principal ingredient
added, the seal, is the generalization of the notions of agents and locations. Hierarchical locations are added to the syntax, and locations influence the possible interaction
among processes. As in the π calculus, interaction takes place over named channels.
Communication is constrained to take place inside a location, or to spread over two locations that are in a parent-child relationship. Locations are also the unit of movement,
abstracting both the notions of site and agent: a location, together with its contents, can
be sent over a channel, mimicking mobility of active computations.
Djoin [10] extends the π calculus with location, migration, remote communication
and failure. The calculus allows one to express mobile agents roaming on the net, however, differently from the Mobile Ambient calculus, the details of message routing are
hidden.
The most famous one is the Mobile Ambient calculus [13,7]: this specification language provides a very simple framework that encompasses mobile agents, the domains
where agents interact and the mobility of the agents themselves. An ambient is a generalization of both agent and place notions. Like an agent, an ambient can move across
places (also represented by ambients) where it can interact with other agents. Like a
place, an ambient supports local undirected communication, and can receive messages
(also represented by ambients) from other places [14]. The formal semantics we give to
mobile systems draws many ideas from the ambient calculus.
The disadvantages of process algebra-based approaches, however, is that they model
only limited details of the systems (they are restricted only to communication structures
and do not preserve any information about data). This restricts the set of properties that
can be analyzed to a set of control-specific properties. Additionally, process-algebraic
techniques usually deal with coarse over approximations during the analysis of mobile
systems. Over-approximations are useful to reduce the analysis complexity and guarantee that, if no errors are found in the abstract system, then no errors are present in the
actual system. However, if errors are found, the verification techniques developed for
process algebra fail to guarantee that they are real. In contrast to the process algebraic
approach, our techniques not only model both data and communication structures but
also (in the context of the abstraction-based model checking) simulate the errors on the
actual system and, if the errors are found to be spurious, the approximated programs are
Automated Verification of Security Policies in Mobile Code
41
refined. To the best of our knowledge, there are no abstraction-refinement techniques
that would support the process algebraic analysis techniques.
3 Formal Semantics of Mobile Programs
3.1 Mobile Programs
This section gives the syntax of mobile programs using a C-like programming language
(which we believe is one of the most popular general-purpose languages). We extend
the standard definition of multi-threaded programs with an explicit notion of location
and moving actions1 . The syntax of a mobile program is defined using a finite set of
variables (either local to a thread or shared among threads), a finite set of constants,
and a finite set of names, representing constructs for thread synchronization, similar to
the Java wait and notify constructs. It is specified by the following grammar:
LT ::=
| [[ T ]
| LT1 LT2
T ::=
T1 | T2
| Instr
Instr ::=
Instr1 ; Instr2
| x := e
| if (Expr != 0) Instr
| while (Expr != 0) Instr
| skip
| m
| fork
| M Instr
Expr ::=
c
| Expr1 ( + | - | * | /) Expr2
M Instr ::=
| go in() | go out()
location-aware threads
single thread
parallel composition
threads
parallel comp.
sequential exec.
instructions
sequential exec.
assignment
condition
loop
skip
sync. call
thread creation
moving action
expressions
constant
arith. operation
moving actions
move in/out
In the grammar, x ranges over variables, c over constants, and m over the names of
synchronization constructs. The meaning of the constructs for expressions and instructions is rather intuitive: an expression can be either a constant or an arithmetic operation
(i.e., sum, difference, product and division). The instruction set mainly consists of the
standard instructions for imperative languages: a sequential composition operator (;),
the assignment instruction, the control flow instructions if and while, and the skip
statement. The instructions specific to the threads package are the fork instruction,
which spawns a new thread that is an exact copy of the thread executing the fork
instruction, and the call to a synchronization method m.
We further assume a set of location names Loc, and we let , 1 , 2 , . . . range over
Loc. A thread is [[ T ] , with being the location name of thread T . More than one
1
For detailed discussion on programming languages for mobile code and their syntax the reader
can refer to [15].
42
C. Braghin, N. Sharygina, and K. Barone-Adesi
thread may be identified by the same location, that is [[ T1 | T2 ] (examples will be
shown later). A mobile program is defined by the parallel composition of multiple
threads. A location can thus be seen as a bounded place, where mobile computation
happens.
Conceptually, thread locations represent the geographical distribution of the Web. To
capture this fact, we use a special structure, called a location net, which encapsulates
the hierarchical nesting of the Web. We define the location net as a tree, whose nodes
are labeled by unique location names, and the root is labeled by the special location
name env, representing the external environment of the system under analysis. A tree
t is identified with the set of its paths.
Example 1. As a running example consider a shopping agent program, where several
agents are sent out over the network to visit airline Web-sites to find the best airfare.
Each agent is given various requirements, such as departure and destination time restrictions. After querying the airline database, it reports back the information to the
user who made the request.
For simplicity, let’s assume that the system is composed of threads T1 ...T6 which
are distributed among various locations: Loc = {env, 0 , 1 , 2 , 3 , 4 } and that a single thread is sent out. Here, 2 , 3 , 4 are the locations of various websites; 1 is the
location of the agent, 0 is the program sending out the agent, and env the generalized environment location. Clearly, some of the locations are nested, and the location net corresponds to a tree, which can be defined by the set of its paths, i.e.,
t = {env.0 .1 , env.2 , env.3 , env.4 }, or can be depicted as follows.
In the rest of the paper, when referring to nodes of the location net, we borrow standard vocabulary to define the relationship among tree nodes, such as father, child and
sibling. For instance, in our example, 2 and 3 are siblings, whereas 0 is the father of
1 (and 1 is the child of 0 ).
The location net represents the topology of thread locations. In fact, it implicitly represents the distribution of threads. Location-aware threads can perform moving actions to
change this distribution. These actions are the moving instructions, go in and go out.
The explicit notion of location and the existence of moving actions affect the interaction
among concurrent threads as follows (the formal definition will be given in Section 3.2):
- There are two types of composition: the parallel composition among threads identified by the same location (i.e., [[ T1 | T2 ] ), and the parallel composition among
threads identified by different locations (i.e., 1 [ T1 ] 2 [ T2 ] ) - see the example
below.
- The execution of moving actions changes the location net, i.e., mobility can be
described by updates of the location net.
Automated Verification of Security Policies in Mobile Code
43
- The execution of moving actions is constrained by the structure of the location net,
i.e., moving actions can be performed only if the thread location and the target
location has the father-child or siblings relationship.
Example 2. For example, if threads T1 and T2 represent a mail server and a browser
running at site l0 and threads T3 ...T6 are each running at sites l1 ...l4 , then the shopping
agent program of Example 1 can be formalized as follows:
0 [ T 1 | T 2 ] 1 [ T 3 ] 2 [ T 4 ] 3 [ T 5 ] 4 [ T 6 ]
In this program, threads T1 and T2 are running in parallel locally since 0 [ T1 | T2 ] .
On the contrary, T3 and T4 are running remotely since 1 [ T3 ] 2 [ T4 ] .
3.2 The Computational Model
In this section we formalize the semantics of mobile programs. We first define the semantics of a single thread, and then extend it to the case of a multi-threaded system.
As done in the examples of the previous section, when discussing about multi-threaded
systems consisting of n threads, we will use i, with 1 ≤ i ≤ n, as a unique identifier of
each thread T (i.e., we will write Ti ).
Definition 1 (Location-aware Thread). A thread is defined as a Labeled Kripke Structure T = (S, Init, AP, L, Σ, R) such that:
- S is a (possibly infinite) set of states;
- Init ∈ S is the initial state;
- AP is the set of atomic propositions;
- L : S → 2AP is a state-labeling function;
- Σ is a finite set (alphabet) of actions;
- R ⊆ S × Σ × (S ∪ { S × S }) is a total labeled transition relation.
A state s ∈ S of a thread is defined as a tuple (Vl , Vg , pc, ϕ, η), where Vl is the evaluation of the set of local variables, Vg is the evaluation of the set of global variables, pc
is the program counter, ϕ : Loc → Loc is a partial function denoting the location net
(where Loc is the set of location names as defined in Section 3.1), and η : N → Loc is a
partial function denoting the thread location. More specifically, ϕ describes the location
net at a given state by recording the father-child relationship among all nodes of the net
(⊥ in the case of env), whereas η(i) returns the location name of Ti (i.e., the thread
identified by i).
Example 3. Consider again the shopping agent program and its location net as defined in Example 2. In this case, the location net function is ϕ(0 ) = env, ϕ(1 ) =
0 , ϕ(2 ) = env, ϕ(3 ) = env, ϕ(4 ) = env. In addition, the thread location function
for threads T1 · · · T6 is defined as η(1) = 0 , η(2) = 0 , η(3) = 1 , η(4) = 2 , η(5) =
3 , η(6) = 4 .
The transition relation R is labeled by the actions of which there are four types: moving,
synchronization, thread creation, and τ actions, which are contained in the mutually
disjoint sets Σ M , Σ S , Σ T , Σ τ , respectively. We use Σ to identify the set of all actions. τ represents a generic action such as an assignment, a function call, etc. We write
44
C. Braghin, N. Sharygina, and K. Barone-Adesi
a
a
s −→ s to mean (s, a, s ) ∈ R, with a ∈ Σ. Moreover, we write s −→ i s to specify
which thread performed the action. Note that, since we allow thread creation, if thread
fork
Ti performs a fork action, s can be defined as a pair of states s.t. s −−−−−→ i (s , s),
where s is the next state of s, and s = Initi is an initial state of the newly created
thread (which corresponds to the initial state of Ti ).
Table 1 gives the inference rules for the labeled transition relation in the case of
moving actions (go in(), go out()), thread creation action, fork, and the synchronization action m. For the rules corresponding to the generic operations the reader is
referred to [16]. The premises of the rules presented in Table 1 represent guarded conditions for the execution of the actions. All rules check the value of Instr(s.pc), which
determines the instruction to be executed by the running thread. Then, depending on
the type of the action, they check further guarding conditions. In the consequences of
the inference rules, we describe (within square brackets) the updates of the thread state
caused by the execution of an action. We use the standard notation ϕ ∪ {1 → 2 } (with
1 , 2 ∈ Loc) to indicate the update to function ϕ, i.e., the updates to the location net.
In the case of a ”fork” action, thread Ti spawns a new thread that is an exact copy
of itself. As a consequence, the program counter of Ti is updated, and a new thread is
created with an initial state s. The initial state is a copy of the initial state of Ti .
In the case of a ”go in()” action, if is a sibling location to thread Ti location
(i.e., s.ϕ(s.η(i)) = s.ϕ()), then the thread makes a transition and changes the state
accordingly: the program counter pc is incremented, and the location net is updated (
is now the father location of Ti location). If is not a sibling location, then the action is
not performed because the guard does not hold.
In the case of a”go out()” action, if is the father location to thread Ti location
(i.e., s.ϕ(s.η(i)) = ), then the thread makes a transition and changes the state accordingly: the program counter pc is incremented, and the location net is updated ( is now
a sibling location of Ti location). If is not the father location, then the action is not
performed because the guard does not hold.
Note that the subtle features of mobile programs (namely, location, location net and
unbounded thread creation) are modeled explicitly.
Let T1 , · · · , Tn be a set of threads initially present in the mobile program P, then
P = T1 · · · Tn . The parallel composition operation is defined as follows.
Definition 2 (Mobile Program). Let thread T1 = (S1 , Init1 , AP1 , L1 , Σ1 , R1 ) and
thread T2 = (S2 , Init2 , AP2 , L2 , Σ2 , R2 ) be two Labeled Kripke structures. Then their
composition is defined as follows: T1 T2 = (S1 × S2 , Init1 × Init2 , AP, L, Σ1 ∪
Σ2 , R) with the labeled transition relation defined in Table 2.
In Table 2, a single state belonging to thread Ti is denoted by si , i.e., with i as superscript to indicate the thread number. When needed, we also use a subscript (and variable
j) to indicate the position of an element in the path. For example, si1 is the initial state
of thread Ti . Given a state si ∈ Si of thread Ti , si .Vl , si .Vg , si .pc, si .ϕ and si .η are
the values of local variables Vl , of global variables Vg , of program counter pc, of ϕ
and of η, respectively. Moreover, Instr(si .pc) denotes the instruction pointed by pc in
thread Ti at state si . Note that ∀i, j, i = j, Σi ∩ Σj = Σ S , that is threads share only
synchronization actions. In other words, threads proceed independently on local actions
Automated Verification of Security Policies in Mobile Code
45
Table 1. Inference rules for the labeled transition relation R for thread Ti
(F ORK - ACTION )
Instr(s.pc) = fork
s −−−→ i (s , s) [s .pc = s.pc + 1; s = Initi ]
fork
(in- ACTION )
Instr(s.pc) = go in() ∧ (∃1 .1 := s.η(i) ∧ s.ϕ(1 ) = s.ϕ())
s −−−−−→ i s [s .pc = s.pc + 1; s .ϕ = s.ϕ ∪ {1 → }]
go in()
(out- ACTION )
Instr(s.pc) = go out() ∧ (∃1 .1 := s.η(i) ∧ s.ϕ(1 ) = )
s −−−−−−→ i s [s .pc = s.pc + 1; s .ϕ = s.ϕ ∪ {1 → s.ϕ()}]
go out()
(S YNC - ACTION )
Instr(s.pc) = m
s −→ i s [s .pc = s.pc + 1]
m
and synchronize on shared actions (m ∈ Σ S ), or on shared data (by definition of Si ,
S1 ∩ S2 = ∅). This notion of composition is derived from CSP [17].
The definition of a path of a mobile program reflects the possibility of unbounded
thread creation during the execution of the fork instruction.
Definition 3 (Path). A path π = (s11 , s21 , . . . , sn1 1 ), a1 , (s12 , s22 , . . . , sn2 2 ), a2 , . . . of
a mobile program is an alternating (possible infinite) sequence of tuples of states and
events such that:
(i) nj ∈ N and, ∀i, j ≥ 1, si1 = Initi , sij ∈ Si , and aj ∈ ∪i Σi ;
aj
(ii) either sij −−→ sij+1 or sij = sij+1 for 1 ≤ i ≤ nj+1 ;
(iii) if aj = fork:
aj
nj+1
= Initk with skj −−→ skj+1
– then nj+1 = nj + 1 and sj+1
– else nj+1 = nj .
A path includes tuples of states, rather than a single state. The reason for that is that
when a fork operation is executed, the state of the newly created thread must be
recorded. Our notation indicates each state sji by two indices, i and j, one to indicate
the thread number, the other one to indicate the position in the path, respectively. The
size of the tuple of states (i.e., the number of the currently existing threads) increases
only if a fork is executed, otherwise it remains unchanged (case (iii)). In case of a
fork, index k identifies the thread that performed the action. Thus, the state of the
newly created thread is a copy of the initial state of thread Tk . Moreover, depending on
the type of action (i.e., shared or local) one or more threads will change state, whereas
the others do not change (case (ii)).
46
C. Braghin, N. Sharygina, and K. Barone-Adesi
Table 2. The labeled transition relation for the parallel composition of two threads
(S YNC - ACTION )
a
a ∈ Σ1S ∧ s1 −→ 1 s
1
a
∧ a ∈ Σ2S ∧ s2 −→ 2 s
a
1
2
∧ s1 .η(1) = s2 .η(2)
2
(s1 , s2 ) −→ (s , s )
(L-PAR )
a∈
Σ1M
(R-PAR )
a
∧ s −→ 1 s
a
1
1
(s1 , s2 ) −→ 1 (s , s2 )
a
a ∈ Σ2M ∧ s2 −→ 2 s
a
2
2
(s1 , s2 ) −→ 2 (s1 , s )
4 Specifying Security Policies of Mobile Programs
In order to support features of mobile systems, we devised a policy specification language that defines rules for expressing also the code location. This security language
primarily works at the level of method calls and variable accesses. Methods may be
disallowed to an agent, either in general, or when invoked with specific arguments.
(Global) variables may be marked as having a high security level, and they cannot be
assigned to variables of a lower level; it is also possible to specify methods that may not
be accessed within or passed to (no Read Up, no Write Down). In this way, it is possible
to express both information flow and access control policies with the same language .
The BNF specification of the language follows, where terminals appear in Courier,
non terminals are enclosed in angle brackets, optional items are enclosed in square
brackets, items repeated one or more times are enclosed in curly brackets, and alternative choices in a production are separated by the | symbol. A policy might contain: (i)
the definition of security levels; (ii) a list of operation definitions; and (iii) a list of
deny statements, each one including one or more permission entries. In the definition of
security levels, we enumerate the high level variables to specify a multi-level security
policy. The definition of an operation collects together functions with the same meaning
or side-effect (e.g., scanf and fread). A deny statement specifies which types of actions
are not allowed to entities. By default, in the absence of deny statements, all actions are
allowed to every possible user.
The entities to deny permissions to consist of processes (e.g., agents), identified by
their current location. The keyword public means that the permission is denied to all
entities. As we are dealing with mobile systems, an entity can also be identified by the
host address (via codeBase), or by the location (via codeOrigin) it came from.
The keyword remote identifies non-local locations.
A permission entry must begin with the keyword permission. It specifies actions
to deny. An action can be a function (either user-defined or from the standard library),
or an operation (a collection of functions). If it is a function, it is possible to also specify
(i) formal parameters (variable names), (ii) actual parameters (the value of the arguments passed), (iii) an empty string, denying access to the function regardless of the
Automated Verification of Security Policies in Mobile Code
47
arguments to it, or (iv) the keyword high (no high variables can be passed as arguments to this function). Notably, an actual parameter may be a location (a trailing *
prevents not only the location, but all sub-locations too).
policy −→ { sec levels | operation def | deny statement }
deny statement −→ deny to deny target [ code base ] [ code origin ]
{ permission entry {, permission entry } }
deny target −→ public | entity list
entity list −→ entity id {, entity id }
entity id −→ location id
location id −→ identifier
identifier −→ ( letter | symbol ) { letter | digit | symbol }
symbol −→ _ | .
code base −→ codeBase IPv4 addr
code origin −→ codeOrigin ( location | remote)
location −→ location id {: location id }
permission entry −→ permission action
action −→ function | operation
function −→ function function id parameters
function id −→ identifier
parameters −→ actual par | formal par | high | ε
actual par −→ " string "
formal par −→ args vars | " location id " [*]
vars −→ identifier {, identifier }
operation def −→ operation { function id {, function id } }
operation −→ operation operation id
operation id −→ identifier
receiver −→ location id
sec levels −→ High={ vars }
Consider the Java sandbox: it is responsible for protecting a number of resources by
preventing applets from accessing the local hard disk and the network. In our language,
a sketch of this security policy could be expressed as:
operation read_file_system { fread, read, scanf, gets}
deny to public codeOrigin remote
{ permission function connect_to_location,
permission operation read_file_system }
A multi-level security policy could be expressed as:
High={confidential_var, x}
deny to public codeOrigin remote
{ permission function fopen high}
48
C. Braghin, N. Sharygina, and K. Barone-Adesi
4.1 Security and Projection
To cope with the computational complexity of verifying mobile programs, we define
projection abstractions. Given a path of a multi-threaded program T1 · · · Tn , one
can construct projections by restricting the path to the actions in the alphabet of threads,
or to states satisfying some conditions. We exploit the explicit notion of locations and
define the location-based projections, which allow efficient verification of locationspecific security policies (security policies in which codeOrigin or codeBase is
present). With a location-specific policy, only processes which run on the indicated location need to be verified.
In the following, we assume only paths of finite length, as they are computed by
the symbolic fix-point algorithm to handle verification of systems with an unbounded
number of threads. In addition, we write for the empty path, and we use the dot
notation to denote the concatenation of sequences. The concatenation of sequences will
be used in the inductive definitions of projections to concatenate subsequences of paths.
Notice that . is the concatenation operator for sequences of characters, thus it is not
affected by the presence of mismatched parentheses.
Definition 4 (Location Projection, π ↓ ). Let P be T1 · · · Tn and ∈ Loc be
a location. The projection function P roj : L(P)∗ → L(P)∗ is defined inductively as
follows (we write π ↓ to mean P roj (π)):
1.
2.
3.
4.
5.
↓ =
If si .η(i) = then (si .π) ↓ = si .(π ↓ )
If si .η(i) = then (si .π) ↓ = π ↓
If a ∈ Σi , with i s.t. si .η(i) = , then (a.π) ↓ = a.(π ↓ )
If a ∈ Σi , with i s.t. si .η(i) = , then (a, (s1 , s2 , . . . , sn ).π) ↓ = π ↓
This projection traces the execution of threads for a particular location. The following
information is collected: (i) states of threads whose location is (i.e., threads Ti such
that si .η(i) = ), and (ii) actions that are performed by the threads whose location is
(i.e., actions a such that a ∈ Σi , with [[ Ti ] ). Here, the concatenation is done on
each state element of the path, since each single state is examined to satisfy condition
(i) (rules 2-3). On the contrary, once an action does not satisfy condition (ii), the next
tuple is erased (rule 4).
With respect to what happens at a particular location during execution of a mobile
program, there is no loss of precision in this projection-based abstraction. The projection removes only states and actions which are irrelevant to the particular location.
Moreover, since security policies are defined in terms of a single location, this abstraction does not introduce spurious counterexamples during the verification of security
policies using the codeOrigin entry.
5 A Model Checking Framework for Verification of Security
Policies
A prototype framework for security analysis of mobile programs is shown in the picture
below. A mobile program, P , and a security policy, S, are provided as an input to the
model checking engine.
Automated Verification of Security Policies in Mobile Code
49
These inputs are processed, creating a new program, P , annotated with the security
invariants. It has the following property: an assertion assert(0) (a security invariant)
is not reachable in P if and only if P enforces the security policy S. Thus, it is sufficient
to give P as an input to a model checker to statically determine whether or not an
assert(0) is reachable in P .
The procedure for annotating the program with security invariants is a multi-step process. First, the intersection of methods in the security policy and methods used within
the agent to verify is found. Then, a wrapper method is created for each of these methods. This wrapper contains an assert(0), either unconditionally, or within a guard,
based on the policy (this may check where the agent came from, and/or the arguments
being passed to the method). The handling of high variable access is more complex (due
to scoping and syntax), but analogous. This annotating procedure, as in SLIC [18], is the
implementation of Schneider’s security automata [19]. In fact, the annotated program
P consists of program P with inlined the reference monitor that enforces the security
policy S.
Our framework uses a model checking toolset, SATABS [1]. Applying model checking to the analysis of mobile and multi-threaded systems is complicated by several factors, ranging from the perennial scalability problems to thread creation that is potentially
unbounded and that thus leads to infinite state space. Predicate abstraction is one of the
most popular and widely applied methods for systematic state-space reduction of programs. It abstracts data by only keeping track of certain predicates on the data. Each
predicate is represented by a Boolean variable in the abstract program, while the original
data variables are eliminated. The resulting Boolean program is an over-approximation
of the original program. One starts with a coarse abstraction, and if it is found that an
error-trace reported by the model checker is not realistic, the error trace is used to refine the abstract program, and the process proceeds until no spurious error traces can
be found. The actual steps of the loop follow the abstract-verify-refine paradigm [20].
SATABS implements the abstraction refinement loop by computing and refining abstract
programs. The procedure for the location-specific projections can be seen as the extension
of SATABS’s abstraction procedures. Among various techniques employed by SATABS,
there is a model checker for Boolean programs (computed by the SATABS abstraction
engine), B OPPO[16] that handles unbounded thread creation. The execution of a fork
action corresponds to the migration of the code to the new sites and potentially leads to
the creation of an unbounded number of new threads. SATABS implements a symbolic
algorithm for over-approximating reachability in Boolean programs to support arbitrary
thread creation which is guaranteed to terminate [21]. The devised algorithm is used as
the underlying reachability engine in the CEGAR framework and is efficient. The SATABS ability to handle programs with arbitrary thread creation was the key reason for
using it as a model checking engine of our security framework.
50
C. Braghin, N. Sharygina, and K. Barone-Adesi
An initial configuration file can also be provided, to test whether the policy is upheld
in specific network configurations (where the agent came from, both on the underlying
network and the location network, and where it’s currently running). Several functions
exist within the mobile code framework to check these values; there is a dynamic version to be used at run-time, and a static version which is generated from the specified
initial configuration. To check whether the policy holds under all possible conditions,
it suffices to not provide these function definitions to SATABS, which then treats the
results as non-deterministic; this can be accomplished by telling SATABS to use the
run-time version of the definitions, not providing an initial configuration, or by not providing the generated location file as an input to SATABS.
SATABS supports C programs, thus our benchmarks have a C-base mobile language. Since serialization is not possible in C, we only allow code mobility (i.e., applet
sending); running code cannot migrate. It is straightforward to extend our approach to
benchmarks using other programming languages (e.g., Java, Telescript, etc.) by implementing a different front-end targeted to the language of choice.
5.1 Experimental Results
To validate the theoretical concepts presented in this paper, an experimental mobile
code framework was developed, for which a number of examples of mobile code agents
were generated. The mobile code agents were a shopping agent [22] and an updating
agent [23].
The shopping example deals with a shopping query client, which sends several
agents out to query simulated airline services in order to find available airfares. The
agent is run on a simulated airline server, which is a distinct location on the location net
from the original query client, and may be on a remote host. When the agent receives a
reply, or fails to, it then tries to report back to the shopping query client.
The updating example specifies a central update server and several clients. The
clients contact the server, and updates are sent, as an executable agent, whenever an
update is available. This represents a way to keep the client software up to date, without
forcing the client to poll the update server.
We verified a number of security policies ranging from file access control to policies
that conditionally allowed the use of mobile code APIs based on the codeOrigin.
The examples have been tested against different security policies, some general and
some application dependent, as well as different initial location configurations. Both
contain a ”malicious” action (opening a connection to the location named ”bad” and
opening /etc/passwd, respectively), and one of the security policies for each checks
this. The results of the experiments, with a location projection (where =the agent’s
location) on the whole system, are reported in Table 5.1.
The above policies are of a few forms, best shown by example. The updating agent
opens /etc/passwd: Policy 2 (ua) disallows this action if and only if the agent came from
a remote location, whereas every other argument to fopen is allowed.
deny to public codeOrigin remote
{ permission function fopen "/etc/passwd"}
Automated Verification of Security Policies in Mobile Code
51
Table 3. Agent benchmarks with deterministic configurations: pv = policy violated, ua = updating
agent, sa = shopping agent
policy
none (ua)
1 (ua)
2 (ua)
3 (ua)
none (sa)
no effect (sa)
1 (sa)
2 local (sa)
2 remote (sa)
3 codeBase (sa)
3 (sa)
time (s) # iterations # predicates
0
1
0
10.888
2
11
34.812
14
18
0.194
1
3
0.001
1
0
0
1
0
151.644
7
17
100.234
5
15
524.866
12
36
340.011
12
22
108.564
6
16
pv? SATABS: pv?
no
no
yes
yes
yes
yes
yes
yes
no
no
no
no
yes
yes
no
no
yes
yes
yes
yes
yes
yes
Policy 3 codeBase in the shopping agent example is a variant on the policy above: it
specifies codeBase (an IPv4 origin address) instead of codeOrigin, and is tailored to the
”malicious action” found in the shopping agent.
deny to public codeBase 127.0.0.1
{ permission function connect_to_location bad}
Other policies are: ”none” (verifying the agent without any security policy), the Javalike policy described in Section 4 (Policy 1 (ua)), and the security-level example policy
also described in Section 4 (Policy 3 (ua)).
We were able to validate our technique on systems of different complexities, by
changing the number of agents instantiated. Our tools correctly detected every security policy violation with no false positives. We observed that without performing projections the verification was problematic, whereas when using location projection the
technique scaled gracefully and the complexity of the verification was highly reduced.
Table 1 reports the total verification time (in sec) for the shopping agent and the updating examples; a number of predicates and a number of the CEGAR loop iterations
indicate the complexity of the abstracted models.
6 Conclusion
In this paper, we introduced a framework for the modeling and verification of mobile
programs. The system semantics were presented in terms of Labeled Kripke Structures,
which encapsulated the essential features of mobile programs: namely, location and
unbounded thread creation. The explicit modeling of these features enabled the specification of mobile systems security policies, which are otherwise difficult to define.
The verification was based on model checking, exploiting abstraction-refinement techniques that not only allowed handling unbounded state space, but also deal effectively
with large systems.
52
C. Braghin, N. Sharygina, and K. Barone-Adesi
Acknowledgments. The authors thank Daniel Kroening for useful discussions and
support during the implementation of the prototype framework for verifying security
policies.
References
1. Clarke, E., Kroening, D., Sharygina, N., Yorav, K.: SATABS: SAT-based predicate abstraction for ANSI-C. In: Halbwachs, N., Zuck, L.D. (eds.) TACAS 2005. LNCS, vol. 3440, pp.
570–574. Springer, Heidelberg (2005)
2. Blaze, M., Feigenbaum, J., Ioannidis, J., Keromytis, A.D.: The role of trust management in
distributed systems security, pp. 185–210 (1999)
3. Weeks, S.: Understanding trust management systems. In: IEEE Symposium on Security and
Privacy, pp. 94–105 (2001)
4. Schwoon, S., Jha, S., Reps, T.W., Stubblebine, S.G.: On generalized authorization problems.
In: CSFW, pp. 202–217 (2003)
5. Ganapathy, V., Jaeger, T., Jha, S.: Automatic placement of authorization hooks in the linux
security modules framework. In: ACM Conf. on Comp.and Comm. Security., pp. 330–339
(2005)
6. Necula, G.C., Lee, P.: Research on proof-carrying code for untrusted-code security. In: IEEE
Symposium on Security and Privacy, p. 204 (1997)
7. Cardelli, L., Gordon, A.D.: Mobile Ambients. In: Nivat, M. (ed.) ETAPS 1998 and FOSSACS 1998. LNCS, vol. 1378, pp. 140–155. Springer, Heidelberg (1998)
8. Hennessy, M., Riely, J.: Resource Access Control in Systems of Mobile Agents. In: HLCL
’98. Journal of TCS, pp. 3–17. Elsevier, Amsterdam (1998)
9. De Nicola, R., Ferrari, G., Pugliese, R.: Klaim: a Kernel Language for Agents Interaction
and Mobility. IEEE Transactions on Software Engineering 24(5), 315–330 (1998)
10. Fournet, C., Gonthier, G., Lévy, J.J., Maranget, L., Rémy, D.: A Calculus of Mobile Agents.
In: Sassone, V., Montanari, U. (eds.) CONCUR 1996. LNCS, vol. 1119, pp. 406–421.
Springer, Heidelberg (1996)
11. Milner, R., Parrow, J., Walker, D.: A Calculus of Mobile Processes, I and II. Information and
Computation 100(1), 1–40, 41–77 (1992)
12. Vitek, J., Castagna, G.: Seal: A Framework for Secure Mobile Computations. In: Bal, H.E.,
Cardelli, L., Belkhouche, B. (eds.) Internet Programming Languages. LNCS, vol. 1686, pp.
47–77. Springer, Heidelberg (1999)
13. Cardelli, L.: Wide Area Computation. In: Wiedermann, J., van Emde Boas, P., Nielsen, M.
(eds.) ICALP 1999. LNCS, vol. 1644, pp. 10–24. Springer, Heidelberg (1999) (Invited Paper)
14. Cardelli, L., Gordon, A.D.: Mobile Ambients. Theoretical Computer Science 240(1), 177–
213 (2000)
15. Braghin, C., Sharygina, N.: Modeling and Verification of Mobile Systems. In: Proc. of TV
06 (2006)
16. Cook, B., Kroening, D., Sharygina, N.: Symbolic model checking for asynchronous boolean
programs. In: Valmari, A. (ed.) Model Checking Software. LNCS, vol. 3925, pp. 75–90.
Springer, Heidelberg (2006)
17. Roscoe, A.: The theory and practice of concurrency. Prentice-Hall, Englewood Cliffs (1997)
18. Ball, T., Rajamani, S.K.: SLIC: a Specification Language for Interface Checking (of C).
Technical Report MSR-TR-2001-21, Microsoft Research (2002)
19. Schneider, F.B.: Enforceable security policies. ACM Transactions on Information and System Security, vol. 3(1) (2000)
Automated Verification of Security Policies in Mobile Code
53
20. Kurshan, R.: Computer-Aided Verification of Coordinating Processes. Princeton University
Press, Princeton (1995)
21. Cook, B., Kroening, D., Sharygina, N.: Over-Approximating Boolean Programs with Unbounded Thread Creation. In: FMCAD 06: Formal Methods in System Design, Springer,
Heidelberg (2006)
22. White, J.: Telescript technology: The foundation of the electronic marketplace. Technical
report, General Magic Inc (1994)
23. Bettini, L., De Nicola, R., Loreti, M.: Software update via mobile agent based programming.
In: SAC, pp. 32–36. ACM, New York (2002)
Slicing Concurrent Real-Time System
Specifications for Verification
Ingo Brückner
Universität Oldenburg, Department Informatik, 26111 Oldenburg, Germany
ingo.brueckner@informatik.uni-oldenburg.de
Abstract. The high-level specification language CSP-OZ-DC has been
shown to be well-suited for modelling and analysing industrially relevant
concurrent real-time systems. It allows us to model each of the most
important functional aspects such as control flow, data, and real-time
requirements in adequate notations, maintaining a common semantic
foundation for subsequent verification. Slicing on the other hand has
become an established technique to complement the fight against state
space explosion during verification which inherently accompanies increasing system complexity. In this paper, we exploit the special structure of
CSP-OZ-DC specifications by extending the dependence graph—which
usually serves as a basis for slicing—with several new types of dependencies, including timing dependencies derived from the specification’s DC
part. Based on this we show how to compute a specification slice and
prove correctness of our approach.
1
Introduction
When modelling and analysing complex systems, their various behavioural aspects need to be considered such as the admitted sequence of events taking place
during operation, the associated modifications induced on the system state, or
the real-time constraints that need to be imposed on the system’s behaviour in
order to achieve a functionally correct system model. In the area of safety-critical
systems the application of formal methods with exactly defined semantics is advisable which are open to subsequent analysis and mathematical proof of certain
desired properties. However, there is no single formalism which is equally well
suited for each of the needed modelling tasks. Therefore, numerous combinations
of different such modelling notations have been proposed in order to address each
of the different system aspects with a dedicated technique [15,21,26,24].
The notation we consider in this paper is the high-level specification language CSP-OZ-DC [12], a formalism which has already been shown to be appropriate for modelling industrially relevant specifications such as parts of the
European Train Control System (ETCS, [8]). CSP-OZ-DC combines three individually well-researched formalisms: Communicating Sequential Processes (CSP,
This work was partly supported by the German Research Council (DFG) as part
of the Transregional Collaborative Research Center “Automatic Verification and
Analysis of Complex Systems” (SFB/TR 14 AVACS, www.avacs.org).
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 54–74, 2007.
c Springer-Verlag Berlin Heidelberg 2007
Slicing Concurrent Real-Time System Specifications for Verification
55
[11]) to specify system behaviour in terms of ordering of events and communication between processes; Object-Z (OZ, [20]) to define a system’s state space and
modifications associated with the occurrence of events; Duration Calculus (DC,
[9]) to define real-time properties over certain events or states. In CSP-OZ-DC,
a common semantic basis is given to these three formalisms by extending the
DC semantics such that it also covers the CSP and the OZ part. Furthermore,
CSP-OZ-DC provides a compositional translation into phase event automata, a
variant of timed automata which is appropriate for subsequent verification by
model-checking [8,19,2].
One of the main obstacles for automated verification, however, is the problem of state space explosion, i.e., the exponential blow-up in the number of
system states to be analysed. Many techniques have been proposed to tackle
this problem and the frontier of systems being amenable to model checking has
been pushed forward again and again throughout the last years by the—often
complementary—application of various state reduction methods such as partialorder reduction [18] or predicate abstraction [6].
Aiming in the same direction is the method of slicing. It was originally introduced by Weiser [25] in the context of program analysis in order to determine
those parts of a program which are relevant with respect to a specific debugging
task. Having become an established method in the area of program analysis [23],
slicing has found numerous further areas of application [28] in the past decades,
among them the area of software verification where it has successfully been applied to various targets such as Java [10] and Promela [17]. As a syntax-based
approach that operates at the source code level, slicing can exploit additional
knowledge about the system structure. It has hence been shown to be effective
in addition to complementary techniques working on the semantic level of the
models generated from the source code [7].
Slicing in the context of verification is usually done in two steps. First, a dependence graph is constructed representing control and data dependencies present
inside the source code. This first preparatory step is independent from the actual
verification property and thus only needs to be performed once for a given verification target. Second, a backwards analysis is performed on the dependence
graph with the verification property as slicing criterion, i.e., a starting point to
identify elements that directly or indirectly affect the property to be verified.
Computing the specification slice relevant to the verification property allows us
to omit the irrelevant parts in the subsequent verification step such that the
state space to be examined is already reduced before the verification actually
starts. An important requirement in this context is the correctness of the slicing approach, i.e., the verification result must remain the same, regardless of
whether verification is performed on the original target or on its slice.
In this paper we apply slicing to CSP-OZ-DC specifications as a preparatory step for subsequent verification with respect to test formulas [16], which
form a subset of DC that is amenable to model-checking. The rich syntactical
structure of CSP-OZ-DC specifications and their clear separation in different
parts addressing different system aspects makes them an ideal target for the
56
I. Brückner
syntax-oriented technique of slicing. We exploit the special structure of CSPOZ-DC specifications by introducing several new types of dependencies such as
predicate, synchronisation, and timing dependencies into the dependence graph.
In comparison to conventional dependence graphs these dependencies yield additional information about the specification allowing us to construct a more precise
dependence graph and thus a more precise slicing outcome. Building upon previous work [4,3], we show correctness of our approach not only with respect to
test formulas, but, more generally, with respect to any logic which is invariant
under stuttering, i.e., which cannot distinguish between interpretations that are
equivalent up to some stuttering steps (defined by sets of irrelevant variables
and events obtained from slicing).
The paper is structured as follows. The next section introduces CSP-OZDC by giving a small example and roughly introducing the semantics of such
specifications. In section 3 we present the dependence graph construction and
the subsequent slicing algorithm, both illustrated by the running example. A
sketch of the correctness proof of the slicing algorithm is given in section 4. The
last section concludes and briefly discusses related work.
2
CSP-OZ-DC
For illustrating our approach we use a CSP-OZ-DC specification of an air conditioner system. It can operate in two modes, either heating or cooling. Initially
the air conditioner is off. When it is switched on (workswitch), it starts to run.
While running, the air conditioner either heats or cools its environment and simultaneously allows the user to switch the mode (modeswitch), refill fuel (refill )
or switch it off again. Cooling or heating is modelled by a consumption of one
unit of fuel (consume) and an emission of hot or cold air (dtemp). For the specification we first define the mode of operating (TMode ::= heat | cool ).
The first part of the class defines its interface towards the environment by
means of several communication channels (chan). The next part specifies its
dynamic behaviour, i.e., the allowed ordering of method execution. It is defined
via a set of CSP process equations, beginning with the initially active main
process. The operators appearing here are prefixing →, sequential composition
, interleaving ||| (parallel composition with no synchronisation) and external
choice 2. The third part of a CSP-OZ-DC class describes the attributes and
methods of the class.
For every method we might have an enable schema fixing a guard for method
execution (enabling schemas equivalent to true are left out) and an effect
schema describing the effect of a method upon execution. For instance, the
enable schema of method consume tells us that the air conditioner has to be
on and a minimal amount of fuel is necessary for consume to take place. Upon
execution one unit of fuel is consumed according to its effect schema. The
method level on the other hand is always enabled, it just displays the current
level of fuel.
Slicing Concurrent Real-Time System Specifications for Verification
57
The concluding Duration Calculus (DC) part of the class defines real-time
properties of the system within a number of DC counterexample formulas, i.e.,
a subset of DC which is amenable for later verification. The only formula in the
DC part of AC specifies that whenever the air conditioner is turned on for some
time (work = 1) and an event workswitch occurs, an event off must follow
within at most one time unit (negatively defined by . . . off ∧ > 1 . . . as
part of the counterexample). The expression work = 1 denotes a non-empty
time interval throughout which predicate work = 1 holds. workswitch refers to
a point interval at which event workswitch occurs, while off refers to a nonempty time interval without any occurrence of event off . The chop operator
connects all three intervals and surrounds them with initial and concluding true
intervals of arbitrary length. These surrounding intervals enable the observation
of the counterexample to happen at any point in time.
AC
chan workswitch, consume, off
chan refill : [f ? : Z]
chan level : [f ! : Z]
chan modeswitch : [m? : TMode]
chan dtemp : [t! : TMode]
main = workswitch → On
Ctrl = modeswitch → Ctrl
On
= (Work ||| Ctrl) main
2 refill → Ctrl
Work = consume → dtemp → level → Work
2 workswitch → SKIP
2 off → SKIP
Init
¬work
mode = heat
work : B
mode : TMode; fuel : Z
effect workswitch
Δ(work )
work = ¬work
enable consume
work ∧ fuel > 5
effect consume
Δ(fuel)
fuel = fuel − 1
effect modeswitch
Δ(mode); m? : TMode
effect dtemp
t! : TMode
effect level
f! : Z
mode = m?
t! = mode
f ! = fuel
enable off
enable refill
¬work
fuel < 100
effect refill
Δ(fuel); f ? : Z
fuel = fuel + f ?
¬(true work = 1 workswitch off ∧ > 1 true)
The air conditioner’s environment is specified within a second class. Apart from
modelling the temperature, this class also models the lighting situation (via type
LMode ::= brighten | darken), possibly determined by some further components
beyond the scope of our small example.
Intuitively, it is already quite obvious that in this specification the additional
aspect of lighting is completely independent from the temperature. In section 3
we will see how to automatically obtain this observation as part of the slicing
result.
58
I. Brückner
Env
chan dtemp : [t? : TMode], dlight : [l? : LMode], tchange, lchange
main = Temp ||| Light
Temp = dtemp → tchange → Temp
Light = dlight → lchange → Light
temp, light, dt, dl : Z
Init
temp = 0 ∧ light = 0
effect dtemp
t? : TMode; Δ(dt)
effect dlight
l? : LMode; Δ(dl)
t? = cool ⇒ dt = −1
t? = heat ⇒ dt = 1
l? = darken ⇒ dl = −1
l? = brighten ⇒ dl = 1
effect tchange
Δ(temp)
effect lchange
Δ(light)
temp = temp + dt
light = light + dl
¬(true dlight lchange ∧ > 1 true)
Finally, parallel composition of the air conditioner and the environment with synchronisation on the set of common events defines our complete example system:
System = AC
Env
{dtemp}
The compositional semantics of such specifications [12] integrates the trace semantics for CSP [11], the history semantics for Object-Z [20], and the set of
interpretations for Duration Calculus formulas [9].
Definition 1. An interpretation is a function I : Time → Model mapping the
time domain Time == R+ to the set of Z models Model == NAME W with
NAME being the set of all valid identifiers and W being the world, i.e., the set
of all possible semantic values.
An interpretation of a CSP-OZ-DC class defines a set of observables, i.e., timedependent functions yielding valuations for
– all variables that are used in the CSP-OZ-DC class,
– boolean channel variables for all channels of the CSP-OZ-DC class changing
its value at each point in time when the associated event occurs,
– parameter variables for all channels equipped with parameters containing
the parameter values at the point in time when the associated event occurs.
The following definition yields an abstract view of interpretations where time is
not taken into account.
Definition 2. Let I(t ) be an interpretation, changing its valuation at points in
time 0 = t0 < t1 < t2 < . . . from Mi−1 to Mi due to events ei occurring at ti ,
i ≥ 1. Then Untime(I) = M0 , e1 , M1 , e2 , M2 , . . . is the corresponding sequence
of alternating states and events.
An interpretation is fair with respect to a set of events E ⊆ Events (or
E -fair) iff inf (Untime(I)) ∩ E = ∅ where inf (Untime(I)) = {e ∈ Events |
∃ infinitely many i ∈ N : ei = e}.
Slicing Concurrent Real-Time System Specifications for Verification
59
The semantics of a CSP-OZ-DC class is provided by the set of interpretations
that satisfy the given class, i.e., by interpretations I that satisfy all three parts
comprising the class.
CSP part: I |= CCSP iff Untime(I) corresponds to a run of the labelled transition system that is defined by the operational semantics of the CSP part [11].
Object-Z part: I |= COZ iff Untime(I) is in the history semantics of the
Object-Z part [20], i.e., its first valuation satisfies the Init schema of the
Object-Z part, all its valuations satisfy the State schema of the Object-Z
part, and all its events together with their pre- and post-states satisfy the
enable and effect schemas of the associated method.
DC part: I |= CDC iff I satisfies each of the DC formulas according to the
semantics of DC [9].
To argue about the events taking place at a given point in time, we use the
following function.
Definition 3. Let I : Time → Model be an interpretation and t a point in time.
TakesPlace(I, t ) is the set of events that take place in I at time t :
TakesPlace(I, t ) = {e ∈ Events | ∃ ε > 0 :
∀ tl ∈ [t − ε, t ), tr ∈ [t , t + ε] : I(tl )(e) = I(tr )(e)}
The next definition allows us to refer to the CSP process term that remains in
a given interpretation at a given point in time.
Definition 4. Let main be the CSP part of a CSP-OZ-DC specification C and
I an interpretation satisfying C with 0 = t0 < t1 < t2 < . . . the points in
time where I changes and ei ∈ TakesPlace(I, ti ) for i > 0. Then the residual
CSP process term associated with a point in time, denoted by CSPC (I, ti ), is
ei
e1
e2
P1 −→
. . . −→
Pi being a valid
defined as CSPC (I, ti ) = Pi with main ≡ P0 −→
transition according to the operational semantics of the CSP part of C .
For describing properties of CSP-OZ-DC classes we can now use DC test formulas [16] which can be evaluated on the set of interpretations defined by the
CSP-OZ-DC class. In this paper, we will not introduce this subset of DC, but
instead only assume that our logic is invariant under projection, i.e., that it
cannot distinguish interpretations where one is a projection of the other onto
some set of observables. A precise definition of projection is given in section 4.
One property of interest for our air conditioner specification could for instance
be whether there are always at least 5 fuel units left when the air conditioner is
on (which in fact is not true): ϕ ≡ ¬3(work ∧ fuel < 5).
The main purpose of the technique proposed in this paper is to determine
whether it is possible to check the property on a reduced specification C such
that the following holds1 : C |= ϕ iff C |= ϕ.
As we will see it is possible to omit elements of the CSP part, the Object-Z
part, and of the DC part of the example system for checking our property.
1
C |= ϕ stands for “the formula ϕ holds on all interpretations satisfying C ”.
60
3
I. Brückner
Slicing
In general, the aim of program slicing is to determine those parts of a given
program that are relevant with respect to a given slicing criterion such that only
these relevant parts need to be considered when analysing the program with
respect to the slicing criterion. This relevance analysis is usually based on the
preceding construction of a program dependence graph (PDG) that comprises all
dependence relations between elements of the program code. In preparation for
the construction of the PDG for CSP-OZ-DC specifications we first construct the
specification’s control flow graph (CFG) which represents the execution order of
the specification’s schemas according to the CSP part.
3.1
Control Flow Graph
Starting with the start .main node, representing the beginning of control flow
according to the CSP main process definition, its nodes (n ∈ NCFG ) and edges
(−→CFG ⊆ NCFG × NCFG ) are derived from the syntactical elements of the
specification’s CSP part, based on an inductive definition for each CSP operator.
Nodes either correspond
– to schemas of the Object-Z part (like enable e and effect e),
– to operators in the CSP part (like nodes interleave and uninterleave for
operator |||, nodes extchoice and unextchoice for operator 2, or nodes parS
and unparS for operator ), or
S
– to the structuring of the CSP process definitions (like start .P and term.P
for entry and exit points of CSP process P , or call .P and ret .P for call and
return points of references to process P ).
For multiple occurrences of Object-Z methods inside the CSP process definitions
unique CFG nodes are introduced, e.g. by a naming convention of the associated
enable and effect nodes where the methods’ names are extended by an ordinal
referring to their syntactical occurrence inside the CSP process definitions.
Parallel Composition of Several Classes. When computing the PDG for
the parallel composition of several classes, we start by constructing the CFG’s
for each individual class. These are then combined into one single global CFG
for the entire parallel composition in the following steps:
1. The CFG nodes start .main and term.main of class C are renamed into
start .C and term.C such that these nodes remain unique in the final CFG.
2. For each pair of classes (C1 , C2 ) that should run in parallel composition,
parallel synchronisation nodes parS and unparS are created and linked to
the respective start and term nodes of each CFG. The synchronisation set
S contains all events over which both classes need to synchronise.
3. Finally, new start .main and term.main nodes are created and connected to
each of the newly created parallel synchronisation nodes.
Slicing Concurrent Real-Time System Specifications for Verification
61
Instead of constructing one PDG for each individual class as explained in the
following section, the construction of the PDG for the parallel composition of all
involved classes is then based on this previously constructed global CFG. Apart
from this the construction for parallel composition of classes proceeds as usual.
3.2
Program Dependence Graph
The conventional program dependence graph (PDG) usually represents data and
control dependencies that are present inside a program. In our case we derive
several additional types of dependence from the rich syntactical structure of
CSP-OZ-DC specifications, among them predicate dependence representing connections between schemas and associated predicates, synchronisation dependence
representing mutual communication relations between processes, and timing dependence representing timing relations derived from DC formulas.
In addition to the nodes of the CFG, the PDG contains nodes for each predicate inside a specification schema: Npred = {px | p predicate of schema node x }.
Again, predicate nodes are replicated for each occurrence of their associated
event inside the CSP part, e.g., for each CFG schema node. Thus the set of
nodes of the PDG is NPDG = NCFG ∪ Npred . Another important difference between both graphs is the set of edges they have. An edge connects two PDG
nodes, if predicate, control, data or synchronisation dependencies exist between
these nodes according to the definitions given below.
Before continuing with the construction of the PDG we first introduce some
abbreviations. When reasoning about paths inside the CFG, we let pathCFG (n, n )
denote the set of sequences of CFG nodes that are visited when walking along CFG
edges from node n to node n . When we refer to schemas or predicates associated
with a PDG node n, we let
– out(n) denote all output variables (those decorated with a !),
– in(n) denote all input variables (those decorated with a ?),
– mod(n) denote out (n) plus all variables being modified (those appearing in
the Δ-list of the schema or in primed form in a predicate),
– ref(n) denote in(n) plus all referenced (unprimed) variables
– vars(n) = mod(n) ∪ ref(n) denote all variables.
Next, we proceed with definitions of the various kinds of dependence types that
establish the program dependence graph for CSP-OZ-DC specifications. An example of each type of dependence can be found in the dependence graph of our
example air conditioner system, depicted in figure 1.
Predicate Dependence. Each predicate that occurs in a CSP-OZ specification
is located inside some schema. The idea of predicate dependence edges
pred
−→ ⊆ (NCFG × Npred ∪ Npred × NCFG )
is to represent this relation between schemas and their associated predicates. An
example can be seen in figure 1 between node eff dtemp 10 and node
t?=cool => dt’=-1 .
62
I. Brückner
start
cd
par_AC.Env.{dtemp}
cd
start_Env
cd
par_|||_2
cd
call_Temp_18
call_Light_23
cd
cd
cd
en_dtemp_10
eff_dlight_11
cd
cd
pred
dd dd
eff_tchange_12
pred
t?=heat => dt’=1
cd
en_dlight_11
temp’=0
cd
light’=0
l?=darken => dl’ = -1
cd
start_AC
cd
cd
cd
...
cd
pred td
sd
cd
en_dtemp_5
dd dd
pred
cd
call_Light_15
pred
eff_dtemp_10
t?=cool => dt’=-1
dd en_tchange_12
pred
start_Light
cd
call_Temp_22
pred
cd
start_Temp
cd
cd
cd
l?=brighten => dl’ = 1
dd eff_lchange_9
dd
en_lchange_9
...
pred
light’ = light+dl
dd
temp’ = temp+dt
Fig. 1. Program dependence graph for the example system. Nodes inside bold bounding
rectangles belong to the same class, nodes inside dashed bounding rectangles to the
same event. Note, that most of the AC part is hidden, indicated by ”. . .” nodes.
For predicates of enable schemas, these edges lead from the enable node
to its predicates and vice versa, while for predicates of effect schemas there
are only edges in the direction from the effect schema to its predicates. The
different treatment of enable and effect schema predicates provides a way to
represent the tighter connection between enable schemas and its predicates:
enable predicates do not only depend on the event they are associated with but
also serve as the event’s guard, i.e., a mutual dependence exists, while this is not
the case for events of an effect schema.
Predicate nodes belonging to the Init schema are attached to the associated
start .main node in the way like predicate nodes belonging to an effect schema
are attached to the associated effect node. This reflects the initial restriction
of the state space according to the Init schema.
Finally, another type of predicate dependence exists for predicate nodes n ≡
px implying modifications of variables mentioned in the DC part. Their so far
unidirectional connection via the predicate dependence edge coming from their
associated effect schema node n ≡ effect x needs to be complemented by
another predicate dependence edge in the opposite direction. This treats such
predicate nodes in a similar way as predicate nodes of enable schemas, since
they play—in conjunction with the DC formula—a similar role: They can be
regarded as a guard for the associated event, since it can only take place if the
predicate complies with the restrictions given in DC .
Slicing Concurrent Real-Time System Specifications for Verification
63
Control Dependence. The further construction of the PDG starts with the
cd
introduction of control dependence edges: −→ ⊆ NCFG × NCFG
The idea behind these edges is to represent the fact that an edge’s source node
controls whether the target node will be executed. In particular, a node cannot
be control dependent on itself. We distinguish the following types of control
dependence edges:
– Control dependence due to nontrivial precondition exists between an enable
node and its effect node iff the enable schema is non-empty (i.e., not
equivalent to true).
– Control dependence due to external (resp. internal) choice or parallel composition with synchronisation exists between an extch (resp. intch) or parS
node and its immediate CFG successors.
– Control dependence due to synchronisation exists between an enable node
and its associated effect node iff both nodes are located inside a branch
attached to a parallel composition node and their associated event belongs
to the synchronisation alphabet of this parallel composition node. Note, that
even an event with an empty enable schema can be source of a control dependence edge, since synchronisation determines whether control flow continues.
– Control dependence due to timing exists between an enable node and its
associated effect node iff there exists a DC formula that mentions the given
event or variables that are modified by it. Again, even events with an empty
enable schema can be source of a control dependence edge, since the DC
part may restrict whether control flow continues.
An example of control dependence due to synchronisation can be seen in figure 1
between nodes en dtemp 10 and eff dtemp 10 .
Additionally, some further control dependence edges are introduced in order
to achieve a well-formed graph:
–
–
–
–
Call edges exist between a call node and its associated start node.
Termination edges exist between a term node and its associated ret node.
Start edges exist between a start node and its immediate CFG successor.
Return edges exist between a ret node and its immediate CFG successor.
Finally, all previously defined (direct) control dependence edges are extended to
CFG successor nodes as long as they do not bypass existing control dependence
edges. The idea of this definition is to integrate indirectly dependent nodes (that
would otherwise be isolated) into the PDG.
– Indirect control dependence edges exist between two nodes n and n iff
cd
∃ π ∈ pathCFG (n, n ) : ∀ m, m ∈ ran π : m −→ m ⇒ m = n
An example of indirect control dependence can be seen in figure 1 between nodes
start Light and en lchange 9 .
64
I. Brückner
dd
Data Dependence. The idea of data dependence edges −→ ⊆ Npred × Npred is
to represent the influence that one predicate might have on a different predicate
by modifying some variable that the second predicate references. Therefore, the
source node always represents a predicate located inside an effect schema, while
the target node may also represent a predicate located inside an enable schema.
We distinguish the following types of data dependence edges:
– Direct data dependence exists between two predicate nodes px and qy (appearing in schemas x and y) iff there is a CFG path between both associated
schema nodes without any further modification of the relevant variable, i.e.,
iff
∃ v ∈ (mod(px ) ∩ ref(qy )) , ∃ π ∈ pathCFG (x , y) :
∀ m ∈ ran π : v ∈ mod(m) ⇒ (m = x ∨ m = y)
– Interference data dependence exists between two nodes px and qy iff the
nodes of both associated schemas x and y are located in different CFG
branches attached to the same interleaving or parallel composition operator,
i.e., iff mod(px ) ∩ ref(qy ) = ∅ and ∃ m : (m ≡ interleave ∨ m ≡ parS ) with
∃ πx ∈ pathCFG (m, x ) ∧ ∃ πy ∈ pathCFG (m, y) : ran πx ∩ ran πy = {m}
– Symmetric data dependence exists between two nodes px and qy iff they are
associated with the same schema and share modified variables, i.e., iff
mod(px ) ∩ mod(qy ) = ∅ ∧ x = y
– Synchronisation data dependence exists between two predicate nodes px
and qy iff both are located inside effect schemas whose respective enable
schemas are connected by a synchronisation dependence edge as defined below and one predicate has an output that the other predicate expects as
input, i.e., iff x = effect e ∧ y = effect e ∧ out(px ) ∩ in(qy ) = ∅
An example of direct data dependence can be seen in figure 1 between nodes
t?=cool => dt’=1 and temp’=temp+dt , where the modification of variable dt
at the source node may directly reach the reference of this variable at the target
node.
Synchronisation Dependence. The idea of synchronisation dependence edges
sd
←→ ⊆ NCFG × NCFG is to represent the influence that two enable schema
nodes of the same event have on each other by being located inside two different
branches of a parallel composition operator that has the schemas’ associated
event in its synchronisation alphabet. Synchronisation dependence exists between two nodes n and n with n ≡ n ≡ enable e iff ∃ m ≡ parS with e ∈ S :
∃ π ∈ pathCFG (m, n) ∧ ∃ π ∈ pathCFG (m, n ) : ran π ∩ ran π = {m}
An example of synchronisation dependence can be seen in figure 1 between node
en dtemp 5 and node en dtemp 10 which both belong to the synchronisation
alphabet of AC and Env . If one of both events is relevant, this also applies to
the other one, since both need to agree in order to occur.
Slicing Concurrent Real-Time System Specifications for Verification
65
Timing Dependence. The representation of dependencies arising from the
DC part needs some additional preparation. The idea of timing dependence edges
td
←→ ⊆ NPDG × NPDG is to represent the mutual influence between neighbouring
elements of a DC counterexample formula.
According to [12], each formula DC occurring in the DC part of CSP-OZ-DC
specifications can be represented as a sequence of PhaseSpec data structures:
DC =
PhaseSpec0DC ; PhaseSpec1DC ; . . . ; PhaseSpecnDC
with PhaseSpeciDC comprising all information specified in the associated phases
of DC , i.e., invariants, time bounds, and forbidden or desired events. Dependencies are defined between nodes associated with the same or neighbouring
PhaseSpecs. For each formula DC we then define a timing node sequence
(TNSDC ) consisting of PDG nodes with relevance to the given formula, i.e.,
– predicate nodes implying modifications of variables mentioned in DC ,
– enable nodes of events mentioned in DC , and
– the start .main node of the given class if the initial phase of DC has a time
bound different from 0.
The nodes in each TNSDC are ordered according to the syntactical occurrence
of their associated specification elements inside DC with the exception of the
start .main node. This node does never occur directly inside a DC formula but
rather serves as a reference point for the length of the first phase which is the
reason why this node—if present—will appear as the first element of the timing
node sequence.
n ∈ ran TNSDC ⇔
n ≡ start .main ∧ timebound (PhaseSpec0DC ) > 0
∨ ∃ PhaseSpeciDC : mod (n) ∩ vars(PhaseSpeciDC ) = ∅
∨ n ≡ enable e ∧ e ∈ events(PhaseSpeciDC )
Based on these timing node sequences, bidirectional timing dependence exists
between two nodes n and n iff there is a TNSDC with two neighbouring timing
nodes n and n .
An example of timing dependence is the edge between nodes en dlight 11 and
en lchange 9 in figure 1. This timing dependence is derived from the DC formula
DC ≡ ¬(true dlight lchange ∧ > 1 true)
which appears in the DC part of the environment specification and which relates both involved events dlight and lchange. This DC counterexample formula
refers to initial and concluding intervals of arbitrary length (true), represented
by PhaseSpec0DC and PhaseSpec2DC . In between, it refers to a point interval
( dlight ) followed by a non-empty interval ( lchange ∧ > 1) which are both
represented by a single data structure, PhaseSpec1DC with information about
initial events (dlight ), forbidden events (lchange), and interval length ( > 1).
66
3.3
I. Brückner
Backward Slice
For our purpose, slicing is used to determine that part of the specification that
is directly or indirectly relevant for the property ϕ to be verified and which
therefore needs to remain in the specification. Computation of this slice starts
from the set of events Eϕ and the set of variables Vϕ that appear directly in
ϕ. Based on this slicing criterion (Eϕ , Vϕ ) we determine the set of PDG nodes
with direct influence on ϕ, i.e., the set of predicate nodes modifying variables
from Vϕ and the set of enable nodes belonging to events from Eϕ :
Nϕ = {px ∈ Npred | mod (px ) ∩ Vϕ = ∅} ∪ {enable e ∈ NCFG | e ∈ Eϕ }
Starting from this initial set of nodes we compute the backward slice by a reachability analysis of the PDG. The resulting set of backwards reachable nodes
contains all nodes that lead via an arbitrary number of predicate, control, data,
synchronisation or timing dependence edges to one of the nodes that already are
in Nϕ . In addition to all nodes from Nϕ , the backward slice contains therefore
also all PDG nodes with indirect influence on the given property, i.e., it is the
set of all relevant nodes for the specification slice:
pred
cd
dd
sd
td
N = {n ∈ NPDG | ∃ n ∈ Nϕ : n (−→ ∪ −→ ∪ −→ ∪ −→ ∪ −→)∗ n}
Thus relevant events are those associated with nodes from N that represent
enable or effect schemas
E = {e | ∃ n ∈ N : n ≡ enable e ∨ n ≡ effect e}
and relevant variables are those associated with nodes from N that represent
predicates:
V =
vars(px ).
px ∈N
3.4
Reduced Specification
Slicing concludes with the computation of the reduced specification, i.e., a version
of the full specification without all details which are not relevant for the property
that served as the slicing criterion. Verification with respect to this property can
afterwards be performed on this reduced specification while the verification result
will be the same.
To compute the CSP part of the reduced specification we need a notion of
projection of CSP process definitions onto the set of relevant events:
Definition 5. Let P be the right side of a process definition from the CSP part
of a specification and E be the set of events that appear in the specification. The
projection of P with respect to a set of events E ⊆ E is inductively defined:
Slicing Concurrent Real-Time System Specifications for Verification
67
1. SKIP |E := SKIP
and STOP |E := STOP
P |E
if e ∈ E
2. (e → P )|E :=
e → P |E else
3. (P ◦ Q )|E := P |E ◦ Q |E with ◦ ∈ {; , , , 2}
4. (P Q )|E := P |E Q |E
S
S ∩E
The projection of the complete CSP part is defined by applying the above definition to the right side of each process definition.
Given the set N , V and E it is then straightforward to construct the reduced
specification. For each class C its slice C contains
–
–
–
–
–
–
only channels from E
the projection of the original specification’s CSP part onto E ,
a state schema with variables from V only (same type as in C ),
schemas only for events in E (plus Init ),
inside these schemas only predicates associated with nodes in N , and
a DC part with only counterexample formulas that mention variables from
V and events from E . (Note that due to the construction of timing dependence edges, for any given counterexample formula either all or none of its
variables and events belong to the slice.)
When computing the slice of the complete system, i.e., the air conditioner specification in parallel composition with the environment with respect to the verification property ϕ ≡ 3(work ∧ fuel < 5), we obtain the following results:
AC: Method level has been removed, which is sensible, since communicating
the current amount of fuel (level ) does not influence ϕ. Note that methods
modeswitch, dtemp as well as variable mode have not been removed. The reason is that method dtemp belongs to the synchronisation alphabet, resulting
in a control dependence edge due to synchronisation. However, when computing a slice of the air conditioner alone (without parallel composition with
the environment), methods dtemp and modeswitch together with variable
mode can be removed, since the amount of available fuel does not depend
on the mode of operating.
Env: Methods tchange, dlight and lchange have been removed as well as variables light , temp, and dl and DC formula ¬3( dlight lchange ∧ > 1).
This result is also sensible, since the actual effect imposed on the environment’s temperature (tchange and temp) does not influence the verification
property and the modelling of the environment’s lighting behaviour (dlight ,
lchange, light and dl ) is not related to the verification property at all.
To summarise, the specification’s state space has not only been reduced with
respect to its control flow space (events level , tchange, dlight , and lchange) but
also with respect to its data state space (variables light , temp, and dl ) and its
timing requirements (the DC part of Env ).
Note, that in both cases neither the original nor the sliced specification satisfy
the given property, so the verification result will be negative in both cases. Nevertheless, this is exactly what we wanted to achieve: A specification slice must
satisfy a slicing criterion if and only if the original specification does so.
68
I. Brückner
4
Correctness
In this section we show correctness of the slicing algorithm, i.e., we show that
the property (and slicing criterion) ϕ holds on the full specification if and only
if it holds on the reduced specification. For proving this we will show that an
interpretation of the reduced specification is a projection of an interpretation of
the full specification onto some relevant subset of the variables and events, i.e.,
they only differ on variables and events that the formula does not mention.
Intuitively, when computing the projection of a given interpretation onto a
set of relevant variables and a set of events, one divides the interpretation into
blocks formed by time intervals beginning at one relevant event and ending at
the next relevant event. The corresponding block in the projection refers to the
same time interval, but does not contain any of the irrelevant events that may
appear inside the block of the original interpretation. Furthermore, throughout
both blocks the interpretation and its projection coincide in the valuation of all
relevant variables.
Definition 6. Let O be a set of observables, E = O ∩ Events the set of events
within O and I, I be two E -fair interpretations with 0 = t0 < t1 < t2 < . . . and
0 = t0 < t1 < t2 < . . . the points in time where I and I change, respectively. I
is in the projection of I with respect to O’, denoted by ProjectionO (I), iff
1. ∀ t : I|O (t ) = I |O (t )
2. ∀ i ≥ 0 : ∃ j : (ti = tj ∧ TakesPlace(I, ti ) = TakesPlace(I , tj ))
∨ (tj < ti < tj +1 ∧ TakesPlace(I, ti ) ∩ E = ∅)
Given a logic which is invariant under projections, such a projection relationship between any two interpretations then guarantees that formulas which only
mention observables from O hold for either both or none of the interpretations.
Note that projection is a particular form of stuttering.
Correctness proof. Now we start the actual correctness proof with several lemmas
showing the relationships between CSP processes and events and variables which
remain in the specification. Due to space restrictions we only present the main
ideas of the proofs.The complete proofs can be found in [1].
Our first lemma states that the projection of each residual CSP process associated with a projection interval without relevant events as defined in definition 6
can mimic the behaviour of the residual CSP process associated with the last
state of the projection block, i.e., the relevant event at the end of the block is
enabled at any point inside the block when computing the CSP projection.
Lemma 1 (Transitions of CSP process projections). Let Pj , . . . , Pj +k +1
be CSP processes, E a set of relevant events, ej +1 , . . . , ej +k −2 irrelevant events
(∈ E ), and ej +k a relevant event (∈ E ), such that
ej +1
ej +3
Pj −→ Pj +2 −→ . . .
ej +k −2
ej +k
−→ Pj +k −1 −→ Pj +k +1
Slicing Concurrent Real-Time System Specifications for Verification
69
is a valid transition sequence. Then the following holds2 :
ej +k
P −→ Pj +k +1 |E with P ∈ {Pj |E , . . . , Pj +k −1 |E }
Proof sketch: The proof builds up on another lemma considering the case of
a single CSP transition: Either this transition is labelled with a relevant event
e ∈ E or with an irrelevant event e ∈ E . In the former case it is easy to see that
the associated projection also can perform this event e, while in the latter case
some further considerations lead to the conclusion that the associated projection
will finally perform the same relevant event as the original process. Both cases
are shown by induction over the structure of the respective CSP processes. For
the proof of the present lemma we then only need to combine both cases in an
induction over the length of the projection block and come to the desired result.
Next, we bridge the gap between transition sequences that we can observe for
CSP processes and paths that are present in the associated control flow graph.
Lemma 2 (CSP transition sequences and CFG paths). Let C be a class
specification, CFG its control flow graph, I an interpretation satisfying C with
0 = t0 < t1 < t2 < . . . the points in time where I changes, ti with i > 0 one
of these points with e ∈ TakesPlace(I, ti ) and f ∈ TakesPlace(I, ti+1 ). Then the
two corresponding nodes enable e and enable f of CFG are related in either
one of the following ways:
1. There exists a path in CFG which leads from enable e to enable f :
pathCFG (enable e, enable f ) = ∅
2. There exists a CFG node interleave i or parSi with S ∩ {e, f } = ∅ which has
enable e and enable f as successors in different branches:
∃ n ∈ CFG : n ≡ interleave i ∨ (n ≡ parSi ∧ S ∩ {e, f } = ∅) :
∃ πe ∈ pathCFG (n, enable e) ∧ ∃ πf ∈ pathCFG (n, enable f ) :
πe ∩ πf = {n}
Proof sketch: The proof consists of two layers of induction over the structure
of the residual CSP process terms CSPC (I, ti ) and CSPC (I, ti+1 ) such that each
possible combination of CSP constructs is shown to be covered by one of the
two cases mentioned in the lemma.
The following lemma states that the set of irrelevant events appearing inside a
projection block does not have any influence on the relevant variables associated
with the states inside the block.
Lemma 3 (No influence of irrelevant events on relevant variables). Let
C be a class specification, I an interpretation satisfying C with 0 = t0 < t1 <
t2 < . . . the points in time where I changes, associated with ei ∈ TakesPlace(I, ti )
for i > 0. Let furthermore E be the set of relevant events computed by the slicing
2
Note, that Pj |E = . . . = Pj +k−1 |E does not necessarily hold.
70
I. Brückner
algorithm with respect to some formula ϕ (with an associated set of variables Vϕ ),
ej +1 , . . . , ej +k −1 ∈ E , and ej , ej +k ∈ E . Then the following holds:
I(tj )|V = . . . = I(tj +k −1 )|V
with V = Vϕ ∪
ref (e)
e∈{ei ∈E |i≥j }
Proof sketch: We show this by contradiction: Supposed, the equality does not
hold. This implies the existence of a data dependence between an event inside
the block and the relevant event. In consequence, this leads to the event inside
the block being a member of the set of relevant events.
Our last lemma states that DC formulas which the slicing algorithm identified to
be irrelevant with respect to a property to be verified do not impose restrictions
on any relevant event.
Lemma 4 (No influence of irrelevant DC formulas on relevant events).
Let C be a class specification, E the set of relevant events obtained from slicing
C with respect to some slicing criterion ϕ, and DC a counterexample formula
from the DC part of C which is irrelevant with respect to ϕ. Let
EDC = events(DC ) ∪ {e ∈ Events | mod (e) ∩ vars(DC ) = ∅}
be the set of events that DC refers to either directly or indirectly by referring to
some variable that is modified by the respective event. Then the following holds:
1. There exists no CFG path connecting events from EDC with events from E .
2. Timings of events from EDC are not affected by timings of events from E .
Proof sketch: We show both claims by contradiction: Supposed, a path as in
(1) exists, then this leads to the existence of a control dependence and thus to
DC being relevant. Supposed, an irrelevant event as in (2) is forced to occur
before a certain relevant event, then this leads to a connection between both
nodes either via control flow edges, via a common DC formula, or via two DC
formulas with a common reference point and thus in all cases to e and hence
DC being relevant.
Now we come to our main theorem that states the existence of a projection
relationship between any two interpretations associated with the original and to
the sliced specification.
Theorem 1. Let C be a class specification and C the class obtained when slicing C with respect to a formula ϕ, associated with sets of events Eϕ and variables
Vϕ . Let E and V be the set of events and variables, respectively, which the slicing algorithm delivers as those of interest (in particular Eϕ ⊆ E and Vϕ ⊆ V ).
Then for any E -fair interpretation I satisfying C there is a corresponding E fair interpretation I satisfying C such that
I ∈ ProjectionV ∪E (I).
Slicing Concurrent Real-Time System Specifications for Verification
71
Proof sketch: We need to consider two directions: (1) We have to show that
for any interpretation of C we can construct a corresponding interpretation
of C and (2) vice versa. For both directions we define a set of variables V i
that contains all variables mentioned in the slicing criterion and for each ei ∈
TakesPlace(I, ti )∩E all variables referenced by ei or subsequent relevant events:
V i = Vϕ ∪
ref (e)
e∈{ej ∈E |j ≥i}
1. Let I be an interpretation satisfying C . We inductively construct an interpretation I which coincides with I on relevant relevant events from E
and relevant variables from V i , i.e., intervals of I containing only irrelevant events correspond to intervals of I containing no events but the same
valuations of relevant variables.
We have to show that I satisfies C . To this end we use induction over
the length of I where we apply lemma 3 and lemma 1 when showing that
we can remove some intermediate sequences from the original interpretation
such that all schemas, process definitions and timing constraints from the
reduced specification are satisfied.
2. Let I be an interpretation satisfying C with 0 = t0 < t1 < t2 < . . . the
points in time where I changes and TakesPlace(I , ti ) ∩ E = ∅.
We inductively construct an interpretation I with
0 = t0 < t01 < t02 < . . . < t0n0 < t1 < t11 < t12 < . . . < t1n1 < t2 < t21 < . . .
the points in time where I changes, such that the same relevant events
appear in I and I at points in time ti for i > 0, and additional (irrelevant)
events appear in I at points in time tiji for i ≥ 0 and 1 ≤ ji ≤ ni .
In the induction we apply lemma 3 to show that we can safely insert
the necessary additional steps in I such that the associated schemas of the
full specification are satisfied. Furthermore, we apply lemma 2 to show that
these additional steps are possible according to the process definitions from
the full specification. Finally, we use lemma 4 to show that the additional
DC formulas are satisfied by choosing appropriate points in time for the
additional events in I such that I is indeed an interpretation of C .
5
Conclusion
We presented a slicing approach with the intention to use it as a preprocessing step in the verification of high-level specifications of concurrent real-time
systems with respect to real-time properties. The overall aim of introducing slicing into the verification workflow is to complement other strategies to fight the
problem of state space explosion. Our slicing algorithm is custom-tailored to the
integrated specification language CSP-OZ-DC in order to exploit its particular
features in the construction of an adequate dependence graph. Once this graph
is constructed, it allows us to compute slices of the original specification with
72
I. Brückner
respect to a wide set of verification properties as we demonstrated for a small
example specification. Subsequent verification runs can be performed on the slice
instead of the full specification without changing the verification result.
Currently, we are integrating the proposed slicing technique as a plugin into
the modelling environment Syspect [22] which was already used to automatically generate the dependence graph in figure 1. This tool gives (1) a precise
CSP-OZ-DC semantics to a subset of UML notations such as state charts, class
diagrams, and component diagrams, and (2) has a plugin-based connection to
the verification tool chain for CSP-OZ-DC proposed in [13] and evaluated in [8],
currently based on the abstraction-refinement model checker ARMC [19] and
the deductive model checker SLAB [2].
Related Work. Program slicing as originally defined by Weiser in the field of
program analysis and debugging [25] has been enhanced with respect to many
different aspects, having found numerous additional fields of application at the
same (for overview papers see [23,28]) and a similarly wide spectrum of targets,
including Z-based specifications [5,27] as in our case.
Formal verification is an application area of slicing that has recently seen
increasing interest, since slicing seems to be one technique that can help to tackle
the problem of state space explosion during model checking. Empirical results [7]
have shown that slicing can indeed effectively complement other strategies such
as predicate abstraction [6] and partial order reduction [18] that are mostly
applied on a different stage than slicing, namely either during or after model
generation has already been performed. In contrast to that, slicing can be applied
beforehand as a relatively cheap syntax-based method to reduce the input to
model generation. Thus, the benefit of slicing can be seen in two directions:
First, it enables an optimisation by accelerating the process of model generation,
which is for larger systems already a substantial part of the complete verification
process. Second, it yields smaller models to which subsequently the mentioned
orthogonal strategies for state space reduction can still be applied.
Existing approaches to static slicing of formal specifications, however, do not
consider verification, i.e., slicing is not carried out with respect to verification
properties. Work on slicing used for reducing programs before verification has
for instance been done for Java [7] and Promela [17]. Furthermore, we are not
aware of any existing approaches that consider slicing of high-level specifications
of real-time systems, while on the semantic level of timed automata slicing has
been applied in [14].
References
1. Brückner, I.: Slicing CSP-OZ-DC Specifications for Verification. Technical report,
Univ. Oldenburg (2007) http://csd.informatik.uni-oldenburg.de/∼ingo/
ifm07.pdf
2. Brückner, I., Dräger, K., Finkbeiner, B., Wehrheim, H.: Slicing Abstractions. In:
FSEN’07. LNCS, Springer, Heidelberg (to appear, 2007)
Slicing Concurrent Real-Time System Specifications for Verification
73
3. Brückner, I., Wehrheim, H.: Slicing an Integrated Formal Method for Verification.
In: Lau, K.-K., Banach, R. (eds.) ICFEM 2005. LNCS, vol. 3785, pp. 360–374.
Springer, Heidelberg (2005)
4. Brückner, I., Wehrheim, H.: Slicing Object-Z Specifications for Verification. In: Treharne, H., King, S., Henson, M.C., Schneider, S. (eds.) ZB 2005. LNCS, vol. 3455,
pp. 414–433. Springer, Heidelberg (2005)
5. Chang, D., Richardson, D.: Static and Dynamic Specification Slicing. In: SIGSOFT
ISSTA, pp. 138–153. ACM Press, New York (1994)
6. Clarke, E.M., Grumberg, O., Jha, S., Lu, Y., Veith, H.: Counterexample-Guided
Abstraction Refinement. In: CAV’00, pp. 154–169 (2000)
7. Dwyer, M.B., Hatcliff, J., Hoosier, M., Ranganath, V., Wallentine, R., Wallentine, T.: Evaluating the Effectiveness of Slicing for Model Reduction of Concurrent
Object-Oriented Programs. In: Hermanns, H., Palsberg, J. (eds.) TACAS 2006 and
ETAPS 2006. LNCS, vol. 3920, Springer, Heidelberg (2006)
8. Faber, J., Meyer, R.: Model Checking Data-Dependent Real-Time Properties of
the European Train Control System. In: FMCAD’06, pp. 76–77. IEEE Computer
Society Press, Los Alamitos (2006)
9. Hansen, M.R., Chaochen, Z.: Duration Calculus: Logical Foundations. Formal Aspects of Computing 9, 283–330 (1997)
10. Hatcliff, J., Dwyer, M., Zheng, H.: Slicing Software for Model Construction. Higherorder and Symbolic Computation 13(4), 315–353 (2000)
11. Hoare, C.A.R.: Communicating Sequential Processes. Prentice-Hall, Englewood
Cliffs (1985)
12. Hoenicke, J.: Combination of Processes, Data, and Time. PhD thesis, Univ. of
Oldenburg (2006)
13. Hoenicke, J., Maier, P.: Model-checking specifications integrating processes, data
and time. In: Fitzgerald, J.A., Hayes, I.J., Tarlecki, A. (eds.) FM 2005. LNCS,
vol. 3582, pp. 465–480. Springer, Heidelberg (2005)
14. Janowska, A., Janowski, P.: Slicing Timed Systems. Fundamenta Informaticae 60(1–4), 187–210 (2004)
15. Mahony, B., Dong, J.S.: Timed communicating Object-Z. IEEE Transactions on
Software Engineering 26(2), 150–177 (2000)
16. Meyer, R., Faber, J., Rybalchenko, A.: Model Checking Duration Calculus: A Practical Approach. In: Barkaoui, K., Cavalcanti, A., Cerone, A. (eds.) ICTAC 2006.
LNCS, vol. 4281, pp. 332–346. Springer, Heidelberg (2006)
17. Millett, L., Teitelbaum, T.: Issues in Slicing Promela and its Applications to Model
Checking. STTT 2(4), 343–349 (2000)
18. Peled, D.A.: Ten years of partial order reduction. In: Vardi, M.Y. (ed.) CAV 1998.
LNCS, vol. 1427, pp. 17–28. Springer, Heidelberg (1998)
19. Podelski, A., Rybalchenko, A.: ARMC: the logical choice for software model checking with abstraction refinement. In: Hanus, M. (ed.) PADL 2007. LNCS, vol. 4354,
Springer, Heidelberg (2006)
20. Smith, G.: The Object-Z Specification Language. Kluwer Academic Publishers,
Dordrecht (2000)
21. Smith, G., Hayes, I.J.: An introduction to Real-Time Object-Z. Formal Aspects of
Computing 13(2), 128–141 (2002)
22. Syspect. Endbericht der Projektgruppe Syspect. Technical report, Univ. of Oldenburg (2006) http://syspect.informatik.uni-oldenburg.de/
23. Tip, F.: A Survey of Program Slicing Techniques. Journal of Programming Languages 3(3), 121–189 (1995)
74
I. Brückner
24. Treharne, H., Schneider, S.A.: Communicating B Machines. In: Bert, D., Bowen,
J.P., Henson, M.C., Robinson, K. (eds.) B 2002 and ZB 2002. LNCS, vol. 2272,
pp. 416–435. Springer, Heidelberg (2002)
25. Weiser, M.: Programmers use slices when debugging. Communications of the
ACM 25(7), 446–452 (1982)
26. Woodcock, J.C.P., Cavalcanti, A.L.C.: The Semantics of Circus. In: Bert, D.,
Bowen, J.P., Henson, M.C., Robinson, K. (eds.) B 2002 and ZB 2002. LNCS,
vol. 2272, pp. 184–203. Springer, Heidelberg (2002)
27. Wu, F., Yi, T.: Slicing Z Specifications. SIGPLAN 39(8), 39–48 (2004)
28. Xu, B., Qian, J., Zhang, X., Wu, Z., Chen, L.: A brief survey of program slicing.
SIGSOFT SEN 30(2), 1–36 (2005)
Slotted-Circus
∗
A UTP-Family of Reactive Theories
Andrew Butterfield1 , Adnan Sherif2 , and Jim Woodcock3
1
2
Trinity College Dublin
Andrew.Butterfield@cs.tcd.ie
Universidade Federal de Pernambuco
ams@cin.ufpe.br
3
University of York
Jim.Woodcock@cs.york.ac.uk
Abstract. We present a generic framework of UTP theories for describing systems whose behaviour is characterised by regular time-slots, compatible with the general structure of the Circus language [WC01a]. This
“slotted-Circus” framework is parameterised by the particular way in
which event histories are observable within a time-slot, and specifies
what laws a desired parameterisation must obey in order for a satisfactory theory to emerge.
Two key results of this work are: the need to be very careful in formulating the healthiness conditions, particularly R2; and the demonstration
that synchronous theories like SCSP [Bar93] do not fit well with the way
reactive systems are currently formulated in UTP and Circus.
1
Introduction
1.1
Circus and Slotted-Circus
The formal notation Circus [WC01a] is a unification of Z and CSP, and has been
given a UTP semantics [WC02]. A Circus text describes behaviour as a collection
of actions, which are a combination of processes with mutable state. However,
apart from event sequencing, there is no notion of time in Circus.
A timed version of Circus (Circus Time Action or CTA) has been explored
[SH02, She06] that introduces the notion of discrete time-slots in which sequences
of events occur. In CTA, we have a two-level notion of history: the top-level views
history as a sequence of time-slots; whilst the bottom-level records a history of
events within a given slot. The key notion in this paper is that we can instantiate
the bottom-level history in a variety of ways: as simple traces, or multisets of
events, or as the more complex “micro-slot” structures used in the operational
semantics of Handel-C [BW05].
This paper describes a generalisation of CTA called “slotted-Circus”, which
is a collection of theories parameterised by different ways to instantiate the
∗
Research reported in this paper was partially supported by QinetiQ.
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 75–97, 2007.
c Springer-Verlag Berlin Heidelberg 2007
76
A. Butterfield, A. Sherif, and J. Woodcock
P; Q =
∃ obs0 • P [obs0 /obs ] ∧ Q[obs0 /obs]
P c Q =
c∧P ∨¬c∧Q
P Q =
P ∨Q
i∈I Pi
=
∃ i : I • Pi
S P =
[P ⇒ S ]
Fig. 1. Basic UTP Operators
bottom-level event history within a time-slot. The motivation behind this work
is the desire to re-cast existing semantics for Handel-C into the UTP framework
so that Circus can be used as a specification language.
The Handel-C denotational [BW02] and operational semantics use this timeslot model, but with varying degrees of complexity in the slot structure, depending on which language constructs we wish to support. The slotted-Circus
framework reported here is intended to be a foundation for formulating the
common parts of these models, making it easier to explore the key differences.
1.2
UTP: General Principles
Theories in UTP are expressed as predicates over a pre-defined collection of
free observation variables, referred to as the alphabet of the theory. The predicates are generally used to describe a relation between a before-state and an
after-state, the latter typically characterised by dashed versions of the observation variables. A predicate whose free variables are all undashed is called a
(pre-)condition. A given theory is characterised by its alphabet, and a series
of healthiness conditions that constrain the valid assertions that predicates may
make. In almost all cases there are some basic operators common to every theory
(Figure 1). Sequential composition (P ; Q ) corresponds to relational composition, i.e., the existence of an intermediate state (obs0 ), such that P relates obs
to obs0 , whilst Q relates obs0 to obs . The conditional P c Q is generally used
when c is a condition and asserts that P holds if c is true, otherwise it asserts
Q . Nondeterminism between two predicates P Q is simply logical disjunction,
which extends to an existential quantifier for a nondeterministic choice over an
indexed set (i Pi ). We capture the notion of refinement as logical entailment
between the implementation and specification predicates, quantified over all free
variables.
We note that UTP follows the key principle that “programs are predicates”
[Hoa85b], and so does not distinguish between the syntax of some language and
its semantics as alphabetised predicates. In other words, we view the language
constructs as being “syntactic sugar” for their predicate semantics, rather than
defining some form of semantic function mapping some abstract syntax type to
some domain capturing its meaning.
Slotted-Circus
77
Action ::= Skip | Stop | Chaos
| Name+ := Expr+ | Comm → Action | Action 2 Action
| Action |[ VS | CS | VS ]| Action | Action \CS
| μ Name • F (Name) | Wait t | . . .
Comm ::= Name.Expr | Name!Expr | Name?Name
Expr ::= expression
t ::= positive integer valued expression
Name ::= channel or variable names
CS ::= channel name sets
VS ::= variable sets
Fig. 2. Slotted-Circus Syntax
1.3
Structure and Focus
The main technical emphasis of this paper is on the construction of the generic
framework and the required healthiness conditions, with the semantics of the
language constructs and a case study provided to give a feel for its utility. We
first present the syntax §2, generic framework §3, healthiness conditions §4, and
semantics §5. We then discuss instantiation §6 and describe a case-study §7,
before mentioning related §8 and future §9 work, and concluding §10. Two appendices give supporting material.
2
Syntax
The syntax of Slotted-Circus is similar to that of Circus, and a subset is shown
in Figure 2. The notation X + denotes a sequence of one of more X . We assume
an appropriate syntax for describing expressions and their types, subject only
to the proviso that booleans and non-negative integers are included.
The basic actions Skip, Stop, Chaos are similar to the corresponding CSP behaviours [Hoa85a, Sch00], respectively denoting actions that do nothing and terminate, do nothing and wait forever, or act unpredictably forever. We also introduce (multiple) assignment (:=) and event (communication) prefixes Comm →
Action as basic actions. The communication prefixes range over communicating
a value on a channel (Name.Expr), sending a value on a channel (Name!Expr), or
receiving a value on a channel (Name?Name). The composite action operator 2
denotes external choice, whilst parallel composition of actions (|[VS | CS | VS]|) is
parameterised by three sets, the first and third denoting the variables the corresponding action may modify, while the middle one specifies the synchronisation
channels. We require that parallel processes modify disjoint parts of the state.
We also have hiding (\ CS) and recursively defined actions (μ Name • F (Name)).
The key construct related to time-slots, and hence not part of Circus, is Wait t
which denotes an action that simply waits for t time-slots to elapse, and then
terminates.
78
3
A. Butterfield, A. Sherif, and J. Woodcock
Generic Slot-Theory
Both the semantics of Handel-C [BW05] and the timed extension to Circus called
“Circus Timed Actions (CTA)” [SH02, She06] have in common the fact that the
models involve a sequence of “slots” that capture the behaviour of the system
between successive clock ticks. These slots contain information about the events
that occurred during that time slot (“history”) as well as the events being refused
at that point. A key feature of all these semantic models is that the progress
of events during a time-slot is observable, rather than just the overall outcome
for an entire slot. While the initial goal was to develop a synchronous variant
of Circus, it rapidly became clear that it was worth investing time in a generic
slot-based theory, which could then be specialised to cover synchronicity, CTA,
and the various slot-models that could be used to characterise Handel-C and
similar synchronous hardware languages at various levels of detail.
We begin our description of the generic slotted theory by noting that it is
parametric in three inter-related aspects:
– A given set of events, E .
– A type constructor H that builds a slot’s history-type from an event type.
– A collection of basic functions that work with H E , which must satisfy
certain laws.
Given H, we then define the notion of a slot (S) as being a pair: a history and
a set of events denoting a refusal:
SE=
(H E ) × (P E )
(1)
In a sense a slot is similar to the notion of a failure in CSP [Ros97], except that
it covers only the events within a single time-slot (i.e., between two successive
clock ticks). Given a notion of time-slot, we then introduce the top-level notion
of event history as being a non-empty sequence of slots. The presence of clockticks in the history is denoted by the adjacency of two slots, so a slot-sequence
of length n + 1 describes a situation in which the clock has ticked n times.
We can now describe the observational variables of our generic UTP theory:
ok : B —True if the process is stable, i.e., not diverging.
wait : B —True if the process is waiting, i.e., not terminated.
state : Var →
Value —An environment giving the current values of slotted-Circus
variables
slots : (S E )+ : —A non-empty sequence of slots recording the behaviour of the
system.
The variables ok , wait play the same role as the in the reactive systems theory
in [HH98, Chp. 8], while state follows the trend in [SH02] of grouping all the
program variables under one observational variable, to simplify the presentation
of the theory.
In order to give the generic semantics of the language, we need to provide six
functions and two relations over H E , listed in Figure 3. Function Acc returns the
Slotted-Circus
79
AccH : H E → P E
EqvTrcH : E ∗ ↔ H E
HNullH : H E
H
:HE ↔HE
HaddH : H E × H E → H E
HsubH : H E × H E → H E
HHideH : P E → H E → H E
HSyncH : P E → H E × H E → P(H E )
Fig. 3. Generic Functions over H E
set of events mentioned (Accepted) in its history argument. The relation EqvTrc
relates a history to all event sequences (traces) compatible with it. HNull is a
constant denoting an empty history. Infix symbol captures the notion of one
history being a prefix, of pre-history of another, and is required to be a preorder. The functions Hsub and Hadd capture the notions of history subtraction
and addition (extension). In particular we note that Hsub is partial and is only
defined when the second argument is a pre-history of the first. Function HHide
acts to remove a set of events from a history. Finally the HSync function generates all the possible histories that can result from the synchronisation of two
histories over a given event set.
In order to produce a coherent theory, the functions have to obey a number
of laws, listed in Appendix A. Most of the properties concerned capture reasonable behaviours that one would expect of histories, e.g., that history addition
is associative, or that the null history acts as a unit. Most of these laws where
determined by the needs of the general theory, in particular the definitions and
proofs needed to establish the required healthiness conditions.
As an example, a variation of the CTA theory of [She06] can be captured by
defining an event history (HCTA E ) to be a sequence of events, and instantiating
most of the functions and relations as the corresponding ones for sequences.
E∗
HCTA E =
3.1
(2)
Derived Types and Operators
Given the definition of H, and the associated functions and relations, we need
to use these to define the corresponding aspects for slots, and the slot-sequences
that comprise our observational variables (see Figure 4). EqvTrace, defined in
terms of EqvTrc, relates traces to slot-sequences with which they are compatible.
The functions Refs and EqvRef extract refusals from slot-sequences, with the
former returning a refusal-set list, whilst the latter singles out the last refusal
set. A slot-sequence s is a slot-prefix of a slot-sequence t , written s t if the
front of s is a prefix of t and the history component of the last slot of s is
a history-prefix of the corresponding component of the first slot of t − s. The
80
A. Butterfield, A. Sherif, and J. Woodcock
EqvTrace : E ∗ ↔ (S E )∗
Refs : (S E )+ → (P E )+
EqvRef : (S E )+ → P E
: (S E )+ ↔ (S E )+
≈:SE ↔SE
+
+
∼
= : (S E ) ↔ (S E )
SaddS : S E × S E → S E
SsubS : S E × S E → S E
: ((S E )+ × (S E )+ ) → (S E )+
: ((S E )+ × (S E )+ ) → (S E )+
Fig. 4. Derived Functions and Relations
relation is a pre-order. Slot equivalence ≈ and Slot-sequence equivalence (∼
=)
are the symmetric closure of and respectively, giving equivalence relations.
An important point to note here is that if s ∼
= t , then s and t are identical,
except for the refusal values in the last slot in each.
The notions of adding (extending) and subtracting histories are lifted to the
slot level, but here an issue immediately arises as to how the refusal components
are handled. If we consider history addition, then Hadd (h1 , h2 ) is intended to
capture the history resulting from the events of history h1 , followed by those
of h2 . We now note that in most CSP-like theories, a failure consisting of a
trace/history of events (h) coupled with a refusal set (r ), is to be interpreted
as stating that the process under consideration is refusing the events in r , after
having performed the events in h. Given this interpretation, we are then required
to specify slot addition and subtraction as follows:
(Hadd (h1 , h2 ), r2 )
Sadd ((h1 , ), (h2 , r2 )) =
Ssub((h1 , r1 ), (h2 , )) =
(Hsub(h1 , h2 ), r1 )
For history subtraction, the value Hsub(h1 , h2 ) is defined only if h2 h1 , and
denotes those events in h1 that occurred after those in h2 . The significance of this
interpretation is important, as will be made clear when we consider an attempt
to model Synchronous CSP (SCSP) [Bar93] later in this paper. A consequence
of this interpretation is that one of the healthiness conditions discussed in the
next section (R2) becomes more complex.
Given slot addition and subtraction, these can then be lifted to act on slotsequences, as and respectively. The latter is only defined if its second
argument is a -prefix of its first. Slot-sequence addition concatenates its two
arguments, merging the last slot of the first with the first slot of the second:
front (slots1 ) Sadd (last(slots1 ), head (slots2 )) tail (slots2 ) (3)
slots1 slots2 =
Slotted-Circus
81
Slot-sequence subtraction s t is defined when t s, in which case both s
and t can be written as
s = pfx slots sfx
t = pfx slott
In this case, the subtraction becomes:
s t =
Ssub(slots , slott ) sfx
4
(4)
Healthiness Conditions
Given that we are defining semantics as predicates over before- and after- observations, we need to ensure that what we write is feasible, in that we do not
describe behaviour that is computationally or physically infeasible (e.g., undoing
past events). In UTP, the approach to handling feasibility is to define a number
of so-called healthiness conditions that characterise the sort of predicates which
make sense in the intended interpretation of the theory.
While the notion of healthiness-conditions is well-understood in the UTP
community, we are still going to take time for the presentation that follows, as
we highlight a prevalent use of overloading that can have unexpected effects in
inexperienced hands.
Given a healthiness condition called H we introduce two functions, mkH and
isH. In order to denote a healthiness condition, we require that the former is
an idempotent monotonic predicate transformer, w.rt. to the standard ordering
used in UTP, namely that S P iff [P ⇒ S ]. The role of mkH is to convert
an un-healthy predicate into a healthy one, in some fashion, but also to leave
already healthy predicates unchanged (hence the need for idempotency, so that
a healthy predicate is a fixed-point of mkH).
mkH : Predicate → Predicate
mkH = mkH ◦ mkH
Function isH asserts a healthiness condition, i.e., is a higher order predicate
that tests a given predicate to see if it is healthy:
isH : Predicate → B
isH(P ) =
P ≡ mkH(P )
We can summarise by saying that a healthy predicate is a fixed-point of the
corresponding healthiness predicate transformer. In most material on UTP, it is
conventional to overload the notation H to refer to both mkH and isH, with
the use usually being clear from context. In either case it is also conventional
to refer in general to H as a healthiness condition, even in a context were it
would actually be a predicate transformer. We shall adopt this convention in the
sequel.
82
A. Butterfield, A. Sherif, and J. Woodcock
However a hazard can arise when alternative formulations of H are available;
note that different functions may have the same set of fixed-points. We illustrate
this later when discussing R2.
The healthiness conditions we introduce here for slotted-Circus parallel some
of those in [HH98, Chp. 8] for general reactive systems, namely R1, R2, R3 and
CSP1.
4.1
Reactive Healthiness
We shall discuss R1 and R3 first, as these are fairly straightforward, while R2
deserves some discussion, as its adaption for slotted-Circus was decidedly nontrivial.
R1 simply states that a slotted-Circus process cannot undo the past, or in
other words, that the slots observation must be an extension of slots, whilst R3
deals with the situation when a process has not actually started to run, because
a prior process has yet to terminate, characterised by wait = True. In this case
the action of a yet-to-be started process should simply be to do nothing, an
action we call “reactive-skip” (II). Reactive skip has two behavioural modes: if
started in an unstable state (i.e the prior computation is diverging), then all it
guarantees is that the slots may get extended somehow; otherwise it stays stable,
and leaves all other observations unchanged.
R1(P ) =
P ∧ slots slots
R3(P ) =
II wait P
II =
¬ ok ∧ slots slots
∨
ok ∧ wait = wait ∧ state = state ∧ slots = slots
The purpose of the slots observation variable in slotted-Circus, and its trace
analogue (tr ) in UTP reactive-process theory, is to facilitate the definition of
operators such as sequential composition. What is not permitted however, is for
a process to be able to base its actions on the history of past events as recorded
by this variable—any such “memory” of the past must be captured by the state
observation. Healthiness condition R2 is concerned with ensuring that a process
can only specify how the history is extended, without reference to what has
already happened. In [HH98, Chp. 8] this is captured by stating that P is R2healthy if it is invariant under an arbitrary shift in the prehistory, or in other
words, a non-deterministic choice over all possible values that tr might take:
R2–UTP(P ) =
P [s, s (tr − tr )/tr , tr ]
s
≡ ∃ s • P [s, s (tr − tr )/tr , tr ]
It would seem reasonable to expect the slotted-Circus version to simply replace
tr by slots and use the slot-sequence analogues of sequence concatenation and
subtraction. This would result in the following definition (here the a indicates
“almost”):
R2a(P ) =
∃ ss • P [ss, ss (slots slots)/slots, slots ]
(5)
Slotted-Circus
83
Whilst this looks plausible, there is in fact a problem with it, which only becomes
apparent when we attempt to apply the definition later on in the semantics and
then prove certain key desirable properties. Consider the predicate slots = slots
which asserts that no events occur. This predicate should be R2-healthy, as it
describes a process that chooses to do nothing, regardless of the value of slots.
However calculation shows that
R2a(slots = slots) ≡ slots ∼
= slots .
The equality gets weakened to the slot-sequence equivalence introduced earlier.
An immediate consequence of this is that II is not healthy by this definition, as
calculation shows that the slot-equality is weakened to slot-equivalence (underlined below).
R2a(II) ≡ ¬ ok ∧ slots slots ∨ ok ∧ wait = wait ∧ state = state ∧ slots ∼
= slots
Original work explored keeping R2a as is, and redefining II to be that version
shown above. However this then weakened a number of key properties of II,
most notably to do with its role as an identity for sequential composition under
appropriate circumstances.
The underlying problem with R2a has to do with the fact that in slottedCircus, unlike UTP, we have refusals interleaved with events in slots, and slotsequence operators that treat refusals, particularly the last, in a non-uniform
way. The problem is that R2a weakens the predicate a little too much, so we
need to find a way to strengthen its result appropriately. The appropriate way
to handle this issue has turned out to be to modify the definition of R2 to require that we only quantify over ss values that happen to agree with slots on
the very last refusal. This has no impact on predicates like and ∼
= which are
not concerned with the last refusals, but provides just enough extra information to allow slot-sequence equality be considered as R2-healthy. The slightly
strengthened version now reads:
R2(P ) =
∃ ss • P [ss, ss (slots slots)/slots, slots ] ∧ Ref (last(slots)) = Ref (last(ss))
The proof that R2 is idempotent is somewhat more involved than those for
R1 and R3. Calculations show that predicates slots slots , slots ∼
= slots,
slots = slots (se Appendix B) and II, are all R2-healthy. It also distributes
through disjunction, which is very important.
It is worth pointing out that two versions of R2 are presented in [HH98]. The
second, which we shall call R2’ is shown in an appendix:
R2’(P ) =
P [ , tr − tr /tr , tr ]
Both R2 and R2’ have the same set of fixed points, so can be used interchangeably as a test for healthiness. However, if used to make a predicate healthy, then
R2 is more forgiving than R2’:
R2(tr = a ∧ tr = a, b ) ≡ (tr − tr ) = b
R2’(tr = a ∧ tr = a, b ) ≡ false
This is an example of where overloading the notation H to stand for both mkH
and isH can be misleading. We note that the version of R2 used in [She06] is
the CTA equivalent of R2’.
84
A. Butterfield, A. Sherif, and J. Woodcock
Reactive Healthiness. A reactive slotted-Circus process is one that satisfies
all three of the above healthiness conditions, so we define an overall condition
R as their composition:
R=
R3 ◦ R2 ◦ R1
(6)
In fact all three conditions commute with each other, so we re-order the above
composition to suit.
4.2
CSP Healthiness
In addition to the reactive-healthiness just introduced, shared by a range of
concurrent theories including ACP and CSP, there are a number of aspects of
healthiness specific to CSP-like theories. In [HH98, Chp. 8] there are five of these
presented, but for our purposes it suffices to consider only the first one.
A process is CSP1 healthy if all it asserts, when started in an unstable state
(due to some serious earlier failure), is that the event history may be extended:
CSP1(P ) =
P ∨ ¬ ok ∧ slots slots
5
(7)
Slotted Semantics
We are now in a position to give the semantics of the slotted-Circus language
which is presented for completeness in Figures 5 & 6.
We shall not give a detailed commentary to all the definitions shown but
instead will focus on some key points.
The STOP action refuses all events, but does allow the clock to keep ticking. Assignment and channel-communication take less than a clock-cycle, so we
can sequence arbitrarily many in a time-slot. This does raise the possibility of
Zeno processes (infinite events within a time-slot), so some care will be required
here (disallowing infinite histories). This is more power than that required for
synchronous hardware, where we expect these actions to synchronise with the
clock, but we can model that by postfixing a Wait 1 statement, as used in the
case study shown later. An important point to note is the definition of channel
input (c?x → P ), not only involves an event c.e for some e, but also updates
the state. This is exploited later to allow shared variables.
The definition of external choice is quite complex —see [She06, p69] for a
discussion.
We define slotted-parallel in a direct fashion, similar to that used for Circus,
avoiding the complexities of the UTP/CTA approaches, and also handling error
cases in passing. An error occurs in P |[ sA | C | sB ]| Q if P (Q ) modifies any
variable in sB (sA ).
5.1
Laws
The language constructs displayed here obey a wide range of laws, many of which
have been described elsewhere [HH98, WC01b, SH02, She06] for those constructs
Slotted-Circus
85
Chaos =
b R(true)
Stop =
b CSP1(R3(ok ∧ wait ∧ EqvTrace(, slots slots)))
b&A =
b A b Stop
Skip =
b R(∃ ref • ref = EqvRef (slots) ∧ Skip)
Wait t =
b CSP1(R(ok ∧ delay(t) ∧ EqvTrace(, slots slots)))
delay(t) = (#slots − #slots < t) wait (#slots − #slots = t ∧ state = state)
!!
ok = ok ∧ wait = wait ∧ slots = slots
x := e =
b CSP1 R
∧ state = state ⊕ {x → val (e, state)}
val : Expr × (Name → Value) → Value
´
`
c.e → Skip =
b CSP1 ok ∧ R (wait com(c) ∨ complete com(c.e))
wait com(c) = wait ∧ possible(c)(slots, slots ) ∧ EqvTrace(, slots slots)
[
/
Refs(slots − front(slots))
possible(c)(slots, slots ) = c ∈
term com(c.e) = ¬ wait ∧ #slots = #slots ∧ EqvTrace(c, slots slots)
complete com(c.e) = term com( c.e) ∨ wait com(c); term com(c.e)
c!e → Skip =
b c.e → Skip
´
`
c?x → Skip =
b ∃ e • c.e → Skip[state0 /state] ∧ state = state0 ⊕ {x → e}
comm → A =
b (comm → Skip); A
A2B =
b CSP2(ExtChoice1(A, B ) ∨ ExtChoice2(A, B ))
ExtChoice1(A, B ) =
b A ∧ B ∧ Stop
ExtChoice2(A, B ) =
b (A ∨ B ) ∧ DifDetected (A, B )
1
00
(ok„∧ ¬ wait) ∧
« 1
0
C
BB
A ∧ B ∧ ok ∧
C
BB
B @ @ wait ∧ slots = slots ∨ A A ;
B
DifDetected (A, B ) =
b ¬ ok ∨ B
B „ Skip
«
@ (ok ∧ ¬ wait ∧ slots = slots) ∨
(ok ∧ ImmEvts(slots, slots ))
1
C
C
C
C
C
C
A
ImmEvts(slots, slots ) =
b ¬ EqvTrc(, head (slots slots))
Fig. 5. Slotted-Circus Semantics (part I)
that slotted-Circus shares with other languages (e.g. non-deterministic choice,
sequential composition, conditional, guards, STOP , SKIP ). Here we simply
indicate some of the laws regarding Wait that peculiar to slotted-Circus
(Figure 7).
5.2
Links
In [HH98, §1.6,pp40–1], a general Galois connection between an abstract theory
with observational variable a and a concrete theory over observation c is:
[(∃ c • D (c) ∧ (c, a)) ⇒ S (a)] iff [D (c) ⇒ (∀ a • (c, a) ⇒ S (a))]
Here D and S are corresponding design (concrete) and specification (abstract)
predicates respectively, while (c, a) is the linking predicate connecting observations at the two worlds. Of interest to us in the main are links between Circus
86
A. Butterfield, A. Sherif, and J. Woodcock
A |[ sA | {| cs |} | sB ]| B
=
∃ obsA , obsB •
A[obsA /obs ] ∧ B [obsB /obs ] ∧
⎞
⎛ ⎛
sA −
stateA = sA −
state ∨
⎜ if ⎝ sB −
stateB = sB −
state ∨ ⎠
⎜
⎜
sA ∩ sB = ∅
⎜
⎜ then ¬ ok ∧ slots slots
⎜
⎞
⎛
⎜
ok = okA ∧ okB ∧
⎜
⎜
⎟
⎜
⎜ else ⎜ wait = (waitA ∨ 1.waitB ) ∧
⎟
⎝
⎝ state = (sB −
−
stateA ) ⊕ (sA stateB ) ∧ ⎠
ValidMerge(cs)(slots, slots , slotsA , slotsB )
⎞
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎟
⎠
ValidMerge : P E → ((S E )+ )4 → B
ValidMerge(cs)(, s, s , s0, s1 ) = dif (s , s) ∈ TSync(cs)(dif (s0, s),dif (s1 , s))
TSync : P E → (S E )∗ × (S E )∗ → P((S E )+ )
TSync(cs)(s1 , s2 ) = TSync(cs)(s2 , s1 )
TSync(cs)(, ) = {}
TSync(cs)(s, ) =
TSync(cs)
A \ hidn =
R
μ X • F (X ) =
s1 oo S1 ,
s2 oo S2
s | s ∈ SSync(cs)(s, SNull (Ref (s)))
⎧
⎫
⎨ s oo S
⎬
=
| s ∈ SSync(cs)(s1 , s2 ) ∧
⎩
⎭
S ∈ TSync(cs)(S1 , S2 )
∃ s • A[s/slots ] ∧
slots slots = map(SHide(hidn))(dif (s, slot))
{X
; Skip
| F (X ) X }
Fig. 6. Slotted-Circus Semantics (II)
Wait n; Wait m = Wait (m + n)
Wait n 2 Wait n + m = Wait n
(Wait n; P ) 2 (Wait n; Q) = Wait n; (P 2 Q)
(Skip 2 (Wait n; P )) = Skip,
n>0
(a → P ) 2 (Wait n; (a → P )) = (a → P )
Fig. 7. Laws of slotted-Circus Wait
(playing the role of the abstract theory with observations a) and various instantiations of slotted-Circus (concrete, with obsevations c). The difference between
Circus and slotted-Circus is that the former has observations tr and ref , whilst
the latter subsumes both into slots. However we can immediately exploit the
method just presented by using the following relationship to define , which here
relates the Circus observational variables to those of slotted-Circus:
EqvTrace(tr , slots) ∧ ref = EqvRef (slots)
(8)
Slotted-Circus
87
So we get a Galois-link between Circus and any instantiation of slotted-Circus
for free. Similarly, a given relationship between different H types allows us to
generate Galois-links between different slotted-Circus instantiations.
6
Instantiating Slotted-Circus
We now look at the issue of giving one or more concrete instantiations to the
slotted-Circus framework just described. Originally, this work was aimed at producing a synchronous version of Circus, in which all events in a time-slot were
to be considered as simultaneous. One motivation for this was to support the
Handel-C language, which maps programs to synchronous hardware in which all
variable updates are synchronised with a global clock edge marking the end of
a computation cycle [Cel02]. However, there were two main difficulties with this
approach.
The first was that the formal semantics developed for Handel-C outside of the
UTP framework [BW02, BW05] actually modelled activity within a time-slot as
a series of decision-making events spread out in time, all culminating in a set
of simultaneous variable updates at the end of the slot. This approach, adopted
in both the operational and denotational semantics, gives a very natural and
intuitive description of what is taking place during Handel-C execution.
The second difficulty is more fundamental in nature, and exposed a key assumption underlying the UTP reactive theories, and those for CSP in general.
Early work looked at the Ph.D thesis of Janet Barnes [Bar93] which introduced
a synchronous version of CSP (SCSP). The key observation was a sequence of
slots, each comprising two event sets, one denoting the events occurring in that
slot (Acceptances) and the other describing the events refused (Refusals). A
healthiness condition required that the acceptances and refusals in any slot be
disjoint. However, implicit in this disjointedness condition is the notion that both
the acceptances and refusals are truly simultaneous. However, in the failures of
CSP, and the corresponding tr and ref observations of UTP, the key interpretation involved is that the refusals describe what is being refused given that the
event history has just taken place. As a specific example, consider the process
a → b → P . A possible (failure) observation of this process is ( a , {a}), i.e.,
we have observed the occurrence of the a event and the fact that the process is
now refusing to perform an a.
Consider trying to instantiate a slot where the history is simply an event-set,
as per SCSP:
A ∈ SCSP E =
PE
∅
HNullSCSP =
A1 ∪ A2
HaddSCSP (A1 , A2 ) =
HsubSCSP (A1 , A2 ) =
A1 \ A2
...
We find that we cannot guarantee law [Sadd:unit] (Appendix A), even if the
SCSP invariant is not required. This property is required to demonstrate that
88
A. Butterfield, A. Sherif, and J. Woodcock
slots ∼
= slots is R2-healthy. The underlying problem is that the definition of R2
relies on being able to deduce that slots is empty if subtracting slots from slots
leaves slots unchanged. However at the history-as-set level, we cannot deduce
H = ∅, given that H \ H = H .
6.1
Multiset History Instantiation
We can define an instantiation where the event history is a multiset or bag of
events (HMSA ), so event ordering is unimportant, but multiple event occurrences
in a slot do matter (Figure 8). The bag notation used here is that of Z [Spi87].
The events accepted are simply the bag domain. A trace corresponds to a bag
if it contains the same number of events as that bag. A null history is simply
an empty bag. A bag is a prefix if smaller than another bag. History addition
and subtract are the bag equivalents. History synchronisation merges the parts
of the two bags disjoint from the synchronisation set, with the intersection of all
three. Hiding is modelled by bag restriction.
The proofs that the above instantiation satisfy the properties in Appendix A
are all straightforward. The proof of law [ET:pfx] for MSA is shown in Appendix B.
HMSA E =
E → N1
Acc(bag) =
dom(bag)
EqvTrc(tr , bag) =
items(tr ) = bag
HNull =
[[]]
bag1
bag2 =
bag1 bag2
Hadd (bag1 , bag2 ) =
bag1 ⊕ bag2
Hsub(bag1 , bag2 ) =
bag1 bag2
HSync(cs)(bag1 , bag2 ) =
{(cs −
(bag1 ⊕ bag2 )) ⊕ (cs (bag1 ∩ bag2 ))}
where
∩ is bag interesection
HHide(hdn)bag =
hdn −
bag
Fig. 8. Multiset Action Instantiation (MSA)
7
Example Circus Process
We illustrate slotted Circus using an example originally due to Hoare [Hoa85a].
The problem is to compute the weighted sums of consecutive pairs of inputs.
Suppose that the input stream contains the following values: x0 , x1 , x2 , x3 , x4 , . . .;
then the output stream will be
(a ∗ x0 + b ∗ x1 ), (a ∗ x1 + b ∗ x2 ), (a ∗ x2 + b ∗ x3 ), (a ∗ x3 + b ∗ x4 ), · · ·
for weights a and b. We specify this problem with a synchronous process with
two channels: left , used for input, and right used for output. Since each output
Slotted-Circus
89
requires two consecutive values from the input stream, the first output cannot
occur before the third clock cycle.
clock
left
right
0
x0
1
x1
2
x2
a ∗ x0 + b ∗ x1
3
x3
a ∗ x1 + b ∗ x2
4
x4
a ∗ x2 + b ∗ x3
5
x5
a ∗ x3 + b ∗ x4
···
···
Hoare’s solution performs the two multiplications in parallel and then adds the
results. Suppose the implementation technology is a single field-programmable
gate array; the circuitry for the computation of the output would then be inherently parallel anyway. Let’s assume instead that we want to implement the
two multiplications on separate FPGAs. It’s clear that the a-product is always
ready one clock cycle before we need to perform the addition. Let’s keep this
intermediate result in the variable m: First however, note we are going to tar-
clock
left
m
right
0
x0
1
x1
a ∗ x0
2
x2
a ∗ x1
m + b ∗ x1
3
x3
a ∗ x2
m + b ∗ x2
4
x4
a ∗ x3
m + b ∗ x3
5
x5
a ∗ x4
m + b ∗ x4
···
···
···
get a Handel-C-like scenario where channel communication and assignment take
one-clock cycle, and we have shared variables. We need to reason about interleavings of assignments, but rather than re-work the whole theory to have
state-sequences, we simply convert assignments into channel communications.
So for the following case study, we have the following shorthands:
shorthand expansion
c?1 x
c?x → Wait 1.
c!1 x
c!x → Wait 1.
x :=1 e (a!1 e |[ ∅ | a | x ]| a?1 x ) where a is fresh.
δP
variables modified by P i.e used in x := . . . or c?x
P ||| Q P |[ δP | ∅ | δQ ]| Q
In effect the clock-cycle wait is built into the communication and assignment
notations, effectively avoid any Zeno hazards. Now we’re ready to specify the
problem as a slotted Circus process. The process WS is clearly deadlock and
WS =
var x , m : N • ( left?1 x ; ( left?1 x ||| m :=1 a ∗ x );
( μ X • ( left?1 x ||| m :=1 a ∗ x ||| right!1 (m + b ∗ x ) ) ; X ) )
livelock free: it is a non-stopping process with no internal synchronisations; and
it is hiding and chaos-free, with guarded recursion. Now we need to decompose
WS into two parallel processes with encapsulated state. We can replace the
use of m by a channel communication that passes the intermediate value. One
process (WSL) will receive the input stream and compute the a-product; the
other (WSR) will compute the b-product and the sum, and generate the output
90
A. Butterfield, A. Sherif, and J. Woodcock
stream. But now we see a problem with WS . The value x1 is received by WSL
in the first clock cycle, and so it can be communicated to WSR in the second
cycle. So it can’t be used by WSR until the third clock cycle. So we need to
delay the output on the right by another clock cycle. Our timing diagram shows
this more clearly.
clock
left
w
m
right
0
x0
1
x1
x0
2
x2
x1
a ∗ x0
3
x3
x2
a ∗ x1
m + b ∗ x1
4
x4
x3
a ∗ x2
m + b ∗ x2
5
x5
x4
a ∗ x3
m + b ∗ x3
···
···
···
···
Here’s another version of WS that does this.
WS =
var w , x , m : N •
left?1 x ; ( left?1 x ||| w :=1 x );
( left?1 x ||| w :=1 x ||| m :=1 a ∗ w );
( μ X • ( left?1 x ||| w :=1 x ||| m :=1 a ∗ x ||| right!1 (m + b ∗ w ) ) ; X )
Our refinement strategy is to split into two processes. The variable x belongs in
WSL, since it is used to store the current input. The variable m can be placed
in WSR, since it is used directly in producing outputs, but its value must be
computed in WSL, and so the value will have to be communicated from left
to right. The variable w records the previous input, and this is used in both
left and right processes; so we duplicate its value using a ghost variable v . The
ghost variable can then be used in the right-hand process in the calculation of
the output on the right. Our refinement starts with organising the variables.
(To reduce clutter, we abbreviate left ?1 x by ?1 x and right !1 e by !1 e. We also
separate the beginning and end of variable scopes.)
var w , x , m ;
?1 x ; (?1 x ||| w :=1 x ) ; (?1 x ||| w , m :=1 x , a ∗ w ) ;
(μ X • (?1 x ||| w , m :=1 x , a ∗ w ||| !1 (m + b ∗ w )) ; X ) ;
end w , x , m
= { v ghosts w }
var w , x , m ;
?1 x ; (?1 x ||| w :=1 x ) ;
var v ;
(?1 x ||| v , w , m :=1 x , x , a ∗ w ) ;
(μ X • (?1 x ||| v , w , m :=1 x , x , a ∗ w ||| !1 (m + b ∗ v )) ; X ) ;
end v ;
end w , x , m
= { widen scope }
var v , w , x , m ;
?1 x ; (?1 x ||| w :=1 x ) ; (?1 x ||| v , w , m :=1 x , x , a ∗ w ) ;
(μ X • (?1 x ||| v , w , m :=1 x , x , a ∗ w ||| !1 (m + b ∗ v )) ; X ) ;
end v , w , x , m
Slotted-Circus
91
Our next step is to insert some hidden events to prepare for the communication of
values between the two processes. We add two hidden channels: c communicates
x ’s value; and mid communicates m’s value. These events are not needed in the
first two steps.
= { hiding }
( var v , w , x , m ;
?1 x ; (?1 x ||| w :=1 x ) ; (?1 x ||| c.x ||| mid .a ∗ w ||| v , w , m :=1 x , x , a ∗ w ) ;
(μ X •
(?1 x ||| c.x ||| mid.a ∗ w ||| v, w , m :=1 x , x , a ∗ w ||| !1 (m + b ∗ v)) ; X );
end v , w , x , m ) \ {|c, mid |}
Now we can prepare for the parallel split by organising each step into parallel
parts, examining each atomic action and assigning it to the left or right component. The right-hand process doesn’t need to do anything during the first two
steps, so we make it wait. In the third step, the the input belongs on the left.
The pair of actions (c.x ||| v :=1 x ) can be replaced by a communication: the
left performs the output c!1 x and the right performs the input c?1 v . Similarly,
(mid .a ∗ w ||| m :=1 a ∗ w ) can be replaced by mid !1 a ∗ w and mid ?1 m.
Finally, the assignment to w belongs on the left. The body of the recursion is
split in exactly the same way, with the addition of the output being assigned to
the right-hand process.
= { parallel }
( var v , w , x , m ;
(?1 x Wait 1) ;
((?1 x ||| w :=1 x ) Wait 1) ;
((?1 x ||| c!1 x ||| mid !1 a ∗ w ||| w :=1 x ) (c?1 v ||| mid ?1 m)) ;
(μ X • ( (?1 x ||| c!1 x ||| mid !1 a ∗ w ||| w :=1 x )
(c?1 v ||| mid ?1 m ||| !1 (m + b ∗ v ) ) ; X )) ;
end v , w , x , m ) \ {|c, mid |}
We also need to split the recursion into two parallel parts. Since the body comprises two atomic steps in parallel, the fixed-point operator distributes cleanly
through the parallel operator.
= { parallel }
( var v , w , x , m ;
(?1 x Wait 1) ;
((?1 x ||| w :=1 x ) Wait 1) ;
((?1 x ||| c!1 x ||| mid !1 a ∗ w ||| w :=1 x ) (c?1 v ||| mid ?1 m)) ;
( (μ X • (?1 x ||| c!1 x ||| mid !1 a ∗ w ||| w :=1 x ) ; X ) ;
(μ X • (c?1 v ||| mid ?1 m ||| !1 (m + b ∗ v )) ; X ) ) ;
end v , w , x , m ) \ {|c, mid |}
Now we can perform the parallel split, using an interchange law for sequence and
parallel that is similar to the spreadsheet rules in UTP. We create the left-hand
92
A. Butterfield, A. Sherif, and J. Woodcock
process by encapsulating w and x , retaining the left-hand parts, and discarding
the right-hand parts. We create the right-hand process similarly.
= { parallel split }
( ( var w , x ;
?1 x ;
(?1 x ||| w :=1 x ) ;
(?1 x ||| c!1 x ||| mid !1 a ∗ w ||| w :=1 x ) ;
(μ X • (?1 x ||| c!1 x ||| mid !1 a ∗ w ||| w :=1 x ) ; X ) ;
end w , x )
( var v , m ;
Wait 1 ; Wait 1 ;
(c?1 v ||| mid ?1 m) ;
(μ X • (c?1 v ||| mid ?1 m ||| !1 (m + b ∗ v )) ; X ) ;
end v , m )
) \ {|c, mid |}
Now we can tidy up the processes for our final result.
( var w , x : N •
left ?1 x ; (left ?1 x ||| w :=1 x ) ; (left ?1 x ||| c!1 x ||| mid !1 a ∗ w ||| w :=1 x );
(μ X • (left ?1 x ||| c!1 x ||| mid !1 a ∗ w ||| w :=1 x ) ; X ) ;
var v , m : N • ( Wait 2 ; (c?1 v ||| mid ?1 m) ;
(μ X • (c?1 v ||| mid ?1 m ||| right !1 (m + b ∗ v )) ; X ) ; )
) \ {|c, mid |}
Of course, since this is equal to WS , it is deadlock and livelock-free and computes
the right results.
A key point of the above case-study is that it works in any of the instantiations
mentioned so far for slotted-Circus, namely CTA or MSA.
8
Related Work
During the development of Handel-C at Oxford, a lot of the principles and theory
was developed and published [PL91, HIJ93]. Here the emphasis was very much
on the verified compilation into hardware of an occam-like language. However
with the commercialisation of this as the language Handel-C the formal aspects
and hardware compilation parted company, and the Handel-C language acquired
new constructs like “prialt” that were not treated in the literature.
Modern Handel-C [Cel02] also has the idea of connecting hardware with different clocks together using tightly controlled asynchronous interfaces. Modelling
this kind of behaviour requires a theory that mixes time and asynchronicity, such
as timed-CSP [Sch00].
Slotted-Circus
93
There has been work done on hardware semantics, ranging from the “reFLect”
language used by Intel for hardware verification [GJ06], to the language Esterel
used mainly for the development of flight avionics [BG92]. The Intel approach is a
suite of hardware description languages, model-checkers and theorem provers all
written and/or integrated together using the reFLect language, aimed mainly
at the verification of computer datapath hardware. The Esterel language is a
hardware description language with a formal semantics, and so is quite lowlevel in character, and so in the context of this research could be considered a
potential replacement of Handel-C as an implementation technology. However,
it is unclear how well it would link to the kind of specification and refinement
style of work that we are proposing to support.
9
Future Work
We have described a generic framework for instantiating a wide range of slottedtheories, capturing their common features. An important aspect that has yet to
be covered is what distinguishes the the various instantiations from one another,
i.e. how do the laws of CTA differ from those of MSA, for instance. We know for
example that the following is a law of MSA, but not of CTA, or slotted-Circus
in general:
a →b→P =b→a →P
Also worthy of exploration are the details of the behaviour of the Galois links
inbetween different instances of slotted-Circus, and between those and standard
Circus. These details will provide a framework for a comprehensive refinement
calculus linking all these reactive theories together.
In order to deal with the asynchronously interfaced multiple-clock hardware
now supported by Handel-C we will need to exploit the link from the slotted
theories to the generally asynchronous Circus theory itself.
Also of interest will be to consider to what extent the work on “generic composition” [Che02, Che06] can contribute to a clear and or tractable presentation
of this theory.
10
Conclusions
A framework for giving UTP semantics to a class of reactive systems whose execution is demarcated by regular clock ticks has been presented. The general
nature of the observational variables and the key operations on same have been
discussed, showing how they are used build to both the healthiness conditions
and the language semantics. A key result of this work has been the care needed
to get a satisfactory definition of R2, and exposing the fact that certain synchronous theories like SCSP do not fit this particular UTP pattern for describing
reactive systems.
94
A. Butterfield, A. Sherif, and J. Woodcock
Acknowledgement
We would like to thank the Dean of Research at TCD and QinetiQ for their
support of this work, and the comments of the anonymous reviewers, which
helped improve key material in this paper.
References
[Bar93]
Barnes, J.E.: A Mathematical Theory of Synchronous Communication.
Technical Monograph PRG-112, Oxford University Computing Laboratory
Programming Research Group, Hilary Term (1993)
[BG92]
Berry, G., Gonthier, G.: The ESTEREL synchronous programming language: design, semantics, implementation. Science of Computer Programming 19, 87–152 (1992)
[BW02] Butterfield, A., Woodcock, J.: Semantic domains for handel-C. Electr. Notes
Theor. Comput. Sci, vol. 74 (2002)
[BW05] Butterfield, A., Woodcock, J.: prialt in Handel-C: an operational semantics. International Journal on Software Tools for Technology Transfer
(STTT) 7(3), 248–267 (2005)
[Cel02]
Celoxica Ltd. Handel-C Language Reference Manual, v3.0, (2002) URL:
www.celoxica.com
[Che02] Chen, Y.: Generic composition. Formal Asp. Comput 14(2), 108–122 (2002)
[Che06] Chen, Y.: Hierarchical organisation of predicate-semantic models. In: Dunne,
S., Stoddart, B. (eds.) UTP 2006. LNCS, vol. 4010, pp. 155–172. Springer,
Heidelberg (2006)
[GJ06]
Melham, T., Grundy, J., O’Leary, J.: A reflective functional language for
hardware design and theorem proving. Journal of Functional Programming 16(2), 157–196 (2006)
[HH98]
Hoare, C.A.R., He, J.: Unifying Theories of Programming. Series in Computer Science. Prentice-Hall, Englewood Cliffs (1998)
[HIJ93]
Jifeng, H., Page, I., Bowen, J.: Towards a provably correct hardware implementation of Occam. In: Milne, G.J., Pierre, L. (eds.) CHARME 1993.
LNCS, vol. 683, pp. 214–225. Springer, Heidelberg (1993) IFIP WG10.2
[Hoa85a] Hoare, C.A.R.: Communicating Sequential Processes. Intl. Series in Computer Science. Prentice-Hall, Englewood Cliffs (1985)
[Hoa85b] Hoare, C.A.R.: Programs are predicates. In: Proc. of a discussion meeting
of the Royal Society of London on Mathematical logic and programming
languages, Upper Saddle River, NJ, USA, pp. 141–155. Prentice-Hall, Inc,
Englewood Cliffs (1985)
[PL91]
Page, I., Luk, W.: Compiling Occam into field-programmable gate arrays.
In: Moore, W., Luk, W. (eds.) FPGAs, Oxford Workshop on Field Programmable Logic and Applications, 15 Harcourt Way, Abingdon OX14 1NV,
UK, pp. 271–283 Abingdon EE&CS Books (1991)
[Ros97]
Roscoe, A.W.: The Theory and Practice of Concurrency. international series
in computer science. Prentice-Hall, Englewood Cliffs (1997)
[Sch00]
Schneider, S.: Concurrent and Real-time Systems — The CSP Approach.
Wiley, Chichester (2000)
Slotted-Circus
95
[SH02]
Sherif, A., He, J.: Towards a time model for circus. In: George, C.W., Miao,
H. (eds.) ICFEM 2002. LNCS, vol. 2495, pp. 613–624. Springer, Heidelberg
(2002)
[She06]
Sherif, A.: A Framework for Specification and Validation of Real Time Systems using Circus Action. Ph.d. thesis, Universidade Federale de Pernambuco, Recife, Brazil (2006)
[Spi87]
Spivey,: The Z Notation: A Reference Manual. Prentice Hall, Englewood
Cliffs (1987)
[WC01a] Woodcock, J.C.P., Cavalcanti, A.L.C.: A Concurrent Language for Refinement. In: Butterfield, A., Pahl, C. (eds.) IWFM’01: 5th Irish Workshop in
Formal Methods, Dublin, Ireland, July 2001. BCS Electronic Workshops in
Computing (2001)
[WC01b] Woodcock, J., Cavalcanti, A.: Circus: a concurrent refinement language.
Technical report, University of Kent at Canterbury (October 2001)
[WC02] Woodcock, J., Cavalcanti, A.: The semantics of circus. In: ZB, pp. 184–203
(2002)
A
Generic Laws
The functions and relations over H E required to define a slotted-Circus theory,
need to satisfy the following laws:
[ET:elems] EqvTrc(tr , hist ) ⇒ elems(tr ) = Acc(hist )
[HIST:eq] (h1 = h2 ) ≡ ∀ tr • EqvTrc(tr , h1 ) ≡ EqvTrc(tr , h2 )
[HN:null] Acc(HNull ) = {}
[pfx:refl] hist hist = True
[pfx:trans] hist1 hist2 ∧ hist2 hist3 ⇒ hist1 hist3
[pfx:anti-sym] hist1 hist2 ∧ hist2 hist1 ⇒ hist1 = hist2
[SN:pfx] HNull hist
[ET:pfx] hist1 hist2 ⇒ ∃ tr1 , tr2 • EqvTrc(tr1 , hist1 ) ∧ EqvTrc(tr2 , hist2 ) ∧ tr1 ≤ tr2
[Sadd:events] Acc(Sadd (h1 , h2 )) = Acc(h1 ) ∪ Acc(h2 )
[Sadd:unit] Sadd (h1 , h2 ) = h1 ≡ h2 = HNull
[Sadd:assoc] Sadd (h1 , Sadd (h2 , h3 )) = Sadd (Sadd (h1 , h2 ), h3 )
[Sadd:prefix] h Sadd (h, h )
[Ssub:pre] pre Ssub(h1 , h2 ) = h2 h1
[Ssub:events] h2 h1 ∧ h = Ssub(h1 , h2 ) ⇒
Acc(h1 ) \ Acc(h2 ) ⊆ Acc(h ) ⊆ Acc(h1 )
[SSub:self] Ssub(h, h) = HNull
[SSub:nil] Ssub(h, HNull ) = h
[SSub:same] hist hista ∧ hist histb ⇒
Ssub(hista , hist ) = Ssub(histb , hist ) ≡ hista = histb
96
A. Butterfield, A. Sherif, and J. Woodcock
[SSub:subsub] histc hista ∧ histc histb ∧ histb hista
⇒ Ssub(Ssub(hista , histc ), Ssub(histb , histc )) = Ssub(hista , histb )
[Sadd:Ssub] hist hist ⇒ Sadd(hist, Ssub(hist , hist)) = hist
[Ssub:Sadd] Ssub(Sadd(h1 , h2 ), h1 ) = h2
[SHid:evts] Acc(SHide(hid)(h)) = Acc(h) \ hid
[SNC:sym] SSync(cs)(h1 , h2 ) = SSync(cs)(h2 , h1 )
[SNC:one] ∀ h ∈ SSync(cs)(h1 , HNull) • Acc(h ) ⊆ Acc(h1 ) \ cs
[SNC:only] h ∈ Acc(SSync(cs)(h1 , h2 )) ⇒ Acc(h ) ⊆ Acc(h1 ) ∪ Acc(h2 )
[SNC:sync] h ∈ Acc(SSync(cs)(h1 , h2 )) ⇒ cs ∩ Acc(h ) ⊆ cs ∩ (Acc(h1 ) ∩ Acc(h2 ))
[SNC:assoc] SyncSet(cs)(h1 )(SSync(cs)(h2 , h3 )) = SyncSet(cs)(h3 )(SSync(cs)(h1 , h2 ))
B
Proofs for R2-ness of = and MSA Prefix
R2(slots = slots)
≡
“ defn. R2, apply substitution, shorthand RL(s) = Ref (last(s)) ”
∃ ss • ss (slots slots) = ss ∧ RL(slots) = RL(ss)
≡
“ Property 1 (below) ”
∃ ss • slots slots = SNull (RL(ss)) ∧ RL(slots) = RL(ss)
≡
“ Property 2 (below) ”
∃ ss • front(slots ) = front(slots) ∧ tail (slots ).1 = tail (slots).1
∧ RL(slots ) = RL(ss) ∧ RL(slots) = RL(ss)
≡
“ Liebniz, restrict quantification scope ”
front(slots ) = front(slots) ∧ tail (slots ).1 = tail (slots).1
∧ RL(slots ) = RL(slots) ∧ ∃ ss • RL(slots) = RL(ss)
≡
“ defn. of equality, witness ss = slots ”
slots = slots
Property 1: ( ss tt = ss ) ≡ tt = SNull (RL(ss))
Property 2: (tt tt) = SNull(r) ≡ front(tt) = front(tt ) ∧ last(tt).1 = last(tt ).1 ∧ RL(tt ) = r
bag1
≡
bag2
“ defn. of prefix ”
bag1 bag2
≡
“ bag property ”
∃ bagΔ • bag2 = bag1 ⊕ bagΔ
≡
“ bag property: ∀ bag • ∃ tr • items(tr ) = bag ”
∃ bagΔ , trΔ , tr1 , • bag2 = bag1 ⊕ bagΔ ∧ items(trΔ ) = bagΔ ∧ items(tr1 ) = bag1
≡ “ One-point rule backwards tr2 = tr1 trΔ ”
∃ bagΔ , trΔ , tr1 , tr2 • bag2 = bag1 ⊕ bagΔ ∧ items(trΔ ) = bagΔ ∧ items(tr1 ) = bag1 ∧ tr2 = tr1 trΔ
Slotted-Circus
≡
≡
≡
“ One-point rule bagΔ , Liebniz bag1 ”
∃ trΔ , tr1 , tr2 • bag2 = items(tr1 ) ⊕ items(trΔ ) ∧ items(tr1 ) = bag1 ∧ tr2 = tr1 trΔ
“ items is a sequence homomorphism ”
∃ trΔ , tr1 , tr2 • bag2 = items(tr2 ) ∧ bag1 = items(tr1 ) ∧ tr2 = tr1 trΔ
“ sequence property ”
∃ trΔ , tr1 , tr2 • bag2 = items(tr2 ) ∧ bag1 = items(tr1 ) ∧ trΔ = tr2 − tr1
≡
“ One point rule: trΔ , requires definedness of tr2 − tr1 ”
∃ tr1 , tr2 • bag2 = items(tr2 ) ∧ bag1 = items(tr1 ) ∧ tr1 ≤ tr2
≡
97
“ def. of EqvTrc, backwards ”
∃ tr1 , tr2 • EqvTrc(tr2 , bag2 ) ∧ EqvTrc(tr1 , bag1 ) ∧ tr1 ≤ tr2
Bug Hunting with False Negatives
Jens Calamé1 , Natalia Ioustinova1 , Jaco van de Pol1,2 , and Natalia Sidorova2
1
Centrum voor Wiskunde en Informatica,
P.O.Box 94079, 1090 GB Amsterdam, The Netherlands
2
Eindhoven University of Technology,
P.O.Box 513, 5600 MB Eindhoven, The Netherlands
jens.calame@cwi.nl, ustin@cwi.nl,
jaco.van.de.pol@cwi.nl, n.sidorova@tue.nl
Abstract. Safe data abstractions are widely used for verification purposes. Positive verification results can be transferred from the abstract
to the concrete system. When a property is violated in the abstract system, one still has to check whether a concrete violation scenario exists.
However, even when the violation scenario is not reproducible in the
concrete system (a false negative), it may still contain information on
possible sources of bugs.
Here, we propose a bug hunting framework based on abstract violation scenarios. We first extract a violation pattern from one abstract
violation scenario. The violation pattern represents multiple abstract violation scenarios, increasing the chance that a corresponding concrete
violation exists. Then, we look for a concrete violation that corresponds
to the violation pattern by using constraint solving techniques. Finally,
we define the class of counterexamples that we can handle and argue
correctness of the proposed framework.
Our method combines two formal techniques, model checking and
constraint solving. Through an analysis of contracting and precise abstractions, we are able to integrate overapproximation by abstraction
with concrete counterexample generation.
1
Introduction
Abstractions [5,6,7,9,13,18] are widely used to reduce the state space of complex,
distributed, data-oriented and thus large systems for verification purposes. We
focus on abstractions that are used to check satisfaction rather than the violation
of properties. These abstractions are constructed in such a way that we can
transfer positive verification results from the abstract to the concrete model,
but not the negative ones. Counterexamples found on the abstract system may
have no counterpart in the concrete system. We further refer to this kind of
counterexamples as false negatives. False negatives are usually used to refine
the abstraction and iteratively call the model checking algorithm on the refined
abstraction [4,10,17].
Part of this research has been funded by the Dutch BSIK/BRICKS project.
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 98–117, 2007.
c Springer-Verlag Berlin Heidelberg 2007
Bug Hunting with False Negatives
99
tick
k+
tick
k-1
tick
...
tick
0
Fig. 1. Abstracted timer
In this paper, we consider false negatives in the context of data abstractions,
i.e. abstractions that substitute actual data values by abstract ones and operations on concrete data by operations on abstract data, depending on the
property being verified. We use the timer abstraction from [8] as an illustrating
example in this paper. This abstraction leaves all values of a discrete timer below
k unchanged and maps all higher values to the abstract value k + . Note that the
deterministic time progress operation tick (decreasing the values of active timers
by one), becomes non-deterministic in the abstract model (see Fig. 1). But this
abstraction allows us to only regard the k smallest values and the constant k +
in order to prove that a property holds for any value n.
Consider a system, where every timer setting set(n) is followed by n tick steps
before the timer is set again, for some constant value n. Being set to a value n
above k, the abstract timer can do an arbitrary number of tick steps, before it
reaches value k − 1. From there, it decreases until it expires at 0.
We now use this k + timer abstraction to verify an action-based LTL property
(a → ♦b) and obtain the following trace as a counterexample for the abstract
system: a.set(k + ).tick 3 .b.(a.set(k + ).tick 2 .d) . Note that the timer abstraction
affected the parameter of the set action, so that the number of tick steps following
set(k + ) is not fixed anymore. This trace obviously is a false negative since it does
not reflect any possible trace of the original system (remember the constant n).
Assuming that the trace a.set(n).tick n .b.(a.set(n).tick n .d) exists in the original system, the false negative still contains a clue for finding this concrete counterexample. We can relax the found abstract counterexample by using the information that the operations on timers are influenced by the timer abstraction
and check whether the concrete system contains a trace matching the pattern
a.any .b.(a.any .d) where any represents any action on timers. We call such a
pattern a violation pattern. Note that any trace matching the violation pattern
violates our property of interest. The pattern contains a cyclic part, and it is
more restrictive than the negation of the property. Therefore, when enumerative
model checking is concerned, it is easier to find a trace of the concrete system
satisfying the pattern than one that violates the property.
In this paper, we propose a framework that supports the bug hunting process
described in the above example. In this framework, we apply a combination of abstraction, refinement and constraint solving techniques to process algebraic specifications. The framework is illustrated in Fig. 2 where M denotes the concrete
system, Mα stands for an abstraction of M, φ is the property in question and φα
is its abstraction. When checking whether the abstract system satisfies the abstract
property, we may obtain a counterexample having no counterpart in the concrete
system (the set (Mα \M) ∩ ¬φ). Given the counterexample, we relax actions influenced by the data abstraction and construct a violation pattern that represents
100
J. Calamé et al.
Μα
Μ
V
¬φ
¬φ α
Fig. 2. Violation pattern approach
a set of traces violating the property and resembling the counterexample. For this
to work, we need an accurate analysis of contracting and precise abstractions [16].
In short, contracting abstractions abstract a system property in a way, that less
traces fulfill this property, while precise abstractions do not affect fulfilling traces.
To check whether there is a concrete trace matching the violation pattern, we
transform the violation pattern and the specification of the concrete system into
a constraint logic program. Subsequently, a constraint solver is used to find a
concrete trace matching the violation pattern, if such a trace exists.
The rest of the paper is organized as follows: In the remainder of this section,
we compare our work with related work. In Section 2, we define the class of
systems we are working with. Furthermore, we define a next-free action-based
LTL (ALTL) and extend it by data (eALTL). In Section 3, we work out abstractions of labeled transition systems and of eALTL properties. In Section 4, we
present a taxonomy of counterexamples, of which we select the false negatives
to build up a bug hunting framework and discuss its correctness in Section 5. In
Section 6, we give an example for the implementation of this framework. Finally,
we conclude with Section 7.
Related Work
First, we compare our method with the more traditional CEGAR approach
(Counter-Example-Guided Abstraction Refinement) [4,17], which has recently
been extended to state- and event-based software by the ComFoRT framework [3]. In both methods, abstractions preserve properties in one direction
only: if the abstract system satisfies the property, so does the concrete system;
a counterexample may however be a real one or a false negative. In the CEGAR method, the abstraction is refined based on abstract counterexamples, and
model checking is iteratively applied to the refined abstractions of the system.
Our method is to generalize false negatives and then to find violations in the concrete specification, which are similar to the original false negative. Note that in
principle both methods can be combined: given a false negative, one could search
for a concrete violation using our method. If it is found, the CEGAR loop can be
terminated early. If still no concrete counterexample is found, one can proceed
by refining the abstraction as in the CEGAR approach and iterate verification.
For counterexamples that have been produced when model checking the abstract model, it has to be determined whether they represent real system defects. In [21], the problem of automating this analysis has been addressed. For
this purpose, the authors propose two techniques: model checking on choice-free
Bug Hunting with False Negatives
101
paths and abstract counterexample guided concrete simulation. In [20], an approach based on test generation is proposed for searching for concrete instances
of abstract counterexamples. Only counterexamples for safety properties are addressed by those approaches, i.e. it works only for finite counterexamples, while
we deal with infinite traces. Unlike these approaches, we look for a concrete trace
that does not match a counterexample itself, but a violation pattern that has
been generated from it.
Finally, [15] and [22] are orthogonal to ours, because there model checking
methods are proposed that rely on a refinement of an underapproximation of the
system behavior. These methods aim at the falsification of a desired property and
apply a refinement when no counterexample is found. In contrast, we try to prove
the property and, if we do not succeed, try to find a concrete counterexample.
2
The Specification Framework
We did our research in the setting of the process-algebraic language μCRL [14].
As graphical notation, we will use symbolic transition systems (STS s, cf. [24]).
A specification S over an alphabet of actions Act (defined below), is given as the
n
Pi of a finite number of processes. A process definition
parallel composition Πi=1
P is given by a four-tuple (Var , Loc, Edg, (init , ηinit )), where Var denotes a finite
set of variables, and Loc denotes a finite set of locations , or control states.
A mapping of variables to values is called a valuation; we denote the set of
valuations by Val = {η | η : Var → D}. We assume standard data domains such
as N or B. The set Expr denotes the set of expressions, built from variables
and function symbols in the usual way. An expression can be evaluated to a
value, given a valuation for the variables. We write D when leaving the datadomain unspecified and silently assume all expressions to be well-typed. The
initial location and valuation are given by (init , ηinit ). The set Edg ⊆ Loc ×
Act × Loc denotes the set of edges. An edge describes changes of configurations
specified by an action from Act.
Let Event be a set of system events (cf. channel names, action names). As
actions, we distinguish (1) the input of an event s together with a local variable
to which the received value can be assigned, (2) the output of an event s together
with a value described by an expression, and (3) internal actions, like assignments. Every action is guarded by a boolean expression g. This guard decides,
whether the action may be executed (when the guard evaluates to true) or not.
So we define the set Act to consist of: g?s(x), g!s(e), or g τ, x := e, resp., and
ˆ ∈ Edg ,
we use ι, ι . . . when leaving the action unspecified. For an edge (, ι, )
ˆ
we write more suggestively →ι .
Examples of specifications can be found in Fig. 6 later in this paper. There,
the system on the left-hand side awaits an input in(x), with a variable x that
will be instantiated at runtime. Depending on the value of x, the system will
then output the event out with either the value of x or 0.
Before we define the semantics of our specifications, we introduce the notion
of labeled transition systems and traces.
102
J. Calamé et al.
Definition 1 (Total LTS ). A labeled transition system (LTS ) is a quadruple
M = (Σ, Lab, Δ, σinit ) where Σ is a set of states, Lab is a set of action labels,
Δ ⊆ Σ × Lab × Σ is a labeled transition relation and σinit ∈ Σ is the initial
state. A total LTS does not contain any deadlocks.
Further we write σ →λ σ for a triple (σ, λ, σ ) ∈ Δ and refer to it as a λ-step of
M. For the rest of the paper, we assume LTS s to be total.
Definition 2 (Traces). Let M = (Σ, Lab, Δ, σinit ) be an LTS . A trace β of
M is a mapping β : N \ {0} → Lab, such that there is a mapping β : N → Σ and
for any i, (i + 1) ∈ N : β [i] →β[i+1] β [i + 1] ∈ Δ with β [0] = σinit . We further
refer to the suffix of β starting at β[i] as β i . By [[M]]trace , we denote the set of
all traces in M.
The step semantics of S is given by an LTS M = (Σ, Lab, Δ, σinit ). Here, the
set of states is Σ := Loc × Val with the initial state σinit := (init , ηinit ) ∈ Σ. The
(possibly infinite) set of labels is Lab := {s(d) | s ∈ Event, d ∈ D}. Finally, the
transitions Δ ⊆ Σ × Lab × Σ are given as a labeled transition relation between
states. The labels differentiate internal actions and communication steps, either
input or output, which are labeled by an event and a value being transmitted,
i.e. τ , ?s(v) or !s(v), respectively.
Receiving an event s with a communication parameter x, →g?s(x) ˆ ∈ Edg ,
results in updating the valuation η[x→v] according to the parameter of the event
ˆ The possible input values are limited by the
and changing current location to .
ˆ
guard. Output, →g!s(e) ∈ Edg, is guarded, so sending a message involves
evaluating the guard and the expression according to the current valuation. It
ˆ Assignments,
leads to the change of the location of the process from to .
ˆ
→gτ,x:=e ∈ Edg, result in the change of a location and the update of the
valuation η[x→v] , where [[e]]η = v. Assignment transitions are labeled by the
corresponding action label τ . Firing such a transition also involves evaluating
the guard and the expression according to the current valuation.
2.1
ALTL with Data (eALTL)
To specify properties of a system, we propose a data extension for action-based
Linear Temporal Logic (ALTL [12]). This logic specifies system properties in
terms of events parameterized with data. Here, we first define action formulae,
their satisfaction and then define extended ALTL, eALTL.
Definition 3 (Action Formulae). Let x be a variable from Var , expr be a
boolean expression from Expr , a be an event from Event, then the syntax of an
action formula ζ is defined as follows:
ζ ::= | {a(x) | expr(x)} | ¬ζ | ζ ∧ ζ
We will use a(x) as an abbreviation for {a(x) | true} and a(d) as an abbreviation
for {a(x) | x = d}. We do not impose any limitations on the set of boolean
expressions.
Bug Hunting with False Negatives
103
Definition 4 (Interpretation of an action formula). Let act ∈ Lab and ζ
be an action formula, then the satisfaction of ζ on act is defined as follows:
act |=
always (true)
act |= {a(x) | expr(x)} if there exists some d ∈ D s.t.
act = a(d) and [[expr]][x→d] = true
act |= ζ1 ∧ ζ2
if act |= ζ1 and act |= ζ2
act |= ¬ζ
if not act |= ζ
Definition 5 (eALTL Formulae). Let ζ be an action formula. The syntax of
eALTL formulae is defined by the following grammar:
φ ::= ζ | ¬φ | φ ∧ φ | φUφ
Definition 6 (Semantics of eALTL). Let β be a (infinite) trace, φ, φ1 , φ2 be
eALTL formulae, ζ be an action formula then
β
β
β
β
|= ζ
|= ¬φ
|= φ1 ∧ φ2
|= φ1 Uφ2
if β[1] |= ζ
if not β |= φ
if β |= φ1 and β |= φ2
if there exists k ∈ N such that
for all 0 ≤ i < k : β i |= φ1 and β k |= φ2
Let M = (Σ, Lab, Δ, σinit ) be an LTS . We say that M |= φ iff β |= φ for
all traces β of M starting at σinit . We introduce the following shorthand notations: ⊥ for ¬; ♦φ for Uφ; φ for ¬♦¬φ; φ1 ∨ φ2 for ¬(¬φ1 ∧ ¬φ2 ); φ1 ⇒
φ2 for ¬φ1 ∨ φ2 ; φ1 Rφ2 for ¬(¬φ1 U¬φ2 ). eALTL is suitable to express a broad
range of property patterns like occurrence, bounded response or absence [11]. For
our further work on abstracting properties of systems, we will require that property formulae are in positive normal form, i.e. all negations are pushed inside,
right before action formulae.
3
Abstraction of Systems and Properties
In this section, we present an abstraction mechanism based on homomorphisms
as in [5,16], and adapted to an action-based setting. Abstracting a system leads
to a smaller state space which can thus be examined easier. However, model
checking an abstracted system also requires the abstraction of the properties
that have to be checked. We will first present the abstraction of systems and
then the abstraction of eALTL properties.
3.1
Abstraction of a System
The basis for the abstraction is a homomorphism α = hs , ha defining two
abstraction functions which regard states and actions of an LTS [5,23]. The
function hs : Σ → Σ α maps the states of a concrete system M to abstract
states. The function ha : Lab → Lab α does the same with action labels of M.
104
J. Calamé et al.
σ
hS
λ
ha
σˆ
hS
σα
λα
σˆ α
Fig. 3. Abstraction requirement for LTS s
Definition 7. Let abstraction α = hs , ha for automaton M = (Σ, Lab, Δ, σinit )
be given. We define α(M) to be (Σ α , Lab α , Δα , hs (σinit )), where σ α →λα σ̂ α ∈
Δα if and only if σ →λ σ̂ ∈ Δ, for some σ, σ̂ and λ such that hs (σ) = σ α ,
hs (σ̂) = σ̂ α , and ha (λ) = λα .
Now, we define a homomorphic relation on traces, ≡α ⊆ Lab × Lab α , which
relates concrete traces from Lab to their abstract counterparts in Lab α .
Definition 8 (Trace Inclusion w.r.t. α). Let α = hs , ha be a homomorphism. For a trace β of Lab and trace β α of Lab α , we say β ≡α β α iff for all
i ∈ N : β α [i] = ha (β[i]).
We say that M ⊆α Mα iff for every trace β of M there exists a trace β α of
Mα such that β ≡α β α .
It is well known that homomorphic abstractions lead to overapproximations.
Notably, the abstract system covers at least the traces of the concrete system:
Lemma 9. Let M be an LTS with homomorphism α. Then M ⊆α α(M).
It is often more convenient to apply abstractions directly on a system specification S than on its transition system M. Such an abstraction on the level of S
is well-developed within the Abstract Interpretation framework [6,7,9]. Abstract
Interpretation imposes a requirement on the relation between the concrete specification S and its abstract interpretation S α . This takes the form of a safety
requirement on the relation between data and operations of the concrete system
and their abstract counterparts (we skip the details). Each value of the concrete domain D is related by a data abstraction function hd to a value from
the abstract domain Dα . For every operation (function) f on the concrete data
domain, an abstract function f α is defined, which overapproximates f . For reasons of simplicity, we assume f to be a unary operation. Furthermore, we apply
only data abstraction. This means that the names of actions in a system are not
affected by the abstraction, i.e. ha (a(d)) = a(hd (d)) such that two actions a(x)
and b(y) cannot be mapped to the same abstract action.
However, applying abstractions directly on a system’s specification S rather
than on its LTS leads to a loss of precision. Let S α be the abstract interpretation
of S, and let Mα and M be their underlying LTS s. It is well known that Mα
is only an overapproximation of α(M) (cf. [5]). In particular, we will still have
trace inclusion up to α: M ⊆α α(M) ⊆α Mα .
Bug Hunting with False Negatives
105
Fig. 4. Contracting Abstraction
3.2
Abstraction of eALTL Formulae
The abstraction of eALTL formulae is based on the notions of contracting and
precise abstractions as it has been introduced in [16]. In a contracting abstraction, a property φα holds for a trace β α iff the property φ holds for all concrete
traces β with β α = α(β). Note that for soundness of abstract model checking, we
need contracting abstractions. This does, however, not imply that all properties
that hold for the original system, must also hold in the abstract system (see
Fig. 4, ellipse vs. hatched square). In precise abstractions, this cannot happen.
Definition 10 (Contracting and Precise Abstraction). Let φ be a property
over an action alphabet λ. Its abstraction φα is
– contracting iff: ∀β ∈ Lab : α(β) |= φα ⇒ β |= φ.
– precise iff:
∀β ∈ Lab : α(β) |= φα ⇔ β |= φ.
In the following, we define an abstraction of eALTL formulae that is guaranteed
to be contracting. We assume all formulae to be in positive normal form.
Definition 11 (Abstraction of Action Formulae). Action formulae as defined in Def. 3 are abstracted as follows:
α() :=
α({a(x) | expr(x)}) := {a(xα ) | ∀x : hd (x) = xα → expr(x))}
α(¬{a(x) | expr(x)}) :=
{b(xα )} ∨ {a(xα ) | ∀x : hd (x) = xα → ¬expr(x)}
b=a
α(ζ1 ∧ ζ2 ) := α(ζ1 ) ∧ α(ζ2 )
The abstraction of eALTL formulae is more straightforward, since we do not
have to regard negations on this level.
Definition 12 (Abstraction of eALTL Formulae). eALTL formulae as defined in Def. 5 are abstracted as follows:
α(φ1 ∧ φ2 ) := α(φ1 ) ∧ α(φ2 )
α(φ1 Uφ2 ) := α(φ1 )Uα(φ2 )
106
J. Calamé et al.
In order to have precise abstractions, we need a restriction on the homomorphism α. We define that α is consistent with φ, iff for all action formulae ζ
occuring in φ, {ha (act)|act |= ζ} ∩ [[¬α(ζ)]] = ∅, i.e. the hatched square and the
ellipse in Figure 4 coincide.
Lemma 13. If α is consistent with φ, then α(φ) is precise.
4
Classification of Counterexamples
We can now explain model checking by abstraction for eALTL formulae. Let a
specification S (with underlying LTS M) and an eALTL property φ be given.
Let us investigate whether a contracting abstraction α suffices for our needs.
We compute α(φ) and S α , generate its underlying LTS Mα and use a model
checking algorithm to check Mα |= φα . If this holds, we can derive by our
previous results, that also M |= φ, without ever generating M. If it does not
hold, we obtain a counterexample. Here we provide a classification of abstract
counterexamples and demonstrate their relationship with contracting and precise
abstractions of eALTL formulae.
Given a concrete system M, its abstraction Mα , a property φ and its abstraction φα , we differentiate between three classes of abstract counterexamples (see
Fig. 5). Given a counterexample χα , we refer to a concrete trace χ ∈ [[M]]trace such
that χ ≡α χα as a concrete counterpart of χα . The first class (see counterexample
1 in Fig. 5) consists of the counterexamples having no concrete counterparts in
the concrete system. These counterexamples are referred to as false negatives.
The second class (see counterexample 2 in Fig. 5) consists of counterexamples
having (at least one) concrete counterpart satisfying the original property. We
further refer to this class as spurious counterexamples.
The third class (see counterexample 3 in Fig. 5) consists of the counterexamples having at least one counterpart in the concrete system; moreover all concrete
counterparts violate the concrete property. Counterexamples from this class are
referred to as ideal counterexamples.
Μα
Μ
2
3
1
¬φ
¬φ α
Fig. 5. Classification of counterexamples
Definition 14. Let χα be a counterexample obtained by verifying an abstraction
φα of a property φ on the abstraction Mα of a system M w.r.t. the homomorphism h. We distinguish the following three cases:
Bug Hunting with False Negatives
0
0
? in( x)
? in( x)
1
1
( x ≥ 2) >!out ( x)
( x < 2) >!out (0)
107
( x = c) ∨ ( x = d )
>!out ( x)
( x = a ) ∨ ( x = b) ∨
( x = c) >!out (b)
2
2
S
Sα
Fig. 6. Concrete and Abstracted Specifications from Example 15
1. We call χα a false negative, if there is no χ ∈ [[M]]trace such that χ ≡α χα .
2. We call χα a spurious counterexample if there exists χ ∈ [[M]]trace such that
χ ≡α χα and χ |= φ.
3. Otherwise, we call χα an ideal counterexample.
Contracting abstractions may lead to spurious counterexamples. The following
example illustrates this case.
Example 15. Let S in Fig. 6 be the specification of a concrete system. We abstract Z into Zα = {a, b, c, d} where a stands for the numbers from (−∞, −3);
b stands for the numbers from [−3, 0]; c stands for the numbers from (0, 3]; and
d stands for the numbers from (3, +∞). By applying this abstraction to S we
obtain S α (see Fig. 6).
Consider the property φ = ♦({out(x) | (x ≥ 2)}). We compute the contracting
abstraction of φ as follows:
φ = ♦({out(x) | (x ≥ 2)})
φα = ♦({out(xα ) | ∀x : hd (x) = xα → (x ≥ 2)})
= ♦(out(d))
Verifying φα on S α we may obtain the trace in(c).out(c) as a counterexample,
because it is a trace in S α , but does not satisfy φ. However, the concrete trace
in(2).out(2) corresponding to the abstract counterexample satisfies ♦(out(x) ∧
(x ≥ 2)). Hence, ¬φα is not precise enough.
Such spurious counterexamples are problematic for tracking real bugs. Therefore,
we will use precise abstractions, in order to avoid spurious counterexamples. A
contracting abstraction can be made precise, by fitting the abstraction to the
predicates in the specification and the formula:
Example 16. Let S in Fig. 7 be the specification of a concrete system. We abstract Z into Zα = {a, b, c, d} where the interpretation of a and b remains the
same as in Example 15 while c represents the numbers from the interval (0, 2)
and d represents those from [2, +∞). By applying this abstraction to S we obtain
S α (see Fig. 7).
108
J. Calamé et al.
0
0
? in( x)
? in( x)
1
1
( x ≥ 2) >!out ( x)
( x < 2) >!out (0)
( x = a ) ∨ ( x = b) ∨
( x = d ) >!out ( x)
( x = c) >!out (b)
2
2
S
Sα
Fig. 7. Concrete and Abstracted Specifications from Example 16
Consider again the property φ = ♦({out(x) | (x ≥ 2)}) and its abstraction
φα = ♦(out(d)). Verifying φα on S α we may obtain the following counterexamples: in(a).out(b), in(b).out(b), and in(c).out(b). In this example it is straightforward to see that any concretization of these traces is a counterexample for φ.
So in this case, the abstraction is precise.
5
Bug Hunting with False Negatives
Counterexamples that are false negatives still have a value for detecting bugs
in specifications. By relaxing them, i.e. making them even more abstract, false
negatives cover a larger part of the system, which can contain bugs. In this
manner, they can serve as a starting point for bug hunting.
In this section, we provide an overview of our framework for bug hunting with
false negatives. This process comprises the following steps:
1. Specify a requirement as a formula φ of eALTL.
2. Choose and apply a data abstraction, which is consistent with φ, to the
specification of the concrete system and to the concrete property.
3. Abstract counterexamples for the property are (automatically) determined
using model checking.
4. Generalize the false negative further by relaxing actions, which are not directly relevant for our search. This results in a violation pattern. The relaxing
process itself is automatic, only the counterexample and the set of directly
relevant actions have to be given as input to the algorithm (see Alg. 1).
5. The concrete counterexamples are automatically computed by finding the
intersection of the original system and the violation pattern.
Since the first three steps of the framework can be handled by existing data
abstraction and model checking techniques, our contribution concerns the steps 4
and 5 of the framework.
5.1
Constructing a Violation Pattern
A counterexample that we obtain in case the property is violated on our abstract
model is an infinite trace of the form βp βsω where βp is a finite prefix and βsω is
a cyclic suffix with a finite cycle base βs .
Bug Hunting with False Negatives
a
0
a
1
set(k+)
tick
2
3
tick
tick
4
5
b
7
set(k+)
8
tick
6
d
109
10
tick
9
Fig. 8. A concrete counterexample
set(k+)
0
a
set(k+)
tick
1
b
2
a
tick
3
d
Fig. 9. The violation pattern for the counterexample
Although the counterexample χα may have no counterpart in the concrete
system, it can contain a clue about a counterexample present in the concrete
system. Therefore we transform a counterexample χα into a violation pattern V,
considering only infinite counterexamples.
A violation pattern is an LTS that accepts all traces hitting a distinguished
cyclic state infinitely often. The violation pattern accepts only traces which are
similar to the counterexample and violate the abstract property. The actions
mentioned in the property are essential for the property violation. Therefore
we keep this information in the violation pattern. For actions influenced by the
abstraction, the order and the number of actions in a similar trace may differ from
those of the counterexample. We will now first illustrate the idea of similarity
on a simple example and then generalize it.
Example 17. Let us come back to the example from the introduction. Assume
that we model-check the property (a → ♦b) and obtain the abstract counterexample a.set(k + ).tick 3 .b.(a.set(k + ).tick 2 .d)ω (see Fig. 8). The k + is in this
case an abstraction of a timer: The original value of the timer is preserved up to
k; any value above k is abstracted to the constant value k + . To guarantee that
the property is violated by any trace accepted by the pattern, we keep at least
the actions a and b, because they are mentioned in the property (see Fig. 9).
Since we are searching for similar traces with an infinite cyclic suffix βs , we may
also decide to keep information about some actions of this cycle. Here we also
provide the action step d in the cycle (see Fig. 9). The actions tick and set(k + )
are not mentioned in the property and are definitely influenced by the timer
abstraction. Therefore, we relax these actions, meaning, we allow these actions
to occur an arbitrary number of times in an arbitrary order (see states 1 and 3
of the violation pattern in Fig. 9).
We refer to the set of action labels that we do not want to relax by Lab keep .
This set includes at least all the labels mentioned in the abstract (and also the
concrete) property. In the violation pattern, we distinguish a cyclic state which
110
J. Calamé et al.
corresponds to the first state in the cyclic suffix. The last action in the cycle
base of an infinite counterexample leads to this cyclic state.
Ideally, we would like to relax more actions influenced by data abstraction.
These actions can be found by applying static analysis techniques. The more
actions we keep, the more concrete the counterexample is and the faster we can
check whether there is a concrete trace matching the pattern. By keeping too
many actions, however, we might end up with a violation pattern that specifies
traces having no counterparts in the concrete system.
α
Definition 18 (Non-relaxed Actions). Given a set Act φ of actions appearing in a property φα , we define that some set Lab keep of non-relaxed actions in
α
a violation pattern is consistent if and only if Lab keep ⊇ Act φ .
Lab keep can optionally contain additional actions, like the last action of a cyclic
suffix, or actions not influenced by the data abstraction, to make the violation
pattern more specific.
Definition 19 (Violation Pattern). Given an abstract counterexample χα =
βp βsω and a set Lab keep of non-relaxed actions, a violation pattern is an extended
LTS V = (Σ, Lab, Δ, σinit , σcyclic ) constructed by Algorithm 1, where σcyclic is the
cyclic state.
The set of traces visiting the cyclic state infinitely often, is further referred to
as the set [[V]]trace of accepted traces.
Given a counterexample χα = βp βsω and a set Lab keep of actions to keep,
Algorithm 1 constructs the violation pattern V. The algorithm starts with creating the initial state σinit := 0 of V and goes through βp βs . When the algorithm
encounters an action to relax, it adds a self-loop transition labeled with this
action to the current state of V. When it encounters an action to keep, it adds a
transition from the current state to the (new) next state labeled by this action
or, if the algorithm has reached the end of the cycle base, back to the cyclic
state. The first state of βs is assigned to σcyclic .
Lemma 20. Let Lab keep be consistent with φα , let χα be a counterexample for
φα , and V be a violation pattern generated from χα and Lab keep . Every trace
β α ∈ [[V]]trace satisfies: β α |= φα .
Proof Sketch. If a counterexample χα is relaxed, at least all actions from the
property’s alphabet are in Lab keep (see Def. 18), i.e. they are not relaxed. This
means, that if a trace β α is in [[V]]trace , it contains all actions from φα in the
same order as they appear in the counterexample χα .
Since we are considering next-free properties, the absolute position of the
actions in question in the particular trace is not required, to keep violating the
property φα . Preserving the cyclic state σcyclic for an infinite counterexample also
allows us to preserve the cyclicity of the infinite suffix of such a counterexample.
Bug Hunting with False Negatives
111
Algorithm 1. Build Violation Pattern
Require: χα = βp βsω , Lab keep
Ensure: V = (Σ, Lab, Δ, σinit , σcyclic )
1: σinit := 0; Σ := {σinit };
2: st := 0;
3: for all i = 1..|βp βs | do
4:
if χα [i] ∈ Lab keep then
5:
Δ := Δ ∪ {(st, χα [i], st)};
6:
fi
7:
if i = |βp | + 1 then
8:
σcyclic := {st};
9:
fi
10:
if χα [i] ∈ Lab keep ∨ i = |βp βs | then
11:
if i = |βp βs | then
12:
st := σcyclic ;
13:
else
14:
st := st + 1;
15:
fi
16:
Σ := Σ ∪ {st };
17:
Δ := Δ ∪ {(st, χα [i], st )};
18:
st := st ;
19:
fi
20: od
5.2
// trace, actions to keep
// violation pattern
// initialization
// current state st of V
// for all steps of βp βs
// add a relaxed step
// indicate the first state of the cycle
// if step to be kept or last one
// if last state in cycle base
// next state is the cyclic one
// next state is arbitrary
// add a new state,
// add the step to the new state
// proceed with the next state of V
Looking for a Concrete Counterexample
After we have constructed the violation pattern V, we check whether there is
a concrete counterexample χ = χp χω
s , such that the corresponding abstract
counterexample χα ∈ [[V]]trace .
For infinite counterexamples we need to check that some state of χs corresponds to σcyclic . We employ constraint solving [19] to find a concrete counterexample, which allows us to check this condition for infinite (but cyclic) traces,
and also for certain infinite and parameterized systems.
To find a concrete trace matching the violation pattern V, we transform the
specification of the concrete system and the violation pattern into a constraint
program and formulate a query to find such a trace. This transformation is similar
to the one described in [2]. Note that for a concrete system with an infinite state
space, it is possible that the constraint solver will not terminate. Moreover, it is
possible that the only traces that match the violation pattern are spiral traces,
not cyclic ones (i.e. we do have a loop with respect to control locations, but some
variable is infinitely growing) and we will not be able to find them.
The transformation of the specification of the concrete system into a rule
system RS is defined in Table 1. Each edge of the specification S is mapped into
a rule ← g. In the rule, g is a guard and is a user-defined constraint of the form
ˆ Var ),param(Y )). The first parameter state of the users(state(, Var ),state(,
defined constraint describes the source states corresponding to the edge in terms
of control locations of a process and valuations of process variables. The second
112
J. Calamé et al.
Table 1. From specification S to rule system RS
ROutput
RInput
→g!s(e) ˆ ∈ Edg
ˆ Var ), param(e)) ← g
s(state(, Var ), state (,
→g?s(x) ˆ ∈ Edg
ˆ Var [x→Y ] ), param(Y )) ← g
s(state(, Var ), state (,
RAssign
→gτ,x:=e ˆ ∈ Edg
ˆ Var [x→e] ), param) ← g
τ (state(, Var ), state (,
Table 2. From violation pattern V to rule system RV
(1)
(2)
σ →!s(v) σ̂ ∨ σ →?s(v) σ̂ ∨ σ →τ σ̂
σ = σcyclic
σ(state(X), C̄, β̄) ← s(state(X), state (X ), param(Y ))∧
v = α(Y ) ∧ σ̂(state(X ), C̄, [β̄, s(Y )])
σ →!s(v) σ̂ ∨ σ →?s(v) σ̂ ∨ σ →τ σ̂
σ = σcyclic
σ(state(X), C̄, β̄) ← s(state(X), state (X ), param(Y ))∧
v = α(Y ) ∧ X ∈ C̄ ∨ σ̂(state(X ), [X | C̄], [β̄, s(Y )])
parameter state describes the destination states in terms of control locations of a
process and valuations of process variables. The third parameter param contains
parameters representing input and output values. The constraint is satisfied iff
ˆ η̂),
the guard g is satisfied. This means, that there is a transition (, η) →gs(d) (,
ˆ Var ), param(Y )) ← g holds, for
if and if only the rule s(state(, Var ), state(,
some substitution Var = η, Var = η̂, Y = d that makes guard g become true.
In ROutput, the name of the constraint coincides with the event s. Note that
the values of the process variables Var remain unmodified and the output value
is represented by the parameter Y whose value is given by the expression e. In
RInput, the input leads to the substitution of the value of process variable x by
the value of the input parameter Y . In RAssign, an assignment is represented
by substituting the value of the process variable x by the valuation of expression
e. These rules have no local parameters, so the parameter structure is empty.
Transformation of the edges of V = (Σ, Lab, Δ, σinit , σcyclic ) into the rules of
the rule system RV is defined in Table 2. Here, we abbreviate (, Var ) by X
ˆ
and (, Var ) by X . Intuitively, given a step of V, a rule of RV checks whether
the concrete system may make this step. The rules also take into account the
information about the cyclic state and the data abstraction.
The rules in Table 2 transform the steps of a violation pattern into rules of the
C̄, β̄)
form: ← ξ ∧ gα ∧ ν. is a user-defined constraint of the form σ(state(X),
specifying the source state state(X) of the concrete system, the set of states,
which are possibly on a cycle, in the set C̄. This set is accumulatively constructed,
and it contains concrete candidate cyclic states that match with σcyclic in the
Bug Hunting with False Negatives
113
violation pattern. The third parameter, β̄, contains the trace that has already
been visited while examining V and will contain the end result.
state(X
), param(Y )) as
ξ is a user-defined constraint of the form s(state(X),
defined above. It represents a step on which the concrete system and the violation
pattern can potentially synchronize.
The guard gα checks whether the data parameters of the concrete action are
a concretization of the data parameters of the abstract action.
Finally, ν determines whether and how the violation pattern has to be examined further. We will explain this in more detail shortly. Simplified, ν stops the
further examination of V, if we have reached the cyclic state of V. Otherwise, it
decides that the next step in V will be taken and sets the parameters accordingly.
We will now describe the rules in more detail. Rule 1 of Table 2 transforms
steps of the violation pattern whose actual state σ is not the beginning of the
state(X
), param(Y ))
cycle base. The step specified by the constraint s(state(X),
changes the state to σ̂ in the violation pattern and to state(X ) in the concrete
), C̄, [β̄, s(Y )]) in . The
system. That is captured by the constraint σ̂(state(X
constraint is satisfied only if both the violation pattern and the concrete system
can make the specified step and the action labeling the step of the concrete
system satisfies the constraint v = α(Y ). When doing the next examination step,
C̄ is left unchanged, while the actual event s together with a concretization Y
of its parameter v, is added to the examination trace β̄.
Rule 2 transforms those steps of the violation pattern, which start from a state
corresponding to the beginning of the cycle. If the actual corresponding state in
the system is found in C̄, the state is cyclic and has already earlier been visited
during the examination. In this case, examination ends successfully. If the state
is not yet in C̄, it is potentially cyclic. In this case, the step is treated like in Rule
1, just that the actual state of the system is added to C̄. Logging potentially
cyclic states and examining the violation pattern further allows us to not only
detect obvious cycles, i.e. cycles in the system which are also immediately visible
in the violation pattern. We can also detect those cycles, where the system spirals
before entering a real cycle. In this case, the system first runs through a cycle
with respect to the location, but differing in the data part of the system state,
before finally returning to a previously visited state. In such a case, the cyclic
state of the violation pattern is visited more than once.
The rule system RV , together with the rule system RS , forms the constraint
program. In order to check whether we can find a concrete counterexample
matching the violation pattern, we transform the pair of the initial state of
the violation pattern and the initial state of the concrete system into the query
init ), [], []) (initial state without any potentially cyclic states
qinit := σinit (state(X
and without action steps yet in the counterexample trace) and ask a constraint
solver, whether it finds a solution in the constraint program formed by RS and
RV . If yes, it provides us a counterexample as a list of actions and violation
pattern states, which has been collected over the examination of V. If constraint
solving does not find a solution, we cannot give a conclusive answer and have
114
J. Calamé et al.
to use e.g. abstraction refinement techniques to find out, whether the property
holds on the concrete system or not.
Lemma 21. If the query qinit to the rule system RV holds for some trace β,
then β ∈ [[M]]trace , and α(β) ∈ V.
Proof Sketch. Assume, that qinit holds in rule system RV for a trace β. Then,
this trace is in [[M]]trace , since the conditions for the execution of particular actions in RV are based on RS , an exact specification of the operational semantics
of the specification language as defined in Section 2.
The abstraction of the trace β, α(β), however, is in the violation pattern V.
The reason therefore is, that the rule system RV is generated from this violation
pattern and thus only reflects steps (and inductively: traces), which appear in V.
Thus, the rule system only holds for those traces β, where α(β) ∈ V.
5.3
Correctness of the Framework
In this section, we argue the correctness of the framework, which has been worked
out in the previous two subsections on the derivation of a violation pattern and
the search for further counterexamples using constraint solving.
Theorem 22. Let α = hs , ha be an abstraction consistent with eALTLproperty φ. Let LTSs M and Mα be given, such that M ⊆α Mα . Furthermore, assume that the counterexample χα ∈ [[Mα ]]trace and χα |= φα . Let V be
a violation pattern built from χα and a consistent Lab keep by the algorithm in
Fig. 1. Let β be a trace for which qinit holds, according to the constraint solving
procedure defined in Subsection 5.2. Then β is a counterexample: β ∈ [[M]]trace
and β |= φ.
Proof Sketch. By Lemma 21, β ∈ [[M]]trace and α(β) ∈ [[V]]trace . By Lemma 20,
α(β) |= φα . By Lemma 13, as α is a precise abstraction, we have β |= φ.
6
Implementation
To check the applicability of our framework we performed a number of verification experiments with μCRL specifications [14]. For constraint solving, we used
Eclipse Prolog [1].
We took a mutant of the Positive Acknowledgment Retransmission Protocol
(PAR) [25] as our case study. The usual scenario for PAR includes a sender, a
receiver, a message channel and an acknowledgment channel. The sender receives
a frame from the upper layer, i.e. from its environment, sends it to the receiver
via the message channel, the receiver delivers the frame to the upper layer and
sends a positive acknowledgment via the acknowledgment channel to the sender.
PAR depends on timers, which we have chosen too low for our experiments.
We tried to verify that for any setting of the sender timer exceeding some value
k, all messages sent by the upper layer to the sender are eventually received by
the upper layer from the receiver. To prove that the property holds for any setting
Bug Hunting with False Negatives
115
of the sender timer exceeding k, we applied the timer abstraction described in
Section 1 to the sender timer. The property was not satisfied on the abstract
system (since the k we took was less than the sum of the channel delays) and
we obtained a counterexample.
The abstract counterexample was not reproducible on the concrete system,
since the number of tick steps from a setting of the sender timer till its expiration varied along the trace due to the use of the abstraction. We transformed the
counterexample into a violation pattern by relaxing the actions on the sender
timer as influenced by the abstraction. The specification of the system was transformed from μCRL into a set of Prolog constraint rules, while the violation pattern was immediately formulated as a set of Prolog rules according to our theory
(Def. 18, 19 and Fig. 9). The constraint solver was then able to find a concrete
counterexample for our property.
7
Conclusion
We proposed a novel framework for interpreting negative verification results
obtained with the help of data abstractions. Existing approaches to handling
abstract counterexamples try to find an exact counterpart of the counterexample
(e.g. [21]). When no concrete counterpart can be found, data abstraction is
considered to be not fine enough and abstraction refinement is applied (e.g. [4]).
In our framework we look for useful information in false negatives, combining the two formal methods model checking and constraint solving. Given a
specification of a system and a property (formulated as an eALTL formula), we
first choose and apply data abstraction to both of them and then verify the abstract property on the abstract system. If the verification results in a violation
of the abstract property and the obtained counterexample has no counterpart in
the concrete system, we transform the counterexample into a violation pattern,
which is further used to guide the search for concrete counterexamples.
The framework allows to handle counterexamples obtained when verifying
safety properties, but also counterexamples for liveness properties. Moreover,
the framework can be applied for searching concrete counterexamples in parameterized and infinite state systems. Success is not always guaranteed – the
violation pattern can be too strict, concrete counterexamples can have a spiral
form (i.e. a loop in the specification, that does not lead back to a state fully
identical to its starting state), or there could be no counterexample at all since
the property just holds on the concrete system. Still, our approach can help in
finding counterexamples in those cases when a data abstraction influences the
order and the number of some actions, e.g. as timer and counter abstractions
do. Even though, we defined the framework for homomorphistic abstractions in
this paper, it seems to be possible to generalize abstraction and refinement on
the basis of Galois-connections and so define a framework for bughunting with
false negatives based on abstract interpretation.
The approach to the generation of a violation pattern leaves a certain freedom
in the sense that the set of actions to relax can be more/less restrictive. Tuning
116
J. Calamé et al.
the violation pattern or using the expertise of system developers to pick an
appropriate set of actions to relax can be potentially less costly than repeating
the abstraction/refinement cycle immediately. More case studies comparing both
approaches and trying their combinations are still needed.
References
1. Brisset, P., et al.: ECLIPSe Constraint Library Manual, version 5.9 edn. (May
2006) http://eclipse.crosscoreop.com/eclipse/doc/libman.pdf
2. Calamé, J.R., Ioustinova, N., v.d. Pol, J.C.: Towards Automatic Generation of Parameterized Test Cases from Abstractions. Technical Report SEN-E0602, Centrum
voor Wiskunde en Informatica (March 2006) (To appear in ENTCS)
3. Chaki, S., Clarke, E., Grumberg, O., Ouaknine, J., Sharygina, N., Touili, T.,
Veith, H.: State/Event Software Verification for Branching-Time Specifications.
In: Romijn, J.M.T., Smith, G.P., van de Pol, J. (eds.) IFM 2005. LNCS, vol. 3771,
pp. 53–69. Springer, Heidelberg (2005)
4. Clarke, E.M., Grumberg, O., Jha, S., Lu, Y., Veith, H.: Counterexample-guided
Abstraction Refinement for Symbolic Model Checking. Journ. of the ACM 50(5),
752–794 (2003)
5. Clarke, E.M., Grumberg, O., Long, D.E.: Model Checking and Abstraction. ACM
Transactions on Programming Languages and Systems 16(5), 1512–1542 (1994) A
preliminary version appeared in the Proc. of the POPL’92
6. Cousot, P., Cousot, R.: Abstract Interpretation: A Unified Lattice Model for Static
Analysis of Programs by Construction or Approximation of Fixpoints. In: Proc. of
the 4th ACM SIGACT-SIGPLAN Symp. on Principles of programming languages
(POPL’77), pp. 238–252. ACM Press, New York (1977)
7. Dams, D.: Abstract Interpretation and Partition Refinement for Model Checking.
PhD dissertation, Eindhoven University of Technology (July 1996)
8. Dams, D., Gerth, R.: The Bounded Retransmission Protocol Revisited. Electronic
Notes in Theoretical Computer Science 9, 26 (1999)
9. Dams, D., Gerth, R., Grumberg, O.: Abstract Interpretation of Reactive Systems.
ACM Transactions on Programming Languages and Systems (TOPLAS) 19(2),
253–291 (1997)
10. Das, S., Dill, D.L.: Counter-Example Based Predicate Discovery in Predicate Abstraction. In: FMCAD, pp. 19–32 (2002)
11. Dwyer, M.B., Avrunin, G.S., Corbett, J.C.: Patterns in Property Specifications for
Finite-state Verification. In: Proc. of the 21st Intl. Conf. on Software Engineering,
pp. 411–420. IEEE Computer Society Press, Los Alamitos (1999)
12. Giannakopoulou, D.: Model Checking for Concurrent Software Architectures. PhD
thesis, Imperial College of Science Techn. and Med., Univ. of London (March 1999)
13. Graf, S., Saïdi, H.: Construction of Abstract State Graphs with PVS. In: Proc. of
the 9th Intl. Conf. on Computer-Aided Verification, pp. 72–83 (1997)
14. Groote, J.F., Ponse, A.: The Syntax and Semantics of μCRL. In: Ponse, A., Verhoef, C., van Vlijmen, S. (eds.) Algebra of Communicating Processes. Workshops
in Computing, pp. 26–62. Springer, Heidelberg (1994)
15. Grumberg, O., Lerda, F., Strichman, O., Theobald, M.: Proof-guided
Underapproximation-Widening for Multi-Process Systems. In: Proc. of the Ann.
Symp. on Principles of Programming Languages, pp. 122–131 (2005)
Bug Hunting with False Negatives
117
16. Kesten, Y., Pnueli, A.: Control and Data Abstraction: The Cornerstones of Practical Formal Verification. Intl. Journ. on Software Tools for Technology Transfer 2(4),
328–342 (2000)
17. Lakhnech, Y., Bensalem, S., Berezin, S., Owre, S.: Incremental Verification by Abstraction. In: Proc. of the Intl. Conf. on Tools and Algorithms for the Construction
and Analysis of Systems, pp. 98–112 (2001)
18. Loiseaux, C., Graf, S., Sifakis, J., Bouajjani, A., Bensalem, S.: Property Preserving
Abstractions for the Verification of Concurrent Systems. Formal Methods in System
Design 6(1), 11–44 (1995)
19. Marriott, K., Stuckey, P.J.: Programming with Constraints – An Introduction. MIT
Press, Cambridge (1998)
20. Pace, G., Halbwachs, N., Raymond, P.: Counter-example Generation in Symbolic
Abstract Model-Checking. Intl. Journ. on Software Tools for Technology Transfer 5(2), 158–164 (2004)
21. Pasareanu, C.S., Dwyer, M.B., Visser, W.: Finding Feasible Counter-examples
when Model Checking Abstracted Java Programs. In: Proc. of the Intl. Conf. on
Tools and Algorithms for the Construction and Analysis of Systems, pp. 284–298
(2001)
22. Pasareanu, C.S., Pelánek, R., Visser, W.: Concrete Model Checking with Abstract
Matching and Refinement. In: Proc. of the Intl. Conf. on Computer-Aided Verification, pp. 52–66 (2005)
23. v.d. Pol, J.C., Espada, M.A.V.: Modal Abstractions in μCRL. In: Rattray, C.,
Maharaj, S., Shankland, C. (eds.) AMAST 2004. LNCS, vol. 3116, Springer, Heidelberg (2004)
24. Rusu, V., du Bousquet, L., Jéron, T.: An Approach to Symbolic Test Generation.
In: Grieskamp, W., Santen, T., Stoddart, B. (eds.) IFM 2000. LNCS, vol. 1945,
pp. 338–357. Springer, Heidelberg (2000)
25. Tanenbaum, A.S.: Computer Networks. Prentice Hall International, Englewood
Cliffs (1981)
Behavioural Specifications from Class Models
Alessandra Cavarra and James Welch
Oxford University Computing Laboratory
Wolfson Building, Parks Road, Oxford OX1 3QD UK
Abstract. This paper illustrates a technique to automatically derive
intra-object behaviours (in the form of state diagrams) from an object
model. We demonstrate how we may take specifications, written in a
restricted language of pre- and postconditions, and generate protocols of
usage that represent possible behaviours of the generated program. We
discuss how to use these state diagrams to analyse the specification for
errors, and how to produce correct abstractions to show a particular class
of properties of a system. This approach proves successful and scalable for
specific domains of application such as database systems and e-commerce
websites.
1
Introduction
Techniques for automatically generating programmes from their specifications
has been a goal of research in software engineering for many years. Techniques
such as automatic programming [12,15,16] met with limited success, but the
growth of model-driven development has led to a renewed effort, most notably
in the form of Model Driven Architecture (MDA)[11].
Much of this work has been on the static properties of programs—in the
conversion of the structure of the specification into an equivalent structure in
the program code. In particular, the class diagrams of the Unified Modeling
Language (UML)[14] are commonly translated into Java class ‘stubs’, where
default create, read, update and destroy methods can be created, but further
functionality is typically required to be added manually by the programmer.
In general, dynamic properties of the system are much harder than static
properties to translate into code, not least because algorithmic code is often
difficult to express using specification languages such as UML, since a suitable
abstraction is harder to find. The wide variety of ways in which dynamic properties may be expressed (states, events, interactions, use cases, etc.) is also a
hindrance—the interaction between types of specification is not clearly defined
and detailed specifications prove hard to consistently refine.
A typical specification or requirements document is expressed in many ways—
for example domain artifacts in a class diagram, business rules in terms of invariants, pre- and postconditions, and protocols in terms of state and sequence
diagrams. Whilst each individual part of the specification may be validated independently, the interaction between parts of the specification is less easily understood and harder to reason about. This also leads to the problem of requirements
traceability.
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 118–137, 2007.
c Springer-Verlag Berlin Heidelberg 2007
Behavioural Specifications from Class Models
119
When generating systems in such a manner, we must test their functionality by
testing the resulting application, validating the functionality of the system with
respect to the intended functionality. However, exhaustive testing is infeasible,
and so a more logical solution is to validate the correctness of the specification,
on the assumption that the system functionality is correctly refined from the
specification.
For some predicate P or sequence of transitions S , we may like to ask the
following questions of our specification:
– Is it possible that a state satisfying P might occur during the operation of
the system?
– Is it possible that S may be performed?
– Is it S the only sequence of transactions that may occur?
Moreover, we may wish to enforce these conditions: P must never hold of any
state of the system; S must be an allowed sequence; S must never be allowed to
happen; S must be the only sequence of transactions that may occur. In many
cases, as discussed in [4], such properties may not be expressed explicitly in
terms of invariants, since to do so would make the specification too restrictive
for use in real-life.
In previous works [2,5,4] we have introduced Booster, a domain-specific language for specifying information-driven systems. The language is an integrated
formal specification language, based upon object-oriented constructs, and defines
functionality in a declarative style—in terms of pre- and post-conditions. Whilst
the correctness of each method individually may be determined, it is harder to
prove that a system comprising of these methods is correct.
In this paper, we provide a solution to this problem in a domain-specific setting, by automatically generating protocols for usage. These allow us to “step
through” the proposed system, checking for allowable states, and validating sequences of transactions.
Whilst the ideas presented here are specific to the Booster language, they may
be usefully adapted for a more generic class of specification, although automation
may not always be possible. In particular, these ideas can be applied to systems
specified using UML class diagrams annotated with constraints written in a
restricted version of the Object Constraint Language. However, as described in
[4], the Object Constraint Language is in some ways less expressive Booster as
it lacks the ability to compose method specifications.
We start this paper by introducing the Unified Modeling Language—in particular the notions of Class and State Diagrams. Next we give an overview of
the key features of the Booster language, and compare it with the UML. In section 4 we discuss the process of automatically generating workflows from Booster
specifications; in section 5 we illustrate this theory with an example, showing
how the technique can be useful. The paper concludes with a brief discussion of
the validity of this work and how the process may be applied with more general
specifications, an orientation of this work amongst recent related work, and a
discussion of future research goals in this area.
120
2
A. Cavarra and J. Welch
UML
The Unified Modeling Language [14] has gained popularity in the last decade and
is now widely used in industry, despite a number of continuing challenges (most
notably the lack of a universally-accepted precise semantics). UML contains a
vast set of notations to describe the structure and the dynamics of a software
system. The language is composed of two different categories of diagrams representing the two views of a system: the static view, modeling information that
does not evolve with time, and the dynamic view, where the evolution of the
components of the system is shown.
However, most of the notation provided by UML is actually seldom adopted
in practice, while the parts that are mainly used are those that were already well
established before the advent of UML: class, state, and sequence diagrams. For
the purpose of this work we concentrate on class and state diagrams.
2.1
Class Diagrams and OCL
Class diagrams provide a static structural view of the system; they depict the
classes of the system, their inter-relationships, and the operations and attributes
of the classes.
The application concepts are modelled in UML as classes, each of which describes a set of objects that hold information and communicate to implement a
behaviour. The information they hold is modelled as attributes; the behaviour
they perform is modelled as operations. Structural relationships between objects
of different classes are represented by associations. The definition of associations
may be enhanced by a name, role names and cardinality (multiplicity).
Class diagrams can be annotated with constraints written using the Object
Constraint Language [17]. OCL is a declarative language for describing rules
that apply to UML models; it allows the definition of invariants on classes and
sets of associated classes, and pre- and postconditions on classes’ operations.
In previous work [4] we have discussed the differences between the UML and
Booster, and described how techniques in Booster may be usefully applied to
models in the UML and OCL.
2.2
State Diagrams
UML state diagrams are a variation of Harel’s statecharts [8]. They focus on the
event-ordered behaviour of an object. A state diagram shows the event triggered
flow of control due to transitions which lead from state to state, i.e. it describes
the possible sequences of states and actions through which a model element can
go during its lifetime as a result of reacting to discrete events.
In UML 2.0 in addition to expressing the behaviour of a part of the system,
state diagrams can also be used to express the usage protocol of part of a system.
These kinds of state diagrams are referred to as behavioural state diagrams and
protocol state diagrams ( PSD - introduced in UML 2.0) respectively. A PSD
specifies which operations of the class can be called in which state and under
Behavioural Specifications from Class Models
121
which condition, thus specifying the allowed call sequences on the operations of
the class. A protocol state machine presents the possible and permitted transitions on the instances of a class, together with the operations that carry the
transitions. A protocol transition specifies a legal transition for an operation.
Transitions of protocol state machines have the following information: a precondition, a trigger, and a postcondition. The protocol transition specifies that the
associated operation can be called for an instance in the origin state under the
initial condition, and that at the end of the transition, the destination state will
be reached under the final condition (post).
3
The Booster Language
The Booster notation, first described in [2], combines key features of three earlier
formal methods—the Z notation, the B method, and the Refinement Calculus—
with the aim of automatically generating software components whose design is:
– transformational —the intended effect of an operation can be described in
terms of values of inputs, outputs, and attributes immediately before, and
immediately after, the operation has been performed.
– sequential —at most one operation may be acting upon the data within the
component at any one time; the current operation must finish reading or
updating the data before the next can begin.
In particular, this encompasses components based upon an object database,
accessed through transactions and queries.
Specifications are structured in an object-based style—using classes, associations and inheritance. On each class attributes may be defined, which may be
of primitive type or may define end-points for associations. Invariants may be
defined in the scope of a class, but their effect may extend to associated classes.
Methods are defined on each class to update the attributes of the current class
and also any associated classes. Such methods are defined declaratively in terms
of pre- and postconditions. Preconditions may be any arbitrary predicate defined
in terms of the state of input values and attribute values before the execution of
the method.
Postconditions are more restricted however, and are limited to the syntax
provided in Fig. 1.
A postcondition is a series of conjuncts, separated by the symbol ‘&’. A conjunct may be an implication, a universal quantification, or a primitive postcondition. The antecedent of an implication is an arbitrary predicate, interpreted
as a constraint upon the values of attributes before the operation is performed.
The consequent of an implication is a conjunction of primitives. The range of a
universal quantification is a collection of objects of the same class, constrained
by the antecedent of an implication. A primitive postcondition is an assertion
of equality between a variable and an expression, of set membership, or of its
negation.
122
A. Cavarra and J. Welch
postcondition ::=
conjunct | conjunct “ & ” postcondition
conjunct ::=
implication | forall | primitive
implication ::=
antecedent “ => ” consequent
forall ::=
“ forall( ” class “ ). ” implication
consequent ::=
primitive | primitive “ & ” consequent
primitive ::=
variable “ = ” expression |
expression “ : ” variable |
expression “ /: ” variable
Fig. 1. Syntax of postconditions in Booster
We may also create new methods from existing specifications. For example,
given methods M1 and M2 we may create a new method M1 AND M2 which has
the effect of schema conjunction from Z—the new method has the effect of
calling both M1 and M2 at the same time. Similarly we may use OR for schema
disjunction, THEN for sequential composition, and ALL which has the effect of an
iterated conjunction. Compound methods may be expanded to form primitive
methods; for example M1 AND M2 has a precondition that is the conjunction of
the individual preconditions, postconditions are similarly conjoined. There are
restrictions upon the use of AND to ensure preconditions are not automatically
false; this is explained in [5].
The restriction imposed upon postconditions is powerful in that we may reason about methods without having to concern ourselves with non-determinism
and algorithmic detail. We may automatically generate applications from specifications written in the Booster language; this is a two phase process. The first
stage is that of expansion, where a specification is automatically transformed into
an equivalent specification, also written in the Booster language. This expansion
includes:
–
–
–
–
–
Providing specifications for “default methods” such as Create and Destroy;
Inheritance hierarchies are flattened[3];
Compound methods are reduced to primitive methods[5]
Adding scoping information for attributes;
Inferring types and adding preconditions to ensure the type-correctness of
all reference and input values;
– Automatically maintaining association invariants[18];
– Automatically guarding against breaking other invariants[4]
Behavioural Specifications from Class Models
123
This expansion allows the programmer to specify only the intended effect of a
method. Any consequences implied by the rest of the model will be automatically
included, and if the intention of the method is impossible in the context of the
model a false precondition will always be generated.
The second phase takes the expanded specification and produces imperative
code—this stage has been explained in [5] and [3]. Method specifications are
compiled into sequential transactions; two methods cannot update the same piece
of data at the same time. These transactions are “atomic” - they are assumed
to occur instantaneously and model states during execution are not of interest.
Preconditions are translated into guards for the transaction; a transaction cannot be called if its guard evaluates to false. Postconditions are translated into
independent substitutions upon attribute values; the execution of all substitutions is guaranteed to terminate in a state satisfying the postcondition, changing
only the values mentioned in the postcondition.
An extract from an example Booster specification is shown in Fig. 2. This
describes a class of Reader objects—people who are registered on a system for
registering library borrowing. A Reader object has values for his name (of type
String), and for his age (a natural number). The next attribute denotes an association between the classes Reader and Library—a Reader may belong to
a number of libraries. The association is bi-directional—there is an attribute
Readers in the class Library—whenever Reader.Libraries is updated then
Library.Readers must be too, and vice-versa. Similarly, the final attribute denotes an association between Reader and Book. The definition of these other
classes will be given later in the paper.
CLASS Reader
ATTRIBUTES
Name : STRING
Age : NAT
Libraries : SET(Library.Readers)
Books : SET(Book.Reader)
METHODS
Create,
Destroy,
Borrow( Book_in.Library : Libraries
| Book_in : Books)
Fig. 2. An example of a class in Booster
There are three methods defined on the Reader class: Create and Destroy,
which are both to be given default implementations, and Borrow, which associates a new Book with this reader. The precondition ensures that the reader is
a member of the same library as the book (an input-value); the postcondition
states that the new book is a member of the set of books that this reader has
borrowed.
124
A. Cavarra and J. Welch
This information could have been presented in the UML, although, as explained in [4], the Booster language is more appropriate for our purposes. The
language is more restricted, less verbose, and allows us to form new methods by
combining existing specifications, something currently not possible in the OCL.
However the work presented in this paper could equally be done using a subset
of the UML and OCL, with the same refinement semantics that is provided in
Booster.
4
The Generation of State Diagrams
Given a specification in Booster, consisting of classes, attributes and methods
with pre- and postconditions, we would like to be able to explore the dynamic
properties inherent in the model. In particular this paper addresses those of
state and usage protocols—we generate a UML protocol state diagram—and
from this we can validate some dynamic properties of our models. From the state
machine we can find out whether a particular state is allowed by our system, and
which sequence of transactions will achieve that state. We can decide whether
a sequence of transactions is allowed by our intended system, or whether some
sequence of transactions is the only allowed interaction. Moreover, just viewing
a state machine for a system can give us a better idea of its functionality and we
may gain insight into how the system may be used. In this section, we describe
how this can be achieved and in Section 5 we illustrate the application of this
technique.
4.1
Abstraction
When generating a state machine we must first consider which parts of the
system we are interested in. Generating the entire state machine for a system of
classes will be computationally expensive, in that there may be many states and
transitions to consider. Additionally, such a state machine would be difficult to
view or to manually reason about.
Instead, we must generate a sub-graph of the entire state machine—an abstraction that represents particular properties—and we begin this process by
choosing a particular subset of state that we are interested in. We must choose a
particular subset of attributes that are relevant to the dynamic properties that
we wish to validate—the smallest such subset will create the smallest possible
state chart.
Additionally, where attributes may take on a large number of values (e.g.
attributes of natural number type, or set-valued attributes), we must restrict the
states of these attributes to a smaller number that represents values that we are
interested in. For example, we may restrict our interest in a particular attribute,
that is of type natural number, to the values {0, 1, 2, > 2}. Here we consider
states in which the attribute takes the values 0, 1, 2 or any natural number
greater than 2. The abstraction must not restrict the values of the attribute, but
provide a state for every possible value. Such restrictions are usually intuitive
Behavioural Specifications from Class Models
125
from the validation we are interested in; as with all automatic processes it is easy
to adjust the restrictions and re-generate the state machine if the restrictions
are too weak or too strong.
This abstraction process may be automated by considering the semantics
of the property we are interested in, however in general further abstraction is
necessary since some system state, initial conditions and input variable may need
choosing according to an envisaged scenario.
Having reduced the number of states that we are interested in, it is now
possible to automatically reduce the number of transitions that are relevant.
Booster has a notion of a change list, similar to the frame in the refinement
calculus—denoting a set of attributes which are subject to change in the course
of a method. This change list may be specified explicitly by the modeller as
syntactic sugar, but is usually deduced from the postcondition. A postcondition
in Booster is refined into a combination of substitutions on attribute values,
each of which may be guarded. Each substitution is a simple deduction from the
postcondition, and the attribute on the left-hand-side of the substitution is part
of the change-list. For example, the postcondition:
value_in : this.att
gives rise to the substitution:
this.att := this.att ∪ value in
and we deduce that this.att is part of the change-list. From this analysis we can
calculate the change-list of every method, and restrict our transitions to those
corresponding to methods whose change-list includes part of the state that we
are interested in.
Additionally, we may wish to include those methods whose precondition includes a restriction upon any part of our chosen state, and any others which may
be of interest. We could alternatively choose to ignore certain methods which
lead to sub-sections of the state machine that are uninteresting—for example
the creation of extra objects—that may increase the size of the state machine
without adding to our understanding of the system.
Typically the state machine we are interested in will be based upon the lifecycle of an object—from its creation to its destruction. We may wish to further
restrict our interest to a particular circumstance though, and choose initial values
for the system. For example, we may wish to only consider the system after
a particular event has occurred, or after a particular state has been reached.
This additional restriction can form part of the validation, or may assist in
viewing particular behaviours of the system—especially when the generated state
machine is still large.
Other initial values are necessary for providing the state machine an environment. We might need to assume existence of other objects in the system so
that interactions may take place—we may need to make assumptions on the
attributes and associations of these objects too. For example, if we are looking
at the lifecycle of an object, and a transition causes it to be linked with another
126
A. Cavarra and J. Welch
object, we might prefer to assume that it already exists, rather than cluttering
our state machine with the creation and lifecycle of that object too.
Our example in section 5 illustrates these restriction and initialisation choices,
explains why they are important and discusses how optimal choices can be made.
4.2
Transitions
Having made assumptions about the environment for our state machine, and
made restrictions on the states and the transitions, we can now show how to
build a state machine. Initially we shall consider a particular state and explain
how transitions may be created from methods to leave this state. In the next
subsection we discuss how new states may be created so that an entire graph
may be constructed.
We analyse the precondition in the context of the current subset of state—this
state includes the attributes we have singled out as in our scope of interest, the
values assigned to any input values this method may require, and the state of
any objects that we have made assumptions about previously. We may attempt
to evaluate a precondition in this state and we get three possibilities:
– the precondition is a restriction upon the part of the state we know nothing
about;
– the precondition is partly a restriction upon the state we do know about,
but based upon a part of the state that is outside our scope of interest;
– or that the precondition may be entirely evaluated (to either true or false)
based upon the current subset of state.
In the first situation, we have a method which is only applicable in conditions
which are outside our scope of interest. However, its effect may be within our
scope of interest so it still must be considered. There is a transition corresponding
to this state but it is annotated with a precondition—this precondition corresponds to the entire precondition of the method. Our experience shows that this
kind of transition is rare—generally a precondition for a method provides conditions to ensure that the effect is achievable and so some parts of the precondition
can be evaluated, as in the next case.
In the second case, we have a method whose precondition may be partially
evaluated in the current subset of state. By lazy evaluation we can determine
whether such a precondition is guaranteed to be true, false, or still indeterminable. If the precondition is still indeterminable, we create a transition between this state and the next, and add a precondition to the transition, asserting
that the parts of the precondition that cannot be evaluated hold true. If the precondition is evaluable, and is either true or false, then we may proceed as for
the next case.
In the final case, we have a method whose precondition either evaluates to
true or false. With the latter, this method is never applicable in the current
state and so no transition corresponds to it from this state. In the former, we
create a transition from this state to the next, which corresponds to this method.
There may be a precondition on this transition though, which corresponds with
Behavioural Specifications from Class Models
127
restrictions to input variables, assumptions about objects in our environment,
and parts of the state which fall outside our area of scope.
We choose to ignore those methods that only manipulate the state of other
objects in the system—those that are in our environment. This is because we
only care about the other objects when they become part of the current scope—
before this time their interactions and updates are uninteresting.
4.3
States
When we create a state machine we expect the modeller to provide some initial
conditions—in particular the initial state from which we begin generation. Alternatively, when considering the life-cycle of an object, we may wish to start in an
initial pseudo-state such as those defined in the UML, where the first transition
is always the Create method.
From the first state we find all the transitions that are possible, as described
above. These may have preconditions attached to them, that restrict their operation in certain states outside our scope of interest. Each transition corresponds
to a method in the system, and it is from the method that we construct the next
state. Since every postcondition in Booster can be translated into a collection
of substitutions, we can evaluate each in the context of the current state, any
inputs, our assumed environment, and the fact that the precondition is true.
Such substitutions may either alter the value of an attribute we are interested
in, or it may leave it unchanged. Since new values may be entirely determined,
we can calculate the new state of the system. This may be a new state, unseen by
us in the course of this generation, or it may be a state we have already seen—
perhaps even the current state—in which case the transition takes us back to
that state.
In some cases the new value in the substitution may be indeterminable, because the expression uses attributes outside the scope of interest. In this case we
have three options available to us:
– add transitions leading to every feasible state in the diagram—states in which
the other attributes correspond to the correct substitution—adding the precondition that the expression evaluates to the value determined by the new
state;
– the modeller must make an assumption about the value of the new expression, and this must be factored in elsewhere in the state diagram as well;
– or the modeller must choose to increase the number of attributes in the
scope of interest, to allow the expression to be evaluated—in this case the
generation of the state-diagram must restart.
Generation of a state machine can be performed in a breadth-first or depthfirst manner, depending on the type of validation required.
4.4
Validation and Verification
The purpose of creating a state machine may vary—typically it will be to verify
some dynamic property of the specified system, although they may also be helpful
128
A. Cavarra and J. Welch
for customers to look at, or for the modeller to get a better idea of the system they
are building. In the first instance the verification can be performed automatically;
the type of verification required can be split into two distinct cases.
In the first case, the question asked is of the form: “What sequence of events
leads to the system state satisfying a particular predicate?”. This is a reachability
problem –we are looking for one or more states that satisfy a particular condition
and we can evaluate each state as we generate it. We can present each sequence
that starts in an initial state and ends in a state satisfying the condition.
In the second case, we answer questions of the form: “Is this particular sequence of transactions S allowed to occur in the generated system?”. S may also
include splitting and joining, and so may be a state diagram itself. Therefore the
problem may be solved by deciding whether S is a sub-graph of the generated
state machine G. The states of S must be a subset of the states of G, and for
any transition between states s1 and s2 there must be the equivalent transition
in G. Any preconditions on the generated transitions must be examined by the
modeller—to decide whether the abstraction is appropriate.
For a particular sequence of transactions, or protocol of usage S we can ensure:
– that S is available during the operation of the system;
– that S is the only sequence of states available;
– or that S is never allowed to happen during the operation of the system.
We can achieve these in obvious ways—by changing the preconditions or postconditions of already defined methods such that extra conditions are enforced,
and adding extra attributes to represent the state of the system. In such modifications however, we may only strengthen preconditions and postconditions,
never weakening constraints that have already been specified by the modeller.
Of course, such guarantees are only applicable in the context of the abstraction,
and it is up to the modeller to decide whether the abstraction is sufficient.
5
A Worked Example
We now present an example to show the validity of our work. In this example we
will start with an initial system, and show how we may generate a state machine
from it to verify a particular property. We show an extract from the generated
state machine that is sufficient to show the property does not hold, and discuss
how we might change the model accordingly.
5.1
An Example Specification
The initial system is that of a library system, first introduced in [18]. Whilst just
a simple problem, it is hopefully complex enough to examine issues that apply
to the kind of systems in the application domain of Booster. The specification is
presented in Fig. 3.
In the library system there are objects representing libraries, readers and
books. A reader may be a member of any number of libraries, and as a member
Behavioural Specifications from Class Models
129
of a library is entitled to borrow books from that library. A book belongs to one
library, and may be in the possession of at most one reader at any one time.
We describe this system using three classes: Library, Reader and Book. A
Book object has many attributes, representing such details as the title, the author’s name, the publisher, the ISBN number, however these are not of interest
in this example. We consider only the attributes Library and Borrower here.
The attribute Library denotes a mandatory end to an association with the class
Library—the other end of the association is the reference attribute Books in the
class Library. The attribute Borrower is an optional (denoted by square brackets []) end of an association with the class Reader and the attribute Books—this
is an optional-to-many association.
The system also defines a many-to-many association between the classes
Library and Reader. These associations define the only attributes that we are
interested in for the purposes of this example. Similarly, we just present a certain
number of methods that are interesting for the purpose of this example–those
that manipulate these particular associations. This is a part of the abstraction
process–focusing on particular attributes for the properties we are interested in.
In Fig. 3 we present the expanded version of all methods, and for reasons
of space and clarity we’ve omitted parts of the precondition that are irrelevant
for this presentation (such as those pertaining to type checking of references or
setting of other attributes).
The first method defined on the Library class is one that adds a reader
to its membership (note that every person in this system is represented by a
Reader object). The precondition for this method is that there are still some
readers in the system that are not already members of this current library, and
that the input variable, Member_in is not already a member of the library. The
postcondition states that Member_in has this library in its set of libraries, and
that this current library has Member_in in the set of members.
As an aside, this method in Booster could have been specified simply by
specifying the intention: Member_in : Members and the expansion process would
have produced the additional pre- and postconditions, and provided scoping as
explained in section 3. The next method on the class Library, RemoveMember is
similarly defined—the method is unavailable if the input is not a current member
of the library, the effect is that both ends of the association are updated.
Class Reader has three methods that are relevant to this example. The first,
Create, is always available and simply creates a new object. The set Reader is the
extension of the class Reader, that is the set of all objects of that class. Since the
attributes Books and Libraries are not mentioned in the postcondition, they
take on default values, namely the empty set. The Destroy method is always
available, and removes every link it has with other objects and removes itself
from the extension.
Finally the class Book has two methods of interest. The first, Transfer, moves
a book from one library to another. The precondition is that there is at least
one more library in the system where it can be transferred, and that the input
Library_in is not the current location of the book. The postcondition is made
130
A. Cavarra and J. Welch
CLASS Library
ATTRIBUTES
...
Books
: SET ( Book . Library )
Members
: SET ( Reader . Libraries )
METHODS
AddMember( 0 < (Reader.card - Library_this.Members.card) &
Member_in /: Library_this.Members
| Library_this : Member_in.Libraries &
Member_in : Library_this.Members )
RemoveMember( Member_in : Library_this.Members
| Library_this /: Member_in.Libraries &
Member_in /: Library_this.Members )
CLASS Reader
ATTRIBUTES
...
Books
: SET ( Book . Borrower )
Libraries : SET ( Library . Members )
METHODS
Create( true | Reader_new : Reader)
Destroy( true
| forall (Book_each).(Book_each : Reader_this.Books
=> Reader_this /: Book_each.Borrower) &
forall (Library_each).(Library_each : Reader_this.Libraries
=> Reader_this /: Library_each.Members) &
Reader_this /: Reader )
Borrow( 0 < (Book.card - Reader_this.Books.card) &
Book_in.Borrower = {} &
Book_in.Library : Reader_this.Libraries
| Book_in.Borrower = Reader_this &
Book_in : Reader_this.Books )
CLASS Book
ATTRIBUTES
...
Borrower : [ Reader . Books ]
Library
: Library . Books
METHODS
Transfer( 2 > Library.card &
Library_in /= Book_this.Library
| Book_this /: Book_this.Library_0.Books &
Book_this : Library_in.Books &
Book_this.Library = Library_in )
Return( Book_this.Borrower /= {}
| Book_this.Borrower = {} &
Book_this /: Book_this.Borrower_0.Books)
Fig. 3. An extract from the Library System Specification in Booster
Behavioural Specifications from Class Models
131
up of three parts: that the book is removed from the Books attribute of the old
library (variables in the pre-state are denoted with _0). Secondly, the method
Return is only available when the book is loaned to a reader; its effect is to
remove the link between the current book and the reader it was loaned to.
The specification as it stands is enough to generate a system, and dynamic
properties of the generated system are inherent in the pre- and postconditions.
However to decide whether the specification is correct with respect to the dynamic properties, we must make these properties more explicit. For this example,
we are interested in the question: “Can a reader have a book on loan that does
not belong to a library he is a member of?”. This is a typical question that might
be asked of such a system. We may have decided to disallow such a scenario by
creating an invariant in the class Book:
Book_this.Borrower /= {}
=> Book_this.Borrower : Book_this.Library.Readers
However, as we described in [4], such an invariant may be too strong—for
example a reader may be banned from a library before he has returned all his
books. For the purposes of this example, we will find all the scenarios where such
a situation may occur, so we can strengthen our specification accordingly.
5.2
Generation
We begin by choosing an abstraction that is relevant to our particular problem.
In presenting this example we have already partly achieved this: we have only
presented the attributes and methods that we might be interested in.
For this example we are going to produce the state machine of the object lifecycle for the class Reader. The property we are interested in can be expressed using the attributes Reader.Books and Reader.Libraries, and the derived value
Reader.Books.Library which contains the set of all libraries that own the books
that the current reader has on loan. This uses the attribute Book.Library, which
gives three system attributes that we are interested in. We can therefore restrict
our analysis to just the methods that modify these attributes. This is exactly the
set of methods presented in Fig. 3. We assume the lack of Create and Destroy
methods for libraries and books for clarity and simplicity, however in the full
generation we would expect them to appear.
We must also make some initial assumptions about the environment in which
this Reader object is to live. We assume that there is one Book object, B1 ,
and two Library objects in scope, L1 and L2 , and these are the only other
objects in the system. This will largely decrease the state space, but hopefully
not so much that no useful information can be obtained from the state machine.
We will assume that B1 belongs to L1 . These assumptions can be modified if
the generated state machine does not show us enough information; however the
authors’ experience is that a small environment such as this is generally suitable.
When generating the state machine, we do not consider updates to these objects
unless they directly update our three attributes—these objects only become of
interest when they are accessible through association.
132
A. Cavarra and J. Welch
We can now choose an abstraction for the state, so that the generated state
machine will be small enough to view. For the attribute Reader.Libraries we
choose the set of states {{}, {L1 }, {L2 }, {...}} where {...} is any other state. We
choose the same abstraction for Reader.Books.Library and {{}, {B1 }, {...}} for
the attribute Reader.Books.
Our final configuration is that of the initial state. Since we are interested in
the object-lifecycle, we begin in the initial pseudo-state and the first transition
will always be the Create method.
An extract from the generated state machine is shown in Fig. 4. The entire
state-machine is just over twice the size of this, and can be easily viewed on a
screen, but is not suitable for presentation in this format. Properties are typically
verified automatically, so there is often no need to present the state machine in
its entirety. However the modeller can gain a better understanding of his model
by viewing the whole thing.
Reader.Create
L1.AddMember
Reader.Libraries : {L1}
Reader.Books : { }
Reader.Books.Library : { }
Reader.Libraries : { }
Reader.Books : { }
Reader.Books.Library : { }
L1.RemoveMember
Reader.Destroy
B1.Return
Reader.Libraries : {L1}
Reader.Books : {B1}
Reader.Books.Library : {L2}
[Library_in = L2]
B1.Transfer
[B1.Library = L1]
Reader_this.Borrow
Reader.Libraries : {L1}
Reader.Books : {B1}
Reader.Books.Library : {L1}
Reader.Destroy
[Member_in = Reader_this]
L1.RemoveMember
Reader.Libraries : { }
Reader.Books : {B1}
Reader.Books.Library : {L1}
Reader.Destroy
Fig. 4. An extract of the generated state machine
Behavioural Specifications from Class Models
133
Observe that the generated state machine is actually a protocol state machine
where states are labeled by the postcondition of their incoming transitions rather
than by abstract names.
The original question, “Can a reader have a book on loan that does not belong
to a library he is a member of?”, can be solved by searching for a state in which
the derived set Reader.Books.Library is not a subset of Reader.Libraries.
Automatic analysis of the generated state diagram can show that there are
two ways of reaching the specific state. The two usage protocols are:
Reader .Create → L1 .AddMember → Reader this.Borrow → B1 .Transfer
and
Reader .Create → L1 .AddMember → Reader this.Borrow → L1 .RemoveMember
Either a book may be transferred to a different library while a reader is
borrowing it (and the reader is not a member of the new library), or a library
may remove a reader before he has returned his books from that library. The
modeller may now add preconditions to the methods if they wish to prevent such
scenarios from happening.
The modeller may also look at the state machine for themselves and notice other dynamic properties that they weren’t expecting—for example that a
reader can be removed from the system (using Destroy), whilst still holding
books. This may not have been their intention and so they can add preconditions appropriately. It is the authors’ experience that this process can be helpful
before generating a system so that modelling errors can be eliminated.
The process as it stands relies a lot upon the intuition of the modeller to
provide a useful abstraction upon the attributes and their states. However, as
an automatic process, a new state machine can easily be generated if the current
one does not provide the intended answers. The examination of preconditions
on the transitions is also important—to help decide whether the state machine
is an accurate representation of what may happen in the system.
6
Discussion
In this section we discuss the implications of this work in relation to the Booster
language, Model-Driven Development, and Model-Driven Architecture. We give
an overview of related work, and discuss why our methods are novel. Finally
we provide details of our future research plans regarding Booster and software
modelling.
The practice of model-driven development is becoming increasingly popular.
A strong design and build process centered on refinement and verification can
increase the quality of software applications. Techniques for automatic refinement are slowly being developed. Such tools increase the speed of development
as well as reducing the scope for manually-introduced errors.
In Booster, the refinement process is entirely automated—this is possible by
restricting the specification language and the application domain. This restriction is not overly inhibiting though, as the application domain covers a broad
134
A. Cavarra and J. Welch
range of information systems, including database systems and e-commerce websites.
This level of automation makes the Booster language essentially a higherlevel programming language, and this becomes the artifact which is used for
correctness proofs. Such proofs ensure that the model is consistent with the
requirements of the system, as opposed to traditional proof techniques which
ensure consistency between specification and program code.
Whilst the static structure of the specification is relatively easy to verify, dynamic properties may be expressed in a wider variety of forms and so are much
harder to verify. In Booster, dynamic properties are expressed in terms of preand postconditions. Such constraints imply restrictions on usage scenarios, but
these restrictions must be made explicit in order for them to be validated against
a specification. In this paper we have shown how we may automatically translate pre- and postconditions in Booster into state machines that more explicitly
depict workflows and object-life cycles.
This is possible through the restricted nature of the Booster specification
language—that we may automatically derive state substitutions from postconditions. Such substitutions allow us to determine exactly when a method is
applicable, and what the resultant state will be. The technique is not possible where postconditions are unrestricted constraints, where the method that
satisfies them may be non-deterministic or algorithmic in nature. Booster also
ensures that methods are refined into sequential atomic transactions, where a
single piece of data cannot be updated by two methods at the same time. In
such a way the state machines generated are dependent on the actions of one
user at a time, keeping the machines simple.
This technique proves to be scalable: the state machine generation is not
affected by the number of classes in the model, but depends only on the chosen
abstraction. The abstraction techniques used here are not new—indeed they are
commonly used in model-checking to reduce the state space[1], and have also
been used in a similar context by Gupta[7].
The result of this work is that the activity of software development can be
raised to a higher level–testing can be performed at the level of specification
rather than code. The code from which the application is built is brought closer to
the abstractions of customer requirements, and so may be more easily understood
by non-experts. Indeed, the generation of state machines and the presentation of
specifications in a variety of graphic forms is a useful tool in narrowing the gap
between customers and system developers, as well as aiding the documentation
process.
6.1
Related Work
The work most closely related to ours is that of Gupta[7]. In this work the
author also takes specifications written in the form of class diagrams and preand postconditions. In this respect our work is very similar; however there are
important differences between our work and his.
Behavioural Specifications from Class Models
135
Firstly our pre- and postconditions define the complete constraints upon an
object, not just a partial restriction. Using the Booster expander, we can ensure
that all constraints take account of the whole model and do not just specify the
intended effect of the model. In this respect we do not treat classes independently,
but analyse all methods of associated classes that may change the attributes of
the current class. Such a distinction is important, since invariants generally affect
more attributes than just those of the current class—in particular association
invariants[18].
Most importantly, the restricted nature of Booster postconditions means that
instead of considering the constraints upon the after-state of a method, we can
consider the actions of the methods themselves by calculating the substitutions
that satisfy the constraints. In Gupta’s work, restrictions are necessary on the
types of predicate—they need to be in Disjunctive Normal Form—and he makes
no mention of non-determinism or partiality.
We perform a similar abstraction step to that in Gupta’s work, in order to
reduce the number of states and transitions that we need consider. However, in
our work we can make additional reductions to the number of transitions because
we know which substitutions are to take place—we can calculate exactly which
variables are to change and consider just the methods which change attributes
that we are interested in. In the more general setting, methods have no notion
of a change list and so every method must be considered at every step.
This abstraction technique is also subject to considerable research—in particular that of slicing state machines[13,20,9], and model-checking[1]. Whilst our
approach is to produce the abstraction as it is generated, an alternative method
would be to generate the whole state machine and then use the techniques in
these papers to perform the abstraction. However this would be computationally expensive, since the number of states and transitions in the complete state
machine would normally be too great to analyse automatically.
Other research has explored the relationship between object-state and dynamic behaviour, notably that of Holt et al[10] and Graham[6]. However, this
work has been focussed on testing implementations, and has been manually implemented in a wider application domain.
Other related work includes [19] where state charts are generated from sequence diagrams. These links between types of specification diagrams are useful
in allowing the modeller and customer to explore a system before it is built. Other
types of dynamic modelling with Booster is the subject of further research, as
explained below.
6.2
Further Work
Further work is centered around the ongoing research into the Booster language
and toolset—the main focus of which is the integration with the UML. We are
currently in the process of developing a UML profile—restricting the syntax of
the OCL and providing a semantics similar to that of Booster, and extending
the OCL to allow method composition. This integration will allow us to exploit
136
A. Cavarra and J. Welch
interesting existing work on UML, in particular tools, IDEs, and to appeal to
practitioners who are more familiar with the graphical notation.
In relation to the work presented here, we wish to be able to factorise the
generated state machines, by using sequential composite states. This would decrease the size of the generated diagrams and make them easier to read by the
specifier or a customer.
Another interesting area of exploration is that of validation and correction of
class models or Booster specifications against state machines. We want to allow
the users to be able to modify the generated state machines, for example by
adding preconditions or extra transitions, and see these changes automatically
reflected in the Booster model.
Such further research will increase the applicability of the work presented
here, and increase our knowledge of the relationship between static and dynamic
properties of system specifications.
References
1. Clarke, E.M., Grumberg, O., Long, D.E.: Model checking and abstraction. ACM
Trans. Program. Lang. Syst. 16(5), 1512–1542 (1994)
2. Davies, J., Crichton, C., Crichton, E., Neilson, D., Sørensen, I.H.: Formality, evolution, and model-driven software engineering. In: Mota, A., Moura, A. (eds.) Proceedings of SBMF 2004. ENTCS (2005)
3. Davies, J., Faitelson, D., Welch, J.: Domain-specific Semantics and Data Refinement of Object Models. In: Moreira, A.M., Ribeiro, L. (eds.) SBMF 2006: Brazilian
Symposium on Formal Methods, pp. 185–200 (2006)
4. Davies, J., Welch, J., Cavarra, A., Crichton, E.: On the generation of object
databases using booster. In: ICECCS ’06: Proceedings of the 11th IEEE International Conference on Engineering of Complex Computer Systems, Washington,
DC, USA, pp. 249–258. IEEE Computer Society, Los Alamitos (2006)
5. Faitelson, D., Welch, J., Davies, J.: From predicates to programs: the semantics of
a method language. Electronic Notes in Theoretical Computer Science (to appear
2006)
6. Graham, I.: Graham/SOMA (Semantic Object Modeling Approach) method, pp.
73–83. Wiley-QED Publishing, Somerset, NJ (1994)
7. Gupta, A.: Automated Object’s Statechart Generation from Class Method Contract. In: Proceedings of the 3rd Workshop on Model design and Validation
(MoDeV2a’06): Perspectives on Integrating MDA and V&V, Genoa, Italy, October
2006, ACM/IEEE, New York (2006)
8. Harel, D.: Statecharts: A visual formalism for complex systems. Science of Computer Programming 8(3), 231–274 (1987)
9. Heimdahl, M.P.E., Whalen, M.W.: Reduction and slicing of hierarchical state machines. In: Jazayeri, M., Schauer, H. (eds.) FSE 1997. LNCS, vol. 1267, pp. 450–467.
Springer, Heidelberg (1997)
10. Holt, N.E., Anda, B.C.D., Asskildt, K., Briand, L.C.L., Endresen, J., FrØystein, S.:
Experiences with precise state modeling in an industrial safety critical system. In:
Houmb, S.H., Georg, G., France, R., Petriu, D.C., Jürjens, J. (eds.) Critical Systems Development Using Modeling Lanuguages, CSDUML’06, pp. 68–77. Springer,
Heidelberg (2006)
Behavioural Specifications from Class Models
137
11. Kleppe, A., Warmer, J., Bast, W.: MDA Explained. The Model Driven Architecture: Practice and Promise. Addison-Wesley, Reading, MA (2003)
12. Manna, Z., Waldinger, R.J.: Toward automatic program synthesis. Commun. ACM,
vol. 14(3) (1971)
13. Nowack, A.: Slicing abstract state machines. In: Zimmermann, W., Thalheim, B.
(eds.) ASM 2004. LNCS, vol. 3052, pp. 186–201. Springer, Heidelberg (2004)
14. Object Management Group. UML 2.0 superstructure specification (2005)
http://www.omg.org/cgi-bin/doc?ptc/05-07-04
15. Prywes, N., Amir, S., Shastry, S.: Use of a nonprocedural specification language
and associated program generator in software development. ACM Trans. Program.
Lang. Syst., vol. 1(2) (1979)
16. Ruth, G.R.: Automatic programming: Automating the software system development process. In: ACM ’77: Proceedings of the 1977 annual conference, ACM Press,
New York (1977)
17. Warmer, J., Kleppe, A.: The Object Constraint Language: Getting Your Models
Ready for MDA, 2nd edn. Addison Wesley, Reading, MA (2003)
18. Welch, J., Faitelson, D., Davies, J.: Automatic maintenance of association invariants. In: SEFM ’05: Proceedings of the Third IEEE International Conference on
Software Engineering and Formal Methods, Washington, DC, pp. 282–292. IEEE
Computer Society, Los Alamitos (2005)
19. Whittle, J., Schumann, J.: Generating statechart designs from scenarios. In: ICSE
’00: Proceedings of the 22nd international conference on Software engineering, New
York, pp. 314–323. ACM Press, New York (2000)
20. Xie, T., Notkin, D.: Automatic extraction of sliced object state machines for component interfaces. In: Proceedings of the 3rd Workshop on Specification and Verification of Component-Based Systems at ACM SIGSOFT 2004/FSE-12 (SAVCBS
2004), October 2004, pp. 39–46 (2004)
Inheriting Laws for Processes with States
Yifeng Chen
Department of Computer Science,
University of Durham, Durham DH1 3LE, UK
Yifeng.Chen@dur.ac.uk
Abstract. This paper studies the laws of communicating sequential processes (CSP) with Z-like initial and final states. Instead of defining a large
semantics including all observable aspects, we incrementally develop the
model in three stages: partially correct relational model, then totally correct sequential model and finally the reactive-process model with states.
The properties of each model are captured as algebraic laws. A law in one
model may or may not be true in its submodels. We apply a technique
based on healthiness conditions to identify the conditions for law inheritance. Such abstract conditions themselves can be captured as pattern
laws of commutativity. The model uses a new approach to define parallel compositions using just the primitive commands, nondeterministic
choice, conjunction and some unary (hiding) operators.
1
Introduction
This paper studies the laws of communicating sequential processes with Z-like
initial and final states. Instead of defining a large semantics including all observable aspects, we incrementally develop the model in three stages: partially correct
relational model, then totally correct sequential model and finally the reactiveprocess model with states. The intended model then becomes a submodel with
more healthiness conditions. In particular, we aim at reusing the laws of predicate calculus and sequential models. Many laws of sequential languages also hold
in CSP, but there are exceptions. For example, SKIP is the unit of sequential composition: (SKIP A) = A = (A SKIP) in both sequential and parallel models.
On the other hand, we have (A CHAOS) = CHAOS in sequential models but
not in CSP. For a counterexample, we have (a → SKIP) CHAOS = (a → CHAOS)
in which the following divergences cannot undo the action that is already performed.
How do we know which laws are inheritable and which are not? In previous
approaches and also Unifying Theories of Programming [12], this is done by
checking and re-proving laws individually. For example, a conditional test can be
moved ahead of a proceeding assignment statement if the condition is substituted
for the assignment:
(s:= e if b then A else B) = if b[e/s] then (s:= e A) else (s:= e B). (1)
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 138–155, 2007.
c Springer-Verlag Berlin Heidelberg 2007
Inheriting Laws for Processes with States
139
This law holds in both the partially correct relational model and the totally
correct sequential model. However, because an assignment statement is denoted
as different predicates in the two models, the law had to be re-proved in UTP
([12] Section 3.1). Such re-proof not only leads to tedious proof obligations but
also raises question over the benefit of theory linking.
We will use a new technique first outlined in [6] and later further developed
in [7]. The technique is based on a meta-theory about healthiness conditions.
We are able to identify some abstract conditions on the structures of laws. Such
conditions are captured in the form of pattern laws for semantic embedding’s
commutativity with respect to program operators. For example, we will show
that if in a law of sequential programs, the first argument of every sequential
composition terminates successfully, and its second argument does not deadlock
or diverge, then the law also holds in CSP with states.
The contribution of this paper is to apply the techniques to integrate eventbased parallel specifications and state-based sequential specifications. Some results of [7] are repeated here for coherent presentation.
Integrating event-based and state-based specifications has long been of intense
research interests due to its importance in applications as well as its technical
challenges. States are originally abstracted from process calculi because shared
variables cause interference between processes, and such concurrent specifications (e.g. in action systems) are not compositional at observational level. On
the other hand, pure process calculi are found too restrictive for various applications. A typical area is verification of security protocols. Most security protocols
do depend on states. The problem is a matter of tradeoff between compositionality and flexibility.
Morgan [13] first studied failures-divergences modelling of action systems. The
linking theory was further developed in [3] and applied to the combination of
CSP and B-Method [15]. Another line of research integrates CSP with Z-style
specifications [12,4]. A CSP process is extended with an initial state for the start
of the process and a final state for its end. Unlike action systems, intermediate
states are not represented. This formalism is more abstract. Parallelism is compositional and entirely handled by CSP. This paper follows the second approach
and studies laws and law inheritance in such a model. We will show that although
the formalism does not model action systems directly, action systems become
special specifications, as states can be used to determine the actions performed
by a process.
CSP, as a language, has too many different binary operators. There has been
effort in unifying different kinds of parallelism. The most basic form of parallelism
is conjunction (e.g. [8]). Conjunction is useful in specification, but realistic parallel compositions are not as simple. UTP uses a technique called parallel-by-merge.
The idea is to define parallel compositions as a parallel-by-merge composition
with a certain parameter M . The parameter is a three-way relation that connects to the non-conjunctive observables of the composition, hides them and generates the observable for the composition. A slightly more general notation called
parallel-via-medium was introduced in [5]. The notation is general and powerful
140
Y. Chen
but unfortunately difficult to manipulate. Hoare [11] recently expresses the view
that it is desirable to unify various parallel compositions using conjunction. In
this paper, by temporarily dropping some healthiness conditions of CSP (C1-C7
Chapter 7 of [10]), we are able to define all the CSP parallel compositions using
just the primitive commands, disjunction (nondeterministic choice), conjunction
and a number of unary hiding operators. The dropped healthiness conditions can
be restored at the end without affecting any established laws. For each model,
we will study its healthiness conditions, the corresponding semantic construction
and an algebraic normal form.
Section 2 reviews Unifying Theories of Programming. Section 3 defines healthiness conditions, commands, laws and fixpoints. Section 4 introduces the models
of partially correct relational model and the totally correct sequential model.
Section 5.2 studies the CSP model with states.
2
Unifying Theories of Programming
This section is prepared for those readers who are unfamiliar with the notations
of this style of algebraic semantics. UTP, the latest development in relational
semantics, is aimed at linking different computational models with predicates
and functions on predicates. Each program or specification is represented as a
predicate, or simply a set of value assignments over some free logical variables.
For example, a predicate x = x + 1 denotes a sequential program x:= x + 1
that increases x by 1. Two predicates are considered the same if they describe
the same relation. Both universal disjunction (set union) and conjunction (set
intersection) are allowed. Thus the underlying logic is infinitary.
A healthiness condition classifies predicates into the groups of healthy and
unhealthy ones. A general programming theory can be specialised by adding
new healthiness conditions. It has been shown that if the additional healthiness
condition of a submodel is well-formed as the fixpoint equation A = h(A) of
a monotonic and idempotent predicate function h , then the inter-model mapping between the original model and the submodel is entirely characterised by
the predicate function h. Any predicate A is transformed by h into a healthy
predicate h(A).
Healthiness condition is a complementary technique to the more traditional
semantic construction in denotational semantics and abstract interpretation. For
example, a binary relation r ⊆ N × N has a downwards closed range iff it satisfies a healthiness condition r = (r s) where s =
{(n, m) | n m}. Alternatively, given arbitrary S ⊆ N and k ∈ N , we can construct such a relation as
S × {n | n k} in correspondence. Sometimes the two approaches are used in a
combination.
In UTP’s sequential models, a binary relation is a predicate on undashed
and dashed variables in pairs. For example, (x = x + 1 ∧ y = y) represents an
assignment x:= x + 1 with program variables x and y . The sequential composition (A B) is defined as (∃v0 · A[v0 /v ] ∧ B[v0 /v]) where v = x, y. Nondeterministic choice A B =
A ∨ B is disjunction. The constant predicates
⊥ =
tt and
=
ff represent chaos and magic, respectively. The refinement
Inheriting Laws for Processes with States
141
order A B corresponds to reduction of nondeterminism and set containment.
The semantics
of a recursion A = f (A) is defined as Tarski’s weakest fixpoint
μf =
{A | A f (A)} where f is a monotonic predicate function closed in
the complete lattice of healthy predicates.
The above simple model is not totally correct for sequential computation, as it
does not distinguish termination and nontermination. UTP introduces another
model with two special logical variables ok and ok where ok , not appearing
in any program, records the observation that the program has been started,
and ok records that the program has terminated. The assignment x:= x + 1
is now represented as ok ⇒ (x = x + 1 ∧ y = y ∧ ok ) . To achieve an appropriate set of laws, undesirable predicates must be excluded from the semantic space. Four healthiness conditions have been introduced incrementally: H1
A = (ok ⇒ A) (denoted as hok in this paper), H2 A = (A ∨ ∃ok · (A ∧ ¬ok )) ,
H3 A = (A (ok ⇒ ((x , y , ok ) = (x, y, ok ))) and H4 (A tt) = tt . H1 states
that if a computation has not started, it behaves chaotically. H2 describes the
downward closure of ok . A model satisfying H1 and H2 can be extended into
a reactive parallel model incorporating intermediate states between the initial
state and the final state [12]. H3 states that if a computation may not terminate
from some initial state, then in the final state, x , y and ok are chaotic. H4 excludes infeasible specification and guarantees some final state from every initial
state. The last one is not in the regular form A = h(A) and yields a CPO [1] instead of a complete lattice. We leave such a healthiness condition to be included
at last. As long as it yields a property-preserving sub-language, all results from
the complete-lattice model of specifications can be inherited.
We accept two classes of logical variables: non-overlined variables such as
u, v, u , v , · · · and overlined ones such as u, v, u , v , · · · . Healthiness conditions
are best defined with generic compositions. A generic composition [5] is a relational composition with a designated interface of non-overlined variables.
Definition 1.
∃v0 · A[v0 /v] ∧ C[v0 /v]
A :v C =
A fresh variable list v0 is used to connect the list v of A and the list v of C
with the interface v0 hidden by the existential quantifier. For example, the following composition relates two predicates on only x (and x for the second
predicate): (x = 10 ∧ y = 20) :x (x x ∧ z = 30) = (10 x ∧ y = 20 ∧ z = 30) .
Generic composition and its inverse form a Galois connection and satisfy the
algebraic laws of strictness, distributivity and associativity. The notation is especially useful when the interfaces of the operators in a predicate are not identical. For example, the interface can be expanded with new logical variables:
A :v C = A :v,u (C ∧ u = u) where {v} ∩ {u} = ∅. Many healthiness conditions
can now be simplified using the notation.
3
3.1
A Meta-theory of Predicative Modelling
Set-Theoretic Predicate Calculus
Let ν denote the set of all logical variables and C be a set of all constants.
When a variable list is expected, we assume the variables in ν to be ordered
142
Y. Chen
alphabetically. For example (ν = ν ) describes pairwise equality. A value assignment a is a total function a ∈ (ν → C). A predicate is a set of assignments. Let
Pred =
℘(ν → C) denote the complete lattice of all predicates whose (refinement) order is ⊇ (also written as
), lub is ∩, glb is ∪, top is the empty
set ∅ and bottom is (ν → C). Here we are following the convention of UTP in
which the complete lattice is “upside-down”. Let s, t, u, · · · denote (finite and
order-sensitive) lists of variables and let {s} denote the set of variables from
the list. Let A, B, C, · · · denote predicates in Pred. The following table lists
the predicate commands including functional equality, substitution, existential
quantification, universal disjunction and negation:
Command
s = e(t)
A[e(t)/s]
∃s · A
S
¬A
Set-theoretic definition
=
=
=
=
=
{a | a(s) = e ◦ a(t)}
{a | a ∈ A, a = a † {s → e ◦ a (t)}}
{a | a ∈ A, a(u) = a (u)}
S
(ν → C) \ A
where e is a list of (total) expressions, s, t, u are variable lists, and S ⊆ ℘(ν → C)
is a set of predicates. We use a(s) to denote the tuple of constants from the
assignment a on the list s ofvariables.Other predicate commands can be derived:
universal conjunction S =
¬ {¬A | A ∈ S} , binary disjunction A ∨
B =
{A, B}, implication A⇒B =
¬A∨B , true tt =
(s = s), false
¬tt
ff =
and universal quantifier ∀x · A =
¬∃x · ¬A. We assume that ff = ∅ .
We prefer program notations in semantic models: the bottom ⊥ =
tt (or
abort and chaos),
the
top
=
ff
(or
magic),
the
glb
(or
universal
nondeter
S =
S, the lub
S =
S, the binary nondeterministic
ministic choice)
choice A B =
A ∨ B, conjunctive parallel composition A B =
A ∧ B and
the binary conditional (or if b then A else B ) A b B =
(b ∧ A) ∨ (¬b ∧ B)
where the boolean expression b = b(t) is a parameter. The basic laws of glb, lub
and conditional are listed as follows. All distributivities also hold for universal
glb and lub.
(1) ⊥ A = ⊥
(2) A = A
(3) ⊥ A = A
(4) A =
Law 2 (Pred...) The operators
and
are idempotent, commutative and
associative and distribute each other.
Law 1 (Pred...)
Law 3 (Pred...) (1)
(3)
(4)
(5)
(6)
(7)
(8)
AbA = A
(2) A tt B = A
A b B = B ¬b A
A c (B b C) = (A c B) b (A c C)
A c (B b C) = (A c B) c ∨ b C
(A B) b C = (A b C) (B b C)
(A b ) (A c ) = A b ∨ c
(A b B) C = (A C) b (B C)
Inheriting Laws for Processes with States
3.2
143
Predicate Functions
Let f, g, h, · · · denote (total) predicate functions. We use f (Pred) to denote
the range of a unary predicate function f . Let f ◦ g(A) =
f (g(A)) .
Definition 2. A function f commutes with another function g for a predicate A , if we have f ◦ g(A) = g ◦ f (A). They commute in a semantic space
h(Pred) if we have f ◦ g ◦ h = g ◦ f ◦ h . They are simply called commutative
if they commute in Pred . A unary function f commutes with an n-arg function g for the arguments A1 , A2 , · · · , An , if we have: f (g(A1 , A2 , · · · , An )) =
g(f (A1 ), f (A2 ), · · · , f (An )). A unary function f is idempotent, if we have f ◦
f = f . A unary function is called a healthiness function if it is monotonic
and idempotent.
A unary
function f is called linear, if it distributes universal
disjunction f ( M) = {f (A) | A ∈ M} for any M ⊆ Pred. A function f absorbs another function g , if we have f ◦ g = f . A function f is closed with
respect to a unary function g, if we have f ◦ g = g ◦ f ◦ g .
Linearity implies monotonicity. The range of a linear function is always a complete lattice whose glb and lub are disjuction and conjunction, respectively. Absorbtion characterises the link between the healthiness conditions of a model and
its submodels. Closure is a necessary property relating program operators and
healthiness conditions. A command is called a primitive, if it is a healthy predicate in the semantic space. Assignment statements are primitives. A program
operator is an n-ary monotonic predicate function closed in the semantic space.
A program operator is closed in a semantic space h(Pred) iff it is closed with
respect to the healthiness function h.
3.3
Semantic Inheritance
The healthiness function h2 of a submodel must absorb that h1 of the original abstract model to render an embedding, i.e. h2 ◦ h1 = h2 . If h2 is also closed with
respect to h1 (i.e. h1 ◦ h2 = h2 ), then the submodel becomes a sublattice. Such
sublattice extension is assumed in the original meta-theory of UTP ([12] Section
4.1), although some semantic extensions are not sublattices. For example, the extension from the sequential model to reactive processes (such as CSP) is a Galois
embedding satisfying an additional healthiness condition A = (A∧tr tr ) (i.e. R1
of UTP). It prevents any computation (even chaos) from unwinding the actions
already performed. The healthiness function htr transforms the primitive ⊥ = tt
into tr tr . Related laws and fixpoints can be affected by such transformation.
A primitive C in the original model satisfying C = h1 (C) is inherited by the
submodel as h2 (C) . That means, in general, an inherited primitive is not the
original predicate! For example, assignment statement x:= x + 1 is denoted by
a predicate x = x + 1 in the partially correct relational model with the only
program variable x. The healthiness function hok transforms the predicate to a
different one ok ⇒ (x = x + 1). On the other hand, we follow a principle of UTP
and assume that an operator is always inherited exactly as its original definition.
Violating this requirement may lead to unnecessary complexity in future studies.
144
Y. Chen
The law AB = BA holds in every model with a linear healthiness function.
Another law (⊥ ) =
holds in the partially correct relational model but
not in the totally correct sequential model where (⊥ ) = ⊥. The law (1)
provides another example. We now address this important issue and consider
the simplest case first.
Theorem 1 (Simple inheritance of laws). Let h1 and h2 be the healthiness
functions of a model and its submodel, respectively. If h2 ◦ h1 = h2 = h1 ◦ h2 ,
and every primitive in a law of the original model is also healthy in the submodel,
then the law also holds in the submodel.
For example, if disjunction is closed in a model, then the law A B = B A of
Pred must hold, as every semantic space is a sublattice of Pred . The following
theorem handles the general case when a submodel may not be a sublattice, or
the primitives in the law are not healthy in the submodel.
Theorem 2 (Inheritance of laws). Let h1 and h2 be the healthiness functions of a model and its submodel, respectively. If we have h2 ◦ h1 = h2 , and
h2 commutes with every operator for its arguments in a law, then that law also
holds in the submodel.
Note that the healthiness function h2 only needs to commute with the operators
for their arguments in the law. The program letters, as arguments, are already
h1 -healthy.
4
4.1
Basic Models
Partially Correct Relational Model
Model Rel(v) is a property-preserving sub-language of Pred. The undashed
variables v and the dashed variables v record the observation about the start
andthe
end of a computation, respectively. Rel(v) inherits the commands ⊥,
, , , and b(t, s ) where s and t are variable lists such that no single variable appears twice in each list and {s, t} ⊆ {v} . Note that the binary conditional
b(t, s ) may test the variables s about the final state. This flexibility is convenient for future extension to reactiveness. We introduce two new commands:
s:= e(t) =
(s = e(t) ∧ v1 = v1 )
assignment
A B =
∃v0 · (A[v0 /v ] ∧ B[v0 /v]) sequential composition
where v1 =
v \ {s}, and v0 is a fresh list of variables. An assignment
statement
keeps variables not in s unchanged. We use a convention II s =
e s:= e to
denote the terminating program that assign arbitary values to s and makes it
chaotic, and SKIP to denote II s with the empty list s. The sequential composition is standard relational composition. Predicates in this model only depend
on the variables v, v . The following healthiness condition is a mathematical
representation of this frame restriction:
Inheriting Laws for Processes with States
HC 1 (hv )
A = ∃ξξ · A
145
(ξ =
ν \ {v, v }) .
As a convention, we write A = A(v, v ) to denote such a healthy predicate.
Note that the condition is semantical not syntactical: a predicate (v = v ∧ y = y)
is healthy even if y ∈ {v, v }. The corresponding healthiness function
∃ξξ · A forces any variable not in {v, v } to be chaotic (and hence
hv (A) =
unobservable). All related laws of Pred are inherited.
The basic laws concerning assignments and sequential composition are listed
as follows. Some laws are shared by submodels, while others may be more specific
to this model.
Law 4 (Rel,Seq,CspZ)
(1) s:= e = s, t:= e, t (2) s, t:= e, f = t, s:= f, e
(3) u, s, t:= e, f, g = s, t, u:= f, g, e
(4) (s:= e s:= f (u)) = s:= f (u[e/s])
(5) (s:= e t:= f (u)) = s, t:= e, f (u[e/s])
(6) (s:= e s:= f ) = (s:= e) e = f
= s:= e(t) b[e(t)/s ]
(7) s:= e(t) b
Law 5 (Rel,Seq,CspZ)
(1) ⊥ ⊥ = ⊥
(2) ( A) =
(3) ( ) is associative, distributes and has left unit SKIP.
(4) u:= e (A b B) = (u:= e A) b[e/u] (u:= e B)
(5) (A b(v) B) C = (A C) b(v) (B C)
Law 6 (Rel,Seq)
(1) (v:= e ⊥) = ⊥
(2) (v:= f ) =
Law 7 (Rel,CspZ) (A SKIP) = A
Law 8 (Rel) (A
4.2
) =
Sequential Specifications
The model Seq(w) is a submodel of Rel(w, ok ) and inherits all commands
with the only restriction that the special variable ok does not appear in any
program, i.e. {s, t} ⊆ {w}. Here the original variable list v has split into the
special variable ok and a smaller variable list w . The syntactical restriction
immediately leads to a new healthiness condition:
HC 2 (hok = )
A = A :ok ,ok (ok = ok ⇒ ok = ok )
This condition states that the logical variables ok and ok are either equal,
representing a terminating computation, or chaotic, representing nontermination. A predicate A satisfies A = hok ◦ hok = (A), iff there exist B = B(w, w ) and
C = C(w, w ) such that B ∧ C = ff , A = Φ(B, C) Φ(B, C) =
(B ∨ (C ∧
ok = ok )) . The closure of operators can be shown using this constructive form.
146
Y. Chen
Adding the healthiness condition alone will not change the laws, because
all primitives (i.e. chaos, magic and syntax-restricted assignments) remain unchanged, and the space is a sublattice, according to Theorem 1. That means
although the additional healthiness condition has already distinguished termination and nontermination, it does not generate the desirable set of laws. For
example, we would still have (⊥ x:= 1) = (x:= 1) , which violates the intuition that no computation after nontermination is observable. To make sure
(⊥ A) = A , we need to weaken every healthy predicate so that when a computation does not start, it behaves chaotically. This leads us to H1 of UTP:
HC 3 (hok ) A = (ok ⇒ A) .
Let hseq =
hok ◦ hok = . A sequential specification is a predicate A that satisfies
hseq (A) = A . A predicate A satisfies A = hseq (A), iff there exist B = B(w, w )
and C = C(w, w ) such that B ∧ C = ff , A = ¬ok ∨ Φ(B, C) .
In fact, the healthiness condition hseq is exactly the same as the composition
of H1 and H2 in UTP. The condition H2 A = hok (A) =
A :ok (ok ⇒ ok )
states that if a computation may not terminate (i.e. ¬ok ) then ok must be
entirely chaotic, and we have hok ◦ hok = hok ◦ hok = hok ◦ hok = ! Why do we
prefer hok ◦ hok = to H1 and H2? That is because this way of introducing healthiness functions highlights the healthiness condition that preserves laws and the
condition that alters them. As we have explained, hok = reflects a syntactical restriction over the language and preserves all laws, while hok alters them. Firstly,
it changes magic from ff into ¬ok ; secondly, the new space is no longer a sublattice as ¬ok is not hok = -healthy; finally, hok does sometimes but not always
commute with sequential composition. For example, we have a counterexample:
hok (⊥ x:= 1) = ¬ok ∨ (x := 1 ∧ v0 = v0 ) = tt = hok (⊥) hok (x:= 1)
where v0 =
v \ {x} . This is exactly the reason why, by adding hok , we deny
some laws from Rel(v) and at the same time render some new laws!
An interesting question is: how do we know which laws will be inherited
and which will be denied? The method used in UTP is to re-prove the laws
individually. For example the law (1) is re-proved. A more general solution is to
use Theorem 2. In fact if the first argument of a sequential composition always
terminates from any initial state, the function hok does distribute sequential
composition. In the relational model Seq(w), a predicate that always terminates
satisfies the healthiness condition A = (A ∧ ok = ok ) . Remember that II w =
(ok = ok ) . Thus we essentially need to show the following equality
hseq ((A ∧ II w ) B) = hseq ((A ∧ II w ) hseq (B)
hseq (A) .
for any hseq -healthy predicates A and B . We use a convention [A] =
Then such commutativity corresponds to a pattern law that links semantic denotations in both models.
Law 9 (Rel→Seq)
(1) [(A II w ) B] =
[A
II w ] [B]
(2) [ · ] commutes with , , and b .
Inheriting Laws for Processes with States
147
Other commutativities of Law 9(2) are readily provable. We can directly apply
these pattern laws of inheritance on the law (1):
[s:= e] [A] b [B]
.
= [s:= e A b B]
= [(s:= e A) b[e/s] (s:= e B)]
= ([s:= e] [A]) b[e/s] ([s:= e] [B])
Similarly, Law 1-6 are inherited. When the first argument does not always terminate, we need a new law to make the law set complete:
Law 10 (Seq,CspZ) (⊥ b
) A = (⊥ ∃w · b
).
Evidently (⊥ A) = ⊥ becomes a special case. For completeness, Law 1-7 and
10 are complete for transformation of any Seq program to a normal form:
⊥ B e : C(w,e(w)) (w:= e(w) ∃w · C )
where B = B(w, w ) and C = C(w, w ) are two predicates. The healthiness condition hseqok (A) is also complete and cannot be stronger, as every healthy predicate
is the semantics of some program.
If we impose an additional restriction that the condition b = b(t) in binary
conditionals (A b(t) B) does not contain dashed variables. This syntactical
restriction leads to a further healthiness condition A = (A (ok ⇒ v = v ))
(H3 of UTP). This condition states that if a computation does not terminate,
then both ok and the final state w become chaotic. The seuqential model
with this healthiness condition is totally correct and satisfies the law A = (A
SKIP) . The semantic construction is still ¬ok ∨ Φ(B, C) although B = B(w) no
longer depends on dashed variables, reflecting the syntactical restriction. As hw
commutes with hseq , adding this healthiness condition renders a sublattice. All
primitives are unchanged. According to Theorem 1, all laws of Seq(w, ok ) are
inherited. We can further impose the feasibility condition H4 (leaving out and
, see Section 2) and Dijkstra’s finitary condition [9,5]. These conditions are of
higher order and form a CPO instead of a complete lattice. Nevertheless, they
will not deny any existing laws as long as such healthiness conditions are added
after the regular healthiness conditions.
5
5.1
CSP-Z Specifications
The Model
CspZ(u) is a submodel of Seq(tr, wait , ref , u) in which the original variable
list w splits up into three special variables and a smaller list u of state variables.
The variable tr represents the (finite) trace record of actions and tr, tr ∈ A∗
where the alphabet A is a non-empty finite set of actions. The variable wait
was first introduced by Hoare and He [12] to replace the tick action in the
original CSP model. If a process does not diverge i.e. ok is true, then wait
148
Y. Chen
denotes deadlock, and ¬wait denotes a successful termination. The variable ref
represents the refusal set of actions ( ref , ref ⊆ A ). The refusals help distinguish
external choice and nondeterministic choice. The variable list u contains all
variables of state-based sequential computation.
As a sub-language, CspZ(u) only inherits the primitives chaos ⊥ , magic ,
state-variable assignment s:= e(t) where {s, t}
{u}, stop (ref , wait := B, ¬wait )
⊆
and action (tr:= tr a) , and the operators , , ( ) , and b where B ⊆ A
and the conditionals only depend on the values of state variables at the start:
b = b(u) . We will use these restricted commands to define CSP processes.
Further healthiness conditions are needed. The healthiness condition hw states
that if a computation diverges, then all of wait , ref , u become chaotic while
tr is arbitrarily extending tr . Evidently, hw is similar but different from H3 of
UTP, as the following skipping command maintains the monotonicity of tr, tr
even if the previous computation does not terminate. This healthiness condition denies Law 6, as no following computation can unwind the actions already
performed. The condition htr ensures the monotonicity of trace extension. Note
that chaos is now strengthened from tt to tr tr . The condition hΔtr (i.e. R2
of UTP) requires a process to depend only on the trace record during the lifespan. The healthiness condition href requires a computation not to depend on
ref (CSP3 of UTP), rendering the law A = (SKIP A). The condition hwait
states that, after succussful termination, a process always refuses all actions,
rendering the law A = (A SKIP), and after deadlock, the state variables are
chaotic. This corresponds to the CSP property that if a process ends with the
action , then it can refuse all actions in the end. This condition (CSP4 of
UTP [12]) was neglected in earlier models [10,14]. The condition hwait requires
every healthy predicate to skip and preserve the refusals if the previous process
stops in waiting, rendering the law (STOP A) = STOP.
HC 4 (hw ) A = A (v = v ok tr tr )
HC 5 (htr ) A = (A ∧ tr tr ).
HC 6 (hΔtr ) A = A :tr,tr (tr −tr = tr −tr)
HC 7 (href ) A = ∃ref · A
HC 8 (hwait ) A = A :ref ,u (ref = ref wait u = u )
HC 9 (hwait ) A = hw (v = v) wait A
hwait ◦ hwait ◦ href ◦ hΔtr ◦ hw ◦ hseq be the healthiness function of
Let hcspz =
CspZ(u) . A predicate A satisfies A = hcspz (A), iff there exist predicates of divergences D = D(dtr, u), failures F = F (dtr, ref , u) and terminating behaviours
T = T (dtr, u, u ) such that D = ∃s · (D[s/dtr] ∧ s dtr), F T D , and
A = hwait ◦ htr ◦ hok ( Φ(D, F wait T )[tr −tr/dtr] ) .
Inheriting Laws for Processes with States
149
Note that the refinement of such specifications corresponds to refinement for
every of D , F and T for uniqueness of the representation. The closure of operators can be shown using this constructive form. Most primitives have different
semantic denotations now. For example, skip is changed from (ok ⇒ v = v)
into (v = v wait ∃ref · v = v) ok tr tr .
5.2
CSP Commands and Action System
The following table lists a few inherited primitives as CSP-style convention commands:
CHAOS
VOID
STOPB
DOa
=
⊥
=
=
ref , wait := B, ¬wait
=
tr:= tr a
divergences
magic
immediate waiting
doing action a
where B ⊆ A and a ∈ A . CHAOS is the weakest process that can do everything,
although it must extend traces. Note that CHAOS is already transformed by hcspz .
VOID is the strongest specification and will erase all previous successfully terminating behaviours. STOPB deadlocks and refuses to engage in any action from
B (without downward closure). SKIP immediately terminates successfully and
refuses all actions after termination. DOa performs an action a and terminates
successfully (without any waiting before the action).
SKIP and DOs t =
DO
Let the convention DO =
s DOt denote the processes
terminating after a sequence of actions, DOp =
s ∈ p DOs be a process that
nondeterministically chooses an action sequence to perform,
DO∗ =
DOA∗ be
the process with chaotic action sequences, STOP⊆B =
STOP
be
the waitC
C⊆B
ing process with downwards-closed refusals, STOP =
STOP⊆A be deadlock, and
MOVE =
(II u DO∗ (SKIP STOP)) be the weakest convergent process with
chaotic states. We need other useful commands in specifications:
a→A
ACT
=
(DOa STOP⊆A\{a} ) A
=
a DOa (u) = a VOID
bA =
(A ACT ) b VOID
action followed by a process
state-controlled action
guarded process
where : C|u| → A is a mapping from states to actions. The process a → A
behaves like A after performing as action a. ACT performs an action, which is
controlled by the initial state and the state-event mapping . A guarded process
b A first checks the guard condition on the initial state. If the guard is true,
then it behaves like A and then performs an action according to the final state
of A . Normally A in a guarded process is a state-variable assignment. Such a
guarded process is called a guarded assignment, which can be used to link events
and states.
150
Y. Chen
An action system [2], in state-based parallelism, can be represented as a loop
of guarded commands after some initialisation:
B0 do b1 B1 [] · · · []bn Bn od
where each Bi is an assignment, and each bj is a guard on the state. Semantically, intermediate states are observable and interleaved. Action systems are
not representable in sequential model Seq(w), which does not represent the
intermediate states. Such an action system is now represented using guarded
assignments in CspZ(u) as follows:
B0 μX · ((b1 B1 ) · · · (bn Bn ) (¬b1 ∧ · · · ∧ ¬bn ) SKIP)) X
where extracts some information about the intermediate states. If the alphabet can be infinite and contain all possible states, then we can use an identity
function (u) = u to represent the action system faithfully. In most systems, the
set of observable actions depend on states but the intermediate states of local
variables are not directly observable. The mapping can be used to determine
the state influence on observable intermediate actions. Communication and concurrency are still model-checkable if the alphabet is finite, and then the above
definition becomes attractive. Such systems can be composed in parallel using
CSP operators. Note that CspZ(u) is essentially an integration of CSP and Z
rather than that of CSP and action system. The modelling of alphabetical hiding
is a technical complication in CSP-style action system. But it is not a problem
here, as we do not need to merge adjacent intermediate states after hiding the
actions between them, because such intermediate states do not exist.
Action systems is essentially variable-sharing parallelism. Parallel action systems may interfere with each other’s state. Our approach is essentially to restrict
variable-sharing within individual processes and use CSP parallel compositions
to compose them and make use of the normal-form technique in verification and
refinement calculus.
5.3
Law Inheritance
The simple inheritance Theorem 1 is no longer applicable. The more general
Theorem 2 works when hcspz commutes with the operators. The following laws
identify the patterns for such commutativity where [A] =
hcspz (A):
Law 11 (Seq→CspZ)
(1)
(2)
(3)
(4)
[A DO∗ B MOVE] = [A DO∗ ] [B MOVE]
[CHAOS B] = [CHAOS] [B]
[s:= e B] = [s:=e]
[B]
[ · ] commutes with ,
and b(u) .
According these patterns, some laws are directly inheritable. For example, we
still have the algebraic-unit law [SKIP] [A] = [SKIP A] = [A] , and [DOs ]
[DOt ] = [DOs DOt ] = [DOs t ] . On the other hand, the model Seq(w)’s laws
(STOPB CHAOS) = CHAOS and (DOa CHAOS) = CHAOS no longer hold in the
new model. Instead, we have [STOPB ] [CHAOS] = [STOPB ] and [DOa] [CHAOS] =
[CHAOS] due to the new property-altering healthiness functions. Law 1, 2, 4, 5
and 10 are inherited. New laws will be introduced in the next subsection.
Inheriting Laws for Processes with States
5.4
151
Parallelism as Conjunction
We have temporarily neglected several healthiness conditions of CSP, including
some closure and feasibility requirements. The reason is that we intend to define
all CSP binary compositions using just disjunction, conjunction and some unary
operators:
=
=
=
=
δ(A)
τ (A)
ω(A)
ρ(A)
hcspz (A ∧ ¬ok )
hcspz (∃tr · A)
hcspz (∃wait · A)
hcspz (∃ref · A)
extracting divergences
hiding traces
hiding wait
hiding refusals
where the function hcspz is employed to force semantic healthiness. The idea is
perhaps best explained in an analogy to predicate calculus in which we usually
define a binary operator with just disjunction, conjunction and existential hiding:
A⊕B =
∃ab · (A[a/x] ∧ B[b/x] ∧ x = a ⊕ b)
where ⊕ is some merging operator. We may re-write this as follows:
A⊕B =
a,b
(x = a ⊕ b ∃x · (A x = a) ∃x · (B x = b)).
(2)
The three unary operators are just like the existential quantifier and can help
hide the observation on traces, waiting and refusals, respectively. The three
operators can be merged into one, although it is more flexible to have them
separately. We temporarily drop the downward-closure healthiness conditions
(C2 and C3 of CSP). Thus STOPB with a fixed (i.e. not downwards-closed)
refusal is a valid command. Such a specification can be used to extract the
refusal of a computation by conjunction, playing a similar role as x = a and
x = b in (2). We have a new Law 12 for deadlock-led sequential compositions,
and other laws for operator elimination into the normal form. Distributivities
also hold for universal glb and lub.
Law 12 (CspZ)
(1) (STOPB A) = STOPB
(2) (A SKIP) = A
(3) (s:= e DOa ) = (DOa s:= e)
Law 13 (CspZ)
(1) (DOa A) STOPB = (DOa A) SKIP = VOID
(2) (DOa A) (DOa B) = DOa (A B)
(3) (DOa A) (DOb B) = VOID
(a = b)
Law 14 (CspZ)
(1)
(2)
(3)
(4)
δ(CHAOS) = CHAOS
δ(VOID) = δ(STOPB ) = δ(SKIP) = δ(s:= e) = VOID
δ(DOa A) = DOa δ(A)
δ distributes and b .
152
Y. Chen
Law 15 (CspZ) (1)
(3)
(5)
(7)
σ(CHAOS) = CHAOS
(2) σ(VOID) = VOID
σ(STOPB ) = (DO∗ STOPB ) (4) σ(SKIP) = DO∗
σ(s:= e) = (DO∗ s:= e)
(6) σ(DOa A) = σ(A)
σ distributes and b .
Law 16 (CspZ) (1)
(3)
(5)
(7)
(2) ρ(VOID) = VOID
ρ(CHAOS) = CHAOS
(4) ρ(SKIP) = SKIP
ρ(STOPB ) = STOP
ρ(s:= e) = s:= e
(6) ρ(DOa A) = DOa ρ(A)
ρ distributes and b .
Law 17 (CspZ)
(1) ω(CHAOS) = CHAOS
(3) ω(VOID) = VOID
(5) ω(s:= e) = (STOP s:= e)
(7) ω distributes and b .
(2) ω(STOPB ) = (STOPB SKIP)
(4) ω(SKIP) = (STOP SKIP)
(6) ω(DOa A) = DOa ω(A)
CSP-Z specifications have a normal form:
(DOs CHAOS) u = a VOID
s,a:D(s,a)
(DOs STOPB ) u = a VOID
s,B,a:F (s,B,a)
s,a,b:T (s,a,b) (DOs u:= b) u = a VOID.
where D = D(dtr, u), F = F (dtr, ref , u) and T = T (dtr, u, u ). Every specification
is transformable to this normal form. Proof is standard application of the laws
by induction on the structure of an arbitrary specification.
5.5
Binary Compositions
We now define external choice that diverges if either argument diverges, conjoins (i.e. intersects, for downwards-closed processes) the refusals during actionless waiting, or otherwise behaves nondeterministically, a convention of constant
choice Ab between A and SKIP according to the constant boolean b, fixedalphabet parallel composition that conjoins traces, disjoins the waiting status
and takes union of refusals when being convergent, and the interleaving composition ||| that interleaves traces, disjoins waiting status and conjoins (i.e. intersects, for downwards-closed processes) refusals:
AB =
δ(A B) ((A B) MOVE) (A B)
b
A
=
({A | b} ∪ {SKIP | ¬b})
AB =
δ(A B) b,c,B,C (ω ◦ ρ(A DO∗ STOPbB )
b∨c
ω ◦ ρ(B DO∗ STOPcC ) (DO∗ STOPB∪C
))
b
AB =
δ(A B) s,t,b,c (ω ◦ τ (A DOs STOP )
ω ◦ τ (B DOt STOPc ) (DOs t STOPb∨c ))
where s t is the set of all interleavings of two traces s and t .
Inheriting Laws for Processes with States
153
The following table lists some algebraic properties of various compositions:
zero
unit
CHAOS
VOID
VOID
CHAOS
VOID, STOPB , CHAOS
SKIP
CHAOS
STOP
CHAOS
CHAOS
SKIP
where we note that VOID, STOPB , CHAOS are only the left zeros of sequential
composition, which has no right zero.
Although all laws about these compositions are derivable from the laws of
the hiding operators, we still list some interesting ones, as they can be useful in
reasoning.
Law 18 (CspZ)
(1) (A CHAOS) (B CHAOS) = (A CHAOS) (B CHAOS)
(2) (A STOP) (B STOP) = (A B STOP)
(3) (A STOP) (B MOVE) = (B MOVE)
(4) (A MOVE) (B MOVE) = (A B) MOVE
(5) is idempotent, commutative and associative, and distributes and b.
Law 19 (CspZ)
(1) (A CHAOS) (B CHAOS) = (A CHAOS) (B CHAOS)
(2) (DOa A) (DOa B) = (DOa A B)
(a = b)
(3) (DOa A) (DOb B) = VOID
(4) (STOPB STOPC ) = STOPB∪C
(5) (STOPB s:= e) = (STOPB SKIP) = STOPB⊆
(6) (s:= e t:= f ) = (s:= e t:= f )
(7) is idempotent, commutative and associative, and distributes and b.
Law 20 (CspZ)
(1) (A CHAOS) (B CHAOS) = (A CHAOS) (B CHAOS)
(3) (DOa A) (DOb B) = (DOa A (DOb B)) (DOb (DOa A) B)
(4) (STOPB STOPC ) = STOPB B = C VOID
(5) (STOPB s:= e) = (STOPB SKIP) = STOPB
(6) (s:= e t:= f ) = (s:= e t:= f )
(7) is commutative and associative, and distributes and b.
5.6
CSP
Csp is a submodel of CspZ(u) where the state-variable list u is empty. Only
standard CSP commands are inherited: CHAOS, SKIP, STOP, a → A, A B , AB
and A B. Because of the syntatical restriction, Csp satisfies more healthiness
conditions. The condition h∅ (C1 of CSP) states that a process at least can
deadlock immediately without refusing any action. The condition href (C3 of
CSP) requires subset closure for ref so that intersection of refusals corresponds
to simple predicative conjunction. The condition hΔtr↓ (C2 of CSP) describes
154
Y. Chen
the prefix closure of traces with the empty refusal. The healthiness condition
href •tr (i.e. C4 of CSP) states that if a process cannot refuse an action, it must
be able to perform it. This condition is of higher order [5] and renders a CPO
instead of a complete lattice – just like the feasibility healthiness condition of
sequential programming. Because a href •tr -healthy predicate in CspZ(u) is still
hcspz -healthy, no difficulty is caused if we always impose it at last, and the
semantic extension is still property-preserving. All CspZ(u) laws (for the sublanguage) are inherited. Details are abbreviated, as our focus is on propertyaltering extensions.
HC 10 (h∅ ) A = A ∨ (¬wait ∧ wait ∧ tr = tr ∧ ref = ∅)
HC 11 (href ) A = A :ref (ref ⊇ ref )
HC 12 (hΔtr↓ )
A = A ∨ A :wait ,ref ,tr (tr −tr > tr −tr ∧ ¬wait ∧ wait ∧ ref = ∅)
HC 13 (href •tr )
A[tr0 , ref 0 /tr , ref ] ⇒ ∀a ∈ A · (A[ref 0 ∪ {a}/ref ] ∨ A[tr0 a, ∅ /tr , ref ])
6
Conclusions and Future Work
The handling of fixed points is a challenging issue, which has been addressed
in [7] by two major theorems. Note that the fixed-point theory of UTP no longer
works for our model development, because sequential model is not a sublattice
of the relational model, neither is it the case for the process-state model to the
sequential model. More preconditions are needed to link fixed points in a model
and those in its submodels. Many results and theorems can be found in [7].
The discussions of this paper remain at the theoretical level. More case studies
need to be carried out. If all state-event mappings in a CspZ specification have
finite ranges, then it becomes model-checkable. Tools like FDR can be applied
without modification. Another possible way of application is to use the algebraic
laws in verifying static analysers. A static analyser can be defined in abstract
interpretation as a partial semantic function. We can apply the function on the
normal form to illustrate its effect on any arbitrary process. Similar application
has been successfully achieved for Bulk-Synchronous Parallel programming [16].
References
1. Abramsky, S., Jung, A.: Domain theory. In: Abramsky, S., Gabbay, D., Maibaum,
T.S.E. (eds.) Handbook of Logic in Computer Science, pp. 1–168. Oxford University
Press, New York (1994)
2. Back, R.J., von Wright, J.: Trace refinement of action systems. In: International
Conference on Concurrency Theory, pp. 367–384 (1994)
3. Butler, M.: A CSP Approach To Action Systems. PhD thesis, OUCL, University
of Oxford, Oxford (1992)
Inheriting Laws for Processes with States
155
4. Cavalcanti, A., Woodcock, J.: Predicate transformers in the semantics of Circus.
IEE Proceedings - Software 150(2), 85–94 (2003)
5. Chen, Y.: Generic composition. Formal Aspects of Computing 14(2), 108–122
(2002)
6. Chen, Y.: Hierarchical organisation of predicate-semantic models. In: Dunne, S.,
Stoddart, B. (eds.) UTP 2006. LNCS, vol. 4010, pp. 155–172. Springer, Heidelberg
(2006)
7. Chen, Y.: Sharing properties between programming models. Technical report, Department of Computer Science, Durham University (2007)
8. Chen, Y., Sanders, J.W.: Logic of global synchrony. ACM Transactions on Programming Languages and Systems 26(2), 221–262 (2004)
9. Dijkstra, E.W.: Guarded commands, nondeterminacy and the formal derivation of
programs. Communications of the ACM 18(8), 453–457 (1975)
10. Hoare, C.A.R.: Communicating Sequential Processes. Prentice-Hall, Englewood
Cliffs (1985)
11. Hoare, C.A.R.: Dicussions about parallel composition as conjunction. Private communication (2006)
12. Hoare, C.A.R., He, J.: Unifying Theories of Programming. Prentice-Hall, Englewood Cliffs (1998)
13. Morgan, C.C.: Beauty is our business: a birthday salute to Edsger W. Dijkstra.
chapter Of wp and CSP, pp. 319–326. Springer, Heidelberg (1990)
14. Roscoe, A.W.: The Theory and Practice of Concurrency. Prentice-Hall, Englewood
Cliffs (1998)
15. Schneider, S., Treharne, H.: Verifying controlled components. In: Boiten, E.A.,
Derrick, J., Smith, G.P. (eds.) IFM 2004. LNCS, vol. 2999, pp. 87–107. Springer,
Heidelberg (2004)
16. Zhou, J., Chen, Y.: Generating C code from LOGS specifications. In: Liu, Z., Araki,
K. (eds.) ICTAC 2004. LNCS, vol. 3407, pp. 195–210. Springer, Heidelberg (2005)
Probabilistic Timed Behavior Trees
Robert Colvin, Lars Grunske, and Kirsten Winter
ARC Centre for Complex Systems,
School of Information Technology and Electrical Engineering
University of Queensland, Australia
Abstract. The Behavior Tree notation has been developed as a method
for systematically and traceably capturing user requirements. In this paper we extend the notation with probabilistic behaviour, so that reliability, performance, and other dependability properties can be expressed.
The semantics of probabilistic timed Behavior Trees is given by mapping
them to probabilistic timed automata. We gain advantages for requirements capture using Behavior Trees by incorporating into the notation an
existing elegant specification formalism (probabilistic timed automata)
which has tool support for formal analysis of probabilistic user requirements.
Keywords: Behavior Trees, probabilities, timed automata, model
checking.
1
Introduction
Representing the user requirements of a large and complex system in a manner that is readable by the client and preserves their vocabulary and intention
(validatable), while also having a formal underpinning (verifiable), is an important task for systems engineering. The Behavior Tree (BT) notation [Dro03]
is a graphical language that supports a behaviour-oriented design method for
handling real-world systems [WD04]. The notation facilitates systematic and
traceable translation of natural language requirements which structures the compositional and behavioural information. The notation includes a core subset
which has a formal basis [Win04] and can be model checked [GLWY05].
Currently the Behavior Tree notation does not have a syntax for expressing probabilistic behaviour. Such behaviour is important in system specification
as many systems specify, for instance, hardware dependability requirements or
probabilistic measures on performance. In this paper, we extend the Behavior
Tree (BT) notation to include probabilistic choice, thereby increasing the expressiveness of the language and also allowing stochastic properties to be model
checked. The new notation, which we call probabilistic timed Behavior Trees
(ptBTs), is an extension of timed Behavior Trees (tBTs), which are introduced
in [GWC07]. It allows the user to model timed as well as probabilistic behaviour.
The contributions of the paper are: 1) an operational semantics for timed
Behavior Trees in terms of timed transition systems, based on their mapping
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 156–175, 2007.
c Springer-Verlag Berlin Heidelberg 2007
Probabilistic Timed Behavior Trees
157
to timed automata [BW04] given in [GWC07]; and 2) the syntax and semantics
of probabilistic timed Behavior Trees, which extend those for timed Behavior
Trees, and are based on probabilistic timed automata [Bea03] and probabilistic
timed transition systems. We use two examples to demonstrate the extension,
and describe how probabilistic timed Behavior Trees can be model checked.
The paper is structured as follows. Section 2 introduces Behavior Trees and
their timed extension, and in Section 3 their semantics is given in terms of timed
automata. In Section 4 probabilities are introduced to the timed BT notation
and a semantics is given in terms of probabilistic timed automata. Section 5
gives two examples of probabilistic timed Behavior Trees and explains how they
were model checked using PRISM [HKNP06].
2
Preliminaries on Behavior Trees
As preliminaries we introduce the Behavior Tree notation and their extension to
timed Behavior Trees.
2.1
Behavior Trees
The Behavior Tree (BT) notation [Dro03] is a graphical notation to capture the
functional requirements of a system provided in natural language. The strength
of the BT notation is two-fold: Firstly, the graphical nature of the notation provides the user with an intuitive understanding of a BT model - an important
factor especially for use in industry. Secondly, the process of capturing requirements is performed in a stepwise fashion. That is, single requirements are modelled as single BTs, called individual requirements trees. In a second step these
individual requirement trees are composed into one BT, called the integrated
requirements tree. Composition of requirements trees is done on the graphical
level: an individual requirements tree is merged with a second tree (which can
be another individual requirements tree or an already integrated tree) if its root
node matches one of the nodes of the second tree. Intuitively, this merging step
is based on the matching node providing the point at which the preconditions
of the merged individual requirement tree are satisfied. This structured process
provides a successful solution for handling very large requirements specifications
[Dro03,WD04].
The syntax of the BT notation comprises nodes and arrows. The notation
contains a rich variety of node types for expressing behaviour; in this paper we
tag
Component
[B]
Flag
a) State Realisation
tag
Component
>B<
tag
Component
?B?
Flag
b) Selection
Flag
d) Internal Input Event
tag
Component
<B>
tag
c) Guard
Flag
e) Internal Output Event
Fig. 1. BT node types
Component
?? B ??
Flag
158
R. Colvin, L. Grunske, and K. Winter
focus on a core subset of the language which models state tests and updates
and event initiation and response. Each BT node type in Figure 1 refers to a
particular component, C , and a behaviour, B , and is optionally marked by one
or more flags. Nodes also contain a tag, which is used for traceability; since the
tags have no effect on the semantics, we will ignore them for the purposes of this
paper. The nodes types in Figure 1 are described below.
(a) A state realisation, where B is either a simple state name or an expression.
A state realisation node models that C realises (enters) state B . For example, the root node of Figure 2 models that initially the Power component
is in state on.
(b) A selection, where B is a condition on C ’s state; the control flow terminates
if the condition evaluates to false.
(c) A guard, where B is a condition on C ’s state, as with (b); however, the
control flow can only pass the guard when the condition holds, otherwise
it is blocked and waits until the condition becomes true.
(d-e) An event modelling communication and data flow between components
within the system, where B specifies an event; the control flow can pass the
internal event node when the event occurs (the message is sent), otherwise
it is blocked and waits; the communication is synchronous.
Power
[ on ]
Lamp
[ off ]
User
[ idle ]
Lamp
> press <
User
< press >
Lamp
[ on ]
User
[ idle ]
Lamp
> timeout <
Lamp
[ off ]
Lamp
> press <
Lamp
[ on ]
Fig. 2. Example: A simple lamp and its user
The control flow of the system is specified by either a single arrow leaving a
node, for sequential flow, or multiple arrows leaving a node, for concurrent or
alternative flow. In addition, atomic flow is specified by line with no arrowhead;
this indicates that the behaviour of the child node occurs immediately after the
behaviour of the parent node. We note that more than one input/output event
is not allowed within an atomic block of nodes, since this could induce deadlock
(for a more detailed discussion see [GWC07]).
Probabilistic Timed Behavior Trees
159
The example in Figure 2 shows three types of edges: after the initialisation
the control flow branches into two concurrent threads, the left modelling the
behaviour of the lamp, and the right modelling an abstract user. The lamp thread
contains alternative flow, when either a timeout event happens which causes the
lamp to switch off, or another press signal is send by the user. The lamp waits
for either of these events to occur. The first one to happen determines the flow
of control. This alternative flow is marked by the black box on the branching
edges.
A flag in BT node can specify: (a) a reversion node, marked by ‘ ˆ’, if the node
is a leaf node, indicating that the control flow loops back to the closest matching
ancestor node (a matching node is a node with the same component name, type
and behaviour) and all behaviour begun at that node initially is terminated; (b)
a referring node, marked by ‘∼’, indicating that the flow continues from the
matching node; (c) a thread kill node, marked by ‘−−’, which kills the thread
that starts with the matching node, or (d) a synchronisation node, marked
by ‘=’, where the control flow waits until all other threads with a matching
synchronisation node have reached the synchronisation point. Every leaf node
in Figure 2 is marked as a reversion node; we do not utilise the other flags in
the examples in this paper.
2.2
Timed Behavior Trees
Timed Behavior Trees (tBTs), originally introduced in [GWC07], extend BTs
with the notion of real-valued clocks for expressing timing behaviour. The timing
information expressed by timed automata [BW04] was adopted. All clocks are
initialised to zero and progress simultaneously with the same rate. Clocks can
be reset at any time, and they can constrain the behaviour in terms of guards
and invariants: a guard over a clock restricts the time when a step can be taken,
and an invariant restricts the time a component can remain in a state without
changing to the next state. The tBT notation therefore extends a BT node by
three slots: a guard G over clock values, a reset R of clocks, and an invariant
I over clocks. (If not relevant to a particular node, the slots may be omitted.)
As with timed automata, we restrict clock invariants to be expressions of the
form x ⊕ t , where x is a clock, t evaluates to an integer value, and ⊕ is one of
<, ≤, =, ≥, >.
As an example, in Figure 3 we augment the lamp Behavior Tree of Figure 2
with explicit timing constraints. The thread on the left hand side introduces the
clock variable x , which is reset as soon as the event press is received. When the
lamp realises the state on it must satisfy the invariant x ≤ 5, modelling that
the lamp can remain in state on for at most 5 time units before switching off
(after exactly 5 time units) or the user presses the button. If the user presses
the button while the lamp is on, the lamp may stay on for an additional 5 time
units, as indicated by the reset of clock x . In the right-hand thread, a second
clock y enforces a more specific timed behaviour in that the user cannot press
the button twice within 1 time unit.
160
R. Colvin, L. Grunske, and K. Winter
Power
[ on ]
Lamp
[ off ]
User
[ idle ]
R y := 0
Lamp
> press <
R x := 0
Lamp
[ on ]
I x =< 5
Lamp
[ off ]
G x=5
User
< press >
G y>1
User
[ idle ]
R y := 0
Lamp
> press <
Lamp
[ on ]
G x<5
R x := 0
Fig. 3. Timed system of a lamp and its user in tBT
3
Semantics of Timed Behavior Trees
A timed Behavior Tree (tBT) can be defined as a finite automaton, which contains state variables and clock variables, a finite set of locations, and a finite set
of labelled edges. Locations model the states of the system, abstracting from the
evaluation of state and clock variables. Edges symbolise the transitions between
the locations. A transition from one location to the next can be guarded and it
can perform one or more actions as well as a number of clock resets. Each edge
also has an optional synchronisation event.
Components in a tBT are treated as state variables in a timed automaton,
while events are treated as timed automaton synchronisations. A Behavior Tree
node represents an edge in a timed automaton, as nodes embody state changes
and events. Each arrow in a BT (except for atomic flow) corresponds to a location
in a timed automaton. The guards and updates (including resets) of clock and
state variables, and synchronisation events, are therefore added to the edges,
though clock invariants are pushed to the location following the edge. The general
mapping for a node is given in Figure 4.
Nodes. More concretely, the nodes in Figure 1 may be represented as follows
(altering the component behaviour section in Figure 4). State realisations are
mapped to an update of the relevant component, while a guard node is mapped
to a guard on the component. Both input and output events are mapped to
synchronisations of the same name, with input events decorated with ‘?’ and
output events with ‘!’. The transfer of data through events may be modelled
Probabilistic Timed Behavior Trees
161
S0
S0
tag Component
behaviour
G
R
I
component_behaviour
x<10
x:=0
x < 10
x := 0
x =< 5
S1 x=<5
S1
Fig. 4. tBT node (left) and corresponding timed automaton (right)
S0
cond
S1
¬cond
S2
Fig. 5. Behaviour for selections
using state variables. A selection node requires the addition of an extra edge
and terminal state (S2 ) for the case where the condition is not satisfied; this is
shown in Figure 5.
Control flow. Sequential flow, as mentioned above, maps to a location, while
alternative flow maps straightforwardly to nondeterministic choice. Nodes joined
by atomic flow are joined together so that their updates and guards are combined
into one transition. Because we restrict atomic flow in tBTs to contain only one
synchronisation, this representation is straightforward.
Concurrency. We will call tBTs without concurrent flow of control sequential
tBTs. A sequential tBT maps to a single timed automaton as described above.
Timed BTs with concurrent branching, called concurrent tBTs, map to a network
of automata, acting concurrently and synchronising on events. Each thread maps
to a single automaton, which has to be invoked at a particular point in the
control flow, namely the branching point that starts the thread. Therefore, each
single automata has an initial location which models the thread being disabled.
The location disabled can be exited only via an edge that is labelled with the
special synchronisation event invoke? . The process that starts the thread sends
the matching synchronisation event invoke! and terminates, i.e., goes itself to
the location disabled.
162
R. Colvin, L. Grunske, and K. Winter
Flags. We may now specify how a tBT node’s flags are represented. Firstly we
note that both reversion nodes and thread kill nodes terminate the behaviour of
processes at an arbitrary point in their execution. For each automaton p that
may be killed by process q, we introduce a synchronisation event kill q? , and
augment p with edges labelled with kill q? leading from each location in p to
the disabled location (this approach introduces less overhead than if we were to
take the approach of associating kill ? events with the process being killed). This
way, an automaton’s behaviour is terminated whenever the corresponding kill q!
event is received. In Figure 6 we depict the user thread from Figure 3 as a timed
automaton in a network system, assuming that it may be killed by process q at
any time.
S0
disabled
invoke_user?
kill_q?
S1
user:=idle
y:=0
kill_q?
S2
kill_q?
press!
y>1
S3
Fig. 6. Timed automaton simulating the user thread within the lamp system
A node with a reversion flag is typically modelled as a transition from the
current location to the location immediately after the edge representing the
target node. In general we choose the after-location rather than the beforelocation to allow for resetting of local clocks (see [GWC07] for why reversions
may have different clock resets to their matching node). However, when there are
no resets in the reversion node, or if the resets are identical, we can more simply
represent reversions as an edge to the before-location. For the examples in this
paper, we adopt this more straightforward approach. The reversion transition is
labelled with kill q!, which terminates the behaviour of all automata, if any, that
are invoked after the matching node (in Figure 6 there are none). A node with a
referring flag is modelled simply as a transition from the current location to the
location preceding the target node. A node with a kill flag generates a kill! event,
and a node with a synchronisation flag is modelled directly as a synchronisation
transition in a timed automaton.
3.1
Operational Semantics
The semantics of a sequential tBT is given as as a timed automaton. To a
large extent our definitions follow the definitions of the operational semantics of
Probabilistic Timed Behavior Trees
163
timed automata in [BW04]. We divert from these, however, where it is suitable
for modelling Behavior Trees, e.g., we separate actions (state updates) from
synchronisations, and explicitly define state variables to represent components,
which can be of any type, whereas in [BW04] state variables are treated as a
special kind of clock variable.
Let V be a finite set of state variables, and C be a finite set of clocks. Let Σ(V)
denote the set of actions (representing state updates), and let G(V) denote the
set of conditions over state variables (representing guards and selections). Let
G(C) be a set of guards over clocks, R(C) a set of clock resets, and I(C) a set of
clock invariants. We write skip to represent an action or clock reset which does
has no effect, and true for variable and clock guards which are always satisfied.
Let Θ be the synchronisation events, with ε ∈ Θ a distinguished element which
represents an internal step, i.e., no synchronisation.
Definition 1. A sequential tBT is a tuple L, l0 , E , I where
–
–
–
–
L is a finite set of locations
l0 ∈ L is the initial location
E ⊆ L × Θ × G(C) × G(V) × R(C) × Σ(V) × L is the set of edges
I : L → I(C) is the mapping that assigns clock invariants to locations.
We use the notation l
s,g,c,r ,a
→ l if (l , s, g, c, r , a, l ) ∈ E .
As an example, consider the sequential tBT representing the user in Figure 6.
There are four locations, with the initial location S0 . The invocation edge is
the tuple (S0 , invoke user ?, true, true, skip, skip, S0 ). The User [idle] edge is the
tuple (S1 , ε, true, true, (y := 0), (User := idle), S2 ), while the User press edge is
the tuple (S2 , press!, (y > 1), true, skip, skip, S3 ). The reversion is represented as
an edge back to the location S1 , i.e., (S3 , ε, true, true, skip, skip, S1 ). The edge
corresponding to a kill q event occurring while the lamp process is in location
S3 is (S3 , kill q?, true, true, skip, skip, S0 ).
Before giving the operational semantics we introduce some notation. We use
clock assignments to denote the progress of time and with it changing clock
values, and variable assignments to monitor the evaluation of the state variables.
A clock assignment is a mapping from clocks C to non-negative real numbers R+ .
If u is a clock assignment, then u + d denotes the clock assignment that maps all
c ∈ C to u(c) + d . Resetting clocks is denoted as [r → 0]u which maps all clocks
in r ⊆ C to 0 and leaves all other clocks in C \ r unchanged. Let v be a variable
assignment mapping all variables in V to a value in their domain. Updating
state variables is denoted as [x → e]v which changes the variable assignment to
map variables x ⊆ V to corresponding values in e and leaves all other variables
unchanged.
The semantics of a sequential tBT can be given as a timed transition system,
in which a state of a sequential tBT can be given as a tuple consisting of a
location, a variable assignment, and a clock assignment, i.e., l , v , u.
164
R. Colvin, L. Grunske, and K. Winter
There are two types of transitions possible: the system either delays for some
time (delay step) or takes one of the enabled transitions (action step).
Definition 2. The semantics of a sequential tBT is a timed transition system
with states l , v , u and transitions as follows.
d
- l , v , u −→ l , v , u + d
if u and u + d satisfy I (l ) for a d ∈ R+
α
- l , v , u −→ l , v , u
(delay step)
(action step)
s,g,c,r ,a
if l
→ l , u satisfies g, v satisfies c,
v = [x → e]v if a = (x → e),
u = [r → 0]u, and u satisfies I (l ).
According to this definition, if a process is in a location from where no action
step is enabled by the time the clock evaluation violates the location invariant,
no further step is possible (the delay step is also disabled) and the process
halts. Furthermore, this definition allows for indefinitely many delay steps if the
automaton is in a state for which no location invariant is specified (i.e., any u
and u + d will satisfy true).
3.2
Concurrent Timed Behavior Trees
The semantics of a concurrent tBT can now be given as a network of timed
automata, i.e., parallel automata that operate in an interleaving fashion using a
handshake synchronisation mechanism. A state of a network with n concurrent
processes is formalised as a tuple ls, v , u with ls being a vector of length n
of the current locations in each process, v the variable assignment1 and u the
clock assignment. Let li denote the i-th element of location vector ls and ls[li /li ]
denote the vector ls with the element li being substituted by li . With
I (ls) we
denote the conjunction of invariants on all locations, i.e., I (ls) = i I (li ).
Let s?, s! ∈ Θ symbolise reading and sending of a synchronisation event,
respectively, also recalling ε ∈ Θ denotes an internal action of the system.
A network can perform three types of steps: a delay step and an action step,
both similar to the steps in a single automaton, and also a synchronisation step.
Definition 3. The semantics of a concurrent tBT is a network of timed transition systems with states ls, v , u and transitions as follows.
d
- ls, v , u −→ ls, v , u + d
if u and u + d satisfy I (ls) for a d ∈ R+
ε
- ls, v , u −→ ls[li /li ], v , u
ε,g,c,r ,a
(delay step)
(action step)
li ,
if li
→
u satisfies g, v satisfies c,
v = [x → e]v if a = (x → e),
u = [r → 0]u, and u satisfies I (ls[li /li ]).
1
State variables are not related to a particular process but treated as global and are
therefore accessible by any process.
Probabilistic Timed Behavior Trees
ε
- ls, v , u −→ ls[li /li ][lj /lj ], v , u
if there exists i = j such that
s?,gi ,ci ,ri ,ai
165
(synchronisation step)
s!,gj ,cj ,rj ,aj
1. li
→ li , lj
→ lj
and u satisfies gi ∧gj and v satisfies ci ∧cj
and
2. v = [xi /ei ]([xj /ej ]v )
if ai = (xi → ei ) and aj = (xj → ej ) and
3. u = [ri ∪ rj → 0]u and u satisfies
I (ls[li /li ][lj /lu ]).
Note that in a synchronisation step the sending process updates the state variables (if its action a contains updates) before the receiving process, facilitating
synchronous message passing.
4
Probabilistic Timed Behavior Trees
In this section we extend timed Behavior Trees to probabilistic timed Behavior
Trees (ptBTs). We follow the well-established and expressive approach of annotating transitions with a probability that the transition will take place. In the
Behavior Tree notation, this means we associate with each node an optional
probability slot which contains a number from 0 to 1, i.e., in the range [0, 1]. As
an example, in which probabilistic choice is used to model component failures,
consider the ptBT in Figure 7 which extends the lamp example with a 1% chance
that the lamp will fail (e.g., blow a fuse) whenever it is switched from off to on.
For clarity, and without loss of generality, we impose a well-formedness condition on ptBTs that either every child node of a node has an associated probability, or none do (a child node is a direct descendant). We have therefore introduced
probabilistic branching in addition to alternative and concurrent branching. The
probabilities in the child nodes must sum to less than or equal to 1. If the probabilities sum to P , and P is less than one, it is understood that with probability
1 − P no transition is taken.2 In the lamp example, the probabilities of the child
nodes of the Lamppress node sum to 1, indicating that one of the actions must
be taken. In the user thread, however, the probability of the user pressing the
button is 0.3. Thus it is implicit there is a 70% chance that the user will not
press the button as time passes.
The mapping of ptBTs to probabilistic timed automata follows that of tBTs
for the non-probabilistic constructs in the language, with the addition that probabilities are added to the corresponding edges in the automaton, if the sum of the
probabilities is 1. If the probabilities of all the edges leaving a location sum to P
for P < 1, in general an additional edge looping back to itself with probability
2
This models an exponentially distributed delay before the next action is taken. In
continuous timed systems, such behaviour can also be represented using real-valued
rates, giving the expected incidence of events per time unit. For simplicity we define
ptBTs to contain probabilities only (values in the range [0,1]), but in Section 5 we
describe how rates may be introduced for model checking.
166
R. Colvin, L. Grunske, and K. Winter
Power
[ on ]
Lamp
[ off ]
User
[ idle ]
R y := 0
Lamp
> press <
R x := 0
Lamp
[ on ]
I x =< 5
P 0.99
Lamp
[ off ]
G x=5
Lamp
[ Faulty ]
P 0.01
Lamp
> press <
Lamp
[ on ]
G x<5
R x := 0
User
< press >
G y>1
0.3
P
User
[ idle ]
R y := 0
Fig. 7. Probabilistic timed system of a lamp and its user
1 − P is added, which includes any clock guards – see Figure 8 for an example.
An exception to this is if the node is an output event. Because it is not possible to label only one edge in a probabilistic choice in a timed automaton with
a synchronisation, an intermediate location is added between the probabilistic
choice and the synchronisation – an example is given later in Figure 9.
To specify probabilistic properties we may choose from several different specification languages: continuous stochastic logic (CSL) [ASSB96], if the model is deterministic and uses continuous time; probabilistic computation tree logic (PCTL)
[HJ94], if the model uses discrete time; or PCTL’s extension to probabilistic timed
computation tree logic (PTCTL) [KNSS02], if the model is nondeterministic and
uses continuous time. As an example, if the global time is recorded in clock G,
the dependability property “with what probability will the Lamp enter the faulty
state before X time units” can be formally stated in PCTL as
P=? (true U (lamp = faulty ∧ G ≤ X ))
where U is the temporal until operator, and a property true U φ models eventually φ.
4.1
Semantics of Probabilistic Timed Behavior Trees
We give the meaning of ptBTs as probabilistic timed automata. There are several
ways in which probabilities may be added to the timed automaton model, e.g.,
by associating them with edges [KNPS06] or with locations [KNSS00]. We follow
Probabilistic Timed Behavior Trees
167
S0
tag Component
[ state ]
G
R
I
P
S0
0.5
x < 10
x := 0
x =< 5
0.5
Component := state
x<10
x:=0
0.5
S1 x=<5
S1
Fig. 8. ptBT node (left) and corresponding probabilistic timed automaton (right)
the former approach, and replace the target locations in edges with a probability
mapping on clock resets, variable updates, and target locations. A probability
mapping on type T is a partial function from elements of T to values in the
range [0, 1], which sum to 1, i.e.,
Dist(T ) =
{p : T → [0, 1] |
p(t ) = 1}
t: dom p
Definition 4. A sequential probabilistic tBT is a tuple L, l0 , E , I where
–
–
–
–
L is a finite set of locations
l0 ∈ L is the initial location
E ⊆ L × Θ × G(C) × G(V) × Dist(R(C) × Σ(V) × L) is the set of edges
I : L → I(C) is the mapping that assigns clock invariants to locations.
In Figure 9 we give the graphical representation of the sequential probabilistic
timed automaton for the user process in the lamp example, alongside its representation as a tuple. By including resets and updates with the target locations
in the distribution we may enforce differing resets and updates depending on
how the probabilistic choice is resolved.
The semantics of a probabilistic timed automaton is updated so that an action
step from location l1 to l2 may be taken only if the associated probability is
greater than 0. This is given by the second line in the action step constraint
below, which is otherwise identical to Definition 2.
Definition 5. The semantics of a sequential ptBT is a probabilistic timed transition system with states l , v , u and transitions as follows.
d
- l , v , u −→ l , v , u + d
if u and u + d satisfy I (l ) for a d ∈ R+
(delay step)
168
R. Colvin, L. Grunske, and K. Winter
S0
disabled
invoke_user?
S1
user:=idle
y:=0
y>1
0.7
S2
0.3 y>1
S3
press!
L = {S0 , S1 , S2 , S3 , S4 }
l0 = S0
E = {(S0 , invoke user ?, true, true, {(skip, skip, S1 ) → 1.0}),
(S1 , ε, true, true, {((y := 0), (user := idle), S2 ) → 1.0}),
(S2 , ε, (y > 1), true, {(skip, skip, S3 ) → 0.3, (skip, skip, S2 ) → 0.7}),
(S3 , press!, true, true, {(skip, skip, S4 ) → 1.0}),
(S4 , ε, true, true, {(skip, skip, S1 ) → 1.0})}
I = (λ l : L • true)
S4
Fig. 9. Sequential ptBT of the user process as a probabilistic timed automaton, with
its representation as a tuple
a
- l , v , u −→ l , v , u
if (l , s, g, c, D ) ∈ E ,
(r , a, l ) ∈ dom D and D (r , a, l ) > 0, and
u satisfies g, v satisfies c,
v = [x → e]v if a = (x → e),
u = [r → 0]u, and u satisfies I (l )
(action step)
By augmenting edges with distributions, which therefore represent a set of “probable” edges, rather than assigning a single probability for that edge, we are able
to more succinctly capture the “sum to one” property, and express nondeterministic behaviour. A non-probabilistic timed automaton can be mapped to a
probabilistic timed automaton by replacing each edge (l , s, g, c, r , a, l ) with the
edge (l , s, g, c, D ), where the distribution D maps (r , a, l ) to 1.0. Such distributions are called point distributions. When a nondeterministic choice is made
between two locations, this is represented by two edges, each of which has a
point distribution on the target edge.
4.2
Semantics of Concurrent Probabilistic Timed Behavior Trees
The semantics of concurrent ptBTs must also be extended in a similar way to
Definition 3, so that both probabilities in a synchronisation step are greater than
0. The definition below differs from Definition 3 in that probabilities are checked
to be non-zero in action and synchronisation steps.
Definition 6. The semantics of a concurrent ptBT is a network of probabilistic
timed transition systems with states ls, v , u and transitions as follows.
d
- ls, v , u −→ ls, v , u + d
if u and u + d satisfy I (ls) for a d ∈ R+
(delay step)
Probabilistic Timed Behavior Trees
ε
- ls, v , u −→ ls[li /li ], v , u
if (li , ε, g, c, D ) ∈ Ei ,
(r , a, li ) ∈ dom D and D (r , a, li ) > 0,
u satisfies g, v satisfies c,
v = [x → e]v if a = (x → e),
u = [r → 0]u, and u satisfies I (ls[li /li ]).
ε
- ls, v , u −→ ls[li /li ][lj /lj ], v , u
if there exists i = j such that
169
(action step)
(synchronisation step)
1. (li , s?, gi , ci , Di ) ∈ Ei and
(lj , s!, gj , cj , Dj ) ∈ Ej and
(ri , ai , li ) ∈ dom Di ∧ (rj , aj , lj ) ∈ dom Dj and
Di (ri , ai , li ) · Dj (rj , aj , lj ) > 0 and
u satisfies gi ∧ gj and v satisfies ci ∧ cj and
2. v = [xi /ei ]([xj /ej ]v )
if ai = (xi → ei ) and aj = (xj → ej ) and
3. u = [ri ∪ rj → 0]u and u satisfies
I (ls[li /li ][lj /lu ]).
The addition of probabilities does not greatly affect the semantics, however it has
important implications for model checking. In an execution of the probabilistic
Lamp system in Figure 7, the probability of each transition is recorded, and
hence it is possible, in exhaustive analysis, to determine the probabilities of each
execution. We explore this in more detail in the next section.
5
Model Checking Probabilistic Timed Behavior Trees
In this section we describe how probabilistic timed Behavior Trees may be model
checked using the model checker PRISM [HKNP06], and provide two examples.
PRISM (Probabilistic Symbolic Model Checker) provides model checking facilities for three types of probabilistic models: deterministic time Markov chains
(DTMCs), continuous time Markov chains (CTMCs), and Markov decision processes (MDPs) (for an overview of the three models and how they may be model
checked, see [Kwi03]). To utilise PRISM, we must therefore translate ptBTs
into one of the three model types. DTMCs and CTMCs are deterministic, and
hence are suitable for deterministic ptBTs. MDPs, which are generalisations of
DTMCs, contain nondeterministic choice, though, like DTMCs, are limited to
discrete time. Because ptBTs contain nondeterministic choice, we will typically
translate a ptBT model into a PRISM MDP for model checking, following guidelines given in [KNPS06]; in Section 5.1 we give an example of this using the Lamp
ptBT. In Section 5.2 we give a deterministic ptBT, which we model check as a
PRISM CTMC.
5.1
Case Study 1 - Lamp Example
Consider the user probabilistic timed automaton given in Figure 9. Its translation
into a PRISM MDP is given below.
170
R. Colvin, L. Grunske, and K. Winter
module user
L: [0..4] init 0;
user: [0..1] init 0;
y: [0..MAX_Y] init 0;
[invoke_user] L=0
[]
L=1
[time]
L=2 & y>1
[press]
[]
[time]
-> (L’=1);
-> (L’=2) & (y’=0) & (user’ = 1);
-> 0.3: (L’=3) & INC(y) +
0.7: (L’=2) & INC(y);
L=3
-> (L’=4);
L=4
-> (L’=1);
!(L=2 & y> 1) and !(L=3)
-> INC(y);
endmodule
The variable L represents the locations, and user the user component (0 representing the user’s initial state, and 1 representing the idle state). We also
declare local clock y, which for efficiency reasons is at most MAX Y . (Within
the code, the abbreviation INC (Y ) increments y up to the maximum MAX Y .)
Each action line corresponds to an element of E , and is of the form
[sync] guard -> action
for non-probabilistic behaviour, or
[sync] guard -> prob1 : action1 + prob2 : action2 + ...
for probabilistic behaviour. The start of a line gives the synchronisation event enclosed in square brackets (which are empty for internal actions), and the guards
combine the conditions on clocks and state variables (there is no distinction
in PRISM). The action part updates variables and clocks. The translation is
straightforward, except that we must explicitly model the advancement of time,
as observed in local clock y. Any action which results in the passing of time is
synchronised with the global clock (see below) on the event time, and any local
clocks are incremented (since this is a discrete time model). In addition, the last
action line allows time to advance with no action being taken (the guard is used
to prevent doubling up of time increments, and to ensure no time passes between
the probabilistic choice and the press event occurring).
Global time is maintained via the time module. After invocation, the time
module increments the global clock synchronously with all modules which maintain their own local clocks.
module time
time_L : [0..1] init 0;
global_clock: [0..MAX_GLOBAL_CLOCK] init 0;
[invoke_clock] time_L=0 -> (time_state’=1);
[time]
time_L=1 -> (time_state’=1) & INC(global_clock);
endmodule
Probabilistic Timed Behavior Trees
171
The full PRISM model also contains a process representing the lamp, and a
process which initiates the lamp, timer, and user processes. Having translated the
model into an MDP, we may check whether it satisfies reliability requirements
written in probabilistic computation tree logic (PCTL) [HJ94]. For example,
“The probability that the lamp fails within 100 time units should be less than
10 percent” is given as
Pmin<0.1 [ true U (lamp_state = faulty & global_clock <= 100) ]
where faulty is an abbreviation for the corresponding integer-valued lamp state.
Given a failure probability of 0.01 for the lamp, and that the user presses the
button with a probability of 0.3, the model checking showed the model fulfils
this requirement.
5.2
Case Study 2 - Viking Example
In this section we give a model with no nondeterminism or local clocks, which
can be model checked as a PRISM CTMC. The example involves a group of four
Vikings attempting to cross a bridge, from the “unsafe” side to the “safe” side,
though the bridge may hold only one at a time – see Figure 10. An individual
Viking can step on to the bridge, and then cross to the safe side. However if
more than one steps on to the bridge at the same time, they begin arguing,
which may result in one or more of the Vikings backing down and returning
to the unsafe side of the bridge. (The behaviour of the system can be likened
to processes competing for access to a critical section.) For reasons of space we
show the thread for only one Viking – the other three are similar.
The Viking BT is specified as follows: initially each Viking is unsafe, and with
a rate (described below) given by enter rt they enter the bridge. Note that the
System
[ init ]
Viking1
[ unsafe ]
Viking2
[ unsafe ]
....
Viking1
< enter >
P enter_rt
Vcnt
?=1?
Vcnt
[0]
Bridge
> enter <
Vcnt
?>1?
Viking1
<leave>
P leave_rt
Viking1
<leave>
P argue_rt
Viking1
[ safe ]
Viking1 ^
[ unsafe ]
Vcnt
[ Vcnt+1 ]
Bridge ^
< enter >
Fig. 10. Viking Behavior Tree
Bridge
> leave <
Vcnt
[ Vcnt-1 ]
Bridge ^
< leave >
172
R. Colvin, L. Grunske, and K. Winter
Fig. 11. Result of PRISM model checking for the Viking example with a parameter
sweep over the enter and arguing probabilities
passage of time is implicit in this model, and that as time passes it becomes
more and more likely that an individual Viking will enter the bridge. Entering
a bridge is modelled by a synchronisation with the bridge process, which is
described below. After entering the bridge, the Viking may leave if he is the
only occupant, and does so at the rate given by leave rt. If there is more than
one Viking on the bridge, he begins “arguing” with the other Vikings, and may
back down and leave the bridge, returning to the unsafe side, at a rate given by
argue rt. The bridge process simply maintains a count of the number of Vikings
on the bridge by synchronising on leave and enter events from each Viking.
This model may be translated into a CTMC, because it is deterministic and
does not contain local clocks. However, CTMCs operate on rates, rather than
probabilities, and thus the value in the probability slot must be interpreted as a
rate. This is straightforward, unless the rate of an event occurring is more than
once per time unit (since this would require a value greater than one, i.e., could
not be interpreted as a probability). In this example we set our rates to be less
than once per second, and leave the extension of ptBTs to use rates as future
work. The translation of the Viking ptBT to a PRISM CTMC is straightforward,
since time does not need to be explicitly modelled.
We may check various properties of the Viking model, as with the lamp. Because the model is a CTMC, we use continuous stochastic logic (CSL) [ASSB96]
instead of PCTL. In this case, we may determine which combination of probabilities gives the best performance, as measured by how quickly all Vikings make
it to the safe side of the bridge. As an example, we fix the leaving probability at
1.0, i.e., Vikings will exit the bridge to the safe side at the earliest opportunity,
and observe the change in probability that results from varying the probabilities
of entering and arguing (also called a parameter sweep). This is checked against
the following property, which queries the probability of all four Vikings becoming safe within G time units (all safe is an abbreviation for each Viking being
in the safe state).
P=? [true U<G all_safe]
Probabilistic Timed Behavior Trees
173
The results of the analysis in PRISM are presented in Figure 11. The graphs
show the probabilities that all Vikings are safe for varying values of the argue
and enter rates with the leave rate set at 1. The graph on the left gives the
probabilities for the case where G = 10, i.e., all Vikings are safe within 10 time
units, while the graph on the right is for the case where G = 20. In both cases
a higher argue rate gives better performance, but over a longer time span a
less aggressive enter strategy gives better performance (optimal enter rate for
G = 10 is approximately 0.8, while for G = 20 it is approximately 0.4).
6
Related Work
Various notations have been extended to enable modelling of probabilistic behaviour, e.g., stochastic Petri Nets [MBC+ 95], probabilistic timed CSP [Low95],
stochastic π calculus [Pri95], probabilistic action systems [Tro99], and probabilistic statecharts [JHK02].
From the perspective of probabilistic requirements capture, the closest work
to our own is that of Jansen et al. [JHK02], who extend UML statecharts with
probabilities. Statecharts, like Behavior Trees, is a graphical notation to support
modelling of system requirements. Similarly to our work, the semantics of probabilistic statecharts, which is given in terms of Markov Decision Processes (MDP),
provides an interface to the model checker PRISM. In contrast to probabilistic
timed BTs, however, probabilistic statecharts do not allow modelling timed behaviour since a notion of clocks is not included. Furthermore, the Behavior Tree
approach allows individual requirements to be successively integated by grafting
them onto the growing design tree as branches, as outlined in Section 2. Because
Behavior Trees have been specifically designed for this purpose, they provide
a simpler and more straightforward mechanism for building the system model
from its individual requirements than is possible using other notations.
7
Conclusion and Future Work
In this paper we have given a probabilistic extension to the timed Behavior
Tree notation and a semantics in terms of probabilistic timed automata (see,
e.g., [Bea03]), as well as given a more rigorously defined semantics of timed
Behavior Trees [GWC07]. The extension was demonstrated with two examples,
which were also model checked in PRISM [HKNP06]. The notation extension
was designed to be straightforward for system modellers to incorporate when
capturing probabilistic requirements, as well as allow the probabilistic behaviour
of faulty components to be specified. Probabilistic system properties may then
be formally verified after translation to probabilistic timed automata.
The addition of probabilistic choice to Behavior Trees was particularly motivated by the need for modelling faulty behaviour of safety-critical embedded
systems. Consequently, in future work, we will enhance the automatic Failure
Mode and Effect Analysis (FMEA) for Behavior Trees [GLWY05]. The procedure currently uses fault injection experiments and model checking of the
174
R. Colvin, L. Grunske, and K. Winter
resulting Behavior Tree to determine whether the injected failure leads to a hazard condition, which is specified as a normal temporal logical formula. However,
a limitation of this procedure is that the model checker will generate counter
examples that are relatively improbable. With the results presented in this paper, we propose to assign to each of these injected faults an occurrence rate, and
perform an analysis of the resulting behaviour with probabilistic model checking.
We will then be able to analyse hazard conditions together with their tolerable
hazard probabilities.
As it stands, current probabilistic model checking approaches work with exponential distributions only, but in practice, many faults are distributed differently;
in particular, many faults are Weibull distributed [Bir99], and follow the common
“bathtub” curve which models a burn-in and wear-out phase. Consequently, we
will investigate how to include arbitrary distributions in the probabilistic timed
BT notation, and in what way these distributions can be supported by model
checking tools.
Acknowledgements. This work was produced with the assistance of funding
from the Australian Research Council (ARC) under the ARC Centres of Excellence program within the ARC Centre for Complex Systems (ACCS). The authors wish to thank their colleagues in the Dependable Complex Computer-based
Systems project and the anonymous reviewers for their constructive suggestions.
References
ASSB96.
Aziz, A., Sanwal, K., Singhal, V., Brayton, R.K.: Verifying continuous time
markov chains. In: Alur, R., Henzinger, T.A. (eds.) CAV 1996. LNCS,
vol. 1102, pp. 269–276. Springer, Heidelberg (1996)
Bea03.
Beauquier, D.: On probabilistic timed automata. Theoretical Computer Science 292(1), 65–84 (2003)
Bir99.
Birolini, A.: Reliability Engineering: Theory and Practice, 3rd edn. Springer,
Heidelberg (1999)
BW04.
Bengtsson, J., Wang, Y.: Timed automata: Semantics, algorithms and tools.
In: Desel, J., Reisig, W., Rozenberg, G. (eds.) Lectures on Concurrency and
Petri Nets. LNCS, vol. 3098, Springer, Heidelberg (2004)
Dro03.
Dromey, R.G.: From requirements to design: Formalizing the key steps.
In: Int. Conference on Software Engineering and Formal Methods (SEFM
2003), pp. 2–13. IEEE Computer Society Press, Los Alamitos (2003)
GLWY05. Grunske, L., Lindsay, P., Winter, K., Yatapanage, N.: An automated failure mode and effect analysis based on high-level design specification with
Behavior Trees. In: Romijn, J.M.T., Smith, G.P., van de Pol, J. (eds.) IFM
2005. LNCS, vol. 3771, pp. 129–149. Springer, Heidelberg (2005)
GWC07. Grunske, L., Winter, K., Colvin, R.: Timed Behavior Trees and their Application to Verifying Real-time Systems. In: Proc. of 18th Australian Conference on Software Engineering (ASWEC 2007), April 2007, accepted for
publication (2007)
HJ94.
Hansson, H., Jonsson, B.: A logic for reasoning about time and reliability.
Formal Aspects of Computing 6(5), 512–535 (1994)
Probabilistic Timed Behavior Trees
175
HKNP06. Hinton, A., Kwiatkowska, M., Norman, G., Parker, D.: PRISM: A tool for
automatic verification of probabilistic systems. In: Hermanns, H., Palsberg,
J. (eds.) TACAS 2006 and ETAPS 2006. LNCS, vol. 3920, pp. 441–444.
Springer, Heidelberg (2006)
JHK02.
Jansen, D.N., Hermanns, H., Katoen, J.-P.: A probabilistic extension of
UML Statecharts. In: Damm, W., Olderog, E.-R. (eds.) FTRTFT 2002.
LNCS, vol. 2469, pp. 355–374. Springer, Heidelberg (2002)
KNPS06. Kwiatkowska, M., Norman, G., Parker, D., Sproston, J.: Performance analysis of probabilistic timed automata using digital clocks. Formal Methods
in System Design 29, 33–78 (2006)
KNSS00. Kwiatkowska, M., Norman, G., Segala, R., Sproston, J.: Verifying quantitative properties of continuous probabilistic timed automata. In: Palamidessi,
C. (ed.) CONCUR 2000. LNCS, vol. 1877, pp. 123–137. Springer, Heidelberg
(2000)
KNSS02. Kwiatkowska, M., Norman, G., Segala, R., Sproston, J.: Automatic verification of real-time systems with discrete probability distributions. Theoretical
Computer Science 282(1), 101–150 (2002)
Kwi03.
Kwiatkowska, M.: Model checking for probability and time: From theory to
practice. In: Proc. 18th Annual IEEE Symposium on Logic in Computer
Science (LICS’03), Invited Paper, pp. 351–360. IEEE Computer Society
Press, Los Alamitos (2003)
Low95.
Lowe, G.: Probabilistic and prioritized models of timed CSP. Theoretical
Computer Science 138(2), 315–352 (1995)
MBC+ 95. Marsan, M.A., Balbo, G., Conte, G., Donatelli, S., Franceschinis, G.: Modelling with Generalized Stochastic Petri Nets. Wiley Series in Parallel Computing. Wiley, Chichester (1995)
Pri95.
Priami, C.: Stochastic π calculus. The. Computer Journal 38(6), 578–589
(1995)
Tro99.
Troubitsyna, E.: Reliability assessment through probabilistic refinement.
Nordic Journal of Computing 6(3), 320–342 (1999)
WD04.
Wen, L., Dromey, R.G.: From requirements change to design change: A formal path. In: Int. Conference on Software Engineering and Formal Methods
(SEFM 2004), pp. 104–113. IEEE Computer Society Press, Los Alamitos
(2004)
Win04.
Winter, K.: Formalising Behaviour Trees with CSP. In: Boiten, E.A., Derrick, J., Smith, G.P. (eds.) IFM 2004. LNCS, vol. 2999, pp. 148–167.
Springer, Heidelberg (2004)
Guiding the Correction of Parameterized
Specifications
Jean-François Couchot1,2 and Frédéric Dadeau3
1
3
INRIA Futurs, ProVal, Parc Orsay Université, F-91893
2
LRI, Univ Paris-Sud, CNRS, Orsay F-91405
Lab. d’Informatique de Grenoble, BP. 72, Saint-Martin d’Hères F-38402
Abstract. Finding inductive invariants is a key issue in many domains
such as program verification, model based testing, etc. However, few approaches help the designer in the task of writing a correct and meaningful
model, where correction is used for consistency of the formal specification
w.r.t. its inner invariant properties. Meaningfulness is obtained by providing many explicit views of the model, like animation, counter-example
extraction, and so on. We propose to ease the task of writing a correct
and meaningful formal specification by combining a panel of provers, a
set-theoretical constraint solver and some model-checkers.
1
Introduction
When designing safe softwares, writing formal specifications is a hard but valuable task, since consistency between the program and its inner properties can be
translated into Proof Obligations (POs) that can then be discharged into some
more or less automated prover.
The B method [1] ranges in this scope, by providing a formal development
framework. It starts from often parameterized abstract specifications, called abstract machines, that are later refined until a parameter-free implementation is
obtained. Intuitively, an abstract machine is composed of state variables, an initialisation operation, some operations that modify the values of state variables
and an invariant that represents properties that must hold for each state of the
execution.
Invariant verification techniques can be divided into two main categories:
model-checking (Spin [28], SMV [35]), which exhaustively explores the states
of the execution graph, and deductive approaches, based on automatic provers
(Simplify [21], Yices [23], haRVey [20]) or interactive ones (COQ [34], PVS
[37], HOL [27]). Intuitively, model-checking aims at checking whether all reachable states satisfy a given property, which is then called an invariant. On the
other hand, deductive approaches try to show that a property is inductive,
i.e., established by initialisation and preserved through each operation. The
B method is conceived as a deductive approach, in which the generated POs
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 176–194, 2007.
c Springer-Verlag Berlin Heidelberg 2007
Guiding the Correction of Parameterized Specifications
177
are discharged into a set-theoretical prover [16,2]. Some model-checkers for B
machines have been developed, such as ProB [31] or the BZ-Testing-Tools [3]
animator, but all of them require finite and enumerated data structures to
work.
Each inductive property is obviously an invariant, whereas an invariant is,
seldom if ever, inductive. If the invariant is not inductive, invariance proofs fail.
In an interactive mode, the modeler is asked to manually end the proof, which
might be useless since the errors are located in the specification. In an automatic mode, the proof may end. When it does, it generally answers “not valid”,
sometimes while extracting the subformula that originates this answer. This allows the engineer to modify either the invariant, or the code of the operation,
or both. When the proof does not terminate, the validity of the considered formula is unknown. Thus, the engineer is left with unknown results concerning the
inductivity of the invariants he wrote.
This paper presents an original framework relying on the efficient combination
of deductive and model-checking approaches, in order to be able to help the
engineer in the process of designing, automatically checking the correctness and
(eventually) correcting a formal specification.
This framework is depicted in Fig. 1. We first consider the translation of the
formal specification into the Why language. Why [24] is a verification tool that
is dedicated to build POs for a variety of provers, and runs them to perform the
verification. In case of failure of all the provers, our approach aims at providing
a concrete counter-examples for the induction property. This task starts with
an instantiation of the parameters, by using recent results in proof techniques
applied on software verification [26]. It makes it possible to use CLPS [3], a settheoretical constraint solver, to solve the instantiated constraint, which results in
a counter-example if the formula is invalid. In addition, B animators [31,11] are
employed to automatically produce an execution trace leading to this counterexample when it exists. The modeler obtains, for free, some guidance information
that helps her/him to modify the incriminated part of her/his formal specification. Furthermore, in order to be able to give a feedback on the PO validity,
when the proof does not terminate, or when the prover is unable to decide the
theory involved within the formula, we also propose to instantiate the formula
before checking its consistency with CLPS.
This paper is organized as follows. Section 2 presents the consistency checking
of B machines, that makes it possible to establish their correction, and presents
the running example that will illustrate our approach throughout the following sections. We give in Sect. 3 the translation of B machines into the Why
language. Then, we present in Sect. 4 the instantiation techniques that are sufficient to compute a counter-example. In Sect. 5, we show how to help the designer in the task of correcting her/his specification by computing an execution
trace that leads to the counter-example. Finally, we draw a comparison with
some related works in Sect. 6, before we conclude and present future works in
Sect. 7.
178
J.-F. Couchot and F. Dadeau
B parameterized
specification
Why specification
Automatic
provers
yes
yes
All proofs
end?
All proofs
are valid?
no
Incriminated subformula
extraction
no
no
Constraints
solving (CLPS)
Parameters
instantiation
Unsat.
Sufficient
instantiation ?
yes
Sat.
Counter-example
computation
Finite trace
computation (B animator)
Fig. 1. Combining deductive and constraint-satisfaction approaches
2
Correction of a B Machine
The B formal method [1] was developed by J.-R. Abrial. It scopes the whole
software development process, from the abstract specification to the automatic
code generation into a classical programming language, such as C or Ada, by
using successive refinement steps. The first step details the software as a machine,
called abstract machine. It may contain abstract data, such as abstract sets or
parameters, which makes its behaviors undeterministic. These parameters have
to be precised in subsequent refinement steps.
Fig. 2 gives an example of an abstract parameterized machine in the scope of
this study.
Semantically, the abstract machine of Fig. 2 simulates the global behavior of
a set of processors running in parallel the distributed MESI [38] cache coherence
protocol. In this protocol, each processor manages its own cache that can be in
one of the following control states M, E, S and I. The global machine state is
then defined by the sets m, e, s and i that precise which cache among those of
c are respectively in the M, E, S and I control states.
Syntactically, such a B machine is composed of the following clauses:
• the MACHINE clause specifies the machine name and its parameters, that
may be finite sets. In the example, the machine is parameterized by c which
is the finite set of processors that follow the transition system detailed by
the machine.
• The VARIABLES clause contains all the machine state variables, that may
be modified by the operations.
Guiding the Correction of Parameterized Specifications
MACHINE
mesiSet(c)
VARIABLES
m, e, s, i
INVARIANT
m, e, s, i ∈ (c) ∧
m
e ∪s ∪i =c ∧
j ∪
=k
j ,k ∈{m,e,s,i} j ∩ k = ∅ ∧
((∃ p1 . p1 ∈ c ∧ p1 ∈ s) ⇒
¬(∃ p2 . p2 ∈ c ∧ p2 ∈ m))
INITIALISATION
m, e, s, i := ∅, ∅, ∅, c
OPERATIONS
sendWriteInvalidate =
ANY
179
p WHERE p ∈ c ∧ p ∈ s THEN
m, e, s, i :=
∅, {p}, ∅, i ∪ m ∪ e ∪ (s \ {p})
END;
sendRead =
ANY p WHERE p ∈ c ∧ p ∈ i THEN
m, e, s, i :=
∅, ∅, m ∪ e ∪ s ∪ {p}, i \ {p}
END;
write =
ANY p WHERE p ∈ c ∧ p ∈ e THEN
e, m := e \ {p}, m ∪ {p}
END
END
Fig. 2. Set-Theoretical B Specification of the MESI Protocol
• The INVARIANT clause contains the I predicate that defines the properties
on the state variables that must be initially established and preserved by
each operation.
The first three lines of the INVARIANT specify that set variables m,
e, s and i describe a partition of set c, which means that each processor
is only in one control state at any time. These lines will be referred as
Inv type(m, e, s, i, c) in the remainder of the paper. The last two lines of
the INVARIANT express a cache coherence property: when a processor is
reading, (i.e., in the S control state), no other processor can modify its cache
(i.e., is in M). This property will be referred as Inv read(m, e, s, i, c) in the
following sections. Of course, Inv is the conjunction of Inv type and Inv read.
• The INITIALISATION and OPERATIONS clauses contain respectively a
(generalized) substitution U assigning an initial value to each state variable and a collection SUBSTS of generalized substitutions that modify their
values.
Any processor can read in its own cache, except if it is in the Invalidate
state (I), which means that its content is not consistent with central memory.
In the Shared state (S), the cache content is a copy of central memory.
Before it is modified, a cache in state S asks others to be invalidated, by
invoking operation sendWriteInvalidate, and switches to Exclusive (E state).
This control state means that it owns the exclusiveness of writing into the
central memory and into the cache. This writing step is represented by the
write operation, that moves each cache into the Modified state (M). The
sendRead operation expresses that a processor with an invalidated cache (i.e.
in I state) that requires to read in central memory moves all the Modified
and Exclusive processors to the Shared state. Initially, all the processors are
Invalidated.
180
J.-F. Couchot and F. Dadeau
Notice that this example illustrates that sets are convenient structures to
express local transitions (by adding and removing a singleton), rendez-vous
transitions (by adding and removing two singletons), and broadcast transitions (by building the union of sets), commonly used in distributed cachecoherence algorithms.
The POs of a B abstract machine ensure its consistency with respect to the invariant. They are syntactically based on a weakest precondition calculus (syntactically
written [ ]) that transforms a predicate according to a generalized substitution. Intuitively, [S ] I represents the set of states where all successors by S verify I .
POs can be separated into two classes. First, the PO [U ] I that is valid if and
only if the invariant is established by the initialisation. Next, for each substitution S ∈ SUBSTS, the PO I ⇒ [S ] I ensures that the operation defined by S
preserves the invariant.
The next section presents how we translate the B machines for the PO generator.
3
Translation into Why Language
In a previous work [19], we have shown how the POs expressing the consistency
of a B machine can be discharged into the haRVey prover. Even if this technique
is scalable, it is constrained to the evolution of this prover. Instead of developing
as many PO generators as there exists provers, we translate the B machine into
a Hoare-Floyd style program annotated with assertions corresponding to the
invariant and we let a generic tool producing the POs and sending them to
several provers.
The Why [24] tool presents this combination of features, allowing to discharge the generated POs into a variety of provers such as Simplify, Zenon [22],
CVC-lite [8], Ergo [18], or SMT provers (Yices [23], mathsat [12], rv-sat [25]).
Furthermore, it makes it possible to declare logical models as sets of types, functions, predicates and axioms declarations. The axiomatized symbols can be used
in both programs and annotations.
Intuitively, the translation of a B machine into the Why language consists, in
a first step, in axiomatizing the symbols and, in a second step, in translating the
general substitution language into an annotated language. We present hereafter
the intuitions of these two steps.
First of all, the theories that are commonly used in B are axiomatized in Why
syntax. For instance, here is how we define set theory with a set of axioms, called
SSET in [19]
∀ e . (e ∈ ∅),
(1)
∀ e . (e ∈ {e}),
∀ e, f . (e = f ⇒ ¬e ∈ {f }),
(2)
(3)
∀ e, s1 , s2 . (e ∈ s1 ∪ s2 ⇔ (e ∈ s1 ∨ e ∈ s2 )),
(4)
∀ e, s1 , s2 . (e ∈ s1 ∩ s2 ⇔ (e ∈ s1 ∧ e ∈ s2 )),
(5)
Guiding the Correction of Parameterized Specifications
181
∀ e, s1 , s2 . (e ∈ s1 \ s2 ⇔ (e ∈ s1 ∧ ¬e ∈ s2 )),
(6)
∀ s1 , s2 . (s1 ⊆ s2 ⇔ ∀ e.(e ∈ s1 ⇒ e ∈ s2 )),
(7)
∀ s1 , s2 . (s1 = s2 ⇔ ∀ e.(e ∈ s1 ⇔ e ∈ s2 )).
(8)
Such axioms are polymorphic in the sense that they are defined for any element
e, f of sort α and any set s1 , s2 is of sort α set. The typing variable α is
instantiated according to the formula it is applied to.
Each symbol of this theory gives rise to two symbols in Why, one for the
expression part and one for the predicative part.
For instance, union : α set × α set → α set, which expresses the union
function, is given by
parameter union_ : s1: ’a set → s2: ’a set →
{ } ’a set { set_equal(result,union(s1,s2)) }
which signifies that, given two sets of α elements, s1 and s2, the result of
(union s1 s2) is a set of α elements that is equal to the union which is
axiomatized with
axiom union_def :
forall s1: ’a set . forall s2: ’a set . forall el : ’a.
member(union(s1,s2),el) ↔ member(s1,el) or member(s2,el),
where member is also axiomatized, according to axioms (1), (2) and (3).
Total function theory is axiomatized by the theory of arrays [6], given by
∀ a, i, e . rd(wr(a, i, e), i) = e
∀ a, i, j , e . i = j ⇒ rd(wr(a, i, e), j ) = rd(a, j )
(9)
(10)
∀ a, b . (∀ i . rd(a, i) = rd(b, i)) ⇔ a = b
(11)
where a, b are arrays of sort (α, β) array, i, j are indexes of sort α, which allows
arrays to be indexed with any sorts, and e is a value of sort β. Other relations
(e.g. partial functions) are rewritten into sets of pairs, using symbols defined in
SSET and the theory of pairs [39],
∀ i, j . π1 (i, j ) = i
∀ i, j . π2 (i, j ) = j
∀ p . π1 (p), π2 (p) = p
where i is of sort α, j is of sort β, p is of sort (α, β) pair and has the following
signature : α × β → (α, β) pair.
We sketch here the translation of B operations into functions. First of all,
the predicate describing the INVARIANT clause is duplicated both in the precondition and in the postcondition of each function encoding an operation. The
parameters of the function are those of the operation, plus the local variables in
the scope of an ANY operator. The generalized substitutions are directly translated into their counterpart in the Why programming language with assertions.
182
J.-F. Couchot and F. Dadeau
For instance, the precondition is moved in the precondition part of the function,
the if . . . then . . . else . . . structure is translated into its equivalent in Why. The
any . . . where . . . then . . . choice becomes an if . . . then . . . in Why as follows: the
declared variable is introduced as a parameter of the function and the condition
of the any is duplicated as in the if condition.
S || (S || S ) = (S || S ) || S
S || S = S || S
skip || S = S
(P =⇒ S ) || S = P =⇒ (S || S )
(S [] S ) || S = (S || S ) [] (S || S )
(if P then S else S ) || S = if P then (S || S ) else (S || S )
(@x . S ) || S = (@x . (S || S )) if x is not free in S
where S , S , S are generalized substitutions, P is a predicate, x
is a variable.
Fig. 3. Reduction of the || operator
We now focus on the parallel substitution (), classically present in abstract
machines. Since this feature is not taken into account by the Why language, we
reduce this substitution following a method that is twofold. First, the parallel
substitution is reduced until it only concerns assignments, following the rules [9]
given in Fig. 3. Next, multiple assignments are classically rewritten into sequential ones by introducing temporary variables storing the expression on the right
part of the assignment. Such local variables declarations are encoded with a
let . . . in . . . structure in Why.
Back to MESI. The following code is the write function translated from the
write operation where the function parameter p results from the any translation
and the local variable t originates from ||.
let write (p : elem) =
{ Inv(m,e,s,i,c) }
if ((member_ !c p) && (member_ !e p) then
begin
let t = (minus_ !e (singleton_ p)) in
m := (union_ !m (singleton_ p));
e := t
end
{ Inv(m,e,s,i,c) }
The results of our experiments on discharging proof with provers that can
be plugged into Why are given in Fig. 4 with a timeout (TO) set to 10s for an
Intel Pentium 4, 1.7GHz with 756Mb of memory. They reveal how hard it is
Guiding the Correction of Parameterized Specifications
183
Proof Obligations Simplify Ergo Yices Zenon haRVey-sat haRVey-fol CVC-lite
sendWriteInvalidate
yes
yes
yes
TO
no
unknown unknown
sendRead
yes
yes
yes
TO
no
unknown unknown
write
unknown no unknown TO
no
unknown unknown
Fig. 4. Results of discharging POs
to write a correct specification for first order provers that are not complete but
hopefully correct. They show that the write function does not seem to respect
the invariant: no prover succeeds in establishing the validity of the corresponding
proof obligation. In other words, the unsatisfiability of its negation, i.e.
Inv(m,
e, s, i, c) ∧
∃ p . (p ∈ c ∧ p ∈ e ∧ ¬Inv(m, e, s, i, c) m ← m ∪ {p}, e ← e \ {p} ,
(12)
can not be established by any prover.
The designer is then invited to correct the write operation or to strengthen
the invariant. If she/he guesses that the invariant is not inductive and uses an
automated method to strengthen it according to the write operation, she/he
obtains the following assertion
Inv (me, e, s, i, c) ∧ (∀ p . (p ∈ c ∧ p ∈ e) ⇒ Inv (m ∪ {p}, e \ {p}, s, i, c)) .
(13)
Although this approach is correct, it usually leads to invariance formulae that do
not make sense and, thus, produces what we absolutely want to avoid, namely
meaningless specifications.
The next section shows how to exhibit a counter-example, as a starting point
for debugging a specification.
4
Parameter Instantiation
This section suggests two methods for providing a counter-example from a (satisfiable) formula. The first method combines a result in model theory with a
constraint solving procedure. The second one, coarser, follows the intuition by
applying incremental approach.
4.1
Sort-Based Instantiation
Intuitively, the sets used in a specification often originate from a partitioning of
a more general set, and hence, are generally pairwise disjoint. Such sets can be
seen as sorts and we are left to check the satisfiability of a formula in a multisorted logic. For this formula, the Herbrand satisfiability method takes the sorts
into account and produces a finite model when it exists. Such model can be
seen as an instantiation of the initial set-theoretical formula. We now detail this
approach, composed of five steps.
184
J.-F. Couchot and F. Dadeau
The first step consists in syntactically extracting the sorts of the formula. Sets
declared as machine parameters are considered as primary sorts in a first phase.
Then, all abstract sets that are defined as subsets of a primary sort are checked
to be pairwise disjoint, and are considered as sorts in a second phase. Predicates
that define the sorts are then removed from the invariant formula and in the
inherited proof obligations.
The second step is a reduction of set-theoretical symbols: in the remaining
formula, all the uninterpreted symbols from the set-theory, except membership
(e.g. inclusion, union) are translated into formulas where the sole predicates are
equality between two elements of sort α and membership (by applying axioms
from (5) to (8) in the left to the right direction of implication). Similarly, equality
of arrays is reduced to equality between values by applying axiom (11).
The third step consists in assigning one sort to each variable. The two non
obvious cases are when a variable should have two sorts, which results from the
union of two sets, and when the variable belongs to a singleton. The former
case gives rise to splitting by introducing a fresh variable and duplicating the
corresponding subformula. The latter is interpreted by the fact that the variable
has the same sort as the element in the singleton. In what follows, p : τ denotes
that p is of sort τ .
Back to MESI. The PO corresponding to (12) in which sets are translated
into sorts is
((∃ p1 : s) ⇒ ¬(∃ p2 : m)) ∧
(∃ p : e) ∧ (∃ p3 : s) ∧
(∃ p4a : m) ∨ (∃ p4b : e)
where the last line is the result of the interpretation of (∃ p4 ∈ m ∪ {p}).
The fourth step exploits the multi-sorted Herbrand satisfiability method: we
classically start by considering a Skolem form of the formula and use the following
quantifier elimination result.
Theorem 1. ([26, Cor. 1]) Let τ be a sort such that there is no function symbol
f of signature τ1 ×· · ·×τn → τ , n 1, and let x be a variable of sort τ . Suppose
that ∀ x . Φ(x ) is a closed formula in
Skolem form, then ∀ x . Φ(x ) is satisfiable if
and only if the finite conjunction c∈Hτ Φ(c) is satisfiable, where Hτ is the set
of all well-sorted terms of sort τ .
Notice that this method might not be complete since all variables do not necessarily occur in the formula. In that case, the remaining set variables are supposed
to be the empty set.
Furthermore, in addition to giving a counter-example when validity is not automatically proved, this instantiation technique provides an enumerated specification as general as the parameterized one, since it yields an over approximation
of the specification parameters. For the details of the method, see [26]. Such
specification is called a general bounded specification in the following.
Guiding the Correction of Parameterized Specifications
185
Back to MESI. The multi-sorted Herbrand universe calculus gives the following instantiation
m ⊆ {p4a } ∧ e ⊆ {p4b , p} ∧ s ⊆ {p3 } ∧ i = ∅ ∧ c ⊆ {p, p3 , p4a , p4b }
(14)
for PO (12). When applied on other proof obligations, this calculus shows that a
set c of cardinality less or equal to 8 is sufficient to make the MESI be a general
bounded specification.
The fifth and last step uses the set-theoretical CLPS constraint solver [11] in
order to return a counter-example as explicit as possible. CLPS is natively able
to manage set-theoretical and relational structures based on the notion of pairs.
Thus, it manages relations and all kinds of functions. The native CLPS operators
are given in Fig. 5. All other operators from the B notation are rewritten in order
to match the solver syntax. For example, let X and Y two relations and consider
the B left overriding function X
− Y which defines the union between Y and
all the pairs (x , y) ∈ X such that x does not belong to the domain of X . Such
expression is substituted with the fresh variable Z , which is constraint by the
following set of literals:
{D 2 = dom(Y ), D 1 = dom(X ), D 3 = D 1–D 2, D 4 = D 3 X , Z = D 4 ∪ Y }
In this formula, dom and are native CLPS operators.
This solver uses an AC-3 arc consistency algorithm, meaning that the consistency of a constraint system can only be ensured by checking that a solution to
the constraint system described by this formula exists. Its strongest requirement
is the finiteness of the data domains, which is ensured by previous step.
Solver Primitive
A eq B
A neq B
A ins S
A nin S
S sub T
S#N
rdom(Q,S,R)
dom(S,R)
ran(S,R)
inv(Q,R)
power(T,S)
pcart(S,T,U)
couple(X,Y)
S union T
S inter T
S setminus T
Usual definition
Equality
Disequality
Membership
Non Membership
Inclusion
Cardinality
Domain Restriction
Domain
Range
Inverse relation
Powerset
Cartesian product
Couple
Union
Intersection
Set difference
Mathematical notation
A=B
A = B
A∈S
A ∈ S
S ⊆T
N = card (S )
Q =S R
S = dom(R)
S = ran(R)
Q = R −1
T = P(S )
S =T ×U
X → Y
S ∪T
S ∩T
S \T
Fig. 5. Operators of the CLPS set solver
186
J.-F. Couchot and F. Dadeau
Back to MESI. The ground formula (14) ∧ (12) is given to CLPS which concludes that it is satisfiable for m = ∅, e = {p}, s = {p3 } and i = ∅.
4.2
Incremental Instantiation
The instantiation technique presented in Sect. 4.1 is obtained by applying the
theorem given in [26]. This theorem requires several conditions to be applied.
When it is not applicable, our proposal is to automatically perform an incremental instantiation of the abstract sets.
The idea is to consider arbitrarily finite sets for each abstract set. These
sets must be finite and contain a large number of constants. For instance, one
can start from a partial Herbrand instantiation if this one is infinite. Thus, the
data domains are finite. The conjunction of the formula with this instantiation
constraint is then given to CLPS, as previously, to check its satisfiability.
Back to MESI. Suppose that the prover was unable to conclude on the example, an instantiation of c = {q1 , q2 , q3 , . . . , q
N } is computed by iterating over the
values of N . The instantiated formula is then given to CLPS which checks its
satisfiability.
Figure 6 shows the results of this experiment on PO formula (12), for which
we iterated over the size of c from 1 to 4. In this figure, each qi , 1 i 4, is a
fresh constant. The minimal counter-example is obtained for a set c containing
two elements, as in Sect. 4.1.
Value of c Satisfiability of (12)
Example
{q1 }
no
none
{q1 , q2 }
yes
s = {q1 }, e = {q2 }
{q1 , q2 , q3 }
yes
s = {q1 , q2 }, e = {q3 }
{q1 , q2 , q3 , q4 }
yes
s = {q1 , q2 , q3 }, e = {q4 }
Fig. 6. Results using an iterative instantiation on the example
The designer is left with the choice of strengthening the invariant or modifying
the operations. The next section shows how we can guide her/him in this choice.
5
Reaching the Counter-Example
The previous section ends with an instantiation of the state variables that makes
the invariant not inductive. Thus, all data in the B specification are finite and
different techniques, such as model-checking may be applied. We propose to first
integrate ProB [31] to find a counter-example. If the system is too complex for
the model-checking to be applied, we propose to use symbolic animation to reach
a counter-example. In this latter case, we use the symbolic animation engine of
the BZ-Testing-Tools [3,11] framework, in order to compute an execution trace
Guiding the Correction of Parameterized Specifications
187
that leads to the violation of the invariant. This engine has already been put
into practice in the framework of automated generation of boundary test cases
from set-theoretical B models [4,5].
The two animators impose a strong requirement that the model must be finite.
Such a requirement is compliant with our method, as presented in the previous
section which may produce a general bounded specification When the method
cannot be applied, an incremental instantiation of the parameters is repeatly
applied to check the reachability of the counter-example.
In this section, we first introduce ProB and we present its application on the
MESI example (Sect. 5.1). Then, in order to demonstrate the scalability of our
approach, we formalize the notion of symbolic animation (Sect. 5.2), we give
some efficiency keynotes on the BZ-Testing-Tools animator (Sect. 5.3) and we
show how to interpret the animation results, by pointing out of which part of
the specification should be modified (Sect. 5.4).
5.1
Using the ProB Model-Checker
ProB [31] is a model checker that relies on constraint solving technologies to
compute the transitions between states. From a given state, ProB compute all
the successors and checks whether the invariant is true or false within these
states. If the invariant is checked as false, it returns an execution path that
provides a counter-example. ProB offers heuristics to detect permutations in
states and is optimized to handle relatively large states spaces [32,33].
Back to MESI. We instantiate the MESI machine, setting the parameter c to
8 elements. ProB computes in 10 seconds the 270 states of the system execution, and does not find a violation of the invariant. Thus, we conclude that the
invariant is not inductive, but still, it is an invariant, which can not be violated
during the possible executions of the system.
Since ProB enumerates the complete reachability graph of the B specification
execution, it may face the problem of combinatorial explosion, when applied
to large systems. Therefore, we propose to use symbolic animation in order to
handle large state spaces.
5.2
Symbolic Animation
Symbolic animation consists in using an underlying constraint solver for representing symbolic states, each of which gather a possibly large number of concrete
states. Thus, it avoids the exhaustive enumeration of possible states, as done in
ProB [31], by providing an optimization that increases the scalability of the
approach.
A symbolic state is a constraints system over the state variables, that represents a set of concrete states, whose state variable values are the solutions
of this constraint system. Thus, a symbolic state is seen as a set of constraints
over the state variables. The consistency of these constraints guarantees that the
symbolic state represents at least one concrete state; there are as many concrete
state as solutions to the constraint system.
188
5.3
J.-F. Couchot and F. Dadeau
Efficiency Keynotes on the BZ-Testing-Tools Animator
This section presents the keynotes on the BZ-Testing-Tools animator. To show
how convenient the animator is for the task of checking the reachability of a
counter-example, we focus on its relevant features: behavior extraction and behavior animation heuristic.
First of all, the possible transitions are extracted from the B operations, as
a path through the control-flow graph of the considered operation. Intuitively,
an if . . . then . . . else . . . structure is split into two subparts, the first one representing the if . . . then part, the second one representing the else part.
Each B operation is then decomposed into behaviors, which represent a path
in the control-flow graph of the operation. A behavior b(P , X , X ) is expressed
as a predicate over P , X and X which respectively stand for the operation
parameters, the current values of state variables and their next values. Consider
for instance the B operation in Fig. 7, where x is a state variable of type BOOL.
It is composed of the two behaviors (p ∈ 0..1000 ∧ p ≤ 500 ∧ x = TRUE ) and
(p ∈ 0..1000 ∧ p > 500 ∧ x = FALSE ). Notice that on the MESI example,
given in Fig. 2, each operation has only one behavior.
Activating a behavior of an operation from a functional model is seen as
solving a constraint satisfaction problem between the state before the operation
and the constraints given by the transition of the operation. More formally, let
ρ1 (X ) be a symbolic state and let b(P , X , X ) be a behavior extracted from
an operation, symbolic state ρ2 (X ) resulting from the activation of b in ρ1 is
defined by
ρ2 (X ) = ρ1 (X ) ∧ ∃ P . b(P , X , X ).
The behavior b is said to be activable in ρ1 if and only if the resulting constraint
system is satisfiable.
Back to MESI. Consider the MESI example, with a finite set c arbitrarily
instantiated to c = {q1 , q2 , q3 , q4 }. Let ρ1 (m0 , e0 , s0 , i0 ) be
m0 = ∅ ∧ e0 = ∅ ∧ s0 = ∅ ∧ i0 = {q1 , q2 , q3 , q4 }
op1(p) =
ˆ
PRE
p ∈ 0..1000
THEN
IF p ≤ 500 THEN
x := TRUE
ELSE
x := FALSE
END
END
Fig. 7. A simple B operation with two behaviors
Guiding the Correction of Parameterized Specifications
189
i.e. the symbolic state representing the initial state. The set of symbolic states
resulting from the activation of the sendRead operation is defined by
ρ2 (m1 , e1 , s1 , i1 ) ≡ ρ1 (m0 , e0 , s0 , i0 ) ∧ ∃ p0 . p0 ∈ i0 ∧
m1 = m0 ∧ e1 = e0 ∧ s1 = s0 ∪ {p0 } ∧ i1 = i0 \{p0 }
which is satisfiable, if and only if
ρ2 (m1 , e1 , s1 , i1 ) ≡ ρ1 (m0 , e0 , s0 , i0 ) ∧ p0 ∈ {q1 , q2 , q3 , q4 } ∧
m1 = ∅ ∧ e1 = ∅ ∧ s1 = {p0 } ∧ i1 = {q1 , q2 , q3 , q4 }\{p0 }
is, where p0 is the Skolem constant of p0 . Such a predicate implicitly represents
4 concrete states, according to the value of p0 in {q1 , q2 , q3 , q4 }.
Symbolic animation consists in repeating this process at will, for each operation, until a pertinent state is reached. Notice that symbolic states are never
enumerated. This technique reduces the reachability graph size and delays combinatorial explosion. The BZ-Testing-Tools animator implements these principles.
It is provided with a Graphical User Interface, that makes it possible to validate
a B model. Nevertheless, it is also possible to use the API of the animator to
automatically animate a B model. In this case, the animation can be randomized, or guided by a target, reached by using heuristics as it is now described.
The heuristic aims at guiding the choice of behaviors –and, as the consequence,
of operations– to activate in order to reach the counter-example.
The counter-example trace computation uses the symbolic animation guided
by a “best-first” algorithm and a customized heuristic function. This algorithm
aims at defining whether a symbolic state is pertinent w.r.t. the given target or
not. The trace computation aims at reaching a state that satisfies the constraints
given by the predicate describing the counter-example. The parameters of the
activated operation are left unspecified until the search ends with a counterexample that instantiates them. The heuristic we use consists in computing the
distance from the current symbolic state to the target to reach, also considered
as a symbolic state. The distance between two symbolic states is evaluated as
sum of the distances between the symbolic values of all variables in these states.
A symbolic variable is defined by a domain and associated constraints depending on other variables. The distance between two symbolic variables (represented
by Diff in the Fig. 8) is evaluated to 0 if and only if the domains of the two
variables intersect. Otherwise, the distance depends on the type of the data, and
the proximity of the two domains.
Figure 8 illustrates the concept of distance between two domains. In this
figure, “VarDom” represents the variable domain, “CurrVarDom” is the domain
of the current state variable, “TargetVarDom” is the domain of the variable in
the targeted state, and “UnifiedDom” is the unification of the two variables, i.e.,
the intersection of the latter two domains. Such heuristic has been shown to beat
other approaches in symbolic animation [17].
Back to MESI. Running the counter-example search algorithm does not detect any counter-example for a depth of 6, in 17 seconds.
190
J.-F. Couchot and F. Dadeau
Fig. 8. Distance between two variables
Compared to ProB, this algorithm does not produce a better result on a small
example. Moreover, the result of the algorithm is partial (since it is bounded),
whereas in ProB it is absolute. Indeed, the computational complexity of the
algorithm is O(n d ) where n is the number of behaviors extracted from the B
machine operations, and d is the search depth. Nevertheless, this heuristic is
useful. First, it makes it possible to handle large systems, and thus, it is possible
to provide a result even when ProB fails. In addition, it is important to notice
that this algorithm only aims at quickly and efficiently finding a trace, when
it exists. If the trace does not exist, as in the MESI example, the computation
of all symbolic paths of a given depth has to be performed before concluding,
matching the worst case computational complexity.
5.4
Interpreting the Reachability Result
Basically, there are three possible issues for the animation. The first case is when
the animator ends after having reached the counter-example. In this case, the
formula claimed to be an invariant is not one, let-alone an inductive invariant.
The spurious operations may be corrected by strengthening their guards.
The second case is when the analysis ends on the general bounded specification with an unreachable counter-example, when the graph is small enough to
be completely explored. In this case, the method has computed the strongest
invariant, which is indeed inductive but may be meaningless for the specifier
(in the running example, it contains 270 states!). We propose that the specifier
strenghten the invariant by removing the states corresponding to the counterexample.
The third case is when the bounded animator gives an unreachability answer
for an arbitrarily instantiated specification: since reachability is undecidable, the
search depth is bounded, and so, it is possible that no counter-example trace will
be found. What does it mean if the invariant has not been checked as inductive?
The states that cause the invariant to be violated can simply be unreachable,
and the B specification is still correct.
Guiding the Correction of Parameterized Specifications
191
The answer depends on the goal of the specification. If the specification aims
at establishing B refinement properties, it is mandatory that the invariant is
strengthened to be inductive. If the specification aims at verifying safety properties or generating test cases, the guarantee that the invariant cannot be violated
for a given execution depth k may be sufficient. Even in a test generation process,
it is still possible to run the generated tests (whose size is greater than k ) on the
specification, and to check that no test provokes a violation of the invariant.
Back to MESI. We give to the animator the general bounded specification
MESI, such that c has cardinality less than or equal to 8. It concludes that the
counter-example cannot be reached. The designer is then invited to strenghten
the invariant by removing states where s and e are simultaneously non empty,
which is given by the new invariant
Inv type(m, e, s, i, c) ∧ (∃ p1 . p1 ∈ c ∧ p1 ∈ s) ⇒
(¬(∃ p2 . p2 ∈ c ∧ p2 ∈ m) ∧ ¬(∃ p3 . p3 ∈ c ∧ p3 ∈ e)) .
This invariant is both meaningful and inductive.
6
Related Work
To the best of our knowledge, the approach we present here is original and has
never been introduced previously.
Several works [7,13,26] have shown cases where all subtleties of a parameterized
system are already present in some instantiated version of it. As done in this paper,
these work strongly rely on the fact that the correctness of a small instantiated system implies the correctness of the parameterized one. Unfortunately, such methods
build a consistency proof by providing strengthened invariants which may be to involved for the designer to understand (it is even referred as invisible invariants in [7]
since they may not be seen). In this work, less ambitious but more pragmatic, the
model instantiation is computed thanks to sorts. By translating sets into sorts, we
follow the idea previously developed in [10].
Similar work exists on combining test generation and proof. In [30], the authors describe a process that aims at increasing the confidence in a Java program
that has not been proved correct w.r.t. its JML specification. Indeed, when the
prover fails to establish the correctness of a piece of code, a large suite of tests
cases is produced. The process is different from our approach, since we systematically compute a reachable counter-example. Moreover, we only focus on
the specification itself, without having to take a particular implementation into
account.
The work we present in this paper is also related to bounded model-checking
(BMC) [14], in which a model execution is computed until a given depth to check
whether different properties are satisfied. In practice, BMC has been applied
to the verification of safety properties [40]. Our work differs from the other
animation/model-checking approaches, such as [15,36,31,35], in the sense that,
for us, the animation is only employed to find a counter-example. Indeed, most of
192
J.-F. Couchot and F. Dadeau
the other approaches consider animation itself as the answer to the verification
problem. For us, animation is complementary to proof techniques. Moreover,
our proposal makes it possible to deal with a parameterized models, that cannot
be treated by classical animators without being first instantiated. From that
point of view, the trinity Proof-Instantiation-Animation proposed here is clearly
original.
7
Conclusion and Future Work
This paper has presenteed strategies of collaboration between provers and symbolic animators using constraint solving, in order to help the specifier dealing
with the answers given by these tools. The relevance of this help is illustrated in
the context of the correction of parameterized B machines.
First, the provers have to be automated, in order to avoid the hazard of having
to manually deal with some subtle proof obligations, that dismiss the modeller
from her/his initial specification work. Second, the goal of checking parameterized systems makes it mandatory to resort to theorem proving techniques. Third,
parameter-related data are a burden for all theorem provers. Even when the termination of the computation is experimentally observed, it cannot in general be
theoretically determined. Thus, it is sometimes necessary to stop the execution
of the prover if it seems to diverge. Fourth, the unavoidable instantiation of
parameters makes it possible to compute a counter-example, and an associated
execution trace, using advanced constraint solving techniques.
Among the tools we have considered, the Why tool is especially interesting,
since it addresses a large variety of provers, working on different theories. This
increases the chances for a proof obligation not checked by one of the provers to
be checked by another one.
For the future, we are curently implementing a complete tool chain that aims
at automatically checking the correctness of B invariants by combining proof
and constraint solving, as described in Fig. 1. This will make it possible for us to
validate our approach on realistic and industrial case studies. Separated experiments with Why tool [29] and BZ-Testing-Tools [3] that target the verification
or validation of large-scale systems are very promising.
References
1. Abrial, J.-R.: The B Book - Assigning Programs to Meanings, August 1996. Cambridge University Press, Cambridge (1996)
2. Abrial, J.-R., Cansell, D.: Click’n’prove: Interactive proofs within set theory. In:
Basin, D., Wolff, B. (eds.) TPHOLs 2003. LNCS, vol. 2758, pp. 1–24. Springer,
Heidelberg (2003)
3. Ambert, F., Bouquet, F., Chemin, S., Guenaud, S., Legeard, B., Peureux, F.,
Vacelet, N., Utting, M.: BZ-TT: A tool-set for test generation from Z and B using
constraint logic programming. In: Proc. of Formal Approaches to Testing of Software FATES 2002, co-located with CONCUR ’02, pp. 105–120, INRIA Technical
Report (August 2002)
Guiding the Correction of Parameterized Specifications
193
4. Ambert, F., Bouquet, F., Legeard, B., Peureux, F.: Automated boundary-value test
generation from specifications - method and tools. In: 4th Int. Conf. on Software
Testing, ICSTEST 2003, pp. 52–68 (2003)
5. Ambert, F., Bouquet, F., Legeard, B., Peureux, F., Py, L., Torrebore, E.: Automated Test Case and Test Driver Generation for Embedded Software. In: ICSSEA
- Int. Conf. on Software, System Engineering and Applications, December 2004,
pp. 34–49 (2004)
6. Armando, A., Ranise, S., Rusinowitch, M.: A rewriting approach to satisfiability
procedures. Journal of Information and computation 183, 140–164 (2003) Special
Issue on the 12th International Conference on Rewriting Techniques and Applications (RTA’01) (2003)
7. Arons, T., Pnueli, A., Ruah, S., Xu, J., Zuck, L.D.: Parameterized verification with
automatically computed inductive assertions. In: Berry, G., Comon, H., Finkel, A.
(eds.) CAV 2001. LNCS, vol. 2102, pp. 221–234. Springer, Heidelberg (2001)
8. Barrett, C., Berezin, S.: CVC Lite: A new implementation of the cooperating validity checker. In: Alur, R., Peled, D.A. (eds.) CAV 2004. LNCS, vol. 3114, Springer,
Heidelberg (2004)
9. Bert, D., Potet, M.-L.: La méthode B. École Jeunes chercheurs en programmation
(May 2003)
10. Bodeveix, J.-P., Filali, M., Munoz, C.: A Formalization of the B method in Coq
Available at http://www.csl.sri.com/papers/pbs2/
11. Bouquet, F., Legeard, B., Peureux, F.: A constraint solver to animate a B specification. International Journal on Software Tools for Technology Transfer 6(2),
143–157 (2004)
12. Bozzano, M., Bruttomesso, R., Cimatti, A., Junttila, T., van Rossum, P., Schulz,
S., Sebastiani, S.: MathSAT: Tight integration of SAT and decision procedures.
Journal of Automated Reasoning 35, 265–293 (2005)
13. Chou, C.-T., Mannava, P.K., Park, S.: A simple method for parameterized verification of cache coherence protocols. In: Hu, A.J., Martin, A.K. (eds.) FMCAD
2004. LNCS, vol. 3312, pp. 382–398. Springer, Heidelberg (2004)
14. Clarke, E., Biere, A., Raimi, R., Zhu, Y.: Bounded model checking using satisfiability solving. Formal Methods in System Design 19(1), 7–34 (2001)
15. Clarke, E.M., Grumberg, O., Peled, A.: Model Checking (CLA e 99:1 1.Ex). MIT
Press, Cambridge (1999)
16. ClearSy. Manuel de référence du langage B v.1.8.5. (2004) Available at
http://www.atelierb.societe.com/ressources/manrefb.185.fr.pdf
17. Colin, S.: Procédures de recherche en génération de tests à partir de modéles de
spécifications. PhD thesis, LIFC - University of Franche-Comté (2005)
18. Conchon, S., Contejean, E.: The Ergo automatic theorem prover (2006) Available
at http://ergo.lri.fr/
19. Couchot, J.-F., Déharbe, D., Giorgetti, A., Ranise, S.: Scalable automated proving and debugging of set-based specifications. Journal of the Brazilian Computer
Society 9(2), 17–36 (2003) ISSN 0104-6500
20. Déharbe, D., Ranise, S.: Light-weight theorem proving for debugging and verifying
units of code. In: 1st International Conference on Software Engineering and Formal
Methods (SEFM’03), pp. 220–228 (2003)
21. Detlefs, D., Nelson, G., Saxe, J.B.: Simplify: a theorem prover for program checking.
J. ACM 52(3), 365–473 (2005)
22. Doligez, D.: The zenon prover. Distributed with the Focal Project, at
http://focal.inria.fr/
194
J.-F. Couchot and F. Dadeau
23. Dutertre, B., de Moura, L.M.: A Fast Linear-Arithmetic Solver for DPLL(T). In:
Ball, T., Jones, R.B. (eds.) CAV 2006. LNCS, vol. 4144, pp. 81–94. Springer, Heidelberg (2006)
24. Filliâtre, J.-C.: Why: a multi-language multi-prover verification tool. Research Report 1366, LRI, Université Paris Sud (March 2003)
25. Fontaine, P.: haRVey-sat (2006) Available at
http://harvey.loria.fr/haRVey.html
26. Fontaine, P., Gribomont, E.P.: Decidability of invariant validation for parameterized systems. In: Garavel, H., Hatcliff, J. (eds.) ETAPS 2003 and TACAS 2003.
LNCS, vol. 2619, pp. 97–112. Springer, Heidelberg (2003)
27. Gordon, M.J.C., Melham, T.F. (eds.): Introduction to HOL (A theorem-proving
environment for higher order logic). Cambridge University Press, Cambridge (1993)
28. Holzmann, G.: The model checker SPIN. Software Engineering 23(5), 279–295
(1997)
29. Hubert, T., Marché, C.: A case study of C source code verification: the SchorrWaite algorithm. In: 3rd IEEE International Conference on Software Engineering
and Formal Methods (SEFM’05), pp. 190–199. IEEE Computer Society Press, Los
Alamitos (2005)
30. Ledru, Y., du Bousquet, L., Dadeau, F., Allouti, F.: A case study in matching
test and proof coverage. In: Proceedings of the Third International Workshop on
Model-Based Testing (MBT’07), co-located with ETAPS’07, to be pubilshed in
ENTCS (2007)
31. Leuschel, M., Butler, M.: Pro B: A model checker for B. In: Araki, K., Gnesi, S.,
Mandrioli, D. (eds.) FME 2003. LNCS, vol. 2805, pp. 855–874. Springer, Heidelberg
(2003)
32. Leuschel, M., Butler, M., Spermann, C., Turner, E.: Symmetry reduction for B
by permutation flooding. In: Julliand, J., Kouchnarenko, O. (eds.) B 2007. LNCS,
vol. 4355, pp. 79–93. Springer, Heidelberg (2006)
33. Leuschel, M., Turner, E.: Visualising Larger State Spaces in ProB. In: Treharne,
H., King, S., Henson, M.C., Schneider, S. (eds.) ZB 2005. LNCS, vol. 3455, pp.
6–23. Springer, Heidelberg (2005)
34. The Coq development team. The Coq proof assistant reference manual. LogiCal
Project, Version 8.0 (2004)
35. McMillan, K.L.: The SMV system. Carnegie-Mellon University (1992)
36. Miller, T., Strooper, P.: Animation can show only the presence of errors, never
their absence. In: ASWEC ’01: Proceedings of the 13th Australian Conference on
Software Engineering, p. 76. IEEE Computer Society Press, Los Alamitos (2001)
37. Owre, S., Rushby, J.M., Shankar, N.: PVS: a prototype verification system. In:
Kapur, D. (ed.) Automated Deduction - CADE-11. LNCS, vol. 607, pp. 748–752.
Springer, Heidelberg (1992)
38. Papamarcos, M.S., Patel, J.H.: A low-overhead coherence solution for multiprocessors with private cache memories. In: ISCA ’84: Proceedings of the 11th annual
international symposium on Computer architecture, pp. 348–354. ACM Press, New
York (1984)
39. Ranise, S.: Satisfiability solving for program verification: towards the efficient combination of Automated Theorem Provers and Satisfiability Modulo Theory Tools.
In: Ahrendt, W., Baumgartner, P., de Nivelle, H. (eds.) Proc. of the DISPROVING:
Non-Validity, Non-Provability, co-located with IJCAR 2006, pp. 49–58 (2006)
40. Sheeran, M., Singh, S., Stålmarck, G.: Checking safety properties using induction
and a sat-solver. In: Johnson, S.D., Hunt Jr., W.A. (eds.) FMCAD 2000. LNCS,
vol. 1954, pp. 108–125. Springer, Heidelberg (2000)
Proving Linearizability Via Non-atomic
Refinement
John Derrick1 , Gerhard Schellhorn2 , and Heike Wehrheim3
1
Department of Computing, University of Sheffield, Sheffield, UK
J.Derrick@dcs.shef.ac.uk
2
Universität Augsburg, Institut für Informatik, 86135 Augsburg, Germany
schellhorn@informatik.uni-augsburg.de
3
Universität Paderborn, Institut für Informatik, 33098 Paderborn, Germany
wehrheim@uni-paderborn.de
Abstract. Linearizability is a correctness criterion for concurrent objects. In this paper, we prove linearizability of a concurrent lock-free
stack implementation by showing the implementation to be a non-atomic
refinement of an abstract stack. To this end, we develop a generalisation
of non-atomic refinement allowing one to refine a single (Z) operation
into a CSP process. Besides this extension, the definition furthermore
embodies a termination condition which permits one to prove starvation
freedom for the concurrent processes.
Keywords: Object-Z, CSP,refinement, concurrent access, linearizability.
1
Introduction
Linearizability was defined by Herlihy and Wing [14] as a correctness criterion
for objects shared by concurrent processes. Like serialisability for database transactions, it permits one to view concurrent operations on objects as though they
occur in some sequential order. As Herlihy and Wing put it,
Linearizability provides the illusion that each operation applied by concurrent processes takes effect instantaneously at some point between its
invocation and its response.
Recently, Groves et al. [9,4] started work on verifying correctness (and more
specifically linearizability) of concurrent data structures using forward and backward simulations between I/O-automata. Concurrent data structures allow concurrent access by several processes, the only atomic operations being the reading
of variables and an atomic compare-and-swap (atomically comparing the values
of two variables plus setting a variable). In general concurrent access increases
the level of parallelism in the use of the data structure but potentially introduces
flaws due to individual atomic operations being applied out of order (with respect
to what was required by the design). Linearizability is a correctness condition
that is used to check whether such flaws have been introduced, it is, however, not
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 195–214, 2007.
c Springer-Verlag Berlin Heidelberg 2007
196
J. Derrick, G. Schellhorn, and H. Wehrheim
trivial to demonstrate that linearizability holds. The approach taken by Groves
et al. uses I/O-automata to model the concurrent implementation as well as an
abstract data structure in which operations are taken to be atomic. Correctness
of the implementation is shown via forward and backward simulations between
these automata (with proofs conducted in PVS), that is, the simulations guarantee linearizability, and the allowable orderings of concrete operations is described
via program counters.
In this paper, we investigate the use of (Object-)Z refinement [7,20] as a means
for showing the correctness, and in particular linearizability, of concurrent implementations of abstract data structures. However, in moving between an abstract
data structure and its concurrent implementation the granularity of operations
completely change, we therefore have to employ non-atomic refinement as the
correctness criteria. Non-atomic refinement as defined in [5,6] allows an abstract
operation to be implemented by a sequence of concrete operations. We generalise
this here since our objective is to encode the orderings of concrete operations not
via program counters or sequences but more naturally by process descriptions,
and we use CSP [15] to model this. The description of the concurrent implementation is thus given in a combination of CSP and Object-Z (in CSP-OZ
[11]). As a consequence, the existing definition of non-atomic refinement (only
allowing for fixed sequences of concrete operations) is generalised to include operation decompositions given as CSP processes. We prove that this definition of
non-atomic refinement guarantees linearizability.
In addition to linearizability, we study progress properties for concurrent data
structures. As the concurrent implementations need to guarantee interferencefreedom for concurrent accesses, operations which have already been partly carried out might need to be reset or retried. This potentially introduces starvation
of processes. While Groves et al. are concerned with proving safety properties,
i.e. linearizability, we, in addition, show that a particular form of starvation freedom to be also guaranteed by definition of non-atomic refinement that we use.
To do this, we introduce a condition on a variant in our simulation rules, similar
to variants employed in Event B [2]. The whole approach is exemplified by the
example of a concurrent stack implementation from [4].
The paper is structured as follows. The next section introduces our running
example of a concurrent stack modelled in a combination of Object-Z and CSP.
Section 3 sets the ground for our investigations, giving amongst others the existing definition of non-atomic refinement in Z, more specifically the forward
simulation rules. This definition is then generalised in Section 4 to allow refinements of a single operation into a whole CSP process. In Section 5 we show that
this generalised definition of non-atomic refinement guarantees linearizability.
The last section concludes and discusses related work.
2
An Abstract and a Concrete Stack
As an example of a data structure and its concurrent implementation we take
the lock-free implementation of a stack as treated in [4]. Abstractly, the stack is a
Proving Linearizability Via Non-atomic Refinement
197
sequence of elements of some given type T (containing some dedicated element
empty) together with two operations push and pop. Here, we will use plain
Object-Z [10,19] to describe the abstract stack and a combination of Object-Z
and CSP (CSP-OZ [11]) for the implementation.
In Object-Z, a class specification consists of a state schema defining the variables of the class, an initialisation schema giving constraints for initial states
and a number of operation schemas. An operation schema defines the variables
to be changed by the operation (in a Δ-list), declares inputs and outputs (with
? and !, respectively) and gives constraints on the allowed changes. Primed variables in these predicates refer to after states. For instance, operation pop below
is allowed to change stack , has an output variable v ! and defines the output to
be empty when the stack is empty, and to be the head of the stack otherwise.
In the former case the stack remains unchanged, in the latter the top element is
removed.
A
stack : seq T
Init
stack =
push
Δ(stack )
v? : T
pop
Δ(stack )
v! : T
stack = v ? stack
stack = ⇒
v ! = empty ∧ stack = stack
stack = ⇒
v ! = head stack ∧ stack = tail stack
Next, the stack is implemented by a linked list of nodes. A node consists of a
value val : T and a pointer next to the next node in the list. The pointer may also
be empty (value null ). A variable head is used to keep track of the current head
of the list. Operations push and pop are split into several smaller operations,
making new nodes, swapping pointers etc.. There is one operation atomically
carrying out a comparison of values and an assignment: CAS (mem, exp, new )
(Compare-and-swap) compares mem to exp; if this succeeds mem is set to new
and CAS returns true, otherwise the CAS fails, leaves mem unchanged and
returns false. Below the implementations of pop and push are first given in
pseudo-code. (Note, that pop continues on the next page.)
push(v : T):
1 n:= new(Node);
2 n.val := n;
3 repeat
4
ss:= Head;
5
n.next := ss;
pop(): T:
1
repeat
2
ss:= Head;
3
if ss = null then
4
return empty;
5
ssn := ss.next;
198
J. Derrick, G. Schellhorn, and H. Wehrheim
6
until CAS(Head,ss,n)
6
7
8
lv := ss.val
until CAS(Head,ss,ssn);
return lv
The push operation first creates a new node with the value to be pushed onto
the stack. It then repeatedly sets a local variable ss to head and the pointer
of the new node to ss. This ends once the final CAS detects that head (still)
equals ss upon which head is set to the new node n. Note that the CAS in push
does not necessarily succeed: in case of a concurrent pop, head might have been
changed in between. The pop is similar: it memorizes the head it started with
in ss, then determines the remaining list and the output value. If head is still
equal to ss in the end, the pop takes effect and the output value is returned.
For an Object-Z description of this, we first have to define an appropriate free
type for the linked list and operations for extracting values from nodes in the
list.
Node ::= nodeT × Node | null
first : Node →
T
∀ t : T , n : Node •
first node(t , n) = t
second : Node →
T
∀ t : T , n : Node •
second node(t , n) = n
collect : Node →
seqT
collect = λ N . if N = null then else first (N ) collect (second (N ))
collect (N ) constructs the sequence of nodes reachable from N . It is undefined for
cyclic structures. Since in our example cyclic structures are not used, we assume
all equations collect (N ) = stack to imply definedness of collect implicitly.
The class specifying the implementation of the stack contains an Object-Z part
describing all the operations of the above given pseudo-code. The numbering is
according to line numbers in the pseudo-code, but where we have sometimes
merged two operations into one (e.g., psh2 incorporates lines 1 and 2).
In addition to the Object-Z, we have a number of CSP process equations
describing the possible orderings of these operations. We use a small fragment
of CSP, specifically, → stands for the prefix operator of CSP (sequencing) and
2 is the external choice. The main process, main = U ||| O , specifies that the
push and pop operations are to be executed concurrently, since processes O and
U specify that every stack object should continously allow pop’s and push’s.
Finally, the CSP processes PUSH and POP model one execution of the above
pseudo-code programs, respectively.
C
main = U ||| O
U = PUSH ; U
O = POP ; O
PUSH = psh2 → Rep
Rep = psh4 → psh5 → (CASt psh → Skip
2 CASf psh → Rep)
Proving Linearizability Via Non-atomic Refinement
199
POP = pop2 → (pop3t → Skip
2 pop3f → pop5 → pop6 → (CASt pop → Skip
2 CASf pop → POP ))
head , sso, ssu, ssn, n : Node
lv : T
Init
head = null
psh2
Δ(n)
v? : T
n = node(v ?, null )
psh4
Δ(ssu)
psh5
Δ(n)
ssu = head
n = node(first n, ssu)
CASt psh
Δ(head )
CASf psh
head = ssu
head = ssu
head = n
pop2
Δ(sso)
sso = head
pop3t
v! : T
sso = null ∧ v ! = empty
pop3f
sso = null
pop5
Δ(ssn)
pop6
Δ(lv )
ssn = second sso
lv = first sso
CASt pop
Δ(head )
v! : T
CASf pop
head = sso
head = sso ∧ head = ssn
v ! = lv
The semantics of this combination of CSP and Object-Z can best be understood as a parallel composition of the CSP and the Object-Z semantics: at any
200
J. Derrick, G. Schellhorn, and H. Wehrheim
point in time there are certain operations which the CSP process currently allows and others which the Object-Z part allows; if an operation is allowed by
both the object can execute it and thereby progresses to a new Object-Z state
and a new (the remaining) CSP process. Note that the CSP process is making
no restrictions on the values of inputs and outputs, these solely depend on the
Object-Z part. For a formal definition of the semantics see [11].
The objective in this paper is to show that the data structure C is linearizable
with respect to A. Linearizability requires that each operation appears to occur
atomically at some point between its invocation and its response. For this, we
first have to fix a linearization point for every operation, saying which operation
in the implementation is the one where the effect ”seemingly instantaneous”
takes place. For both push and pop these are the CASt operations, and for pop
it is, in addition, pop3t . Once the linearization operation has been executed
the effect has taken place. For the proof of linearizability we proceed in two
steps: we first show that C is a non-atomic refinement of A (in a sense yet
to be defined) and then in general prove that non-atomic refinements imply
linearizability.
3
Background
The general idea of the correctness proof is to show linearizability via a refinement proof. A prominent property of the stack example is the fact that a single
abstract operation is split into several concrete operations. There are currently
two notions of refinement for Z (or Object-Z) which can cope with this issue:
weak refinement [8,7] and non-atomic refinement [5,6]. The former assumes that
all but one of these operations abstractly correspond to a skip, that is, has
no effect. The latter, however, allows one to really split an abstract operation,
here into a sequence of two concrete operations. This latter definition is thus
our starting point, however, one which we will later generalise to allow a concrete decomposition where several concrete operations are ordered according to
a CSP process. We thus start by explaining the current version of non-atomic
refinement as given in [5,6].
The following definition applies to pure Object-Z specifications C and A,
where we (as usual) use a blocking interpretation of preconditions. It assumes
that every abstract operation AOp is split into exactly two operations COp1 o9
COp2 . It extends the standard conditions of forward simulation with additional
conditions dealing with the new states where the sequence COp1 o9 COp2 has been
started but not yet terminated, where we record this information in a sequence S .
For example, S might be COp1 denoting the fact that COp1 o9 COp2 has begun
but not yet terminated. Furthermore, at the concrete level, these decompositions
might well be interleaved. Thus, DOp1 , say, occurs after COp1 but before COp2 ,
S would then be COp1 , DOp1 . For every such sequence we use a specific retrieve
relation R S , which records the partial effects which might already have been
achieved in the concrete specification.
Proving Linearizability Via Non-atomic Refinement
201
Definition 1
A specification C is a non-atomic forward simulation of the specification A if
there is a retrieve relation R such that every abstract operation AOp is recast
into a sequence of concrete operations COp1 o9 COp2 , and there is a family of
retrieve relations R S such that the following hold.
I CState • CInit ⇒ (∃ AState • AInit • R)
C R = R
S1. ∀ AState, CState, CState • R S ∧ COp1 ⇒ ∃ AState • ΞAState ∧ (R S COp1 )
S2 Start.
∀ AState; CState • R ⇒ (pre AOp ⇐⇒ pre COp1 )
S2 Continue.
∀ AState, CState • R S ∧ COp1 ∈ S ⇒ pre COp2
S3. ∀ AState, CState, CState • R S ∧ COp2 ⇒
2
COp1 ∈ S ∧ ∃ AState • AOp ∧ (R S \COp1 )
We briefly explain every condition. Condition I is the usual initialisation and
condition C describes a coupling between the retrieve relations: when the sequence S is empty, R S coincides with the usual retrieve relation. Condition S1
is used to record the started but not yet finished refinements in R S : once a COp1
has been executed we are in an intermediate state which is related to the same
abstract state as before, however, under a retrieve relation R S with COp1 attached to the end of the sequence. The conditions S2 are applicability conditions:
the start condition guarantees that COp1 can be executed whenever the corresponding abstract operation is enabled, and the continue condition guarantees
that started refinement may always be completed. Condition S3 (correctness
condition) rules out that refinements can be started ”in the middle”, i.e., that
a COp2 occurs with no previous (uncompleted) COp1 , and in addition does the
matching with the abstract operation. It furthermore (upon completion of the sequence) removes the first operation from R S . These conditions are schematically
represented in Figure 1.
AOp
AInit
I
<>
R=R
R
s
R
s^<COp1>
R
s
R
CInit
COp1
Condition I and C
Condition S1
COp1
COp2
Condition S3
Fig. 1. Conditions required for non-atomic refinement
S \ COp1
202
J. Derrick, G. Schellhorn, and H. Wehrheim
Examples of the definition of non-atomic refinement are given in [6], which
also shows that it is sound with respect to an action refinement definition of
CSP failures refinement.
Our aim is to derive a definition of non-atomic refinement that is (i) applicable
to examples such as the stack, and (ii) guarantees linearizability. For Definition
1, linearizability is already guaranteed: if a concrete specification has executions
where operations interfere in an undesired way, it is not possible to match the
concrete operations with the abstract specification and the conditions for this
non-atomic refinement are not satisfied. However, this notion of non-atomic refinement isn’t applicable to our example as it stands: we need to split abstract
operations into CSP processes, not just sequences of two operations.
In the next section, we generalise Definition 1 to derive a definition of nonatomic forward simulation that ensures linearizability. Before doing so we first
have to define some notations about CSP processes that we need later in the
paper.
Notation and Conventions. We assume that the abstract operation to be split
will always be named AOp, its CSP process is AOP . The operations in AOP
are usually COp1 , . . . , COpn . In our example, AOp might be push and the CSP
process PUSH would then be AOP . In the CSP process describing the refinement
of an abstract operation we only use the CSP fragment consisting of →, ;
(sequencing), 2 (external choice) and process calls to occur. Hence we essentially
allow regular expressions here. These CSP processes are then combined using
interleaving (|||, parallel composition with no synchronisation). In the CSP terms
we will only have operation names, never values of inputs and outputs. We
assume the main process of our specification to be defined as main = Q1 || . . . ||
Qn , where every Qk is Qk = AOPk ; Qk . Thus all implementations of abstract
operations are running in parallel, AOPk describes one execution of the abstract
operation’s implementation.
Definition 2
The traces (viz: executions) of CSP processes are defined via its operational semantics (see e.g., [18]). The set of terminating traces of a CSP process P is
√
Term(P ) = {tr | tr ∈ traces(P )}. An operation op itself is terminal if it
is last in a terminal trace: op = last(tr ) for some tr ∈ Term(P ), otherwise it is
non-terminal.
The initial operations of some CSP process P are denoted by init(P ) = {Op |
P −Op
−→ }, and the CSP processes after executing a trace tr are P after tr = {P |
tr
P −−
2
→ P }. We let init be defined on sets of processes as well.
For example, terminated traces of PUSH include psh2, psh4, psh5, CASt psh
as well as psh2, psh4, psh5, CASf psh, psh4, psh5, CASt psh, and CASt psh is the
only terminal operation of PUSH .
For POP we have, e.g., init (POP ) = {pop2}, and POP after pop2, pop3f ,
pop5 is pop6 → (CASt pop → skip 2 CASf pop → POP ).
Proving Linearizability Via Non-atomic Refinement
4
203
Generalised Non-atomic Refinement
There are several aspects we need to take into account when we generalise nonatomic refinement from a decomposition of two operations in sequence to arbitrary CSP processes. The most important point is that when an arbitrary CSP
process is used, it may restrict the allowed order of operations (over and above
a fixed sequential decomposition). Hence for the applicability and correctness
conditions we have to look at both the current Z state and the current CSP
process.
Definition 3 below is based on the same ideas as the previous definition of
non-atomic refinement: we have a family of relations R S , R representing the
usual abstraction relation and for a nonempty S , R S are retrieve relations for
the intermediate states in the concrete implementation.
The sequence S represents initial parts of the CSP processes, where operations
coming from different abstract operations can be mixed (depending on the order
in which they have taken place). For instance, a possible sequence S for our
stack example could be psh2, psh4, pop2, psh5 (i.e., the parts of PUSH and
POP that have already been executed). When projecting such a sequence onto
the alphabet of a particular CSP process (i.e., S α(AOP )), we see the projection
to the operations belonging to one abstract operation.
In deriving the correct forward simulation conditions there are different situations which have to be covered:
S2 Start. S α(AOP ) might be empty for some AOP , that is, there is currently
no refinement started for AOP . In this situation we have to guarantee that
the process AOP can start if and only if the abstract operation is enabled.
S2 Continuation. S α(AOP ) might not be empty but also is not a terminated
trace, and here we need to ensure continuation.
S1 and S3. Some started but not yet terminated trace in a refinement is continued with a concrete operation (note that this requires the operation to
be enabled in the current state as well as allowed next in the CSP process).
If this continuation does not lead to termination, this is abstractly matched
by an empty step, however, we record the effect of the operation in R S .
If this continuation leads to termination, the correct match with a corresponding abstract operation has to take place and the whole completed trace
is removed from S (condition S3).
We are led to the following definition, where conditions C and I are the coupling
of abstraction relations and the initialisation condition, respectively. Condition
S4 is discussed below.
Definition 3. A specification C is a generalised non-atomic forward simulation
of the specification A if there is a retrieve relation R such that every abstract
operation AOp is recast into a CSP process AOP , and there is a family of simulation relations R S and an ordering relation <WF such that the following hold.
204
J. Derrick, G. Schellhorn, and H. Wehrheim
C R = R
I ∀ CState • CInit ⇒ (∃ AState • AInit ∧ R )
S1 ∀ non-terminal COpi • ∀ AState; CState; CState •
R S ∧ COpi ∧ (S COpi ) α(AOP ) ∈ traces(AOP )
⇒ ∃ AState • ΞAState ∧ (R S COpi )
S2 Start
∀ AState; CState •
R S ∧ (S α(AOP ) = ) ⇒ (preAOp ⇔ ∃ COpi ∈ init (AOP ) • preCOpi )
S2 Continuation
∀ AState; CState • R S ∧ S α(AOP ) ∈ Term(AOP ) ∧ (S α(AOP ) = )
⇒ ∃ COpi ∈ init (AOP after (S α(AOP ))) • pre COpi
S3 ∀ terminal COpt • ∀ AState; CState; CState •
R S ∧ COpt ∧ (S COpt α(AOP ) ∈ Term(AOP )
⇒ ∃ AState • AOp ∧ (R S \(S COpt α(AOP )) )
S4 ∀ AState; CState; CState •
R S ∧ COpi ∧ S α(AOP ) = ∧ (S COpi ) α(AOP ) ∈ traces(AOP )
2
⇒ (S COpi , CState ) <WF (S , CState)
Condition S4 is a completely new condition ensuring progress in a refinement.
To understand the need for a progress condition, consider the following ’decomposition’ of a single abstract operation AOp, given here as a CSP process:
P = Invoke → (COp1 → P
2
COp2 → skip)
It is easy to define R = R and a family of simulations R Invoke
= R Invoke,COp1 = R Invoke,COp1 ,COp1 = . . . pictured as in Figure 2.
Without condition S4 this example satisfies the requirements of a generalised
forward simulation, and thus would be seen as an acceptable implementation of
AOp, even though we have introduced non-termination - potentially Invoke and
COp1 can be applied indefinitely.
Fig. 2. Potential non-termination in a non-atomic refinement
Proving Linearizability Via Non-atomic Refinement
205
Condition S4 ensures that this type of non-progression cannot be introduced,
not even when several operations are in progress. It requires the existence of a
well-founded ordering over S ×CState (that is, the existence of a well-founded set
(WF , <WF )) such that every ’progression’ lowers its value, and S4 expresses this
requirement. The precondition S α(AOP ) = excludes invoking operations
that start a new process from this condition.
Taken together, the roles of the individual conditions can be expressed as in
Figure 3.
Fig. 3. The roles of the conditions in a generalised forward simulation
We now show how the definition can be applied to our running example of a
concurrent implementation of a stack.
4.1
Example
The definition of generalised non-atomic forward simulation requires, in addition to the standard retrieve relation between abstract and concrete states, the
existence of a number of simulation relations for each abstract operation being decomposed. To derive these, one needs to understand how the concurrent
implementation evolves as it performs its individual steps.
Consider first push. This first performs the updates as pictured in Figure 4.
Initially, and after every completed push and pop, head in C should point to
the same list as stack , we thus have:
R
AState
CState
collect (head ) = stack
The effect of any of the concrete components psh2, psh4 and psh5 is to update
the concrete state, but still preserving the invariant collect (head ) = stack . The
206
J. Derrick, G. Schellhorn, and H. Wehrheim
Fig. 4. The concrete push operation
latter can only change after a ’visible’ concrete effect, that is, a linearisation
point. We thus have the following.
R psh2
AState
CState
v? : T
R psh2,psh4
AState
CState
v? : T
collect (head ) = stack
n = node(v ?, null )
collect (head ) = stack
n = node(v ?, null )
R psh2,psh4,psh5
AState
CState
v? : T
collect (head ) = stack
ssu = head
n = node(first v ?, ssu)
R psh2,psh4,psh5,CASf psh = R psh2
R psh2,psh4,psh5,CASt psh = R
Note that head = ssu is established by psh4 but not recorded in R psh2,psh4 ,
since executing CASt pop will destroy this property. We do not need this property
since CASt psh checks if the head is still ssu. Note also that we record and
preserve the input value v ? received in psh2 in the simulation relations. Thereby
we are able to move it forwards through the triangular diagrams set up by
condition S1 until we are able to check equality with the abstract input in
condition S3.
The relations for push are conjunctively combined with simulations for pop.
These latter ones can be derived in a similar fashion where R = R pop2 , and
others such as
Proving Linearizability Via Non-atomic Refinement
R pop2,pop3f
AState
CState
R pop2,pop3f ,pop5
AState
CState
collect (head ) = stack
sso = null
collect (head ) = stack
sso = null
ssn = second sso
R pop2,pop3f ,pop5,pop6
AState
CState
R pop2,pop3f ,pop5,pop6,CASf pop
AState
CState
collect (head ) = stack
sso = null
ssn = second sso
lv = first sso
collect (head ) = stack
sso = head
207
Note that at the end of the loop, when CASf pop has just been executed, we
need the information that the test has been negative1 . Again:
R pop2,pop3f ,pop5,pop6,CASf pop,pop2 = R pop2
R pop2,pop3f ,pop5,pop6,CASt pop = R = R pop2,pop3t
The superscripts of the simulations intuitively correspond to values of the
program counter of the pseudo-code for push and pop given in Section 2.
Given any S ∈ init (PUSH ||| POP ) the necessary superscript S1 for the
push operation is the longest postfix of S α(PUSH ) that is a prefix of
psh2, psh4, psh5, CASt push or psh2, psh4, psh5, CASf psh. Similarly S2 is defined as the longest postfix of S α(POP ) that is a prefix of one of pop2, pop3t ,
pop2, pop3f , pop5, pop6, CASf pop or pop2, pop3f , pop5, pop6, CASt pop. The
family R S of relations needed for the proof obligations is defined as
R S := R S1 ∧ R S2
It is easy, but tedious, to verify conditions C, I, S1, S2 start, S2 continuation and S3.
The basic idea to establish termination via condition S4 is that starting the
push loop will establish head = ssu in psh4. The equation will subsequently be
invalidated only when the pop process executes CASt pop. But then the POP
process has terminated, and the next iteration of the push loop will terminate
too, since an intervening CASt pop is no longer possible.
This fact can be exploited to define an order that decreases in every step as
follows:
– first, the number of instructions left that the push/pop process must execute
to reach the end of the push/pop loop is relevant, since it decreases during
1
This is required for the lifeness proof only. For safety R would be sufficient.
208
J. Derrick, G. Schellhorn, and H. Wehrheim
execution of every instruction within the loop. This distance to the end of
the loop can be defined as
pushdist (S ) := 4 − length(S1 ),
popdist (S ) = 5 − length(S2 )
– second, the pop loop (5 instructions) will be executed once more, when the
push program is in its “critical section” after ssu has been set to be head in
psh4, but when head = ssu is false again. Therefore we define a predicate
critpush(S ) which is true, if last(S1 ) is one of psh4 or psh5. Dually, predicate
critpop(S ) is true iff last(S2 ) ∈ {pop3f , pop5, pop6, CASf pop}.
– Finally, if none of the two processes has finished, then as argued above, one of
them can modify head , so that the other must go once more through the loop
(4 or 5 instructions). That the push processes has finished is characterised
by last(S1 ) = CASt psh and similarly for the pop process as last(S2 ) ∈
{pop3t , CASt pop}.
Altogether we can define an upper bound on the maximal number of instruction
needed to finish both loops (identifying boolean values true and falsewith1 and 0)
#(S , CState) :=
pushdist (S ) + popdist (S )
+ 4 ∗ (head = ssu ∧ critpush(S ))
+ 5 ∗ (head = sso ∧ critpop(S ))
+ 5 ∗ (last(S1 ) = CASt psh ∧ last(S2 ) ∈ {pop3t , CASt pop})
and use this number to define
(S , CState ) <WF (S , CState)iff #(S , CState ) < #(S , CState)
The order decreases for every step executed by the pop process.
– For CASt pop and pop3t popdist (S ) decreases and head = ssu may become
true. This may add 4 when critpush(S ) holds, but then last(S1 ) = CASt psh,
so the last summand no longer adds 5, since last(S2 ) enters {pop3t , CASt pop}.
– When pop3f , pop5 or pop6 are executed, popdist (S ) decreases and everything
else remains constant.
– Executing pop2 has only to be considered when the loop is repeated, i.e. when
S2 = pop2, pop3f , pop5, pop6, CASf pop. In this case R S2 implies head =
sso (CASf pop has just been executed) and popdist (S ) increases from 0 to 4.
The critical section of pop is entered, and pop2 sets sso = head . Therefore
the fourth summand no longer adds 5 and #(S , CState) decreases in this
case too.
For push operations the argument is as follows:
– For CASt psh pushdist (S ) decreases and head = sso may become true. This
may add 5 when critpop(S ) holds, but then last(S2 ) ∈ {pop3t , CASt pop}.
Since last(S1 ) enters CASt psh, the last summand no longer adds 5.
Proving Linearizability Via Non-atomic Refinement
209
– When psh4 or psh5 are executed pushdist (S ) decreases. All other summands
remain unchanged: for psh4 citpush(S ) becomes true, but since head = ssu
after the operation, the third summand remains unchanged.
– Executing CASf psh restarts the loop of the push program, and increases
pushdist (S ) from 1 to 3. Since head = ssu remains true and critpush(S )
becomes false, the third summand no longer adds 4.
– Executing psh2 does not need not to be considered, since it is only executed
to start a push (when S α(PUSH ) = ).
Summarising this proves condition S4: every step that does not start a new push
or pop process leads to a smaller pair (S , CState). With no new processes started
the running ones will terminate after a finite number of steps, livelock is absent.
5
Linearizability
Finally, we come to linearizability. Rather than attempt an additional proof, we
show linearizability by proving that generalised non-atomic refinement implies
it. The results of the previous section are then enough to show all we set out to
do.
For the rest of this section we assume that A = (AState, AInit , (AOpj )j ∈J )
is the Z component of the abstract specification. A is implemented by a specification C which includes a CSP component. Then, for every abstract operation
AOpj we have some CSP process AOP which consists of a number of concrete
operations from α(AOP ) implementing it. The set of operations (COpi )i∈I is
thus partitioned into a disjoint set of operations, one for each abstract operation.
To prove that refinement implies linearizability, we need to formalize the latter,
which we do by realising that it is a correctness criterion which requires a comparison of histories or runs of specifications. Thus we need to give an operational
semantics defining the runs of our classes, and we do this now.
Definition 4. Let C be a a combined CSP and Object-Z specification with some
dedicated main process main and some Object-Z part (CState, CInit , (COpi )i∈I ).
A run of C is a transition sequence
COp .in .out
COp .in .out
0
0
i1
1
1
0
(cs0 , P0 ) −−−−i−
−−−−−
→ (cs1 , P1 ) −−−−−
−−−−−
→ ...
such that
– initialisation: cs0 ∈ CInit and P0 = main, and
COpi
j
Pj +1 .
– succession: (csj , inj , outj , csj +1 ) ∈ COpij and Pj −−−−→
COp .in .out
COp .in .out
0
0
i1
1
1
0
From a run (cs0 , P0 ) −−−−i−
−−−−−
→ (cs1 , P1 ) −−−−−
−−−−−
→ . . . we can derive
2
its history H = COpi0 .in0 .out0 COpi1 .in1 .out1 . . ..
Note that the in’s and out ’s can also be empty. The difference between the histories and traces of a CSP process is that the former include input and output values.
210
J. Derrick, G. Schellhorn, and H. Wehrheim
We write traces(H ) to denote the sequence of operation names, without any input and output values. We assume that there are no τ -transitions generated from
the CSP part, that is, the Object-Z and CSP components progress jointly, which
can be guaranteed if we exclude internal choice from the CSP fragment used, and
use a specific semantics for process identifiers. For specifications without a CSP
process, runs are defined similarly, simply leaving out the CSP component.
For linearizability we have to fix when an operation starts and when it ends.
Thus we assume that we have fixed operations standing for the invocation and
the return of an abstract operation. For instance, pop2 is the invocation of an
abstract Pop and pop3t and CASt pop are possible returns. Inputs are passed
upon invocation and outputs upon return. Particular instantiations of operations
with inputs or outputs give us events: for example, pop2.5 and pop3t .empty are
possible events. The set of all invocationevents is Inv , those specific to some
operation AOp are Inv (AOp), i.e., Inv = j ∈J Inv (AOpj ). Similarly, Ret is the
set of all return events and Ret (AOp) those of some operation AOp.
Definition 5. A history is sequential if it can be divided into subsequences belonging to one abstract operation AOp, such that they start with an invocation
from Inv (AOp), end with a return from Ret (AOp) and, in between, have only
operations of α(AOP ) (this is the completed part). The last such subsequence
can possibly end without being completed (a pending operation). The history is
complete if every invocation operation is eventually followed by a corresponding
return.
2
For example, H = psh2.2, psh4, pop2, psh5, CASt psh, pop3f , psh2.8 is not sequential since in the initial subsequence psh2.2, psh4, although psh2.2 ∈
Inv (Push), psh4 is not a return of Push.
In general, histories need not be sequential but might contain arbitrary interleavings of implementations of (abstract) operations (as far as the specification
allows). A history H is thus an interleaving of some sequential histories, each describing the invocations of one operation which currently have taken place. Some
invocations can be completed (viz. followed by a return), but others cannot. We
let rem(H ) denote those subsequences of H containing only the non-completed
parts. For instance, for H = psh2.2, psh4, pop2, psh5, CASt psh, pop3f , psh2.8
the remaining non-completed part is rem(H ) = pop2, pop3f , psh2.8. This is
almost those part of the current run that we keep in the sequence S of our relations R S . Almost, but not quite, since we do not have values of inputs and
outputs in S . We let rem (H ) be the sequence without input and output values.
For linearizability, we are interested in the global order of abstract operation
execution, and this will be determined by the order of their linearization points,
which - in our case - are the terminal operations. This gives rise to the following
notion of equivalence on histories.
Definition 6. Two histories H1 and H2 are equivalent iff the following hold:
1. H1 Ret = H2 Ret and
2. ∀ AOp • H1 Inv (AOp) = H2 Inv (AOp).
2
Proving Linearizability Via Non-atomic Refinement
211
Requirement (2) states that the individual operations are invoked with the same
inputs. Requirement (1) states a similar property for returns and outputs (thus
the same inputs lead to the same outputs), and, in addition, requires that the
overall ordering of returns is the same in H1 and H2 . Strictly speaking, this
is a little stronger than is required by linearizability (which only requires that
the partial orders defined by returns and invocations are consistent), but it is
guaranteed by non-atomic refinement and easier to state.
Definition 7. A history H is linearizable if it can be extended by zero or more
events to give a history H such that
1. H is complete, and
2. H is equivalent to some complete sequential history G.
2
A specification is linearizable if all its histories are.
This allows us to finally state the result.
Theorem 1. Let A, C be Object-Z specifications, C with and A without a CSP
component. If C is a generalised non-atomic refinement of A, then C is linearizable.
Proof
We show that
1. every history H of C can be completed to some history H ,
2. for H there is some corresponding history HA of A,
3. from HA we can easily construct a sequential history G of C which is equivalent to H .
Proof of 2):
Let H be a complete history and R S the family of retrieve relations proving C
to be a generalised non-atomic refinement of A. For the history H there is an
associated run
COp0 .in0 ,out0
(cs0 , P0 ) −−
−−−−−−−−
→ (cs1 , P1 ) . . .
We inductively show that we can construct a corresponding run of A.
Base case. Using condition I we can find a state as0 such that as0 ∈ AInit and
(as0 , cs0 ) ∈ R .
Induction step. For our induction step we assume the following hypothesis
(which is also fulfilled by the base case). The current CSP process is always
of the form Pk = Pk ,1 ; Q1 || . . . || Pk ,n ; Qn . If we have constructed the
COp0 .in0 ,out0
abstract run as0 −−
−−−−−−−−
→ as1 . . . ask and have a history Hk so far, then
trace(Hk )
we have for S = rem (Hk ) that (ask , csk ) ∈ R S , main −
→ Pk and for
−−−−−−
trace(H ) α(AOP )
j
all j , 1 ≤ j ≤ n, AOPj −−−−−−k−−−−−−−
→ Pk ,j .
k
Pk +1 and (csk , ink ,
By definition of the semantics we know that Pk −COp
−−−
→
S α(AOP )
j
outk , csk +1 ) ∈ COpk . Assume COpk ∈ α(AOpj ). Since AOPj −−−−−−−−
→
Pk ,j we get (S COpk ) α(AOPj ) ∈ traces(AOPj ). Now we have to
consider two cases:
212
J. Derrick, G. Schellhorn, and H. Wehrheim
– COpk is non-terminal:
Then by condition S1 of the refinement (ask , csk +1 ) ∈ R S COpk and the
abstract run is not extended further.
– COpk is terminal:
k
k
Pk +1 and hence (definition of terminal) Pk ,j −COp
We know Pk −COp
−−−
→
−−−
→
skip and (S COpk ) α(AOPj ) ∈ Term(AOPj ). By condition S3 of
the refinement we thus find ask +1 such that for ink being the input value
of the last invocation stored in R S and outk being the output value in
COpk .outk we have (ask , ink , outk , ask +1 ) ∈ AOPj and (ask +1 , csk +1 ) ∈
R S \((S COpk )α(AOPj )) .
Proof of 1):
Let H be a non-completed history of C . Consider its run, ending in state csk .
With the same argument as above we can construct a corresponding abstract
run of A, i.e., we have a state ask and a relation R S such that (ask , csk ) ∈ R S
and S has all the properties we assumed in the induction above. Let AOpj
be an operation whose implementation is not completed. Then S α(AOPj ) ∈
Term(AOPj ) nor is S α(AOPj ) = . Hence by condition S2 Continuation
there is a COpi ∈ α(AOPj ) which is enabled and the run can be continued
with this operation. By condition S4 this continuation of one abstract operation
eventually ends; then we continue with the next pending operation.
Proof of 3):
Straightforward: the abstract sequence constructed in 2) has an ordering consistent with the returns and has the same inputs and outputs. Thus we just
construct the corresponding sequential run out of it; its history will be equivalent to the one we started with.
2
This completes the proof that generalized non-atomic refinement implies linearizability, and that, for example, our concrete implementation of the stack
possesses this property.
6
Conclusion
There are a number of (related) approaches to showing that concurrent implementations are correct. To some extent these depend on the mechanisms used in
the algorithms, for example whether locks are used to provide critical sections.
Our starting point is the recent work of Groves and Colvin who have been
considering verification of concurrent implementations which use ’compare and
swap’ instructions to avoid the potential bottlenecks of lock-based algorithms.
Specifically, we have taken the core of the algorithm in [4] and reformulated it
using an integration of Object-Z and CSP. In [4] specifications are based on two
IO-automata. One roughly corresponds to our concrete model with interleaved
runs, while the other corresponds to runs with sequential histories G that we
construct in the linearization proof of Section 5. Linearization is shown using
refinement of IO Automata using forwards and backwards simulation and was
Proving Linearizability Via Non-atomic Refinement
213
mechanized in PVS. The basic proof principle common to our and their approach
is induction over the length of histories.
However, our approach differs from theirs, in that we start with an abstract
level containing atomic stack operations. We also have embedded sufficient conditions into our generalised forward simulation so that it alone guarantees both
refinement as well as linearizability.
Further work by Groves and Colvin includes [12], where they verify an improved version of an algorithm of Hendler et al [13] (which in turn extends the
algorithm of [4]) using a new approach based on action systems. This approach,
like ours starts with an abstract level of atomic push and pop operations.
The approach uses a different proof technique than our and their earlier work.
Specifically, it works by induction over the number of completed abstract runs
(traces in Term(POP ) or Term(PUSH )) contained in a history, and it is based
on the approaches of Lipton [17] and Lamport and Schneider [16].
Both [4] and [12] consider safety only, while we also consider absence of livelock. For action systems, the extension of the framework of [16] to considering
termination described in [3] should be analogous to our consideration of livelock.
Additional relevant work in state-based formalisms includes [1], where the
correctness of a concurrent queue algorithm using Event B is shown. There, instead of verifying a given implementation, correctness is achieved by construction
involving only correct refinement steps.
Acknowledgements
We would like to thank Simon Bäumler for discussions on ideas in this paper.
John Derrick was supported by the Leverhulme Trust via a Research Fellowship
for this work.
References
1. Abrial, J.-R., Cansell, D.: Formal Construction of a Non-blocking Concurrent
Queue Algorithm (a Case Study in Atomicity). Journal of Universal Computer
Science 11(5), 744–770 (2005)
2. Abrial, J.-R., Cansell, D., Mery, D.: Refinement and Reachability in Event B.
In: Treharne, H., King, S., Henson, M.C., Schneider, S. (eds.) ZB 2005. LNCS,
vol. 3455, pp. 222–241. Springer, Heidelberg (2005)
3. Back, R.-J.: Atomicity refinement in a refinement calculus framework. Reports on
Computer Science and Mathematics 141, Abo Akademi (1993)
4. Colvin, R., Doherty, S., Groves, L.: Verifying concurrent data structures by simulation. ENTCS 137, 93–110 (2005)
5. Derrick, J., Wehrheim, H.: Using coupled simulations in non-atomic refinement.
In: Bert, D., Bowen, J.P., King, S. (eds.) ZB 2003. LNCS, vol. 2651, pp. 127–147.
Springer, Heidelberg (2003)
6. Derrick, J., Wehrheim, H.: Non-atomic refinement in Z and CSP. In: Treharne, H.,
King, S., Henson, M.C., Schneider, S. (eds.) ZB 2005. LNCS, vol. 3455, Springer,
Heidelberg (2005)
214
J. Derrick, G. Schellhorn, and H. Wehrheim
7. Derrick, J., Boiten, E. (eds.): Refinement in Z and Object-Z: Foundations and Advanced Applications, May 2001. Formal Approaches to Computing and Information
Technology. Springer, Berlin Heidelberg (2001)
8. Derrick, J., Boiten, E., Bowman, H., Steen, M.: Specifying and Refining Internal
Operations in Z. Formal Aspects of Computing 10, 125–159 (1998)
9. Doherty, S., Groves, L., Luchangco, V., Moir, M.: Formal verification of a practical
lock-free queue algorithm. In: de Frutos-Escrig, D., Núñez, M. (eds.) FORTE 2004.
LNCS, vol. 3235, pp. 97–114. Springer, Heidelberg (2004)
10. Duke, R., Rose, G., Smith, G.: Object-Z: A specification language advocated for the
description of standards. Computer Standards and Interfaces 17, 511–533 (1995)
11. Fischer, C.: CSP-OZ - a combination of CSP and Object-Z. In: Bowman, H., Derrick, J. (eds.) Second IFIP International conference on Formal Methods for Open
Object-based Distributed Systems, July 1997, pp. 423–438. Chapman & Hall, Sydney (1997)
12. Groves, L., Colvin, R.: Derivation of a scalable lock-free stack algorithm. ENTCS
(To appear, 2007)
13. Hendler, D., Shavit, N., Yerushalmi, L.: A scalable lock-free stack algorithm. In:
SPAA ’04: Proceedings of the sixteenth annual ACM symposium on Parallelism in
algorithms and architectures, pp. 206–215. ACM Press, New York (2004)
14. Herlihy, M., Wing, J.M.: Linearizability: A correctness condition for concurrent
objects. ACM Transactions on Programming Languages and Systems 12(3), 463–
492 (1990)
15. Hoare, C.A.R.: Communicating Sequential Processes. Prentice-Hall, Englewood
Cliffs (1985)
16. Lamport, L., Schneider, F.B.: Pretending atomicity. Technical Report TR89-1005,
SRC Digital (1989)
17. Lipton, R.J.: Reduction: a method of proving properties of parallel programs. Commun. ACM 18(12), 717–721 (1975)
18. Roscoe, A.W.: The Theory and Practice of Concurrency. International Series in
Computer Science. Prentice-Hall, Englewood Cliffs (1998)
19. Smith, G.: The Object-Z Specification Language. Kluwer Academic Publishers,
Dordrecht (2000)
20. Woodcock, J.C.P., Davies, J.: Using Z: Specification, Refinement, and Proof.
Prentice-Hall, Englewood Cliffs (1996)
Lifting General Correctness into Partial
Correctness is ok
Steve Dunne and Andy Galloway
School of Computing, University of Teesside
Middlesbrough, TS1 3BA, UK
s.e.dunne@tees.ac.uk
High Integrity Systems Engineering, Department of Computer Science,
University of York, UK
andyg@cs.york.ac.uk
Abstract. Commands interpreted in general correctness are usually
characterised by their wp and wlp predicate transformer effects. We describe a way to ascribe to such commands a single predicate transformer
semantics which embodies both their wp and wlp characteristics. The
new single predicate transformer describes an everywhere-terminating
“lifted” computation in an ok -enriched variable space, where ok is inspired by Hoare and He’s UTP but has the novelty here that it enjoys
the same status as the other state variables, so that it can be manipulated
directly in the lifted computation itself.
The relational model of this lifted computation is not, however, simply
the canonical UTP relation of the original underlying computation, since
this turns out to yield too cumbersome a lifted computation to permit
reasoning about efficiently with the mechanised tools available. Instead
we adopt a slightly less constrained model, which we are able to show is
nevertheless still effective for our purpose, and yet admits a much more
efficient form of mechanised reasoning with the tools available.
1
Introduction
We adopt a general-correctness1 [21] perspective on computations and reconcile
the UTP-style relational characterisation of computations in this perspective as
described in [11] with their more familiar Dijkstra-style predicate-transformer
characterisation. This general-correctness perspective allows us to describe accurately the behaviour of what we might call contingently-terminating computations, which are guaranteed to terminate with specified results from some
starting states, permitted but not guaranteed to terminate with specified results from certain other states, and guaranteed not to terminate from yet other
starting states.
To provide a concrete syntax in which to describe these computations we will
employ the Abstract Command Language [12,10]. We will describe a way to ascribe
1
Chen [4] calls it factual correctness, while Hesselink [19] and Nelson [26] both use a
similar semantics in their analyses of programs without explicitly naming it.
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 215–232, 2007.
c Springer-Verlag Berlin Heidelberg 2007
216
S. Dunne and A. Galloway
to such commands a single predicate-transformer semantics which embodies both
their wp and wlp characteristics. The new single predicate transformer describes
an everywhere-terminating “lifted” computation in an ok -enriched variable space,
where ok is inspired by Hoare and He’s Unifying Theories of Programming (UTP)
[20] but with the novelty that it enjoys the same status as the other state variables,
so that it can be manipulated directly by the lifted computation itself.
The relational model of this lifted computation is not, however, simply the
canonical UTP relation of the original underlying computation, since this turns
out to yield too cumbersome a lifted computation to permit reasoning about efficiently with the mechanised tools available. Instead we adopt a slightly less
constrained model, which we will prove is nevertheless still effective for our
purpose, yet admits a much more efficient form of mechanised reasoning with
the tools available. We seek to model our contingently-terminating computations in this way so that to reason about them we can thereby make direct
use of existing support tools such as the BToolkit [2], AtelierB [5] or ProB [22]
without any modification, even though they were all designed to support only
total-correctness reasoning. We do this by using such tools to reason about the
corresponding lifted computations rather than directly about the underlying
computations themselves.
In Section 2 we set out some necessary terminology, definitions and notation that we employ in the rest of the paper. In Section 3 we review the notion of general correctness and introduce abstract commands as a formal language for writing contingently-terminating programs, together with some elements of the theory which underpins them. In Section 4 we summarise the alternative UTP-inspired representation of contingently-terminating computations
originally given in [11], and show how to reconcile this with the wp-wlp predicatetransformer representation. We also extend the class of relations called prescriptions identified in [11] by introducing the new notion of pseudo-prescription, and
show that this extended class is closed under disjunction and relational composition as well as retaining a vital property we call compositionality. In Section
5 we reach the heart of the matter where we explore what we actually require
of any lifting scheme. Finally, we propose our particular lifting scheme, showing
that this does indeed fulfil our requirements, and illustrate its application by
means of a small example.
2
Preliminaries
Following established UTP practice we deal extensively in this paper with alphabetised relations, i.e. relations expressed as predicates over an explicitly given or
understood alphabet of variables. Often this alphabet includes Boolean-valued
variables ok and ok , and then for conciseness we frequently take the liberty of
treating these variables themselves as predicates, for example writing just ¬ ok
instead of ok = FALSE. We refer interchangeably to a relation and its predicate
providing its alphabet is understood. We define the following partial order on
relations A and B sharing the same alphabet α :
Lifting General Correctness into Partial Correctness is ok
217
Definition 1. (Implication Ordering on Predicates)
A≤B
=df
∀ α. B ⇒ A
The constant predicates true and false are respectively the bottom and top of
this lattice. For any predicate A we therefore have true ≤ A ≤ false . We deem
relations A and B to be equal if their predicates are true of precisely the same
bindings of the variables of their common alphabet:
Definition 2. (Equality for predicates)
A = B
=df
(A ≤ B ) ∧ (B ≤ A)
Binary Relations and Conditions. A homogeneous binary relation is one
whose alphabet is of the form (v , v ) where v is a list of undashed variables and v is
a corresponding list of dashed versions of these. The undashed variables v represent
the relation’s input states while the dashed variables v represent its output states.
A condition is a relation whose predicate constrains only undashed variables.
Syntactic Substitution. If A is a predicate expression over an alphabet which
includes a list of variables u, and E is list of appropriately typed expressions
corresponding to u, we write A[E /u] to denote the predicate derived from A by
replacing each free occurrence of each of the variables of u with the corresponding
expression from E . Note that syntactic substitution distributes through the basic
logical connectives such as conjunction and disjunction, so that for example
(A ∨ B )[E /u]
= A[E /u] ∨ B [E /u]
Some Convenient Relational Abbreviations. If A is a predicate expression over alphabet (w , ok , w , ok ) we will write Att , Atf , Aft and Aff as abbreviations for A[true, true/ok , ok ], A[true, false/ok , ok ], A[false, true/ok , ok ] and
A[false, false/ok , ok ] respectively.
Composition of Relations. Let A and B be homogeneous binary relations
with a common alphabet (v , v ). Then we have
Definition 3. (Relational Composition)
A;B
∃ v . A[v /v ] ∧ B [v /v ]
=df
where v is a fresh list of variables corresponding with those of v . In particular,
relational composition gives us a convenient way of formally expressing that
a relation A is a condition, namely that A ; true = A. Among the important
algabraic properties of relational composition are that it is associative and leftand right-distributes through disjunction, so that, for example, for homogeneous
binary relations A, B and C on a common alphabet we have
(A ; B ) ; C = A ; (B ; C )
(A ∨ B ) ; C = (A ; C ) ∨ (B ; C )
A ; (B ∨ C )
=
(A ; B ) ∨ (A ; C )
218
S. Dunne and A. Galloway
Relational Algebra. We will make use of the identities expressed by the following proposition
Proposition 2.1. (Some useful relational identities)
(1)
(2)
(3)
(4)
(A ; B )tt
(A ; B )tf
(A ; B )ft
(A ; B )ff
=
=
=
=
(Att ; Btt ) ∨ (Atf ; Bft )
(Atf ; Bff ) ∨ (Att ; Btf )
(Aft ; Btt ) ∨ (Aff ; Bft )
(Aff ; Bff ) ∨ (Aft ; Btf )
Proof: By defn of “ ; ” and appropriate true and false case splits for ok and ok .
3
General Correctness and Abstract Commands
General correctness separates for a computation the respective issues of (a) its reliable termination and (b) the correctness of its result should it (whether reliably
or even fortuitously) terminate, treating these two concerns quite orthogonally.
As such it discriminates between computations more finely than total correctness,
which simply superimposes (a) on (b), thereby equating all behaviour other than
reliably terminating as indistinguishably pathological. Thus general correctness
not only allows the specifier to express the conditions required for guaranteed
termination of a computation and constrain its result in those circumstances, it
also allows him to constrain its result in cases where termination is not guaranteed, even to the point of sometimes forbidding fortuitous termination altogether,
thereby demanding actual non-termination.
3.1
The Interactive Era
One of the reviewers of the draft version of this paper was sceptical of the value
of considering general correctness at all, describing it as “a mere cul-de-sac in
the history of computing”. While it is certainly true that total correctness has
predominated almost absolutely until recently in all the prominent refinement
and program-correctness theories such as [24,1,3,20], we believe this reflects a
historical pre-occupation with pure sequential computation, which has in fact
been largely superseded by the current focus on interactive computing. Even in
1998 Milner [23] was already pointing out that computing is interaction. This has
important implications for software developers. No longer are we always necessarily exclusively concerned with the result of executing our sequential programs
through to successful termination. Such programs now often provide the individual interacting threads of today’s complex distributed processing systems, and
thus we may require them to behave reliably even in situations where termination is not even in prospect. A channel-listener, for example, must idle until it
detects an incoming message, then deal effectively with such a message if and
when it arrives. But since there is never a guarantee that such a message will
ever arrive, our channel-listener must be capable in principle of idling indefinitely. There are circumstances, therefore, where non-termination is precisely
Lifting General Correctness into Partial Correctness is ok
219
what we demand. As formal software specifiers and designers we must have a
specification language in which we can formally articulate such a requirement,
and a design calculus with which we can prove that a given program meets such
a specification. To quote from [18]:
With the addition of communication, non-terminating executions can
perform useful computation, so a semantics that does not insist on termination is useful.
We might go further and say we need a semantics in which we can insist on nontermination in certain conditions. In short, we must learn to work in the context
of general correctness. In this regard it is also salient to point to work undertaken by various authors in the field of timed refinement, for example [14,15],
and [16,17]. Such work invariably exhibits the quintessential general-correctness
characteristic that actual non-termination is precisely characterisable. Total correctness, on the other hand, can only subsume non-termination into the completely unpredictable behaviour known as divergence or chaos.
3.2
Abstract Commands
We first introduced abstract commands [12], as an adaptation of Abrial’s generalised substitutions [1], to express computations in general correctness, and subsequently further developed them by introducing the notion of frames [10]. Dawson [6] later formalised our resulting theory of abstract commands in Isabelle/
HOL to confirm its soundness. In this paper, however, we confine ourselves to
commands sharing a common frame w of all state variables in the context of discourse. Each such command S is fully characterised by its termination predicate
trm(S ), which defines from which starting states it can be relied on to terminate,
and its weakest liberal precondition wlp(S , Q ) which defines from which starting
states it must if it does terminate establish any particular postcondition Q . The
trm-wlp semantics of each of our basic abstract commands is given in Table 1.
The weakest-precondition (wp) and weakest-liberal-precondition (wlp) predicate
transformers were of course invented by Dijkstra [8,9] who linked them by the
healthiness rule
wp(S , Q ) = wp(S , true) ∧ wlp(S , Q )
In our approach, however, we choose to treat wp(S , true) as primitive and denote
it by trm(S ), so that wp(S , Q ) can then be obtained using Dijkstra’s rule as
wp(S , Q ) =df
3.3
trm(S ) ∧ wlp(S , Q )
Normal Form of an Abstract Command
The before-after predicate prd(S ) of an abstract command S operating in a state
space characterised by state variable(s) w is defined as
prd(S ) =df
¬ wlp(S , w = w )
220
S. Dunne and A. Galloway
Table 1. Basic abstract commands
name of C
syntax
trm(C )
wlp(C , Q)
skip
skip
true
Q
assignment
u := E
true
Q[E /u]
termination
precondition
P |S
P ∧ trm(S )
wlp(S , Q)
guard
P −→ S
P ⇒ trm(S )
P ⇒ wlp(S , Q)
bounded choice
S T
trm(S ) ∧ trm(T )
wlp(S , Q) ∧ wlp(T , Q)
unbounded choice
@z . S
∀ z . trm(S )
∀ z . wlp(S , Q)
sequential
composition
S ;T
trm(S ) ∧
wlp(S , trm(T ))
wlp(S , wlp(T , Q))
It relates each initial state w to the possible final states w which of S might
yield. Indeed S can be expressed in normal form as
S
=
trm(S ) | @ w . prd(S ) −→ w := w
This normal form embodies the following identities which follow from our definitions of prd(S ) and wp(S , Q ) :
wlp(S , Q )
=
∀ w . prd(S ) ⇒ Q [w /w ]
wp(S , Q )
=
trm(S ) ∧ ∀ w . prd(S ) ⇒ Q [w /w ]
3.4
Indeterminate Assignment
Given a relation R on (w , w ) we also define the following useful derived command we call an indeterminate assignment :
w :R
=df
@ w . R −→ w := w
Our operational intuition of w : R is that from each starting state it assigns to w
a nondeterministically-chosen final state from among those related by R to that
starting state. Where the starting state in question has no related final states
the assignment is miraculous (i.e. unenabled). We note that trm(w : R) = true
and prd(w : R) = R. Our indeterminate assignment w : R corresponds with
what Back and von Wright [3], working in total correctness, call the demonic
relational update on R and denote by [R].
Using indeterminate assignment we can express the normal form of an abstract
command S more succinctly as
S
=
trm(S ) | w : prd(S )
Lifting General Correctness into Partial Correctness is ok
4
221
General Correctness and UTP
In [11] we introduced the notion of a prescription as the general-correctness
counterpart of Hoare and He’s total-correctness notion of a design [20], and
developed a corresponding theory for these. They have subsequently attracted
the interest of other authors [13,7] who have incorporated them into their own
investigations.
Let w be the state variable(s) of our state space and ok be an auxiliary
Boolean variable which when initially true signifies the computation has started
and when finally true signifies it has terminated. We recall from [11] that a
prescription is an alphabetised relation over (w , ok , w , ok ) whose predicate can
be expressed in the form
(ok ∧ P ⇒ ok ) ∧ (ok ⇒ R ∧ ok )
where P and R are subsidiary predicates not containing ok or ok . We abbreviate
it as P R . Conversely, for any prescription A over (w , ok , w , ok ) we have that
A
=
¬ Atf
Att
If P is simply a condition – i.e. it constrains only the undashed state variables
w – then we call P
R a normal prescription, and interpret it operationally
as If the program starts in a state satisfying P it must eventually terminate;
moreover, if it terminates R will be satisfied, and it must have started, though
not necessarily from a state satisfying P . In this case we call P the termination
condition of P R . In the rest of this paper all the prescriptions we encounter
will be normal ones in this sense.
4.1
Prescriptions versus Predicate Transformers
We can reconcile the predicate-transformer (abstract command) and relational
(prescription) representations of a computation in general correctness by noting
that the computation represented imperatively by any abstract command S is
represented relationally by the normal prescription trm(S ) prd(S ).
Conversely, we know that any normal prescription A represents a computation
in general correctness, and that this is also characterised by its pair of predicate
transformers wp and wlp, which can be derived from A by
wp(A, Q )
=df
¬ (A ; ¬ (ok ∧ Q ))[true/ok ]
wlp(A, Q )
=df
¬ (A ; ¬ (ok ⇒ Q ))[true/ok ]
Equivalently, we could instead first introduce the notion of a rich condition
as a predicate over (w , ok ) and then define a weakest-rich-precondition (wrp)
predicate transformer for A, such that for any rich postcondition R
wrp(A, R)
=df
¬ (A ; ¬ R)
222
S. Dunne and A. Galloway
A’s wp and wlp can then be derived from its wrp as
wp(A, Q )
=
wrp(A, (ok ∧ Q ))[true/ok ]
wlp(A, Q )
=
wrp(A, (ok ⇒ Q ))[true/ok ]
thus achieving a unification of wp and wlp arguably more transparent than that
offered in [25]. And indeed since (ok ⇒ Q ) ≤ Q ≤ (ok ∧ Q ) in the lattice of
rich conditions we might even be tempted to define an intermediate predicate
transformer “whp”, as it were “halfway” between wp and wlp, by
whp(A, Q )
=df
wrp(A, Q )[true/ok ]
Curiously, it turns out this is indistinguishable from wp, save that unlike wp it
has the property that whp(A, true) = true for every A .
4.2
Pseudo-prescriptions
Prescriptions are canonical relational representations of computations in general
correctness, in the sense that any two distinct normal prescriptions will represent
distinct computations. There are several equivalent convenient healthiness tests
to determine whether a relation over (w , ok , w , ok ) is actually a prescription.
For example, a relation A over (w , ok , w , ok ) is a prescription if and only if
A[false/ok ] = ¬ ok [11, Thm 1]. Equivalently, A is a prescription if and only if
Aft = false and Aff = true.
We note that any relation A over (w , ok , w , ok ) in a sense “encodes” the
normal prescription ¬ (Atf ; true) Att . We call the latter A’s intrinsic prescription and denote it more compactly by P(A). Indeed, echoing established
UTP practice in [20] we can regard our P( ) as an idempotent “healthifying”
function on relations whose fixed points are precisely the normal prescriptions
over (w , ok , w , ok ) .
Unfortunately arbitrary relations suffer the shortcoming that their intrinsic
prescriptions are not in general compositional with respect to relational composition. That is to say, for arbitrary relations A and B over (w , ok , w , ok ) it
is not always the case that P(A ; B ) = P(A) ; P(B ). We can, however, define a
class of relations called pseudo-prescriptions somewhat larger than that of prescriptions, which are compositional with respect to their intrinsic prescriptions.
We say that a relation A over (w , ok , w , ok ) is a pseudo-prescription if and
only if Aft = false and Aff ; true = true. Our pseudo-prescriptions enjoy some
important properties as expressed in the following two propositions:
Proposition 4.2.1 (Closure of pseudo-prescriptions)
Pseudo-prescriptions are closed under disjunction and relational composition.
Proof: The closure of pseudo-prescriptions under disjunction follows trivially
from the distributivity of syntactic substitution through disjunction, giving that
(A ∨ B )ft = Aft ∨ Bft , and (A ∨ B )ff = Aff ∨ Bff , and then the leftdistributivity of “ ;” through disjunction, giving that
(A ∨ B )ff ; true = (Aff ∨ Bff ) ; true = (Aff ; true) ∨ (Bff ; true)
Lifting General Correctness into Partial Correctness is ok
223
Their closure under relational composition is shown by
(A ; B )ft
= { Prop 2.1.(3) }
(Aft ; Btt ) ∨ (Aff ; Bft )
= { A and B are pseudo-prescriptions so Aft = Bft = false }
(false ; Btt ) ∨ (Aff ; false)
= { relational algebra and logic }
false
and then
(A ; B )ff ; true
= { Prop 2.1.(4) }
((Aff ; Bff ) ∨ (Aft ; Btf )) ; true
= { A is pseudo-prescription so Aft = false }
((Aff ; Bff ) ∨ (false ; Btf )) ; true
= { relational algebra and logic }
(Aff ; Bff ) ; true
= { “ ;” is associative }
Aff ; Bff ; true
= { B is pseudo-prescription so Bff ; true = true }
Aff ; true
= { A is pseudo-prescription so Aff ; true = true }
true
The next proposition establishes that, at least when applied to pseudoprescriptions, our intrinsic-prescription extractor function P( ) is compositional
with respect to “ ; ”. The significance of this is that we can safely use pseudoprescriptions as surrogates for the computations embodied in their intrinsic
prescriptions, since when we compose them we know the result will accurately
encode the actual compositions of the original underlying computations.
Proposition 4.2.2 (Compositionality of pseudo-prescriptions)
Let A and B be relations over (w , ok , w , ok ) such that Aft = Bft = false and
Aff ; true = Bff ; true = true. Then P(A ; B ) = P(A) ; P(B ).
Proof:
P(A ; B )
= { defn of intrinsic prescription }
¬ ((A ; B )tf ; true)
(A ; B )tt
= { Props. 2.1.(1), 2.1.(2) }
¬ (((Atf ; Bff ) ∨ (Att ; Btf )) ; true)
(Att ; Btt ) ∨ (Atf ; Bft )
= { composition distributes through ∨ }
(Att ; Btt ) ∨ (Atf ; Bft )
¬ ((Atf ; Bff ; true) ∨ (Att ; Btf ; true))
224
S. Dunne and A. Galloway
= { Bff ; true = true and Bft = false }
(Att ; Btt ) ∨ (Atf ; false)
¬ ((Atf ; true) ∨ (Att ; Btf ; true))
= { relational algebra and logic }
¬ (Atf ; true) ∧ ¬ (Att ; Btf ; true)
Att ; Btt
= { composition of normal prescriptions [11, Cor. 6.1] }
(¬ (Atf ; true) Att ) ; (¬ (Btf ; true) Btt )
= { defn of intrinsic prescription }
P(A) ; P(B )
Pseudo-prescriptions certainly still represent computations in general correctness, though those representations are clearly no longer canonical since distinct
pseudo-prescriptions can share the same intrinsic prescription and therefore
represent the same computation. In the next section we will see how pseudoprescriptions play a fundamental role in validating that our lifting of abstract
commands into partial-correctness computations is sound.
5
Lifting a Computation
The notion of lifting a computation is motivated by the crucial insight that a
computation on an underlying space w with a contingent termination behaviour
can be modelled by an always-terminating one on the enriched state (w , ok ).
Providing our lifting scheme is sound, then by reasoning about its lifted counterpart we can thereby indirectly arrive at valid conclusions about the underlying
computation itself.
Because the lifted computation is acting on the enriched state it can manipulate ok as an ordinary program variable. An always-terminating computation
is of course completely described by its partial-correctness semantics, and is
therefore fully characterised in predicate-transformer terms by its wlp, and in
relational terms by its before-after state relation.
Since we now have two state spaces so to speak in play at the same time,
namely an underlying state space characterised by w alone and an enriched one
characterised by (w , ok ). we must be careful to keep track over which of these
our various predicate transformers are ranging. To help us do this we adopt the
convention that the bold-font version wlp of our weakest-liberal-precondition
predicate transformer ranges over the enriched state (w , ok ), thereby characterising computations on this enriched state, whereas the ordinary-font wp and wlp
predicate transformers range over the underlying state w and so characterise
ordinary computations on that underlying state.
Note that if C is an abstract command over enriched state (w , ok ), then
prd(C )
=
=
¬ wlp(C , (w , ok ) = (w , ok ))
¬ wlp(C , w = w ∨ ok = ok )
Table 2 lists the explicitly derived prds of some typical commands over the
enriched state (w , ok ).
Lifting General Correctness into Partial Correctness is ok
225
Table 2. Derived prds of commands over enriched state (w , ok )
5.1
name
syntax
prd
skip
skip
w = w ∧ ok = ok
assignment
u := E
where u ⊆ w
u = E ∧ y = y ∧ ok = ok
where y is w \u
assignment
ok := false
w = w ∧ ¬ ok
termination
precondition
P |C
prd(C )
guard
G −→ C
G ∧ prd(C )
bounded choice
C D
prd(C ) ∨ prd(D)
unbounded choice
@z . C
∃ z , z . prd(C )
sequential
composition
C ;D
prd(C ) ; prd(D)
Lifting Abstract Commands
We seek to associate with each abstract command S acting on a state w an
always-terminating one C acting on an enriched state (w , ok ), in such a way
that S ’s wp and wlp effects can be recovered from C by
wp(S , Q )
=
wlp(C , ok ∧ Q )[true/ok ]
wlp(S , Q )
=
wlp(C , ok ⇒ Q )[true/ok ]
In relational terms this is equivalent to requiring that
trm(S )
prd(S )
=
P(prd(C ))
We will call a lifting scheme with this property effective. A canonical way to
derive such an C would be to define it as an indeterminate assignment based on
the characteristic prescription of S , as in
C
=df
w , ok : (trm(S )
prd(S ))
since then prd(C ) would be trm(S ) prd(S ) which as a normal prescription is
a fixed point of P( ). Such a lifting scheme, though, is impractical since it yields
cumbersome lifted computations which cannot be reasoned about efficiently with
the available mechanised support tools.
Instead we propose the lifting scheme L detailed in Table 3. The merit of this
scheme is that it is very easy to mechanise, and yields lifted commands hardly any
226
S. Dunne and A. Galloway
Table 3. Lifting Scheme L for Abstract Commands
name of C
syntax
L(C )
skip
skip
skip
assignment
u := E
u := E
termination
precondition
P |S
(¬ P −→ ok := false) L(S )
guard
G −→ S
(ok ⇒ G) −→ L(S )
bounded choice
S T
L(S ) L(T )
unbounded choice
@z . S
@ z . L(S )
sequential
composition
S ;T
L(S ) ; L(T )
more complex in form than the underlying commands concerned, which are thus
very amenable to efficient mechanised reasoning via the tools available. Clearly,
though, our lifting scheme L is not canonical since it lifts some semanticallyequivalent commands to distinct lifted commands. For example, it is easy to
show that skip and w : w = w are semantically equivalent, yet L(skip) is skip
while L(w : w = w ) turns out to be
(¬ ok −→ @ w . w := w )
skip
which is clearly not the same as skip. Nevertheless, our lifting scheme does have
the vital property expressed by the following proposition:
Proposition 5.1.1 (Compositionality of lifting scheme L)
For any abstract command expression S the lifting scheme L in Table 3 ensures
that prd(L(S )) is a pseudo-prescription.
Proof: By structural induction over the syntax of abstract commands. For example, in the case of P | S we have
prd(L(P | S ))
= { Table 3 }
prd((¬ P −→ ok := false)
L(S ))
= { Table 2 }
prd(¬ P −→ ok := false) ∨ prd(L(S ))
= { Table 2 }
(¬ P ∧ prd(ok := false)) ∨ prd(L(S ))
Lifting General Correctness into Partial Correctness is ok
= { Table 2 }
(¬ P ∧ w = w ∧ ¬ ok ) ∨ prd(L(S ))
and now substituting [false, true/ok , ok ] in (1) yields
(¬ P ∧ w = w ∧ ¬ true) ∨ prd(L(S ))ft
= { logic }
false ∨ prd(L(S ))ft
= { logic }
prd(L(S ))ft
= { by inductive assumption prd(L(S )) is a pseudo-prescription }
false { thus establishing that prd(L(P | S ))ft = false }
On the other hand, substituting [false, false/ok , ok ] in (1) yields
(¬ P ∧ w = w ∧ ¬ false) ∨ prd(L(S ))ff
= { logic }
(¬ P ∧ w = w ) ∨ prd(L(S ))ff
and then composing (2) with true yields
((¬ P ∧ w = w ) ∨ prd(L(S ))ff ) ; true
= { “ ;” left-distributes through ∨ }
((¬ P ∧ w = w ) ; true) ∨ (prd(L(S ))ff ; true)
= { by inductive assumption prd(L(S )) is a pseudo-prescription }
((¬ P ∧ w = w ) ; true) ∨ true
= { logic }
true { thus also establishing that prd(L(P | S ))ff ; true = true }
We conclude that prd(L(P | S )) is indeed a pseudo-prescription if L(S ) is.
227
(1)
(2)
This in turn leads to our main result:
Proposition 5.1.2 (Effectiveness of lifting scheme L)
For any abstract command expression S the lifting scheme L in Table 3 ensures
that
wp(S , Q )
wlp(S , Q )
=
=
wlp( L(S ), ok ∧ Q )[true/ok ]
wlp( L(S ), ok ⇒ Q )[true/ok ]
Proof: Again, by structural induction over the syntax of abstract commands. In
particular, the demonstration for sequential composition follows from the com
positionality of pseudo-prescriptions via Props 4.2.1, 4.2.2 and 5.1.1 .
5.2
An Example
The archetypal extreme contingently-terminating computation is perhaps the
infinite loop known variously as loop [26], never [11] or abort2 [9,25]. which is
2
Not to be confused with its total-correctness namesake which may or may not terminate.
228
S. Dunne and A. Galloway
in fact nowhere allowed to terminate. It is expressed in UTP relational terms
by the prescription false
false, or equivalently in abstract-command terms
as false | false −→ skip. It is never actually obliged to terminate (termination
condition false), and in fact to do so it would have to achieve the impossible
(postcondition false), so we can conclude it never does so. Reasoning formally
directly in the abstract-command semantics of Table 1 we have
trm(never)
= { defn of never as an abstract command }
trm(false | false −→ skip)
= { defn of termination precondition in Table 1 }
false ∧ trm(false −→ skip)
= { logic }
false
meaning it is never guaranteed to terminate, while
wlp(never, false)
= { defn of never as an abstract command }
wlp(false | false −→ skip , false)
= { defn of termination precondition in Table 1 }
wlp(false −→ skip , false)
= { defn of guard in Table 1 }
false ⇒ wlp(skip, false)
= { logic }
true
meaning if it did so it would always establish the impossible (postcondition false),
from which we can conclude it can never do so.
Now we repeat our reasoning, but this time we proceed indirectly. First we lift
never using Table 3 and then we extract trm(never) and wlp(never, false) from
its lifted counterpart using Prop. 5.1.2 :
L(never)
= { defn of never }
L(false | false −→ skip)
= { Table 3 lifting a termination precondition }
L(false −→ skip)
(¬ false −→ ok := false)
= { logic }
(true −→ ok := false)
L(false −→ skip)
= { discard trivial guard }
ok := false
L(false −→ skip)
= { Table 3 lifting a guard }
ok := false
(ok ⇒ false) −→ L(skip)
Lifting General Correctness into Partial Correctness is ok
= { logic }
ok := false
¬ ok −→ L(skip)
= { Table 3 lifting skip }
ok := false
¬ ok −→ skip
And now having obtained L(never) we proceed to derive trm(never) and
wlp(never, false) :
trm(never)
= { for any command S trm(S ) = wp(S , true) }
wp(never, true)
= { Prop. 5.1.2 }
wlp(L(never) , ok ∧ true)[true/ok ]
= { logic }
wlp(L(never) , ok )[true/ok ]
= { derivation of L(never) above }
wlp(ok := false
¬ ok −→ skip , ok )[true/ok ]
= { defn of
in Table 1 }
(wlp(ok := false, ok ) ∧ wlp(¬ ok −→ skip, ok ))[true/ok ]
= { defn of := in Table 1 }
(false ∧ wlp(¬ ok −→ skip, ok ))[true/ok ]
= { logic }
false
as we would expect. And then we have
=
=
=
=
=
=
=
=
wlp(never, false)
{ Prop. 5.1.2 }
wlp(L(never) , ok ⇒ false)[true/ok ]
{ logic }
wlp(L(never) , ¬ ok )[true/ok ]
{ derivation of L(never) above }
wlp(ok := false
¬ ok −→ skip , ¬ ok )[true/ok ]
{ defn of
in Table 1 }
(wlp(ok := false, ¬ ok ) ∧ wlp(¬ ok −→ skip, ¬ ok ))[true/ok ]
{ defn of := in Table 1 }
(¬ false ∧ wlp(¬ ok −→ skip, ¬ ok ))[true/ok ]
{ logic }
wlp(¬ ok −→ skip, ¬ ok )[true/ok ]
{ defn of guard in Table 1 }
(¬ ok ⇒ wlp(skip, ¬ ok ))[true/ok ]
{ defn of skip in Table 1 }
229
230
S. Dunne and A. Galloway
(¬ ok ⇒ ¬ ok )[true/ok ]
= { logic }
true
again as we would expect. This illustrates how reasoning about our infinite loop
never, as it were vicariously, through its lifted always-terminating counterpart
ok := false
¬ ok −→ skip is both effective and sound.
6
Conclusion
We have shown how a contingently-terminating computation expressed by an
abstract command can be equivalently expressed as a prescription. Conversely,
we have shown how a prescription can be interpreted as an abstract command
by extracting its wp and wlp predicate-transformer effects. We also showed how
each of these can be regarded as particular cases of a higher-level predicate
transformer wrp also extractible from the prescription, which works on “rich
conditions” rather than ordinary conditions, thus achieving a interesting unification of wp and wlp.
We defined the new notion of the intrinsic prescription encoded within an
arbitrary relation over (w , ok , w , ok ) and used this to define our idempotent
“healthifying” function P( ) applying to all such relations and yielding normal
prescriptions. We identified a class of relations over (w , ok , w , ok ) called pseudoprescriptions subsuming prescriptions and showed that not only are these closed
under disjunction and relational composition, but that they also have the important property of compositionality with respect to their intrinsic prescriptions.
We defined an efficient easily-mechanisable lifting scheme for abstract commands
whose lifted counterparts correspond to pseudo-prescriptions whose compositionality guarantees the effectiveness of the scheme. The importance of such a
scheme is that it gives us the means to reason in general correctness about our
abstract-command programs with existing support tools only designed to reason
in total or partial correctness, without needing to modify these at all.
From a theoretical point of view it is interesting to note that we know our
pseudo-prescriptions are not the least-constrained effective encodings of our
contingently-terminating computations. It remains to characterise these leastconstrained such encodings, and investigate whether they might offer any advantages over pseudo-prescriptions.
References
1. Abrial, J.-R.: The B-Book: Assigning Programs to Meanings. Cambridge University
Press, Cambridge (1996)
2. B-Core. The B-Toolkit. http://www.b-core.com
3. Back, R.-J., von Wright, J.: Refinement Calculus: A Systematic Introduction.
Springer, Berlin Heidelberg (1998)
4. Chen, Y.: A fixpoint theory for non-monotonic parallelism. Theoretical Computer
Science 308, 367–392 (2003)
Lifting General Correctness into Partial Correctness is ok
231
5. ClearSy. Atelierb. http://www.atelierb.societe.com
6. Dawson, J.E.: Formalising general correctness. In: Computing: The Australasian
Theory Symposium 2004. Electronic Notes in Theoretical Computer Science,
vol. 91, pp. 46–65. Elsevier, Amsterdam (2004)
7. Deutsch, M., Henson, M.C.: A relational investigation of UTP designs and perscriptions. In: Dunne, S.E., Stoddart, W.J. (eds.) UTP 2006. LNCS, vol. 4010, pp.
101–122. Springer, Heidelberg (2006)
8. Dijkstra, E.W.: A Discipline of Programming. Prentice-Hall, Englewood Cliffs
(1976)
9. Dijkstra, E.W., Scholten, C.S.: Predicate Calculus and Program Semantics.
Springer, Berlin Heidelberg (1990)
10. Dunne, S.E.: Abstract commands: a uniform notation for specifications and implementations. In: Fidge, C.J. (ed.) Computing: The Australasian Theory Symposium
2001. Electronic Notes in Theoretical Computer Science, vol. 42, Elsevier, Amsterdam (2001) http://www.elsevier.nl/locate/entcs
11. Dunne, S.E.: Recasting Hoare and He’s unifying theory of programs in
the context of general correctness. In: Butterfield, A., Strong, G., Pahl, C.
(eds.) Proceedings of the 5th Irish Workshop in Formal Methods, IWFM
2001, Workshops in Computing, British Computer Society, Vancouver (2001),
http://ewic.bcs.org/conferences/2001/5thformal/papers
12. Dunne, S.E., Stoddart, W.J., Galloway, A.J.: Specification and refinement in general correctness. In: Evans, A., Duke, D., Clark, A. (eds.) Proceedings of the 3rd
Northern Formal Methods Workshop. BCS Electronic Workshops in Computing
(1998) http://www.ewic.org.uk/ewic/workshop/view.cfm/NFM-98
13. Guttmann, W., Mőller, B.: Modal design algebra. In: Dunne, S.E., Stoddart, W.J.
(eds.) UTP 2006. LNCS, vol. 4010, pp. 236–256. Springer, Heidelberg (2006)
14. Hayes, I.J.: Separating timing and calculation in real-time refinement. In: Grundy,
J., Schwenke, M., Vickers, T. (eds.) International Refinement Workshop and Formal
Methods Pacific 1998, pp. 1–16. Springer, Heidelberg (1998)
15. Hayes, I.J.: Reasoning about non-terminating loops using deadline commands.
In: Backhouse, R., Oliveira, J. (eds) Mathematics of Program Construction (MPC2000), (2000) Also available as Technical Report UQ-SVRC-00-02,
http://svrc.it.uq.edu.au
16. Hehner, E.C.R.: Termination is timing. In: van de Snepscheut, J.L.A. (ed.) Mathematics of Program Construction. LNCS, vol. 375, pp. 36–47. Springer, Heidelberg
(1989)
17. Hehner, E.C.R.: A Practical Theory of Programming. Springer, Heidelberg (1993)
18. Hehner, E.C.R., Gravell, A.M.: Refinement semantics and loop rules. In: Woodcock,
J.C.P., Davies, J., Wing, J.M. (eds.) FM 1999. LNCS, vol. 1709, pp. 1497–1510.
Springer, Heidelberg (1999)
19. Hesselink, W.H.: Programs, Recursion and Unbounded Choice. Cambridge Tracts
in Theoretical Computer Science, vol. 27. Cambridge University Press, Cambridge
(1992)
20. Hoare, C.A.R., Jifeng, H.: Unifying Theories of Programming. Prentice Hall, Englewood Cliffs (1998)
21. Jacobs, D., Gries, D.: General correctness: a unification of partial and total correctness. Acta. Informatica 22, 67–83 (1985)
22. Leuschel, M., Butler, M.: ProB: a model checker for B. In: Araki, K., Gnesi, S.,
Mandrioli, D. (eds.) FME 2003. LNCS, vol. 2805, pp. 855–874. Springer, Heidelberg
(2003)
232
S. Dunne and A. Galloway
23. Milner, A.J.R.G.: Computing is interaction. Invited address FACS 21st Anniversary Symposium, December 2, 1998. The Royal Society, London (1998)
24. Morgan, C.C.: Programming from Specifications, 2nd edn. Prentice Hall International, Englewood Cliffs (1994)
25. Morgan, C.C., McIver, A.: Unifying wp and wlp. Information Processing Letters 59,
159–163 (1996)
26. Nelson, G.: A generalisation of Dijkstra’s calculus. ACM Transactions on Programmg Languages and Systems, vol. 11(4) (1989)
Verifying CSP-OZ-DC Specifications with
Complex Data Types and Timing Parameters
Johannes Faber1 , Swen Jacobs2 , and Viorica Sofronie-Stokkermans2
1
Department of Computing Science, University of Oldenburg, Germany
j.faber@uni-oldenburg.de
2
Max-Planck-Institut Informatik, Saarbrücken, Germany
{sjacobs,sofronie}@mpi-sb.mpg.de
Abstract. We extend existing verification methods for CSP-OZ-DC to
reason about real-time systems with complex data types and timing parameters. We show that important properties of systems can be encoded
in well-behaved logical theories in which hierarchic reasoning is possible.
Thus, testing invariants and bounded model checking can be reduced to
checking satisfiability of ground formulae over a simple base theory. We
illustrate the ideas by means of a simplified version of a case study from
the European Train Control System standard.
1
Introduction
Complex real-time systems, consisting of several components that interact, arise
in a natural way in a wide range of applications. In order to verify these systems,
one needs, on the one hand, to find a suitable specification language, and on the
other hand, to develop efficient techniques for their verification.
In the specification of complex systems, one needs to take several aspects
into account: control flow, data changes, and timing aspects. Motivated by this
necessity, in [HO02, Hoe06] a specification language CSP-OZ-DC (COD) is defined, which combines Communicating Sequential Processes (CSP), Object-Z
(OZ) and the Duration Calculus (DC). Verification tasks (e.g., invariant checking or bounded model checking) can usually be reduced to proof tasks in theories
associated to the COD specification. These theories can be combinations of concrete theories (e.g., integer, rational or real numbers) and abstract theories (e.g.,
theories of functions or of data structures). Existing verification techniques for
COD [HM05, MFR06] do not incorporate efficient reasoning in complex theories,
which is essential to perform such verification tasks efficiently.
In this paper, we analyse both aspects mentioned above. We use COD specifications of systems, with complex data types and timing parameters, and analyse
possibilities for efficient invariant checking and bounded model checking in these
systems. The main contributions of the paper can be described as follows.
This work was partly supported by the German Research Council (DFG) under
grant SFB/TR 14 AVACS. See http://www.avacs.org for more information.
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 233–252, 2007.
c Springer-Verlag Berlin Heidelberg 2007
234
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
Specification: We extend existing work in which COD specifications were used
[HO02, Hoe06, MFR06] in two ways:
(i) We use abstract data structures for representing and storing information
about an unspecified parametric number of components of the systems.
This allows us to pass in an elegant way from verification of several finite
instances of a verification problem (for 2, 3, 4, ... components) to general
verification results, in which the number of components is a parameter.
(ii) In order to refer to time constants also within the specification’s data
(OZ) part, we introduce timing parameters. This allows for more flexible
specifications of timing constraints.
Verification: We show that, in this context, invariant checking or bounded
model checking can be reduced to proving in complex theories. We analyse
the theories that occur in relationship with a given COD specification, and
present a sound and efficient method for hierarchic reasoning in such theories.
We identify situations where the method is sound and complete (i.e., where
the specific properties of systems define chains of local theory extensions).
Applications: Our running example is an extension of a case study that we
considered in [JSS07] (in which we first applied hierarchic reasoning in the
verification of train control systems). Here, we additionally encompass efficient handling of emergency messages and illustrate the full procedure –
starting from a COD description of the case study to the verification.
Structure of the paper. We illustrate the idea of our approach by means of a case
study, which will be our running example (Sect. 1.1). Section 2 introduces the
specification language COD and discusses an extension with timing parameters.
Section 3 presents an operational semantics of COD specifications, in terms
of Phase Event Automata (PEA), and discusses some simplifications for PEA.
Section 4 presents a verification method for COD specifications: the associated
PEA are translated into transition constraint systems; verification is reduced to
satisfiability checking in combinations of theories. We identify some theories, in
which hierarchic reasoning is possible, occurring frequently in applications.
1.1
Illustration
We here give a general description of a
RBC
case study inspired by the specification
of the European Train Control System
(ETCS) standard [ERT02]. We explain
the tools we used for modelling the example and give the idea of the method
braking distance
for checking safety. This will be used as a
running example throughout the paper.
Fig. 1. Emergencies in the ETCS
Related ETCS scenarios have been studied in [HJU05, FM06, MFR06, TZ06].
The example we consider has a less complicated control structure than those
in [FM06, MFR06]. Instead, it considers an arbitrary number of trains, and
hence, needs to use more realistic and sophisticated data types.
Verifying CSP-OZ-DC Specifications
235
The RBC Case Study. We consider a radio block centre (RBC), which communicates with all trains on a given track segment. The situation is sketched
in Fig. 1. Every train reports its position to the RBC in given time intervals
and the RBC communicates to every train how far it can safely move, based
on the position of the preceding train; the trains adjust their speed between
given minimum and maximum speeds. If a train has to stop suddenly, it sends
an emergency message. The RBC handles the message sent by a train (which
we refer to as emergency train) by instructing each train behind the emergency
train on the track to stop too.
Idea. In this case study, the following aspects need to be considered:
(1) The scenario describes processes running in parallel.
(2) We need to specify the state space and the pre- and postconditions of actions.
(3) There are timing constraints on the duration of system states.
For encompassing all these aspects, we use the specification language COD,
that allows to express the control flow of the systems (expressed in CSP), data
structures used for modelling state and state change (OZ) and time constraints
(DC). We pass from specification to verification as follows:
– We associate so-called Phase Event Automata ACSP , AOZ , ADC with the
CSP, OZ and DC part, respectively. Their parallel composition A represents
the semantics of the COD specification.
– From A we derive a family of transition constraints that describe the properties of the transitions in the system.
– We use this set of transition constraints for checking given safety properties.
This last verification step is highly non-trivial. Transition constraints may combine constraints over various theories. In our case, we need to reason in a combination of a theory of integers (indices of trains), reals (for modelling speeds or
distances), arrays (in which the current speed and reported positions of the trains
are stored), and functions (e.g., associating with each speed an upper bound for
the optimal braking distance at that speed). Many of these data structures have
additional properties, which need to be specified as axioms in first-order logic
with quantifiers. We show that properties of systems can be encoded in wellbehaved logical theories in which efficient reasoning is possible.
2
CSP-OZ-DC: A High-Level Specification Language
In order to capture the control flow, data changes, and timing aspects of the
systems we want to verify, we use the high-level specification language CSP-OZDC (COD) [HM05, Hoe06], which integrates three well-investigated formalisms:
Communicating Sequential Processes [Hoa85], Object-Z [Smi00], and Duration
Calculus [ZH04], allowing the compositional and declarative specification of each
aspect by means of the best-suited formalism. In particular, data and data
changes are specified in a constraint-based representation (using OZ). In this
236
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
paper, we use this advantage of the COD representation and extend the known
verification procedures for COD [HM05, MFR06] to combination of theories.
We give an intuition of the formalism and its advantages using our case study:
We model a radio block centre (RBC) that controls the railway traffic on a single
(to simplify matters infinite) track segment. This RBC controls n consecutive
trains, represented by their position and speed values. The full COD specification
is given in Fig. 2, that we explain in the remainder of this section.
The specification begins with the declaration of a timing parameter T PR
(cf. Sect. 2.1), followed by the interface part, in which methods are declared.
These methods are used in all parts (CSP, OZ, DC) of the COD specification,
and provide the functionality of the COD class.
Interface:
method positionReport
method detectEmergency : [trainNumber : N]
CSP. We use CSP [Hoa85] to specify the control flow of a system using processes
over events. The interface part declares all possible events.
CSP:
c
main = Driveability ||| Detection
c
Driveability = positionReport → Driveability
c
Detection = detectEmergency → Detection
The main process of our specification comprises an interleaving of two subprocesses, Driveability and Detection, for controlling the trains and incoming emergency messages synchronously. The Detection process detects emergencies using
detect Emergency events, while the Driveability process regularly updates the
train positions using positionReport events.
OZ. The data space and its changes are specified with OZ schemata [Smi00].
The OZ part of the running example begins with the state schema defining the
state space of the RBC. Positions and speed values of the trains are given by
sequences train : seq Position and speed : seq Speed , where the types are given by
reals: Position == R, Speed == R+ . Sequences, in the sense of OZ, are partial
functions train : N → Position, that are defined for all i ≤ n. A third data type
is Acceleration, which is also real-valued: Acceleration == R+ .
State space:
train : seq Position
speed : seq Speed
maxSpeed , minSpeed : Speed
brakingDist : Speed → Position
emergencyTrain : N
maxDec : Acceleration
d : Position
n:N
The variable emergencyTrain is a pointer to the first train on the track that reported an emergency. We also define some important constants, for the maximal
speed, for the minimal speed (without emergencies), the number of trains n, and
the safety margin between trains d . Next follow axioms for the data structures
defined in the state schema.
Verifying CSP-OZ-DC Specifications
237
Axioms:
0 < minSpeed < maxSpeed
n = #train = #speed
0 < d = brakingDist(maxSpeed )
s2
∀ s : Speed • brakingDist(s) ≥ 2∗maxDec
∀ s1 , s2 : Speed | s1 < s2 • brakingDist(s1 ) < brakingDist(s2 )
brakingDist(0) = 0
The latter three axioms ensure a safety distance between the trains. The function
brakingDist yields for a given speed value the distance needed by a train in order
to stop if the emergency brakes are applied. For the constant maximal decelerspd 2
.
ation maxDec, the minimal braking distance for a speed value spd is 2∗maxDec
Since the trains can not always reach their maximal deceleration, we define this
term as a lower bound for our braking function. We require monotonicity of
brakingDist and specify its value for a speed value of 0.
Every COD class has an Init schema (cf. Fig. 2) that constrains initial values
of state variables, and communication schemata which define state changes. Every communication schema (prefix com) belongs to a CSP event as given by the
interface of a class. Every time a CSP event occurs the state space is changed
according to the constraints of the appropriate communication schema.
com detectEmergency
Δ(speed , emergencyTrain)
newEmergencyTrain? : N
newEmergencyTrain? ≤ n
emergencyTrain = min{newEmergencyTrain?, emergencyTrain}
speed (emergencyTrain ) = 0
∀ i ∈ N | i = emergencyTrain • speed (i) = speed (i)
Consider for instance the schema for detectEmergency. The first line identifies
state variables that are changed by this schema, the remaining variables implicitly stay unchanged. The expression newEmergencyTrain? (second line) represents an input variable. The following lines constrain state changes (primed
variables denote the post-state while unprimed variables refer to the pre-state).
For example emergencyTrain = min{newEmergencyTrain?, emergencyTrain}
sets the new value for emergencyTrain. (The train with the lowest number is
the first on the track. So, emergencyTrain always points to the first train on
the track that reported an emergency.) The schema com positionReport (Fig. 2)
sets the speed values for all trains and calculates their new positions: without
an emergency train in front, the speed can be arbitrary between minSpeed and
maxSpeed , unless the distance to the previous train is too small (< d ); in this
case the speed is set to minSpeed . In case of an emergency, the trains behind the
emergency train brake with maximal deceleration.
DC. The duration calculus (DC) is an interval-based dense real-time logic[ZH04].
Important operators of the DC are the chop operator that splits an interval
238
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
into subintervals, the operator yielding the length of an interval, and the everywhere operator p specifying that a predicate p holds everywhere on an interval.
An explicit time constant t ∈ Q+ or a symbolic constant T are used to define
interval lengths. Since DC is undecidable we use a decidable sub-class (counterexample formulae). We apply the algorithm of [Hoe06] to generate automata
from DC specifications of this subclass.
DC:
¬(true positionReport ( < T PR) positionReport true)
¬(true positionReport ∧ ( > T PR) true)
In the DC specification above, the first formula specifies that it will never be
the case (¬) that two positionReport events () are separated () by an interval
with a length () smaller than T PR. (So there will be at least T PR time units
between two position reports.) In the second formula, describes an interval in
which no position report event is detected. The formula states that there is no
interval of a length greater than T PR without a positionReport event. Together
the formulae define the exact periodicity of positionReport .
2.1
Timing Parameters in COD
The original definition of COD in [Hoe06] only allows for using rational numbers to define interval lengths. This restriction results in a loss of generality: a
developer always has to define exact values for every interval, even if the specification does not depend on an exact length. In our example, one has to replace
the T PR constant in the DC formulae with a fixed rational to get a valid COD
specification. To overcome this problem, we introduce timing parameters as an
extension for COD. That is, we allow the usage of symbolic constants for the
interval definitions in the DC part, like T PR in our example. These symbolic
constants are declared as generic constants (parameters of the class) and also
are accessible in the OZ part. For instance, we use T PR in the schema of
positionReport . That allows us to use the same (undetermined) interval length
in the OZ and in the DC part.
3
Operational Semantics of COD Specifications
In this section, we present a translation from COD specifications to PEA. We extend existing translations from COD to PEA to also deal with timing parameters
and study possibilities of simplifying the PEA obtained this way.
3.1
Translation of COD Specifications into PEA
Phase Event Automata (PEA) are timed automata [AD94] involving both data
and timing aspects. Our definition of PEA is based on [Hoe06], but differs in
that we also allow symbolic constants to occur in clock invariants Lc (C ). In
what follows, let L(V ) be a subset of the language of OZ predicates.1 For a
1
Ideally, L(V ) should be expressive enough so that specifications with complex data
types can be translated, but should permit automatic verification.
Verifying CSP-OZ-DC Specifications
train : seq Position
speed : seq Speed
maxSpeed, minSpeed : Speed
brakingDist : Speed → Position
CSP Interpart face
RBC [T PR : Q+ ]
method positionReport
method detectEmergency : [trainNumber : N]
c
main = Driveability ||| Detection
c
Driveability = positionReport → Driveability
c
Detection = detectEmergency → Detection
239
emergencyTrain : N
maxDec : Acceleration
d : Position
n :N
0 < minSpeed < maxSpeed
n = #train = #speed
0 < d = brakingDist(maxSpeed)
s2
∀ s : Speed • brakingDist(s) ≥ 2∗maxDec
∀ s1 , s2 : Speed | s1 < s2 • brakingDist(s1 ) < brakingDist(s2 )
brakingDist(0) = 0
(1)
com positionReport
Δ(train, speed)
∀ i : dom train | i = 1 ∧ i < emergencyTrain
• minSpeed ≤ speed (i) ≤ maxSpeed
∀ i : dom train | 1 < i < emergencyTrain ∧ train(i − 1) − train(i) ≥ d
• minSpeed ≤ speed (i) ≤ maxSpeed
∀ i : dom train | 1 < i < emergencyTrain ∧ train(i − 1) − train(i) < d
• minSpeed = speed (i)
∀ i : dom train | i ≥ emergencyTrain
• speed (i) = max {speed(i) − maxDec ∗ T PR, 0}
∀ i : dom train • train (i) = train(i) + speed (i) ∗ T PR
OZ part
Init
emergencyTrain > n
∀ i : dom speed • minSpeed ≤ speed(i) ≤ maxSpeed
∀ i : dom train | i = 1
• train(i) < train(i − 1) − brakingDist(speed(i))
com detectEmergency
Δ(speed, emergencyTrain)
newEmergencyTrain? : N
¬(true positionReport ( < T PR) positionReport true)
¬(true positionReport ∧ ( > T PR) true)
DC
part
newEmergencyTrain? ≤ n
emergencyTrain = min{newEmergencyTrain?, emergencyTrain}
speed (emergencyTrain ) = 0
∀ i ∈ N | i = emergencyTrain • speed (i) = speed(i)
Fig. 2. The COD specification for the emergency case study
set C of clock variables and timing parameters T , the set Lc (C , T ) of (convex)
clock constraints with constants is defined by the following BNF grammar:
δ ::= c < t | c ≤ t | c < z | c ≤ z | δ ∧ δ,
where c ∈ C is a clock, t ∈ Q+ is a rational constant, and z ∈ T is a timing
parameter. The semantics is given by clock valuations γ : C → R+ assigning non-negative reals to clocks. The semantics of a timing parameter z is an
240
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
interpretation I : T → Q+ . We write γ, I |= δ iff δ holds for γ and I. For a set of
clocks X , we denote by (γ + t ) the increasing of clocks, i.e., (γ + t )(c) := γ(c)+ t ,
and by γ[X := 0] the valuation, where each clock in X is set to zero and the
values of the remaining clocks are given by γ.
Definition 1 (Phase Event Automaton). A phase event automaton (PEA)
is a tuple (P , V , A, C , E , s, I , P 0 ), where P is a finite set of locations (phases)
with initial locations P 0 ⊆ P ; V , A, C are finite sets of real-valued variables,
events, and real-valued clocks, respectively; s : P → L(V ), I : P → Lc (C , T )
assign state invariants resp. clock invariants to phases. The set of edges
is E ⊆
∪A∪C
)×P(C
)×P
.
We
assume
that
a
stuttering
edge
(p,
P
×L(V
∪V
e∈A ¬e ∧
v
=v
,
∅,
p)
(empty
transition)
exists
for
every
phase
p.
v ∈V
The operational semantics of PEA is defined by infinite runs of configurations
(p0 , β0 , γ0 , t0 , Y0 ), (p1 , β1 , γ1 , t1 , Y1 ), · · · , where initially p0 ∈ P 0 and γ0 (c) = 0
for c ∈ C . For i ∈ N and variable valuations βi (with βi (v ) = βi (v )) we demand
β(i) |= s(pi ) and γi + ti , I |= I (pi ) and ti > 0. For transitions (pi , g, X , pi+1 ) ∈
E we further require βi , βi+1
, γi + ti , Yi |= g and γi+1 = (γi + ti )[X := 0].
Thus, a PEA is an automaton enriched by constraints to define data changes and
clocks to measure time (similar to a timed automaton). An edge (p1 , g, X , p2 )
represents a transition from p1 to p2 with a guard g over (possibly primed)
variables, clocks, and events, and a set X of clocks that are to be reset. Primed
variables v denote the post-state of v whereas the unprimed v always refers to
the pre-state. In the parallel composition of PEA, we consider conjunctions of
guards of transitions and invariants of locations.
Definition 2 (Parallel Composition). The parallel composition of two PEA
A1 and A2 , where Ai = (Pi , Vi , Ai , Ci , Ei , si , Ii , Pi0 ), is defined by
A1 || A2 := (P1 × P2 , V1 ∪ V2 , A1 ∪ A2 , C1 ∪ C2 , E , s1 ∧ s2 , I1 ∧ I2 , P10 × P20 ),
where ((p1 , p2 ), g1 ∧ g2 , X1 ∪ X2 , (p1 , p2 )) ∈ E iff (pi , gi , Xi , pi ) ∈ Ei with i = 1, 2.
The translation of COD specifications into PEA is compositional: every part
of the specification is translated separately into PEA; the semantics for the
entire specification is the parallel composition of the automata for every part:
A(COD) = A(CSP ) A(OZ ) A(DC ).
Translation of the CSP part. The translation of the CSP part into PEA is
based on the structured operational semantics of CSP [Ros98]. If this semantics
of the CSP part is given as a labelled transition system (Q , A, q0 , −→) with
locations Q and events A from the COD specification, its PEA is A(CSP ) =
(Q , ∅, A, ∅, E , s, I , {q0}), where s(q) = true, I (q) = true for all q ∈ Q and
E = {(p, only(e), ∅, p ) | p −→ p } ∪ {(p, only(τ ), ∅, p) | p ∈ Q }.
e
The predicate only(e) demands that only the event e is communicated whereas
only(τ ) demands that no event is communicated. That is, E consists of transitions for every transition in the original transition system and of stuttering edges
for every location. The PEA of our example’s CSP part is pictured in Fig. 3.
Verifying CSP-OZ-DC Specifications
241
Translation of the OZ part. The OZ part of a COD specification is translated
into a PEA with two locations: one for setting the initial values of state variables
and one for the running system, with a transition for each state changing event.
The variables of the PEA are the variables Var (State) declared in the state
schema. The set A of events of the PEA consists of all COD events for which a
communication schema com c exists. For each such event the automaton has a
transition executing the state change as defined in the associated communication
schema. The resulting PEA is A(OZ ) = ({p0 , p1 }, Var (State), A, ∅, E , s, I , {q0}),
where s(p0 ) = Init (invariant from the initial schema), s(p1 ) = State (invariant
from the state schema), I (pi ) = true for i = 1,2, and
E = {(p1 , only(c) ∧ com c, ∅, p1 ) | c ∈ A} ∪
{(pi , only(τ ) ∧ ΞState, ∅, pi ) | i = 1, 2} ∪ {(p0 , only(τ ) ∧ ΞState, ∅, p1 )}.
The OZ predicate ΞState demands that the state space is not changed:ΞState :⇔
v ∈Var (State) v = v . The formula com c only changes the state of the variables
occurring in the Δ list of the corresponding operation schema; the remaining
variables remain implicitly unchanged. The OZ part PEA of the RBC is illustrated in Fig. 3. Formula (1) refers to the state schema from Fig. 2. The operation
schemata, e.g., com positionReport refer to the constraints of the specification.
Translation of the DC part. Each formula of the DC part is translated into
an individual PEA. The translation of counter-example formulae (cf. Sect. 2),
e.g., ¬(phase0 event1 phase1 · · · phasen ), into PEA is similar to
the translation of a non-deterministic finite automaton into a deterministic one:
every location of the resulting automaton represents a subset of DC phases.
Every run of the automaton leading to a location labelled with phasei accepts
the prefix of the DC counter-example up to phasei . In addition, phasei may have
an upper or lower time bound. In this case, the automaton includes a clock ci
measuring the duration of the phase. Event expressions eventi separating two DC
phases constitute the guards that restrict transitions from phasei−1 to phasei .
Technical details of the construction can be found in [Hoe06]. The automata for
the DC part of the RBC specification are displayed in Fig. 3(c). For instance,
the upper automaton enforces the behaviour defined by the second DC formulae
of our example (Fig. 2). It consists of one location with a clock invariant, i.e, the
automaton stays in this location for at most T PR time units – the only way to
reset the clock c1 is the transition that synchronises on positionReport . By this,
every positionReport event has to occur in time.
3.2
PEA with Timing Parameters
As we allow timing parameters to occur in the DC part and in convex clock
expressions, we need to adapt the translation of the DC part into PEA given in
[Hoe06]: since the original translation does not depend on concrete values of rational constants, we can treat timing parameters exactly like rational constants.
The clock constraints generated by the translation are then convex as before.
242
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
only(detectEmergency)
c1 ≤ T PR
main
true
Drive|Detect
only(positionReport)
positionReport
{c1}
¬positionReport
∧ c1 < T PR
(a) CSP part
(1) ∧ Init
only(detectEmergency) ∧
com detectEmergency
¬positionReport ∧
(1)
¬detectEmergency ∧
ΞState
only(positionReport) ∧
com positionReport
(b) OZ part
¬positionReport
c2 < T PR
positionReport
{c2}
c2 ≤ T PR
¬positionReport
∧ c2 ≥ T PR positionReport
∧ c2 ≥ T PR
¬positionReport
{c2}
(c) DC part
Fig. 3. PEA for the RBC case study. Boxes around formulae indicate state invariants;
braces ({c1},{c2}) indicate clock resets.; Ξ is defined on page 241.
Important properties of PEA, e.g., the translation into TCS (cf. Sect. 4), only
depend on the convexity of clock constraints. We thus obtain:
Theorem 1. The translation from COD with complex data types and timing
parameters to PEA described here is sound (i.e., the PEA runs are exactly the
system runs admitted by the CSP, OZ, and DC part) and compositional.
3.3
Simplifications of PEA
As mentioned in Section 3.1, the operational semantics of the whole COD specification is given by the parallel product of the individual PEA. This product can
grow very large: theoretically, its size is the product of the size of all individual
automata, both in terms of locations and in terms of transitions. We propose
the following simplifications for the product PEA:
– Transitions whose combined guards evaluate to false can be removed, as
can be locations that are not connected to an initial state. We can also
remove all events from the PEA, as these are only used for synchronising
the individual automata [Hoe06].
– Consider the case that we have several clocks in the product automaton.
All clocks run at the same speed and can be reset to 0 by transitions. If we
have two (or more) clocks for which the set of transitions that resets them is
the same, we can identify them, i.e., remove one clock and replace it by the
other in all guards. This not only gives us a system with one variable less,
but may also remove additional transitions by making their guards false.
Theorem 2. Let A = (P , V , A, C , E , s, I , P 0 ) be a PEA, c1 , c2 ∈ C . If
{(p1 , g, X , p2 ) ∈ E | c1 ∈ X } = {(p1 , g, X , p2 ) ∈ E | c2 ∈ X }, then A is equivalent to A = (P , V , A, C \ {c2 } , E , s , I , P 0 ), where E , s and I result from
E , s and I by replacing all occurrences of c2 by c1 .
Verifying CSP-OZ-DC Specifications
243
c1 < T PR ∧ Ξ
(1) ∧ Init ∧
c1 ≤ T PR
c1 < T PR ∧ Ξ
c1 < T PR ∧ Ξ
c1 < T PR ∧
com detectEmergency
c1 < T PR ∧ Ξ
(1) ∧ c1 ≤ T PR
(1) ∧ Init ∧ c1 ≤ T PR
c1 < T PR
∧Ξ
c1 < T PR
∧Ξ
c1 < T PR ∧ Ξ
c1 < T PR ∧ Ξ
(1) ∧ c1 ≤ T PR
com positionReport
{c1,c2}
c1 ≤ T PR ∧
c2 ≤ T PR ∧ (1)
c1 < T PR ∧
c2 < T PR ∧
Ξ
com positionReport
∧ c2 ≥ 1 {c1,c2} c1 < T PR ∧ c2 < T PR ∧
com detectEmergency
c1 < T PR ∧ Ξ
Fig. 4. Simplified product PEA
Applied to the running example, the first simplification reduces the product
automaton from 8 locations and 90 transitions (without stuttering edges) to 5
locations and 10 transitions. With the second one, we remove one clock variable
and one additional transition from the product automaton. The entire product
automaton with simplifications is pictured in Fig. 4. It basically comprises four
locations representing slightly different possibilities to initialise the system and
one dead end location in the lower right corner. The latter is eventually entered and can be interpreted as the main state of the system. Here the trains
periodically report their positions to the RBC and emergencies may be detected.
4
Verification of COD Specifications
In this section, we elaborate on verifying safety properties of systems with complex data types specified in COD, based on their translation to PEA. We define
transition constraint systems (TCS) and show how to extract a TCS from a
PEA. We introduce the verification tasks that we consider. After an intuitive
presentation of our idea for efficient verification, we formally analyse situations
where verification problems can be reduced to checking satisfiability of ground
formulae over a simple theory. The method is illustrated on the running example.
Language and theory associated with a COD specification. Let S be
a COD specification. The signature of S , ΣS consists of all sorts, functions
and predicates declared in the OZ specification either implicitly (by mentioning
standard theories) or explicitly. The theory of S , TS is constructed by extending
the (many-sorted) combination T0 of all standard theories used in the OZ and DC
specification with the functions declared in the OZ part and the axioms for the
data structures specified at the beginning of the OZ part (which we will denote
by Ax). In what follows, the theory TS will be considered to be a background
theory: even if we do not refer to it explicitly, it is always taken into account.
244
4.1
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
Translation of PEA to TCS
Let Σ be a signature, V a set of (typed) variables, and V a copy of corresponding
primed variables. Let F (X ) be the family of all Σ-formulae in the variables X .
Definition 3 (Transition Constraint Systems). A transition constraint system T is a tuple (V, Θ, Φ) with Θ ∈ F(V) and Φ ∈ F(V ∪ V ). The formula Θ
characterises the initial states of T , Φ the transition constraints of T (i.e., the
relationships between the variables V and V – before and after transitions).
A translation from PEA to TCS has been developed by Hoenicke and Maier
[HM05, Hoe06]. We use the simplified translation from [Hoe06].
Let S be a COD specification and AS = (P , V , A, C , E , s, I , P0 ) the PEA
associated with S . We associate with AS the TCS T (AS ) = (V, Θ, Φ), where:
– V = V ∪ A ∪ C ∪ {len, pc}, where len is a real-valued variable representing
the time spent in the current state, and pc is the program counter that is
interpreted
over P and represents
the current location (phase) of the system.
– Θ = p∈P0 pc=p ∧ len>0 ∧ c∈C c=len ∧ s(p) ∧ I (p). Θ requires that there
exists an initial location p in which a positive time len is spent, all clocks are
set to
p hold.
len and both the state and the clock invariant of the location
– Φ = (p1 ,g,X ,p2 )∈E pc=p1 ∧pc =p2 ∧g ∧s (p2 )∧I (p2 )∧len >0∧ c∈X c =len ∧
c∈C \X c =c + len , where s and I represent s and I with unprimed variables replaced by primed ones. The formula Φ states that there exists a
transition (p1 , g, X , p2 ) such that the program counter is p1 before and p2
after the transition, the guard g of the transition as well as the state and
clock invariant of location p2 are satisfied, the system will remain in p2 for
some positive time, and clocks are incremented by len if they are not reset
by the transition (otherwise they are set to len ).
We thus obtain a representation of the original COD specification S in terms
of first-order formulae over the signature ΣS and theory TS of S . We encode
states of the system by formulae over V. If σ, σ are states (encoded as formulae
over V, and V respectively), we say that σ is reachable in one step from σ in
TS = (V, Θ, Φ) w.r.t. TS if TS , σ, σ |= Φ. A run of TS is a sequence of states
σ1 , . . . σm such that TS , σ1 |= Θ and σi+1 is reachable in one step from σi .
As a consequence of the results in [Hoe06] we obtain:
Corollary 1. The translation from PEA to TCS preserves the semantics: every
run in the TCS can be mapped to a run of the PEA; the mapping is surjective.
Example 1. Consider the RBC example discussed in Sect. 1.1. We use the simplified PEA A = (P , V , A, C , E , s, I , P0 ) developed in Sect. 3.3, where A = ∅ and
C = {x1 }. The TCS T (A) = (V, Θ, Φ) associated with A is defined as follows2 :
(1) V = V ∪ A ∪ C ∪ {len, pc}. For technical reasons we model the variables of
type sequence (e.g. train, speed) as functions of sort i → num.
2
We will use a sans serif font for all symbols in the signature of the TCS T (A).
Verifying CSP-OZ-DC Specifications
245
The following formulae (extracted from the OZ specification) help define T (A):
φinput = newEmergencyTrain > 0,
φclock = x1 <1 ∧ len >0 ∧ x1 =x1 + len ∧ x1 ≤1,
φinit = (∀ i : 1<i≤n → train(i)<train(i − 1)−brakingDist(speed(i)))∧
(∀ i : 1≤i≤n → minSpeed≤speed(i)≤maxSpeed) ∧ (emergencyTrain>n),
φemerg = newEmergencyTrain ≤ n ∧
emergencyTrain = min {newEmergencyTrain, emergencyTrain} ∧
speed (emergencyTrain ) = 0 ∧
∀ i : i = emergencyTrain → speed (i) = speed(i),
φposRep = ∀ i : i=1 ∧ emergencyTrain>i → minSpeed≤speed (i)≤maxSpeed ∧
∀ i : 1<i<emergencyTrain ∧ train(i − 1)−train(i)≥d
→ minSpeed≤speed (i)≤maxSpeed ∧
∀ i : 1<i<emergencyTrain ∧ train(i − 1)−train(i)<d
→ speed (i)=minSpeed ∧
∀ i : i≥emergencyTrain → speed (i)=max {speed(i)−maxDec∗T PR, 0} ∧
∀ i : 1≤i≤n → train (i)=train(i)+speed (i)∗T PR,
φconst = c∈const c = c, where const = {maxDec, maxSpeed, minSpeed, n, d, T PR}
is the set of all variables in V that do not change during execution.
(2) The initial predicate is Θ = pc = 1 ∧ len > 0 ∧ x1 = len ∧ φinit .
(3) We describe the transition relation Φ in terms of the individual transitions.
Several transitions change only the clock, but no state variables. Let S1 =
{(1, 1), (1, 3), (3, 3)} , S2 = {(1, 2), (1, 4), (2, 2), (2, 4), (4, 4)} ⊂ P × P , and
(pc=i ∧ pc =j ∧ φclock ∧ φinit ∧ φconst ∧ φinput ) if (i, j ) ∈ S1
φ(i,j ) =
.
(pc=i ∧ pc =j ∧ φclock ∧ φconst ∧ φinput )
if (i, j ) ∈ S2
Finally, we have the following transitions that change the state variables:
φ1 = (pc=4 ∧ pc =4 ∧ φemerg ∧ φclock ∧ φconst ∧ φinput ),
φ2 = (pc=4 ∧ pc =5 ∧ φposRep ∧ len >0 ∧ x1 =0 ∧ x1 ≤ 1 ∧ φconst ∧ φinput ),
φ3 = (pc=5 ∧ pc =5 ∧ φemerg ∧ φclock ∧ φconst ∧ φinput ),
φ4 = (pc=5 ∧ pc =5 ∧ φposRep ∧ len >0 ∧ x1 =0 ∧ x1 ≤1 ∧ φconst ∧ φinput ).
4
Altogether, Φ = (i,j )∈S1 ∪S2 φ(i,j ) ∨ i=1 φi .
4.2
Verification of TCS
The verification problems we consider are invariant checking and bounded model
checking. We explain the problems which occur in this context, and present an
idea that allows to solve these problems in certain situations. We illustrate the
problems as well as the verification methods on our case study.
Invariant checking. We can check whether a formula Ψ is an inductive invariant of a TCS T =(V, Θ, Φ) in two steps: (1) prove that TS , Θ |= Ψ ; (2) prove that
TS , Ψ, Φ |= Ψ , where Ψ results from Ψ by replacing every x ∈ V by x . Failure
to prove (2) means that Ψ is not an invariant, or Ψ is not inductive w.r.t. T .3
3
Proving that a Ψ is an invariant of the system in general requires to find a stronger
formula Γ (i.e., T0 |= Γ → Ψ ) and prove that Γ is an inductive invariant.
246
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
Example 2. For the system described in Sect. 1.1, let Ψ be the formula that
states that the distance between two trains must always be greater than the
sum of the braking distances of the trains in between (Ψ is a safety condition):
Ψ = ∀ i : 1 < i ≤ n → train(i) < train(i − 1) − brakingDist(speed(i)).
To check that Ψ is an inductive invariant, we need to check that:
(1) The initial states of the system, given by Θ, satisfy the safety property Ψ .
(2) Assuming that a given state σ satisfies Ψ , any state σ reachable from σ
using the transition predicate Φ satisfies Ψ .
Checking (1) is not a problem. For (2) we need to show TS |= Ψ ∧ Φ → Ψ ,
where TS is the theory associated with the COD specification, an extension of
T0 (many-sorted combination of real arithmetic (sort num) with an index theory
describing precedence of trains (sort i)), with the set of definitions Def ⊆ Ax for
global constants of the system (Ax are the axioms in the OZ specification) and
with function symbols brakingDist, train, train , speed, speed fulfilling the axioms
specified in Ax, Ψ , and Φ. We need to show that T0 ∧ Ax ∧ Ψ ∧ Φ ∧ ¬Ψ |=⊥.
Bounded model checking. We check whether, for a fixed k , unsafe states
are reachable by runs of T =(V, Θ, Φ) of length at most k . Formally, we check
whether:
j
TS ∧ Θ0 ∧
Φi ∧ ¬Ψj |=⊥
for all 0 ≤ j ≤ k ,
i=1
where Φi is obtained from Φ by replacing all variables x ∈ V by xi , and all
variables x ∈ V by xi+1 ; Θ0 is Θ with x0 replacing x ∈ V; and Ψi is Ψ with xi
replacing x ∈ V.
Problem. Standard combination methods [NO79, Ghi04] allow for testing satisfiability in certain combinations of theories, but only for ground formulae.
Our problem contains several non-ground formulae: the global axioms Ax, the
invariant Ψ and the transition relation Φ. Only ¬Ψ corresponds to a ground set of
clauses. Thus, standard methods are not directly applicable. We want to reduce
the problem above to a ground satisfiability problem over decidable theories. To
this end, we may replace quantified formulae by a number of ground instances,
giving a decidable ground satisfiability problem over the base theory T0 (plus
free function symbols). This approach is sound, but in general not complete. In
what follows, we identify situations when this method is complete.
Our idea. In order to overcome the problem mentioned above we proceed as
follows. We start from a base theory T0 associated with the COD specification S
(usually a many-sorted combination of standard theories, e.g., integers or reals).
For the case of invariant checking we consider the following successive extensions
of T0 and study possibilities of efficient reasoning in these extensions:
– the extension T1 of T0 with the definitions and axioms in the OZ part of the
COD specification for variables which do not occur in Φ (i.e., do not change);
Verifying CSP-OZ-DC Specifications
247
– the extension T2 of T1 with the remaining variables in a set V (including
those of sort sequence, modelled by functions) which occur in Φ and satisfy
Ψ (together with the corresponding definitions and axioms);
– the extension T3 of T2 with primed variables V (including primed versions
of functions for the variables of sort sequence) satisfying Φ.
Example 3. Again consider the running example. We consider successive extensions of T0 , a many-sorted combination of real arithmetic (for reasoning about
time, positions and speed, sort num) with an index theory (for describing precedence between trains, sort i). For the case of invariant checking, we have:
– the extension T1 of T0 with a monotone and bounded function brakingDist
as well as global constants, defined by Def ⊆ Ax,
– the extension T4 of T1 with V-variables from Φ, satisfying Ψ , defined by:
– Let T2 be the extension of T1 with the (free) function speed.
– Let T3 be the extension of T2 with the binary function secure defined for
every 0 < i < j < n by secure(i, j ) = jk =i+1 brakingDist(speed(k )).
– T4 is the extension of T3 with function train satisfying Ψ (equivalent to Ψ ):
Ψ = ∀ i, j (0 < i < j ≤ n → train(j ) < train(i) − secure(i, j )),
– the extension T5 of T4 with functions train and speed satisfying Φ.
We show that for all of these extensions hierarchic reasoning is possible (cf.
Sect. 4.3).4 This allows us to reduce problem (2) to testing satisfiability of ground
clauses in T0 , for which standard methods for reasoning in combinations of theories can be applied. A similar method can be used for bounded model checking.
4.3
Efficient Reasoning in Complex Theories: Locality
In the following, we identify situations in which we can give sound, complete
and efficient methods for reasoning in theory extensions.
Local theory extensions. Let T0 be a theory with signature Π0 =(S0 , Σ0 , Pred).
We consider extensions with new sorts S1 and new function symbols Σ1 constrained by a set K of (universally quantified) clauses in signature Π=(S , Σ, Pred),
where S = S0 ∪ S1 and Σ = Σ0 ∪ Σ1 . We are interested in checking satisfiability
of sets of ground clauses G with respect to such theory extensions.
When referring to sets G of ground clauses we assume they are in the signature
Π c = (S , Σ ∪ Σc , Pred) where Σc is a set of new constants. An extension T0 ⊆
T0 ∪ K is local if satisfiability of a set G of clauses w.r.t. T0 ∪ K only depends
on T0 and those instances K[G] of K in which the terms starting with extension
functions are in the set st(K, G) of ground terms which already occur in G or
K. Formally, the extension T0 ⊆ T0 ∪ K is local if condition (Loc) holds:
4
We consider extensions with axiom Ψ instead of Ψ since Ψ defines a local theory
extension, and hence it allows for hierarchic reasoning (cf. Sect. 4.3), whereas Ψ
does not have this property. We are currently studying possibilities of automatically
recognising local theory extensions, and of automatically generating (equivalent) sets
of axioms defining local extensions from given sets of axioms.
248
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
(Loc)
For every set G of ground clauses, T0 ∧ K ∧ G is unsatisfiable iff T0 ∧
K[G] ∧ G has no partial model where all terms in st(K, G) are defined
A partial model of T0 ∧K[G]∧G is a partial Π c -structure P s.t. P|Π0 is a total
model of T0 and P satisfies all clauses in K[G]∧G where all terms are defined.
We give examples of local theory extensions relevant for the verification tasks
we consider. Some appear in [GSSW06, SS05, SS06], some are new.
Theorem 3. The extension of any theory with free function symbols is local.
In addition, assume the base theory has a reflexive partial ordering ≤. Then:
(1) Extensions of T0 with axioms of the following type are also local:
∀ x1 , . . . , xn (φ(x1 , . . . , xn ) → f (x1 , . . . , xn ) ≤ t (x1 , . . . , xn ))
(GBoundtf )
where t (x1 , . . . , xn ) is a term, φ(x1 , . . . , xn ) a conjunction of literals, both in
the base signature Π0 and with variables among x1 , . . . , xn .
(2) For i ∈ {1, . . . , m}, let ti (x1 , . . . , xn ) and si (x1 , . . . , xn ) be terms and let
φi (x1 , . . . , xn ) be conjunctions of literals, all of them in the base signature
Π0 , with variables among x1 , . . . , xn , such that for every i = j , φi ∧φj |=T0 ⊥.
Any “piecewise-bounded” extension T0 ∧(GBoundf ), where f is an extension
m
[s ,t ],φ
symbol, is local. Here (GBoundf ) = i=1 (GBoundf i i i );
[si ,ti ],φi
(GBoundf
)
∀ x (φi (x ) → si (x ) ≤ f (x ) ≤ ti (x )).
(3) For many ordered theories including the reals (for a complete list see [SS05,
SS06, JSS07]), extensions with (possibly strictly) monotone functions are
local. Combinations with boundedness axioms (GBoundtf ), where t has the
same monotonicity as f , do not destroy locality.
Hierarchic reasoning in local theory extensions. Let T0 ⊆ T1 =T0 ∪ K be
a local theory extension. To check the satisfiability of a set G of ground clauses
w.r.t. T1 we can proceed as follows (for details cf. [SS05]):
Step 1: Use locality. By the locality condition, G is unsatisfiable w.r.t. T1 iff
K[G]∧G has no partial model in which all the subterms of K[G]∧G are defined,
and whose restriction to Π0 is a total model of T0 .
Step 2: Flattening and purification. We purify and flatten K[G] ∧ G by introducing new constants for the arguments of the extension functions as well as for the
(sub)terms t = f (g1 , . . . , gn ) starting with extension functions f ∈ Σ1 , together
with corresponding new definitions ct ≈ t . The set of clauses thus obtained has
the form K0 ∧ G0 ∧ D , where D is a set of ground unit clauses of the form
f (c1 , . . . , cn ) ≈ c, where f ∈ Σ1 and c1 , . . . , cn , c are constants, and K0 , G0 are
clause sets without function symbols in Σ1 .
Step 3: Reduction to testing satisfiability in T0 . We reduce the problem to testing
satisfiability in T0 by replacing D with the following set of clauses:
n
N0 =
{
ci = di → c = d | f (c1 , . . . , cn ) = c, f (d1 , . . . , dn ) = d ∈ D }.
i=1
Verifying CSP-OZ-DC Specifications
249
Theorem 4 ([SS05]). Assume that T0 ∪ K is a local extension of T0 . With the
notations above, G is satisfiable in T0 ∪ K iff K0 ∧ G0 ∧ N0 is satisfiable in T0 .
The method above is easy to implement and efficient. If all the variables in K are
guarded by extension functions then the size of K0 ∧ G0 ∧ N0 is polynomial in the
size of G. Thus, the complexity of checking the satisfiability of G w.r.t. T0 ∧ K
is g(n k ) (where k depends on K cf. e.g. [SS05]) where g(n) is the complexity of
checking the satisfiability of a set of ground clauses of size n in T0 .
Application to parametric verification of COD specifications. A sound
but potentially incomplete method for checking whether T0 ∧Ax∧Ψ ∧Φ∧¬Ψ |= ⊥,
which can always be used, is to take into account only certain ground instances
of the universally quantified formulae in Ax∧Ψ ∧Φ, related to the ground formula
G = ¬Ψ . However complete approaches can often be obtained, because many
axioms used in verification problems define chains of local extensions of T0 :
– definitions for constants can be expressed by axioms of the type GBoundtf ;
– often, transition relations which reflect updates of variables or of a sequence
f according to mutually exclusive “modes of operation” are axiomatised by
axioms of the form (GBoundf ) as defined in Theorem 3(2) and 3(3).
If a complete approach can be given, the method for hierarchic reasoning described above can be used in two ways. If the constraints on the parameters of
the systems are completely specified in the COD specification, then it allows us
to reduce the problem of checking whether a system property Ψ is an inductive
invariant to the problem of deciding satisfiability of a set of constraints in T0 .
Alternatively, we may choose not to specify all constraints on the parameters.
As a side effect, after the reduction of the problem to a satisfiability problem in
the base theory, one can automatically determine constraints on the parameters
(in the running example these are, e.g., T PR, minSpeed, maxSpeed, ...), which
guarantee that the property is an inductive invariant and are sufficient for this.
(This can be achieved for instance using quantifier elimination.)
4.4
Example: The RBC Case Study
We show how the verification method based on hierarchic reasoning can be
applied to our case study. The following is a consequence of Theorem 3.
Theorem 5. Let T0 be the (many-sorted) combination of real arithmetic (for
reasoning about time, positions and speed, sort num) with an index theory (for
describing precedence between trains, sort i).
(1) The extension T1 of T0 with a monotone and bounded function brakingDist
as well as global constants, with definitions Def ⊆ Ax, is local.
(2) The extension T2 of T1 with the (free) function speed is local.
(3) The extension T3 of T2 with the function secure (cf. Example 3) is local.
(4) The extension T4 of T3 with functions train satisfying Ψ (Example 3) is local.
(5) The extension T5 of T4 with functions train and speed satisfying Φ is local.
250
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
We follow the steps in the method for hierarchic reasoning in Sect. 4.3 and
reduce the verification task to a satisfiability problem in the base theory T0 . To
make our task slightly simpler, we split the transition relation and look at every
φi separately. Those φi that do not change the state variables train and speed
are sure to preserve the invariant. Furthermore, the program counters do not
interfere with the invariant. As a result, we have two interesting cases:
Φ1 = φemerg ∧ φclock ∧ φconst ∧ φinput ,
Φ2 = φposRep ∧ len > 0 ∧ x1 = 0 ∧ x1 ≤ 1 ∧ φconst ∧ φinput .
We start with the first transition. We have to prove T0 ∧ Def ∧ Def secure ∧ Ψ ∧
Φ1 ∧ ¬Ψ |=⊥. This is a satisfiability problem over T4 ∧ Φ1 . In a first reduction,
this problem is reduced to a problem over T4 = T0 ∧ Def ∧ Def secure ∧ Ψ :
Step 1: Use locality. For this step, the set of ground clauses we consider is G =
¬Ψ = {1 < k1 , k1 ≤ n, k2 = k1 + 1, s = speed (k1 ), train (k1 ) ≥ train (k2 ) −
brakingDist(s)}. Of the extension symbols train and speed , only speed occurs in
Φ1 . Ground terms with speed are speed (k1 ) in G and speed (emergencyTrain )
in Φ1 . Thus, Φ1 [G] consists of two instances of Φ1 : one with i instantiated to
k1 , the other with i instantiated to emergencyTrain (we remove clauses that are
generated in both instantiations such that they only appear once):
Φ1 [G] = φclock ∧ φinput ∧ φconst ∧ newEmergencyTrain ≤ n ∧
emergencyTrain = min {newEmergencyTrain, emergencyTrain} ∧
speed (emergencyTrain ) = 0 ∧
k1 = emergencyTrain → speed (k1 ) = speed(k1 ) ∧
emergencyTrain = emergencyTrain
→ speed (emergencyTrain ) = speed(emergencyTrain ).
Step 2: Flattening and purification. Φ1 [G] ∧ G is already flat with respect to
speed and train . We purify the set of clauses by replacing every ground term
with speed or train at the root with new constants c1 , . . . , c4 and obtain a set
of definitions D = {speed (emergencyTrain ) = c1 , speed (k1 ) = c2 , train (k1 ) =
c3 , train (k2 ) = c4 }, together with the purified sets of clauses
G0 = {1 < k1 , k1 ≤ n, k2 = k1 + 1, s = c2 , c3 ≥ c4 − brakingDist(s)}
Φ1 [G]0 = φclock ∧ φinput ∧ φconst ∧ newEmergencyTrain ≤ n ∧
emergencyTrain = min {newEmergencyTrain, emergencyTrain} ∧
c1 = 0 ∧ k1 = emergencyTrain → c2 = speed(k1 ) ∧
emergencyTrain = emergencyTrain → c1 = speed(emergencyTrain ).
Step 3: Reduction to satisfiability in T4 . We add the set of clauses N0 =
{emergencyTrain = k1 → c1 = c2 , k1 = k2 → c3 = c4 }. This allows us to remove
D and obtain a ground satisfiability problem in T4 : Φ1 [G]0 ∧ G0 ∧ N0 . In four
further reduction steps, we reduce this problem (using a similar procedure) to
a ground satisfiability problems over T0 . This set of clauses can now directly be
handed to a decision procedure for the combination of the theories of reals and
indices. In the same way, the transition Φ2 can be handled.
Verifying CSP-OZ-DC Specifications
5
251
Conclusions
In this paper, we presented a method for invariant checking and bounded model
checking for complex specifications of systems containing information about processes, data, and time. In order to represent these specifications in full generality,
we used the specification language CSP-OZ-DC (COD) [HO02, Hoe06]. Similar
combined specification formalisms are, e.g., [MD99, Smi02, Süh02] but we prefer
COD due to its strict separation of control, data, and time, and to its compositionality (cf. Sect. 3), that is essential for automatic verification.
One of our goals was to model complex systems with a parametric number of
components. For this, it was essential to use complex data structures (e.g., arrays,
functions). Therefore, in this paper we needed to extend existing verification
techniques for COD [HM05, MFR06] to situations when abstract data structures
appear. Also, in order to achieve a tighter binding of the OZ to the DC part, we
introduced timing parameters, allowing for more flexible specifications.
We showed that, in this context, invariant checking or bounded model checking can be reduced to proving in complex theories. This was done using translations from COD to PEA (and then to simplified PEA) and from PEA to TCS
(these translations can be fully automated – we already have tool support for
them). We then analysed the type of theories that occur in relationship with a
given COD specification, and presented a sound method for efficient reasoning
in these theories. At the same time, we identified situations when the method
is sound and complete (i.e., when the specific properties of “position updates”
can be expressed by using chains of local theory extensions). All these ideas
were illustrated by means of a running example complementing scenarios studied in [FM06, MFR06] (as now we consider an arbitrary number of trains) and
in [JSS07] (as now we also encompass efficient handling of emergency messages).
We kept the running example relatively easy in order to ensure clarity of presentation. More complicated scenarios can be handled similarly (we also considered,
e.g., situations in which time passes between position and speed updates).
In ongoing work, we investigate possibilities to use methods for abstractionbased model checking and invariant generation for this type of models.
References
[AD94]
Alur, R., Dill, D.L.: A theory of timed automata. Theoretical Computer
Science 126(2), 183–235 (1994)
[ERT02]
ERTMS User Group, UNISIG. ERTMS/ETCS System requirements specification. Version 2.2.2 (2002) http://www.aeif.org/ccm/default.asp
[FM06]
Faber, J., Meyer, R.: Model checking data-dependent real-time properties
of the European Train Control System. In: FMCAD, pp. 76–77. IEEE
Computer Society Press, Los Alamitos (2006)
[Ghi04]
Ghilardi, S.: Model theoretic methods in combined constraint satisfiability.
Journal of Automated Reasoning 33(3–4), 221–249 (2004)
[GSSW06] Ganzinger, H., Sofronie-Stokkermans, V., Waldmann, U.: Modular proof
systems for partial functions with Evans equality. Information and Computation 204(10), 1453–1492 (2006)
252
J. Faber, S. Jacobs, and V. Sofronie-Stokkermans
[HJU05]
[HM05]
[HO02]
[Hoa85]
[Hoe06]
[JSS07]
[MD99]
[MFR06]
[NO79]
[Ros98]
[Smi00]
[Smi02]
[SS05]
[SS06]
[Süh02]
[TZ06]
[ZH04]
Hermanns, H., Jansen, D.N., Usenko, Y.S.: From StoCharts to MoDeST: a
comparative reliability analysis of train radio communications. In: Workshop on Software and Performance, pp. 13–23. ACM Press, New York
(2005)
Hoenicke, J., Maier, P.: Model-checking of specifications integrating processes, data and time. In: Fitzgerald, J.A., Hayes, I.J., Tarlecki, A. (eds.)
FM 2005. LNCS, vol. 3582, Springer, Heidelberg (2005)
Hoenicke, J., Olderog, E.-R.: CSP-OZ-DC: A combination of specification
techniques for processes, data and time. Nordic Journal of Computing 9(4),
301–334 (March 2003)
Hoare, C.A.R.: Communicating Sequential Processes. Prentice-Hall, Englewood Cliffs (1985)
Hoenicke, J.: Combination of Processes, Data, and Time. PhD thesis, University of Oldenburg, Germany (2006)
Jacobs, S., Sofronie-Stokkermans, V.: Applications of hierarchic reasoning
in the verification of complex systems. ENTCS (special issue dedicated to
PDPAR 2006), 15 pages (To appear, 2007)
Mahony, B.P., Dong, J.S.: Overview of the semantics of TCOZ. In: IFM,
pp. 66–85. Springer, Heidelberg (1999)
Meyer, R., Faber, J., Rybalchenko, A.: Model checking duration calculus:
A practical approach. In: Barkaoui, K., Cavalcanti, A., Cerone, A. (eds.)
ICTAC 2006. LNCS, vol. 4281, pp. 332–346. Springer, Heidelberg (2006)
Nelson, G., Oppen, D.C.: Simplification by cooperating decision procedures. ACM TOPLAS 1(2), 245–257 (1979)
Roscoe, A.W.: Theory and Practice of Concurrency. Prentice-Hall, Englewood Cliffs (1998)
Smith, G.: The Object Z Specification Language. Kluwer Academic Publishers, Dordrecht (2000)
Smith, G.: An integration of real-time Object-Z and CSP for specifying
concurrent real-time systems. In: Butler, M., Petre, L., Sere, K. (eds.) IFM
2002. LNCS, vol. 2335, pp. 267–285. Springer, Heidelberg (2002)
Sofronie-Stokkermans, V.: Hierarchic reasoning in local theory extensions. In: Nieuwenhuis, R. (ed.) Automated Deduction – CADE-20. LNCS
(LNAI), vol. 3632, pp. 219–234. Springer, Heidelberg (2005)
Sofronie-Stokkermans, V.: Interpolation in local theory extensions. In: Furbach, U., Shankar, N. (eds.) IJCAR 2006. LNCS (LNAI), vol. 4130, pp.
235–250. Springer, Heidelberg (2006)
Sühl, C.: An overview of the integrated formalism RT-Z. Formal Asp.
Comput 13(2), 94–110 (2002)
Trowitzsch, J., Zimmermann, A.: Using UML state machines and petri
nets for the quantitative investigation of ETCS. In: VALUETOOLS, pp.
1–34. ACM Press, New York (2006)
Zhou, C., Hansen, M.R.: Duration Calculus. Springer, Heidelberg (2004)
Modelling and Verification of the LMAC
Protocol for Wireless Sensor Networks
Ansgar Fehnker1, , Lodewijk van Hoesel2 , and Angelika Mader2,
1
2
National ICT Australia and University of New South Wales, Australia
ansgar.fehnker@nicta.com.au
Department of Computer Science, University of Twente, The Netherlands
l.f.w.vanhoesel@utwente.nl, mader@ewi.utwente.nl
Abstract. In this paper we report on modelling and verification of a
medium access control protocol for wireless sensor networks, the LMAC
protocol. Our approach is to systematically investigate all possible connected topologies consisting of four and of five nodes. The analysis is
performed by timed automaton model checking using Uppaal. The property of main interest is detecting and resolving collision. Evaluation of
this property for all connected topologies requires more than 8000 model
checking runs. Increasing the number of nodes would not only lead increase the state space, but to a greater extent cause an instance explosion
problem. Despite the small number of nodes this approach gave valuable
insight in the protocol and the scenarios that lead to collisions not detected by the protocol, and it increased the confidence in the adequacy
of the protocol.
1
Introduction
In this paper we report about modelling and verification of a medium access control protocol for wireless sensor networks, the LMAC protocol [10]. The LMAC
protocol is designed to function in a multi-hop, energy-constrained wireless sensor network. It targets especially energy-efficiency, self-configuration and distributed operation. In order to avoid energy-wasting effects, like idle listening,
hidden terminal problem or collision of packets, the communication is scheduled.
Each node gets periodically a time interval (slot) in which it is allowed to control the wireless medium according its own requirements and needs. Here, we
concentrate on the part of the protocol that is responsible for the distributed
and localised strategy of choosing a time slot for nodes.
Although, the basic idea of the protocol is quite simple, the possible behaviours get quickly too complex to be overseen by pure insight. Therefore, we
chose a model checking technique for the formal analysis of the protocol. We
apply model checking in an experimental approach [4,6]: formal analysis can
only increase the confidence in the correctness of an implementation, but not
National ICT Australia is funded through the Australian Government’s Backing
Australia’s Ability initiative, in part through the Australian Research Council.
supported by NWO project 632.001.202, Methods for modelling embedded systems.
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 253–272, 2007.
c Springer-Verlag Berlin Heidelberg 2007
254
A. Fehnker, L. van Hoesel, and A. Mader
guarantee it. This has two reasons: first, a formal correctness proof is only about
a model, and not about the implementation. Second, we will (and can) not prove
correctness for the general case, but only for instances of topologies.
Model checking as a way to increase the confidence comes also into play, as
we do not aim to prove that the protocol is correct for all considered topologies.
This is in contrast to related work on verification of communication protocols,
such as [1]. It is known beforehand that there exist problematic topologies for
which the LMAC protocol cannot satisfy all relevant properties. The aim is to
iteratively improve the model, and to reduce the number of topologies for which
the protocol may fail. This is an important quantitative aspect of the model
checking experiments presented in this paper.
In order to get meaningful results from model checking we follow two lines:
Model checking experiments: We systematically investigate all possible connected topologies of 4 and 5 nodes, which are in total 11, and 61 respectively. For
12 different models and 6 properties we performed about 8000 model checking
runs using the model checker Uppaal [2,3]. There are the following reasons for
the choice of the model checking approach considering all topologies:
(1) Relevant faults appear already in networks with a small number of nodes.
Of course, possible faults that involve more nodes are not detected here.
(2) It is not enough to investigate only representative topologies, because
it is difficult to decide what “representative” is. It turned out that topologies
that look very “similar” behave differently, in the sense that in one collision can
occur, which does not in the other. This suggests that the systematic way to
investigate all topologies gives more reliable results. This forms a contrast to
similar approaches such as [8] which considers only representative topologies,
and the work in [5], which considers only very regular topologies.
(3) By model checking all possible scenarios are traversed exhaustively. It
turned out that scenarios leading to collisions are complex, and are unlikely to
be found by a simulator. On the other hand, simulations can deal with much
higher numbers of nodes. We believe that both, verification and simulation, can
increase the confidence in a protocol, but in complementary ways.
Systematic model construction: The quality of results gained from model
checking cannot be higher than the quality of models that is used. We constructed the models systematically, which is presented in sufficient detail. We
regard it as relevant that the decisions that went into the model construction
are explicit, such that they can be questioned and discussed. It also makes it
easier to interpret the result of the model checking experiments, i.e. to identify
what was proven, and what not. The reader who is not interested in the details
of the model should skip therefore Section 4.
The goal of the protocol is to find a mapping of time slots to nodes that prevents collisions. To this end it is necessary that not only direct neighbours have
different slots, but also that all neighbours of a node have pairwise different slots.
Neighbours of neighbours will be called second-order neighbours. The problem
Modelling and Verification of the LMAC Protocol
255
is at least NP-hard [7,9]: each solution to the slot-mapping problem is also a
solution to the graph colouring problem, but not vice versa.
When starting the protocol analysis using Uppaal, the protocol had been
developed [10], implemented and analysed by simulation. The specification consisted of the publication mentioned, and personal explanations. Our analysis
here restricts to the fragment of the protocol concerned with the slot distribution mechanism trying to avoid collision. Other aspects, as time synchronisation
or sleeping modes of nodes, are covered by the protocol, but are not addressed
in the analysis here. During our modelling and verification efforts we found
that the implementation covered more aspects than the specification did. The
main results of our analysis were an improvement of the protocol, such that less
collisions remain undetected, and an analysis of possible undetected collisions
showing that undetected collisions do not prevent connection to the gateway.
The paper is structured as follows. In Section 2 we give a short description of
the LMAC protocol, and in Section 3 a brief introduction to timed automata. The
models and properties are described in detail in Section 4. The model checking
results are discussed in Section 5. We conclude with discussions in Section 6.
2
The LMAC Protocol
In schedule-based MAC protocols, time is organised in time slots, which are
grouped into frames. Each frame has a fixed length of a (integer) number of time
slots. The number of time slots in a frame should be adapted to the expected
network node density or system requirements.
The scheduling principle in the LMAC protocol [10] is very simple: every
node gets to control one time slot in every frame to carry out its transmission.
When a node has some data to transmit, it waits until its time slot comes up,
and transmits the packet without causing collision or interference with other
transmissions. In the LMAC protocols, nodes always transmit a short control
message in their time slot, which is used to maintain synchronisation.
The control message of the LMAC protocol plays an important role in obtaining a local view of the network within a two-hop distance. With each transmission
a node broadcasts a bit vector of slots occupied by its (first-order) neighbours .
When a node receives a message from a neighbour, it marks the respective time
slots as occupied. To maintain synchronisation other nodes always listen at the
beginning of time slots to the control messages of other nodes.
In the remainder we will briefly describe the part of LMAC concerned with
the choice of a time slot. We define four operational phases (Fig. 1):
Initialisation phase (I) — The node samples the wireless medium to detect
other nodes. When a neighbouring node is detected, the node synchronizes (i.e.
the node knows the current slot number), and proceeds to the wait phase W, or
directly to the discover phase D.
Wait phase (W) — We observed that ,especially at network setup, many
nodes receive an impulse to synchronize at the same time. The protocol introduces randomness in reaction time between synchronising with the network and
256
A. Fehnker, L. van Hoesel, and A. Mader
I
synchronizable
transmission detected
select
waiting
time k
W
after waiting k frames lengths
no neighbors
D
after one frame length
no free slot
no neighbors
select
slot
A
reported collision
Fig. 1. Control flow diagram of the protocol
actually choosing a free time slot, to reduce the likelihood that nodes select slots
at the same time. This is achieved by inserting a random wait time after the
initialisation phase I and before the discover phase D.
Discover phase (D) — The node collects first-order neighbourhood information
during one entire frame and records the occupied time slots. If all information
is collected, the node chooses a time slot and advances to the active phase A.
By performing an ’OR’-operation between all received bit vectors, a node in
the discover phase D can determine which time slots in its second-order neighbourhood are unoccupied and can be freely used. At this moment the node can
choose any time slot that it marked as unoccupied. To reduce the probability of
collisions, the protocol is to randomly choose one of the available slots.
Active phase (A) — The node transmits a message in its own time slot. It
listens in all other time slots and accepts data from neighbouring nodes. The
node also keeps its view on the network up-to-date. When a neighbouring node
informs that there was a collision in the time slot of the node, it will return to the
wait phase W. Collisions can occur when two or more nodes choose the same time
slot for transmission simultaneously. This can happen with small probability at
network setup or when network topology changes due to mobility of nodes.
The nodes that cause a collision cannot detect the collision by themselves; they
need to be informed by their neighbouring nodes. These neighbouring nodes use
their own time slot to inform the network that they detected a collision. When
a node is informed that it is in a collision it will give up its time slot and return
to the discover phase D.
Modelling and Verification of the LMAC Protocol
3
257
Timed Automata
Systems are modelled in Uppaal as a parallel composition of timed automata [3].
Time is modelled using real-valued clocks and time only progresses in the locations of the automata: transitions are instantaneous. The guards on transitions
between locations in the automata and the invariants in the various locations
may contain both integer-valued variables and real-valued clocks. Clocks can be
reset to zero on transitions. Several automata can synchronize on transitions using handshake and broadcast synchronisation. Shared variables can be used to
model data transfer between automata. Locations can be declared urgent, which
means time is not allowed to progress, or committed, which means time is not
allowed to progress and interleaving is restricted. If only one automaton is in a
committed location at any one time, its transitions are guaranteed to be atomic.
Properties of systems are checked by the Uppaal model checker, which performs an exhaustive search through the state space of the system for the validity
of these properties. It can check for invariant, reachability, and liveness properties of the system, specified in a fragment of TCTL.
4
4.1
Models and Properties
Model Decomposition
Uppaal models are, as mentioned in the previous section, parallel compositions of
timed automata, and allow for compositional modeling of complex systems. The
LMAC protocol is naturally distributed over the different nodes. The Uppaal
model reflects this by including exactly one timed automaton model for each
node. Each of these timed automata models is then organised along the lines of
the flow chart in Section 2.
The Uppaal model of the LMAC protocol will be used to analyse the behaviour,
correctness and performance of the protocol. Since the LMAC protocol builds on
an assumed time synchronisation, the Uppaal model will also assume an existing
synchronisation on time. Although it would be interesting to analyse the timing
model in detail, it falls outside of the scope of the protocol and this investigation.
The LMAC protocols divides time into frames, which are subdivided into
slots. Within a slot, each node communicates with its neighbours and updates
its local state accordingly. We model each slot to take two time units. Each
node has a local clock. Nodes communicate when their local clock equals 1, and
update information when their clocks equals 2. At this time the clock will be
reset to zero.
Based on this timing model, the protocol running on one node is modelled as
a single timed automaton. The complete model contains one of these automata
for each node in the network. The timed automata distinguish between 4 phases,
as shown in the control flow graph in Figure 1. The first phase is the initialisation phase, the second the optional wait phase. The next part models the discover
258
A. Fehnker, L. van Hoesel, and A. Mader
phase which gathers neighbourhood information. At the end of the discover phase
a node chooses a slot, and proceeds to the fourth and last phase, the active phase.
Figure 2 to 6 depict the models for each phase. Details of the different parts will
be discussed later in this section. Note, that the model presented here serves as
a baseline for an iterative improvement of model and protocol.
Channels and Variables
Global channels and variables. The wireless medium and the topology of the
network are modelled by a broadcast channel sendWM, and a connectivity matrix
can hear. A sending node i synchronises on transitions labeled sendWM!. The
receiving nodes j then synchronizes on label sendWM? if can hear[j][i] is true.
This model of sending is used in the active phase (Fig. 6), and the model of
receiving during initialisation (Fig. 2), discover (Fig. 4) and active phase (Fig. 6).
The model uses three global arrays to maintain a list of slot numbers and
neighbourhood information for each node. Array slot no records for each node
the current slot number. Array first and second record for each node information on the first and second-order neighbours, respectively. Note, that the
entries of these arrays are bit vectors, and will be manipulated using bit-wise
operations. All nodes have read access to each of the elements in the arrays, but
only write access to its own. The arrays are declared globally to ease read access.
The model uses two additional global variables aux id and aux col. These
are one place buffers, used during communication to exchange information on
IDs and collisions.
Local variables. Each node has five local variables. Variable rec vec is a local copy
of received neighbourhood information, counter counts the number of slots a node
has been waiting, and current the current slot number, with respect to the beginning to the frame. Variable col records the reported collisions, while detected
is used to record detected collisions. Finally, each node has a local clock t.
The node model. The remainder of this section will discuss each part of the
node model in detail.
Initialisation phase. The model for the initialisation phase is depicted in Figure
2. As long a node does not receive any message it remains in the initial node. If
a node receives a message, i.e. if it can hear (can hear[id][aux id]==1) and
synchronise with the sender (sendWM?), it sets its current slot number to the slot
number of the sender (current=slot no[aux id]), and resets its local clock
(t=0). The slot number of the sender is part of the message that is send. From
this time on the receiver will update the current slot number at the same rate as
the sender. They are equal whenever either of them sends. This synchronisation
is the subject of one of the properties that will be verified later.
If the receiver receives a second packet before the end of the slot a collision has
occurred. The node will discard the received information and return to the initial
Modelling and Verification of the LMAC Protocol
259
initial
can_hear[id][aux_id]==1
sendWM?
current=slot_no[aux_id],
t=0
t==1
t=0
t<=1
can_hear[id][aux_id]==1
sendWM?
t<=1
t==1
current=(current+1)%frame,
t=0
to wait
Fig. 2. Model of the initialisation phase
from init
t==1
current=(current+1)%frame,
t=0
from choice
counter=0
waiting
t<=2
counter=0
t==2 &&
t==2 &&
counter==frame-1 counter==2*frame-1
counter=0,
counter=0,
t=0
t=0
t==2 && counter<3*frame-1
counter++,
t=0
t==2 &&
counter==3*frame-1
counter=0,
t=0
to listening
Fig. 3. Model of the wait phase
location. If no collision occurs, the node will proceed to the next slot, increment
the current slot counter modulo the length of the frame (current=current+1%
frame), and proceed to the wait phase (Figure 3).
Wait Phase. When a node enters the wait phase, it may decide (non-deterministically) to skip this phase. A node waits for at most 3 frames in this location waiting. Waiting is implemented as a self loop, which is guarded by
counter<3*frame-1. The loop increments the counter at the end of a slot (t==2).
A node can proceed to the discover phase when it waited for exactly one, two or
three frames.
Discover Phase. The model for the discover phase consists of four locations
(Figure 4). The entry location listening0 models when a node is sensing the
medium. Location rec one0 models that a node continues sensing after reception
of a first message. Location done0 is reached when a node detected a collision.
Finally, the model contains a committed location, in which the node checks if
it listened to the medium for a full frame. If it did, it proceeds to choose a free
slot, otherwise it continues listening.
Clocks and variables will be updated as follows. When a node enters location
listening0, the local clock will be zero. It will wait in this location for at
260
A. Fehnker, L. van Hoesel, and A. Mader
from wait
t<=2
rec_one0
can_hear[id][aux_id]==1
sendWM?
listening0
rec_vec=first[aux_id],
first[id]|=(1<<current)
t<=2
t==2
current=(current+1)%frame,
second[id]|=rec_vec,
rec_vec=0,
t=0
done0
t==2
can_hear[id][aux_id]==1
current=(current+1)%frame,
t<=2 t=0
sendWM?
detected=(detected<0)?current:detected,
rec_vec=0
from collision
counter<frame-1
counter++
t==2
current=(current+1)%frame,
t=0
t<=2
counter>=frame-1
second[id]|=first[id]
to choice
Fig. 4. Model of the discover phase
from listening
counter>=frame-1
second[id]|=first[id]
to wait
second[id]==max_vec
counter=-1,
second[id]=0,
first[id]=0,
second[id]=0,
detected=-1
!((second[id]>>0)&1)!((second[id]>>1)&1)!((second[id]>>2)&1)!((second[id]>>3)&1)!((second[id]>>4)&1)
slot_no[id]=0,
second[id]=0
slot_no[id]=1,
second[id]=0
slot_no[id]=2,
second[id]=0
slot_no[id]=3,
second[id]=0
slot_no[id]=4,
second[id]=0
to normal
Fig. 5. Model of the choice
most 2 time units, enforced by invariant t<=2. If it receives a message from a
neighbouring node, it will record the neighbour information of that neighbour
(rec vec=first[aux id]). The node sets the bit for the current slot in its own
neighbourhood vector to true (first[id]|=1<<current). If the node does not
receive any message by the end of the slot (t==2), it will increment the current
slot number, and move to a committed location.
When the node received one message, it waits in location rec one0 either
until it receives a second message (collision), or until the end of the slot (t==2).
The node uses the received neighbourhood information only in the latter case
to update the information on slots occupied by the second-order neighbours
(second[id]|=rec vec). In the first case the node records if a collision occurred if it was the first collision since the beginning of the discover phase
(detected=(detected<0)?current:detected). Note, that detected has value
−1 if no collision has been detected yet. At the end of a slot(t==2) the node
enters the committed location. If it listened for less than a frame length, it will
return to listening0, otherwise it will choose a slot.
Modelling and Verification of the LMAC Protocol
261
collision
from choice
ready
t<=1
from choice
from choice
current==slot_no[id]
from choice
current!=slot_no[id]
from choice
t==2 && (col==slot_no[id])
counter=0,
current=(current+1)%frame,
col=-1,
detected=-1,
slot_no[id]=-1,
first[id]=0,
rec_vec=0,
t=0
listening
t<=2
can_hear[id][aux_id]==1
sendWM?
col=aux_col,
first[id]|=(1<<current)
t<=2
rec_one
t==2
current=(current+1)%frame,
t=0
t==1
aux_id=id,
aux_col=detected
t==2 &&
col!=slot_no[id]
current=(current+1)%frame,
t=0
t==2
current=(current+1)%frame,
t=0
t==2
current=(current+1)%frame,
t=0
can_hear[id][aux_id]==1
sendWM!
sending detected=-1
t<=2
sent
t<=2
done
sendWM?
detected=(detected<0)?current:detected
Fig. 6. Model of the active phase
Choosing. Choosing is not a actual phase, but an important intermediate state.
Choosing a slot is modelled by a single committed location (Figure 5). Before
entering this location the node computes the slots that are neither occupied by
the (first-order) neighbours, nor by the second-order neighbours (second[id]
|= first[id]). If all slots are reported occupied, the node returns to the wait
phase (second[id]==max vec)1 . If there are available slots, i.e the corresponding
bits in the bit-vector second[id] are equal to zero, the node will select nondeterministically one of these slots.
Active Phase. The main phase of a node is the active phase. The model for this
phase is depicted in Figure 6. Locations ready, sending, and sent deal with the
transmission of a message, locations listening, rec one, and done deal with
receiving messages.
From the central committed location, which is entered at the beginning of a
slot, the node proceeds to send, if the chosen slot number is equal to current slot
number (current==slot no[id]), and proceeds to the discover phase otherwise
(current!=slot no[id]).
If a node wants to send it waits for one time unit in location ready. After one
time unit, the node first copies its ID and collision information into global buffers
aux id, aux col, and then triggers all nodes in it neighbourhood to update their
local information through broadcast channel sendWM!. The node then stays in
location sent until the end of the slot.
1
Constant max vec is a bit-vector where all elements are set to true.
262
A. Fehnker, L. van Hoesel, and A. Mader
If a node is ready to receive a message it waits in location listening. It
remains in that location either until the end of the slot, or until it receives a
message. In the former case it increments the slot number at the end of the
slot, and proceed with the next slot. In the latter case, if it receives a message, it updates its local information and enter location rec one. If a second
message arrives while in rec one, it discards the received information, records
the collision (detected=(detected<0)?current:detected), and waits for the
remaining time of the slot in done. If no collision occurred while in rec one, the
node proceeds at the end of the slot (t==2) depending on the received collision
information col. If a collision has been reported and it is equal to its slot number
(col==slot no[id]), the node returns to the discover phase, and resets all local
information. Otherwise, it updates its neighbourhood information, and proceeds
with the next slot.
The next section briefly discusses some properties of the timed automaton
model of the LMAC protocol, in particular a property that ensures that after a
collision nodes involved will choose a new slot.
4.2
Properties
The timed automata model of the LMAC protocol should guarantee basic safety
properties. The most basic property is freedom from deadlocks, which can be
checked in Uppaal by verifying the following:
AG¬deadlock
(1)
In addition, we require that the model successfully implements synchronisation
of nodes. First, nodes should be synchronised halfway the duration of a slot,
since at this time they will send and receive information. We prove for each pair
(i, j) of first-order neighbours
AG(nodei .t == 1 ⇒ nodej .t == 1)
(2)
In addition neighbours should agree on the current slot number, to ensure that
received information is interpreted correctly.
AG(nodei .t == 1 ⇒ nodei .current == nodej .current)
(3)
Since we only consider completely connected networks, pairwise synchronisation
implies synchronisation of the entire network. The nodes do not to be synchronised when nodei .t = 1. This can happen when one node increments its current
slot number before the other.
In addition to these safety properties the protocol should satisfy a very basic
reachability property: There should exist a path to a state, such that all nodes
are active, and such that they have a chosen a slot number that is distinct from
their first and second-order neighbour’s slot. Let N be the set of all pairs of first
and second-order neighbours. We then verify
(slot no(i) = slot no(j) ∧ active(i) ∧ active(j))
(4)
EF
(i,j)∈N
Modelling and Verification of the LMAC Protocol
263
where active(i) is true if a node is its active phase. If the model cannot satisfy
this property, it is not even possible to reach a configuration without collision,
i.e the related colouring problem has no solution.
The previous property guarantees that there exists a solution, but it does not
guarantee that the protocol find this solution. The LMAC protocol chooses slots
randomly from the available slots. This is implemented in the timed automaton
model as a non-deterministic choice. It is therefore possible that two nodes will
repeatedly choose the same slot. For a probabilistic model we could try to prove
that with probability one distinct slots will eventually be chosen. Unfortunately,
we cannot use the timed automaton model to prove this directly.
Alternatively, we verify two liveness properties to show that the protocol will
eventually resolve all conflicts, if satisfied. The first is to show that whenever
two first or second-order neighbours choose the same slot number, they will
eventually choose a new slot number. We show for each pair (i, j) in N
AG (slot no(i) == slot no(j) ∧ sending(i) ∧ sending(j))
(5)
⇒ AF (¬active(i) ∨ ¬active(j))
A node may leave the active phase eventually due to a third node reporting the
collision or a triggered timeout.
The second liveness property is, that if a node is about to choose a slot,
and if it can only choose from one available slot, its neighbours who are in
the discover phase are not forced to the make the same choice. The neighbour
should eventually be able to choose a different slot. The latter requirement can
be dropped, if the neighbour that was forced to a choice, left the active phase
and either waits or discovers. For all pairs (i, j) in N we show
AG (choosing(i) ∧ available slot(i) == 1 ∧ discover(j)) ⇒
(6)
AF (choosing(j) ∧ (slot no(i) = slot no(j) ∨ wait(i) ∨ discover(i)))
This means that, even if a node is forced to a certain choice (choosing(i) ∧
available slot(i) == 1), neighbours can eventually choose a different slot.
4.3
Simplification
The model described in Section 4.1 was close to the informal description of the
protocol as presented in Section 2. As such each node was equipped with its own
clock, and its internal actions completely independent from other nodes.
Checking the reachability probability property (4) was easy, and checking the
safety properties (1) to (3) was possible, although demanding in terms of memory
and time constraints, while proving the liveness properties (5) and (6) turned
out to exceed the memory and time constraints for most topologies. To be able
to verify the protocol for all topologies with up to 5 nodes for all properties, we
had to simplify the model. The simplification reduced the number of clocks and
non-essential interleaving, while keeping the essential behavior.
The simplification builds on two observations. Firstly, that all clocks are synchronised, and secondly that all updates are local. We introduce a scheduler,
264
A. Fehnker, L. van Hoesel, and A. Mader
with its own clock, that synchronizes the internal update of the nodes at the
end of a slot. Without loss of subsequent behavior this scheduler realises a local
partial order reduction.
Given that the local clocks of the nodes are only reset during the update of a
node, and given that we can safely synchronize all updates, as mentioned before,
we find that all clocks are now perfectly synchronised. This means that for clocks
t1 and t2 holds the invariant t1 == t2 . We can therefore safely replace the local
clocks of the nodes by the single clock of the scheduler.
The simplification reduced number of clocks and manually introduced a partial
order reduction on internal transitions. It should be noted that the scheduler
added to the model to achieve this reduction has no equivalent in the actual
LMAC protocol. It was purely introduced to reduce the complexity of the model
checking problem. If anything it reflects that the LMAC protocol builds on an
existing time synchronisation.
5
Results
This section reports on the model checking results for the properties defined in
Section 4.2.
While the safety and reachability properties should be satisfied by all models,
it is known beforehand that the LMAC protocol is not able to resolve all collisions. This is the subject of the first liveness property (5). Two neighbouring
nodes will remain in a collision perpetually, if no third node is able to report
this collision, either because there is no third node, or because the third node is
unable to send a message without collision. This is a fundamental shortcoming
of collision detection algorithms. The aim of the model checking experiments is
to iteratively improve the model, and thus the protocol, to reduce the number
of topologies that suffer from this problem. This means to reduce the number of
topologies and pairs of neighbours that do not satisfy property (5). The improvements deal with modelling bugs, clarification of an ambiguous informal protocol
description, to improvements of the protocol.
The model checking experiments have been performed on a Mac Pro with 2
x 3 GHz Dual-Core processor, and a 4 GB 667 MHz memory. We used Uppaal
version 4.0. Checking property (5) for a five-node model, i.e. ca. 500 runs of the
model checker, took about an hour. This machine outperformed different other
PCs, the weakest ones taking a week for the same set of verifications without
solving them all, or the better ones, doing the job in a few hours, but still failing
due to memory limitations for some experiments, which had to be killed when
using too much memory.
5.1
Safety and Reachability Properties
For basic model we assume a network of 4 nodes, and a frame length of 5 slots.
For this basic model there are 11 topologies, with 64 pairs of first and secondorder neighbours. The experiments show that the basic model (and all models
Modelling and Verification of the LMAC Protocol
265
model 1, topology 4, pair (0,2)
node
i
0 0
d 1
d 1
i i
4
5
7
0
i
i
0
0
0
0
d
d
d
d
d
d
d
d
3 i
i
i
i
0
1
2
3
0
1
2
6
0
0
0
1
1
1
1
1
1
0
1
1
0
d
0
d
d
d
d
d
0
0
0
0
d
d
d
d
d
d
d
w w w w w d
d
8
2
2
0
2
2
0
0
0
2
2
2
2
0
0
0
2
2
0
0
2
d
d
d
d
2
2
2
2
d
d
d
d
d
3
0
0
d
d
d
d
0
2
d 3 3
2 2 2
3 3 3
d 4 4
3
3
2
2
3
3
4
4
3 3 3
2 2 2
3 3 3
4 4 4
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
Fig. 7. Scenario of an unresolved collision between node 0 and 2. The y-axis shows
the different nodes, the x-axis the time. Each slot contains whether the node is in
the initialisation (i), waiting (w), discover (d), or active phase. In the latter case the
current slot number is shown. White bold face indicates that the node is sending, black
bold face that a node is receiving. Bold italics on a dark (red) background indicate
collisions.
that will be derived in the process) satisfy the safety and reachability properties
(1) to (4). This means that the models are deadlock free, that the nodes are
synchronised, and that for each topology there exist a path that assigns the slots
without collision, i.e. that there exists a solution of the related graph colouring
problem.
5.2
Liveness Properties
The main liveness property (5) deals with unresolved collisions. In the basic
model unresolved collisions may occur for in 3 topologies, for a total of 6 pairs
of neighbours. From this basic model for 4 nodes we arrive in 12 iterations at a
model that satisfactory resolves collisions for topologies with 5 nodes.
Model 1. This is the basic model for 4 nodes, and a frame length of 5 slots. Among
the collisions that are not resolved are collisions that separate a node from
the other nodes. An example scenario of such behavior is depicted in Figure 7.
It belongs to topology 4, depicted in Figure 8.
At time 0 the gateway, node 0, sends a first message.
This message is received by node 1 and 2 and they start
0
1
listening to the medium. One frame later node 1 and 2
both select slot 1, and send at time 6. This leads to
a collision at node 0. Node 0 reports the collision at
time 10, and node 1 and 2 return to the discover phase.
2
3
At the end of the scenario node 0 and node 2 collide,
perpetually, since there is no neighbour to witness the
Fig. 8. Topology 4
collision. Node 2 does not receive any message from then
on, since it cannot listen while sending. Node 2 entered
this collision, because it chose a slot, while it had insufficient information. Node
2 listened from time 21 to time 26, but received not a single message. It had no
information about its neighbours, when it made its choice, and any choice had
the potential to lead to a collision.
266
A. Fehnker, L. van Hoesel, and A. Mader
node
model 4, topology 5, pair (1,3)
0
0
0
0
0
0
0
0
0
0
0
0
1
i
w
w
w
w
w d
d
d
d
2
i
d
d
d
d
d 1
1
1
1
3
0
0
0
0
0
d
2
2
2
2
2
2
1
1
1
1
1
1
1
d 2
2
2
2
2
0
1
2
3
0
i
i
i
i
i
i
i
d
d
d
d
0
1
2
3
4
5
6
7
8
9
10 11 12 13 14 15 16
(a)
(b)
Fig. 9. (a) Scenario of an unresolved collision between node 1 and 3 in topology 5. (b)
Topology 5. Node 1 and 3 may fail to resolve a collision.
Model 2. The second model improves on the first model, by introducing the rule
that a node may not choose if it received no information in the discover phase.
This additional rule successfully deals with the collision depicted in Figure 7.
This model run into problems because it does not reset its first-order neighbour information. After a few repeated choices some node assume that all slots
are occupied. They cannot enter the active phase, and consequently cannot report collisions between other nodes. This bug was in the model because of an
incomplete informal specification.
Model 3. Model 3 improves on model 2, in that it resets all neighbourhood
information after it sends a message. It propagates in the active phase only
information collected during the last frame length of slots.
The additional rules in Model 2 and 3 do not eliminate the possibility that a
nodes may become disconnected from the network. It may still happen if a node
only receives messages while it sends, and no third node witnesses or reports the
collision.
Model 4. The fourth model improves on the third model in that a node chooses
anew if it does not receive any message in a frame length. This last additional
rule resolves all remaining collisions for topologies with 4 nodes which are not
ring topology bugs. There is one ring topology, and only two pairs of nodes in
it are affected. A scenario leading to this bug is depicted in Figure 9. This kind
of collision is however not problematic, since all nodes are able to communicate
with the gateway.
Model 5. The fifth model is identical to Model 4, except that it is instantiated
for topologies with 5 nodes. There are 61 different topologies, with 571 pairs of
neighbours. Although Model 4 was able to resolve all collisions except for the ring
topology bug, applied to topologies of 5 nodes many other unresolved collisions
suddenly occur. Model checking revealed 56 unresolved collisions, affecting 18
topologies. Also, the model checker was not able to complete for 26 topologies due
to memory and time constraints. Once the computer starts swapping memory,
progress typically stalls.
Model 6. The sixth model improves on the fifth model by an additional rule. If
a node has chosen a slot, and it is active, but has not sent its first message yet,
Modelling and Verification of the LMAC Protocol
267
node
model 10, topology 31, pair (2,4)
0 0 0 0 0 0 0 0 0 d d d d d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 3 d d d d d 2 2 2 2 2 2 2 2 2 2 2 w w w w w w w w w w w w w w w d d d d d w w w
2 3 d d d d d 1 1 1 1 1 1 1 d d d d d 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
3 d d d d d 0 0 0 d d d d d 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 1 1 1 1 1 1 1 1 1 1 1 1 1 d d d d d 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
Fig. 10. Scenario of an unresolved collision between node 0 and 3
and if it then receives from a neighbour information that it slot is occupied by
a second-order neighbour, then the node proceeds to choose a new slot.
Model 7. The seventh model modifies a rule introduced in Model 2. If it receives
in the listing phase only collisions, it does not have sufficient information about
its second-order neighbours to make a choice that avoids collisions. The new rule
states that a node will not choose if it did not receive a single message, except
for collisions.
In the seventh model the following could occur. First, a node reported a
collision to all neighbours. Next, these neighbours proceeded to the discover
phase. As a consequence, the node which reported the collision would receive
no message for a frame length of slots, and incorrectly conclude that it is was
disconnected from the network.
Model 8. Model 8 modifies a rule, which was introduced earlier, to avoid the
scenario described for model 7. A node concludes that it is alone if it does not
hear a neighbour in two frame lengths. This prevents a node that reported a
collision to conclude that it is disconnected, just because its neighbours went to
the discover phase for one frame length.
Model 9. Model 9 further refines the rule about when nodes conclude that they
are alone and disconnected. If a node is active, but has not sent yet, it concludes
that it disconnected if it has received no message in the frame length of slots
right before its first transmission.
Model 10. Model 10 fixes a problem that occurs right after choosing a slot.
Model 3 introduced that neighbour information is reset once in a frame length
of slots during the active phase. When a mode transitions from the discover
phase to the active phase it does not reset the neighbourhood information. As
a consequence it may reflect the state of up to two frames length in the past by
the time a node is sending. Model 10 fixes this by resetting all information, even
if collected during the discover phase, after one frame length. In addition a node
concludes that is alone if it hears nothing but collisions for two frame lengths.
Model 11. The eleventh model also refines the rules about when a node has to
conclude that it is in a collision. It tackles the problem depicted in Figure 10.
Nodes 0 and 3 enter a perpetual collision, since node 1 wrongly concluded at time
268
A. Fehnker, L. van Hoesel, and A. Mader
node
model 11, topology 41, pair (1,4)
0 0
1 i
2 i
3 i
4 i
0
0
w
w
d
i
1
0
w
w
d
i
2
0
w
w
d
i
3
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
w w d d d d d 2 2 2 2 d d d d d 3 3 3 3 3 d d d d d 2 2 2 2 2 d d d d d
w w d d d d d 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
d d 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
i i i d d d d d 2 2 2 d d d d d 3 3 3 3 3 d d d d d 2 2 2 2 2 d d d d d
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
Fig. 11. Node 1 and 4 are perpetually forced to make the same choice
36 that it was disconnected. Node 1 assumed to be alone, since it only heard
collisions for two frame lengths. However, the collisions in the frame running
from time 27 to 31 differ from the collisions between 33 and 36. Node 1 is not
disconnected, and it actually successfully reported a collision at time 32.
Model 11 introduces a new rule about when to conclude that it is in a collision.
A node chooses anew if it either receives nothing for two frames or if it witnesses
the same collision for the second time. The rational for the latter case is, that
if a node observes a collision for the second time, it apparently unsuccessfully
reported the collision, likely because it is in a collision itself.
Model 11 resolves all remaining perpetual collisions that happen not in ring
topology. The remaining perpetual collisions happen in the ring of 5 nodes, or
topologies that contain a ring of 4 nodes. Overall, this are 35 pairs of nodes in 13
topologies that potentially end up in an perpetual collision. These are depicted
in Figure 12.
As it comes to the second liveness property – that if a node is forced to
choose a slot, all nodes in the discover phase will eventually be able to choose
a different slot – it turns out that Model 11 fails for 42 pairs in 14 topologies.
Figure 11 depicts an example scenario. First node 1 and 4 both choose the slot
2. This collision is reported at time 14 by node 2. At time 15 node 0 sends
its neighbourhood information to node 1. Based on information collected in the
frame from time 10 to 14, it reports that all slots but slot 3 are occupied. Node
1 hence has to choose slot 3 at time 19. Node 4 receives in its discover phase
messages in slot 1 and 4. In slot 1, it also learns from node 3 that slots 2 and 0
are occupied. Hence, node 4 has to choose node 3 as well, leading to a collision
at time 23. This collision gets reported at time 24.
During the next discover phase, both, node 1 and 4 learn that all but slot 2
are occupied. Node 1 and 4 have therefore to choose slot 2 at the end of their
discover phase. They end up in a collision again, which gets reported, and at the
end of the next discover phase they both have to choose slot 3 again. Etcetera.
Model 12. Model 12 is identical to model 11 except that it assumes a frame
length of 6 slots. Increasing the frame size does not influence the number of
potential collisions in ring topologies. However, since it increases the number of
available slots, all pairs in all topologies now satisfy the second liveness property.
If one node is forced to choose a certain slot, the second can eventually choose
a slot that differs from the first nodes slot.
Modelling and Verification of the LMAC Protocol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
269
Fig. 12. Final results for all 61 topologies with 5 nodes. The gateway is the solid node.
Dashed lines depict pairs of neighbours that may end up in an perpetual collision.
Only in the ring topology 14 this may happen also between second-order neighbours.
6
Conclusion
In this paper we reported about the analysis of a medium access protocol for wireless networks, the LMAC protocol. The analysis technique we applied was model
checking, using the timed automaton model checker Uppaal [3]. Our approach
was a systematic analysis of all possible connected network topologies with 4
and with 5 nodes. The most relevant property we investigated was, whether
270
A. Fehnker, L. van Hoesel, and A. Mader
collisions are detected and a new choice of slots is initiated afterwards. We
checked 12 different models, four for all topologies of four nodes, eight for all
topologies consisting of five nodes. The sequence of models reflects the increments
in insight in the protocol, and in the improvements of the protocol. Figure 12
shows the results for the last of the models.
Checking the models against a number of properties summed up to more than
8000 model checking runs in total. For example, in each of the eight five node
models there are 571 pairs of nodes. For each pair it needs to be investigate
whether a possible collision is detected by the protocol or not. This results in
4568 instances of property 5 alone that need to be model checked.
Extending the systematic analysis to 6 node topologies would not only increase
the model checking time for each instance, but also the number of instances to
investigate. With 6 nodes we would have 486 different topologies and 6273 pairs
of nodes to analyse. This would lead not only to a state space explosion problem
within one model, but to a much higher extent to a instance explosion problem.
For the state space explosion fully symbolic model checking techniques could
be helpful, but not for the instance explosion problem. Furthermore, it seems
to be difficult to parameterise topologies, having parametric model checking
techniques in mind. An alternative approach for showing correctness for a class
of topologies, using a combination of model-checking and abstract interpretation,
was presented in [1]. Here however, we face the additional problem that essential
properties are not valid for a number of instances. Therefore, we argue that
with straightforward model checking techniques, not much more can be done.
A possible extension could be stochastic analysis with a probabilistic model
checker, which will be discussed below.
There are three main results: (1) the description of the protocol is improved,
(2) the protocol itself is improved, and (3), problematic topologies with possible
scenarios of unresolved collision have been identified.
Improvement of the protocol description. We had a quite usual experience
here: several “bugs” found in first rounds of analysis turned out to be present in
the documentation of the protocol, but not in the implementation. The respective
“patches” were added to the documentation.
Protocol improvements. Some scenarios leading to unresolved collisions helped
to improve the protocol, and were absent in the later protocol versions:
– There is an additional trigger for the choice of a new slot: if a node hears
nothing, it concludes that it is isolated or participating itself in an collision,
and starts a new choice.
– If a node hears the same collision twice, it concludes that its collision report
has not been heard. The only reason for this is that this node itself is in a
collision. Therefore it starts a new choice in this situation.
– Some situations of collision detected could be solved by a change in parameters in the protocol, e.g., the time that a node listens before it chooses a
new slot, was extended from one frame to two frames.
Modelling and Verification of the LMAC Protocol
271
– The frequency of information update was increased, e.g. slots where collisions
were heard are only stored for one frame. Timely resets seem to be crucial
for the protocol.
Protocol faults. It is the case that collisions are not detected if there is not a
third node which can observe the collision. This situation occurs in all topologies
containing a square. Fortunately, even when there is a collision, all nodes are still
connected to the gateway, which makes these collisions less dramatic. The only
exception to this pattern is the ring-topology of five nodes, where also unresolved
collision can occur.
As mentioned, the colouring problem that the LMACprotocol tries to solve is
NP-hard. It cannot be expected that a light-weight, distributed algorithm finds
a solution in all cases.
Further results are:
Justification of the verification approach.The real faults found in the protocol were detected in non-trivial scenarios, generated by Uppaal-counterexamples
and, for readability, transformed to a graphic by a Matlab procedure. Figure 10
contains an example of such a scenario. It is obvious that these scenarios, due to
complexity, are unlikely to be found during a simulation run.
Justification of the analysis of all possible topologies. We found that
small changes in the topology can lead to different results. Intuitively, one would
expect that “similar” topologies give similar results. Unfortunately, any intuition
of this kind was proved wrong. Also another intuition, that most collisions occur
when the connectivity is higher turned out to be wrong. It turns out the collisions get resolved when the connectivity is high. This justifies our approach of
systematically investigating all topologies. Selecting “representative” topologies
is misleading, because there are no criteria for what “representative” could be.
Quantification of the success rate. For the 61 topologies we investigated
571 pairs of nodes for collision detection. 35 pairs of these showed a possible
unresolved collision. There are two aspects of probability present: first, for a
fixed topology we could determine the probability of an undetected collision.
This exceeds the possibilities of Uppaal, and would require a probabilistic model
checker (what we have not done). The second aspect is the probability of a
certain topology. This cannot be answered in general, because it depends on the
application domain, and the level of mobility in the network investigated.
Future work. We have not considered the probabilistic aspects of the protocol.
There are two sources of probabilities in the protocol: the choice of a new slot
out of all free slots, and the waiting time before choosing a new slot. We see two
different approaches to treat these aspects: one is by simple meta-argumentation,
based on combinatorics and elementary stochastics (e.g.,“What is the probability
that two nodes keep choosing the same waiting times?”). The other possibility
is by using a probabilistic model checker, like PRISM. However, probabilistic
models are typically even more complex than the ones we considered, which
272
A. Fehnker, L. van Hoesel, and A. Mader
decreases the limit of what can be analysed. In this case a number of effective
abstraction steps have to be applied to the model, to decrease its complexity.
We have not yet considered aspects of energy efficiency in the choice of new
slots. One source of energy consumption is the number of iterations are necessary, to choose a slot without creating a collision. To answer this question
probabilistic analysis is necessary. Another source of energy consumption is in
the number of hops that a packet needs to reach the gateway. The choice of a
slot can influence latency. Here, it seems that the “more deterministic” choice
for a latency-minimizing slot increases the chance for collision during the slot
selection phase. In contrary, when we apply a uniformly distributed choice of
slots during the selection phase, the latency will not be optimal. What the right
balance is between these parameters is subject to further analysis.
References
1. Bauer, J., Schaefer, I., Toben, T., Westphal, B.: Specification and verification of
dynamic communication systems. In: Application of Concurrency to System Design
(ACSD’06), pp. 189–200. IEEE Computer Society, Los Alamitos (2006)
2. Behrmann, G., David, A., Larsen, K.G.: A tutorial on uppaal. In: Bernardo, M.,
Corradini, F. (eds.) Formal Methods for the Design of Real-Time Systems: SFMRT 2004. LNCS, vol. 3185, Springer, Heidelberg (2004)
3. Behrmann, G., David, A., Larsen, K.G., Hakansson, J., Petterson, P., Yi, W.,
Hendriks, M.: Uppaal 4.0. In: Quantitative Evaluation of Systems - (QEST’06),
pp. 125–126. IEEE Computer Society Press, Los Alamitos (2006)
4. Brinksma, E.: Verification is experimentation! Int. J. on Software Tools for Technology Transfer 3(2), 107–111 (2001)
5. Cardell-Oliver, R.: Why Flooding is Unreliable (Extended Version). Technical Report UWA-CSSE-04-001, CSSE, University of Western Australia (2004)
6. Mader, A., Wupper, H., Boon, M.: The construction of verification models for
embedded systems. Technical report TR-CTIT-07-02, Centre for Telematics and
Information Technology, Univ. of Twente, The Netherlands (January 2007)
7. Moscibroda, T., Wattenhofer, R.: Coloring unstructured radio networks. In: Proc.
of 17th Symposium on Parallelism in Algorithms and Architectures (2005)
8. Olveczky, P., Thorvaldsen, S.: Formal modeling and analysis of wireless sensor
network algorithms in real-time maude. In: Proceedings of the 14th International
Workshop on Parallel and Distributed Real-Time Systems (WPDRTS 2006), IEEE
Computer Society Press, Los Alamitos (2006)
9. Sridharan, A., Krishnamachari, B.: Max-min fair collision-free scheduling for wireless sensor networks. In: Workshop on multi-hop wireless networks (2004)
10. van Hoesel, L.F.W., Havinga, P.J.M.: A lightweight medium access protocol (lmac)
for wireless sensor networks: Reducing preamble transmissions and transceiver state
switches. In: In 1st International Workshop on Networked Sensing Systems (INSS
2004), pp. 205–208 (June 2004)
Finding State Solutions to Temporal Logic Queries
Mihaela Gheorghiu, Arie Gurfinkel, and Marsha Chechik
Department of Computer Science, University of Toronto,
Toronto, ON M5S 3G4, Canada
{mg,arie,chechik}@cs.toronto.edu
Abstract. Different analysis problems for state-transition models can be uniformly treated as instances of temporal logic query-checking, where solutions to
the queries are restricted to states. In this paper, we propose a symbolic querychecking algorithm that finds exactly the state solutions to a query. We argue that
our approach generalizes previous specialized techniques, and this generality allows us to find new and interesting applications, such as finding stable states. Our
algorithm is linear in the size of the state space and in the cost of model checking,
and has been implemented on top of the model checker NuSMV, using the latter
as a black box. We show the effectiveness of our approach by comparing it, on a
gene network example, to the naive algorithm in which all possible state solutions
are checked separately.
1 Introduction
In the analysis of state-transition models, many problems reduce to questions of the
type: “What are all the states that satisfy a property ϕ?”. Symbolic model checking
can answer some of these questions, provided that the property ϕ can be formulated in
an appropriate temporal logic. For example, suppose the erroneous states of a program
are characterized by the program counter (pc) being at a line labeled ERROR. Then
the states that may lead to error can be discovered by model checking the property
EF (pc = ERROR), formalized in the branching temporal logic CTL [10].
There are many interesting questions which are not readily expressed in temporal
logic and require specialized algorithms. One example is finding the reachable states,
which is often needed in a pre-analysis step to restrict further analysis only to those
states. These states are typically found by computing a forward transitive closure of the
transition relation [8]. Another example is the computation of “procedure summaries”.
A procedure summary is a relation between states, representing the input/output behavior of a procedure. The summary answers the question of which inputs lead to which
outputs as a result of executing the procedure. They are computed in the form of “summary edges” in the control-flow graphs of programs [21,2]. Yet another example is the
algorithm for finding dominators/postdominators in program analysis, proposed in [1].
A state t is a postdominator of a state s if all paths from s eventually reach t, and t is a
dominator of s if all paths to s pass through t.
Although these problems are similar, their solutions are quite different. Unifying
them into a common framework allows reuse of specific techniques proposed for each
problem, and opens a way for creating efficient implementations to other problems of
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 273–292, 2007.
c Springer-Verlag Berlin Heidelberg 2007
274
M. Gheorghiu, A. Gurfinkel, and M. Chechik
a similar kind. We see all these problems as instances of model exploration, where
properties of a model are discovered, rather than checked. A common framework for
model exploration has been proposed under the name of query checking [5].
Query checking finds which formulas hold in a model. For instance, a query EF ? is
intended to find all propositional formulas that hold in the reachable states. In general, a
CTL query is a CTL formula with a missing propositional subformula, designated by a
placeholder (“?”). A solution to the query is any propositional formula that, when substituted for the placeholder, makes a CTL formula that holds in the model. The general
query checking problem is: given a CTL query on a model, find all of its propositional
solutions. For example, consider the model in Figure 1(a), where each state is labeled
by the atomic propositions that hold in it. Here, some solutions to EF ? are (p∧¬q ∧r),
representing the reachable state s0 , and (q ∧ r), representing the set of states {s1 , s2 }.
On the other hand, ¬r is not a solution: EF ¬r does not hold, since no states where
r is false are reachable. Query checking can be solved by repeatedly substituting each
possible propositional formula for the placeholder, and returning those for which the
resulting CTL formula holds. In the worst case, this approach is exponential in the size
of the state space and linear in the cost of CTL model checking.
Each of the analysis questions described above can be formulated as a query. Reachable states are solutions to EF ?. Procedure summaries can be obtained by solving
EF ((pc = PROC END) ∧ ?), where pc = PROC END holds in the return statement of
the procedure. Dominators/postdominators are solutions to the query AF ? (i.e., what
propositional formulas eventually hold on all paths). This insight gives us a uniform
formulation of these problems and allows for easy creation of solutions to other, similar, problems. For example, a problem reported in genetics research [4,12] called for
finding stable states of a model, that are those states which, once reached, are never left
by the system. This is easily formulated as EF AG ?, meaning “what are the reachable
states in which the system will remain forever?”.
These analysis problems further require that solutions to their queries be states of the
model. For example, a query AF ? on the model in Figure 1(a) has solutions (p∧¬q∧r)
and (q ∧ r). The first corresponds to the state s0 and is a state solution. The second corresponds to a set of states {s1 , s2 } but neither s1 nor s2 is a solution by itself. When
only state solutions are needed, we can formulate a restricted state query-checking problem by constraining the solutions to be single states, rather than arbitrary propositional
formulas (that represent sets of states). A naive state query checking algorithm is to
repeatedly substitute each state of the model for the placeholder, and return those for
which the resulting CTL formula holds. This approach is linear in the size of the state
space and in the cost of CTL model checking. While significantly more efficient than
general query checking, this approach is not “fully” symbolic, since it requires many
runs of a model-checker.
While several approaches have been proposed to solve general query checking, none
are effective for solving the state query-checking problem. The original algorithm of
Chan [5] was very efficient (same cost as CTL model checking), but was restricted
to valid queries, i.e., queries whose solutions can be characterized by a single propositional formula. This is too restrictive for our purposes. For example, neither of the
Finding State Solutions to Temporal Logic Queries
275
queries EF ?, AF ?, nor the stable states query EF AG ? are valid. Bruns and
Godefroid [3] generalized query checking to all CTL queries by proposing an automatabased CTL model checking algorithm over a lattice of sets of all possible solutions. This
algorithm is exponential in the size of the state space. Gurfinkel and Chechik [15] have
also provided a symbolic algorithm for general query checking. The algorithm is based
on reducing query checking to multi-valued model checking and is implemented in a
tool TLQSolver [7]. While empirically faster than the corresponding naive approach of
substituting every propositional formula for the placeholder, this algorithm still has the
same worst-case complexity as that in [3], and remains applicable only to modest-sized
query-checking problems. An algorithm proposed by Hornus and Schnoebelen [17]
finds solutions to any query, one by one, with increasing complexity: a first solution
is found in time linear in the size of the state space, a second, in quadratic time, and
so on. However, since the search for solutions is not controlled by their shape, finding
all state solutions can still take exponential time. Other query-checking work is not
directly applicable to our state query-checking problem, as it is exclusively concerned
either with syntactic characterizations of queries[23], or with extensions, rather than
restrictions, of query checking [24,26].
In this paper, we provide a symbolic algorithm for solving the state query-checking
problem, and describe an implementation using the model-checker NuSMV [8]. The
algorithm is formulated as model checking over a lattice of sets of states, but its implementation is done by modifying only the interface of NuSMV. Manipulation of
the lattice sets is done directly by NuSMV. While the running time of this approach
is the same as in the corresponding naive approach, we show empirical evidence
that our implementation can perform better than the naive, using a case study from
genetics [12].
The algorithms proposed for the program analysis problems described above are
special cases of ours, that solve only EF ? and AF ? queries, whereas our algorithm
solves any CTL query. We prove our algorithm correct by showing that it approximates
general query checking, in the sense that it computes exactly those solutions, among
all given by general query checking, that are states. We also generalize our results to
an approximation framework that can potentially apply to other extensions of model
checking, e.g., vacuity detection, and point to further applications of our technique,
e.g., to querying XML documents.
There is a also a very close connection between query-checking and sanity checks
such as vacuity and coverage [19]. All these problems require checking several “mutants” of the property or of the model to obtain the final solution. The algorithm for
solving state queries presented in this paper bears many similarities to the algorithms
described in [19]. Since query-checking is more general, we believe it can provide a
uniform framework for studying all these problems.
The rest of the paper is organized as follows. Section 2 provides the model checking
background. Section 3 describes the general query-checking algorithm. We formally
define the state query-checking problem and describe our implementation in Section 4.
Section 5 presents the general approximation technique for model checking over lattices
of sets. We present our case study in Section 6, and conclude in Section 7.
276
M. Gheorghiu, A. Gurfinkel, and M. Chechik
s0
p
¬q
r
s1
(a)
s2
p
q
r
¬p
q
r
[[]](s)
[[a]](s)
[[¬a]](s)
[[ϕ ∧ ψ]](s)
[[ϕ ∨ ψ]](s)
[[EX ϕ]](s)
(b)
[[AX ϕ]](s)
[[EG ϕ]](s)
[[AG ϕ]](s)
[[E[ϕ U ψ]]](s)
[[A[ϕ U ψ]]](s)
, for ∈ {true, false}
a ∈ I(s), for a ∈ A
a∈
/ I(s), for a ∈ A
[[ϕ]](s) ∧ [[ψ]](s)
[[ϕ]](s) ∨ [[ψ]](s)
[[ϕ]](s )
s ∈R(s)
s ∈R(s) [[ϕ]](s )
[[νZ.ϕ ∧ EXZ]](s)
[[νZ.ϕ ∧ AXZ]](s)
[[μZ.ψ ∨ (ϕ ∧ EXZ)]](s)
[[μZ.ψ ∨ (ϕ ∧ AXZ)]](s)
Fig. 1. (a) A simple Kripke structure; (b) CTL semantics
2 Background
In this section, we review some notions of lattice theory, minterms, CTL model checking, and multi-valued model checking.
Lattice theory. A finite lattice is a pair (L, ), where L is a finite set and is a
partial order on L, such that every finite subset B ⊆ L has a least upper bound (called
join and written B) and a greatest lower bound (called meet and written B). Since
the lattice is finite, there exist = L and ⊥ = L, that are the maximum and
respectively minimum elements in the lattice. When the ordering is clear from the
context, we simply refer to the lattice as L. A lattice if distributive if meet and join
distribute over each other. In this paper, we work with lattices of propositional formulas.
For a set of atomic propositions P , let F (P ) be the set of propositional formulas over
P . For example, F ({p}) = {true, false, p, ¬p}. This set forms a finite lattice ordered
by implication (see Figure 2(a)). Since p ⇒ true, p is under true in this lattice. Meet
and join in this lattice correspond to logical operators ∧ and ∨, respectively.
A subset B ⊆ L is called upward closed or an upset, if for any a, b ∈ L, if b ∈ B and
b a, then a ∈ B. In that case, B can be identified by the set M of its minimal elements
(b ∈ B is minimal if for all a ∈ B if a b), then a = b), and we write B = ↑M . For
example, for the lattice (F ({p}), ⇒) shown in Figure 2(a), ↑{p, ¬p} = {p, ¬p, true}.
The set {p, ¬p} is not an upset, whereas {p, ¬p, true} is. For singletons, we write ↑a
for ↑{a}. We extend the ↑ notation to any set A ⊆ L by ↑A = ↑M , where M is the set
of minimal elements in A. We write U(L) for the set of all upsets of L, i.e., A ⊆ L iff
↑A ∈ U(L). U(L) is closed under union and intersection, and therefore forms a lattice
ordered by set inclusion. We call (U(L), ⊆) the upset lattice of L. The upset lattice of
F ({p}) is shown in Figure 2(b).
An element j in a lattice L is join-irreducible if j = ⊥ and j cannot be decomposed
as the join of other lattice elements, i.e., for any x and y in L, j = x y implies j = x
or j = y [11]. For example, the join-irreducible elements of the lattice in Figure 2(a)
are p and ¬p, and of the one in Figure 2(b) — ↑true, ↑p, ↑¬p, and ↑false.
Finding State Solutions to Temporal Logic Queries
277
↑false
true
¬p
p
{p, ¬p}
↑{p, ¬p}
↑p
↑¬p
{p}
{¬p}
↑true
∅
false
↑{}
(a)
(b)
(c)
Fig. 2. Lattices for P = {p}: (a) (F(P ), ⇒); (b) (U(F(P )), ⊆); (c) (2M(P ) , ⊆)
Minterms. In the lattice of propositional formulas F (P ), a join-irreducible element
is a conjunction in which every atomic proposition of P appears, positive or negated.
Such conjunctions are called minterms and we denote their set by M(P ). For example,
M({p, q}) = {p ∧ q, p ∧ ¬q, ¬p ∧ q, ¬p ∧ ¬q}.
CTL model checking. CTL model checking is an automatic technique for verifying
temporal properties of systems expressed in a propositional branching-time temporal
logic called Computation Tree Logic (CTL) [9]. A system model is a Kripke structure
K = (S, R, s0 , A, I), where S is a set of states, R ⊆ S × S is a (left-total) transition
relation, s0 ∈ S is the initial state, A is a set of atomic propositions, and I : S → 2A
is a labeling function, providing the set of atomic propositions that are true in each
state. CTL formulas are evaluated in the states of K. Their semantics can be described
in terms of infinite execution paths of the model. For instance, a formula AG ϕ holds
in a state s if ϕ holds in every state, on every infinite execution path s, s1 , s2 , . . . starting at s; AF ϕ (EF ϕ) holds in s if ϕ holds in some state, on every (some) infinite execution path s, s1 , s2 , . . .. The formal semantics of CTL is given in Figure 1(b).
Without loss of generality we consider only CTL formulas in negation normal form,
where negation is applied only to atomic propositions [9]. In Figure 1(b), the function
[[ϕ]] : S → {true, false} indicates the result of checking a formula ϕ in state s; the
(Z) are
set of successors for a state s is R(s) {s |(s, s ) ∈ R}; μZ.f (Z)
and νZ.f
i
least and greatest
fixpoints
of
f
,
respectively,
where
μZ.f
(Z)
=
f
(false)
and
i>0
νZ.f (Z) = i>0 f i (true). Other temporal operators are derived from the given ones,
for example: EF ϕ = E[true U ϕ], AF ϕ = A[true U ϕ]. The operators in pairs
(AX, EX), (AG, EF ), (AF, EG), . . . are duals of each other.
A formula ϕ holds in a Kripke structure K, written K |= ϕ, if it holds in the
initial state, i.e., [[ϕ]](s0 ) = true. For example, on the model in Figure 1(a), where
A = {p, q, r}, properties AG (p ∨ q) and AF q are true, whereas AX p is not. The
complexity of model-checking a CTL formula ϕ on a Kripke structure K is O(|K|×|ϕ|),
where |K| = |S| + |R|.
Multi-valued model checking. Multi-valued CTL model checking [6] is a generalization of model checking from a classical logic to an arbitrary De Morgan algebra
(L, , ¬), where (L, ) is a finite distributive lattice and ¬ is any operation that is an
278
M. Gheorghiu, A. Gurfinkel, and M. Chechik
involution (¬¬ = ) and satisfies De Morgan laws. Conjunction and disjunction are the
meet and join operations of (L, ), respectively. When the ordering and the negation
operation of an algebra (L, , ¬) are clear from the context, we refer to it as L. In this
paper, we only use a version of multi-valued model checking where the model remains
classical, i.e., both the transition relation and the atomic propositions are two-valued,
but properties are specified in a multi-valued extension of CTL over a given De Morgan
algebra L, called χCTL(L). The logic χCTL(L) has the same syntax as CTL, except
that the allowed constants are all ∈ L. Boolean values true and false are replaced
by the and ⊥ of L, respectively. The semantics of χCTL(L) is the same as of CTL,
except [[ϕ]] is extended to [[ϕ]] : S → L and the interpretation of constants is: for all
∈ L, [[]](s) . The other operations are defined as their CTL counterparts (see Figure 1(b)), where ∨ and ∧ are interpreted as lattice operators and , respectively. The
complexity of model checking a χCTL(L) formula ϕ on a Kripke structure K is still
O(|K| × |ϕ|), provided that meet, join, and quantification can be computed in constant
time [6], which depends on the lattice.
3 Query Checking
In this section, we review the query-checking problem and a symbolic method for
solving it.
Background. Let K be a Kripke structure with a set A of atomic propositions. A CTL
query, denoted by ϕ[?], is a CTL formula containing a placeholder “?” for a propositional subformula (over the atomic propositions in A). The CTL formula obtained by
substituting the placeholder in ϕ[?] by a formula α ∈ F(A) is denoted by ϕ[α]. A formula α is a solution to a query if its substitution into the query results in a CTL formula
that holds on K, i.e., if K |= ϕ[α]. For example, (p ∧ ¬q ∧ r) and (q ∧ r) are among the
solutions to the query AF ? on the model of Figure 1(a), whereas ¬r is not.
In this paper, we consider queries in negation normal form where negation is applied only to the atomic propositions, or to the placeholder. We further restrict our
attention to queries with a single placeholder, although perhaps with multiple occurrences. For a query ϕ[?], a substitution ϕ[α] means that all occurrences of the placeholder are replaced by α. For example, if ϕ[?] = EF (? ∧ AX ?), then ϕ[p ∨ q] =
EF ((p ∨ q) ∧ AX (p ∨ q)). We assume that occurrences of the placeholder are either non-negated everywhere, or negated everywhere, i.e., the query is either positive or
negative, respectively. Here, we limit our presentation to positive queries; see Section 5
for the treatment of negative queries.
The general CTL query-checking problem is: given a CTL query on a model, find
all its propositional solutions. For instance, the answer to the query AF ? on the model
in Figure 1(a) is the set consisting of (p ∧ ¬q ∧ r), (q ∧ r) and every other formula
implied by these, including p, (q ∨ r), and true. If α is a solution to a query, then any β
such that α ⇒ β (i.e., any weaker β) is also a solution, due to the monotonicity of positive queries [5]. Thus, the set of all possible solutions is an upset; it is sufficient for the
query-checker to output the strongest solutions, since the rest can be inferred from them.
One can restrict a query to a subset P ⊆ A [3]. We then denote the query by ϕ[?P ],
and its solutions become formulas in F (P ). For instance, checking AF ?{p, q} on the
Finding State Solutions to Temporal Logic Queries
279
model of Figure 1(a) should result in (p ∧ ¬q) and q as the strongest solutions, together
with all those implied by them. We write ϕ[?] for ϕ[?A].
n
If P consists of n atomic propositions, there are 22 possible distinct solutions to
ϕ[?P ]. A “naive” method for finding all solutions would model check ϕ[α] for every
possible propositional formula α over P , and collect all those α’s for which ϕ[α] holds
n
in the model. The complexity of this naive approach is 22 times that of usual modelchecking.
Symbolic algorithm. A symbolic algorithm for solving the general query-checking
problem was described in [15] and has been implemented in the TLQSolver tool [7].
We review this approach below.
Since an answer to ϕ[?P ] is an upset, the upset lattice U(F (P )) is the space of all
possible answers [3]. For instance, the lattice for AF ?{p} is shown in Figure 2(b). In
the model in Figure 1(a), the answer to this query is {p, true}, encoded as ↑{p}, since
p is the strongest solution.
Symbolic query checking is implemented by model checking over the upset lattice.
The algorithm is based on a state semantics of the placeholder. Suppose query ?{p} is
evaluated in a state s. Either p holds in s, in which case the answer to the query should
be ↑p, or ¬p holds, in which case the answer is ↑¬p. Thus we have:
↑p
if p ∈ I(s),
[[?{p}]](s) =
↑¬p if p ∈ I(s).
This case analysis can be logically encoded by the formula (p ∧ ↑p) ∨ (¬p ∧ ↑¬p).
Let us now consider a general query ?P in a state s (where ? ranges over a set of
atomic propositions P ). We note that the case analysis corresponding to the one above
can be given in terms of minterms. Minterms are the strongest formulas that may hold
in a state; they also are mutually exclusive and complete — exactly one minterm j holds
in any state s, and then ↑j is the answer to ?P at s. This semantics is encoded in the
following translation of the placeholder:
(j ∧ ↑j).
T (?P ) =
j∈M(P )
The symbolic algorithm is defined as follows: given a query ϕ[?P ], first obtain
ϕ[T (?P )], which is a χCTL formula (over the lattice U(F (P ))), and then model check
this formula. The semantics of the formula is given by a function from S to U(F (P )),
as described in Section 2. Thus model checking this formula results in a value from
U(F (P )). That value was shown in [15] to represent all propositional solutions to
ϕ[?P ]. For example, the query AF ? on the model of Figure 1(a) becomes
AF ((p ∧ q ∧ r ∧ ↑(p ∧ q ∧ r))∨
(p ∧ q ∧ ¬r ∧ ↑(p ∧ q ∧ ¬r))∨
(p ∧ ¬q ∧ r ∧ ↑(p ∧ ¬q ∧ r))∨
(p ∧ ¬q ∧ ¬r ∧ ↑(p ∧ ¬q ∧ ¬r))∨
. . .).
The result of model-checking this formula is ↑{p ∧ ¬q ∧ r, q ∧ r}.
280
M. Gheorghiu, A. Gurfinkel, and M. Chechik
The complexity of this algorithm is the same as in the naive approach. In practice,
however, TLQSolver was shown to perform better than the naive algorithm [15,7].
4 State Solutions to Queries
Let K be a Kripke structure with a set A of atomic propositions. In general query checking, solutions to queries are arbitrary propositional formulas. On the other hand, in state
query checking, solutions are restricted to be single states. To represent a single state, a
propositional formula needs to be a minterm over A. In symbolic model checking, any
state s of K is uniquely represented by the minterm that holds in s. For example, in the
model of Figure 1(a), state s0 is represented by (p ∧ ¬q ∧ r), state s2 by (p ∧ q ∧ r), etc.
Thus, for state query checking, an answer to a query is a set of minterms, rather than
an upset of propositional formulas. For instance, for the query AF ?, on the model of
Figure 1(a), the state query-checking answer is {p∧¬q ∧r}, whereas the general querychecking one is ↑{r∧q, p∧¬q ∧r}. While it is still true that if j is a solution, everything
in ↑j is also a solution, we no longer view answers as upsets, since we are interested
only in minterms, and j is the only minterm in the set ↑j (minterms are incomparable by
implication). We can thus formulate state query checking as minterm query checking:
given a CTL query on a model, find all its minterm solutions. We show how to solve
this for any query ϕ[?P ], and any subset P ⊆ A. When P = A, the minterms obtained
are the state solutions.
Given a query ϕ[?P ], a naive algorithm would model check ϕ[α] for every minterm
α. If n is the number of atomic propositions in P , there are 2n possible minterms,
and this algorithm has complexity 2n times that of model-checking. Minterm query
checking is thus much easier to solve than general query checking.
Of course, any algorithm solving general query checking, such as the symbolic approach described in Section 3, solves minterm query checking as well: from all solutions, we can extract only those which are minterms. This approach, however, is much
more expensive than needed. Below, we propose a method that is tailored to solve just
minterm query checking, while remaining symbolic.
4.1 Solving Minterm Query Checking
Since an answer to minterm query checking is a set of minterms, the space of all answers
is the powerset 2M(P ) that forms a lattice ordered by set inclusion. For example, the
lattice 2M({p}) is shown in Figure 2(c). Our symbolic algorithm evaluates queries over
this lattice. We first adjust the semantics of the placeholder to minterms. Suppose we
evaluate ?{p} in a state s. Either p holds in s, and then the answer should be {p}, or ¬p
holds, and then the answer is {¬p}. Thus, we have
{p}
if p ∈ I(s),
[[?{p}]](s) =
{¬p} if p ∈ I(s).
Finding State Solutions to Temporal Logic Queries
281
This is encoded by the formula (p ∧ {p}) ∨ (¬p ∧ {¬p}). In general, for a query ?P ,
exactly one minterm j holds in s, and in that case {j} is the answer to the query. This
gives the following translation of placeholder:
Am (?P )
(j ∧ {j}).
j∈M(P )
Our minterm query-checking algorithm is now defined as follows: given a query
ϕ[?P ] on a model K, compute ϕ[Am (?P )], and then model check this over 2M(P ) .
For example, for AF ?, on the model of Figure 1(a), we model check
AF ((p ∧ q ∧ r ∧ {p ∧ q ∧ r})∨
(p ∧ q ∧ ¬r ∧ {p ∧ q ∧ ¬r})∨
(p ∧ ¬q ∧ r ∧ {p ∧ ¬q ∧ r})∨
(p ∧ ¬q ∧ ¬r ∧ {p ∧ ¬q ∧ ¬r})∨
. . .),
and obtain the answer {p ∧ ¬q ∧ r}, that is indeed the only minterm solution for this
model.
To prove our algorithm correct, we need to show that its answer is the set of all
minterm solutions. We prove this claim by relating our algorithm to the general algorithm in Section 3. We show that, while the general algorithm computes the set
B ∈ U(F (P )) of all solutions, ours results in the subset M ⊆ B that consists of only
the minterms from B. We first establish an “approximation” mapping from U(F (P ))
to 2M(P ) that, for any upset B ∈ U(F (P )), returns the subset M ⊆ B of minterms.
Definition 1 (Minterm approximation). Let P be a set of atomic propositions.
Minterm approximation fm : U(F (P )) → 2M(P ) is fm (B) B ∩ M(P ), for any
B ∈ U(F (P )).
With this definition, Am (?P ) is obtained from T (?P ) by replacing ↑j with fm (↑j) =
{j}. The minterm approximation preserves set operations; this can be proven using the
fact that any set of propositional formulas can be partitioned into minterms and nonminterms.
Proposition 1. The minterm approximation fm : U(F (P )) → 2M(P ) is a lattice homomorphism, i.e., it preserves the set operations: for any B, B ∈ U(F (P )), fm (B) ∪
fm (B ) = fm (B ∪ B ) and fm (B) ∩ fm (B ) = fm (B ∩ B ).
By Proposition 1, and since model checking is performed using only set operations,
we can show that the approximation preserves model-checking results. Model checking ϕ[Am (?P )] is the minterm approximation of checking ϕ[T (?P )]. In other words,
our algorithm results in set of all minterm solutions, which concludes the correctness
argument.
Theorem 1 (Correctness of minterm approximation). For any state s of K,
fm ([[ϕ[T (?P )]]](s)) = [[ϕ[Am (?P )]]](s).
282
M. Gheorghiu, A. Gurfinkel, and M. Chechik
In summary, for P = A, we have the following correct symbolic state query-checking
algorithm : given a query ϕ[?] on a model K, translate it to ϕ[Am (?A)], and then model
check this over 2M(A) .
The worst-case complexity of our algorithm is the same as that of the naive approach.
With an efficient encoding of the approximate lattice, however, our approach can outperform the naive one in practice, as we show in Section 6.
4.2 Implementation
Although our minterm query-checking algorithm is defined as model checking over a
lattice, we can implement it using a classical symbolic model checker. This is done by
encoding the lattice elements in 2M(P ) such that lattice operations are already implemented by a symbolic model checker. The key observation is that the lattice (2M(P ) , ⊆)
is isomorphic to the lattice of propositional formulas (F (P ), ⇒). This can be seen,
for instance, by comparing the lattices in Figures 2(a) and 2(c). Thus, the elements of
2M(P ) can be encoded as propositional formulas, and the operations become propositional disjunction and conjunction. A symbolic model checker, such as NuSMV [8],
which we used in our implementation, already has data structures for representing
propositional formulas and algorithms to compute their disjunction and conjunction
— BDDs [25]. The only modifications we made to NuSMV were parsing the input and
reporting the result.
While parsing the queries, we implemented the translation Am defined in Section 4.1.
In this translation, for every minterm j, we give a propositional encoding to {j}. We
cannot simply use j to encode {j}. The lattice elements need to be constants with respect to the model, and j is not a constant — it is a propositional formula that contains
model variables. We can, however, obtain an encoding for {j}, by renaming j to a similar propositional formula over fresh variables. For instance, we encode {p ∧ ¬q ∧ r}
as x ∧ ¬y ∧ z. Thus, our query translation results in a CTL formula with double the
number of propositional variables compared to the model. For example, the translation
of AF ?{p, q} is
AF ((p ∧ q ∧ x ∧ y)∨
(p ∧ ¬q ∧ x ∧ ¬y)∨
(¬p ∧ q ∧ ¬x ∧ y)∨
(¬p ∧ ¬q ∧ ¬x ∧ ¬y)).
We input this formula into NuSMV, and obtain the set of minterm solutions as a propositional formula over the encoding variables x, y, . . .. For AF ?{p, q}, on the model in
Figure 1(a), we obtain the result x ∧ ¬y, corresponding to the only minterm solution
p ∧ ¬q.
4.3 Exactness of Minterm Approximation
In this section, we address the applicability of minterm query checking to general query
checking. When the minterm solutions are the strongest solutions to a query, minterm
query checking solves the general query-checking problem as well, as all solutions to
that query can be inferred from the minterms. In that case, we say that the minterm
Finding State Solutions to Temporal Logic Queries
283
approximation is exact. We would like to identify those CTL queries that admit exact
minterm approximations, independently of the model. The following can be proven
using the fact that any propositional formula is a disjunction of minterms.
Proposition 2. A positive query ϕ[?P ] has an exact minterm approximation in any
model iff ϕ[?P ] is distributive over disjunction, i.e., ϕ[α ∨ β] = ϕ[α] ∨ ϕ[β].
An example of a query that admits an exact approximation is EF ?; its strongest solutions are always minterms, representing the reachable states. In [5], Chan showed that
deciding whether a query is distributive over conjunction is EXPTIME-complete. We
obtain a similar result by duality.
Theorem 2. Deciding whether a CTL query is distributive over disjunction is
EXPTIME-complete.
Since the decision problem is hard, it would be useful to have a grammar that is guaranteed to generate queries which distribute over disjunction. Chan defined a grammar for
queries distributive over conjunction, that was later corrected by Samer and Veith [22].
We can obtain a grammar for queries distributive over disjunction, from the grammar
in [22], by duality.
5 Approximations
The efficiency of model checking over a lattice is determined by the size of the lattice.
In the case of query checking, by restricting the problem and approximating answers,
we have obtained a more manageable lattice. In this section, we show that our minterm
approximation is an instance of a more general approximation framework for reasoning
over any lattice of sets. Having a more general framework makes it easier to accommodate other approximations that may be needed in query checking. For example, we
use it to derive an approximation to negative queries. This framework may also apply
to other analysis problems that involve model checking over lattices of sets, such as
vacuity detection [14].
We first define general approximations that map larger lattices into smaller ones. Let
U be any finite set. Its powerset lattice is (2U , ⊆). Let (L, ⊆) be any sublattice of the
powerset lattice, i.e., L ⊆ 2U .
Definition 2 (Approximation). A function f : L → 2U is an approximation if:
1. it satisfies f (B) ⊆ B for any B ∈ L (i.e., f (B) is an under-approximation of B),
and
2. it is a lattice homomorphism, i.e., it respects the lattice operations: f (B ∩ C) =
f (B) ∩ f (C), and f (B ∪ C) = f (B) ∪ f (C).
From the definition of f , the image f (L) of L through f is a sublattice of 2U , having
f () and f (⊥) as its maximum and minimum elements, respectively.
We consider an approximation to be correct if it is preserved by model checking:
reasoning over the smaller lattice is the approximation of reasoning over the larger
284
M. Gheorghiu, A. Gurfinkel, and M. Chechik
one. Let ϕ be a χCTL(L) formula. We define its translation A(ϕ) into f (L) to be the
χCTL(f (L)) formula obtained from ϕ by replacing any constant B ∈ L occurring
in ϕ by f (B). The following theorem simply states that the result of model checking A(ϕ) is the approximation of the result of model checking ϕ. Its proof follows by
structural induction from the semantics of χCTL, and uses the fact that approximations are homomorphisms. [18] proves a similar result, albeit in a somewhat different
context.
Theorem 3 (Correctness of approximations). Let K be a classical Kripke structure,
L be a De Morgan algebra of sets, f be an approximation function on L, and ϕ be a
χCTL(L) formula. Let A(ϕ) be the translation of ϕ into f (L). Then for any state s of K,
f ([[ϕ]](s)) = [[A(ϕ)]](s).
Theorem 1 is a corollary to Theorem 3. Our minterm approximation satisfies condition
(1) of Definition 2, since fm (B) = B ∩ M(P ) ⊆ B, and it also satisfies condition (2)
by Proposition 1. Thus, fm is an approximation to which Theorem 3 applies, yielding
Theorem 1.
The minterm approximation defined in Section 4.1 was restricted to positive queries.
The general approximation framework defined above makes it easy to derive a minterm
approximation for negative queries. We denote a negative query by ϕ[¬?P ]. To obtain
the minterm solutions to ϕ[¬?P ], we can check ϕ[?P ], that is, ignore the negation and
treat the query as positive. For example, to check the negative query AF ¬?{p, q}, we
check AF ?{p, q} instead. The minterm solutions to the original negative query are
the duals of the maxterm solutions to ϕ[?P ]. A maxterm is a disjunction where all the
atomic propositions are, positive or negated. We denote by X (P ) the set of maxterms
over a set P of atomic propositions. For example, X ({p, q}) = {p ∨ q, p ∨ ¬q, ¬p ∨
q, ¬p ∨ ¬q}. A minterm j is a solution to ϕ[¬?P ] iff its negation ¬j is a maxterm
solution to ϕ[?P ]. We thus need to define a maxterm approximation fx : U(F (P )) →
2X (P ) for positive queries. We define fx such that, for any upset B, it returns the subset
of maxterms in that set, i.e., fx (B) = B ∩ X (P ). According to Definition 2, fx is an
approximation: (1) holds by fx ’s definition, and (2) follows from the fact that any set of
propositional formulas can be partitioned into maxterms and non-maxterms. We define
the translation:
(j ∧ fx (↑j)).
Ax (?P )
j∈M(P )
Then, by Theorem 3, model-checking ϕ[Ax (?P )] results in all the maxterm solutions
to ϕ[?P ]. By negating every resulting maxterm, we obtain all minterm solutions to
ϕ[¬?P ]. For example, maxterm solutions to AF ?{p, q} for the model of Figure 1(a)
is the set X ({p, q}); thus, the minterm solutions to AF ¬?{p, q} are the entire set
M({p, q}).
In summary, we have shown that minterm approximations can be generalized to an
approximation framework over any lattices of sets, which is applicable, for instance, to
finding minterm solutions to negative queries.
Finding State Solutions to Temporal Logic Queries
285
6 Case Study
In this section, we study the problem of finding stable states of a model, and evaluate
the performance of our implementation by comparing it to the naive approach to state
query checking.
In a study published in plant research, a model of gene interaction has been proposed to compute the “stable states” of a system of genes [12]. This work defined stable
states as reachable gene configurations that no longer change, and used discrete dynamical systems to find such states. A different publication, [4], advocated the use of
Kripke structures as appropriate models of biological systems, where model checking
can answer some of the relevant questions about their behaviour. [4] also noted that
query-checking might be useful as well, but did not report any applications of this technique. Motivated by [4], we repeated the study of [12] using our state query-checking
approach.
The model of [12] consists of 15 genes, each with a “level of expression” that is
either boolean (0 or 1), or ternary (0,1, or 2). The laws of interaction among genes have
been established experimentally and are presented as logical tables. The model was
translated into a NuSMV model with 15 variables, one per gene, of which 8 are boolean
and the rest are ternary, turning the laws into NuSMV next-state relations. The model
has 559,872 states and is in the Appendix.
The problem of finding all stable states of the model and the initial states leading to
them is formulated as the minterm query checking of EF AG?, where ? ranges over
all variables. Performance of our symbolic algorithm (Section 4) and the naive state
query-checking algorithm for this query is summarized in the top row of the table in
Figure 3(a), where the times are reported in minutes. Our algorithm was implemented
using NuSMV as described in Section 4.2. The naive algorithm was also implemented
using NuSMV by generating all possible minterms over the model variables, replacing
each for the placeholder in EF AG? and calling NuSMV to check the resulting formulas. Both algorithms were run on a Pentium 4 processor with 2.8GHz and 1 GB of
RAM. Our algorithm gave an answer in under two hours, being about 20% faster than
the naive.
To have a larger basis of comparison between the two algorithms, we varied the
model (see rows 2-4), and the checked queries (see rows 5-7). Each “mutant” was
obtained by permanently switching a different gene off (see Appendix), as indicated
in [12]. The performance gain of our algorithm is robust to these changes.
Discussion. Performance improvements observed in our case study may not be attainable for every model. If the model is sufficiently small, our algorithm is likely to
be faster. As models grow, however, the naive algorithm, which uses fewer BDD variables, will be more scalable. For more challenging models, a combination of the two
approaches may yield the best results.
Another alternative is an iterative approach. Suppose we are interested in checking a
query AF ? with two propositions, a and b. We first check AF ?{a} and AF ?{b}. If no
value is found for a proposition, then the query has no minterm solutions. Otherwise, the
results correspond to the values each proposition has in all minterm solutions. For example, suppose we obtain a = false, whereas b can be either true or false. We proceed
286
M. Gheorghiu, A. Gurfinkel, and M. Chechik
1
2
3
4
5
6
7
Model
Query
original
mutant 1
mutant 2
mutant 3
original
original
original
EF AG ?
EF AG ?
EF AG ?
EF AG ?
AG ?
EF ?
AF ?
(a)
Algorithms
Ours Naive
117
116
117
117
116
118
117
145
144
145
146
145
146
145
paper
author
Chandra
title
Merlin
“A Paper Title”
(b)
Fig. 3. (a) Experimental results; (b) An XML example (adapted from [13])
by checking a query for each pair of propositions, using for the placeholder replacement only those values found in the previous step. For example, we check AF ?{a, b},
replacing ? by (¬a ∧ b ∧ {¬a ∧ b}) ∨ (¬a ∧ ¬b ∧ {¬a ∧ ¬b}). We continue with
checking triples of propositions using the valued obtained for pairs, and so on, until the
query is checked on all atomic propositions, or it has been established that no answer
exists. In this iterative process, there is place for heuristics that would switch between
checking queries by our algorithm or the naive one, based on the resources available
(time vs. memory). We will address such improvements in future optimizations of our
implementation.
7 Conclusions
We have identified and formalized the state query-checking problem, which is of practical interest and can be solved more efficiently than general query checking. We have
presented a symbolic algorithm that solves this problem, described a simple implementation using the NuSMV model checker, and showed its effectiveness on a realistic case
study. We proved our algorithm correct by introducing the notion of approximation,
which we have extended to reasoning over any lattice of sets. Our state query-checking
algorithm generalizes techniques previously proposed for computing procedure summaries [2] and postdominators [1]. In essence, we generalized these algorithms, specialized for EF ? and AF ? queries, respectively, to arbitrary CTL queries. Our algorithm
solves general state-based queries by computing fixpoints over pre-image computations,
i.e., iterating over EX and AX. While some of these queries can be solved by fixpoints
over post-image computations, such as the query EF ? for discovering the reachable
states, not every state-based CTL query can be solved that way, and this impossibility
result follows from the work in [16].
We have also presented the application of state query checking to finding stable states
in gene networks. In the rest of this section we present another application, that we are
currently investigating.
State query checking can be applied to querying XML documents, which are modelled as trees. A simple example, of a fragment from a document containing information
Finding State Solutions to Temporal Logic Queries
287
about research papers and adapted from [13], is shown in Figure 3(b). An example
query is “what are the titles of all papers authored by Chandra?”. Viewing tree nodes as
states and edges as transitions yields a state-transition model, on which CTL properties
can be evaluated [20]. Unfortunately, our example, like many other XML queries, needs
to refer to both past and future, and is expressed as a CTL+Past formula as follows [13]:
EX past (title ∧ EX past (paper ∧ EX (author ∧ EX Chandra))).
Such formulas cannot be evaluated without modifying the internals of standard modelcheckers. Formulating this question as a query yields
paper ∧ EX (title ∧ EX ?) ∧ EX (author ∧ EX Chandra),
whose desired solutions are states (here, the node labeled “A Paper Title”), and which
avoids the use of the past, and can be solved by our approach, without modifying existing model checkers.
Acknowledgements. We are grateful to Miguel Carrillo Barajas of the Universidad
Nacional Autónoma de México (UNAM), for providing us with the gene model, relevant references, and helpful clarifications. We thank Jocelyn Simmonds for helping us
with implementation, and Shiva Nejati for comments on this paper. This research was
supported in part by NSERC.
References
1. Aminof, B., Ball, T., Kupferman, O.: Reasoning About Systems with Transition Fairness. In:
Baader, F., Voronkov, A. (eds.) LPAR 2004. LNCS (LNAI), vol. 3452, pp. 194–208. Springer,
Heidelberg (2005)
2. Ball, T., Rajamani, S.: Bebop: A Symbolic Model Checker for Boolean Programs. In:
Havelund, K., Penix, J., Visser, W. (eds.) SPIN Model Checking and Software Verification.
LNCS, vol. 1885, pp. 113–130. Springer, Heidelberg (2000)
3. Bruns, G., Godefroid, P.: Temporal Logic Query-Checking. In: Proc. of LICS’01, pp. 409–
417 (2001)
4. Chabrier-Rivier, N., Chiaverini, M., Danos, V., Fages, F., Schachter, V.: Modeling and Querying Biomolecular Interaction Networks. Theor. Comp. Sci. 325(1), 25–44 (2004)
5. Chan, W.: Temporal-Logic Queries. In: Emerson, E.A., Sistla, A.P. (eds.) CAV 2000. LNCS,
vol. 1855, pp. 450–463. Springer, Heidelberg (2000)
6. Chechik, M., Devereux, B., Easterbrook, S., Gurfinkel, A.: Multi-Valued Symbolic ModelChecking. ACM Trans. on Soft. Eng. and Meth. 12(4), 1–38 (2003)
7. Chechik, M., Gurfinkel, A.: TLQSolver: A Temporal Logic Query Checker. In: Hunt Jr.,
W.A., Somenzi, F. (eds.) CAV 2003. LNCS, vol. 2725, pp. 210–214. Springer, Heidelberg
(2003)
8. Cimatti, A., Clarke, E.M., Giunchilia, E., Giunchiglia, F., Pistore, M., Roveri, M., Sebastiani,
R., Tacchella, A.: NuSMV Version 2: An Open Source Tool for Symbolic Model Checking.
In: Brinksma, E., Larsen, K.G. (eds.) CAV 2002. LNCS, vol. 2404, pp. 359–364. Springer,
Heidelberg (2002)
9. Clarke, E., Grumberg, O., Peled, D.: Model Checking (1999)
288
M. Gheorghiu, A. Gurfinkel, and M. Chechik
10. Clarke, E.M., Emerson, E.A., Sistla, A.P.: Automatic Verification of Finite-State Concurrent
Systems Using Temporal Logic Specifications. ACM Trans. on Prog. Lang. and Sys. 8(2),
244–263 (1986)
11. Davey, B.A., Priestley, H.A.: Introduction to Lattices and Order (1990)
12. Espinosa-Soto, C., Padilla-Longoria, P., Alvarez-Buylla, E.R.: A Gene Regulatory Network
Model for Cell-Fate Determination during Arabidopsis thaliana Flower Development That
Is Robust and Recovers Experimental Gene Expression Profiles. The. Plant Cell. 16, 2923–
2939 (2004)
13. Gottlob, G., Koch, C.: Monadic Queries over Tree-Structures Data. In: Proc. of LICS’02, pp.
189–202 (2002)
14. Gurfinkel, A., Chechik, M.: How Vacuous Is Vacuous? In: Jensen, K., Podelski, A. (eds.)
TACAS 2004. LNCS, vol. 2988, pp. 451–466. Springer, Heidelberg (2004)
15. Gurfinkel, A., Chechik, M., Devereux, B.: Temporal Logic Query Checking: A Tool for
Model Exploration. IEEE Trans. on Soft. Eng. 29(10), 898–914 (2003)
16. Henzinger, T.A., Kupferman, O., Qadeer, S.: From Pre-Historic to Post-Modern Symbolic
Model Checking. Form. Meth. in Syst. Des. 23(3), 303–327 (2003)
17. Hornus, S., Schnoebelen, P.: On Solving Temporal Logic Queries. In: Kirchner, H., Ringeissen, C. (eds.) AMAST 2002. LNCS, vol. 2422, pp. 163–177. Springer, Heidelberg (2002)
18. Konikowska, B., Penczek, W.: Reducing Model Checking from Multi-Valued CTL* to CTL*.
In: Brim, L., Jančar, P., Křetı́nský, M., Kucera, A. (eds.) CONCUR 2002. LNCS, vol. 2421,
Springer, Heidelberg (2002)
19. Kupferman, O.: Sanity Checks in Formal Verification. In: Baier, C., Hermanns, H. (eds.)
CONCUR 2006. LNCS, vol. 4137, Springer, Heidelberg (2006)
20. Miklau, G., Suciu, D.: Containment and Equivalence for an XPath fragment. In: Proc. of
PODS’02, pp. 65–76 (2002)
21. Reps, T.W., Horwitz, S., Sagiv, M.: Precise Interprocedural Dataflow Analysis via Graph
Reachability. In: Proc. of POPL’95, pp. 49–61 (1995)
22. Samer, M., Veith, H.: Validity of CTL Queries Revisited. In: Baaz, M., Makowsky, J.A. (eds.)
CSL 2003. LNCS, vol. 2803, pp. 470–483. Springer, Heidelberg (2003)
23. Samer, M., Veith, H.: A Syntactic Characterization of Distributive LTL Queries. In: Dı́az, J.,
Karhumäki, J., Lepistö, A., Sannella, D. (eds.) ICALP 2004. LNCS, vol. 3142, pp. 1099–
1110. Springer, Heidelberg (2004)
24. Samer, M., Veith, H.: Parameterized Vacuity. In: Hu, A.J., Martin, A.K. (eds.) FMCAD 2004.
LNCS, vol. 3312, pp. 322–336. Springer, Heidelberg (2004)
25. Somenzi, F.: Binary Decision Diagrams. In: Somenzi, F. (ed.) Calculational System Design.
NATO Science Series F: Computer and Systems Sciences, vol. 173, pp. 303–366. Sciences,
Sciences (1999)
26. Zhang, D., Cleaveland, R.: Efficient Temporal-Logic Query Checking for Presburger Systems. In: Proc. of ASE’05, pp. 24–33 (2005)
Appendix
-- flower gene network model
-- created by Miguel Carrillo Barajas of UNAM
(miguel_carrillob@yahoo.com)
-- according to the paper [12]
Finding State Solutions to Temporal Logic Queries
MODULE main
VAR
ft : {0,1};
emf1: {0,1};
tfl1: {0,1,2};
lfy : {0,1,2};
ful : {0,1,2};
ap1 : {0,1,2};
ap3 : {0,1,2};
pi : {0,1,2};
ag : {0,1,2};
ufo : {0,1}; --No change
wus : {0,1};
ap2 : {0,1};
sep : {0,1};
lug : {0,1}; --No change
clf : {0,1}; --No change
ASSIGN
-- FUL
next(ful):= case
tfl1=1 | tfl1=2
:
ap1=0 & tfl1=0
:
ap1=1 & tfl1=0
:
ap1=2 & tfl1=0
:
1 :
esac;
--FT
next(ft):= case
emf1=0 : 1;
emf1=1 : 0;
1 : ft;
esac;
--AP1
next(ap1):= case
ag=2
ag=0
ag=1
ag=0
& lfy>=tfl1
ag=1
& lfy>=tfl1
(ag=0 | ag=1) & lfy<tfl1
esac;
--EMF1
next(emf1):=case
lfy=0
: 1;
0;
2;
1;
0;
ful;
&
&
&
&
&
ft=1
ft=1
ft=0
ft=0
ft=0
:
:
:
:
:
:
1 :
0;
2;
1;
2;
1;
0;
ap1;
289
290
M. Gheorghiu, A. Gurfinkel, and M. Chechik
(lfy=1 | lfy=2) : 0;
1 : emf1;
esac;
--LFY
next(lfy):=case
tfl1=0
ap1=0 & ful=0 & tfl1=0
ap1=0 & ful=0 & (tfl1=1
ap1=0 & ful=0 & (tfl1=1
ap1=0 & ful=1 & (tfl1=1
ap1=0 & ful=1 & tfl1=0
ap1=0 & ful=2 & (tfl1=0
ap1=0 & ful=2 & tfl1=0
ap1=0 & ful=2 & tfl1=2
ap1=0 & ful=2 & (tfl1=1
ap1=0 & ful=1 & (tfl1=1
ap1=1
& (tfl1=0
ap1=1
& tfl1=2
ap1=1
& (tfl1=0
ap1=1
& tfl1=2
ap1=2
& tfl1=2
ap1=2
& (tfl1=0
ap1=2
| tfl1=2)
| tfl1=2)
| tfl1=2)
| tfl1=1)
| tfl1=2)
| tfl1=2)
| tfl1=1)
| tfl1=1)
| tfl1=1)
&
&
&
&
&
&
&
&
&
&
&
&
&
&
&
&
emf1=0
emf1=1
emf1=0
emf1=1
emf1=0
emf1=1
emf1=0
emf1=1
emf1=0
emf1=1
emf1=1
emf1=0
emf1=1
emf1=1
emf1=0
emf1=1
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
& emf1=0 :
1 :
2;
1;
1;
0;
1;
1;
2;
1;
1;
1;
0;
2;
0;
1;
1;
1;
2;
2;
lfy;
esac;
--AP2; in mutant1 this is fixed to 0
next(ap2):=case
tfl1=0
: 1;
tfl1=1 | tfl1=2 : 0;
1 : ap2;
esac;
--WUS
next(wus):=case
wus=0
: 0;
wus=1 & ag=2
& sep=1
: 0;
wus=1 & ag=2
& sep=0
: 1;
wus=1 & (ag=0 | ag=1)
: 1;
1 : wus;
esac;
--AG
next(ag):=case
(lfy >= tfl1)
& ap2=0
(lfy < tfl1)
(lfy > tfl1)
& wus=1 & ap2=1
lfy=2
& tfl1=2
& wus=1 & ap2=1
:
:
:
:
2;
0;
2;
2;
Finding State Solutions to Temporal Logic Queries
291
(lfy = tfl1) & (tfl1 <2)
& ap2=1
: 0;
(lfy> tfl1)
& (ag=0 | ag=1) & wus=0 & ap2=1 & clf=0 : 1;
(lfy> tfl1)
& ag=2 & wus=0 & ap2=1 & sep=0 & clf=0 : 1;
(lfy> tfl1)
& (ag=0 | ag=1) & wus=0 & ap2=1 & lug=0 : 1;
(lfy> tfl1)
& ag=2 & wus=0 & ap2=1 & sep=0 & lug=0
: 1;
(lfy> tfl1) & ap1=0 & (ag=0 | ag=1) & wus=0 & ap2=1
: 1;
(lfy> tfl1) & ap1=0 & ag=2
& wus=0 & ap2=1 & sep=0 : 1;
lfy=2 & tfl1=2
& (ag=0 | ag=1) & wus=0 & ap2=1 & clf=0 : 1;
lfy=2 & tfl1=2
& ag=2 & wus=0 & ap2=1 & sep=0 & clf=0 : 1;
lfy=2 & tfl1=2
& (ag=0 | ag=1) & wus=0 & ap2=1 & lug=0 : 1;
lfy=2 & tfl1=2
& ag=2 & wus=0 & ap2=1 & sep=0 & lug=0
: 1;
lfy=2 & tfl1=2 & ap1=0 & (ag=0 | ag=1) & wus=0 & ap2=1
: 1;
lfy=2 & tfl1=2 & ap1=0 & ag=2 & wus=0 & ap2=1 & sep=0
: 1;
lfy> tfl1 & (ap1=1 | ap1=2) & (ag=0 | ag=1) &
wus=0 & ap2=1 & lug=1 & clf=1 : 0;
lfy> tfl1 & (ap1=1 | ap1=2) & ag=2 &
wus=0 & ap2=1 & sep=0 & lug=1 & clf=1 : 0;
lfy=2 & tfl1=2 & (ap1=1 | ap1=2) &
(ag=0 | ag=1) & wus=0 & ap2=1 & lug=1 & clf=1 : 0;
lfy=2 & tfl1=2 & (ap1=1 | ap1=2) &
ag=2 & wus=0 & ap2=1 & sep=0 & lug=1 & clf=1 : 0;
lfy > tfl1 & ag=2
& wus=0 & ap2=1 & sep=1
: 2;
lfy=2 & tfl1=2 & ag=2
& wus=0 & ap2=1 & sep=1
: 2;
1 : ag;
esac;
--TFL1
next(tfl1):=case
emf1=0 : 0;
ap1=2
& emf1=1 : 0;
(ap1=0 | ap1=1) & lfy=2
& emf1=1 : 0;
ap1=1
& (lfy=0 | lfy=1) & ap2=1 & emf1=1 : 0;
ap1=1
& (lfy=0 | lfy=1) & ap2=0 & emf1=1 : 1;
ap1=0
& (lfy=0 | lfy=1)
& emf1=1 : 2;
1 : tfl1;
esac;
--PI
next(pi):=case
lfy=0 & ap3=0
: 0;
lfy=0 & (ap3=1 | ap3=2) & pi=0
: 0;
lfy=0 & ap1=0 & (ap3=1 | ap3=2) & (pi=1 | pi=2) & ag=0
: 0;
lfy=0 & ap1=0 & (ap3=1 | ap3=2) &
(pi=1 | pi=2) & (ag=1 | ag=2) & sep=0 : 0;
lfy=0 & (ap1=1 | ap1=2) & (ap3=1 | ap3=2) &
(pi=1 | pi=2) & sep=0 : 0;
(lfy=1 | lfy=2) & ap3=0
& ag=0
: 0;
292
M. Gheorghiu, A. Gurfinkel, and M. Chechik
(lfy=1 | lfy=2) & ap3=0
& (ag=1 | ag=2)
(lfy=1 | lfy=2) & (ap3=1 | ap3=2) & pi=0
(lfy=1 | lfy=2) & ap1=0 & (ap3=1 | ap3=2) &
(pi=1 | pi=2)
(lfy=1 | lfy=2) & ap1=0 & (ap3=1 | ap3=2) &
(pi=1 | pi=2) & (ag=1 | ag=2) &
(lfy=1 | lfy=2) & (ap1=1 | ap1=2) & (ap3=1 | ap3=2) &
(pi=1 | pi=2)&
ap1=0
& (ap3=1 | ap3=2) &
(pi=1 | pi=2) & (ag=1 | ag=2) &
(ap1=1 | ap1=2) & (ap3=1 | ap3=2) & (pi=1 | pi=2) &
esac;
--SEP
next(sep):=case
tfl1=0
(tfl1=1 | tfl1=2)
: 1;
: 1;
& ag=0: 1;
sep=0 : 1;
sep=0 : 1;
sep=1 : 2;
sep=1 : 2;
1 : pi;
: 1;
: 0;
1 : sep;
esac;
--AP3; in mutant3 this is fixed at 0
next(ap3):=case
ag in {1,2} & pi in {1,2} & sep= 1 & ap3
ap1 in {1,2} & pi in {1,2} & sep= 1 & ap3
lfy in {1,2}
& sep= 0
lfy in {1,2}
& ap3= 0
lfy in {1,2} & pi= 0
ap1= 0 & lfy in {1,2} & ag= 0
sep= 0
ap3= 0
pi= 0
ap1= 0 & ag= 0
lfy= 0
& sep= 0
lfy= 0
& ap3= 0
lfy= 0 & pi= 0
ap1= 0 & lfy= & ag= 0
in {1,2}
in {1,2}
& ufo= 1
& ufo= 1
& ufo= 1
& ufo= 1
& ufo= 0
& ufo= 0
& ufo= 0
& ufo= 0
:
:
:
:
:
:
:
:
:
:
:
:
:
:
1 :
esac;
--UFO no change
next(ufo):=ufo;
--LUG no change; in mutant2 this is fixed at 0
next(lug):=lug;
--CLF no change
next(clf):=clf;
--------------------------------------------------
2;
2;
1;
1;
1;
1;
0;
0;
0;
0;
0;
0;
0;
0;
ap3;
Qualitative Probabilistic Modelling in Event-B
Stefan Hallerstede and Thai Son Hoang
ETH Zurich
Switzerland
{halstefa,htson}@inf.ethz.ch
Abstract. Event-B is a notation and method for discrete systems modelling by refinement. We introduce a small but very useful construction:
qualitative probabilistic choice. It extends the expressiveness of Event-B
allowing us to prove properties of systems that could not be formalised
in Event-B before. We demonstrate this by means of a small example,
part of a larger Event-B development that could not be fully proved
before. An important feature of the introduced construction is that it
does not complicate the existing Event-B notation or method, and can
be explained without referring to the underlying more complicated probabilistic theory. The necessary theory [18] itself is briefly outlined in this
article to justify the soundness of the proof obligations given. We also
give a short account of alternative constructions that we explored, and
rejected.
1
Introduction
We consider modelling of software systems and more generally of complex systems to be an important development phase. We also believe that more complex
models can only be written when the method of stepwise refinement [9] is used.
Formal notation is indispensable in such a modelling activity. It provides the
foundation on which building models can be carried out. Simply writing a formal text is insufficient, though, to achieve a model of high quality. The only
serious way to analyse a model is to reason about it, proving in a mathematically rigorous way that all required properties are satisfied.
Event-B [7] is a formalism and method for discrete systems modelling. It has
been developed from the B-Method [1] using many ideas of Action Systems [8].
The semantics of an Event-B model is characterised by proof obligations. In fact,
proof obligations have a two-fold purpose. On the one hand, they show that
a model is sound with respect to some behavioural semantics. On the other
hand, they serve to verify properties of the model. This goes so far that we
only focus on the proof obligations and do not present a behavioural semantics
at all. This approach permits us to use the same proof obligations for very
This research was carried out as part of the EU research project IST
511599 RODIN (Rigorous Open Development Environment for Complex Systems)
http://rodin.cs.ncl.ac.uk.
J. Davies and J. Gibbons (Eds.): IFM 2007, LNCS 4591, pp. 293–312, 2007.
c Springer-Verlag Berlin Heidelberg 2007
294
S. Hallerstede and T.S. Hoang
different modelling domains, e.g., reactive, distributed and concurrent systems
[5], sequential programs [3], electronic circuits [11], or mixed designs [2], not
being constrained to semantics tailored to a particular domain. Event-B is a
calculus for modelling that is independent of the various models of computation.
The standard reasoning in Event-B is based on (demonic) nondeterminism
which is usually sufficient for systems modelling. However, some system behaviours are more appropriately modelled probabilistically. Event-B is extensible, that is, it can be extended when more expressiveness is needed. In this
article, we focus on extending Event-B with means for qualitative modelling of
probability. This extension grew out of the need for “almost-certain termination”
properties used in some communication protocols, e.g. [5]. We use it to demonstrate how Event-B can be extended and discuss what problems we encountered.
The extension has been made so that the impact on the notation is minimal, and
the resulting proof obligations are as simple as possible. We also discuss some
alternatives that may appear attractive to achieve convenient notation: they
would lead, however, to more complicated proof obligations. We consider this a
serious drawback because we think reasoning is the main purpose of modelling.
Some probabilistic models can only be expressed in terms of numerical measures, e.g., certain reliability problems [21, Chapter 4.4], or performance problems [13]. Yet, there is also a large class of problems where the exact numerical
measures are not of importance, e.g., when modelling communication protocols
[16], or human behaviour [2]. When modelling these, stating exact probabilities
would be over-specific: all we need is a termination property making use of a
strong local fairness property associated with probabilistic choice [14]. In this
article we restrict our attention to this qualitative aspect of probability.
In Event-B, simplicity and efficiency are favoured over completeness and generality [7]. Generality comes at the price of intricate reasoning and, in particular,
much reduced possibilities for automated tool support [4]. The available theory
[21] for probabilistic reasoning about models is very rich but associated with intricate reasoning. So, a probabilistic Event-B will have to use a simplified theory.
Our requirements on probabilistic Event-B are threefold:
(i) it should be simple, i.e., easy to understand;
(ii) it should be useful, i.e., solve a commonly encountered class of problems;
(iii) and it should permit efficient tool support.
Simplicity of the notation is very important because an Event-B model is understood as a means of reasoning and communication: we must not have doubts
about the meaning of a model. We also require that we have good reason for
the extension: if we would not know of any problem that we could solve –only
or better– by means of the extended method, there would be little point in
extending Event-B.
Overview. The paper is structured as follows. In Section 2, we give an overview of
the Event-B modelling notation, along with the proof obligations that give meanings to Event-B constructs. In Section 3, we consider a probabilistic extension of
Event-B for almost-certain convergence. In particular, Section 3.1 discusses the
Qualitative Probabilistic Modelling in Event-B
295
necessary additions to the notation and the proof obligations in order to accommodate the extension, and in Section 3.2, we consider the rejected alternatives.
An example of a communication protocol is given in Section 4 to illustrate our
approach. In Section 5, we give justifications of our proof obligations. Finally, a
summary and some conclusions are presented in Section 6.
2
The Event-B Modelling Notation
Event-B [7], unlike classical B [1], does not have a concrete syntax [12]. Still,
we present the basic notation for Event-B using some syntax. We proceed like
this to improve legibility and help the reader remember the different constructs
of Event-B. The syntax should be understood as a convention for presenting
Event-B models in textual form rather than defining a language.
Event-B models are described in terms of the two basic constructs: contexts
and machines. Contexts contain the static part of a model whereas machines
contain the dynamic part. Contexts may contain carrier sets, constants, axioms,
where carrier sets are similar to types [7]. In this article, we simply assume that
there is some context and do not mention it explicitly. Machines are presented
in Section 2.1, and machine refinement in Section 2.2.
2.1
Machines
Machines provide behavioural properties of Event-B models. Machines may contain variables, invariants, theorems, events, and variants. Variables v define
the state of a machine. They are constrained by invariants I(v). Possible state
changes are described by means of events. Each event is composed of a guard
G(t, v) and an action S(t, v), where t are local variables the event may contain.
The guard states the necessary condition under which an event may occur, and
the action describes how the state variables evolve when the event occurs. An
event can be represented by the term
any t where G(t, v) then S(t, v) end.
(1)
when G(v) then S(v) end
(2)
The short form
is used if event e does not have local variables, and the form
(3)
begin S(v) end
if in addition the guard equals true. A dedicated event of the form (3) is used
for initialisation. The action of an event is composed of several assignments of
the form
x := E(t, v)
x :∈ E(t, v)
x :| Q(t, v, x )
,
(4)
(5)
(6)
296
S. Hallerstede and T.S. Hoang
where x are some variables, E(t, v) expressions, and Q(t, v, x ) a predicate. Assignment form (4) is deterministic, the other two forms are nondeterministic.
Form (4) assigns x to an element of a set, and form (5) assigns to x a value
satisfying a predicate. The effect of each assignment can also be described by a
before-after predicate:
(7)
BA x := E(t, v)
=
x = E(t, v)
(8)
BA x :∈ E(t, v)
=
x ∈ E(t, v)
BA x :| Q(t, v, x )
=
Q(t, v, x ) .
(9)
A before-after predicate describes the relationship between the state just before an assignment has occurred (represented by unprimed variable names x)
and the state just after the assignment has occurred (represented by primed
variable names x ). All assignments of an action S(t, v) occur simultaneously
which is expressed by conjoining their before-after predicates, yielding a predicate A(t, v, x ). Variables y that do not appear on the left-hand side of an
assignment of an action are not changed by the action. Formally, this is achieved
by conjoining A(t, v, x ) with y = y, yielding the before-after predicate of the
action:
(10)
BA S(t, v)
=
A(t, v, x ) ∧ y = y .
In proof obligations we represent the before-after predicate BA S(t, v) of an
action S(t, v) directly by the predicate
S(t, v, v ) .
Proof obligations serve to verify certain properties of a machine. All proof
obligations in this article are presented in the form of sequents: “antecedent”
“succedent”.
For each event of a machine, feasibility must be proved:
I(v)
G(t, v)
(11)
(∃v · S(t, v, v )) .
By proving feasibility, we achieve that S(t, v, v ) provides an after state whenever
G(t, v) holds. This means that the guard indeed represents the enabling condition
of the event.
Invariants are supposed to hold whenever variable values change. Obviously,
this does not hold a priori for any combination of events and invariants and,
thus, needs to be proved. The corresponding proof obligation is called invariant
preservation:
I(v)
G(t, v)
(12)
S(t, v, v )
I(v ) .
Qualitative Probabilistic Modelling in Event-B
297
Similar proof obligations are associated with the initialisation event of a machine.
The only difference is that the invariant does not appear in the antecedent of
the proof obligations (11) and (12). For brevity, we do not treat initialisation
differently from ordinary events of a machine. The required modifications of the
concerned proof obligations are obvious.
2.2
Machine Refinement
Machine refinement provides a means to introduce more details about the dynamic properties of a model [7]. For more on the well-known theory of refinement,
we refer to the Action System formalism that has inspired the development of
Event-B [8]. We present some important proof obligations for machine refinement. As mentioned before, the user of Event-B is not presented with a behavioural model but only with proof obligations. The proof obligations describe
the semantics of Event-B models.
A machine CM can refine at most one other machine AM . We call AM the
abstract machine and CM a concrete machine. The state of the abstract machine
is related to the state of the concrete machine by a glueing invariant J(v, w),
where v are the variables of the abstract machine and w the variables of the
concrete machine.
Each event ea of the abstract machine is refined by one or more concrete
events ec. Let abstract event ea and concrete event ec be:
ea
=
any t where G(t, v) then S(t, v) end
ec
=
any u where H(u, w) then T (u, w) end
(13)
.
(14)
Somewhat simplified, we can say that ec refines ea if the guard of ec is stronger
than the guard of ea, and the glueing invariant J(v, w) establishes a simulation
of ec by ea:
I(v)
J(v, w)
H(u, w)
(15)
T(u, w, w )
(∃t, v · G(t, v) ∧ S(t, v, v ) ∧ J(v , w )) .
In the course of refinement, often new events ec are introduced into a model.
New events must be proved to refine the implicit abstract event skip that does
nothing. Moreover, it may be proved that new events do not collectively diverge
by proving that a variant V (w) is bounded below:
I(v)
J(v, w)
H(u, w)
V (w) ∈ N
(16)
,
298
S. Hallerstede and T.S. Hoang
and is decreased by each new event. We refer to the corresponding proof obligation as progress:
I(v)
J(v, w)
H(u, w)
(17)
T(u, w, w )
V (w ) < V (w) ,
where we assume that the variant is an integer expression. It can be more elaborate [7] but this is not relevant here. We call events that satisfy (16) and (17)
convergent.
3
Qualitative Probabilistic Event-B
The purpose of qualitative probabilistic reasoning is to provide the concept of
almost-certain convergence [14,18]1 . Similarly to [14,18] qualitative probabilistic
reasoning is introduced into Event-B by means of the qualitative probabilistic
choice 2 :
S ⊕ T
,
where S or T are chosen with some positive probability (see Section 5). The
probabilistic extension should not depart from the existing structure of EventB machines. Hence, we only consider introducing probabilistic choice in places
where we already have nondeterministic choice. In Event-B nondeterministic
choice appears in three places:
(i) choice among different events,
(ii) choice of local variables of events,
(iii) nondeterministic assignments.
In each of these, we could also use probabilistic choice. We present our favoured
solution based on (iii) in Section 3.1, and discuss the alternatives based on (i)
and (ii) in Section 3.2.
3.1
Almost Certain Convergence in Event-B
In this section, we introduce step by step the proof obligations for almost-certain
convergence in Event-B. Although we treat probability on the level of assignments, we actually do not mix probabilistic assignments and nondeterministic
assignments in the same event. This saves us from having to define the meaning
of their simultaneous joint effect. Hence, we say the action of an event is either
1
2
The authors of [14,18] use the term “almost-certain termination”.
We do not use the term “abstract probabilistic choice” to avoid clashes with other
refinement terminology, e.g., “concrete abstract probabilistic choice”.
Qualitative Probabilistic Modelling in Event-B
299
probabilistic or nondeterministic. Still, for better readability, we introduce some
notation for qualitative probabilistic assignments corresponding to (5):
x ⊕| Q(t, v, x ) .
(18)
With respect to invariant preservation a probabilistic action behaves identically to a nondeterministic action, i.e., demonically (see Section 5). However, it
behaves angelically with respect to progress. We can rephrase the progress proof
obligation (17) as follows:
I(v)
J(v, w)
H(u, w)
(∀w · T(u, w, w ) ⇒ V (w ) < V (w))
,
i.e. the action must decrease the variant V (w). The corresponding proof obligation for a new event with a probabilistic action follows from the angelic interpretation of the action. This means it may decrease the variant V (w):
I(v)
J(v, w)
H(u, w)
(∃w · T(u, w, w ) ∧ V (w ) < V (w))
(19)
.
Note, that proof obligation (19) subsumes feasibility (11).
For convergence of an event, (16) and (17) are sufficient. For almost-certain
convergence of an event, on the other hand, the corresponding proof obligations
(16) and (19) are not sufficient. An upper bound U (w) is required that dominates
the variant V (w):
I(v)
J(v, w)
(20)
H(u, w)
V (w) ≤ U (w) ,
for all new events.
Figure 1 shows the evolution of the variant V (w) and the upper bound U (w) in
a concrete machine for a new nondeterministic event nd and a new probabilistic
event pr: event nd must decrease the variant V (w) whereas pr may decrease
it. However, the possible variation of V (w) by event pr is limited below by the
constant 0 –proved by means of (16)– and above by U (w). The upper bound
U (w) itself is bound below by 0 as a consequence of (16) and (20). Given that
U (w) is constant or, at least, not increasing, this is sufficient for almost-certain
convergence of nd and pr. For all new events of the concrete machine we have
to prove:
I(v)
J(v, w)
H(u, w)
(21)
T(u, w, w )
U (w ) ≤ U (w) ,
300
S. Hallerstede and T.S. Hoang
U(w)
V(w)
0 nd
pr
nd
pr
Fig. 1. Almost-certain convergence
Note, that proof obligation (21) is based on the demonic interpretation of the
actions of all new events, i.e. all new events must not increase the upper bound.
Hence, the following fact makes the difference to “certain” convergence: new
events with probabilistic actions may decrease the variant but must not increase
the upper bound.
The infimum probability associated with the probabilistic action T(u, w, w )
must be greater than zero [18]. Using qualitative probabilistic assignment (18),
we can only achieve this by requiring finiteness of the possible choices for w of
the probabilistic action T(u, w, w ):
I(v)
J(v, w)
H(u, w)
(22)
finite({w | T(u, w, w )}) .
Events with probabilistic actions that satisfy (19) to (22) are called almostcertainly convergent. Note, that almost-certain convergence also imposes proof
obligations (20) and (21) on new nondeterministic events, and that if we have new
events with nondeterministic actions and new events with probabilistic actions,
we prove their joint almost-certain convergence.
3.2
The Rejected Alternatives
In order to see the advantages of the approach to almost-certain convergence
presented in the Section 3.1, we discuss the two alternatives: probabilistic choice
among different events or probabilistic choice of local variables of events. We
begin with the discussion with the latter.
It seems natural to introduce probabilistic choice at the level of local variables,
say:
ec
=
prob any u where H(u, w) then T (u, w) end
However, treating probabilistic choice on this level would lead to unnecessarily
complicated proof obligations while our aim is to keep them simple. In particular,
Qualitative Probabilistic Modelling in Event-B
301
probabilistic progress proof obligations would be difficult compared to (19):
I(v)
J(v, w)
(23)
(∃u · H(u, w) ∧ (∀w · T(u, w, w ) ⇒ V (w ) < V (w)))
.
We would have to think about two quantifiers, whereas in (19) only one existential quantification needs to be discarded.
Probabilistic choice among different events has been discussed in [20]. This
approach does only require little modification to the Event-B notation. It requires
the introduction of additional variables to group probabilistic choices, say:
ec1
=
prob a any u1 where H1 (u1 , w) then T1 (u1 , w) end
ec2
=
prob a any u2 where H2 (u2 , w) then T2 (u2 , w) end
,
denoting the abstract probabilistic choice ec1 ⊕ ec2 . For probabilistic progress
we would obtain a proof obligation with two disjuncts (i = 1, 2):
(∃ui · Hi (ui , w) ∧ (∀w · Ti (ui , w, w ) ⇒ V (w ) < V (w)))
in its succedent.
More problems may appear when trying to specify more general probabilistic
choices, say, between n components where n is a positive number, e.g., in the
dining philosophers [21, Chapter 3]. We also need to determine the order in which
probabilistic choices and nondeterministic choices are resolved: there are still
nondeterministic choices among events and of local variables. Given the intricate
relationship of probabilistic and nondeterministic choice this could potentially
lead to models very difficult to comprehend. Then perhaps, the best would be to
restrict the body of the event to being entirely deterministic. It appears that we
would have to make decisions that may seem arbitrary or introduce restrictions
that make the notation more complex.
3.3
Preliminary Study of Refinement
As mentioned in the introduction, we consider refinement to be crucial in the
development of complex systems. A theory of probabilistic refinement is available
[21], but it is intricate too. Hence, to use it with Event-B, we need to simplify
it first. We do not want to complicate the reasoning associated with Event-B
refinement.
In qualitative probabilistic Event-B we have to address refinement of events
with non-deterministic actions and events with probabilistic actions. As usual,
it should be possible to refine a nondeterministic action by a probabilistic action
[19]. Concerning refinement of events with probabilistic actions, we have two
major possibilities: either we permit probabilistic choice to be refined or we do
not permit it.
The second alternative appears attractive because we could reason about
probabilistic models with minimal extra effort. We would have to learn less
302
S. Hallerstede and T.S. Hoang
proof obligations, and we could use standard Event-B refinement. We could
ignore probability most of the time, avoiding data-refinement of probabilistic
actions, for instance. Probabilistic proofs would only occur where they are necessary, not complicating entire developments. To achieve this, some techniques
presented in [6] could be used to delay probabilistic proofs. Only at a very late
stage probabilistic concerns would enter the scene, at a stage where refinement
of probabilistic actions would no longer be necessary.
By contrast, if we need to refine probabilistic actions, we have to take into account the angelic interpretation for probabilistic progress (19). We are uncertain
whether refinement of probabilistic actions is needed in practice, or whether the
techniques discussed in the preceding paragraph would suffice. This remains to
be investigated. Which techniques are more appropriate only (more) experience
will show.
4
Example: Contention Resolution in the Firewire
Protocol
The Contention problem in the Firewire tree identify protocol [16,17] is one
example of a use of probability to break symmetry. The example has been treated
in classical B [14,18]. In this section, we will look at how we can achieve a similar
result in Event-B.
We use the contention problem in the Firewire protocol to demonstrate the
usefulness of qualitative probabilistic modelling in a practical problem [5]. In
our presentation, we do not deal with the full model but focus on almost-certain
convergence which allows us to prove a probabilistic termination property of the
Firewire protocol left open in [5].
In this section, we first give an overview of the Firewire protocol. Then we
give the specification of the contention problem in Event-B. We show the failure
of an attempt to use nondeterministic resolution and how to solve the problem
by the approach proposed in Section 3.1.
4.1
Overview of the Firewire Protocol
Purpose. A set of devices is linked by a network of bidirectional connections.
The network is an acyclic graph with devices as nodes (Figure 2a). The protocol
provides a symmetric and distributed solution for finding a node that will be
the leader of the network in a finite amount of time. All devices run the same
algorithm to find the leader of the network. Figure 2b shows a possible state
of the network of Figure 2a after a leader has been elected. The Firewire tree
identify protocol for achieving this is described below.
Protocol. Any node with only one connection can send the message “req” via
that connection requesting the neighbouring node to be leader. Also, any node
that has already received the message “req” via all its connections except one,
can send the message “req” via that last remaining connection. Message sending
Qualitative Probabilistic Modelling in Event-B
303
*
(a) Initial state of network
(b) State of network after leader
election (leader marked with a “ *”)
Fig. 2. Abstraction of leader election protocol
happens distributed and nondeterministically, i.e., there is no supervisory coordination. Eventually, there will be one node that received the message “req” via
all its connections: that node will become the leader of the network. An example
of the initial state and possible final state is shown in Figure 2.
Contention. At the final stage of the protocol, there are two nodes left that are
linked to each other and have not yet sent the message “req”. If both nodes try
to send the message “req” via that (bidirectional) connection, a livelock occurs
where it cannot be decided which node should become the leader. Each node
req
req
Fig. 3. Contention
detects the problem by receiving the message “req” from the node to which
it has just sent the same message. We identify this as the contention problem
illustrated in Figure 3.
Fortunately, there exists a probabilistic protocol to resolve the contention
within finite time; this is proved in Event-B by means of almost-certain convergence in Section 4.4 below. Before it is proved, we present the protocol and
show that (demonic) nondeterminism is unsuitable to model the probabilistic
behaviour. The protocol works as follows:
Each node independently chooses with the same non-zero probability, either
to send the message after a short delay or after a long delay (the assumption
for the long delay being that it is long enough for the message to be transferred
from one node to another). Eventually, it is “almost certain” that one of them
will choose to send the message after a short delay, while the other node will
choose to send the message after a long delay. The message that was sent after
a short delay will then be received before the other is sent (according to the
assumption). An example for solving contention can be seen in Figure 4, where
one process has chosen to send a message after a short delay and the other after
a long delay.
304
S. Hallerstede and T.S. Hoang
*
req
(a) Message sent after short wait is
received, the other message not sent
(b) State after contention resolution
(leader marked with a “ *”)
Fig. 4. Probabilistic contention resolution
4.2
Event-B Model of the Contention Problem
An Event-B model of the Firewire tree identify protocol has already been developed in [5]. We do not repeat the model but focus only on the contention
problem that is only partially modelled in [5] leaving the termination property of the protocol unproved. In this sense, we complete the model within the
Event-B framework. We take the abstract view of the contention problem only
presenting what is essential. We define a carrier set W AIT containing the two
constants: short and long.
sets:
W AIT = {short, long}
Two variables x and y represent the state of the two nodes in contention:
either sending the message after a short or long delay.
variables:
x, y
invariants:
x ∈ W AIT
y ∈ W AIT
There is only one event which resolves the contention (in one shot) by assigning
different values to x and y. This only specifies that the problem is to be resolved
but not how.
(abstract_)resolve
when
x = y
then
x, y :| x = y
end
4.3
Attempting Nondeterministic Contention Resolution
We attempt to achieve contention resolution by nondeterminism. We will see
why it fails and see better what is gained by probabilistic reasoning. We refine
Qualitative Probabilistic Modelling in Event-B
305
the abstract model, introducing two new variables, namely u and v, in the refinement. They represent the intermediate states of the two nodes during contention
resolution.
variables:
invariants:
u ∈ W AIT
v ∈ W AIT
x, y, u, v
A new event draw models (nondeterministically) the effect of randomly choosing for both of the two nodes either sending messages after a long or a short
delay. The new event is enabled while the values of u and v are the same. It
draws new values until they are different.
Event resolve has an additional guard u = v (compared to the initial model
of Section 4.2) indicating that two different delay times u and v have been
successfully drawn. In this case, x and y will be assigned to u and v, respectively,
and the contention is resolved.
draw
when
u = v
then
u :∈ W AIT
v :∈ W AIT
end
(concrete_)resolve
when
u = v
x = y
then
x, y := u, v
end
The concrete event resolve refines the abstract event resolve because the concrete event contains the guard u = v. We obtain the following proof obligation,
see (15), that is trivially discharged:
x = u
y = v
u = v
x = y
.
Failure of Demonic Nondeterminism. We are left to prove that the new
event draw does not take control of the system forever. However, we cannot state
a variant that would satisfy proof obligation (17). The problem is that the new
event draw may behave like skip, doing nothing: the new event draw can be
always enabled: the nondeterministic choice in event draw can always set u and
v to their old values leaving draw always enabled. Using nondeterminism, we
stuck and the termination property of the protocol cannot be proved.
306
4.4
S. Hallerstede and T.S. Hoang
Probabilistic Contention Resolution
Probabilistic choice (18) is appropriate to model contention resolution and prove
(almost-certain) termination of the protocol, thus, fully solving the problem of
contention. Using probabilistic choice, we can model the event draw as follows:
draw
when
u=v
then
u ⊕| u ∈ W AIT
v ⊕| v ∈ W AIT
end
The meaning of the new event draw is that u and v are chosen from the set
W AIT probabilistically. The choices must be proper (see [18]), in other words,
the probability should not be 0 or 1.
Based on the probabilistic draw, we can prove that the event draw converges
almost-certainly. According to Section 3.1, we have to show (19), (20), and (21).
We take as variant the embedded predicate u = v , where P is defined to
have value 1 if P holds and 0 if P does not hold. A suitable upper bound is the
constant 1.
variant:
bound:
u=v
1
For (21) there is nothing to prove. The proof that the variant is dominated
by the bound (20) follows from the definition of the embedded predicate above:
...
u=v ≤1
.
Finally, one has to prove (probabilistic) progress (19). This is where nondeterminism failed: we were not able to prove progress by means of (17). We have
to prove that event draw may decrease the variant u = v :
u ∈ W AIT
v ∈ W AIT
u = v
∃u , v · u ∈ W AIT ∧ v ∈ W AIT ∧
u = v < u = v
.
This is easy: we instantiate u to short and v to long, yielding for the left hand
side of the inequation
u = v
=
long = short
= 0
Qualitative Probabilistic Modelling in Event-B
307
by definition of the embedded predicate. Also, from u = v, we infer for the right
hand side
u=v
= 1 .
Hence, the claim follows from