Tuesday 6/12/2012 from 7-10pm
CENTER 105
Stay tuned for review session
- Program = Algorithm + Data Structures
- Execute
- Program = Facts + Rules
- Query
- 1970s: Logic + Automated Theorem Proving
- Developed for Artificial Intelligence
- Carnitas is Mexican
- Mexican food is delicious
- What is a delicious food ?
- Carnitas!
- Specify what you want
- Specify desired properties of result
- Not how to obtain result
Ideal for Searching Large Space of Results
- It is often hard to specify search algorithm
- But easy to specify the characteristics of the solution.
A to B with price (P1) AND B to C with price (P2)...Then
A to C with price (P1 + P2) ...
- What is cheapest flight from SAN to JFK with duration < 6 Hrs ?
- El Cuervo makes CA Burrito (profit =
$2), Fish Taco (profit =$1)
- Burrito Capacity <
200- Taco Capacity <
500- Total Capacity <
400
max 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)
- Scheduling
- Travel, Sports, ...
- Rule-based Anomaly detection
- Credit card fraud!
- SQL (and similar DB Query Languages)
- Find all pairs of stocks, with same price on same day,
- More than 50 times last year
- Many of these are inspired-by / subsets of Prolog ...
- Terms
- Facts
- Queries (Implementation: Unification)
- Rules
- Programs (Implementation: Backtracking Search)
- Numeric Computation
- Data Structures
- Puzzle Solving
Prolog Program
... but facts and rules about what ?
- Terms
"Tree-like" values, similar to Ocaml ADTs
- Constants
- Atoms
- Variables
- Compound Terms
Constants the simplest term, representing primitive values
- Basic types like integers, reals
- Examples:
1,92,4.4
Atom: any identifier starting with lower-case
x,alice,taco,giraffe,appleSauce
Atom: any identifier starting with lower-case
x, alice, taco, giraffe, appleSauce
- Elements of a single mega enum type
- Similar to tags used in ML types (except ML tags are uppercase)
type atoms = x | alice | taco | giraffe | appleSauce | ...
Atom: any identifier starting with lower-case
x, alice, taco, giraffe, appleSauce
- Prolog knows NOTHING about the tags, they are just names
- Each tag is equal to itself (more later...)
alice = alicetaco = taco
- Each tag is disequal to every other tag
alice = taconever holds in Prolog
Variables: any identifier starting with upper-case
X, Y, Z, Head, Tail, Taco, Burrito, Alice, Bob
_ is the wildcard variable, similar to ML
- Even though
x = amakes no sense to Prolog ...
- ...
X = adoes 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
- Terms are NOT Function Calls!
- More like trees
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 
- The term is just a box containing
5labeledfactorial
Prolog term factorial(5) is simply the tree 
5 labeled factorial
factorialjust a label called a function symbol
- Prolog has no idea about implementation of function ...
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).
- Note
kim,holly,margaretetc. are all atoms
- Facts are just terms (typically without variables.)
- Specified by term followed by
.
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).
- You can make up and add new facts to the collection
- We will be able to ask Prolog queries over these facts
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).
- Represent functions that evaluate to a boolean
- e.g.
parentis 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)
- Programmer mentally notes that:
parent(kim, holly)meanskimis a "parent-of"hollyparent(margaret, kim)meansmargaretis a "parent-of"kim- etc.
Standard 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:
- Plg: Prompts you to type a query
- You: Type a query
- Plg: Tries to prove your query
- Plg: Prints out the result (or
failure)
- Repeat (go to 1)
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.
- This is not one of the facts we gave it, and,
- We are yet to supply it with rules for inferring new facts.
A slightly different query yields a different result.
A slightly different query yields a different result.
?- parent(margaret, kim).
true.
- As this was indeed one of the facts loaded in lec-prolog
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
- Some
parentOforchildOfmethods
- to represent parent-child relationship
- Some looping or iteration
- to search through all pairs
- Instead, Prolog uses facts and queries
- to search forwards and backwards
- to enumerate all results
- in a single uniform declarative manner!
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.
- Q: When is the term
Xidentical to the termkim?
- A: When we substitute
Xwith the valuekim!
?- 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.
- Pretty simple...
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).
- Subst
W = 2. Query is:a(2, foo(2, Y), Y) = a(2, foo(X, 3), Z).
- Subst
X = 2. Query is:a(2, foo(2, Y), Y) = a(2, foo(2, 3), Z).
- Subst
Y = 3. Query is:a(2, foo(2, 3), 3) = a(2, foo(2, 3), Z).
- Subst
Z = 3. Query is:a(2, foo(2, 3), 3) = a(2, foo(2, 3), 3).
- Done!
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).
- Subst
W = 2. Query is:a(2, foo(2, Y), Y) = a(2, foo(X, 3), X).
- Subst
X = 2. Query is:a(2, foo(2, Y), Y) = a(2, foo(2, 3), 2).
- Subst
Y = 3. Query is:a(2, foo(2, 3), 3) = a(2, foo(2, 3), 2).
3 = 2cannot be unified, Fail!
When we ask
?- parent(margaret, X).
Prolog checks if the above term can be unified with any known fact (term).
- If unification succeeds then it replies
true
- And also the unifying substitutions for
X- Which are the solutions for the query!
- If unification fails then it replies
false
When 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.
- For example, to determine if
margaretis the grandparent ofholly
Often useful to ask questions over multiple terms.
margaret is the grandparent of holly?- parent(margaret, X), parent(X, holly).
- Is there a person
Xwho is a child ofmargaretAND a parent ofholly?
- Is there
Xs.t.parent(margaret, X)ANDparent(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.
- For example, to find the great-grandparents of
kim
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.
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).
- Conjunctions let us mine the database for complex relationships...
- ... but its cumbersome to repeatedly write down long queries
- We need a way to compose complex queries from simple queries...
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
- Fact: Clause without any conditions
- Rules: Clause with conditions
- Basic Facts / Predicates
- Rules for generating new Facts / Predicates
Complex Programs need Complex Predicates with Multiple Rules
- Scope
- Multiple Rules: Disjunction
- Multiple Rules: Recursion
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).
- In Prolog, the scope of a variable is the single rule containing it.
- There is no connection between variables across rules.
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
- either have a parent
- or have a child
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)
- If we can prove
parent(X, _)Then we can provehas_family(X)
- If we can prove
parent(_, X)Then we can provehas_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)... or
parent(Anc, P)andparent(P, Child)... or
parent(Anc, GP)andparent(GP, P)andparent(P, Child)... or
- ... if some chain of parent-links holds between
AncandChild.
Lets write a predicate ancestor(Anc, Child) which is true if
... if some chain of parent-links holds between Anc and Child.
- If
Ancis the parent ofChild
ancestor(Anc, Child) :- parent(Anc, Child).
- If
Pis the parent ofChildandAncis an ancestor ofP
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 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!