Declarative Debugging in Constraint Logic Programming: the Cover Relation Alexandre Tessier LIFO, Universite d'Orleans BP 6759, 45067 Orleans Cedex 2, France Alexandre.Tessier@lifo.univ-orleans.fr ftp://ftp-lifo.univ-orleans.fr/pub/Users/tessier/ http://www.univ-orleans.fr/~tessier fax: (+33) 38417137, phone: (+33) 38494670 Abstract This work is motivated by the declarative insuciency diagnosis of constraint logic programs, but focuses only, in this paper, on theoretical viewpoints. Many techniques have been developed for logic programming but cannot be merely adapted to constraint logic programming. An answer is not covered by a more general computed answer any more. Practical implementations use incomplete solvers with regard to theoretical framework of CLP (Jaar and Lassez 1986) based on a theory or a domain. New theoretical foundations are necessary. Constraint logic program semantics is redened in terms of proof trees using a cover relation. Proof trees give an intrinsic denition to the answers provided by a program. The cover relation expresses that a constraint is covered by a (possibly innite) constraint set. Thus we give a theoretical framework where declarative diagnosis method can be studied thanks to the inductive nature of the semantics. We dene the notions of symptoms and errors and we prove that if there exists a symptom then there exists an error. 1 Contents 1 Introduction 2 Preliminaries 3 Operational Semantics 3.1 3.2 3.3 3.4 Skeletons : : : : : : : : Reject Criterion : : : : Answers : : : : : : : : Resolution : : : : : : : 3.4.1 SLD-Resolution 3.4.2 SLD-tree : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 4 Declarative Semantics 4.1 4.2 4.3 4.4 : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : Cover Relation : : : : : : : : : : : : : : : : : : : : Proof Trees : : : : : : : : : : : : : : : : : : : : : : Correspondance betwwen Proof Trees and Skeletons Declarative Semantics : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 3 6 9 9 12 13 13 14 15 16 16 17 19 20 5 Declarative Insuciency Diagnosis 24 6 Conclusion 30 5.1 Denitions : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 25 5.2 Diagnosis Algorithm : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : 29 2 1 Introduction Program debugging is known to be a time consuming task in the programming process. For a large broadcasting, Constraint Logic Programming (CLP) systems must integrate debugging tools. A great strength of Constraint Logic Programming (CLP) is its declarative nature. For a declarative language (with a semantics independent of its execution model), it is essential to consider a declarative error notion. Indeed, it is incoherent to use only low level debugging tools based on an understanding of the operational behaviour of the system and to give up a high level knowledge of the declarative meaning of the programs. But, the success of a declarative debugging tool is directly related to the language declarativity level. From this viewpoint, CLP is used in a much more declarative way than LP. In particular, the availability of global constraints and disequations makes useless: negation by failure, \cut", \is", meta-predicate such \var", etc. For these reasons, an essential component of a complete CLP system should be a declarative debugging tool. In this context, declarative means that the user does not need to understand the operational behaviour of the system. It is evident that a computer cannot diagnose errors in a program without being told a part of what should be computed by the program. But, only the intended declarative semantics of the program is required. Declarative error diagnosis in Logic Programming (LP) was introduced by E. Y. Shapiro [27] under the name of algorithmic debugging. Many techniques inspired by the Shapiro's method have been developed for logic programs [12, 11, 21, 8, 13, 7, 9, 22, 24, 3]. But, declarative diagnosis of constraint logic programs is relatively unexplored. We focus in this paper on the theoretical aspects of the declarative insuciency diagnosis of constraint logic programs. That is, how to declaratively point a small piece of erroneous code when an answer is lacking. Declarative debugging algorithms usually proposed in LP strongly use the Herbrand's models properties. Known LP techniques cannot be straightforwardly adapted to CLP: In CLP, Herbrand's interpretations do not represent program semantics any more. Some elements of the constraint domain are not nitely expressible in the program language (e.g. in CLP(R) [17]). But when we debug we would stay in the program language. How can we express that an answer misses because of some domain values? In fact, elements of the domain are only manipulated through constraints. In LP, each answer, which is a logical consequence of the program, is covered by a single more general computed answer. In CLP, there is no single cover any more. A sucient condition for the single cover property is the Independence of Negated Constraint (INC) [23] which is, unfortunately, veried by few interesting constraint domains. For example, in CLP(R), let us consider the program: p(x) p(x) 3 x<0 x0 Assume that for the goal p(x) we expect the answer true. Must we consider true as an insuciency symptom and the previous program as wrong? In fact, the IR-theory has for logical consequence 8x(true ! (x < 0 ^ x 0)). So it is not because true does not occur (in the less general sense) in the answer set fx < 0; x 0g that an answer is lacking. We must consider the whole answer set and check if it covers the expected answer. We start in reformulating program semantics bases. Our approach of constraint logic program semantics in terms of proof trees based on a cover relation is an extension of the grammatical view of LP [10, 4]. Proof trees give an intrinsic denition to the answers provided by a program. Relations between declarative semantics and operational semantics is then better explain. The cover relation expresses that a constraint is covered by a (possibly innite) constraint set. Practical implementations use incomplete constraint solvers with regard to theoretical framework [18] based on a theory or a domain. Our semantics abstract the constraint interpretation. Then, the constraint interpretation by a domain D or a (non satisfaction complete) theory T or an (incomplete) constraint solver A becomes particular case. We show that classical semantics [18, 14, 23, 19, 29, 19] are instance of our own. We can remark that the three previous possible constraint interpretations have not the same behaviours: T (or D) vs. A. For example, the constraint solver of CLP(R) provides three kinds of answers: yes (satisable constraint), no (unsatisable constraint), maybe (it cannot decide). It answers yes for x x = 1 ^ x = 1 and maybe for x x = 1, nevertheless j= 9x(x x = 1 ^ x = 1) ! 9x(x x = 1) (where j= F means that F is a logical consequence of the empty theory); it answers no for x = 1 ^ x = 0 and maybe for x x = 1 ^ x x = 0, nevertheless j= :9x(x = 1 ^ x = 0) ! :9x(x x = 1 ^ x x = 0). T vs. D. Let us consider the program ent(x) x = 0 ent(x) x = y + 1; ent(y) When constraint interpretation is the domain IN, the declarative answer true to the goal ent(x) is not covered by a nite part of the computed answers fx = 0; x = 1; : : : ; x = i; : : :g. But when constraint are interpreted through a theory, a model of which is IN, the declarative answer true is covered by a nite part of the computed answers because of the compactness theorem of the rst order logic. First, we give the operational semantics in terms of skeleton. Skeletons glue together the clause used during the compitation leaving aside the computation rule. The operational semantics is parametrized by a reject criterion which eliminates some unsatisable answer constraints. The notion of domain or theory usual for the constraint interpretation becomes a parameter of the reject criterion. Then we can take into account the incompleteness of some constraint solvers which cannot be expressed in a logical framework as previously shown. The system end the computation when the current store is rejected. 4 Next, we dene the declarative semantics. We introduce a cover relation between a constraint c and a constraint set C , denoted by c ` C and read: c is covered by C . The cover relation abstracts the dierent previous cover notions. When C = ; we nd the reject criterion. Thus, it generalizes the reject criterion. We nd the entailment relation when C is a singleton, [26] shows the interest of a framework based on an abstract entailment relation rather than a domain or a theory. The semantics is given in term of proof tree roots build on two kinds of rule: the program rules and the cover rules. The proof trees determine the declarative semantics while the proof trees which only use program rules determine an abstraction of the operational semantics. On the one hand, for each complete proof tree, there exists a complete proof tree with the same conclusion which uses a single cover rule, and this cover rule is used at the proof tree root. Thus, we rediscover well known results when the cover relation is deduced from a domain or a theory. On the other hand, for each complete proof tree, there exists a complete proof tree with the same conclusion which alternates program rules at even depth and cover rules at odd depth. The previous results are essential because they assert that, on the one hand, answers dened by covering computed answers and, on the other hand, answers dened by applying alternately program rules and cover rules are exactly all the declarative answers. They guarantee the consistency of denitions and results of our declarative diagnosis method. The inductive nature of our semantics is adapted to study declarative diagnosis in the algorithmic debugging way. In this framework, where we just consider missing answers, two notions of symptoms are dened: incompleteness symptoms and insuciency symptoms. Two associated kinds of errors are dened: non covered constrained atoms which are called strong insuciencies and non completely covered constrained atoms called weak insuciencies. We prove that is there exists a symptom then there exists an error. The two kinds of symptoms and errors are known in LP [27, 12, 11], but were dened into dierent frameworks. Thus, we contribute to better understand and compare them. Finally, we propose a diagnosis algorithm which given a computed symptom, that is a goal a which provides a nite standard SLD-tree such that an answer is missing, localizes an error (weak insuciency) in the program through implementation independent interaction with the expected semantics (the oracle). The rest of the paper is organized as follow: Sect. 2 denes the program language and some notations. The operational semantics is introduced in Setc. 3. Sect. 4 denes the declarative semantics, it presents the cover relation and its properties. Sect. 5 studies the declarative insuciency diagnosis. The conclusion recapitulates main ideas and the works in progress. 5 2 Preliminaries Let us consider once and for all four sets which dene the program language: an innite set of variables V ; a set of function symbols ; a set of constraint predicate symbols c; a set of program predicate symbols p. The term set is built as usual on V; . Atomic formulas build on V and p of the form p(x ; : : : ; xn), where p is a n-ary predicate symbol of p and x ; : : : ; xn are n distinct variables, are called atoms. The constraint language CONST is a subset of the rst order language build on V , and c. We assume that it is closed under conjunction and existential quantication. A constraint is a formula of CONST. Let us introduce some notations: x~ denotes a sequence of distinct variables x ; : : : ; xn. If F is a formula (built on V , , p [ c) then var(F ) denotes the free variable sequence of F . If c is a constraint, x~ is the variable sequence x ; : : : ; xn , y~ are the free variables of c not in x~ and a is an atom then { 9x c denotes 9x 9xn c, { 9 x c denotes 9y c, { 9 a c denotes 9 var a c. A clause is a (n + 2)-tuple (0 n) denoted by a c 2 a ; : : : ; an, where each ai is an atom and c is a constraint. When n = 0, the clause is called a fact. This denition is equivalent to the denition of [19]. Given a clause R of the previous form, we dene head(R) = a , body(R) = c 2 a ; : : : ; an, constraint(R) = c, arity(R) = n. A program is a set of clauses. A constrained atom is a pair a[c] where a is an atom and c is a constraint. In order to simplify we consider atomic goals rather than general goals. Indeed, given a general goal c 2 a ; : : : ; an we can add a clause p(~x) c 2 a ; : : : ; an, where p is a new predicate symbol and x~ = var(c 2 a ; : : : ; am), then we can consider answers to the atomic goal p(~x). Thus a goal is a, where a is the atom. 1 1 1 1 ~ 1 ~ ~ ( ) 0 1 0 1 1 1 1 6 Remark. A general goal g denes a new relation whose arity is the number of free variables of g. Let ansg be this relation (ansg 62 p [ c). Let us consider the program Pans built on V; ; c; p [fansg j g is a goal for P g and denes as follow: Pans = P [fansg (var(g)) g j gis a goal for P g. The language of P determines the language of Pans and given P we can determine Pans. The predicates added to the language do not occur in the clause body of Pans. Then, an answer to a general goal g for P is an answer to the goal ansg (var(g)) for Pans. But the notation would be less readable if we consider the two programs P and Pans. Thus we just consider the program P and answers to atomic goal for P . Moreover, the set of answers to the general goal c 2 a1; : : : ; an can be easily dened as the set fc ^ c1 ^ ^ cn j ci is an answer to ai , for i = 1; : : : ; n and c ^ c1 ^ ^ cn is \satisable"g. This paper is illustrated by the example of defective components detection in a binary adder. This example, in Prolog III with booleans [2], is due to A. Colmerauer [6]. The reader must not confuse our aim which is to diagnose error in a program and the example which detects a defective component in a binary adder. Example 1 We are interested in detecting the defective components in a binary adder which computes the binary sum of three bits X1,X2,X3 in the form of a binary number given in two bits Y1,Y2. X1 P1 AND AND P4 XOR OR P2 X2 X3 P3 U1 Y1 U2 P5 XOR U3 Y2 The binary adder. We are only interested, in the following program DETECT1 (write in PROLOG III with the edinburgh syntax), by the case where a single component is defective. go(C,E,S) :circuit(C,E,S), enu(E) {C = [0',0',0',0',1'], S = [1',1']}. circuit(C,E,S) :at_most_1(C,X) {C = [P1,P2,P3,P4,P5], E = [X1,X2,X3], S = [Y1,Y2], X = 1', ~P1 => (U1<=>(X1&X3)), ~P2 => (U2<=>(X2&U3)), ~P3 => (Y1<=>(U1|U2)), ~P4 => (U3<=>~(X1<=>X3)), ~P5 => (Y2<=>~(X2<=>U3))}. 7 at_most_1(L,X) {L = [], X = 0'}. at_most_1(L,X) :at_most_1(Q,Z) {L = [Y|Q], X = Y|Z, Y&Z = 0'}. boolean(X) {X = 0'}. boolean(X) {X = 1'}. enu(L) {L = []}. enu(L) :boolean(X), enu(Q) {L = [X|Q]}. circuit(C,E,S) expresses the relation between inputs, outputs and the defective component. C is the component list (P1 to P5), a component is defective when its value is 1', E is the input list (X1,X2,X3) and S is the output list (Y1,Y2). U1,U2,U3 are outputs of component P1,P2,P4. go(C; E; S) provides the inputs when the component P5 is defective and in order to simplify we impose that the outputs are 1',1'. Answers provided by PROLOG III to the goal go(C; E; S) are: ?{C {C {C {C go(C,E,S). = [0',0',0',0',1'], = [0',0',0',0',1'], = [0',0',0',0',1'], = [0',0',0',0',1'], E E E E = = = = [0',1',1'], [1',0',1'], [1',1',0'], [1',1',1'], S S S S = = = = [1',1']} [1',1']} [1',1']} [1',1']} First and third answers appear because a defective component does not always provide an erroneous output (implications in the program). 8 3 Operational Semantics This section briey describes operational semantics of programs. That is, given a program P , how to build the answers to a goal a for P . It ends by the denition of SLD-tree useful to dene the computed symptoms for declarative insuciency diagnosis in Sect 5. We rst introduce the notion of skeleton which links operational semantics (derivations, SLD-tree...) and declarative semantics (proof trees, xed point...) of a program. On the one hand, skeletons describe the SLD-resolution. On the other hand, they provide an intrinsic denition of answer notion. Thus, many results of independence of the selection rule can be straightforwardly proved. But this is out the scope of this paper (the reader can see [4]). 3.1 Skeletons A skeleton is an oriented tree, labeled by P [ f?g, such that, for each node N , let label(N ) be its label: the degree of N is arity(label(N )) (arity(?) = 0); if label(N ) = a c 2 a ; : : : ; an then N has n children N ; : : : ; Nn such that, for each 0 1 1 i = 1; : : : ; n, label(Ni ) is { either ? { or a clause Ri of P whose head predicate symbol is the same that the predicate symbol of ai (see Ex. 2). For each skeleton S , we denote by undef (S ) the set of nodes of S labeled by ?; def (S ) the set of the other nodes; root(S ) its root. Example 2 A skeleton for the program DETECT1: go(C; E; S ) ? boolean(X ) C = [00; 00; 00; 00; 10] ^ S = [10; 10] 2 circuit(C; E; S ); enu(E ) enu(L) @ L = [X jQ] 2 boolean(X ); enu(Q) X = 10 2 boolean(X ) enu(L) X = 10 2 boolean(X ) @ L = [X jQ] 2 boolean(X ); enu(Q) @ enu(L) X = 00 2 L = [X jQ] 2 boolean(X ); enu(Q) @ enu(L) 9 L = [] 2 A renaming function for a skeleton S , is a mapping choice (from nodes to P [ f?g) in the following way: for each node N of S if N = root(S ) then choice(N ) = label(N ); if N is a leaf labeled by ? (label(N ) = ?) then choice(N ) = label(N ); otherwise choice(N ) = label(N ), where is a renaming such that: { if N is the i child of N 0 then the i atom of body(choice(N 0 )) is head(choice(N )), { for each node N 0 which is not in the subtree rooted by N , for each variable x 2 var(body(choice(N ))) var(head(choice(N ))), x has no free occurrence in choice(N 0 ). Intuitively, for each node of the skeleton except the root, we choose a variant of its label. Thanks to the standard form of the program (i.e. arguments of the atoms are distincts variables), we choose a variant whose head is syntactically identical to the corresponding atom of the body of the variant of the clause choosen for its father and such that the new variables (i.e. variables of the body which do not occur in the head) of the variant are dierent of the new variables of the variant choosen for the other nodes. We associate to each skeleton S and each renaming function choice for S the constraint system const(S; choice) = fconstraint(choice(N )) j N 2 def (S )g. Renaming function just determines renaming of constraint system variables. It is necessary to handle the constraints as a system rather than a formula with quantiers, then innite constraint systems can be considered. The system is sometimes denoted const(S ). It is dened up to a variable renaming. When def (S ) is nite, we denote by conj (S; choice) the conjunction of the constraints of const(S; choice), AC (S ) the constraint 9 x conj (S; choice), where x~ are the variables of the head of choice(root(S )). AC (S ) does not depend on the renaming function but only on var(head(label(root(S )))). AC (S ) is called the constraint associated to S . th th ~ Example 3 We show the skeleton of Ex. 2 where clauses are renamed according to a renaming function. go(C; E; S ) ? boolean(X 0 ) C = [00; 00; 00; 00; 10] ^ S = [10; 10] 2 circuit(C; E; S ); enu(E ) @ E = [X 0jE 0] 2 boolean(X 0 ); enu(E 0) enu(E ) X 0 = 10 2 boolean(X 00 ) enu(E 0) X 00 = 10 2 boolean(X 000 ) @0 E = [X 00 jE 00] 2 boolean(X 00 ); enu(E 00) enu(E 00) X 000 = 00 2 @ E 00 = [X 000jE 000 ] 2 boolean(X 000 ); enu(E 000) @ enu(E 000) 10 E 000 = [] 2 The constraint system is f C = [00; 00; 00; 00; 10] ^ S = [10; 10]; E = [X 0 jE 0]; X 0 = 10; E 0 = [X 00jE 00]; X 00 = 10; 00 E = [X 000 jE 000]; X 000 = 00; E 000 = [] g Its associated constraint is 9X 09E 0 9X 009E 00 9X 000 9E 000 (C = [00; 00; 00; 00; 10] ^ S = [10; 10] ^ E = [X 0jE 0]^ X 0 = 10 ^ E 0 = [X 00jE 00] ^ X 00 = 10 ^ E 00 = [X 000jE 000 ] ^ X 000 = 00 ^ E 000 = []) It simplied by Prolog III into C = [00; 00; 00; 00; 10] ^ S = [10; 10] ^ E = [10; 10; 00] A complete skeleton is a skeleton S such that undef (S ) = ;. Finite complete skeletons dene general answers of a program, in the sense that, if S is a nite complete skeleton rooted by a g then P j= AC (S ) ! a. Example 4 If we plug the following nite complete skeleton: circuit(C; E; S ) C = [P 1; P 2; P 3; P 4; P 5] ^ E = [X 1; X 2; X 3] ^ S = [Y 1; Y 2] ^ X = 1 ^ P 1 ) (U 1 , (X 1&X 3))^ P 2 ) (U 2 , (X 2&X 3))^ P 3 ) (Y 1 , (U 1jU 2))^ P 4 ) (U 3 , (X 1 , X 3))^ P 5 ) (Y 2 , (X 2 , U 3)) 2 at most 1(C; X ) 0 at most 1(C; X ) C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 2 at most 1(C ; X ) at most 1(C ; X ) C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 2 at most 1(C ; X ) at most 1(C ; X ) C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 2 at most 1(C ; X ) at most 1(C ; X ) C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 2 at most 1(C ; X ) at most 1(C ; X ) C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 2 at most 1(C ; X ) 1 2 3 4 1 2 3 4 1 1 2 3 4 2 3 4 5 1 1 2 1 1 3 2 2 4 5 5 5 3 4 4 at most 1(C ; X ) 2 3 3 1 4 5 5 1 2 1 2 3 3 4 4 5 5 1 2 3 4 5 2 3 4 5 C = [] ^ X = 00 2 5 5 in the undened leaf of the skeleton of Ex. 3 then we obtain a nite complete skeleton whose associated constraint is simplied by PROLOG III into C = [00; 00; 00; 00; 10] ^ E = [10; 10; 00] ^ S = [10 ; 10] 11 3.2 Reject Criterion Some general answers are less interesting. For example, if AC (S ) is always false then AC (S ) ! a is always true regardless of the program. From a theoretical viewpoint, these answers are not interesting. From an operational viewpoint, we have to avoid useless investigation which are possibly innite. The system tries to eliminate these \trivial answers" thanks to a reject criterion. The operational behaviour of the program is parametrized by this reject criterion. A reject criterion, denoted by ` ;, is a relation over CONST. It can take into account the working of an interpreter which provides answers with the comment maybe, indicating that the (incomplete) constraint solver answers neither yes nor no. Reject criterion abstract constraint interpretation. It is a relation over constraints in a syntactic way. In order to simplify, we assume, to the paper end, that if c and c are two constraints then: c ^ c and c ^ c are the same constraint; if x is a free variable of c which has no free occurrence in c then (9x c ) ^ c and 9x (c ^ c ) are the same; if x and y are two variables then 9x9y c and 9y9x c are the same, if x is a variable then 9x c and 9x9x c are the same. For each rejected constraint c, denoted by c ` ;, the reject criterion ` ; veries the three following properties: CONJ : for each constraint c0, c ^ c0 ` ;; EXIS : for each variable x, 9x c ` ;; RENA : for each renaming , c ` ;. Reject criterion is not any one. In general, it is dened from: a domain D, denoted by `D ;, then c `D ; if, for each valuation v in D, v(c) is false; a theory T , denoted by `T ;, then c `T ; if, for each model D of T , c `D ; (i.e. T j= :c); a constraint solver A, denoted by `A ;, then c `A ; if the solver answers no for the satisability of c. Thanks to the reject criterion, the operational semantics can be studied by abstracting the constraint interpretation. Thus, we can take into account the behaviour of an incomplete constraint solver. 1 1 2 2 1 1 1 2 2 2 1 1 1 12 1 1 2 3.3 Answers We assume that a reject criterion ` ; and a program P are xed. Denition 3.1 1. A skeleton S is rejected if there exists a nite subset C of const(S ) such that Vc2C c ` ; (note that S nite is rejected i AC (S ) ` ;). 2. An answer to the goal a is a non rejected nite complete skeleton S rooted by a variant of a clause whose head is a. Then AC (S ) is an answer constraint to the goal a. Example 5 The skeleton of Ex. 4 plug in the undened leaf of the skeleton of Ex. 3 is an answer to the goal go(C; E; S ), its constraint system is not rejected. The answer constraint is: 9E 0 9X 09E 00 9X 00 9E 000 9X 0009P 19P 29P 39P 49P 59X 19X 29X 39Y 19Y 29U 19U 29U 3 9Y 9C 9X 9Y 9C 9X 9Y 9C 9X 9Y 9C 9X 9Y 9C 9X 0 0 0 (C = [0 ; 0 ; 0 ; 00; 10] ^ S = [10 ; 10] ^ E = [X 0 jE 0] ^ E 0 = [X 00jE 00] ^ E 00 = [X 000jE 000 ] ^ E 000 = [] ^ X 0 = 10 ^ X 00 = 10 ^ X 000 = 00 ^ C = [P 1; P 2; P 3; P 4; P 5] ^ E = [X 1; X 2; X 3] ^ S = [Y 1; Y 2] ^ X = 10^ P 1 ) (U 1 , (X 1&X 3))^ P 2 ) (U 2 , (X 2&X 3))^ P 3 ) (Y 1 , (U 1jU 2))^ P 4 ) (U 3 , (X 1 , X 3))^ P 5 ) (Y 2 , (X 2 , U 3)) ^ C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 ^ C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 ^ C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 ^ C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 ^ C = [Y jC ] ^ X = Y jX ^ (Y &X ) = 00 ^ C = [] ^ X = 00) 1 1 1 3 3 2 1 1 2 2 2 3 3 3 4 4 4 5 5 5 1 1 1 1 1 2 2 1 2 2 2 2 2 3 3 3 3 3 4 4 3 4 4 4 4 4 5 simplied into: 5 4 5 5 5 5 5 5 C = [00; 00; 00; 00; 10] ^ S = [10; 10] ^ E = [10; 10; 00] 3.4 Resolution We describe now a process which provides all the answers for a goal a. It is possible to generate all the nite skeletons rooted by a clause whose head is a, but for ecient purpose, we want to build only skeletons which are susceptible to be non rejected. The skeleton S is a sub-skeleton of the skeleton S if S coincide with S on def (S ). Thus, def (S ) def (S ) and S is obtained by labelling by ? some nodes of S (their children are removed). If S is a sub-skeleton of S then each renaming function choice for S can be extended in a renaming function choice for S such that, if N 2 def (S ) then choice (N ) = choice (N ). Thus, const(S ; choice ) const(S ; choice ) and, consequently, each sub-skeleton of a non rejected skeleton is not rejected (CONJ property of ` ;). 2 1 2 1 2 2 2 1 2 2 1 1 2 1 2 1 2 1 1 13 2 1 2 3.4.1 SLD-Resolution The top-down resolution consists in building skeletons obtained by plugging in undened leaves other skeletons, until it is an answer. A skeleton S 0 derives from a non rejected skeleton S by the leaf N 2 undef (S ) if S 0 is not rejected and there exists R 2 P such that S 0 is obtained from S by plugging sq(R) in N , where sq(R) is the skeleton whose root is labeled by R and has arity(R) children labeled by ?. The SLD-derivation is a top-down resolution which, given a goal a, builds a sequence of non rejected nite skeletons rooted by renamed clause R such that head(R) = a, in the following way: rst state is sq(R), 1. if sq(R) is rejected then there is no answer, the resolution end; 2. from the state S , if S is complete then S is a computed answer; otherwise, the following state is a skeleton S 0 which derives from S . S is a nal state when no state derives from S . Then S is a success state if S is complete, otherwise it is a failure state. We call SLD-derivation every (nite or innite) state sequence S ; : : : ; Si; : : : such that S = sq(R), each state (except the rst one) derives from the previous and the sequence is innite or the last state is a nal state. 1 1 Lemma 3.2 The SLD-resolution has the two following properties: 1. each computed answer is an answer; 2. it computes all the answers. Proof. 1. The rst property is obvious: the SLD-resolution only build non rejected nite skeletons rooted by a renamed clause R whose head is a. 2. To prove the second one, let us consider an answer S for the goal a. The breadth rst traversal of S provide a sequence of nodes N ; : : : ; Nm . We dene the sequence of skeletons S ; : : : ; Sm: Si is a sub-skeleton of S such that def (Si) = fN ; : : : ; Nig. Then, it is easy to show that S ; : : : ; Sm is a SLD-derivation and Sm = S , thus S is a computed answer. 1 1 1 1 The SLD-resolution is twice non deterministic: the choice of the leaf where the skeleton is plugging in, the choice of the clause which roots the plugged skeleton. 14 We call computation rule a mapping r which, for each incomplete skeleton S in a derivation, provides a leaf in undef (S ). Given a computation rule r, the SLD-resolution according to r for a goal a is a SLD-resolution for the goal a where, at each step S , the choosen leaf is r(S ). 3.4.2 SLD-tree Denition 3.3 A SLD-tree for the goal p(~x) is a (possibly innite) tree A rooted by p(~x), with nodes, expect the root, labeled by non rejected nite skeletons such that: a node labeled by an answer S has no child, it is a success node and S is a computed answer; if R ; : : : ; Rn are the clause of the denition of p and ; : : : ; n are variable renamings such that head(Ri )i = p(~x), for i = 1; : : : ; n then the root has n child labeled by sq(Rii ), for i = 1; : : : ; n; for each node M of A (expect the root) labeled by an incomplete skeleton S , let N 2 undef (S ), children of M exactly correspond to skeletons which derive from S by N and they are labeled by these skeletons, if M has no children then M is a failure node. 1 1 A Branch of a SLD-tree for a correspond to a SLD-derivation for a. A success branch (resp. failure, innite) correspond to a success SLD-derivation (resp. failure, innite). Lemma 3.4 S is a computed answer to the goal a i S is an answer to the goal a. Proof. There exists a one-to-one correspondence between success branches of an SLD-tree for the goal a and answer skeletons to the goal a. The standard strategy is based on the computation rule which choose the left most undened leaf. The SLD-tree for a according to the computation rule r is the SLD-tree such that, for each node labeled by an incomplete skeleton S , the chosen leaf is r(S ). Lemma 3.5 The computed answers are independent of the computation rule. Proof. Answer skeletons are independent of the computation rule and there exists a one-toone correspondence between success branches of an SLD-tree for the goal a and answer skeletons to the goal a. 15 4 Declarative Semantics In LP, a declarative answer to the goal a is a substitution such that P j= a. For each declarative answer substitution, there exists a single more general computed answer substitution. The similar results in CLP should be that, if P j= c ! a (or P; T j= c ! a or P j=D c ! a) then there exists a single computed answer constraint c0 to the goal a such that c0 is \more general" than c. It is well known that this is wrong in general . Nevertheless, we would keep a similar property which links declarative answer constraints and computed answer constraints. In fact, each declarative answer is covered by a (possibly innite) set of computed answers. This relation is called the cover relation. Our declarative semantics has no logical nature. It is dened inductively by two kinds of rules. First rules stem from clauses of the program and the second ones are dened from the cover relation. We nd again every known results when the cover relation is deduced from a domain or a theory. 1 4.1 Cover Relation A cover relation ` is a binary relation over CONST 2CONST. It veries, for each constraint c, the six following properties: CONJ : let c ; : : : ; cn be n constraints and C ; : : : ; Cn be n constraint sets such that ci ` Ci, i = 1; : : : ; n, then c ^ ^ cn ` fc0 ^ ^ c0n j c0i 2 Ci; i = 1; : : : ; ng REFL : c ` fcg; EXIS : let x~ be a variable sequence and C be a constraint set such that c ` C , then 9x c ` f9x c0 j c0 2 C g; TRAN : let C be a constraint set such thatSc ` C and (Cc0 )c 2C be a constraint set family such that c0 ` Cc0 , for c0 2 C , then c ` c 2C Cc0 ; MONO : let C; C 0 be two constraint sets such that c ` C and C C 0, then c ` C 0 ; RENA : let be a variable renaming and C be a constraint set such that c ` C , then c ` fc0 j c0 2 C g. 1 1 1 ~ 1 ~ 0 0 0 0 0 The cover relation extends the reject criterion. A constraint is rejected when it is covered by the empty set. We recognise the three properties (CONJ, EXIS, RENA) of reject criterions. (CONST; `) denes a constraint system in a sense similar to [26, 15, 5]. In general, the cover relation is deduced from: a domain D, denoted by `D , c `D C if for each valuation in D which satises c there exists a constraint in C satised by the valuation; a theory T , denoted by `T , c `T C if, for each model D of T , c `D C ; 1 These property is veried when there is the Independence of Negated Constraint [23]. 16 a constraint solver A, denoted by `A and dened by the least relation verifying the ve properties and such that c `A ; if the constraint solver answers no for the satisability of c. Thanks to the cover relation, which generalizes the reject criterion, we can elaborate a semantics which takes into account the dierent constraint interpretations. Interest of this novel semantics is to study the declarative insuciency diagnosis and to dene the notion of symptoms and errors for constraint programs. 4.2 Proof Trees The semantics is described in terms of root of proof trees built on a rule system. There is two kind of rules: the rst ones are dened by the clause of the program and the second ones are dened by the cover relation. Denition 4.1 Program Rules For each renamed clause a dene the program rule: c 2 a ; : : : ; an of P and each constraint c ; : : : ; cn, we 1 1 a [c ] an[cn] a[9 a (c ^ c ^ ^ cn)] 1 1 1 when n = 0 we deduce the axiom a[9 c] . a Cover Rules For each atom a, each constraint c and each constraint set C such that c ` C , we dene the cover rule: fa[c0 ] j c0 2 C g a[c] when C = ; we deduce the axiom a[c] . As to each rule system, we associate, in the classical way, a notion of proof trees [1]. Proof trees which use the two kinds of rule determine the declarative semantics while proof trees which only use program rules determine an abstraction of the operational semantics. Denition 4.2 An answer to the goal a is the root a[c] of a proof tree. A computed answer to the goal a is the root a[c] of a proof tree which only use program rules. 17 Answers and computed answers dened in Sect 3 are called answer skeletons and computed answer skeletons. Remark. When c ` ;, for each atom a, a[c] is an answer. Then a[c] is called a trivial answer to a according to `. It is independent of the program. The system tries to eliminate, as far as possible, these trivial answers which have no interest for the user (see Sect 3. For example, in CLP(R), consider the program: p(x; y) x > y 2 q(x; y) v = x x ^ w = y y 2 p(v; w) r(x) x = y 2 p(x; y) r(x) x = y 2 q(x; y) We obtain the two answers r(x)[x > x] and r(x)[x x > x x] to the goal r(x). According to IR, both answer constraints are unsatisable. The rst one is removed, while the second one is described as maybe. Example 6 go(C; E; S )[C = [00 ; 00; 00 ; 00; 10] ^ S = [10; 10 ] ^ E = [00 ; 10; 10]] is a computed answer to the goal go(C; E; S ). See the following proof, denoted by A , where constraints are simplied for further legibility: at_most_1(C 5,X5 )[C 5=[] X5 =0’] at_most_1(C 4,X4 )[C 4=[1’] X4 =1’] at_most_1(C 3,X3 )[C 3=[0’,1’] X3 =1’] at_most_1(C 2,X2 )[C 2=[0’,0’,1’] X2 =1’] boolean(X’’’)[X’’’=1’] enu(E’’’)[E’’’=[]] at_most_1(C 1,X1 )[C 1=[0’,0’,0’,1’] X1 =1’] boolean(X’’)[X’’=1’] enu(E’’)[E’’=[1’]] at_most_1(C ,X )[C =[0’,0’,0’,0’,1’] X =1’] enu(E’)[E’=[1’,1’]] boolean(X’)[X’=0’] circuit(C,E,S) [C=[0’,0’,0’,0’,1’] S=[1’,1’] E=[0’,1’,1’] enu(E)[E=[0’,1’,1’]] go(C,E,S)[C=[0’,0’,0’,0’,1’] S=[1’,1’] E=[0’,1’,1’] There exists a similar proof, denoted by B , for the computed answer go(C; E; S )[C = [00; 00; 00; 00; 10] ^ S = [10; 10] ^ E = [10; 10; 00]]. From the cover rule stemming from 9A (E = [A; 10; A]) ` fE = [00; 10; 10]; E = [10 ; 10; 00]g and the CONJ property of ` we deduce the answer go(C; E; S )[9A (C = [00 ; 00; 00; 00; 10]^S = [10; 10] ^ E = [A; 10; A])] to the goal go(C; E; S ) and the proof: A B 0 0 0 0 0 go(C; E; S )[9A (C = [0 ; 0 ; 0 ; 0 ; 1 ] ^ S = [10; 10] ^ E = [A; 10; A])] 18 4.3 Correspondance betwwen Proof Trees and Skeletons Given a nite complete skeleton S and a renaming function choice for S , we denote by AP (S; choice) the tree which has exactly the same node that S up to their labels, and which veries the following property: for each node N of AP (S; choice), let N 0 be the corresponding node in S , SN the subtree of S rooted by N 0 and a = head(choice(N 0 )), N is labeled by a[AC (SN )]. Given a proof tree A which only uses program rules, we denote by SQ(A) the tree which has exactly the same node that A up to their labels, and which veries the following property: for each node N of SQ(A), let N 0 be the corresponding node in A, N is labeled by the clause which provides the program rule linking N 0 with its children. 0 0 Lemma 4.3 1. If S is a nite complete skeleton and choice is a renaming function for the skeleton S then AP (S; choice) is a proof tree (only using program rules). 2. If A is a complete proof tree only using program rules and rooted by a[c] then SQ(A) is a nite complete skeleton and AC (SQ(A)) = c. 3. a[c] is a computed answer to the goal a i there exists a nite complete skeleton S such that head(root(S )) = a and AC (S ) = c. Proof. 1. We prove the lemma by induction on the skeleton S . If S is 1 high then it is rooted by the fact a c 2 . From this fact, we deduce the program rule: a[9 c] . AP (S; choice) is the 1 high tree rooted by a[9 a c] a and it is a complete proof tree which only uses the previous program rule. Let us assume that for each complete skeleton S whose height is h and for each renaming function choice for S , AP (S; choice) is a complete proof tree only using program rules. Let S be a (h + 1) high complete skeleton and choice be a renaming mapping for S . We have to show that AP (S; choice) is a complete proof tree only using program rules. Let N be the root of S and a c 2 a ; : : : ; an = choice(N ). The root of S has n children S ; : : : ; Sn which are complete skeletons whose height h. Thus, for each i = 1; : : : ; n, AP (Si; choiceSi ) is a complete proof tree only using program rules (choiceSi is the renaming function for Si deduced from choice). The complete proof trees AP (Si; choiceSi ) are rooted by ai[AC (Si)]. For each i = 1; : : : ; n, we denote by 9 ai ci the constraint AC (Si ). AP (S; choice) is rooted by a[AC (S )]. On the one hand, the clause a c 2 a ; : : : ; an = choice(N ) provides the program rule a[9a [9(9a1 c c] ^ a n [^9 9an cnc] )] . On the other hand, the constraint AC (S ) 1 1 1 1 a 1 a1 1 an n 19 is 9 a (c ^ ^ cn). 9 a (9 a1 c ^ ^ 9 an cn) and 9 a (c ^ ^ cn) are the same constraint because, for each i; j = 1; : : : ; n such that i 6= j , for each node pair Ni of Si and Nj of Sj , the free variables of choice(Ni) which do not occur in ai and the free variables of choice(Nj ) which do not occur in aj are separate, thus 9 ai ci ^ 9 aj cj and 9 ai 9 aj (ci ^ cj ) are the same constraint. Therefore, AP (S; choice) is a complete proof tree only using program rules. It is the tree rooted by the previous program rule and whose root has n children which are the AP (Si; choiceSi ). 1 1 1 2. It is proved by induction on the proof tree A in the same way that the previous proof. 3. It is a consequence of 1. and 2. The connection between proof trees and skeletons being clearly establish (a nite skeleton is in connection with an equivalence class of proof trees), we denes declarative semantics of a program as a constrained atom set called the success set. We distinguish two success set, rst one describes theoretical operational semantics and second one describes declarative semantics. 4.4 Declarative Semantics We dene the semantics of a program as a constrained atom set called the success set. We distinguish two success set, the rst one describes the operational semantics while the second one describes the declarative semantics. Denition 4.4 The success set associated to the program P is SS (P ) = fa[c] j a[c] is a computed answerg. The success set associated to the program P and the cover relation ` is SS`(P ) = fa[c] j a[c] is an answerg. Remark. Let us consider the subset SS `;(P ) of SS (P ) dened by SS `;(P ) = fa[c] j a[c] 2 SS (P ) and not(c ` ;)g, we show that (see [4]) SS ` ;(P ) = SS (P; T ) of [18], SS ` ; (P ) = lfp(SPD ) of [19], SS ` ; (P ) = SS (P; D) of [14]. SS `;(P ) = SSRC (P ) of [4] if the reject criterion RC is ` ;. T D D 3 20 SS (P ) (resp. SS`(P )) is the set dened inductively by program rules (resp. program rules and cover rules). Success sets can also be dened as least xed point of immediate consequence operators linked with the two kinds of rules. Denition 4.5 Let TP , T`, T`[;P et T`;P be the four immediate consequence operators (from constrained atom sets to constrained atom sets), dened by: TP (I ) = fa[c] j there exists a program rule a [c ]; a: :[c:]; an[cn] such that ai [ci] 2 I , for each i = 1; : : : ; ng 0 0 T`(I ) = fa[c] j there exists a cover rule fa[c ] j c 2 C g 1 1 a[c] such that a[c0 ] 2 I , for each constraint c0 2 C g T`[;P (I ) = TP (I ) [ T`(I ) T`;P (I ) = T` (TP (I )) Lemma 4.6 1. lfp(TP ) = TP " ! = SS (P ) 2. SS`(P ) = fa[c] j there exists C , c ` C and a[c0 ] 2 SS (P ), c0 2 C g 3. lfp(T`[;P ) = T` (lfp(TP )) = T`(SS (P )) = SS` (P ) = T`[;P " ! + 1 4. lfp(T`[;P ) = lfp(T`;P ) Proof. 1. Consequence of the Knaster-Tarski's theorem. 2. Lemma is proved by induction on rules distinguishing the two cases corresponding to the two kinds of rules. (a) Let a[9a [cc ^] c ^an[c^n] c ] be a program rule. a n Let us assume that, for each i = 1; : : : ; n, ai[ci] 2 SS`(P ) and there exists a constraint set Ci such that ci ` Ci and, for each constraint c0i 2 Ci, ai[c0i] 2 SS (P ). We have to show that there exists a constraint set C such that 9 a (c^c ^ ^cn ) ` C and, for each c0 2 C , a[c0] 2 SS (P ). The program rule is deduced from the renamed clause a c 2 a ; : : : ; an. Thus, for each n-tuple of constraint c0 ; : : : ; c0n such that, for each i = 1; : : : ; n, 0 0 c0i 2 Ci we have the program rule a[9a [cc ^] c 0 ^an[c^n] c0 ] , consequently a[9 a c ^ a n c0 ^ ^ c0n] 2 SS (P ). 1 1 1 1 1 1 1 1 1 1 21 The CONJ and REFL property of the cover relation guarantees that c ^ c ^ ^ cn ` fc ^ c0 ^ ^ c0n j c0i 2 Ci; for each i = 1; : : : ; ng The EXIS property of the cover relation guarantees that 9 a (c ^ c ^ ^ cn) ` f9 a (c ^ c0 ^ ^ c0n) j c0i 2 Ci; for each i = 1; : : : ; ng Therefore, C = f9 a (c ^ c0 ^ ^ c0n ) j c0i 2 Ci; for each i = 1; : : : ; ng is sucient. 0 0 0 (b) Let fa[c ] aj [cc]2 C g be a cover rule. Let us assume that, for each c0 2 C 0, a[c0] 2 SS`(P ) and there exists a constraint set Cc0 such that c0 ` Cc0 and, for each constraint c00 2 Cc0 , a[c00 ] 2 SS (P ). Then, we have to show that there exists a constraint set C such that c ` C and, for each c00 2 C , a[c00] 2 SS (P ). The cover rule is deduced from c ` C 0. The TRAN property of the cover relation guarantees that [ 0 Cc c` 1 1 1 1 1 0 0 0 c 2C 0 0 0 Thus, C = Sc 2C Cc0 is sucient. 3. The proof is a direct consequence of 1. and 2. 4. It is straightforward to show that for each pair of constrained atom sets I; J if I J then T`;P (I ) T`;P (J ), that is T`;P is monotonous (the rule system associated to this operator can be dened from the composition of program rules with cover rules). Thus T`;P has a least xed point. lfp(T`;P ) T` (lfp(TP )) because the lfp(T`[;P ) = T` (lfp(TP )) and the REFL property of `. lfp(T`;P ) lfp(T`[;P ) because for each ordinal number , there exists an ordinal number such that T`;P " T`[;P " . It is also straightforward to show that: for each constraint set X , T`;P (T`[;P (X )) T`[;P (X ). 0 0 0 The least xed point of TP corresponds to roots of proof trees only using program rules, the least xed point of T`[;P correspond to roots of proof trees and the least xed point of T`;P correspond to roots of proof trees which use program rules at even depth and cover rules at odd depth. For each proof tree, there exists a proof tree with the same conclusion which uses a single cover rule, and this cover rule is used at the proof tree root. Thus, we rediscover well known results when ` is deduced from a domain or a theory. Our answer denition is equivalent to the denition of [29] when ` is deduced from a domain. 22 Equalities of Lemma 4.6 are essential because they assert that, on the one hand, answers dened by covering computed answers and, on the other hand, answers dened by applying alternately program rules and cover rules are exactly all the answers. Equality of these three sets guarantees consistency of denitions and results of Sect. 5. 23 5 Declarative Insuciency Diagnosis This section extends, to CLP, works on declarative error diagnosis for LP based on the Shapiro's method [27, 12, 21, 11, 7, 9]. Answers provided by a program are sometimes symptom of errors in the program. Error diagnosis is error localization when a symptom (wrong answer or missing answer) is observed. We just treat missing answers. Declarative incorrectness diagnosis (wrong answers) is studied in the framework of Sect. 3 [20]. Example 7 In order to illustrate this section, we consider the program DETECT2 which is an erroneous version of program DETECT1 of Ex. 1: go(C,E,S) :circuit(C,E,S), enu(E) {C = [0',0',0',0',1'], S = [1',1']}. circuit(C,E,S) :at_most_1(C,X) {C = [P1,P2,P3,P4,P5], E = [X1,X2,X3], S = [Y1,Y2], X = 1', ~P1 => (U1<=>(X1&X3)), ~P2 => (U2<=>(X2&U3)), ~P3 => (Y1<=>(U1|U2)), ~P4 => (U3<=>(~X1&~X3)), ~P5 => (Y2<=>(~X2&~U3))}. at_most_1(L,X) {L = [], X = 0'}. at_most_1(L,X) :at_most_1(Q,Z) {L = [Y|Q], X = Y|Z, Y&Z = 0'}. boolean(X) {X = 0'}. boolean(X) {X = 1'}. enu(L) {L = []}. enu(L) :boolean(X), enu(Q) {L = [X|Q]}. 24 Answers provided by Prolog III to the goal ?{C {C {C ; ; are: go(C E S) go(C,E,S). = [0',0',0',0',1'], E = [0',1',0'], S = [1',1']} = [0',0',0',0',1'], E = [1',0',1'], S = [1',1']} = [0',0',0',0',1'], E = [1',1',1'], S = [1',1']} Our purpose is to elaborate an algorithm which assists the user, as well as possible, to search, through all the program, errors when an answer is missing. We would like to call the algorithm in the following case: answers to the goal a are c ; : : : ; cm , the constrained atom a[c] is expected but c is not covered by c ; : : : ; cm. 1 1 5.1 Denitions The intended semantics of a program P is formalized by a constrained atom set denoted by I. We say that the program P is nitely incomplete according to I for the atom a if there exists a nite SLD-tree for the goal a whose success constitute the constraint set C and there exists a constraint c such that a[c] 2 I and not(c ` C ). Then, a[c] is called a computed symptom. Thus, a computed symptom is an element of I which is not in T` (lfp(TP )). We recall, once more, that T`(lfp(TP )) = lfp(T`[;P ) = lfp(T`;P ). Example 8 go(C; E; S )[9A (C = [00; 00; 00 ; 00 ; 10 ]^S = [10 ; 10]^E = [A; 10 ; A])] is a computed symptom for the program DETECT2 (see Ex. 6 and Ex. 7). As usual, the problem is easier to solve when we generalize: we will show that a computed symptom is a particular case of an expected constrained atom which is not in lfp(T`;P ). Denition 5.1 1. P is complete (resp. sucient) for the constrained atom a[c] if, for each constraint c0 such that c0 ` fcg and a[c0 ] 2 I , a[c0 ] 2 lfp(T`;P ) (resp. a[c0 ] 2 gfp(T`;P )). 2. a[c] is covered by P according to I if a[c] 2 T`;P (I ). 3. a[c] is completely covered by P according to I if, for each constraint c0 such that c0 ` fcg and a[c0 ] 2 I , a[c0 ] is covered by P according to I . 4. A strong insuciency is a constrained atom a[c] 2 I non covered by P according to I (i.e. a[c] 2 I T`;P (I )). 5. A weak insuciency is a constrained atom a[c] non completely covered by P according to I (i.e. there exists c0 , c0 ` fcg and a[c0 ] is a strong insuciency). 6. a[c] is an incompleteness symptom (resp. insuciency symptom) of P according to I if a[c] 2 I lfp(T`;P ) (resp. a[c] 2 I gfp(T`;P )). 25 The interest is that the denitions (covered/completely covered, strong/weak insuciency, insuciency/incompleteness symptom) are formulated in an uniform framework and extend existing denitions of LP. Thus, they are better understood, particularly thanks to proof trees and T`;P . Particular case of LP is obtained when we change constraints by substitutions and the cover by the single cover \less general". The uniform framework contributes to the comparison between [12] and [11]. Now we can express how symptoms (insuciency symptom and incompleteness symptom) are linked to errors (strong insuciency and weak insuciency). Lemma 5.2 1. If a[c] is a strong insuciency then a[c] is a weak insuciency. 2. There exists a strong insuciency i there exists a weak insuciency. 3. If a[c] is an insuciency symptom then a[c] is an incompleteness symptom. 4. There exists a strong insuciency if there exists an insuciency symptom. Proof. 1. Let a[c] be a strong insuciency, i.e. a[c] 2 I T`;P (I ). If c0 = c then c0 ` fcg and a[c0 ] 2 I but a[c0 ] is not covered by P , thus a[c] is not completely covered by P and a[c] is a weak insuciency. 2. ) is deduced from 1. ( Let a[c] be a weak insuciency, i.e. there exists c0 such that c0 ` fcg, a[c0 ] 2 I and a[c0 ] is not covered by P , thus a[c0] is a strong insuciency. 3. Let a[c] be an insuciency symptom, i.e. a[c] 2 I gfp(T`;P ). lfp(T`;P ) gfp(T`;P ), thus, a[c] is an incompleteness symptom. 4. Let us assume that there is no strong insuciency, thus I T`;P (I ). Therefore I is a post xed point of T`;P , I gfp(T`;P ) and, consequently, there is no insuciency symptom. Lemma 5.2 is essential inasmuch as it expresses links between the dierent notions and shows that if there exists a symptom then there exists an error. The particular case where the error is the symptom establishes the correspondence strong insuciency / insuciency symptom and weak insuciency / incompleteness symptom. Diagnosis algorithm is used when a symptom is observed during a computation. Thus, we show that a computed symptom is a particular case of insuciency symptom (or incompleteness symptom). This particular case corresponds to the existence of a nite SLD-tree for the goal concerning the symptom atom. 26 Lemma 5.3 If there exists a nite SLD-tree for the goal a with success c ; : : : ; cm then there exists an integer k such that, for each constraint c, if a[c] 2 TP # k then c ` ; or c 2 fc ; : : : ; cmg. Proof. Let us assume that there exists a nite SLD-tree for the goal a. Let k0 be the height of this SLD-tree. Each skeleton S for the goal a (rooted by a : : :), such that the depth of the nodes of undef (S ) is > k0, is rejected. From Lemma 4.3 and the previous remark, let c be a constraint, each partial proof tree, only using program rules, rooted by a[c], whose hypotheses depth is > k0, is such that c ` ;. Let c be a constraint such that a[c] is the root of a complete proof tree, only using program rules, whose height is k0 such that, for each i = 1; : : : ; m, c 6= ci. Thus, from Lemma 4.3, there exists a complete skeleton, whose height is k0 , for the question a whose associated constraint is dierent of the answer constraints to the goal a. This contradicts hypotheses on the SLD-tree for a. Constrained atoms of TP # n exactly are the root of proof trees, only using program rules, whose height is n and the root of partial proof trees whose undened nodes (hypothesis) depth is n. So, k = k0 + 1 is sucient. 1 1 Lemma 5.4 For each integer n, if a[c] 2 T`;P # n then there exists C such that c ` C and, for each constraint c0 2 C , a[c0 ] 2 TP # n. Proof. The lemma is proved by induction on the integer n. 1. If a[c] 2 T`;P # 0 then C = fcg is sucient. 2. Let us assume that, for each integer i n, if a[c] 2 T`;P # i then there exists C such that c ` C and, for each constraint c0 2 C , a[c0 ] 2 TP # i. Let a[c] 2 T`;P # n + 1, thus a[c] 2 T` (TP (T`;P # n)). Consequently there exists C such that c ` C and, for each constraint c0 2 C , a[c0] 2 TP (T`;P # n). So, for each constraint c0 2 C , there exists a renamed clause a cc 2 ac1 ; : : : ; acmc such that c0 = 9 a (c0c ^ c0 ^ ^ c0mc ) and, for each i = 1; : : : ; mc , a[c0i] 2 T`;P # n. That is, for each constraint cci , there exists Cci such that cci ` Cci and, for each constraint c0 2 Cci , aci [c0 ] 2 TP # n. On the one hand, the constraint c is such that c ` f9 a (cc ^ c0 ^ ^ c0mc ) j c0 2 C g. On the other hand, for each constraint c0 2 C , for each constraint c0c1 2 Cc1 ; : : : ; c0cmc 2 Ccmc , a[9 a (cc ^ c0c1 ^ ^ c0cmc )] 2 TP # n + 1. The CONJ and REFL properties of the cover relation guarantees that, for each constraint c0 2 C , 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 c0c ^ cc1 ^ ^ c0cmc ` fc0 ^ cc1 ^ ^ c0cmc j c0ci 2 Cci ; i = 1; : : : ; m0cg 0 0 0 0 0 0 0 0 0 The EXIS property of the cover relation guarantees that, for each constraint c0 2 C , 9 a (c0c ^ cc ^ ^ c0cmc ) ` f9 a (c0 ^ cc ^ ^ c0cmc ) j c0ci 2 Cci ; i = 1; : : : ; m0cg 0 1 0 0 1 0 27 0 0 0 0 The TRAN property of the cover relation guarantees that c ` f9 a (c0 ^ cc1 ^ ^ c0cmc ) j c0 2 C; c0ci 2 Cci ; i = 1; : : : ; m0cg 0 0 0 0 0 C = f9 a (c0 ^ cc1 ^ ^ c0cmc ) j c0 2 C; c0ci 2 Cci ; i = 1; : : : ; m0cg is sucient. 0 0 0 0 0 Lemma 5.5 If a[c] 2 T`;P # ! and there exists a nite SLD-tree for the goal a with success c ; : : : ; cm then there exists C fc ; : : : ; cm g such that c ` C (i.e. a[c] 2 SS`(P )). Proof. Let a[c] 2 T`;P # ! such that there exists a nite SLD-tree for a with success 1 1 c ; : : : ; cm. Lemma 5.4 shows that, for each integer n, there exists Cn0 such that c ` Cn0 and, for each constraint c0 2 Cn0 , a[c0] 2 TP # n. Lemma 5.3 guarantees that there exists k such that, for each constraint c0, if a[c0] 2 TP # k then c ` ; or there exists 1 i m such that c0 = ci. C = Ck0 is sucient. 1 Lemma 5.6 If a[c] is a computed symptom then a[c] is an insuciency symptom. Proof. Let a[c] be a computed symptom. If a[c] is not an insuciency symptom then a[c] 2 gfp(T`;P ), thus a[c] 2 T`;P # ! and, from Lemma 5.5, c is covered by the answer constraints to the question a. This is not possible because a[c] is a computed symptom. Thus, a[c] is an insuciency symptom. Consequently, if there exists a computed symptom then there exists a strong insuciency and a weak insuciency (regardless of the computation rule). It emerges from this that there exists two families of denitions concerning missing answers. The two families exists in LP and constraint introduction makes clear subtleties in their dierences. We fully understand these dierences thanks to T`;P , because its least xed point is equal to T` (lfp(TP )) (the two sets are proved equal to lfp(T`[;P )) and because there is not the single cover property any more. It is interesting to note that T`;P has been selected in the denitions, whereas it is not the most natural to dene SS` (P ). We emphasize that, in general, gfp(T`;P ) 6= T`(gfp(TP )) 6= gfp(T`[;P ). In LP, two algorithm families are associated to the two denition families. Algorithms of [27, 12] (strong insuciency) provide an error notion more precise than algorithms of [11] (weak insuciency), but oracle interaction is more complicated. Indeed, for [27, 12], oracle answers to query by substitutions (variable instantiation) while, for [11], it just answers yes or no. 2 2 As usual, the intended semantics interaction is formalized by the concept of oracle. 28 5.2 Diagnosis Algorithm Now, we propose an algorithm inspired from [11]. The input is a computed symptom according to the standard strategy and the output is a weak insuciency. Thus oracle just answers yes or no while it has to answer by constraint in an algorithm which searches a strong insuciency. The search forest for p(~x)[c] consists of a tree for each non-unary clause R 2 P of the packet of p such that if p(~x) c 2 b ; : : : ; bn is a variant of R then not(c ^ 9 x c ` ;). The tree is rooted by hb ; c ^ 9 x ci. Let hbi; cii be a node of the tree and C = fVc 2SSbi c00 j SSbi = fc00 j bi [c00] is an answer and not(c00 ^ ci ` ;)gg then, for each c0 2 C , hbi; cii, has a node 1 1 1 1 1 ~ ~ 00 labeled by hbi ; c0i if i < n; labeled by h2; c0i if i = n. +1 We call incompleteness question for the node N labeled by hbi; cii: \Is there exist c0 such that a[c0 ] 2 I , c0 ` fcig, not(c0 ` fc00 j hx; c00 i labels a child of N g)?" Let a[c] be the algorithm input, we ask incompleteness question for nodes labeled by hbi; cii (bi 6= 2) of the search forest of a[c]. If the answer is yes then the algorithm is recursively called with bi [9 bi ci]. If the answer is no for every node then the algorithm terminates with output a[c] which is a weak insuciency. Remark. Incompleteness questions of our algorithm are nite because the input is a computed symptom (i.e. the standard SLD-tree is nite). Example 9 Insuciency diagnosis session for the program DETECT2. Constraint are simplied by Prolog III. Symptom: go(C; E; S )[9A(C = [00; 00; 00; 00; 10] ^ E = [A; 10; A] ^ S = [10; 10])] Is there exist a constraint c such that go(C; E; S )[c] expected, c ` f9A(C = [00 ; 00; 00; 00; 10] ^ E = [A; 10; A] ^ S = [10; 10])g and not(c ` ;)? YES Is there exist a constraint c such that circuit(C; E; S )[c] expected, c ` f9A(C = [00; 00; 00; 00; 10] ^ E = [A; 10; A] ^ S = [10; 10])g and not(c ` ;)? YES Is there exist a constraint c such that at most 1(C; X )[c] expected, c ` fC = [00; 00; 00; 00; 10] ^ X = 10g and not(c ` fC = [00; 00; 00; 00; 10] ^ X = 10g)? NO Error: circuit(C; E; S )[9A(C = [00; 00; 00; 00; 10] ^ E = [A; 10; A] ^ S = [10; 10])] The algorithm has isolated a denition which is responsible for the symptom. Error is due to the denition of circuit (XOR has been coded by NOT OR). 29 6 Conclusion We reformulate operational semantics and declarative semantics of constraint logic programs in a uniform formal framework. Thus, computed answers and declarative answers are straightforwardly linked through an abstract cover relation. Program semantics can be dened in reference to a model or a theory, and it can also take into account incompleteness of constraint solvers. The interest of this novel semantics is to study error diagnosis. We have dened insuciency symptoms and incompleteness symptoms and the two associated kinds of errors in a uniform framework contributing to their comparison. The diagnosis algorithm behave as an intelligent trace. It follows the straight path toward the error and generate only relevant information. It provides a limited piece of erroneous code (a predicate denition) which makes correction easier. The algorithm of Sect. 5.2 assume that the symptom is computed by the standard strategy. In accordance with Lemma 5.6 and 5.2, it would be interesting to have an algorithm which does not depend on the computation rule used to compute the symptom. Since the two families of symptoms and errors are dened in a single framework, we can nd algorithms in which they collaborate (to combine straightforward query and more precise errors). Some programs have the form: go(~x) big constraint 2 . Then, we observe an incompleteness symptom go(~x)[c] and we call our diagnosis algorithm which provide the error go(~x)[c]. It is not very interesting! We can discuss the programming methodology and prefer a better structured program: in general, it is more straightforward to cut a problem in easier subproblem: : : but it is not the matter. Debugging the big constraint has no mean in our framework: constraint predicates are assumed to be correct. Concerning this program, there exists a symptom because the programmer has made an error when he wrote the big constraint. It is certainly possible to say more than go(~x)[c] is an error. The aim is to elaborate appropriate formal ways based on a semantics of the variables of the constraint. More and more CLP systems, for practical purpose, use approximations of the possible domain values of the variables. Approximations contains all the answers but eventually other values (i.e. the answer constraint is covered by the approximation). They are, for example, intervals on continuous domain (CLP(BNR), Prolog IV) or (nite) discrete domain (CLP(FD), CHIP). Works in progress consist in taking into account approximations in our framework. Approximations have similar properties to cover relations. We could take advantage of the analogies in dening new symptom and error notions. 30 References [1] Peter Aczel. An Introduction to Inductive Denitions, chapter 7, pages 739{782. In J. Barwise, editor, Handbook of Mathematical Logic. North-Holland Publishing Company, 1977. [2] Frederic Benhamou. Boolean Algorithms in Prolog III. In Alain Colmerauer and Frederic Benhamou, editors, Constraint Logic Programming: Selected Research, chapter 17, pages 307{326. MIT Press, 1993. [3] Michel Bergere. Approche declarative du diagnostic d'erreur pour la programmation en logique avec negation. PhD thesis, Universite d'Orleans, 1991. [4] Michel Bergere, Gerard Ferrand, Francois Le Berre, Bernard Malfon, and Alexandre Tessier. La Programmation Logique avec Contraintes revisitee en termes d'arbres de preuve et de squelettes. Technical Report 95/06, LIFO, University of Orleans, 1995. [5] Philippe Codognet. Programmation logique avec contraintes : une introduction. In Journees Francophones de Programmation en Logique, volume 14 of Technique et Science Informatique, pages 665{692. Hermes, 1995. [6] Alain Colmerauer. An Introduction to Prolog III. Communications of the ACM, 33(7):69{90, 1990. [7] Marco Comini, Giorgio Levi, and Giuliana Vitiello. Abstract Debugging of Logic Programs. In Laurent Fribourg and F. Turini, editors, Logic Program Synthesis and Transformation and Metaprogramming, volume 883 of Lecture Notes in Computer Science, pages 440{450. Springer-Verlag, 1994. [8] Marco Comini, Giorgio Levi, and Giuliana Vitiello. Declarative Diagnosis Revisited. In John Lloyd, editor, International Logic Programming Symposium, Logic Programming, pages 275{287. MIT Press, 1995. [9] Marco Comini, Giorgio Levi, and Giuliana Vitiello. Ecient Detection of Incompleteness Errors in the Abstract Debugging of Logic Programs. In Mirelle Ducasse, editor, Automated and Algorithmic Debugging, pages 159{174. IRISA-CNRS, 1995. [10] Pierre Deransart and Jan Maluszynski. A Grammatical View of Logic Programming. MIT Press, 1993. [11] Wlodek Drabent, Simin Nadjm-Tehrani, and Jan Maluszynski. Algorithmic Debugging with Assertions. In Harvey Abramson and M. H. Rogers, editors, Meta-Programming in Logic Programming, pages 501{522. MIT Press, 1989. [12] Gerard Ferrand. Error Diagnosis in Logic Programming: an adaptation of E. Y. Shapiro's method. Journal of Logic Programming, 4:177{198, 1987. 31 [13] Gerard Ferrand. The Notions of Symptom and Error in Declarative Diagnosis of Logic Programs. In Automated and Algorithmic Debugging, volume 749 of Lecture Notes in Computer Science, pages 40{57. Springer-Verlag, 1993. [14] Maurizio Gabbrielli and Giorgio Levi. Modeling answer constraints in Constraint Logic Programs. In Vijay A. Saraswat and K. Ueda, editors, International Conference on Logic Programming, pages 238{252. MIT Press, 1991. [15] Roberto Giacobazzi, Saumya K. Debray, and Giorgio Levi. A Generalized Semantics for Constraint Logic Programs. In International Conference on Fifth Generation Computer Systems, pages 581{591, 1992. [16] Roberto Giacobazzi, Saumya K. Debray, and Giorgio Levi. Generalized Semantics and Abstract Interpretation for Constraint Logic Programs. Journal of Logic Programming, 25(3):191{248, 1995. [17] Nevin C. Heintze, Joxan Jaar, Spiro Michaylov, Peter J. Stuckey, and Roland H.C. Yap. The CLP(R) Programmer's Manual Version 1.2. IBM Thomas J. Watson Research Center, 1992. [18] Joxan Jaar and Jean-Louis Lassez. Constraint Logic Programming. In 14th ACM Symposium on Principles of Programming Languages, pages 111{119. ACM, 1987. [19] Joxan Jaar and Michael J. Maher. Constraint Logic Programming: a survey. Journal of Logic Programming, 19-20:503{581, 1994. [20] Francois Le Berre and Alexandre Tessier. Declarative Incorrectness Diagnosis in Constraint Logic Programming. In Joint Conference on Declarative Programming, 1996. [21] John W. Lloyd. Declarative Error Diagnosis. New Generation Computing, 5:133{154,, 1987. [22] John W. Lloyd. Foundations of Logic Programming. Springer-Verlag, second edition, 1987. [23] Michael J. Maher. A Logic Programming view of CLP. In Warren, editor, International Conference on Logic Programming, pages 737{753. MIT Press, 1993. [24] Simin Nadjm-Tehrani. Contributions to the Declarative Approach to Debugging Prolog Programs. PhD thesis, Linkoping University, 1989. [25] Vijay A. Saraswat. The Category of Constraint Systems is Cartesian-Closed. In Logic In Computer Science. IEEE Press, 1992. [26] Vijay A. Saraswat, Martin Rinard, and Prakash Panangaden. Semantic foundations of concurrent constraint programming. In Symposium on Principles of Programming Languages, pages 333{352. ACM Press, 1991. 32 [27] Ehud Y. Shapiro. Algorithmic Program Debugging. ACM Distinguished Dissertation. MIT Press, 1982. [28] Pascal Van Hentenryck. Constraint Satisfaction in Logic Programming. Logic Programming. MIT Press, 1989. [29] Pascal Van Hentenryck. Constraint Logic Programming. Knowledge Engineering Review, 6(3):151{194, 1991. 33