An Automatic Partial Deduction System for Constraint Logic Programs Yi Tao and William I. Grosky Department of Computer Science Wayne State University Detroit, MI 48202
Chunnian Liu Department of Computer Science Beijing Polytechnic University Beijing 100022, P.R. China
(e-mail: yit,
[email protected])
(e-mail:
[email protected])
Abstract This paper presents a new procedure of partial deduction of various constraint logic programs. The procedure takes a program-goal pair (P0, Q0) as input and outputs a resultant program-goal pair (Pn, Qn). The procedure always terminates and the computational equivalence of the program-goal pairs (P0, Q0) and (Pn, Qn) is preserved. Pn is more efficient in solving Qn than P0 in solving Q0. Our procedure is based on the idea of program transformation, using transformation rules such as unfolding, constraint simplification, code deletion with respect to a goal, introduction of a newly defined clause, and folding. We have implemented the procedure in an integrated partial deduction system, which can work with Prolog, CLP(Bool), and CLP(R) programs. Our results are compared with those resulting from other partial deduction methods, and it is shown that our method generates more succinct and efficient resultant programs in general.
1
Introduction
Constraint logic programming (CLP) and partial deduction (PD) or partial evaluation (PE) are relatively new and active research fields in logic programming. In 1987, J.Jaffar and J.-L.Lassez [1] developed the constraint logic programming scheme CLP(D), which defines a class of languages based on the paradigm of rule-based constraint programming. Each instance of this scheme is a programming language and is obtained by the specification of the structure of the computation domain. The outstanding aspect of this class is that all the languages are soundly based within a single framework of formal semantics. For example, if the structure R is such that the constraints are relations over real arithmetic terms
with uninterpreted functors, we get an instance of the CLP(R) language. Similarly, we can get other constraint logic programming languages such as CLP(Bool), if the domain is Boolean, and CLP(FD), if the domain is finite. In fact, Prolog is also an instance of this scheme, which restricts the domain to the Herbrand universe. In 1981, Komorowski first introduced partial evaluation into the area of logic programming. Lloyd and Shepherdson [2] developed the theoretical foundation of partial deduction for Prolog programs, and some implemented partial evaluators have been reported [4-7]. On the other hand, research on partial deduction of other constraint logic programs has just begun. As far as we know, there is only one paper concerning the partial deduction of CLP [3] besides our own work [8, 9]. With respect to (wrt) problem solving, partial deduction produces a specialized resultant program with respect to the input program and goal. With respect to program transformation, given an input program-goal pair (P0, Q0), partial deduction produces a series of programgoal pairs (P1, Q1), ..., (Pn, Qn), with (Pn, Qn) called the resultant program-goal pair. Partial deduction should guarantee termination and the computational equivalence of the program-goal pairs (P0, Q0) and (Pn, Qn) should be preserved. Also, Pn is more efficient in solving Qn than P0 in solving Q0. The partial deduction procedure for constraint logic programs we present in this paper is based on the idea of program transformation. It is a natural extension of our new method of partial deduction of Prolog programs [10]. We have implemented the procedure on a Sun SPARC workstation for three languages: Prolog, CLP(Bool), and CLP(R), and the integrated partial evaluator is called CLP-PE, which provides our Constraint Logic Programming System [11] with a tool of optimizing programs. The outline of this paper is as follows. In the next section, we briefly introduce the concepts of partial
deduction and computational equivalence. Section 3 gives the formal definitions of the program transformation rules employed in our partial deduction procedure. In Section 4 we present the core algorithm of our partial deduction procedure for constraint logic programs and discuss its computational equivalence and termination issues. Section 5 shows running examples of partial deduction of CLP(Bool) and CLP(R) programs, and the partially evaluated results are compared with those resulting from other partial deduction methods. Finally, we give some conclusions and topics for further research.
2
PD(PE) and Computational Equivalence
Lloyd and Shepherdson in [2] describe partial evaluation as follows: "Given a program P and a goal G, partial evaluation produces a new program P', which is P 'specialized' to the goal G. The intention is that G should have the same (correct and computed) answers wrt P and P', and that G should run more efficiently for P' than for P. The basic technique for obtaining P' from P is to construct 'partial' search trees for P and suitably chosen atoms as goals, and then extract P' from the definitions associated with the leaves of these trees." The computational equivalence of the original program P and partially evaluated program P' with respect to the goal G means that any answer computed by P with respect to G is also correctly computed by P' with respect to G (completeness) and conversely (soundness). In [2], it is concluded that partial evaluation for definite programs and goals is always sound, but may not be complete, and for normal programs (i.e., those in which negation is allowed), partial evaluation is generally not only incomplete, but also unsound. However, for normal programs and goals, if the coveredness (Let P be a normal program, G a normal goal, A a finite set of atoms, P' a partial deduction of P with respect to A, and P* the subprogram of P' consisting of the definitions of predicate symbols in P' on which G depends. We say that P' ∪ {G} is A-covered if P* ∪ {G} is A-closed.) and independence (Let S be a finite set of atoms. We say that S is independent if no pair of atoms in S have a common instance.) conditions are satisfied, the computational equivalence of the original and partially evaluated programs will be ensured. The detailed theorems and their proofs can also be found in [2].
3
Transformation Rules for CLP Programs
In this section a brief introduction of the syntax and semantics of CLP languages is given, and then we present the formal definitions of the program transformation rules employed in our partial deduction procedure.
Constraint logic programming languages, similar to Prolog, comply with the syntax of Horn clauses. The CLP program and goal have the following forms: fact clause: rule clause: query clause:
a(...). a(...) :- b1(...), ..., bn(...). ?- b1(...), ..., bn(...).
where a(...), which is called the head of the clause, is an atom. bi (1≤i≤n), which is called a subgoal, is an atom or a constraint. b1(...),...,bn(...) is called the body of the clause. An atom with predicate symbol p of arity m has the form of p(X1,...,Xm), and X1,...,Xm are terms. Constraints depend on the constraint domain D and the operations on D. For example, X = false .or. Y is a boolean constraint; X > 3+Y+7 is an arithmetic constraint. A CLP program is a finite set of fact and rule clauses. A CLP goal is a query clause. The CLP scheme adopts the resolution theorem proving which is similar to Prolog, but it replaces syntactic unification over the Herbrand universe in Prolog with semantic unification over the intended domain of discourse. A complete description of the syntax and semantics of CLP languages can be found in [1].
3.1 Unfolding Let CLP program Pk be a set of clauses {E1,...,Er, C, D1,...,Dn}, where clause C is of the form H :- Before, A, After., for A an atom, and Before and After the conjunction of possibly empty subgoals. Assume that: A is unifiable with any head hd(Di), 1 ≤ i ≤ n, of D1,...,Dn, and θi is the most general unifier (mgu) of A and hd(Di). θi., b) Clause Ci is (H :- Before, bd(Di), After)θ where bd(Di) is the body of Di, for 1 ≤ i ≤ n.
a)
Then we say that C1,...,Cn results from unfolding A in C wrt D1,...,Dn. CLP program Pk+1 = {E1,...,Er, C1,...,Cn, D1,...,Dn} is the result of this unfolding of Pk.
3.2 Constraint Simplification Let CLP program Pk be a set of clauses {E1,...,Er, C}, − Before, A, After., for where clause C is of the form H :− A a constraint, and Before and After the conjunction of possibly empty subgoals. Assume that: a)
A can be simplified to A'. For example, X=false .xor. Y can be simplified to X = Y, and X > 3+Y+7 can be simplified to X > Y+10. − Before, A', After. b) Clause C' is H :−
Then we say that C' results from simplifying A in C. CLP program Pk+1 = {E1,...,Er, C'} is the result of this simplification of Pk. We note that if the constraint is the form X=Y, in which X is a variable and Y is either a constant or a − Before, variable, the simplified clause C' will be (H :− After){X/Y}.. In this case, the transformation is a special form of constraint simplification, called instantiation broadcasting.
3.3 Code Deletion with Respect to a Goal Let CLP program Pk be a set of clauses {E1,...,Er,C1,...,Cs}, and goal Qk of the form ?-G1,...,Gn.. Assume that: a)
The dependency graph of Pk is the same as that of the program resulting from omitting the constraints in Pk. b) According to Pk's dependency graph, E1,...,Er are all of the clauses on which Qk depends.
Then we say that C1,...,Cs are useless in computing answers by Pk with respect to Qk. CLP program Pk+1 = {E1,...,Er} is the result of deleting code C1,...,Cs with respect to Qk from program Pk.
3.4 Introduction of a Newly Defined Clause Let CLP program Pk be a set of clauses {E1,...,Er, C}, where C is of the form H :- B1,...,Bm., and goal Qk of the form ?- G1,...,Gn.. For Case 1, assume that: a) X1,...,Xw are all the distinct variables in Qk. b) Clause N is new(X1,...,Xw) :- G1,...,Gn.. Then we say that introducing the newly defined clause with respect to Qk results in N. CLP program Pk+1 = {E1,...,Er, C, N} is the result of introducing the newly defined clause into Pk. Qk+1 is new(X1,...,Xw). For Case 2, assume that: a)
X1,...,Xw are all the distinct variables in Bi,...,Bj, for 1 ≤ i ≤ j ≤ m. b) Clause N is new(X1,...,Xw) :- Bi,...,Bj.. Then we say that introducing newly defined clause with respect to Bi,...,Bj of C results in N. CLP program Pk+1 = {E1,...,Er, C, N} is the result of introducing the newly defined clause into Pk. We note that in our implemented partial evaluator, all of the predicate symbols of the heads (atoms) of these
newly defined clauses are introduced dynamically as distinct names, e.g., new1, new2,....
3.5 Folding Let CLP program Pk be a set of clauses {E1,...,Er, C, D}, where C is of the form H :- B1,...,Bm., and D is of the form Fq :- S1,...,Sw.. Assume that: a) Bi,...,Bj, for 1 ≤ i ≤ j ≤ m, and j-i+1 = w, is an instance of S1,...,Sw. That is, a substitution θ θ = {Bi,...,Bj}. exists such that {S1,...,Sw}θ b) D is the only clause in Pk. c) All the distinct variables of S1,...,Sw appear in Fq. θ , Bj+1,...,Bm. d) Clause C' is H :- B1,...,Bi-1, {Fq}θ Then we say that C' results from folding Bi,...,Bj of C by D. CLP program Pk+1 = {E1,...,Er, D, C'} is the result of this folding of Pk.
4
The Partial Deduction Procedure
We present a new and general partial deduction procedure for constraint logic programs in this section. This procedure is based on the idea of program transformation, employing the transformation rules introduced in Section 3. It inputs a program-goal pair (P0, Q0), outputs a resultant program-goal pair (Pn, Qn), and always terminates. The computational equivalence of the program-goal pairs (P0, Q0) and (Pn, Qn) is preserved. Pn is more efficient in solving Qn than P0 in solving Q0. We have implemented this procedure for three languages: Prolog, CLP(Bool), and CLP(R), and the integrated partial evaluator is called CLP-PE.
4.1 Core Algorithm of CLP-PE Main Procedure CLP_PE(P0, Q0, Pn, Qn) % Input Parameters: a program-goal pair (P0, Q0). %Output Parameters: a resultant program-goal pair (Pn, Qn). % Local Procedure: gen_resultant(Pn, A, ΦR). BEGIN_CLP_PE { 1. Introduce newly defined clause N wrt Qn: 1.1. n := 0; % n is the subscript of program-goal pairs and its initial value is 0. 1.2. (Pn,Qn) is transformed by introducing newly defined clause N wrt Qn to obtain (Pn++,Qn++); 1.3. Establish a well-structured set ΦL of predicate symbols wrt Pn and the user;
% ΦL is well-structured wrt Pn if, whenever ΦL and there exists a clause in Pn with the r∈Φ ΦL. form of q(…) :- …, r(…), …., then q∈Φ 1.4. ΦF := {N}; % ΦF is a set of clauses resulting from the transformation of introducing the newly defined clause. 1.5. ΦA := {the head of clause N}; % ΦA is a set of atoms which are the heads of the clauses in ΦF.
2. Partially deduce each atom in ΦA by the transformation rules of unfolding, constraint simplification, folding, and introducing newly defined clauses wrt the clause body: while ΦA ≠ ∅ do 2.1. A is some atom in ΦA; ΦA := ΦA - {A}; 2.2. gen_resultant(Pn, A, ΦR); % ΦR is returned by unfolding and simplifying clause A :- A. wrt program Pn, similar to the set of resultants resulting from partially deducting pure Prolog in [2]. Its complete description will be given later in this section. 2.3. Transform ΦR to ΦR'; % Each clause Ci in ΦR is transformed to clause Ci' in ΦR' by folding subgoals of the clause body and then introducing the new clause if needed. The head of Ci' is the same as that of Ci, but each subgoal Gj of the clause body is transformed to Gj' as follows: if Gj is an atom and Gj is foldable by some clause of the form F:-G. in ΦF then θ (θ θ is the substitution from the Gj' := Fθ folding.); else if Gj is an atom and the predicate symbol of Gj ∈ ΦL then Introduce the newly defined clause C wrt Gj of Ci, and let C be of the form of new(...) :- Gj.; Gj' := the head of clause C; % Enlarge the following global sets: ΦA := ΦA ∪ {Gj'}; ΦF := ΦF ∪ {C}; ΦL := ΦL ∪{the predicate symbol of Gj'}; Pn++ := Pn ∪ {C}; Qn++ := Qn; else Gj' := Gj; 2.4. ΦP := ΦP ∪ ΦR'; ΦR' results from transformations wrt atom A. %Φ end_of_while 3. Qn++ := Qn; % Replace ΦF in Pn with ΦP to obtain Pn++. Pn++ := (Pn - ΦF) ∪ ΦP;
4. Delete useless code from Pn wrt Qn to obtain resultant program-goal pair (Pn++,Qn++); } END_CLP_PE Local Procedure: gen_resultant(P, A, ΦR) % Purpose: clause A :- A. is transformed in finite times via unfolding and constraint simplification to obtain clause set ΦR wrt program P. % Input: P is a program; A is an atom. % Output: ΦR is a set of clauses. Two functions used in gen_resultant are as follows: i. set(C), called by separate(C), returns a set of unfolded atoms which are chosen during the transformations of unfolding and constraint simplification from A :- A. to clause C. ii. separate(C), called by gen_resultant(P, A, ΦR), returns null, an atom, or a constraint. It scans the subgoals in the body of clause C from left to right. If Bi is the current subgoal, then acts as follows: 1. If the body of C is scanned to the end, then return null; 2. If Bi is an atom having its predicate symbol belong to ΦL, and there exists only one fact clause in P which is unifiable with Bi, then return Bi; 3. If Bi is an atom, its predicate symbol belongs to ΦL, and an argument in Bi exists such that the length of the argument is more than the predefined constant maxlength, then scan Bi+1, and return; 4. If Bi is an atom having its predicate symbol belong to ΦL, and Bi is not a variant of, nor an instance of, nor more general than, nor has a common instance with, any atom in set(C), then return Bi; (Note: These 4 conditions are analogous to the computation rules of Rv, Ri, Rg, and Rci, respectively, in [4]. Users are prompted to choose only one out of them while running the partial deduction system.) 5. If Bi is a constraint which can be further simplified, then return Bi; 6. If conditions 1, 2, 3, 4 and 5 do not hold, then scan Bi+1, and return; BEGIN_gen_resultant(P, A, ΦR) { 1. ΦR := ∅; ΦS := {A :- A.}; 2. while ΦS ≠ ∅ do 2.1. C := some clause in the set ΦS of clauses; 2.2. G := separate(C); 2.3. Process G as follows: if G is null
then ΦS := ΦS - {C}; ΦR := ΦR ∪ {C}; % C is one of the resultants else if G is an atom then Unfold atom G in clause C wrt program Pn to obtain a set ΦN of clauses; ΦS - {C}) ∪ ΦN; ΦS := (Φ else if G is a constraint which can be furtherly simplified then Simplify constraint G in clause C to obtain a new clause B; ΦS - {C}) ∪ {B}; ΦS := (Φ } END_gen_resultant
4.2 Some Remarks on CLP-PE In [6], it is indicated that "for the most important class of programs to be partially evaluated, the metainterpreters, folding for composite goals does not seem to be required for getting satisfactory results." In our partial deduction procedure, the transformations of folding and introducing a newly defined clause with respect to the atoms in the body of some clause are imposed on a single atom. Thus, our partial evaluator does not need users' information to direct the transformation process; it is automatic. In fact, the procedure we present can be easily extended to the case of folding and introducing a newly defined clause with respect to multiple atoms, as long as we can find a complete set of rules to guide the process of partial deduction. It is worth noting that the following two points are very effective in leading to well partially-evaluated resultant programs. First, our partial deduction procedure always removes those instantiated variables from the atom that needs to be partially evaluated using the transformation rule of introducing a newly defined clause. Second, the procedure employs instantiation broadcasting in the transformation rule of constraint simplification. Finally, in the partial evaluator for CLP(R) programs that we have implemented, constraint simplification is limited to single linear arithmetic constraints and some special cases such as 3*X=12 and 5*X-2.01*Y=0, in which, for example, we will remove the constraint 3*X=12 by substituting any variable X in the clause containing 3*X=12 with 4. Now we are working to deal with a group of arithmetic constraints as a unit in our partial evaluator.
4.3 Termination Problem of CLP-PE We can prove that the above partial deduction procedure for constraint logic programs always terminates within a finite number of steps. An informal argument for this is as follows. 1. It can be proved that subprocedure gen_resultant(P, A, ΦR) always terminates. Let us ΦS ≠ ∅) do'. consider the loop statement 'while (Φ Because the function separate(C) is limited by a predefined constant maxlength, after being called a finite number of times, it will always return null. Each time the loop is executed, the set ΦS (loop variable) will strictly decrease down to ∅ finally. Therefore the loop will terminate. 2. It can be proved that the partial deduction procedure CLP_PE(P0, Q0, Pn, Qn) always terminates. First of all, consider the loop statement ΦA ≠ ∅) do'. The loop body deals with the 'while (Φ head (an atom) of one newly defined clause each time, but it may introduce more newly defined clauses. If we can put a limit on the number of these newly defined clauses, the loop will terminate. In fact, there exists a predefined constant maxlength in the partial deduction procedure, so the length of any argument of the subgoals (atoms) of the clauses in ΦR is no more than the threshold set by the predefined constant maxlength owing the fact that ΦR is returned by the subprocedure ΦR). Therefore, if variants are gen_resultant(P,A,Φ not considered, the number of existing atoms with one predicate symbol is limited. Therefore only a finite number of newly defined clauses can be introduced. The predefined constant maxlength is only one of the methods to guarantee the termination of the partial deduction procedure. Actually, the termination problem itself is an active area of research in partial deduction. Interested readers can also refer to [2, 4-7], for other methods of dealing with this problem.
4.4 Computational Equivalence of CLP-PE The computational equivalence of the resultant program-goal pair (Pn, Qn) and the input program-goal pair (P0, Q0) means that any answer computed by P0 with respect to Q0 is also correctly computed by Pn with respect to Qn, and conversely [2, 4-7]. In the partial deduction procedure for constraint logic programs CLP_PE(P0, Q0, Pn, Qn) we present, variable ΦA is a set of atoms which consists of the heads of the
clauses resulting from the transformation of introducing a newly defined clause. Thus, ΦA is finite and independent. Furthermore, any atom in ΦA is the most general form of new(X1,...,Xn) in which the arguments X1,...,Xn, for n ≥ 0, are distinct variables, so we can also conclude that Pn ∪ {Qn} is ΦA-covered. Thus, since our procedure satisfies the independence and coveredness conditions, it preserves the computational equivalence of program-goal pairs (P0, Q0) and (Pn, Qn).
5
Partial Deduction of CLP Programs
This section gives running examples of the partial deduction of CLP programs to show that our partial evaluator CLP-PE is effective. First of all, we partially evaluate a CLP(Bool) program appearing in [3]. Then we briefly compare the partial deduction method in [4] with ours. Finally the partial deduction of a CLP(R) program is given.
5.1 CLP(BOOL) Program Let us consider the following program P1. 1. add([A], [B], [C], D) :adder(A, B, false, C, D). 2. add([A|As], [B|Bs], [C|Cs], D) :add(As, Bs, Cs, E), adder(A, B, E, C, D). 3. adder(A, B, C, D, E) :- half(A, B, AB, C1), half(AB, C, D, C2), E = C1 .or. C2. 4. half(A, B, C, D) :C = A .xor. B, D = A .and. B. In P1, predicate half(A, B, C, D) defines a half adder in which bit A plus bit B is sum C with a carry bit D. A full adder is defined by adder(A, B, C, D, E), in which the sum of bit A, bit B, and low carry bit C is bit D with high carry bit E. The clauses defining predicate symbol add compute the sum of two binary numbers which are expressed by the lists of boolean values with the lowest order bit at the end of the list. If we want to double the binary number X to form a sum, the goal Q1 is ?- add(X, X, Y, C)., in which C is the highest order bit and Y is the list consisting of the left bits of the sum. According to our procedure, the process of partial deduction is as follows: Step 1: Introduce a newly defined clause with respect to the goal ?- add(X, X, Y, C). to obtain the new goal Q1' ?- new(X, Y, C)., and the introduced new clause is the following, 5. new(X, Y, C) :- add(X, X, Y, C). Step 2: ΦR is a set of clauses consisting of clause 6 and clause 7 after the first execution of subprocedure
gen_resultant(P1, new(X,Y,C), ΦR). 6. new([A], [false], A). 7. new([A|As], [C|Cs], A) :add(As, As, Cs, C). Step 3: Fold add(As, As, Cs, C) in the body of clause 7 by clause 5 to obtain clause 8. 8. new([A|As], [C|Cs], A) :- new(As, Cs, C). Step 4: Execute the transformation of code deletion with respect to new goal Q1' ?- new(X, Y, C). to obtain the resultant program P1' = {clause6, clause8}. Obviously program-goal pairs (P1,Q1) and (P1',Q1') are computationally equivalent. P1' is more efficient in solving Q1' than P1 in solving Q1, because the resultant program P1' is only a bit shift program which does not contain any boolean constraints. Program P1 was originally presented in [3], which also gave a partial deduction method which preserves breadth-first equivalence. The algorithm in [3] employs the 5 transformations of constraint simplification, failure elimination, unfolding, partial specialization, procedure factorization and dead code elimination, and produced the following program and goal as the result. P1'': query([X|Xs], [X|Ys]) :- add_1(Xs, Ys). add_1([ ], false). add_1([A|As], [A|Bs]) :- add_1(As, Bs). Q1'': ?- query(X,Y). Program P1'' contains one more clause than program P1'. This shows that our partial deduction procedure is better than that in [3] for partially evaluating programgoal pair (P1,Q1).
5.2 Prolog Program Benkerimi and Lloyd [4] developed a partial deduction procedure for logic programs in [4] based on the definitions of partial deduction and the notion of computational equivalence. In their algorithm, the initial value of ΦA consists those L-selectable atoms in the goal. After each atom in ΦA is partially evaluated, all of the Lselectable atoms in the bodies of the resultants resulting from the corresponding partial deduction are added to ΦA to be partially evaluated. In order to preserve the computational equivalence of partial deduction, ΦA has to be finite and independent. The partial deduction procedure we present is different from that in [4]. The main difference is that our procedure is based on the idea of program transformation [10]. In the process of partial deduction of Prolog programs, we employ the 4 transformation rules of unfolding, folding, introducing a newly defined clause,
and deleting code with respect to a goal. The procedure in [4], however, depends on the definitions of partial deduction and the two conditions of computational equivalence. In Benkerimi and Lloyd's procedure, unfolding is the only means of partial deduction. Since we adopt the transformations of introducing a newly defined clause and folding to build the set ΦA of atoms, the set ΦA is finite and independent. Our procedure avoids the computation of the msg of the pair of atoms which have a common instance and replacing this pair with their msg. Thus, it generally produces a more efficient resultant program than the procedure in [4]. In addition, our procedure generally produces more succinct resultant programs since it employs the transformation of code deletion with respect to a goal.
5.3 CLP(R) Program Partial deduction of CLP(R) programs is a new field of research on partial deduction. The partial evaluator CLP-PE we have implemented can solve a single arithmetic constraint and make special form of constraint simplification, instantiation broadcasting, in some cases. Consider CLP(R) program P2 containing some arithmetic constraints, 1. mortgage(P, 1, I, MP, B) :- Interest = P*I/1200, B = P + Interest - MP. 2. mortgage(P, Time, I, MP, B) :- Time > 1, Interest = P*I/1200, Newp = P + Interest - MP, Newt = Time - 1, mortgage(Newp, Newt, I, MP, B). In program P2, the parameters considered above are the principal, life of mortgage in months, interest rate, monthly payment, and the balance. If we know that the interest rate is 12%, and the balance is finally 0, the relation of the other three variables forms the goal Q2 ?mortgage(P, T, 12, MP, 0).. According to our procedure, the process of partial deduction is as follows: Step 1: Introduce newly defined clause wrt goal ?mortgage(P,T,12,MP,0). to obtain new goal Q2' ?- new(P, T, MP)., and the introduced new clause is the following. 3. new(P ,T, MP) :mortgage(P, T, 12, MP, 0). From step 2 to step 8, we describe the first execution of subprocedure gen_resultant(P, A, ΦR). Step 2: Unfold mortgage(P, T, 12, MP, 0) in the body of clause 3 by clauses 1, 2 to obtain clauses 4, 5. 4. new(P, 1, MP) :- Interest = P*12/1200, 0=P + Interest - MP. 5. new(P, T, MP) :- Time > 1,
Interest = P*12/1200, Newp = P + Interest - MP, Newt = T - 1, mortgage(Newp, Newt, 12, MP, 0). Step 3: Simplify the constraint Interest=P*12/1200 in the body of clause 4 to obtain clause 6. 6. new(P, 1, MP) :- Interest = 0.01*P, 0 = P + Interest - MP. Step 4: According to the constraint Interest = 0.01*P in the body of clause 6, we substitute any occurrence of the variable Interest in clause 6 with the arithmetic term 0.01*P, and Interest = 0.01*P is then removed from this clause. (This is a special case of the transformation of constraint simplification.) 7. new(P, 1, MP) :- 0 = P + 0.01*P - MP. Step 5: Simplify the constraint 0 = P + 0.01*P - MP in the body of clause 7 to obtain clause 8. 8. new(P,1,MP) :- 0 = MP - 1.01*P. Step 6: Simplify the constraint Interest=P*12/1200 in the body of clause 5 to obtain clause 9, too. 9. new(P,T,MP) :- Time > 1, Interest = 0.01*P, Newp = P + Interest - MP, Newt = T - 1, mortgage(Newp, Newt, 12, MP, 0). Step 7: Using the constraint Interest = 0.01*P in the body of clause 9, we substitute any occurrence of variable Interest in clause 9 with the arithmetic term 0.01*P, and Interest = 0.01*P is then removed from this clause. (This is a special case of the transformation of constraint simplification.) 10. new(P, T, MP) :- Time > 1, Newp = P + 0.01*P - MP, Newt = T - 1, mortgage(Newp, Newt, 12, MP, 0). Step 8: Simplify the constraint Newp = P + 0.01*P MP in the body of clause 10 to obtain clause 11. 11. new(P, T, MP) :- Time > 1, Newp + MP - 1.01*P = 0, Newt = T - 1, mortgage(Newp, Newt, 12, MP, 0). Up to this point, the first execution of subprocedure gen_resultant(P, A, ΦR) is finished. The returned value of variable ΦR is the set of clauses 8, 11. Step 9: Fold mortgage(Newp, Newt, 12, MP, 0) in the body of clause 11 by clause 3 to obtain clause 12. 12. new(P, T, MP) :- Time > 1, Newp + MP - 1.01*P = 0, Newt = T - 1, new(P, T, MP).
Step 10: Make the transformation of code deletion with respect to the new goal Q2' ?- new(P, T, MP). to obtain the resultant program P2' = {clause8, clause12}. Obviously, the resultant program P2' is more efficient than the original program P2 because P2' contains less arithmetic constraints than P2.
6
to find the solution to introducing newly defined clauses with respect to multiple atoms in the clause body and to make folding multiple atoms together possible.
References [1]
J. Jaffar and J.-L. Lassez, Constraint Logic Programming, Proceedings of the 14th ACM Symposium on Principles of Programming Languages, Munich, Germany, pp. 111-119, 1987.
[2]
J.W. Lloyd and J.C. Shepherdson, Partial Evaluation in Logic Programming, Journal of Logic Programming, Vol. 11, No. 3&4, pp. 217-242, 1991.
[3]
T.J. Hickey and D.A. Smith, Towards The Partial Evaluation of CLP Languages, Proceedings of PEPM’91, New Haven, Connecticut, pp.43-51, 1991.
[4]
K.Benkerimi and J.W. Lloyd, A Partial Evaluation Procedure for Logic Programs, Proceedings of the 1990 North American Conference on Logic, Austin, Texas, pp. 343-358, 1990.
[5]
J. Komorowski, Synthesis of Programs in the Partial Deduction Framework, In Automating Software Design, (Eds.), pp. 377-403, 1991.
[6]
D. Sahlin, Mixtus: An Automatic Partial Evaluator for Full Prolog, New Generation Computing, Vol. 12, No. 1, pp. 7-51, 1993.
[7]
Y. Tao, The Design and Implementation of a Partial Evaluator of Logic Programs, Journal of Beijing Polytechnic University, Vol. 20, No. 3 pp. 109-118, 1994.
[8]
X. Zhang and C. Liu, Partial Evaluation of CLP(R) Programs, Journal of Computer Research and Development, Vol. 33, No. 5, pp. 347-354, 1996.
[9]
Y. Tao and C. Liu, A Partial Deduction Procedure for Constraint Logic Programs, Chinese Journal of Computers, Vol. 20, No. 3, pp. 238-244, 1997.
[10]
Y. Tao and C. Liu, A New Method of Partial Deduction of Prolog, To appear in Journal of Beijing Polytechnic University, Vol. 32, No. 3, 1997.
[11]
C. Liu, X. Zhang, K. Yang, Y. Tao, and Zhiyang Wang, A Multi-domain CLP and its Partial Deduction, Journal of Software, Vol. 28, No 10, pp. 303-309, 1996.
Conclusion
Recently, constraint logic programming and partial deduction have attracted the increasing interests of researchers. Although current research activities are relatively active in both fields, few papers are concerned with the combination of these areas. Our paper gives a new and general partial deduction procedure for constraint logic programs. Based on this procedure, we have implemented an integrated partial deduction system to optimize Prolog, CLP(Bool) and CLR(R) programs. The partial evaluator is written in the logic programming language supported by our self-developed multi-domain CLP system [11], and consists of approximately 2000 lines of code. Since the domain of real numbers is much more complex than the boolean domain, we are still involved in extending our partial deduction system to CLR(R). As far as we know, no papers besides our own [8,9] have discussed the partial deduction of CLP(R) programs. Although our partial evaluator CLP-PE simplifies only individual arithmetic constraints at this moment, our continuing work in this direction is trying to develop systematic theories and adequate techniques to deal with general arithmetic constraints. Most of the implemented partial deduction systems reported as we know are not automatic. That is, human assistance is needed in the process of partial deduction in one way or another. Therefore, the users of these partial evaluators are limited to experienced researchers. This situation exists because it is very hard to find a completely automatic method that can satisfactorily partially evaluate all kinds of program-goal pairs. In our paper, we employ explicit program transformation rules to design and develop a fully automatic partial deduction system. As of now, we put some limitations on folding in our partial deduction procedure to achieve automation. That is, the newly defined clause is introduced only with respect to a single atom in the clause body, and folding is also done with respect to a single atom. Our current research goal is