9th International Workshop on Rewriting Logic and its Applications
WRLA 2012
Tallinn, Estonia, 24–25 March 2012
Pre-Proceedings
9th International Workshop on Rewriting Logic and its Applications
WRLA 2012 Tallinn, Estonia, 24–25 March 2012
Pre-Proceedings
Institute of Cybernetics at Tallinn University of Technology Tallinn ◦ 2012
9th International Workshop on Rewriting Logic and its Applications WRLA 2012 Tallinn, Estonia, 24–25 March 2012 Pre-Proceedings Edited by Francisco Dur´an
Institute of Cybernetics at Tallinn University of Technology Akadeemia tee 21, 12618 Tallinn, Estonia http://www.ioc.ee/
The final proceedings of WRLA 2012 will appear in Springer’s Lect. Notes in Comput. Sci. (LNCS).
c 2012 the editors and authors
Preface This volume contains the proceedings of the Ninth International Workshop on Rewriting Logic and its Applications (WRLA 2012) that was held in Tallinn, Estonia, on March 24–25, 2012, as a satellite workshop of the European Joint Conferences on Theory and Practice of Software (ETAPS 2012). Rewriting logic is a natural semantic framework for representing concurrency, parallelism, communication and interaction, as well as being an expressive (meta)logical framework for representing logics. It can then be used for specifying a wide range of systems and programming languages in various application fields. In recent years, several executable specification languages based on rewriting logic (ASF+SDF, CafeOBJ, ELAN, Maude) have been designed and implemented. The aim of the WRLA workshop series is to bring together researchers with a common interest in rewriting logic and its applications, and to give them the opportunity to present their recent works, discuss future research directions, and exchange ideas. Previous WRLA workshops were held in Asilomar (1996), Pont-`a-Mousson (1998), Kanazawa (2000), Pisa (2002), Barcelona (2004), Vienna (2006), Budapest (2008), and Paphos (2010). Workshop proceedings have been published in Elsevier’s Electronic Notes in Theoretical Computer Science (ENTCS) series since its inception in 1996 until 2010, moving to Springer’s Lecture Notes in Computer Science (LNCS) for that edition. In addition, selected papers from WRLA 1996 have been published in a special issue of Theoretical Computer Science, selected papers from WRLA 2004 appeared in a special issue of HigherOrder and Symbolic Computation, and a special issue in the Journal of Logic and Algebraic Programming is currently under preparation for extended versions of selected papers of WRLA 2010. WRLA 2012 will count with Saddek Bensalem as invited speaker. The program of the workshop, including regular papers and papers presenting work in progress, each of which was reviewed by four reviewers, will be completed with invited talks from Santiago Escobar, Mark Hills, Grigore Rosu, and Martin Wirsing. I would like to thank the authors who submitted their work to WRLA 2012 and who, through their contributions, made this workshop a high-quality event. I would also like to thank the program committee members and the external reviewers for their timely and insightful reviews as well as for their involvement in the post-reviewing discussions. I am also grateful to my friends who provided me with all kinds of help and useful advice, to the invited speakers, to the WRLA steering committee for their work in getting the proceedings published in Springers LNCS series. I also thank Andrei Voronkov for the excellent EasyChair conference system.
February 7, 2012 M´ alaga
Francisco Dur´an
iii
Program Committee Emilie Balland Artur Boronat Roberto Bruni Manuel Clavel Grit Denker Francisco Dur´ an Steven Eker Santiago Escobar Kokichi Futatsugi Alexander Knapp Dorel Lucanu Salvador Lucas Narciso Mart´ı-Oliet Jos´e Meseguer Ugo Montanari Pierre-Etienne Moreau Kazuhiro Ogata Miguel Palomino Grigore Rosu Vlad Rusu Carolyn Talcott Mark Van Den Brand Martin Wirsing Peter Csaba Ølveczky
UHP-LORIA University of Leicester Dipartimento di Informatica, Universita’ di Pisa Universidad Complutense de Madrid SRI International University of M´alaga SRI International Technical University of Valencia JAIST Universit¨at Augsburg Alexandru Ioan Cuza University Universidad Polit´ecnica de Valencia Universidad Complutense de Madrid University of Illinois at Urbana-Champaign Dipartimento di Informatica - Universita’ di Pisa INRIA-LORIA Nancy JAIST Universidad Complutense de Madrid University of Illinois at Urbana-Champaign Inria SRI International TU/e Ludwig-Maximilians-Universitaet Muenchen University of Oslo
iv
Additional Reviewers
A Abraham, Erika Arusoaie, Andrei B Bach, Jean-Christophe Brauner, Paul E Ellison, Chucky F Fantechi, Alessandro K Kuiper, Ruurd L Lluch Lafuente, Alberto M Meredith, Patrick P Prugniel, Francois V Vandin, Andrea W Wijs, Anton
v
vi
Table of Contents Rigorous Component-based System Design . . . . . . . . . . . . . . . . . . . . . . . . . . . Saddek Bensalem, Ananda Basu, Marius Bozga and Joseph Sifakis
1
Narrowing in Rewriting Logic and applications . . . . . . . . . . . . . . . . . . . . . . . Santiago Escobar
7
Analyzing PHP Source Code Using Rascal - a Rewriting Logic Perspective Mark Hills, Paul Klint and Jurgen Vinju
8
The K Framework Distilled . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dorel Lucanu and Grigore Rosu
9
Design and Analysis of Cloud-Based Architectures with KLAIM and Maude . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Martin Wirsing, Jonas Eckhardt, Tobias Muhlbauer and Jose Meseguer
10
Making Maude Definitions more Interactive . . . . . . . . . . . . . . . . . . . . . . . . . . Andrei Arusoaie, Traian Serbanuta, Chucky Ellison and Grigore Rosu
11
Bounded Model Checking of Recursive Programs with Pointers in K . . . . . Irina Mariuca Asavoae, Frank De Boer, Marcello M. Bonsangue, Dorel Lucanu and Jurriaan Rot
26
Model Checking LTLR Formulas under Localized Fairness . . . . . . . . . . . . . . Kyungmin Bae and Jose Meseguer
29
Modelling and Analyzing Adaptive Self-Assembling Strategies with Maude Roberto Bruni, Andrea Corradini, Alberto Lluch Lafuente, Fabio Gadducci and Andrea Vandin
48
Some Like It Very Hot: Formal Modeling and Analysis of Extreme Heat Exposure to the Human Body in HI-Maude . . . . . . . . . . . . . . . . . . . . . . . . . . Muhammad Fadlisyah, Peter Olveczky and Erika Abraham
68
Order-Sorted Equality Enrichments Modulo Axioms . . . . . . . . . . . . . . . . . . . Ra´ ul Guti´errez, Jos´e Meseguer and Camilo Rocha
69
Timed CTL Model Checking in Real-Time Maude . . . . . . . . . . . . . . . . . . . . Daniela Lepri, Peter Olveczky and Erika Abraham
89
State Space c-Reductions of Concurrent Systems in Rewriting Logic . . . . . 185 Alberto Lluch Lafuente, Jose Meseguer and Andrea Vandin Specifying and Analyzing the Kademlia Protocol in Maude . . . . . . . . . . . . . 128 Isabel Pita and Adrian Riesco Using narrowing to test Maude specifications . . . . . . . . . . . . . . . . . . . . . . . . . 144 Adrian Riesco vii
A Rule-Based Framework for Building Superposition-Based Decision Procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Elena Tushkanova, Alain Giorgetti, Christophe Ringeissen and Olga Kouchnarenko Facilitating the Transformation of State Machines from Equations into Rewrite Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183 Min Zhang and Kazuhiro Ogata
viii
Rigorous Component-based System Design Saddek Bensalem1,2 , Ananda Basu1 , Marius Bozga1 , Paraskevas Bourgos1 , and Joseph Sifakis1 1
VERIMAG Laboratory, Universit´e Joseph Fourier Grenoble, CNRS 2 CEA-Leti, MINATEC Campus, Grenoble France
Abstract. Rigorous system design requires the use of a single powerful component framework allowing the representation of the designed system at different levels of detail, from application software to its implementation. This is essential for ensuring the overall coherency and correctness. The paper introduces a rigorous design flow based on the BIP (Behavior, Interaction, Priority) component framework [1]. This design flow relies on several, tool-supported, source-to-source transformations allowing to progressively and correctly transform high level application software towards efficient implementations for specific platforms.
1
Introduction
Traditional engineering disciplines such as civil or mechanical engineering are based on solid theory for building artefacts with predictable behaviour over their life-time. These follow laws established by simple Newtonian physics and recognized building codes and regulations. Their complexity is limited by these physical and normative factors. In contrast, for systems engineering, we do not have an equivalent theoretical basis allowing to infer system properties from the properties of its components. Computer science provides only partial answers to particular system design problems. With few exceptions, in this domain predictability is impossible to guarantee at design time and therefore, a posteriori validation remains the only means for ensuring their correct operation over time. The complexity of systems currently being built, the fast pace of technological innovation, and the harsh market conditions to which they are subjected, including in particular time-to-market, create many difficulties for system design. These difficulties can be traced in large part to our inability to predict the behaviour of an application s oftware running on a given platform. Usually, such systems are built by reusing and assembling components: simpler sub-systems. his is the only way to master the complexity and to ensure the correctness of the overall design, while maintaining or increasing productivity. However, system-level integration becomes extremely hard because components are usually highly heterogeneous: and have different characteristics, are often developed using different technologies, and highlight different features from different viewpoints. Other difficulties stem from current design approaches, often empirical and based on expertise and experience of design teams. Naturally, designers attempt to solve new problems
2
S. Bensalem, A. Basu, M. Bozga, P. Bourgos, J. Sifakis
by reusing, extending and improving past solutions proven to be efficient and robust. This favors component reuse and avoids re-inventing and re-discovering design solutions every time. Nevertheless, on a l onger term perspective, it may also be counter-productive: people are not always able to adapt in a satisfactory manner to new requirements and moreover, they tend to reject better solutions simply because they do not fit their design know-how.
2
System design
System design is facing several difficulties, mainly due to our inability to predict the behavior of an application software running on a given platform. Usually, systems are built by reusing and assembling components that are, simpler subsystems. This is the only way to master complexity and to ensure correctness of the overall design, while maintaining or increasing productivity. However, system level integration becomes extremely hard because components are usually highly heterogeneous: they have different characteristics, are often developed using different technologies, and highlight different features from different viewpoints. Other difficulties stem from current design approaches, often empirical and based on expertise and experience of design teams. Naturally, designers attempt to solve new problems by reusing, extending and improving existing solutions proven to be efficient and robust. This favors component reuse and avoids re-inventing and re-discovering designs. Nevertheless, on a longer term perspective, this may also be counter-productive: designers are not always able to adapt in a satisfactory manner to new requirements. Moreover, they a priori exclude better solutions simply because they do not fit their know-how. System design is the process leading to a mixed software/hardware system meeting given specifications. It involves the development of application software taking into account features of an execution platform. The latter is defined by its architecture involving a set of processors equipped with hardware-dependent software such as operating systems as well as primitives for coordination of the computation and interaction with the external environment. System design radically differs from pure software design in that it should take into account not only functional but also extra-functional specifications regarding the use of resources of the execution platform such as time, memory and energy. Meeting extra-functional specifications is essential for the design of embedded systems. It requires evaluation of the impact of design choices on the overall behavior of the system. It also implies a deep understanding of the interaction between application software and the underlying execution platform. We currently lack approaches for modelling mixed hardware/software systems. There are no rigorous techniques for deriving global models of a given system from models of its application software and its execution platform. A system design flow consists of steps starting from specifications and leading to an implementation on a given execution platform. It involves the use of methods and tools for progressively deriving the implementation by making adequate design choices.
Rigorous Component-based System Design
3
We consider that a system design flow must meet the following essential requirements: – Correctness: This means that the designed system meets its specifications. Ensuring correctness requires that the design flow relies on models with welldefined semantics. The models should consistently encompass system description at different levels of abstraction from application software to its implementation. Correctness can be achieved by application of verification techniques. It is desirable that if some specifications are met at some step of the design flow, they are preserved in all the subsequent steps. – Productivity: This can be achieved by system design flows – providing high level domain-specific languages for ease of expression – allowing reuse of components and the development of component-based solutions – integrating tools for programming, validation and code generation – Performance: The design flow must allow the satisfaction of extra-functional properties regarding optimal resource management. This means that resources such as memory, time and energy are first class concepts encompassed by formal models. Moreover, it should be possible to analyze and evaluate efficiency in using resources as early as possible along the design flow. Unfortunately, most of the widely used modeling formalisms offer only syntactic sugar for expressing timing constraints and scheduling policies. Lack of adequate semantic models does not allow consistency checking for timing requirements, or meaningful composition of features. – Parcimony: The design flow should not enforce any particular programming or execution model. Very often system designers privilege specific programming models or implementation principles that a priori exclude efficient solutions. They program in low level languages that do not help discover parallelism or non determinism and enforce strictly sequential execution. For instance, programming multimedia applications in plain C may lead to designs obscuring the inherent functional parallelism and involving built-in scheduling mechanisms that are not optimal. It is essential that designers use adequate programming models. Furthermore, design choices should be driven only by system specifications to obtain the best possible implementation.
3
Rigorous design flow
We call rigorous a design flow which allows guaranteeing essential properties of the specifications. Most of the rigorous design flows privilege a unique programming model together with an associated compilation chain adapted for a given execution model. For example, synchronous system design relies on synchronous programming models and usually targets hardware or sequential implementations on single processors [2]. Alternatively, real-time programming based on scheduling theory for periodic tasks, targets dedicated real-time multitasking platforms [3].
4
S. Bensalem, A. Basu, M. Bozga, P. Bourgos, J. Sifakis
A rigorous design flow should be characterized by the following: – It should be model-based, that is all the software and system descriptions used along the design flow should be based on a single semantic model. This is essential for maintaining the overall coherency of the flow by guaranteeing that a description at step n meets essential properties of a description at step n − 1. This means in particular that the semantic model is expressive enough to directly encompasses various types of component heterogeneity arising along the design flow [4]: – Heterogeneity of computation: The semantic model should encompass both synchronous and asynchronous computation by using adequate coordination mechanisms. This should allow in particular, modeling mixed hardware/software systems. – Heterogeneity of interaction: The semantic model should enable natural and direct description of various mechanisms used to coordinate execution of components including semaphores, rendezvous, broadcast, method call, etc. – Heterogeneity of abstraction: The semantic model should support the description of a system at different abstraction levels from its application software to its implementation. This makes possible the definition of a clear correspondence between the description of an untimed platform-independent behavior and the corresponding timed and platform-dependent implementation. – It should be component-based, that is it provides primitives for building composite components as the composition of simpler components. Existing theoretical frameworks for composition are based on a single operator e.g., product of automata, function call. Poor expressiveness of these frameworks may lead to complicated designs: achieving a given coordination between components often requires additional components to manage their interaction. For instance, if the composition is by strong synchronization (rendezvous) modelling broadcast requires an extra component to choose amongst the possible strong synchronizations a maximal one. We need frameworks providing families of composition operators for natural and direct description of coordination mechanisms such as protocols, schedulers and buses. – It should rely on tractable theory for guaranteeing correctness by construction to avoid as much as possible monolithic a posteriori verification. Such a theory is based on two types of rules: – Compositionality rules for inferring global properties of composite components from the properties of composed components e.g. if a set of components are deadlock-free then for a certain type of composition the obtained composite components is deadlock-free too. A special and very useful case of compositionality is when a behavioral equivalence relation between components is a congruence [5]. In that case, substituting a component in a system model by a behaviorally equivalent component leads to an equivalent model. – Composability rules ensuring that essential properties of a component are preserved when it is used to build composite components.
Rigorous Component-based System Design
4
5
The BIP Design Flow
BIP [1] (Behavior, Interaction, Priority) is a general framework encompassing rigorous design. It uses the BIP language and an associated toolset supporting the design flow. The BIP language is a notation which allows building complex systems by coordinating the behaviour of a set of atomic components. Behavior is described as a Petri net extended with data and functions described in C. The transitions of the Petri are labelled with guards (conditions on the state of a component and its environment) as well as functions that describe computations on local data. The description of coordination between components is layered. The first layer describes the interactions between components. The second layer describes dynamic priorities between the interactions and is used to express scheduling policies. The combination of interactions and priorities characterizes the overall architecture of a component. It confers BIP strong expressiveness that cannot be matched by other languages [6]. BIP has clean operational semantics that describe the behaviour of a composite component as the composition of the behaviors of its atomic components. This allows a direct relation between the underlying semantic model (transition systems) and its implementation.
Application Software
Mapping
translation(1) correctness(2) Application Software Model BIP D−Finder
Abstract System Model
Hardware Architecture translation
Hardware Architecture model Model BIP transformation(3)
transformation(5) Concrete System Model
BIP
model transformation
BIP
execution & calibration
code generation(6) Application
Instrumented System Model BIP
performance analysis(4) Simulation, Statistical Model Checking
Functional Code
Mapping
Glue Code
111111111 000000000 Runtime
Platform (MPARM)
Fig. 1. BIP Design Flow for Manycore
The BIP design flow uses a single language to ensure consistency between the different design steps. This is mainly achieved by applying source-to-source transformations between refined system models. These transformations are proven correct-by-construction, that means, they preserve observational equivalence and
6
S. Bensalem, A. Basu, M. Bozga, P. Bourgos, J. Sifakis
consequently essential safety properties. The design flow involves several distinct steps, as illustrated in figure 1: 1. The translation of the application software into a BIP model. This allows its representation in a rigorous semantic framework. Translations for several programming models (including synchronous, data-flow and event-driven) into BIP are already implemented. 2. Correctness checking of the functional aspects of the application software. Functional verification needs to be done only at high level models since safety properties and deadlock-freedom are preserved by different transformations applied along the design flow. To avoid inherent complexity limitations, the verification method rely on compositionality and incremental techniques. 3. The generation of an abstract system model from the BIP model representing the application software, a model of the target execution platform as well as a mapping of the atomic components of the application software model into processing elements of the platform. The obtained model takes into account hardware architecture constraints and execution times of atomic actions. Architecture constraints include mutual exclusion induced from sharing physical resources such as buses, memories and processors as well as scheduling policies seeking optimal use of these resources. 4. Performance analysis on the system model using simulation-based models combined with statistical model checking. 5. The generation of a concrete system model obtained from the abstract model by expressing high level coordination mechanisms e.g., interactions and priorities by using primitives of the execution platform. This transformation involves the replacement of atomic multiparty interactions and/or dynamic priorities by protocols using asynchronous message passing (send/receive primitives) and arbiters ensuring. These transformations are proved correctby-construction as well. 6. The generation of platform dependent code, inluding both functional and glue code needed to deploy and run the application on the target multicore. In particular, components mapped on the same core can be statically composed thus avoiding extra overhead for (local) coordination at runtime.
References 1. A. Basu, M. Bozga, and J. Sifakis. Modeling Heterogeneous Real-time Systems in BIP. In Software Engineering and Formal Methods SEFM’06 Proceedings, pages 3–12. IEEE Computer Society Press, 2006. 2. N. Halbwachs. Synchronous Programming of Reactive Systems. Kluwer Academic Publishers, 1993. 3. A. Burns and A. Welling. Real-Time Systems and Programming Languages. Addison-Wesley, 2001. 3rd edition. 4. T. Henzinger and J. Sifakis. The Embedded Systems Design Challenge. In Formal Methods FM’06 Proceedings, volume 4085 of LNCS, pages 1–15. Springer, 2006. 5. R. Milner. A Calculus of Communication Systems, volume 92 of LNCS. Springer, 1980. 6. S. Bliudze and J. Sifakis. A Notion of Glue Expressiveness for Component-Based Systems. In CONCUR’08, volume 5201 of LNCS, pages 508–522. Springer, 2008.
Narrowing in Rewriting Logic and Applications* Santiago Escobar1 1
Universitat Politècnica de València
Abstract: Narrowing was originally introduced to solve equational E-unification problems. It has also been recognized as a key mechanism to unify functional and logic programming. In both cases, narrowing supports equational reasoning and assumes confluent equations. Narrowing has also been generalized to support rewrite theories, where each rewrite theory includes an equational theory and a collection of rules with no restrictions. Such rewrite theories axiomatize concurrent systems, whose states are equivalence classes of terms modulo the equations, and whose transitions are specified by the rules. In the context of rewrite theories, narrowing is generalized to perform a much wider range of analysis techniques: from an equational reasoning technique to symbolic reachability analysis and symbolic model checking of temporal formulas, and also to support a much wider range of applications: from programming languages and E-unification to security protocol verification and theorem proving. In this talk, we present the current use of narrowing in rewriting logic and Maude and motivate its applications to different areas.
* This work has been partially supported by the EU (FEDER) and the Spanish MEC/MICINN under grant TIN 2010-21062-C02-02, and by Generalitat Valenciana PROMETEO2011/052.
Analyzing PHP Source Code Using Rascal - a Rewriting Logic Perspective Mark Hills1,2 , Paul Klint1,2 , and Jurgen J. Vinju1,2 1
Centrum Wiskunde & Informatica, Amsterdam, The Netherlands 2 INRIA Lille Nord Europe, France
Abstract. Rascal is a meta programming language that enables rapid construction of tools for source code analysis and source code transformation. In this paper we explain the design and implementation of a Rascal solution to the static analysis of PHP code. By doing type and alias analysis, the tool detects possible errors in PHP4 code running on the PHP5 runtime, including errors caused by a change in the object-passing semantics. We speculate how a similar tool could have been implemented using rewriting logic in Maude. This discussion bridges communities by mapping not only terms and concepts, but also solution patterns. Our conclusion is that Rascal and Maude do share common ground, but that they are also complementary.
The K Framework Distilled Dorel Lucanu1 and Grigore Rosu2 1 2
Alexandru Ioan Cuza University, Rumania, University of Illinois at Urbana-Champaign
Abstract. K is a rewrite-based executable semantic framework in which programming languages, type systems and formal analysis tools can be defined using configurations, computations and rules. Configurations organize the state in units called cells, which are labeled and can be nested. Computations carry computational meaning as special nested list structures sequentializing computational tasks, such as fragments of program. Computations extend the original language abstract syntax. K (rewrite) rules make it explicit which parts of the term they read-only, write-only, read-write, or do not care about. This makes K suitable for defining truly concurrent languages even in the presence of sharing. Computations are like any other terms in a rewriting environment: they can be matched, moved from one place to another, modified, or deleted. This makes K suitable for defining control-intensive features such as abrupt termination, exceptions or call/cc. This talk will give an overview of the K framework and discuss its current implementation.
Design and Analysis of Cloud-Based Architectures with KLAIM and Maude? Jonas Eckhardt 1
1,2,3
Martin Wirsing1,5 , , Tobias M¨ uhlbauer1,2,3 , Jos´e Meseguer4
Ludwig-Maximilians-Universit¨ at M¨ unchen, 2 Technische Universit¨ at M¨ unchen, 3 Universit¨ at Augsburg, 4 University of Illinois at Urbana-Champaign, 5 IMDEA Software
Abstract. Cloud computing is a modern paradigm for offering and utilizing distributed infrastructure resources in a dynamic way. Cloud-based systems are safety- and security-critical systems; they need to satisfy time-critical performance-based quality of service properties and to dynamically adapt to changes in the potentially hostile and uncertain environment they operate in. These aspects make distributed Cloud-based systems complex and hard to design, build, test, and verify. In this paper we propose the coordination language KLAIM for modelling cloud-based architectures whereas for formally analysing such architectures we use a rewritingbased approach. KLAIM is a process algebrabased formalism for designing distributed applications with (object-oriented) mobile code. It supports explicit localities and multiple tuple spaces and permits exchanging data and processes and retrieving information over the net. As examples for the design of cloud-based architectures in KLAIM we present a simple (Fibonacci-) server consumer application, a load balancing algorithm, a mutual exclusion algorithm and a defense mechanism against denial-of-service attacks. For analysing KLAIM specifications we specify KLAIM in object-oriented Maude and then show how to realize distributed KLAIM programs by providing multiple instances of Maude which communicate via sockets. Then we use the Maude system, the Maude LTL modelchecker and the statistical model checker PVeStA for simulating the cloud computing examples and for verifying appropriate correctness properties. Key words: Cloud computing, rewriting logic, Maude, coordination language, KLAIM, LTL model checking, statistical model checking
?
This work has been partially sponsored by the Software Engineering Elite Graduate Program, the EU-funded projects FP7-257414 ASCENS and FP7-256980 NESSoS, and AFOSR Grant FA8750-11-2-0084. The fourth author was also partially supported by the “Programa de Apoyo a la Investigaci´ on y Desarrollo” (PAID-02-11) of the Universitat Polit`ecnica de Val`encia.
Making Maude Definitions more Interactive Andrei Arusoaie1 , Traian Florin S, erbănut, ă1,2 , Chucky Ellison2 , and Grigore Ros, u2 University Alexandru Ioan Cuza of Ias, i {andrei.arusoaie,traian.serbanuta}@info.uaic.ro 2 University of Illinois at Urbana-Champaign {tserban2,celliso2,grosu}@illinois.edu 1
Abstract. This paper presents an interface for achieving interactive executions of Maude terms by allowing console and file input/output (I/O) operations. This interface consists of a Maude API for I/O operations, a Java-based server offering I/O capabilities, and a communication protocol between the two implemented using the external objects concept and Maude’s TCP sockets. This interface was evaluated as part of the K framework, providing interactive interpreter capabilities for executing and testing programs for multiple language definitions.
1
Introduction
Formal specifications are often used when designing complex systems. The executability aspect of rewriting logic [11], and Maude’s ability to efficiently execute, explore, and analyze rewrite theories [5] offers an additional level of support when designing a new system, as it allows the designer to experiment, test, and revise a specification before deciding to implement it. In certain cases, it even allows for the specification to become the implementation, eliminating the need of building another executable model. However, many systems include a human component, who is allowed/required to provide input to the system for directing its evolution. To handle interaction, Maude provides the read-eval-print loop in the LOOPMODE standard module, but this allows only for very limited user interaction. Furthermore, according to the Maude manual [4], it “may not be maintained in future versions, because the support for communication with external objects makes it possible to develop more general and flexible solutions for dealing with input/output in future releases.” While Maude’s external objects do allow interaction in principle, they are low-level and cannot be used for generic input/output (I/O) without significant infrastructure external to Maude. Our contribution is to provide this infrastructure and to develop an easy to use interface for it within Maude. Figure 1 presents a high-level view of the I/O interface. It includes a Maude API for I/O, a Java-based server for handling requests, and a protocol for delivering queries and transmitting the responses. Using this interface, potentially any Maude definition can be enhanced with I/O capabilities. A Java wrapper which runs on top of both Maude and the Java server allows for the user to
12
A. Arusoaie, T. F. S, erbănut, ă, C. Ellison and G. Rosu
Java Maude wrapper Maude + I/O
SOCKET
Java I/O Server
Fig. 1. The architecture of the Maude I/O interface
experience interpreter-like behavior: the console in which the program is started is the one interactively displaying the output of the program and requesting input. In addition to console I/O, this new framework also provides support for file I/O, including both sequential and random-access. Moreover, all of these actions are allowed to take place potentially anywhere in the term. The Maude I/O interface and the examples presented in this paper, as well as the Java I/O server are available online [3,2]. Additionally, this interface has been used as part of the K framework tool [1] to obtain interpreter-like behavior for a number of language definitions, including a definition of the C language [8]. The remainder of this paper is structured as follows. Section 2 describes the I/O interface from a user point-of-view and illustrates some usage patterns through examples. Section 3 details the implementation, both for the Maude I/O client and the Java I/O server components. Section 4 reviews related work and Section 5 concludes.
2
The I/O interface
The basic standard I/O interface exposes several I/O commands for the standard input and standard output streams defined in the STANDARD-IO module: op #printString : String → IOResult . op #readInt() : → IOResult . op #eof() : → IOResult .
op #printChar : Char → IOResult . op #readChar() : → IOResult . op #readToken() : → IOResult .
The resulting sort for these directives is “IOResult” which is defined in the “IO-INTERFACE” together with several constructors for it: op op op op
#success : → IOResult . #string : [ String ] → IOResult . #int : Int → IOResult . #char : [Char] → IOResult .
op #ioError : String → IOResult . op #flag : [Bool] → IOResult . op #eof : → IOResult .
#printString sends an entire string, character by character, to the standard output stream and returns #success. #readInt reads a token and returns an #int containing the number read. #eof() tests the standard input stream for the end of file and returns a #flag result with the argument set appropriately. #printChar sends one character to the standard output stream and returns #success. #readChar reads a character from the standard input stream and returns
Making Maude Definitions more Interactive
13
a #char or #eof. Finally, #readToken skips the whitespace from the standard input and then returns a #string containing all characters read until the next whitespace or the end of file is encountered, or #eof if the end of file is reached while skipping over whitespace. In case of an I/O error or a communication error, an #ioError term detailing the error is produced. We will present their formal definition in the next section, but in the meanwhile, let us start with some examples. 2.1
Example 1: A straightforward usage of the I/O interface
Let us begin with an example showing how our I/O interface can be used in a Maude definition. For this we have chosen a very simple expression language, called EXP. The following module defines its syntax: mod EXP−SYNTAX is including INT . including STRING . sort Exp . subsort Int < Exp . op _+_ : Exp Exp →Exp [ditto ] . op _∗_ : Exp Exp → Exp [ ditto ] . endm
op op op op
_ifnz_ : Exp Exp → Exp [strat(2 0)] . nzloop : Exp → Exp [strat (0)] . input : String → Exp . print : String Exp → Exp .
EXP has integers as basic values and extends two of the integer operations: addition and multiplication. Moreover, it provides a guarded expression, ifnz, which evaluates its first argument only if the evaluation of the second one produces a non-zero value, and a fix-point operator, nzloop, which evaluates its argument as long as its value is not zero. Note that in the absence of any side effects, the nzloop construct is rather non-sensical, as its argument would always evaluate to the same value. However, adding I/O constructs to the language allows for some interesting (albeit simple) programs to be written in this language, like, for example: nzloop(print("3∗x=",3 ∗ input("x= (0 to stop)? " )))
The intended meaning of input construct is somehow similar to the INPUT instruction of the BASIC language [6], in that it prompts the string in its argument to the user and expects an integer to be entered, returning that integer. The meaning of print is that it prints the string in the first argument, then prints the string representation of the second argument (which is expected to be evaluated to an integer), and then advances the line feed. With this intuition in mind, the semantics of the program above is that reads a number “x” from the console and computes and displays “3*x” until the number entered is 0 (included). The module in Figure 2 formally defines the semantics described above. Assuming this module is included in a file named io-test.maude (which also loads the io-interface.maude file) and that the Maude command for rewriting (with external objects) the above program is written in a file named io-test-cmd.maude, the following command “executes” the program interactively: java -jar MaudeIO.jar \ --maudeFile io-test.maude \
14
A. Arusoaie, T. F. S, erbănut, ă, C. Ellison and G. Rosu
mod EXP−SEMANTICS is including EXP−SYNTAX . including STANDARD−IO . op read : → Exp . eq print(S,I) = #printString(S + string(I,10) + "\n"); I .
eq input(S) = #printString(S); #readInt(); read . eq nzloop(E) = nzloop(E) ifnz E . eq E ifnz 0 = 0 . eq E ifnz NzI = E . var I : Int . endm
var S : String .
op _;_ : IOResult Exp → Exp [strat (1 0)] . eq #success ; E = E . eq #int(I) ; read = I .
var NzI : NzInt .
var E : Exp .
Fig. 2. A Straight-forward semantics for the EXP language
--moduleName EXP-SEMANTICS \ --commandFile io-test-cmd.maude Here is a possible interaction sequence between the user and the tool: x= (0 to stop)? 5 3*x=15 x= (0 to stop)? 10 3*x=30 x= (0 to stop)? 7 3*x=21 x= (0 to stop)? 0 3*x=0 Maude> ========================================== erewrite in KRUNNER : nzloop(print("3*x=", 3 * input("x= (0 to stop)? "))) . rewrites: 8452 in 59ms cpu (5345ms real) (141321 rewrites/second) result Zero: 0 Maude> Bye.
Allowing I/O operations anywhere in the term/program provides a high degree of flexibility, but at a price. As running multiple I/O commands at the same time creates race conditions, the user has to provide mechanisms to avoid these races. One such example is the “_;_ ” command defined in the semantics above whose only purpose is to ensure that the printing command completes before the next command is executed (enforced by the strategy annotation), resembling the _>>_ sequentialization operator of the Haskell I/O monad [13]. However, parallel I/O commands are still possible in our language, producing potentially undesirable effects. For example, when executing the program print("Hello " ,1) + print("World!",2)
Making Maude Definitions more Interactive
15
a possible result would be the following: HWoerllldo! 2 1 Maude> ========================================== erewrite in KRUNNER : print("Hello ", 1) + print("World!", 2) . rewrites: 1525 in 9ms cpu (23ms real) (160374 rewrites/second) result NzNat: 3
While this may be acceptable behavior, it is also possible to avoid it if not. This can be done by sequentializing the two printing expressions programatically, e.g., by relying on the strategy of ifnz, like “print("World!",2) ifnz print("Hello ",1)”. 2.2
Interaction with Maude’s analysis tools
The definition presented above is very simple, but it can also easily become quite chaotic, due to its very direct use of I/O (through external objects). It is also impossible to test it in the absence of the I/O server. However, it is quite easy to add I/O as a natural extension to specifications which are already amenable for testing, exploration, and analysis. Figure 3 presents an SOS-style rewriting logic semantics [17,12] for the EXP language. To simulate input and output it uses a configuration which, in addition to the program to be evaluated, contains a list of integers for input and a string buffer for output. The small-step semantics is given through the rules for the •_ operation which defines the application of a single computation step in an SOS style. Also note that the semantics of input has changed, by creating separate small steps for the prompt and read operations. Given an input list, this semantics can be tested, explored, and even modelchecked using Maude. Moreover, using the proposed I/O interface, it is quite easy to turn it into an I/O-enabled interpreter. One relatively simple way to achieve this is by adding a special input constant requestInt and an equation for requesting an int when the input list becomes empty: op requestInt : → [ Int ] . rl •{read, nil ,Out} ⇒ {read,requestInt ,Out} .
The reason for allowing requestInt to be in the kind of List {Int} is because we want to catch this state at the top level by making the equation for “* ” not applicable. However, to ensure that requestInt is propagated, we need to declare the variable In' to also be in the kind. Then, we need to add an additional equation at the top to flush the output buffer and perform the actual read: eq ∗{E,requestInt,Out} = ∗ •{(#printString(Out) ; #readInt() ; {E,nil,""})} .
These operations are sequenced using the same idea as in the previous definition; moreover, once an integer is read, it is added to the In list: op _;_ : IOResult State → State [strat (1 0)] . eq #success ; State = State . eq #int(I) ; {E,In,Out} = {E,I In,Out} .
16
A. Arusoaie, T. F. S, erbănut, ă, C. Ellison and G. Rosu
mod EXP−SEMANTICS is including EXP−SYNTAX . including LIST{Int} . including STANDARD−IO . sort State .
op {_,_,_} : Exp List{Int} String → State .
op •_: State State . eq ∗ State = ∗ • State . crl if crl if crl if rl rl rl crl if rl rl rl
op ∗_ : State State . op read : → Exp .
•{E1 ∗ E2,In,Out} ⇒ {E1' ∗ E2,In ', Out'} •{E1,In,Out} ⇒ {E1',In ', Out'} . •{E1 + E2,In,Out} ⇒{E1' + E2,In',Out'} •{E1,In,Out} ⇒ {E1',In ', Out'} . •{print(S,E),In,Out} ⇒ {print(S,E'),In ', Out'} •{E,In,Out} ⇒ {E',In ', Out'} . •{input(S),In,Out} ⇒ {read,In,Out + S} . •{read,I In, Out} ⇒ {I , In, Out} . •{print(S,I ), In,Out} ⇒ {I ,In,Out + S + string(I,10) + "\n"} . •{E2 ifnz E1,In,Out} ⇒ {E2 ifnz E1',In ', Out'} •{E1,In,Out} ⇒ {E1',In ', Out'} . •{E ifnz 0,In,Out} ⇒ {0,In,Out} . •{E ifnz NzI,In,Out} ⇒ {E,In,Out} . •{nzloop(E),In,Out} ⇒ {nzloop(E) ifnz E,In,Out} .
var I : Int . var S : String . var NzI : NzInt . var E E1 E2 E' E1' E2' : Exp . var In In' : List {Int} . var Out Out' : String . var State : State . endm Fig. 3. An SOS-like semantics for EXP in Maude
Finally, we might want to add an additional equation to flush the output buffer at the end of the execution: eq ∗ •{I,In,Out} = #printString(Out) ; {I,In,""} .
Since in this particular example the communication with the I/O server is enforced to occur at the top of the term, this semantics guarantees the sequencing of the print statements above, producing a reasonable output: Hello 1 World!2 Maude> ========================================== erewrite in KRUNNER : * {print("Hello ", 1) + print("World!", 2),nil,""} . rewrites: 1455 in 12ms cpu (51ms real) (114738 rewrites/second) result State: {3,nil,""}
Moreover, if we exclude the final equation from this semantics (e.g., by putting it in its own separate module which is only used for I/O interpretation) the modified semantics still has all the good properties of the non-I/O definition. That is, if provided with enough input in the initial configuration, the list will
Making Maude Definitions more Interactive
17
not become empty during the rewrite/search/model-checking process and thus the I/O-blocking communication commands will not impede the analysis process. Note: As the I/O operations rely on external objects, they cannot be executed as part of the rewriting process for verifying a rewriting condition. Therefore in definitions using conditional rewriting, like the one presented above, the I/O request must be pushed outside of the condition context before it can be handled (we did that above by using the requestInt construct). 2.3
The File I/O Interface
As detailed in the next section, the simple I/O interface exhibited above is implemented in terms of a file I/O interface, defined by the IO-INTERFACE module, which provides file-handle-parameterized versions of its basic I/O commands: op #fPrintString : Nat String → IOResult . op #fPrintChar : Nat Char → IOResult . op #fReadInt : Nat → IOResult . op #fReadChar : Nat →IOResult . op #fEof : Nat → IOResult . op #fReadToken : Nat →IOResult .
In addition to those, it also provides commands for opening and closing files, op #open : String → IOResult . op #reopen : Nat String → IOResult . op #close : Nat → IOResult .
— opens a file , mapping it to a #handle — maps a different file to the #handle — closes the file mapped to the #handle
as well as several lower-level commands for accessing the contents of a file: op #fReadByte : Nat →IOResult . op #fPutByte : Nat Nat →IOResult . op #fPeekByte : Nat → IOResult .
op #flush : Nat → IOResult . op #tell : Nat → IOResult . op #seek : Nat Nat → IOResult .
As a simple example of how this more advanced interface could be used, let us provide an addition to the I/O rules above, which would allow specifying the input file in the initial configuration. Thus, if an input file is specified, it would be used instead of the standard input stream whenever the input list becomes empty. To achieve this we introduce a new construct, stream, a rewriting rule, and an equation. stream holds a file handle and acts as a potential marker in the input list to signal where input should be read from. The first rule signals a request for reading from the file stream, while the second one actually performs the read operation. op stream : IOResult → List {Int} . rl •{read,stream(#handle(N)),Out} ⇒ {read,requestInt stream(#handle(N)),Out + S} . eq ∗{E,requestInt stream(#handle(N)),Out} = ∗ .(#printString(Out) ; #fReadInt(N) ; {E,stream(#handle(N)),""}) .
With only this addition, the program behaves as follows. As long as there is any integer in the input list, the execution proceeds as without any I/O. When the
18
A. Arusoaie, T. F. S, erbănut, ă, C. Ellison and G. Rosu
list contains no more integers, there are two options: (1) if the list is empty, then input will be requested from the standard input stream; (2) if the list contains a stream term, then input will be read from that stream. For example, assuming the contents of the test.in file are “3 -5 0”, rewriting with the following command: erew * {nzloop(print("3*x=",3 * input("x= (0 to stop)? "))), stream(#open("file:test.in#r")), ""} .
will produce the output: x= (0 to stop)? 3*x=9 x= (0 to stop)? 3*x=-15 x= (0 to stop)? 3*x=0 Maude> ========================================== erewrite in KRUNNER : * {nzloop(print("3*x=", 3 * input("x= (0 to stop)? "))), stream(#open("file:test.in#r")),""} . rewrites: 6311 in 39ms cpu (63ms real) (159962 rewrites/second) result State: {0,stream(#handle(3)),""} Maude> Bye.
The argument of #open contains the usual URI description of a file location before the “#” symbol, while the “r” after the symbol specifies that the file should be opened for read-only access. 2.4
Separating the I/O server from Maude
The common usage pattern for the I/O interface presented above is that both Maude and the Java I/O Server are executed as subprocesses of the same Java wrapper application. This way, users interact directly with the console they used to start the execution of the program. Moreover, as this close integration uses a fresh TCP port for communication, this allows multiple instances of Maude using I/O to be running at the same time. Unfortunately this hides the Maude console and inhibits the user from interacting with Maude directly. As sometimes it might be useful to have both the I/O console and the Maude console available, let us describe how this can be achieved. First, one needs to fix the port on which communication takes place. To do so, it needs to add an equation of the form “eq #TCPPORT = 8001 .” either in the definition using the I/O interface, or right after the definition of the #TCPPORT constant in the tcp-interface.maude file (if this behavior is desired for all definitions). Then, the server must be started first in a console taking as parameter the same port number: java -jar ioserver.jar 8001 Once the server is running, the definition can be loaded into Maude in a separate console. Now we have two consoles, communicating between them. The rewriting commands can be given using the normal Maude console and the Maude result will be displayed here, while the I/O messages will be displayed in the console running the I/O server and I/O input will be requested from there.
Making Maude Definitions more Interactive
3
19
Implementation
This section comes to give additional details for the implementation of the I/O interface described in the prior sections. As hinted in the introduction and depicted in Figure 1, both the I/O Server and Maude are wrapped by a Java process which is intended to offer to the user the console he expects when a program is executed. The wrapper hides some operations that a casual user would not care about. This wrapper is executed as a normal Java jar, taking as arguments the file containing the Maude definition, the name of the main module, and the file containing the rewrite command to be executed, as exhibited in Section 2.1. The main purpose of this wrapper is to automatically setup Maude and the I/O Server. An unused TCP port p is identified and an equation: eq #TCPPORT = p .
is added automatically in a module KRUNNER, which includes the main module of the definition. The wrapper also sets up the port number for the I/O Server which is then started before Maude is launched and the files containing the modified definition and the rewriting command are loaded. 3.1
The Maude I/O client
STANDARD-IO
TCP-CLIENT
#readInt() #printString #eof ...
IO-INTERFACE #fReadToken #fPrintString #fEof #fOpen ...
request: 315#writebyte#1#97# response: 315#success# request: 315#readbyte#0# response: 315#success#97#
#start #toSend #TCPPORT #containedRequest ... SOCKET
#tcpRequest ("readbyte#0#") “97” #tcpRequest ("writebyte#0#97#") “success”
TCP-INTERFACE #tcpRequest #errorTCPSyntax #checkResult #getTCPData ...
Fig. 4. The architecture of the Maude component of the I/O interface
Figure 4 presents the architecture of the Maude component of the I/O interface and briefly describes the interaction between its various sub-components. The
20
A. Arusoaie, T. F. S, erbănut, ă, C. Ellison and G. Rosu
user interacts with it using either the basic, console-only interface provided by the STANDARD-IO module (see Section 2.1 and 2.2), or the more comprehensive, file-based one provided by the IO-INTERFACE module (see Section 2.3). The constructs in the STANDARD-IO module desugar into their correspondents from the IO-INTERFACE module. The IO-INTERFACE module reduces all operations to simple, byte-based requests, and uses the TCP-INTERFACE function #tcpRequest as an interface to the I/O Server. This result of communication is further interpreted by the functions in the IO-INTERFACE module and is transformed into a term of the IOResult sort which contains a series of constructors for each specific type of answers, such as #success, #int, #string, and #eof. As most of the I/O interface was exhibited in the previous section, we will focus here on the implementation details: how the high-level constructs are expressed in terms of the lower level ones and how the communication takes place. The STANDARD-IO module defines handles for the standard input, output, and error streams: ops #stdin #stdout #stderr : → Nat . eq #stdin = 0 . eq #stdout = 1 .
eq #stderr = 2 .
These handles are then used to express the STANDARD-IO constructs in terms of those from the IO-INTERFACE: eq #eof() = (#fEof(#stdin)) . eq #readChar() = (#fReadChar(#stdin)) . eq #printChar(C) = #fPrintChar(#stdout,C) . eq #readToken() = (#fReadToken(#stdin)) . eq #readInt() = #fReadInt(#stdin) . eq #printString(S) = #fPrintString(#stdout,S) .
The IO-INTERFACE module provides functionality for lower level I/O constructs falling the following three categories. The first category consists of I/O primitives whose semantics is simply a request to the server: eq #open(S) = #handle(rat(#tcpRequest("open#" + S + "#"), 10)) . eq #close(N) = #checkSuccess(#tcpRequest("close#" + string(N,10) + "#")) . eq #fReadByte(N) = #byte(rat(#tcpRequest("readbyte#" + string(N,10) + "#"),10)) . ceq #fPutByte(N,B) = #checkSuccess(#tcpRequest( "writebyte#" + string(N,10) + "#" + string(B,10) + "#")) if B < 256 .
These functions rely on functions like #checkSuccess to translate the string answer provided by #tcpRequest into a term of the appropriate IOResult type. Note that these TCP requests have a very regular form, of #-separated pieces of information, among which the first is the command, and the following are additional arguments to the command, like, e.g., “open#file:in.txt#r#”.
Making Maude Definitions more Interactive
21
The second category includes functions that easily desugar into primitives, e.g.: eq #fPrintChar(N,C) = #fPutByte(N,ascii(C)) . eq #fReadChar(N) = #char(#fReadByte(N)) . eq #fReadInt(N) = #int(#fReadToken(N)) . op #char : IOResult → IOResult . eq #char(#byte(B)) = #char(char(B)) . eq #char(#eof) = #eof .
op #int : IOResult → IOResult . eq #int(#string(S)) = #int(rat(S,10)) . eq #int(#eof) = #eof .
Finally, there are the more involved functions like #fPrintString which iterates over the characters of a string one by one, waiting for the printing of a character to succeed before printing the next and flushing the output buffer at the end, eq #fPrintString(N,"") = #flush(N) . eq #fPrintString(N,S) = #fPrintString(N,S, #fPrintChar(N,substr(S,0,1))) [owise] . op #fPrintString : Nat String IOResult → IOResult . eq #fPrintString(N,S,#success) = #fPrintString(N,substr(S,1,length(S))) .
or like #fReadToken which reads character by character from the file specified by the handle, skipping over the initial whitespace and then accumulating the characters read until whitespace is again encountered. The TCP-INTERFACE module provides functionality for initializing the communication process and extracting the relevant data once the communication process concludes with a result. The semantics of the #tcpRequest construct is: eq #tcpRequest(S:String) = #tcpRequest(S:String, counter) . op #tcpRequest : String [Nat] → String . eq #tcpRequest(S:String, N:Nat) = #checkResult(#containedRequest(#start(N:Nat) #toSend(S:String))) . #tcpRequest creates a object configuration, wrapped by the #containedRequest construct; this configuration includes a primitive to start the communication with the server and the request to be sent. #checkResult expects the result to be either of the form success#data### or of the form fail#reason### and returns “data” in case of success or an #errorTCPSyntax term otherwise.
The TCP-CLIENT module provides rules for initiating the TCP communication through a socket, sending a message, waiting for a response, and closing the connection. First, a fresh id is generated using Maude’s builtin COUNTER module, and is used to establish a connection with the I/O server using the TCP sockets interface provided by Maude: op #start : → Configuration . op #start : Nat → Configuration .
eq #start = #start(counter) . op cnum : Nat → Oid .
22
A. Arusoaie, T. F. S, erbănut, ă, C. Ellison and G. Rosu
rl #start(N) ⇒ < cnum(N) : Client | state : connecting > createClientTcpSocket(socketManager, cnum(N), "localhost", #TCPPORT) .
The #TCPPORT constant is the one mentioned in Section 2.4, being either set manually if running the I/O server separately from Maude, or automatically by the Java wrapper. Once the initial exchange of messages takes place between Maude and the server, the #toSend message is transformed into a message addressed to the server and the state of the system becomes sending: rl < cnum(N) : Client | state : connected, connectedTo: Server, A > #toSend(S) ⇒ < cnum(N) : Client | state : sending, connectedTo: Server, A > send(Server, cnum(N), (string(N:Nat,10) + "#" + S + "\r\n")) .
Note that the body of the message is prefixed with the number of the client (for logging and debugging reasons) and is appended with the end-of-line markers as a message separator. Thus, the complete message being sent to the server is of the form “23#open#file:in.txt#r#\r\n”. There are additional rules for continuing the dialogue with the server following the TCP protocol, but once the communication has finished, the answer is extracted by the rule below and the header of the message (containing the number identifying the communication) is removed by the #checkAnswer function: rl #containedRequest( < Me : Client | state: finished, ⇒ #checkAnswer(Me, S) .
3.2
answer: S, A >)
The Java I/O server
In this section we discuss the I/O Server architecture and implementation details. While describing the main components, we will motivate our choices regarding their design. The purpose of the I/O Server is to implement a socket-based service for simulating file operations over regular files, standard input, and standard output. So far it has only been used with Maude as a client, but the implementation is rather client-independent. The architecture and data flow of the I/O Server is depicted in Figure 5. The server has two main components: the communication component, which is responsible for receiving/sending messages, and the resource management component, which manages resources (files, stdin, stdout, stderr) and operations on them. In this section, we will refer to them as RequestManager and ResourceManager. Before describing these components, we will briefly explain the behavior and capabilities of the I/O Server. First, the complete list of operations currently accepted by the server is the following: – open - open a new file – reopen - reopen an existent file – close - close a file or stream – seek - seek a particular location – readbyte - read a byte – position - go to a specific location – writebyte - write a byte – peek - peek a byte – flush - flush the buffer – eof - check end of file
Making Maude Definitions more Interactive
RequestManager
23
ResourceManager
invalid request
valid request
request request request
Thread pool Task queue
Create task
...
Threads
response response response
concurrent hashmap
T
T
...
T
ate cre open delete
concurrent hashmap interface
Fig. 5. The data-flow scheme of the I/O server.
The server receives requests, each request carrying one of the commands above, and it answers the requests upon executing the corresponding operation. The requests and answers are formatted as a string which contains data separated by “#”: request: 315#writebyte#1#97# response: 315#success#
The request contains the client id, the operation name followed by the resource id and operation parameters, if any. For instance in the above request the client having the id 315 asks the server to write at the standard out stream the byte corresponding to character “a” (the stdin, stdout and stderr streams have fixed ids 0, 1, and 2, respectively). The I/O Server generates a fresh id (identifying the file handle) as response to the client which requests to “open” a new file. The response usually contains the client id which stands for a weak kind of authentication, the status of the operation and the result of its execution if exists. The RequestManager component uses TCP sockets to provide a reliable point-to-point communication with the client. To be able to handle multiple request concurrently, we use the Thread Pool pattern. For each request, the associated command is analyzed and, if found valid, a task is created and queued for execution. Commands are executed in parallel, each thread being responsible for executing a command and sending the response to the client. The thread pool executor (defined in the ThreadPoolExecutor class) registers commands as members of the abstract class Command which implements the Java Runnable interface, and assigns them to threads as these become available. The second component of the I/O Server handles resources and operations on them. Currently, the ResourceManager can store three types of resources: random access files, standard input, and standard output. It provides operations to add, retrieve, or delete a resource. Some operations, for instance peek, readbyte, seek, and position cannot be applied on the standard output; in such
24
A. Arusoaie, T. F. S, erbănut, ă, C. Ellison and G. Rosu
cases, when operations are not applicable on a specific type of resource, the ResourceManager throws exceptions to the RequestManager, which in turn will send to the client a meaningful failure message. Regarding the implementation, for each resource we have a corresponding class (ResourceInFile, ResourceOutFile, . . . ) which must extend the abstract class Resource. This class contains abstract methods which correspond to commands received by the I/O Server (readbyte(), writebyte(), . . . ). To store the resources we use the ConcurrentHashMap class which has two highly concurrent properties: writing to it locks only a portion of the map and reads can generally occur without locking.
4
Related Work
This paper uses a technology similar to that used for developing Mobile Maude [7], but with a different aim: there sockets communication was used to communicate between different instances of Maude; here we use a similar mechanism to communicate with an external I/O server. The motivation for this work came from our research in programming language design, namely in our efforts to make the implementation of the K semantic framework [1,16] easier to use and experiment with. K [16] is a rewrite-based executable semantic framework specialized for defining programming languages, type systems and formal analysis tools. The K tool [1,18] transforms K definitions into rewriting logic theories which can be executed, explored and analyzed using Maude. So far the K tool has been used to give complete definitions to real languages like C [8] and Scheme [10], along with many educational languages and a novel rewriting-based program verification logic named matching logic [15,14]. The I/O interface described in this paper is an integral part of the K tool and provides I/O capabilities for all K semantics defined using the tool. Most notably, it has been used to extensively test the K definition of C [8] against the gcc torture tests [9].
5
Conclusions and Future Work
We have described a methodology and a system for achieving interactive (file) input/output from within the Maude system. This technology was designed for modeling, in an executable way, runtime interaction needed in a system. It can additionally be used for runtime logging or tracing, and provides an easy way of getting output from a Maude execution. The I/O interface is generic and can easily be used in potentially any Maude definition. The interface itself is reasonably stable, as it has been implemented and extensively used as part of the K framework. This work could serve as a means for experimenting with I/O before the technology is integrated in Maude directly as a special purpose external object. As our interface uses URIs, it should be relatively easy to incorporate support for accessing additional resources such as URLs. Moreover, adding primitives for locking resources would offer a thread-safe mechanism of accessing the resources.
Making Maude Definitions more Interactive
6
25
Acknowledgments
The research presented in this paper was supported in part by the DAK project Contract 161/15.06.2010, SMIS-CSNR 602-12516.
References 1. The K semantic framework website (2010), https://k-framework.googlecode.com 2. The Java I/O server: svn repository with full sources (2011), https://k-framework. googlecode.com/svn/trunk/core/java 3. The Maude I/O interface: svn repository with specification and examples (2011), http://k-framework.googlecode.com/svn/branches/inProgress/core/io 4. Clavel, M., Durán, F., Eker, S., Lincoln, P., Martí-Oliet, N., Meseguer, J., Talcott, C.: Maude Manual (Version 2.6) (January 2011), http://maude.cs.uiuc.edu/ maude2-manual/ 5. Clavel, M., Durán, F., Eker, S., Meseguer, J., Lincoln, P., Martí-Oliet, N., Talcott, C.: All About Maude, A High-Performance Logical Framework, LNCS, vol. 4350. Springer (2007) 6. Coan, J.S.: Basic BASIC: an introduction to computer programming in BASIC language. Hayden Book Co., Rochelle Park, N.J. (1978) 7. Durán, F., Riesco, A., Verdejo, A.: A distributed implementation of Mobile Maude. In: WRLA’06. ENTCS, vol. 176 (4), pp. 113–131 (2007) 8. Ellison, C., Ros, u, G.: An executable formal semantics of C with applications. In: POPL’12. ACM (2012), to appear 9. FSF: C language testsuites: “C-torture” version 4.4.2 (2010), http://gcc.gnu.org/ onlinedocs/gccint/C-Tests.html 10. Meredith, P., Hills, M., Ros, u, G.: An executable rewriting logic semantics of K-Scheme. In: SCHEME’07. pp. 91–103 (2007) 11. Meseguer, J.: Conditional rewriting logic as a unified model of concurrency. Theoretical Computer Science 96(1), 73–155 (1992) 12. Meseguer, J., Braga, C.: Modular rewriting semantics of programming languages. In: AMAST’04. LNCS, vol. 3116, pp. 364–378. Springer (2004) 13. Peyton Jones, S.L., Wadler, P.: Imperative functional programming. In: POPL ’93. pp. 71–84 (1993) 14. Rosu, G., Stefănescu, A.: Matching logic: A new program verification approach. In: ICSE’11 (NIER Track). pp. 868–871 (2011) 15. Ros, u, G., Ellison, C., Schulte, W.: Matching logic: An alternative to Hoare/Floyd logic. In: AMAST’10. LNCS, vol. 6486, pp. 142–162 (2010) 16. Ros, u, G., S, erbănut, ă, T.F.: An overview of the K semantic framework. J. Logic and Algebraic Programming 79(6), 397–434 (2010) 17. Serbănută, T.F., Rosu, G., Meseguer, J.: A rewriting logic approach to operational semantics. Information and Computation 207, 305–340 (2009) 18. S, erbănut, ă, T.F., Ros, u, G.: K-Maude: A rewriting based tool for semantics of programming languages. In: WRLA’09. LNCS, vol. 6381, pp. 104–122 (2010)
Bounded Model Checking of Recursive Programs with Pointers in K Irina M˘ariuca As˘avoae1 , Frank de Boer2,3 , Marcello M. Bonsangue3,2 , Dorel Lucanu1 , Jurriaan Rot3 1
Faculty of Computer Science - Alexandru Ioan Cuza University, Romania 2 Centrum voor Wiskunde en Informatica, The Netherlands 3 LIACS - Leiden University, The Netherlands
The current work proposes a method, and its implementation, for model checking sequential imperative programs with pointers and recursive procedure calls. To achieve this goal, the following development steps are taken: (a) introduce Shylock, an abstract programming language with an improved abstract semantics designed to overcome the problem of unbounded pointer allocation; (b) use the K framework [7] to specify Shylock and its semantics, as such obtaining an interpreter for Shylock and the for-free model checking capabilities available in K via Maude [3]; (c) address the limitations imposed in Shylock’s verification by Maude’s model checker prerequisites by several solutions for defining bounded model checking. In the followings we present in more details and justify the appropriateness of the (a, b, c) steps. (a) Firstly, we introduce Shylock - a simple imperative programming language with pointers and recursive procedures which use local and global variables to store references in the heap. The recursion allows unbounded object allocation, hence the heap size may grow unboundedly making the direct verification of such programs more challenging. We advertise Shylock as a simple but expressive enough language to represent an abstraction for imperative or object oriented programming languages like C or Java. More to the point, we actually promote the abstract interpretation perspective, [2], that advocates applying analysis or verification methods to an abstract, simplified model. The advantage of the abstract model consists in the enhanced effectiveness for verification, or even existence of decidability results in certain cases. Moreover, the verification results obtained on the abstract model automatically have concrete interpretation, based on the relation between the real/concrete programming language and the abstract one. To show the relevance of Shylock, we plan to apply meta-programming techniques for generating suitable Shylock abstract models for C and Java programs. The definition of the abstract operators in abstract interpretation is, in our settings, tantamount to giving semantics for Shylock. We propose an abstract semantics which introduces a novel mechanism for managing the object identities in the heap. This mechanism resides in a combination of memory reuse upon generation of fresh object identities combined with a renaming scheme to resolve possible resulting clashes. The memory reuse allows the allocation of any object identity which is unreachable in the context of the current procedure but not necessarily in the context of pending local environments on the stack. The renaming scheme resolves possible resulting name clashes upon changing the context, i.e., upon procedure call/return. The proposed mechanism
Bounded Model Checking of Recursive Programs with Pointers in K
27
significantly simplifies, comparing to the standard approach in [1], the heap transformation operations performed on procedure calls and returns. (b) Secondly, we faithfully implement the formal semantics of Shylock using K -Maude [8]. By faithful implementation we understand that the K specification and the formal semantics of Shylock are bisimilar. The K specification for Shylock has the following desiderata: (1) to contribute to the pool of languages defined in K with a fairly elaborated language semantics; (2) to set the grounds for an extensive future work of semiautomatically proving the simulation between the concrete and abstract semantics; (3) most importantly, to use the semantics for verification by model checking techniques. (1) The quality of solely Shylock’s semantics lies in the specification of the rules for fresh object creation (i.e., the memory reuse), and procedure call/return (i.e., the renaming scheme). Each element in this entire mechanism is implemented equationally, i.e., by means of structural K rules which have equational interpretation when compiled in Maude. Hence, if we interpret Shylock as an abstract model for C or Java, the K specification for Shylock’s abstract semantics renders an equational abstraction. (2) The K framework already offers the semantic specification of languages such as C [4] and KOOL. However, it is notoriously difficult and not recommended to alter a concrete semantics for such a purpose as abstraction. Instead, the abstract interpretation standardized approach advocates for the following separation of concerns: the concrete and the abstract models are defined in isolation, the analysis and verification methods are developed in the abstract and are projected in the concrete using the a priori proved relation between concrete and abstract. To convey the same perspective in K, we can consider the C specification as the concrete model, the Shylock specification as the abstract model, and we are left to prove the simulation relation between the two. As such, once established the relation between concrete and abstract, Shylock is yet another witness to the versatility of the equational abstraction methodology [5]. (3) We employ the K specification of Shylock to derive verification capabilities provided for free by the Maude LTL model checker. The atomic properties are defined as regular expressions for the heap structure exploration. Maude’s model checker provides a substantial expressivity w.r.t. atomic properties in comparison with other model checking tools. This feature justifies the appropriateness of using K -Maude for Shylock in order to consequently model check Shylock programs. However, due to the prerequisites imposed by the Maude’s model checker, we can successfully verify only a restricted class of Shylock programs. We address this issue in step (c). (c) Our renaming scheme defined for resolving name clashes in the context of memory reuse is based on the concept of cut points as introduced in [6]. Cut points are objects in the heap that are referred to from both local and global variables, and as such, are subject to modifications during a procedure call. Recording cut points in extra logical variables allows for a sound return in the calling procedure, enabling a precise abstract execution w.r.t. object identities. Hence, under the assumption of a bounded visible heap, the programs can be represented by finitary structures, namely finite pushdown systems. Hence, the K specification for Shylock programs is bisimilar with a finite state pushdown system and compiles in Maude into a rewriting system. Obviously, in the presence of recursive procedures, the stack in the pushdown system grows unboundedly
28
I. As˘avoae, F. de Boer, M. Bonsangue, D. Lucanu and J. Rot
and, even if the abstraction ensures a finite state space, the equivalent transition system is infinite and so is the associated rewriting system. To overcome this drawback we approach two solutions: (i) apply a further abstraction to enforce the finiteness of the equivalent transition system; (ii) apply collecting semantics over the current abstraction to specify model checking algorithms for pushdown systems. (i) In order to use Maude’s model checker for Shylock programs with recursive procedure calls we need to employ another abstraction over the current one. Basically, we add to the semantics a computation bounding mechanism which cuts the recursion after a predefined number of recursive calls, hence semantically transforming the model checking into bounded model checking. This composition of abstractions is naturally expressed in K by adding new cells containing the bound for the recursion depth and the current depth for each recursive call, and by transforming the procedure call rewrite rule into a conditional rewrite rule. It is relatively easy to prove that there is a stuttering simulation between Shylock and recursion-bounded Shylock. Using this solution we obviously lose completeness of the model checking procedure for Shylock. (ii) The value of Shylock abstract semantics for model checking concerns its pushdown system characterization for which there are standardized model checking algorithms [9]. Hence, we propose embedding the K specification for Shylock abstract semantics into a K specification for Shylock collecting semantics. The Shylock collecting semantics renders an exhaustive execution of Shylock’s abstract semantics, is terminating, and produces the reachable state space and/or the reachability automaton. Using the reachable state space we can model check heap invariants (defined by the atomic propositions), while the reachability automaton can be coupled with the the LTL property to obtain the the full power LTL model checking capabilities. Consequently, this second solution preserves the completeness of the model checking for Shylock. This is currently ongoing work available for presentation in the near future.
References 1. A. Bouajjani, S. Fratani, and S. Qadeer. Context-Bounded Analysis of Multithreaded Programs with Dynamic Linked Structures. In CAV 2007, vol. 4590 of LNCS, Springer 2007. 2. P. Cousot, and R. Cousot. Abstract Interpretation and Application to Logic Programs, Journal of Logic Programming, 13(2–3), pp. 103–179, 1992. 3. S. Eker, J. Meseguer, and A. Sridharanarayanan. The Maude LTL Model Checker. In WRLA 2002, vol. 71 of ENTCS, pp. 162–187, 2002. 4. C. Ellison, and G. Ros¸u. An Executable Formal Semantics of C with Applications. In POPL 2012, to appear. 5. J. Meseguer, M. Palomino, and N. Mart´ı-Oliet. Equational abstractions. In Theoretical Computer Science, vol. 403(2-3), pp. 239–264, 2008. 6. N. Rinetzky, J. Bauer, T. W. Reps, S. Sagiv, and R. Wilhelm. A semantics for procedure local heaps and its abstractions. In POPL 2005, pp. 296–309, 2005. 7. G. Ros¸u, and T. F. S¸erb˘anut¸a˘ . An overview of the K semantic framework. Journal of Logic and Algebraic Programming, 79(6):397–434, 2010. 8. G. Ros¸u, and T. F. S¸erb˘anut¸a˘ . K-Maude: A Rewriting Based Tool for Semantics of Programming Languages. WRLA 2010, vol. 6381of LNCS, pp.104–122, Springer 2010. 9. S. Schwoon. Model-Checking Pushdown Systems. PhD thesis, Technische Universit¨at M¨unchen, 2002.
Model Checking LTLR Formulas under Localized Fairness Kyungmin Bae and Jos´e Meseguer Department of Computer Science, University of Illinois at Urbana-Champaign, Urbana IL 61801 {kbae4,meseguer}@cs.uiuc.edu
Abstract. Many temporal logic properties of interest involve both state and action predicates and only hold under suitable fairness assumptions. Temporal logics supporting both state and action predicates such as the Temporal Logic of Rewriting (TLR) can be used to express both the desired properties and the fairness assumptions. However, model checking such properties directly can easily become impossible for two reasons: (i) the exponential blowup in generating the B¨ uchi automaton for the implication formula including the fairness assumptions in its condition easily makes such generation unfeasible; and (ii) often the needed fairness assumptions cannot even be expressed as propositional temporal logic formulas because they are parametric, that is, they correspond to universally quantified temporal logic formulas. Such universal quantification is succinctly captured by the notion of localized fairness; for example, fairness localized to the parameter o in object fairness conditions. We summarize the foundations and present the language design and implementation of the new Maude LTLR Model Checker under localized fairness. This is the first tool we are aware of which can model check temporal logic properties under parametric fairness assumptions.
1
Introduction
Many temporal logic properties of interest involve both state and action predicates and only hold under suitable fairness assumptions. For example, the effective transmission of data by a fault-tolerant network protocol can only be proved under the assumption that the receiving node will receive messages infinitely often if it is infinitely often enabled to receive them. Although in principle temporal logics supporting both state and action predicates such as the Temporal Logic of Rewriting (TLR) can be used to express both the desired properties and the fairness assumptions, in practice model checking directly such properties can easily become impossible for two reasons. First of all, the exponential blowup in generating the B¨ uchi automaton for the formula ψ → ϕ, where ϕ is the desired property and ψ specifies the fairness assumptions, easily makes such generation unfeasible. To address this problem, various techniques to build in the fairness assumptions ψ into the model checking algorithm, so that only ϕ has to be model checked, have been proposed as the basis of various model checkers [12, 14, 18].
30
Kyungmin Bae and Jos´e Meseguer
However, a second serious difficulty not addressed by those techniques and tools exists: often the needed fairness assumptions ψ cannot even be expressed as propositional temporal logic formulas because they are parametric, that is, they correspond to universally quantified temporal logic formulas which are outside the scope of current fairness-supporting model checkers. A good example of parametric fairness is provided by object fairness assumptions such as “each object o infinitely often enabled to receive a message of the form m(o, q) will receive it infinitely often,” which is universally quantified over all the (possibly dynamically changing) objects o in the system. In rewriting logic such message reception can be expressed by a rewrite rule of the form: [rec] : [o | s] m(o, k) → [o | f (s, k)] where f (s, k) denotes a new state after receiving a message. This object fairness assumption can be described as the universally quantified LTLR formula: (∀o) enabled .rec(o) → rec(o) where enabled .rec(o) is the obvious state predicate holding iff the rec rule is enabled for object o. Such universal quantification can be succinctly captured by the notion of localized fairness [15]. The idea is that a rewrite rule like the one above is itself universally quantified over a finite set of variables; for example, for the rec rule the set {o, s, k}. Then the above strong object fairness condition corresponds to localizing the strong fairness requirement for rule rec to the singleton subset {o}. In general, fairness assumptions for a given rule can be localized to any chosen subset of its variables. Is it possible at all to model check temporal logic properties under such parametric fairness assumptions? The question is nontrivial, because, even under the finite-state assumption which can make the number of actual instances of the universal quantification finite, it may be impossible to have a priori knowledge about the actual number of such instances. For example, we may be dealing with an object-based system where objects are dynamically created, so that the entire state space may first have to be searched to determine which objects exist. We have recently reported on the automata-theoretic and algorithmic foundations of a novel model checking algorithm which solves the problem of model checking LTL properties under parameterized fairness and has good performance in practice [2]. However, the work in [2] dealt with this problem at an automatatheoretic level and did not present a suitable property specification language in which such parameterized fairness assumptions could be naturally expressed. In this paper we show that the intrinsically parametric nature of rewrite rules and the great flexibility of the Linear Temporal Logic of Rewriting (LTLR) to express parametric action patterns based on such rules makes LTLR an ideal property specification language for a model checker under parameterized fairness assumptions. In this way, the algorithm presented in [2] becomes available for rewriting logic specifications. Furthermore, we present and illustrate with examples a new LTLR model checker under localized fairness assumptions for Maude, which implements the algorithm in [2] at the C++ level as an extension
Model Checking LTLR Formulas under Localized Fairness
31
of the Maude system. A nontrivial part of this model checker is its user interface. First of all, a simple way for users to specify localized fairness assumptions as rule annotations is provided. Secondly, since LTLR formulas involve spatial action patterns which in turn involve rule labels, LTLR formulas go beyond the syntax available to Maude from parsing the system module to be model checked, or even such module syntax extended by the state predicates and the temporal logic connectives. We explain how rule annotations can also be used for this purpose. Of course, reflection techniques and the Full Maude infrastructure are used in an essential way to obtain this expressive and user-extensible user interface. The new Maude LTLR model checker is the first tool we are aware of which can model check temporal logic properties under parametric fairness assumptions. The tool and a collection of examples can be accessed at http://www.cs.illinois.edu/~kbae4/tlr.
2
Preliminaries on Localized Fairness
This section recalls preliminary notions on rewrite theories, the linear temporal logic of rewriting (LTLR), and localized fairness specifications. We also summarize our previous works on the LTLR model checking algorithm [1] and the LTL model checking algorithm under parameterized fairness assumptions [2], which provide the basis for the new LTLR model checker described in this paper. 2.1
Rewrite Theories
A rewrite theory [4] is a triple R = (Σ, E, R) such that: – (Σ, E) is a theory in membership equational logic with Σ a signature, E a set of conditional equations and memberships, and – R is a set of (possibly conditional) rewrite rules written l : q → r, where l is a label, and q and r are Σ-terms. The state space with a chosen type k is specified as the k-component of the initial algebra TΣ/E,k , i.e., each state is an E-equivalence class [t]E of ground terms with type k. Each rule l : q → r specifies the system’s concurrent transitions. A one-step rewrite from a state [t[θq]]E containing a substitution instance θq to the state [t[θr]]E in which θq has been replaced by θr is denoted by: [t[l(θ)]]E : [t[θq]]E →R [t[θr]]E where [t[l(θ)]]E is called a one-step proof term. A computation (π, γ) of R is a γ(0) γ(1) γ(2) path π(0) − −→ π(1) −−→ π(2) −−→ · · · where π(i) = [ti ]E with the state type k, γ(i) π(i) −−→ π(i + 1) is a one-step rewrite with a one-step proof term γ(i) for each i ∈ N. (π, α)i denotes the suffix of (π, α) beginning at position i ∈ N, i.e., (π, α)i = (π ◦ si , α ◦ si ) with s the successor function. Any finite computation of R can be extended into an infinite computation if R has no deadlock states. Any rewrite theory whose rules have no rewrites in their conditions can be transformed into a semantically an equivalent deadlock-free theory [17]. We will assume from now on that a rewrite theory is deadlock free.
32
2.2
Kyungmin Bae and Jos´e Meseguer
The Linear Temporal Logic of Rewriting
The linear temporal logic of rewriting (LTLR) is a state/event extension of linear temporal logic with spatial action patterns that describe properties of one-step rewrites [1]. The only syntactic difference between LTLR and LTL is that an LTLR formula may include spatial action patterns δ1 , . . . , δn as well as state propositions p1 , . . . , pm , and therefore can describe properties involving both states and events, e.g., fairness conditions. Given a set of state propositions Π and a set of spatial action patterns W , the syntax of LTLR formulas is as follows: ϕ ::= p | δ | ¬ϕ | ϕ ∧ ϕ0 | ϕ | ϕUϕ0 where p ∈ Π and δ ∈ W . Other operators can be defined by equivalences, e.g., 3ϕ ≡ trueUϕ, and ϕ ≡ ¬3¬ϕ. The semantics of LTLR over a set of state propositions Π and a set of spatial action patterns W is defined on a rewrite theory R that contains a subtheory for Π, W , boolean values, and one-step proof terms. A state proposition (resp., a spatial action pattern) is defined by a parametric function symbol of the form p : s1 . . . sn → Prop (resp., δ : s1 . . . sm → Action). The satisfaction relations for state propositions and spatial action patterns are defined by means of equations using the following auxiliary operators: |= : k Prop → Bool
|= : ProofTerm Action → Bool
in which a state proposition p is satisfied on a state [t]E if and only if E ` (t |= p) = true, and a spatial action pattern δ is satisfied on a one-step proof term [λ]E if and only if E ` (λ |= δ) = true. An LTLR formula ϕ is satisfied on R from an initial state [t]E , denoted by R, [t]E |= ϕ, if and only if for each infinite computation (π, γ) starting from [t]E , the path satisfaction relation R, (π, γ) |= ϕ holds, which is defined inductively as follows: – – – – – – 2.3
R, (π, γ) |= p iff E ` (π(0) |= p) = true R, (π, γ) |= δ iff E ` (γ(0) |= δ) = true R, (π, γ) |= ¬ϕ iff R, (π, γ) 6|= ϕ R, (π, γ) |= ϕ ∧ ϕ0 iff R, (π, γ) |= ϕ and R, (π, γ) |= ϕ0 R, (π, γ) |= ϕ iff R, (π, γ)1 |= ϕ R, (π, γ) |= ϕ Uϕ0 iff ∃j ≥ 0. R, (π, γ)j |= ϕ0 , ∀0 ≤ i < j. R, (π, γ)i |= ϕ. Localized Fairness
Fairness of a rewrite theory R is often expressed by patterns of rewrite events, i.e., by spatial action patterns. A one-step rewrite event is usually too specific to describe a general fairness requirement. Definition 1. A basic action pattern of a rewrite theory R = (Σ, E, R) is a simple parametric spatial action pattern of the form l(y) such that l is the label of some rule l : q → r ∈ R and y ⊆ vars(q). A ground instance θ(l(y)) of a basic action pattern l(y) is satisfied on each one-step proof term of the form [t[l(θ)]]E .
Model Checking LTLR Formulas under Localized Fairness
33
A basic action pattern l(∅) with no variables is denoted by just a rule label l. Also, a parametric state proposition enabled (l(y)) can be defined in R such that a ground instance θ(enabled (l(y))) is satisfied on each state [t]E from which there exists a one-step rewrite [t[l(θ)]]E . The satisfaction relations for both basic action patterns and enabled propositions can be defined by equations and automatically generated from R (see Section 4.3). A localized fairness specification [15] is a pair of finite sets (J , F) whose elements are basic action patterns of the general form l(y). The set J stands for weak fairness conditions1 and F stands for strong fairness conditions.2 This localized fairness specification is quite general so that many different notions of fairness, such as object/process fairness, can be expressed in a unified way [15]. Intuitively, localized fairness given by l(y) ∈ J ∪ F means that for each ground instance ϑ(l(y)) of l(y), the corresponding one-step rewrite satisfies the desired weak or strong fairness requirements. Each localized fairness pattern can be expressed by an equivalent universally quantified LTLR formula [2] of the form ∀y ϕ, where ϕ is quantifier-free, vars(ϕ) ⊆ y, and: R, (π, γ) |= ∀y ϕ
⇔
R, (π, γ) |= θϕ for each ground substitution θ
A weak (resp. strong) fairness condition with respect to a basic action pattern l(y) is then expressed by the quantified LTLR formula ∀y 3enabled (l(y)) → 3l(y) (resp., ∀y 3enabled (l(y)) → 3l(y)). A localized fairness specification (J , F) defines a set of fair computation of a rewrite theory R. An infinite computation (π, γ) of R is J , F–fair if and only if every localized fairness condition in J ∪ F is satisfied on (π, γ) in R. That is, – R, (π, γ) |= ∀y j 3enabled (lj (y j )) → 3lj (y j ), for each lj (y j ) ∈ J , and – R, (π, γ) |= ∀yf 3enabled (lf (yf )) → 3lf (yf ), for each lf (yf ) ∈ F. An LTLR formula ϕ is then fairly satisfied on R from an initial state [t]E under (J , F), denoted by R, [t]E |=J ∪F ϕ, if and only if R, (π, γ) |= ϕ holds for each J , F-fair computation (π, γ) starting from the initial state [t]E . 2.4
Model Checking Algorithms
The model checking problem for an LTLR formula ϕ on a rewrite theory R can be characterized by automata-theoretic techniques on the associated labeled Kripke structure (LKS) using the B¨ uchi automaton B¬ϕ [1, 3]. Definition 2. An LKS K is a 6-tuple (S, S0 , Π, L, W, T ), where S is a set of states, S0 ⊆ S is a set of initial states, Π is a set of state propositions, L : S → P(Π) is a state-labeling function, W is a set of events (i.e., spatial action patterns), and T ⊆ S × P(W ) × S is a labeled transition relation. 1 2
If an event is continuously enabled beyond a certain point, it is taken infinitely often. If an event is enabled infinitely often, then it is taken infinitely often.
34
Kyungmin Bae and Jos´e Meseguer
A path (π, α) of K is an infinite sequence hπ(0), α(0), π(1), α(1), . . .i such that α(i) π(i) ∈ S, α(i) ⊆ W , and π(i) − −→ π(i + 1) for each i ≥ 0. If R is a computable rewrite theory that satisfies additional decidability conditions [16], given an initial state [t]E , a set of state propositions Π, and a set of spatial action patterns W , we can construct the corresponding LKS KΠ,W (R)t such that R, [t]E |= ϕ if and only if KΠ,W (R)t |= ϕ for any LTLR formula ϕ over Π and W [1]. Therefore, a formula ϕ has no counterexample on R from an initial state [t]E if and only if the product automaton KΠ,W (R)t × B¬ϕ has no accepting path, which can be easily checked using the nested depth first search algorithm [10]. On the other hand, the model checking algorithm for a universally quantified LTLR formula ∀x ϕ on a rewrite theory R is nontrivial, since in general, such a variable quantification ranges over an infinite set, e.g., a set of tuples of ground terms having specified sorts in R. We cannot directly use the corresponding LKS KΠ,W (R)t for model checking such universally quantified LTLR formulas. However, the satisfaction relation for ∀x ϕ can be efficiently determined on a finite LKS satisfying finite instantiation property (FIP) [2]. Definition 3. An LKS K = (S, S0 , Π, L, W, T ) satisfies a finite instantiation property (FIP) if and only if: (i) for each state s ∈ S, L(s) is finite, and (ii) for 0 3 A each transition s − → s ∈ T , the set A is finite. The path-realized set R(π,α),ϕ is a set of substitutions that is guaranteed to be finite if the underlying LKS K is finite and satisfies FIP (see [2] for a detailed definition). Only such a finite path-realized set is necessary to decide the satisfaction of a universally quantified formula ∀x ϕ on K as shown in the following lemma [2], in which K⊥ = (S, S0 , Π ∪ Π⊥ , L, W ∪ W⊥ , T ) is an extension of K such that K⊥ may have additional void state propositions Π⊥ and spatial action patterns W⊥ which are never satisfied on K⊥ . Lemma 1. Given a finite LKS K satisfying FIP, a universally quantified LTLR formula ∀x ϕ, and a path (π, α), for each ground substitution θ, there exists ϑ ∈ R(π,α),ϕ such that K, (π, α) |= θϕ iff K⊥ , (π, α) |= ϑϕ. For a finite LKS K satisfying FIP, we can have an efficient algorithm to model check an LTLR formula ϕ under fairness assumptions of the form ∀y 3Φ → 3Ψ or ∀y 3Φ → 3Ψ , where Φ and Ψ are boolean formulas with no temporal operators [2]. The model checking algorithm consists basically in finding a reachable strongly connected component (SCC) S from initial states in the product automaton K × B¬ϕ such that: (i) S satisfies an acceptance condition of B¬ϕ , and (ii) all realized substitution instances of fairness formulas hold in S. The SCC S satisfies the universally quantified fairness formulas, thanks to Lemma 1. Such an SCC S exists in K × B¬ϕ if and only if there is a fair counterexample of ϕ in K. The complexity of the algorithm is O(k · f · |K| · 2|ϕ| ), where k is the number of fairness formulas and f is the number of realized substitutions [2]. 3
More precisely, there are only finitely many ground instances for each parametric proposition. But if the signature is finite as usual, the definitions are equivalent.
Model Checking LTLR Formulas under Localized Fairness
3
35
The Maude LTLR Model Checker under Fairness
We have developed a new Maude LTLR model checker to support model checking under localized fairness specifications using the algorithm in [2]. This tool extends the previous LTLR model checker [1] and the existing LTL model checker [8] in Maude. The new LTLR model checker allows the user to specify localized fairness conditions for each rule in a system module, and provides a simple user interface to perform model checking under localized fairness assumptions. The earlier version of the LTLR model checker [1] did not support localized fairness assumptions, and before this work the model checking algorithm in [2] had not been integrated with a suitable property specification language in which such parameterized fairness assumptions could be naturally expressed. This section presents rewrite theories and LTLR as an ideal property specification language for a parameterized fairness assumptions with user-friendly tool support. Throughout this section, we will use a simple fault-tolerant client-server communication model borrowed from [16] to illustrate the new LTLR model checker under localized fairness specifications. In this model, each client C sends a query N to a server S to receive an answer, and the server returns the answer f(S,C,N) of the query using a function f. The configuration of the system is a multiset of clients, servers, and messages, with the empty multiset null. A client is represented as a term [C,S,N,W] with C the client’s name, S a server’s name, N a number representing a query, and W either a number representing an answer or nil if the answer has not yet been received. A server is represented as a term [S] with the name S, and a message is represented as a term I
[C,S,N,nil] S req(c)); (just : enabled(reply(a,b)) => reply(a,b)); (just : enabled(reply(a,c)) => reply(a,c)); (just : enabled(rec(b)) => rec(b)); just : enabled(rec(c)) => rec(c) .) ltlr model check in CLIENT-SERVER-CHECK : [a][b,a,1,nil][c,a,0,nil] |= rec under fairness : (just : enabled(req(b))=> req(b)); (just : enabled(req(c))=> req(c)); (just : enabled(reply(a,b))=> reply(a,b)); (just : enabled(reply(a,c))=> reply(a,c)); (just : enabled(rec(b))=> rec(b)); just : enabled(rec(c))=> rec(c) result ModelCheckResult : counterexample(nil, {[a][b,a,1,nil][c,a,0,nil], {’req : ’C \ b ; ’S \ a}} {[a](a BasicActionPattern [ctor] .
– assignment operators for each sort Si of the variable xi in l(x1 , . . . , xn ) op _\_ : Qid Si -> Assignment [ctor ...] .
– an equation to define the satisfaction relation with respect to proof terms eq {C | ’l : ’x1 \ x1 ; ... ; ’xn \ xn ; SUBST} |= l(x1 ,...,xn ) = true .
Together with the theory transformation CONTEXT[_] to generate a context signature, the theory transformation ACTION[_] replaces a previous theory transformation [1] that was defined in the old version of the LTLR model checker to generate a signature for context terms and assignment operators. Next, the module expression FAIR[M] creates a declaration of the state proposition enabled (l(y)) for each l(y) ∈ B. Basically, such enabled propositions are defined by operators _enables_: K Action -> Bool for each relevant kind K, where E ` t enables δ = true means that the one-step rewrite associated to the one-step proof term δ can happen inside the term t. ceq S:State |= enabled(BSP) = true if S:State enables BSP .
For each l(x1 , . . . , xn ) ∈ B and its associated rule l : t → t0 if cond , where the kind of t is Kl , the basic declarations of enables operators are given as follows:
Model Checking LTLR Formulas under Localized Fairness
43
op _enables_ : Kl Action -> Bool . ceq t enables l(x1 , . . . , xn ) = true if cond .
For each free constructor operator f : K1 . . . Kn → K, where enables operators are defined for a nonempty set of kinds {Ki1 , . . . , Kik } ⊆ {K1 , . . . , Kn }, the following declarations of enables operators are given in FAIR[M]: op _enables_ : K Action -> Bool . ceq f(X1 :K1 ,...,Xn :Kn ) enables BSP if Xi1 enables BSP or-else ... or-else
Xik enables BSP .
Finally, for each associative constructor operator g : K K → K, and for each equation ceq t enables δ = true if cond for a kind K, the extended declarations of enables operators are given in FAIR[M] as follows, where X1 : K and X2 : K are fresh variables not appearing in the original equation: op ceq ceq ceq
_enables_ : K Action -> Bool . g(X1 :K, t, X2 :K) enables δ = true if cond . g(X1 :K, t) enables δ = true if cond . g(t, X2 :K) enables δ = true if cond .
If the associative constructor satisfies another axiom such as commutative or identity, only some of the above equations will be required. Note that the above extended declarations are essentially the generalization of equations for extension matching modulo equational axioms [4]. The enables declarations for free and associative constructors can be computed iteratively until reaching a fixed point. Since the right side of each enables equation is true, we can easily prove the following proposition by induction on the height of the conditional proof tree. Proposition 1. Given a rewrite theory R = (Σ, E ∪ B, R) with signature of constructors Ω that are free modulo the axiom of B,6 for a basic action pattern l(y) of R, a term [t]E , and a substitution ϑ, if E ` t enables ϑ(l(y)) = true, then there exists a one-step rewrite from [t]E with a one-step proof term λ such that E ` (λ |= l(ϑy)) = true.
5
An Example
This section illustrates a rewriting logic specification of the Evolving Dining Philosophers problem [13] with a localized fairness specification. This problem is similar to the famous Dining Philosophers problem, but a philosopher can join or leave the table, so that the number of philosophers can change dynamically. In this example, it is very hard to specify exact fairness conditions even if an initial state of the system is already given, because we cannot know how many philosophers can be in the model without exploring the entire state space, but the fairness conditions of this system depend on each philosopher in the system. 6
That is, TΣ/E∪B |Ω ' TΩ/B .
44
Kyungmin Bae and Jos´e Meseguer
Each philosopher is represented by a term ph(I, S, C), where I is the philosopher’s id, S is the philosopher’s status, and C is the number of chopsticks held. Likewise, a chopstick with id I is represented by a term stk(I). The configuration of the system is described by a set of philosophers and chopsticks, built by an associative-commutative set union operator _;_. The signature is defined in the Maude language as follows: sorts Philo Status Chopstick Conf . op ph : Nat Status Nat -> Philo . subsort Philo Chopstick < Conf . ops think hungry : -> Status . op none : -> Conf . op stk : Nat -> Chopstick . op _;_ : Conf Conf -> Conf [comm assoc id: none] .
The state is a triple < P, N, CF > with sort Top, where P is a global counter, N is the number of philosophers, and CF is a set of philosophers and chopsticks. The behavior of philosophers is then described by the following rewrite rules with a necessary localized fairness specification: rl [wake ] : ph(I, think, 0) => ph(I, hungry, 0) [metadata "just(I)"] . crl [grab ] : < P, N, ph(I, hungry, C) ; stk(J) ; CF > => < P, N, ph(I, hungry, C + 1) ; CF > if J == left(I) or J == right(I, N) [metadata "fair(I)"] . rl [stop ] : < P, N, ph(I, hungry, 2) ; CF > => < P, N, ph(I, think, 0) ; stk(left(I)) ; stk(right(I, N)) ; CF > .
The functions left(I) = I and right(I,N) = (I + 1) rem N return the chopstick’s id on the left (resp., right) of philosopher I, where _rem_: Nat Nat -> Nat is the reminder operator. We now specify the dynamic behavior of philosophers in the Evolving Dining Philosopher problem. Although there is no limit to the number of philosophers in the original problem, we can give an unpredictable bound using the Collatz conjecture [6]. There is a global counter P that symbolizes a philosophical problem, and philosophers keep thinking the problem by changing the number n to: (i) 3n + 1 for n odd, or (ii) n/2 for n even. crl [solve ]: < P, N, ph(I, think, 0) ; CF > if P > 1 /\ Q := collatz(P) .
=>
< Q, N, ph(I, think, 0) ; CF >
New philosophers can join the group only if the global number is a multiple of the current number of philosophers. No more philosophers can join after the number eventually goes to 1. We assume that only the last philosopher can leave the group for simplicity. To keep consistency, whenever a philosopher joins or leaves the table, the related chopsticks should not be held by another philosopher. crl [join ] : < P, N, ph(N, think, 0) ; CF > => < P, N + 1, ph(N, think, 0) ; ph(N + 1, think, 0) ; stk(N + 1) ; CF > if P rem N == 0 . crl [leave ]: < P, N, CF ; ph(N, think, 0) ; stk(N) > => < P, N - 1, CF > if N > 2 .
Model Checking LTLR Formulas under Localized Fairness
45
In order to perform model checking, we define the following module after loading the LTLR model checker interface in Full Maude. (mod PHILO-CHECK is including PHILO . including LTLR-MODEL-CHECKER . subsort Top < State . op eating : Nat -> Prop [ctor] . op init : -> State . vars P N : Nat . var I : NzNat . var CF : Conf . eq < P, N, ph(I, hungry, 2) ; CF > |= eating(I) = true . eq init = < 12, 2, ph(1,think,0); stk(1); ph(2,think,0); stk(2) > . endm)
The state proposition eating(I) is satisfied if the philosopher I is eating. The initial state is the case of 2 philosophers with the global counter 12, expressed by < 12, 2, ph(1, think, 0); stk(1); ph(2, think, 0); stk(2) >. We are interested in verifying the liveness property []~ deadlock -> eating(1), where deadlock is a spatial action pattern satisfied on deadlock states [1]. Without fairness assumptions, the model checker generates the following counterexample for this formula, in which only the philosopher 2 performs actions while the order philosophers keep idle and no new philosopher joins: Maude> (mc init |= [] ~ deadlock -> eating(1) .) ltlr model check in PHILO-CHECK : init |= []~ deadlock -> eating(1) result ModelCheckResult : counterexample( {< 12,2,stk(1); stk(2); ph(1,think,0); ph(2,think,0)>, {’solve : ’I \ 1}} {< 6,2,stk(1); stk(2); ph(1,think,0); ph(2,think,0)>, {’solve : ’I \ 1}} ..., {< 1,2,stk(1); stk(2); ph(1,hungry,0); ph(2,think,0)>, {’wake : ’I \ 2}} {< 1,2,stk(1); stk(2); ph(1,hungry,0); ph(2,hungry,0)>, {’grab : ’I \ 2 ; ’J \ 1}} {< 1,2,stk(2); ph(1,hungry,0); ph(2,hungry,1)>, {’grab : ’I \ 2 ; ’J \ 2}} {< 1,2,ph(1,hungry,0); ph(2,hungry,2)>, {’stop : ’I \ 2} })
When we assume localized fairness conditions, the model checker can verify the formula []~ deadlock -> eating(1) as follows: Maude> (pfmc init |= [] ~ deadlock -> eating(1) .) ltlr model check under localized fairness in PHILO-CHECK : init |= []~ deadlock -> eating(1) result Bool : true
Note that the reachable state space from the initial state has 12 ground fairness conditions instantiated by realized substitutions. The previous LTL and LTLR
46
Kyungmin Bae and Jos´e Meseguer
model checkers cannot verify the formula with those 12 fairness conditions in a reasonable time. Furthermore, using the previous model checker, we could not know how many ground fairness conditions would be required to prove the formula before exploring the entire state space .
6
Related Work and Conclusions
The usual model checking method to verify a property ϕ under parameterized fairness assumptions, is to construct the conjunction of corresponding instances of fairness, and to apply either: (i) a standard LTL model checking algorithm for the reformulated property fair → ϕ, or (ii) a specialized model checking algorithm which handles fairness, based on either explicit graph search [7, 9, 14], or a symbolic algorithm [12]. Approach (i) is inadequate for fairness, since the time complexity is exponential in the number of strong fairness conditions, while the other is linear. Furthermore, compiling such a formula, expressing a conjunction of fairness conditions, into B¨ uchi automata is usually not feasible in reasonable time [19]. There are several tools to support the specialized algorithms such as PAT [18] and Maria [14]. Our tool is related to the second approach to deal with fairness, but it does not require pre-translation of parameterized fairness, and can handle dynamic fairness instances. In conclusion, we have addressed the real need of verifying temporal logic properties under parametric fairness assumptions. Such parametric assumptions occur very often in practice, but up to now have not been supported by existing model checking techniques and tools. To address this need three things are required: (i) expressive system specification languages; (ii) expressive temporal logics; and (iii) novel model checking techniques and tools. This paper has argued and demonstrated with examples that rewriting logic answers very well need (i) and that TLR, and in particular LTLR, are very expressive to deal with need (ii). It has also presented a novel Maude LTLR model checker under localized fairness which directly addresses need (iii) in an efficient way. Acknowledgments. This work has been supported in part by NSF Grants CNS 09-04749 and CCF 09-05584, AFOSR Grant FA8750-11-2-0084, Boeing Grant C8088-557395, and the “Programa de Apoyo a la Investigaci´on y Desarrollo” (PAID-02-11) of the Universitat Polit`ecnica de Val`encia.
References 1. Bae, K., Meseguer, J.: The Linear Temporal Logic of Rewriting Maude Model Checker. In: WRLA. LNCS, vol. 6381, pp. 208–225. Springer (2010) 2. Bae, K., Meseguer, J.: State/event-based LTL model checking under parametric generalized fairness. In: Computer Aided Verification. LNCS, vol. 6806, pp. 132– 148. Springer (2011) 3. Chaki, S., Clarke, E., Ouaknine, J., Sharygina, N., Sinha, N.: State/event-based software model checking. In: Proc. 4th Intl. Conf. on Integrated Formal Methods (IFM’04). LNCS, vol. 2999, pp. 128–147. Springer (2004)
Model Checking LTLR Formulas under Localized Fairness
47
4. Clavel, M., Dur´ an, F., Eker, S., Meseguer, J., Lincoln, P., Mart´ı-Oliet, N., Talcott, C.: All About Maude – A High-Performance Logical Framework, LNCS, vol. 4350. Springer (2007) 5. Couvreur, J., Duret-Lutz, A., Poitrenaud, D.: On-the-fly emptiness checks for generalized B¨ uchi automata. Model Checking Software pp. 169–184 (2005) 6. Dams, D., Gerth, R., Grumberg, O.: Abstract interpretation of reactive systems. ACM Transactions on Programming Languages and Systems 19, 253–291 (1997) 7. Duret-Lutz, A., Poitrenaud, D., Couvreur, J.M.: On-the-fly emptiness check of transition-based Streett automata. In: ATVA. LNCS, vol. 5799. Springer (2009) 8. Eker, S., Meseguer, J., Sridharanarayanan, A.: The Maude LTL model checker and its implementation. In: Model Checking Software: Proc. 10th Intl. SPIN Workshop. LNCS, vol. 2648, pp. 230–234. Springer (2003) 9. Henzinger, M.R., Telle, J.A.: Faster algorithms for the nonemptiness of Streett automata and for communication protocol pruning. In: SWAT. LNCS, vol. 1097, pp. 16–27. Springer (1996) 10. Holzmann, G., Peled, D., Yannakakis, M.: On nested depth first search (extended abstract). In: The Spin Verification System. pp. 23–32. American Mathematical Society (1996) 11. Holzmann, G.: The SPIN model checker: Primer and reference manual. Addison Wesley Publishing Company (2004) 12. Kesten, Y., Pnueli, A., Raviv, L., Shahar, E.: Model checking with strong fairness. Formal Methods in System Design 28(1), 57–84 (2006) 13. Kramer, J., Magee, J.: The evolving philosophers problem: Dynamic change management. Software Engineering, IEEE Transactions on 16(11), 1293–1306 (2002) 14. Latvala, T.: Model checking LTL properties of high-level Petri nets with fairness constraints. In: ICATPN. LNCS, vol. 2075, pp. 242–262. Springer (2001) 15. Meseguer, J.: Localized fairness: A rewriting semantics. In: RTA. LNCS, vol. 3467, pp. 250–263. Springer (2005) 16. Meseguer, J.: The temporal logic of rewriting: A gentle introduction. In: Concurrency, Graphs and Models. LNCS, vol. 5065, pp. 354–382. Springer (2008) 17. Meseguer, J., Palomino, M., Mart´ı-Oliet, N.: Equational abstractions. Theoretical Computer Science 403(2-3), 239–264 (2008) 18. Sun, J., Liu, Y., Dong, J., Pang, J.: PAT: Towards flexible verification under fairness. In: Computer Aided Verification. pp. 709–714. Springer (2009) 19. Vardi, M.: Automata-theoretic model checking revisited. In: Verification, Model Checking, and Abstract Interpretation. pp. 137–150. Springer (2007)
Modelling and Analyzing Adaptive Self-Assembling Strategies with Maude
?
Roberto Bruni1 , Andrea Corradini1 , Fabio Gadducci1 , Alberto Lluch Lafuente2 , and Andrea Vandin2 1
Dipartimento di Informatica, Universit` a di Pisa, Italy [bruni,andrea,gadducci]@di.unipi.it 2 IMT Institute for Advanced Studies Lucca, Italy [alberto.lluch,andrea.vandin]@imtlucca.it
Abstract. Building adaptive systems with predictable emergent behavior is a challenging task and it is becoming a critical need. The research community has accepted the challenge by introducing approaches of various nature: from software architectures, to programming paradigms, to analysis techniques. We recently proposed a conceptual framework for adaptation centered around the role of control data. In this paper we show that it can be naturally realized in a reflective logical language like Maude by using the Reflective Russian Dolls model. Moreover, we exploit this model to specify a prominent example of adaptive system: robot swarms equipped with obstacle-avoidance self-assembly strategies. Such a case study is further quantitatively analyzed by exploiting the statistical model checker PVesta.
Keywords: Adaptation, autonomic, self-assembly, swarms, ensembles, Maude
1
Introduction
How to engineer autonomic system components so to guarantee that certain goals will be achieved is one of todays’ grand challenges in Computer Science. First, autonomic components run in unpredictable environments, hence they must be engineered by relying on the smallest possible amount of assumptions, i.e. as adaptive components. Second, no general formal framework for adaptive systems exists that is widely accepted. Instead several adaptation models and guidelines are presented in the literature that offer ad hoc solutions, often tailored to a specific application domain or programming language. Roughly, there is not even a general agreement about what “adaptation” is. Third, it is not possible to mark a b/w distinction between failure and success, because the randomized behaviour of the system prevents an absolute winning strategy to exist. Fourth, efforts spent in the accurate analysis of handcrafted adaptive components are unlikely to pay back, because the results are often scarcely reusable when the components’ software is updated or extended with new features. ?
Research supported by the European Integrated Project 257414 ASCENS.
Adaptative Self-Assembling Strategies with Maude
49
We address here some of the above concerns, presenting the methodology we have devised for prototyping well-engineered self-adaptive components. Our case study consists of modeling and analyzing self-assembly strategies of robots whose goal is crossing a hole while navigating towards a light source. We specified such robots with Maude, exploiting on one hand the Reflective Russian Dolls (RRD) model [21] and on the other hand the conceptual framework we proposed in [6], which provides simple but precise guidelines for a clean structuring of self-adaptive systems. We report also on the results of the analysis of our model using PVesta [2], as well as on relevant aspects of our experience using it. When is a software system adaptive? Self-adaptation is a fundamental feature of autonomic systems, that can specialize to several other so-called self-* properties (like self-configuration, self-optimization, self-protection and self-healing, as discussed e.g. in [10]). Self-adaptive systems have become a hot topic in the last decade: an interesting taxonomy of the concepts related to self-adaptation is presented in [18]. Several contributions have proposed reference models for the specification and structuring of self-adaptive software systems, ranging from architectural approaches (including the well-known MAPE-K [9, 10, 12], FORMS [23], the adaptation patterns of [7], and the already mentioned RRD [21]), to approaches based on model-based development [24] or model transformation [11], to theoretical frameworks based on category theory [17] or stream-based systems [5]. Even if most of those models have been fruitfully adopted for the design and specification of interesting case studies of self-adaptive systems, in our view they missed the problem of characterizing what is adaptivity in a way that is independent of a specific approach. We have addressed this problem in [6], where we have proposed a very simple criterion: a software system is adaptive if its behaviour depends on a precisely identified collection of control data, and such control data can be modified at run time. We discuss further this topic in §3. Is Maude a convenient setting to study self-adaptation? A “convenient” framework must provide a reusable methodology for modelling self-adaptive systems independently of their application domain together with a flexible analysis toolset to investigate formal properties of the semantics of such systems. There are several reasons why we think that Maude [8] is a good candidate. First, the versatility of rewrite theories can offer us the right level of abstraction for addressing the specification, modelling and analysis of self-adaptive systems and their environments within one single coherent framework. Second, since Maude is a rule-based approach, the control-data can be expressed naturally as a sub-set of the available rules and the reflection capability of Maude can be exploited to express control-data manipulation via ordinary rewrite rules, along the so-called tower of reflection and its modular realization as the RRD approach [14]. Third, the conceptual framework for adaptation described in [6], to be further elaborated in §4, facilitates early and rapid prototyping of self-adaptive systems, to be simulated. Fourth, the formal analysis toolset of Maude can support simulations and analysis over the prototypes. In particular, given the probabilistic nature of adaptive systems, where absolute guarantees cannot be proved, we think that
50
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
the statistical model checker PVesta [2] is useful, because it allows to conduct analysis that are parametric w.r.t. the desired level of statistical confidence. Pragmatically, the possibility to rapidly develop and simulate self-adaptive systems and to compare the behaviour emerging from different adaptation strategies at the early stages of software development is very important for case studies like the robotic scenario described in the next paragraphs. Indeed, such physical devices require specialized programming skills and their experimentation in real world testing environments involves long time consumption (6 hours or more for each run) and only a limited number of pieces is available (around 25 units) because their maintenance is expensive. Also, their hardware (both mechanic and electronic parts) and software are frequently updated, making harder to build, to maintain and to rely on sophisticated simulators that can take as input exactly the same code to be run on the robots. Even when this has been attempted, the tests conducted on the real systems can differ substantially from the simulated runs. Thus, early simulation on prototypes can at least speed-up debugging and dispense the programmers from coding lowest-performance strategies. Synopsis. In §2 we present the case study analysed in this paper. In §3 we summarize the conceptual framework for adaptation proposed in [6] and along which we will design adaptive systems in Maude. The general guidelines and principles to be exploited in Maude for modelling self-adaptive systems are described in §4, together with the software architecture used to realize our conceptual framework. In §5 we illustrate the concrete implementation of the case study, while the experimentations are described in §6; for the sake of presentation, we focus on one of the self-assembly strategies. Some concluding remarks and ongoing research avenues are discussed in §7. We assume the reader to have some familiarity with the Maude framework.
2
Case Study: Self-Assembling Robot Swarms.
Self-assembling robotic systems are formed by independent robots capable to connect physically when the environment prevents them from reaching their goals individually. Self-assembly units must be designed in a modular way and their logic must be more sophisticated than, say, that of cheaper pre-assembled units, because self-assembly is a contingency mechanism for environments where versatility is a critical issue and the size and morphology of the assembly cannot be known in advance. Such features make the self-assembling robot swarm a challenging scenario to engineer. In [16], different self-assembly strategies are proposed to carry out tasks that range from hill-crossing and hole-crossing to robot rescue: case by case, depending e.g. on the steep of the hill, the width of the hole, the location of the robot to be rescued, the robots must self-assemble because incapable to complete the task individually. We focus on the hole-crossing scenario as a running case study, where “the robots in the swarm are required to cross a hole as they navigate to a light source” and depending on the width of the hole “a single unit by itself will fall off into the crevice, but if it is a connected body, falling can be prevented”.
Adaptative Self-Assembling Strategies with Maude
51
Fig. 1. Excerpt of the basic self-assembly response strategy (borrowed from [16]).
The experiments in [16] were conducted on the SWARM-BOT robotic platform [15], whose constituents are called s-bots (see Fig. 6, bottom right). Each s-bot has a traction system that combines tracks, wheels and a motorised rotation system, has several sensors (including infra-red proximity sensors to detect obstacles, ground facing proximity sensors to detect holes, and a 360 degrees view thanks to a camera turret), and is surrounded by a transparent ring that contains eight RGB colored LEDs (Light Emitting Diodes) distributed uniformly around the ring. The LEDs can provide some indications about the internal state of the s-bot to (the omni-directional cameras of) nearby s-bots. For example, the green color can be used to signal the willingness to connect to an existing ensemble, and the red color can be used for the willingness to create a new assembly. The ring can also be grasped by other s-bots thanks to a gripper-based mechanism. Roughly, the strategies described in [16] are: (i) the independent execution strategy, where s-bots move independently one from the other and never selfassemble; (ii) the basic self-assembly response strategy (see below), where each s-bot moves independently (blue light) until an obstacle is found, in which case it tries to aggregate (green light) to some nearby assembly, if some available, or it becomes the seed of a new assembly (red light); (iii) the preemptive self-assembly strategy, where the s-bots self-assemble irrespectively of the environment and not by emergency as in the basic self-assembly response; (iv) the connected coordination strategy, where the sensing and actuation of assembled robots is coordinated according to a leader-follower architecture. The experiments were conducted with different strategies in different scenarios (with holes of different dimension and random initial positions of the s-bots) and repeated for each strategy within each scenario (from a minimum of 20 times and 2 s-bots to a maximum of 60 times and 6 s-bots). Videos of the experiments described in [16] are linked from the web page describing our Maude implementation: http://sysma.lab.imtlucca.it/tools/ensembles.
52
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
Basic self-assembly response strategy. We describe here the basic self-assembly strategy of [16], which is the strategy on which we will focus in the rest of the paper. The finite state machine of the strategy is depicted in Fig. 1. Each state contains its name and the color of the LEDs turned on in that state, while transitions are labelled with their firing condition. This controller is executed independently in each individual s-bot (a concrete one in [16], or a software abstraction in this work). In the starting state (Independent Phototaxis) each s-bot turns on its blue LEDs, and navigates towards the target light source, avoiding possible obstacles (e.g. walls or other robots). If an s-bot detects a hole (through its infra-red ground sensors), or sees a green or red s-bot, then it switches to state Anti Phototaxis, i.e. it turns on its green LEDs and retreats away from the hole. After the expiration of a timeout, the s-bot passes to state Aggregate: it randomly moves searching for a red (preferably) or a green s-bot. In case it sees a red s-bot, it switches to state Self Assemble, assembles (grabs) to the red s-bot, turns on its red LEDs and switches to state Wait. If instead it sees a green s-bot, with probability Prob(Become seed) it switches to state Assembly Seed, turns on its red LEDs, and becomes the seed of a new ensemble. Once in state Assembly Seed, the s-bot waits until a timeout expires and switches to state Wait, unless it sees another red s-bot, in which case it reverts to state Aggregate. Once no green s-bots are visible, assembled “waiting” s-bots switch to state Connected Phototaxis and navigate to the light source.
3
A Framework for Adaptation
Before describing how we modeled and analysed the scenario we just presented, let us explain some guidelines that we followed when designing the system. The main goal was to develop a software system where the adaptive behaviour of the robots is explicitly represented in the system architecture. To this aim, we found necessary to first understand “when is a software system adaptive”, by identifying the features distinguishing such systems from ordinary (“non-adaptive”) ones. We addressed this problem in [6], proposing a simple structural criterion to characterize adaptivity. Oversimplifying a bit, according to a common black-box perspective, a software system is “self-adaptive” if it can modify its behaviour as a reaction to a change in its context of execution. Unfortunately this definition is hardly usable: accordingly to it almost any software system can be considered selfadaptive. Indeed, any system can modify its behaviour (e.g., executing different instructions, depending on conditional statements) as a reaction to a change in the context of execution (like the input of a data from the user). We argue that to distinguish situations where the modification of behaviour is part of the application logic from those where they realize the adaptation logic, we must follow a white-box approach, where the internal structure of a system is exposed. Our framework requires to make explicit that the behavior of a component depends on some well identified control data. We define adaptation as the run-time modification of the control data. From this definition we derive
Adaptative Self-Assembling Strategies with Maude
53
that a component is called adaptable if it has a clearly identified collection of control data that can be modified at run-time. Further, a component is adaptive if it is adaptable and its control data are modified at run-time, at least in some of its executions; and it is self-adaptive if it can modify its own control data. Under this perspective, and not surprisingly, any computational model or programming language can be used to implement an adaptive system, just by identifying the part of the data governing the behavior. Consequently, the nature of control data can greatly vary depending on the degree of adaptivity of the system and on the computational formalisms used to implement it. Examples of control data include configuration variables, rules (in rule-based programming), contexts (in context-oriented programming), interactions (in connector-centered approaches), policies (in policy-driven languages), aspects (in aspect-oriented languages), monads and effects (in functional languages), and even entire programs (in models of computation exhibiting higher-order or reflective features). In [6] we discussed how our simple criterion for adaptivity can be applied to several of the reference models we mentioned in the introduction, identifying for each of them what would be a reasonable choice of control data. Interestingly, in most situations the explicit identification of control data has the effect of revealing a precise interface between a managed component (mainly responsible for the application logic) and a control component (encharged of the adaptation logic). As a paradigmatical ex- Fig. 2. Control data in MAPE-K. ample, consider the MAPE-K architecture [9], according to which a self-adaptive system is made of a component implementing the application logic, equipped with a control loop that monitors the execution through sensors, analyses the collected data, plans an adaptation strategy, and finally executes the adaptation of the managed component through effectors; all the phases of the control loop access a shared knowledge repository. Applying our criterion to this model suggests a natural choice for the control data: these must include the data of the managed component that are modified by the execute phase of the control loop. Clearly, by our definitions the managed component is adaptive, and the system made of both component and control loop is self-adaptive. Fig. 3. Tower of adaptation. The construction can be iterated, as the control loop itself could be adaptive. Think e.g. of an adaptive component which follows a plan to perform some tasks.
54
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
This component might have a manager which devises new plans according to changes in the context or in the component’s goals. But this planning component might itself be adaptive, where some component controls and adapts its planning strategy, for instance determining the new strategy on the basis of a tradeoff between optimality of the plans and computational cost. In this case the manager itself (the control loop) should expose its control data (conceptually part of its knowledge repository) in its interface. In this way, the approach becomes compositional in a layered way, which allows one to build towers of adaptive components (Fig. 3) as we do in §5 and §6 for robot prototypes.
4
Adaptivity in Maude
We argue here the suitability of Maude and rewriting logic as a language and a model for adaptivity (§4.1), describe a generic architecture for developing adaptive components in Maude (§4.2) and show that it conforms to well-assessed conceptual models for adaptivity, including our framework (§4.3). 4.1
Maude, Logical Reflection and Adaptivity
As argued in [14], Rewriting Logic (RL) is well-suited for the specification of adaptive systems, thanks to its reflective capabilities. The reflection mechanism yields what is called the tower of reflection. At the ground level, a rewrite theory R (e.g. a software module) allows to infer a computation step R ` t → t0 from a term t (e.g. a program state) to a term t0 . A universal theory U lets infer the computation U ` (R, t) → (R, t0 ) at the “meta-level” where theories and terms are meta-represented as terms. The process can be repeated as U itself is a rewrite theory. This mechanism is efficiently supported by Maude and fostered many meta-programming applications like analysis and transformation tools. Since a theory can be represented by a term, it is also possible to specify adaptation rules that change the (meta-representation of the) theory, as in r ` (R, t) → (R0 , t0 ), so that the reduction continues with a different set of rules R0 . The reflection mechanism of RL has been exploited in [14] to formalize a model for distributed object reflection, suitable for the specification of adaptive systems. Such model, called Reflective Russian Dolls (RRD), has a structure of layered configurations of objects, where each layer can control the execution of objects in the lower layer by accessing and executing the rules in their theories, possibly after modifying them, e.g., by injecting some specific adaptation logic in the wrapped components. It is worth stressing that logical reflection is only one possible way in which a layer can control the execution of objects of the lower level: objects within a layer interact via message passing, thus objects of the higher layer might intercept messages of the lower level, influencing their behaviour. But even if the resulting model is still very expressive, some form of reflection seems to be very convenient, if not necessary, to implement adaptivity. This is clearly stated in [14] and at a more general level in [3], where (computational) reflection is promoted as a necessary criterion for any self-adaptive software system.
Adaptative Self-Assembling Strategies with Maude
55
The RRD model has been exploited for modeling policy-based coordination [21] and for the design of PAGODA, a modular architecture for specifying autonomous systems [22]. Our case study conforms to this model. 4.2
Generic Architecture
This section describes how we specialize the RRD architecture for modeling adaptive components. We focus on the structure of the layers and on the interactions among them, abstracting from the details of our case study, discussed in §5. Intra-layer architecture Each layer is a component having the structure illustrated in Fig. 4. Its main constituents are: knowledge (K), effects (E), rules (R) and managed component (M ). Some of them are intentionally on the boundary of the component, since they are part of its interface: knowledge and effects Fig. 4. Intra-layer. act respectively as input and output interfaces, while rules correspond to the component’s control interface. Therefore we will consider the rules R as the control data of a layer. The managed component is a lower-level layer having the same structure: clearly, this part is absent in the innermost layer. The knowledge represents the information available in the layer. It can contain data that represent the internal state or assumptions about the component’s surrounding environment. The effects are the actions that the component is willing to perform on its enclosing context. The rules determine which effects are generated on the basis of the knowledge and of the interaction with the managed component. Typical rules update the knowledge of the managed component, execute it and collect its effects. In this case the layer acts as a sort of interpreter. In other cases rules can act upon the rules of the managed component, modifying them: since such rules are control data, the rules modifying them are adaptation rules according to §3. Inter-layer architecture Layers are organized hierarchically: each one contains its knowledge, effects, rules and, in addition, the managed underlying layer. The outermost layer interacts with the environment: its knowledge represents the perception that the adaptive component has of the environment, while its effects represent the actions actually performed by the component. Each layer elaborates its knowledge and propagates it to the lower level, if any. While descending the hierarchy, the knowledge becomes simpler, and the generated effects more basilar. Similarly to layered operating systems, each layer builds on simpler functionalities of the lower one to compute more complex operations. The diagram in the middle of Fig. 5 shows the control and data flow of ordinary behavior (without adaptations). Knowledge is propagated down to the core (layer 0) and the effects are collected up to the skin (layer 2). This flow of information is governed by the rules. Knowledge and effects are subject to modifications before each propagation. For example, layer 2 may decide to
56
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
Fig. 5. Inter-layer architecture (left), ordinary flow (center), adaptation flow (right).
propagate to layer 1 only part of the knowledge perceived from the environment, possibly after processing it. Symmetrically, layer 1 may decide to filter part of the effects generated by layer 0 before the propagation to layer 2, for example discarding those violating some given constraints. Instead the diagram depicted on the right of Fig. 5 corresponds to adaptation. The outermost layer acts ordinarily, but in layer 1 an adaptation is triggered. This can be due to some conditions on the present knowledge or to the status of the managed component. The result is that the rules of layer 1 act (among other things) upon the rules of layer 0 (denoted by the arrow passing through them).
4.3
Generic Architecture and Adaptation Frameworks
Let us relate the generic architecture just presented with some general frameworks used for modeling adaptive systems. As suggested in §3, we identified explicitly the control data of each layer, namely, its set of rules: this will allow to distinguish the adaptation behaviour from the standard computations of the system. Our architecture is a simplified version of the RRD of [14], because each layer is a single object rather than a proper configuration. The interaction between a layer and its managed component is realized both with logical reflection and with access to shared data (knowledge and effects). Further, there is a clear correspondence between the reflective tower of the RRD model and the adaptation tower discussed in §3, as depicted in Fig. 6. This shows that the rules of each layer implement the MAPE control loop on the lower layer. Moreover, the generic architecture imposes the encapsulation of all components of the tower, apart from the robot itself. This offers several advantages: (i) management is hierarchical (e.g. self-management is forbidden); and (ii) the adaptive component is controlled by the topmost layer, which nevertheless can delegate the basic functionalities to lower layers.
5
Concrete Architecture and Case Study Implementation
This section instantiates the generic architecture shown in §4.2 to our case study (§5.1), and presents some relevant details of its implementation (§5.2). We will call s-bots simply robots in the following.
Adaptative Self-Assembling Strategies with Maude
57
Fig. 6. Architecture as an instance of the framework.
5.1
Architecture of the Case Study
The three layers of the concrete architecture of the case study (cf. Fig. 6, top-right) essentially capture the informal description of [16], in the following sense. Layer 0 (kernel). This layer (corresponding to PAGODA’s hardware abstraction layer [22]) models the core functionalities of a robot (see [16, §3]). The rules implement basic movements and actioning of the gripper. Layer 1 (basic control). This layer represents the basic controller managing the core functionalities of the robot according to the context. The controller may e.g. allow to move only in some directions (e.g. towards a light source) or to search for a robot to grab. This layer corresponds to the individual states of state machines modeling the self-assembly strategies, like the one of Fig. 1 (see [16, §5 and §7]). Layer 2 (adaptation). This is the layer of the adaptation manager, which reacts to changes in the environment activating the proper basic controller. In our case study, this layer corresponds to the entire state machine modelling the self-assembly strategy of Fig. 1, and in particular it takes care of the transitions between their states. This is done by constantly monitoring the environment and the managed component M , and by executing an adaptation phase when needed, which means changing the rules of M . A few other self-assembly strategies are discussed in [16]: they could be implemented by changing the rules of this layer. The three layers differ in their sets of rules and, of course, in the managed component, but they share part of the signature for knowledge and effects. In particular, knowledge includes predicates about properties of the ground (wall, hole, free), the presence of robots in the surrounding (their LED emissions), and
58
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
the direction of the light source (the goal). Effects include moving or emitting a color towards a direction, and trying to grab a robot located in an adjacent cell. Knowledge and effects are currently implemented as plain sets of predicates. More sophisticated forms of knowledge representation based on some inference mechanism (like prolog specifications, ontologies or constraints) are subject of current investigation but not necessary in the presented case study. Simulator. The execution environment of the robots is realized by a simulator which consists of three parts: the orchestrator, the scheduler and the arena. The orchestrator takes care of the actual execution of the actions required to manage the effects generated by a robot. For instance, it decides if a robot can actually move towards the direction it is willing to move. The scheduler, implemented as an ordinary discrete-event scheduler, activates the scheduled events, allowing a robot or the orchestrator to perform its next action. Intuitively, the emission of an effect e by the outermost layer of a component c causes the scheduling of the event “execute effect e on c” for the orchestrator. Symmetrically, the handling by the orchestrator of an effect previously generated by a component c induces the scheduling of an event “generate next effect” for c. Finally, the arena defines the scenario where robots run. We abstracted arenas in discrete grids, very much like a chessboard. Each grid’s cell has different attributes regarding for example the presence of holes or light sources. A cell may also contain in its attributes (at most) one robot, meaning that the robot is in that position of the arena. Each robot can move or perform an action in eight possible directions (up, down, left, right and the four diagonals). 5.2
Implementation Details
On the structure of adaptive components. Our implementation, similarly to the systems described in [14], relies on Maude’s object-like signature (see [8, Chapter 8]). Such signature allows to model concurrent systems as configurations (collections) of objects, where each object has an identifier, a class and a set of attributes. Intuitively, < oid : cid | attr1, attr2 > is an object with identifier oid, class cid and two attributes attr1, attr2. Each layer is implemented as an object with attributes for knowledge (K), effects (E), rules (R) and managed component (M): the first two are plain sets of predicates, the third one is a meta-representation of a Maude module, and the fourth one is an object. Three classes are introduced for the different layers, namely AC0, AC1 and AC2. For design choice, the objects implementing the layers of a robot have the same identifier: in terms of [14] we use homunculus objects. Therefore a sample robot can have the following overall structure: < c(0) : AC2 | K: E: R: M:
gripper(open) on(right,none) towards(right,light) ... , emitt(up,Green) go(right) ... , mod_is_sorts_._____endm, < c(0) : AC1 | K: ... , E: ... , R: ... , M: < c(0) : AC0 | K: ... , E: ... , R: ... > > >
Adaptative Self-Assembling Strategies with Maude
59
On the structure of the simulator. The arena is implemented as a multiset of objects of class Cell. A cell may contain in the attributes an object of class AC2 representing a robot, and the orchestrator implements the move of a robot by changing the cell in which it is stored. This way the robots have no information about the global environment or their current position, but only about the contiguous cells and the direction to take to reach the goal. The cell incapsulating a robot actually acts as a fourth layer over the object of class AC2. In fact, it is responsible of updating its knowledge, of taking care of its effects (e.g. the cell must expose the status of robot’s LEDs), and of handling the interactions between the robot and the scheduler.
Rules of adaptive components. The behaviour of each layer is specified by the rules contained in its attribute R, which is a term of sort Module consisting of a meta-representation of a Maude module. This solution facilitates the implementation of components’ behaviour as ordinary Maude specifications and their treatment for execution (by resorting to meta-level’s rewriting features), monitoring and adaptation (by examining and modifying the meta-representation of modules). In fact, on the one hand a generic meta-rule can be used to self-execute an object: the object with rules R proceeds by executing R in its meta-representation. On the other hand, rules are exposed to the outer component, which can execute or manipulate the inner one, and analyse the obtained outcome. In order to give an idea on how the flows of execution and information of Fig. 5 are actually implemented, we present one sample rule for each of the three layers. For the sake of presentation we abstract from irrelevant details. Layer 0. This layer implements robots’ core functionalities. For example, the following rule computes the set of directions towards which the robot can move: rl [admissibleMovements]: < oid : AC0 | K: oneStep k0, E: e0, A0 > => < oid : AC0 | K: k0, E: e0 canMoveTo(freeDirs(k0)), A0 > .
A rule, like admissibleMovements, can be applied to a Maude term t if its left-hand side (LHS) (here the object < oid : AC0 | ... > preceding =>) matches a subterm of t with some matching substitution σ, and in this case the application consists of replacing the matched sub-term with the term obtained by applying σ to the right-hand side, i.e. the object following =>. We shall also use Maude equations: they have higher priority than rules, meaning that rules are applied only to terms in normal form with respect to the equations. Rule admissibleMovements rewrites an AC0 object to itself, enriching its effects with the term obtained by simplifying equationally canMoveTo(freeDirs(k0)). Notice that the constant oneStep is consumed by the application of the rule: intuitively, it is a token used to inhibit further applications of the rule, obtaining a one step reduction. The equations will reduce freeDirs(k0) to the set of directions containing each dir appearing in a fact on(dir,content) of k0 such that content does not contain obstacles. Operator canMoveTo instead is a constructor.
60
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
Layer 1. Objects of class AC1 correspond to components of layer 1, implementing individual states of the state machine of Fig. 1. Rules of this layer can execute the component of the lower level providing additional knowledge, and can elaborate the resulting effects. The following rule implements (part of) the logic of state Independent Phototaxis, computing the desired direction towards which to move. crl [IP-main]: < oid : AC1 | K: oneStep k1, E: e1 , M: < oid : AC0 | K: k0 , E: e0, R: m0, A0 >, A1 > => < oid : AC1 | K: k1, E: e1 go(dir), M: < oid : AC0 | K: k0b, E: e0, R: m0, A0b >, A1 > if < oid : AC0 | K: k0b, E: e0 canMoveTo(freeDirs), A0b > := execute(< oid : AC0 | K: oneStep update1To0(k1,k0), E: e0, A0 >, m0) /\ preferredDirs := intersection(freeDirs, dirsToLight(k1)) /\ dir := uniformlyChooseDir(preferredDirs, freeDirs) .
This is a conditional rule, as evident from the keyword crl and the if clause following the RHS. Thus, it can be applied to a matched sub-term only if its (firing) condition is satisfied under the matching. In this case the condition is the conjunction (/\) of three sub-conditions, each consisting of a sort of assignment. The sub-conditions are evaluated sequentially, and the LHS of operator := will be bound in the rest of the rule to the term obtained by reducing its RHS. The first sub-condition exploits reflection: the operator execute makes use of Maude’s meta-level functionalities to execute the object in its first parameter via the rules meta-represented in its second one. More precisely, execute will apply a single rule of module m0 to the managed component < oid : AC0 ... >, after having updated its knowledge. In fact the operation update1To0(k1,k0) implements a (controlled) propagation of the knowledge from layer 1 to layer 0, filtering k1 before updating k0 (for example, information about the surrounding cells is propagated, but information about the goal is discarded). The assignment of the first sub-condition binds freeDirs to the directions towards which the managed component can move. This is used in the second sub-condition to compute the intersection between the directions in freeDirs and those towards the light, evaluated reducing dirsToLight(k1). The resulting set of directions is bound to preferredDirs. Finally, in the third sub-condition dir is bound to a direction randomly chosen from preferredDirs, or from freeDirs if the first set is empty. Comparing the LHS and the RHS, one sees that the overall effect of rule IP-main is the production of a new effect at layer 1, go(dir), and the update of the knowledge of the managed component of layer 0. Notice that the rules of layer 0 (m0) are not affected by the rule: in fact in our implementation rules of layer 1 never trigger an adaptation phase on layer 0. This is just a design choice, as clearly our architecture doesn’t forbids it. Layer 2. A component of this layer corresponds to the entire state machine of Fig. 1. It monitors the environment, and at each step it triggers a reduction of the managed component of layer 1; if necessary, it also enforces a transition from the current state to a new one of the state machine by performing an adaptation phase, i.e. by changing the rules of the managed component.
Adaptative Self-Assembling Strategies with Maude
61
The following is the main rule governing this layer: crl [adaptAndExecute]: < oid : AC2 | K: generateNextEffect k2, E: e2, M: < oid : AC1 | K: k1 , E: e1 , R: m1 , A1 >, A2 > => < oid : AC2 | K: k2A, E: e2A schedule(event(oid,effect)), M: < oid : AC1 | K: k1b, E: e1A, R: m1A, A1b >, A2A > if < oid : AC2 | K: k2A, E: e2A, M: < oid : AC1 | K: k1A, E: e1A, R: m1A, A1A >, A2A > := computeAdaptationPhase(< oid : AC2 | K: k2, E: e2, M: < oid : AC1 | K: k1, E: e1, R: m1, A1 >, A2 >) /\ < oid : AC1 | K: k1b, E: e1A effect, A1b > := execute( < oid : AC1 | K: oneStep update2To1(k2A,k1A), E: e1A, A1A >, m1A) .
The rule is triggered by the token generateNextEffect, generated by the cell containing the robot. The execution of the rule consists of an adaptation phase followed by an execution phase, both on the managed component. The two phases are triggered by the two sub-conditions of the rule. The adaptation phase is computed by the operation computeAdaptationPhase, using the knowledge of layer 2 (k2) to enact a state transition, if necessary. Among those defining the operation, the equation below encodes the transition of Fig. 1 from state Aggregate to state Self Assemble, labeled with Close to red: ceq [AggToSA]: computeAdaptationPhase( < oid2 : AC2 | K: state(Aggregate) k2, E: e2 , M: < oid1 : AC1 | R: m1 , E: e1 , a1 > , a2 >) = < oid2 : AC2 | K: state(SelfAssemble) k2, E: emitt(green), M: < oid1 : AC1 | R: m1b, E: none, a1 > , a2 > if seeEffect(led(red),k2) /\ m1b := upModule(’AC1-SELF_ASSEMBLE,false) .
The conditional equation states that if a robot in state Aggregate sees in its neighborhood a robot with red LEDs on, then it must pass to state Self Assemble and turn on its green LEDs. Also the rules of the managed component are changed: the new module m1b is obtained with the operation upModule, producing the meta-representation of the Maude module passed as first parameter. We specified one equation for each transition of Fig. 1, plus the following one where owise is a special attribute that tells the interpreter to apply the equation only if none of the others is applicable: eq [idle]: computeAdaptationPhase(obj) = obj [ owise ] .
Once the adaptation phase is concluded, the second sub-condition of rule adaptAndExecute takes care of the one step execution of the (possibly adapted) managed component, using operation execute. Finally, the effects generated by layer 1 are wrapped in the constructors event and schedule, and are added to the
effects of layer 2, so that the cell containing it will propagate it to the scheduler.
6
Analysis of Adaptation Strategies
This section describes some of the analysis activities carried out with our implementation, available at http://sysma.lab.imtlucca.it/tools/ensembles together with some additional material such as animated simulations.
62
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
robot led
goal
hole Fig. 7. Three states of a simulation: initial (left), assembly (middle), final (right).
The analysis has been carried out in two phases: (§6.1) discrete event simulation; and (§6.2) statistical analysis. The rationale is the following. In the early development phases we have mainly concentrated on performing single simulations that have been informally analyzed by observing the behavior of the assemblies in the automatically generated animations. A couple of trial-anderror iterations (where the model was fixed whenever some anomalous behavior was spotted) were enough for the model to acquire sufficient maturity to undergo a more rigorous analysis in terms of model checking. Ordinary model checking is possible in the Maude framework (via Maude’s reachability analysis capabilities, or LTL model checker) but suffers from the state explosion problem and is limited to small scenarios and to qualitative properties. To tackle larger scenarios, and to gain more insight into the probabilistic model reasoning about probabilities and quantities rather than possibilities, we resorted to statistical model checking techniques. We now provide the details of these analysis phases, centered around one crucial question: How many robots reach the goal by crossing the hole? 6.1
Simulations
Simulations are performed thanks to the discrete-event simulator mentioned in §5.2 along the lines of the ones reported in [1, 2, 20]. Valuable help has been obtained implementing an exporter from Maude Configuration terms to DOT graphs3 , offering the automatic generation of images from states: they have greatly facilitated the debugging of our code. For example, Fig. 7 illustrates three states of one interesting simulation, in which robots execute the basic self-assembly response strategy. The initial state (left) consists of three robots (grey circles with small dots on their perimeter) in their initial state (emitting blue light), a wide hole (the black rectangle) and the goal of the robots, i.e. a source of light (the orange circle on the right). After some steps, where the robots execute the self-assembly strategy, two robots finally get assembled (middle of Fig. 7). The assembled robots can then safely cross the hole and reach the goal (right of Fig. 7), while the not assembled one remains abandoned in the left part of the arena. While performing such simulations with different scenarios, varying the location of the goal and number and distribution of the robots, and with different 3
DOT is a well-established graph description language (http://www.graphviz.org/).
Adaptative Self-Assembling Strategies with Maude
63
parameters for duration of timeouts and actions, we observed several bizarre behaviors. For instance, in various simulations we observed some not-assembled robots erroneously believing to be part of an assembly, moving into the hole and disappearing. In other simulations we instead noticed pairs of robots grabbing each other. These observations triggered the following questions: Is there an error in our implementation? Is there an error in the strategies defined in [16]? Examining carefully the description of the strategy, we discovered that the two behaviors are indeed not explicitly disallowed in [16] and originated by the two transitions (see Fig. 1 in §2) outgoing from the state Assembly Seed (willing to be grabbed). The first transition leads to state Wait, triggered by the expiration of a timeout, while the second one leads to state Aggregate (willing to grab), triggered by the event See red (i.e. another robot willing to be grabbed). Considering the first behavior, a robot can change from state Assembly Seed to state Wait without another robot actually attaching to it. The robot then evolves to state Connected phototaxis believing to be assembled with other robots. Considering instead the second behaviour, once a robot i grabs a robot j, i becomes itself “willing to be grabbed” (turning on its red LEDs) to allow other robots to connect to the assembly. Now, it is clear that if j is grabbed while being in state Assembly Seed, then its transition towards state Aggregate is allowed, leading to the second bizarre behaviour. Interestingly enough, we hence notice that the two bizarre behaviors strongly depend on the duration of the timeout: a short one favors the first behaviour, while a long one favors the second one. Are these behaviors actually possible in real robots or are they forbidden by real life constraints (e.g. due to the physical structure of the robots or to some real-time aspects)? We have still no answer to this question which is subject of current work (in the context of the ASCENS project [4]). So far, we observed that the self-assembly strategies described in [16] might be adequate for s-bots but not in general for self-assembly settings where other constraints might apply. 6.2
Statistical Model Checking
A qualitative analysis can prove that an assembly strategy can result in different degrees of success, from full success (all robots reach the goal) to full failure (no robot reaches the goal). However, in the kind of scenario under study different levels of success are typically assumed. The really interesting question is how probable are they? Moreover, another interesting measure could be the expected number of robots reaching the goal. An analysis based on statistical model checking (see e.g. [19, 20, 2]) is more appropriate in these cases. Such techniques do not yield the absolute confidence of qualitative model checking but allow to analyze (up to some statistical errors and at different levels of confidence) larger scenarios and to deal with the stochastic nature of probabilistic systems. We consider the following properties: (P0 ) What is the probability that no robot reaches the goal? ; (P1 ) What is the probability that at least one robot reaches it? ; and (P2 ) What is the expected number of robots reaching the goal?
64
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
We have used PVesta [2], a parallel statistical model checker and analysis tool, to perform some comparative analysis. PVesta performs a statistical evaluation (Monte Carlo based) of properties expressed in the transient fragments of PCTL and CSL, and of quantitative temporal expressions (QuaTEx)[1], allowing to query about expected values of real-typed expressions of a probabilistic model. We performed a comparative analysis (with respect to the above properties) between robots equipped differently. We use 4-bots, an abstraction of real s-bots with only 4 LEDs and sensors and capable to move and grip in only 4 directions (up, down, left, right); and 8-bots, which are like 4-bots, but enriched with LEDs, sensors, and movement and gripping capabilities in 4 additional directions (the diagonals). All robots execute the same strategy, namely basic self-assembly response. The aim was not to derive exact statistical measures but to gain some intuition of the success and performance impact of the different robot models. The arena was configured as follows (cf. Fig. 8): an 11 × 7 grid containing 3 robots, the goal (a source of light) and a hole dividing the robots from the goal. We remind that an robot alone is not able to cross the hole, and hence needs to cooperate (assemble) with other robots to cross it. In general, the 8-bots exhibit a better success rate. Indeed, the only morphology of assembled robots that offers a full success for three 4-bots is a line orthogonal to the hole. In all the other possible morphologies, at least one 4-bot falls in the hole or remains isolated in the left part of the arena. More precisely, the analysis of P0 on the 4-bots provides values around 0.5 (i.e. about half of the cases ends up without any 4-bot reaching the goal). For 8-bots this value is approximately half as much. Regarding the success of at least one robot (P1 ), the 8-bots exhibit again a much better rate (around 0.8) than the 4-bots (around 0.5). Finally, the expected number of successful 4-bots (P2 ) is about less than one, while for the 8-bots case it is around one and a half. These preliminary data of the statistical analys seems to confirm intuition. As we argue above, the less topological constraints are imposed on the robots the more flexible their behavior is. Forthcoming experiments will try to accurately estimate the above mentioned (and other) properties, extending our comparative analysis to consider other robot features and strategies, and validate our reFig. 8. An initial state. sults with the ones reported in [16].
A Sample QuaTEx Expression. We conclude this section discussing the quantitative temporal expression we defined to estimate the expected number of robots reaching the goal. QuaTEx [1] is a language to query quantitative aspects of probabilistic systems. Exactly as temporal logics allows to express temporal formulae, QuaTEx allows to write quantitative temporal expressions.
Adaptative Self-Assembling Strategies with Maude
65
PVesta statistically evaluates quantitative temporal expressions with respect to two parameters: α and δ. Specifically, expected values are computed from n independent simulations, with n large enough to grant that the size of the (1−α)100% confidence interval for the expected value is bounded by δ. Intuitively, if a QuaTEx expression is estimated as x, then, with probability (1 − α), its actual value belongs to the interval [(1 − δ)x, (1 + δ)x]. In the rest of this section we see how the mentioned QuaTEx expression has been defined, and how its value is actually computed for single simulations. We do not detail how PVesta performs one-step systems executions, since this is out of the scope of this paper. Details can be found in [1]. Before defining our expression it is necessary to define real-typed Maude operations representing the states predicates we are interested in. We defined the state predicate completed : Configuration -> Float, reducing to 1.0 for terminal (absorbing) states, and to 0.0 otherwise. A terminal state is a state with no more robots, a state with all the robots in goal, or the state obtained after a given maximum number of steps. We also defined the state predicate countRobotInGoal : Configuration -> Float, counting the number of succesful robots. Then we defined the equations necessary to PVesta to access such predicates (where C is a variable with sort Configuration): eq val(0,C) = completed(C), and eq val(1,C) = countRobotInGoal(C). Actually QuaTEx’s syntax requires to indicate the term “val(n,s)” with “s.rval(n)”, where n and s are respectively terms with sort Natural and Configuration. Finally, the QuaTEx expression to estimate the expected number of robots reaching the goal is easily expressed as count_s-bots_in_goal() = if { s.rval(0) == 1.0 } then s.rval(1) else #count_s-bots_in_goal() fi; eval E[ count_s-bots_in_goal() ] ;
Informally, a QuaTEx expression consists in a list of definitions of recursive temporal operators, followed by a query of the expected value of a path expression obtained (arithmetically) combining the temporal operators. Our formula defines the temporal operator count s-bots in goal(), which also corresponds to the estimated path expression eval E[ count s-bots in goal() ]. The path expression is evaluated by PVesta in the initial state (s) of the system (e.g. the state depicted in Fig. 8). The tool first evaluates the guard of the if then else statement, i.e. s.rval(0) == 1.0. The condition reads as “is the state predicate rval(0) equal to 1.0 if evaluated in the state s?”, corresponds to “is the current state a final state?”. If the guard is evaluated to true, then the path expression is evaluated as s.rval(1), that is in the number of robots that reached the goal in the state s. If the guard is evaluated to false, then the path expression is evaluated as #count s-bots in goal(), read “evaluate count s-bots in goal() in the state obtained after one step of execution”. The symbol #, named “next”, is in fact a primitive temporal operator. To conclude, the evaluation of the QuaTEx expression consists in performing step-wise system simulations, and is evaluated as the (mean of the) number of robots that reached the goal in the terminal states of each simulation.
66
7
R. Bruni, A. Corradini, F. Gadducci, A. Lluch Lafuente and A. Vandin
Conclusion
The contributions of our paper are: (i) a description (§4,§5) of how to realize in Maude our recently proposed approach to adaptive systems [6] in a simple and natural way; and (ii) a description (§6) of how to exploit some Maude tools for the analysis of our models, and PVesta [2] in particular. Our work is inspired by early approaches to coordination and adaptation based on distributed object reflection [14, 21] and research efforts to apply formal analysis onto such kind of systems (e.g. [13]), with a particular focus on adaptive systems (e.g. [22, 4]). Among those, the PAGODA project [22] is the closest in spirit and shape. Our work is original in its clear and neat representation and role of control data in the architecture, and in the fact that this is, as far as we know, the first analysis of self-assembly strategies based on statistical model checking. The case study of self-assembly strategies for robot swarms [16] has contributed to assess our approach. Overall, the experimentation we have conducted demonstrates that Maude is well-suited for prototyping self-assembly systems in early development phases, and that the associated simulation can be useful to discover and resolve small ambiguities and bugs in self-assembly strategies. Furthermore, statistical model checking can provide rough estimation of success rate, that can be used to compare different strategies and also to validate/confute/refine analogous measures provided by other tools or in real world experiments. We plan to further develop our work by considering other case studies, more realistic abstractions and more modular implementations. However, the real challenging question to be tackled is can we exploit the proposed architecture to implement smarter adaptation strategies or to facilitate their analysis? We envision several interesting paths in this regard. First, we are investigating how logical reflection can be exploited at each layer of the architecture, for instance to equip components with dynamic planning capabilities based on symbolic reachability techniques. Second, we are developing a compositional reasoning technique that exploits the hierarchical structure of the layered architecture. All in all, we believe that our work is a promising step towards the non-trivial challenges of building predictive adaptive systems, and to analyze them.
References 1. Agha, G.A., Meseguer, J., Sen, K.: PMaude: Rewrite-based specification language for probabilistic object systems. In: Cerone, A., Wiklicky, H. (eds.) QAPL 2005. ENTCS, vol. 153(2), pp. 213–239. Elsevier (2006) 2. AlTurki, M., Meseguer, J.: PVeStA: A parallel statistical model checking and quantitative analysis tool. In: Corradini, A., Klin, B., Cˆırstea, C. (eds.) CALCO 2011. LNCS, vol. 6859, pp. 386–392. Springer (2011) 3. Andersson, J., de Lemos, R., Malek, S., Weyns, D.: Reflecting on self-adaptive software systems. In: SEAMS 2009. pp. 38–47. IEEE (2009) 4. Autonomic Service Component Ensembles (ASCENS), http://www.ascens-ist.eu 5. Broy, M., Leuxner, C., Sitou, W., Spanfelner, B., Winter, S.: Formalizing the notion of adaptive system behavior. In: Shin, S.Y., Ossowski, S. (eds.) SAC 2009. pp. 1029–1033. ACM (2009)
Adaptative Self-Assembling Strategies with Maude
67
6. Bruni, R., Corradini, A., Lluch Lafuente, A., Gadducci, F., Vandin, A.: A conceptual framework for adaptation. In: de Lara, J., Zisman, A. (eds.) FASE 2012. LNCS, vol. 7212, pp. 240–254. Springer (2012) 7. Cabri, G., Puviani, M., Zambonelli, F.: Towards a taxonomy of adaptive agentbased collaboration patterns for autonomic service ensembles. In: Smari, W.W., Fox, G.C. (eds.) CTS 2011. pp. 508–515. IEEE Computer Society (2011) 8. Clavel, M., Dur´ an, F., Eker, S., Lincoln, P., Mart´ı-Oliet, N., Meseguer, J., Talcott, C.L.: All About Maude, LNCS, vol. 4350. Springer (2007) 9. Horn, P.: Autonomic Computing: IBM’s perspective on the State of Information Technology (2001) 10. IBM Corporation: An Architectural Blueprint for Autonomic Computing (2006) 11. Karsai, G., Sztipanovits, J.: A model-based approach to self-adaptive software. Intelligent Systems and their Applications 14(3), 46–53 (1999) 12. Kephart, J.O., Chess, D.M.: The vision of autonomic computing. Computer 36(1), 41–50 (2003) 13. Meseguer, J., Sharykin, R.: Specification and analysis of distributed object-based stochastic hybrid systems. In: Hespanha, J., Tiwari, A. (eds.) HSCC 2006, LNCS, vol. 3927, pp. 460–475. Springer (2006) 14. Meseguer, J., Talcott, C.: Semantic models for distributed object reflection. In: Magnusson, B. (ed.) ECOOP 2002, LNCS, vol. 2374, pp. 1–36. Springer (2002) 15. Mondada, F., Pettinaro, G.C., Guignard, A., Kwee, I.W., Floreano, D., Deneubourg, J.L., Nolfi, S., Gambardella, L.M., Dorigo, M.: Swarm-bot: A new distributed robotic concept. Autonomous Robots 17(2-3), 193–221 (2004) 16. O’Grady, R., Groß, R., Christensen, A.L., Dorigo, M.: Self-assembly strategies in a group of autonomous mobile robots. Autonomous Robots 28(4), 439–455 (2010) 17. Pavlovic, D.: Towards semantics of self-adaptive software. In: Robertson, P., Shrobe, H.E., Laddaga, R. (eds.) IWSAS 2000. LNCS, vol. 1936, pp. 65–74. Springer (2000) 18. Salehie, M., Tahvildari, L.: Self-adaptive software: Landscape and research challenges. ACM Transactions on Autonomous and Adaptive Systems 4(2), 1–42 (2009) 19. Sen, K., Viswanathan, M., Agha, G.: On statistical model checking of stochastic systems. In: Etessami, K., Rajamani, S.K. (eds.) CAV 2005. LNCS, vol. 3576, pp. 266–280. Springer (2005) 20. Sen, K., Viswanathan, M., Agha, G.A.: Vesta: A statistical model-checker and analyzer for probabilistic systems. In: Baier, C., Chiola, G., Smirni, E. (eds.) QEST 2005. pp. 251–252. IEEE Computer Society (2005) 21. Talcott, C.L.: Coordination models based on a formal model of distributed object reflection. In: Brim, L., Linden, I. (eds.) MTCoord 2005. ENTCS, vol. 150(1), pp. 143–157. Elsevier (2006) 22. Talcott, C.L.: Policy-based coordination in PAGODA: A case study. In: Boella, G., Dastani, M., Omicini, A., van der Torre, L.W., Cerna, I., Linden, I. (eds.) CoOrg 2006 & MTCoord 2006. ENTCS, vol. 181, pp. 97–112. Elsevier (2007) 23. Weyns, D., Malek, S., Andersson, J.: FORMS: a formal reference model for selfadaptation. In: Figueiredo, R., Kiciman, E. (eds.) ICAC 2010. pp. 205–214. ACM (2010) 24. Zhang, J., Cheng, B.H.C.: Model-based development of dynamically adaptive software. In: Osterweil, L.J., Rombach, H.D., Soffa, M.L. (eds.) ICSE 2006. pp. 371–380. ACM (2006)
Some Like it Very Hot: Formal Modeling and Analysis of Extreme Heat Exposure to the Human Body in HI-Maude 1 ¨ ´ Muhammad Fadlisyah1 , Peter Csaba Olveczky , and Erika Abrah´ am2 1
2
University of Oslo, Norway RWTH Aachen University, Germany
Abstract. In this paper we use HI-Maude to model and analyze the human thermoregulatory system and the effect of extreme heat exposure to the human body. The case study is motivated by the 2010 Sauna World Championships, which ended in a tragedy when the last two finalists were severely burnt in surprisingly short time (one of them died the next day). HI-Maude is a recent rewriting-logic-based formal modeling language and analysis tool for complex hybrid systems whose components influence each others’ continuous dynamics. One distinguishing feature of HI-Maude is that the user only needs to describe the continuous dynamics of single components and interactions, instead of having to explicitly define the continuous dynamics of the entire system. HI-Maude analyses are based on numerical approximations of the system’s continuous behaviors. Our detailed models of human thermoregulation and the sauna used in the world championships allow us to use HI-Maude to formally analyze how long the human body can survive when experiencing extreme conditions, as well as analyzing possible explanations for the still unsolved tragedy in the 2010 Sauna World Championships.
Order-Sorted Equality Enrichments Modulo Axioms? Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha Department of Computer Science University of Illinois at Urbana-Champaign
Abstract. Built-in equality and inequality predicates based on comparison of canonical forms in algebraic specifications are frequently used because they are handy and efficient. However, their use places algebraic specifications with initial algebra semantics beyond the pale of theorem proving tools based, for example, on explicit or inductionless induction techniques, and of other formal tools for checking key properties such as confluence, termination, and sufficient completeness. Such specifications would instead be amenable to formal analysis if an equationally-defined equality predicate enriching the algebraic data types were to be added to them. Furthermore, having an equationally-defined equality predicate is very useful in its own right, particularly in inductive theorem proving. Is it possible to effectively define a theory transformation E 7→ E ' that extends an algebraic specification E to a specification E ' where equationally-defined equality predicates have been added? This paper answers this question in the affirmative for a broad class of order-sorted conditional specifications E that are sort-decreasing, ground confluent, and operationally terminating modulo axioms B and have a subsignature of constructors. The axioms B can consist of associativity, or commutativity, or associativity-commutativity axioms, so that the constructors are free modulo B. We prove that the transformation E 7→ E ' preserves all the just-mentioned properties of E. The transformation has been automated in Maude using reflection and it is used in Maude formal tools.
1
Introduction
It can be extremely useful, when reasoning about equational specifications with initial semantics, to have an explicit equational specification of the equality predicate as a binary Boolean-valued operator ‘'’. For example, in theorem proving where the logic of universal quantifier-free formulas is automatically reduced to unconditional equational logic so that the formula (u 6= v ∨ w = r) ∧ q = t becomes equivalent to the equation (not(u ' v) or w ' r) and q ' t = true, ?
This work has been supported in part by NSF Grant CCF 09-05584, the “Programa de Apoyo a la Investigaci´ on y Desarrollo” (PAID-02-11) of the Universitat Polit`ecnica de Val`encia, the EU (FEDER), the spanish MICINN/MINECO under Grant TIN2010-21062-C02 and by the Generalitat Valenciana, ref. PROMETEO/2011/052.
70
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
and in inductionless induction where inductive proofs are reduced to proofs by consistency because any equation not holding inductively makes true = false. An equationally-defined predicate can as well be useful in the elimination of built-in equalities and inequalities that often are introduced in algebraic specifications through built-in operators. Such built-in equalities and inequalities are not defined logically but operationally, for both expressiveness and efficiency reasons, by comparison of canonical forms. However, their non-logical character renders any formal reasoning about specifications using them impossible. In particular, the use of formal tools such as those checking termination, local confluence, or sufficient completeness of an algebraic specification is impossible with built-in equalities and inequalities, but becomes possible when they are replaced by an equationally axiomatized equality predicate ‘'’. That is, the equality between t and t0 is now expressed as t ' t0 = true, and their inequality as t ' t0 = false. Furthermore, the equality t ' t0 will still be correct when t and t0 are terms with variables, whereas a built-in equality predicate will often give a false negative answer for such terms, even when the equations are confluent and terminating. For example, for natural number addition ‘+’, defined by equations x + 0 = x and x + s(y) = s(x + y), the terms x + y and y + x are already in canonical form and a built-in equality predicate ‘≡’ will evaluate x + y ≡ y + x to false. Instead, x + y ' y +x will remain in canonical form with ‘'’ and one can then inductively prove x + y ' y + x = true using the equations defining ‘+’ and ‘'’. In principle, the meta-theorem of Bergstra and Tucker [2] ensures that any computable data type can be axiomatized as an initial algebra defined by a finite number of Church-Rosser and terminating equations. This also means that such a computable data type plus its equality predicate is also finitely axiomatizable by a finite set of Church-Rosser and terminating equations. However, the BergstraTucker result is non-constructive in the sense that it does not give an algorithm to actually obtain the equational specification of the data type with its equality predicate. Therefore, what would be highly desirable in practice is a general constructive theory transformation E 7→ E ' that adds equationally-axiomatized equality predicates to an algebraic data type specification E. Such a transformation should be as general as possible for it to be useful in practice. For example, a transformation applicable only to “vanilla-flavored” specifications without support for types and subtypes, or that excludes conditional equations and rewriting modulo axioms would be extremely limited. The transformation should also come with strong preservation properties. For example, if E is ground confluent, ground operationally terminating, and sufficiently complete, then E ' should also enjoy these same properties that are often essential both for executability and for a variety of formal reasoning forms. These generality and property-preservation requirements on the transformation E 7→ E ' are a tall order. For instance, if f is a free constructor symbol, then the equations f (x1 , . . . , xn ) ' f (y1 , . . . , yn ) = x1 ' y1 and . . . and xn ' yn and f (x1 , . . . , xn ) ' g(y1 , . . . , ym ) = false, for each constructor g 6= f of same type, give a perfectly good and straightforward axiomatization of equality for f . But how can the equality predicate be defined when f satisfies, e.g., associativity and
Order-Sorted Equality Enrichments Modulo Axioms
71
commutativity axioms? Also, how should sorts and subsorts be dealt with? An even harder issue is the preservation of properties such as ground confluence, operational termination, and sufficient completeness. The difficulty is that for any given specification there are tools that can be used to prove such properties, but we need a proof that will work for all specifications in a very wide class. What we actually need are metatheorems ensuring that these properties are preserved under the transformation for any equational specification in the input class. We present in this paper an effective theory transformation E 7→ E ' that satisfies the above-mentioned preservation properties. The class of equational theories E accepted as inputs to the transformation is quite general. Modulo mild syntactic requirements, it consists of all order-sorted theories E of the form (Σ, E ] B) having a subsignature Ω of constructors and such that: (i) B is a set of associativity, or commutativity, or associativity-commutativity axioms1 ; (ii) the equations E can be conditional and are sort-decreasing, ground confluent, and operationally terminating; and (iii) the constructors Ω are free modulo B, i.e., there is an isomorphism TΣ/E]B |Ω ∼ = TΩ/B of initial algebras. Outline. Preliminaries on order-sorted equational specifications are presented in Section 2. Section 3 contains the definition and fundamental properties of an equality enrichment. Sections 4 and 5 present the transformation E 7→ E ' and state its basic metatheorems. An overview on the implementation of the transformation, some of its practical consequences, and a case study are presented in Section 6. The extended version of this paper [9] contains the details and proofs of the mathematical development. The implementation of the transformation, the case study, and more examples are available at http://camilorocha.info.
2
Preliminaries
We assume basic knowledge on term rewriting [1] and order-sorted algebra [7]. Order-Sorted Signatures and Terms. We assume an order-sorted signature Σ = (S, ≤, F ) with a finite poset of sorts (S, ≤) and a finite set of function symbols F . We also assume that the function symbols in F can be subsort overloaded and satisfy that if f ∈ Fw,s ∩ Fw0 ,s0 then w ≡≤ w0 implies s ≡≤ s0 , where ≡≤ denotes the equivalence relation generated by ≤ on S and (w, s), (w0 , s0 ) ∈ S ∗ × S. We say that f : s1 · · · sn → s ∈ F is a maximal typing of f in Σ if there is no other f : s01 · · · s0n → s0 ∈ F such that si ≤ s0i , 1 ≤ i ≤ n, and s ≤ s0 . We let X = {Xs }s∈S be an S-sorted family of disjoint sets of variables with each Xs countably infinite. The set of Σ-terms of sort s is denoted by TΣ (X)s and the set of ground terms of sort s is denoted by TΣ,s , which we assume nonempty for each s. We let TΣ (X) and TΣ denote the corresponding order-sorted term algebras. The set of variables of a term t is written Var(t) and is extended to 1
Identity axioms are excluded from our transformation. However, by using the transformation described in [5] and subsort-overloaded operators, one can often extend our transformation to specifications that also include identity axioms.
72
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
sets of terms in the natural way. A substitution θ is a sorted mapping from a finite subset Dom(θ) ⊆ X to TΣ (X) and extends homomorphically in the natural way; Ran(θ) denotes the set of variables introduced by θ. The application of a substitution θ to a term t is denoted by tθ and the composition of two substitutions θ1 and θ2 is denoted by θ1 θ2 . A substitution θ is called ground iff Ran(θ) = ∅. We assume that all order-sorted signatures are preregular [7], so that each Σ-term t has a least sort ls(t) ∈ S such that t ∈ TΣ (X)ls(t) . Order-Sorted Equational Theories. A Σ-equation is an expression t = t0 with t ∈ TΣ (X)s , t0 ∈ TΣ (X)s0 , and s ≡≤ s0 . A conditional V Σ-equation is a Horn clause t = t0 if C with t = t0 a Σ-equation and C = i ui = vi a finite conjunction of Σ-equations. An equational theory is a tuple (Σ, E) with Σ an order-sorted signature and E a finite set of conditional Σ-equations. For ϕ a conditional Σ-equation, (Σ, E) ` ϕ iff ϕ can be proved from (Σ, E) by the deduction rules in [13] iff ϕ is valid in all models of (Σ, E) [13]. An equational theory (Σ, E) induces the congruence relation =E on TΣ (X) defined for any t, u ∈ TΣ (X) by t =E u iff (Σ, E) ` (∀X) t = u. We let TΣ/E (X) and TΣ/E denote the quotient algebras induced by =E on the algebras TΣ (X) and TΣ , respectively. We call TΣ/E the initial algebra of (Σ, E) and call a conditional Σ-equation ϕ an inductive consequence of (Σ, E) iff TΣ/E |= ϕ, i.e., iff (∀θ : X −→ TΣ )(Σ, E) ` ϕθ. A theory inclusion (Σ, E) ⊆ (Σ 0 , E 0 ), with Σ ⊆ Σ 0 and E ⊆ E 0 , is called protecting iff the unique Σ-homomorphism TΣ/E −→ TΣ 0 /E 0 |Σ of the Σ-reduct of the initial algebra TΣ 0 /E 0 is a Σ-isomorphism. Executability Conditions. We assume that the set of equations of an equational theory can be decomposed into a disjoint union E ] B, with B a collection of axioms (such as associativity, and/or commutativity, and/or identity) for which there exists a matching algorithm modulo B producing a finite number of B-matching substitutions, or failing otherwise. Furthermore, we assume that all axioms in B are sort-preserving, i.e., for each u = v ∈ B and substitution θ we have ls(uθ) = ls(vθ). The conditional equations E can be oriented into a set of (possibly conditional) (ground) sort-decreasing, (ground) operationally terminat− → ing [12], and (ground) confluent conditional rewrite rules E modulo B. We let − → →E/B denote the one-step rewrite relation induced by E modulo B on TΣ (X), and let →∗E/B denote its reflexive and transitive closure. A set of rewrite rules − → E modulo B is: (i) sort-decreasing iff for each t = t0 if C ∈ E and substitution
θ we have ls(tθ) ≥ ls(t0 θ) if (Σ, E ] B) ` Cθ; (ii) operationally terminating iff − → there is no infinite well-formed proof tree modulo B in E [5]; and (iii) confluent if for all t, t0 , t00 ∈ TΣ (X), if t →∗E/B t0 and t →∗E/B t00 , then there is u ∈ TΣ (X) − →
such that t0 →∗E/B u and t00 →∗E/B u. A set of rewrite rules E modulo B is ground sort-decreasing, ground operationally terminating, and ground confluent iff it is, respectively, sort-decreasing, operationally terminating, and confluent for ground terms. We let t ↓E/B ∈ TΣ,s (X) denote the E-canonical form of t modulo B, i.e., t →∗E/B t↓E/B and t↓E/B cannot be further rewritten. Under the above assumptions t↓E/B is unique up to B-equality.
Order-Sorted Equality Enrichments Modulo Axioms
73
Free Constructors Modulo. Given E = (Σ, E ] B) ground sort-decreasing, ground confluent, and ground operationally terminating modulo B, we say that Ω ⊆ Σ is a subsignature of free constructors modulo B iff Ω has the same poset of sorts as Σ and for each sort s in Σ and ground term t ∈ TΣ,s there is a u ∈ TΩ,s satisfying t =E]B u and, moreover, v↓E/B =B v for each v ∈ TΩ,s .
3
Equality Enrichments
An equality enrichment [14] of an equational theory E is an equational theory E ' extending E that defines equality in TE as a Boolean-valued function, as stated in Definition 1. In this section we fix an order-sorted signature Σ = (S, ≤, F ) and an order-sorted equational theory E = (Σ, E) with initial algebra TE . Definition 1 (Equality Enrichment) (generalizes [14, Definition 68]). An equational theory E ' = (Σ ' , E ' ) is called an equality enrichment of E, with Σ ' = (S ' , ≤ ' , F ' ) and Σ = (S, ≤, F ), iff – E ' is a protecting extension of E; – the poset of sorts of Σ ' extends (S, ≤) by adding a new sort Bool that belongs to a new connected component, with constants > and ⊥ such that TE ' ,Bool = {[>], [⊥]}, with > = 6 E ' ⊥; and – for each connected component in (S, ≤) there is a top sort k ∈ S ' and a binary commutative operator ' : k k −→ Bool in Σ ' , such that the following holds for any ground terms t, u ∈ TΣ,k : E `t=u E 6` t = u
⇐⇒ ⇐⇒
E ' ` (t ' u) = >, E
'
` (t ' u) = ⊥.
(1) (2)
An equality enrichment E ' of E is called Boolean iff it contains all the function symbols and equations making the elements of TE ' ,Bool a two-element Boolean algebra. The equality predicate ' in E ' is sound for inferring equalities and inequalities in the initial algebra TE , even for terms with variables. The precise meaning of this claim is given by Proposition 1. Proposition 1 (Equality Enrichment Properties). Let E ' = (Σ ' , E ' ) be an equality enrichment of E. Then, for any Σ-equation t = u with X = Var(t) ∪ Var(u): TE |= (∀X) t = u
⇐⇒
TE ' |= (∀X) (t ' u) = >,
(3)
TE |= (∃X) ¬(t = u)
⇐⇒
TE ' |= (∃X) (t ' u) = ⊥,
(4)
TE |= (∀X) ¬(t = u)
⇐⇒
TE ' |= (∀X) (t ' u) = ⊥.
(5)
Note that by using an equality enrichment E ' of E, the problem of reasoning in TE about a universally quantified inequality ¬(t = u) (abbreviated t 6= u) can be reduced to reasoning in TE ' about the universally quantified equality
74
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
(t ' u) = ⊥. A considerably more general reduction, not just for inequalities but for arbitrary quantifier-free first-order formulae, can be obtained with Boolean equality enrichments, as stated in Corollary 1. Corollary 1. Let E ' = (Σ ' , E ' ) be a Boolean equational enrichment of E. Let ϕ = ϕ(t1 = u1 , . . . , tn = un ) be a quantifier-free Boolean formula whose atoms are the Σ-equations ti = ui with variables in X, for 1 ≤ i ≤ n, and with Boolean connectives in {¬, ∨, ∧}. Then, the following holds TE |= (∀X)ϕ
⇐⇒
TE ' |= (∀X) ϕ(t b 1 ' u1 , . . . , tn ' un ) = >,
(6)
where ϕ(t b 1 ' u1 , . . . , tn ' un ) is the Σ ' -term of sort Bool obtained from ϕ by replacing every occurrence of the logical connectives ¬, ∨, and ∧ by, respectively, the function symbols ¬ , t , and u in E Bool (making TE,Bool a Boolean algebra) and every occurrence of an atom ti = ui by the Bool term ti ' ui , for 1 ≤ i ≤ n. A key property of an equality enrichment E ' of E is that, if E ' is extended with any set E 0 of Σ-equations that are not satisfiable in TE , then the resulting extension is inconsistent so that one can derive the contradiction > = ⊥. Conversely, if the set E 0 of Σ-equations extending E ' is satisfiable in TE , then the resulting extension is consistent and therefore cannot yield a proof of contradiction. Statements (7) and (8) in Corollary 2 account for these two facts. Corollary 2 (generalizes [14, Theorem 74]). Let E ' = (Σ ' , E ' ) be a equational enrichment of E and let E 0 be a collection of Σ-equations. Then the following holds TE 6|= E 0 TE |= E
4
0
⇐⇒ ⇐⇒
(Σ ' , E ' ∪ E 0 ) ` > = ⊥, (Σ
'
,E
'
0
∪ E ) 6` > = ⊥.
(7) (8)
Equality Enrichments of Theories with Free Constructors Modulo
In this section we present the effective theory transformation E 7→ E ' for enriching order-sorted equational theories having free constructors modulo structural axioms with an equality predicate. We fix an order-sorted equational theory E = (Σ, E ] B), with Σ = (S, ≤, F ), and assume that Ω ⊆ Σ is a subsignature of free constructors modulo B, where B is a union of associative (A), commutative (C), and associative-commutative (AC) axioms. Furthermore, the following convention is adopted: for x a variable and s a sort, the expression xs indicates that x has sort s, i.e., x ∈ Xs . The theory transformation performed by E 7→ E ' consists of two main tasks or subtransformations. On input E, it first extends E by adding new sorts, the equational theory E Bool of Booleans with constructors > and ⊥ (and with the other usual Boolean connectives equationally defined), some auxiliary functions, and the predicate ' for each top sort in the input theory E. Then, it generates a set of equations defining ' that depend on the structural axioms of the symbols in Ω. More precisely,
Order-Sorted Equality Enrichments Modulo Axioms
75
Transformation 1: extends the input theory E by 1. generating a fresh top sort for each connected component in Σ that does not have it, 2. adding the theory E Bool with sort Bool , 3. adding a Boolean-valued (binary) commutative operator ' for the top sort of each connected component of E, and 4. adding for each f ∈ Ω with A or AC structural axioms the Booleanvalued unary operator root kf , and if f is AC adding also the Booleanvalued binary operator in kf . Transformation 2: for each f ∈ Ω, and depending on the structural axioms of f , generates a suitable set of equations defining ' , root kf , and in kf . Auxiliary Boolean-valued operators root kf and in kf are useful for checking if terms are rooted by or contain the constructor symbol f , respectively. In this paper we use the Boolean theory E Bool specified in [3, Subsection 9.1]. The theory E Bool has free constructors modulo B Bool , it is sort-decreasing, confluent, and operationally terminating modulo AC, and hence provides a Boolean decision procedure. It has signature of free constructors Ω Bool = {>, ⊥}, set of defined 6 ⊥. The symbols Σ Bool \ Ω Bool = { ¬ , u , t , , ⊃ }, and satisfies TE Bool |= > = choice of E Bool is somewhat arbitrary: any equational theory implementing a Boolean decision procedure should suffice for our purposes. Definition 2 spells out in detail Transformation 1 and prepares the ground for Transformation 2. Definition 2 (Enrich). Given E, the transformation E 7→ E ' generates the smallest equational theory E ' = (Σ ' , E ' ] B ' ) satisfying: – E ∪ E Bool ⊆ E ' ; – the poset of sorts of E ' extends that of E by adding a new connected component {Bool }, and by adding a fresh top sort to any connected component of the poset of sorts of E lacking a top sort; – for each top sort k in Σ ' of a connected component of Σ, Σ ' contains a commutative operator: ( ' ) : k k → Bool , B ' contains the commutative structural axiom: xk ' yk = yk ' xk , and E ' contains the equation: xk ' xk = >; – for each top sort k in Σ ' of a connected component of Σ and for each function symbol f : s s0 → s00 ∈ Ω, with s ≤ k, s0 ≤ k, and s00 ≤ k: • if f has axioms A or AC, then Σ ' contains the symbol: root kf : k → Bool ,
76
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
• if f has axioms AC, then Σ ' contains the symbol: in kf : k k → Bool ; – for each function symbol f ∈ Ω, E ' contains the equations enrichE (f ) (see the upcoming definitions). Function enrichE in Definition 2 formally specifies Transformation 2 and is defined by cases for each constructor symbol depending on its structural axioms. We start with the definition of enrichE for the case in which the constructor symbol has no structural axioms; we call such a symbol absolutely free. Definition 3 (Absolutely Free Enrich). Assume f ∈ Ω is an absolutely free symbol. Then, for each maximal typing f : s1 . . . sn → s of f ∈ Ω, enrichE (f ) adds the following equations: – for each g : s01 . . . s0m → s0 ∈ Ω a maximal typing of g such that s ≡≤ s0 and f 6= g: f (x1s1 , . . . , x1sn ) ' g(ys101 , . . . , ysm0m ) = ⊥, – for f itself: f (x1s1 , . . . , xnsn ) ' f (ys11 , . . . , ysnn ) =
l
xisi ' ysi i ,
1≤i≤n
– for each 1 ≤ i ≤ n such that si ≡≤ s: f (x1s1 , . . . , xnsn ) ' xisi = ⊥. In Definition 3, some equations use the Boolean operator u in E Bool to obtain a recursive definition of ' . Example 1 shows the results of applying Definition 2 and Definition 3 to a concrete specification. Example 1. Consider the equational theory E NATURAL in Figure 1 (left) that represents the natural numbers in Peano notation. An equality enrichment consists of E NATURAL extended with the equational theory E Bool and an equational definition of ' . The equational theory in Figure 1 (right) is an equality enrichment of E NATURAL . The last equation is not essential, but it is useful for detecting a greater number of inequalities between terms with variables. Definition 4 presents the definition or enrichE for the case in which the input symbol is commutative. For the definition of enrichE in the case of an commutative function symbol f with maximal typing of sort s0 , it is assumed that its two arguments have the same sort s. Definition 4 (C-Enrich). Assume f ∈ Ω is commutative and non-associative. Then, for each maximal typing f : s s → s0 of f ∈ Ω, enrichE (f ) adds the following equations:
Order-Sorted Equality Enrichments Modulo Axioms
fmod NATURAL is sort Nat . op 0 : -> Nat [ctor] . op s : Nat -> Nat [ctor] . endfm
77
fmod EQ-NATURAL is protecting NATURAL . protecting BOOL . op ~ : Nat Nat -> Bool [comm] . vars N M : Nat . eq N ~ N = true . eq 0 ~ s(N) = false . eq s(N) ~ s(M) = N ~ M . eq s(N) ~ N = false . endfm
Fig. 1. Equality Enrichment for E NATURAL .
– for each g : s01 . . . s0m → s00 ∈ Ω a maximal typing of g such that s0 ≡≤ s00 and f 6= g: f (x1s , x2s ) ' g(ys101 , . . . , ysm0m ) = ⊥, – for f itself: f (x1s , x2s ) ' f (ys1 , ys2 ) = (x1s ' ys1 u x2s ' ys2 ) t (x1s ' ys2 u x2s ' ys1 ), – if s ≡≤ s0 we add the equation: f (x1s , x2s ) ' x1s = ⊥. For the definition of enrichE in the case of an associative function symbol f with maximal typing of sort s, it is assumed that its two arguments have also sort s. Furthermore, a top typing for such an f is also assumed, i.e., a typing f : s0 s0 → s0 satisfying that if f : s s → s is another typing with s ≡< s0 , then s0 ≥ s (note that a top typing of f may not belong to Ω, as in Example 2 below). Definition 5 (A-Enrich). Assume f ∈ Ω is associative and non-commutative. Then for each maximal typing f : s s → s of f ∈ Ω, enrichE (f ) adds the following equations: – for each g : s01 . . . s0m → s0 a maximal typing of g ∈ Ω such that s ≡≤ s0 and f 6= g: f (x1s , x2s ) ' g(ys01 , . . . , ysm0m ) = ⊥, root kf (g(x1s0 , . . . , xm s0m )) = ⊥, 1
– for f itself: root kf (f (x1s , x2s )) 1 f (xs , x2s ) ' f (x1s , ys2 ) f (x1s , x2s ) ' f (ys1 , x2s ) f (x1s , x2s ) ' f (ys1 , ys2 )
= >, = x2s ' ys2 , = x1s ' ys1 , =⊥ if ¬ (root kf (x1s )) u ¬ (root k (y 1 )) u f s ¬ (x1 ' y 1 ) = >, s s
78
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
fmod LIST is protecting NATURAL . sorts NeNatList NatList . subsorts Nat < NeNatList < NatList . op nil : -> NatList [ctor] . op ; : NeNatList NeNatList -> NeNatList [ctor assoc] . op ; : NatList NatList -> NatList [assoc] . var L : NatList . eq L ; nil = L . eq nil ; L = L . endfm fmod EQ-LIST is protecting LIST . protecting BOOL . protecting EQ-NATURAL . op ;-NeNL-root : NatList -> Bool . op ~ : NatList NatList -> Bool [comm] .
vars P Q R S : NeNatList . var N : Nat . eq ;-NeNL-root(0) = false . eq ;-NeNL-root(s(N)) = false . eq ;-NeNL-root(nil) = false . eq ;-NeNL-root(P ; Q) = true . eq P ~ P = true . eq 0 ~ nil = false . eq s(N) ~ nil = false . eq (P ; Q) ~ 0 = false . eq (P ; Q) ~ s(N) = false . eq (P ; Q) ~ nil = false . eq (P ; Q) ~ P = false . eq (P ; Q) ~ Q = false . eq (P ; Q) ~ (P ; R) = Q ~ R . eq (P ; Q) ~ (R ; Q) = P ~ R . ceq (P ; Q) ~ (R ; S) = false if (not(;-NeNL-root(P)) and not(;-NeNL-root(R)) and not(P ~ R)) = true . endfm
Fig. 2. Equality Enrichment for E LIST .
– for each 1 ≤ i ≤ 2: f (x1s , x2s ) ' xis = ⊥. Example 2. Consider the equational theory E LIST in Figure 2 that specifies the lists of natural numbers in Peano notation. Note that ; is a constructor symbol only when its arguments are non-empty lists. Therefore, the signature of free constructors modulo B of the theory E LIST is: {nil : → NatList, ; : NeNatList NeNatList → NeNatList}. In order to have a recursive definition of equality for lists, enrichE (f ) uses the auxiliary function root kf that checks if a term of sort k is rooted by the constructor symbol f . Figure 2 presents E EQ-LIST , an equality enrichment for E LIST . We illustrate the use of E EQ-LIST with the following two cases: – for ((0; 0); 0) ' ((0; 0); 0), the only applicable equations are P ' P = >, (P ; Q) ' (P ; R) = Q; R, and (P ; Q) ' (R; Q) = P ; R by proper associative commutations, and the result is always > independently of their application order; and
Order-Sorted Equality Enrichments Modulo Axioms
79
– for ((0; s(0)); 0) ' (s(0); 0) the last equation defined for E EQ-LIST is applicable under substitution σ(P ) = σ(S) = 0, σ(R) = s(0), and σ(Q) = s(0); 0 by proper associative commutations since it is the only equation that satisfies ¬ root NeNatList (0) u ¬ root NeNatList (s(0)) u ¬ 0 ' s(0) = >, thus obtaining ; ; ((0; s(0)); 0) ' (s(0); 0) = ⊥. In the case in which the input symbol of enrichE with maximal typing of sort s is associative-commutative, it is assumed that its two arguments also have sort s and there is a top typing for f , as in the associative case. Definition 6 (AC-Enrich). Assume f ∈ Ω is associative-commutative. Then for each maximal typing f : s s → s of f ∈ Ω, enrichE (f ) adds the following equations: – for each g : s01 . . . s0m → s0 a maximal typing of g ∈ Ω such that s ≡≤ s0 and f 6= g: f (x1s , x2s ) ' g(ys10 , . . . , ysm0m ) = ⊥, 1 root kf (g(x1s0 , . . . , xm s0m )) = ⊥, 1
– for f itself: root kf (f (x1s , x2s )) = >, in kf (xs , yk ) = ⊥ if root kf (xs ) = >, k in f (xs , f (xs , ys )) = > if ¬ (root kf (xs )) = >, k 1 1 2 in f (xk , f (ys , ys )) = (xk ' ys ) t in kf (xk , ys2 ) if ¬ (root kf (xk )) u ¬ (root k (y 1 )) = >, f s k in f (xk , yk ) = xk ' yk if ¬ (root kf (xk )) u ¬ (root k (y )) = >, f k f (xs , ys ) ' f (xs , zs ) = ys ' zs , if ¬ (root kf (x1s ))) u f (x1s , x2s ) ' f (ys1 , ys2 ) = ⊥ ¬ (in k (x1 , f (y 1 , y 2 ))) = >, s s s f f (x1s , x2s ) ' x1s = ⊥. Intuitively, if a term of sort k rooted by an associative-commutative symbol f is viewed as a multiset with union operator f , then function in kf in Definition 6 helps in identifying the cases in which an element (a term not rooted by f ) belongs to the multiset. Example 3. Consider the equational theory E MSET in Figure 3 defining multisets of natural numbers in Peano notation. Theory E EQ-MSET in Figure 3 is an equality enrichment for E MSET , where auxiliary functions root kf and in kf are used to give a recursive comparison of equality for constructor terms rooted by AC-symbols. Consider the following two cases: – for ((0 0) 1) ' ((0 1) 0), the only applicable equations are P ' P = > and (P Q) ' (P R) = Q R by proper associative-commutative commutations, and the result is always > independently of their application order; and
80
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
fmod MSET is protecting NATURAL . sorts NeNatMSet NatMSet . subsort Nat < NeNatMSet < NatMSet . op empty : -> NatMSet [ctor] . op : NeNatMSet NeNatMSet -> NeNatMSet [ctor assoc comm] . op : NatMSet NatMSet -> NatMSet [assoc comm] . var T : NatMSet . eq empty T = T . endfm fmod EQ-MSET is protecting MSET . protecting BOOL . protecting EQ-NATURAL . op -NeNMS-root : NatMSet -> Bool . op in--NeNMS : NatMSet NatMSet -> Bool . op ~ : NatMSet NatMSet -> Bool [comm] . vars P Q R S : NeNatMSet . var N : Nat . vars T U : NatMSet . eq -NeNMS-root(0) = false . eq -NeNMS-root(s(N)) = false .
eq -NeNMS-root(empty) = false . eq -NeNMS-root(P Q) = true . ceq in--NeNMS(P,Q) = false if -NeNMS-root(P) = true . ceq in--NeNMS(P, (P Q)) = true if not(-NeNMS-root(P)) = true . ceq in--NeNMS(T, (Q R)) = (T ~ Q) or in--NeNMS(T,R) if (not(-NeNMS-root(T)) and not(-NeNMS-root(Q))) = true . ceq in--NeNMS(T,U) = T ~ U if (not(-NeNMS-root(T)) and not(-NeNMS-root(U))) = true . eq P ~ P = true . eq 0 ~ empty = false . eq s(N) ~ empty = false . eq (P Q) ~ 0 = false . eq (P Q) ~ empty = false . eq (P Q) ~ s(N) = false . eq (P Q) ~ P = false . eq (P Q) ~ (P R) = Q ~ R . ceq (P Q) ~ (R S) = false if (not(-NeNMS-root(P)) and not(in--NeNMS(P, R S))) = true . endfm
Fig. 3. Equality Enrichment for E MSET .
– for ((0 s(0)) 0) ' (s(0) 0), we can apply the following equations: • (P Q) ' P = ⊥ under substitution σ(P ) = 0 s(0) and σ(Q) = 0 by proper associative-commutative commutations; • (P Q) ' (P R) = Q R under substitutions: ∗ σ(P ) = 0, σ(Q) = 0 s(0), and σ(R) = s(0), obtaining s(0) 0 ' s(0), and hence the only applicable equations now are: · P Q ' s(N ) = ⊥ using the substitution σ(P ) = s(0), σ(Q) = 0 (or vice versa), and σ(N ) = 0 · P Q ' P = ⊥ under substitution σ(P ) = s(0) and σ(Q) = 0, ∗ σ(P ) = s(0), σ(Q) = 0 0, and σ(R) = 0, obtaining 0 0 ' 0, and hence the only applicable equations now are: · P Q ' 0 = ⊥ using the substitution σ(P ) = 0 and σ(Q) = 0, · P Q ' P = ⊥ under substitution σ(P ) = 0 and σ(Q) = 0.
Order-Sorted Equality Enrichments Modulo Axioms
5
81
Executability Properties of E '
It would be enormously useful, both from a theoretical and a practical point of view, that if a theory E satisfies some executability properties, then that the equality enrichment E ' of E obtained from the transformation in Section 4 could inherit these properties. In particular, if the original theory E is sort-decreasing (resp., ground sort-decreasing), confluent (resp., ground confluent), and operationally terminating (resp., ground operationally terminating), then E ' must be so. Also, the subsignature of free constructors of E ' must be an extension of the subsignature of free constructors of E (modulo the structural axioms). In this way, full agreement between mathematical and operational semantics is preserved in the equality enrichment E ' of E. Note that the domain of the transformation E 7→ E ' includes exactly those equational theories whose structural axioms are any combination of A and/or C axioms for some of its symbols. However, if the input theory E has symbols with identity axioms, one could use the results in [5] to remove them and instead add them as equations, provided that the constructors remain free after the transformation. Note that, as illustrated by the LIST and MSET examples, where identities for lists and multisets are specified as oriented equations and not as axioms, this is often possible in practice. In what follows, E = (Σ, E ] B) is an order-sorted equational theory with signature of free constructors Ω ⊆ Σ modulo B and E ' = (Σ ' , E ' ] B ' ) is the Boolean equality enrichment E ' obtained by using the transformation E 7→ E ' . 5.1
Preservation of Executability Properties and Free Constructors
Recall from Section 2 that the equational theory E = (Σ, E]B) is sort-decreasing (resp., ground sort-decreasing) iff for each t = t0 if C ∈ E, and substitution (resp., ground substitution) θ with (Σ, E]B) ` Cθ, we have ls(tθ) ≥ ls(t0 θ). The key observation is that since[ Bool is a fresh sort in a new connected component ' of E and all equations in enrichE (f ) are of sort Bool , it is impossible that f ∈Ω
the equations in E Bool or in
[
enrichE (f ) can be applied to terms in TΣ .
f ∈Ω
Theorem 1. If E is sort-decreasing (resp., ground sort-decreasing), then E ' is sort-decreasing (resp., ground sort-decreasing). The notion of reductive theory is used in proving E ' operationally terminating. Definition 7 (Reductive Theory Modulo Axioms). Let be the strict subterm relation on terms. An equational theory E = (Σ, E ] B) is reductive modulo B iff there exists a reduction ordering and a symmetric, stable, and monotonic relation ∼ such that: V 1. l ∈ / X for each equation l = r if V i=1..n ti = ui ∈ E. 2. l r for each equation l = r if i=1..n ti = ui ∈ E.
82
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
3. l( ∪)+ ti and l( ∪)+ ui for each equation l = r if 4. u ∼ v for each equation u = v ∈ B 5. ∼ ; ⊆.
V
i=1..n ti
= ui ∈ E.
Lemma 1. If an equational theory E = (Σ, E ] B) is reductive modulo B, then it is operationally terminating modulo B. In general, the union of two operationally terminating theories may not be operationally terminating. Furthermore, the fact of dealing with arbitrary theories whose rules are unknown makes the task of proving operational termination of the union more involved. However, sort information is used to obtain a proof of operational termination in the following way: 1. first, we prove that (Σ ' , E ] B ' ) is operationally terminating (resp., ground operationally terminating) and confluent (resp., ground confluent)2 , 2. then, we prove that (Σ ' , (E ' \ E) ] B ' ) is operationally terminating (resp., ground operationally terminating), 3. finally, we prove that the union of both theories is operationally terminating (resp., ground operationally terminating). Theorem 2. If E is sort-decreasing (resp., ground sort-decreasing), confluent (resp., ground confluent) and operationally terminating (resp., ground operationally terminating) in a Σ-extensible way, then E ' is operationally terminating (resp., ground operationally terminating). Since E ' is sort-decreasing by Theorem 1 and operationally terminating by Theorem 2, the confluence of E ' follows from its local confluence. Similarly, ground local confluence follows for the ground case. Theorem 3. If E is sort-decreasing (resp., ground sort-decreasing), operationally terminating (resp., ground operationally terminating) in a Σ-extensible way, and confluent (resp., ground confluent), then E ' is confluent (resp., ground confluent). The proof of Theorem 3 is obtained by case analysis. It considers the conditional critical pairs of E that are joinable by assumption, the critical pairs of E Bool that are also joinable by the choice of E Bool , and the conditional critical pairs of E ' \ (E ∪ E Bool ). Note that, since we may have B ' containing associative axioms, B ' -unification is infinitary in general. Hence, we have to reason about the possible form of any B ' -unifier that can involve a critical pair between two oriented equations with A symbols to conclude the local confluence of E ' . Lemma 2 is used for reasoning about the signature of constructors of E ' . 2
We assume that operational termination (resp., ground operational termination) of (Σ, E ] B) is Σ-extensible, i.e., if (Σ, E ] B) is operationally terminating (resp., ground operationally terminating) then (Σ ∪ ∆, E ] B) is so too. This is not a strong restriction in practice, since all the actual existing tools for proving termination properties on rewriting theories generate Σ-extensible orderings.
Order-Sorted Equality Enrichments Modulo Axioms
83
Lemma 2. Let E ' be obtained by using the transformation E 7→ E ' , where E is ground sort-decreasing, ground confluent, and ground operationally terminating in a Σ-extensible way, and Ω is the signature of free constructors modulo B of 0 E. Then, if t, t0 ∈ TΩ , then t ' t0 →+ E ' /B ' > iff t =B t . Intuitively, Lemma 2 states that E ' is a conservative extension of E for ground terms in Σ and the equationally defined equality predicate in E ' is well-defined. We identify Ω ' = Ω ] {>, ⊥} ⊆ Σ ' as a signature of constructors for E ' and prove that the constructors in Ω ' are free modulo B ' . Theorem 4. If E is ground sort-decreasing, ground confluent, and ground operationally terminating in a Σ-extensible way, and Ω is the signature of free constructors modulo B of E, then E ' has Ω ' = Ω ] {>, ⊥} ⊆ Σ ' as a signature of free constructors modulo B ' . 5.2
E ' is an Equality Enrichment
The properties of E ' inherited from E are very useful in proving that E ' is indeed an equality enrichment. Theorem 5. Let E = (Σ, E ] B) be an order-sorted equational theory with signature Ω ⊆ Σ of free constructors modulo B and let E ' = (Σ ' , E ' ] B ' ) be the equational theory obtained by using E 7→ E ' . If E is ground sortdecreasing, ground operationally terminating in a Σ-extensible way, and ground confluent modulo B, then E ' is a Boolean equality enrichment of E.
6
Automation and Applications of E 7→ E '
The transformation E 7→ E ' is obviously constructive and has been automated in Maude using its reflective features: it takes the meta-representation of E in Maude as input and constructs a meta-representation of E ' as output. The transformation itself has already been incorporated into Maude formal tools, including the Maude Church-Rosser and Coherence Checker [6] (CRC-ChC), and the Maude Invariant Analyzer tool [17]. 6.1
A Case Study
We present a case study in which the transformation E 7→ E ' is used in the Maude Invariant Analyzer (InvA) tool [17]. The InvA tool mechanizes an inference system for deductively proving safety properties of rewrite theories: it transforms all formal temporal reasoning about safety properties of concurrent transitions to purely equational inductive reasoning. The InvA tool provides a substantial degree of mechanization and can automatically discharge many proof obligations without user intervention. In this section, we illustrate how equality enrichments can be used to support the deductive verification task in the InvA tool for a mutual exclusion property of processes in the QLOCK protocol. The mutual exclusion protocol QLOCK uses a global queue as follows:
84
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
– each process that participates in the protocol does the following: • if the process wants to use the critical resource and its name is not in the global queue, it places its name in the queue; • if the process wants to use the critical resource and its name is in the global queue, if its name is at the top of the queue then the process gains access to the critical resource; otherwise it waits; and • if the process finishes the critical resource, it removes its name from the top of the global queue; – the protocol should start from a state where the queue is empty; and – it is assumed that each process can use the critical resource any number of times. Consider the following equational theory E QLOCK-STATE , which represents the states of QLOCK with terms of sort State. It protects the equational theory E MSET presented in Section 4. Processes and names of processes are modeled with natural numbers of sort Nat in Peano notation. A term Pi | Pw | Pc | Q of sort State describes the state in which Pi is the collection of processes whose name is not in the global queue (or idle processes), Pw is the collection of processes whose names that are waiting to gain access to the critical resource (or waiting processes), Pc is the collection of processes that are using the critical resource (or critical processes), and Q is the global queue of the system. Sorts MSet and Queue are used to represent collections of processes and queues of processes’ names, respectively. fmod QLOCK-STATE is protecting MSET .
sort Queue . op nil : -> Queue [ctor] . op _@_ : Nat Queue -> Queue [ctor] . op _;_ : Queue Queue -> Queue . eq nil ; Q:Queue = Q:Queue . eq (N:Nat @ Q1:Queue) ; Q2:Queue = N:Nat @ (Q1:Queue ; Q2:Queue) . sort State . op _|_|_|_ : MSet MSet MSet Queue -> State [ctor] . endfm
The behavior of a concurrent system in rewriting logic is specified by rewrite rules that define how the individual transitions change the state of the system. The specification of all transitions of QLOCK is described by six rewrite rules in the rewrite theory RQLOCK as follows. mod QLOCK is protecting QLOCK-STATE . vars Pi Pw Pc : MSet .
var Q : Queue .
rl [to-wait-1] : N | Pw | Pc | Q
=>
vars N N’ N’’ : Nat .
empty | Pw N | Pc
Order-Sorted Equality Enrichments Modulo Axioms | rl [to-wait-2] : | rl [to-crit-1] : rl [to-crit-2] : rl [to-idle-1] : rl [to-idle-2] : endm
Q ; (N @ nil ) . N Pi | Pw | Pc | Q => Pi | Pw N | Q ; (N @ nil ) . Pi | N | Pc | N @ Q => Pi | empty Pi | Pw N | Pc | N @ Q => Pi | Pw Pi | Pw | N | N’ @ Q => Pi N | Pw Pi | Pw | Pc N | N’ @ Q => Pi N |
85
Pc | Pc N | N @ Q . | Pc N | N @ Q . | empty | Q . Pw | Pc | Q .
Rewrite rules to-idle-1 and to-idle-2 specify the behavior of a process that finishes using the critical resource: it goes to state idle and the name on top of the global queue is removed. Similarly, rewrite rules to-wait-1 and to-wait-2, and to-crit-1 and to-crit-2, specify the behavior of a process that wants to use the critical resource and of a process that is granted access to the critical resource, respectively. We want to verify that the QLOCK system satisfies the following safety properties. It is key that: (i) it satisfies the mutual exclusion property, namely, that at any point of execution there is at most one process using the critical resource. We also want to verify that: (ii) the name on top of the global queue coincides with the name of the process using the critical resource, if any. Finally, we want to verify that: (iii) the global queue only contains the names of all waiting and critical processes. State predicates mutex , priority, and cqueue, respectively, specify properties (i), (ii), and (iii) in the following equational theory E QLOCK-PREDS . State predicate init specifies the set of initial states of QLOCK, with auxiliary function set? that characterizes multisets having no repeated elements. State predicate unique is a strengthening of mutex and priority. Auxiliary function to − soup on input Q of sort Queue computes the multiset of natural numbers appearing in Q. fmod QLOCK-PREDS is protecting QLOCK-STATE . protecting EQ-MSET . vars N N’ vars Pi Pw Pc
: Nat . : MSet .
var Q : Queue . var NeS : NeMSet .
ops init mutex unique priority cqueue : State -> [Bool] . eq eq eq eq eq eq eq eq eq eq
init( Pi | empty | empty | nil ) = set?(Pi) . mutex( Pi | Pw | empty | Q ) = true . mutex( Pi | Pw | N | Q ) = true . mutex( Pi | Pw | N NeS | Q ) = false . unique( Pi | Pw | empty | Q ) = set?(Pi Pw) . unique( Pi | Pw | N | N @ Q ) = set?(Pi Pw N) . unique( Pi | Pw | N NeS | Q ) = false . priority( Pi | Pw | empty | Q ) = true . priority( Pi | Pw | N | N’ @ Q ) = N ~ N’ . priority( Pi | Pw | N Pc | N’ @ Q ) = (N ~ N’) and
86
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha
(Pc ~ empty) . eq cqueue( Pi | Pw | Pc | Q ) = Pw Pc ~ to-soup(Q) . .... endfm
Observe that E QLOCK-PREDS protects the equality enrichment E EQ-MSET , in Section 4, for the connected component of sort MSet that defines the equality enrichment for sorts Nat, MSet, and NeMSet. The equality enrichments for these sorts are key in the specification of the state predicates. For instance, predicates priority and cqueue are directly defined in terms of the equality predicate for sorts Nat and MSet, and also use the Boolean connective for conjunction and that comes with the Boolean equality enrichment. Auxiliary function set? also makes use of the equality enrichment for sort Nat. Note that, in general, defining from scratch the equality enrichment for an AC-symbol such as the multiset union in E MSET , can be a daunting task. Instead, in E QLOCK-PREDS , the definition of the state predicate cqueue was straightforward with the help of the equality enrichment for multisets of natural numbers. By using the InvA tool we are able to automatically prove that predicates mutex and priority are invariants of RQLOCK for any initial state that satisfies predicate init. For predicate cqueue some proof obligations cannot be automatically discharged. In general terms, 22 out of 26 proof obligations were automatically discharged. However, this is an encouraging result, given that the current version of the InvA tool does not yet have dedicated inference support for Boolean equality enrichments, which could further improve the degree of automation.
7
Related Work and Conclusion
In [8], the author generalizes and simplifies the technique given in [15] for proving induction hypothesis without induction (so-called inductionless induction) using enriched theories with equality. The notion of s-taut related to a sort s can be seen as a initial approximation of what we called in this paper an equality enrichment. The technique described in the paper is based in the result stated in Corollary 2. In [14], the authors define the notion of equality enrichment (without axioms) as an explicit subrepresentation of an equational equality presentation. Our work extends this notion of equality enrichment with subsorts and axioms and also presents an automatic way to generate this equality enrichment modulo axioms. As the authors of [14] also remark, an equality enrichment can be used for inductionless induction theorem proving. In [16], the authors propose an equality predicate for algebraic specifications. Unlike our work, the authors do not consider axioms and sufficient completeness in their theories, hence they have to manage terms with defined symbols. In the positive cases, their equality predicate is equivalent to ours, but in the negative cases, a false answer in [16] does not mean that both terms are distinct for any possible instantiation (as we state in our work), because the negative rules are
Order-Sorted Equality Enrichments Modulo Axioms
87
based on a check of convergence between terms. The goal of this behavior is to avoid false positives instead of capturing negative cases. In conclusion, this paper solves an important open problem: how to make the addition of equationally defined equality predicates effective and automatic for a very wide class of equational specifications with initial algebra semantics. That such a transformation should exists is suggested by the Bergstra-Tucker meta-theorem [2], but such a meta-result is not constructive and gives no insight as to how the transformation could be defined. We have shown that it can be defined for a very wide class of algebraic specifications with highly expressive features such as order-sorted types, conditional equations, and rewriting modulo commonly occurring axioms. We have also shown that all the expected good properties of the input theory E are preserved by the transformation E 7→ E ' . Using reflection, the transformation has been implemented in Maude and has already been integrated into the Maude Church-Rosser and Coherence Checker [6] (CRC-ChC), and the Maude Invariant Analyzer tool [17]. In the near future it should be added to other tools such as the Maude Termination Tool [4] (MTT) and the Maude Sufficient Completeness Checker [11] (SCC). One obvious advantage of these additions is the possibility of systematically transforming specifications making use of built-in equalities and inequalities, which cannot be handled by formal tools, into specifications where such built-in equalities and inequalities are systematically replaced by equationally-defined equalities, so that formal tools can be applied. But this is not the only possible application by any means. For example, the case study in Subsection 6.1 shows how the addition of equationally-defined equality predicates also makes the specification and verification of safety properties in the InvA tool considerably easier. It is also clear that adding an equationally-defined equality to Maude’s Inductive Theorem Prover [10] (ITP) would make this tool more effective in many ways, and would also greatly reduce the complexities of dealing with arbitrary universal formulas as goals, since all such formulas could be reduced to unconditional equality goals. It would also be very useful to explore the use of the E 7→ E ' transformation in inductionless induction theorem proving. Yet another very useful field of application would be early failure detection in narrowingbased unification. The idea is that E ] B-unification goals can be viewed as equality goals, which can be detected to have already failed if they can be rewritten to false with E ' modulo B ' . In general, the contribution presented in this work opens many useful applications to improve the state of the art in formal verification of algebraic specifications using, in particular, the Maude formal environment.
References 1. Baader, F., Nipkow, T.: Term Rewriting and All That. Cambridge University Press (1998) 2. Bergstra, J., Tucker, J.: Characterization of Computable Data Types by Means of a Finite Equational Specification Method. In: de Bakker, J.W., van Leeuwen,
88
3.
4.
5.
6.
7.
8.
9.
10.
11.
12. 13.
14. 15.
16.
17.
Ra´ ul Guti´errez, Jos´e Meseguer, and Camilo Rocha J. (eds.) Proc. of the 7th International Colloquium on Automata, Languages and Programming, ICALP’80. LNCS, vol. 81, pp. 76–90. Springer-Verlag (1980) Clavel, M., Dur´ an, F., Eker, S., Lincoln, P., Mart´ı-Oliet, N., Meseguer, J., Talcott, C.: All About Maude – A High-Performance Logical Framework, LNCS, vol. 4350. Springer-Verlag (2007) Dur´ an, F., Lucas, S., March´e, C., Meseguer, J., Urbain, X.: Proving Operational Termination of Membership Equational Programs. Higher Order Symbolic Computation 21(1-2), 59–88 (2008) Dur´ an, F., Lucas, S., Meseguer, J.: Termination Modulo Combinations of Equational Theories. In: Ghilardi, S., Sebastiani, R. (eds.) Proc. of the 7th International Conference on Frontiers of Combining Systems, FroCoS’09. LNCS, vol. 5749, pp. 246–262. Springer-Verlag (2009) Dur´ an, F., Meseguer, J.: On the Church-Rosser and Coherence Properties of Conditional Order-Sorted Rewrite Theories. Journal of Logic and Algebraic Programming to appear (2011) Goguen, J., Meseguer, J.: Order-Sorted Algebra I: Equational Deduction for Multiple Inheritance, Overloading, Exceptions and Partial Operations. Theoretical Computer Science 105, 217–273 (1992) Goguen, J.A.: How to Prove Algebraic Inductive Hypotheses Without Induction. In: Bibel, W., Kowalski, R. (eds.) Proc. of the 5th Conference on Automated Deduction, CADE’80. LNCS, vol. 87, pp. 356–373. Springer-Verlag (1980) Guti´errez, R., Meseguer, J., Rocha, C.: Order-Sorted Equality Enrichments Modulo Axioms (Extended Version). Tech. rep., University of Illinois at Urbana-Champaing (December 2011), available at http://hdl.handle.net/2142/28597 Hendrix, J.: Decision Procedures for Equationally Based Reasoning. Ph.D. thesis, Department of Computer Science, University of Illinois at Urbana-Champaign, Urbana, IL, USA (2008) Hendrix, J., Clavel, M., Meseguer, J.: A Sufficient Completeness Reasoning Tool for Partial Specifications. In: Giesl, J. (ed.) Proc. of the 16th International Conference on Rewriting Techniques and Applications, RTA’05. LNCS, vol. 3467, pp. 165–174. Springer-Verlag (2005) Lucas, S., March´e, C., Meseguer, J.: Operational Termination of Conditional Term Rewriting Systems. Information Processing Letters 95(4), 446–453 (2005) Meseguer, J.: Membership Algebra as a Logical Framework for Equational Specification. In: Parisi-Presicce, F. (ed.) Recent Trends in Algebraic Development Techniques, Proc. of the 12th International Workshop on Workshop on Algebraic Development Techniques, WADT’97. LNCS, vol. 1376, pp. 18–61. Springer-Verlag (1997) Meseguer, J., Goguen, J.A.: Initially, Induction and Computability. Algebraic Methods in Semantics (1986) Musser, D.R.: On Proving Inductive Properties of Abstract Data Types. In: Proc. of the 7th Annual ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages, POPL’80. pp. 154–162. ACM Press (1980) Nakamura, M., Futatsugi, K.: On Equality Predicates in Algebraic Specification Languages. In: Jones, C.B., Liu, Z., Woodcock, J. (eds.) Proc. of the 4th International Conference on Theoretical Aspects of Computing, ICTAC’07. LNCS, vol. 4711, pp. 381–395. Springer-Verlag (2007) Rocha, C., Meseguer, J.: Proving safety properties of rewrite theories. In: Corradini, A., Klin, B., Cˆırstea, C. (eds.) Proc. of 4th International Conference on Algebra and Coalgebra in Computer Science, CALCO’11. LNCS, vol. 6859, pp. 314–328. Springer-Verlag (2011)
Timed CTL Model Checking in Real-Time Maude? 1,3 ´ ¨ Daniela Lepri1 , Erika Abrah´ am2 , and Peter Csaba Olveczky 1 University of Oslo, Norway RWTH Aachen University, Germany University of Illinois at Urbana-Champaign, USA 2
3
Abstract. This paper presents a timed CTL model checker for RealTime Maude and its semantic foundations. In particular, we show that our timed CTL model checking procedure is sound and complete for a fairly large class of systems. An important benefit of our model checker is that it also automatically provides a timed CTL model checker for subsets of modeling languages, like Ptolemy II and (Synchronous) AADL, which have Real-Time Maude model checking integrated into their tool environments.
1
Introduction
Real-Time Maude [28] extends Maude [13] to support the formal modeling and analysis of real-time systems in rewriting logic. Real-Time Maude is characterized by its expressiveness and generality, natural model of object-based distributed real-time systems, the possibility to define any computable data type, and a range of automated formal analysis such as simulation, reachability and temporal logic model checking. This has made it possible to successfully apply the tool to a wide range of real-time systems, including advanced state-of-theart wireless sensor network algorithms [16, 29], scheduling algorithms requiring unbounded queues [24], and routing protocols [30]. Real-Time Maude’s expressiveness and generality also make it a suitable semantic framework and analysis tool for modeling languages for real-time systems [22]. For example, the tool has been used to formalize the industrial avionics modeling standard AADL [23], a synchronous version of AADL [6], (subsets of) Ptolemy II discrete-event (DE) models [7], the web orchestration language Orc [2], etc. Real-Time Maude formal analysis has been integrated into the tool environment of some of these languages, enabling a model engineering process that combines the convenience of an intuitive modeling language with formal analysis. In Real-Time Maude, the data types of the system are defined by an algebraic equational specification, and the system’s instantaneous transitions are modeled ?
This work was partially supported by the Research Council of Norway through the Rhytm project, by the DAADppp HySmart project, and by AFOSR Grant FA875011-2-0084.
90
´ ¨ D. Lepri, E. Abrah´ am, and P. Cs. Olveczky
by (instantaneous) rewrite rules. Time advance is modeled explicitly by so-called tick (rewrite) rules of the form {t} => {t0 } in time u if cond , where {_} is an operator that encloses the entire global state, and the term u denotes the duration of the rewrite. Real-Time Maude is parametric in the time domain, which may be discrete or dense. For dense time (in particular), tick rules typically have the form {t} => {t0 } in time x if x {f (y + x)} in time x if x k r there is a one-step tick rewrite tj −→ t with ∆ ≤ dπj + r then there is an l π with ∆ ≤ dl , and – for each k, if for each j > k both a maximal tick step with duration 0 and an inst instantaneous rule can be applied in tj then tl −→ tl+1 is a one-step rewrite applying an instantaneous rule for some l > k. We denote the set of all timed fair paths of R starting in t0 by tfPaths R (t0 ). A term t is reachable from t0 in R in time r iff there is a path π ∈ tfPaths R (t0 ) with tπk = t and dπk = r for some k. A path π is time-divergent iff for each time value r ∈ Time there is an i ∈ N such that dπi > r. The Real-Time Maude tool [27] extends the Maude system [13] to support the specification, simulation, and analysis of real-time rewrite theories. RealTime Maude is parametric in the time domain, which may be discrete or dense, and defines a supersort TimeInf of Time which adds the infinity element INF. To cover all time instances in the dense time domain, tick rules should have one of the forms 4
0
Notice that t −→ t0 could be either a 0-time tick step or an instantaneous one-step rewrite.
94
´ ¨ D. Lepri, E. Abrah´ am, and P. Cs. Olveczky crl [tick] : {t} => {t0 } in time x if x {t0 } in time x if cond [nonexec] . (∗), or rl [tick] : {t} => {t0 } in time x [nonexec] . (§).
where x is a new variable of sort Time not occurring in {t} and cond. This ensures that the tick rules can advance time by any amount in rules of the form (∗) or (§) and any amount less than or equal to u in rules of the form (†). Rules of these forms are called time-nondeterministic and are not directly executable in general, since many choices are possible for instantiating the new variable x. In contrast to, e.g., timed automata, where the restrictions in the formalism allow the abstraction of the dense time domain by “clock regions” containing bisimilar states [3], for the more complex systems expressible in Real-Time Maude there is not such a discrete “quotient”. Instead, Real-Time Maude executes time-nondeterministic tick rules by offering a choice of different time sampling strategies [27], so that only some moments in the time domain are visited. For example, the maximal time sampling strategy advances time by the maximum possible time elapse u in rules of the form (†) (unless u equals INF), and tries to advance time by a user-given time value r in tick rules having other forms. In the default mode each application of a time-nondeterministic tick rule will try to advance time by a time value r. The paper [27] explains the semantics of Real-Time Maude in more detail. In particular, given a real-time rewrite theory R and a time sampling strategy σ, there is a real-time rewrite theory Rσ that has been obtained from R by applying the theory transformation corresponding to using the time sampling strategy σ when executing the tick rules. In particular, the real-time rewrite theory RmaxDef (r ) denotes the real-time rewrite theory R where the tick rules are applied according to the maximal time sampling strategy, while Rdef (r) denotes R where the tick rules are applied according to the default time sampling strategy (tick steps which advance time by 0 are not applied). A real-time rewrite theory R is time-robust if the following hold for all ground terms t, t0 , t00 of sort GlobalSystem and all ground terms r, r0 , of sort Time: – t = t0 holds in the underlying equational theory for any 0-time tick step 0 t −→0 t0 . r+r r – t −→ t00 if and only if there is a t0 of sort Time such that t −→ t0 and r0
t0 −→ t00 . r inst – If t −→ t0 is a tick step with r > 0, and t0 −→ t00 is an instantaneous one-step r rewrite, then t −→ t00 is a maximal tick step. r – for M = {r | ∃t0 . t −→ t0 } we have that either there is a maximal element in M or M is the whole domain of Time. Real-Time Maude extends Maude’s linear temporal logic model checker to check whether each behavior, possibly up to a certain time bound, satisfies an (untimed) LTL formula. State propositions are terms of sort Prop. The labeling of states with propositions can be specified by (possibly conditional) equations of the form {stateP attern} |= prop = b
Timed CTL Model Checking in Real-Time Maude
95
for b a term of sort Bool, which defines the state proposition prop to evaluate to b in all states matching the given pattern. We say that a set of atomic propositions is tick-invariant in R if tick rules do not change their values. Since the model checking commands execute time-nondeterministic tick rules according to a time sampling strategy, only a subset of all possible behaviors is analyzed. Therefore, Real-Time Maude analysis is in general not sound and complete. However, the reference [26] gives easily checkable sufficient conditions for soundness and completeness, which are satisfied by many large Real-Time Maude applications.
3
Timed CTL Model Checking for Real-Time Maude
In untimed temporal logics it is not possible to reason about the duration of/between events. There are many timed extensions of temporal logics [4, 31, 11]. In this paper we consider TCTL [5] with interval time constraints on temporal operators. 3.1
Timed CTL
In computation tree logic (CTL) [5], a state formula specifies a property over the computation tree corresponding to the system behavior rooted in a given state. State formulae are constructed by adding universal (A ) and existential (E ) path quantifiers in front of path formulae to specify whether the path formula must hold, respectively, on each path starting in the given state, or just on some path. Path formulae are built from state formulae using the temporal operators X (“next”) and U (“until”), from which F (“finally”) and G (“globally”) can be derived. Timed CTL (TCTL) is a quantitative extension of CTL [5], where the scope of the temporal operators can be limited in time by subscripting them with time constraints. In this paper we consider an interval-bound version of TCTL where the temporal operators are subscripted with a time interval. A time interval I is an interval of the form [a, b], (a, b], [a, b∞ ) or (a, b∞ ), where a and b are values of sort Time and b∞ is a value of sort TimeInf. Definition 1. Given a set Π of atomic propositions, TCTL formulae are built using the following abstract syntax: ϕ
::=
true
|
p
|
¬ϕ
|
ϕ∧ϕ
|
E ϕ UI ϕ
|
A ϕ UI ϕ
where p ∈ Π and I is a time interval. We omit the bound [0, ∞) as subscript and we write ≤ b, < b, ≥ a and > a for [0, b], [0, b), [a, ∞) and (a, ∞), respectively. We denote by TCTLcb the fragment of TCTL where all time bounds are of the form [a, b] with a < b, or [a, ∞).
´ ¨ D. Lepri, E. Abrah´ am, and P. Cs. Olveczky
96
3.2
Timed Kripke Structures and TCTL Semantics
The semantics of TCTL formulae is defined on Kripke structures. A Kripke structure is a transition system with an associated labeling function, which maps each state in the transition system to the set of atomic propositions that hold in that state. A timed Kripke structure is a Kripke structure where each transition has the r form s −→ s0 , where r denotes the duration of the transition step. Definition 2. Given a set of atomic propositions Π and a time domain T , a T timed Kripke structure is a triple T K = (S, −→, L) where S is a set of states, T −→⊆ S×T ×S is a transition relation with duration, and L is a labeling function T L : S → P(Π). The transition relation −→ is total,5 i.e., for each s ∈ S there T r T exist r ∈ T , s0 ∈ S such that (s, r, s0 ) ∈−→. We write s −→ s0 if (s, r, s0 ) ∈−→. We use a similar notation for timed paths in a timed Kripke structure T K as for r0 r1 real-time rewriteP theories. Thus, a timed path is written π = t0 −→ t1 −→ . . ., m−1 π π π we define dm = i=0 ri , tm = tm and rm = rm , and the set of all timed fair paths originating in state t is denoted by tfPaths T K (t). The semantics of TCTL formulae is defined as follows: T
Definition 3. For timed Kripke structures T K = (S, −→, L), states t ∈ S, and TCTL formulae ϕ, the pointwise satisfaction relation T K, t |=p ϕ is defined inductively as follows: T K, t |=p T K, t |=p T K, t |=p T K, t |=p T K, t |=p
true p ¬ϕ1 ϕ1 ∧ ϕ2 E ϕ1 UI ϕ2
iff iff iff iff
T K, t |=p A ϕ1 UI ϕ2 iff
always. p ∈ L(t). T K, t 6|=p ϕ1 . T K, t |=p ϕ1 and T K, t |=p ϕ2 . there exists π ∈ tfPaths T K (t) and an index k s.t. dπk ∈ I, T K, tπk |=p ϕ2 , and T K, tπl |=p ϕ1 for all 0 ≤ l < k. for each π ∈ tfPaths T K (t) there is an index k s.t. dπk ∈ I, T K, tπk |=p ϕ2 , and T K, tπl |=p ϕ1 for all 0 ≤ l < k. T
For a timed Kripke structure T K = (S, −→, L), a state t ∈ S and paths π, π 0 ∈ tfPaths T K (t) we say that π 0 is a simple time refinement of π if either rk π = π 0 or π 0 can be obtained from π by replacing a transition tk −→ tk+1 , r0
r 00
k k rk > 0, by a sequence tk −→ t −→ tk+1 of transitions for some t ∈ S and time values rk0 , rk00 > 0 with rk0 + rk00 = rk . A path π 0 is a time refinement of another path π if π 0 can be obtained from π by applying a (possibly infinite) number of time refinements. We also say that π is a time abstraction of π 0 .
5
T
T
T
A transition relation −→ can be made total by defining (−→)• =−→ ∪{(s, 0, s) ∈ T
S × T × S | ¬∃ s0 ∈ S, r ∈ T s.t. (s, r, s0 ) ∈−→}.
Timed CTL Model Checking in Real-Time Maude
97
Definition 4. The continuous-time satisfaction relation T K, t |=c ϕ is defined as the pointwise one for the first four cases; for the last two cases we have: T K, t |=c E ϕ1 UI ϕ2 iff there is a path π ∈ tfPaths T K (t) such that for each time refinement π 0 ∈ tfPaths T K (t) of π there is an 0 0 index k s.t. dπk ∈ I, T K, tπk |=c ϕ2 , and 0 T K, tπl |=c ϕ1 for all 0 ≤ l < k. T K, t |=c A ϕ1 UI ϕ2 iff for each path π ∈ tfPaths T K (t) there is a time refinement π 0 ∈ tfPaths T K (t) of π and an index k 0 0 s.t. dπk ∈ I, T K, tπk |=c ϕ2 , and 0 T K, tπl |=c ϕ1 for all 0 ≤ l < k. 3.3
Associating Timed Kripke Structures to Real-Time Rewrite Theories
To each real-time rewrite theory we associate a timed Kripke structure as follows: Definition 5. Given a real-time rewrite theory R = (Σ, E, R, φ, τ ), a set of atomic propositions Π and a protecting extension (Σ ∪ Π, E ∪ D) ⊇ (Σ, E), we define the associated timed Kripke structure T
T K(R)Π = (TΣ/E,GlobalSystem , (−→R )• , LΠ ), T
where (−→R )• ⊆ TΣ/E,GlobalSystem × TΣ/E,φ(Time) × TΣ/E,GlobalSystem contains r all transitions of the kind t −→ t0 which are also one-step rewrites in R and 0 all transitions of the kind t −→ t for all those states t that cannot be further rewritten in R, and for LΠ : TΣ/E,GlobalSystem → P(Π) we have that p ∈ LΠ (t) if and only if E ∪ D ` (t |= p) = true. We use this transformation to define R, LΠ , t0 |=c ϕ as T K(R)Π , t0 |=c ϕ, and similarly for the pointwise semantics. The model checking problems T K(R)Π , t0 |=p ϕ and T K(R)Π , t0 |=c ϕ are decidable if – the equational specification in R is Church-Rosser and terminating, – the set of states reachable from t0 in the rewrite theory R is finite, and – given a pair of reachable states t and t0 , the number of one-step rewrites of r the kind t −→ t0 in R is finite. As mentioned above, real-time rewrite theories generally contain a time-nondeterministic tick rule, but since Real-Time Maude executes such theories by applying a time sampling strategy σ, our model checker does not analyze R but the executable theory Rσ in which the time sampling strategy transformation has been applied. Thus, we associate a timed Kripke structure not to R, but to Rσ , and hence the third requirement is satisfied by all but the most esoteric cases; indeed, the tick rules in all Real-Time Maude applications we have seen are deterministic, in the sense that there is at most one one-step tick rewrite r t −→ t0 from any state, when the time sampling strategy is taken into account. We denote by T K(R, t0 )Π the timed Kripke structure associated to R which is restricted to states reachable from t0 , and for states t reachable from t0 we write R, LΠ , t |= ϕ for T K(R, t0 )Π , t |= ϕ.
98
4
´ ¨ D. Lepri, E. Abrah´ am, and P. Cs. Olveczky
Sound and Complete TCTL Model Checking for Real-Time Maude
As mentioned above, at least for dense time domains, Real-Time Maude only analyzes a subset of all possible behaviors in a real-time rewrite theory with time-nondeterministic tick rules, namely, those behaviors obtained by applying the tick rules according to a selected time sampling strategy. The paper [26] specifies some conditions on a real-time rewrite theory R and on the atomic propositions that ensure that model checking RmaxDef (r ) , i.e., using the maximal time sampling strategy, is indeed a sound and complete model checking procedure to check whether all behaviors in the original model R satisfy an LTL formula without the next operator. For example, if no application of a tick rule changes the valuation of the atomic propositions in a formula and instantaneous rewrite rules can only be applied after maximal tick steps or after applying an instantaneous rule, then model checking RmaxDef (r ) gives a sound and complete model checking procedure for R.6 This result yields a feasible sound and complete model checking procedure for many useful (dense-time) systems, such as “discrete-event” systems, that includes many systems that cannot be modeled as, e.g., timed automata. As explained in the introduction, this completeness result does not carry over to timed temporal logic properties. To keep the exposition simple, in the following we focus on dense time, since we can achieve sound and complete model checking for discrete time by exploring all possible tick steps in the pointwise semantics, and by advancing time by the smallest possible non-zero duration in the continuous semantics.7 Furthermore, in this paper we restrict our formalisms to TCTLcb .8 Our solution to achieve completeness for TCTLcb is to make sure that time progress “stops” at any time point when a time bound in the formula is reached. Since a TCTL formula must be recursively evaluated in each reachable state, we must make sure that from any reachable state we “stop” at a time relative to this state whenever a bound in the formula is reached. This condition is guaranteed if we split any tick step by an amount that divides all possible maximal tick durations and all possible finite non-zero time bounds in the formula. Let r¯ be the greatest common divisor of the durations of all maximal tick steps in RmaxDef (r ) reachable from the initial state and each finite non-zero time bound in the formula, then we divide each maximal tick step into smaller steps of duration 2r¯ . 6 7
8
The requirements in [26] are weaker than the above. This condition is generally stronger than what needed, in fact we could abstract theories with discrete time domain in a way similar to what we do for dense time, i.e. by advancing time by some value smaller than the r¯ explained in what follows, if possible. We are currently working on releasing the restriction to closed bounds. However, our proof for the completeness result cannot be directly extended to TCTL formulae with open bounds.
Timed CTL Model Checking in Real-Time Maude
99
To formalize this notion, let us first consider the time domain. Real-time rewrite theories are parametric in their time domain; the time domain must only satisfy some abstract properties given in some functional theory defined in [25] that defines the time domain abstractly as a commutative monoid (0, ≤, T ime) with some additional operators. The following functional theory states that there exists a function gcd on the non-zero time values with the expected properties and a commutative function middle that states that given two non-equal times x < y there is always a third time in between, that is x < middle(x,y) < y. fth GCD-TIME-DOMAIN is including LTIME-INF . sort NzTime . subsort NzTime < Time . cmb T:Time : NzTime if T:Time =/= 0 . op gcd : NzTime NzTime -> NzTime [assoc comm] . op _divides_ : NzTime NzTime -> Bool . op middle : Time Time -> NzTime [comm] . vars T1 T2 T3 : NzTime . vars T T’ : Time . eq T1 divides T1 = true . ceq T1 divides T2 = false if T2 < T1 . eq T1 divides (T1 + T2) = T1 divides T2 . eq gcd(T1, T2) divides T1 = true . ceq gcd(T1, T2) >= T3 if T3 divides T1 /\ T3 divides T2 . ceq middle(T, T’) > T = true if T’ > T . ceq middle(T, T’) < T’ = true if T’ > T . endfth
In the following we assume that all considered time domains satisfy the theory GCD-TIME-DOMAIN, and write gcd for the interpretation of gcd. The real-time rewrite theory Rgcd(t0 ,r,ϕ) is obtained from the tick-robust realtime rewrite theory R, a state t0 in R, and a TCTL formula ϕ, by advancing time by the greatest common divisor of all the following values: – all tick step durations appearing in paths from tfPaths RmaxDef (r ) (t0 ) and – all finite non-zero lower and upper bounds of all temporal operators in ϕ. Definition 6. For a real-time rewrite theory R whose time domain satisfies the theory GCD-TIME-DOMAIN, a non-zero time value r, a TCTL formula ϕ and a state t0 of R we define T1 (R, t0 , r) = {r0 ∈ NzTime | ∃π ∈ tfPaths RmaxDef (r ) (t0 ). ∃i ≥ 0. r0 = riπ } T2 (ϕ) = {r ∈ NzTime | there exists a subformula E ϕ1 UI ϕ2 or A ϕ1 UI ϕ2 of ϕ with r a non-zero finite lower or upper bound in I} GCD(R, r, ϕ, t0 ) = gcd(T1 (R, t0 , r) ∪ T2 (ϕ)) where gcd(T ) for a non-empty set T of time points is recursively defined as · 0 ) = gcd({gcd(r1 , r2 )} ∪ T 0 ). gcd({r}) = r and gcd({r1 , r2 }∪T If T1 (R, t0 , r) and T2 (ϕ) are finite then the GCD value is well-defined and we can define the real-time rewrite theory Rgcd(t0 ,r,ϕ) as follows:
100
´ ¨ D. Lepri, E. Abrah´ am, and P. Cs. Olveczky
Definition 7. Given a real-time rewrite theory R whose time domain satisfies the theory GCD-TIME-DOMAIN, a non-zero time value r, a TCTL formula ϕ, a state t0 of R, and assume that r¯ = GCD(R, t0 , r, ϕ) is a defined non-zero time value. Then Rgcd(t0 ,r,ϕ) is defined as R but where each tick rule of the forms (†), (∗), and (§) is replaced by the respective tick rule: crl [tick] : {t} => {t0 } in time x if x := r¯/2 /\ cond [nonexec] . crl [tick] : {t} => {t0 } in time x if x := r¯/2 /\ cond [nonexec] . crl [tick] : {t} => {t0 } in time x if x := r¯/2 [nonexec] .
The following lemma states that the evaluation of the formula ϕ and its subformulae do not change inside tick steps of Rgcd(t0 ,r,ϕ) . Lemma 1. Assume a time-robust real-time rewrite theory R whose time domain satisfies the theory GCD-TIME-DOMAIN. Let Π be a set of tick-invariant atomic propositions, and assume a protecting extension of R defining the atomic propositions in Π and inducing a labeling function LΠ . Let t0 be a state of R, r a non-zero time value of sort Time, ϕ a TCTLcb formula over Π, and assume that r¯ = GCD(R, t0 , r, ϕ) is a defined non-zero time value. Then for each subformula ϕ0 of ϕ, each time-divergent path π ∈ tfPaths R (t0 ) π rj−1
rπ
i and for all tick step sequences tπi −→ . . . −→ tπj in π satisfying n · r¯ < dπi < dπj < (n + 1) · r¯ for some n we have that
R, tπi |=c ϕ0
iff
R, tπj |=c ϕ0 .
Proof. The proof by induction on the structure of ϕ0 can be found in our technical report [18]. Based on the above lemma we gain our completeness result: Theorem 1. Let R, LΠ , t0 , r, ϕ and r¯ be as in Lemma 1. Then R, LP , t |=c ϕ
⇐⇒
Rgcd(t0 ,r,ϕ) , LP , t |=p ϕ
for all states t reachable in Rgcd(t0 ,r,ϕ) from t0 . Proof. The proof by induction on the structure of ϕ0 can be found in our technical report [18].
5
Implementation
Our model checker makes the natural and reasonable assumption that given a real-time rewrite theory R, and an initial state t0 on which we would like to check some TCTL formula ϕ, all behaviors starting from t0 are time-diverging w.r.t. the selected time sampling strategy σ. Notice that this assumption also implies T that the transition relation −→Rσ , in the respective timed Kripke structure r T K(Rσ , t0 )Π , consisting of all the one-step rewrites t −→ t0 in Rσ is total.
Timed CTL Model Checking in Real-Time Maude
101
Also notice that checking that all behaviors from the given t0 are time-diverging reduces, when the untimed reachable state space from t0 is finite, to checking that the timed Kripke structure associated to R has no zero-time loops. The current implementation of the model checker assumes that time values are either in NAT-TIME-DOMAIN-WITH-INF or POSRAT-TIME-DOMAIN-WITH-INF, and provides the user with two possible model-checking strategies: (i) The default strategy, in the pointwise semantics, which applies the userdefined time sampling strategy. (ii) The gcd strategy, which requires the maximal time sampling strategy and performs the model checking for the satisfaction problem Rgcd(t0 ,r,ϕ) , t0 |=p ϕ. Soundness and completeness of the gcd strategy might come at the cost of a larger state space due to the application of the gcd transformation, e.g. if the maximal time sampling strategy leads to tick step whose durations vary from very “small” ones to very “big” ones. When the gcd strategy is impractical, the user can still perform model checking in the pointwise semantics for TCTLcb formulae with the generally faster default strategy, which does not increase the system state space and can still be very useful to discover potential bugs, as illustrated below. Real-Time Maude, and hence our model checker, is implemented in Maude, making extensive use of Maude’s meta-programming capabilities. The model checker first constructs the timed Kripke structure, according to the selected model checking strategy, by collecting all the reachable states and transitions. When the gcd strategy is selected, the timed Kripke structure is refined by “splitting” the transitions into smaller ones of duration equal to the computed greatest common divisor. Then, the satisfaction sets of each subformula are recursively computed. Since the meta-representation of the states can be fairly large9 , performing the rest of the model checking procedure on the generated timed Kripke structure is fairly inefficient. In our current implementation, we assign a unique natural number to each (meta-represented) state in the generated timed Kripke structure, and construct a more compact timed Kripke structure, where all the occurrences of these meta-represented states are replaced by their respective identifiers. We then perform the recursive computation of the satisfaction set of ϕ, on this compact representation. This optimization led to a large performance improvement and made it feasible to apply our model checker to the case studies in reasonable time, especially in the Ptolemy II case, whereas working directly on meta-represented terms made model checking unfeasible even for simple case studies. Our implementation of the TCTL model checker is based on the explicit-state CTL model checking approach [8] that, starting with the atomic propositions, recursively computes for each subformula of the desired TCTL formula the set of satisfying reachable states. We implemented specific procedures for a basic set of 9
For example, each state in the Maude representation of the Ptolemy II model in Section 6 “contains” the entire Ptolemy II model.
102
´ ¨ D. Lepri, E. Abrah´ am, and P. Cs. Olveczky
temporal modal operators and we expressed other formulae into this canonical form. The basic set consists of the CTL modal operators E ϕ1 U ϕ2 , E G ϕ, the TCTL≤≥ 10 modal operators E ϕ1 U∼r ϕ2 with ∼∈ {>, ≥}, E ϕ1 U∼r ϕ2 with ∼∈ {0 ϕ2 and the TCTLcb modal operator E ϕ1 U[a,b] ϕ2 . The procedures for CTL modalities follow the standard explicit algorithm [8]. For TCTL≤≥ modalities, our implementation adapts the TCTL≤≥ model checking procedure defined in [17] for time-interval structures and to timed Kripke structures with time-diverging paths. The ease and flexibility of the Maude meta-level allowed us to implement the model checker reasonably quickly and easily. However, the convenience of operating at the meta-level comes at a certain cost in terms of computational efficiency, even with our optimizations. Therefore, the current Real-Time Maude model checker should be regarded as a working prototype for a C++ implementation that we plan to implement in the future. Our model checker is available at http://folk.uio.no/leprid/TCTL-RTM/ together with the technical report [18], the specifications and analysis commands of the case studies in this paper.
5.1
Using the Model Checker
In Real-Time Maude, the user is provided with two TCTL model checking commands, corresponding respectively to the default and gcd strategy, with syntax (mc-tctl t |= ϕ .)
and
(mc-tctl-gcd t |= ϕ .)
for t the initial state and ϕ one of the possible TCTL formula. The syntax of TCTL formulae is fairly intuitive, with syntactic sugar for (untimed) CTL formulae, common abbreviations and boolean connectors such as AF, EF, AG, EG, iff and implies, etc. For example, E true U≤r (¬ϕ∧A G (E F[a,b] ϕ0 )) is written as11 : E tt U[ (mc-tctl {init} |= AG((’HierarchicalTrafficLight . ’Decision | (port ’Error is present)) implies AF[ (mc-tctl {init} |= AG((’HierarchicalTrafficLight . ’Decision | (port ’Error is present)) implies AF[c a, b c] (’HierarchicalTrafficLight | (’Cyel = # 1, ’Cgrn = # 0, ’Cred = # 0)))) .)
Figure 2 shows the dialog window for the Real-Time Maude code generation of the hierarchical traffic light model: after entering the error handling property, a simple click on the Generate button will display the result of the model checking command execution in the “Code Generator Commands” box.
7
Conclusions and Future Work
We have described the semantic foundations of our TCTL model checker for Real-Time Maude. Our modeling formalism is more expressive than those of other timed model checkers, allowing us to analyze real-time systems which are beyond the scope of other verification tools. In particular, we have proved soundness and completeness of our model checker for a class of dense-time Real Time Maude specifications that contain many systems outside the scope of other real-time model checkers. Furthermore, the introduced TCTL model checker also provides for free a timed temporal logic model checker for interesting subsets of modeling languages widely used in industry, such as Ptolemy II and the avionics standard AADL. In future work, the model checker should also provide counter-examples in a user-friendly way, when possible. We want to relax the restriction to closed bounds and even extend our model checker to time-bounded TCTL model checking to support the model checking of systems with infinite reachable state space. Finally, the current version of the tool is implemented at the Maude meta-level; for efficiency purposes, it should be implemented in C++ in the Maude engine.
References 1. Aalst, W.M.P.v.d.: Interval timed coloured Petri nets and their analysis. In: Application and Theory of Petri Nets 1993. LNCS, vol. 691, pp. 453–472. Springer (1993) 2. AlTurki, M., Meseguer, J.: Real-time rewriting semantics of Orc. In: Proc. PPDP’07. ACM (2007) 3. Alur, R., Dill, D.L.: A theory of timed automata. Theoretical Computer Science 126(2), 183–235 (1994) 4. Alur, R., Henzinger, T.: Logics and models of real time: A survey. In: Real Time: Theory in Practice. LNCS, vol. 600. Springer (1992)
106
´ ¨ D. Lepri, E. Abrah´ am, and P. Cs. Olveczky
5. Alur, R., Courcoubetis, C., Dill, D.: Model-checking in dense real-time. Inf. Comput. 104, 2–34 (May 1993) ¨ 6. Bae, K., Olveczky, P.C., Al-Nayeem, A., Meseguer, J.: Synchronous AADL and its formal analysis in Real-Time Maude. In: ICFEM’11. LNCS, vol. 6991. Springer (2011) ¨ 7. Bae, K., Olveczky, P.C., Feng, T.H., Lee, E.A., Tripakis, S.: Verifying hierarchical Ptolemy II discrete-event models using Real-Time Maude. Science of Computer Programming (2011), to appear, doi:10.1016/j.scico.2010.10.002 8. Baier, C., Katoen, J.P.: Principles of Model Checking. MIT Press (2008) 9. Behrmann, G., David, A., Larsen, K.G.: A tutorial on uppaal. In: SFM-RT 2004. LNCS, vol. 3185. Springer (2004) 10. Boucheneb, H., Gardey, G., Roux, O.H.: TCTL Model Checking of Time Petri Nets. J Logic Computation 19(6), 1509–1540 (2009) 11. Bouyer, P.: Model-checking timed temporal logics. ENTCS 231, 323–341 (2009) 12. Clarke, E.M., Grumberg, O., McMillan, K.L., Zhao, X.: Efficient generation of counterexamples and witnesses in symbolic model checking. In: DAC ’95 (1995) 13. Clavel, M., Dur´ an, F., Eker, S., Lincoln, P., Mart´ı-Oliet, N., Meseguer, J., Talcott, C.: All About Maude, LNCS, vol. 4350. Springer (2007) 14. Eker, J., Janneck, J.W., Lee, E.A., Liu, J., Liu, X., Ludvig, J., Neuendorffer, S., Sachs, S., Xiong, Y.: Taming heterogeneity—the Ptolemy approach. Proceedings of the IEEE 91(2), 127–144 (2003) 15. Gardey, G., Lime, D., Magnin, M., Roux, O.H.: Rom´eo: A tool for analyzing time Petri nets. In: CAV’05. LNCS, vol. 3576. Springer, Edinburgh, Scotland, UK (2005) 16. Katelman, M., Meseguer, J., Hou, J.: Redesign of the LMST wireless sensor protocol through formal modeling and statistical model checking. In: Proc. FMOODS’08. LNCS, vol. 5051. Springer (2008) 17. Laroussinie, F., Markey, N., Schnoebelen, P.: Efficient timed model checking for discrete-time systems. Theor. Comput. Sci. 353, 249–271 (2006) ¨ ´ 18. Lepri, D., Olveczky, P.C., Abrah´ am, E.: Timed CTL model checking in Real-Time Maude, http://folk.uio.no/leprid/TCTL-RTM/tctl-rtm2011.pdf ¨ ´ 19. Lepri, D., Olveczky, P.C., Abrah´ am, E.: Model checking classes of metric LTL properties of object-oriented Real-Time Maude specifications. In: Proc. RTRTS’10. EPTCS, vol. 36, pp. 117–136 (2010) 20. Markey, N., Schnoebelen, P.: TSMV: A Symbolic Model Checker for Quantitative Analysis of Systems. In: QEST. IEEE Computer Society (2004) 21. Morasca, S., Pezz`e, M., Trubian, M.: Timed high-level nets. The Journal of RealTime Systems 3, 165–189 (1991) ¨ 22. Olveczky, P.C.: Semantics, simulation, and formal analysis of modeling languages for embedded systems in Real-Time Maude. In: Formal Modeling: Actors, Open Systems, Biological Systems. LNCS, vol. 7000. Springer (2011) ¨ 23. Olveczky, P.C., Boronat, A., Meseguer, J.: Formal semantics and analysis of behavioral AADL models in Real-Time Maude. In: Proc. FMOODS/FORTE’10. LNCS, vol. 6117. Springer (2010) ¨ 24. Olveczky, P.C., Caccamo, M.: Formal simulation and analysis of the CASH scheduling algorithm in Real-Time Maude. In: Proc. FASE’06. LNCS, vol. 3922. Springer (2006) ¨ 25. Olveczky, P.C., Meseguer, J.: Specification of real-time and hybrid systems in rewriting logic. Theoretical Computer Science 285, 359–405 (2002) ¨ 26. Olveczky, P.C., Meseguer, J.: Abstraction and completeness for Real-Time Maude. Electronic Notes in Theoretical Computer Science 176(4), 5–27 (2007)
Timed CTL Model Checking in Real-Time Maude
107
¨ 27. Olveczky, P.C., Meseguer, J.: Semantics and pragmatics of Real-Time Maude. Higher-Order and Symbolic Computation 20(1-2), 161–196 (2007) ¨ 28. Olveczky, P.C., Meseguer, J.: The Real-Time Maude tool. In: Proc. TACAS’08. LNCS, vol. 4963. Springer (2008) ¨ 29. Olveczky, P.C., Thorvaldsen, S.: Formal modeling, performance estimation, and model checking of wireless sensor network algorithms in Real-Time Maude. Theoretical Computer Science 410(2-3), 254–280 (2009) 30. Riesco, A., Verdejo, A.: Implementing and analyzing in Maude the enhanced interior gateway routing protocol. Electr. Notes Theor. Comput. Sci. 238(3), 249–266 (2009) 31. Wang, F.: Formal verification of timed systems: A survey and perspective. Proceedings of the IEEE 92(8), 1283–1307 (2004) 32. Wang, F.: REDLIB for the formal verification of embedded systems. In: Proc. ISoLA’06. IEEE (2006) 33. Wirsing, M., Bauer, S.S., Schroeder, A.: Modeling and analyzing adaptive usercentric systems in Real-Time maude. In: Proc. RTRTS’10. EPTCS, vol. 36, pp. 1–25 (2010) 34. Yovine, S.: Kronos: A verification tool for real-time systems. Software Tools for Technology Transfer 1(1–2), 123–133 (1997)
State Space c-Reductions of Concurrent Systems in Rewriting Logic? Alberto Lluch Lafuente1 , Jos´e Meseguer2 , and Andrea Vandin1 1 2
IMT Institute for Advanced Studies Lucca, Italy University of Illinois in Urbana-Champaign, USA
Abstract. We present c-reductions, a state space reduction technique. The rough idea is to exploit some equivalence relation on states (possibly capturing system regularities) that preserves behavioral properties, and explore the induced quotient system. This is done by means of a canonizer function, which maps each state into one (of the) canonical representative(s) of its equivalence class. The approach exploits the expressiveness of rewriting logic and its realization in Maude to enjoy several advantages over similar approaches: flexibility and simplicity in the definition of the reductions (supporting not only traditional symmetry reductions, but also name reuse and name abstraction); reasoning support for checking and proving correctness of the reductions; and automatization of the reduction infrastructure via Maude’s meta-programming features. The approach has been validated over a set of representative case studies, exhibiting comparable results with respect to other tools.
1
Introduction
State space reduction techniques have been extensively investigated since the birth of automated verification and have contributed to its success by enhancing the performance of tools and allowing the analysis of larger and larger systems. State space reduction techniques have been particularly successful in model checking [1], where techniques such as abstract interpretation, partial order reduction, and symmetry reduction allow to consider smaller though equivalent systems and thus save precious space and time resources. Symmetry reduction, for instance, enjoys a vast literature [2] but, while most of the authors agree on the effectiveness of the technique, symmetry reduction has not established itself as standard feature of verification tools as is the case of other state space reduction techniques. Notable examples are model checkers such as SPIN [3], where symmetry reduction and abstract interpretation are not built-in while other techniques like partial order reduction are. There are several reasons for this: (i) automatic detection of system regularities is a hard task, very often delegated to the system designer since there are only ?
Work supported by NSF Grant CCF 09-05584, AFOSR Grant FA8750-11-2-0084 and the EU Project ASCENS.
State Space c-Reductions of Concurrent Systems in Rewriting Logic
109
few solutions available (e.g. [4]); (ii) their exploitation is done by complementing (or enriching) the system description language with some meta-data in a different language, so that the user is hence required to use this new language; (iii) the implementation of state space reduction techniques has to be combined (both theoretically and practically) with the rest of the techniques and algorithms implemented in the model checker, and often this integration effort has to be repeated for every new version, improvement or technique of the model checker; and (iv) checking correctness of the defined reductions is not easy and requires reasoning techniques (e.g. theorem proving) that are not integrated in the model checking framework, or that are not part of the user’s skills. Our work started with the following question: can we use rewriting logic to generalize symmetry reduction techniques in a way that does not suffer the above problems (i)–(iv) and, in addition, effectively improves the performance of state space exploration? Our hope on the suitability of rewriting logic (and its realization in Maude [5]) for such purposes was motivated by the possibility of exploiting its expressiveness and formal verification support [6] (including model checking and theorem proving). Contributions. This paper offers a first answer to the above question by presenting a generalization of symmetry reductions called c-reductions. Its key idea is the reduction of each state into one of the canonical representatives of an equivalence class induced by a relation on states that preserves the system properties under study (i.e. a bisimulation). The approach is fully general: it subsumes many reduction techniques (symmetry reduction, name reuse and name abstraction) and can be applied to any Kripke structure. However, the method is particularly beneficial when Kripke structures are described by rewrite theories (and any computable Kripke structure can be formally specified by a finitely described rewrite theory [7]). The c-reduction approach tackles the above mentioned issues (i)–(iv) in the following way: (i) reductions are defined using ordinary ingredients of the system description language, namely functions and equations; (ii) the implementation of reductions does not interfere with the theory of rewriting logic or with the Maude engine and its commands, since it is essentially based on equational simplification, a standard feature of the setting; (iii) the approach is highly automatizable (thanks to Maude’s metaprogramming facilities based on logical reflection) and, at the same time, flexible enough to allow customization (e.g. by allowing the user to define the canonization functions or parts of them); (iv) correctness checks are semi-automatized by techniques well supported by the Maude formal environment, e.g. critical pair analysis to check that canonizer functions do not “interfere” with other functions and are “coherent” with respect to behavioural rules. We have evaluated our approach over an ample set of examples by considering the ease of defining reduction strategies, the effectiveness of the correctness checks, and the performance of the resulting reductions. With respect to previous works we have observed performance gains in some cases (including previous implementations of symmetry reductions in Maude [8]), more flexibility in the definition
110
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
of reductions, which allow us to subsume a wide range of reductions including permutation and rotation symmetries, name reuse and name abstraction, which have interesting applications (e.g. implementation of the operational semantics of languages with dynamic features such as resource allocation). A preliminary version of our tool is available for download [9]. Synopsis. §2 offers the necessary background. §3 presents the c-reduction technique in a generic way, focusing on Kripke structures. §4 describes the realization of c-reductions in rewriting logic, highlighting the theoretical results, and the reasoning and verification mechanisms and tools, that can be exploited to analyze and develop and c-reductions. §5 evaluates the performance of creductions through some representative examples. Finally, §6 concludes the paper, describes subjects of current work and outlines future research directions.
2
Preliminaries
We focus on system specifications in the form of theories of rewriting logic [6], which can be realized in practice in terms of Maude modules [5]. Definition 1 (rewrite theory). A rewrite theory R is a tuple R = (Σ, E ∪ A, R, φ) where Σ is a signature, specifying the basic syntax (function symbols) and type infrastructure (sorts, kinds and subsorting) for terms, i.e., state descriptions; E is a set of (possibly conditional) equations, which induce equivalence classes of terms, and (possibly conditional) membership predicates, which refine the typing information; A is a set of axioms which also induce equivalence classes of terms, i.e., equational axioms describing structural equivalences between terms, like associativity and commutativity; R is a set of (possibly conditional) nonequational rules, which specify the local concurrent transitions in a system whose states are E∪A-equivalence classes of ground Σ-terms; and where φ : Σ → Pfin (N) is a frozenness map, assigning to each function symbol f of arity n a subset φ(f ) ⊆ {1..n} of its frozen argument positions, i.e. positions under which rewriting with rules in R is forbidden. For the sake of simplicity, we assume that the system under study is described by a rewrite theory R = (Σ, E ∪ A, R, φ) whose rules are “topmost” for a designated kind [State] of states. We also assume that an operator { } is used to enclose states so that all transitions in R have that operator as their top operator in their lefthand sides. What follows can be of course generalized but the former assumptions facilitate the presentation. Finally, we shall assume that R has good executability properties, i.e., that E is sufficient complete, confluent and terminating modulo A (that is that the equational part correctly defines functions), and R is coherent with E modulo A [5] (that is that applying equations to evaluate functions does not interfere with the application of the rules that dictate the system transitions). Fortunately, the standard Maude tools offer some automatization support for checking such properties.
State Space c-Reductions of Concurrent Systems in Rewriting Logic
111
We consider a well-known semantical domain for rewrite theories, namely, Kripke structures, which are suitable to formulate state space exploration problems like model checking. Definition 2 (Kripke structure). A Kripke structure K is a tuple K = (S, →, L, AP ) such that S is a denumerable set of states, →⊆ S × S is a transition relation between states, and L : S → 2AP is a labelling function mapping states into sets of atomic propositions AP (i.e. observations on states). The Kripke semantics of a rewrite theory is defined as expected, with Statesorted terms as states and one-step rewrites between State-sorted terms as transitions. The labelling function is defined by Boolean predicates specified equationally in the rewrite theory. As proved in [7], any computable Kripke structure, even an infinite-state one, can be obtained from an executable rewrite theory using only a finite signature Σ, and finite sets E of equations, A of axioms and R of rules. Definition 3 (rewrite theory semantics). Let R = (Σ, E ∪ A, R, φ) be a rewrite theory with a designated state sort State, symbols and equations for a labelling function L ∈ Σ, and atomic propositions AP . The Kripke structure associated to R is KR = (TState/E∪A , →, LE/A , AP ) such that TState/E∪A are all State-sorted states, → is defined as {[u] → [v] | R ` u →1R,State v} (i.e. transitions are one-step rewrites between E ∪ A equivalence classes of Stateterms in R), and LE/A is the interpretation of L in the initial algebra TΣ/E∪A . We will consider bisimulation as the key semantic equivalence. Definition 4 (bisimulation). Let K = (SK , →K , LK , APK ), H = (SH , →H , LH , APH ) be two Kripke structures, and let ∼ ⊆ SK × SH be a relation between SK and SH . We say that ∼ is a bisimulation between K and H iff for each two states s ∈ SK and s0 ∈ SH such that s ∼ s0 we have that: (i) LK (s) = LH (s0 ); (ii) s →K r implies that there is a state r0 s.t. s0 →H r0 and r ∼ r0 ; and (iii) s0 →H r0 implies that there is a state r s.t. s →K r and r ∼ r0 . In what follows we shall focus on bisimulations such that the relation ∼ is an equivalence relation. In particular this includes the case of bisimulations induced by symmetries, i.e., when two states are bisimilar if they belong to the same class of symmetric states. This is precisely the case of those examples we use as a benchmark in the performance evaluation of §5, in which systems are composed by families of replicated concurrent processes with identical behavior. The nature of the symmetry depends very often on the communication topology. For example, in the well-known Peterson’s mutual exclusion protocol [10] there is a full symmetry between the processes: we can safely interchange any two processes as long as actual identifiers are not observed. Another example is the well-known Dijktra’s Dining Philosophers problem [11], which does not exhibit a full symmetry but a rotational one (due to the circular topology): any rotation of philosophers in a state yields a bisimilar state (if we are not interested in their actual identity).
112
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
Equivalence classes of symmetric states can be conveniently defined as the orbits of a group action, which yields the cases of symmetry reductions as special instances of our approach. We hence recall here some basic notions of groups. Definition 5 (groups, generators and actions). A group is a tuple (G, ◦) such that G is a set of elements and ◦ : G × G → G is a binary operation on G where ◦ is associative; there is an identity element e ∈ G such that ∀f ∈ G.f ◦ e = e ◦ f = f ; and each element f ∈ G has an inverse f −1 ∈ G such that f ◦ f −1 = f −1 ◦ f = e. Let (G, ◦) be a group and H ⊆ G be a subset of G. The group generated by H denoted hH, ◦i is defined as the closure of H under the inverse and product operators ( )−1 and ◦ of G. In general hH, ◦i will be a subgroup of (G, ◦), but if hH, ◦i coincides with (G, ◦), then H is said to generate G and its elements are called generators. Let (G, ◦) be a group and A be a set. A group action of G on A is a monoid homomorphism J·K : G → (A → A), that is, Jf ◦ gK = Jf K; JgK, where f ; g denotes function composition in (A → A), and JeK = idA , with idA the identity on A.
Notable examples are full symmetric and rotation groups, which capture typical symmetries introduced by replication (e.g. of processes with identical behavior) in concurrent systems. Generators define groups in a finite and concise manner. Well known examples of generators for full symmetric and rotation groups are transpositions and single rotations, respectively. Group actions (which allow us to apply group operations to concrete domains like state descriptions) can be defined by means of equations of the form [[f]](t) = t’ where f denotes a group element (possibly a generator) and t, t’ are State-sorted terms. Since rewriting logic (and its realization in Maude) allows to handle the axioms of sets (associativity, commutativity, identity), a group action can be described very concisely. For instance, consider the case of systems defined by multisets of attributed objects and the group of all permutations on object identifiers for which transpositions are generators. The application of transpositions can be defined (by structural induction) with the following equations eq eq eq eq eq eq
[[ij]](none) [[ij]](obj1 conf) [[ij]](< k | A1 >) [[ij]](i) [[ij]](j) [[ij]](k)
= = = = = =
none . [[ij]](obj1) [[ij]](conf) . < [[ij]](k) | [[ij](A1) > . j . i . k [owise] .
where none denotes the empty set, set union is denoted by juxtaposition and < k | A1 > denotes an object with identifier k and attributes A1. The equations for applying the transpositions to attributes, for example, to object references, are neglected here since they are example-specific. Such conciseness is crucial for our approach since most of the correctness checks rely on these equations: the fewer equations, the fewer proofs and checks to be carried out.
State Space c-Reductions of Concurrent Systems in Rewriting Logic
3
113
C-Reductions for Kripke Structures
This section introduces the idea of canonical reductions, abbreviated c-reductions as a generic means to reduce a Kripke structure K by exploiting some equivalence relation ∼ on the states of K which is also a bisimulation on K (i.e. between K and itself). In the next section we will explain how c-reductions are realized and analyzed in rewriting logic, where Kripke structures are specified by rewrite theories. We start by defining canonizer functions, which are used to compute for a given state a canonical representative of its equivalence class, modulo some equivalence relation which is also a bisimulation (e.g. a canonical permutation of the identifiers of processes with identical behavior). Definition 6 (canonizer functions). Let K = (S, →, L, AP ) be a Kripke structure, and let ∼⊆ S × S be a an equivalence relation which is a bisimulation on K. A function c : S → S is a ∼-canonizer (resp. strong ∼-canonizer) iff for each s ∈ S we have s ∼ c(s) (resp. s ∼ c(s), and s ∼ s0 → c(s) = c(s0 )). Canonizer functions are used to compute smaller but semantically equivalent (i.e. bisimilar) Kripke structures by applying canonizers after each transition. Strong canonizers provide unique representatives for the equivalence classes of states and, hence, more drastic space reductions. That is, for two different but equivalent states s ∼ s0 they provide the same canonical representative (i.e. c(s) = c(s0 )). Typical examples of strong canonizers for equivalence classes are functions based on enumeration strategies [4] which generate the complete set of states of the equivalence class and then apply some function over it (e.g. based on a total ordering of the states). For example, consider a system where some class of processes exhibit a full symmetry (like the afore-mentioned Peterson’s mutual exclusion protocol). Then an enumeration strategy canonizer just generates all states that result from permuting (symmetric) processes in all possible ways and then selects one according to some total order (e.g. the lexicographical order of the description of states). Of course, strong canonizers can be obtained in more efficient and smarter ways. An example is shown in §4.4. Instead, a non-strong (or weak) canonizer might provide different representatives for equivalent states, that is it might be the case that c(s) 6= c(s0 ) even though s ∼ s0 . Weak canonizers provide weaker space reductions but they sometimes enjoy advantages over strong canonizers. For instance, in some cases they are easier to be defined and analyzed, and their computation can be much more efficient in terms of runtime cost. Such heuristic canonizers can be found for instance in [12, 13] where the rough idea is to consider an ordering of the states that depends on part of the state description only. The resulting ordering relation is partial and the representative of a state is computed as one of the least states of the ordering (obtained by iteratively applying some monotonic operation like a transposition). The reduction of the state space is obtained by applying the canonizer to states after a transition. This is what we call a c-reduction.
114
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
Definition 7 (c-reduction of a Kripke structure). Let K = (S, →, L, AP ) be a Kripke structure, and let c : S → S be a ∼-canonizer function for some equivalence relation ∼∈ S × S which is a bisimulation on K. We call the Kripke structure Kc = (S, (→; c), L, AP ) the c-reduction of K, where the composed transition relation →; c is defined as {(s, c(r)) ∈ S 2 | s → r}. We sometimes decompose transitions s → c(s0 ) in Kc to make explicit the canonization step from a state s to its canonical representative c(s) with s → s0 →c c(s0 ). An important result is then that a c-reduction is bisimulation preserving. Theorem 1 (∼-preservation). Let K = (S, →, L, AP ) be a Kripke structure, let ∼ be an equivalence relation on S that is a bisimulation on K, and let c be a ∼-canonizer function. Then ∼ is a bisimulation relation between K and Kc . Proof. Let s and s0 be two arbitrary states of S such that s ∼ s0 . Condition (i) of Def. 4 holds trivially by the definition of ∼. Condition (ii) is also easy to see. Indeed if we have s → r, we know that s0 can simulate the transition s → r by a transition s0 → r0 since ∼ is a bisimulation on K. But then we have r ∼ c(r0 ) (since c preserves ∼, and ∼ is an equivalence relation an hence symmetric and transitive). Condition (iii) is also easy to show /r / r0 / c(r0 ) s s0 (c.f. beside figure (ii)). Indeed, a tranc O z: O c # O O : z c # z: #c sition s0 → r0 →c c(r), can be simu0 / / / 0 0 r c(r ) s s r lated by some transition s → r such c that r ∼ r0 since ∼ is a bisimulation (i) (ii) on K. But, as in the above case, we also have that r0 ∼ c(r) (since c preserves ∼ and ∼ is an equivalence relation and hence transitive). t u
4
C-Reductions in Rewriting Logic
We now describe a methodology for defining and analyzing c-reductions in rewriting logic. We shall often mention how such formalization can benefit from the tool support offered by the Maude framework such as Maude’s LTL Model Checker [14], Invariant Analyzer [15], Inductive Theorem Prover [16, 17] and Church Rosser and Coherence Checker [18]. We assume that there is some regularity in R (e.g. replicated process) that implicitly defines a bisimulation ∼ on states (e.g. a permutation of processes) to be exploited to ease the analysis of R. Our methodology is then based on the following steps: (i) implement the regularity correctly; if it is defined by a group action, implement the group action that induces ∼ and verify that it is indeed a group action (§4.1) which ensures ∼ to be an equivalence relation; (ii) verify that ∼ preserves the state predicates (§4.2); (iii) verify that ∼ is a bisimulation (§4.3); (iv) define a c-canonizer and show it to be a (possibly strong) ∼-canonizer (§4.4); (v) build the c-reduction of R (§4.5); and (vi) evaluate its performance (§5).
State Space c-Reductions of Concurrent Systems in Rewriting Logic
115
We remark that the steps of this methodology proceed by tackling different levels of abstraction so that they act as building blocks to be re-used whenever needed. For instance, verifying a c-reduction strategy does not require performing all the verification steps if it is based on a state equivalence that has been already proven to be correct. In practice, bisimulation relations and their canonizers need not to be defined and proven to be correct for every system, as there will be classes of systems for which they can be specified once and for all. In such cases, one can define reductions as theory transformations for wide classes of examples corresponding, for instance, to certain permutation groups, or to other useful equivalence relations besides the symmetry reduction case. In Maude this can be done by exploiting reflection, so that the c-reduction is automatized as a function at the metalevel, possibly after checking some proof obligations. Our current prototype [9], for instance, is able to apply some generic reductions to object based Maude modules. In addition, in some cases it may be more convenient to bypass some steps, for instance to check the correctness of a canonizer when it is not clear which is the underlying group action (which may not exist at all, since even if we focus here on group-theoretic reductions, c-reductions are more general). A last remark is that even if we put some stress on reductions based on group actions in some of the steps of our methodology, the c-reduction technique, in particular steps (v)-(vii), is more general and accepts arbitrary canonizers. The point of focusing on group action is to show an example of generic reduction that is amenable to semi-automatic correctness checks (steps (i)-(iv)). This paper puts the emphasis on steps (iv) to (vi) which constitute our main contribution here; while steps (i) to (iii) receive less attention since they are work in progress (though useful to illustrate the whole picture of our approach). 4.1
Checking group actions
In the case of equivalences yielded by group actions, one can start defining the group, the generators and their group actions and provide a formal proof of their properties. Many symmetries such as full and rotation symmetries have been identified and thoroughly studied in the past so we won’t pay much attention to this aspect in this work. In what follows we will sometimes instantiate our methodology on the particular case of symmetries assuming correctly defined groups, generators and actions. We assume that the relation on states we have to analyze is equationally defined by topmost equations relating two State-sorted terms. In the case of group actions with generators, we can just give equations of the form [[g]]({t}) = {t’}, for g being a generator (plus the equations defining the inverse operation, unless inverses of generators can be obtained by composition of generators as in the case of transpositions and rotations). Such equations define the actual application of a generator. An example of such equations was provided in §2. Of course, we need to check that for each generator g and each state u we have Jg ◦ g −1 K(u) = u, but this can be done easily because we can devise inductive proofs exploiting generators. For instance, in the case of full symmetries all we
116
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
have to do is to prove the equality Ji ↔ jK(Ji ↔ jK({t})) = {t}, i.e. that applying the same transposition of i and j (denoted i ↔ j) twice amounts to applying the identity so that rewrite steps are reversible. If one has correctly specified a group action, and in particular checked (or given as explicit equations) the monoid homomorphism equations [[id]]({t}) = {t} and [[g◦g’]]({t}) = [[g]]([[g’]]({t})) plus the above-mentioned check of the inverses for generators, one has already proved that ∼ is an equivalence relation. Indeed a group action implicitly defines an equivalence relation between states as follows {t} ∼ {t0 } ⇔ ∃f ∈ G s.t.Jf K({t}) = {t0 }. 4.2
Checking that ∼ preserves atomic predicates
To ensure that ∼ preserves the atomic predicates AP under consideration we can proceed as follows. We first define a rewrite theory R∼ for the sole purpose of this analysis defined as R∼ = (Σ ∪ Σ∼ , E ∪ E∼ ∪ A, {{t} => [[g]]({t})) | g is a generator or the inverse of a generator}, φ), where Σ∼ and E∼ extend the equational part of R with the definition of the equations for the functions generating the state orbits (e.g. the group generators) for the relation ∼. In words, we substitute the rules of R by rules that allow us to go from a state u to another state v that results from applying a generator (or the inverse of a generator) to u. If the action group is correctly defined (as we discussed in 4.1, i), it is easy to see (by the properties of the generators of a group) that in this rewrite theory two states are reachable if and only if they are in the same orbit, i.e. that the relation ∼ is defined by the rewrite relation →∗R∼ . That is, that u ∼ v holds exactly when the above defined rewrite theory can prove u →∗R∼ v. Moreover, proving that a predicate p is preserved by ∼ is exactly proving that p is invariant under R∼ . Such a proof can be greately facilitated if p is defined by pattern matching, i.e. by topmost unconditional equations of the form p({t}) = true. More formally, if we let R∼ be the rewrite theory defined above (and we check that the lefthand sides of all its rules are free constructor terms modulo A), all we have to do is to prove that for each rule {t’} => [[g]]({t’} ∈ R∼ , equation p({t}) = true ∈ E, and A-unifier θ between t’ and t (i.e. a mapping θ of variables into non-necessarily ground terms such that θ(t’) =A θ(t)), then we have p({θ([[g]]({t})}) = true. If such is the case, indeed, we can conclude that for each pair of states u, v ∈ TStateE /A it holds that u ∼ v implies p(u) = p(v), i.e. that p is invariant under ∼. Fortunately, Maude has a tool called the Invariant Analyzer [19, 15] (InvA) which can automate a good part of the effort of proving such invariants, leaving the remaining proof obligations for Maude’s inductive theorem prover [17]. As a matter of fact, as part of our experimentation we were able to use the tool to check that a simple neighborhood property of a model of the dining philosophers problem (“no two consecutive philosophers eating”) is invariant under rotations but not under arbitrary permutations. The first result was
State Space c-Reductions of Concurrent Systems in Rewriting Logic
117
obtained in a fully automatic way, while the second follows from an analysis of the few proof obligations provided by InvA. 4.3
Checking that ∼ is a bisimulation
Once ∼ has been shown to preserve the atomic predicates of interest, all there is left to check is that ∼ is a bisimulation. In our setting this amounts to checking the join/ {θ(t’)} {θ(t)} R ability of suitable “critical pairs” between the state R∼ R∼ ∗ transition rules {t} => {t’} if cond in our original / {w} set R, and the rules {t’’} => {t’’’} of R∼ . For A- {θ(t’’’)} R unifiers θ between t and t’’ bisimulation is ensured if we prove that for each critical pair denoted with ordinary arrows in the diagram on the right, there is a rule in R giving us a one-step rewrite {θ(t’’’)} →R {w} for which we can prove: {θ(t’)} →∗R∼ {w}. Part of this could be automatized by using Maude’s automated reachability analysis capabilities, possibly including narrowing-based ones since some of the above terms might not be ground (i.e. they might contain variables). Of course, it is not as easy as it sounds, since the above proofs are inductive, so that sometimes it may not be straightforward to show these properties for all ground terms just by rewriting terms with variables: some inductive arguments may also be needed. 4.4
Defining and analyzing canonizer functions
The next step is to define canonizer functions c : [State] → [State] in a protecting extension of the rewrite theory R under study. Note that in order to define the function c : [State] → [State] we may need to define some auxiliary functions (for example, the ordering relations used in symmetry reductions to determine a representative for each orbit). Definition 8 (c-extension of a rewrite theory). Let R = (Σ, E ∪ A, R, φ) be a rewrite theory and c a canonizer function. The c-extension of R is the rewrite theory Rc = (Σ ] Σc , E ∪ Gc ∪ A, R, φc ) where c ∈ Σc , and Σc \ {c} are other auxiliary functions; (Σ ] Σc , E ∪ Gc ∪ A) is a protecting extension of (Σ, E ∪ A), and is ground confluent, ground terminating, and sufficiently complete w.r.t. the same signature of constructors; and φc extends φ with frozenness maps for all arguments of all functions in Σc . Imposing frozenness on the operators of Σc is needed for the coherence result of Lemma 1. For a given bisimulation ∼ many candidate canonizers may exist, each leading to different results in terms of the size of the reduced state space and computational performance. In any case, all canonizer functions must enjoy correctness properties such as the extended equational theory being confluent, terminating, sufficiently complete with respect to constructors (which may be the same constructors as those of
118
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
(Σ, E ∪ A)). More importantly (for what regards our contribution), canonizer functions must preserve ∼, i.e. they must be ∼-canonizers. This might require some theorem proving but it can be relatively easy to check in most cases, since we can use the equations Gc and show that each one preserves ∼. For example, in the case of local reduction strategies [4] the equations Gc defining c are of the form c({t}) = c([[g]]({t})) if [[g]]({t}) < id2 | A2 > conf1 ) = c([[id1id2]]( < id1 | A1 > < id2 | A2 > conf1 ) if id1 < id2 /\ [[id1id2]](A2) < A1 . eq c(conf1) = conf1 [ owise ] . Note that if < is a total order, then the equations are confluent and the canonizer is strong. A very similar situation is that of enumeration strategies [4] where canonizers are defined as c({t}) = min{[[f]]({t})} where f ranges over all elements of the group under consideration. Again, preservation of ∼ by c follows from the very definition of c. Indeed, for all states u, c(u) will be necessarily of the form Jg1 ◦ g2 ◦ · · · ◦ gn K(u), with each gi being a generator. We call the equation format described in this paragraph group application form. All the c-reduction strategies evaluated in §5 are essentially of these forms. Proposition 1. Let R be a rewrite theory, R∼ be defined as usual, and Rc be the c-extension of R such that the equations of Ec defining c are in group application form. Then, for all states u ∈ TState/E∪A we have that c(u) ∼ u. In practice, when implementing c-strategies in the above form, all we have to check are the ordinary well-definedness properties of the equations of c: termination and sufficient completeness with respect to constructors, for which one can rely on the standard Maude tools. 3
Such order takes into account the ordering of the identities id1, id2 first and the order of their attributes second. In our tool < is based on the lexicographical order of the meta-representation of terms by default but it can be customized at the object level to achieve better results in terms of performance as we show in §5.
State Space c-Reductions of Concurrent Systems in Rewriting Logic
119
Note that proving ground confluence of c is not sufficient to show that c is a strong canonizer. It may still be the case that for some two states u, v such that u ∼ v we have that c(u) 6= c(v). Indeed, what we need to prove to show that c is a strong canonizer is that for all generators g and states s we have c(s) = c(JgK(s)). It is easy to see that if the previous property holds, an inductive argument allows us to conclude c(s) = c(Jf K(s)) for any possible group operation f and hence for any two equivalent states s ∼ s0 = Jf K(s). But the above check can be reduced to an ordinary (automatic) confluence check if we extend Ec with the set of equations test(g,c({t})) = c([[g]]({t})) and test(g,c({t})) = c(({t})), for all generators g (and inverse generators) of the group under consideration, where test is an auxiliary function symbol that ensures that the generator is applied only once. We denote this extension of Ec by Ec∼ . In words, the idea is that applying or not a group generator and then canonizing should result in the very same state. Proposition 2. Let R be a rewrite theory, R∼ be defined as usual, Rc be the c-extension of R, and let Ec∼ be defined as above. If (Σ ∪ Σc , E ∪ Ec∼ , A) is confluent, then c is a strong canonizer. This result paves the way for the use of Maude’s confluence checker [18]. Of course, there are cases in which no check is needed. For instance, it is well-known that enumeration strategies yield strong canonizers, while local strategies are not strong in general. 4.5
Building c-reductions
The next step is to build the c-reduction. Recall that we have defined the creduction Kc of a Kripke structure K in Def. 7. Starting from a system specification given as a rewrite theory R, our goal is to build Kc (R), but this can be easily done by applying a theory transformation mapping R into its c-reduction Rc , which is defined as follows. Definition 9 (c-reduction of a rewrite theory). Let Rc = (Σ ∪ Σc , E ∪ Gc ∪ A, R, φc ) be the c-extension of a rewrite theory R = (Σ, E ∪ A, R, φ). We call the rewrite theory Rc = (Σ ∪ Σc , E ∪ Gc ∪ A, Rc , φc ) where Rc = {t => c(t’) if cond | (t => t’ if cond) ∈ R} a c-reduction of R. In words, Rc is very much like R, but each rule t => t’ if cond in R, is transformed into a rule t => c(t’) if cond, i.e., into a rule where the canonizer function c is applied to the right hand side to ensure that canonization is performed after each system transition. This step is supported by our prototype [9], though limited to a particular class of rewrite theories (those using the object based signature). The implementation exploits Maude reflective features: the transformation is defined by a function that manipulates the meta-representation of the theory to be c-reduced. Note that in some cases it might be convenient not to apply the canonizer after each step. For instance if we know that the rule will always result in a canonical state we can save the time of applying the function.
120
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
It is trivial to show that Rc is a c-reduction by construction, and in particular that Kc (R) = K(Rc ). It can also be shown that it has good executability properties. By the properties required for Gc , it inherits all the properties of the equational part of R, namely sufficient completeness, confluence and termination modulo A. What is left to show is that Rc is coherent modulo A. Lemma 1 (coherence of Rc ). Let R = (Σ, E ∪ A, R, φ) be ground confluent, terminating, sufficiently complete, and with R ground coherent with E modulo A. Then Rc defined as above has Rc ground coherent with E ∪ Gc modulo A. Proof. Since R is topmost and all op1/ / c(v) u v erators in Σc are frozen (see Def. 8), c R >>> III >> ∗ any ground Σ ∪ Σc -term u of sort I∗ E/A E/A $ 1 State such that R ` u → v must ∗ @w ∗ : c(w) be a Σ term. Therefore, its E ∪ Gc /Auu u u E/A 1/ 0 canonical form u0 is exactly its E/A- E/A! 0 / c(v 0 ) E/A v u c R canonical form. By the ground coherence of R with E modulo A we obtain the inner pentagon in the diagram on the right which trivially yields the outer pentagon, proving E ∪ Gc ` c(v) = c(v 0 ) as desired. t u Theorem 2 (executability of Rc ). Let R = (Σ ∪ c, E ∪ Gc ∪ A, R, φ) be a rewrite theory with good executability properties, then Rc has good executability properties. Proof. The proof immediatedly follows from the fact that Rc has the same equational part as Rc and from Lemma 1. t u
5
Performance experiments
We present here a subset of the experiments we carried out, with the main purpose of validating the effectiveness of the implementation of the c-reduction approach in Maude. Our main hypothesis to be checked is that the relative performance gain (in terms of runtime and state space reductions) is comparable to the one obtained by state-of-the-art model checkers. The second hypothesis is that c-reductions are more efficient than the previous approach to symmetry reductions in Maude described in [8]. Finally, we enrich the experiments where we combine various c-reductions not supported by the previously mentioned tools. The Maude implementation of the benchmark examples used here are included in the release of our prototype [9]. Comparison with SymmSPIN We have chosen SymmSPIN [12, 13] as a representative model checker with which to compare our approach. SymmSPIN extends the SPIN [3] model checker with support for symmetry reductions. It is worth to remark that we do not perform absolute comparison as we aim at
State Space c-Reductions of Concurrent Systems in Rewriting Logic
121
SymmSpin c-reductions weak strong weak strong Experiment n if sf tf sf tf sf tf sf tf 2 -0.50 -0.48 +0.00 -0.49 +0.00 -0.45 +0.00 -0.45 +0.00 Peterson 3 -0.83 -0.75 -0.79 -0.82 -0.79 -0.77 +0.00 -0.83 +1.50 4 -0.96 -0.91 -0.77 -0.95 -0.84 -0.93 -0.75 -0.95 +0.50 DBM
7 -0.99 -0.99 -0.99 -0.99 -0.80 -0.98 -0.87 -0.99 +2.00 8 -0.99 -0.99 -0.99 -0.99 -0.48 -0.99 -0.95 -0.99 -0.65 Table 1. SymmSpin vs c-reductions in Maude.
checking the usefulness of our approach (experiments with SymmSPIN cannot be reproduced since the tool is no more available for download). We have implemented in Maude two of the benchmark models tested in [12, 13], namely Peterson’s mutual exclusion protocol [10], and a database management system [20]. Both examples exhibit a full symmetry due to the presence of families of replicated concurrent processes with identical behavior. In both cases we manually translated the Promela specification into Maude specifications, in the most faithful manner we could. We have considered various c-reduction strategies. For the sake of simplicity, we consider only the two best strategies of SymmSPIN (i.e. pc-segmented and pc-sorted ) and the two best of our own strategies our implementation (partly inspired by the ones proposed in [12, 13]), for which regards time and state space reduction. We call them strong and weak as they are actually strong and non-strong canonizers. Table 1 presents the results for instances of the models with increasing number of components (n). We offer only results for those instances for which it has been possible to generate the unreduced state spaces, so to compare the relative gain of the reductions in terms of relative state reduction factor (sf) and relative time reduction factor (tf). A relative state (resp. time) reduction factor of k indicates that, if the non-reduced exploration involved n states (resp. seconds) then the reduced exploration involved m = n + (k × n) states (resp. seconds). Put it otherwise, k is calculated as k = (m/n) − 1. Clearly, values below 0 indicate a reduction, while numbers above 0 an increase. The table also includes the “ideal” relative reduction factor (if), which in the case of full symmetries is (1/n!) − 1 where n is the size of the permutations (i.e. the number of replicated processes in the examples), since the size of each orbit is at most n!. So for an exhaustive exploration that requires s states and t seconds an ideal factor k means that we can expect the reduction to require at the best the exploration of n + (k × s) states in t + (k × t) seconds (where k is obviously negative). Clearly, “sf” and “tf” are always greater than “if”. We highlight cells corresponding to the best results in each category (state space and run-time gain) for each model instance. It is worth to remark that the results for the SymmSPIN tool have been derived from [12]. Reproducing them was not possible since SymmSPIN is not available
122
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
Reflection-based c-reductions Params Not reduced weak strong n m states if states sf tf states sf tf states sf tf 2 5 38,029 -0.50 19,295 -0.49 +9.62 21,630 -0.43 +1.14 19,025 -0.50 +0.46 3 2 72,063 -0.83 13,280 -0.82 +7.30 29,534 -0.59 +1.01 12,235 -0.83 +0.34 3 3 952,747 -0.83 174,428 -0.81 +5.65 307,532 -0.68 -0.50 160,121 -0.83 +0.30 Table 2. Reflection-based symmetry reduction vs. c-reductions in Maude.
for download. Fortunately, we are not interested in absolute measures but in the relative gain of the reduction. The two approaches provide state space reductions near to the ideal gain. The two strategies based on weak canonizers provide very similar outcomes, while the ones based on strong canonizers reduce similarly. SymmSPIN is more timeefficient, which is not a surprise, since the reduction algorithms are implemented in a procedural language (C) and efficiently compiled, while our implementation is based on a declarative language (Maude) running over an intepreter (the Maude engine). Comparison with reflection-based symmetry reduction in Maude Our second set of experiments aims at checking whether c-reductions offers better performances than the symmetry reduction implementation in Maude described in [8]. Very briefly, the main idea of [8] is to select the canonical representative of a state on the basis of the lexicographical order of the meta-representation of the state, which is achieved by exploiting Maude’s reflection capabilities. The comparison is performed over the Chain-Replication protocol used in [8]. As in the previous case, the replication of identical processes yields a full symmetry. Table 2 presents our results in the same format as Table 1 with the only exception that the model is instantiated with two parameters: the number n of replicated components and the number m of queries they perform. The table shows that the reductions of the reflection-based approach of [8] are bounded by the ones obtained by our strategies. That is: our weak strategy (resp. strong) provides a better (resp. worse) time reduction factor, while our strong (resp. weak) strategy provides a better (resp. worse) space reduction factor. In particular our weak strategy offers worse space reductions, while the strong one offers better space reductions. More interestingly, our reduction strategies introduce much less time overhead, differing often by an order of magnitude. This is not a surprise, since resorting to Maude’s meta-level involves a considerable overhead. Canonizers based on the lexicographical order of meta-representations are also implemented in our prototype [9] where similar results can be observed. Exploiting permutations, rotations, reuse and abstraction Our last set of experiments regards the joint application of a number of c-reductions of different nature, not supported by the previously mentioned tools. As a test case we have considered a message-passing solution to the Dining Philosophers problem
State Space c-Reductions of Concurrent Systems in Rewriting Logic
123
NR NR+RS+FS NA NA+RS n states time states time states time states time 2 21 0 10 0 18 0 10 0 3 115 8 27 12 76 0 27 8 4 801 100 86 60 322 20 86 48 5 6,251 1,456 275 320 1,364 124 275 248 6 54,869 20,765 982 1,732 5,778 740 982 1,412 7 541,731 463,080 3,499 11,828 24,476 6,624 3499 8,124 8 O.T. O.T. 13,016 49,651 103,682 29,329 13,006 35,594 9 O.T. O.T. 48,828 247,987 439,204 192,072 48,819 186,329 Table 3. c-reductions for the dining philosophers.
along the lines of the case study used in [21], where newly generated messages (representing forks) receive fresh identities (as the original purpose of [21] was to reason about individual messages). There are a couple of regularities that can be exploited in the form of c-reductions and that happen to yield bisimulations (for an empty set of atomic predicates): the rotational symmetry of philosophers, the full symmetry of messages, the reuse of message identifiers and their abstraction. Of course, the situation is different when one considers state predicates that involve the identity of philosophers or messages. However, our goal here is to validate the effectiveness of the mentioned c-reductions. Table 3 reports the results. The table presents the size of the state space and the time (in ms) to generate it, for instances of the model with increasing number of philosophers. The table considers the state spaces generated in the following cases: reuse of message identifiers (NR), reuse together with (rotational and full) symmetry reduction (NR+RS+FS), abstraction of name identifiers (NA), and abstraction of name identifiers together with (rotational) symmetry reduction (NA+RS). The sizes of the unreduced state spaces are not shown since they are infinite (due to the creation of messages with fresh identifiers). The first clear advantage is that reuse of message identifiers yields finite state spaces (since the number of messages in each state is bounded by n). Besides this, we see how combining various c-reductions results in better and more efficient reductions. To be noticed is the fact that name reusing alone ran out of time (more than 5 hours) for models instantiated with more than 7 philosophers, while combining it with symmetry reductions (for messages and philosophers) allows us to manage larger instances. In particular, the best reductions are obtained with the combination of name abstraction and rotational symmetry (NA+RS), while name abstraction alone (NA) offers the fastest explorations from 2 to 8 philosophers, and is outperformed by the combination NA+RS for greater instances.
124
6
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
Conclusion
We have presented c-reductions, a state space reduction technique, whose main idea is to use canonizer functions mapping each state into a canonical representative of its equivalence class modulo a bisimulation equivalence relation, capturing some specific system regularities. The main differentiating features with respect to other state space reduction techniques are (i) reductions are defined using the system description language; (ii) (re)use of the standard techniques of the verification setting to check correctness of the reduction; (iii) automatization: both for applying the reduction and for checking its correctness; and (iv) generality: it subsumes in a uniform way symmetry reduction as well as other kinds of reductions (name reuse, abstraction). We have presented the basic infrastructure of our approach, described some typical classes of reductions, illustrated how they can be analyzed and presented some performance results. Our methodology consists on performing a series of incremental verification steps §4.1-§4.5 which include checking that the equivalence relation is a bisimulation and that reduction strategies preserve such equivalence relation. In this paper we have focused on steps §4.4-§4.5. Steps §4.1-§4.4 are subject of current work but we have offered a preliminary sketch of our ideas. It is worth to remark that these steps are not to be repeated every time a system is going go be verified. The idea is rather to consider those steps as incrementally providing results to be reused again and again. We also presented a representative subset of the performance experiments we have carried out. In all cases, regardless of the chosen c-reduction strategy, the c-reductions allow us to explore larger state-spaces. In particular, considering full symmetries, strategies based on the strong canonizers offer in general greater reductions, at the cost of more time, which in some cases is compensated by the smaller sizes of the obtained state spaces. Strategies based on weak canonizers require less application-specific code and less comparisons (e.g. since they are based on an ordering relation on states that takes into account part of the state descriptions only), but offer weaker reductions. We have observed a comparable performance with respect to mature tools such as SPIN and performance gains with respect to a previous implementations of symmetry reductions in Maude [8]. Moreover, the flexibility of our approach has allowed us to define a wide range of reductions. Beyond the classical permutation and rotation symmetries, we have considered some simple cases of name reuse and name abstraction, which are crucial to deal with the infinite state spaces of systems with dynamic allocation of resources. Compared to the approach presented in [12, 13] we are able to treat a wider class of systems, where identifiers of symmetric objects can appear as pointers in attributes of other objects, and with wider classes of symmetries such as rotational ones. Similar remarks can be made about the approach presented in [8], with respect to which we offer a wider class of reduction strategies and better performance. A closely related work is the automatic symmetry detection of [4] which also provides an alternative symmetry reduction extension (TopSPIN) of the
State Space c-Reductions of Concurrent Systems in Rewriting Logic
125
SPIN model checker. Our approach does not consider automatic detection of symmetries but, instead, user-definable ones, together with a methodology to check their correctness, with the main advantage being that we rely on tools and techniques used to perform the verification of the system itself. Both lines of research are essentially complementary and can converge in a synergistic way. We are also investigating how to apply our approach to improve the efficiency of rewriting-logic based interpreters of programming languages with primitives for dynamic memory allocation, and to further explore the combination of creductions with other state space reduction techniques, with a particular attention to those already proposed in the setting of rewriting logic and Maude, such as partial order reduction [22], and abstraction [23]. The closest of such approaches is probably [23] where abstractions are defined equationally. The main difference with our approach is in the kind of behavioral equivalence considered: equational abstractions yield simulations while our approach focuses on bisimulations. Another significant difference is that in our approach one has some control on when to apply a reduction, i.e. the c-reduction procedure might be applied to some of the rules only, excluding for instance those rules that are known to yield representative states (e.g. if they affect a part of the state that does not play a role in a symmetry). In that way some unnecessary computations can be spared. A more detailed comparison is under study. Current efforts are also devoted to a deeper investigation of state space reduction techniques based on name-reuse. Such techniques have a limited impact on Kripke models, where object identifiers are “global”, in the sense that they represent an entity through all the states of a model. These techniques become instead fundamental using more sophisticated models (together with non-propositional property specification languages), where object identifiers are local to single states, and “trans-states identities” are explicitly represented through suitable mappings associated to state transitions. Notable examples are History Dependent Automata [24], High-level Allocational B¨ uchi Automata [21], Graph Transition Systems [25] and Counterpart models [26]. We are also working further (and experimenting) on the verification steps that we could only sketch in this paper (steps §4.1-§4.3). Even if we put some stress on reductions based on group actions the c-reduction our approach is more general and accepts any possible canonizer function. Appropriate correctness check methodologies for such cases should however be developed. Particularly interesting could be the definition of c-reductions inspired by process algebra techniques for the minimization of processes modulo bisimulation and fort the axiomatisation of bisimulation relations. Another possible extension the treatment of equivalence preorder like simulations (as we mentioned when discussing the relation with [23]), and further develop the automatization of our approach and the use of the integrated Maude formal environment [27]. A preliminary version of our tool is publicly available [9]. At the current stage the tools is limited to the application of a set of generic c-reductions to object-based Maude modules.
126
Alberto Lluch Lafuente, Jos´e Meseguer, and Andrea Vandin
Acknowledgements. We are grateful to the reviewers for their helpful criticism and detailed comments, and to Dragan Boˆsnaˆcki for a detailed discussion of our work and its comparison with symmetry reduction techniques.
References 1. Clarke, E.M., Grumberg, O., Peled, D.A.: Model Checking. The MIT Press (1999) 2. Wahl, T., Donaldson, A.F.: Replication and abstraction: Symmetry in automated formal verification. Symmetry 2 (2010) 799–847 3. Holzmann, G.: The SPIN model checker: primer and reference manual. AddisonWesley Professional (2003) 4. Donaldson, A.F., Miller, A.: A computational group theoretic symmetry reduction package for the SPIN model checker. In: Algebraic Methodology and Software Technology. (2006) 374–380 5. Clavel, M., Dur´ an, F., Eker, S., Lincoln, P., Mart´ı-Oliet, N., Meseguer, J., Talcott, C.L.: All About Maude. Volume 4350 of LNCS. Springer (2007) 6. Meseguer, J.: Conditional rewriting logic as a united model of concurrency. Theoretical Computer Science (TCS) 96 (1992) 73–155 7. Meseguer, J., Palomino, M., Mart´ı-Oliet, N.: Algebraic simulations. Journal of Logic and Algebraic Programming 79 (2010) 103–143 8. Rodr´ıguez, D.E.: Combining techniques to reduce state space and prove strong properties. In: Proceedings of the 7th International Workshop on Rewriting Logic and its Applications (WRLA 2008). Volume 238(3) of ENTCS. (2009) 267 – 280 9. C-Reducer, http://sysma.lab.imtlucca.it/tools/c-reducer. 10. Lynch, N.A.: Distributed Algorithms. Morgan Kaufmann Publishers Inc. (1996) 11. Dijkstra, E.W.: Hierarchical ordering of sequential processes. Acta Informaticae 1 (1971) 115–138 12. Bosnacki, D., Dams, D., Holenderski, L.: A heuristic for symmetry reductions with scalarsets. In: International Symposium of Formal Methods Europe on Formal Methods for Increasing Software Productivity (FME’01), Springer (2001) 13. Bosnacki, D., Dams, D., Holenderski, L.: Symmetric SPIN. International Journal on Software Tools for Technology Transfer (STTT) 4 (2002) 92–106 14. Eker, S., Meseguer, J., Sridharanarayanan, A.: The maude ltl model checker and its implementation. In Ball, T., Rajamani, S.K., eds.: SPIN. Volume 2648 of Lecture Notes in Computer Science., Springer (2003) 230–234 15. The Maude Invariant Analyzer Tool (InvA), camilorocha.info/software/inva. 16. Clavel, M., Palomino, M., Riesco, A.: Introducing the ITP tool: a tutorial. Journal of Universal Computer Science 12 (2006) 1618–1650 17. Maude Interactive Theorem Prover, maude.cs.uiuc.edu/tools/itp/. 18. Dur´ an, F., Meseguer, J.: A Church-Rosser Checker Tool for Conditional Order¨ Sorted Equational Maude Specifications. In Olveczky, P.C., ed.: Proceedings of the 8th International Workshop on Rewriting Logic and its Applications (WRLA’10). Volume 6381 of LNCS., Springer (2010) 69–85 19. Rocha, C., Meseguer, J.: Proving safety properties of rewrite theories. In Corradini, A., Klin, B., Crstea, C., eds.: Algebra and Coalgebra in Computer Science. Volume 6859 of LNCS. Springer (2011) 314–328 20. Valmari, A.: Stubborn sets for reduced state generation. In: Proceedings on Advances in Petri nets 1990, Springer (1991)
State Space c-Reductions of Concurrent Systems in Rewriting Logic
127
21. Distefano, D., Rensink, A., Katoen, J.P.: Model checking birth and death. In Baeza-Yates, R.A., Montanari, U., Santoro, N., eds.: 2nd International Conference on Theoretical Computer Science (TCS’02). Volume 223., Kluwer (2002) 22. Farzan, A., Meseguer, J.: Partial order reduction for rewriting semantics of programming languages. In: Proceedings of the 6th International Workshop on Rewriting Logic and its Applications (WRLA’06). Volume 176 of ENTCS. (2007) 61–78 23. Meseguer, J., Palomino, M., Mart´ı-Oliet, N.: Equational abstractions. Theoretical Computer Science 403 (2008) 239–264 24. Montanari, U., Pistore, M.: Structured coalgebras and minimal HD-automata for the π-calculus. Theoretical Computer Science 340 (2005) 539–576 25. Rensink, A.: Isomorphism checking in GROOVE. ECEASST 1 (2006) 26. Gadducci, F., Lluch Lafuente, A., Vandin, A.: Counterpart semantics for a secondorder µ-calculus. In Ehrig, H., Rensink, A., Rozenberg, G., Sch¨ urr, A., eds.: 5th International Conference on Graph Transformation (ICGT’10). Volume 6372 of LNCS. Springer (2010) 282–297 27. The Maude Formal Environment, http://maude.lcc.uma.es/MFE/.
Specifying and Analyzing the Kademlia Protocol in Maude? Isabel Pita and Adri´an Riesco Facultad de Inform´ atica, Universidad Complutense de Madrid, Spain
[email protected],
[email protected]
Abstract. Kademlia is a peer-to-peer distributed hash table (DHT) currently used in the P2P eDonkey file sharing network. Kademlia offers a number of desirable features that result from the use of a notion of distance between objects based on the bitwise exclusive or of the n-bit quantities that represent both nodes and files. Nodes keep information about files close or near to them in the key space and the search algorithm is based on looking for the closest node (or almost closest node, if the information is replicated) to the file key. The structure of the routing table defined in each peer guarantees that the lookup algorithm takes no longer than log n steps. This paper presents the distributed specification of the behavior of a P2P network that uses the Kademlia DHT in the formal specification language Maude. We use sockets to connect different Maude instances and create a P2P network where the Kademlia protocol can be used. This protocol is executed on top of a previously developed routing protocol that provides real-time by connecting Maude to an external Java server and allows peers to enter and leave the network dynamically. Then, we show how to represent this distributed system in one single term in order to simulate and analyze the system using Real-Time Maude. Keywords: Kademlia, distributed specification, formal analysis, Maude, Real-Time Maude.
1
Introduction
Distributed Hash tables (DHTs) are becoming an essential factor in the implementation of P2P networks since the Kad DHT was incorporated in the eMule client [4] of the eDonkey file sharing network. Previously a large number of DHTs were studied through theoretical simulations and analysis, such as Chord [22], CAN [18], Pastry [21], and also Kademlia [10], in which the Kad DHT is based. P2P networks are mainly used for file sharing applications, due to its lack of security. The large number of users involved in the networks and the absence of a central authority that certificates the trust of the participating nodes imply that the system must be able to operate even though some participants are malicious. ?
Research supported by MEC Spanish project DESAFIOS10 (TIN2009-14599-C0301) and Comunidad de Madrid program PROMETIDOS (S2009/TIC1465).
Several attacks to P2P networks have been studied in the literature [24,5], in particular, the problem of ensuring efficient and correct peer discovery despite adversarial interference like the Sybil attack or the Eclipse attack. However, the majority of these studies examine the problems, drawing examples from existing systems, or experimentally evaluate the attacks over the networks. Formal methods, which have had a great success in the analysis of distributed networks and protocols, have almost not contributed to P2P networks, nor to the DHT implementations. One of the first formal proposals is due to Borgstr¨on et al., who prove in [3] correctness of the lookup operation of the DHT-based DKS system, developed in the context of the EU-project [8], for a static model of the network using value-passing CCS. Moreover, Bakhshi and Gurov, give in [2] a formal verification of Chord’s stabilization algorithm using the π-calculus. Lately Lu, Merz, and Weidenbach [9] have modeled Pastry’s core routing algorithms in the specification language TLA+ and have proved properties of correctness and consistency using its model checker. This paper presents a distributed specification in Maude [6], a formal specification language based on rewriting logic, of the behavior of a P2P network that uses the Kademlia DHT. Rewriting logic [11] was proposed in the early nineties as a unified model for concurrency in which several well-known models of concurrent and distributed systems can be represented. The specification language Maude supports both equational and rewriting logic computations. It can be used to specify in a natural way a wide range of software models and systems and, since (most of) the specifications are directly executable, Maude can be used to prototype those systems. Moreover, the Maude system includes a series of tools for formally analyzing the specifications. Since version 2.2, Maude supports communication with external objects by means of TCP sockets, which allows the implementation of real distributed applications. Real-Time Maude [16] is a natural extension of the Maude language that supports the specification and analysis of real-time systems, including object-oriented distributed ones. It supports a wide spectrum of formal methods, including: executable specification, symbolic simulation, breadth-first search for failures of safety properties in infinite-state systems, and linear temporal logic model checking of time-bounded LTL formulas. Real-Time Maude has strengthened that analyzing power by allowing to specify sometimes crucial timing aspects. It has been used, for example, to specify the Enhanced Interior Gateway Routing Protocol (EIGRP) [20], embedded systems [15], and the AER/NCA active network protocol [13]. Moreover, analysis of real-time systems using Maude sockets, and thus requiring a special treatment for them, has been studied [23,1]. While the algebraic representation of the distribution used in these works follows, as well as our work, the approach presented in [20], the way used to relate logical and physical time allows a more precise and formal analysis than the one used here, allowing the system to synchronize only when needed. We consider this approach an interesting subject of future work. As part of an ongoing work to develop distributed applications in Maude, we specified a distributed version of the mobile agents language Mobile Maude and
algorithmic skeletons in [19]. Both specifications used Maude sockets to connect different Maude instances. These systems were executed on different topologies, being available star, ring, and centralized ring architectures. These topologies were improved in a later work when we developed the Enhanced Interior Gateway Routing Protocol (EIGRP) in Maude [20]. This protocol allowed us to build dynamic (nodes can be added anytime) and reconfigurable (when a node leaves the network alternative paths are found) topologies, on top of which we can execute any distributed Maude specification. This work used Maude sockets to, in addition to connecting different Maude instances, connect Maude to a Java server that communicates the time elapsed to the Maude specification. In this way, it was possible to use Real-Time in Maude for analyzing the system. In this paper we present, from the point of view of the implementation of distributed applications in Maude, the first system implemented on top of the routing protocol described in [20]. Our implementation of the Kademlia protocol uses real-time by sharing the “tick” messages sent from the Java server and allows peers to be added and removed dynamically, while the underlying protocol takes care of redirecting the messages. In this way we show that “real” distributed applications can be implemented in Maude in an incremental and easy way. From the point of view of the analysis, this distributed system can be simulated and analyzed in Maude by using an algebraic specification of the sockets provided by Maude; an abstraction of the underlying routing protocol, which allows the analysis tools to focus on the properties; and by using RealTime Maude. That is, we abstract some implementation details but leave the protocol implementation unmodified, which allows us to use the centralized protocol to prove properties that must also hold in the distributed version. The analyses that can be performed on the protocol include the simulation of the system to study, for example, how its properties change when its parameters, like the redundancy constant, are modified; examine the reaction of the system to different attacks; and check properties such as that any published file can be found or that files remain accessible even if their publishing peers become offline. The use of formal methods to describe the behaviour of the Kademlia DHT may help to understand the informal description in [10]. In particular, the Maude language, that we proposed, gives us the opportunity of executing the distributed specification taking into account the time aspects of the protocol. It also allows us to analyze all possible executions of the system, using the centralized model that mirrors the distributed one, either by searching in the execution tree or by using model checking techniques. The rest of the paper is structured as follows: Section 2 presents how to specify generic distributed systems in Maude, and the Kademlia protocol. Section 3 describes the distributed specification in Maude of this protocol. Section 4 shows how the distributed system can be represented in one single term, while Section 5 describes how to simulate and analyze it. Finally, Section 6 concludes and presents some future work.
2
Preliminaries
We present in this section the basic notions about Maude and Kademlia.
2.1
Maude
In Maude [6] the state of a system is formally specified as an algebraic data type by means of an equational specification. In this kind of specification we can define new types (by means of keyword sort(s)); subtype relations between types (subsort); operators (op) for building values of these types; and equations (eq) that identify terms built with these operators. The dynamic behavior of such a distributed system is then specified by rewrite rules of the form t −→ t0 if C, that describe the local, concurrent transitions of the system. That is, when a part of a system matches the pattern t and satisfies the condition C, it can be transformed into the corresponding instance of the pattern t0 . In object-oriented specifications, classes are declared with the syntax class C | a1 :S1 ,. . ., an :Sn , where C is the class name, ai is an attribute identifier, and Si is the sort of the values this attribute can have. An object is represented as a term < O : C | a1 : v1 , . . ., an : vn > where O is the object’s name, belonging to a set Oid of object identifiers, and the vi ’s are the current values of its attributes. Messages are defined by the user for each application (introduced with syntax msg). In a concurrent object-oriented system the concurrent state, which is called a configuration, has the structure of a multiset made up of objects and messages that evolves by concurrent rewriting. The rewrite rules specify the behavior associated with the messages. By convention, the only object attributes made explicit in a rule are those relevant for that rule. We use Full Maude’s objectoriented notation and conventions [6] throughout the whole paper; however, only the centralized specification is specified in Full Maude (which is required by Real-Time Maude), while the actual implementation of the distributed protocol is in Core Maude because Full Maude does not support external objects. The complete Maude code can be found at http://maude.sip.ucm.es/kademlia. In [20], we described a methodology to implement distributed applications in such a way that the distributed behavior remains transparent to the user by using a routing protocol, the Enhanced Interior Gateway Routing Protocol (EIGRP). Figure 1 presents the architecture proposed in that paper, where the lower layer provides mechanisms to translate Maude messages from and to String (Maude sockets can only transmit Strings); to do so, the user must instantiate a theory requiring a (meta-represented) module with the syntax of all the transmitted messages. The intermediate layer, EIGRP, provides a message of the form to_:_, with the first argument an object identifier (the addressee of the message) and the second one a term of sort TravelingContents, that must be defined in each specific application. We have slightly modified this layer to share the tick!
6 Kademlia to : / tick!
!
EIGRP Protocol send
!
Basic intrastructure
Message/String conversion
Figure 7: Design for Kademlia Fig. 1. Layers for distributed applications
< O1 : C1 |
message obtained from the Java server in charge of dealing with time.1 This layer provides a fault-tolerant and dynamic architecture where nodes may join and < O2 : C2 | atr2 : v2 > leave at any moment, and where nodes are always reached by using the shortest O1 : msg1 us to implement realistic systems. Finally, the upper layer is path, thustoallowing the application one, which in our case corresponds to Kademlia. It relies on the lower layers to deliver the messages and focus on its specific tasks, just like the atr1 : v1Kademlia > real protocol. < O3 : C3 | atr3 : v3 >
< O4 : C4 | atr4 : v4, atr5 : v5 >
2.2
“to O3 : msg3”
Kademlia
Kademlia is a peer-to-peer (P2P) distributed hash table used by the peers to Application access files shared by other peers. In Kademlia both peers and files are identified to : with n-bit quantities, computed by a hash function. Information of shared files ! is kept in the peers EIGRP with anprotocol ID close toElection the ID file, where of the next the hostnotion of distance between two IDs is defined as the bitwise exclusive or of the n-bit quantities. send Then, the lookup algorithm!which is based on locating successively closer nodes Message/String conversion infrastructure to any desired keyBasic has O(log n) complexity. Each node stores contact information about others. In Kademlia, every node keeps a list of: IP address, UDP port and node ID, for nodes of distance between 8: Design 2i and Figure 2i+1 from itself,after for ithe = first 0, . . abstraction . , n and n the ID length. In the Kademlia Program Syntax paper [10] these lists, called k-buckets, have at most k elements, where k is chosen such that any given Parsing k nodes are very unlikely to fail within an hour of ! each other. k-buckets are kept sorted by the time they were last seen. When a Maude module node receives any message (request or reply) from another node, it updates the Plural transformation appropriate k-bucket for the ! sender’s node ID. If the sender node exists, it is moved to the tail ofMaude the list. If it does not exist and there is free space in the module appropriate k-bucket it is inserted at the tail of the list. Otherwise, the k-bucket has not free space, the node at the head of the list is contacted and if it fails to respond it Figure is removed from the list and the new contact is added at the tail. In 9: Program transformation the case the node at the head of the list responds, it is moved to the tail, and 1
In the standard implementation, tick! messages are introduced into the configuration each second. However, the time can be customized to get these messages in the time span defined by the user.
Fig. 2. A routing table example for node 00000000
the new node is discarded. This policy gives preference to old contacts, and it is due to the analysis of Gnutella data collected by Saroiu et al. [7] which states that the longer a node has been up, the more likely it is to remain up another hour. k-buckets are organized in a binary tree called the routing table. Each kbucket is identified by the common prefix of the IDs it contains. Internal tree nodes are the common prefix of the k-buckets, while the leaves are the k-buckets. Thus, each k-bucket covers some range of the ID space, and together the kbuckets cover the entire ID space with no overlap. Figure 2 shows a routing table for node 00000000 and a k-bucket of length 5. IDs have 8 bits. The Kademlia protocol consists of four Remote Procedure Calls (RPCs): – PING checks whether a node is online. – STORE instructs a node to store a file ID together with the contact of the node that shares the file to publish it to other nodes. – FIND-NODE takes an ID as argument and the recipient returns the contacts of the k nodes it knows that are closest to the target ID. – FIND-VALUE takes an ID as argument. If the recipient has information about the argument, it returns the contact of the node that shares the file; otherwise, it returns a list of the k contacts it knows that are closest to the target. In the following we summarize the processes of looking for a value and publishing a shared file from the Kademlia paper [10]. Looking for a value. To find a file ID, a node starts by performing a lookup to find the k nodes with the closest IDs to the file ID. First, the node sends a FIND-VALUE RPC to the α nodes it knows with an ID closer to the file ID, where α is a system concurrency parameter. As nodes reply, the initiator sends new FIND-VALUE RPCs to nodes it has learned about from previous RPCs, maintaining α active
RPCs. Nodes that fail to respond quickly are removed from consideration. If a round of FIND-VALUE RPCs fails to return a node any closer than the closest one already seen, the initiator resends the FIND-VALUE to all of the k closest nodes it has not queried yet. The process terminates when any node returns the value or when the peer that started the query has obtained the responses from its k closest nodes. Publishing a shared file. Publishing is performed automatically whenever a file needs it. To maintain persistence of the data, files are published by the node that shares them from time to time. Nodes that know about a file publish it more frequently than the node that shares it. To share a file, a peer locates the k closest nodes to the key, as it is done in the looking for a value process, although it uses the FIND-NODE RPC. Once it has located the k closest nodes, it sends them a STORE RPC.
3
Distributed Implementation
We present in this section the main details of the distributed implementation of the Kademlia protocol. A more detailed explanation of the data types, classes, and messages in the specification may be found in [17]. The Kademlia network is modeled as a Maude configuration of objects and messages. Peers in our specification are objects of class Peer, defined as follows: class Peer | RT : RoutingTable, Files : TFileTable, Publish : TPublishFile, SearchFiles : TSearchFile, SearchList : TemporaryList .
where the object identifier is the node ID, which we have simplified from its original version and is expressed with the operator peer, that takes a natural number, which is the decimal representacion of the reverse of the node n-bit ID, as argument. The attributes related to the Kademlia network are: – RT is a list that keeps the information of the routing table. – Files is a table that keeps the information of the files the peer is responsible for publishing. It includes the file ID, the identification of the peer that shares the file, a time for republishing the file and keep it alive, and a time to remove the file from the table. – Publish is a table that keeps the information of the files shared by the peer. The information includes the file ID, the file’s location in the peer and a time for republishing the file. This time is greater than the time for republishing of the Files table, and prevents the information in the Files table from being removed. – SearchFiles is a table that keeps the files a peer is looking for. The information includes the file ID, and a waiting time to proceed with the search. This time is used when the file is not found and it should be researched later.
– SearchList is an auxiliary list used in the search and publish processes to keep the information of the nodes that have been already contacted by the searcher/publisher and the state in which the searching/publishing process is. As the searcher/publisher finds out new closer nodes to the file ID, it stores them in this file, and starts sending them messages. The messages represent the RPCs. There is a message for each RPC defined in the Kademlia protocol. For example, the FIND-NODE message and its reply are defined as follows: op FIND-NODE : Nat Nat -> TravelingContents [ctor] . op FIND-NODE-REPLY : Nat Nat NatList -> TravelingContents [ctor] .
Note that terms of this form will be used to form messages with the operator to_:_ described in Section 2.1, where the first parameter is the identifier of the addressee. The first parameter of these operators identifies the peer sending the message, while the second one represents the key the sender is looking for. The reply has also an additional parameter that keeps a list of the k nodes the peer knows that are the closest ones to the target, where k is the bucket dimension. The specification of the different processes follows their definition. For example, the searching process starts automatically when there are IDs in the SearchFiles attribute of some connected peer with time for searching equal to one. A greater value indicates that the file has already been searched for, it was not found, and now it is waiting for repeating the search. When the search starts, the auxiliary list SearchList is filled with the closest nodes the searcher has in its routing table, and the time of this file in the searchFiles table is set to INF. It will remain with this value until the search process ends. The process continues by sending FIND-VALUE RPCs to the first nodes in the list to find closer nodes to the file ID. The RPC is only sent if the number of parallel messages is less than the given constant, ParallelSearchRPC, the peer in charge of the search has not received response yet from a certain number of peers given by the kSearched constant, and there are nodes in the search list that have not been contacted yet. Notice that we have to ask as many nodes as possible, because there can be nodes not so close to the objective as others but that have in their routing tables information of the closest ones. Once the RPC is sent, a flag is activated in the search list that marks this node as in process with set-flag: crl [lookfor-file21] : < peer(SENDER) : Peer | SearchFiles : < I1 & (S1 ; INF) > # SF, SearchList : SL > => < peer(SENDER) : Peer | SearchFiles : < I1 & (S1 ; INF) > # SF, SearchList : set-flag(Tr,SrchListRmve,SL) > to peer(Tr) : FIND-VALUE(SENDER, I1) if not all-sended(SL) /\ Tr := first-not-send(SL) /\ messages-in-process(SL) < ParallelSearchRPC /\ number-nodes-reply(SL) < kSearched .
The receiver may find the file the searcher is looking for in his table or it may return the closest nodes it knows about. In the first case, it sends a FIND-VALUE-REPLY2 message to the searcher including the node ID of the peer that shares the file. When the searcher receives this reply the process finishes by sending a FILE-FOUND message and the file is removed from its searching table. The FILE-FOUND message remains in the configuration to show the files that have been searched and found, easing the proof of properties. In the second case, the receiver sends a FIND-VALUE-REPLY1 message to the searcher including the closest nodes to the file ID it knows about. When the searcher receives this message it changes its search list, adding the nodes ordered by the distance to the objective. Only nodes closer than the one which proposes them are added. When the full list is traversed, a flag is activated to mark this node as done in the search list. Additionally, the searcher routing table is updated with the move-to-tail operation that puts the ID of the message sender first in the list, so that it will not be removed from the routing table, as it is the last peer the searcher knows it is alive: rl [lookfor-file3] : to peer(REC) : FIND-VALUE-REPLY2(SENDER, I1, P3) < peer(REC) : Peer | RT : R1, SearchList : SL, SearchFiles : < I1 & (S1 ; INF) > # SF > => < peer(REC) : Peer | RT : move-to-tail(SENDER, REC,R1), SearchList : mt-list, SearchFiles : SF > to peer(REC) : FILE-FOUND(SENDER,I1) . rl [lookfor-file40] : to peer(REC) : FIND-VALUE-REPLY1(SENDER, P3, L) < peer(REC) : Peer | RT : R1, SearchList : SL, SearchFiles : < I1 & (S1 ; INF) > # SF > => < peer(REC) : Peer | RT : move-to-tail(SENDER, REC,R1), SearchFiles : < I1 & (S1 ; INF) > # SF, SearchList : insert(L,SL,SENDER,REC,P3) > .
Another important rule in the system consists of updating the peer when a tick! message arrives. In order to treat similarly the distributed and centralized versions, we define a delta function [14] on peers that updates the time-related attributes: rl [tick!]: tick! < O : Peer | > => delta(< O : Peer | >, 1) .
where delta just applies auxiliary delta functions to each of the attributes. These auxiliary functions just traverse the tables and lists, decreasing the time stored on the appropriate fields: eq delta(< O : Peer | Files : FT1, Publish : PF, SearchFiles : SF, SearchList : SL >, TC) = < O : Peer | Files : delta(FT1, TC), Publish : delta(PF, TC),
SearchFiles : delta(SF, TC), SearchList : delta(SL, TC) > .
Executable examples of the distributed protocol can be found at http:// maude.sip.ucm.es/kademlia.
4
Centralized Simulation
We use Real-Time Maude [14,16] to specify our timed system. It declares modules defining the natural numbers as the time values of sort Time, with operations like plus, GlobalSystem. In Real-Time Maude an object-oriented system is represented as a term of sort Configuration (a subsort of System) and, since it has a rich structure, it is useful to have an explicit operation delta, that defines the effect of time elapse on each object and message in a configuration. An operation mte giving the maximum time elapse permissible to ensure timeliness of time-critical actions, and defined separately for each object and message, is also useful. Then, time elapse is modeled by the tick rule crl [tick] : { SYSTEM } => { delta(SYSTEM, T) } in time T if T < S : Socket | listA < O : Process | conf
: : : :
O, listA : dl(to O’ : TC, 0) DML > CONF > DML > (to O’ : TC CONF) > .
The mte function applied to sockets returns the minimum time required by the messages in the head of the lists, while delta updates the messages in the lists. That is, we consider that this abstract architecture is initially connected (there exists an object of class Socket) for each pair of locations connected, directly or indirectly, in the real system, and it never fails, that is, connections are never broken.3 In this way we prevent the search and model-checking commands from using the rules for connecting the locations, for redirecting messages, and for transforming the messages from/into String, which introduces a lot of nondeterminism (although the order in the creation of the connections and in the redirection of messages is not important, these tools must traverse all the possible paths to check the given properties). In order to simulate errors and disconnections in the peers we have added two attributes to the Peer class: Life and Reconnect, containing values of sort TimeInf. Basically, when the Life attribute reaches the value 0, it is set to INF, the peer cannot receive nor send messages, and the Reconnect attribute is set to a random value. Similarly, when Reconnect reaches 0, it is set to INF, Life is set to a random time, and the peer works again. Once this class has been modified, we only need to (i) define the mte function on peers and messages; (ii) modify the delta function on peers to take the Life and Reconnect values into account, and define it over messages; (iii) add a condition in each rule saying that the value in Life is greater than 0 and different from INF; and (iv) add the rules for disconnecting and reconnecting the peer. For messages, mte and delta are easily defined; mte returns 0 for all of them except for FILE-FOUND, that is 3
Note that errors in the connections will be simulated by making the peers to fail, as we will see later. It is anyway easily simulated in sockets e.g. by adding an attribute numMsgs indicating the number of messages that can be sent through the socket before it fails; see [20] for details.
just used for information purposes and thus it is not processed,4 while delta does not modify them: eq mte(to O : FILE-FOUND(SENDER,I1)) = INF . eq mte(MSG) = 0 [owise] . eq delta(MSG, T) = MSG .
As explained above, the delta function for peers is very similar to the one presented in the previous section, just including (and updating) the new attributes, and thus we focus on mte. When the peer is connected, we return the minimum between all the other time-related attributes, while when it is disconnected (K2 is a variable of sort Nat) then nothing else “works” and mte returns the time left for reconnecting: eq mte(< O : Peer | Files : FT1, Publish : PF, SearchFiles : SF, Life : K1, Reconnect : INF >) = min(minTime(FT1), min(minTime(PF), min(minTime(SF), K1))) . eq mte(< O : Peer | Reconnect : K2 >) = K2 .
where the functions minTime computes the minimum time used in the tables.
5
Protocol Properties
We can use now Real-Time Maude in two different ways: to execute the centralized specification and to verify different properties. The former is achieved by using the commands trew and tfrew, that execute the system (the second one applies the rules in a fair way) given a bound in the time; with find earliest and find latest, that allow the user to check the paths that lead to the first and last (in terms of time) state fulfilling a given property; and with tsearch, that checks whether a given state is reachable in the given time. The latter is accomplished by using the tsearch command to check that an invariant holds; by looking for the negation of the invariant we can examine whether there is a reachable state that violates it. The specification can also be analyzed by using timed model checking with the command mc, that allows the user to state linear temporal logic formulas with a bound in the time. We will use in this section two network topologies as case studies, of 6 and 20 nodes. We abstract the concrete connections and suppose total network connectivity. The life time of each node is randomly chosen, although we use an upper bound life constant to control the ratio of alive nodes. We change the peers that share and search files, as well as the number and time of published and searched files. We can simulate how different attacks may affect a network. For example, in the node insertion attack, an attacking peer catch search requests for a file, which are answered with bogus information [12]. The attacking peer creates its own 4
We assume here that messages are attended as soon as they are received. For this reason, a rule is in charge of deleting messages addressed to inactive peers.
ID such that it matches the hash value of the file. Then the search requests are routed to the attacking peer, that may return its own file instead of routing the search to the original one. Since the Kademlia network sends the request not only to the closest peer the searcher may find the original file. The find earliest command can be used to study different network parameters and check whether this attack is effective. We study if a file may be found in a node that is not the closest one to the file ID, with the following Real-Time Maude command: Maude> (find earliest init =>* {< O : Process | conf : (to O’ : FILE-FOUND(SENDER, N2) CONF) > CONF’} .)
Note that, since the FILE-FOUND message returns in its first parameter the peer that is publishing the file, we only need to check whether the peer ID is the closest to the file ID. From the model-checking point of view, there are several properties that can be proved over this protocol. The basic property all P2P networks should fulfill is that if a peer looks for a file that is published somewhere, the peer eventually finds it. We define three propositions (of sort Prop, imported from the TIMED-MODEL-CHECKER module defined in Real-Time Maude) over the configuration expressing that a peer publishes a file; a peer is looking for that file; and the peer that searches the file finds it. Note that, as in the command above, all the properties are defined taking into account that the configurations are wrapped into objects of class Process, that may contain other objects and messages on the conf attribute (hence the CONF variable used there) and that other processes may also appear in the initial configuration (hence the CONF’ variable used at the Process level): op PublishAFile : Nat -> Prop [ctor] . eq {< O : Process | conf : (< O’ : Peer | Publish : < I1 & (S1 @ TC4) > # PF > CONF) > CONF’} |= PublishAFile(I1) = true . op SearchAFile : Nat Nat -> Prop [ctor] . eq {< O : Process | conf : (< peer(N) : Peer | SearchFiles : < I1 & (S1 ; TC3) > # SF > CONF) > CONF’} |= SearchAFile(N,I1) = true . op FindAFile : Nat Nat -> Prop [ctor] . eq {< O : Process | conf : (to peer(Searcher) : FILE-FOUND(I2,I1) CONF) > CONF’} |= FindAFile(Searcher,I1) = true .
Assuming an initial configuration where a peer publishes the file 200, that is searched by peer(22), we can use the following command to check that the property holds: Maude> (mc init’ |=t PublishAFile(200) /\ SearchAFile(22,200) => FindAFile(22,200) in time < 20 .) Result Bool : true
Another basic property is that once a file is published it remains published in some peers unless the publisher is disconnected. We can define the properties
FilePublished, stating that a peer publishes a file, and PeerOffline, indicating that a peer is offline, similarly to the properties above and use the following command to check the property: Maude> (mc init |=t ( [] (FilePublished(53,0)) U PeerOffline(0) in time < 40 .) Result ModelCheckResult : counterexample(...)
In a network where peer(0) has published file 53. Notice that the model checker finds a counterexample. The reason is that all the peers that share the file may be offline at the same time. The property should be reformulated, stating that if the file is published it will always be published again or the publisher will be disconnected: Maude> (mc init |=t ([] (FilePublished(53,0) \/ PeerOffline(0)) in time < 40 .) Result Bool : true
See http://maude.sip.ucm.es/kademlia to obtain the source code of the centralized specification, the complete initial terms used in the commands above, and the different properties proved.
6
Conclusions and Ongoing Work
We have presented in this paper a distributed implementation of the Kademlia protocol in Maude. This distributed system uses sockets to connect different Maude instances and, moreover, to connect each one of these instances to a Java server that provides tick messages notifying when a given amount of time has elapsed. It can be used to share files (only text files in the current specification) using this protocol, allowing peers to connect and disconnect in a dynamic way, adding and searching for new files. Moreover, we also provide a centralized specification of the system, which abstracts most of the details of the underlying architecture to focus on the Kademlia protocol. This centralized specification allows us to simulate and analyze the system using Real-Time Maude to represent the real time implemented in Java in the distributed version. We are currently working to improve the analysis by defining a more precise relation between physical and logical time, following the approach in [23,1]. There are some open issues from the model point of view. We want to incorporate more network processes, like the one that automatically connects a node to the network. There are also some eMule facilities that we have not studied yet, like the modification of the routing table to keep more contacts in it or to allow the publication of keywords and notes related to files. There are also some protections eMule implements to protect itself against possible attacks, like the protection of hot nodes, that requires a deeper study. It will also be useful to compare the eMule implementation with the aMule and BitTorrent ones. Finally, we want to study and prove more complex properties over the protocol.
References 1. M. AlTurki and J. Meseguer. Dist-Orc: A rewriting-based distributed implemen¨ tation of Orc with formal analysis. In P. C. Olveczky, editor, Proceedings of the 1st International Workshop on Rewriting Techniques for Real-Time Systems, RTRTS 2010, volume 36 of EPTCS, pages 158–177, 2010. 2. R. Bakhshi and D. Gurov. Verification of peer-to-peer algorithms: A case study. In Combined Proceedings of the Second International Workshop on Coordination and Organization, CoOrg 2006, and the Second International Workshop on Methods and Tools for Coordinating Concurrent, Distributed and Mobile Systems, MTCoord 2006, volume 181 of Electronic Notes in Theoretical Computer Science, pages 35– 47. Elsevier, 2007. 3. J. Borgstr¨ om, U. Nestmann, L. O. Alima, and D. Gurov. Verifying a structured peer-to-peer overlay network: The static case. In C. Priami and P. Quaglia, editors, Proceedings of the International Workshop on Global Computing 2004, GC 2004, volume 3267 of Lecture Notes in Computer Science, pages 251–266. Springer, 2004. 4. H. Breitkreuz. The eMule project. http://www.emule-project.net. 5. E. Chan-Tin, P. Wang, J. Tyra, T. Malchow, D. F. Kune, N. Hopper, and Y. Kim. Attacking the Kad network—real world evaluation and high fidelity simulation using DVN. Wiley Security and Communication Networks, 2009. 6. M. Clavel, F. Dur´ an, S. Eker, P. Lincoln, N. Mart´ı-Oliet, J. Meseguer, and C. Talcott. All About Maude: A High-Performance Logical Framework, volume 4350 of Lecture Notes in Computer Science. Springer, 2007. 7. S. S. P. Gummadi and S. Gribble. A measurement study of peer-to-peer file sharing systems. Technical Report UW-CSE-01-06-02, Department of Computer Science and Engineering, University of Washington, July 2001. 8. S. Haridi. EU-project PEPITO IST-2001-33234, 2002. Project funded by EU IST FET Global Computing (GC). http://www.sics.se/pepito/. 9. T. Lu, S. Merz, and C. Weidenbach. Model checking the Pastry routing protocol. In J. Bendisposto, M. Leuschel, and M. Roggenbach, editors, 10th International Workshop Automatic Verification of Critical Systems, AVOCS 2010, pages 19–21. Universit¨ at D¨ usseldorf, 2010. 10. P. Maymounkov and D. Mazi`eres. Kademlia: A peer-to-peer information system based on the XOR metric. In P. Druschel, M. F. Kaashoek, and A. I. T. Rowstron, editors, Revised Papers from the First International Workshop on Peer-to-Peer Systems, IPTPS 2001, volume 2429 of Lecture Notes in Computer Science, pages 53–65. Springer, 2002. 11. J. Meseguer. Conditional rewriting logic as a unified model of concurrency. Theoretical Computer Science, 96(1):73–155, 1992. 12. D. Mysicka. eMule attacks and measurements. Master’s thesis, Swiss Federal Institute of Technology (ETH) Zurich, 2007. ¨ 13. P. Olveczky, J. Meseguer, and C. Talcott. Specification and analysis of the AER/NCA active network protocol suite in Real-Time Maude. Formal Methods in System Design, 29:253–293, 2006. ¨ 14. P. C. Olveczky. Real-Time Maude 2.3 Manual, 2007. http://heim.ifi.uio.no/ ~peterol/RealTimeMaude. ¨ 15. P. C. Olveczky. Formal model engineering for embedded systems using Real-Time Maude. In F. Dur´ an and V. Rusu, editors, Proceedings of the 2nd International Workshop on Algebraic Methods in Model-based Software Engineering, AMMSE 2011, volume 56 of Electronic Proceedings in Theoretical Computer Science, pages 3–13, 2011.
¨ 16. P. C. Olveczky and J. Meseguer. Semantics and pragmatics of Real-Time Maude. Higher-Order and Symbolic Computation, 20:161–196, 2007. 17. I. Pita. A formal specification of the Kademlia distributed hash table. In V. M. Gul´ıas, J. Silva, and A. Villanueva, editors, Proceedings of the 10 Spanish Workshop on Programming Languages, PROLE 2010, pages 223–234. Ibergarceta Publicaciones, 2010. http://www.maude.sip.ucm.es/kademlia. Informal publication– Work in progress. 18. S. Ratnasamy, P. Francis, M. Handley, R. Karp, and S. Shenker. A scalable contentaddressable network. ACM SIGCOMM Computer Communication Review - Proceedings of the 2001 SIGCOMM conference, 31:161–172, October 2001. 19. A. Riesco. Distributed and mobile applications in Maude. Master’s thesis, Departamento de Sistemas Inform´ aticos y Computaci´ on, Facultad de Inform´ atica de la Universidad Complutense de Madrid, June 2007. 20. A. Riesco and A. Verdejo. Implementing and analyzing in Maude the enhanced interior gateway routing protocol. In G. Ro¸su, editor, Proceedings of the Seventh International Workshop on Rewriting Logic and its Applications, WRLA 2008, volume 238(3) of Electronic Notes in Theoretical Computer Science, pages 249– 266. Elsevier, 2009. 21. A. I. T. Rowstron and P. Druschel. Pastry: Scalable, decentralized object location, and routing for large-scale peer-to-peer systems. In R. Guerraoui, editor, Proceedings of the IFIP/ACM International Conference on Distributed Systems Platforms Heidelberg, Middleware 2001, volume 2218 of Lecture Notes in Computer Science, pages 329–350. Springer, 2001. 22. I. Stoica, R. Morris, D. Karger, M. F. Kaashoek, and H. Balakrishnan. Chord: A scalable peer-to-peer lookup service for internet applications. ACM SIGCOMM Computer Communication Review, 31:149–160, October 2001. 23. M. Sun and J. Meseguer. Distributed real-time emulation of formally-defined pat¨ terns for safe medical device control. In P. C. Olveczky, editor, Proceedings of the 1st International Workshop on Rewriting Techniques for Real-Time Systems, RTRTS 2010, volume 36 of EPTCS, pages 158–177, 2010. 24. G. Urdaneta, G. Pierre, and M. van Steen. A survey of DHT security techniques. ACM Computing Surveys, 43(2), January 2011.
Using narrowing to test Maude specifications? Adri´an Riesco Facultad de Inform´ atica, Universidad Complutense de Madrid, Spain
[email protected]
Abstract. Testing is one of the most important and most time-consuming tasks in the software developing process and thus techniques and systems to automatically generate and check test cases have become crucial. In previous work we have presented techniques to test membership equational logic specifications; these techniques consist of two steps: first several ground terms are generated by using all the available constructor symbols in a breadth-first search, and then these terms are processed to check whether they fulfill some properties. This approach presents the drawback of separating two related processes, thus examining several terms that are indistinguishable from the point of view of testing. We present here a narrowing-based test-case generator that improves the performance of the tool and extends its use to rewriting logic specifications. First, we present two mechanisms to improve the narrowing commands currently available in Maude to use conditional statements and equational modules. Then, we show how to use these new narrowing commands to perform three different approaches to testing for any Maude specification: code coverage, property-based testing, and conformance testing. Finally, we present trusting mechanisms to improve the performance of the tool. We illustrate the tool by means of an example. Keywords: testing, Maude, narrowing, coverage, property, conformance
1
Introduction
Testing is a technique for checking the correctness of programs by means of executing several inputs and studying the obtained results. Testing is one of the most important stages of the software-development process, but it also is a very time-consuming and tedious task, and for this reason several efforts have been devoted to automate it [2,1]. Basically, we can distinguish two different approaches to testing: glass-box testing [13,23], that uses the specific statements of the system to generate the most appropriate test cases, and black-box testing [31,14,5], that considers the system as a black box with an unknown structure and where a specification of the system is used to generate the test cases and check their correctness. We can also distinguish different kinds of testing depending on how the test cases are obtained: they can either be ground terms that are later executed to check the obtained results or terms with variables that ?
Research supported by MEC Spanish project DESAFIOS10 (TIN2009-14599-C0301) and Comunidad de Madrid program PROMETIDOS (S2009/TIC1465).
Using narrowing to test Maude specifications
145
are symbolically executed [19] to find the most appropriate values to test the program. While the former generates in general more test cases (because it just combines constructors to build terms) they can be illegal (input that can never be used in real executions) and equivalent (different test cases check the same statements), the latter generates less but more accurate test cases. Maude [8] is a high-level language and high-performance system supporting both equational and rewriting logic computation for a wide range of applications. Maude modules correspond to specifications in rewriting logic [21]. This logic is an extension of equational logic; in particular, Maude functional modules correspond to specifications in membership equational logic [3], which, in addition to equations, allows the statement of membership axioms characterizing the elements of a sort. Rewriting logic extends membership equational logic by adding rewrite rules, that represent transitions in a concurrent system. Maude system modules are used to define specifications in this logic. The current version of Maude supports a limited version of narrowing [30], a generalization of term rewriting that allows to execute terms with variables by replacing pattern matching by unification, for some unconditional rewriting logic theories without memberships. This limitation is dropped in this work by using a program transformation and by checking separately the conditions. As part of an ongoing project to test and debug Maude specifications, we have implemented a declarative debugger for Maude specifications [27], that allows the user to debug both wrong (incorrect results obtained from a valid input) and missing (incomplete results obtained from a valid input) answers in any Maude specification, and a test case generator for functional modules [26]. The testing approach used in that paper consists of different phases: first, the module is preprocessed to obtain the statements used by the functions being tested; then, terms are generated by using a breadth-first search that takes into account the constructor information provided by the user, and then each of these terms is executed step-by-step to check the used statements. However, this approach uses ground terms and, as explained above, presents an important drawback: since the test cases are not generated following the structure of the program but just the available constructors, most of them apply the same statements, hence consuming most of the time and preventing more complex terms from being checked due to the time and space constraints. This problem is solved here by symbolically executing terms with variables with narrowing. We present in this paper a program transformation to test Maude functional modules by using narrowing, a strategy to use membership axioms and conditional statements in the narrowing process,1 and the adaptation of three testing techniques to Maude: two white-box approaches (one selects a set of test cases whose correctness must be checked by the user, while the other one checks whether a property holds in the specification) and one black-box mechanism 1
This strategy allows all kinds of conditions: rewrite and equational conditions, solved by narrowing (the latter, which includes equational and matching conditions, requires a previous transformation), and membership conditions, solved by using unification.
146
Adri´ an Riesco
(conformance testing). In the first case, in addition to other criteria described in [26], we have adapted a new criterion to select the set of test cases to be checked by the user in system modules, which is based on modified condition decision coverage [18] and checks the negative information (the rules that are not applied). Finally, we enhance the performance of the tool by providing trusting techniques that prevent the system from taking into account some statements. The transformation, the extension of the narrowing process, and the testing strategies have been implemented in a Maude prototype by using its meta-level capabilities, that allow to manipulate Maude modules and statements as usual data. Moreover, it also provides support for some predefined modules and attributes, such as owise, that indicates that the current equation is only used when the rest of equations cannot be applied. The rest of the paper is organized as follows: Section 2 presents some related work and its relation with our system. Section 3 introduces Maude and narrowing, Section 4 describes a module transformation that allows us to use narrowing on Maude functional modules, while Section 5 presents how to use conditional rules in the narrowing process. Section 6 illustrates how the techniques described in the previous sections are used to generate test cases, while Section 7 presents some trusting techniques to improve the performance of the system. Finally, Section 8 concludes and outlines some future work. The source code of the tool, examples, related papers, and much more information is available at http://maude.sip.ucm.es/testing/.
2
Related work
Different approaches to testing for declarative languages have been proposed in the literature. As explained in the introduction, test cases can be checked in different ways: executing ground test cases or symbolically executing terms with variables. The first approach is followed by Smallcheck [29], a property-driven Haskell tool that considers that most of the errors can be found by using only a few constructors, and thus it generates all the possible combinations of constructors given a (usually small) bound on the size of the test cases. Another tool following this ground approach is Quickcheck [7], a test-case generator developed for Haskell specifications where the programmer writes assertions about logical properties that a function should fulfill; test cases are randomly generated by using the constructors of the data type (in contrast to the complete search performed by Smallcheck) to test and attempt to falsify these assertions. The project, started in 2000, has been extended to generate test cases for several languages such as Java, C++, Erlang, and several others. Finally, Easycheck [6] is a test-case generator for Curry that takes advantage of the non-determinism of functional-logic programs to generate a tree of potential test cases, that is later traversed to list only the most interesting ones. The second approach has been applied by Lazy Smallcheck [29] (an improvement of a previous system called SparseCheck), a library for Haskell to
Using narrowing to test Maude specifications
147
test partially-defined values that uses a mechanism similar to narrowing to test whether the system fulfills some requirements. Another way of achieving symbolic execution is by considering that the statements in the program under test introduce constraints on the variables, an approach followed by PET [15], that uses Constraint Logic Programming to generate test cases satisfying some coverages on object-oriented languages. Finally, narrowing has been used to verify security protocols [20,17], symbolically exploring the state space trying to find a flow in the protocol. The previous version of our approach is quite similar to Smallcheck: we generate the complete search space given the constructors and a bound, but we use them for both white-box and black-box testing, while Smallcheck only tries to disprove some properties. Note that, on the one hand, the strategies in our previous system could possibly be improved by following an approach similar to Easycheck, while on the other hand we can consider that the current narrowing approach is another way of pruning the tree of possible terms, making our approach similar to it. Regarding Quickcheck, it is an industrial tool with several heuristics and a lot of experience in testing, and hence it presents a better performance than our tool, that we try to improve by providing trusting mechanisms to the user. On the other hand, an advantage of our tool is the computation of test cases fulfilling different coverage criteria, which allows the user to test the specification by checking test cases “by hand” even when no properties over the specification are stated, and the usage of Maude as both a specification and implementation language, which allows to perform conformance testing using a previously tested Maude module as specification. Moreover, both Quickcheck and our tool implement the shrinking mechanism, that consists of returning the simplest form of a term that detects a bug in the program; in our case it is implemented by performing a breadth-first search using narrowing steps, that will find the simplest term (w.r.t. the number of steps) reproducing the buggy behavior. The more similar approach to ours is Lazy Smallcheck; both are narrowing-based experimental tools that focus on research rather than in efficiency, and thus they present a similar performance; however, Smallcheck is only applied to propertybased testing. PET provides a coverage of the statements in Java-like programs, but it does not allow the user to state properties or check the correctness of the system against a specification. Finally, the verification of security protocols focus on a specific problem and cannot be compared with the rest of tools. Note that, in general, each system only focus in one testing approach: coverage, properties, or conformance. Maude features allow us to implement a wide range of testing techniques: we can manipulate its modules to perform white-box testing by using its meta-level capabilities; its analysis tools (such as the search command) ease the testing of properties; and Maude programs can be used as specification of others.
3
Preliminaries
This section introduces Maude and its narrowing mechanisms [9].
148
3.1
Adri´ an Riesco
Maude
Maude functional modules [8, Chap. 4], with syntax fmod ... endfm, are executable membership equational specifications that allow the definition of sorts (by means of keyword sort(s)); subsort relations between sorts (subsort); operators (op) for building values of these sorts, giving the sorts of their arguments and result, and which may have attributes such as being associative (assoc) or commutative (comm), for example; memberships (mb) asserting that a term has a sort; and equations (eq) identifying terms. Both memberships and equations can be conditional (cmb and ceq). Maude system modules [8, Chap. 6], introduced with syntax mod ... endm, are executable rewrite theories [21]. A system module can contain all the declarations of a functional module and, in addition, declarations for rules (rl) and conditional rules (crl). An important characteristic of Maude functional modules is that sorts are grouped into equivalence classes called kinds; that is, all the sorts related by a subsort relation belong to the same kind [8]. Intuitively, terms with a kind but without a sort represent undefined or error elements. We will make extensive use of kinds to indicate that variables may have any sort when performing unification; the proper sorts of the variables will be later checked by means of membership axioms. We introduce Maude modules with an example; variable declarations are not shown because of space constraints, but assume they are defined at the sort level. We specify ordered lists of natural numbers in the following module: (fmod SORTED-NAT-LIST is pr NAT .
We use the sort NatList, with constructors nil and _._, for generic lists and SortedList for sorted lists, which are a subsort of NatList: sorts SortedList NatList . op nil : -> SortedList [ctor] .
subsorts SortedList < NatList . op _._ : Nat NatList -> NatList [ctor] .
We use membership axioms to characterize nonempty sorted lists. They indicate that the singleton list is ordered (ol1) and that a larger list is ordered if the first element is equal to or smaller than the second one and the rest of the list is also ordered (ol2): mb [ol1] : N . nil : SortedList . cmb [ol2] : N . N’ . L : SortedList if N SortedList . eq [is1] : ins-sort(nil) = nil . eq [is2] : ins-sort(N . L) = ins-list(ins-sort(L), N) .
This function returns the singleton list when inserting an element into the empty list, and otherwise it distinguishes whether the first element in the list is smaller or not:
Using narrowing to test Maude specifications op ins-list : SortedList eq [il1] : ins-list(nil, ceq [il2] : ins-list(N . ceq [il3] : ins-list(N .
149
Nat -> SortedList . N) = N . nil . SL, N’) = N’ . (N . SL) if N’ NatWithEmpty [ctor] . op mtSoup : -> NatSoup [ctor] . op _,_ : NatSoup NatSoup -> NatSoup [ctor assoc comm id: mtSoup] . op _[_][_]_ : NatSoup NatList NatWithEmpty NatSoup -> System [ctor] .
We use the rule ticket to introduce a new process into the list of waiting processes: rl [ticket] : (N, NS) [NL] [NWE] NS’ => NS [ins-list(NL, N)] [NWE] NS’ .
If at least one process is waiting to enter the critical section and it contains the value empty, then the first process in the list is introduced into the critical section: rl [cs-in] : NS [N . NL] [empty] NS’ => NS [NL] [N] NS’ .
The rule cs-out moves the process from the critical section to the finished section: rl [cs-out] : NS [NL] [N] NS’ => NS [NL] [empty] (N, NS’) .
Finally, the rule reset moves the elements in the fourth component of the system to the first one to start the process again: rl [reset] : mtSoup [nil] [empty] NS => NS [nil] [empty] mtSoup . endm)
150
3.2
Adri´ an Riesco
Narrowing
Narrowing [30,12,22] is a generalization of term rewriting that allows free variables in terms and replaces pattern matching by unification in order to reduce these terms. It was first used for solving equational unification problems [28] and then generalized to deal with problems of symbolic reachability. Similarly to rewriting, where at each rewriting step one must choose which subterm of the subject term and which rule of the specification are going to be considered, at each narrowing step one must choose which subterm of the subject term, which rule of the specification, and which instantiation on the variables of the subject term and the rule’s lefthand side are going to be considered. The difference between a rewriting step and a narrowing step is that in both cases we use a rewrite rule l ⇒ r to rewrite t at a position p, but narrowing unifies the lefthand side l and the chosen subject term t before actually performing the rewriting step, while in rewriting this term must be an instance of l (i.e., only matching is required). Using this narrowing approach, we can obtain a substitution that, applied to an initial term that only contains variables (except for the function symbol at the top), generates the most general term that can apply the traversed rules. We denote by t σ t0 , with σ = q1 ; . . . ; qn a sequence of labels, the succession of narrowing steps applying (in the given order) the statements q1 ; . . . ; qn that leads from the initial term t (possibly with variables) to the term t0 , and by θσ the substitution used by this sequence, which results from the composition of the substitutions obtained in each narrowing step. We will overload the notation t q t0 by using conditions in q to illustrate narrowing steps due to conditions. In the example above, we could start from the term NS1 [NL] [NWE] NS2, with NS1 and NS2 variables of sort NatSoup, NL a variable of sort NatList, and NWE a variable of sort NatWithEmpty, and apply one step of narrowing to obtain a set of four terms, each of them corresponding to the application of one of the rules for System. For example, NS1 [NL] [NWE] NS2
ticket
NS3 [ins-list(NL, N1)] [NWE] NS2
where NS1 has been replaced by N1, NS3 (with N1 and NS3 fresh variables of sorts Nat and NatSoup, respectively) and then the rule ticket has been applied. The latest version of Maude includes an implementation of narrowing for free, C, AC, or ACU theories in Full Maude [9]. More specifically, we are interested in the metaNarrowSearchPath function that, given a term and a bound on the number of narrowing steps, returns all the possible paths starting from this term, the used substitutions, and the applied rules. We use this command to perform a breadth-first search of the state space. Note that the current implementation of narrowing only works for non-conditional rules and specifications without membership axioms; we will show in Section 5 how to check separately the conditions, including membership conditions.
Using narrowing to test Maude specifications
4
151
A module transformation for narrowing
We present in this section a simple module transformation that will be applied to the modules in order to use narrowing with the equational part of Maude. This transformation has two objectives: on the one hand it transforms equations into rules (and thus it requires to transform equational conditions into rewrite conditions), which allows us to use narrowing with the equational part of Maude system modules. On the other hand, and since the current implementation of narrowing in Maude does not support memberships, we transform all the terms where membership inferences may be needed into equivalent terms with the variables declared at the kind level, while extra membership conditions stating the correct sort, that will be separately checked with the mechanisms in the next section, are added for each variable whose type has changed. More specifically, the transformation takes an equation of the form l = r if
n ^ i=1
ti = t0i ∧
m ^ j=1
pj := uj ∧
l ^
vk : sk
k=1
and returns a rule kind (l) ⇒ kind (r) if mbs(l) ∧ Vn (kind (ti ) ⇒ wi ∧ kind (t0i ) ⇒ wi ) ∧ Vi=1 m (kind (uj ) ⇒ kind (pj ) ∧ mbs(pj )) ∧ Vlj=1 k=1 kind (vk ) : sk where – The terms wi are fresh variables of the same kind as the corresponding term. – The function kind replaces the sort of all the variables in the term given as argument by the corresponding kind (we follow here the Maude approach that represents each variable as a pair of an identifier and a type, that can be either a sort or a kind; thus, we can modify these pairs when the second component is a sort by the appropriate kind). – The function mbs generates a conjunction of conditions stating that the variables, whose type has been changed by its kind, have in fact the sort previously required, that is: mbs(f (t1 , . . . , tn )) = mbs(t1 ) ∧ · · · ∧ mbs(tn ) mbs(c) = nil mbs(v) = kind (v) : sort(v) where f is a function symbol, the ti are terms, c is a constant, v is a variable, and sort(v) returns the sort of v. We have to transform similarly all the membership axioms and rules in the module in order to apply them. In the membership case we obtain another membership axiom with the lefthand side and the condition transformed as shown
152
Adri´ an Riesco
above,2 while rules are transformed into rules, being the equational part transformed as in the previous cases while the rewriting conditions remain unchanged. Note that, since Maude equational modules are assumed to be confluent and terminating, the equations may be understood as oriented from left to right, which is what we are explicitly doing when transforming them into rules. Moreover, the kind transformation only postpones (but not prevents from) the checking of the specific sorts of the variables to the condition of the rule. For these reasons, it is straightforward to see that this transformation is correct, even though it can only be executed by using narrowing as explained in the next section. If we transform the critical section example above, the membership axiom ol2 is modified as follows (assume that the variables are now declared at the kind level): cmb [ol2] : N . N’ . L : SortedList if N : Nat /\ N’ : Nat /\ L : NatList /\ N B /\ true => B /\ N’ . L : SortedList .
The first three conditions indicate that the variables, that are now declared at the kind level, have in fact the appropriate sort. The next two conditions deal with the first condition of the original axiom, N B .
where the first three conditions indicate that the variables have the appropriate sort. The next two conditions deal with the condition of the original axiom, N’ +; the tool also provides searches in zero or more steps with =>* and searches for final forms with =>!) and at most 10, match the pattern and fulfill the condition (the negation of the invariant). In this case, the tool has found (as expected) an initial state that, after applying one rule (in this specific case it is cs-out although it would be possible to apply other rules), reaches a state that does not fulfill the invariant. In this case the narrowing process has fixed the value of the first NatSoup to mtSoup to fulfill the condition and has forced an element to be in the critical section to apply the rule, while the nil list and the singleton soup are just possible instances of the variables left by the narrowing stepNS1 [NL] [NWE] NS2 cs-out NS1 [NL] [empty] (N1, NS2) and then checking the property by instantiating NS1 with mtSoup when applying the equations for empty?. 6.3
Conformance testing
Conformance testing [31,14,5] involves testing a system with respect to its specification. The goal of this approach is to check that the system presents the same behavior as the specification, that has already been tested. To check whether an implementation conforms to a specification we must formalize the conformance notion by means of an implementation relation that relates the two systems. In our case, and taking into account that a rewrite system can be understood as a labeled transition system, where terms stand for states and rewrites for transitions, we apply to Maude specifications the conformance testing strategies for such systems [31]. In particular, we use the relation conf [4], that requires the implementation to perform the same actions as the specification, although it allows the implementation to execute some other actions not included in the specification, that is, conf requires that an implementation does what it should do, not that it does not do what it is not allowed to do. In our framework we consider that only the rules in the original specification must be executed in the implementation, and thus narrowing steps using
Using narrowing to test Maude specifications
159
equations are considered auxiliary and it is not required to reproduce them in the implementation. In this way, we compute all the possible paths by using narrowing in the specification and then that all these paths are also possible in the implementation. More formally, if we denote by σ |R the restriction of σ to the rules in R, that is, remove from σ all those statements that are not in the set, then we require that for every narrowing sequence t σs ts in the specification there exists a narrowing sequence t σi ti in the implementation such that σs |R is a prefix of σi |R . Note that, although the reached states may be different in the specification and the implementation (only the applied rules matter), we consider that both the correct specification and the system being tested share the same signature for the initial terms and the same rule labels; this can be achieved by means of a renaming. For the sake of example, we could create a new module RED-CS that has the same rules as CS except for the rule cs-out. We can state CS as the specification with: Maude> (correct test module CS .) CS selected as correct module for testing.
Now, we can check the behavior of RED-CS with respect to this module with: Maude> (test in RED-CS : System .) Starting from the term 0 [nil] [0] 0 the rule cs-out could not be applied to the implementation.
That is, the tool shows the simplest term (in fact, only the 0 in the critical section is instantiated during the process) that is required to find the disconformity between the specification and the implementation due to the cs-out rule.
7
Trusting
Our tool provides some trusting techniques to enhance its performance. Basically, it only takes into account labeled statements when computing coverages and checking the implementation relation. Moreover, the user can also select a subset of these statements by using the different commands available in the tool (trusting of all the statements of a given module, trusting of a complete kind of statements—e.g. all the equations, memberships, or rules—and trusting of single statements). Using these commands we can use different trusting strategies: assuming that our specifications are structured, we can test first easier specifications, and then trust them when testing larger specifications including them; and we can trust all the equations (except for the ones defining the property when checking invariants) and memberships when testing system modules. Of course, trusting mechanisms are correct assuming the user points out as trusted only rules that are not relevant for the testing process. Trusting works in a different way depending on the testing strategy: if we are computing a coverage then the trusted statements are removed from the needed coverage, and thus we may reduce both the number and the complexity
160
Adri´ an Riesco
of the test cases. When using conformance testing, the trusted statements are related to the specification and indicate that the behavior specified by the rule is not required to be performed in the system being tested (e.g. because it is an auxiliary rule). That is, the sequences of statements σ required for coverage are not required to contain the trusted statements,5 while the restriction to rules in the specification given in conformance testing is now applied to non-trusted rules in the specification. For example, we can trust the statements il3 and ol2 (which required the longest computations in Figure 1) if we are sure of its correctness to improve the performance of the computation of the global branch coverage in Section 6.1 by using the commands: Maude> (test include SORTED-NAT-LIST .) Labels hd il1 il2 il3 is1 is2 ol1 ol2 have been added to the coverage. Maude> (test deselect il3 ol2 .) Labels il3 ol2 have been excluded from the coverage. Maude> (test in SORTED-NAT-LIST : ins-sort .) 1. ins-sort(0 . 0 . 0 . nil) has been reduced to 0 . 0 . 0 . nil All the statements were covered.
Obtaining in this case a simpler test case that covers all the statements. It is interesting to see that trusting a rule when using conformance provides more flexibility, because it allows to perform some analyses by removing auxiliary rules that are not supposed to be applied in the final implementation. However, if the user trusts a statement that should not be trusted he may obtain an incorrect answer, hence the assumption presented above about the correctness of trusting, that may produce incorrect results. Similarly, we can trust the rule cs-out when using conformance testing and check that in this case the specification and the implementation perform the same actions: Maude> (test deselect cs-out .) Labels cs-out have been excluded from the coverage. Maude> (test in RED-CS : System .) The implementation conforms to the specification.
The improvement in the performance when using trusting is highly dependent on the selected set of statements: while in some cases trusting may reduce the number of steps more than a 50%, in other cases they are not reduced at all. For example, the global branch coverage obtained in Section 6.1 was highly reduced by trusting the statements shown above, reducing the depth of the search tree from 10 to 7, as illustrated in Figure 2.6 However, selecting other statements such as is1 or is2, that must be always executed in order to reach a state where other statements can be used, would not reduce the size of the search at all. All the examples in this paper, and much more information is available at http://maude.sip.ucm.es/testing/. 5
6
Note that using trusting when using system coverage will remove the statements from both the positive and negative information. Remember that this is one branch of the search tree, that is, trusting has reduced the depth of the search tree from 10 to 7, which results in a huge improvement of the performance.
Using narrowing to test Maude specifications ins-sort(L) is2 ins-list(ins-sort(L1), N1) is2 ins-list(ins-list(ins-sort(L2), N2), N1) is2 ins-list(ins-list(ins-list(ins-sort(L3), N3), N2), N1) ins-list(ins-list(ins-list(nil, N3), N2), N1) il1 ins-list(ins-list(N3 . nil, N2), N1) il2 ins-list(0 . N3 . nil, N1) il2,is1 0 . 0 . N3 . nil
161
is1
Fig. 2. Narrowing path for global branch coverage with trusting
8
Concluding remarks and ongoing work
We have presented in this paper how to use narrowing to generate test cases for Maude specifications. To achieve this we use a module transformation that allows us to use the equational part of Maude modules in the narrowing process and a method to check whether the conditions of the applied statements are fulfilled, including those conditions that require membership axioms. Using these techniques we have implemented a tool that is able to compute a set of test cases fulfilling two different coverage criteria, to check whether an invariant is fulfilled by the specification, and to examine whether an implementation of the system fulfills the behavior indicated by its specification. Moreover, two different sets of test cases can be computed: a smaller set that contains more complex terms or a larger set that contains less complex terms; the user is in charge of selecting the most appropriate depending on the complexity of the specification and his knowledge of it. Trusting mechanisms are also provided to improve the performance of both coverage criteria and conformance testing. Finally, some predefined modules can be also used to generate the test cases. We are currently working on a comparison between our current approach using narrowing and (i) the previous one using ground terms, and (ii) similar approaches in other languages, either using narrowing, like Lazy Smallcheck, or random testing, like QuickCheck. As future work, we plan to extend the tool by introducing symbolic model checking [11], that would allow the user to check linear temporal logic formulas over the specification starting from a term with variables, thus proving the formula on, potentially, all the possible inputs of the system. Moreover, we are studying new coverage criteria and implementation relations to allow the user to choose the most appropriate technique for each application. Finally, we also intend to develop a distributed implementation of the tool to deal with narrowing; in this way, we can start the symbolic search of the system in one Maude instance and then send the different paths to different Maude processes, that must share some information (the coverage and the reached states) to finish the search as soon as possible. Acknowledgements I thank Santiago Escobar for his kind help with narrowing.
162
Adri´ an Riesco
References 1. B. Beizer. Software testing techniques. Dreamtech, 2002. 2. P. Borba, A. Cavalcanti, A. Sampaio, and J. Woodcook, editors. Testing Techniques in Software Engineering. Second Pernambuco Summer School on Software Engineering, PSSE 2007, Recife, Brazil, December 3-7, 2007, Revised Lectures, volume 6153 of Lecture Notes in Computer Science. Springer, 2007. 3. A. Bouhoula, J.-P. Jouannaud, and J. Meseguer. Specification and proof in membership equational logic. Theoretical Computer Science, 236:35–132, 2000. 4. E. Brinksma, G. Scollo, and C. Steenbergen. LOTOS specifications, their implementations and their tests. Protocol Specification, Testing, and Verification, VI:349–360, 1987. 5. E. G. Cartaxo, F. G. O. Neto, and P. D. L. Machado. Test case generation by means of UML sequence diagrams and labeled transition systems. In Proceedings of the IEEE International Conference on Systems, Man and Cybernetics, SMC 2007, pages 1292–1297. IEEE, 2007. 6. J. Christiansen and S. Fischer. Easycheck – test data for free. In Proceedings of the 9th International Symposium on Functional and Logic Programming, FLOPS 2008, volume 4989 of Lecture Notes in Computer Science. Springer, 2008. 7. K. Claessen and J. Hughes. Quickcheck: A lightweight tool for random testing of Haskell programs. In ACM SIGPLAN Notices, pages 268–279. ACM Press, 2000. 8. M. Clavel, F. Dur´ an, S. Eker, P. Lincoln, N. Mart´ı-Oliet, J. Meseguer, and C. Talcott. All About Maude: A High-Performance Logical Framework, volume 4350 of Lecture Notes in Computer Science. Springer, 2007. 9. M. Clavel, F. Dur´ an, S. Eker, P. Lincoln, N. Mart´ı-Oliet, J. Meseguer, and C. Talcott. Maude Manual (Version 2.6), January 2011. http://maude.cs.uiuc.edu/ maude2-manual. 10. A. Dupuy and N. Leveson. An empirical evaluation of the MC/DC coverage criterion on the HETE-2 satellite software. In Proceedings of the 19th Digital Avionics Systems Conference, DASC 2000, volume 1, pages 1B6.1–1B6.7, 2000. 11. S. Escobar and J. Meseguer. Symbolic model checking of infinite-state systems using narrowing. In Proceedings of the 18th International Conference on Term Rewriting and Applications, RTA 2007, volume 4533 of Lecture Notes in Computer Science, pages 153–168. Springer, 2007. 12. M. Fay. First-order unification in an equational theory. In W. H. Joyner, editor, Proceedings of the 4th Workshop on Automated deduction, Academic Press, pages 161–167, 1979. 13. S. Fischer and H. Kuchen. Systematic generation of glass-box test cases for functional logic programs. In Proceedings of the 9th ACM SIGPLAN International Conference on Principles and Practice of Declarative Programming, PPDP 2007, pages 63–74. ACM Press, 2007. 14. M.-C. Gaudel. Software testing based on formal specification. In P. Borba, A. Cavalcanti, A. Sampaio, and J. Woodcock, editors, Testing Techniques in Software Engineering, Second Pernambuco Summer School on Software Engineering, PSSE 2007, Revised Lectures, volume 6153 of Lecture Notes in Computer Science, pages 215–242. Springer, 2010. 15. M. Gomez-Zamalloa, E. Albert, and G. Puebla. Test case generation for objectoriented imperative languages in CLP. Theory and Practice of Logic Programming, 10:659–674, 2010.
Using narrowing to test Maude specifications
163
16. R. M. Hierons, K. Bogdanov, J. P. Bowen, J. D. Rance Cleaveland, J. Dick, M. Gheorghe, M. Harman, K. Kapoor, P. Krause, G. L¨ uttgen, A. J. H. Simons, S. Vilkomir, M. R. Woodward, and H. Zedan. Using formal specifications to support testing. ACM Computing Surveys, 41(2):1–76, 2009. 17. F. Jacquemard, M. Rusinowitch, and L. Vigneron. Compiling and verifying security protocols. In M. Parigot and A. Voronkov, editors, Proceedings of the 7th international conference on Logic for programming and automated reasoning, LPAR 2000, volume 6397 of Lecture Notes in Computer Science, pages 131–160. Springer, 2000. 18. R. Jasper, M. Brennan, K. Williamson, B. Currier, and D. Zimmerman. Test data generation and feasible path analysis. In Proceedings of the 1994 ACM SIGSOFT international symposium on Software testing and analysis, ISSTA ’94, pages 95– 107. ACM, 1994. 19. J. C. King. Symbolic execution and program testing. Communications of the ACM, 19:385–394, July 1976. 20. C. Meadows. Applying formal methods to the analysis of a key management protocol. Journal of Computer Security, 1, 1992. 21. J. Meseguer. Conditional rewriting logic as a unified model of concurrency. Theoretical Computer Science, 96(1):73–155, 1992. 22. A. Middeldorp and E. Hamoen. Counterexamples to completeness results for basic narrowing. In Proceedings of the 3rd International Conference on Algebraic and Logic Programming, volume 632 of Lecture Notes in Computer Science, pages 244– 258. Springer, 1992. 23. R. A. M¨ uller, C. Lembeck, and H. Kuchen. A symbolic Java virtual machine for test case generation. In IASTED Conf. on Software Engineering, pages 365–371, 2004. 24. S. C. Ntafos. A comparison of some structural testing strategies. IEEE Transactions on Software Engineering, 14:868–874, June 1988. 25. C. Pacheco. Directed Random Testing. PhD thesis, Massachusetts Institute of Technology, June 2009. 26. A. Riesco. Test-case generation for Maude functional modules. In Proceedings of the 20th International Workshop on Algebraic Development Techniques, WADT 2010, Lecture Notes in Computer Science. Springer, 2011. To appear. 27. A. Riesco, A. Verdejo, N. Mart´ı-Oliet, and R. Caballero. Declarative debugging of rewriting logic specifications. Journal of Logic and Algebraic Programming, 2011. To appear. 28. J. A. Robinson. A machine-oriented logic based on the resolution principle. Journal of the ACM, 12(1):23–41, 1965. 29. C. Runciman, M. Naylor, and F. Lindblad. Smallcheck and Lazy Smallcheck: automatic exhaustive testing for small values. In A. Gill, editor, Proceedings of the 1st ACM SIGPLAN Symposium on Haskell, Haskell 2008, Victoria, BC, Canada, 25 September 2008, pages 37–48. ACM, 2008. 30. J. R. Slagle. Automated theorem-proving for theories with simplifiers, commutativity and associativity. Journal of the ACM, 21(4):622–642, 1974. 31. J. Tretmans. Model based testing with labelled transition systems. In R. M. Hierons, J. P. Bowen, and M. Harman, editors, Formal Methods and Testing, An Outcome of the FORTEST Network, Revised Selected Papers, volume 4949 of Lecture Notes in Computer Science, pages 1–38. Springer, 2008.
A Rule-Based Framework for Building Superposition-Based Decision Procedures Elena Tushkanova1,2 , Alain Giorgetti1,2 , Christophe Ringeissen1 , and Olga Kouchnarenko1,2 1 2
INRIA Nancy - Grand Est, 615 rue du Jardin Botanique, Villers-les-Nancy, France CNRS FEMTO-ST and University of Franche-Comt´e, 16 route de Gray, Besan¸con, France
Abstract. This paper deals with decision procedures specified as inference systems. Among them we focus on superposition-based decision procedures. The superposition calculus is a refutation-complete inference system at the core of all equational theorem provers. In general this calculus provides a semi-decision procedure that halts on unsatisfiable inputs but may diverge on satisfiable ones. Fortunately, it may also terminate for some theories of interest in verification, and thus it becomes a decision procedure. To reason on the superposition calculus, a schematic superposition calculus has been studied, for instance to automatically prove termination. This paper presents an implementation in Maude of these two inference systems. Thanks to this implementation we automatically derive termination of superposition for a couple of theories of interest in verification.
1
Introduction
Satisfiability procedures modulo background theories such as classical data structures (e.g., lists, records, arrays, . . .) are at the core of many state-of-the-art verification tools. Designing and implementing satisfiability procedures is a very complex task, where one of the main difficulties consists in proving their soundness. To overcome this problem, the rewriting approach [2] allows us to build satisfiability procedures in a flexible way, by using a superposition calculus [14] (also called Paramodulation Calculus in [9]). In general, a fair and exhaustive application of the rules of this calculus leads to a semi-decision procedure that halts on unsatisfiable inputs (the empty clause is generated) but may diverge on satisfiable ones. Therefore, the superposition calculus provides a decision procedure for the theory of interest if one can show that it terminates on every input made of the (finitely many) axioms and any set of ground literals. The needed termination proof can be done by hand, by analysing the (finitely many) forms of clauses generated by saturation, but the process is tedious and error-prone. To simplify this process, a schematic superposition calculus has been developed [9] to build the schematic form of the saturations. This schematic superposition calculus is very useful to analyse the behavior of the superposition calculus on a
Title Suppressed Due to Excessive Length
165
given input theory, as shown in [10] to prove automatically the termination and the combinability of the related decision procedure. This paper explains how to prototype the schematic superposition calculus to provide a toolkit for further experiments. The main idea is to implement the calculus so that the user can easily modify the code corresponding to an executable specification. Implementing this schematic calculus in an off-the-shelf equational theorem prover like the E prover [16] or SPASS [17] would be a difficult and less interesting task, since the developer and the user would have to understand a complex piece of code which is the result of years of engineering and debugging. To make the task easier another quite natural solution would be to use a logical framework since this calculus is defined by an inference system. This is why we propose to prototype the schematic superposition calculus by using a rule-based logical framework. Our goal is to get a rule-based program which is as close as possible to the formal specification. To achieve this goal, we propose to use Maude because Maude includes support for unification and narrowing, which are key operations of the calculus of interest, and the Maude meta-level provides a flexible way to control the application of rules and powerful search mechanisms. Our implementation of schematic superposition is very useful to get an automatic validation of saturations described in previous papers. Hence, our experimentations allow us to find a flaw in an example of [10]. The paper is structured as follows. After introducing preliminary notions and presenting superposition calculi in Section 2, Section 3 explains how we implement these calculi using the Maude system. Then Section 4 reports our experimentations with our implementation to prove the termination of superposition for theories corresponding to classical data structures such as lists and records. Section 5 concludes and presents future work.
2 2.1
Background First-Order Logic
We assume the usual first-order syntactic notions of signature, term, position, and substitution, as defined, e.g., in [5]. We use the following notations: l, r, u, t are terms, v, w, x, y, z are variables, all other lower case letters are constant or function symbols. Given a function symbol f , a f -rooted term is a term whose top-symbol is f . A compound term is a f -rooted term for a function symbol f of arity different from 0. Given a term t and a position p, t|p denotes the subterm of t at position p, and t[l]p denotes the term t in which l appears as the subterm at position p. When the position p is clear from the context, we may simply write t[l]. The depth of a term is defined inductively as follows: depth(t) = 0, if t is a constant or a variable, and depth(f (t1 , . . . , tn )) = 1+max{depth(ti ) | 1 ≤ i ≤ n}. A term is flat if its depth is 0 or 1. Application of a substitution σ to a term t (resp. a formula ψ) is written σ(t) (resp. σ(ψ)). A literal is either an equality l = r or a disequality l 6= r. A positive literal is an equality and a negative literal is a disequality. We use the symbol ./ to
166
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
denote eiher = or 6=. The depth of a literal l ./ r is defined as follows: depth(l ./ r) = depth(l) + depth(r). A positive literal is flat if its depth is 0 or 1. A negative literal is flat if its depth is 0. A first-order formula is built in the usual way over the universal and existential quantifiers, Boolean connectives, and symbols in a given first-order signature. We call a formula ground if it has no variables. A clause is a disjunction of literals. A unit clause is a clause with only one disjunct, equivalently a literal. The empty clause, denoted ⊥, is the clause with no disjunct, corresponding to an unsatisfiable formula. We also consider the usual first-order notions of model, satisfiability, validity, logical consequence. A first-order theory (over a finite signature) is a set of firstorder formulae with no free variables. When T is a finitely axiomatized theory, Ax(T ) denotes the set of axioms of T . We consider first-order theories with equality, for which the equality symbol = is always interpreted as the equality relation. A formula is satisfiable in a theory T if it is satisfiable in a model of T . The satisfiability problem modulo a theory T amounts to establishing whether any given finite conjunction of literals (or equivalently, any given finite set of literals) is T -satisfiable or not. In this paper, we study decision procedures for the satisfiability problem modulo T , where Ax(T ) is a finite set of literals. We consider inference systems using well-founded orderings on terms/literals that are total on ground terms/literals. An ordering < on terms is a simplification ordering [5] if it is stable (l < r implies lσ < rσ for every substitution σ), monotonic (l < r implies t[l]p < t[r]p for every term t and position p), and has the subterm property (i.e., it contains the subterm ordering: if l is a strict subterm of r, then l < r). Simplification orderings are well-founded. A term t is maximal in a multiset S of terms if there is no u ∈ S such that t < u, equivalently t 6< u for every u ∈ S. Hence, if t 6≤ u, then t and u are different terms and t is maximal in {t, u}. An ordering on terms is extended to literals by using its multiset extension on literals viewed as multisets of terms. Any positive literal l = r (resp. negative literal l 6= r) is viewed as the multiset {l, r} (resp. {l, l, r, r}). Also, a term is maximal in a literal whenever it is maximal in the corresponding multiset. 2.2
Paramodulation Calculus
In this paper we consider unit clauses, i.e. clauses composed of at most one literal. We present the restriction UPC (for Unit Paramodulation Calculus) of the inference system PC. Our presentation of this calculus takes the best (to our sense) from the presentations in [2], [9] and [10]. The inference system UPC consists of the rules in Figs. 1 and 2. Expansion rules (Fig. 1) aim at generating new (deduced) clauses. For brevity left and right paramodulation rules are grouped into a single rule, called Superposition, that uses an equality to perform a replacement of equal by equal into a literal. Reflection rule generates the empty clause when the two sides of a disequality are unifiable. Contraction rules (Fig. 2) aim at simplifying the set of literals. Using Subsumption, a literal is removed when it is an instance
Title Suppressed Due to Excessive Length
167
of another one. Simplification rewrites a literal into a simpler one by using an equality that can be considered as a rewrite rule. Trivial equalities are removed by Deletion. A fundamental feature of PC and UPC is the usage of a simplification ordering < to control the application of Superposition and Simplification rules by orienting equalities. Hence, the Superposition rule is applied by using terms that are maximal in their literals with respect to j Si , that is, the union for each j ≥ 0 of the set of clauses occurring in all future steps starting from Sj . A derivation S0 , S1 , ..., Si , ... is fair if for every inference with premises in the limit, there is some j ≥ 0 such that the inference is redundant with respect to Sj . The set of persistent literals obtained by a fair derivation is called the saturation of the derivation.
Superposition
l[u0 ] ./ r u=t σ(l[t] ./ r) if i) σ(u) 6≤ σ(t), ii) σ(l[u0 ]) 6≤ σ(r), and iii) u0 is not a variable.
Reflection
u0 = 6 u ⊥
Above, u and u0 are unifiable and σ is the most general unifier of u and u0 . Fig. 1. Expansion inference rules of UPC
168
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
Subsumption
S ∪ {L, L0 } if L0 = σ(L). S ∪ {L}
Simplification
S ∪ {C[l0 ], l = r} S ∪ {C[σ(r)], l = r} if i) l0 = σ(l), ii) σ(l) > σ(r), and iii) C[l0 ] > (σ(l) = σ(r)).
Deletion
S ∪ {u = u} S Fig. 2. Contraction inference rules of UPC
2.3
Schematic Paramodulation Calculus
The Schematic Unit Paramodulation Calculus SUPC is an abstraction of UPC. Indeed, any concrete saturation computed by UPC can be viewed as an instance of an abstract saturation computed by SUPC, as shown by Theorem 2 in [10]. Hence, if SUPC halts on one given abstract input, then UPC halts for all the corresponding concrete inputs. More generally, SUPC is an automated tool to check properties of UPC such as termination, stable infiniteness and deduction completeness [10]. This paper focuses on termination. SUPC is almost identical to UPC, except that literals are constrained by conjunctions of atomic constraints of the form const(x) where x is a variable. For sake of brevity, const(x1 , . . . , xn ) denotes the conjunction const(x1 ) ∧ · · · ∧ const(xn ). SUPC consists of the rules in Figs. 3 and 4. With respect to [10], we have slightly adapted the subsumption rule so that the instantiation is not only a renaming but also a substitution instantiating constrained variables by constrained variables. This allows us to have a more compact form of saturations even for simple cases, as shown in Sect. 4. For a given theory T with signature Σ, SUPC is executed with the input Ax(T ) ∪ GT0 where GT0 is defined by GT0 = {⊥, S x = y k const(x, y), x 6= y k const(x, y)} ∪ f ∈Σ {f (x1 , . . . , xn ) = x0 k const(x0 , x1 , . . . , xn )} and schematizes any set of ground flat equalities and disequalities built over Σ, along with the empty clause. 2.4
Maude Language
Maude [4] is a rule-based language well-suited to implement the above inference systems. Maude’s basic programming statements are equations and rules. Its semantics is based on rewriting logic where terms are reduced by applying rewrite rules. Maude has many important features such as reflection, pattern-matching,
Title Suppressed Due to Excessive Length
Superposition
169
l[u0 ] ./ rkϕ u = tkψ σ(l[t] ./ rkϕ ∧ ψ) if i) σ(u) 6≤ σ(t), ii) σ(l[u0 ]) 6≤ σ(r), and iii) u0 is not an unconstrained variable.
Reflection
u0 6= ukψ if σ(ψ) is satisfiable. ⊥
Above, u and u0 are unifiable and σ is the most general unifier of u and u0 . Fig. 3. Constrained expansion inference rules of SUPC
Subsumption
S ∪ {Lkψ, L0 kψ 0 } S ∪ {Lkψ} if either a) L ∈ Ax(T ), ψ is empty and for some substitution σ, L0 = σ(L); or b) L0 = σ(L) and ψ 0 = σ(ψ), where σ is a renaming or a mapping from constrained variables to constrained variables.
Simplification
S ∪ {C[l0 ]kϕ, l = r} S ∪ {C[σ(r)]kϕ, l = r} if i) l = r ∈ Ax(T ), ii) l0 = σ(l), iii) σ(l) > σ(r), and iv) C[l0 ] > (σ(l) = σ(r)).
Tautology
Deletion
S ∪ {u = ukϕ} S S ∪ {Lkϕ} if ϕ is unsatisfiable. S Fig. 4. Contraction inference rules of SUPC
unification and narrowing. Reflection is a very desirable property of a computational system, because a reflective system can access its own meta-level and this way can be much more powerful, flexible and adaptable than a nonreflective one. Maude’s language design and implementation make systematic use of the fact that rewriting logic is reflective. Narrowing [3] is a generalization of term rewriting that allows free variables in terms (as in logic programming) and replaces pattern-matching by unification in order to (non-deterministically) instantiate and reduce a term. The narrowing feature is provided in an extension of Maude named Full Maude. It is clearly of great interest to implement the superposition rules of our calculi.
170
3
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
Implementation
This section describes the main ideas and principles of our implementation of UPC and SUPC in Maude. 3.1
Data Representation
Let us consider how we represent terms ans literals. Maude symbols are reflected in Maude as elements of the sort Qid (quoted identifier). Maude terms are reflected as elements of the sorts Constant, Variable and Term. We exploit the Maude reflection feature by using the sort Term to define the new sort Literal for literals, as follows: fmod LITERAL is pr META-TERM . sort Literal . op _equals_ : Term Term -> Literal [comm] . op _!=_ : Term Term -> Literal [comm] . endfm The attribute [comm] declares that the infix binary symbols equals and != for equality and disequality are commutative. For sets of literals we define the sort SetLit by instantiating the polymorphic sort Set{X} defined in the parameterized module SET{X :: TRIV} of the prelude of Maude, as follows: view Literal from TRIV to LITERAL is sort Elt to Literal . endv fmod SETLIT is pr LITERAL . pr SET{Literal} * (sort Set{Literal} to SetLit) . endfm The first three lines declare that the sort Literal can be viewed as the sort of elements provided by the theory TRIV. This Maude view is named Literal. It is used in the module SETLIT to instantiate Set{X} as Set{Literal}. Finally, the sort SetLit is a renaming of the sort Set{Literal}. Consequently, the sets in this sort can be built by using the constant empty, and by using an associative, commutative, and idempotent union operator, written , . A singleton set is identified with its element (Literal is a subsort of Set{Literal}). A schematic literal is the empty clause, an axiom, or a constrained literal. The sort AConstr of atomic constraints is defined by the operator op const : Term -> AConstr . and the sort Constr of constraints is a renaming of the sort Set{AConstr} of sets of atomic constraints. Then, the sort SLiteral of schematic literals is declared by
Title Suppressed Due to Excessive Length
171
fmod SLITERAL is sort SLiteral . op emptyClause : -> SLiteral . op ax : Literal -> SLiteral . op _ || _ : Literal Constr -> SLiteral . endfm where the infix operator || constructs a constrained literal from a literal and a constraint. Similarly, for sets of schematic literals a sort SetSLit is defined in a module SETSLIT. 3.2
Inference Rules
This section presents the encoding of SUPC, the encoding of UPC being similar. Let us emphasize two main ideas of this encoding: 1) inference rules are translated into rewrite rules, and 2) rule application is controlled thanks to specially designed states. More precisely, the encoding description starts with the translation of some contraction rules into rewrite rules (the simplification rule is omitted). Afterwards, it continues with the expansion rules, whose fair application strategy is encoded by using a notion of state together with rules to specify the transitions between states. Contraction rules The following Maude conditional rewrite rule encodes the first case of Subsumption inference rule in SUPC: crl [subsum1] : (ax(L1), (L2 || Phi2)) => ax(L1) if LiteralMatch(L1, L2) =/= noMatch . The function call LiteralMatch(L1, L2) checks if the second literal L2 is matched by the first one (L1), by calling the Maude function metaMatch. The following two Maude conditional rewrite rules encode the second case of Subsumption inference rule, decomposed into two cases: crl [subsum2] : L1 || Phi1, L2 || Phi2 => L1 || Phi1 if isRename(L1 || Phi1, L2 || Phi2) . crl [subsum3] : L1 || Phi1, L2 || Phi2 => L1 || Phi1 if filter(L1 || Phi1, L2 || Phi2) . The function isRename checks if one constrained literal is the renaming of another one by checking the existence of a substitution mapping the first literal into the second one, and the constraint of the first literal into the constraint of the second one. Moreover, this substitution should replace variables by variables and the correspondence between the replaced variables and the replacing ones should be one to one. The function call filter(L1 || Phi1, L2 || Phi2) checks if the constrained literal L1 || Phi1 is more general than the constrained literal L2 || Phi2 by determining the existence of a substitution mapping the
172
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
first literal into the second one, and the constraint of the first literal into the constraint of the second one. The Simplification inference rule rewrites a literal into a simpler one by using an axiom as a rewrite rule. This is performed by the Maude function metaFrewrite that rewrites the metarepresentation of a term with the rules defined in the metarepresentation of a module. In our implementation, a function addRl adds an axiom to the metarepresentation of a module INITIAL-MODULE where all the functional symbols are defined. op addRl : Term Term -> Module . eq addRl(L, R) = addRules( (rl (L) => (R) [none] .), upModule(’INITIAL-MODULE, false)) . This function uses the Full Maude function addRules that takes a set of rules and a module as parameters. The axiom ax(L equals R) is added by the function call addRl(L,R). The inference rule Tautology is simply encoded by the rewrite rule rl [tautology] : U equals U || Phi => empty . The inference rule Deletion is encoded by the conditional rewrite rule crl [del] : L || Phi => empty if isSatisfiable(Phi) == false . where the function isSatisfiable checks if a given constraint holds, i.e. none of the terms it constraints is compound. Expansion rules The order of rule applications has to be controlled. In particular, contraction rules should be given a higher priority than expansion ones. An expected solution could be to control rule applications with the strategy language described in [8, 11], but unfortunately it appeared not to be compatible with the Full Maude version 2.5b required for narrowing (see details below). To circumvent this technical problem we propose to control rules with states. We consider three distinct states, for the sets of literals derived by SUPC. These states and the sort of states are defined as follows: mod STATE is pr SETSLIT . sort State . op state : SetSLit -> State . op _selectOneLitFromGenSet_ : SetSLit SetSLit -> State . op _redundancy_ : SetSLit SLiteral -> State . endm The input state of the expansion rules of SUPC is expected to be of the form state(S) where S is a set of schematic literals. The Reflection rule checks whether a given set of schematic literals contains a constrained disequality whose two sides are unifiable by a substitution that also satisfies the constraint. In this case the empty clause is added to the set of literals. The Reflection rule is encoded by the following conditional rewrite rule:
Title Suppressed Due to Excessive Length
173
crl [reflection] : state((S, U’ != U || Phi)) => state((S, U’ != U || Phi, emptyClause)) if isSatisf(U’ != U || Phi) . where the function isSatisf performs the above mentioned checking. The Superposition rule l[u0 ] ./ rkϕ u = tkψ σ(l[t] ./ rkϕ ∧ ψ) produces a new literal of the form σ(l[t] ./ rkϕ ∧ ψ) from any set containing two schematic literals (axioms or constrained literals) of the form l[u0 ] ./ rkϕ and u = tkψ, if the side conditions given in Fig. 3 are satisfied with the most general unifier σ of u and u0 . This notion of superposition is close to the notion of narrowing. The idea is to use the second literal u = t as a rewriting rule u → t, to narrow the left-hand side l[u0 ] of the first literal. If the narrowing succeeds it produces a term σ(l[t]) where σ is a most general unifier of u and u0 . It remains to apply σ to the right-hand side r of the first literal and to the conjunction of the two constraints ϕ and ψ. To narrow we use a function metaENarrowShowAll already implemented in Full Maude version 2.5. In this version the narrowing was restricted to nonvariable positions, along its standard definition. But the Superposition rule of SUPC requires the unusual feature: narrowing should also be applied at the positions of the variables schematizing constants. Therefore we have asked Santiago Escobar, the developer of narrowing in Full Maude, to implement this feature. He has kindly added a flag alsoAtVarPosition to the narrowing function for disabling the standard restriction. A second difficulty is that the metaENarrowShowAll function called on the term l(u0 ) and the rule u → t generates all the possible narrowings at all the positions, whereas one application of the Superposition rule produces only one literal. To solve this problem two additional states S selectOneLitFromGenSet S 0 and S redundancy L have been introduced, where S is a given set of schematic literals, S 0 is the set of schematic literals produced by the narrowing function applied to two schematic literals from S, and L is one schematic literal. Then Superposition is encoded by four Maude rewriting rules named sup, select, no-sup and pick. The sup rule is defined by rl [sup] : state((S, L1, L2)) => (S, L1, L2) selectOneLitFromGenSet applySup(L1, L2) . where the function applySup generates from L1 and L2 a set of new schematic literals by calling the narrowing function and checking the ordering conditions of the Superposition rule. The ordering conditions invoke a function implementing the orderings detailed in Section 3.4. When the set of new schematic literals is empty, the rule rl [no-sup] : S selectOneLitFromGenSet empty => state(S) .
174
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
returns the input set in a state ready for another expansion. Otherwise, the rule rl [select] : S selectOneLitFromGenSet (L, S’) => if checkConstr(L) then S redundancy L else S selectOneLitFromGenSet S’ fi . considers one by one the schematic literals in the new set until the set is empty or a schematic literal L with a satisfiable constraint is found. Satisfiability is checked by invoking the function checkConstr. If the constraint of L is satisfiable then a state S redundancy L is constructed. It is an input state for the rule rl [pick] : S redundancy L => if L isRedundant S == false then state((S, L)) else state(S) fi . which checks if a generated schematic literal L is redundant with respect to a given set S of schematic literals. The redundancy is checked by the function isRedundant that uses the Maude function metaSearch. This function tries to reach the set S from the union (S, L) of S and {L} by applying contraction rules. If the new schematic literal is not redundant then it is added to the state, otherwise, the state is unchanged. 3.3
Saturation
A forward search for generated sets of schematic literals is performed by a function searchState defined by op searchState : State Nat -> State . eq searchState(S’, N) = downTerm(getTerm(metaSearch( upModule(’SP, false), upTerm(S’), ’state[’S:SetSLit], nil, ’*, unbounded, N)), error1) . where SP is a module where all the expansion rules are defined. The function call searchState(S,N) tries to reach the Nth state from an initial state S by applying the expansion rules. It uses a breadth-first exploration of the reachable state space, which is a fundamental graph traversal strategy implemented by the Maude metaSearch function with the ’* parameter. When the Maude function downTerm fails in moving down the meta-represented term given as its first argument, it returns its second argument, namely error1, which is declared as a constant of sort State (op error1 : -> [State] .). Then the principle of saturation is implemented by the function saturate defined by op saturate : State -> State . eq saturate(St) = if searchState(St, 1) == error1 then St else if searchState(St, 1) =/= St then saturate(searchState(St, 1)) else St fi fi .
Title Suppressed Due to Excessive Length
175
which implements a fixpoint algorithm in order to get the state of a saturated set of schematic literals. If the initial state is already saturated, then the function returns it unchanged. A saturated set of schematic literals could alternatively be computed from an initial state by the Maude metaSearch function with a ’! parameter (searching for a state that cannot be further rewritten), but the function searchState computing intermediary states is also interesting for debugging purposes. Note that the Maude metaSearch function is already used with the parameter ’! to apply contraction rules. 3.4
Orderings
A fundamental feature of our superposition calculi is the usage of a simplification ordering which is total on ground terms. This section presents all the orderings used in the side conditions of the inference rules and describes their implementation. In our calculi, we assume that compound terms are greater than constants. To satisfy this assumption, it is sufficient to use an LPO ordering with a precedence on function symbols such that non-constant function symbols are greater than constants. Definition 1. Given a precedence >F on function symbols, the lexicographic path ordering (LPO) >lpo [5] is defined as follows:
LPO1
(s1 , . . . , sn ) >lex f (s1 , . . . , sn ) >lpo t1 , . . . , tm lpo (t1 , . . . , tm ) f (s1 , . . . , sn ) >lpo f (t1 , . . . , tm )
LPO2
f >F g f (s1 , . . . , sn ) >lpo t1 , . . . , tm f (s1 , . . . , sn ) >lpo g(t1 , . . . , tm )
LPO3
uk >lpo t f (u1 , . . . , uk , . . . , up ) >lpo t
LPO4
f (u1 , . . . , uk , . . . , up ) >lpo uk
where f and g are two functional symbols, n ≥ 0 and m ≥ 0 are two nonnegative integers, p ≥ 1 is a positive integer, and s1 , . . . , sn , t1 , . . . , tm , u1 , . . . , up , t are terms. We write s >lpo t1 , . . . , tm when s >lpo tk for any positive integer k ∈ [1, m]. The ordering >lex lpo denotes the lexicographic extension of >lpo . The lexicographic extension can be specified as an inference system that can be directly encoded in Maude. The LPO ordering is implemented as a Boolean function gtLPO() such that gtLPO(s, SC, t) = true if and only if s >lpo t. One can remark the additional parameter SC. It collects the constrained variables that are viewed as constants in the precedence ordering: constrained variables are smaller than non-constant function symbols. Let us briefly present the four main rules implementing gtLPO(s, SC, t).
176
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
1. When n ≥ 1 and m ≥ 1, the rule LPO1 is encoded by ceq gtLPO(F[NeSL], SC, F[NeTL]) = true if gtLexLPO(NeSL, SC, NeTL) == true and termGtList(F[NeSL], SC, NeTL) == true . where NeSL and NeTL are non-empty lists of terms. Here the head symbols of s and t are equal. Then the list of subterms NeSL of s = F[NeSL] should be greater than the list of subterms NeTL of t and the term s should be greater than all the elements in the list of subterms of t. 2. When n ≥ 1 and m ≥ 1, the rule LPO2 is encoded by ceq gtLPO(F[NeSL], SC, G[NeTL]) = true if (gtSymb(F, SC, G) == true) and termGtList(F[NeSL], SC, NeTL) == true . Here the heads of s and t are not equal. Then the head of s should be greater than the head of t and s should be greater than all the direct subterms of t. 3. The rule LPO3 is encoded by ceq gtLPO(F[UL1, Uk, UL2], SC, t) = true if gtLPO(Uk, SC, t) == true . whose condition checks whether a direct subterm of s = F[UL1, Uk, UL2] is greater than t. 4. The rule eq gtLPO(F[UL1, Uk, UL2], SC, Uk) = true . encodes LPO4, when a direct subterm of s = F[UL1, Uk, UL2] is equal to t. The ordering >lpo on terms is extended to literals thanks to the multiset extension of >lpo . An equality l = r is represented as a multiset {l, r} while a disequality l 6= r is represented as a multiset {l, l, r, r}. As for the lexicographic extension, the multiset extension can be specified as an inference system that can be directly encoded in Maude.
4
Experimentations
We have done some experiments to compare the (schematic) saturations computed by our tool with corresponding results we can find in the literature. For the theory of lists without extensionality, our tool generates the same saturation as the one given in [9]. More surprisingly, for the theory of lists with extensionality, our implementation reveals that the description given in [10] for the saturation is incomplete. We also consider the case of records of length 3 for which superposition is known to terminate on ground literals [1].
Title Suppressed Due to Excessive Length
4.1
177
Theories of Lists
We experiment with two theories of lists ` a la Shostak, either without or with extensionality. Let ΣList = {cons, car, cdr} be the signature of the theory of lists. The set GList consists of the empty clause ⊥ and the following schemas of ground flat 0 literals over the signature ΣList : x = y k const(x, y)
(1)
x 6= y k const(x, y)
(2)
car(x) = y k const(x, y)
(3)
cdr(x) = y k const(x, y)
(4)
cons(x, y) = z k const(x, y, z)
(5)
where x, y and z are constrained variables. Theory of lists without extensionality The theory of lists without extensionality is axiomatized by the following two axioms: car(cons(X, Y )) = X
(6)
cdr(cons(X, Y )) = Y
(7)
where X and Y are universally quantified variables. Lemma 1. The set GList ∪ {(6), (7)} is saturated by SUPC. 0 This result is given in [9]. The interested reader can find our proof in Appendix A. From an encoding of GList ∪ {(6), (7)} our tool generates no new schematic 0 literal. Notice that on this example the abstraction by schematization is exact, in the following sense: the saturated set computed by SUPC is the schematization of any saturated set computed by UPC. Theory of lists with extensionality This theory is axiomatized by the two axioms (6) and (7), plus the axiom (called the extensionality axiom) cons(car(X), cdr(X)) = X
(8)
where X is a universally quantified variable. Lemma 2. The saturation of GList ∪ {(6), (7), (8)} by SUPC consists of GList , 0 0 (6), (7), (8) and the following constrained literals: cons(x, cdr(y)) = z k const(x, y, z)
(9)
cons(car(x), y) = z k const(x, y, z)
(10)
car(x) = car(y) k const(x, y)
(11)
cdr(x) = cdr(y) k const(x, y)
(12)
cons(car(x), cdr(y)) = z k const(x, y, z)
(13)
178
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
Proof. The set of axioms {(6), (7), (8)} is saturated. The set GList is also satu0 rated. It remains to show the same property for the union of both. Superposition between (6) and (5) and between (7) and (5) respectively yields renamings of (3) and (4), which are immediately removed by the subsumption rule. Superposition between (8) and (3) yields the new constrained literal cons(x, cdr(y)) = y k const(x, y).
(14)
Then, Superposition between (14) and (1) gives the constrained literal (9), which subsumes (14). Similarly, Superposition between (8) and (4) yields the new constrained literal cons(car(x), y) = x k const(x, y)
(15)
and Superposition between (15) and (1) gives the constrained literal (10), which subsumes (15). Superposition between (6) and (10) and between (7) and (9) respectively gives the constrained literals (11) and (12). Superposition between (8) and (11) gives the new constrained literal cons(car(x), cdr(y)) = y k const(x, y)
(16)
and Superposition between (16) and (12) gives the constrained literal (13), which subsumes (16). Superposition between any axiom and (1) yields constrained literals that are immediately removed by the subsumption rule. Any other application of Superposition rule between an axiom and a constrained literal yields a constrained literal that is already in the set GList ∪ {(6), (7), (8)} ∪ 0 {(9), (10), (11), (12), (13)}. Since no other rule can be applied to this set of schematic literals, we conclude that it is saturated. t u The example given in [10] is not complete. In that paper, it is said that ∪ {(6), (7), (8)}, consists of the constrained the saturation by SUPC of GList 0 literals (9) and (10), while it also contains (11), (12) and (13). From an encoding of GList ∪ {(6), (7), (8)} our tool generates these five new constrained literals. 0 On this example we can see that the abstraction by schematization is a overapproximation: the abstract saturation computed by SUPC is larger than any concrete saturation computed by UPC. 4.2
Theory of Records
A record can be considered as a special form of array where the number of elements is fixed. Contrary to the theory of arrays, the theory of records can be specified by unit clauses. The termination of superposition for the theories of records with and without extensionality is shown in [1]. We consider here the theory S3of records of length 3 without extensionality given by the signature ΣRec = i=1 {rstorei , rselecti } and axiomatized by the following set of axioms Ax(Rec): rselecti (rstorei (X, Y )) = Y for all i ∈ {1, 2, 3}
Title Suppressed Due to Excessive Length
179
and rselecti (rstorej (X, Y )) = rselecti (X, Y ) for all i, j ∈ {1, 2, 3}, i 6= j, where X and Y are universally quantified variables. Let GRec be defined as in 0 Section 2.3. Rec Lemma 3. The saturation of GRec 0 ∪Ax(Rec) by SUPC consists of G0 , Ax(Rec) and the constrained literals
rselecti (x) = rselecti (y) k const(x, y) for i = 1, 2, 3. A proof of this lemma can be found in Appendix B. From an encoding of GRec ∪ 0 Ax(Rec) our tool generates the schematic saturation given in Lemma 3 which corresponds to the form of saturations described in [1].
5
Conclusion
This paper reported on a prototyping environment for designing and verifying decision procedures. This environment, based on the theoretical studies in [9, 10], is the first implementation including both superposition and schematic superposition calculi. It has been implemented from scratch on the firm basis provided by Maude. Some automated deduction tools are already implemented in Maude, for instance a Church-Rosser checker [6], a coherence checker [7], etc. Our tool is a new contribution to this collection of tools. This environment will help testing new saturation strategies and experimenting new extensions of the original (schematic) superposition calculus. A short term future work is to consider nonunit clauses. Since schematic superposition is interesting beyond the property of termination, we also want to extend the implementation so that we can check deduction completeness and stably infiniteness [10] which are key properties for the combination of decision procedures. We are also interested in developing new schematic calculi for superposition modulo fragments of arithmetic such as Integer Offsets [13] and Abelian Groups [12]. The reported implementation is a firm basis for all these future developments. Acknowledgments: We are deeply grateful to S. Escobar for his help on the use of narrowing in Maude and to A. Verdejo for his answers about strategy language for Maude.
References [1] Armando, A., Bonacina, M.P., Ranise, S., Schulz, S.: New results on rewrite-based satisfiability procedures. ACM Trans. Comput. Log. 10(1) (2009) [2] Armando, A., Ranise, S., Rusinowitch, M.: A rewriting approach to satisfiability procedures. Inf. Comput. 183(2), 140 – 164 (2003)
180
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
[3] Clavel, M., Dur´ an, F., Eker, S., Escobar, S., Lincoln, P., Mart´ı-Oliet, N., Meseguer, J., L. Talcott, C.: Unification and narrowing in maude 2.4. In: Treinen, R. (ed.) RTA. Lecture Notes in Computer Science, vol. 5595, pp. 380–390. Springer (2009) [4] Clavel, M., Dur´ an, F., Eker, S., Lincoln, P., Mart´ı-Oliet, N., Meseguer, J., F. Quesada, J.: Maude: Specification and programming in rewriting logic. Theoretical Computer Science (2001) [5] Dershowitz, N., Jouannaud, J.P.: Rewrite systems. In: van Leeuwen, J. (ed.) Handbook of Theoretical Computer Science, Formal Models and Sematics, vol. B, pp. 243–320. MIT Press (1990) [6] Dur´ an, F., Meseguer, J.: A church-rosser checker tool for conditional order-sorted ¨ equational maude specifications. In: Olveczky [15], pp. 69–85 [7] Dur´ an, F., Meseguer, J.: A maude coherence checker tool for conditional order¨ sorted rewrite theories. In: Olveczky [15], pp. 86–103 [8] Eker, S., Mart´ı-Oliet, N., Meseguer, J.and Verdejo, A.: Deduction, strategies, and rewriting. Electr. Notes Theor. Comput. Sci. 174(11), 3–25 (2007) [9] Lynch, C., Morawska, B.: Automatic decidability. In: LICS. pp. 7–. IEEE Computer Society (2002) [10] Lynch, C., Ranise, S., Ringeissen, C., Tran, D.K.: Automatic decidability and combinability. Inf. Comput. 209(7), 1026–1047 (2011) [11] Mart´ı-Oliet, N., Meseguer, J., Verdejo, A.: Towards a strategy language for maude. Electron. Notes Theor. Comput. Sci. 117, 417–441 (January 2005), http://dx.doi.org/10.1016/j.entcs.2004.06.020 [12] Nicolini, E., Ringeissen, C., Rusinowitch, M.: Combinable extensions of abelian groups. In: Schmidt, R. (ed.) Proc. of 22nd International Conference on Automated Deduction, (CADE’09). LNAI, vol. 5663, pp. 51–66. Springer, Montreal (Canada) (2009) [13] Nicolini, E., Ringeissen, C., Rusinowitch, M.: Combining satisfiability procedures for unions of theories with a shared counting operator. Fundamenta Informaticae 105(1-2), 163–187 (2010) [14] Nieuwenhuis, R., Rubio, A.: Paramodulation-based theorem proving. In: Robinson, J.A., Voronkov, A. (eds.) Handbook of Automated Reasoning, pp. 371–443. Elsevier and MIT Press (2001) ¨ [15] Olveczky, P.C. (ed.): Rewriting Logic and Its Applications - 8th International Workshop, WRLA 2010, Held as a Satellite Event of ETAPS 2010, Paphos, Cyprus, March 20-21, 2010, Revised Selected Papers, Lecture Notes in Computer Science, vol. 6381. Springer (2010) [16] Schulz, S.: System abstract: E 0.61. In: Gor´e, R., Leitsch, A., Nipkow, T. (eds.) IJCAR. Lecture Notes in Computer Science, vol. 2083, pp. 370–375. Springer (2001) [17] Weidenbach, C., Dimova, D., Fietzke, A., Kumar, R., Suda, M., Wischnewski, P.: Spass version 3.5. In: Schmidt, R. (ed.) Proc. of 22nd International Conference on Automated Deduction, (CADE’09). LNAI, vol. 5663, pp. 140–145. Springer, Montreal (Canada) (2009)
Title Suppressed Due to Excessive Length
A
181
Schematic Saturation of Lists
Lemma 1. Let
GList 0
x = y x 6= y = {⊥} ∪ car(x) = y cdr(x) = y cons(x, y) = z
k const(x, y) k const(x, y) k const(x, y) k const(x, y) k const(x, y, z)
(1) (2) (3) (4) (5)
and let Ax(List) =
car(cons(X, Y )) = X cdr(cons(X, Y )) = Y
(6) (7)
The set GList ∪ Ax(List) is saturated by SUPC. 0 Proof. The set of axioms {(6), (7)} is saturated. The set GList is also saturated. 0 It remains to show the same property for the union of both. Superposition between (6) and (5) yields a renaming of (3), which is immediately removed by the subsumption rule. Similarly, Superposition between (7) and (5) yields a renaming of (4), which is removed by the subsumption rule as well. Superposition between any axiom and (1) yields a schematic literals that are immediately removed by the subsumption rule. Since no other rule can be applied between an axiom and a schematic literal, we conclude that the set GList ∪ {(6), (7)} is saturated. t u 0
B
Schematic Saturation of Records
Lemma 3. Let GRec be composed of the empty clause ⊥ and the constrained 0 literals x = y k const(x, y)
(17)
x 6= y k const(x, y)
(18)
rstore1 (x, y) = z k const(x, y, z)
(19)
rstore2 (x, y) = z k const(x, y, z)
(20)
rstore3 (x, y) = z k const(x, y, z)
(21)
rselect1 (x) = y k const(x, y)
(22)
rselect2 (x) = y k const(x, y)
(23)
rselect3 (x) = y k const(x, y)
(24)
Let Ax(Rec) be composed of the axioms rselect1 (rstore1 (X, Y )) = Y
(25)
rselect2 (rstore2 (X, Y )) = Y
(26)
182
E. Tushkanova, A. Giorgetti, C. Ringeissen and O. Kouchnarenko
rselect3 (rstore3 (X, Y )) = Y
(27)
rselect1 (rstore2 (X, Y )) = rselect1 (X)
(28)
rselect1 (rstore3 (X, Y )) = rselect1 (X)
(29)
rselect2 (rstore1 (X, Y )) = rselect2 (X)
(30)
rselect2 (rstore3 (X, Y )) = rselect2 (X)
(31)
rselect3 (rstore1 (X, Y )) = rselect3 (X)
(32)
rselect3 (rstore2 (X, Y )) = rselect3 (X)
(33)
The saturation of GRec ∪ Ax(Rec) by SUPC consists of GRec 0 0 , Ax(Rec) and the following constrained literals: rselect1 (x) = rselect1 (y) k const(x, y)
(34)
rselect2 (x) = rselect2 (y) k const(x, y)
(35)
rselect3 (x) = rselect3 (y) k const(x, y)
(36)
Proof. The set of axioms Ax(Rec) is saturated. The set of schematic literals GRec is also saturated. It remains to show the same property for the union of 0 both. Superposition between (25) and (19) yields a renaming of (22), which is immediately removed by the subsumption rule. It is similar for the indices 2 and 3, between (26) and (20) and between (27) and (21). Superposition between (28) and (20) yields the constrained literal (34). Afterwards, Superposition between (29) and (21) yields a renaming of (34), which is immediately removed by the subsumption rule. It is similar for the indices 2 and 3, between (30) and (19) and between (32) and (19). Superposition between any axiom and (17) yields schematic literals that are immediatly removed by the subsumption rule. Since no other rule can be applied between an axiom and a schematic literal, we conclude that the set GRec ∪ 0 Ax(Rec) ∪ {(34), (35), (36)} is saturated for SUPC. t u
Facilitating the Transformation of State Machines from Equations into Rewrite Rules Min Zhang and Kazuhiro Ogata School of Information Science Japan Advanced Institute of Science and Technology (JAIST) {zhangmin, ogata}@jaist.ac.jp
Abstract. The multiplicity of formalisms and corresponding verification systems makes the transformation useful for interoperations among them. We have proposed an approach to the transformation of state machines from a syntax-constrained class of equational theories into rewrite theories, which can be verified by Maude’s model checking facilities. However, the efficiency of model checking generated rewrite theories varies, depending on the forms of original equational theories. This paper serves as a practical guide for developing equational theories to facilitate the transformation, aiming at generating efficiently model-checkable rewrite theories. Three case studies are conducted, and experimental results show that the efficiency is significantly improved.
1
Introduction
The multiplicity of formalisms and corresponding verification systems makes the transformations useful for the interoperations among formalisms and collaborations between verification systems. For instance, in the field of algebraic approach based formalizations and verifications, CafeOBJ uses equational theories for theorem proving [1], while Maude uses rewrite theories for model checking [2]. An approach called induction-guided falsification (IGF) has been proposed to achieve the combination of the two verifications [3]. To facilitate the combination, we have proposed an approach to the transformation from a syntax-constrained class of equational theories into rewrite theories [4]. Not only does the transformation save us duplicate effort of developing specifications, but it guarantees the consistency between two specifications of the same system. Equational theories that are transformed by the approach are represented as OTSs (observational transition systems), and generated rewrite theories are represented as CTSs (component-based transition systems). Briefly, OTSs treat each system state as a set of observable values and each transition as a set of equations, while CTSs treat each state as a set of components and each transition as a rewrite rule. The transformation approach can generate efficiently model checkable CTSs, although it is only suitable for a syntax-constrained class of OTSs. We have shown that not all OTSs have corresponding rewrite theories in this approach [4]. To the best of our knowledge, most OTSs conform to (or can be tailored to) the syntax-constraints. However, for a state machine there
184
Min Zhang and Kazuhiro Ogata
may exist two or more OTSs that represent it, and the efficiency of generated CTSs from them varies. The goal of this paper is to serve as a practical guide for developing OTSs that meet two requirements: (1) they can be transformed; and (2) generated CTSs are efficiently model-checkable. We conduct three non-trivial case studies including an authentication protocol NSPK (Needham-Schroeder Public Key), an electronic payment protocol iKP, and a distributed mutual exclusion protocol SKP (Suzuki-Kasami protocol). The case studies show that the CTSs generated from those OTSs that are tailored by following the guidance can be more efficiently model checked than the CTSs generated from those ones before being tailored, i.e. less time is needed to model check the CTSs generated from tailored OTSs, compared to those that are translated from unmodified ones. The rest of this paper is organized as follow. Section 2 introduces the definitions of OTSs and CTSs. Section 3 describes the transformation approach, and Section 4 presents the tips for developing desirable OTSs. Section 5 describes the three case studies, and presents the experimental result. Section 6 talks about some related work and Section 7 concludes the paper.
2
Preliminaries
State machine is a mathematical concept for modeling computer systems. In algebraic approaches, a state machine can be specified as an equational theory, or as a rewrite theory [2, Chpt. 6]. OTS is proposed to describe state machines as equational theories [5], while CTS to describe state machines as rewrite theories. 2.1
Observational Transition Systems (OTSs)
We suppose that there exists a universal state space denoted by Υ and that each data type used in OTSs is provided. A data type is denoted by D with a subscript. Definition 1 (OTSs). An OTS S is a triple hO, I, T i s.t.: – O: A set of observers. Each observer is a function o : Υ Do1 . . . Dom → Do . Two states υ1 , υ2 are called equal (denoted by υ1 =S υ2 ) whenever each observer returns the same value with the same parameters from the two states. – I: A set of initial states s.t. I ⊆ Υ . – T : A set of transitions. Each transition is a function t : Υ Dt1 . . . Dtn → Υ . Each transition t preserves the equivalence between two states in that whenever υ1 =S υ2 , t(υ1 , y1 , . . . , yn ) =S t(υ2 , y1 , . . . , yn ) for any other parameters y1 , . . . , yn . Each t has an effective condition c-t : Υ Dt1 . . . Dtn → Bool, s.t. for any state υ if ¬c-t(υ, y1 , . . . , yn ), t(υ, y1 , . . . , yn ) =S υ. In OTSs, equations are used to formalize initial states and the changes of observed values of each observer caused by transitions. Any state υ0 in I
Title Suppressed Due to Excessive Length
185
must satisfy a set of equations, each of which corresponds to an observer o : Υ Do1 . . . Dom → Do as follows: o(υ0 , xo1 , . . . , xom ) = fo (υ0 , xo1 , . . . , xom )
(1)
where fo (υ0 , xo1 , . . . , xom ) returns a value of Do , and no transitions are allowed to occur in it. There is an equation declared for each pair of observer o and transition t in the following form: o(t(υ, yt1 , . . . , ytn ), xo1 , . . . , xom ) = fo0 (υ, yt1 , . . . , ytn , xo1 , . . . , xom )
(2)
where fo0 (υ, yt1 , . . . , ytn , xo1 , . . . , xom ) returns a value of Do , and transitions cannot occur in it. Equation 2 holds under the condition that c-t(υ, yt1 , . . . , ytn ) is true, specifying how all the values observed by o are changed by the transition from the state represented by υ to the one by t(υ, yt1 , . . . , ytn ). An equation is declared to define c-t(υ, yt1 , . . . , ytn ). 2.2
Component-based Transition Systems (CTSs)
CTS is another notion of describing state machines as rewrite theories where transitions are represented as rewrite rules [6]. A state in CTSs is represented as a configuration which is essentially a set of components. This is inspired by the treatment of states based on an associative and commutative (AC) operation in rewriting logic [7]. There are two kinds of components in configurations, namely observable components and transitional components. Each observable component in a configuration c corresponds to a value in the state represented by c. All the observable components together in a configuration identify a state. Transitional components are used to provide transition information, including the names and parameters of transitions. Transitions among states are formalized as rewrite rules. A rewrite rule is applied only in one direction from left to right. In CTS, a rewrite rule specifies how values are changed by the transformations from states to their successors. If the pattern in the lefthand side of a rule matches a fragment of a configuration c and the rule’s condition is satisfied, the state transition specified by the rule takes place, and the matched fragment of c is transformed into the corresponding instance of the righthand side. Let c0 be a configuration by applying a rule to c. We call c0 a successor configuration of c. Let C be a universal set of configurations, Doc and Dtc be the data types for observable components and transitional components respectively. Definition 2 (CTSs). A CTS S is a four-tuple hC o , C t , C0 , Ri, where: – C o : a set of observable component constructors e.g. o[ , . . . , ]: : Do1 . . . Dom Do → Doc ; – C t : a set of transitional component constructors e.g. t : Dt1 . . . Dtn → Dtc ; – C0 : a set C0 ⊆ C of initial configurations; – R : a set of rewrite rules.
186
Min Zhang and Kazuhiro Ogata
Observable component constructors are declared in mixfix style by convention. Underbars in constructors indicate where corresponding arguments go. A rewrite rule r in R is in the form of L ⇒ R or L ⇒ R if C, where L, R are configurations or segments of configurations, and C is a condition. A rewrite rule L ⇒ R can be considered as a special case of L ⇒ R if C with C being always true. Without loss of generality, r refers to L ⇒ R if C by default in the paper.
3
Transformation from OTSs to CTSs
In this section, we describe the definition of the syntax-constrained OTSs, and the approach to the transformation from them into corresponding CTSs. 3.1
Syntax-constrained OTSs
We only allow two classes of observers in the syntax-constrained OTSs. An observer must be in the form of either o : Υ → Do or oˆ : Υ Dp → Doˆ. Dp is usually a data type of processes, principals, or agent in systems to be formalized. o is called a system-level observer, and oˆ a process-level observer. All process-level observers in a syntax-constrained OTS must have the same arity. The equation declared for o or oˆ w.r.t a transition t : Υ Dt1 . . . Dtn → Υ must be in one of the following three forms: o(t(υ, yt1 , . . . , ytn )) = fo (υ, yt1 , . . . , ytn )
(3)
oˆ(t(υ, yt1 , . . . , ytn ), xp ) = oˆ(υ, xp )
(4)
oˆ(t(υ, yt1 , . . . , yti−1 , x0p , yti+1 , . . . , ytn ), xp ) = foˆ(υ, yt1 , . . . , yti−1 , x0p , yti+1 , . . . , ytn ) oˆ(υ, xp )
if xp = x0p otherwise
(5)
Equation 3 says that the value observed by o is changed into fo (υ, yt1 , . . . , ytn ) by the transition from υ into t(υ, yt1 , . . . , ytn ), and Equation 4 says no values observed by oˆ are changed. When Dp is in t’s arity, we assume Dti (1 ≤ i ≤ n) is Dp . Let x0p be a variable of Dp . Equation 5 says that the value observed by oˆ w.r.t. xp is changed into foˆ(υ, yt1 , . . . , ytn ), and no other values are changed. The above three equations guarantee that there is at most one value among the values observed by each observer that is changed by a transition, and make it decidable to compute which value may be changed. We can transform each OTS that conforms to the above constraints into a corresponding CTS. 3.2
The transformation
The transformation from the constrained class of OTSs into CTSs consists of two phases, i.e., translation and optimization.
Title Suppressed Due to Excessive Length
187
Translation phase. The translation phase consists of three steps, i.e., (1) to translate observers and transitions into observable and transitional component constructors, (2) to generate initial configurations, and (3) to translate equations into rewrite rules. 1. Translation of observers and transitions. Observers and transitions are translated into corresponding observable and transitional component constructors. The correspondences between them are as follows: o : Υ → Do =⇒ o: : Do → Doc
oˆ : Υ Dp → Doˆ =⇒ oˆ:[ ] : Dp Doˆ → Doc
∗ ∗ t : Υ Dt1 . . . Dtn → Υ =⇒ t : Dt1 . . . Dtn → Dtc ∗ Dti denotes a data type of sets of elements which are of Dti . By default, elements of Dti are concatenated associatively and commutatively by an empty operator. ∗ ∗ ∗ Let yti be a variable of Dti , and yti of Dti . (yti yti ) matches an arbitrary nonempty set ψ of elements of Dti , with yti being instantiated by an arbitrary ∗ element e in ψ, and yti by ψ − {e}. This feature will be used in the generation of rewrite rules from equations. The translations of observers and transitions are formalized by functions ho : O → C o and ht : T → C t : if obs ≡ o : Υ → Do o: : Do → Doc ho (obs) , oˆ[ ]: : Dp Doˆ → Doc if obs ≡ oˆ : Υ Dp → Doˆ ∗ ∗ ht (tran) , t : Dt1 . . . Dtn → Dtc
if tran ≡ t : Υ Dt1 . . . Dtn → Υ
We also write ho (o), ho (ˆ o) and ht (t) for convenience if no confusions are caused. 2. Generation of initial configurations. In OTSs, each initial state is identified by a set of all values returned by all observers. Such a value is represented by an observable component in CTSs. All the observable components together with a set of transitional components form an initial configuration. For a systemlevel observer o, its corresponding observable component is (o : fo (υ0 )), where fo (υ0 ) denotes the value observed by o in the initial state υ0 . For a process-level observer oˆ : Υ Dp → Doˆ, there are |Dp | values observed by oˆ. |Dp | denotes the number of all the elements of Dp . We declare an auxiliary function mk-ˆ o : Dp∗ → C s.t. mk-ˆ o(∅) , ∅0 , mk-ˆ o(p p∗ ) , (ˆ o[p] : foˆ(υ0 , p)) (mk-ˆ o(p∗ )). Function mk-ˆ o takes a set ψp of elements of Dp , and returns a set of observable components, each of which corresponds to an value observed by oˆ w.r.t. an element p ∈ ψp , i.e., foˆ(υ0 , p). For a transition t : Υ Dt1 . . . Dtn → Υ , the corresponding transitional ∗ ∗ ∗ component of t is t(yt1 , . . . , ytn ) in initial configurations, where yti is a variable ∗ of Dti , denoting a set of elements of Dti for i = 1, . . . , n. We declare an initial configuration generator init, which takes a set of parameters and returns an initial configuration. Suppose that there are k1 and k2 observers of the first and second kinds, and k3 transitions in a restricted OTS. init : Dp∗ D1∗ . . . Dl∗ → C s.t.: init(p∗ , y1∗ , . . . , yl∗ ) , (o1 : fo1 (υ0 )) . . . (ok1 : fok1 (υ0 )) mk-ˆ o1 (p∗ ) . . . mk-ˆ ok2 (p∗ ) ∗ ∗ ∗ ∗ t1 (yt1 1 , . . . , yt1 n1 ) . . . tk3 (ytk 1 , . . . , ytk nk ) 3
3
3
188
Min Zhang and Kazuhiro Ogata
where, {D1∗ , . . . , Dl∗ } is a set of l(l ≥ 0) data types s.t. each Dj (j = 1, . . . , l) must ∗ in be in the arity of at least one transition in the original OTS and each Dti the arity of each transitional component constructor t is in the set. Each ni (i = 1 . . . , k3 ) is the number of parameters of transitional component constructor ti , and each yt∗i j (j = 1 . . . , ni ) is a parameter in {y1∗ , . . . , yl∗ }. 3. Transformation of equations into rewrite rules. We generate a rewrite rule for each t in T from all the equations that are declared for t. Table 1 Table 1. Representation of the changes of values in a transition t w.r.t. parameters yt1 , . . . , ytn in OTS and CTS transition/observer
t : Υ Dt1 . . . Dtn → Υ o : Υ → Do
oˆ : Υ Dp → Doˆ
OTS CTS state/ successor state/ component in configu- component in successor ration configuration value value ∗ ∗ ∗ ∗ υ t(υ, yt1 , . . . , ytn ) t(yt1 yt1 , . . . , ytn ytn ) t(yt1 yt1 , . . . , ytn ytn ) o(υ) fo (υ, yt1 , . . . , ytn ) (o : o(υ)) (o : fo (υ, yt1 , . . . , ytn )) oˆ(υ, p)
oˆ(υ, p)
oˆ(υ, yti ) foˆ(υ, yt1 , . . . , ytn )
(ˆ o[p] : oˆ(υ, p)) (ˆ o[yti ] : oˆ(υ, yti ))
(ˆ o[p] : oˆ(υ, p)) (ˆ o[yti ] : foˆ(υ, yt1 , . . . , ytn ))
shows how to represent the change of the values caused by a transition t w.r.t. parameters yt1 , . . . , ytn . In OTS, υ denotes a state, and t(υ, yt1 , . . . , ytn ) denotes the successor state of υ if c-t(υ, yt1 , . . . , ytn ). Since each yti is a variable of Dti , yti can be instantiated by an arbitrary element of Dti . The transition from the state represented by υ to the one represented by t(υ, yt1 , . . . , ytn ) specifies all possible state transitions caused by t. The changes of values are parameterized ∗ ∗ ) by υ, yt1 , . . . , ytn . In CTS, we use a transitional component t(yt1 yt1 , . . . , ytn ytn to provide these parameters except υ. To ensure each yti can be instantiated by an arbitrary element of Dti , a transitional component in a concrete configuration ∗ carries the set of all the elements of Dti . Thus, whenever (yti yti ) matches these elements, yti can be instantiated by an arbitrary one in the set with the rest of ∗ all elements being assigned to yti , due to the associativity and commutativity of the empty concatenation operation. In OTS, the value that is observed by o in υ is o(υ), which is changed into fo (υ, yt1 , . . . , ytn ) in t(υ, yt1 , . . . , ytn ) according to Equation 3. This can be represented by the transformation of an observable component (o : o(υ)) into the one (o : fo (υ, yt1 , . . . , ytn )). The values observed by oˆ are not changed according to Equation 4, or only one value oˆ(υ, yti ) is changed into foˆ(υ, yt1 , . . . , ytn ) according to Equation 5. In CTS, we use an observable component (ˆ o[xp ] : oˆ(υ, xp )) to represent the observed value oˆ(υ, xp ). The component will not be changed in the successor configuration, and is not necessarily specified in a rule. Similarly, we construct an observable component (ˆ o[yti ] : oˆ(υ, yti )) to represent the observed value oˆ(υ, yti ). The component is transformed into (ˆ o[yti ] : foˆ(υ, yt1 , . . . , ytn )) in the second case. Without loss of generality, we assume that the equation defined for each oˆ conforms to Equation 5. We introduce new variables zi of
Title Suppressed Due to Excessive Length
189
Doi (i = 1, . . . , k1 ) and zk1 +j of Doˆj (j = 1, . . . , k2 ) to replace oi (υ) and oˆj (υ, ytij ) (1 ≤ ij ≤ n). We obtain the following rule: ∗ ∗ t(yt1 yt1 , . . . , ytn ytn )(o1 : z1 ) . . . (ok1 : zk1 )(ˆ o1 [yti1 ] : zk1 +1 ) . . . (ˆ ok2 [ytik2 ] : zk1 +k2 ) ∗ ∗ ⇒ t(yt1 yt1 , . . . , ytn ytn ) (o1 : fo1 (υ, yt1 , . . . , ytn )) . . . (ok1 : fok1 (υ, yt1 , . . . , ytn ))
(ˆ o1 [yti1 ] : foˆ1 (υ, yt1 , . . . , ytn )) . . . (ˆ ok2 [ytik2 ] : foˆk2 (υ, yt1 , . . . , ytn )) if c-t(υ, yt1 , . . . , ytn ) [zi 7→ oi (υ), zk1 +j 7→ oˆj (υ, ytij )].
(6)
It is worth mentioning that there may be some observed values that are not changed but only used in the change of other values. In this situation, we need to add their corresponding observable components to the both sides of the rule. We omit this case for simplicity since it is straightforward. Optimization. The generated rewrite rule is not optimal because there are some redundant parameters which can be removed. These parameters may lead to the drastic increase the size of each configuration. For instance, the existence ∗ of a parameter (yti yti ) in a transitional component indicates that each instance of a configuration must contain a transitional component that takes a set of all elements of Dti as one of its parameters. This may lead to the drastic increase of the size of configurations when the number of the elements of some Dti is huge. Thus, it is desirable to remove these redundant parameters from generated rules. We propose three optimization functions to achieve this. 1. Condition simplification gc : For each generated rewrite rule r, if r ≡ (L ⇒ R if x = T ) L[x 7→ T ] ⇒ R[x 7→ T ] gc (r) , L[x 7→ T ] ⇒ R[x 7→ T ] if C[x 7→ T ] if r ≡ (L ⇒ R if x = T ∧ C) r otherwise where, x is variable and T is an M -pattern term 1 . ∗ ∗ ∗ )) L ⇒ 2. Variable elimination gv : If r ≡ t((yt1 yt1 ), . . . , (yti yti ), . . . , (ytn ytn ∗ ∗ ∗ t((yt1 yt1 ), . . . , (yti yti ), . . . , (ytn ytn )) R if C, yti is in L, or not in R and C: ∗ ∗ ∗ ∗ gv (r) ,t((yt1 yt1 ), . . . , (yti−1 yti−1 ), (yti+1 yti+1 ), . . . , (ytn ytn ))L ⇒
∗ ∗ ∗ ∗ t((yt1 yt1 ), . . . , (yti−1 yti−1 ), (yti+1 yti+1 ), . . . , (ytn ytn )) R if C.
∗ ∗ ∗ Meanwhile, the arity of t is updated, i.e. t : Dt1 . . . Dti . . . Dtn → Dtc is ∗ ∗ ∗ ∗ . . . Dti−1 Dti+1 . . . Dtn → Dtc . Otherwise, gv (r) , r. changed into t : Dt1 Computationally, yti in the transitional component makes sure that yti occurs at the lefthand side of the rule, making the rule executable. If yti occurs in L, yti in the transitional component is instantiated by the same value as the one assigned to yti in L when the rule is executed. If yti does not occur in R, C, the result after the rule is executed is not determined by the value of yti . Thus, removing yti does not change the executability of the rule. 1
T is an M -pattern if for any well-formed substitution σ s.t. for each variable x in its domain the term σ(x) is in canonical form w.r.t. the equations in M (a functional module that represents an equational theory), then σ(T ) is also in canonical form.
190
Min Zhang and Kazuhiro Ogata
3. Component eliminations go : go (r) , L ⇒ R if C if r satisfies one of the following conditions: (a) r ≡ t L ⇒ t R if C; (b) r ≡ (o : zi )L ⇒ (o : zi )R if C, zi is not in R and C; (c) r ≡ (ˆ o[yti ] : zi )L ⇒ (ˆ o[yti ] : zi )R if C, zi is not in R and C, and yti is in L or not in R and C. The above three conditions make sure that a related component is neither changed nor used by other components in the rule. They are not necessarily included in rules. Removing them makes generated rule simpler, without changing the meaning of the rule. If r does not satisfy neither of the conditions, go (r) = (r). Condition simplification is usually first applied to a rule, making the rule satisfy the conditions of other two functions and hence can be further optimized. We apply the three optimization functions to the generated rewrite rules until no functions can be applied further, and obtain optimized rules. It can drastically reduce the size of each configuration by removing unnecessary arguments from transitional components, and hence makes generated CTSs more efficiently model-checkable.
4 4.1
Facilitating the Transformation Developing syntax-constrained OTSs
It is sometimes not straightforward to develop a syntax-constrained OTS for a given system. One way is to use as many system-level observers as possible to make the OTSs conform to the constraints. It is straightforward since no restrictions are imposed to the equations declared for such observers, but nontrivial because it sometimes needs tricks to use them from case to case. Example 1. Let us consider a system where there is an infinite list of natural numbers. Initially, all are 0. After the ith time tick, the first ith numbers are increased by one. To model the system, we declare in an OTS Stick two observers step : Υ → N and num : Υ N → N . They observe the current step and each natural number in the list. We use transition tick : Υ → Υ to represent the tick action. We omit the definition of initiate states since it is straightforward. We define the following two equations for tick: step(tick(υ)) = step(υ) + 1 num(υ, x) + 1 num(tick(υ), x) = num(υ, x)
(7) if x ≤ step(υ) otherwise
(8)
Obviously, Stick does not conform to the restrictions and cannot be transformed. Actually, there does not exist such a CTS corresponding to Stick if each observable component in the CTS corresponds to one natural number in the list.
Title Suppressed Due to Excessive Length
191
That is because the natural numbers observed by num and changed by tick are unbounded. It needs unbounded number of rewrite rules to specify, which is impossible in a CTS. An alternative way is to use two system-level observers nonzeros and zeros instead of num. The former observes the list of non-zero numbers, and the latter observes the list of all the zeros in the system. Let NatList be the data type of lists of natural numbers. Then, nonzeros : Υ → NatList, and zeros : Υ → NatList. Equations defined for them are as follows: nonzeros(tick(υ)) = (step(υ) + 1) | nonzeros(υ)
(9)
zeros(tick(υ)) = zeros(υ)
(10)
where, “ | : N NatList → NatList” is a constructor of list of natural numbers. The two equations can be explained by Figure 1. Initially, the list of non-zeros
υ0
tick
υ1
tick
nonzeros: nonzeros: 1 zeros: 0|0| . . . zeros: 0|0| . . .
υ2
tick
υ3
tick
υ4 . . .
nonzeros: 2|1 nonzeros: 3|2|1 nonzeros: 4|3|2|1 zeros: 0|0| . . . zeros: 0|0| . . . zeros: 0|0| . . .
Fig. 1. Changes of the non-zero and zero lists by tick
is empty which is represented by nonzeros(υ0 ) = ( denotes the empty list), and the other is an infinite list of zeros represented by zeros(υ0 ) = 0|0| . . .. After each tick, the number of proceeding steps is appended to the head of the nonzero list, and the zero list is unchanged. Since all observers are system-level, the OTS conforms to the syntax constraints and can be transformed. The syntax-constrained OTSs are well suitable for (but no limited to) specifying asynchronous distributed systems [4]. For other systems, it may need some tricks to use system-level observers instead of process-level observers depending concrete cases like Example 1. 4.2
Tailoring OTSs for model-checkable CTSs
∗ As described in Section 3, the existence of a parameter (yti yti ) in a transitional component may lead to the drastic increase of the size of corresponding configurations. Large size of configurations reduces the efficiency of model checking a CTS, because it is not only memory-consuming, but time-consuming to apply rewrite rules to the configurations. A worse case is that when the number of elements of Dti is large or even infinite. It may make the size of CTSs too large to be fed into model checker. Although we can choose only a reasonably smaller subset to represent in components, this may lead to the loss of some cases during model checking, making the verification result less convincing. In order to make use of optimization functions to simply transitional components, we need
192
Min Zhang and Kazuhiro Ogata
to make developed OTSs satisfy the conditions of optimization functions, especially gc . That is because after gc is applied, the simplified rewrite rule can satisfy the conditions of other two functions. Let us consider the following rewrite rule: ∗ ∗ ∗ ∗ ∗ ∗ t((yt1 yt1 ), . . . , (yti yti ), . . . , (ytn ytn )) L ⇒ t((yt1 yt1 ), . . . , (yti yti ), . . . , (ytn ytn )) R if x = T ∧ C
We assume that yti does not occur in L, but in T , which is an M -pattern term. By gc , x in T is substituted by T . Since, yti occurs in T , gv can be applied to the rule, and the transitional component is simplified. Thus, a way of making generated CTSs maximally simplified by optimizations is to specify effective conditions as conjunctions with conjuncts being equations. Example 2. Suppose in a system processes communicate with each other by exchanging messages. Once a message m is put into the network and sent to a process p, p fetches m from the network and puts it into its own message set. Let P, M, M ∗ be the data types of processes, messages, and sets of messages respectively. We declare a system-level observer nw : Υ → M ∗ for the set of messages in the network, a process-level observer ms : Υ P → M ∗ for the set of messages owned by each process, and a transition fetch : Υ P M → Υ to model the action. The effective condition of fetch is represented by c-fetch : Υ P M → Bool s.t.: c-fetch(υ, p, m) = in?(m, nw(υ)) ∧ (dst(m) = p) where, p and m are variables of P and M respectively, dst(m) denotes the destination of m, and in? is a predicate denoting if a message m is in the network. Then, the following two equations specify that m is deleted from the network in υ if c-fetch(υ, p, m) is true. nw(fetch(υ, p, m)) = del(m, nw(υ)) add(m, ms(υ, p)) ms(fetch(υ, p, m), p0 ) = ms(υ, p0 )
if p = p0 otherwise
where, p0 is a variable of P , and del (add) is a function of deleting (adding) a message from (to) a set of messages. The equations are transformed into the following rewrite rule according to the approach: fetch((m m∗ ))(nw: m∗1 )(ms[p]: m∗2 ) ⇒ fetch((m m∗ ))(nw: del(m, m∗1 )) (ms[p]: add(m, m∗2 )) if in?(m, m∗1 ) ∧ dst(m) = p
(11)
where m∗ , m∗1 , m∗2 are variables of M ∗ , and fetch : M ∗ → Dtc . The rule cannot be simplified further by the proposed optimization functions. Each configuration must contain a transitional component w.r.t. fetch, with a set of all messages in it. This may lead to the huge size of the configurations, depending upon the
Title Suppressed Due to Excessive Length
193
number of messages used in the network. In practice, it is usually large, or even infinite, which makes the generated CTS even cannot be fed into model checker, as demonstrated in Section 5. An alternative is to specify the conjunct in?(m, nw(υ)) in the effective condition of fetch as an equation. We modify the arity of c-fetch, and obtain a new one c-fetch0 : Υ P M M ∗ → Υ . c-fetch0 (υ, p, m, m∗ ) = (nw(υ) = (m m∗ )) ∧ (dst(m) = p) The conjunct nw(υ) = (m m∗ ) also denotes that m is in the network. Consequently, the transition fetch needs to be modified to be fetch0 : Υ P M M ∗ → Υ . An intermediate rule generated from the equation is in the form of: fetch0 ((m m∗1 ), (m∗ m∗∗ ))(nw: m∗2 )(ms[p]: m∗3 ) ⇒ fetch0 ((m m∗1 ), (m∗ m∗∗ )) (nw: del(m, m∗2 ))(ms[p]: add(m, m∗3 )) if (m∗2 = (m m∗ )) ∧ dst(m) = p
(12)
where, send0 : M ∗ M ∗∗ → Dtc , and m∗∗ is a variable of M ∗∗ . M ∗∗ is a data type of sets of elements of M ∗ . We can apply gc , gv , and go to the rule 12, and obtain an optimized one: (nw: (m m∗ ))(ms[p]: m∗3 ) ⇒ (nw: m∗ )(ms[p]: add(m, m∗3 )) if dst(m) = p Transitional component w.r.t. fetch0 is removed from configurations, which reduces the size of each configuration. Moreover, we do not need to enumerate all messages to initialize the transitional component, or choose a subset of messages if the number of messages is large or infinite. It makes the generated CTS more efficiently model checkable.
5
Case studies
We conduct three case studies including NSPK, iKP, and SKP, which have been modeled as OTSs and verified in CafeOBJ [3,8,9]. Although the OTSs can be transformed into CTSs, neither of the CTSs can be efficiently model checked due to the large size of configurations. Following the guidance in Section 4, we tailor these old OTSs and transform the tailored OTSs into CTSs, model check the generated CTSs and record the time spent on model checking. Experimental results show that CTSs that are generated from tailored OTSs need less time to be model checked. The experimental environment is Maude 2.6, running on Ubuntu 10.04 on a laptop with a 1.20GHz dual-core processor and 4GB memory. NSPK is a security protocol to achieve the mutual authentication between two principals over a network [10]. Each principal holds a pair of public and private keys. A connection between two principals is established by three message exchanges. Firstly, a principal p encrypts the tuple of a nonce np and p’s identifier with a principal q’s public key, and sends the ciphertext Eq (np , p) to q. q decrypts the ciphertext with its private key and obtains np and p’s identifier. Then, q
194
Min Zhang and Kazuhiro Ogata
generates a nonce nq , encrypts the tuple of nq and np with p’s public key, and sends the ciphertext Ep (nq , np ) to p. p decrypts the ciphertext with its private key and obtains nq , which convinces p that it is communicating with q. Finally, p encrypts nq with q’s public key and sends the ciphertext Eq (nq ) to q. q decrypts the ciphertext with its private key, and obtains nq , which convinces q that it is communicating with p. In [3], NSPK is formalized as an OTS SNSPK . There are three observers rand, nw and nonces in SNSPK respectively for random numbers, messages that are put in the network, and nonces collected by intruders. Without the loss of generality, we only consider in SNSPK the formalization of the action that q sends Ep (nq , np ) to p as an example. Let P and N are data types of principals and nonces. The action is specified by a transition send2 : Υ P P P N → Υ . Its effective condition is denoted by c-send2 : Υ P P P N → Bool s.t.: c-send2 (υ, q, p, p0 , n) = p 6= q ∧ in?(m(p0 , p, q, enc1 (p, n, q)), nw(υ)) It says that transition from υ to send2 (υ, q, p, p0 , n) takes place whenever q 6= p and the message m(p0 , p, q, enc1 (p, n, q)) is in the network. m(p0 , q, p, enc1 (p, n, q)) denotes the message that is sent by p0 from p to q with a ciphertext Eq (n, p) that is specified as enc1 (p, n, q). The effective condition can also be specified by c-send02 : Υ P P P N M ∗ → Bool (M ∗ is the data type of sets of messages) s.t. c-send02 (υ, q, p, p0 , n, ms) = p 6= q ∧ nw(υ) = (m(p0 , p, q, enc1 (p, n, q)) ms) (13) We modify the representations of other transitions’ effective conditions in SNSPK , 0 0 and obtain a new one denoted by SNSPK . We transform SNSPK and SNSPK into 0 . their corresponding CTSs denoted by SNSPK and SNSPK We assume that there are three principals (including two normal ones and an intruder), two random numbers used the protocol. This leads to 18 nonces and 32706 messages. SNSPK is hardly model checked because the transitional component corresponding to send2 takes 32706 messages as one of its arguments, which makes the size of SNSPK to large to be fed into Maude model checker. 0 , transitional components are removed or simplified by optimization In SNSPK based on the equations like 13, making the size of each configuration reasonably 0 in Maude against the secrecy property, which small. We model check SNSPK says that nonces generated by normal principals cannot be gleaned by intruders. Maude returns a counterexample in 181.2 seconds. This result coincides with the claim that NSPK does not satisfy secrecy property [3]. iKP is an electronic payment protocol to achieve authenticated payment among three parties: acquirer, buyers and sellers [11]. The protocol is based on public key cryptography. Each acquirer A has a secret and public key pair. Only the public key is known by both sellers and buyers. Each seller S in 2KP/3KP and each buyer B in 3KP has a secret and public key pair. There are six message exchanges among a buyer B, a seller S and an acquire A to complete a transaction. iKP has been modeled as an OTS SiKP which consists of 11 observers and 38 transitions. We only consider one transition sdvm as an example. The transition
Title Suppressed Due to Excessive Length
195
specifies an action that a seller s sends an invoice message to a buyer b once s receives an initiate message generated by b. An initiate message is represented by im(b0 , b, s, hbn) where b0 is the sender of the message, b and s are the buyer and seller involved in the transaction, and hbn is the keyed hashed BAN used in the transaction between b and s. The effective condition of sdvm is specified by the following equation: c-sdvm(υ, b0 , b, s, pr) = in?(im(b0 , b, s, hbn), nw(υ)) which says that an initiate message must be in the network. pr denotes a price which is a piece of information of the invoice message to be sent to b. We tailor the effective condition as follows: c-sdvm0 (υ, b0 , b, s, pr, ms) = (nw(υ) = (im(b0 , b, s, hbn) ms))
(14)
where, ms is a variable denoting a set of messages. It is similar to tailor the 0 . effective conditions of other 37 transitions. We obtain a new OTS SiKP 0 0 We transform SiKP and SiKP into SiKP and SiKP respectively, and model check them against the payment agreement property. In SiKP , each configuration contains a set of messages that are to be used in message exchanges. We suppose there exists one trustable buyer, one trustable seller, one intruder buyer and one intruder seller. The number of all messages is more than 10 billion, and hence impossible to include in a component. Even if we had all the messages in the component, it would drastically increase the size of each configuration, making SiKP impossible be model checked. 0 we only provide the number of buyers and sellers for each However, in SiKP configuration, because messages in transitional components are removed by optimizations based on the equations like 14. We use two buyers and two sellers 0 in SiKP , and model check it in Maude against the payment agreement property. The property says that whenever an acquire authorizes a payment, both the buyer and seller involved in the payment must have agreed on it. Maude returns a counterexample in 1.196 seconds. The counterexample coincides with the reality that iKP protocols do not satisfy the property [8]. SKP is used to solve the distributed mutual exclusion problem for a computer network where there are a fixed number N (≥ 1) of nodes, and the nodes have no memory in common and can communicate only by exchanging messages. The communication delay is completely unpredictable, namely that although messages eventually arrive at their destinations, they are not guaranteed to be delivered in the same order as they are sent. The mutual exclusion means that at most one node is allowed to stay in its critical section at any moment. The basic idea is to transfer the privilege among nodes for entering critical sections. We omit the details of the algorithm. One can refer to [12] for details. SKP has been modeled as an OTS SSKP , and theorem proved to enjoy the mutual exclusion property in CafeOBJ [9]. In SSKP , a transition receiveReq : Υ P R → Υ is declared to specify the action that a process p receives a request
196
Min Zhang and Kazuhiro Ogata
from other processes for the privilege of entering the critical section. P and R are data types of processes and requests. The effective condition of the transition is c-receiveReq : Υ P R → Bool s.t.: c-receiveReq(υ, p, r) = in?(rm(p, r), nw(υ)) ∧ (fst(r) 6= p) The equation says that a request message denoted by rm(p, r) is in the network and the request r is not sent by p. We tailor the representation of the effective condition according to the second case in Section 4.2. Let c-receiveReq 0 : Υ P R M ∗ → Bool, s.t.: c-receiveReq 0 (υ, p, r, m∗ ) = (nw(υ) = rm(p, r) m∗ ) ∧ (fst(r) 6= p)
(15)
0 We obtain a new OTS denoted by SSKP . 0 0 , and We transform SSKP and SSKP into corresponding CTSs SSKP and SSKP model check them by Maude respectively. Table 2 shows the time that is taken to model check the mutual exclusion property with different number of processes 0 from 2 to 7. It is obvious that SSKP needs less time than SSKP . That is because
0 with the increase of the Table 2. Time (s) spent on model checking SSKP and SSKP number of processes from 2 to 7.
SSKP 0 SSKP
2 0.008 0.004
3 0.128 0.032
4 2.252 0.260
5 41.514 2.916
6 1272.467 38.650
7 – 4095.575
each configuration in SSKP contains a transitional component which consists of a set of n2 requests between n processes. With the increase of the number of processes in the protocol, the size of each configuration increases, leading to the drop in the efficiency of model checking SSKP . The transitional component is 0 because of the equation 15. The efficiency is removed by optimizations in SSKP only affected by the increase of processes. The time increases with the growth of the number of processes mostly due to the increase of the number of states. In sum, the three case studies show that by following the guidance described in Section 4 we can develop desirable syntax-constrained OTSs from which generated CTSs are efficiently model-checkable.
6
Related work
To the best of our knowledge, there are at lest three other related approaches proposed to the translation of state machines from equations into rewrite rules [13,14,15]. The purpose of these approaches including ours is the same, i.e., to generate rewrite theory for model checking. However, none of the three approaches concern with the efficiency issue. For some OTSs of protocols such as
Title Suppressed Due to Excessive Length
197
NSPK, iKP, and SKP, no result can be returned by model checking the generated rewrite theories in reasonable time (e.g. a few of days). Even worse, generated rewrite theory may be to huge too be fed into Maude model checkers. Most algebraic languages endow users with freedom to choose their own style to formalize systems. However, the lack of guidance may cause their formalisms to be less readable, at higher risk of having errors, or of lower efficiency. It is necessary to have some systematic methods or guidance for user to formalize systems uniformly. This can bring multiple benefits, e.g., the improvement of readability, ease or efficiency in verification or transformation, etc. Several related methods and advises in this field have been proposed. The OTS/CafeOBJ modeling method is another example [5]. It guides users for formalizing systems as a subclass of behavioral specifications, which can be systematically theorem proved by proof score approach in CafeOBJ. Although the purposes of these methods are different, they share some commons i.e., making systems more uniformly formalized in certain approaches or by syntactical constraints. This may lead to less flexibility of formalisms, but we believe that this sacrifice is worthwhile with little or no loss of the expressiveness.
7
Conclusion and Future Work
We have presented some guidance for developing desirable equational theories, which are represented as a syntax-constrained class of OTSs. Such OTSs can be transformed into a class of rewrite theories that are represented by CTSs. We conducted three non-trivial case studies to show that the rewrite theories that are generated from tailored OTSs are more efficiently model-checkable than those generated from those OTSs before being tailored. The three cases have been well formally analyzed. We used them as benchmarks to evaluate how much the effectiveness of generated CTSs can be improved in model checking. We will try to formalize new systems as OTSs by following the guidance, transforming them into CTSs, and using the IGF approach to verify the systems with both OTSs and CTSs. One candidate system is OSEK/VDX, a set of standards in the automotive industry for a distributed, real-time architecture for control unit in vehicles [16]. We choose OSEK/VDX as an application for three reasons: (1) it is a safety-critical system, and some important properties must be guaranteed e.g., deadlock freedom; (2) it is a really industrial specification and has not been sufficiently studied from a formal verification point of view; and (3) it is not a typical asynchronous distributed system, and the guide suites to specify the system as a syntax-constrained OTS.
References 1. Diaconescu, R., Futatsugi, K.: CafeOBJ Report. World Scientific (1998) 2. Clavel, M., Dur´ an, F., et al.: All about Maude. LNCS 4350, Springer (2007) 3. Ogata, K., Nakano, M., Kong, W., Futatsugi, K.: Induction-Guided Falsification. In: 8th ICFEM, LNCS 4260, Springer (2006) 114–131
198
Min Zhang and Kazuhiro Ogata
4. Zhang, M., Ogata, K., Nakamura, M.: Specification Translation of State Machines from Equational Theories into Rewrite Theories. In: 12th ICFEM, LNCS 6447, Springer (2010) 678–693 5. Ogata, K., Futatsugi, K.: Some tips on writing proof scores in the OTS/CafeOBJ method. Essays Dedicated to Joseph A. Goguen, LNCS 4060 (2006) 596–615 6. Bruni, R., Meseguer, J.: Generalized Rewrite Theories. ICALP’03, LNCS 2719 (2003) 252–266 7. Meseguer, J.: Conditional Rewriting Logic as a Unified Model of Concurrency. TCS 96 (1992) 73–155 8. Ogata, K., Futatsugi, K.: Formal Analysis of iKP Electronic Payment Protocols. In: ISSS’02, LNCS 2609, Springer (2002) 441–460 9. Ogata, K., Futatsugi, K.: Formal Analysis of Suzuki & Kasami Distributed Mutual Exclusion Algorithm. In: FMOODS’02, LNCS, Springer (2002) 181–195 10. Needham, R., Schroeder, M.: Using encryption for authentication in large networks of computers. CACM 21 (1978) 993–999 11. Bellare, M., Garay, J., et al.: Design, implementation, and deployment of the iKP secure electronic payment system. IEEE Journal of Selected Areas in Communications 18 (2000) 611–627 12. Suzuki, I., Kasami, T.: A distributed mutual exclusion algorithm. ACM Trans. Comput. Syst. 3 (1985) 344–349 13. Futatsugi, K.: Fostering Proof Scores in CafeOBJ. In: 12th ICFEM, LNCS 6447, Springer (2010) 1–20 14. Nakamura, M., Kong, W., et al: A Specification Translation from Behavioral Specifications to Rewrite Specifications. IEICE Transactions 91-D (2008) 1492–1503 15. Kong, W., Ogata, K., et al: A Lightweight Integration of Theorem Proving and Model Checking for System Verification. In: 12th APSEC. (2005) 59–66 16. Lemieux, J.: Programming in the OSEK/VDX Environment. Cmp (2001)
Author Index
A Abraham, Erika Arusoaie, Andrei Asavoae, Irina Mariuca B Bae, Kyungmin Basu, Ananda Bensalem, Saddek Bonsangue, Marcello M. Bozga, Marius Bruni, Roberto C Corradini, Andrea D De Boer, Frank E Eckhardt, Jonas Ellison, Chucky Escobar, Santiago F Fadlisyah, Muhammad G Gadducci, Fabio Giorgetti, Alain Guti´errez, Ra´ ul H Hills, Mark K Klint, Paul Kouchnarenko, Olga L Lepri, Daniela Lluch Lafuente, Alberto Lucanu, Dorel M Meseguer, Jose Muhlbauer, Tobias O Ogata, Kazuhiro Olveczky, Peter P Pita, Isabel
68, 89 11 26 29 1 1 26 1 48 48 26 10 10 7 68 48 164 69 8 8 164 89 48, 108 9, 26 10, 29, 69, 108 10 183 68, 89 128
R Riesco, Adrian Ringeissen, Christophe Rocha, Camilo Rosu, Grigore Rot, Jurriaan S Serbanuta, Traian Sifakis, Joseph T Tushkanova, Elena V Vandin, Andrea Vinju, Jurgen W Wirsing, Martin Z Zhang, Min
128, 144 164 69 9, 11 26 11 1 164 48, 108 8 10 183