Deriving Correct Prototypes from Formal Z Specifications Ali E. Abdallah1

Alexandra Barros∗

Jos´e B. Barros2

Jonathan P. Bowen1

1

South Bank University, Centre for Applied Formal Methods School of Computing, Information Systems & Mathematics (SCISM) Borough Road, London SE1 0AA, UK Email: {abdallae, bowenjp}@sbu.ac.uk URL: http://www.cafm.sbu.ac.uk/ 2

Universidade do Minho, Campus De Gualtar, 4710 Braga, Portugal Email: [email protected]

Abstract This paper describes a systematic way of constructing correct prototypes in a functional language such as Miranda from Z specifications. A formal relationship between Z specifications and functional prototypes is established. This relationship is based on model refinement in the sense of specification refinement in the model-oriented specification style. To reduce the number of proofs required in model refinement, we have defined a set of rules which allow to derive a prototype from a specification. The use of such set of rules implicitly guarantee the correctness of the derivation.

Keywords: Formal specification, Functional programming, Prototyping, Refinement.

1

Introduction

The advantages of starting the development of a software system by writing its specification in a highlevel formal notation are well-known for systems of the highest integrity [10, 22]. It is recommended practice for software engineers work on systems where safety or security is paramount [6]. Using the specification to prove or derive properties of the system is one way of exploring the behaviour of the system without implementing it. Devising executable prototypes (preferably automatically) from formal specifications is another important aspect of validation. The existence of a rapid prototype can be useful in the acceptance of a specification [5] and also for testing purposes [37]. This paper describes work which is focused on the development of prototypes written in a functional language such as Miranda1 [12, 13, 35] for Z [33] specifications. The aim of the work was twofold: firstly, to find a systematic way of building prototypes for Z specifications; secondly, to be able to prove that a prototype correctly implements its original specification. Correctness of prototypes can only be proved if the ‘translation’ process has a formal basis. ∗

Supported by JNICT under contract no. BD/1103/90-IA. Miranda has the characteristics which are associated with modern functional languages: it is strongly typed; it has polymorphic types; it has lazy evaluation; it is a higher-order language. There are other quite similar languages such as Haskell [36]. 1

1

Hence we had to establish a formal relationship between Z specifications and functional prototypes. This relationship is based on model refinement in the sense of specification refinement in the modeloriented specification style as described for example in [33]. It builds on two other formal relationships: one between Z and Miranda data types, and another between Z predicates and Miranda Boolean expressions. To reduce the number of proofs required in model refinement, we have defined a set of rules based upon the established relationships which allow us to build prototypes which are implicitly correct.

1.1

Contribution compared with other approaches

Conversion of formal specifications in Z and VDM [24] to logic and functional languages has been reported in the literature for a number of years so that the notion as such is not original. Being a logic-based language, Prolog [29, 34] appears to be a good candidate to use for the prototyping of specifications written in first order predicate logic like Z (and VDM). In fact, an approach pursued by a number of researchers is the translation of model-based specifications [9] to Prolog [14, 21, 25, 38]. An advantage of this approach is that operations defined through relations can be directly implemented. However there is no algorithmic way of transforming first order predicate logic into Horn clauses and, since there are no types in Prolog, the notion of objects belonging to different types is lost and must be coded explicitly if required. On the other hand, the structure of a model-based specification often takes on the form of a functional program. There will be some abstract types and operations manipulating objects of these types. Hence other researchers prefer the alternative approach of translating the specification to a functional language [15, 17, 23, 27, 31, 32]. More recently, a combination of the functional and logic language approach has been found to be useful for both execution and testing [18, 19]. Although the approach presented can be included in the group that uses a functional language as the prototyping language, there is a major difference between the way we tackle the problem and the manner it has been treated previously. The main concern of papers proposing prototyping techniques has been to find a systematic method for building prototypes. However such methods have been devised in an informal ad hoc manner. Hence there is no possibility of checking if a prototype built using one of those procedures correctly implements the original specification. By the other hand, we have established a formal relationship between Z specifications and functional prototypes. Consequently it is possible to check if a prototype is a correct implementation of a specification. Furthermore, based on such relationship, we have defined a systematic way of deriving correct prototypes from specifications in order to reduce the number of proofs required in model refinement.

1.2

Background

The refinement relationship we have established between Z specifications and prototypes is based on data refinement for Z specifications as described in [33], and builds on a relationship between Z data types and Miranda data types which is founded on abstract data types refinement as explained, for example, in [4]: Concrete objects of type C are related to the abstract objects of type A they represent by an abstraction (or “retrieve”) function retr with type retr :: C → A. If retr c = a, then c is said to represent the value a. The abstract data type T specified by the operations aop1 ...aopn is refined by the concrete type t if, for each aopi : t1 ...tm → tn , there is a

2

concrete function opi such that retr (opi x1 ...xm ) = aopi (retr x1 )...(retr xm ). See also [26] for related concepts of refinement.

1.3

Notation

The following notation will be used in this paper: ˜ D stands for the concrete data representation of D, and ˆ T stands for the representing type of T. Alternatively we use A vT a to denote the fact that a is the representing type of A,

1.4

Overview

In Section 2 we describe the class of Z specifications for which a prototype can be “automatically” derived. In Section 3 we show, with the help of a small example, how a Z specification can be systematically implemented in a functional language. In Section 4 we establish a formal relationship (founded on model refinement) between Z specifications and functional prototypes. In Section 5 we present a set of refinement rules based upon the definitions given in the previous section which allow us to build prototypes that are implicitly correct.

2

From “non-executable” to “executable” Z specifications

Formal specifications are not directly executable in general [20] although some believe they should be if possible [16]. This is a differentiating feature from a program which must be executable. A specification should concentrate on the what rather than the how. It can be possible to present a specification in a natural way that is also executable (e.g., see [8]) but normally some compromise is required. Here we assume that the original Z specification has been produced solely with specification (for understandability and perhaps proof of correctness) rather than executability in mind and thus is unlikely to be executable as it stands. For a discussion on the executability of Z, see [11].

2.1

Refinement of specifications

To model a system in Z, as in any specification language with the level of abstraction adequate to define large systems, we can use non-executable definitions and data types that are not oriented towards computer representation [9]. As a consequence, in general, to build an executable version of the specification we have to go through the following two steps. Firstly, refinement of the abstract specification A into a concrete model C. Secondly, translation of C into the prototyping language. Refinement in this context is model-refinement, i.e. specification refinement in the model-oriented specification style as described for example in [33]. The motivation for refining a specification may be to obtain a design nearer the implementation language or to obtain an efficient design [1]. In the prototyping context, refinement aims at replacing the original specification by a design which may be “directly” translated into some programming language, in our case into a functional language. If the specification is expressed in terms of objects that are not directly implementable, it has to go through data refinement in order to be substituted for a model whose objects have Miranda counterparts. Functions defined in an implicit2 way, and non-deterministic operations have to go 2 An implicit specification establishes what is intended to be computed. On the other hand, an explicit specification shows how a result can be computed.

3

through operation refinement. In the case of an implicit specification, an “algorithm” to calculate the after-state values and outputs explicitly has to be found. A non-deterministic operation has to be substituted for a deterministic function that chooses one of the possible values belonging to the range of the relation that defines the operation. This high-level refinement process needs to be undertaken for the final implementation anyway. For a prototype system, this refinement process can be undertaken within the context of Z. For the final system, much further more detailed refinement (e.g., in the style of development encouraged by the B-Method [2]) will be required.

2.2

Extending the subset of “executable” Z specifications

Z Cartesian product types, sequences, integers, and natural numbers have “direct” counterparts in Miranda. Neither sets, binary relations, mappings, nor bags are directly available. Hence data refinement needs have to be done in specifications which involve these kinds of objects before they could be translated. To enlarge the class of specifications that can be automatically prototyped, we have implemented them so that they have become pre-defined Miranda types. In the prototyping context, it seems a good idea for the programmer to provide a selection of different representations for a given data type. For each particular application, a representation is chosen from the available ones, accordingly to the features required for that specific problem (efficiency, generality, etc.). For example, two different representations of finite sets could be available: ordered lists and lists with no duplicates. The first is more efficient, but the second is more general since it can be used to represent non-ordered sets. There should also be a representation of infinite sets available. A possible implementation of infinite sets is proposed in [4]; a set is represented by a function that tests for membership. Two implementations of sets (using ordered lists and lists with no duplicates), and representations for relations, mappings and bags can be found in [3].

3

From “executable” Z specifications to functional prototypes

In this section we demonstrate how a (partially refined) Z specification can be implemented in a functional language. The example is based on a specification presented in [33]. Here we adopt an informal approach to the prototyping problem. The aim is to show that it is possible to derive in a systematic way a functional prototype from a Z specification, and also that this prototype reflects the structure of the specification. In the next section we describe a formal relationship between Z specifications and functional prototypes, and hence how the obtained prototype could be proved a correct implementation of the specification.

3.1

Prototyping the Birthday Book specification Requirements: We wish to build a system that records people’s birthdays in order to issue a reminder when the day comes round.

A well-written Z specification document presented in the typical model-oriented style of Z [9] normally includes sections containing the following [7]: • Given sets that will be used as types; • Global definitions if required;

4

• The system state; • The initial state, which is the state of the system before any operation executes; • The successful behaviour of the operations on the system state, including the (pre)conditions for which the operations terminate successfully; • The behaviour of the system on error situations; • Robust “total” operations built by putting together partial operations defined in previous sections.3 Given sets Z specification: To model the Birthday Book system, we need to deal with people’s names and with dates. For specification purposes, it is not relevant what form these names and dates take, so we introduce the set of all names and the set of all dates as basic types of the specification. [NAME , DATE ] Miranda implementation: Given sets are implemented by choosing a type of the functional language to represent each of them. > name == string > date ::= Date (num, num, num) Global definitions Z specification: Besides eventual operation outputs, each operation returns a result of type REPORT to acknowledge the success or failure of the operation and give some relevant message. REPORT ::= ok hhStringii | error hhStringii Miranda implementation: The implementation of this type definition requires a minor syntax modification. > report ::= Ok string | Error string Abstract state Z specification: There are two observations that we can make of the state: known is the set of names with birthdays recorded; birthday is a function which, when applied to certain names, gives the birthdays associated with them. BirthdayBook known : P NAME birthday : NAME → 7 DATE known = dom birthday Miranda implementation: State schemas are modelled by “type constructors” which build values of the concrete type. To store Birthday Book states we need a set of names, and a mapping from names to dates, as in the state schema. 3

A total operation is one that is well-defined whatever its inputs and before-state; i.e., it has a precondition of “true.”

5

> cstate ::= BirthdayBook (set name,mapping name date) Different commands change different parts of the state. We will need to deal separately with the several components of the state. Hence we define selector functions which given a state return one of its components. > known :: cstate -> set name > known (BirthdayBook (k,b)) = k > birthday :: cstate -> mapping name date > birthday (BirthdayBook (k,b)) = b The state invariant is a predicate which is satisfied in every state of the system and is maintained by every operation on it. Only states that satisfy the properties specified by the invariant are valid states. The invariant is modelled by a Boolean function which tests if a given state satisfies these properties. > validstate :: cstate -> bool > validstate s = (known s) $eqset (dom (birthday s)) Initial state Z specification: When the system is first started, no names are known to the system. InitBook known 0 : P NAME ; birthday 0 : NAME → 7 DATE birthday 0 = ∅ known 0 = dom birthday 0 Miranda implementation: The initial state is modelled by a constant of the concrete state type, set as described in the schema. > cinitbook :: cstate > cinitbook = BirthdayBook (known’, birthday’) > where birthday’ = emptyset > known’ = dom birthday’ Partial operations and preconditions Z specification: One of the operations on the system is to add a new birthday. The birthday function is extended to map the new name to the given date. AddBirthday0 BirthdayBook ; name? : NAME ; date? : DATE known 0 : P NAME ; birthday 0 : NAME → 7 DATE ; result! : REPORT preAddBirthday0 known 0 = dom birthday 0 birthday 0 = birthday ∪ {name? 7→ date?} result! = ok “”

6

The precondition for the success of this operation is that the name to be added must not already be known to the system. preAddBirthday0 BirthdayBook ; name? : NAME ; date? : DATE name? 6∈ known

Miranda implementation: An operation is modelled by a function that takes the before-state and inputs, and returns a new state and eventual operation outputs. AddBirthday0 is guaranteed to modify the state and return outputs as described as long as the precondition holds. > addbirthday_0 :: cstate -> name -> date -> (cstate, report) > addbirthday_0 birthdaybook name? date? > = (birthdaybook’, result!), > if (preaddbirthday_0 birthdaybook name? date?) > where birthdaybook’ = BirthdayBook (known’, birthday’) > known’ = dom birthday’ > birthday’ = (birthday s) $union (mkset [(name?,date?)]) > result! = Ok ‘‘’’

A precondition is modelled by a function that tests for the properties described in the precondition schema. > preaddbirthday_0 :: cstate -> name -> date -> bool > preaddbirthday_0 birthdaybook name? date? > = (name? $notmember (known birthdaybook)) & (validstate birthdaybook)

Error cases When the input name? is already a member of known, the state is not modified and an error message is sent to the user. The partial operation AddBirthdayAlreadyKnown and its associated precondition preAddBirthdayAlreadyKnown are implemented as the functions addbirthday_err1 and preaddbirthday_err1 respectively. Total Operations Z specification: If we use disjunction to put together the description of the successful behaviour with the description of the behaviour on the error situation, then we obtain an operation that is well-defined in every situation. AddBirthday = b AddBirthday0 ∨ AddBirthdayAlreadyKnown Miranda implementation: We use a library function if pre op > if_pre_op :: [(a, bool)] -> a > if_pre_op ((x,b):xs) = x, > = if_pre_op xs,

if b otherwise

to combine the definitions of the two partial functions, just like disjunction combines the schemas of the two “partial” operations, 7

> addbirthday :: cstate -> name -> date -> (cstate, report) > addbirthday birthdaybook name? date? > = if_pre_op [ (addbirthday_0 birthdaybook name? date?, > preaddbirthday_0 birthdaybook name? date?), > (addbirthday_err1 birthdaybook name? date?, > preaddbirthday_err1 birthdaybook name? date?) ] The functional program we have developed is an animated version of the Birthday Book specification. It can be used by both the client and the designer to validate the original description of the system. But, how do we know that this prototype represents our initial specification? What is the relationship between the specification and the prototype? These questions are discussed in the next section.

4

Correctness of the prototype

A major feature of Z specifications is the schema. A schema consists of two parts: a declaration of variables, and a predicate constraining their values. In an “executable” specification, the predicate part of a schema describes the properties which the objects manipulated must satisfy and/or the values to be assigned to the state/operation-outputs. A predicate which describes properties of objects is translated into a Boolean function which tests for those properties. A Z expression which designates some typed value v is translated into an expression which designates the representing value of v in Miranda. We have said that Z sequences may be represented by Miranda lists, Z finite sets may be represented by sets as we have implemented them in Miranda, etc. But what does it mean for a Z type to be represented by a Miranda type? And what is the relationship between a Z predicate and a Miranda Boolean expression? It seemed desirable that, in the first place, the way how predicates and typed expressions in Z are related to typed expressions in Miranda should be investigated. Thus, before describing the relationship between a prototype and a specification, we will see how both Z typed expressions and Z predicates are formally related with Miranda typed expressions.

4.1 4.1.1

Refinement of Z into Miranda Typed expressions:

The formalism behind the representation of a Z data type A by a Miranda type C is data refinement in the sense used for example in [4] to formalize the implementation of abstract types. In order to explain which concrete objects correspond to which abstract objects we define an abstraction (or retrieve) function retr with type retr :: C → A which maps the concrete type into the abstract one. If retr c = a, then c is said to represent the value a. An example of an abstraction function is one that describes the correspondence between the Miranda implementation of sets using ordered lists (set ˜ A) and the Z finite set type (F A): ˜ → FA retrSet1 [[ ]] : set A retrSet1 [[ [] ]] = ∅ retrSet1 [[ (x:xs) ]] = {(retrieveA x )} ∪ (retrSet1 [[ xs ]]), if ordered (x : xs) where ordered [] = true ordered [x ] = true ordered (x : y : xs) = (x < y) ∧ ordered (y : xs)

8

where retrieveA relates elements of A with elements of ˜ A. Each data type available in Z has a set of pre-defined operations associated with it. As well as formalizing the correspondence between values of A and C, the abstraction function retr :: C → A is also used to specify corresponding operations. For example, consider the operation ∪ (set union) defined in the Z tool-kit. The ($union) :: set a -> set a -> set a function, which implements ∪, is specified by the equation ∀ r, s: set a • retrSet1 (r $union s) = (retrSet1 r) ∪ (retrSet1 s). Only implementations that satisfy the above equation are valid. Besides the pre-defined operations which belong to the Z tool-kit, the designer can define his own functions. Again, an implementation g :: i_1 -> ... -> i_n -> o of a function of type G : AI1 → ... → AIn → AO must satisfy the equation retrieve (g a_1 ... a_n) = G (retrieve a_1) ... (retrieve a_n) to be correct. Thus, to relate a Z type T with a Miranda type t we have to: firstly, define a retrieve function which maps objects of t to the objects of T they represent; secondly, show that the functions which implement the operations on T satisfy their specifications (or alternatively derive these functions from their specifications – for example the derivation of $union from the above specification can be found in [3]). retrTuple, retrRel , retrMap, retrSeq, retrBag, retrFreeT , retr Z, and retr N – the abstraction functions for tuples, binary relations, functions, sequences, bags, free types, integers and naturals, respectively – can be found in [3]. An object a is translated to c, if a vdata c, where a vdata c denotes the fact that c is a data refinement of a. Besides the vdata relation symbol, in the following sections we will also use the symbols vT and vf . We will write A vT a to denote the fact that a is the representing type of A, and G vf g to denote the fact that the abstract function G is implemented by the function g. 4.1.2

Predicates:

Any predicates that describe properties of manipulated objects are translated into Boolean expressions that test for those properties. Data refinement is the concept behind the formalization of the prototyping of Z data types. But, since predicates are not typed in the context of Z, this concept is not adequate to justify in a theoretic way the refinement of Z predicates. This leads us into a new theoretic problem. What is the relationship between non-typed predicates and expressions with type bool? We say that a predicate P is refined by a Boolean expression p if whenever P holds for given objects x1 ...xn , p instantiated with the concrete representations of x1 ...xn , reduces to True. Formally, ∀ x1 : Tˆ1 ; ...; xn : Tˆn ; X1 : T1 ; ...; Xn : Tn • P vpred (p x1 ... xn ) ⇔ P [ (retrieve x1 )/X1 , ..., (retrieve xn )/Xn ] ⇒ p x1 ...xn = True. For example, the Z predicate name? 6∈ known is refined by the Miranda Boolean expression n $notmember k if ∀ name? : NAME ; known : P NAME ; n:name; k: set name • name? 6∈ known [ (retrieve n)/name?, (retrieve k)/known ] ⇒ n $notmember k = True. 9

In the next section we present a refinement rule (Rule p.2) which allows to discharge this proof obligation. 4.1.3

Refinement rules:

Given the definitions of vdata and vpred , we can derive laws which relate both Z typed expressions and Z predicates with Miranda typed expressions. For example: Rule set.1: empty set ∅ vdata emptyset Rule set.4: set intersection ∀ A, B : P X ; ˜ A,˜ B:set ˆ X • A ∩ B vdata ˜ A $inter ˜ B Rule p.2: not membership ∀a : X; A : PX; ˜ a:ˆ X; ˜ A:set ˆ X • a 6∈ A vpred ˜ a $notmember ˜ A Rule p.6: conjunction p & ˜ q ∀ p, q : Predicate; ˜ p,˜ q ∈ Bool • p ∧ q vpred ˜ A complete list of laws which are based on the definitions of vdata and vpred can be found in [3]. These rules can be proved correct once for all. Whenever they apply, refinement proof obligations can be immediately discharged, as seen in the previous section.

4.2

Formal relationship between a specification and a prototype

A specification defines: some types which model the data in the specification; the form of abstract states; the initial abstract state; operations that manipulate abstract states. A prototype defines: some types which model the data in the prototype; the type of concrete states together with a Boolean function which tests for the validity of concrete states; an initial concrete state; functions which manipulate the concrete state. Let S be a Z specification, S = k[ hT1 , ..., Tm i, Astate, IAstate, h (Op1 , preOp1 ), ..., (Opk , preOpk ) i ]k and P be the corresponding Miranda prototype, P = k[ where

h t_1,...,t_m i, (cstate, validstate), icstate, h (op_1, preop_1),..., (op_k, preop_k) i ]k

T1 ... Tm Astate IAstate Opi ... Opk preOpi ... preOpk

are user-defined Z types is the abstract state is the initial abstract state are operations on the abstract state are the preconditions of the above operations

t_1...t_m cstate validstate icstate op_i...op_k preop_i...preop_k

are user-defined Miranda types is the type of concrete states is a function that tests for the validity of concrete states is the concrete initial state are operations on the concrete state are the preconditions of the above operations. 10

In Z, the process of substituting an abstract state space and corresponding operations for a state space and operations which are described in terms of more computer-oriented data types is called data refinement [33]. Concrete states are related to abstract states by a retrieve schema, and there are three conditions which must be satisfied for a data refinement to be correct: • each possible initial state of the concrete type must represent a possible initial state of the abstract type; • a concrete operation must allow termination whenever the abstract operation does so; • the state after a concrete operation must represent one of those abstract states in which the abstract operation could terminate. To distinguish this type of refinement from the data type refinement discussed in Section 4.1.1 we will refer to it as model refinement. The prototyping of a Z specification by a functional program is also seen as a step of model refinement in the sense that the specification is seen as an abstract model and the prototype as a concrete model. P is a refinement of S if there is a retrieve function retrAstate which relates each concrete state c with an abstract state A in such a way that • if the state invariant holds for A then c is a valid concrete state; • the abstract and concrete initial states are related by retrAstate; • whenever an abstract operation allows termination its corresponding implementation is guaranteed to terminate, and the state after the concrete operation represents one of those abstract states in which the abstract operation could allow termination. Formally, Definition 1: Refinement of specifications into prototypes P is a refinement of S , i.e., S v P if ∃ retrAstate : cstate → astate, retrT1 : t_1 → T1 , ..., retrTn : t_1 → Tn • Astate vstate (cstate, validstate) IAstate vistate icstate ∧ ∀ i : 1..k • preOpi vpre preop_i ∧ ∀ i : 1..k • Opi vop op_i



where astate is the schema type of bindings of Astate, and the relations vstate , vistate , vpre , vop are as defined in the following subsections.

4.3

Abstract state

Let the abstract state be described by Astate C1 : T1 ; . . . ; Cn : Tn Ainvariant

11

and the state space of the concrete data type be described by > cstate ::= State (t_1, ..., t_n) > validstate :: cstate -> bool > validstate (State (a_1,...,a_n)) = cinvariant a_1 ... a_n. Abstract states are bindings of type  C1 : T1 , ..., Cn : Tn  which satisfy the state invariant Ainvariant. “Valid” concrete states are objects of type cstate which make validstate return True. The state space described by (cstate, validstate) refines the state space described by Astate if the implementation of any abstract state is a valid concrete state. Formally, Definition 2: abstract state refinement Astate vstate (cstate, validstate) ⇔ ∀ s:cstate; V1 : T1 ; ...; Vn : Tn • retrAstate s = h C1 ≡> V1 , ..., Cn ≡> Vn i ∧ Ainvariant [ V1 /C1 , ..., Vn /Cn ] ⇒ validstate s = True 2

4.4

Initial state

Let Ainitstate describe the abstract initial state, Ainitstate Astate 0 initP and cinitstate :: cstate be a constant that represents the concrete initial state. cinitstate refines Ainitstate if cinitstate is the implementation of an abstract state which satisfies the predicate part of Ainitstate. Formally, Definition 3: initial state refinement Ainitstate vistate cinitstate ⇔ ∀ a1 : T1 ; ..., an : Tn • retrAstate cinitstate = h C10 ≡> a1 , ..., Cn0 ≡> an i ⇒ initP ∧ Astate 0 [ a1 /C10 , ..., an /Cn0 ] 2

4.5

Partial operations and preconditions

Let Aop be an operation on the abstract state space,

12

Aop ∆Astate x ? : Tx y! : Ty preAop P

preAop C1 : T1 ; . . . ; Cn : Tn x ? : Tx Pre ∧ Ainvariant and cop be the corresponding operation which implements it on the concrete data space, > cop :: cstate -> tx -> (cstate, ty) > cop s x? = (s’, y!), if (pre_cop s x?) > pre_cop :: cstate -> tx -> bool > pre_cop (State (a_1,...,a_n)) a_n+1 > = (pre a_1...a_n+1) & (validstate (State (a_1,...,a_n))). (cop, pre_cop) refines (Aop, preAop) if cop terminates whenever Aop specifies termination, and the state after the concrete operation represents one of those abstract states in which the abstract operation could allow termination. Saying that cop terminates whenever Aop terminates means that, if an abstract state and a concrete state are related by the retrieve function retrAstate, and the abstract state satisfies the precondition of the abstract operation, then the concrete state must satisfy the precondition of the concrete operation. Formally, Definition 4: precondition refinement preAop vpre pre_cop ⇔ ∀ a1 : T1 ; ...; an : Tn ; an+1 : Tx ; s:cstate; x?:tx • (retrAstate s = h C1 ≡> a1 , ..., Cn ≡> an i) ∧ (retrieve x? = an+1 ) Pre ∧ Ainvariant [a1 /C1 , ..., an /Cn , an+1 /x ?] ⇒ pre_cop s x? = True



2 Saying that the state after the concrete operation represents one of those abstract states in which the abstract operation could terminate means that, if an abstract state and a concrete state are related by retrAstate, and both the abstract and concrete operations are guaranteed to terminate, then every possible state after the concrete operation must be related by retrAstate to a possible state after the abstract operation. Formally, 13

Definition 5: operation refinement Aop vop cop ⇔ 0 ∀ a1 , a10 : T1 ; ...; an , an0 : Tn ; an+1 : Tx ; an+1 : Ty; s,s’:cstate; x?:tx; y!:ty •

Pre [a1 /C1 , ..., an /Cn , an+1 /x ?] ∧ (retrAstate s = h C1 ≡> a1 , ..., Cn ≡> an i) ∧ (retrieve x? = an+1 ) ∧ cop s x? = (s’, y!) ∧ 0 (retrAstate s’ = h C1 ≡> a10 , ..., Cn ≡> an0 i) ∧ (retrieve y! = an+1 )

⇒ 0 (Pre ∧ P ) [ a10 /C10 , ..., an0 /Cn0 , an+1 /y!, a1 /C1 , ..., an /Cn , an+1 /x ? ]

2

5

“Transformational” refinement

This section presents a “transformational” approach to the derivation of prototypes from specifications. The main motivation for the work related with this section has been the need to reduce the number of formal proofs required in model refinement. The “standard” way of refining a model A would lead us to: • Define an implementation-model C; • Relate C to A via a retrieve function; • Use such function to show that C is a valid implementation of A. An alternative strategy consists of transforming A into C using a set of rules which implicitly guarantee the correctness of such a derivation. These rules are based upon the definitions given in Section 4.

5.1

Notation

Let S = k[ A1 ... Aj ... An ]k be a Z specification, and P = k[ c 1 ... c j ... c n ]k be the corresponding functional prototype, where each Ai (with i : 1..n) is a Z paragraph, and each c i (with i : 1..n) is a definition in Miranda. We write k[ Aj ]k vproto k[ c j ]k to denote the fact that Aj is replaced by c j when the specification S is transformed into the prototype P.

5.2

“Transformation” rules

This subsection gives some example rules that may be applied for verification or derivation purposes. For example, the abstract state in the Z specification is refined into a more concrete state in the prototype containing matching state components with suitable invariants renamed appropriately in the prototype depending on the retrieve function:

14

Rule s.1: abstract state k[ Astate C1 : T1 ; . . . ; Cn : Tn invariant ]k vproto k[

> cstate ::= State (t_1, ..., t_n) > validstate :: cstate -> bool > validstate (State (x_1,...,x_n)) = inv x_1 ... x_n

]k

(∀ i : 1..n • Ti vT t_i) ∧ (∀ a_1...a_n • invariant [(retr a_1)/C1 , ..., (retr a_n)/Cn ] vpred inv a_1 ... a_n).

where

2 The initial state in the Z specification, based on the more general abstract state (after initialization), is refined into a more concrete prototype state based on the more specific values assigned to state components at initialization of the system: Rule s.2: abstract initial state k[ AIstate Astate 0 C10 = V1 ; . . . ; Cn0 = Vn ]k vproto k[

> cistate :: cstate > cistate = State (v_1, ..., v_n) ]k ∀ j : 1..n • Vj vdata v_j.

where 2

Preconditions of abstract operations are refined with suitable renaming of the before-state components and any inputs to the operation: Rule s.3: preconditions k[

15

preAop Astate; ain1 ? : I1 ; ...; ainm ? : Im P ]k vproto k[

> pre_cop :: cstate -> i_1 ... -> i_m -> bool > pre_cop s in_1 ... in_m > = (p s in_1 ... in_m) & (validstate s) ]k (∀ j : 1..m • Ij vT i_j) ∧ (∀ a_1...a_n+m • P [(retr a_1)/C1 , ..., (retr a_n+m)/ainm ?] vpred p a_1 ... a_n+m).

where

2 Partial operations including a precondition that is not trivially true, and with after-state components and outputs each explicitly set to a function of the before-state components and inputs, can be refined to a suitable concrete operation when the precondition is true, or to be “undefined” otherwise: Rule s.4: partial operations k[ Aopexec Astate; ain1 ? : I1 ; ...; ainm ? : Im C10 : T1 ; ...; Cn0 : Tn ; aout1 ! : O1 ; ...; aoutk ! : Ok preAop C10 = F1 (C1 , ..., Cn , ain1 ?, ..., ainm ?); ... ; Cn0 = Fn (C1 , ..., Cn , ain1 ?, ..., ainm ?) aout1 ! = Fn+1 (C1 , ..., Cn , ain1 ?, ..., ainm ?); ... ; aoutk ! = Fn+k (C1 , ..., Cn , ain1 ?, ..., ainm ?) ]k vproto k[

> cop :: cstate -> i_1 -> ... -> i_m -> s’plusout > cop s in_1 ... in_m > = Res s’ out_1 ... out_k, if (pre_cop s in_1 ... in_m) > = Undefined, otherwise > where s’ = State (v_1, ..., v_n) > v_1 = f_1 (c_1 s)...(c_n s) in_1...in_m > ... > v_n = f_n (c_1 s)...(c_n s) in_1...in_m > out_1 = f_n+1 (c_1 s)...(c_n s) in_1...in_m > ... > out_k = f_n+k (c_1 s)...(c_n s) in_1...in_m ]k 16

(∀ j : 1..m • Ij vT i_j) ∧ (∀ i : 1..k • aouti vdata out_i) ∧ (∀ i : 1..n • Fi vf f_i).

where 2

Total operations, defined in terms of a disjunction of partial operations, can be refined to execute one of the possible partial operations: Rule s.5: total operations k[ Aop = b Op1 ∨ ... ∨ Opq ]k vproto k[

where 2

> cop :: cstate -> i_1 -> ... -> i_m -> s’plusout > cop s in_1 ... in_m = if_pre_op [ op_0 s in_1 ... in_m, > ..., > op_q s in_1 ... in_m ]

]k

∀ j : 1..n • k[ Opj ]k v k[ op_j ]k.

Global constants can be defined in a very similar way in the concrete prototype as in the original Z specification: Rule gc.1: global constant k[ Ident == Exp ]k vproto k[ ident == exp ]k where 2

Exp vdata exp.

Facilities for declaring free types are also rather similar in the functional representation compared to the matching Z specification: Rule ft.1: free types k[ T ::= c1 hhT1 ii | ... | cn hhTn ii ]k vproto k[ t ::= C_1 t_1 | ... | C_n t_n ]k where 2

∀ i : 1..n • Ti vT t_i.

These rules give a flavour of those needed for transformational refinement to a functional programming prototype. Many more such rules are needed for a practical transformation system; a much larger set of such rules may be found in [3].

6

Conclusion

The main contribution of this work to the prototyping problem consists of a framework for the derivation of correct prototypes from Z specifications. Our approach has had as a first concern the establishment of a formal relationship between specifications and prototypes. The rules to derive prototypes from specifications were then defined with basis on such relationship. These rules have been proved 17

correct with respect to the relationship once for all. Any refinement based on them is then implicitly guaranteed to be correct. The formal relationship between specifications and prototypes builds on a formal relationship between Z data types and Miranda data types. Abstract data types refinement revealed to be appropriate to formalize the translation of Z typed expressions into Miranda typed expressions, but it was not adequate to justify in a formal way the translation of predicates into Boolean expressions because the first are not typed. Hence a new refinement concept had to be introduced to deal with predicates. Besides correctness, another aspect of prototyping of potential importance is the maintenance of the structure of the specification. To aid this, the structure of the specification should be reflected in the structure of the prototype. Otherwise it would be difficult to update the prototype each time a new specification error is detected by the user. During the validation process, the specification might have to be changed several times. If the modifications made on the prototype reflect the modifications made in the specification, then it is easier to perform them. By maintaining the structure of the specification, the validation cycle is easier. Finally, this paper has only been able to give a flavour of the approach suggested using a very simple example by way of illustration. For a much fuller discussion of the approach, with more complex examples and a complete set of rules, see [3].

References [1] A. E. Abdallah. Filter promotion transformation strategies for deriving efficient programs from Z specification. In Shaoying Liu et al. [30], pages 157–167. [2] J.-R. Abrial. The B-Book: Assigning Programs to Meanings. Cambridge University Press, 1996. [3] A. Barros. Formal Methods for Rapid Software Prototyping. PhD thesis, Department of Computer Science, The University of Reading, UK, December 1997. [4] R. Bird. Introduction to Functional Programming. Prentice Hall International Series in Computer Science, 2nd edition, 1998. [5] D. Bjørner, C. George, and S. Prehn. Scheduling and rescheduling of trains. In Hinchey and Bowen [22], chapter 8, pages 157–184. [6] J. P. Bowen. The ethics of safety-critical systems. Communications of the ACM, 43(4):91–97, April 2000. [7] J. P. Bowen. Z: A formal specification notation. In M. Frappier and H. Habrias, editors, Software Specification Methods: An Overview Using a Case Study. Springer-Verlag, 2000. To appear. [8] J. P. Bowen, He Jifeng, and Xu Qiwen. An animatable operational semantics of the Verilog Hardware Description Language. In Shaoying Liu et al. [30], pages 199–207. [9] J. P. Bowen and M. G. Hinchey. Formal models and the specification process. In A. B. Tucker, Jr., editor, The Computer Science and Engineering Handbook, chapter 107, pages 2302–2322. CRC Press, 1997. Section X, Software Engineering. [10] J. P. Bowen and M. G. Hinchey. High-Integrity System Specification and Design. FACIT series. Springer-Verlag, 1999.

18

[11] P. T. Breuer and J. P. Bowen. Towards correct executable semantics for Z. In J. P. Bowen and J. A. Hall, editors, Z User Workshop, Cambridge 1994, Workshops in Computing, pages 185–209. Springer-Verlag, 1994. [12] P. Burton. An Introduction to Functional Programming and Miranda. International Thomson Publishing, 2000. [13] C. Clack, C. Myers, and E. Poon. Programming with MirandaTM . Prentice Hall International, 1995. [14] A. J. J. Dick, P. J. Krause, and J. Cozens. Computer aided transformation of Z into Prolog. In Nicholls [28], pages 71–85. [15] A. Diller. Animation using Miranda. In Z: An Introduction to Formal Methods, chapter 19, pages 271–278. John Wiley & Sons, 2nd edition, 1994. [16] N. E. Fuchs. Specifications are (preferably) executable. In High-Integrity System Specification and Design [10], pages 583–607. [17] H. S. Goodman. The Z-into-Haskell tool-kit: An illustrative case study. In J. P. Bowen and M. G. Hinchey, editors, ZUM’95: The Z Formal Specification Notation, volume 967 of Lecture Notes in Computer Science, pages 374–388. Springer-Verlag, 1995. [18] W. Grieskamp. A computational model for Z based on concurrent constraint resolution. In J. P. Bowen, S. Dunne, A. Galloway, and S. King, editors, ZB 2000: Formal Specification and Development in Z and B, volume 1878 of Lecture Notes in Computer Science, pages 414–432. Springer-Verlag, 2000. [19] W. Grieskamp and M. Lepper. Using Use Cases in executable Z. In Shaoying Liu et al. [30], pages 111–119. [20] I. J. Hayes and C. B. Jones. Specifications are not (necessarily) executable. In High-Integrity System Specification and Design [10], pages 563–581. [21] M. A. Hewitt, C. M. O’Halloran, and C. T. Sennett. Experiences with PiZA, an animator for Z. In J. P. Bowen, M. G. Hinchey, and D. Till, editors, ZUM’97: The Z Formal Specification Notation, volume 1212 of Lecture Notes in Computer Science, pages 37–51. Springer-Verlag, 1997. [22] M.G. Hinchey and J. P. Bowen, editors. Industrial-Strength Formal Methods in Practice. FACIT series. Springer-Verlag, 1999. [23] M. Johnson and P. Sanders. From Z specifications to functional implementations. In Nicholls [28], pages 86–112. [24] C. B. Jones. Systematic Software Development using VDM. Prentice Hall International Series in Computer Science, 1990. [25] R. D. Knott and P. J. Krause. The implementation of Z specifications using program transformation systems: The SuZan project. In C. Rattray and R. G. Clark, editors, The Unified Computation Laboratory, volume 35 of IMA Conference Series, pages 207–220, Oxford, UK, 1992. Clarendon Press. 19

[26] C. C. Morgan. Programming from Specifications. Prentice Hall International Series in Computer Science, 2nd edition, 1994. [27] I. Morrey, J. Siddiqi, R. Hibberd, and G. Buckberry. A toolset to support the construction and animation of formal specifications. Journal of Systems and Software, 41(3):147–160, 1998. [28] J. E. Nicholls, editor. Z User Workshop, Oxford 1989, Workshops in Computing. SpringerVerlag, 1990. [29] U. Nilsson and J. Małuszy´nski. Logic, Programming and Prolog. John Wiley & Sons, 2nd edition, 1995. [30] Shaoying Liu, J. A. McDermid, and M. G. Hinchey, editors. ICFEM 2000: Proc. 3rd IEEE International Conference on Formal Engineering Methods. IEEE Computer Society, 2000. [31] L. B. Sherrell and D. L. Carver. Experiences in translating Z designs to Haskell implementations. Software—Practice and Experience, 24(12):1159–1178, 1994. [32] L. B. Sherrell and D. L. Carver. FunZ: An intermediate specification language. The Computer Journal, 38(3):193–206, 1995. [33] J. M. Spivey. The Z Notation: A Reference Manual. Prentice Hall International Series in Computer Science, 2nd edition, 1992. [34] J. M. Spivey. An Introduction to Logic Programming through Prolog. Prentice Hall International Series in Computer Science, 1996. [35] S. Thompson. Miranda: The Craft of Functional Programming. International Computer Science Series. Addison-Wesley Publishing Company, 1995. [36] S. Thompson. Haskell: The Craft of Functional Programming. International Computer Science Series. Addison-Wesley Publishing Company, 2nd edition, 1999. [37] H. Treharne, J. Draper, and S. Schneider. Test case preparation using a prototype. In D. Bert, editor, B’98: Recent Advances in the Development and Use of the B Method, volume 1393 of Lecture Notes in Computer Science, pages 293–311. Springer-Verlag, 1998. [38] M. M. West and B. M. Eaglestone. Software development: Two approaches to animation of Z specifications using Prolog. IEE/BCS Software Engineering Journal, 7(4):264–276, July 1992.

20

Deriving Correct Prototypes from Formal Z Specifications

Miranda. Neither sets, binary relations, mappings, nor bags are directly available. Hence data refine- ..... the validation cycle is easier. Finally, this paper has only ...

116KB Sizes 0 Downloads 177 Views

Recommend Documents

A Formal Framework for the Correct-by-construction ...
to while building control models. These features helped the engineers to go back and forth between high level models and implementations. This is essential in ...

Deriving Operational Semantics from Denotational ...
aim is to build equivalence between the operational and de- ... transition types for Verilog and define a phase semantics of ... support parallel expansion laws.

Deriving Configuration Interfaces from Feature Models ...
as of task, user, discourse and business models found in the ... plications have permeated a number of markets such as car manufacturers, clothing or computer ...

Deriving Customer Loyalty and Its Determinants from ...
through various social media including online reviews. It is known that ... We implement our framework in section 5 and refine our model in section 6. A brief ...

Prototypes White Paper.pdf
Page 3 of 4. ATTACHMENT ONE. Applicable Statutes, SFC Rules & Regulations, and A/E Design Agreement. W.S. 21-15-114 (a) The school facilities ...

Realizability toposes from specifications
Jul 3, 2015 - The other two capture and restore continuations. 9 / 22 .... includes reading and writing of data – instead of 'values' or Church numerals. 14 / 22 ...

A Study on deriving Respiratory Signals from ECG
The AV node thus acts as a "relay station" delaying stimulation of the ventricles long enough to allow the two atria to finish emptying. 4. The electrical ...... starting pulses for the complete pumping action of the heart, is also affected by the au

Deriving information structure from convergent derivations
DP VP. Nom. DP]]. From (4), the alternative configuration in which Dat internally merges above T is convergent, as it no longer is an intervenor. We assume that ...

Towards deriving conclusions from cause-effect relations
Department of Computer Science ... a central aim of the special sciences. ..... aand P5) we may understand causal literals in the top part of the program as a ...

A Study on deriving Respiratory Signals from ECG
After 1st week of liberal search into this area, the group with the consent of the Instructor ... (all multi-lead ECG data and Respiratory data only available in hard copies) and lack of implementation of ... A period of recovery follows called diast

A Study on deriving Respiratory Signals from ECG
ECG for heart rate monitoring could use a reduced bandwidth 0.5 – 50 Hz. ..... This signal, like other biomedical signals, is not free from the artifacts and noise.

2.Pick out correct secondary storage device from the following
What will happen when we press 'Shift+Tab'keys in MS Excel? A.Cursor ..... C.Create the file and save as web page by selecting file type from the save window*.

《The A-Z of Correct English Common Errors in English》.pdf ...
This file was collected by ccebook.cn form the internet, the author keeps the copyright. More ebooks visit: http://www.ccebook.cn ccebook-orginal english ebooks.

Evolution of Millon's Personality Prototypes
posed a new classification for emotional or psychiatric disorders. The foundation of the system was made up of eight personality prototypes borrowed from the psychi- atric nosology that was current at the time, the second edition of theDiagnostic and

Conditionally Correct Superoptimization - GitHub
as a 3× speedup over code that is already aggressively op-. 1 The discussion in ..... the states of T and R are related by the invariant I. We call this VC Init as it ..... and α is generalized to sets of addresses in the obvious way, α(S) = Us∈

Deriving German scrambling without information ...
man is scope-transparent (Bobaljik & Wurmbrand 2012), movement of the QP to the edge of. vP is both acceptable at the semantic interface and reflected in the ...

Correct List.pdf
Alexis Guiliano 12. Page 3 of 21. Correct List.pdf. Correct List.pdf. Open. Extract. Open with. Sign In. Main menu. Displaying Correct List.pdf. Page 1 of 21.

1 Business Rules Extraction from Business Processes Specifications ...
from specifications of business processes written in natural language, using the .... simple and straightforward mapping to SBVR concepts [Object Management Group,. 2008]. A small .... document with all the BR candidates' sentences. When a ...

Mining API Error-Handling Specifications from Source ...
file system failures, and slow system response. As a simple ... error handling, a send procedure, which sends the content of a file across the network as ... tection and recovery. ...... IEEE Standard for Information Technology - Portable Operating.

Stock Specifications - Pipes
The surface condition complies with API 5L Annex E. (b) External surface of pipe shall be coated with a layer of varnish. NDT. All pipes will be ultrasonic tested ...

GLUT Specifications - Hippo Games
Nov 13, 1996 - The OpenGL Utility Toolkit (GLUT) is a programming interface with ANSI C and FORTRAN bindings for writ- ing window system .... The advantage of a builtin event dispatch loop is simplicity. GLUT contains routines for rendering fonts and

GeoPackage Specifications -
May 11, 2012 - enabled analytics. This GPKG data container ..... GEOS is widely used by both free and commercial software packages. Quantum GIS (QGIS) is.