2
Administrivia
• Homework 1– graded and returned by email– reviewed today
• Reminder– Homework 2 due tonight (by midnight)
• see the hint posted?
3
Homework 1 Review
• Use databasebird(robin). “robin is a bird”
bird(eagle). “eagle is a bird”
• (2pts) What do the following queries return as an answer?
• The queries?- \+ bird(Eagle).?- \+ \+ bird(robin).
• (6pts) Give the logical reasoning for each answer
Key observationcase of first letter matters in Prolog, Eagle is a variable
• ?- \+ bird(Eagle).• false.
• ?- trace.• true.
• [trace] ?- \+ bird(Eagle).• Call: (7) bird(_G334) ? • Exit: (7) bird(robin) ? • false.
4
Homework 1 Review
• Use databasebird(robin). “robin is a bird”
bird(eagle). “eagle is a bird”
• (2pts) What do the following queries return as an answer?
• The queries?- \+ bird(Eagle).?- \+ \+ bird(robin).
• (6pts) Give the logical reasoning for each answer
• ?- \+ \+ bird(robin).• true.[trace] ?- \+ \+ bird(robin). Call: (7) bird(robin) ? Exit: (7) bird(robin) ? true.
debugger gave only abbreviated information
• \+ \+ bird(robin) is true if• \+ bird(robin) is false if• bird(robin) is true• but bird(robin) is true since it’s in the
database• so \+ bird(robin) is false • and so \+ \+ bird(robin) is true • that’s why Prolog says true
5
Homework 1 Review
• (2pts) In Exercise 4, we stated:– has_feathers(Y) :-
bird(Y).– However, it is common
knowledge that, of all the animals in the world, all birds have feathers and only birds have feathers.
– What is missing from my Prolog rule?
– Submit the missing rule.
Key observation:Looking for some way to say “if and only if”e.g. has_feathers(Y) iff bird(Y).
has_feathers(Y) :- bird(Y).bird(Y):- has_feathers(Y).
Assert?- assert((bird(Y):- has_feathers(Y))).
Circularity in definition
6
Homework 1 Review
• (4pts) Although all birds have feathers, not all birds fly, e.g. penguins and ostriches– Add these two birds to the database– Make sure bird/1 and has_feathers/1 are true for them– Modify the can_fly rule to exclude them– hint: look up conjunction (comma symbol in Prolog)– Submit the completed database
% flightless birds
bird(penguin).bird(ostrich).has_feathers(Y) :- bird(Y).
Modifycan_fly(X) :- has_feathers(X).
Key observation:need to specify the fact that certain birds are flightless, and that those birds are excluded from can_fly/1
flightless(penguin).flightless(ostrich). can_fly(X) :- has_feathers(X), \+
flightless(X).
Homework 1 Review
• (4pts) Although all birds have feathers, not all birds fly, e.g. penguins and ostriches– Add these two birds to the database– Make sure bird/1 and has_feathers/1 are true for them– Modify the can_fly rule to exclude them– hint: look up conjunction (comma symbol in Prolog)– Submit the completed database
?- can_fly(X).X = robin ;X = eagle ;false.
?- can_fly(penguin).false.?- trace.true.[trace] ?- can_fly(penguin). Call: (6) can_fly(penguin) ? Call: (7) has_feathers(penguin) ? Call: (8) bird(penguin) ? Exit: (8) bird(penguin) ? Exit: (7) has_feathers(penguin) ? Call: (7) flightless(penguin) ? Exit: (7) flightless(penguin) ? Fail: (6) can_fly(penguin) ? false.
8
Today’s Topics
• More on recursion
• Last time– we defined lastinlist/2 and len/2 to pick the last
element of a list and compute the length of a list, respectively.
lastinlist([X],X). (base case) lastinlist([X|L],Y) :- lastinlist(L,Y). (recursive case)
len([],0). (base case)
len([X|L],N) :- len(L,M), N is M+1. (recursive case)
9
Today’s Topics
• More on recursion
– Look at taking apart and putting lists together– And symbols (atoms)
10
Building and Taking Atoms Apart
• Built-in predicate atom_chars/2 has two modes of usage– atom_chars(symbol,list)
1. takes names apart• ?- atom_chars(will,X).– X is the list of characters representing will
2. builds names from a list of characters• ?- atom_chars(X,[’J’,o,h,n]).
– use single quotes around capitalized J to avoid J being interpreted as a variable
• ?- atom_chars(X,[w,o,n,’’’’,t]).– ’’’’ denotes the single quote (or ’\’’)
11
Building and Taking Atoms Apart
more example queries• ?- atom_chars(has,[h,a,s]).
– Yes
• ?- atom_chars(will,[w,X,l,l]).– X = i
• ?- atom_chars(X,Y).
what happens here?
• ?- atom_chars(X,[J,o,h,n]).
13
Building and Taking Lists Apart
• append/3 is a built-in predicate in SWI-Prolog defined as follows:
– append(L1,L2,L3) is true– if list L3 is the linear concatenation
of lists L1 and L2 [1,2] append [3,4] = [1,2,3,4]
• Example– ?- append([1,2],[3,4],
[1,2,3,4]).• Note
– append/3 has multiple modes of usage
– i.e. it can be used to take apart as well as concatenate lists
• let’s run example queries– ?- append([1],[2,3],X).– ?- append(X,Y,[1,2]).– ?- append(_,[X],[1,2,3]).– ?- append(X,Y,Z).
• Note: – the underscore character ‘_’ is a variable
with no name– it’s a variable but we don’t care about its
final value– no binding will be reported by the
interpreter for underscores
14
Building and Taking Lists Apart
• append/3 can be defined recursively as follows:
– app([],L,L). Base case– app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
• we use the predicate name app/3 here to avoid a naming clash• append/3 is already defined (built-in)
15
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
• Base case says:– if we concatenate [] with an arbitrary list L, we get L
• Recursive case says:– if I have a list headed by X and the tail is L1, i.e. [X|L1], and I want to
concatenate that to another list L2– the answer is going to be a list headed by X– the tail is some other list L3– where L3 is defined as– the concatenation of L1 and L2
Example
?- app([1,2,3],[4,5],L).L = [1|L3]
where L3 is given by
?- app([2,3],[4,5],L3).
16
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
• Base case says:– if we concatenate [] with an arbitrary list L, we get L
• Recursive case says:– if I have a list headed by X and the tail is L1, i.e. [X|L1], and I want to
concatenate that to another list L2– the answer is going to be a list headed by X– the tail is some other list L3– where L3 is defined as– the concatenation of L1 and L2
Example
?- app([1,2,3],[4,5],L).L = [1|L3] where L3 is given by
?- app([2,3],[4,5],L3).L3 = [2|L3’] where L3’ is given by
?- app([3],[4,5],L3’).
17
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
• Base case says:– if we concatenate [] with an arbitrary list L, we get L
• Recursive case says:– if I have a list headed by X and the tail is L1, i.e. [X|L1], and I want to
concatenate that to another list L2– the answer is going to be a list headed by X– the tail is some other list L3– where L3 is defined as– the concatenation of L1 and L2
Example
?- app([1,2,3],[4,5],L).L = [1|L3] where L3 is given by
?- app([2,3],[4,5],L3).L3 = [2|L3’] where L3’ is given by
?- app([3],[4,5],L3’).L3’ = [3|L3”] where L3” is given by
?- app([],[4,5],L3”).
18
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
• Base case says:– if we concatenate [] with an arbitrary list L, we get L
• Recursive case says:– if I have a list headed by X and the tail is L1, i.e. [X|L1], and I want to
concatenate that to another list L2– the answer is going to be a list headed by X– the tail is some other list L3– where L3 is defined as– the concatenation of L1 and L2
Example
?- app([1,2,3],[4,5],L).L = [1|L3] where L3 is given by
?- app([2,3],[4,5],L3).L3 = [2|L3’] where L3’ is given by
?- app([3],[4,5],L3’).L3’ = [3|L3”] where L3” is given by
?- app([],[4,5],L3”).L3” = [4,5] (Base case)
19
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
Example?- app(L1,L2,[1,2]).
matches
app([],L,L). Base caseL1 = [], L2 = [1,2]
1st answer
20
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
Example?- app(L1,L2,[1,2]).
matches
app([],L,L). Base caseL1 = [], L2 = [1,2]
head of recursive case
app([X|L1’],L2’,[X|L3’]) L1 = [1|L1’]L2 = L2’[1,2] = [X|L3’] L3’=[2]?- app(L1’,L2’,L3’).?- app(L1’,L2’,[2]).
21
Example?- app(L1,L2,[1,2]).
matches
app([],L,L). Base caseL1 = [], L2 = [1,2]
head of recursive case
app([X|L1’],L2’,[X|L3’]) L1 = [1|L1’]L2 = L2’[1,2] = [X|L3’] L3’=[2]?- app(L1’,L2’,L3’).?- app(L1’,L2’,[2]).
matches
app([],L,L). Base caseL1’ = []L2’ = L = [2]
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
2nd answerL1 = [1]L2 = [2]
22
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
Example?- app(L1,L2,[1,2]).
matches
app([],L,L). Base caseL1 = [], L2 = [1,2]
head of recursive case
app([X|L1’],L2’,[X|L3’]) L1 = [1|L1’]L2 = L2’[1,2] = [X|L3’] L3’=[2]?- app(L1’,L2’,L3’).?- app(L1’,L2’,[2]).
matches
app([],L,L). Base caseL1’ = []L2’ = L = [2]
Example contd.?- app(L1’,L2’,[2]).
matches
head of recursive case
app([X|L1”],L2”,[X|L3”]) L1’ = [2|L1”]L2’ = L2”[2] = [X|L3”] L3” =[]?- app(L1”,L2”,L3”).?- app(L1”,L2”,[]).
23
Building and Taking Lists Apart
app([],L,L). Base case
app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case
Example?- app(L1,L2,[1,2]).
matches
app([],L,L). Base caseL1 = [], L2 = [1,2]
head of recursive case
app([X|L1’],L2’,[X|L3’]) L1 = [1|L1’]L2 = L2’[1,2] = [X|L3’] L3’=[2]?- app(L1’,L2’,L3’).?- app(L1’,L2’,[2]).
matches
app([],L,L). Base caseL1’ = []L2’ = L = [2]
Example contd.?- app(L1’,L2’,[2]).
matches
head of recursive case
app([X|L1”],L2”,[X|L3”]) L1’ = [2|L1”]L2’ = L2”[2] = [X|L3”] L3” =[]?- app(L1”,L2”,L3”).?- app(L1”,L2”,[]).
matches
app([],L,L). Base caseL1” = [] L2”=L=[]
3rd answerL1 = [1,2]L2 = []