Prolog Tutorial
Prolog Tutorial
Syntax
Prolog programs are constructed from terms : constants, variables, or structures. Constants can be either atoms or numbers: Atoms are strings of characters starting with a lowercase letter or enclosed in apostrophes. Numbers are strings of digits with or without a decimal point and a minus sign. Variables are strings of characters beginning with an uppercase letter or an underscore. Structures consist of a functor or function symbol, which looks like an atom, followed by a list of terms inside parentheses, separated by commas. Structures can be interpreted as predicates (relations): likes(john,mary). male(john). sitsBetween(X,mary,helen). Figure A.1 depicts the following structure as trees:
person(name('Kilgore','Trout'),date(november,11,1922)) tree(5, tree(3,nil,nil), tree(9,tree(7,nil,nil),nil))
COMP780 Semantics
Prolog
A Prolog program is a sequence of statements clauses of the form P0 :- P1, P2, , Pn. where each of P0, P1, , Pn is an atom or a structure. A period terminates every clause. A clause can be read declaratively as P0 is true if P1 and P2 Pn are true or procedurally as
To satisfy goal P0, satisfy goal P1 and then P2 and then and then Pn.
P0 is the head goal; the conjunction of goals P1, P2, , Pn is the body of the clause. A clause without a body P. is a unit clause or fact and means P is true. or goal P is satisfied. A clause without a head, ?- P1, P2, , Pn. is a goal clause or query and means Are P1 and P2 and Pn true? or Satisfy goal P1 and then P2 and then and then Pn. A Prolog program consists of a database of facts about the given information and conditional clauses or rules about how additional info. can be deduced from the facts. A query sets the Prolog interpreter into action.
COMP780 Semantics
Prolog
Prolog contains a large set of predefined predicates and notational variations (e.g., infix symbols) not defined in this grammar. And it allows a special syntax for lists see below.
COMP780 Semantics
Prolog
A Prolog Example
We develop an example incrementally. User queries are shown in boldface followed by the response by the Prolog interpreter.
Comments start with the symbol % and continue to the end of the line.
Some facts:
parent(chester,irvin). parent(chester,clarence). parent(chester,mildred). parent(irvin,ron). parent(irvin,ken). parent(clarence,shirley). parent(clarence,sharon). parent(clarence,charlie). parent(mildred,mary).
Some queries:
?- parent(chester,mildred). yes ?- parent(X,ron). X = irvin yes ?- parent(irvin,X). X = ron; X = ken; % The user-typed semicolon asks the no % system for more solutions. ?- parent(X,Y). X =chester Y = irvin % System will list all of the parent yes % pairs, one at a time,if semicolons % are entered.
COMP780 Semantics
Prolog
Additional facts:
male(chester). female(mildred). male(irvin). female(shirley). male(clarence). female(sharon). male(ron). female(mary). male(ken). male(charlie).
Additional queries:
?- parent(clarence,X), male(X). X = charlie yes ?- male(X), parent(X,ken). X = irvin yes ?- parent(X,ken), female(X). no
Prolog obeys the closed world assumption that presumes that any predicatethat cannot be proved must be false.
?- parent(X,Y), parent(Y,sharon). X = chester Y = clarence yes
COMP780 Semantics
Prolog
The scope of a variable in Prolog is solely the clause in which it occurs. Additional queries:
?- paternalgrandfather(X,ken). X = chester yes ?- paternalgrandfather(chester,X). X = ron; X = ken; X = shirley; % Note the reversal of the roles X = sharon; % of input and output. X = charlie; no ?- sibling(ken,X). X = ron; X = ken; no
The inference engine concludes that ken is a sibling of ken since we have both parent(irvin,ken) and parent(irvin,ken) To avoid this consequence, the description of sibling needs to be more carefully constructed.
COMP780 Semantics
Prolog
Predefined Predicates
1. The equality predicate = permits infix as well as prefix notation e.g.,
?- ken = ken. yes ?- =(ken,ron). no ?- ken = X. % Can a value be found for X to make X = ken % it the same as ken? yes % The equal operator represents the notion % of unification.
2. \+ (not) is a unary predicate: \+ P is true if P cannot be proved false and false if it can e.g., ?- \+ (ken=ron). yes ?- \+ (mary=mary). no The closed world assumption that any property not recorded in the database isnt true governs how \+ works. Since the behavior of \+ diverges from the logical not of predicate calculus, we use \+ as little as possible (not at all in the laboratory exercises).
COMP780 Semantics
Prolog
The following is a new sibling rule (the previous rule must be removed):
sibling(X,Y) :- parent(Z,X), parent(Z,Y), \+ (X=Y).
Queries:
?- sibling(ken,X). X = ron; no ?- sibling(X,Y). X = irvin Y = clarence; % sibling is a symmetric relation. X = irvin % 3 sets of siblings produce 6 answers. Y = mildred; X = clarence % The database allows 14 answers. Y = irvin; X = clarence Y = mildred; X = mildred Y = irvin; Y = mildred X = clarence % No semicolon here. yes
COMP780 Semantics
Prolog
Theres an implicit or between the three definitions of the relation closeRelative. This disjunction may be abbreviated using semicolons as
closeRelative(X,Y) :parent(X,Y) ; parent(Y,X) ; sibling(X,Y).
The three clauses (or single abbreviated clause) are said to define a procedure named closeRelative. The arity of this procedure is two, i.e., closeRelative takes two arguments. The identifier closeRelative may be used as a different predicate with other arities.
COMP780 Semantics
Prolog
Recursion
Suppose we want to define a predicate X is an ancestor of Y, which is true if parent(X,Y) or parent(X,Z) and parent(Z,Y) or parent(X,Z), parent(Z,Z1), and parent(Z1,Y) or A recursive definition is required to allow an arbitrary depth for the definition. The first case above serves as the basis for the recursive definition. The remaining cases are handled by an inductive step.
ancestor(X,Y) :- parent(X,Y). ancestor(X,Y) :- parent(X,Z), ancestor(Z,Y).
Fig. A.3 shows the parent relation between the twelve people defined in our database.
10
COMP780 Semantics
Prolog
Some queries:
?- ancestor(mildred,mary). yes % because parent(mildred,mary). ?- ancestor(irvin,nora). yes % because % parent(irvin,ken) and % ancestor(ken,nora) because parent(ken,nora). ?- ancestor(chester,elizabeth). yes % because % parent(chester,irvin) % and ancestor(irvin,elizabeth) % because parent(irvin,ken) and % ancestor(ken,elizabeth) % because parent(ken,elizabeth). ?- ancestor(irvin,clarence). no % because parent(irvin,clarence) is not provable
% % % and,whoever is substituted for Z, it is impossible to prove parent(irvin,Z) and ancestor(Z,clarence).
All possibilities for Z are tried that make parent(irvin,Z) true, namely Z=ron and Z=ken, and both ancestor(ron,clarence) and ancestor(ken,clarence) fail.
11
COMP780 Semantics
Prolog
Control Aspects
Since efficiency is a concern, Prolog interpreters follow a certain deterministic strategy for discovering proofs. 1. The order in which the clauses defining a given predicate are tested (the rule order or clause order) is top to bottom (as they appear in the text of the program). Rule order determines the order in which answers are found e.g.,
ancestor2(X,Y) :- parent(X,Z), ancestor2(Z,Y). ancestor2(X,Y) :- parent(X,Y). ?- ancestor(irvin,Y). Y = ron, ken, nora, elizabeth % Four answers returned separately. ?- ancestor2(irvin,Y). Y = nora, elizabeth, ron, ken % Four answers returned separately.
2. The left-to-right order in which terms (subgoals) are listed on the RHS of a rule (the goal order) is the order in which the interpreter tries to solve them. Goal order determines the shape of the search tree that the interpreter explores.
12
COMP780 Semantics
Prolog
A poor choice of goal order may give a search tree with an infinite branch down which the interpreter gets trapped e.g.,
ancestor3(X,Y) :- ancestor3(Z,Y), parent(X,Z). ancestor3(X,Y) :- parent(X,Y). ?- ancestor(irvin,elizabeth). yes ?- ancestor3(irvin,elizabeth).
which invokes
ancestor3(Z1,elizabeth), parent(Z,Z1), parent(irvin,Z).
which invokes
ancestor3(Z2,elizabeth), parent(Z1,Z2), parent(Z,Z1), parent(irvin,Z).
The problem with this last definition of the ancestor relation is the left recursion with uninstantiated variables in the first clause. If possible, the leftmost goal in the body of a clause should be nonrecursive so that a pattern match occurs and some variables are instantiated before a recursive call is made.
13
COMP780 Semantics
Prolog
Lists
A list of terms can be represented between brackets e.g., [a,b,c].
Here the head of the list is a, the tail is [b,c]. The tail of, e.g., [a] is [] (the empty list). Lists may contain lists as elements e.g., [a,[b,1],3,[c]] is a list of four elements. As a special form of direct pattern matching, [H|T] matches any list with at least one element: H matches the head of the list, T matches the tail. A list of elements is permitted to the left of the vertical bar e.g., [X,a,Y|T] matches any list with at least three elements whose second element is the atom a: X matches the first element, Y matches the third element, and T matches the rest of the list (possibly empty) after the third element. Using these pattern matching facilities, values can be specified as the intersection of constraints instead of by direct assignment. Lists are ordinary structures with syntactic sugar added. The notation abbreviates terms constructed with the predefined . function symbol and the special atom []. E.g., [a,b,c] abbreviates .(a,.(b,.(c,[]))). [H|T] abbreviates .(H,T). [a,b|X] abbreviates .(a,.(b,X)).
14
COMP780 Semantics
Prolog
List Processing
1. Define last(L,X) to mean X is the last element of the list L.
The last element of a singleton list is its only element. last([X], X). The last element of a list with two or more elements is the last item in its tail.
last([H|T], X) :- last(T, X). ?- last([a,b,c], X). X = c yes ?- last([ ], X). no
The illegal operation of requesting the last element of an empty list simply fails, allowing the caller to try alternative subgoals. Predicate last acts as a generator when run backwards:
?- last(L, a). L = [a]; L = [ _5, a]; % The underline indicates systemL = [ _5, _9, a]; % generated variables. L = [ _5, _9, _13, a]
Variable H in the definition of last plays no part in the body of the rule it doesnt need a name. Prolog has anonymous variables, denoted by an underscore: last([_|T],X) :- last(T,X). Another example: father(F) :- parent(F,_), male(F). The scope of an anonymous variable is its single occurrence. (The authors prefer using named variables for documentation.)
15
COMP780 Semantics
Prolog
2. Define member(X,L) to mean X is a member of the list L. For this predicate we need two clauses, one as a basis case and the second to define the recursion that corresponds to an inductive specification. The predicate succeeds if X is the first element of L.
member(X, [X|T]).
If the item is not in the list, the recursion eventually tries a query of the form member(X,[]). This fails since the head of no clause for member has [] as second argument. 3. Define delete(X,List,NewList) to mean The variable NewList is to be bound to a copy of List with all instances of X removed.
When X is removed from an empty list, we get the same empty list.
delete(X,[ ],[ ]).
When an item is removed from a list with that item as its head, we get the list that results from removing the item from the tail of the list (ignoring the head).
delete(H,[H|T],R) :- delete(H,T,R).
If the previous clause fails, X is not the head of the list, so we retain the head of L and take the tail that results from removing X from the tail of the original list.
delete(X,[H|T],[H|R]) :- delete(X,T,R).
16
COMP780 Semantics
Prolog
4. Define union(L1,L2,U) to mean The variable U is to be bound to the list that contains the unionof the elements of L1 and L2. If the first list is empty, the result is the second list.
union([ ],L2,L2). % clause 1
If the head of L1 is a member of L2, it may be ignored since a union does not retain duplicate elements.
union([H|T],L2,U) :member(H,L2), union(T,L2,U). % clause 2
If the head of L1 is a not member of L2 (clause 2 fails), it must be included in the result.
union([H|T],L2,[H|U]) :union(T,L2,U). % clause 3
In the last two clauses, recursion is used to find the union of the tail of L1 and the list L2.
17
COMP780 Semantics
Prolog
5. Define concat(X,Y,Z) to mean The concatenation of lists X and Y is Z. In the Prolog literature, this predicate is frequently called append.
concat([ ], L, L). % clause a concat([H|T], L, [H|M]) :concat(T, L, M). % clause b ?- concat([a,b,c], [d,e], R). R = [a,b,c,d,e] yes
The inference that produced this answer is illustrated by the search tree in Figure A.4.
18
COMP780 Semantics
Prolog
When the last query succeeds, the answer is constructed by unwinding the bindings:
R = = = = [a | M] [a | [b | M1]] = [a,b | M1] [a,b | [c | M2]] = [a,b,c | M2] [a,b,c | [d,e]] = [a,b,c,d,e].
19
COMP780 Semantics
Prolog
Figure A.5 shows the search tree for another application of concat using semicolons to generate all the solutions.
20
COMP780 Semantics
Prolog
In executing concat, the depth of recursion corresponds to the number of times that items from the first list are attached (cons) to the front of the second list. So the work done by concat is proportional to the length of the first list. When reverse is applied to a list of length n, the concat calls have first arguments of lengths, n-1, n-2, , 2, 1. So the complexity of reverse is proportional to n2.
Predicate help is called n times if the original list is of length n. So the complexity of rev is proportional to n. Note that help is tail recursive.
21
COMP780 Semantics
Prolog
Sorting in Prolog
We need relations for comparing numbers (equal, =:=, and not equal, =\=, are discussed later): M < N, M =< N, M > N, M >= N
These require that both operands be numeric atoms or arithmetic expressions whose variables are bound to numbers.
Insertion Sort
We sort the tail T of a list (recursively) then insert the head X into its proper place in the tail.
insertSort([ ], [ ]). insertSort([X|T], M) :- insertSort(T, L), insert(X, L, M). insert(X, [H|L], [H|M]) :- H<X, insert(X, L, M). insert(X, L, [X|L]).
The clauses for insert are order dependent. We remove this dependence by distinguishing the case where L is empty and explicitly stating the conditions for both remaining cases.
insert(X, [ ], [X]). insert(X, [H|L], [X,H|L]) :- X=<H. insert(X, [H|L], [H|M]) :- X>H, insert(X,L,M).
22
COMP780 Semantics
Prolog
Quick Sort
We split the list into those items less than or equal to the pivot and those greater than the pivot. We arbitrarily chose the first number in the list as the pivot. After the two lists are sorted (recursively), they are concatenated with the pivot in the middle to form an overall sorted list. Splitting is done by the predicate
partition(P, List, Left, Right)
where P and List are inputs, P is a pivot for list List, Left and Right are outputs, Left gets bound to the list of all elements in List less than or equal to P, and Right gets bound to the list of all elements in List greater than P.
partition(P, [ ], [ ], [ ]). partition(P, [A|X], [A|Y], Z) :- A=<P, partition(P, X, Y, Z). partition(P, [A|X], Y, [A|Z]) :- A>P, partition(P, X, Y, Z). quickSort([ ], [ ]). quickSort([H|T], S) :partition(H, T, Left, Right), quickSort(Left, NewLeft), quickSort(Right, NewRight), concat(NewLeft, [H|NewRight], S).
23
COMP780 Semantics
Prolog
7. Since a logical variable is write-once, it is more like a constant identifier with a dynamic defining expression as in Ada (or Pelican) than a variable in an imperative language.
24
COMP780 Semantics
Prolog
The power of logic programming comes from using the logical variable in structures to direct the pattern matching. Results are constructed by binding values to variables according to the constraints imposed by the structures of the arguments of the goal term and the head of the clause being matched. The order that variables are constrained is generally not critical. The construction of complex values can be postponed as long as logical variables hold their places in the structure being constructed.
25
COMP780 Semantics
Prolog
Numerical Comparisons
=:=, =\=, <, >, =<, >= Evaluate both expressions and compare the results.
| ?- 5<8. yes | ?- 5 =< 2. no | ?- N =:= 5. ! Error in arithmetic expression: not a number !(N not instantiated to a number) no | ?- N = 5, N+1 =< 12. N = 5 % The unification N = 5 causes a binding % of N to 5. yes
26
COMP780 Semantics
Prolog
COMP780 Semantics
Prolog
Identity
X == Y Succeed if the terms currently instantiated to X and Y are literally identical, including variable names.
| ?- X=g(X,U), X==g(X,U). yes | ?- X=g(a,U), X==g(V,b). no | ?- X\==X. % X \== X is the negation of X == X no
28
COMP780 Semantics
Prolog
Term Construction
T =.. L L is a list whose head is the atom corresponding to the principal functor of term T and whose tail is the argument list of that functor in T. =.. is pronounced univ.
| ?- T =.. [@<,ant,bat], T. T = ant@<bat yes | ?- T =.. [@<,bat,bat], T. no | ?- T =.. [is,N,5], T. N = 5, T = (5 is 5) yes | ?- member(X,[1,2,3,4]) =.. L. L = [member,X,[1,2,3,4]] yes % Some versions of % require call(T)
29
COMP780 Semantics
Prolog
30
COMP780 Semantics
Prolog
tell(F) The file whose name is the value of F becomes the current output stream. telling(F) F is bound to the name of the current input file. told Close the current output stream. read(T) The next Prolog term in the current input stream is bound to T. The term in the input stream must be followed by a period. write(T) The Prolog term bound to T is displayed on the current output stream. tab(N) N spaces are printed on the output stream. nl Newline prints a linefeed character on the current output stream. abort Immediately terminate the attempt to satisfy the original query and return control to the top level.
31
COMP780 Semantics
Prolog
name(A,L) A is a literal atom or a number, and L is a list of the ascii codes of the characters comprising the name of A.
| ?- name(A,[116,104,101]). A = the | ?- name(1994,L). L = [49, 57, 57, 52]
call(T) Assuming T is instantiated to a term that can be interpreted as a goal, call(T) succeeds if and only if T succeeds as a query. Some Prolog systems use simply T instead of call(T).
32