Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Academia.eduAcademia.edu

Probabilistic timed behavior trees

2007, … of the 6th international conference on …

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