Formal Development of Correct Classes in Computational Logic

Quality software must be reusable, extensible and reliable. In computational logic, we have developed an approach to constructing programs that are formally correct. Our approach can provide a basis for constructing software that is (formally) reusable and extensible, and not just reliable but formally correct. In this paper, we explain our notion of correct classes, and how to develop them.


Introduction
Quality software must be reusable, extensible (or maintainable), and reliable.Object-oriented programming is seen as a suitable programming paradigm for constructing such software.It achieves reusability and extensibility by the use of classes (of objects) with inheritance.Reliability can be gained by verifying assertions which correspond to invariants on classes and pre-post-conditions on their methods.
In computational logic, we have developed an approach to constructing programs that are formally correct (wrt their specifications).Our approach is declarative in the sense that both specifications and programs have declarative (logical) semantics.So we do not have classes of objects with internal states.However, we have classes that are parameterised modules, i.e. generic classes.In addition, we can define and reason about the correctness and reusability of methods (programs) as well as classes.Thus our approach can provide a basis for constructing software that is (formally) reusable and extensible, and not just reliable but formally correct.In this paper, we explain our notion of correct classes, and how to develop them.
For lack of space, we shall assume some familiarity with basic logic programming terminology, as in e.g.[10].

Overview of Our Approach to Logic Program Synthesis
Our approach to program synthesis in computational logic has the following key components (more details can be found in [6,8]): Part of this work was done during the first author's visit to Computing Science Department, Uppsala University, Sweden, supported by the European Union HCM project on Logic Program Synthesis and Transformation, contract no.93/414.He wishes to thank Jonas Barklund for his invitation and hospitality.
A (full) first-order theory that axiomatises the problem domain, called a framework F. F has a model-theoretic semantics, i.e. it has an intended model I. (We will discuss frameworks in Section 3.) Two kinds of specifications: -explicit specifications of new relations and functions in F (see Example 3.1); -partial specifications of relations for synthesis purposes only (see Example 4.10).
These specifications are first-order formulas, and they also have a model-theoretic semantics, i.e. they are interpreted in the intended model I of F. An explicit specification has a unique interpretation, whereas a partial specification has many possible interpretations.The former is used to add new symbols to F, as well as for synthesis of course; whilst the latter is more flexible for synthesis purposes, but it may not be used to introduce new symbols in F. Correctness criteria for programs wrt their specifications, i.e. specifications of the relations they compute, in F. These criteria are also model-theoretic.In a framework F, a logic program P (that computes a specified relation r) has an intended model, viz.its minimum Herbrand model H; and we say P is correct wrt an explicit specification S (of r) iff the interpretation of r in the intended model H of P coincides with (or is at least isomorphic to) its interpretation in the intended model I of F.
If S is a partial specification, then r's interpretation in H must coincide with one of its interpretations in I.
Of course for proving correctness, we use proof-theoretic versions of these correctness criteria.
A synthesis process that employs synthesis methods to derive correct programs from their specifications.(A survey of such methods can be found in [1].)Typically an explicit specification of a new relation in F takes the form: 1

(r(x) $ R(x))
where R(x) is a formula of the language of F. The synthesis process employs some synthesis method to iteratively generate a (possibly infinite) sequence of programs where, for every P j , there is a corresponding set S j of specifications of the new relation symbols of P j .The synthesis method must ensure that each P j is partially correct, i.e.: F S j `Comp + (P j ) where C omp + is (logically equivalent to) the if -part of the completion C omp(P) of P, and that P j terminates.The synthesis process halts successfully, when P j becomes totally correct, i.e.: F S j `Comp(P j ) and that P j terminates. 2 Note that we shall use C omp ?(P) to denote the only-if -part of C omp(P).Note also that since partial correctness is guaranteed in each synthesis step, total correctness can be proved in a synthesis step if F S j `Comp ?(P j ) This provides a useful criterion for determining when to halt the synthesis process with a totally correct program.
To illustrate our approach, here is a very simple example in NAT , the framework of Peano arithmetic (which is defined in Example 3.1): 1 8(F ) denotes F's universal closure. 2 Our current synthesis process does not guarantee termination of P j .

BCS-FACS Northern Formal Methods Workshop, 1996
Example 2.1 Consider the specification S prod : 8 (prod(x; y; z) $ x y = z) A synthesis process (using a completely manual synthesis method) would be the following: 1. Synthesise a clause for prod(x; 0; z).In NAT S prod we can prove: prod(x; 0; z) $ x 0 = z $ z = 0 Thus NAT S prod `Comp + (prod(x; 0; z) z = 0) and we get the program P 1 : prod(x; 0; 0) 2. Next synthesise a clause for prod(x; s(y); z).In NAT S prod we can prove: prod(x; s(y); z) $ x s(y) = z $ x y + x = z $ 9w (prod(x; y; w) ^w + x = z) From this we could synthesise the clause prod(x; s(y); z) prod(x; y; w); w + x = z.The key result of our work so far is that our approach extends to open, or parameterised, frameworks: in such frameworks we can synthesise programs that are steadfast, i.e. open programs that are always totally correct whenever their parameters are instantiated correctly.We will elaborate on this in Section 4.2.Steadfastness thus provides a basis for modularity, reusability, as well as formal correctness.

Parameterised Modules as Generic Classes
As we have just seen, in our approach to logic program synthesis, correct programs are developed in the context of a framework F which is a first-order theory.The use of F marks the main difference between our approach and others.F not only provides an unambiguous underpinning of the semantics of specifications and programs (and hence the latter's correctness wrt the former), but, as we will show in this section, F itself can also be an integral part of a parameterised module, or a generic class in object-oriented terminology, that can be used for modular program development.
We define a parameterised module as follows: F is a full first-order logical theory.Specifications are certain kinds of formulas in the language of F. Programs are either standard or constraint logic programs that have been synthesised from their specifications in F.
A parameterised module M can be visualised as follows:3 Framework:-F : ( Program:prog 1 : The outer box denotes the framework F, while the inner boxes denote logic programs that have been synthesised in F. A framework F basically axiomatises a problem domain, and typically contains ADT's as well as other properties (e.g.theorems) that hold in the problem domain.F may be open or parameterised, i.e. it may contain parameters , and it defines a set of symbols in terms of .
are called framework parameters.These parameters may be instantiated by sort, function or relation symbols that have already been defined elsewhere (in another framework).In each program prog i , i stands for the set of symbols that are defined in prog i (i.e. they appear in the clause heads of prog i ) in terms of the parameters i .i are called program parameters.Program parameters may be just any relation symbols in F that are not yet (completely) defined, or of course they may be relation symbols from .
To be more precise, a closed framework F contains a (many-sorted) signature of An open framework F with parameters will contain in addition: parameter axioms, that state assumptions about the framework parameters .
Frameworks are usually constructed incrementally, possibly by using previously defined frameworks.Typically a framework F axiomatises a new abstract data type T by making use of, or importing, pre-defined types.The signature of F contains the old sorts and a sort symbol for the new data type T. The type T is constructed from constructors, which are declared as functions.The axioms of the pre-defined data types are imported into F, and new axioms are added to define new functions and relations on T.  x y ^y x $ x = y; x y ^y z !x z where NAT is the following framework for Peano arithmetic: Framework NAT ; SORTS: N at; FUNCTIONS: 0 : !N at; s : N at ! N at; +; : (N at; N at) !N at; In LIST , external universal quantifiers have been omitted, variables of sort Elem are in lower-case, and variables of sort List are in upper-case.LIST is essentially the standard axiomatisation of lists.It makes use of, i.e. it imports, the (closed) framework NAT for Peano arithmetic.The function nocc(a; L) gives the number of occurrences of a in L, and the relation elemi(L; i; a) means a occurs at position i in L. The p-axioms are the parameter axioms.In this case, the p-axioms state that must be a partial ordering.
Here we have given only part of the complete axiomatisation of LIST .Other relations and functions can be defined in terms of symbols already defined here.For example, we can define the usual relations len; concat; perm; and ord, Formal Development of Correct Classes in Computational Logic for length, concatenation, permutation, and ordered respectively, as well as the length and catenation functions l and j as follows: $ len(L; n) concat(A; B; L) $ 8i; a (i < l(A) !(elemi(A; i; a) $ elemi(L; i; a))) $ 8i(elemi(L; i; e 1 ) ^elemi(L; s(i); e 2 ) ! e 1 e 2 ) (2) Note also that the last axiom in NAT is an induction schema.This is useful for reasoning about properties of + and which cannot be derived from the other axioms, e.g.associativity and commutativity.In LIST , we can also use induction on lists.This illustrates the fact that in a framework we may have more than just ADT definitions.
The syntax of a framework is thus similar to that of an algebraic ADT (e.g.[3,16]).However, whereas an algebraic ADT is an initial model of its specification, the intended model of a closed framework is an isoinitial model, and an open framework has a class of isoinitial models.Definition 3.2 An isoinitial model I of F is a reachable model, i.e. a model where each element (of the domain) can be represented by a ground term, such that for any relation r defined in F, ground instances r(t) or :r(t) are true in I iff they are true in all models of F.
Like initial semantics (e.g.[3]), isoinitial semantics also guarantees 'no junk' and 'no confusion', but has the additional capability to handle negation, which is important in database applications.

Example 3.2
The isoinitial model of the closed framework LIST (Int; <), i.e. the framework LIST (Elem; ) with the parameters Elem and instantiated to the integer type I nt and < respectively, is the usual list structure (viz.the term model generated by the constructors and nil of List) for integers, with the ordering <. 5Now a parameterised module can be regarded as a generic class of ADT's.As illustrated in Figure 1 contains ADT's as well as programs or methods that work on these ADT's, and is therefore a generic class in objectoriented terminology (e.g.[15,12]).(It is, however, not a class of objects with internal states.)However, in contrast to classes in object-oriented programming, which usually have a type-theoretic characterisation, our classes have a model-theoretic semantics.Furthermore, in a class M, the programs also have intended models, viz.their minimum Herbrand models.Therefore, we can define program correctness in a model-theoretic manner in a class.As a result, we can use model-theoretic semantics to reason about the correctness of classes.

Correct Classes
Reasoning about the correctness of a parameterised module M has to be done at two levels: framework and program levels.M can be composed with other modules, to yield instances of M containing instances of the framework F and the programs prog i .In each instance of M, at the framework level, F is composed with another framework that defines ; whilst at the program level, each program prog i (and its specification spec i ) inherits the new .Correctness of M means the consistency of (each instance of) F, and the correctness of (each instance of) each prog i wrt its specification spec i in (each instance of) F, i.e. the consistency of F and the correctness of each prog i in each instance of M.
We will use only parameterised modules that are correct in this sense, and we will show how to construct such modules.Definition 4.1 A correct parameterised module consists of: 6   an adequate framework F with parameters ; steadfast (logic) programs prog 1 , prog 2 , with parameters 1 ; 2 ; : : : We will define adequate frameworks and steadfast programs more formally in Sections 4.1 and 4.2 respectively.For the moment, informally, an adequate framework F is one that remains consistent and a steadfast program one that remains correct in each instance of M.
As we will show later, this module is correct because the framework LIST is adequate (see Section 4.1), and the programs ms and ps, as well as others which we cannot list here but will see later, are steadfast (see Section 4.2).

Adequate Frameworks
An adequate framework F is one for which a(n intended) model always exists.Adequacy can be achieved by making sure that if F is closed, then F has an isoinitial model; and if F is open, then every closed instance of F has an isoinitial model.We shall discuss adequate closed frameworks first. 6Again we omit spec i for brevity.In general, the existence of an isoinitial model is of course not guaranteed.However, if a framework F has a reachable model I, then it can be shown that I is an isoinitial model of F if and only if every closed atomic formula A (in the language of F) is decided by F, i.e. either F `A or F `:A.This is a useful existence condition for isoinitial models.Furthermore, it can be shown that if F is a (possibly infinite) recursively enumerable axiomatisation, then there exists an isoinitial model in which relation symbols are interpreted by decidable relations, and function symbols are interpreted by total computable functions.Indeed, we only ever use such frameworks, with (computable) isoinitial models.

BCS-FACS
To construct such a framework F n for axiomatising a type T, we proceed incrementally.We start with a small framework F 0 with an obvious isoinitial model I 0 .For instance, if the freeness axioms ( [14]) hold in T, then we use as F 0 the framework consisting of just the constructor symbols in F n together with their freeness axioms.The term model generated by the constructors is of course just the set of ground terms of T. It is an isoinitial model of their freeness axioms, i.e. it is an isoinitial model of F 0 .
Then we successively expand F i into F i+1 by adding new function and relation symbols, together with their axioms, in such a way that I i can be expanded into an isoinitial model I i+1 of F i+1 .
For example, the closed framework LIST (Int; <) can be constructed in this way from the term model generated by constructors and nil of List, which is in turn constructed from the term model generated by the constructors 0 (zero) and s (successor) of NAT .
Framework expansions by definitions of new symbols that preserve isoinitiality in this way are called adequate expansions, and such definitions are also said to be adequate.So we say a framework is adequate if it is constructed only from adequate expansions.A useful criterion for the adequacy of an expansion is the existence of a steadfast program to compute the relation defined by the expansion (see [5]).Thus program synthesis itself provides a means of adequately expanding a framework.1) and F 2 ( 2 ) with signatures 1 and 2 .The composition of F 1 with F 2 is performed through a 1 -renaming .The composite framework is denoted by F 1 ; F 2 ]. ( 1) is a 1 -renaming for 1 and 2 if for every used in 1 , ( ) belongs to 2 , whilst the sort symbols and declarations not used in 1 are mapped into names that do not occur in 2 .
F 1 ; F 2 ] is defined if the p-axioms of F 1 become axioms or theorems of F 2 ,7 and in this case, in F 1 ; F 2 ]: the parameters are the (possible) ones of F 2 ; the signature is ( 1 ) 2 ; the axioms and theorems are the unions of those in F 1 and F 2 .
Our definition of composition essentially coincides with that of institutions [2].However, the theory of institutions is not useful for our purposes, since it does not deal with the problem of preserving consistency.8 Example 4.3 In our approach, framework composition is effected via parameter instantiation.For example, the closed instance LIST (Int; <) of the framework LIST (Elem; ) is the composition of the latter with the framework that defines the integer type I nt with the total ordering <.If K is closed, then f ree(K) is an adequate closed framework, and the structure freely generated by K is an isoinitial model of f ree(K).
If K contains open sorts s 1 ; : : : ; s n , then f ree(K(s 1 ; : : : ; s n )) is an adequate open framework.The (open) framework F( ) consisting of the signature of a specification r(x) $ R(x), where R(x) is a quantifier-free formula that does not contain r; the axiom 8x (r(x) $ R(x)) where is the signature of R(x) (i.e.does not contain r), is an adequate open framework.

Example 4.7 (Logic programs)
Let P be a closed logic program that terminates for every ground atomic goal A. Then the theory T = f ree(P) Ocomp(P ) where f ree(P) is the set of freeness axioms for the constant and function symbols of P, and Ocomp(P ) is the set of completed definitions of the predicates defined by P, is an adequate closed framework, and the minimum Herbrand BCS-FACS Northern Formal Methods Workshop, 1996

Steadfast Programs
In a (parameterised) module M, an open program is steadfast iff it is correct wrt its specification in all instances of M.
Thus steadfastness means 'correct reusability', i.e. a steadfast program is a correctly reusable unit in all instances of M.
Typically, in our approach, from a given specification in a module M we would synthesise a hierarchy of interrelated steadfast programs.The programs in this hierarchy can be composed with each other to form any desired collection of steadfast programs.Then in any instance of M, we have an instance of the same hierarchy of steadfast programs, which can be composed in different combinations.
Correct reusability of steadfast programs means a priori correctness of their composition.This is a very important feature of steadfastness, and contrasts favourably with a posteriori correctness normally employed in verification-based algebraic approaches to program construction.In an open framework F( ), the meaning of the defined symbols is characterised in terms of the parameters .
Since the latter are supplied by a closed framework, steadfastness can be defined as follows (a more abstract, modeltheoretic characterisation, can be found in [9]): Definition 4.6 Let F( ) be an open framework, and P : ( be an open program.P is steadfast in F( ) iff it is steadfast in every closed instance F( ) C, where C is a closed framework.This means that P : ( is (closed and) correct wrt to its specification whenever F( ) becomes closed, and correct closed programs for computing are supplied.In other words, an open program is steadfast iff its clauses that define symbols in are all correct, assuming that the clauses or programs for are all correct.
Note that programs for computing framework parameters can be supplied only after the instantiation F( ) C, while those for the program parameters can be supplied either before or after such an instantiation.We can show that they are steadfast in LIST (Elem; ) by showing that ms and ps define correct clauses for sorting based on merging and partitioning, assuming correct clauses for split and merge, and for P and concat, respectively.
To synthesise a steadfast program P : ( in an open framework, we can employ the same synthesis process that is exemplified in Example 2.1.The criterion for halting synthesis successfully (with a steadfast P) is also the same, except that we need only consider predicate symbols in : BCS-FACS Northern Formal Methods Workshop, 1996 For every predicate p 2 in the current program P j : (i) if F S j `:Comp ?(P j ), search for other clauses with p in their head; (ii) if F S j `Comp ?(P j ), do not search for any more clauses defining p.
If (ii) holds for every defined predicate p of P j , then synthesis successfully halts, and P j is steadfast.Now we will show a hierarchy of steadfast programs that can be synthesised in an open framework in a module M, to illustrate how steadfast programs can be used as correct program units in M and all its instances.
Example 4.10 In the framework LIST (Elem; ), from the specification sort(x; y) $ perm(x; y) ^ord(y) (where perm and ord are as defined in ( 2)) we can derive different steadfast programs Ps, and from these programs we can in turn derive different (steadfast) programs to compute the parameters of Ps.Thus we can synthesise a hierarchy of (steadfast) sorting programs in a modular way.(Note that in the p-axioms we require that is a partial (not necessarily total) ordering.This means that sort(x; y) is a partial map from x to y.Indeed, a sorted y exists only for those x whose elements are totally ordered by .The programs that we exhibit below are steadfast even in this weaker situation, and they behave as the usual sorting programs in the case where is total.)For example, we can synthesise the steadfast program (4) in Example 4.1 for merge sort, where the program parameters split and merge can be defined by the partial specification: split max (x; i; j) $ (perm(x; ijj) ^i x ^j x) 8x; y; a9i; j split(x:y:a; i; j) ^8x; i; j (split(x; i; j) !split max (x; i; j)) ord(x) ^ord(y) !(merge(x; y; z) $ ord(z) ^perm(xjy; z)): where is the well-founded relation x y $ l(x) 1 _ l(x) < l(y).Now (7), like any partial specification, allows many possible interpretations.(Intuitively (7) reflects a design decision to split the input list, then sort the sublists and merge the sorted sublists.)Leaving split and merge open, we can prove that the program (4) is steadfast (in LIST (Elem; )) wrt the specification (6), that is, it is correct in every closed instance of LIST (Elem; ), i.e. for any element type Elem and any (total) ordering relation , whenever merge and split compute relations that satisfy the partial specification (7).Thus it can be composed with different programs for merge and split to yield different sorting programs based on merging.For instance, consider the (adequate) explicit definition split1(x; i; j) $ 9a; A (x = a:A ^i = a:nil ^j = A ^split max (a:A; a:nil; A)) Now split1 satisfies (7), and we can derive the (trivial) closed program: Program:-split1 : split split(a:A; a:nil; A) Composing the programs ms and split1 (and simplifying) will give the following steadfast program for insertion sort: Program:insertion sort : sort ( merge sort(nil; nil) sort(x:A; W) sort(A; V ) ^m erge(x:nil; V; W) Alternatively, from the top-level specification (6), we can synthesise the steadfast program (5) for partition sort, where p is a partition relation partially specified by: p max (X; I; J; K) $ perm(X; IjJjK) ^less(I; J) ^less(J; K)Î X ^J X ^K X; 8x; X 9I; J; K(p(x:X; I; J; K) ^8X; I; J; K(p(X; I; J; K) !p max (X; I; J; K)

Conclusion
We have presented a notion of a correct class and its formal development in computational logic.A class is a parameterised module M consisting of a full first-order theory, or a framework F, and logic programs prog i that are specified and derived in F. The correctness of a class is defined as the adequacy of F and the correctness of prog i in all instances of M. We have discussed the notions of adequate frameworks and steadfast programs, and shown that such frameworks and programs make up correct class.This notion of class is different from that of a module in the algebraic approach in that the latter is usually a structure or a sub-program, whereas in our approach, a class includes a framework and many programs.The presence of the framework allows us to define not only the correctness of the class, i.e. adequacy of the framework and steadfastness of the programs in the framework, but also the correctness of class compositions or instances.Moreover, both notions of correctness are a priori correctness because of adequacy and steadfastness, in contrast to the a posteriori correctness that is usually established by verification in the algebraic approach.
Compared to classes in object-oriented programming, our class also has the advantage of correctness, as shown in Figure 2.However, our class is a class of polymorphic ADT's, rather than a class of state-based objects as in objectoriented programming.To be more precise, our class can be depicted in Figure 3, which is a refinement of Figure 1 in Section 3. The kind of polymorphism in the ADT here is parametric polymorphism, as opposed to inheritance ) that is the basis of inheritance in object-oriented programming.
Thus our class is a semantic characterisation of a generic class in object-oriented programming, with the additional property of correctness, but without the 'efficiency' of state-based objects or the flexibility of sub-type inheritance.It would be interesting to study how the advantages of both approaches could be combined, perhaps through the vehicle of object-oriented logic programming languages such as [11,13].
sort symbols; -function declarations, for declaring constant and function symbols; -relation declarations, for declaring relation symbols; a set of first-order axioms for the declared function and relation symbols, possibly containing induction schemas; a set of theorems, i.e. proven properties of the problem domain.For example, in Example 3.1, C omp(sum; P 4 ) and C omp(prod; P 4 ) are theorems, and to prove them we have (implicitly) used well-known theorems of Peano arithmetic.

Figure 1 :
Figure 1: Parameterised modules as generic classes

Example 4 . 1
We can show that the following module is correct: Framework:-LI S T (Elem; ) Program:ms : sort ( merge; split merge sort program Program:ps : sort ( p; concat partition sort program (3) where LIST (Elem; ) is the (open) list framework of Example 3.1, and the programs are sorting programs derived from a specification of list sorting.For example, the program ms for merge sort is the following:Program:ms : sort ( merge; split sort(nil; nil) sort(x:nil; x:nil) sort(x:y:A; W) split(x:y:A; I; J) ^s ort(I; U) ^s ort(J; V )m erge(U; V; W)

Definition 4 . 3
To extend this discussion to open frameworks, we need to address closed instances of an open framework F, i.e. compositions of F with closed frameworks C's that are closed frameworks themselves.So we will now briefly define framework composition in general, i.e. between open frameworks.Consider two (open) frameworks F 1 (

Example 4 . 4 (
Term models) Consider a set K of constant and function symbols.K may be open or closed, depending on whether it contains open sort symbols or not.(A sort s is open (wrt K) iff no declaration of the form f :a!s belongs to K.)

Example 4 . 5 (
Explicit function definitions) The (open) framework F( ) consisting of the signature containing -sort symbols a and b; -function declaration f : a !b; -relation declaration r : (a; b); the axioms 8x r(x; f(x)) and 8x9!y r(x; y) where = fr; a; bg, is an adequate open framework.

Example 4 . 6 (
Explicit relation definitions) model of P is an isoinitial model of T .Using the above results, we can construct adequate (closed and open) frameworks incrementally.We can also show that the framework LIST (Elem; ) in Example 4.1 (defined in Example 3.1) is an adequate open framework.

Example 4 . 9
The programs ms (4) and ps (5) in Example 4.1 are examples of open programs in an open framework.

Figure 2 :
Figure 2: Correct parameterised modules as correct classes

Figure 3 :
Figure 3: Generic classes Now P 2 is not totally correct: we can prove C omp ?(prod; P 2 ) (i.e. the only-if part of the completed definition of prod wrt P 2 ), but not C omp ?(sum; P 2 ).This means that we can stop synthesis for prod, but not for sum.
The following open framework axiomatises the theory of lists with parametric element type Elem and partial ordering relation :4 Example 3.1 Framework LIST (Elem; ); AXIOMS: For example, the closed framework LIST (Int; <) in Example 3.2 is adequate since it has a reachable isoinitial model.
Northern Formal Methods Workshop, 1996 Definition 4.2 A closed framework is adequate iff it has a reachable isoinitial model.Example 4.2 An open framework F( ) is adequate iff, for every closed framework C, if F ; C] is defined, then F ; C] has a reachable isoinitial model I, i.e. it is closed, and the reduct Ij is an isoinitial model of C. If F 1 ( 1 ) and F 2 ( 2 ) are adequate, and F 1 ; F 2 ] is defined, then F 1 ; F 2 ] is adequate.
Now we define steadfastness.Note that since a program may have (program) parameters that are distinct from the framework parameters, open programs arise in both closed and open frameworks.In a closed framework C, steadfastness can be defined as follows: Definition 4.5 The (open) program P : 1 ( 1 is steadfast in C iff, for every correct (closed) program fQ : 2 (g for computing 2 , with 2 1 and 2 \ 1 = ;, fP Q : 1 2 (g is a correct program for computing 1 2 .Thus programs that are steadfast within a closed framework behave like correct units that can be composed in a correct way.In NAT , from the specification S prod in Example 2.1 we can derive the open program oprod (which is just P 2 (1) in Example 2.1 of course): The program oprod is open, since it does not contain clauses for computing the parameter sum.Therefore, it cannot be used for computing.However, it is steadfast in NAT .This means that, for every (closed) program sum for computing sum, if sum is correct (in NAT ), then fprod sumg is a (closed) correct program for computing prod. in Example 2.1 we could stop synthesis for prod after Step 2 and get the open steadfast program oprod.