% prolog
CProlog version 1.5
 ? [user].
 parent(elizabeth,charles).
 parent(philip,charles).
 parent(elizabeth,anne).
 parent(philip,anne).
 parent(elizabeth,andrew).
 parent(philip,andrew).
 parent(diana,william).
 parent(charles,william).
 parent(diana,harry).
 parent(charles,harry).
 female(elizabeth).
 male(philip).
 male(charles).
 female(anne).
 male(andrew).
 female(diana).
 male(william).
 female(sarah).
 ^D
 user consulted 728 bytes 9.93411e10 sec.
 Note: The normal prompt in Prolog is  ?. This is used for
 entering queries. To change to factentering mode, use the command
 [user]. A single fact can be entered in Prolog using the predicate
 assertz. Thus, we could have written
 assertz(parent(elizabeth,charles)).
 We also have these facts in this form (with no prompt
 symbol) in a file called "notes_a". To read the facts in
 we would have entered
 [notes_a].
 or consult(notes_a).
 To change from add fact mode to query mode, type CntlD.
 A simple fact in Prolog, called a literal, has the form
 predicate(arg1, arg2, ... argk)
 Note that the open parentheses must follow
 immediately after the predicate. If there is a space between,
 it is a syntax error. Also notice that all queries and all facts
 end in a period. The interpreter just keeps reading along until
 it finds a period.
 In a form like "married(elizabeth,philip)", married is the
 predicate, and elizabeth and philip are the arguments.
 ? parent(charles, william).
yes
 Most input from the terminal, to the prompt "?", are queries.
 This query may be read "Is Charles a parent of William?"
 Note that all facts and all queries end with a period. The Prolog
 interpreter will just go on accepting input until you type a
 period.
 ? male(william).
yes
 ? male(frank_sinatra).
no
 If Prolog hasn't been told a fact, it assumes the fact is false.
 ? descendant(william,charles).
no
 Prolog does not know by itself that if X is a parent of Y then
 Y is a descendant of X.
 ? parent(charles, X).
X = william  User enters carriage return to accept answer.
yes
 X and Y are variables, because they begin with capital letters.
 This query means, "Find some X such that charles is the parent of X."
 Prolog returns the first answer that it finds. Since the user
 accepts it, the execution terminates.
 ? parent(elizabeth, X).
X = charles ;  User types a semicolon ; to ask for more solutions.
X = anne ;
X = andrew ;
no  Meaning that Prolog cannot satisfy the user's last request
 to find another solution besides the three it has given already.
 ? parent(X,Y).
X = elizabeth
Y = charles ;
X = philip
Y = charles ;
X = elizabeth
Y = anne  User stops asking for more answers by typing CR
yes
 ? parent(elizabeth, Y), male(Y).
Y = charles ;
Y = andrew ;
no
 If a query has two (or more) goals, separated by commas, then
 Prolog looks for an assignment of variables that satisfies both
 parts. It does this by first finding all the values that satisfy
 the first goal, and checking to make sure that it satisfies the
 second. In this case, the binding X=anne, which satisfies the
 first, is thrown out.
 Rules
 ? [user].
 child(X,Y) : parent(Y,X).
 % X is a child of Y if Y is a parent of X. %

 mother(X,Y) : parent(X,Y), female(X).
 % X is a mother of Y if X is a female parent of Y

 father(X,Y) : parent(X,Y), male(X).
 % X is a father of Y if X is a male parent of Y

 son(X,Y) : child(X,Y), male(X).
 % X is a son of Y is X is a male child of Y

 daughter(X,Y) : child(X,Y), female(X).
 % X is a daughter of Y if X is a female child of Y.
 ^D
 user consulted 632 bytes 0.0166667 sec.
yes
 A rule in Prolog has the form GOAL : FACT1, FACT2 ... FACTk
 where the goal and all the facts are literals. The meaning of
 this rule is, if all the FACTs are true, then the GOAL is true;
 or, to satisfy the GOAL, satisfy all the FACTs; or, if the GOAL
 is invoked, then invoke each of the FACTS, until you succeed
 in satisfying all the facts.
 A rule like this is called a "clause". The goal is called its
 "head", and the facts are called its "body".
 Comments in Prolog either go from a percent sign % to the end of
 the line, or are delimited by /* and */
 ? child(anne, philip).
yes
 Given the goal "child(anne,philip)",
 Prolog finds the rule, "child(X,Y) : parent(Y,X)"
 It now generates the goal "parent(philip,anne)" which succeeds,
 so it returns "yes" for the original goal.
 ? child(anne, W).
W = elizabeth ;  User types a semicolon.
W = philip  User types carriage return.
yes
 Given the goal "child(anne,W)"
 Prolog finds the rule "child(X,Y) : parent(Y,X)"
 It now generates the goal "parent(W,anne)", which succeeds
 with W = elizabeth. So the original goal succeeds with W = elizabeth.
 The user typed a semicolon to ask for more solutions, so it
 looked for another solution to "parent(W,anne)". It found the
 solution W = philip, which it reported and which was accepted
 by the user.
 ? father(philip,andrew).
yes
 Given the goal G1, "father(philip,andrew)"
 Prolog finds the rule "father(X,Y) : parent(X,Y), male(X).
 So it generates the two goals:
 G2, "parent(philip,andrew)"
 G3, "male(philip)"
 Both of these succeed, so the original goal G1 succeeds.
 ? father(W,andrew).
W = philip  User types carriage return
yes
 Given the goal G1 "father(W, andrew)"
 Prolog finds the rule "father(X,Y) : parent(X,Y), male(X).
 So it generates the two goals: G2, "parent(W,andrew)" and G3, "male(W)"
 It first works on G2.
 The first answer it finds for G2 is W = elizabet(.
 Prolog accepts this answer, and tries it for G3.
 This gives the goal "male(elizabeth)", which fails.
 So Prolog goes back to G2.
 The second answer it finds for G2 is W = philip
 This version of G3 "male(philip)" succeeds
 So G1 succeeds with W = philip.
 In general, when Prolog fails on some goal, it goes back to the
 last goal it tried, and see if it can find some other solution
 to the last goal that will make things work. This is called
 "chronological backtracking".
 ? daughter(W,elizabeth).
W = anne
yes
 Given the goal G1: "daughter(W,elizabeth)"
 Prolog finds the rule "daughter(X,Y) : child(X,Y), female(X)."
 So it generates the two goals: G2, "child(W,elizabeth)" and
G3, "female(W).
 It works first on G2, "child(W,elizabeth)".
 It finds the rule, "child(X,Y) : parent(Y,X)."
 So it generates the goal G4: "parent(elizabeth,W)"
 G4 succeeds with W = charles
 So G2 succeeds with W = charles
 So we try that for G3;
 With W = charles, G3 is "female(charles)", which fails.
 So we go back to G4, and look for another solution.
 The next solution to G4 is W = anne
 So we try that with G3
 With W = anne, G3 is "female(anne)", which succeeds.
 So G1 succeeds with W = anne.
 ? daughter(anne,X).
X = elizabeth ;
X = philip ;
no
 ? son(X,Y).
X = charles
Y = elizabeth ;
X = charles
Y = philip ;
X = andrew
Y = elizabeth ;
X = andrew
Y = philip
yes
 Multiple rules
 ? [user].
sibling(X,Y) : parent(Z,X), parent(Z,Y).
/* A sibling is someone with the same parent */
closerelation(X,Y) : child(X,Y).
closerelation(X,Y) : sibling(X,Y).
closerelation(X,Y) : parent(X,Y).
/* A close relation is either a child, or a sibling, or a parent. */
^D
user consulted ...
 When more than one rule is given for a goal, Prolog tries the
 various rules in the given order.
 ? closerelation(anne,charles).
yes
 The second rule succeeds.
 ? closerelation(X,charles).
X = william ;
X = harry ;
X = charles ;
X = charles ;
X = anne ;
X = anne ;
X = andrew ;
X = andrew ;
X = elizabeth ;
X = philip ;
no
 Prolog first goes through the answers given by the "child"
 rule, then the answers given by the "sibling" rule, then the
 answers given by the "parent" rule.
 The goal ``sibling(charles,X)'' succeeds twice for each sibling of
 Charles, as well as for himself, once for their common parent Elizabeth
 and once for their common parent Philip.
 Recursion
 ? [user].
ancestor(X,X).
ancestor(X,Y) : parent(X,Z), ancestor(Z,Y).
^D
user consulted ...
 The ancestor relationship is defined recursively in two rules:
 (Base case) Every man is his own ancestor.
 (Recursive case). If X is a parent of an ancestor of Y, then X
 is an ancestor of Y.
 Note: A literal with variables and no body, such as "ancestor(X,X)",
 is essentially a statement that the form is true for all values of
 the variable; that is, for any X, "ancestor(X,X)" is true.
 ? ancestor(charles,charles).
yes
 The query matches the base rule "ancestor(X,X)".
 ? ancestor(philip,charles).
yes
 The goal G1 "ancestor(philip,charles)" does not match the base
 rule, so Prolog goes onto the second rule
 "ancestor(X,Y) : parent(X,Z), ancestor(Z,Y)"
 and generates the two goals: G2, "parent(philip,Z)"
 and G3, "ancestor(Z,charles)"
 G2 succeeds with Z = charles.
 Substituting Z = charles into G3 gives "ancestor(charles,charles)"
 which succeeds.
 ? ancestor(philip,W).
W = philip ;
W = charles ;
W = william ;
W = harry ;
W = anne ;
W = andrew ;
no
 Given the goal G1: "ancestor(philip,W)",
 Prolog matches it with the rule "ancestor(X,X)" under the
 binding X = W = philip, so it succeeds with W = philip.
 When the user asks it for another solution it tries the next
 rule, "ancestor(X,Y) : parent(X,Z), ancestor(Z,Y).
 So it generates the two goals: G2, "parent(philip,Z)"
 and G3, "ancestor(Z,W)".
 The first solution to G2 is Z = charles.
 This is substituted in G3, giving the goal "ancestor(charles,W)".
 Prolog matches this with the rule "ancestor(X,X)", which
 succeeds under the binding X = W = charles.
 So G1 reports success with the binding W = charles.
 When the user asks for a new solution, Prolog tries to solve G3
 using the recursive rule.
 So it generates the two goals G4, "parent(charles,Z)" and
 G5, "ancestor(Z,W)"
 The first solution to G4 is Z = william.
 This is substituted in G5, giving the goal "ancestor(william,W)"
 Prolog matches this with the rule "ancestor(X,X)", which succeeds
 under the binding X = W = william.
 So G1 reports success with the binding W = william.
 When the user asks for a new solution, Prolog tries to
 solve G5 using the recursive rule for ancestor.
 So it generates the two goals: G6, "parent(william,Z)"
 and G7, "ancestor(Z,W)."
 G6 fails. william is not the parent of anyone.
 Therefore there are no more solutions to G5.
 So Prolog looks for another solution to G4.
 The next solution to G4 is Z = harry.
 ... and so on ...
 Note two things. First, our definition of "ancestor"
 will be terrible for answering queries like "ancestor(W,william)".
 Second, the order of the clauses, and of the literals in the
 clauses is very important. If we had made the definition
 ancestor(X,Y) : parent(X,Z), ancestor(Z,Y).
 ancestor(X,X).
 then Prolog would start by looking at the most remote ancestors,
 and work its way down to the most immediate ancestors.
 If the defintion had been
 ancestor(X,X).
 ancestor(X,Y) : ancestor(Z,Y), parent(X,Z).
 Prolog would go into an infinite loop.
 Lists

 A list is type of structure. The elements of a list are written
 between brackets, separated by commas. The list constructor
 [ X  Y ] means that X is the first element of the list and Y is
 the rest of the elements. More than one thing can come before the
 bar. For example [X, Y, Z  REST] means that X is the 1st element,
 Y is the 2nd, Z is the 3rd, and REST are the rest. [] is the list
 with no elements.
 Lists can contain sublists or other structures as elements.
 ? [X, Y, Z] = [alpha, beta, gamma].
X = alpha
Y = beta
Z = gamma
yes
 ? [FIRST  REST] = [mobydick, peterrabbit, winniethepooh].
FIRST = mobydick
REST = [peterrabbit, winniethepooh]
yes
 ? [X, Y  REST] = [[a, b, c], 1, 2, tree(sam, sarah, sid)].
X = [a, b, c]
Y = 1
REST = [2, tree(sam, sarah, sid)]
yes
 ? [X, Y, Y, a] = [Z, b, W, Z].
X = a
Y = b
Z = a
W = b
yes
 ? [X, Y, Z] = [A, A, q].
X = _0
Y = _0
Z = q
A = _0
yes
 ? [user].
/* X is a member of L if either X is the first element of L, or if
X is a member of the tail of L.
Note that "member(X,L)" is already defined in Prolog, so we name this
"member1". */
 member1(X,L) : L = [X  REST].
 member1(X,L) : L = [Y  REST], member1(X, REST).
 ^D
 user consulted ...
 ? member1(a, [a, b, c]).
yes
 ? member1(b, [a, b, c]).
yes
 ? member1(o, [a, b, c]).
no
 ? member1(a, [[a, b], c]).
no
 ? member1(X, [a, b, c]).
X = a ;
X = b ;
X = c ;
no
 ? member1(a,L).
L = [a  _6] ;
L = [_5, a  _10] ;
L = [_5, _9, a  _14]
yes
 ? [user].
 /* A more elegant way to write the member predicate. The equalities
 are collapsed into the forms of the predicates, and the anonymous
 variable _ is used for variables whose value does not matter
 */
 member1(X,[X_]).
 member1(X,[_REST]) : member1(X,REST).

 /* list_fathers(L, FATHERS) is true if everyone in FATHERS is the
 father of the corresponding person in L. Again, we use a recursive
 definition. If L is the null list, then FATHERS is the null list.
 Otherwise the head of FATHERS is the father of the head of L, and
 the tail of FATHERS is list_fathers of the tail of L. */

 list_fathers(L, FATHERS) : L = [], FATHERS = [].
 list_fathers(L, FATHERS) :
 L = [FIRSTL  RESTL],
 FATHERS = [FIRSTF  RESTF],
 father(FIRSTF, FIRSTL),
 list_fathers(RESTL, RESTF).
^D
user reconsulted ...
 ? list_fathers([charles, harry, anne], [philip, charles, philip]).
yes
 ? list_fathers([charles, harry, anne], L).
L = [philip, charles, philip] ;
no
 ? list_fathers(L, [philip, charles, philip]).
L = [charles, william, charles] ;
L = [charles, william, anne] ;
L = [charles, william, andrew] ;
L = [charles, harry, charles]
yes
 ? list_fathers([X, anne, harry], [philip  REST]).
X = charles
REST = [philip, charles]
yes
 ? [user].
 /* A more elegant formulation of list_fathers */
 list_fathers([], []).
 list_fathers([FIRST REST], [FIRSTF RESTF]) :
 father(FIRSTF,FIRST), list_fathers(REST,RESTF).

 /* append(L, M, N) means that N is the result of appending L and M
 together. We use recursion on the argument L. If the null list
 is appended to M, then the result is M. If [X  RESTL] is appended
 to M giving N, then the first element of N is X, and the rest of
 N is the result of appending RESTL to M. */

 append(L, M, N) : L = [], M = N.
 append(L, M, N) :
 L = [X  RESTL], N = [X  RESTN], append(RESTL, M, RESTN).
 ^D
user reconsulted ...
 ? append([a,b,c], [d,e,f], [a,b,c,d,e,f]).
yes
 ? append([a,b,c], [d,e,f], N).
N = [a,b,c,d,e,f]
yes
 ? append([a,b,c], M, [a,b,c,d,e,f]).
M = [d,e,f]
yes
 ? append(L, M, [a,b,c,d,e,f]).
L = []
M = [a,b,c,d,e,f] ;
L = [a]
M = [b,c,d,e,f] ;
L = [a,b]
M = [c,d,e,f]
yes
 ? [user].
 /* A more elegant formulation of append */
 append([], M, M).
 append([XREST], M, [XRESTN]) : append(REST, M, RESTN).
 ^D
 Useful debugging functions.
trace.  Traces all predicate calls and exits.
spy .  Traces all calls and exits from the specified
predicate. For instance,
 ? spy member.
will cause all calls to member to be traced.
Prolog will stop and ask you for an action at each call.
You can get a list of all possible actions by typing a question mark.
Usually, you will just want to hit carriage return, to have Prolog
proceed to the next call.
listing() prints out all clauses with the predicate.
For example
 ? listing(member).
prints out
member(_3, [_3  _12 ]).
member(_3 , [_10  _12]) :
member(_3, _12).
Note that all variable names are replaced by _number.
 Arithmetic
 Prolog has integer and real arithmetic. Arithmetic works by
 function evaluation, as in ordinary languages, rather than
 by predicates. To assign the value of a term T to a variable X,
 write "X is T". For example, "A is B + 1", "X is 3"
 "WW is (A + B) / log(2)", etc. Note that any variables in the
 must have been instantiated to a numeric value; otherwise the
 "is" fails. If arithmetic relations such as == (numeric equality),
 >, <, >=, =<, are used to compare two terms, both terms must
 be instantiated to a numeric value.

 A variable can only be assigned once; "N is N+1" will always fail.
 Note: All of your functions have to be defined as predicates. You
 cannot define an evaluable function.
 Arithmetic expressions cannot be the head of a clause.
 ? X is 1, Y is X + X, Z is Y * Y.
X = 1
Y = 2
Z = 4
yes
 ? X is 1, Y is X + X, Y > X.
X = 1
Y = 2
yes
 ? X is 1, Y is X + X, X > Y.
no
 ? X is 1, Y > X.
 Error in arithmetic expression: not a number.
no
 ? [user].
 factorial(0,1).
 factorial(N,FACT) : M is N  1, factorial(M,MF), FACT is MF * N.
 ^D
user consulted ...
 ? factorial(5,F).
F = 120
yes
 ? [user].
 nthelement([X_], 1, X).
 nthelement([_REST],N,X) : N > 1, M is N1, nthelement(REST,M,X).
 ^D
user consulted ...
 ? nthelement([a,b,c,d,e,f], 4, X).
X = d
yes
 ? nthelement(L,3,a).
L = [_14,_11,a_5] ;
no
 Not
 If you have a goal of the form "\+", then Prolog tries
 to satisfy the literal. If the literal fails, then the goal
 "\+ ..." succeeds.
 ? [user].
 unparent(X,Y) : \+parent(X,Y).
 ^D
user consulted ...
 ? unparent(charles,anne).
yes
 ? unparent(philip,charles).
no.
 When \+ is used on a literal with variables, the wrong thing
 happens. Prolog does not return a value for which the statement is
 false; rather it checks to see if there are any values for which
 the statement is true, and, if there are any such values, the not
 fails. Even when the goal succeeds, no binding is returned for the
 variable.
 ? unparent(X,charles).
no
 The goal "parent(X,charles)" succeeds with X = elizabeth. Hence
 the goal "not(parent(X,charles))" fails
 ? unparent(X,philip).
X = _0
yes
 Example where "not" is needed to suppress invalid solutions on
 backtracking.
 ? [user].
 /* intersect(L,M,I) computes the intersection of the two lists L and M
 and gives the value in I */

 intersect([],M,[]).
 intersect([XL],M,[XI]) : member(X,M), intersect(L,M,I).
 intersect([_L],M,I) : intersect(L,M,I).
 ^D
 This definition gives the correct solution on the first try, but
 then backtracks to partial solutions
 ? intersect([a,b,c,d], [d,f,e,b], I).
I = [b,d] ;
I = [b] ;
I = [d] ;
I = []
no.
 ? [user].

 intersect([],M,[]).
 intersect([XL],M,[XI]) : member(X,M), intersect(L,M,I).
 intersect([XL],M,I) : \+member(X,M), intersect(L,M,I).
 ^D
 ? intersect([a,b,c,d], [d,f,e,b], I).
I = [b,d] ;
no
 Cut Operator.
 The cut operator, denoted by an exclamation point !, is used to
 control backtracking. If the cut operator occurs in the tail of
 a clause, then, if the clause is invoked, and the goals in the
 clause becore the cut succeed, the cut succeeds immediately, and
 the next goal is tried. On backtracking, if Prolog backtracks to
 the cut operator, then the goal which invoked the clause fails
 immediately. The preceding literals in the tail are not tried
 again, and no other clauses are tried for the invoking goal.
 There are three major uses for the cut operator. The first is
 to signal Prolog that the right rule in a given case has been
 reached, and that no other rules need be tried. This can be used
 to create the equivalent of a "case" statement out of several
 clauses, by making sure that only one of them is tried for each
 goal. This is particularly useful when there are a small number of
 exceptions to a general rule. Enumerate the exceptions first,
 with cut operators.
[user].
 locomotion(X,swim) : inst(X, whale), !.
 locomotion(X,swim) : inst(X, seal), !.
 locomotion(X,fly) : inst(X, bat), !.
 locomotion(X,run) : inst(X, mammal), !.
 locomotion(X,run) : inst(X, ostrich), !.
 locomotion(X,swim) : inst(X, penguin), !.
 locomotion(X,fly) : inst(X, bird), !.
 locomotion(X,swim) : inst(X, fish).
 Now, we add some particular animals and categories
 inst(wally,whale).
 inst(cathy,cow).
 inst(X,mammal) : inst(X,whale).
 inst(X,mammal) : inst(X,cow).
EOT
 ? locomotion(cathy, L).
L = run ;
no.
 ? locomotion(wally, L).
L = swim ;
no.
 Without the cut mark, the query for "wally" would have backtracked and
 found the second solution L = run, because wally is also a mammal.
 A more subtle example of the same thing is in the intersection
 predicate:
 intersect([], M, []).
 intersect([X  RL], M, [X  RI]) :
 member(X,M), !, intersect(RL, M, RI).
 intersect([_  RL], M, I) :
 intersect(RL, M, I).
 Here the cut operator in the second rule signals Prolog that, if
 member(X,M) succeeds, then this rule, which makes X a member of I,
 should be used, and that the third rule, which leaves X
 out of I, should not be invoked, even on backtracking.
 Note that, in both these cases, we could have achieved the same
 effect using "\+" with rules like
 locomotion(X,run) :
 \+inst(X,whale), \+inst(X,seal), \+inst(X,bat)),
 inst(X,mammal).
 or
 intersection([X  RL], M, RI) :
 \+member(X,M), intersection(RL, M, I).
 but these are substantially inefficient.
 Sometimes you want to do this just for efficiency.
 /* mult_list(L,N) returns N as the product of all the number in L.
 For example, mult_list([4,5,6],N) returns N=120. If 0 is encountered,
 then return 0 immediately without proceeding. */
 mult_list([],1).
 mult_list([0  _], 0) : !.
 mult_list([X RL], N) :
 mult_list(RL,N1), N is X * N1.

 Cut/Fail
 If we want to signal particular cases where the goal cannot be
 satisfied, we test for those case, use the cut operator, and then
 fail.
 can_fly(X) : inst(X,ostrich), !, fail.
 can_fly(X) : inst(X,penguin), !, fail.
 can_fly(X) : dead(X), !, fail.
 can_fly(X) : inst(X, bird).
 Use cut to stop backtracking after finding first solution.
 /* factorize(N,FACTORS) returns FACTORS as the list of prime factors
 of N */
 factorize(1, []) : !.
 factorize(N, [FACT  REST_FACTS]) :
 find_factor(N,FACT,2), N1 is N/FACT, factorize(N1, REST_FACTS).
 /* find_factor(N,FACT,LOW) returns the smallest factor of N greater
 than or equal to LOW. */
 find_factor(N,FACT,FACT) : R is N mod FACT, R = 0, !.
 find_factor(N,FACT,LOW) :
 N1 is LOW+1, N1 <= N, find_factor(N,FACT,N1).
 Side effects.
 assertz(CLAUSE) asserts a clause at the end of the database.
 asserta(CLAUSE) asserts a clause at the beginning of the database.
 retract(CLAUSE) retracts a clause unifying with CLAUSE.
 You can use this to get the effect of global variables.
 assign(V,VALUE) :
 ( retract(value_of(V,_)); true),
 asserta(value_of(V,VALUE)).
 ? assign(x,1).
yes
 ? value_of(x,VALUE).
VALUE = 1
yes
 ? assign(x,2).
yes
 ? value_of(x,VALUE).
VALUE = 2
yes
 IMPORTANT: Keep this style of programming to an ABSOLUTE MINIMUM.
 Using backtracking for looping with sideeffects.
 display_children(X) : parent(X,C), nl, write(C), fail.
 display_children(_).
 ? display_children(philip).
charles
anne
andrew
yes
 ? [user].
 copy_children(X,Y) : parent(X,C), assertz(parent(Y,C)), fail.
 copy_children(_,_).
 ^D
 ? copy_children(philip,moe).
yes
 ? display_children(moe).
charles
anne
andrew
yes