240 likes | 331 Views
LING 388: Language and Computers. Sandiway Fong Lecture 5: 9 /8. Administrivia. Homework 1 g raded and returned by email reviewed today Reminder Homework 2 due tonight (by midnight ) s ee the hint posted?. Use database bird(robin ). “ robin is a bird ”
E N D
LING 388: Language and Computers Sandiway Fong Lecture 5: 9/8
Administrivia • Homework 1 • graded and returned by email • reviewed today • Reminder • Homework 2 due tonight (by midnight) • see the hint posted?
Use database bird(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 observation case 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. Homework 1 Review
Use database bird(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 butbird(robin) is true since it’s in the database so \+ bird(robin) is false and so \+ \+ bird(robin) is true that’s why Prolog saystrue 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) iffbird(Y). has_feathers(Y) :- bird(Y). bird(Y):- has_feathers(Y). Assert ?- assert((bird(Y):- has_feathers(Y))). Circularity in definition 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). Modify can_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. Homework 1 Review
Today’s Topics • More on recursion • Last time • we definedlastinlist/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)
Today’s Topics • More on recursion • Look at taking apart and putting lists together • And symbols (atoms)
Building and Taking Atoms Apart • Built-in predicate atom_chars/2 has two modes of usage • atom_chars(symbol,list) • takes names apart • ?-atom_chars(will,X). • X is the list of characters representing will • 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 ’\’’)
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]).
Building and Taking Lists Apart (This is about as complicated as it will get in this class)
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 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) 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 Building and Taking Lists Apart Example ?-app([1,2,3],[4,5],L). L = [1|L3] where L3 is given by ?-app([2,3],[4,5],L3).
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 Building and Taking Lists Apart 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’).
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 Building and Taking Lists Apart 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”).
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 Building and Taking Lists Apart 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)
app([],L,L). Base case app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case Building and Taking Lists Apart Example ?- app(L1,L2,[1,2]). matches app([],L,L). Base case L1 = [], L2 = [1,2] 1st answer
app([],L,L). Base case app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case Building and Taking Lists Apart Example ?- app(L1,L2,[1,2]). matches app([],L,L). Base case L1 = [], 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]).
app([],L,L). Base case app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case Building and Taking Lists Apart Example ?- app(L1,L2,[1,2]). matches app([],L,L). Base case L1 = [], 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 case L1’ = [] L2’ = L = [2] 2nd answer L1 = [1] L2 = [2]
app([],L,L). Base case app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case Building and Taking Lists Apart Example ?- app(L1,L2,[1,2]). matches app([],L,L). Base case L1 = [], 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 case L1’ = [] 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”,[]).
app([],L,L). Base case app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case Building and Taking Lists Apart Example ?- app(L1,L2,[1,2]). matches app([],L,L). Base case L1 = [], 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 case L1’ = [] L2’ = L = [2] 3rd answer L1 = [1,2] L2 = [] 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 case L1” = [] L2”=L=[]
app([],L,L). Base case app([X|L1],L2,[X|L3]) :- app(L1,L2,L3). Recursive case Building and Taking Lists Apart Example ?- app(L1,L2,[1,2]). has 3 answers L1 = [], L2 = [1,2] L1 = [1], L2 = [2] L1 = [1,2], L2 = [] in each case it is true that L1 concatenated with L2 is [1,2]