Relative Correctness of Prolog Programs Extended Abstract
Marc Kirschenbaumy, Ashish Jain, and Leon Sterling Department of Computer Engineering and Science Case Western Reserve University Cleveland, Ohio, 44106, USA.
email: fjain,
[email protected]
Introduction The software crisis for procedural languages was precipitated by the failure of the prevailing adhoc 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, proving theorems about correctness, for example. This paper concerns an approach to simplify Prolog 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 structure. 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 Prolog programming. Rather we are concerned with demonstrating a process of Prolog programming where programs can be proved correct to speci cations. This paper follows from the theory that we presented at the previous Mathematics and AI Conference [3].
Program Maps Intuitively, a program map is concerned with the relationship between the syntactic structures of programs. A preliminary version of the theory was presented in [6] and a more complete version in [3]. Note that our account diers from standard accounts of theory such as [1] and [4]. The dierences arise from our intention to prove results about Prolog programming techniques. We present some essential de nitions and assume familiarity with the notions not explicitly de ned. [3] has the complete set of de nitions, and they will be part of the nal version of the paper.
De nition 0.1 A de nite logic program P with an underlying language LP of a formal rst-order y
Mathematics and Computer Science Department, John Carroll University, Cleveland, OH, 44118. email:
[email protected].
1
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 normal 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 0.2 Given a m-tuple (x1, : : :, xm), the projected n-tuple m n, denoted by m;n (x1 ; : : :; xm ), is (x1 , : : :, xn).
De nition 0.3 Given a logic programz P, P is the logic 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 0.4 Given logic programs P and Q, a mapping hf : FP ! FQ , and a mapping hp : PP ! PQ , a mapping h : LP ! LQ can be induced as follows:
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)) = for any atomic w p(t1; : : :; tm ) in LP , h(p(t1 ; : : :; tm ) = hp (p)m;n (h(t1 ); : : :; h(tm )), where m is arity of p and n is arity of hf (p). for any two ws A and B in LP , h(A; B) = h(A); h(B) for any two ws A and B in LP , h(A : ?B) = h(A) : ?h(B)
De nition 0.5 Given logic programs P and Q, a mapping h : LP ! LQ is a program map if the following holds: if F = ff j f 2 FP ^ hf (f) = g then hf establishes a bijective map between FP nF
and FQ , if T = fp j p 2 PP ^ hp (p) = >g then hp establishes a bijective map between PP n T and PQ , and if C = fC j C 2 CP and the head of C gets mapped to >g then h induces an onto mapping to CQ; that is, for each clause C in CQ there exists a clause C 0 2 CP n C such that h(C 0) is a variant of C. Given an atomic literal p(t1 ; : : :; tm ), intuitively, a program map projects out the last m ? n arguments in the mapping h(p(t1 ; : : :; tm )). The above de nition can be generalized so that the projection can be any arrangement of n of the m arguments for p. The projection used in [3] is more general; we have used a speci c instance of the projection for simplicity.
De nition 0.6 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 logic program P i 8i; 1 i n: Ai 2 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 = ((Gi?1 n Ai ) [ body)i . n denotes the length of the computation . A computation of length n is a refutation if Gn = >. z
In this work, logic program refers to de nite logic programs.
2
De nition 0.7 A computation in a logic 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.
De nition 0.8 Given logic 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 , and A1 ; : : : ; An is over a computation W in Q denoted by the sequences: G0 ; G1 ; : : : ; Gn , C1 ; C2 ; : : : ; Cn , 1 ; : : : ; n , and A1 ; : : : ; An if 8i; 0 i n: h(G0i) = Gi , h(Ci0) = Ci, i h(i0 ), and h(A0i ) = Ai. Given logic 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
De nition 0.9 Given logic programs P and Q, if there exists a program map h : LP ! LQ then
P is an enhancement of Q. A logic program P is an extension of a logic 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.
Two separate enhancements of a common base program can be composed to produce a single program performing the combined task in one traversal. The composition operation was rst introduced in the context of Prolog meta-interpreters in [7]. In [3], an algorithm was presented to compose enhancements of a common base program. For this extended abstract, we will not give the details of the algorithm and the composition operation. More details on composition are in [3]. Composition Extension Theorem: If P and Q are two extensions of R, then the composition of P and Q is an extension of R. Proof: A proof is given in [3].
De nition 0.10 Given logic programs P and Q and a program map h : LP ! LQ , P is in an acceptable form w.r.t. h if the variables which get projected out from the head of the clause in the
mapping h are all distinct and new variables. For example, all the enhancements given in this paper are in acceptable form.
Theorem for Lifting of Computations: Given logic 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. Proof: A proof is given in [3].
De nition 0.11 Given a set P of logic programs, an enhancement structure is the directed graph G where P is the set of vertices of G and there exists an edge from a vertex P to vertex Q i P 6= Q and P is an enhancement of Q.
3
procedure goal info(Goal,Num,Depth,Rules) Types:
Goal Num Depth Rules
Relation scheme:
: atomic formula : integer : integer : list of facts and rule names
can be proved from a collection of rules of the form and facts of the form fact(A). is the number of rules used to prove Goal, is the depth of the proof tree for Goal, and is the list of rule names and facts used to prove the goal. Modes of use: Goal rule(Head,Body,Name) Num Depth Rules goal info(+,-,-,-)
Multiplicities of solution:
same as multiplicity of Goal
Figure 1: A speci cation for goal information
Speci cations and Correctness of Prolog Programs An important issue which must be addressed if Prolog 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. A speci cation consists of a procedure declaration, eectively giving the name and arity of the predicate, a series of type declarations about the arguments, a relation scheme which gives a precise de nition (in natural language) of the intended relation of the predicate, and other important information such as modes of use of the predicate and multiplicities of solutions in each mode of use. We will discuss speci cations in more detail in the full paper. Let us look at a speci c example which will be used throughout the paper. In keeping with the conference theme, we prove the (relative) correctness of a rule interpreter, written in Prolog, that counts the number of reductions in proving a goal, nds the maximum depth of the implicit proof tree [8], and nds the list of rules and facts used in the proof of the goal [8]. Our notion of correctness comes from [8]. Recall that the meaning of a logic program P, M(P), is the set of ground unit goals deducible from P. We assume the intended meaning of a program is also a set of ground unit goals. A program is correct with respect to some intended meaning M if M(P) is a subset of M. A program is complete with respect to M if M is a subset of M(P). Finally, a Prolog program is totally correct over a domain D of goals if for all goals in D the computation terminates, does not produce a runtime error, and whose meaning is the intended meaning. 4
De nition 0.12 Given a logic program Q and its enhancement P, P is relatively correct w.r.t. Q i P is correct (w.r.t. P's speci cations) given that Q is correct (w.r.t. Q's speci cations).
How is the intended meaning given? We assume that the description given in the relation scheme of the speci cation is suciently precise so that the person responsible for proving correctness can determine if a given ground goal satis es the description or not. Note that descriptions in precise natural language is the norm in mathematics communications such as journal papers. We present Program 1 as a candidate program to meet the speci cation in Figure 1. goal info(Goal,N,D,Rules) :- fact(Goal), N=0, D=1, Rules=[Goal]. goal info(Goal,N,D,Rules) :rule(Goal,Body,Name), goal info body(Body,N1,D1,Names), N is N1+1, D is D1+1, 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), N is NA+NB, maximum(DA,DB,D), append(NamesA,NamesB,Names).
Program 1: Computing goal information
Program Development Structures We explain how Program 1 was derived and show how the derivation can be represented in a program development structure. The proof of relative correctness will be based on the program development structure. 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 2: A rule interpreter The rst stage in deriving Program 1 was to start with a skeleton rule interpreter. This is given as Program 2. The interpreter assumes a syntactic form for rules. For example, a rule from the simple expert system in Chapter 19 of [8] would be written as rule(place in oven(Dish,top), pastry(Dish) is true & size(Dish,small) is true,place1). The next stage in deriving Program 1 is to extend Program 2 in three ways { to count the number of rules, to calculate the depth of the proof tree, and to collect the facts and rules used. 5
These are done by standard Prolog programming practice. The desired value is calculated as an extra argument. The value of the base case is lled in, and the value computed in any recursive calls is related to the nal value. num rules(Goal,N) :- fact(Goal), N=0. num rules(Goal,N) :rule(Goal,Body,Name), num rules body(Body,N1), N is 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), N is NA+NB.
Program 3: Counting the number of rules used to solve a goal Program 3 for num rules is derived from solve by adding an argument, saying that the base case value, i.e. when considering a fact, is 0, and, in the recursive case, the number of rules calculated in num rules body is incremented by 1 to give the nal value. The relation between values in the head and body of num rules body is straightforward. Similarly, the program depth can be constructed systematically from solve to compute the depth of a search tree. depth is presented in Program 4. The dierences between depth and num rules is the value in the base case, and the added arithmetic goal, maximum(DA,DB,D) in depth body. Program 5 is the extension for collecting the list of rules. depth(Goal,D) :- fact(Goal), D=1. depth(Goal,D) :rule(Goal,Body,Name), depth body(Body,D1), D is 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).
Program 4: Depth of proof tree rules(Goal,Rules) :- fact(Goal), Rules=[Goal]. rules(Goal,Rules) :rule(Goal,Body,Name), rules body(Body,Names), 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).
Program 5: List of rules and facts 6
Program 2
*HY6HH HHH HH HHH H
Program 3
HHH Y HH HHH
Program 4
6
HHH H
Program 5
*
Program 1
Figure 2: A Program Development Structure The nal stage of developing Program 1 is to combine the calculations performed by Program 3 (num rules), Program 4 (depth), and Program 5 (rules). These calculations can be performed independently. This allows us to compose them into a single Prolog program which is able to perform the individual tasks of Programs 3, 4, and 5 all at the same time. [3] presents an algorithm to do the composition for two logic programs. We can rst compose Program 3 and Program 4 to get the intermediate composite program and then compose the intermediate program and Program 5 to get Program 1. Essentially, the algorithm goes through each clause in solve, nds the corresponding clauses in num rules, depth, and rules and produces a clause for goal info. This is done by rst copying the arguments in solve and then the added arguments from num rules, depth, and rules to give the arguments for goal info. The added goals in num rules, depth, and rules are copied for the recursive clause. The composition algorithm has been implemented and is able to compose a range of extensions. The method presented here to construct Program 1 starting from Program 2, applying techniques to get three enhancements, and composing the three enhancements to get the nal Program 1 can be represented pictorially by the means of a program development structure, a special type of enhancement structure. Developing a theory of enhancement structures is envisaged in future work.
De nition 0.13 A Program Development Structure is a connected directed acyclic graph G where a) vertices of G represent logic programs, b) there exists exactly one vertex of out degree 0, and c)
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. Figure 2 gives the program development structure for goal info. 7
Proof of Relative Correctness Proposition 1 Program 3 (num rules) is an extension of Program 2 (solve). Proof: De ne hf (0) = hf (1) = hf (+) = , hf (&=2) = &=2, hp (num rules) = solve, hp (num rules body) = solve body, hp (rule) = rule, hp (fact) = fact, and hp (=) = hp (is) = >.
The mapping induced by hf and hp is a program map from Lnum rules to Lsolve because there is an onto mapping from Cnum rules to Csolve . Consequently, Program 3 is an enhancement of Program 2. Let R be a refutation for a goal solve(Goal) in Program 2. Let G0 = num rules(Goal; Rules) where Rules is a variable. Since h(G0) = G, it follows from the theorem for lifting of computations that there exists a computation R0 in Program 3 which is over R. If n is the length of R0, the nal resolvent G0n of R0 consists only of literals of the form N0 = 0, or arithmetic goals N1 is N2 + 1 or N3 is N4 + N5 . An inductive proof can be given that there exists an arrangement L1 : : :; Lm of the literals of G0n such that the following is true:
for any i, 1 i m, the variables appearing on the LHS of Li ; i.e, variables of the `type' N0, N1, and N3, do not appear in the LHS of any other literal Lj , 1 j m and j = 6 i, for any i, 1 < i m, if Li is of the form N1 is N2 + 1 then N2 appears on the LHS of a literal Lk , 1 k < i, and for any i, 1 < i m, if Li is of the form N3 is N4 + N5 then N4 and N5 appear on the LHS of literals Ll and Lo , 1 l < i and 1 o < i. Consequently, using the semantics of the arithmetic goal is and the goal =, left to right reduction of the literals L1 ; : : :; Lm will give a refutation for G0n in Program 3. Thus Program 3 is an extension of Program 2 because every refutation R in Program 2 lifts to a computation R0 in Program 3 such that R0 can be extended to a refutation in Program 3.
Proposition 2 Program 4 (depth) is an extension of Program 2 (solve), and Program 5 (rules) is an extension of Program 2 (solve). Proof: : The proof is similar to the proof of Proposition 1 and will be completed in the full version of this paper.
Proposition 3 Program 1 (goal info) is an extension of Program 2 (solve). Proof: : Follows from Propositions 1, 2, and the Composition Extension Theorem. Proposition 4 Program 1 (goal info) is relatively correct w.r.t. Program 2 (solve). Proof: : Assume that solve is correct with respect to its speci cation. We need to show that
is correct with respect to its speci cation given as Figure 1. The proofs of correctness and completeness dier, correctness relying on the structure of the underlying proof tree, while completeness uses the Computation Lifting Theorem. goal info
8
Correctness: Let Goal = goal info(G,N,D,R) be in the meaning of goal info. We proceed by induction on the depth of the proof tree establishing G. Proof trees of depth 0 are facts. By inspection, N, D and R are set to the correct values and Goal is in the intended meaning. Suppose the proof tree underlying Goal has depth d. The second goal info clause in Program 1 must have been used to establish Goal. The proof trees of the goals in the rule body all have depth smaller than d. After the conjunction and is true wrapper are removed, the goals are in the meaning of goal info and by induction are in the intended meaning. Correctness follows by seeing how the values are tted together and from the correctness of composition. This sketch will be done in more detail in the nal paper. Completeness: Let Goal = goal info(G,N,D,R) be a goal in the intended meaning of goal info. G can be proved from the rules and facts. By the completeness of solve, solve(G) is in its meaning and there is a computation of solve proving G. Since goal info is an extension of solve, there is a computation in goal info lying over the computation which extends to a refutation (by the Composition Extension Theorem). Thus there is a goal goal info(G,N1,D1,R1) in the meaning of goal info. We need to show that the number of rules, depth of computation and list of facts and rules correspond. Again with mild hand waving, this is true by inspection of the code and the correctness of composition.
Related Work and Conclusions Deville describes a systematic method of deriving logic descriptions from speci cations in [2]. His method depends on identifying a suitable induction scheme which corresponds to a base program such as is bag. His incorporation of extra arguments is described more declaratively than our Prolog programming techniques, and we believe our description will be more comfortable for software engineering. The work has several parallels and we are investigating extending program maps to his logic descriptions. Several researchers have proposed classi cations of Prolog programming techniques. Bundy et al. and Gegg-Harrison have proposed descriptions which are suitable for teaching novices programming. Neither description has an underlying theory analogous to program maps, nor have they been adopted to proving correctness as far as we can determine. Furthermore our descriptions of techniques are more compact than Gegg-Harrison's schemas and Bundy et al.s' patterns. O'Keefe [5] proposes schemas for Prolog programs which attempt to clarify programmingpractice. Again they are devoid of theory, have poor notation in our opinion, and assume too much knowledge of an inexperienced programmer. In conclusion, this paper has presented a sample proof that a Prolog program meets its speci cation. The proof heavily depends on the systematic approach using standard Prolog programming techniques that was used to derive the program. We introduced the concept of an enhancement structure, and some underlying theory based on program maps. We believe that enhancement structures and program maps can lead to a rigorous Prolog-based discipline of software engineering. 9
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] J. Lloyd. Foundations of Logic Programming. Springer-Verlag, 2nd edition, 1987. [5] Richard O'Keefe. The Craft of Prolog. The MIT Press, 1990. [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 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. [8] Leon Sterling and Ehud Shapiro. The Art of Prolog. The MIT Press, 2nd edition, 1994.
10