2.1 Facts ............................................. 2
2.2 Rules ............................................. 3
2.3 Queries ........................................... 4
3 Prolog 4
3.1 Syntax ............................................ 4
3.2 SLDResolution ....................................... 5
3.3 Lists ............................................. 5
3.4 Recursion .......................................... 5
3.5 is ............................................... 5
3.6 Cut ............................................. 6
3.7 Negation ........................................... 7
3.8 FlowofControl ....................................... 7
3.8.1 ClauseOrder .................................... 7
3.8.2 GoalOrder ..................................... 8
Logic programs are an axiomatization of a problem space. This axiomatization entails a set of logical consequences, which gives meaning to the logic program and solves the problem.
Rather than being derived from the von Neumann machine model and instruction set by a series of abstractions and reorganizations,[logicprogramming] isderivedfrom an abstract model, which has no direct relation to or dependence on one machine model or another. 1
Beforedelvinginto thedetails of thePrologprogramminglanguage(one specificlogicprogramming implementation), we define the general terminology and conceptual tools of logic programming.
A logic program is a knowledge base of facts and rules.
A predicate describes a relation among objectsin a set. In the simplest case, the objectsin the set are referred to by constants, and a predicate expresses a relationship among objects by relating constants. Some simple examples of the use of predicates and constants in logic programming follow:
plus(0,0,0). plus(2,3,5). plus(10,20,30).
older(michael,amy). older(michael,merrie). older(amy,merrie).
mother(anne,keith). mother(piggy,gonzo). mother(barbara,georgejr).
father(henry,keith). father(patrick,henry). father(georgesr,georgejr).
In this sample logic program, plus, older, mother, and father are predicates; and 0, 2, 3, 5, 10, 20, 30, etc. are constants. Togetherpredicates and constants(or, moregenerally, terms) comprise atomic formulas, which are called goals in logic programming. A goal followed by a period is a fact. We read the facts in the above logic program as “2 plus 3 is 5;” “michael is older than merrie;” “piggy is the mother of gonzo;” and so on.
A logic program embodies a knowledge base as well as a specific interpretation. The terms of a logicprogramdefineitsdomain, and thepredicatesgiveit aninterpretation. Thedomain D of the sample program is given by:
D = {0, 2, 3, 5, 10, 20, 30, michael, amy, merrie,
anne, keith, piggy, gonzo, patrick, henry,
barbara, georgesr, georgejr, true, false}
The mapping M describes the interpretation of the predicates:
plusM = {(0, 0, 0), (0, 1, 1), (1, 0, 1), (0, 2, 2), (2, 0, 2), (0, 3, 3), (3, 0, 3),...}
olderM = {(michael, amy), (michael, merrie), (amy, merrie),...} motherM = {(anne, keith), (piggy, gonzo), (barbara, georgejr)} fatherM = {(henry, keith), (patrick, henry), (georgesr, georgejr)}
The domain of a logic program always includes the atoms true and false. Facts are truths: the meaning of a fact in any domain of interpretation is true. The sample logic program defines the truths “Henry isthefatherofKeith;” “PatrickisthefatherofHenry;” “Georgesenioristhefather ofGeorgejunior,” and so on.
A rule in a logic program is a predicate defined in terms of other predicates. For example,
parent(X, Y )← father(X, Y ).
is a rule that defines the parent predicate in terms of the father predicate. This rule reads “X is a parent of Y just in case X is the father of Y .” In this context, X and Y are variables, or placeholders,asin first-orderlogic. Byconvention,variablesbeginwith capitallettersand constants begin with lowercase letters.
Rules in a logic program are expressed as Horn clauses in normal form:
newrule(X1 ,...,Xn)← oldrule1(Y1 ,...,Ym),..., oldruleK(Z1 ,...,Zl).
The goal on the left hand side of ← is called the head of a rule and the goals on the right hand side of ← constitute the body of a rule. Commas between goals indicate conjunction.
In order to define a disjunctive predicate, additional rules are necessary: e.g.,
parent(X, Y )← mother(X, Y ). parent(X, Y )← father(X, Y ).
Together these rules state that “X is a parent of Y just in case X is the mother of Y or X is the father of Y .” A set of rules with the same predicate on the left hand side of ← is called a procedure.
By convention, all variablesinalogicprogramareuniversallyquantified, exceptforthosevariables that appears only in the body of a rule, which can be understood to be existentially quantified. For example, the rule
grandson(X, Y )← parent(Y, Z), parent(Z, X), male(X).
expresses all ofthefollowing the(equivalent) logicalformulas:
| ∀X, Y, Z (parent(Y, Z)∧ parent(Z, X)∧ male(X))→ grandson(X, Y ) | |
|---|---|
| iff | ∀X, Y, Z ¬(parent(Y, Z)∧ parent(Z, X)∧ male(X))∨ grandson(X, Y ) |
| iff | ∀X, Y, Z (¬parent(Y, Z)∨ ¬parent(Z, X)∨ ¬male(X))∨ grandson(X, Y ) |
| iff | ∀X, Y ¬(∃Z ¬(¬parent(Y, Z)∨ ¬parent(Z, X)∨ ¬male(X))∨ grandson(X, Y ) |
| iff | ∀X, Y ¬(∃Z parent(Y, Z)∧ parent(Z, X)∧ male(X))∨ grandson(X, Y ) |
| iff | ∀X, Y ∃Z (parent(Y, Z)∧ parent(Z, X)∧ male(X))→ grandson(X, Y ) |
A query is a goal followed by a question mark. It retrieves information from a logic program, by asking the question: is the goal true: i.e., is the goal a logical consequence of the program? Given the logic program of Section 2.1, the queries
father(henry,keith) ?
father(patrick,keith) ?
are interpreted as true and false, respectively. Conjunctive queries evaluate a logical conjunction of goals. For example,
father(henry,keith), mother(anne,keith) ?
is a conjunctive query. This query evaluates to true iff both goals are true in the context of the current logic program.
Variables in queries are existentially quantified. Thus, the query
mother(X,keith) ?
asks the question “does there exists an object that is the mother of keith?” Logic programs derive all such X that satisfy the relation described by the query.
Why is it that variables in logic programming queries are existentially quantified? The answer is that these variables appear only in the body of a procedure. In particular, the query
mother(X,keith) ?
is an abbreviation for
false ← mother(X,keith)
Prolog was developed by Alain Comerauer and his group at the University of Marseilles-Aix in 1973. It was originally written in Fortran. The name Prolog is an abbreviation for Programmation en Logique. But no Prolog implementation is yet to achieve the ideals of logic programming. To minimize space complexity, Prolog generates search trees in a depth-first manner; thus, it is not complete. To minimize time complexity, Prolog skips occurs checks; thus, it is not sound.
The syntax of Prolog looks much like the logic programming syntax presented in the first half of this lecture, except that Prolog uses the digraph :-to represent logical implication, rather than
←. Here is some additional Prolog terminology: a clause is a rule with n goals in the body;a unit clause is a clause s.t. n =0: i.e., a unit clause is a fact; an iterative clause is a clause s.t. n =1. A program is a set of clauses.
Clause selection in Prolog is performed in a depth-first backtracking SLD fashion. SLD stands for Selecting aliteral, using aLinear strategy, restricted toDefinite(i.e.,Horn) clauses. Inperforming resolution, a Prolog interpreter evaluates the first goal in the body of a rule, resolves that rule and evaluatesthe firstgoal of thenewrule. Thisdepth firstprocessproceedsuntil aboundliteral is found or a goal is unable to be proven. When a goal fails, the Prolog interpreter backs up to the last point where a decision was made. This will be that last point a variable was assigned. If additional assignments are possible, the variable is reassigned and resolution is repeated with the new variable assignment.
Lists are a built-in Prolog data structure, with multiple syntactic variations. The canonical representation of a list is simply .(H,T ), where H is the head of the list and T is the tail. A more convenient syntax is the element syntax denoted [H|T ]. In this syntax, the empty list is denoted by the symbol []. The three columns in the following table present three alternative Prolog representations of lists. The third one is the most common because it is the easiest to read.
| .(a, []) | [a|[]] | [a] |
| .(a, (b, [])) | [a|[b|[]] | [a, b] |
| .(a, (b, X)) | [a|[b|X]] | [a, b|X] |
Recursion is the primary means of flow control in logic programs. The following example of recursiveprogramminginProlog implements arithmetic operations. By definition, a natural number is either 0, or the successor function s() applied to a natural number. For example, the number 1 is represented by s(0). The following Prolog code defines natural numbers, addition, and multiplication. Thethreepredicates, natural
number, plus, and times are alldefined recursively.
natural_number(0).
natural_number(s(X)) :-natural_number(X).
plus(0,X,X) :-natural_number(X).
plus(s(X),Y,s(Z)):-plus(X,Y,Z).
times(0,X,0) :-natural_number(0).
times(s(X),Y,Z) :-times(X,Y,XY), plus(XY,Y,Z).
Prologprovides standardarithmetic operators as well as an assignment operator is(Value, Expression). The is operator is true if the result of Value unifies with Expression. Expression must have an arithmetic value.
?-X is 4+ 3* 2. ?-A is -1, Xis A +1. ?-X is A+ 1, Ais -1.
The first query is true: set X = 10. In the second query, the variable A is bound to −1 prior to being its evaluation in the expression A +1; thus, this query is also true: set X = 0. In the thirdquery, however, the variable A is not bound at the time the is predicate is evaluated. Prolog produces an error if an Expression without an arithmetic value is passed to the is predicate.
The cut predicate, denoted !, provides logic programmers with an explicit means of flow control. In particular, the cut predicate prevents backtracking.
Given a Prolog clause, say p(X) :-q(X), !, r(X)., if q(X) succeeds, and the cut predicate is encountered, then:
Consider the following program, which succeeds if its third argument contains the minimum of its first two arguments:
minimum(X,Y,X) :-X < Y, !. minimum(X,Y,X) :-X is Y, !. minimum(X,Y,Y) :-X > Y, !.
This program has the same semantics as the minimum program without cuts. But the first cut prevents evaluation of the second clause once it is determined that X<Y , and the second cut prevents evaluation of the third clause once it is determined that X ≤ Y . The following example presents an incorrect use of the cut predicate, since the query error(0,1,1) succeeds in this program:
error(X,Y,X) :-X < Y, !. error(X,Y,X) :-X is Y, !. error(X,Y,Y).
If the use of the cut predicatedoes not alterthe meaning of theprogramthenitis called a green cut. Green cuts improve efficiency. Cuts that are not green are called red cuts. Red cuts can be used to implement an if-then-else statement:
if_then_else(P,Q,R) :-P, !, Q. if_then_else(P,Q,R) :-R.
Red cuts are also used to avoid backtracking, if only a single solution is desired. The following version of member succeeds when the first occurrence of X appears in the list, but it does not backtrack to search for additional occurrences of X likethe cut-free version(seeSection3.8):
member(X,[X|Xs]) :-!. member(X,[Y|Ys]) :-member(X,Ys).
If a query fails, then the goal is not a logical consequence of a program. Failure does not imply that the negated form of the goal is a logical consequence of the program. Prolog makes use of a closed-world-assumption, however, under which this implication holds. Interpreting the lack of a proof a formula as proof of its negation is called negation as finite failure.
Negation is implemented in Prolog by the fail predicate, which always fails. Using ! and fail, negation is achieved as follows:
not_f(X) :-f(X), !, fail. not_f(X).
This program succeeds only if f(X) fails. The second clause, which always succeeds, is evaluated only if f(X) fails for all X. Some Prolog implementations include a built-in predicate not, which provides the same functionality.
Prolog evaluates clausesinaprocedurefromtop tobottom, andgoalsinaclausefromlefttoright. Efficient Prolog programs exploit these orderings.
The following Prolog program defines the member relation.
member(X,[X|Xs]). member(X,[Y|Ys]) :-member(X,Ys).
In this implementation, the query member(a,[a,b,c,d,a]) ? unifies with the first rule and succeeds immediately. But consider the following implementation of membership in which the clause ordering is reversed.
member(X,[Y|Ys]) :-member(X,Ys). member(X,[X|Xs]).
The same query, member(a,[a,b,c,d,a]) ?, does not succeed until the entire list has been processed, and the final a is discovered in the unrolling of the recursion stack.
member(a,[a,b,c,d,a]) ? member(a,[a|b,c,d,a]) :-member(a,[b,c,d,a]). member(a,[b|c,d,a]) :-member(a,[c,d,a]). member(a,[c|d,a]) :-member(a,[d,a]). member(a,[d|a]) :-member(a,[a]). member(a,[a]) :-member(a,[]). member(a,[a]).
Thesecondtolast statementintheabovecomputationfails. Afterbacktracking,the finalstatement resolves with the second rule.
One definition of the son relation is presented below, in two ways, using two competing goal orderings. The first ruledefines X tobe a son of Y if X is a child of Y and X is male. The second rule defines X tobe a son of Y if X is male and X is a child of Y .
son(X,Y) :-child(X,Y), male(X). son(X,Y) :-male(X), child(X,Y).
Typically, the set of males is larger than the set of children of any parent. Thus, the first goal ordering, which asks only whether the children of Y are male, is more efficient than the second, which asks whether any male is a child of Y .
4 Documentation
Documentation for the SICStus Prolog system is available at:
http://www.sics.se/isl/sicstuswww/site/documentation.html
The current (as of February 2002) version of SICStus Prolog on the Brown CS server is 3.8.5. Documentation for this version can be found at :
http://www.sics.se/isl/sicstus/docs/3.8.5/html/sicstus.html
References
[1] Sterling,Leon&Shapiro,Ehud(1994) TheArt ofProlog,MITPress.