Tuesday 6/12/2012 from 7-10pm
CENTER 105
Stay tuned for review session
Ideal for Searching Large Space of Results
A to B with price (P1) AND B to C with price (P2)...Then
A to C with price (P1 + P2) ...$2), Fish Taco (profit = $1)200500400max 2.x + 1.y /* profit */
s.t. x < 200 /* burrito capacity */
y < 400 /* taco capacity */
x+y < 300 /* total capacity */
0 < x, y /* must produce! */
Used heavily in many domains (together with statistical methods)
Prolog Program
... but facts and rules about what ?
"Tree-like" values, similar to Ocaml ADTs
Constants the simplest term, representing primitive values
1, 92, 4.4Atom: any identifier starting with lower-case
x, alice, taco, giraffe, appleSauceAtom: any identifier starting with lower-case
x, alice, taco, giraffe, appleSaucetype atoms = x | alice | taco | giraffe | appleSauce | ...Atom: any identifier starting with lower-case
x, alice, taco, giraffe, appleSaucealice = alicetaco = tacoalice = taco never holds in PrologVariables: any identifier starting with upper-case
X, Y, Z, Head, Tail, Taco, Burrito, Alice, Bob
_ is the wildcard variable, similar to ML
x = a makes no sense to Prolog ...X = a does have a meaning but not what you might think!Compound terms are of form atom(term1, term2, term3, ...)
Where each term is one-of
Compound terms are of form atom(term1, term2, term3, ...)
Where each term is one-of
x(y, z) % y, z are atoms
parent(alice, bob) % alice, bob are atoms
parent(alice, Child) % alice is an atom, Child is a variable

Compound terms are of form atom(term1, term2, term3, ...)
Each term is one-of
type term = Constant of int
| Atom of string
| Variable of string
| Compound of string * term list
type term = Constant of int
| Atom of string
| Variable of string
| Compound of string * term list
(Hint: atom = lowercase, variable = uppercase)
Which Ocaml value of type term represents Prolog term parent(alice, bob) ?
A. parent ("alice", "bob")
B. parent (Atom "alice", Atom "bob")
C. [Atom "parent"; Atom "alice"; Atom "bob"]
D. Compound ("parent", [Atom "alice"; Atom "bob"])
E. Compound (Atom "parent", [Atom "alice"; Atom "bob"])
Prolog term parent(alice, Charlie) is represented by:
Compound ("parent", [Atom "alice"; Var "Charlie"])
type term = Constant of int
| Atom of string
| Variable of string
| Compound of string * term list
(Hint: atom = lowercase, variable = uppercase)
What Ocaml value of type term represents Prolog term factorial(5) ?
A. factorial(5)
B. factorial(Atom 5)
C. 120
D. Constant 120
E. Compound ("factorial", [Constant 5])
Prolog term factorial(5) is simply the tree 
5 labeled factorialProlog term factorial(5) is simply the tree 
5 labeled factorialfactorial just a label called a function symbolThe following facts specify a list of parent-child relationships
parent(kim, holly).
parent(margaret, kim).
parent(herbert, margaret).
parent(john, kim).
parent(felix, john).
parent(albert, felix).
kim, holly, margaret etc. are all atoms.The following facts specify a list of parent-child relationships
parent(kim, holly).
parent(margaret, kim).
parent(herbert, margaret).
parent(john, kim).
parent(felix, john).
parent(albert, felix).
The following facts specify a list of parent-child relationships
parent(kim, holly).
parent(margaret, kim).
parent(herbert, margaret).
parent(john, kim).
parent(felix, john).
parent(albert, felix).
parent is a predicate of arity 2 (that takes 2 arguments)The following facts specify a list of parent-child relationships
parent(kim, holly).
parent(margaret, kim).
parent(herbert, margaret).
parent(john, kim).
parent(felix, john).
parent(albert, felix).
parent is a predicate of arity 2 (that takes two arguments)parent(kim, holly) means kim is a "parent-of" hollyparent(margaret, kim) means margaret is a "parent-of" kimStandard interface is a REPL shell
$ rlwrap swipl
130f@ieng6-202]:~:501$ swipl
Welcome to SWI-Prolog (Multi-threaded, 32 bits, Version 5.10.5)
Copyright (c) 1990-2011 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.
For help, use ?- help(Topic). or ?- apropos(Word).
?-
Suppose we have a collection of facts saved in lec-prolog.pl
You can load the facts in ...
?- consult('lec-prolog.pl').
% foo.pl compiled 0.00 sec, 10,640 bytes
true.
... or you can add them one-at-a-time
?- assert(parent(margaret, kim)).
Once facts are loaded, you query Prolog as follows:
failure)The simplest possible query ...
?- parent(margaret, john).
... a fact but typed at the prompt.
The simplest possible query ...
?- parent(margaret, john).
... a fact but typed at the prompt.
O Prolog, is this fact in your Database ... or can it be inferred from your database?
The simplest possible query ...
?- parent(margaret, john).
... a fact but typed at the prompt.
O Prolog, is this fact in your database ... or can it be inferred from your database?
?- parent(margaret, john).
false.
A slightly different query yields a different result.
A slightly different query yields a different result.
?- parent(margaret, kim).
true.
This is where Prolog starts to depart radically from other paradigms...
?- parent(margaret,X).
O Prolog, for which value(s) of
Xis the fact provable ?
This is where Prolog starts to depart radically from other paradigms...
?- parent(margaret,X).
O Prolog, for which value(s) of
Xis the fact provable ?
X = kim.
As when it plugs-in kim for X, it can infer parent(margaret, kim).
Suppose we flip the query.
?- parent(X, kim).
O Prolog, for which value(s) of
Xisparent(X, kim)provable ?
Suppose we flip the query.
?- parent(X, kim).
O Prolog, who are the parents-of
kim?
Suppose we flip the query.
?- parent(X, kim).
O Prolog, who are the parents-of
kim?
?- parent(X, kim).
X = margaret ; % [press ';' if you want another solution]
X = john ; % [press ';' if you want another solution]
false. % [thats all folks, no more solutions ]
Returns all solutions for X that make parent(X, kim) provable.
We can write queries with multiple variables.
?- parent(X, Y).
O Prolog, for which pairs
X,Yisparent(X, Y)provable?
We can write queries with multiple variables.
?- parent(X, Y).
O Prolog, for which pairs
X,Yisparent(X, Y)provable?
?- parent(X, Y).
X = kim, Y = holly ;
X = margaret, Y = kim ;
X = herbert, Y = margaret;
X = john, Y = kim ;
X = felix, Y = john ;
X = albert, Y = felix ;
X = albert, Y = dana ;
X = felix, Y = maya .
Enumerates all facts in the parent database.
Suppose we want to know if there are any strange circularities in the database:
Does there exist any person who is their own parent ?
Which of the following encodes the above in Prolog?
A. parent(kim, kim)
B. parent(x, x)
C. parent(X, X)
D. parent(X, Y)
E. parent(Y, X)

In Java/C# or for that matter ML/Scala/... you would need
parentOf or childOf methods
We can substitute values for their variables to make the terms identical
In Prolog, when you write (e.g. in a query)
?- term1 = term2.
you are asking whether term1 can be unified with term2.
?- kim = kim.
true.
Two same atoms are trivially unified.
?- kim = holly.
false.
Two different atoms can never be unified.
?- foo(kim) = foo(kim).
true.
As there are no variables, and the terms are already identical.
?- foo(kim) = foo(holly).
false.
As there are no variables, and the terms can never be identical.
?- X = kim.
X identical to the term kim?X with the value kim!?- foo(X) = foo(kim).
Q: When is the term X identical to the term kim?
A: When we substitute X with the value kim!
?- foo(X) = foo(kim).
X = kim.
How does Prolog respond to the following query?
?- foo(X, dog) = foo(cat, Y).
A. false
B. X = cat, Y = cat.
C. X = dog, Y = dog.
D. X = dog, Y = cat.
E. X = cat, Y = dog.
?- p(X, dog, X) = p(cat, Y, Y).
?- p(X, dog, X) = p(cat, Y, Y).
The top nodes of both trees have same predicate ... go inside.
?- p(X, dog, X) = p(cat, Y, Y).
To unify X and cat use substitution X = cat
?- p(X, dog, X) = p(cat, Y, Y).
Apply substitution X = cat to both terms. Move on to next leaf...
?- p(X, dog, X) = p(cat, Y, Y).
To unify dog and Y use substitution Y = dog ...
?- p(X, dog, X) = p(cat, Y, Y).
... and apply substitution throughout both terms.
?- p(X, dog, X) = p(cat, Y, Y).
Uh oh, now last leaf has different atoms...
?- p(X, dog, X) = p(cat, Y, Y).
... impossible to unify cat and dog. Unification fails.
?- p(X, dog, X) = p(cat, Y, Y).
false.
How does Prolog respond to the following unification query?
?- a(W, foo(W, Y), Y) = a(2, foo(X, 3), Z).
A. false. (No unification possible)
B. W = 2, X = 2, Y = 2, Z = 2.
C. W = 2, X = 2, Y = 3, Z = 3.
D. W = 3, X = 3, Y = 2, Z = 2.
C. W = 2, X = 3, Y = 2, Z = 3.
How does Prolog respond to the following unification query?
?- a(W, foo(W, Y), Y) = a(2, foo(X, 3), Z).
W = 2. Query is: a(2, foo(2, Y), Y) = a(2, foo(X, 3), Z).X = 2. Query is: a(2, foo(2, Y), Y) = a(2, foo(2, 3), Z).Y = 3. Query is: a(2, foo(2, 3), 3) = a(2, foo(2, 3), Z).Z = 3. Query is: a(2, foo(2, 3), 3) = a(2, foo(2, 3), 3).How does Prolog respond to the following unification query?
?- a(W, foo(W, Y), Y) = a(2, foo(X, 3), Z).
W = 2,
X = 2,
Y = 3,
Z = 3.
How does Prolog respond to the following unification query?
?- a(W, foo(W, Y), Y) = a(2, foo(X, 3), X).
A. false. (No unification possible)
B. W = 2, X = 2, Y = 2, Z = 2.
C. W = 2, X = 2, Y = 3, Z = 3.
D. W = 3, X = 3, Y = 2, Z = 2.
C. W = 2, X = 3, Y = 2, Z = 3.
How does Prolog respond to the following unification query?
?- a(W, foo(W, Y), Y) = a(2, foo(X, 3), X).
W = 2. Query is: a(2, foo(2, Y), Y) = a(2, foo(X, 3), X).X = 2. Query is: a(2, foo(2, Y), Y) = a(2, foo(2, 3), 2).Y = 3. Query is: a(2, foo(2, 3), 3) = a(2, foo(2, 3), 2).3 = 2 cannot be unified, Fail!When we ask
?- parent(margaret, X).
Prolog checks if the above term can be unified with any known fact (term).
true
XfalseWhen we ask
?- parent(margaret, X).
Prolog checks if the above term can be unified with any known fact (term).
true (and the solutions for X)false?- parent(margaret, X).
X = kim.
When we ask
?- parent(X, kim).
When we ask
?- parent(X, kim).
Prolog checks if the above term can be unified with any known fact (term).
true (and the solutions for X)falseWhen we ask
?- parent(X, kim).
Prolog checks if the above term can be unified with any known fact (term).
true (and the solutions for X)false?- parent(X, kim).
X = margaret ;
X = john .
Finally, when we ask
?- parent(X, Y).
Finally, when we ask
?- parent(X, Y).
Prolog checks if the above term can be unified with any known fact (term).
true (and solutions for X, Y)falseFinally, when we ask
?- parent(X, Y).
Prolog checks if the above term can be unified with any known fact (term).
true (and solutions for X, Y)?- parent(X, Y).
X = kim, Y = holly ;
X = margaret, Y = kim ;
X = herbert, Y = margaret;
X = john, Y = kim ;
X = felix, Y = john ;
X = albert, Y = felix ;
X = albert, Y = dana ;
X = felix, Y = maya .
Often useful to ask questions over multiple terms.
margaret is the grandparent of hollyOften useful to ask questions over multiple terms.
margaret is the grandparent of holly?- parent(margaret, X), parent(X, holly).
X who is a child of margaret AND a parent of holly ?X s.t. parent(margaret, X) AND parent(X, holly) ?Often useful to ask questions over multiple terms.
margaret is the grandparent of holly?- parent(margaret, X), parent(X, holly).
Is there a person X who is a child of margaret AND a parent of holly ?
Is there X s.t. parent(margaret, X) AND parent(X, holly) ?
?- parent(margaret, X), parent(X, holly).
X = kim.
Often useful to ask questions over multiple terms.
kimOften useful to ask questions over multiple terms.
kim?- parent(GGP, GP), parent(GP, P), parent(P, kim).
Note: how we link the terms with a variable to capture relationships.
Often useful to ask questions over multiple terms.
kim?- parent(GGP, GP), parent(GP, P), parent(P, kim).
Note: how we link the terms with a variable to capture relationships.
Prolog finds appropriate unifiers and replies
?- parent(margaret, X), parent(X, holly).
GGP = john,
GP = felix,
P = albert.
i.e. john is a great-grandparent following the above chain.
Which of these queries is true iff margaret and kim are (half-) siblings?
A. parent(margaret, kim)
B. parent(margaret, X), parent(X, kim).
C. parent(kim, X), parent(X, margaret).
D. parent(margaret, X), parent(kim, X).
E. parent(X, margaret), parent(X, kim).
headQuery :- condQuery1, condQuery2, condQuery3,...
headQuery :- condQuery1, condQuery2, condQuery3,...
If you can prove condQuery1 AND condQuery2 AND ...
Then you can prove headQuery
headQuery :- condQuery1, condQuery2, condQuery3,...
To prove the goal headQuery ...
Prove subgoals condQuery1 AND condQuery2 AND ...
grandparent predicateOur database includes a parent predicate
Let us use it to define a grandparent predicate
grandparent predicategrandparent(GP, GC) :- parent(GP, P), parent(P, GC).
GP is a grandparent of GC if GP is a parent of P and P is a parent of GC
grandparent predicategrandparent(GP, GC) :- parent(GP, P), parent(P, GC).
?- grandparent(X, kim). % who are the grandparents of kim
X = herbert ; % hit ; to see next
X = felix ; % hit ; to see next
false. % thats it!
grandparent predicategrandparent(GP, GC) :- parent(GP, P), parent(P, GC).
?- grandparent(X, kim). % who are the grandparents of kim
X = herbert ; % hit ; to see next
X = felix ; % hit ; to see next
false. % thats it!
?- parent(herbert, P), parent(P, kim). %% Solution 1. X = herbert
P = margaret.
?- parent(felix, P), parent(P, kim). %% Solution 2. X = felix
P = john .
Which of the following is a valid greatgrandparent predicate?
(Btw, greatgrandparent is the parent of a grandparent.)
% A
greatgrandparent(X, Y) :- parent(X, Y), grandparent(X, Y).
% B
greatgrandparent(X, Y) :- parent(X, Z), grandparent(Z, Y).
% C
greatgrandparent(X, Y) :- grandparent(X, Z), parent(Z, Y).
% D
greatgrandparent(X, Y) :- parent(X, Z), parent(Z, Y).
% E
greatgrandparent(X, Y) :- parent(X, Z), parent(Z, Z1), parent(Z1, Y).
greatgrandparent predicategreatgrandparent(GGP, GC) :- parent(GGP, GP), grandparent(GP, GC).
greatgrandparent predicategreatgrandparent(GGP, GC) :- parent(GGP, GP), grandparent(GP, GC).
?- greatgrandparent(X, holly).
X = herbert.
Facts and Rules are two kinds of clauses
Complex Programs need Complex Predicates with Multiple Rules
Complex Programs need Complex Predicates with Multiple Rules
Scope
Multiple Rules: Disjunction
Multiple Rules: Recursion
A word about scope.
In the grandparent rule, the variable GP appears twice
greatgrandparent(GGP, GC) :- parent(GGP, GP), grandparent(GP, GC).
A word about scope.
In Prolog, the scope of a variable is the single rule containing it.
There is no connection between variables across rules.
foo(P) :- bar(P). % There is no connection between P
stuff(P) :- thing(P). % across the two rules
Complex Programs need Complex Predicates with Multiple Rules
Scope
Multiple Rules: Disjunction
Multiple Rules: Recursion
Lets write a predicate has_family which is true for persons who
Lets write a predicate has_family which is true for persons who
either have a parent
or have a child
has_family(X) :- parent(X, _). % if X is the parent of some _
has_family(X) :- parent(_, X). % if X is the child of some _
_ is a wildcard or dont-care variable (as in ML, Scala)
parent(X, _) Then we can prove has_family(X)parent(_, X) Then we can prove has_family(X)Lets write a predicate has_family which is true for persons who
either have a parent
or have a child
has_family(X) :- parent(X, _). % if X is the parent of some _
has_family(X) :- parent(_, X). % if X is the child of some _
?- has_family(holly).
true. % Second rule fires for holly
?- has_family(mugatu).
false. % Neither rule fires for mugatu
Lets write a predicate has_family which is true for persons who
either have a parent
or have a child
has_family(X) :- parent(X, _). % if X is the parent of some _
has_family(X) :- parent(_, X). % if X is the child of some _
Can be abbreviated to
has_family(X) :- parent(X, _) ; parent(_, X).
Semicolon ; indicates disjunction.
Complex Programs need Complex Predicates with Multiple Rules
Scope
Multiple Rules: Disjunction
Multiple Rules: Recursion
Lets write a predicate ancestor(Anc, Child) which is true if
parent(Anc, Child) ... orparent(Anc, P) and parent(P, Child) ... orparent(Anc, GP) and parent(GP, P) and parent(P, Child) ... orAnc and Child.Lets write a predicate ancestor(Anc, Child) which is true if
... if some chain of parent-links holds between Anc and Child.
Anc is the parent of Childancestor(Anc, Child) :- parent(Anc, Child).P is the parent of Child and Anc is an ancestor of Pancestor(Anc, Child) :- parent(P, Child), ancestor(Anc, P).Lets write a predicate ancestor(Anc, Child) which is true if
... if some chain of parent-links holds between Anc and Child.
ancestor(Anc, Child) :- parent(Anc, Child).
ancestor(Anc, Child) :- parent(P, Child), ancestor(Anc, P).
Lets write a predicate ancestor(Anc, Child) which is true if
... if some chain of parent-links holds between Anc and Child.
ancestor(Anc, Child) :- parent(Anc, Child).
ancestor(Anc, Child) :- parent(P, Child), ancestor(Anc, P).
Lets take it out for a spin!
First, lets find descendants (forwards)
?- ancestor(kim, X).
X = holly.
Lets write a predicate ancestor(Anc, Child) which is true if
... if some chain of parent-links holds between Anc and Child.
ancestor(Anc, Child) :- parent(Anc, Child).
ancestor(Anc, Child) :- parent(P, Child), ancestor(Anc, P).
Lets take it out for a spin!
Next, lets find ancestors (backwards)
?- ancestor(X,kim).
X = margaret ;
X = john ;
X = herbert ;
X = felix ;
X = albert .
kim has a long ancestry!