3 VIAM, Ivane Javakhishvili Tbilisi State University, Georgia. 4 West University of Timisoara, Romania. Abstract. We describe the semantics of CLP(H): constraint ...
Constraint Logic Programming for Hedges: A Semantic Reconstruction Besik Dundua1,3 , M´ ario Florido1 , Temur Kutsia2 , and Mircea Marin4 1
DCC-FC & LIACC, University of Porto, Portugal RISC, Johannes Kepler University, Linz, Austria VIAM, Ivane Javakhishvili Tbilisi State University, Georgia 4 West University of Timi¸soara, Romania 2
3
Abstract. We describe the semantics of CLP(H): constraint logic programming over hedges. Hedges are finite sequences of unranked terms, built over variadic function symbols and three kinds of variables: for terms, for hedges, and for function symbols. Constraints involve equations between unranked terms and atoms for regular hedge language membership. We give algebraic semantics of CLP(H) programs, define a sound, terminating, and incomplete constraint solver, and describe some fragments of constraints for which the solver returns a complete set of solutions.
1
Introduction
Hedges are finite sequences of unranked terms. These are terms in which function symbols do not have a fixed arity: The same symbol may have a different number of arguments in different places. Manipulation of such expressions has been intensively studied in recent years in the context of XML processing, rewriting, automated reasoning, knowledge representation, just to name a few. When working with unranked terms, variables that can be instantiated with hedges (hedge variables) are a pragmatic necessity. In (pattern-based) programming, hedge variables help to write neat, compact code. Using them, for instance, one can extract duplicates from a list with just one line of a program. Several languages and formalisms operate on unranked terms and hedges. The programming language of Mathematica [21] is based on hedge pattern matching. Languages such as Tom [1], Maude [2], ASF+SDF [19] provide capabilities similar to hedge matching (via associative functions). ρLog [17] extends logic programming with hedge transformation rules. XDuce [13] enriches untyped hedge matching with regular expression types. The Constraint Logic Programming schema has been extended to work with hedges in CLP(Flex) [3], which is a basis for the XML processing language XCentric [5] and a Web site verification language VeriFLog [4]. The goal of this paper is to describe a precise semantics of constraint logic programs over hedges. We consider positive CLP programs with two kinds of primitive constraints: equations between hedges, and membership in a hedge regular language. Function symbols are unranked. Predicate symbols have a fixed
arity. Terms may contain three kinds of variables: for terms (term variables), for hedges (hedge variables), and for function symbols (function symbol variables). Moreover, we may have function symbols whose argument order does not matter (unordered symbols): a kind of generalization of the commutativity property to unranked terms. As it turns out, such a language is very flexible and permits to write short, yet quite clear and intuitive code: One can see examples in Sect. 2. We call this language CLP(H), for CLP over hedges. It generalizes CLP(Flex) with function variables, unordered functions, and membership constraints. Hence, as a special case, our paper describes the semantics of CLP(Flex). Moreover, as hedges generalize strings, CLP(H) can be seen also as a generalization of CLP over strings CLP(S) [18], string processing features of Prolog III [6], and CLP over regular sets of strings CLP(Σ∗ ) [20]. Note that some of these languages allow an explicit size factor for string variables, restricting the length of strings they can be instantiated with. We do not have size factors, but can express this information easily with constraints. For instance, to indicate the fact that a hedge variable x can be instantiated with a hedge of minimal length 1 and maximal length 3, we can write a disjunction . . . x = x ∨ x = (x1 , x2 ) ∨ x = (x1 , x2 , x3 ), where the lower case x’s are term variables. Flexibility and the expressive power of CLP(H) has its price: Equational constraints with hedge variables, in general, may have infinitely many solutions [15]. Therefore, any complete equational constraint solving procedure with hedge variables is nonterminating. The solver we describe in this paper is sound and terminating, hence incomplete for arbitrary constraints. However, there are fragments of constraints for which it is complete, i.e., computes all solutions. One such fragment is so called well-moded fragment, where variables in one side of equations (or in the left hand side of the membership atom) are guaranteed to be instantiated with ground expressions at some point. This effectively reduces constraint solving to hedge matching (which is known to be NP-complete [16]), plus some early failure detection rules. Another fragment for which the solver is complete is named after the Knowledge Interchange Format, KIF [12], where hedge variables are permitted only in the last argument positions. We identify forms of CLP(H) programs which give rise to well-moded or KIF constraints. We can easily model lists with ordered function symbols and multisets with the help of unordered ones. In fact, since we may have several such symbols, we can directly model colored multisets. Constraint solving over lists, sets, and multisets has been intensively studied, see, e.g., [10] and references there, and the CLP schema can be extended to accommodate them. In our case, an advantage of using hedge variables in such terms is that hedge variables can give immediate access to collections of subterms via unification. It is very handy in programming. The paper is organized as follows: We start with motivating examples in Sect. 2. In Sect. 3 we describe the syntax of CLP(H). Sect. 4 is about semantics. The constraint solver is introduced in Sect. 5. The operational semantics of CLP(H) is described in Sect. 6. In Sect. 7, we introduce well-moded and KIF fragments of CLP(H) programs, for which the constraint solver is complete. Due to space restrictions, proofs of technical lemmas are put in the report [11].
2
Motivating Examples
In this section we show how to write programs in CLP(H). For illustration, we chose two examples: the rewriting of terms from some regular hedge language and an implementation of the recursive path ordering with status. Example 1. The general rewriting mechanism can be implemented with two CLP(H) clauses: The base case r ewrite(x, y) ← rule(x, y) and the recursive case r ewrite(X(x, x, y), X(x, y, y)) ← rewrite(x, y), where x, y are term variables, x, y are hedge variables, and X is a function symbol variable. It is assumed that there are clauses which define the rule predicate. The base case says that a term x can be rewritten to y if there is a rule which does it. The recursive case rewrites a nondeterministically selected subterm x of the input term to y, leaving the context around it unchanged. Applying the base case before the recursive case gives the outermost strategy of rewriting, while the other way around implements the innermost one. An example of the definition of the rule predicate is . . r ule(X(x1 , x2 ), X(y)) ← x1 in f (a∗ ) · b∗ , x1 = (x, z), y = (x, f (z)), where the constraint5 x1 in f (a∗ )·b∗ requires x1 to be instantiated by hedges from the language generated by the regular hedge expression f (a∗ ) · b∗ (that is, from the language {f, f (a), f (a, a), . . . , (f, b), (f (a), b), . . . , (f (a, . . . , a), b, . . . , b), . . .}). With this program, the goal ← rewrite(f (f (f (a, a), b)), x) has two answers: {x 7→ f (f (f (a, a), f ))} and {x 7→ f (f (f (a, a), f (b)))}. Example 2. The recursive path ordering (rpo) >rpo is a well-known term ordering [8] used to prove termination of rewriting systems. Its definition is based on a precedence order on function symbols, and on extensions of >rpo from terms to tuples of terms. There are two kinds of extensions: lexicographic >lex rpo , when mul terms in tuples are compared from left to right, and multiset >rpo , when terms in tuples are compared disregarding the order. The status function τ assigns to each function symbol either lex or mul status. Then for all (ranked) terms s, t, we define s >rpo t, if s = f (s1 , . . . , sm ) and 1. either si = t or si >rpo t for some si , 1 ≤ i ≤ m, or 2. t = g(t1 , . . . , tn ), s >rpo ti for all i, 1 ≤ i ≤ n, and either τ (f ) (a) f g, or (b) f = g and (s1 , . . . , sn ) >rpo (t1 , . . . , tn ). To implement this definition in CLP(H), we use the predicate rpo for >rpo between two terms, and four helper predicates: rpo all to implement the comparison s >rpo ti for all i; prec to implement the comparison depending on the precedence; ext to implement the comparison with respect to an extension of >rpo ; and status to give the status of a function symbol. The predicate lex implements >lex rpo and 5
In the notation defined later, strictly speaking, we need to write this constraint as f (a(eps)∗ ) · b(eps)∗ , where eps is the regular expression for the empty hedge. However, for brevity and clarity of the presentation we omit eps here.
mul implements >mul rpo . The symbol hi is an unranked function symbol, and {} is an unordered unranked function symbol. As one can see, the implementation is rather straightforward and closely follows the definition. >rpo requires four clauses, since there are four alternatives in the definition: 1. rpo(X (x , x , y), x ). 2a.
rpo(X (x , x , y), y) ← rpo(x , y).
rpo(X (x ), Y (y)) ← rpo all (X (x ), hyi), prec(X , Y ).
2b. rpo(X (x ), X (y)) ← rpo all (X (x ), hyi), ext(X (x ), X (y)). rpo all is implemented with recursion: rpo all (x , h i).
rpo all (x , hy, yi) ← rpo(x , y), rpo all (x , hyi).
The definition of prec as an ordering on finitely many function symbols is straightforward. More interesting is the definition of ext: ext(X (x ), X (y)) ← status(X , lex ), lex (hx i, hyi). ext(X (x ), X (y)) ← status(X , mul ), mul ({x }, {y}). status can be given as a set of facts, lex needs one clause, and mul requires three: lex (hx , x , yi, hx , y, z i) ← rpo(x , y). mul ({x , x }, {x , y}) ← mul ({x }, {y}). mul ({x , x }, {}). mul ({x , x }, {y, y}) ← rpo(x , y), mul ({x , x }, {y}). That’s all. This example illustrates the benefits of all three kinds of variables we have and unordered function symbols.
3
Preliminaries
For common notation and definitions, we mostly follow [14]. The alphabet A consists of the following pairwise disjoint sets of symbols: – – – – – –
VT : term variables, denoted by x, y, z, . . ., VH : hedge variables, denoted by x, y, z, . . ., VF : function variables, denoted by X, Y, Z, . . ., Fu : unranked unordered function symbols, denoted by fu , gu , hu , . . ., Fo : unranked ordered function symbols, denoted by fo , go , ho , . . ., P: ranked predicate symbols, denoted by p, q, . . ..
The sets of variables are countable, while the sets of function and predicate symbols are finite. In addition, A also contains . – The propositional constants true and false, the binary equality predicate =, and the unranked membership predicate in. – Regular operators: eps, ·, +, ∗. – Logical connectives and quantifiers: ¬, ∨, ∧, →, ↔, ∃, ∀.
– Auxiliary symbols: parentheses and the comma. Function symbols, denoted by f, g, h, . . ., are elements of the set F = Fu ∪ Fo . A variable is an element of the set V = VT ∪ VH ∪ VF . A functor, denoted by F , is a common name for a function symbol or a function variable. We define terms, hedges, and other syntactic categories over A as follows: t ::= x | f (H) | X(H) T ::= t1 , . . . , tn
(n ≥ 0)
h ::= t | x H ::= h1 , . . . , hn
Term Term sequence Hedge element
(n ≥ 0)
Hedge
We denote the set of terms by T (F, V) and the set of ground (variable-free) terms by T (F). For readability, we put parentheses around hedges, writing, e.g., (f (a), x, b) instead of f (a), x, b. The empty hedge is written as . Besides the letter t, we use also r and s to denote terms. Two hedges are disjoint if they do not share a common element. For instance, (f (a), x, b) and (f (x), f (b, f (a))) are disjoint, whereas (f (a), x, b) and (f (b), f (a)) are not. An atom is a formula of the form p(t1 , . . . , tn ), where p ∈ P is an n-ary predicate symbol. Atoms are denoted by A. Regular hedge expressions R are defined inductively: R ::= eps | (R · R) | R + R | R∗ | f (R) where the dot · stands for concatenation, + for choice, and ∗ for repetition. . Primitive constraints are either term equalities = (t1 , t2 ) or membership for . hedges in(H, R). They are written in infix notation, such as t1 = t2 , and H in R. . . . . Instead of F1 () = F2 () and fo (H1 ) = fo (H2 ) we write F1 = F2 and H1 = H2 . respectively. We denote the symmetric closure of the relation = by '. A literal L is an atom or a primitive constraint. Formulas are defined as usual. A constraint is an arbitrary first-order formula built over true, false, and primitive constraints. The set of free variables of a syntactic object O is denoted by var (O). We let ∃V N denote the formula ∃v1 · · · ∃vn N , where V = {v1 , . . . , vn } ⊂ V. ∃V N denotes ∃var (N )\V N . We write ∃N (resp. ∀N ) for the existential (resp. universal) closure of N . We refer to a language over the alphabet A as L(A). A substitution is a mapping from term variables to terms, from hedge variables to hedges, and from function variables to functors, such that all but finitely many term, hedge, and function variables are mapped to themselves. Substitutions extend to terms, hedges, literals, conjunction of literals. A (constraint logic) program is a finite set of rules of the form ∀(L1 ∧· · ·∧Ln → A), usually written as A ← L1 , . . . , Ln , where A is an atom and L1 , . . . , Ln are literals (n ≥ 0). A goal is a formula of the form ∃(L1 ∧ · · · ∧ Ln ), n ≥ 0, usually written as L1 , . . . , Ln . We say a variable is solved in a conjunction of primitive constraints K = c1 ∧ · · · ∧ cn , if there is a ci , 1 ≤ i ≤ n, such that . – the variable is x, ci = x = t, and x occurs neither in t nor elsewhere in K, or
. – the variable is x, ci = x = H, and x occurs neither in H nor elsewhere in K, or . – the variable is F , ci = X = F and X occurs neither in F nor elsewhere in K, or – the variable is x, ci = x in f (R) and x does not occur in membership constraints elsewhere in K, or – the variable is x, ci = x in R, x does not occur in membership constraints elsewhere in K, and R has the form R1 · R2 or R∗1 . In this case we also say that ci is solved in K. Moreover, K is called solved if for any 1 ≤ i ≤ n, ci is solved in it. K is partially solved, if for any 1 ≤ i ≤ n, ci is solved in K, or has one of the following forms: – Membership atom: • fu (H1 , x, H2 ) in fu (R). • (x, H) in R where R has a form R1 · R2 or R∗1 . – Equation: . • (x, H1 ) = (y, H2 ) where x 6= y, H1 6= and H2 6= . . 6 , and T = 6 . The variables • (x, H1 ) = (T, y, H2 ), where x 6∈ var (T ), H1 = x and y are not necessarily distinct. . • fu (H1 , x, H2 ) = fu (H3 , y, H4 ) where (H1 , x, H2 ) and (H3 , y, H4 ) are disjoint. A constraint is solved, if it is either true or a non-empty quantifier-free disjunction of solved conjunctions. A constraint is partially solved, if it is either true or a non-empty quantifier-free disjunction of partially solved conjunctions.
4
Semantics
For a given set S, we denote by S ∗ the set of finite, possibly empty, sequences of elements of S, and by S n the set of sequences of length n of elements of S. The empty sequence of symbols from any set S is denoted by . Given a sequence s = (s1 , s2 , . . . , sn ) ∈ S n , we denote by perm(s) the set of sequences {(sπ(1) , sπ(2) , . . . , sπ(n) ) | π is a permutation of {1, 2, . . . , n}}. A structure S for a language L(A) is a tuple hD, Ii made of a non-empty carrier set of individuals and an interpretation function I that maps each function symbol f ∈ F to a function I(f ) : D∗ → D, and each n-ary predicate symbol p ∈ P to an n-ary relation I(p) ⊆ Dn . Moreover, if f ∈ Fu then I(f )(s) = I(f )(s0 ) for all s ∈ D∗ and s0 ∈ perm(s). A variable assignment for such a structure is a function with domain V that maps term variables to elements of D, hedge variable to elements of D∗ , and function variables to functions from D∗ to D. The interpretations of our syntactic categories w.r.t. a structure S = hD, Ii and variable assignment σ is shown below. The interpretations [[H]]S,σ of hedges (including terms) is defined as follows (v ∈ VT ∪ VH ): [[(H1 , . . . , Hn )]]S,σ := ([[H1 ]]S,σ , . . . , [[Hn ]]S,σ ),
[[v]]S,σ := σ(v),
[[f (H)]]S,σ := I(f )([[H]]S,σ ),
[[X(H)]]S,σ := σ(X)([[H]]S,σ ).
Note that terms are interpreted as elements of D and hedges as elements of D∗ . We may omit σ and write simply [[E]]S for the interpretation of a ground expression E. The interpretation of regular expressions is defined as follows: [[eps]]S := {}, [[R1 + R2 ]]S := [[R1 ]]S ∪ [[R2 ]]S ,
[[f (R)]]S := {I(f )(H) | H ∈ [[R]]S }, [[R1 · R2 ]]S := {(H1 , H2 ) | H1 ∈ [[R1 ]]S , H2 ∈ [[R2 ]]S },
[[R∗ ]]S := [[R]]∗S .
Primitive constraints are interpreted w.r.t. a structure S and variable assignment . σ as follows: S |=σ t1 = t2 iff [[t1 ]]S,σ = [[t2 ]]S,σ ; S |=σ H in R iff [[H]]S,σ ∈ [[R]]S ; and S |=σ p(t1 , . . . , tn ) iff I(p)([[t1 ]]S,σ , . . . , [[tn ]]S,σ ) holds. The notions S |= N for validity of an arbitrary formula N in S, and |= N for validity of N in any structure are defined in the standard way. An intended structure is a structure I with the carrier set T (F) and interpretations I defined for every f ∈ F by I(f )(H) := f (H). Thus, intended structures identify terms and hedges by themselves. Also, if R is any regular hedge expression then [[R]]I is the same in all intended structures, and will be denoted by [[R]]. Other remarkable properties of intended structures I are: Variable assignments . are substitutions, I |=ϑ t1 = t2 iff t1 ϑ = t2 ϑ, and I |=ϑ H in R iff Hϑ ∈ [[R]]. Given a program P , its Herbrand base BP is, naturally, the set of all atoms p(t1 , . . . , tn ), where p is an n-ary user-defined predicate in P and (t1 , . . . , tn ) ∈ T (F)n . Then an intended interpretation of P corresponds uniquely to a subset of BP . An intended model of P is an intended interpretation of P that is its model. We will write shortly H-structure, H-interpretation, H-model for intended structures, interpretations, and models, respectively. As usual, we will write P |= G if G is a goal which holds in every model of P . Since our programs consist of positive clauses, the following facts hold: 1. Every program P has a least H-model, which we denote by lm(P, H). 2. If G is a goal then P |= G iff lm(P, H) is a model of G. A partially solved form of a constraint C 1 is a constraint C2 such that C2 is partially solved and I |= ∀ C1 ↔ ∃var (C1 ) C2 for any H-structure I. A ground substitution ϑ is a H-solution (or simply solution) of a constraint C if I |= Cϑ for all H-structures I. The notation |=H C stands for I |= C for all H-structures I. Theorem 1. If the constraint D is solved, then I |= ∃D holds. . . Proof. Since D is solved, each disjunct K in it has a form v1 = e1 ∧ · · · ∧ vn = en ∧ 0 v10 in R1 ∧ · · · ∧ vm in Rm where m, n ≥ 0, vi , vj0 ∈ V and ei is an expression 0 corresponding to vi . Moreover, v1 , . . . , vn , v10 , . . . , vm are distinct and [[Rj ]] 6= ∅ for 0 all 1 ≤ j ≤ m. Assume σi is a grounding substitution for ei for all 1 ≤ i ≤ n, and let e0j be an element of [[Rj ]] for all 1 ≤ j ≤ m. Then σ = {v1 7→ e1 σ10 , . . . , vn 7→ 0 en σn0 , v10 7→ e01 , . . . , vm 7→ e0m } solves K. Therefore, I |= ∃D holds.
5
Solver
We consider constraints in DNF: K1 ∨ · · · ∨ Kn , where K’s are conjunctions of of true, false, and primitive constraints. The solver defined below transforms a constraint into a partially solved form. The solver is formulated in a rule-based way. The number of rules is not small (as it is usual for such kind of solvers, cf., e.g., [9, 7]). To make their comprehension easier, we group them so that similar ones are collected together in subsections. Within each subsection, for better readability, they are put in frames. In the rules, K stands for a maximal conjunction of primitive constraints. The rules are applied in any context. 5.1
Rules
Logical Rules. There are eight logical rules which are applied at any depth in constraints, modulo associativity and commutativity of disjunction and conjunction. N stands for any formula. We denote the whole set of rules by Log. N ∧N
N
false ∧ N
N ∨N
N
false false ∨ N
. H=H
true
true ∧ N
true, if ∈ [[R]] true ∨ N
N in R
N true
Failure Rules. The first two rules perform occurrence check, rules (F3) and (F5) detect function symbol clash, and rules (F4), (F6), (F7) detect inconsistent primitive constraints. We denote the set of rules (F1)–(F7) by Fail. (F1) x ' (H1 , F (H), H2 ) (F2) x ' (H1 , t, H2 )
false, if x ∈ var (H).
false, if x ∈ var (H1 , t, H2 ).
(F3) f1 (H1 ) ' f2 (H2 )
false, if f1 6= f2 .
(F4) ' (H1 , t, H2 )
false.
(F5) f1 (H) in f2 (R)
false, if f1 6= f2 .
(F6) in R (F7)
false, if 6∈ [[R]],
(H1 , t, H2 ) in eps
false.
Decomposition Rules. Each of the decomposition rules operates on a conjunction of constraint literals and gives back either a conjunction of constraint literals again, or constraints in DNF. We denote the set of rules (D1) and (D2) by Dec. (D1) fu (H) ' fu (T ) ∧ K
_
. H = T0 ∧ K ,
T 0 ∈perm(T )
where H and T are disjoint. . . (D2) (t1 , H1 ) ' (t2 , H2 ) t1 = t2 ∧ H1 = H2 , where H1 6= or H2 6= . Deletion Rules. These rules delete identical terms or hedge variables from both sides of an equation. We denote this set of rules by Del.
(Del1)
(x, H1 ) ' (x, H2 )
. H1 = H2 .
. (Del2) fu (H1 , h, H2 ) ' fu (H3 , h, H4 ) fu (H1 , H2 ) = fu (H3 , H4 ). . . (Del3) x ' H1 , x, H2 H1 = ∧ H2 = , if H1 6= . Variable Elimination Rules. These rules eliminate variables from the given constraint keeping only a solved equation for them. They apply to disjuncts. The first two rules replace a variable with the corresponding expression, provided that the occurrence check fails: (E1) x ' t ∧ K
. x = t ∧ Kϑ,
where x 6∈ var (t), x ∈ var (K) and ϑ = {x 7→ t}. If t is a variable then in addition it is required that t ∈ var (K). . x = H ∧ Kϑ, (E2) x ' H ∧ K where x 6∈ var (H), x ∈ var (K), and ϑ = {x 7→ H}. If H = y for some y, then in addition it is required that y ∈ var (K). The next two rules (E3) and (E4) assign to a variable an initial part of the hedge in the other side of the selected equation. The hedge has to be a sequence of terms T in the first rule. The disjunction in the rule is over all possible splits of T . In the second rule, only a split of the prefix T of the hedge is relevant and the disjunction is over all such possible splits of T . The rest is blocked by the term t due to occurrence check: No instantiation of x can contain it.
(E3) (x, H) ' T ∧ K
_
. . x = T1 ∧ Hϑ = T2 ∧ Kϑ ,
T =(T1 ,T2 )
where x 6∈ var (T ), ϑ = {x 7→ T1 }, and H 6= . _ . . (E4) (x, H1 ) ' (T, t, H2 ) ∧ K x = T1 ∧ H1 ϑ = (T2 , t, H2 )ϑ ∧ Kϑ T =(T1 ,T2 )
where x 6∈ var (T ), x ∈ var (t), ϑ = {x 7→ T1 }, and H1 6= . Finally, there are three rules for function variable elimination. Their behavior is standard: (E5) X ' F ∧ K
. X = F ∧ Kϑ,
where X 6= F , X ∈ var (K), and ϑ = {X 7→ F }. If F is a function variable, then in addition it is required that F ∈ var (K). . . (E6) X(H1 ) ' F (H2 ) ∧ K X = F ∧ F (H1 )ϑ = F (H2 )ϑ ∧ Kϑ. where X 6= F , ϑ = {X 7→ F }, and H1 6= or H2 6= . _ . . (E7) X(H1 ) ' X(H2 ) ∧ K X = f ∧ f (H1 )ϑ = f (H2 )ϑ ∧ Kϑ , f ∈F
where ϑ = {X 7→ f }, and H1 6= H2 .
We denote the set of rules (E1)–(E7) by Elim. Membership Rules. The membership rules apply to disjuncts of constraints in DNF, to preserve the DNF structure. They provide the membership check, if the hedge H in the membership atom H in R is ground. Nonground hedges require more special treatment as one can see. To solve membership constraints for term sequences of the form (t, H) with t a term, we rely on the possibility to compute the linear form of a regular expression, that is, to express it as a finite sum of concatenations of regular hedge expressions that identify all plausible membership constraints for t and H. Formally, the linear form of a regular expression R, denoted lf (R), is a finite set of pairs (f (R1 ), R2 ) called monomials, which is defined recursively as follows: lf (eps) = ∅.
lf (R∗ ) = lf (R) R∗ .
lf (f (R)) = {(f (R), eps)}.
lf (R1 + R2 ) = lf (R1 ) ∪ lf (R2 ). lf (R1 · R2 ) = lf (R1 ) R2 , if ∈ / [[R1 ]]. lf (R1 · R2 ) = lf (R1 ) R2 ∪ lf (R2 ), if ∈ [[R1 ]]. These equations involve an extension of concatenation that acts on a linear form and a regular expression and returns a linear form. It is defined as l eps = l, and l R = {(f (R1 ), R2 · R) | (f (R1 ), R2 ) ∈ l, R2 = 6 eps} ∪ {(f (R1 ), R) | (f (R1 ), eps) ∈ l}, if R 6= eps. The rules are as follows: (M1)
(x1 , . . . , xn ) in eps ∧ K
. ∧ni=1 xi = ∧ Kϑ,
where ϑ = {x1 7→ , . . . , xn 7→ }, n > 0. _ (M2) (t, H) in R ∧ K t in f (R1 ) ∧ H in R2 ∧ K , (f (R1 ),R2 )∈lf (R)
where H 6= and R 6= eps. (M3)
(x, H) in f (R) ∧ K . . x in f (R) ∧ H = ∧ K ∨ x = ∧ H in f (R) ∧ K , where H 6= .
(M4) t in R∗
t in R.
t in R1 ∧ in R2 ∧ K ∨ in R1 ∧ t in R2 ∧ K . (M6) t in R1 + R2 ∧ K t in R1 ∧ K ∨ t in R2 ∧ K . (M7) (x, H) in R1 + R2 ∧ K (x, H) in R1 ∧ K ∨ (x, H) in R2 ∧ K . (M5) t in R1 · R2 ∧ K
(M8) v in R1 ∧ v in R2
v in R, where v ∈ VT ∪ VH , [[R]] = [[R1 ]] ∩ [[R2 ]].
Next, we have rules which constrain singleton hedges to be in a term language. They proceed by the straightforward matching or decomposition of the structure.
Note that in (M12), we require the arguments of the unordered function symbol to be terms. (M10) and (M9) do not distinguish whether f is ordered or unordered: . x = x ∧ x in f (R) ∧ K{x 7→ x}, where x is fresh. . (M10) X(H) in f (R) ∧ K X = f ∧ f (H){X 7→ f } in f (R) ∧ K{X 7→ f }. (M9) x in f (R) ∧ K
(M11) fo (H) in fo (R)
H in R.
(M12) fu (T ) in fu (R) ∧ K
_
T 0 in R ∧ K .
T 0 ∈perm(T )
We denote the set of rules (M1)–(M12) by Memb. 5.2
The Constraint Solving Algorithm
In this section, unless otherwise stated, by a constraint we mean a formula K1 ∨ · · · ∨ Kn , where K’s are conjunctions of true, false, and primitive constraints. First, we define the rewrite step step := first(Log, Fail, Del, Dec, Elim, Memb). When applied to a constraint, step transforms it by the first applicable rule of the solver, looking successively into the sets Log, Fail, Del, Dec, Elim, and Memb. The constraint solving algorithm implements the strategy solve defined as a computation of a normal form with respect to step: solve := NF(step). That means, step is applied to a constraint repeatedly as long as possible. It remains to show that this definition yields an algorithm, which amounts to proving that a constraint to which none of the rules Log, Fail, Del, Dec, Elim, and Memb applies, is produced by NF(step) for any constraint C. Theorem 2 (Termination of solve). solve terminates on any input constraint. Proof (Sketch). We define a complexity measure cm(C) for quantifier-free constraints in DNF, and show that cm(C 0 ) < cm(C) holds whenever C 0 = step(C). For a hedge H (resp. regular expression R), we denote by size(H) (resp. by size(R)) its denotational length, e.g., size(eps) = 1, size(f (f (a)), x) = 4, and size(f (f (a · b∗ ))) = 6. The complexity measure cm(K) of a conjunction of primitive constraints K is the tuple hN1 , M1 , N2 , M2 , M3 i defined as follows ({||} stands for a multiset): – N1 is the number of unsolved variables in K. – M1 := {|size(H) | H in R ∈ K, H 6= |}. – N2 is the number of primitive constraints in the form v in R where v ∈ V plus the number of primitive constraints in the form x in R in K . – M2 := {|size(R) | H in R ∈ K|}.
. – M3 := {|size(t1 ) + size(t2 ) | t1 = t2 ∈ K|}. The complexity measure cm(C) of a constraint C = K1 ∨ · · · ∨ Kn is defined as {|cm(K1 ), . . . , cm(Kn )|}. Measures are compared by the multiset extension of the lexicographic ordering on tuples. The Log rules strictly reduce the measure. For the other rules, the table below shows which rule reduces which component of the measure, which implies termination of the algorithm solve. Rule (M1),(M10),(E1)–(E7) (F5),(F7),(M2),(M3), (M11), (M12) (M8), (M9) (F6),(M4)–(M7) (D1), (D2), (F1)–(F4), (Del1)–(Del3)
N1 > ≥ ≥ ≥ ≥
M1 N2 M2 M3 > ≥ > ≥ ≥ > ≥ ≥ ≥ >
The next lemma is needed to prove that the solver reduces a constraint to its equivalent constraint: Lemma 1. If step(C) = D, then |=H ∀ C ↔ ∃var (C) D . Theorem 3. If solve(C) = D, then |=H ∀ C ↔ ∃var (C) D and D is a partially solved form of C. Proof. |=H ∀ C ↔ ∃var (C) D follows from Lemma 1 and the following property: If |=H ∀ C1 ↔ ∃var (C1 ) C2 and |=H ∀ C2 ↔ ∃var (C2 ) C3 , then |=H ∀ C1 ↔ ∃var (C1 ) C3 . The property itself relies on the fact that |=H ∀ ∃var (C1 ) ∃var (C2 ) C3 ↔ ∃var (C1 ) C3 , which holds because all variables introduced by the rules of the solver in C3 are fresh not only for C2 , but also for C1 . As for the partially solved form, by the definition of solve and Theorem 2, D is in a normal form. Assume by contradiction that it is not partially solved. By inspection of the solver rules, based on the definition of partially solved constraints, we can see that there is a rule that applies to D. But this contradicts the fact that D is in a normal form. Hence, D is partially solved. By Lemma 1, we conclude that D is a partially solved form of C.
6
Operational Semantics of CLP(H)
In this section we describe the operational semantics of CLP(H), following the approach for the CLP schema given in [14]. A state is a pair hG k Ci, where G is the sequence of literals and C = K1 ∨ · · · ∨ Kn , where K’s are conjunctions of true, false, and primitive constraints. The definition of an atom p(t1 , . . . , tm ) in program P , defn P (p(t1 , . . . , tm )), is the set of rules in P such that the head of each rule has a form p(r1 , . . . , rm ). We assume that defn P each time returns fresh variants. A state hL1 , . . . , Ln k Ci can be reduced with respect to P as follows: Select a literal Li . Then:
– If Li is a primitive constraint literal and solve(C ∧ Li ) 6= false, then it is reduced to hL1 , . . . , Li−1 , Li+1 , . . . , Ln k solve(C ∧ Li )i. – If Li is a primitive constraint literal and solve(C ∧ Li ) = false, then it is reduced to h k falsei. – If Li is an atom p(t1 , . . . , tm ), then it is reduced to . . hL1 , . . . , Li−1 , t1 = r1 , . . . , tm = rm , B, Li+1 , . . . , Ln k Ci for some (p(r1 , . . . , rm ) ← B) ∈ defn P (Li ). – If Li is a atom and defn P (Li ) = ∅, then it is reduced to h k falsei. A derivation from a state S in a program P is a finite or infinite sequence of states S0 S1 · · · Sn · · · where S0 is S and there is a reduction from each Si−1 to Si , using rules in P . A derivation from a goal G in a program P is a derivation from hG k truei. The length of a (finite) derivation of the form S0 S1 · · · Sn is n. A derivation is finished if the last goal cannot be reduced, that is, if its last state is of the form h k Ci where C is partially solved or false. If C is false, the derivation is said to be failed.
7
Well-Moded and KIF Programs
In this section we consider syntactic restrictions that lead to well-moded and KIF style CLP(H) programs. They are interesting, because the constraints that appear in derivations for such programs can be completely solved by solve. 7.1
Well-Moded Programs
A mode for an n-ary predicate symbol p is a function mp : {1, . . . , n} −→ {i, o}. If mp (i) = i (resp. mp (i) = o) then the position i is called an input (resp. . output) position of p. The predicates in and = have only output positions. For . a literal L = p(t1 , . . . , tn ) (where p can be also in or =), we denote by invar (L) and outvar (L) the sets of variables occurring in terms in the input and output positions of p. A sequence of literals L1 , . . . , Ln is well-moded if the following hold: Si−1 1. For all 1 ≤ i ≤ n, invar (Li ) ⊆ j=1 outvar (Lj ). Si−1 . 2. If for some 1 ≤ i ≤ n, Li is t1 = t2 , then var (t1 ) ⊆ j=1 outvar (Lj ) or Si−1 var (t2 ) ⊆ j=1 outvar (Lj ). 3. If for some 1 ≤ i ≤ n, Li is a membership atom, then the inclusion var (Li ) ⊆ Si−1 j=1 outvar (Lj ) holds. A conjunction of literals G is well-modedV if there exists a well-moded sen quence of literals L1 , . . . , Ln such that G = i=1 Li modulo associativity and commutativity. A formula in DNF is well-moded if each of its disjuncts is. A state hL1 , . . . , Ln k K1 ∨· · ·∨Kn i is well-moded, where K’s are conjunctions of true, false, and primitive constraints, if the formula (L1 ∧· · ·∧Ln ∧K1 )∨· · ·∨(L1 ∧· · ·∧Ln ∧Kn ) is well-moded. A clause A ← L1 , . . . , Ln is well-moded if the following hold:
Si−1 1. For all 1 ≤ i ≤ n, invar (Li ) ⊆ j=1 outvar (Lj ) ∪ invar (A). Sn 2. outvar (A) ⊆ j=1 outvar (Lj ) ∪ invar (A). Si−1 . 3. If for some 1 ≤ i ≤ n, Li is H1 = H2 , then var (H1 ) ⊆ j=1 outvar (Lj ) ∪ Si−1 invar (A) or var (H2 ) ⊆ j=1 outvar (Lj ) ∪ invar (A). 4. If for some 1 ≤ i ≤ n, Li is a membership atom, then outvar (Li ) ⊆ Si−1 j=1 outvar (Lj ) ∪ invar (A). A program is well-moded if all its clauses are well-moded. Example 3. In Example 1, if the first argument is the input position and the second argument is the output position in the user-defined predicates, it is easy to see that the program is well-moded. In Example 2, for well-modedness we need to define both positions in the user-defined predicates to be the input ones. Well-modedness is preserved by program derivation steps: Lemma 2. Let P be a well-moded CLP(H) program and hG k Ci be a well-moded state. If hG k Ci hG0 k C 0 i is a reduction using clauses in P , then hG0 k C 0 i is also a well-moded state. The solver reduces well-moded constrains either to a solved form of to false: Lemma 3. Let C be a well-moded constraint and solve(C) = C 0 , where C 0 6= false. Then C 0 is solved. The theorem below is the main theorem for well-moded CLP(H) programs. It states that any finished derivation from a well-moded goal leads to a solved constraint or to a failure: Theorem 4. Let hG k truei · · · h k C 0 i be a finished derivation with respect to a well-moded CLP(H) program, starting from a well-moded goal G. If C 0 6= false, then C 0 is solved. Proof. We prove a more general statement: Let hG k truei · · · hG0 k C 0 i be a derivation with respect to a well-moded program, starting from a well-moded goal G and ending with G0 that is either or consists only of atomic formulas without arguments (propositional constants). If C 0 6= false, then C 0 is solved. To prove this statement, we use induction on the length n of the derivation. When n = 0, then C 0 = true and it is solved. Assume the statement holds when the derivation length is n, and prove it for the derivation with the length n + 1. Let such a derivation be hG k truei · · · hGn k Cn i hGn+1 k Cn+1 i. There are two possibilities to make the last step: 1. Gn has a form (modulo permutation) L, p1 , . . . , pn , where L is primitive constraint, the p’s are propositional constants, Gn+1 = p1 , . . . , pn , and Cn+1 = solve(Cn ∧ L). 2. Gn has a form (modulo permutation) q, p1 , . . . , pn , where q and p’s are propositional constants, Gn+1 = p1 , . . . , pn , and Cn+1 = Cn .
In the first case, note that by Lemma 2, hGn k Cn i is well-moded. Since the p’s have no influence on well-modedness (they are just propositional constants), Cn ∧ L is well-moded. By Lemma 3 we get that if Cn+1 = solve(Cn ∧ L) 6= false then Cn+1 is solved. In the second case, since Gn consists of propositional constants only, by the induction hypothesis we have that if Cn is not false, then it is solved. But Cn = Cn+1 . It finishes the proof. 7.2
Programs in the KIF Form
A term is in the KIF form (KIF-term) if hedge variables occur only below ordered function symbols,6 and they occupy only the last argument position in each subterm where they appear. For example, the term fo (x, fo (a, x), fu (x, b), x) is in the KIF form, while fo (x, a, x), fu (x, fo (a, x), fu (x, b), x) are not. A hedge (T, h) is in the KIF form, if T is a sequence of KIF-terms and h is either a KIF-term or a hedge variable. . An atom p(t1 , . . . , tn ) (including t1 = t2 ) is in the KIF form, if each ti , 1 ≤ i ≤ n, is a KIF-term. A membership atom H in R is in the KIF-form, if H is a KIF-hedge. A CLP(H) program is in the KIF form, if it is constructed from literals in the KIF form. Note that the programs in examples 1 and 2 are not KIF programs. One could rewrite them in this form, but the code size would become a bit larger. The notion of KIF form extends naturally to constraints and states, requiring that all their literals should be in the KIF form. KIF-programs, like well-moded ones discussed above, also show a good behavior. As the lemmas below state, reductions preserve the KIF form and the solver is complete: Lemma 4. Let P be a CLP(H) program in the KIF form and hG k Ci be a KIFstate. If hG k Ci hG0 k C 0 i is a reduction using clauses in P , then hG0 k C 0 i is also a KIF-state. Lemma 5. Let C be a KIF-constraint and solve(C) = C 0 , where C 0 6= false. Then C 0 is solved. We illustrate how to solve a simple KIF constraint: . Example 4. Let C = f (x, x) = f (g(y), a, y) ∧ x in a(eps)∗ ∧ y in a(eps) · a(b(eps)∗ )∗ . Then solve performs the following derivation: C
2
. . x = g(y) ∧ x = (a, y) ∧ (a, y) in a(eps)∗ ∧ y in a(eps) · a(b(eps)∗ )∗ . . x = g(y) ∧ x = (a, y) ∧ y in a(eps)∗ ∧ y in a(eps) · a(b(eps)∗ )∗ . . x = g(y) ∧ x = (a, y) ∧ y in a(eps) · a(eps)∗
The obtained constraint is solved. 6
If the language does not contain unordered function symbols, then hedge variables are permitted under function symbols as well.
The theorem below is the main theorem for KIF programs and can be proved similarly to the analogous theorem for well-moded programs (Theorem 4). It states that any finished derivation from a KIF-goal with respect to a KIF-program leads to a solved constraint or to a failure: Theorem 5. Let hG k truei · · · h k C 0 i be a finished derivation with respect to a CLP(H) program in the KIF form, starting from a KIF-goal G. If C 0 6= false, then C 0 is solved.
8
Conclusion
We defined a semantics for CLP(H) programs and introduced a solver for positive equational and membership constraints over hedges. The solver, in general, is incomplete. It is natural, since hedge unification is infinitary. We identified two special cases of CLP(H) programs which lead to constraints, for which the solver computes a complete set of solutions.
Acknowledgments This research has been partially supported by LIACC through Programa de Financiamento Plurianual of the Funda¸c˜ao para a Ciˆencia e Tecnologia (FCT), by the FCT fellowship (ref. SFRH/BD/62058/2009), by the Austrian Science Fund (FWF) under the project SToUT (P 24087-N18), and the Rustaveli Science Foundation under the grants DI/16/4-120/11 and FR/611/4-102/12.
References 1. E. Balland, P. Brauner, R. Kopetz, P.-E. Moreau, and A. Reilles. Tom: Piggybacking rewriting on Java. In Proc. RTA’07, volume 4533 of LNCS, pages 36–47. Springer, 2007. 2. M. Clavel, F. Dur´ an, S. Eker, P. Lincoln, N. Mart´ı-Oliet, J. Meseguer, and C. L. Talcott, editors. All About Maude - A High-Performance Logical Framework, How to Specify, Program and Verify Systems in Rewriting Logic, volume 4350 of Lecture Notes in Computer Science. Springer, 2007. 3. J. Coelho and M. Florido. CLP(Flex): constraint logic programming applied to XML processing. In R. Meersman and Z. Tari, editors, CoopIS/DOA/ODBASE (2), volume 3291 of LNCS, pages 1098–1112. Springer, 2004. 4. J. Coelho and M. Florido. VeriFLog: a constraint logic programming approach to verification of website content. In H. T. Shen, J. Li, M. Li, J. Ni, and W. Wang, editors, APWeb Workshops, volume 3842 of LNCS, pages 148–156. Springer, 2006. 5. J. Coelho and M. Florido. XCentric: logic programming for XML processing. In I. Fundulaki and N. Polyzotis, editors, WIDM, pages 1–8. ACM, 2007. 6. A. Colmerauer. An introduction to Prolog III. Commun. ACM, 33(7):69–90, 1990. 7. H. Comon. Completion of rewrite systems with membership constraints. Part II: constraint solving. J. Symb. Comput., 25(4):421–453, 1998.
8. N. Dershowitz. Orderings for term-rewriting systems. Theor. Comput. Sci., 17:279– 301, 1982. 9. A. Dovier, C. Piazza, E. Pontelli, and G. Rossi. Sets and constraint logic programming. ACM Trans. Program. Lang. Syst., 22(5):861–931, 2000. 10. A. Dovier, C. Piazza, and G. Rossi. A uniform approach to constraint-solving for lists, multisets, compact lists, and sets. ACM Trans. Comput. Log., 9(3), 2008. 11. B. Dundua, M. Florido, T. Kutsia, and M. Marin. Constraint logic programming for hedges: A semantic reconstruction. RISC Report Series 14-02, RISC, University of Linz, Austria, 2014. 12. M. R. Genesereth and R. E. Fikes. Knowledge Interchange Format, Version 3.0 Reference Manual. Technical Report Logic-92-1, Stanford University, Stanford, CA, USA, 1992. 13. H. Hosoya and B. C. Pierce. Regular expression pattern matching for XML. J. Funct. Program., 13(6):961–1004, 2003. 14. J. Jaffar, M. J. Maher, K. Marriott, and P. J. Stuckey. The semantics of constraint logic programs. J. Log. Program., 37(1-3):1–46, 1998. 15. T. Kutsia. Solving equations with sequence variables and sequence functions. J. Symb. Comput., 42(3):352–388, 2007. 16. T. Kutsia and M. Marin. Solving, reasoning, and programming in Common Logic. In SYNASC, pages 119–126. IEEE Computer Society, 2012. 17. M. Marin and T. Kutsia. Foundations of the rule-based system ρlog. Journal of Applied Non-Classical Logics, 16(1-2):151–168, 2006. 18. A. Rajasekar. Constraint logic programming on strings: Theory and applications. In SLP, page 681, 1994. 19. M. van den Brand, A. van Deursen, J. Heering, H. A. de Jong, M. de Jonge, T. Kuipers, P. Klint, L. Moonen, P. A. Olivier, J. Scheerder, J. J. Vinju, E. Visser, and J. Visser. The ASF+SDF meta-environment: A component-based language development environment. In R. Wilhelm, editor, CC, volume 2027 of Lecture Notes in Computer Science, pages 365–370. Springer, 2001. 20. C. Walinsky. CLP(Σ∗ ): constraint logic programming with regular sets. In G. Levi and M. Martelli, editors, ICLP, pages 181–196. MIT Press, 1989. 21. S. Wolfram. The Mathematica book. Wolfram-Media, fifth edition, 2003.