Constructing Provably Correct Logic Programs 1

0 downloads 0 Views 320KB Size Report
conditions required of it as follows: hf establishes a bijection between .... Intuitively, lifting of computations means that an enhancement interleaves its compu- ... Before attempting to answer this question, a problem needs to be highlighted.
Constructing Provably Correct Logic Programs Ashish Jain, Marc Kirschenbaumy, and Leon Sterling Department of Computer Engineering and Science Case Western Reserve University Cleveland, Ohio, 44106, USA. email: fjain,[email protected]

Abstract

This paper demonstrates a process of constructing logic programs whereby logic programs can be proved correct with respect to speci cations. Building on previous work on stepwise enhancement and program maps, we introduce program enhancement structures which capture the application of standard programming techniques to well understood programs. We give an overview of our views on correctness, followed by a detailed proof of correctness which uses the program enhancement structure.

1 Motivation The software crisis for procedural languages was precipitated by the failure of the prevailing ad-hoc attitude towards programming to scale to larger programming projects. One response to the software crisis was structured programming. The programmer would be trained to use well-de ned programming constructs, and encouraged to take a disciplined approach. Ideally, a `science of programming' would be developed where correctness theorems could be proved about programs. This paper concerns an approach to systematize logic programming which can be viewed as an analog to structured programming in procedural languages. The programmer is given a collection of operations to construct complicated programs. Behavior of the complicated program can be inferred from the structure of the program and the behavior of the simpler pieces. Proofs of correctness can be leveraged from the construction. In our classroom experience, we are convinced that our approach signi cantly shortens the time it takes students to become competent Prolog programmers. The emphasis of this paper is not, however, on our approach to logic programming. Rather we are concerned with demonstrating a process of programming where programs can be proved correct with respect to speci cations. This paper builds on our previously published theory of program maps [3]. This paper is organized as follows. Section 2 presents program maps for logic programs, y

Mathematics and Computer Science Department, John Carroll University, Cleveland, OH, 44118. email:

[email protected].

1

with improved notation from the theory given in [3]. Section 3 presents an algorithm for composing logic programs. Section 4 describes the process of software development by stepwise enhancement and presents program enhancement structures { a high level representation of program development by stepwise enhancement. Section 5 discusses speci cations of logic programs and a notion of when a program is correct with respect to its speci cation. In Section 6, we give two example constructions and demonstrate usefulness of their respective program enhancement structures in establishing their correctness.

2 Program Maps for Logic Programs Intuitively, a program map relates the syntactic structures of programs. A preliminary version of the theory of program maps for logic programs was presented in [6] and a more complete version in [3]. We assume familiarity with basic terminology of rst order logic. [1] is a good reference for the review of terminology.

De nition 2.1 A de nite logic program P with an underlying language LP of a formal

rst-order theory is represented as the quadruple P = (VP ; FP ; PP ; CP ) where VP is a denumerable set of variables, FP is a nite set of function symbols, PP is a nite set of predicate symbols, and CP is a nite set of de nite Horn clauses with variables, function and predicate symbols appearing only from VP , FP and PP respectively. Constants are treated as function symbols of arity 0.

De nition 2.2 A projection sequence from m to n elements, denoted Sm;n, is a sequence of integers  x1 , x2, : : : , xn  where m  0, n  0, each xi is distinct, and each xi 2 f1; 2; : : :; mg. De nition 2.3 Given a projection sequence Sm;n =  x1, x2, : : : , xn  the projection Sm;n for any m-tuple y1 ; y2 ; : : :; ym , denoted Sm;n (y1 ; y2; : : :; ym ), is yx1 ; yx2 ; : : :; yxn .

De nition 2.4 Given a programz P , P  is the program represented by the quadruple (VP ; FP [ f g; PP [ f>g; CP ) where  and > are special function and predicate symbols of arity 0 not already present in FP and PP respectively.

De nition 2.5 Given programs P and Q, a mapping hf : FP ! FQ , a mapping hp : p associated with each p 2 PP where m is the PP ! PQ , and a projection sequence Sm;n arity of p and n is the arity of hp (p), a mapping h : LP ! LQ can be induced as follows: z

In this work, program refers to a de nite logic program.

2

for any variable x in LP , h(x) = x. for any term f (t1 ; : : :; tn ) in LP , if hf (f ) 6=  then h(f (t1 ; : : :; tn )) = hf (f )(h(t1); : : :; h(tn )) else h(f (t1 ; : : :; tn )) =  p (h(t1 ); : : :; h(tm )), for any atomic w p(t1 ; : : :; tm ) in LP , h(p(t1 ; : : :; tm )) = hp (p)Sm;n where m is arity of p and n is arity of hf (p). for any two w s A and B in LP , h(A; B) = h(A); h(B) for any two w s A and B in LP , h(A:{ B) = h(A):{ h(B)

> is a special symbol denoting an \empty" w . The \clean-up" operation, del>, de ned

in De nition 2.6 makes the notion of empty w more precise.

De nition 2.6 Given a program P , for any w A in LP  , del>(A) is the w obtained from A by deleting all the >s. De nition 2.7 Given programs P and Q, a mapping h : LP ! LQ is a program map if

the following holds: if FP = ff j f 2 FP ^ hf (f ) =  g then hf establishes a bijective map between FP n FP and FQ , if TP = fp j p 2 PP ^ hp (p) = >g then hp establishes a bijective map between PP n TP and PQ , and if CP = fC j C 2 CP and the head of C gets mapped to >g then h induces an onto mapping from CP n CP to CQ. Note that h(C 0), C 0 2 CP n CP , may not be a syntactically identical clause in CQ but could be a variant; that is, identical up to variable renaming. We give a simple example of program map.

Example 2.1 List::

Length::

list([ ]).

length([ ],0).

list([X|Xs]):-

length([X|Xs],s(N)):-

list(Xs).

length(Xs,N).

De ne the program map h : LLength ! LList as follows: 1. F = f0; sg. hf ([]) = [] and hf (j) = j. 2. T = ;. hp (length) = list and S2length ;1 = 1 . 3

3. C = ;. The onto mapping induced by h from CLength n C to CList is given by:

del>(h(length([ ]; 0))) = list([ ]) and del>(h(length([XjXs]; s(N)):- length(Xs; N))) = list([XjXs]):-

list(Xs).

The map h : LLength ! LList given above is a program map because it meets all the conditions required of it as follows: hf establishes a bijection between FLength nF and FList , hp establishes a bijection between FLength n T and FList , and h induces an onto mapping from CLength n C to CList . In Example 2.2, there exists no program map from LLengtha to LList because in order to have an onto map between the clauses, a must get mapped to a variable; a violation of the program map's requirements.

Example 2.2 List::

Lengtha::

list([ ]).

length([ ],0).

list([X|Xs]):-

length([a|Xs],s(N)):-

list(Xs).

length(Xs,N).

De nition 2.8 The sequences:  (G0 = G), G1, : : :, Gn ,  C1, C2, : : : , Cn ,  1, 2, : : :, n , and  A1 , A2, : : :, An  denote a computation for a goal G in a program P i 8i; 1  i  n: Ai is a literal in the conjunct Gi?1 , Ci = C# for some C 2 CP , # is a substitution which renames all the variables of C to distinct, unused variables, and if Ci  (head:{ body) then i = mgu(head; Ai) and Gi is obtained by removing the literal Ai from Gi?1 (denoted Gi?1 n Ai ), adding body to Gi?1 n Ai (denoted body [ (Gi?1 n Ai )), and then applying i to body [ (Gi?1 n Ai ). n denotes the length of the computation . A computation of length n is a refutation if Gn = E x . A refutation R for a non-ground goal G would substitute values for some or all of the variables appearing in G. The substitution capturing the values assigned to the variables appearing in G is called the answer substitution which is de ned more formally in the following de nitions.

De nition 2.9 Given any term or w X , var(X ) denotes all the variables appearing in X . Given a substitution  = fx1=t1 , x2=t2 , : : : , xn =tn g, domain of , denoted domain(), S is fx1, x2 , : : : , xn g, and range of , denoted range(), is ni=1 var(ti ). x

E denotes an empty goal.

4

De nition 2.10 Given substitutions = fx1=t1, x2=t2, : : : , xn=tn g and = fy1=u1, y2 =u2, : : : , ym=um g, the composition of and , denoted : , is the set obtained from the set fx1=t1 , x2 =t2 , : : : , xn =tn , y1 =u1, y2 =u2 , : : : , ym =um g by (a) removing all the elements xi =ti , 1  i  n, where xi  ti , and (b) removing all the elements yi =ui, 1  i  m, where yi  xj , 1  j  n. De nition 2.11 Given a goal G and a refutation R for G in P whose sequence of mgu's is given by  1 ; 2; : : :; n , the answer substitution computed by R is the maximal substitution  such that   1 :2: : : :n and domain()  var(G). Independence of the computation rule is a well known result from the theory of logic programs which proves equivalence amongst refutations using di erent rules for selection of literals. We restate the result via Lemma 2.1 as future proofs refer to this result.

Lemma 2.1 (Independence of the computation rule) Given a refutation R for a goal G in program P which computes the answer substitution

, if we alter the selection of the literals (change the computation rule) then there would exist a refutation R1 for G using the new selection order and if 1 is the answer substitution computed by R1 then G and G1 are invariants (equal modulo variable renaming).

Proof: Proof can be found in both [1] and [5].

De nition 2.12 Given programs P and Q, a program map h : LP ! LQ , a computation W 0 in P denoted by the sequences:

G0; G1; : : :; Gn   C1; : : :; Cn   1 ; : : :; n   A1 ; : : :; An  is over a computation W in Q denoted by the sequences:  G0; G1; : : :; Gn   C1; C2; : : :; Cn   1 ; : : :; n   A1 ; : : :; An  if del> (h(G00)) = G0 and 8i; 1  i  n: del> (h(G0i)) = Gi, del> (h(Ci0)) = Ci, i  h(i0), and h(A0i) = Ai. Given programs P and Q, if a computation W 0 in P is over a computation W in Q then we say W lifts to W 0 . 0



0

0

0

0

,

0

0

,

0

0

, and ,

,

, and

De nition 2.13 Given programs P and Q, if there exists a program map h : LP ! LQ

then P is an enhancement of Q. It should be noted from the de nition of program maps that being an enhancement is a transitive relation; i.e, if P is an enhancement of Q, and Q is an enhancement of S then P is an enhancement of S . In Example 2.1, Length is an enhancement of List. The key idea behind the program map theory is to relate the computations of two programs. Existence of a program map, however, is not a sucient condition to relate the computations as shown by Example 2.3. 5

Example 2.3 List::

Length1::

list([ ]).

length([ ],0).

list([X|Xs]):-

length([X|Xs],s(N)):-

list(Xs).

length(Xs,9).

The program map h1 : LLength1 ! LList is identical to the program map h : LLength ! LList of Example 2.1 with the additional mapping hf (9) = . Though h1 is a program map from LLength1 to LList , the computations don't lift from List to Length1. The following is a speci c instance when a computation fails to lift. list([a]) list([])

E

length([a],s(N)) length([],9) ???

If we insist that all the clauses of an enhancement are such that all arguments which appear in the head of a clause and get projected out by the mapping are new variables then we can successfully relate the computations of such enhancements. De nition 2.14 de nes such forms of enhancements.

De nition 2.14 Given program P which is an enhancement of program Q with program map h : LP ! LQ , a clause head:{ body of P is in an acceptable form w.r.t. h i all the arguments which get projected out of head by the mapping h are distinct variables which appear only in the goals which get mapped to >. Given programs P and Q and a program map h : LP ! LQ , P is in an acceptable form w.r.t. h i all the clauses in CP n CP are in an acceptable form w.r.t. h. In Example 2.4, Length is an enhancement of List and is in an acceptable form.

Example 2.4 List::

Length ::

list([ ]).

length([ ],X1):- X1=0.

list([X|Xs]):-

length([X|Xs],X1):-

list(Xs).

length(Xs,N), X1=s(N).

Enhancements in acceptable form do indeed have their computations related to the computations of the skeleton programs. The following is the result from [3]: 6

Theorem 2.1 (Theorem for lifting of computations for de nite logic programs) Given programs P and Q, a program map h : LP ! LQ , P is in acceptable form w.r.t. h, a goal G in Q, and a goal G0 in P , if h(G0) = G then for every computation W for G in Q there exists a computation W 0 for G0 in P which is over W .

Since logic programs compute via refutations, given an enhancement P of Q, relating the refutations in Q to refutations in P is more useful in relating correctness of the two programs. The following de nition de nes extension, a stronger notion than enhancement, which relates refutations of two programs.

De nition 2.15 A computation in a program P denoted by the sequences:  G0, G1, : : :, Gn ,  C1, C2, : : :, Cn ,  1, 2 , : : :, n , and  A1, A2, : : :, An  extends the computation in the same program P given by the sequences:  G0 , G1, : : :, Gm ,  C1, C2, : : :, Cm ,  1, 2, : : :, m , and  A1, A2 , : : :, Am , if n > m. A program P is an extension of a program Q i P is an enhancement of Q and every refutation in Q lifts to a computation in P which can be extended to a refutation. Intuitively, lifting of computations means that an enhancement interleaves its computations around the control ow of the skeleton program. It can also be viewed as an enhancement inheriting context from the skeleton. By context we mean syntactic entities such as symbol names and argument positions. Given a program map h, the component maps hf and hp relate the context. The inherited context; i.e, the symbols related by the mapping might or might not have the same name in the enhancement. Very often, enhancements are produced by the application of program transformations to skeleton programs, and the names of the function symbols and variables appearing in the skeleton program are preserved in the enhancement. Such name preserving mappings are called normalized program mappings; more formally de ned by the following de nition.

De nition 2.16 Given a program map h : LP ! LQ , h is a normalized program map if: 1. 8f , f 2 FP n FP , hf (f ) = f , and 2. h induces a bijection from CP nCP to CQ with the additional requirement that h(C 0 ), C 0 2 CP n CP , is a clause in CQ, not just a variant of a clause in CQ. Given P as an enhancement of Q and jCP nCP j = jCQj, it is not dicult to see how one can transform P to P 0 by consistently renaming the variables and function symbols such that there exists a normalized program map from P 0 to Q. 7

Given program P which is an enhancement of program Q, a normalized program map h : LP ! LQ , and P is in acceptable form w.r.t h, the theorem for lifting of computations deals with inheriting of the computations by the enhancement. What can be said about the converse? That is, can we say that every computation in P lies over some computation in Q? Before attempting to answer this question, a problem needs to be highlighted. Given a computation W 0 in P , if the sequence of the literals selected in W 0 is  A1 ; A2; : : :; An  and if for some i, 1  i  n, h(Ai ) = > then what would be the corresponding ith step in Q? Clearly, there are syntactic ambiguities if we try to prove that all computations in P are over a computation in Q. We prove Lemma 2.2 which states that given goals g 0 and g such that h(g 0) = g , if any computation W 0 for g 0 in P is such that it never selects a literal which gets mapped to > then W 0 lies over a computation for g in Q.

Lemma 2.2 Given P is an enhancement of Q, normalized program map h : LP ! LQ ,

P is in acceptable form w.r.t. h, goal G00 in P and goal G0 in Q such that h(G00 ) = G0, a computation W 0 in P for G00 given by sequences:  G00 ; G01; : : :; G0n ,  C10 ; : : :; Cn0 ,  10 ; : : :; n0 , and  A01; : : :; A0n , if for any i, 1  i  n, h(A0i) 6= > then there exists a computation W for G0 in Q which lifts to W 0. Proof: Proof follows by induction on n.

Base Case: n = 0. Since h(G00) = G0,  G00  lies over  G0 . Induction Hypothesis: Assume true for n < m where m > 0. Induction Case: We prove the case when n = m. 1. Since h is a normalized program map, h(C10 ) is a clause, say C1, in program Q. 2. A01 is a literal from G00, h(A01 ) 6= >, and since h(G00) = G0, h(A01) is literal in G0. Let A1 = h(A01 ). 3. A01 uni es with the head of C10 with mgu i0 . Since all the non-projecting arguments in the head of C10 and A01 are inherited from the corresponding arguments of the head of C1 and A1 respectively, all the arguments which get projected out from the head of C10 are distinct new variables, and the variables appearing in the head of C10 are di erent from the variables appearing in A01 , the head of C1 and A1 unify with mgu 1 such that 1  10 . 8

4. G02 = ((G01 n A01 ) [ body 0)10 where body 0 is the body of C10 . We de ne G2 to be ((G1 n A1 ) [ body )1 where body is the body of clause C1. It follows from 1, 2, and 3 that h(G02) = G2. By induction hypothesis, it follows that there exists a computation W1 which lifts to the computation denoted by the sequences:  G01 ; G02; : : :; G0n ,  C20 ; : : :; Cn0 ,  20 ; : : :; n0 , and  A02; : : :; A0n . 5. Adding  G0 ,  C1 ,  1 , and  A1  in the front of the respective sequences of W1 gives a computation W in Q which lifts to W 0.

3 Composition of Enhancements Two separate enhancements of a common base program can be composed to produce a single program performing the combined task in one traversal. There is a correspondence between the literals and clauses of two enhancements of the same skeleton program. De nition 3.1 de nes the correspondence.

De nition 3.1 Let P and Q be enhancements of the skeleton program S with program maps hp and hq respectively. A literal lp in LP corresponds to a literal lq in LQ i hp (lp) = hq (lq ). A clause cp in CP corresponds to a clause cq in CQ i hp (cp) = hq (cq ).

Composition of two corresponding clauses is well de ned, but con ict in predicate and variable names between two clauses can lead to ambiguity. In order to deal with such con icting situations, we de ne the following:

De nition 3.2 Given enhancements P and Q of S with the program maps hp : LP ! S  and hq : LQ ! S  respectively, P and Q are orthogonal enhancements of S i : 1. hp and hq are normalized program maps, 2. TP and TQ are disjoint, and 3. the new variables introduced in P are di erent from the new variables introduced in Q. Given orthogonal enhancements P and Q of S , Figure 1 gives an algorithm for composing them into a program called P  Q=S . The composition operation was rst introduced in the 9

context of Prolog meta-interpreters in [8]. The algorithm as stated composes two orthogonal enhancements, but the process can be repeated to compose any nite sequence of orthogonal enhancements. Input: Program S and orthogonal enhancements P and Q of S . Output: The composed program P  Q=S . Algorithm: for each clause CS in S do: nd the corresponding clause, CP , in P ; nd the corresponding clause, CQ , in Q; construct a new clause CP Q such that the principal functor of the head of CP Q is the concatenation of the principal functors of the heads of CP and CQ , and the head of CP Q contains the arguments of the head of CS followed by the additional arguments of the head of CP followed by the additional arguments of the head of CQ ; for each goal LS in the body of CS do: nd the corresponding goal, LP , in CP ; add the goals preceding LP which do not correspond to any goal in the body of CS , and which have not been added already to the body of the new clause, CP Q ; nd the corresponding goal, LQ , in CQ ; add the goals preceding LQ which do not correspond to any goal in the body of CS , and which have not been added already to the body of the new clause, CP Q ; construct a new goal whose principal functor is the concatenation of the principal functors of the goals LP and LQ , and which contains the arguments of LS followed by the additional arguments of LP followed by the additional arguments of LQ , and add the new goal to the body of the new clause, CP Q ; add any remaining goals in CP which do not correspond to any goal in the body of CS , and which have not been added already to the body of the new clause, CP Q ; add the remaining goals in CQ which do not correspond to any goal in the body of CS , and which have not been added already to the body of the new clause, CP Q ; output clause CP Q ; output all clauses of P whose head gets mapped to >; output all clauses of Q whose head gets mapped to >;

Figure 1: An algorithm for composing two orthogonal enhancements of the same program. Lemma 3.1 If P and Q are two orthogonal enhancements of S , then P  Q=S is an enhancement of P .

Proof: Let hp be the program map from P to S and hq be the program map from Q to S . The mapping hpq from P  Q=S to P is de ned as follows: 1. If we denote the set fp  q jp 2 PP n TP ^ q 2 PQ n TQ ^ hp (p) = hq (q )g{ by S then it follows from the construction that PP Q=S = S [ TP [ TQ. 8x 2 TQ de ne hpqp (x) = >. 8x 2 TP de ne hpqp (x) = x. 8x 2 S de ne hpqp (x) = u where x  u  v . x = where m is x's arity. 8x 2 TP de ne S x = 1; 2; : : :; m  8x 2 TQ de ne Sm; 0 m;m where m is x's arity. 8x 2 S , the projection sequence is de ned as follows: {

We represent the concatenation operator by .

10

If x  u  v then let m, n, o, and s be the arities of x, u, v , and hpp (u) respectively. u , denoted by  y1 ; y2; : : :; ys , is Note that by construction, m = n + o ? s. Sn;s x , is de ned to be de ned by the program map hp . The projection sequence for x, Sm;n  w1; w2; : : :; wn  where each wi, 1  i  n, is de ned by the following algorithm: j 1; foreach i = 1 to n do: u then wy = i if yi is in Sn;s i else wyi = s + j ; j = j + 1; 2. Since hp and hq are normalized program maps, by construction it follows that FP Q=S = FS [ FP [ FQ. 8x 2 FS [ FP de ne hpqf (x) = x. 8x 2 FQ de ne hpqf (x) = . The induced mapping hpq is a program map because: 1. it establishes a bijection from PP Q=S n TP Q=S to PP , 2. it establishes a bijection from FP Q=S n FP Q=S to FP , and 3. for any clause head:{ body , it follows from the construction that h(head):{ del> (h(body)) is a clause in program P .

Lemma 3.2 If P and Q are two orthogonal enhancements of S , then P  Q=S is an enhancement of Q.

Proof: A proof similar to the proof of Lemma 3.1 can be given. Theorem 3.1 (Composition Enhancement Theorem)

If P and Q are two orthogonal enhancements of S , then P  Q=S is an enhancement of S . Proof: Follows from Lemma 3.1 and transitivity of enhancements.

4 Program Enhancement Structures Program enhancement structures are a high level representation of program construction by stepwise enhancement. In this section, we sketch the methodology of stepwise enhancement, and de ne program enhancement structures. Stepwise enhancement is a program development methodology consisting of two classes of standard components { Skeletons and Techniques. Skeletons are (usually) simple programs with a well-understood control ow. Good examples are traversals of recursive data 11

structures. Other examples are parsers and language interpreters. Techniques are standard programming practices. For example, incrementing an argument and then carrying it as a context which is the appropriate method for counting the number of elements of a list, the number of nodes in a tree, or the number of goal reductions or depth in a proof tree. Applying a technique to a program creates an enhancement of that program. Complicated programs are built by choosing a skeleton and repeatedly applying techniques. Separate enhancements of the same skeleton can be composed into a single program by the composition algorithm given in Figure 1. More discussion on the methodology can be found in [4] and [7]. Once a program has been developed using stepwise enhancement, one can represent its development graphically. De nition 4.1 proposes one such representation.

De nition 4.1 A program enhancement structure is a connected directed acyclic graph G where a) vertices of G represent programs, b) there exists an edge from vertex P to Q i

P was obtained by an application of a programming technique to Q, or Q was one of the programs used to derive P by composition, c) there exists exactly one vertex of outdegree 0, and d) there exists exactly one vertex of indegree 0.

Note that if there exists an edge from vertex P to vertex Q then there exists a program map from P to Q. As an example, consider the program enhancement structure  for goal info/4 given in Figure 5. The vertices of  are solve/1, num rules/2, depth/2, rules/2, and goal info/2. The code for the programs corresponding to each vertex is given in Section 6.2. In , edges from num rules/2, depth/2, and rules/2 to solve/1 correspond to an application of a programming technique. goal info/4 is obtained by the composition of num rules/2, depth/2, and rules/2. Therefore, in , there exist edges from goal info/4 to num rules/2, depth/2, and rules/2. goal info/4 is the only vertex with indegree 0, and solve/1, the skeleton, is the only vertex of outdegree 0.

5 Speci cations and Correctness of Logic Programs An important issue which must be addressed if logic programming is to be routinely used for large software projects is the clari cation of the role of speci cations. Following Parnas as expounded by Deville [2], we view a speci cation as a document which explains the behavior of a program suciently clearly so that the program can be used without necessitating the code being read. We believe that a speci cation should be the primary form of documentation and be given for each procedure in a program. 12

A speci cation for a logic program consists of a procedure declaration, e ectively giving the name and arity of the predicate, type declarations for each of the arguments, a relation scheme which gives a precise de nition (in natural language) of the intended relation of the predicate, and indication of mode of use. Mode of use uses the convention that + means input and - means output. For any program P , the intended meaning of the program is de ned by De nition 5.1. For an example speci cation, please refer to Figure 2.

De nition 5.1 The intended meaning of a program P , denoted I (P ), is de ned as: I (P ) = ftjt is true according to the relation scheme of Pg. Having made precise the intended meaning of a program, correctness of a program can be established by checking for the inclusion of the intended meaning in the computed meaning of a program and vice versa. De nition 5.3 makes this precise.

De nition 5.2 A goal g in P is in the right mode of use if g respects the mode given by the speci cation and all the ground arguments of g respect the type conditions.

De nition 5.3 Completeness: If g belongs to I (P ) then there exists a goal g0 which is in the right mode of use and which has refutation R in P computing answer substitution 

such that g 0 = g . Soundness: Given a goal g in the right mode of use, if there exists a refutation R for g in P which computes the answer substitution  then g belongs to I (P ). Correctness: A program P is correct w.r.t its speci cation i it is sound and complete. The tenet is that if P is an extension of Q then we can leverage the proof of correctness of P from the correctness of Q by using results from our program map theory. In the next section, we give a couple of examples to demonstrate program construction by stepwise enhancement, program enhancement structures, speci cation for logic programs, and the role of enhancement structures and program map theory in proving correctness of logic programs.

6 Examples Our overall approach to proving correctness is based on assuming the skeleton program has certain properties. In particular, the behavior of the skeleton program, manifest by its computations is assumed to be well understood, and can be used to bridge the gap between 13

the informal language of the speci cation and the formal refutations which are manipulated and discussed in our theory of program maps. In other words, the skeleton has `correct behavior' which can be reasoned about. In the two examples which follow, we assume that the traverse/2 program traverses its rst argument, a list, checking whether each element is a member or not of the second argument. the second example assumes that the rule interpreter, solve/1, correctly nds consequences of a collection of rules and facts by backward chaining. The behavior of the skeleton is important for both the soundness and completeness of the enhanced program. We demonstrate in the two examples.

6.1 Union and Intersection of Ordered Sets The rst example we consider is the union and intersection of ordered sets. An ordered set, which we represent in this paper as in Prolog by a list, has no duplicates, and the order of the elements is given by the position they appear in the list. The speci cation for the desired program is given in Figure 2.

procedure union intersect(S1,S2,U,I) Types: S1

S2 U1 I2

: : : :

ordered set ordered set ordered set ordered set

Relation Scheme: union intersect(S1,S2,U,I) is true i :  U is the ordered set which has a) all the elements from S1 which are

di erent from all the elements of S2 in the same relative order, followed by b) all the elements of S2 in the same order, and c) nothing more.  I is the ordered set which has all the elements which belong to both S1 and S2 in the same relative order as they appeared in S1 and nothing more.

Mode of Use: union intersect(+,+,-,-) Figure 2: A speci cation for union intersect/4 14

union intersect/4

 

HHH  HHH    HHH    H 

intersect/3

union/3

HH

HHj

HHH HHH

   HH  HHj

   

traverse/2

Figure 3: Program enhancement structure of union intersect Here is a candidate program union intersect/4 for the speci cation given in Figure 2. union intersect([],Ys,Us,Is):- eq1(Us,Ys), eq2(Is,[]). union intersect([X|Xs],Ys,Us,Is):- member(X,Xs), union intersect(Xs,Ys,Us,Is1), eq2(Is,[X|Is1]). union intersect([X|Xs],Ys,Us,Is):- non member(X,Xs), union intersect(Xs,Ys,Us1,Is), eq1(Us,[X|Us1]). eq1(X,X). eq2(X,X).

Program union intersect/4 was developed using stepwise enhancement. We have excluded the obvious de nitions for member/2 and non member/2 which can be found in Chapter 7 of [9]. We have also, for readability, renamed the predicate unionintersect by union intersect. The skeleton used for the program is given by traverse/2. Two instances of the build technique were applied to the skeleton to yield two orthogonal enhancements given by union/3 and intersect/3. union/3 and intersect/3 were combined using the composition algorithm to get union intersect/4. The enhancement structure for the development is given in Figure 3. union intersect/4

15

union([],Ys,Us):- eq1(Us,Ys). union([X|Xs],Ys,Us):- member(X,Xs), union(Xs,Ys,Us). union([X|Xs],Ys,Us):- non member(X,Xs), union(Xs,Ys,Us1), eq1(Us,[X|Us1]). eq1(X,X).

Program union/4 intersect([],Ys,Is):- eq2(Is,[]). intersect([X|Xs],Ys,Is):- member(X,Xs), intersect(Xs,Ys,Is1), eq2(Is,[X|Is1]). intersect([X|Xs],Ys,Is):- non member(X,Xs), intersect(Xs,Ys,Is). eq2(X,X).

Program intersect/4 traverse([],Ys). traverse([X|Xs],Ys):- member(X,Xs), traverse(Xs,Ys). traverse([X|Xs],Ys):- non member(X,Xs), traverse(Xs,Ys).

Program traverse/2 We now prove the correctness of union intersect/4 using its program enhancement structure and the theory of program maps.

Correctness of union intersect/4 We rst state a few results which are a direct outcome of the construction process used for union intersect/4.

Lemma 6.1 union/3 and intersect/3 are orthogonal enhancements of traverse/2. Proof: It is easy to check that there exist normalized program maps, and the two enhance-

ments are orthogonal w.r.t traverse/2.

Lemma 6.2 union intersect/4 is an enhancement of traverse/2. Proof: Follows from Theorem 3.1 (composition enhancement theorem). We now explore how the enhancement structure of union intersect/4 can be used to prove the correctness of union intersect/4. We rst prove Lemma 6.3 which uses `lifting 16

of the computations' property for enhancements.

Lemma 6.3 Given a ground goal traverse(S1,S2), any refutation R for traverse(S1,S2) in traverse/2 lifts to a computation W for union intersect(S1,S2,X,Y) (X and Y are variables) in union intersect/4 which can be extended to a refutation, and for any refutation R0 which extends W , union intersect(S1,S2,X,Y) belongs to I (union intersect/4) where  is the answer substitution computed by R0 . Proof: Follows by an induction on the length of S1. Base Case: For traverse([],S2),  computed by R0 for union intersect([],S2,X,Y) is fX/S2, Y/[]g. Clearly, union intersect([],S2,S2,[]) belongs to the intended meaning of .

union intersect/4

Induction Hypothesis: Assume true for all S1 of length < k where k > 0. Induction Case: We now show the proof when length of S1 is k. 1. Without loss of generality, assume S1=[s|Ss]. For a refutation for traverse([s|Ss],S2) in traverse/2 the two cases which need to be considered are: traverse([s|Ss],S2). | member(s,S2), traverse(Ss,S2). . . .

traverse([s|Ss],S2). | non member(s,S2) traverse(Ss,S2). . . .

2. Since the computations lift according to the computation lifting theorem, corresponding to the two possibilities given above, the two possible computations for union intersect([s|Ss],S2,X,Y) in union intersect/4 are: union intersect([s|Ss],S2,X,Y). | member(s,S2), union intersect(Ss,S2,X,Y1), eq2(Y,[s|Y1]). . . .

union intersect([s|Ss],S2,X,Y). | non member(s,S2), union intersect(Ss,S2,X1,Y), eq1(X,[s|X1]). . . .

3. Assume the case when member/2 is selected. Y1 is a variable. Applying the induction hypothesis to traverse(Ss,S2) and union intersect(Ss,S2,X,Y1), we know there exists 1 such that union intersect(Ss,S2,X,Y)1 belongs to I (union intersect/4). Assuming member/2 is correct, s is the rst element of S1 and it also belongs to S2. According to the relation scheme of union intersect/4, s should not be added to X but should be added as the very rst element of Y1. Solving eq2(Y,[s|Y1]) gives substitution Y/[s|Y1], and thus union intersect(S1,S2,X,Y)fY/[s|Y1]g1 also belongs to I (union intersect/4). 17

4. The other case, when non member/2 is selected, can be proved with similar arguments. Proof of soundness, completeness, and correctness of Lemmas 6.4, 6.5, and 6.6.

union intersect/4

are given by

Lemma 6.4 union intersect/4 is sound w.r.t its speci cation. Proof: Let h be the normalized program map between union intersect/4 and traverse/2.

Let union intersect(S1,S2,X,Y) be any goal in the right mode of use; that is, S1 and S2 are ground and of correct types, X is a variable, and Y is a variable. Let R0 be the refutation, and  be the answer substitution computed by R0. Let R01 be the refutation obtained from R0 by delaying selection of the eq1 and eq2 goals. Let  G00 , G01, : : :, G0n?1 , E ,  C10 , C20 , : : :, Cn0 ,  10 , 20 , : : :, n0 , and  A01 , A02 , : : :, A0n  be the sequences for R01. There exists a k, 1  k  n, such that h(G0k ) = > and for any i, 1  i  k, h(A0i ) 6= >. Let W 0 be computation denoted by sequences  G00, G01, : : :, G0k ,  C10 , C20 , : : :, Ck0 ,  10 , 20 , : : :, k0 , and  A01, A02, : : :, A0k . It follows from Lemma 2.2 that there exists a computation R for traverse(S1,S2) in traverse/2 which lifts to W 0. R has to be a refutation because h(G0k ) = >. Thus W 0 lies over a refutation, and W 0 extends to R01 . From Lemma 6.3 we can conclude that union intersect(S1,S2,X,Y)1 is in I (union intersect/4). It follows from Lemma 2.1 that union intersect(S1,S2,X,Y)1 is a variant of union intersect(S1,S2,X,Y), but since they are both ground they are identical.

Lemma 6.5 union intersect/4 is complete w.r.t its speci cation. Proof: Let h be the normalized program map between union intersect/4 and traverse/2.

Assume union intersect(S1,S2,U,I) is in I (union intersect/4). Let union intersect(S1,S2,X,Y) be a goal where X and Y are variables. union intersect(S1,S2,X,Y) is in the correct mode of use. traverse(S1,S2) belongs to I (traverse/2). There exists a refutation R for traverse(S1,S2) in traverse/2. h(union intersect(S1,S2,X,Y))=traverse(S1,S2). By the computation lifting theorem, there exists a computation W for union intersect(S1,S2,X,Y) in union intersect/4 which lies over R. From Lemma 6.3 we can conclude that W can be extended to refutation R0 which computes the answer substitution, say . From Lemma 6.4 we can conclude that union intersect(S1,S2,X,Y) is in 18

procedure goal info(Goal,Num,Depth,Rules) Types:

Goal Num Depth Rules

: atomic formula : integer : integer : list of facts and rule names

Relation Scheme: goal info(Goal,Num,Depth,Rules) is true i :

is the list of rules and facts which when used from left to right gives a proof P for Goal, Num is the number of rules and facts in Rules, and Depth is the depth of the proof tree corresponding to the proof P .

Rules

Modes of Use:goal info(+,-,-,-) Figure 4: A speci cation for goal info/4 I (union intersect/4). Assume X 6= U or Y 6= I. This is clearly not possible because for two ground ordered sets, as per the relation scheme, there has to be a unique output. Thus, X =U and Y =I.

Lemma 6.6 union intersect/4 is correct w.r.t its speci cation. Proof: Proof follows from Lemmas 6.4 and 6.5.

6.2 A rule interpreter to compute goal information The second example we consider is a rule interpreter. Consider the speci cation for a rule interpreter in Figure 4. Note that proof and proof trees are assumed to be understood { de nitions can be found in [9]. The rule interpreter assumes a syntactic form for rules and facts. For example, a rule from the simple expert system in Chapter 17 of [9] would be written as rule(place in oven(Dish,top), pastry(Dish) is true & size(Dish,small) is true,place1) where place1 is the name of the rule. Program goal info/4 is a candidate program meeting the speci cation given in Figure 4.

19

goal info/4

HHH  HHH  HH   HHH  Hj   ?

num rules/2

HHH HHH

depth/2

rules/2

     HH HHH  Hj? solve/1

Figure 5: Program enhancement structure of goal info/4. goal info(Goal,N,D,Rules):fact(Goal), eq1(N,0), eq2(D,1), eq3(Rules,[Goal]). goal info(Goal,N,D,Rules):rule(Goal,Body,Name), goal info body(Body,N1,D1,Names), plus1(N,N1,1), plus2(D,D1,1), eq3(Rules,[Name|Names]). goal info body(Goal is true,N,D,Names):goal info(Goal,N,D,Names). goal info body(GoalA&GoalB,N,D,Names):goal info body(GoalA,NA,DA,NamesA), goal info body(GoalB,NB,DB,NamesB), plus1(N,NA,NB), maximum(DA,DB,D), append(NamesA,NamesB,Names). eq1(X,X). eq2(X,X). eq3(X,X).

Program goal info/4 Once again, goal info/4 was developed using stepwise enhancement. The program enhancement structure for goal info/4 is given in Figure 5. We have excluded the standard de nitions for maximum/2 and plus/3. Note that due to the orthogonal requirement, we have three versions of eq/2 and two versions of plus/3, and for readability, we have renamed some predicate names of goal info. For example, the predicate goal info body actually corresponds to the predicate num rules bodydepth bodyrules body. 20

The skeleton used for the program is given by the following program: solve(Goal):- fact(Goal). solve(Goal):- rule(Goal,Body,Name), solve body(Body). solve body(Goal is true):- solve(Goal). solve body(GoalA&GoalB):- solve body(GoalA), solve body(GoalB).

Program solve/1 Programs num rules/2, depth/2, and rules/2 were obtained from solve by application of the count , calculate, and build technique respectively. The programs for num rules/2, depth/2, and rules/2 are given below. num rules(Goal,N):- fact(Goal), eq1(N,0). num rules(Goal,N):rule(Goal,Body,Name), num rules body(Body,N1), plus1(N,N1,1). num rules body(Goal is true,N):- num rules(Goal,N). num rules body(GoalA&GoalB,N):num rules body(GoalA,NA), num rules body(GoalB,NB), plus1(N,NA,NB). eq1(X,X).

Program num rules/2 depth(Goal,D):- fact(Goal), eq2(D,1). depth(Goal,D):rule(Goal,Body,Name), depth body(Body,D1), plus2(D,D1,1). depth body(Goal is true,D):- depth(Goal,D). depth body(GoalA&GoalB,D):depth body(GoalA,DA), depth body(GoalB,DB), maximum(DA,DB,D). eq2(X,X).

Program depth/2

21

rules(Goal,Rules):- fact(Goal), eq3(Rules,[Goal]). rules(Goal,Rules):rule(Goal,Body,Name), rules body(Body,Names), eq3(Rules,[Name|Names]). rules body(Goal is true,Names):- rules(Goal,Names). rules body(GoalA&GoalB,Names):rules body(GoalA,NamesA), rules body(GoalB,NamesB), append(NamesA,NamesB,Names). eq3(X,X).

Program rules/2

Correctness of goal info/4 Given the program enhancement structure for goal info/4 we establish correctness of goal info/4. Unlike the example for union and intersection, we will only sketch the proofs. The proof for goal info/4 follows the same steps as the detailed proof given for union intersect/4 which shows the usefulness of relating the computational behavior of the skeleton program to enhancements. The rst two lemmas are the outcome of the stepwise enhancement construction.

Lemma 6.7 num rules/2, depth/2, and rules/2 are orthogonal enhancements of solve/1. Proof: There exists normalized program maps from num rules/2, depth/2, and rules/2

to solve such that num rules/2, depth/2, and rules/2 are orthogonal enhancements w.r.t solve/1. The mappings are straightforward.

Lemma 6.8 goal info/4 is an enhancement of solve/1. Proof: Follows from Theorem 3.1 (composition enhancement theorem). The next step, analogous to the step of proving Lemma 6.3, is to prove a result which relates the refutations of solve/1 to the refutations of goal info/4. The program enhancement structure and the program map theory are useful here.

Lemma 6.9 Given a goal solve(Goal), any refutation R for solve(Goal) in solve/1 lifts to a computation W for goal info(Goal,N,D,Rules) (N, D and Rules are variables) in goal info/4 which can be extended to a refutation, and for any refutation R0 which extends W , goal info(Goal,N,D,Rules) belongs to I (goal info/4) where  is the answer substitution computed by R0. 22

Proof: Proof follows by induction on the length of R. The proof structure is similar to the

proof given in Lemma 6.3.

Lemma 6.10 goal info/4 is sound w.r.t its speci cation. Proof: The proof is identical to the proof of Lemma 6.4. Lemma 6.9 is the key to the proof. In order to prove completeness of goal info/4, we need to show some additional properties about the refutations in solve/1. This merits a closer look at the skeleton. There is a fundamental di erence between the skeleton traverse/2 and the skeleton solve/1. There was a unique refutation associated with each ground goal in traverse/2. In this sense, traverse/2 was deterministic. solve/1 is however non-deterministic; i.e, there can be more than one refutation for the same ground goal. Recall that the determinism of traverse/2 was inherited by the enhancement union intersect/4, and this helped us prove completeness of union intersect in Lemma 6.5. This no longer being the case with solve/1, we give a second look to the skeleton solve/1, establish an additional property about the behavior of the computations of the skeleton program, appeal to the program map theory to show that this property would be inherited, and establish correctness. Typically, such a property would be deduced from the relationship between the skeleton and the speci cation. The following property does the trick: If a goal goal can be proved by a given sequence  R1; R2 : : :; Rn  of rules and/or facts then there exists a refutation for solve(goal) in solve/1 which would select the goals rule/3 and/or fact/1 in an order corresponding to the order given in the sequence of rules and/or facts.

Lemma 6.11 goal info/4 is complete w.r.t its speci cation. Proof: A proof structure similar to the proof of Lemma 6.5 together with the additional

property about the refutations of the skeleton solve/1 is enough to establish completeness.

Lemma 6.12 goal info/4 is correct w.r.t its speci cation. Proof: Proof follows from Lemmas 6.10 and 6.11.

7 Conclusions In conclusion, this paper has presented an example proof that a logic program meets its speci cation. The proof heavily depends on the systematic approach using standard programming techniques used to derive the program. We introduced the concept of a program enhancement structure, and some underlying theory based on program maps. 23

We believe that enhancement structures and program maps can lead to a rigorous discipline of software engineering for logic programming-based languages. Skeletons can be viewed as reusable software components whose correctness can be relied upon to construct provably correct software.

Acknowledgments We acknowledge the discussions among the participants of the seminar course CMPS 572 at Case Western Reserve University. Todd Turnidge and Nevzat Balkir made some insightful comments. This work was partially supported by NSF Grant No. CCR-9303484.

References [1] Krzysztof R. Apt. Introduction to logic programming. In J. van Leeuwen, editor, Handbook of Theoretical Computer Science{Vol. B, chapter 10, pages 495{571. The MIT Press/Elsevier, 1990. [2] Yves Deville. Systematic Logic Programming Development. Addison-Wesley, 1990. [3] Marc Kirschenbaum, Leon Sterling, and Ashish Jain. Relating logic program via program maps. Annals of Mathematics and Arti cial Intelligence, 8(III-IV):229{246, 1993. [4] Arun Lakhotia. A Workbench for Developing Logic Programs By Stepwise Enhancement. PhD thesis, Case Western Reserver University, Department of Computer Engineering and Science, 1990. [5] J. Lloyd. Foundations of Logic Programming. Springer-Verlag, 2nd edition, 1987. [6] A.J. Power and Leon Sterling. A notion of map between logic programs. In D.H.D Warren and P. Szeredi, editors, Proceedings of the Seventh International Conference on Logic Programming, pages 390{404. The MIT Press, 1990. [7] Leon Sterling and Marc Kirschenbaum. Applying techniques to skeletons. In J.M.J. Jacquet, editor, Constructing Logic Programs, chapter 6, pages 127{140. John Wiley, 1993. [8] Leon Sterling and Arun Lakhotia. Composing prolog meta-interpreters. In K. Bowen and R. Kowalski, editors, Proceedings of the Fifth International Conference on Logic Programming, pages 386{403, Seattle, August 1988. The MIT Press. [9] Leon Sterling and Ehud Shapiro. The Art of Prolog. The MIT Press, 2nd edition, 1994. 24

Suggest Documents