S7CS/CH/Oct., 2002 PROLOG Prolog is a programming language for symbolic, non-numeric computations. It is specially well suited for solving problems that involve objects and relation between objects. First simple Prolog Program Use an editor to input the following program named family: parent( parent( parent( parent( parent( parent( pam, tom, tom, bob, bob, pat, bob bob liz ann pat jim ). ). ). ). ). ). pam The program developed a relation as the family tree in fig. 1. Enter the IF-Prolog environment, where you can see the prompt ?-, get the Prolog program by enter consult(family). tom bob ann liz pat Then you can have query on the family relation as follows: ?- parent ( bob, pat ). Answer from Prolog: yes ? jim figure 1 A family tree. Study the following I-O carefully: Input parent parent parent parent ( ( ( ( Output liz, pat ). tom, ben ). X, liz). bob, X ). parent ( X, Y). no no X = tom X = ann; X = pat X = pam Y = bob; X = tom Y = bob; X = tom Y = liz; parent(Y, jim), parent(X, Y) ... X = bob Y = pat Basic elements of Prolog Clause. i. A Prolog program consists of clauses. Each clause terminates with a period (.). ii. Each of these clauses declares one fact, e.g. the parent-child relation. iii. In general, a relation is defined as the set of all its instances. PROLOG page 1 S7CS/CH/Oct., 2002 Rules. i. It specifies things that are true if the same condition is satisfied. ii. e.g. To formulate the logical statement, X and Y, ( means “for all”) Y is an offspring of X if X is a parent of Y. The following Prolog clause is used. offspring (Y, X) :- parent (X, Y). iii. Each rule have : a) condition part (on RHS as body ). b) conclusion part (on LHS as head ). Two more examples i. X and Y, X is the mother of Y if X is a parent of Y and X is a female. Formulate the statement by the following PROLOG statements, mother(X, Y) :- parent(X, Y), female(X). ii. X and Y, X is a sister of Y if (1) both X and Y have the same parent, and (2) X is a female. Formulate the statement by the following PROLOG statements, sister( X, Y) parent parent female :( Z, X), ( Z, Y), ( X). Recursive rule definition. Defining a rule based on a definition of itself defined before. e.g. X and Z, X is a predecessor of Z if X is a parent of Z or Y (1) X is a parent of Y, and (2) Y is a predecessor of Z. means “there exists”, means “such that”) Formulate the logical statement as predecessor ( X, Z) :parent ( X, Z). predecessor ( X, Z) :parent ( X, Y), predecessor ( Y, Z). PROLOG page 2 S7CS/CH/Oct., 2002 Here is a complete program family: parent( parent( parent( parent( parent( parent( pam, tom, tom, bob, bob, pat, bob). bob). liz). ann). pat). jim). % Pam is a parent of Bob female( pam). male( tom). male( bob). female( liz). female( ann). female( pat). male( jim). % Pam is female % Tom is male offspring( Y, X) :parent( X, Y). % Y is an offspring of X if % X is a parent of Y mother( X, Y) :parent( X, Y), female( X). % X is the mother of Y if % X is a parent of Y and % X is female grandparent( X, Z) :parent( X, Y), parent( Y, Z). % X is a grandparent of Z if % X is a parent of Y and % Y is a parent of Z sister( X, Y) :parent( Z, X), parent( Z, Y), female(X), different( X, Y). % X is a sister of Y if % X and Y have the same parent and % X is female and % X and Y are different predecessor( X, Z) :parent( X, Z). % Rule pr1 : X is predecessor of Z predecessor( X, Z) :parent( X, Y), predecessor( Y, Z). % Rule pr2 : X is predecessor of Z How does Prolog answer questions? --- Backtracking To answer a question, Prolog tries to satisfy all the goals. (‘To satisfy a goal’ means to demonstrate the goal logically follows from the facts and rules in the program.) Prolog backtracks to the original goal in order to try an alternative way to derive the top goal. e.g. Given the question for the program family: ?- predecessor ( tom, pat). 1st : X = tom, Z = pat 2nd : Rule 1 not true. Backtrack rule 2. 3rd : Match with parent (tom, bob). 4th : Recursive search for predecessor ( bob, pat). 5th : match with rule 1, i.e. parent ( bob, pat). ** Answer found ----> yes. PROLOG page 3 S7CS/CH/Oct., 2002 The complete execution trace is shown in fig. 2. predecessor(tom, pat) by rule pr1 by rule pr2 parent(tom, Y) predecessor(Y, pat) parent(tom, pat) no figure 2 Execution trace Declarative and Procedural meaning of programs The declarative meaning is concerned with the relations defined by the program, i.e. determining WHAT the output of the program is. The procedural meaning is concerned with the relations actually evaluated by the Prolog system, i.e. determining HOW the output is obtained. SYNTAX AND MEANING Data objects Constants (i.e. atoms and number) i. data objects Strings can consist of the following characters: upper-case letters A, B, ... , Z lower-case letters a, b, ... , z digits 0, 1, 2, ... , 9 special characters such as +-*/<>=: .&_~ simple objects structure constants atoms variables numbers Figure 3 Data objects in Prolog ii. Atoms can be constructed in 3 ways: Strings of letters. starting with a lower-case letter. e.g. x___y, miss_Jones Strings of special characters. without predefined meaning e.g. the string ‘:-’ cannot be used. Strings of characters. enclosed in single quotes. e.g. 'Mom', 'Sarah Jones' iii. Numbers in Prolog Integer: -16383 to 16383 Real: not used very much, only decimal point form is used Variables i. Starting with an upper-case letter or an underscored character. ii. e.g. X, Result, _x23 PROLOG page 4 S7CS/CH/Oct., 2002 iii. The lexical scope of variable name is one clause, i.e. if the same name occurs in two clauses, it signifies two different variables. Structures Structured objects are objects that have several components. 5 ii. The components themselves can, in turn, be structures. 3 iii. e.g. date( Day, may, 1983). 2 iv. The figure in fig. 4 shows the relations of points, segments and triangles. 1 i. (6, 4) 4 P2 = (2,3) T (4, 2) P1 = (1,1) 1 v. To formulate in Prolog: 2 (7, 1) 3 4 5 6 7 8 Figure 4 Some simple geometric objects P1 = point( 1, 1) P2 = point( 2, 3) S = seg( point( 1, 1), point( 2, 3)) T = triangle( point( 4, 2), point( 6, 4), point( 7, 1)) vi. The corresponding tree representation is shown in fig. 5. P1 = point 1 S = seg 1 point 1 point 1 2 3 T = triangle point 4 point 2 6 point 4 7 1 Figure 5. Tree representation of the objects in Figure 4. MATCHING Given 2 terms, we say that they match if : i. they are identical, or ii. the variables in both terms can be instantiated to objects in such a way that after the substitution of variables by these objects the terms become identical. Thus, matching is a process that takes as input two terms and checks whether they match. PROLOG page 5 S7CS/CH/Oct., 2002 The general rules to decide whether two terms, S and T, match are as follows: i. If S and T are constants, then S and T match only if they are the same object. ii. If S is a variable and T is anything, then they match, and S is instantiated to T. Conversely, if T is a variable then T is instantiated to S. iii. If S and T are structures then they match only if a) S and T have the same principal functor, and b) all their corresponding components match. The resulting instantiation is determined by the matching of the components. e.g. Defining structures for recognizing horizontal and vertical line segments. vetical( seg( point( X, Y1), point( X, Y2))). horizontal( seg( point( X1, Y), point( X2, Y))). Conjunction and Disjunction In general, a question to the Prolog system is a list of goals separated by commas. A comma between goals thus denotes the conjunction of goals (AND) Prolog also accepts the disjunction of goals (OR). It is lower in order of precedence, and denoted by separated with the semicolon. e.g. translate( Number, Word) :- Number = 1, Word = one; Number = 2, Word = two; Number = 3, Word = three. *** Example: monkey and banana A Monkey is at the door and the banana is hang on from the ceiling the room. The state of the “world” is determined by The position of monkey in the room. Is the monkey on the box or on the floor? The position of the box. Does the monkey have the banana? Four types of movement by the monkey: grasp banana, climb box, push box, walk around Sample Prolog program to find the solution. % move( State1, Move State2): making Move in State1 results in State2; % a state is represented by a term: % state( MonkeyHorizontal, MonkeyVertical, BoxPosition, HasBanana) move( state( middle, onbox, middle, hasnot), % Before move grasp, % Grasp banana state( middle, onbox, middle, has) ). % After move move( state( P, onfloor, P, H), climb, state( P, onbox, P, H) ). PROLOG % Climb box page 6 S7CS/CH/Oct., 2002 move( state( P1, onfloor, P1, H), push( P1, P2), % Push box from P1 to P2 state( P2, onfloor, P2, H) ). move( state( P1, onfloor, B, H), walk( P1, P2), state( P2, onfloor, B, H) ). % Walk from P1 to P2 % canget( State): monkey can get banana in State canget( state( _, _, _, has) ). % can 1 : Monkey already has it canget( State1) :move( State1, Move, State2), canget( State2). % can 2 : Do some work to get it % Do something % Get it now Given the initial state to see if there is a solution as follows, ?- canget( state( atdoor, onfloor, atwindow, hasnot)). state( atdoor, onfloor, atwindow, hasnot) walk( atdoor, P2) state( P2, onfloor, atwindow, hasnot) climb backtrack state( atwindow, onbox, atwindow, hasnot) push( P2, P2’) P2 = atwindow state( P2’, onfloor, P2’, hasnot) No move possible climb state( P2’, onbox, P2’, hasnot) grasp P2’ = middle state( middle, onbox, middle, has) Figure 6 The monkey’s search for the banana. The search starts at the top node and proceeds downwards, as indicated. Alternative moves are tried in the left-to-right order. Backtracking occurred once only. Danger of indefinite looping Considering the following clause in a program: p :- p. The question ?- p. will cause Prolog entering an indefinite loop . Another example of indefinite looping i. Reorder the Monkey and Banana thus the ‘walk’ clause appears first. PROLOG page 7 S7CS/CH/Oct., 2002 ii. Then the execution of our original goal of the previous section, ?- canget( state( atdoor, onfloor, atwindow, hasnot)). would cause an indefinite looping. (Why? The monkey will only walk around.) Program variations through reordering of clauses and goals. Consider the four versions of the predecessor program. pred1( X, Z) :parent( X, Z). pred1( X, Z) :parent( X, Y), pred1( Y, Z). pred2( X, Z) :parent( X, Y), pred2( Y, Z). pred2( X, Z) :parent( X, Z). pred3( X, Z) :parent( X, Z). pred3( X, Z) :pred3( X, Y), parent( Y, Z). pred4( X, Z) :pred4( X, Y), parent( Y, Z). pred4( X, Z) :parent( X, Z). All pred1, pred2 and pred3 can reach a solution. The pred4 is hopeless. LIST The list is a simple data structure widely used in non-numeric programming. e.g. [ann, tennis, tom, skiing] A list consists of two things i. the first term, called the head of the list. ii. the remaining part of the list, called the tail. The head can be any Prolog object; the tail has to be a list. In If-Prolog, a list can be regarded as an empty list or a structure whose functor is dot ‘.’, and that has two arguments: the head and the tail. Thus, the general principle for structuring data objects in Prolog also applies to lists of any length. It can be illustrated by the following example. e.g. ?- List1 = [a,b,c], List2 = '.'(a, '.'(b, '.'(c, []))). List1 = [a,b,c] List2 = [a,b,c] ?- Hobbies = '.'( tennis, '.'( music, [])), Hobbies = [ skiing, food], L = [ ann, [ tennis, music], tom, [skiing, food]]. Hobbies = [ tennis, music] Hobbies = [ skiing, food] L = [ ann, [ tennis, music], tom, [skiing, food]] PROLOG page 8 S7CS/CH/Oct., 2002 Prolog provides another notational extension, the vertical bar, which separates the head and the tail. The notation is L = [a | Tail] Operations on lists include i. checking whether an object is an element of a list, i.e. membership . ii. concatenation of two lists, (Unions of sets) iii. adding or deleting an object to or from a list. iv. checking whether a list is a sublist of another. v. generate permutate of a list Membership member( X, L). where X is an object and L is a list. The goal member( X, L) is true if X occurs in L. Example Truth value member( b, [ a, b, c]) member( b, [ a, [b, c]]) member( [b, c], [a, [b, c]]) True False True The relationship of member would be, X is a member of L if either (1) X is the head of L, or (2) X is the member of the tail of L Thus to formulate the statement in Prolog, member( X, [X | Tail]). member( X, [Head | Tail]) :member( X, Tail). Concatenation conc( L1, L2, L3). where L1 and L2 are two lists and L3 is their concatenation. Example conc( [a,b], [c,d], [a,b,c,d]) conc( [a,b], [c,d], [a,b,a,c,d]) Truth value True False Defining in Prolog conc( [], L, L). conc( [X | L1], L2, [X | L3]) :conc( L1, L2, L3). e.g. ?- conc( [a, [b, c], d], [a, [], b], L). L = [a, [b, c], d, a, [], b] ?- conc( L1, L2, [a, b, c]). L1 = [] L2 = [a, b, c]; L1 = [a] L2 = [b, c]; PROLOG page 9 S7CS/CH/Oct., 2002 L1 = [a, b] L2 = [c]; L1 = [a, b, c] L2 = []; no ? Redefine member1 using conc as member1( X, L) :conc(_, [X, _], L). Adding an item To add an item to a list, it is easiest to put the new item in front of the list so that resulting list becomes. [X | L] where X is the new object and L is original list. Thus it is defined as, add( X, L, [X | L]). Deleting an item del( X, L, L1). There are two cases, where L is the original list, X is the object to be deleted, L1 is the resulting list. i. X is the head of the list. The result is simply the tail. ii. X is in the tail. The result is deleted from the tail (recursive), add the present head. Definition in Prolog. del( X, [X | Tail], Tail). del( X, [Y | Tail], [Y | Tail1]) :del( X, Tail, Tail1). e.g. ?- del( a, [a, b, a, a], L). L = [b, a, a]; L = [a, b, a]; L = [a, b, a]; no ?- del( a, L, [1, 2, 3]). L = [a, 1, 2, 3]; L = [1, a, 2, 3]; L = [1, 2, a, 3]; L = [1, 2, 3, a]; no ?- PROLOG page 10 S7CS/CH/Oct., 2002 In general, the operation of inserting X at any place in some list List giving BiggerList can be defined by the clause: insert( X, List, BiggerList) :del( X, BiggerList, List). Sublist sublist( L1, L2). where L1 is the sublist of L2. Example Truth value sublist( [c,d,e], [a,b,c,d,e]) sublist( [c,e], [a,b,c,d,e]) True False The relation can be formulated as: S is a sublist of L if (1) L can be decomposed into 2 lists, L1 and L2, and (2) L2 can be decomposed into 2 lists, S and L3. Thus, in Prolog sublist( S, L) :conc( L1, L2, L), conc( S, L3, L2). e.g. ?- sublist( S, [a,b,c]). S = []; S = [a]; S = [a, b]; S = [a, b, c]; S = [b]; ... Permutation permutation( L1, L2). To formulate the relation, depending on the first list, there are two cases: The first list is empty. The second list must also be empty. i. ii. where L2 is a permutation of L1 and vice versa. The first list is not empty. The first list has the form [X | L], and a permutation of such a list can be constructed: first premute L obtaining L1 and then insert X at any position into L1. To formulate in Prolog, permutation( [], []). permutation( [X | L], P) :permutation( L, L1), insert( X, L1, P). Operator notation For arithmetic operations, say 2 * a + b * c . PROLOG page 11 S7CS/CH/Oct., 2002 Prolog handles it as ordinary clause +( *( 2, a), *( b, c)). Nevertheless, Prolog allows both notations. Prolog program can define new operators as infix ones in special kinds of clauses, sometimes called directives. In IF-PROLOG , the operator has can be defined by the directive: :- op( 600, xfy, has). It tells Prolog that we want to use ‘has’ as an operator, whose precedence is 600 and its type is ‘xfy’, i.e. infix. e.g. Program can define has and supports which allows clauses like peter has information. floor supports table. which are equivalent to has( peter, information). supports( floor, table). REM. Three operator types: Infix. e.g. a + b. Prefix. e.g. +( a, b). Postfix. e.g. (a, b)+. Notation of x, y and f in the operator definition, ‘f’ indicates the position of the operator. ‘x’ represents an argument whose precedence must be strictly lower than that of the operator. ‘y’ represents an argument whose precedence is lower or equal to that of the operator Arithmetic Prolog has the following basic arithmetic operation. +, -, *, /, div and mod (integer division and modulo) The evaluation of an arithmetic operation is forced by the predefined operator, is. e.g. ?- X = 1 + 2. X = 1 + 2. yes ?- X is 1 + 2. X = 3. yes. ?- Relational operators: >, <, >=, =<, =:=, =\= PROLOG page 12 S7CS/CH/Oct., 2002 The set of predefined operators are follows :::::::::- op( op( op( op( op( op( op( op( op( 1200, xfx, ':-'). 1200, fx, [:-, ?-]). 1100, xfy, ';'). 1000, xfy, ','). 700, xfx, [=, is, <, >, =<, >=, =\=, =:=]). 500, yfx, [+, -]). 500, fx, [+, -, not]). 400, yfx, [*, /, div]). 300, xfx, mod). Example 2277*37 > 1 + 2 =:= 1 + 2 = 2 1 + A = B Result 10000 2 + 1 + 1 + 2 born( Name, Year), Year > = 1950, Year < = 1960. yes yes no A = 2 B = 2 The names of people born between 1950 & 1960 e.g. Given two positive integers, X and Y, their greatest common divisor D, can be found according to 3 cases: i. if X = Y, D = X, ii. if X < Y, D = the greatest common divisor of X and Y-X. iii. if Y < X, D = the greatest common divisor of Y and X-Y. To formulate in Prolog: gcd( X, X, X). gcd( X, Y, D) :X < Y, Y1 is Y - X, gcd( X, Y1, D). gcd( X, Y, D) :Y < X, X1 is X - Y, gcd(X1, Y, D). e.g. Finding the length of a list, length( [], 0). length( [_|Tail], N) :length( Tail, N1), N is 1 + N1. Example : Example programs using structures The family in fig. 7 can be stored in the database by the clause. e.g. family( person( tom, fox, date( 7, may, 1950), works(bbc,15520)), person( ann, fox, date( 9, may, 1951), unemployed), [ person( pat, fox, date( 5, may, 1973), unemployed), person( jim, fox, date( 5, may, 1973), unemployed)]). PROLOG page 13 S7CS/CH/Oct., 2002 family( person( david, brown, date( 7, may, 1950), works(bbc,15520)), person( mary, brown, date( 9, may, 1951), unemployed), [ person( may, brown, date( 5, may, 1973), unemployed), person( john, brown, date( 5, may, 1973), unemployed)]). husband( X) :family( X, _, _). % X is a husband wife( X) :family( _, X, _). % X is a wife child( X) :family( _, _, Children), member( X, Children). % X is a child member( X, [X | L]). member( X, [Y | L]):member( X, L). exists( Person) :husband( Person); wife( Person); child( Person). % Any person in the database dateofbirth( person( _, _, Date, _), Date). salary( person( _, _, _, works( _, S)), S). % Salary of working person salary( person( _, _, _, unemployed), 0). % Salary of unemployed total( [], 0). % Empty list of people total( [Person | List], Sum) :salary( Person, S), total( List, Rest), Sum is S + Rest. % S : salary of first person % Rest : sum of salaries of others Write down the answer to the following queries: Query Answer exists( person( Name, Surname, _, _) ). child(X), dateofbirth( X, date( _, _, 1981) ). wife( person( Name, Surname, _, works( _, _) ) ). exists( person( Name, Surname, date( _, _, Year), unemployed) ), Year < 1963. exists( Person), dateofbirth( Person, date( _, _, Year)), Year < 1950, salary( Person, Salary), Salary < 8000. PROLOG page 14 S7CS/CH/Oct., 2002 family( Husband, Wife, Children), total(Husband, Wife | Children], Income). CONTROLLING BACKTRACKING ~ CUT Studying the following sample program, f( X, 0) :- X < 3. f( X, 2) :- 3 =< X, X < 6. f( X, 4) :- 6 =< X. % Rule 1 % Rule 2 % Rule 3 When the following question is posed, 4 2 ?- f(1,Y), 2 < Y. Y becomes instantiated to 0 and violate the second condition input in question, However, Prolog tries through backtracking two useless alternatives. 3 6 X Figure 7 A double-step function Preventing useless backtracking, the technique of cut is used, with the symbol ‘!’ indicating it. For the previous example, the program can be changed to, f( X, 0) :- X < 3, !. f( X, 2) :- X < 6, !. f( X, 4). For the question f( 1, Y), 2 < Y after finding the second condition does not hold at the first rule, it tries backtracking and then the backtracking is cut. f(1, Y), 2 < Y rule 1 Y=0 rule 2 Y=2 1 < 3, 2< 0 rule 3 Y=4 3 1, 1 < 6, 2 < 2 6 1, 2 < 4 no no CUT 2<0 no Figure 8 At the point marked ‘CUT’ we already know that the rules 2 and 3 are bound to fail. e.g. Computing maximum max( X, Y, X) :- X >= Y. max( X, Y, Y) :- X < Y. These two rules are mutually exclusive, thus formulate in a more economic way, max( X, Y, X) :- X >= Y, !. max( X, Y, Y). PROLOG page 15 S7CS/CH/Oct., 2002 e.g. Single-solution membership member( X, [X | L]). member( X, [Y | L]) :- member( X, L). This is ‘non-deterministic’: if X occurs several times then any occurrence can be found. The following is a deterministic one, member( X, [X | L]) :- ! member( X, [Y | L]) :- member( X, L). To clarify this definition, consider a clause of the form: H :- B1, B2, ... , Bm, !, ... , Bn. Let us assume that this clause was invoked by a goal G that matches H. i. At the moment that the cut is encountered, the system has already found some solution of the goals B1, ... , Bm becomes frozen and all possible remaining alternatives are discarded. ii. The parent goal G now becomes committed to this clause: any attempt to match G with the head of some other clause is precluded. iii. Backtracking will still be possible within the goal list after ‘!’. Negation as Failure That something is not true can be said in Prolog by using a special goal, fail, which always fails, thus forcing the parent goal to fail. e.g. To formulate ‘Mary likes all animals but snakes’. likes( mary, X) :snake( X), !, fail. likes( mary, X) :animal(X). e.g. Defining the difference relation. If Goal succeeds then not (Goal) fails otherwise not (Goal) succeeds. not( P) :P, !, fail; true. Problems with cut and negation Advantages of using cut: i. With cut we can often improve the efficiency of the program. The idea is to explicitly tell Prolog not to try other alternatives because they are bound to fail. ii. Using cut we can specify mutually exclusive rules; so we can express rules of the form: a) b) if condition P then conclusion Q, otherwise conclusion R Disadvantage of using cut: Lose the valuable correspondence between the declarative and procedural meaning of programs. PROLOG page 16 S7CS/CH/Oct., 2002 Remark: If there is no cut in the program, we can change the order of clauses and goals, and this will only affect the efficiency or termination of the program, not the declarative meaning. On the other hand, with using cut, a change in order of clause will change the declarative meaning. 1. 2. p p p p ::::- a, b c a, !, b c % means p <==> (a & b) v c % means p <==> (a & b) v (~a & c) Predefined IF/PROLOG procedures Sample Program: :- op(100, xfy, reports_to). iptool :write('To finish, type in: stop.\n'), write('Type in terms like: X reports_to Y.\n'), repeat, write(:),tab(1), read(Term), interpreter(Term). interpreter(stop) :- !. interpreter(X reports_to Y) :!, asserta(X reports_to Y), fail. interpreter(_) :!, write('"X reports_to Y." expected, try again:\n'), fail. read - It reads the next term from the CURRENT input stream. write - It writes term(s) to the current output streaming according to current operator declarations, with quotes (‘ ’) omitted. repeat i. It always succeeds. ii. Remember that IF/Prolog returns to the last successful solved clause and attempts to find another solution. iii. If repeat was the last successful clause in a procedure in effect it has an “infinite number of solutions” and an infinite sequence of backtracking choices is generated. iv. To exit from a loop caused by repeat, the following clauses must either succeed, or a cut must be executed to that the backtrack point at repeat is removed. PROLOG page 17