Unifying Program Construction and Modification M. FRAPPIER, D´epartement de math´ematiques et d’informatique, Universit´e de Sherbrooke, Sherbrooke, Qu´ebec, Canada, J1K 2R1, E-mail:
[email protected] A. MILI, Department of Computer Science and Electrical Engineering, West Virginia University, Morgantown, West Virginia, 26506, USA. E-mail:
[email protected] J. DESHARNAIS, D´epartement d’informatique, Universit´e Laval, Ste-Foy, Qu´ebec, Canada, G1K 7P4, E-mail:
[email protected] Abstract We propose a method which integrates program modification to the refinement calculus style of program development. Given a program developed through stepwise refinement of a specification, we propose an approach to specify modifications and to derive a new program from the existing refinement steps. This approach is based on the refinement lattice operator meet. A modification to a specification is represented by taking the meet of the old specification and the new feature to add. A solution to the new specification is constructed by coercing the new feature to match the structure of the existing refinement steps. The method fosters reuse of refinement steps and their proofs. We also show that program construction is streamlined by using coercion1 . Keywords : Program modification, relational specifications, refinement lattice.
1
Introduction
Constructing a provably correct program from a formal specification is a challenging task. Over the years, several methods were proposed, and some of them have been used with success on industrial-size problems (e.g., [6]). However, if considerable attention was paid to program construction, little attention was paid to program modification. Software components are not static entities. Requirements evolve, and programs usually undergo continuous change throughout their lifecycle. Thus, it is critical for a program construction method to address the issue of modification. More specifically, a method should foster the reuse of development steps in order to reduce the cost of carrying out a modification. In this paper, we propose a method for program modification which is based on a relational refinement calculus [10]. Specifications and programs are represented by 1 This research is supported by NSERC (Natural Sciences and Engineering Research Council) of Canada and by FCAR (Fonds pour la Formation de Chercheurs et l’Aide ` a la Recherche) of Qu´ ebec.
L. J. of the IGPL, Vol. 6 No. 2, pp. 317–340 1998
317
c Oxford University Press
318 Unifying Program Construction and Modification binary relations. They can be freely mixed during the construction process. Specifications are ordered by the refinement relation, which confers a semilattice structure on the set of specifications. Given a program P which is known (by construction) to be correct with respect to some specification R, and given some specification R0 which is obtained by a (slight) modification of R, we are interested in transforming program P into a program P 0 which is known (by construction) to satisfy R0 . This problem can also be formulated in the following terms: Given specification R0 , find a program P 0 correct with respect to R0 , using the hypothesis that P is correct with respect to R. Given that R is known to be similar to R0 , we interpret this hypothesis to mean that a solution to R0 will look like (i.e. have the same overall design as) the given solution to R, which is P . On the basis of this hypothesis, and to the extent that this hypothesis is valid, our approach consists in imposing the structure of P (which is known) on specification R0 , and decomposing R0 into smaller components which are matched to the corresponding components of P , thereby (inductively) creating new modification problems. The main mathematical issue that this approach raises is that of imposing a predefined structure on a specification, and decomposing it in an optimal manner according to the given structure; we refer to this process as structure coercion. This paper is organized as follows. Sect. 2 briefly introduces the mathematical background of our method. We illustrate the method for combining subspecifications on the Sort specification. In Sect. 3, we introduce our approach for specifying modifications and for deriving programs from modified specifications. We illustrate the approach by modifying the Sort specification. In Sect. 4, we present structure coercion rules and we investigate their optimality. Finally, we conclude with an assessment and some prospects in Sect. 5.
2
Background
2.1 Relations Relations have been used for specification and design in various domains (e.g., [2, 4, 15, 18]). We adopt the definitions provided in [19] for most relational notions used in this paper. We provide set-theoretic definitions of relational notions, and we use their relation-algebraic characterization to conduct proofs. A concrete (homogeneous) binary relation R on a set S (state space) is a subset of the Cartesian product S × S. We denote the universal relation (S × S) by V , the empty relation by ∅ and the identity relation ({(s, s0 )|s0 = s}) by I. Also, the complement R is the set difference V − R, the converse R ∪ is {(s, s0 )|(s0 , s) ∈ R} and ∧ the relational composition is R ◦ R0 = {(s, s0 )|∃t : (s, t) ∈ R ∧ (t, s0 ) ∈ R0 }. We usually omit ◦ and use the concatenation RR0 to represent the relational composition of R and R0 . ∧ ∧ We let dom(R) = {s|∃s0 : (s, s0 ) ∈ R} and rng(R) = {s0 |∃s : (s, s0 ) ∈ R} be ∧ respectively the domain and range of relation R. We let s.R = {s0 |(s, s0 ) ∈ R} be the set of images of an element s by relation R. We may algebraically characterize the domain and range of a relation R as RV and R ∪ V respectively. We say that a relation t is a left vector iff there exists a subset T of the space S such that t = T × S; the converse t ∪ of a left vector t is called a right vector.
2. BACKGROUND 319 An algebraic characterization of a vector t is t = tV . To restrict the domain of a relation R to a subset T of the space (prerestriction), we use t ∩ R, where t is the left vector corresponding to T . Similarly, to restrict the range of a relation R to T (postrestriction), we use R ∩ t ∪ . As a convention, we use symbols P , Q, R (possibly subscripted) for relations, and we use t and u for left vectors.
2.2 Specifications We let a specification be defined by a set S, called the space, and a binary relation R on S, called the relation of the specification. When the space is implicit from the context, we equate the specification with the relation R. A relation R has the following interpretation: if a computation starts in a state s ∈ dom(R), then it must terminate in a state s0 such that (s, s0 ) ∈ R. If a computation starts in a state outside the domain of R, then any outcome is acceptable, including nontermination. Our spaces are typically structured as Cartesian products of elementary sets, and are represented in a Pascal-like fashion. Hence, the declaration space a : Nat, b : Int defines a space S as: S = Nat × Int. For the sake of brevity, instead of writing our relations in the form {(ha, bi, ha0, b0 i) ∈ (Nat × Int) × (Nat × Int)|p(a, b, a0, b0 )} , we simply write {p(a, b, a0, b0 )}. We may suppress the curly brackets when predicates are elementary (e.g., a = b).
2.3 Refinement Lattice A relation P refines a relation Q (written P v Q) iff dom(Q) ⊆ dom(P ) and, for all s in the domain of Q, s.P ⊆ s.Q. Relation v is an ordering (reflexive, transitive and antisymmetric). In terms of program development, we interpret the refinement relation as follows: if P v Q, then any program totally correct wrt P is totally correct with respect to Q. An algebraic characterization of the refinement relation is P v Q ⇔ QV ⊆ P V ∧ QV ∩ P ⊆ Q .
(2.1)
Under the refinement ordering, relations form a complete t-semilattice [8], i.e., a least upper bound exists for any non-empty set of relations.
2.3.1 Demonic Join The least upper bound of two relations P and Q is denoted by P t Q. From the definition of refinement, one finds that P t Q = P V ∩ QV ∩ (P ∪ Q) .
(2.2)
We call operator t the demonic join. In programming terms, the demonic join offers a choice between two specifications: a program satisfies P t Q if and only if it satisfies
320 Unifying Program Construction and Modification either P or Q. As an illustration of this operator, consider the following equalities, where the space is space s : Real: {s02 = s ∧ s0 ≥ 0} t {s02 = s ∧ s0 ≤ 0} = {s02 = s} , {s02 = s} t {s02 = −s} = {s0 = s = 0} = {(0, 0)} . The domain of an expression P t Q is the intersection of the domains of P and Q; on this domain, P t Q is the union of P and Q.
2.3.2 Demonic Meet The greatest lower bound of two relations exists iff the following condition is satisfied: P V ∩ QV ⊆ (P ∩ Q)V .
(2.3)
We refer to this condition as the consistency condition, and we denote it by cs(P, Q). The greatest lower bound of P and Q is denoted by P u Q. When cs(P, Q) holds, one finds from the definition of refinement that P u Q = (QV ∩ P ) ∪ (P ∩ Q) ∪ (P V ∩ Q) .
(2.4)
We call operator u the demonic meet. In programming terms, the demonic meet represents the sum of specifications: a program satisfies P u Q if and only if it satisfies P and Q. We will use the demonic meet to structure specifications and to specify modifications. The demonic meet of two relations is not defined when the relations provide disjoint sets of outputs for some input where they are both defined. The demonic meet can be interpreted as the specification that carries all the requirements of P and all the requirements of Q and nothing more; hence the demonic meet is indeed adding up the specifications. The formula defining demonic meet may be understood as follows: the term QV ∩ P provides that the demonic meet of P and Q behaves like P for inputs where only P is defined; similarly, the term P V ∩ Q provides that the demonic meet behaves like Q for inputs where only Q is defined; the term P ∩ Q provides that the demonic meet behaves like P and Q for inputs where both P and Q are defined. The domain of P u Q is the union of the domains of P and Q. To illustrate this operator, we consider the case where we want a program that merges two sorted lists l1 and l2 into a list l3 . The following is a possible specification: {prm(l1 • l2 , l30 )} u {std(l1 ) ∧ std(l2 ) ∧ std(l30 )} . This specification requires a program to produce a list l3 which is a permutation of the concatenation of the input lists l1 and l2 . Moreover, when the input lists are sorted, the final list l3 is also sorted. Note that when P and Q have the same domain (i.e., P V = QV ), we have P u Q = P ∩ Q, and when P and Q have disjoint domains (i.e., P V ∩ QV = ∅), we have P u Q = P ∪ Q.
2.3.3 Demonic Composition An order-embedding of the refinement semilattice into the inclusion lattice of a relation algebra has been defined in [8]. One finds that the operation corresponding to
2. BACKGROUND 321 composition in the embedding algebra is the so-called demonic composition [3, 4, 8]: P
2
∧
Q = P Q ∩ P QV .
(2.5)
The set-theoretic interpretation of demonic composition is more intuitive: P 2 Q = {(s, s0 )|(s, s0 ) ∈ P Q ∧ s.P ⊆ dom(Q)} . The programming interpretation of demonic composition is the sequential composition of two specifications. As one would expect when such an interpretation is taken, demonic composition is associative, and its unit is the identify relation (I), which corresponds to the skip program. It is noteworthy that when P is deterministic (i.e., PbP ⊆ I) or when the range of P is included in the domain of Q (i.e., P ∪ V ⊆ QV ), the demonic composition of P by Q is the same as the traditional relational composition (P 2 Q = P Q). In practice, we often refine a relation using a demonic composition when either of these two conditions is satisfied, which simplifies the calculations. As an example, consider the following specification on Real which computes the 4th root √ 4 of s ( s). {s02 = s ∧ s0 ≥ 0} 2 {s02 = s} = {s04 = s} The first relation computes the positive square root; its range is {s ≥ 0}. The second relation computes a square root (positive or negative); its domain is also {s ≥ 0}. Hence, the demonic composition returns the same result as the relational composition. In the next example, the demonic composition differs from the relational composition, because for each s 6= 0, the first relation may compute a positive or a negative square root, hence we have s.P 6⊆ dom(Q). The resulting relation is not defined for these values of s. {s02 = s} 2 {s02 = s} = {s = s0 = 0}
2.3.4 Demonic Closure We use the demonic closure operator to specify iterations over a specification: G ∧ ∧ ∧ P i , where P 0 = I and P i+1 = P 2 P i . P∗ = i≥0
A demonic closure is an iteration without termination condition. A termination condition can be specified by taking the demonic meet of a closure and a right vector (see Eq. (2.8) in Sect. 2.5). As an illustration of demonic closure, we consider the specification of a permutation. If we observe that a natural way to define a permutation of an array is by an arbitrary number of swaps of pairs of cells, then we can write a permutation Prm as: Prm = Swap ∗ . Because it is based on demonic product and demonic meet, closure may differ S demonic ∧ ∧ i P , with P 0 = I and significantly from the usual closure (given by P ∗ = i≥0 ∧ P i+1 = P P i ), as the following example illustrates: n
{s02 = s}∗ = {∃n ≥ 0 : s02 = s} , {s02 = s} ∗ = {s = s0 = 0} ,
322 Unifying Program Construction and Modification where s : Real. In the particular case where P is total, the two closures are the same. Typically, a demonic closure will be combined (by the demonic meet) with a right vector which provides the exit condition. An illustrative example of this pattern is the specification of the sort program, which can be written as ∧
Sort = Swap ∗ u Sorted , where Sorted indicates that the output array is sorted. Finally, let us introduce an abbreviation that we often use in program construction. In specifications, a left vector t is a condition that must be satisfied in the initial state; a right vector t ∪ is a condition that must be satisfied in the final state. The preservation of condition v, v being a left vector or a right vector, from the initial ∧ state to the final state is defined as v = v ∩ v ∪ . Note that t ∪ = t ∪ ∩ t ∪ ∪ = t ∪ ∩ t = t . The precedence of relational operators, from highest to lowest, is { , ∪ , ∗ , }, {◦, 2 }, {∩, u}, {∪, t} . The precedence of logical operators, from highest to lowest, is: ¬, ∧, ∨, {⇐, ⇒}, ⇔, {∀, ∃} .
2.4 Refinement Calculus A refinement calculus consists of a formal language, a refinement relation and a set of transformation rules. The formal language embodies specification and programming constructs which can be freely mixed during the development of a program. A transformation rule maps a specification R into a specification R0 such that R is refined by R0 . Thus, transformations preserve correctness. A specification is refined into a program by successive applications of transformation rules. The development of a program Rn from a specification R0 is a sequence of refinements: R0 w R1 w . . . w Rn . The transitivity of the ordering v implies that R0 w Rn . Hence, the resulting program Rn is correct by construction. It is the programmer’s responsibility to select transformation rules, and to satisfy proof obligations associated with each rule. In a refinement step, a specification R is usually decomposed into specifications R1 and R2 such that R w R1 ΦR2 , where Φ is an operator of the language. In turn, R1 and R2 are decomposed until executable elementary statements are obtained. To foster separation of concerns, a refinement calculus must allow the designer to refine R1 without any regards to R or R2 , and, similarly, to refine R2 without any regards to R or R1 ; in addition, correctness must be preserved in the process. A sufficient condition to achieve this goal is to have monotonic specification operators with respect to the refinement relation. Each demonic operator introduced above, except , is monotonic wrt v. Hence, we may use these operators and the refinement relation to build a refinement calculus.
2. BACKGROUND 323 The choice of these demonic operators for building a refinement calculus may seem inadequate, because of their complex definitions. However, the order embedding given in [8] streamlines several proofs, and shows that demonic operations satisfy properties very similar to the native operations of a relation algebra. Moreover, stepwise refinement using demonic operators is not overly complex, since we often use demonic operators when they satisfy conditions where their computation is reduced to a simple expression using native operations. Another potential difficulty with our demonic calculus is that some operations are partial (e.g., u), therefore it is possible to write undefined expressions. Other calculi suffer from a similar constraint (e.g., [1, 12, 13, 14, 16, 20]): undefined expressions in our calculus translate into miraculous or unfeasible specifications in these calculi; checking for definedness in our calculus amounts to checking for feasibility in these calculi. Undefinedness (or unfeasiblity) seems to be an unavoidable constraint so far in refinement calculi. We shall see in Sect. 2.5 that it is not necessary, in practice, to check that all the demonic meets we write are defined. If, after several refinement steps, we find an expression which we know to be defined, we can infer that all intermediate expressions are defined as well; this stems from a monotonicity property of the condition of consistency (under which a demonic meet is defined), which we will discuss in section 2.5. The definitions of these demonic operations stem for our initial choice of how to write specifications. We interpret a relation as a set of input-output pairs that the user considers correct. Hence, the user will consider that a program satisfies a specification R if it delivers an output s0 for an input s such that (s, s0 ) ∈ R. This interpretation of relations leads to our definition of refinement, which leads in turn the definition of demonic operators to represent design constructs like and (u), or (t), sequential execution ( 2 ) and unbounded iteration ( ∗ ).
2.5 Program Construction by Parts Program construction by parts [10, 11] is a paradigm that can be used within a refinement calculus. It consists in tackling a complex specification one component at a time, developing a partially defined solution for each component, then combining the partial solutions into a global solution for the aggregate specification. This method is useful whenever the specification at hand is too complex to be grasped in all its detail. It is applicable whenever the specification is structured as a meet (in the refinement lattice) of independently defined subspecifications —where each subspecification represents a simple functional requirement. In [10], we have proposed a set of rules to combine partially defined solutions to subspecifications. One of the objectives of the rules is to eliminate instances of the demonic meet operator from specifications, because the demonic meet cannot be executed efficiently, to the extent of our knowledge. A way to eliminate demonic meets is to refine a specification by a statement written in the target programming language. Our target programming language is a language with the conventional imperative structures, that is, assignment, sequence, conditional and while loops. For the sake of simplicity, we adopt a subset of Pascal as our target programming language.
324 Unifying Program Construction and Modification Definition 2.1 ∧ Let w = x1 : T1 , . . . , xn : Tn , where xi is a variable and Ti is a type (set of values), be the variables defining the space of a specification; let y : T be a variable not appearing in w. We denote by Sw the space T1 × . . . × Tn , and by Sw+y the space T1 × . . . × Tn × T . Let e be an expression, let P and Q be relations, let t be a left ∧ ∧ vector, let F = t ∩ I ∪ (t ∩ P ) 2 X, and let π = {(s, s0 ) ∈ Sw+y × Sw |∃t : s = hs0 , ti}. Then xi := e = {x0i = e ∧ ∀j ∈ 1..n : i 6= j ⇒ x0j = xj } , ∧
∧
P;Q = P 2Q , ∧
if t then P else Q end = t ∩ P ∪ t ∩ Q , ∧
if t then P end = if t then P else I end , ∧
while t do P end = greatest fixpoint of F wrt v , ∧
var y : T P = π ∪ 2 P 2 π . Conditions in if and while statements are represented by left vectors. The var construct introduces a local variable y of type T . The initial value of y is arbitrary in type T ; its final value is lost when the execution of P is completed. The scope of a declaration var y : T extends as far as possible on the right, and is limited by parentheses if necessary. Because the demonic meet cannot in general be mapped to a Pascal-like statement, the main focus of our refinement process is on eliminating demonic meets from specification expressions, using an inductive argument. First, we consider basis of induction rules, which get rid of the demonic meet altogether. A simple rule to eliminate demonic meets stems from the idempotence property. P uP = P
(2.6)
We use this law when we can find a common refinement for the operands of a demonic meet. The following law allows to replace a demonic meet by an if. (t ∩ P ) u (t ∩ Q) = if t then P else Q end
(2.7)
In the next equation, we use the following concept to represent loop termination: a relation R is said to be progressively finite [19], which we denote by ω(R), iff there exists no infinite sequence s0 , s1 , . . . , si , . . . such that (si , si+1 ) ∈ R for all i. ω(t ∩ P ) ∧ t ⊆ P V
⇒ P∗ ut
∪
w while t do P end
(2.8)
The refined expression in this law is a typical example of the use of a closure in a refinement: the closure represents an unbounded number of iterations over relation P ; ∪ the right vector t imposes a condition on the final states. An intuitive interpretation of this expression is that we may iterate on P until condition ¬t is satisfied. When the prerestriction of P by condition t contains no infinite loops, and when P is defined for states satisfying t, this law provides that the demonic meet expression is refined by a while statement.
2. BACKGROUND 325 If a demonic meet cannot be directly removed, then it is propagated inside the subcomponents to make it easier to remove; this is the inductive step of our inductive process for removing demonic meets. The following laws hold whenever the demonic meets are defined. P1 2 P2 u Q1 2 Q2 w (P1 u Q1 ) 2 (P2 u Q2 )
(2.9)
P ∗ u Q ∗ w (P u Q) ∗
(2.10)
(var y : T P ) u (var y : T Q) w var y : T P u Q
(2.11)
Even though law (2.9) produces more demonic meets than it eliminates, it does make progress towards getting rid of demonic meets, because the meets of the right-hand side are applied to simpler expressions than the demonic meet of the left-hand side. Ultimately, it is by pushing demonic meets deeper in the nesting structure that one can find a simple program refining each operand of the demonic meet. Basis of induction rules are then used to remove the demonic meets. It has been found in [11] that it is not possible to propagate an undefined meet and obtain defined meets. That is, if a relational expression is refined using a propagation rule of the form (P1 ΦP2 ) u (Q1 ΦQ2 ) w (P1 u Q1 )Φ(P2 u Q2 ) , where Φ is a monotonic operator, then if the demonic meets on the right-hand side are defined, the meet on the left-hand side is also defined. Moreover, if an expression P uQ is refined into P 0 u Q0 using P w P 0 and Q w Q0 , then if the second meet is defined, so is the first meet, since in a complete semilattice a greatest lower bound exists if a lower bound exists. A consequence of these observations is that the programmer may delay the verification of the consistency condition, even if meets are propagated. In fact, it is seldom required to prove consistency using definition 2.3: if one is successful in removing a meet using laws (2.6), (2.7) or (2.8), then consistency is proved as a byproduct. One would need to prove consistency using the definition only if it seems impossible to eliminate the meet, as a means of determining if components were refined up to a point where they can no longer be satisfied simultaneously.
2.6 An Example of Refinement We now illustrate the application of the refinement calculus to the Sort problem. This refinement will be reused in Sect. 3.2 where we will make a change to the specification and derive a new program. The space of our specification is given by: space a: array[1..N ] of elementtype; i: 0..N We use the following predicates and functions which we define informally: prm(a, a0 ) st(a) pst(a, i)
a is a permutation of a0 ; a is sorted in ascending sequence; st(a[1..i]) and each element in a[1..i] is less than or equal to each element in a[i + 1..N ]
326 Unifying Program Construction and Modification min(a, i, j) swap(a, i, j)
returns the smallest index of the minimum value in a[i..j]; swaps positions i and j in array a.
Specification Sort may be defined as follows: Sort = prm(a, a0 ) u st(a0 ) . ∧
Component prm(a, a0 ) requires a program to produce a permutation of the input array. Component st(a0 ) requires a sorted output array. A program that satisfies the demonic meet of these two components must produce a sorted permutation of the input array, i.e., the program must sort the input array. We now proceed with the refinement of the Sort specification. Not all laws used in the refinement are presented in this paper. The reader is referred to [10] for a comprehensive set of laws. Our solution is constructed by solving subspecifications prm(a, a0 ) and st(a0 ) independently, and then combining their solutions to derive a program satisfying the entire specification (i.e., Sort). For the sake of readability, we have chosen to present the mathematical material of this paper in small increments, mixing it with motivational material and illustrative examples. A byproduct of this attempt is that some of the refinement rules that we need for the program refinement that follows will not be presented until subsequent sections. Whenever we refer to such a rule, we indicate it with a dagger (†) and add a brief comment to explain the meaning of the rule. The Ri labels appearing on the right-hand side of the refinement steps will be referenced in subsequent discussions. Sort
= w w
w
w
w
h definition of Sort i prm(a, a0 ) u st(a0 ) h predicate calculus: st(a0 ) w {pst(a0 , i0 ) ∧ i0 = N } i 0 prm(a, a ) u {pst(a0 , i0 ) ∧ i0 = N } h refine the conjunction: law (4.23)† i prm(a, a0 ) u pst(a0 , i0 ) u i0 = N h sequential decomposition of prm(a, a0 ): Corollary 4.9† and R1 law (4.11)† i prm(a, a0 ) 2 prm(a, a0 ) u pst(a0 , i0 ) u i0 = N h sequential decomposition of pst(a0 , i0 ): Corollary 4.9† and law (4.8)† i prm(a, a0 ) 2 prm(a, a0 ) u pst(a0 , i0 ) 2 pst(a, i) u i0 = N h sequential decomposition of i0 = N : Corollary 4.9† and law (4.7)† i prm(a, a0 ) 2 prm(a, a0 ) u
2. BACKGROUND 327 pst(a0 , i0 ) 2 pst(a, i) u V 2 i0 = N h propagate demonic meet twice: law (2.9) i w (prm(a, a0 ) u pst(a0 , i0 ) u V ) 2 (prm(a, a0 ) u pst(a, i) u i0 = N )
R2
For the sake of space, let us use the following abbreviations in the sequel: init = prm(a, a0 ) u pst(a0 , i0 ) u V , ∧
loop = prm(a, a0 ) u pst(a, i) u i0 = N . ∧
We resume the refinement using these abbreviations.
w
init 2 loop
h i := 0 refines each component of init: law (2.6) i
i := 0 2 loop We now resume the refinement of loop. loop
=
w
w
w w
h definition of loop i prm(a, a0 ) u pst(a, i) u i0 = N h introduce demonic closure on prm(a, a0 ): law (4.22)† i prm(a, a0 ) ∗ u pst(a, i) u i0 = N h introduce demonic closure on pst(a, i) : law (4.19)† i prm(a, a0 ) ∗ u pst(a, i) ∗ u i0 = N h propagate demonic meet : law (2.10) i (prm(a, a0 ) u pst(a, i) ) ∗ u i0 = N h introduce progressive finiteness with i0 > i i 0 (prm(a, a ) u pst(a, i) u i0 > i) ∗ u i0 = N
At this point, let us introduce the following abbreviation: body = prm(a, a0 ) u pst(a, i) u i0 > i . ∧
We resume the refinement of loop using abbreviation body. =
body ∗ u i0 = N
h definition of body i
R3
R4
R5
328 Unifying Program Construction and Modification h law (2.8) i while i 6= N do body end h refine body: predicate calculus and law (2.6) i w while i 6= N do i := i + 1 2 swap(a, i, min(a, i, N )) end w
The solution derived is the classical Straight Selection Sort.
3
Modification of Specifications
In the context of a refinement calculus, we want to address the following problem: given a specification P which has been refined in a stepwise manner into a program, and given a specification P 0 obtained after modifying P , find a program correct with respect to P 0 (while taking advantage of the solution of P ). A crude approach is to consider P 0 as a new specification, and to derive a program for it from scratch. When P 0 is very different from P , this could well be the best option. But when P 0 is very similar to P , a sensible approach is to try to reuse as much as possible of the solution to P in the refinement of P 0 . Of course, even then, the solution to P may be completely inappropriate. In the case where the solution to P is a good basis for a solution to P 0 , one would like to be able to easily reuse it. In this section, we introduce our approach to this problem. We first present the kind of specification modifications our approach can handle. Then we show how to construct a correct program while reusing existing refinements.
3.1 Specifying Modifications Let us first establish some terminology. Let R be the specification to modify, and let R0 be the specification obtained after modifying R. We say that R is the base specification, and that R0 is a variant of R. Our approach supports modifications which satisfy the following premises. 1. Specification R is structured as the demonic meet of a set of subspecifications {Ri }. 2. The modification to R can be expressed as removing some subspecifications Ri and adding new subspecifications Qi , and then taking their demonic meet (assuming the greatest lower bound exists). ∧
For instance, if we have a base specification R = R1 u R2 u R3 , then a modification ∧ to R may consist in removing R2 and adding Q1 , which results in variant R0 = R 1 u R 3 u Q1 . When the base specification R is not structured as a demonic meet, a modification ∧ may simply consist in adding a new feature Q to R, resulting in variant R0 = R u Q. The designer may also resort to the following law to break R into a demonic meet of subspecifications: R = (t ∩ R) u (t ∩ R) .
3. MODIFICATION OF SPECIFICATIONS
329
Another typical example of modification that can be handled using our approach is program merging [5, 21]. If R1 and R2 are two variants of some initial base specifications, then merging them corresponds to solving specification R1 u R2 . A program satisfying this specification also satisfies R1 and R2 , according to the definition of demonic meet; hence it merges the two versions.
3.2 Constructing a Program for a Modification Given a base specification R and a variant R0 satisfying our premises, we want to find a correct program for R0 while reusing the refinement steps of R. The construction ∧ by parts approach is well suited for this task. Assume that R0 = R u Q. We have a solution for R. All that remains to do is to find a solution for Q, and then combine it with R. As an example, consider the Sort specification of Sect. 2.6. We wish to modify it so that the initial order of duplicate keys is preserved. For instance sorting the following list of pairs (key,datum) [(K2 , Da ), (K2 , Db ), (K1 , Dc )] results in [(K1 , Dc ), (K2 , Da ), (K2 , Db )] instead of [(K1 , Dc), (K2 , Db ), (K2 , Da )]. We specify this feature as follows: seqdup(a, k) dupk(a, a0 )
returns a sequence of the duplicates of k in a in their initial order; ∀k : seqdup(a, k) = seqdup(a0 , k).
The specification of the variant is given by: Sort0 = Sort u dupk(a, a0) . ∧
The monotonicity of u allows us to reuse the refinement steps of Sort as given is Sect. 2.6. Sort u dupk(a, a0 ) = h definition of Sort i prm(a, a0 ) u st(a0 ) u dupk(a, a0 ) h decompose st i w . . . refinement steps of Sort . . . h propagate demonic meet twice: law (2.9) i w (prm(a, a0 ) u pst(a0 , i0 ) u V ) 2 (prm(a, a0 ) u pst(a, i) u i0 = N ) u dupk(a, a0 ) At this point, we have to decompose dupk(a, a0) into a sequence in order to integrate it with the rest of the refinement of Sort. w
h sequential decomposition of dupk(a, a0): Corollary 4.9† and law (4.11)† i
R6
330 Unifying Program Construction and Modification (prm(a, a0 ) u pst(a0 , i0 ) u V ) 2 (prm(a, a0 ) u pst(a, i) u i0 = N ) u dupk(a, a0 ) 2 dupk(a, a0) h propagate demonic meet: law (2.9) i w (prm(a, a0 ) u pst(a0 , i0 ) u V u dupk(a, a0)) 2 (prm(a, a0 ) u pst(a, i) u i0 = N u dupk(a, a0 ))
R7
These last two steps highlight the crux of our approach to modification. We integrated the new component dupk(a, a0) into the existing solution by decomposing it so that its structure matches the structure of the existing refinement steps. In this case, we had three components which were solved by a sequence. Integrating the new component dupk(a, a0) consists in decomposing it into a sequence. This is what we refer to as structure coercion. We shall study structure coercion in detail in Sect. 4. For now, we carry on with our example. h definitions of init and loop i (init u dupk(a, a0)) 2 (loop u dupk(a, a0)) h i := 0 refines each component of init and dupk(a, a0): law (2.6) i w i := 0 2 (loop u dupk(a, a0)) =
This last step illustrates the case where a fragment of the program satisfying the base specifications is reused in the solution to the variant. Refining the second component of the sequence is illustrative in that it will lead to a case where existing program fragments must be discarded.
w
w
w w
= w
loop u dupk(a, a0 ) h reuse refinement steps R3 and R4 i prm(a, a0 ) ∗ u pst(a, i) ∗ u i0 = N u dupk(a, a0 ) h coerce dupk(a, a0 ) into a demonic closure: law (4.22)† i 0 ∗ prm(a, a ) u pst(a, i) ∗ u i0 = N u dupk(a, a0 ) ∗ h propagate demonic meet : law (2.10) i (prm(a, a0 ) u pst(a, i) u dupk(a, a0 )) ∗ u i0 = N h reuse refinement step R5 i (prm(a, a0 ) u pst(a, i) u i0 > i u dupk(a, a0)) ∗ u i0 = N h definition of body i (body u dupk(a, a0)) ∗ u i0 = N h law (2.8) i
R8
4. STRUCTURE COERCION
331
while i 6= N do body u dupk(a, a0) end h reuse refinement of body i 6w while i 6= N do (i := i + 1 2 swap(a, i, min(a, i, N ))) u dupk(a, a0) end Unfortunately, the last refinement step is invalid, because the demonic meet in the while loop is not defined. Indeed, swapping two elements may modify the sequence of duplicate keys (for instance, see the example given in the first paragraph of Sect. 3.2 where the third array is the result of applying Sort to the first array). Fortunately, the meet of body and dupk(a, a0) does exist. Hence, we have identified a modification to the program. We must find a new solution to body and dupk(a, a0). A solution can be derived using the construction by parts approach [10]. We leave it to the reader as an exercise; a potential solution is the Bubble Sort algorithm.
4
Structure Coercion
Our approach to program modification described in the previous section rests on the ability to find a decomposition of a new specification to match the structure of an existing component, which we call structure coercion. Our intent in this section is to study the conditions of feasibility and optimality for structure coercion for various demonic operators. Proofs are omitted; they can be found in [11].
4.1 Sequence Coercion Given a specification P1 2 P2 uR, we want to refine R into a sequence X1 2 X2 . Usually, the refinement step following a coercion is to propagate the demonic meet, obtaining a specification (P1 u X1 ) 2 (P2 u X2 ). An appropriate decomposition of R should ensure that the demonic meets are defined; hence cs(P1 , X1 ) and cs(P2 , X2 ) must hold. There are usually multiple solutions to this problem. Preferably, the solution should be as weak (high in the refinement lattice) as possible, in order to provide the easiest components to refine. With two variables, we may express this criterion as finding a solution (X1 , X2 ) such that for any solution (Y1 , Y2 ), we have Y1 v X1 and Y2 v X2 . In general, there exists no optimal solution wrt to this criterion. The next example ∧ on the space {0, 1} illustrates it. Let R = {(1, 0), (1, 1)}. The following are two solutions: ∧
∧
X2 = {(1, 0), (1, 1)} X1 = {(1, 1)}, ∧ ∧ Y1 = {(1, 0), (1, 1)}, Y2 = {(0, 0), (0, 1), (1, 0), (1, 1)} . There is no solution that is refined by these two solutions simultaneously. Since there is no optimal solution in the general case, we now study sequence coercion when one factor of R is given.
332 Unifying Program Construction and Modification
4.1.1 The Restricted Sequence Coercion To describe the restricted sequence coercion problem, we need to introduce the following terminology. We say that Q is a demonic right factor of R iff there exists X such that X 2 Q v R. Dually, we say that Q is a demonic left factor of R iff there exists X such that Q 2 X v R. Definition 4.1 (Restricted Sequence Coercion Problem) Given relations P1 , P2 , R, Q such that cs(P1 2 P2 , R), cs(P2 , Q) and Q is a demonic right factor of R, then find X such that (a) (b)
R w X 2Q , cs(P1 , X) .
(4.1)
In the sequel, we restrict ourselves to the case where the demonic right factor is given. The results are easily dualized for the demonic left factor. ∧ A solution to Eq. (4.1)(a) has been found in [8]. Let κ(R, Q) = RQ ∪ ∩ V Q ∪ be the conjugate kernel of R and Q [7]. The demonic left residue R over Q is defined as ∧ RQ = κ(R, Q). Its set-theoretic interpretation is {(s, s0 )|s0 ∈ dom(Q)∧s0 .Q ⊆ s.R}. It is the greatest solution wrt v of Eq. (4.1)(a), when a solution exists. The following equivalence expresses this fact. X 2 Q v R ⇔ (RQ) 2 Q v R ∧ X v RQ
(4.2)
Some inequations do not have a solution (e.g., X 2 ∅ v V ). The dual of is the ∧ demonic right residue of R over Q; it is defined as QBBR = κ(R ∪ , (RV ∩ Q) ∪ ) ∪ . Its set-theoretic interpreation is {(s, s0 )|s ∈ rng(Q ∩ RV ) ∧ s.(Q ∩ RV ) ∪ ⊆ s0 .R ∪ }. As expected, when solutions in X to inequation Q 2 X v R exist, QBBR is the greatest solution wrt v. Q 2 X v R ⇔ Q 2 (QBBR) v R ∧ X v QBBR We assign to and BB the same precedence as ◦ and to compute under some conditions.
2
(4.3)
. Demonic residues are simple
RQ ∪ Q v R ⇔ (RQ) 2 Q v R ∧ RQ = RQ ∪
(4.4)
RV = QV ∧ QQ ∪ R ⊆ R ⇒ Q 2 (QBBR) v R ∧ QBBR = Q ∪ R
(4.5)
It is interesting to note that, under some conditions, demonic relational division (residuation) is multiplication (demonic composition) by the inverse (converse), as in arithmetic (where ab = a × 1b = a × b−1 ). In the special case where Q is an assignment statement, the demonic left residue can be computed by syntactic substitution. Let p be a predicate defining a concrete relation. Let E[x1 , . . . , xn\e1 , . . . , en ] denote the simultaneous syntactic substitution of free occurrences of xi by ei in expression E. Then (4.6) V {p} ⊆ (x := e) ⇒ {p}(x := e) = {p[x0 \e0 ]} , where e0 is defined as e[w\w 0 ], and w is the list of variables of the space under consideration. Demonic residues of right vectors are also simple to compute. The following laws hold when t is a left vector. t 6= ∅ ⇒ t ∪ t ∪ = V
(4.7)
4. STRUCTURE COERCION t ∪ BBt ∪ = t
333 (4.8)
Returning to our sequence coercion problem of Def. 4.1, it is easy to show that a greatest solution to Eq. (4.1) exists iff cs(P1 , RQ). Moreover, the greatest solution is given by RQ. It is critical to pick the greatest solution, as it maximizes the chances of satisfying the consistency condition of (4.1)(a).
4.1.2 Optimal Factors When selecting a demonic (left or right) factor of R in the restricted sequence coercion problem (Def. 4.1), it is possible to choose one such that the decomposition of R is “optimal”. Definition 4.2 The demonic composition P 2 Q is said to be an optimal sequential decomposition of relation R iff P 2 Q v R and, for all X, Y , P vX ∧ Qv Y ∧ X2Y vR ⇒ X vP ∧ Y v Q . ∧
As an example, for specification R = {(1, 0), (1, 1)} on space {0, 1}, decompositions (X1 , X2 ) and (Y1 , Y2 ) are optimal: ∧
∧
X2 = {(1, 0), (1, 1)} , X1 = {(1, 1)}, ∧ ∧ Y1 = {(1, 0), (1, 1)}, Y2 = {(0, 0), (0, 1), (1, 0), (1, 1)} . The following decompositions (X10 , X2 ) and (Y1 , Y20 ) are not optimal: ∧
∧
X10 = {(0, 0), (0, 1), (1, 1)} X2 = {(1, 0), (1, 1)} , ∧ ∧ Y20 = {(0, 0), (1, 1)} . Y1 = {(1, 0), (1, 1)}, The demonic composition X10 2 X2 is equal to R, but there exists a relation, namely X1 , that is refined by X10 , and whose composition with X2 is equal to Q. Similarly, the demonic composition Y1 2 Y20 is equal to R, but Y20 v Y2 , and Y1 2 Y2 is equal to R. A designer faced with the selection of a demonic factor for R is best served by selecting X1 or Y2 instead of X10 or Y20 , because they are less refined, hence they leave more freedom in design. The next proposition provides a necessary and sufficient condition for optimality. Proposition 4.3 The demonic composition P 2 Q is an optimal sequential decomposition of relation R iff P = RQ ∧ Q = P BBR. We now present some results which allow the derivation of an optimal sequential decomposition using a demonic right factor. Definition 4.4 Relation Q is said to be an optimal demonic right factor of relation R iff Q is a demonic right factor of R and, for any demonic right factor X of R, Q v X ∧ RQ v RX ⇒ X v Q .
334 Unifying Program Construction and Modification ∧
As an example, for specification R = {(1, 0), (1, 1)} on space {0, 1}, the following relations Q1 and Q2 are optimal demonic right factors of R. Hence, there may be several optimal demonic factors for a relation: ∧
∧
RQ1 = {(1, 1)} Q1 = {(1, 0), (1, 1)} ∧ ∧ Q2 = {(0, 0), (0, 1), (1, 0), (1, 1)} RQ2 = {(1, 0), (1, 1)} . Increasing a demonic right factor in the semilattice results in a decrease of the corresponding demonic left residue, and vice-versa, (which is the same as in arithmetic for an equation x ∗ y = z), because RQ and QBBR are antitone in Q. The following demonic right factor of R with its left residue is not optimal: ∧
∧
Q3 = {(1, 0)} RQ3 = {(1, 1)} . Relation Q3 is not optimal, because Q3 v Q1 and R Q3 v R Q1 , but Q1 6v Q3 . The following proposition characterizes optimal demonic right factors. Proposition 4.5 Relation Q is an optimal demonic right factor of relation R iff Q = (RQ)BBR. Corollary 4.6 If Q is an optimal demonic right factor of R, then (RQ) 2 Q is an optimal sequential decomposition of R. Corollary 4.7 If P 2 Q is an optimal sequential decomposition of R, then Q is an optimal demonic right factor of R. The following proposition provides that, from any demonic right factor Q of a relation R, one can derive an optimal sequential decomposition. Proposition 4.8 If Q is a demonic right factor of R, then (RQ) 2 ((RQ)BBR) is an optimal sequential decomposition of R. Corollary 4.9 The demonic composition (RR) 2 R is an optimal sequential decomposition of R.
4.1.3 Transformation Rules Using law (2.9) and Corollary 4.9, we now propose refinement rules to solve the sequence coercion problem. These rules are optimal in the sense of Def. 4.2 and Def. 4.4. Sequence Coercion in Duet When the designer wants to implement the new feature R with either P1 or P2 , he may use the following laws which we call sequence coercion in duet. (4.9) P1 2 P2 u R w (P1 u R) 2 (P2 u RBBR)
4. STRUCTURE COERCION P1 2 P2 u R w (P1 u RR) 2 (P2 u R)
335
(4.10)
Law (4.9) is used when the designer wants to implement R in conjunction (in duet) with P1 . In that case, the solution to P2 must also preserve the properties of the state related to the application of R. Expression RBBR is just the expression of this preservation. Hence, the law states that the designer must solve P2 with RBBR. Law (4.10) is the dual of law (4.9). Whenever R represents the specification of a while loop, expressions RBBR and RR typically represent meaningful invariants of the loop. At first glance, expressions like RR and RBBR may seem awkward to use and meaningless. In practice, it turns out that their computation returns intuitive, simple specifications,Por at least of the same cognitive complexity as R. For instance, let ∧ N R = {x0 = i=1 a[i]}. Noting that R satisfies the left handside of laws (4.4) and (4.5), we compute RBBR = R ∪ R = {x0 = x} and
( R R = RR
∪
=
N X i=1
a[i] =
N X
) 0
a [i]
.
i=1
In the solution to the modification of Sort in Sect. 3.2, we have used sequence coercion in duet for refinement steps R6 and R7. In that case, the computation of dupk(a, a0)BBdupk(a, a0), interestingly, results in dupk(a, a0 ). Relation dupk(a, a0) is a PER (partial equivalence relation, i.e., symmetric and transitive). The following property holds for PERs: R is a PER ⇒ RR = RBBR = R .
(4.11)
This property follows easily from laws (4.4) and (4.5) after noting that a relation R is a PER iff R = RR ∪ . Sequence Coercion in Solo Another use of Corollary 4.9 is to implement a demonic meet with a sequence. For instance, P u Q
h dual of Corollary 4.9 i (P BBP ) u Q h law (4.10) i w (P u QQ) 2 (P BBP u Q) w
P
2
Our denomination “in solo” stems from the following observations: the first component of the sequence implements P while preserving the critical information required by Q (given by QQ); the second component implements Q while preserving the results obtained by P (given by P BBP ). We have used sequence coercion in solo from refinement step R1 to R2 of the Sort specification in Sect. 2.6. Sequence Coercion in Refrain When P1 or P2 are demonic factors of R, we have the following laws. P1 2 P2 u R w P1 2 (P2 u P1 BBR)
(4.12)
336 Unifying Program Construction and Modification P1 2 P2 u R w (P1 u RP2 ) 2 P2
(4.13)
Our denomination “in refrain” stems from the observation that P1 is used twice in the solution of components. This rule has the advantage of reducing the number of demonic meets to eliminate when compared to coercion in solo or coercion in duet.
4.2 Closure Coercion The coercion problem for the demonic closure operator takes the following form. Definition 4.10 (Closure Coercion) Given relations P and Q such that cs(P ∗ , Q), find relation X such that (a) (b)
Q w X∗ , cs(P, X) .
(4.14)
In general, there are multiple solutions to these two inequations, and there does not exist a greatest solution with respect to the refinement ordering. The following example on the space {0, 1, 2} illustrates this fact: ∧
∧
P = Q = {(0, 0), (0, 1), (1, 1), (1, 2), (2, 2), (2, 0)} . There are three maximal solutions for X: ∧
X1 = {(0, 0), (0, 1), (1, 1), (2, 2)} , ∧ X2 = {(0, 0), (1, 1), (1, 2), (2, 2)} , ∧ X3 = {(0, 0), (1, 1), (2, 2), (2, 0)} . The identity is also a solution, but it is not maximal. The following proposition provides a necessary and sufficient condition for the existence of a solution to Eq. (4.14)(a) in the closure coercion problem. Proposition 4.11 Eq. (4.14)(a) in Def. 4.10 has a solution iff I v Q. Proof. ∃X : Q w X ∗ ⇒ h X ∗ w I for any X i Qw I ⇒ h I = I∗ i ∗ Qw I ⇒ ∃X : Q w X ∗ .
4.2.1 Laws for Deriving Demonic Transitive Roots The following laws provide solutions to Eq. (4.14)(a) in the closure coercion problem (Def. 4.10). (4.15) I v Q ⇒ Q w (QQ) ∗ I v Q ⇒ Q w (QBBQ) ∗
(4.16)
4. STRUCTURE COERCION
337
Solutions QQ and QBBQ are rarely optimal, except in the case where Q = QQ (or Q = QBBQ). This case is trivial, but fortunately it often occurs in practice. In the next example, we see that QQ is a minimal solution wrt v (most refined, hence less desirable). Let {0, 1, 2, 3} be the space of the following relation: ∧
Q = {(1, 0), (1, 1), (1, 2), (2, 1), (2, 2), (2, 3)} . The optimal solution is {(1, 1), (1, 2), (2, 1), (2, 2)} , and the solution QQ is given by {(1, 1), (2, 2)} . The following laws provide optimal solutions to particular cases. QQ = (QQ) ∗
(4.17)
QBBQ = (QBBQ) ∗
(4.18)
t = t ∗
(4.19) ∗
and the definition of a least upper The following law follows from the definition of bound. It is the general mechanism for refining a relation by a closure. (∀i ≥ 0 : Q w P i ) ⇔ Q w P ∗
(4.20)
The next two rules are more specific cases of refinement by a closure. Q w I ∧ Q w Q 2 Q ⇔ Q = Q∗ P is a PER
⇒ P =P∗
(4.21) (4.22)
We have used closure coercion in refinement steps R3 and R4 of Sort in Sect. 2.6 to coerce prm(a, a0 ) with Eq. (4.22) and to coerce pst(a, i) with Eq. (4.19), and also in refinement step R8 of the modification of Sort in Sect. 3.2 to coerce dupk(a, a0) with Eq. (4.22).
4.3 Other Coercions The other interesting cases of coercion are for the demonic meet, the if, while and var constructs. The coercion of a relation into a demonic meet expression may seem useless at first glance, because our paradigm assumes that specifications are structured using demonic meets, and we provided laws to remove demonic meets in Sect. 2.5. However, it often occurs that components of a specification must be further decomposed in terms of demonic meets in order to find a suitable solution, because a specifier must promote minimality, completeness and clarity, rather than implementation issues. We provide two laws for demonic meet coercion. They hold provided that the demonic meet is defined. (4.23) P ∩Q w P uQ P ∪Q w P uQ
(4.24)
338 Unifying Program Construction and Modification P w (t ∩ P ) u (t ∩ P )
(4.25)
The coercion of a relation into an if statement is just a special case of law (4.25), by the definition of an an if statement (Def. 2.1). Q = if t then Q else Q end
(4.26)
The coercion problem for the while construct has already been addressed in [17], where it is shown that if a specification is refined by a while statement, then the specification is in first iterative form. Note that in the construction by parts paradigm, one does not necessarily have to coerce a specification into a while construct. When condition ω(t ∩ P ) ∧ t ⊆ P V is satisfied, the specification while t do P end u Q can be transformed into the specification ∪
(if t then P end) ∗ u t u Q . Then, it remains to coerce Q into a closure. The coercion of a relation into a var construct is simple. Let y be a fresh variable for specification P , then (4.27) P w var y : T πP π ∪ , where π is defined as in Def. 2.1. Since y does not appear in the space of P , the predicate defining P is syntactically the same as the one defining πP π ∪ .
5
Conclusion
This paper presents an approach to correctness-preserving software evolution which integrates program construction and program modification. The approach is based on program construction by parts and structure coercion: the former tackles the issue of combining solutions to the parts of a specification; the latter deals with finding a common structure for the parts of a specification. When used in conjunction, these techniques allow the derivation of new programs, and provide support for correctnesspreserving program modification. One of our objectives is to foster the reuse of existing refinement steps in the modification process. We address one way of achieving it, which consists in taking the demonic meet of some parts of the existing specification and new parts representing the modifications. The coercion rules then allow for the integration of the modification into the existing program. Our approach does not cover all possible cases of modifications. It is interesting to note in the examples provided in the paper that the decompositions introduced by structure coercion are the same as those that are typically chosen in an intuition-based decomposition process. We find it encouraging, since it illustrates how programming activities are amenable to mathematical modeling, and that the results are not foreign to the traditional intuition-based or experience-based programming approach. Other refinement calculi have been proposed in various frameworks. Our approach to program modification could probably be implemented in these calculi, as long as
5. CONCLUSION
339
they include a meet operator with respect to refinement. In [13], construction by parts is addressed in a context where specifications are represented by predicates and termination is represented by a time variable. The calculi presented in [9, 14] use relations, but with different interpretations than ours. In [12, 16, 20], meet operators are studied for specifications represented by a pair [pre, post]. The demonic meet operator could serve as a basis for establishing the correctness of program merging algorithms in [5, 21]. Our future work will focus on two directions. First, we wish to derive other structure coercion rules to streamline the decomposition process; we need heuristics for deriving demonic factors and demonic transitive roots. On the other hand, we want to take a step back, and consider other ways of reusing existing refinement steps for program construction or modification. We may formulate this problem as follows: given a specification R and its refinement steps, and a new specification R0 , find a monotonic function F and relations X1 , . . . , Xn such that F (X1 , . . . , Xn , R) v R0 . Relations Xi represent the new components, and F describes how to combine them with R. By requesting F to be monotonic, the refinement steps of R can be reused verbatim. An even more general formulation is to consider any component Rj of the refinement of R, and solve F (X1 , . . . , Xn , Rj ) v R0 . In general terms, what we are looking for is a calculus for software reuse.
Acknowledgments The authors would like to thank the anonymous referees for their comments and suggestions which led to several improvements.
References [1] Abrial, J.-R.: The B-Book: Assigning Programs to Meanings, Cambridge University Press, 1996. [2] Backhouse, R.C., P.J. de Bruin, P. Hoogendijk, G. Malcolm, E. Voermans, J. van der Woude: A Relational Theory of Data Types. Dept. of Math. and Comp. Sc., Eindhoven University of Technology, The Netherlands, 1992. [3] Backhouse, R.C., J. van der Woude: Demonic Operators and Monotype Factors. Mathematical Structures in Computer Science 3(4) (1993) 417–433. [4] Berghammer, R., G. Schmidt: Relational Specifications. In XXXVIII Banach Center Semesters on Algebraic Methods in Logic and their Computer Science Applications, C. Rauszer, ed., 1993, 167–190. [5] Berzins, V.: Software Merge: Semantics of Combining Changes to Programs. ACM Transactions on Programming Languages and Systems 16(6) (1994) 1875–1903. [6] DaSilva, C., B. Dehbonci, F. Mejia: Formal Specification in Industrial Applications: Subway Speed Control System. In Formal Description Techniques V, M. Diaz, R. Groz, eds, Elsevier, 1993, 199–213. [7] J. Desharnais, A. Jaoua, F. Mili, N. Boudriga, A. Mili: A Relational Division Operator: The Conjugate Kernel. Theoretical Computer Science 114 (1993) 247–272. [8] Desharnais, J. et al: Embedding a Demonic Semilattice in a Relation Algebra. Theoretical Computer Science 149 (1995) 333–360. [9] Dijkstra, R.M.: Relational Calculus and Relational Program Semantics. Computing Science Reports CS-R9408, Department of Computing Science, University of Groningen, 1994. [10] Frappier, M., A. Mili, J. Desharnais: A Relational Calculus for Program Construction by Parts. Science of Computer Programming 26 (1996) 237–254. [11] Frappier, M.: A Relational Basis for Program Construction by Parts. Ph.D. Thesis, Dept. of Computer Science, University of Ottawa, Canada, 1995.
340 Unifying Program Construction and Modification [12] Gardiner, P., C.C. Morgan: Data Refinement of Predicate Transformers. Theoretical Computer Science 87 (1991) 143–162. [13] Hehner, E.C.R.: A Practical Theory of Programming. Springer Verlag, 1993. [14] Hoare, C.A.R., I.J. Hayes, H. Jifeng, C.C. Morgan, A.W. Roscoe, J.W. Sanders, I.H. Sorenson, J.M. Spivey, B.A. Sufrin: Laws of Programming. Communications of the ACM 30(8) (1987) 672–686. [15] Jones, G., M. Sheeran: Designing Arithmetic Circuits by Refinement in Ruby. In Mathematics of program construction : second international conference, R.S. Bird, C.C. Morgan and J.C.P. Woodcock, eds, Oxford, 1992, Lecture Notes in Computer Science 669, Springer-Verlag, 1993. [16] Leino, K.R.M., R. Manohar: Joining Specification Statements. Report RVM23c-1, Digital’s System Research Center, Palo Alto, CA, USA, 1995. [17] Mili, F., A. Mili: Heuristics for Constructing While Loops. Science of Computer Programming 18 (1992) 67–106. [18] M¨ oller, B.: Relations as a Program Development Language. In Constructing Programs from Specifications, B. M¨ oller, ed., Proc. IFIP TC 2/WG 2.1 Pacific Grove, CA, USA, May 13–16, North-Holland (1991) 373–397. [19] Schmidt, G., T. Str¨ ohlein: Relations and Graphs. Springer-Verlag, 1993. [20] Von Wright, J.: A Lattice Theoretical Basis for Program Refinement. Ph.D. Thesis, Dept. of ˙ Computer Science, Abo Akademi, Finland, 1990. [21] Yang, W., S. Horwitz, T. Reps.: A Program Integration Algorithm that Accomodates SemanticsPreserving Transformations. ACM Transactions on Software Engineering and Methodology 1(3) (1992) 310–354.
Received 15 February 1996