weakness of logic programming
DESCRIPTION
Weakness of logic Programming. Horn clause cannot cover all logics “ every living thing is an animal or a plant animal(X) V plant(X) living(X) So we must have the following definition in Prolog animal(X):- living(X), not plant(X). plant(X):- living(X), not animal(X). - PowerPoint PPT PresentationTRANSCRIPT
Weakness of logic Programming
• Horn clause cannot cover all logics• “every living thing is an animal or a plant• animal(X) V plant(X) living(X)
• So we must have the following definition in Prologanimal(X):- living(X), not plant(X).plant(X):- living(X), not animal(X).
Prolog can only have one element on this side
Not will only satisfy if we can’t find that X is an animal.
• Another weakness is the way that Prolog uses its rules from top to bottom. We already saw the problem
• “not” means cannot find. It does not mean false.
exercises• Binary search Tree – nil– t(L,M,R)
• isin(item, Tree)isin(X,t(L,X,R)).isin(X,t(L,M,R)):- X<M, isin(X,L).isin(X,t(L,M,R)):- X>M, isin(X,R).• add(X,Tree,ResultTree)add(X,nil,t(nil,X,nil)).add(X,t(L,X,R),t(L,X,R)).add(X,t(L,M,R),t(L1,M,R)):- X, <M add(X,L,L1).add(X,t(L,M,R),t(L,M,R1)):- X>M, add(X,R,R1).
Controlling backtracking
• We can prevent backtracking, by using a feature called “cut”.
• Normally, prolog backtrack to find all answers, but sometimes we only need the first solution.
• Examplef(X,0):-X <3.f(X,2):- 3=<X, X<6.f(X,4):- 6=<X.
• If we try?-f(1,Y), 2<Y.
We will have Y = 0, and then2<Y will be false
So prolog will try to substitute another value for Y.
f(X,0):-X <3.f(X,2):- 3=<X, X<6.f(X,4):- 6=<X.
f(X,0):-X <3.f(X,2):- 3=<X, X<6.f(X,4):- 6=<X.
f(1,Y), 2<Y.This picture shows all the substitutions.
Rule 1Y =0
f(1,0), 2<0.
succeed
fail
Rule 2Y =2
f(1,2), 2<Y.
3=<1, 1<6.
fail
Rule 3Y =4
f(1,4), 2<4.
1 <3. 6=<1.fail
•Notice that all the rules are mutually exclusive.•If rule 1 succeed, other rules will surely fail.•There is no point substituting rule 2 and 3 if rule 1 succeeds.
f(X,0):-X <3.f(X,2):- 3=<X, X<6.f(X,4):- 6=<X.
f(X,0):-X <3, !.f(X,2):- 3=<X, X<6, !.f(X,4):- 6=<X.
Rule 1Y =0
f(1,0), 2<0.
succeed
Fail, normally it will backtrack pass 1<3.But this time it’ll stop At !
1 <3.
No further execution -> execution speed increases.
• Let’s try another example?-f(7,Y)Y = 4. (this is the answer)• First, try rule 1.– X <3 fails. So the program backtracks and uses rule 2. (we
have not pass the “cut” so it’s ok to backtrack.)• Try rule 2– 3=<7 but 7<6 fails. Therefore it backtracks to rule 3.
• Try rule 3– Succeeds.
f(X,0):-X <3, !.f(X,2):- 3=<X, X<6, !.f(X,4):- 6=<X.
• We can optimize it further.• Notice that if X<3 fails, 3=<X in rule 2 will
always succeed.• Therefore we do not need to test it. (same
reasoning for 6=<X in rule 3).• So we can rewrite the rules to:
f(X,0):-X <3, !.f(X,2):- 3=<X, X<6, !.f(X,4):- 6=<X.
f(X,0):-X <3, !.f(X,2):- X<6, !.f(X,4).
• Be careful now. If we do not have “cut”, we may get several solutions, some of which may be wrong. For example:
?-f(1,Y)Y=0 ;Y=2 ;Y=4
f(X,0):-X <3, !.f(X,2):- X<6, !.f(X,4).
We order it to try other rules here.If we do not have “cut”, it will try other rules and succeed because we’ve deleted the conditional tests.
• When finding answer up to “cut”, the system has already found solutions of B1 to Bm.
• When the “cut” is executed, solutions B1 to Bm are considered fix. For example:
C:-P,Q,R,!,S,T,U.C:-V.A:-B,C,D.?-A.• When ! Is executed. P,Q,R will be fixed (no
backtracking) and C:-V. will never get executed.• Backtracking is still possible in S,T,U but will never go
back beyond the !
H:-B1, B2, …, Bm, !, …, Bn.
We put the question here.
C:-P,Q,R,!,S,T,U.C:-V.A:-B,C,D.?-A. A
B, C, D
P,Q,R,!,S,T,U.
Can backtrack if not reach !
Can backtrack to ! But not beyond that
Let’s see another example next page.
• The rules are mutually exclusive.• So we can use “else if” for efficiency.max(X,Y,X):-X=>Y, !.max(X,Y,Y).• Be careful of the following situation:?-max(3,1,1).yes. • It does not get matched with the first rule from the start.• But it then matches the second rule, because we already took
out the conditional test.• So we fix it in the next page.
max(X,Y,X):-X=>Y.max(X,Y,Y):-X<Y.
max(X,Y,Max):- X=>Y, !, Max =X.max(X,Y,Max):- Max =Y.
max(X,Y,X):-X=>Y, !.max(X,Y,Y).
?-max(3,1,1).Program is able to enter the first rule because Max is not matched to any value.Once X=>Y in the first rule is satisfied, there is no backtracking.
Let’s see an example on list next page.
• If there are many X in the list, this definition allow any X to be returned when we order it to backtrack.
• If we want to make sure that only the first occurrence of X will be returned, we will have to use “cut”.
member(X, [X|L]).member(X, [Y|L]):-member(X, L).
member(X, [X|L]):-!member(X, [Y|L]):-member(X, L).
?-member(X, [a,b,c]).X=a;no
Order it to find another solution (backtrack)
• Add non-duplicate item into a listadd(X, L, L):-member(X,L), !.add(X, L, [X|L]).
?-add(a,[b,c],L).L=[a,b,c]
?-add(X,[b,c],L).L=[b,c]X=b
?add(a,[b,c,X],L).L=[b,c,a]X=a
This is just one solution
• Be careful.– If we define things using “cut”, we normally
intend that every rule is tried, right from the first rule. So “cut” can serve its purpose.
– Any query that allows rule skipping will destroy everything.
?add(a,[a],[a,a]).yes
Does not match the first rule, but match the second rule. This makes things incorrect.
• tennis match examplebeat(tom, jim).beat(ann, tom).beat(pat, jim).
• We want to categorize players into 3 types:– Winner: win every game– Fighter: player with mixed records– Sportman: lose every game
• X is a fighter if • X is a winner if• We can use “if then else”:class(X,fighter):- beat(X,_), beat(_,X), !.class(X,winner):-beat(X,_), !.class(X,sportman):-beat(_,X).
),(:),(: XZbeatZYXbeatY
beat(tom, jim).beat(ann, tom).beat(pat, jim).
),(:_),( XYbeatYXbeat
• We still need to be careful about rules getting skipped. For example:
?-class(tom,sportman).yes (but in fact tom is a fighter)
?-p(X).X=1;X=2;no
p(1).p(2):-!.p(3).
?-p(X),p(Y).X=1, Y=1;X=1, Y=2;X=2, Y=1;X=2, Y=2;no
?-p(X),!, p(Y).X=1, Y=1;X=1, Y=2;no
class(0,zero):-!.class(Number,positive):- Number>0, !.class(Number,negative).
class(Number,positive):- Number>0.class(0,zero).class(Number,negative):-Number<0.
Use cut
• Splitting a list to list of positive (including 0) and negative numbers.
split([],[],[]).split([H|T],[H|Z],R):- H=>0,split(T,Z,R).split([H|T],R,[H|Z]):-H<0,split(T,R,Z).
Use cut
split([],[],[]).split([H|T],[H|Z],R):- H=>0,!, split(T,Z,R).split([H|T],R,[H|Z]):- split(T,R,Z).
Careful:?-split([8,1,-3,0,-4,5],[1,0,5],[8,-3,-4]).Yes (it matches rule 3, skipping earlier rules.)
More difficult to understand
Make it better
split([],[],[]).split([H|T],[H|Z],R):- H=>0,!, split(T,Z,R).split([H|T],R,[H|Z]):- H<0, split(T,R,Z).
More committal
split([],[],[]).split([H|T],[H|Z],R):- H=>0,!, split(T,Z,R).split([H|T],R,[H|Z]):- H<0, !, split(T,R,Z).
Unnecessary cutsplit([],[],[]):- !split([H|T],[H|Z],R):- H=>0,!, split(T,Z,R).split([H|T],R,[H|Z]):- H<0, !, split(T,R,Z).
Any match here will not match any thing else.
H<0 is in the last clause, Whether or not H<0 fails, there are no choices laft.
Multiple choice with cutsquint([],[]).sqluint([X|T],[Y|L]):- integer(X), !, Y is X*X, squint(T,L).sqluint([X|T],[X|L]):-squint(T,L).
The third clause is not used when the goal backtracks. But it still does not stand independently.
Partial mapsevens([],[]).evens([X|T],[X|L]):- 0 is X mod 2, evens(T,L).evens([X|T],L):- 1 is X mod 2, evens(T,L).
evens([],[]).evens([X|T],[X|L]):- 0 is X mod 2, !, evens(T,L).evens([X|T],L):- 1 is X mod 2, evens(T,L).
setify([],[]).setify([X|T],L):- member(X,T), setify(T,L).setify([X|T],[X|L]):- setify(T,L).
setify([],[]).setify([X|T],L):- member(X,T), !, setify(T,L).setify([X|T],[X|L]):- setify(T,L).
tree
insert(I,[], n(I,[],[])).insert(I, n(N,L,R) , n(N,L1,R)):- I<N, !, insert(I, L,
L1).insert(I, n(N,L,R) , n(N,L,R1)):- I>N, !, insert(I, R,
R1).insert(I, n(I,L,R) , n(I,L,R)).
Negation as failure
likes(mary,X):-snake(X),!,fail.likes(mary,X):-animal(X).Or
likes(mary,X):-snake(X),!,fail;animal(X).
“Mary likes all animals but snake.”
different(X,X):- !, fail.different(X,Y).Ordifferent(X,Y):- X=Y, !, fail.
;true.
The “not” predicate
not(P):-P,!,fail;true.
Some prolog allows not p(X) or \+(p(X))
member(X,[X|_]).member(X,[_|T]):-member(X,T).notmem(X,L):- \+(member(X,L)).
notmem1(X,[]).notmem1(X,[Y|T]):-X\==Y, notmem1(X,T).
• Same examples with the use of “not”
likes(mary,X):-animal(X), not snake(X).
different(X,Y):- not X=Y.
class(X,fighter):- beat(X,_), beat(_,X).class(X,winner):-beat(X,_), not beat(_,X).class(X,sportman):-beat(_,X), not beat(X,_).
likes(mary,X):-animal(X), (snake(X), !, fail ; true).
It means ->otherwise
Conclusion about “cut”• Pros– Avoid unnecessary execution.– Use like if-then-else
• Cons– The rule must be tried in order, no skipping.
P:-a,bP:-c.
P:- a,!,b.P:-c.
P:-c.P:-a,!,b.
Logic is P <-> (a ^ b) V cChanging order has no effect.
Logic is P <-> (a ^ b) V ((not a) ^ c)
Logic is P <-> c V (a ^ b)
Different meaning
goodteam(manunited).expensive(manunited).goodteam(liverpool).reasonable(T):- not expensive(T).
?-goodteam(X), reasonable(X).X=liverpool.
?- reasonable(X) , goodteam(X). no
Has assigned value
Has no assigned value. The “not” clause does not assign a value for you. See next page.
?- expensive(X).Means
?-not expensive(X).Means not
)(exp: XensiveX
)(exp: XensiveX
)(exp: XensivenotX
So it gives “no” in the previous page.
It is forall, so prolog cannot instantiate a single value.
Only need to find a single value of X.
Flight • timetable(Place1, Place2, ListOfFlights)• Flight = DepTime / ArrTime / FlightNo /
ListOfDays
• timetable(london, edinburgh, [9:40 / 10:50 / ba4733 / alldays, 19:40 / 20:50 / ba4833 / [mo,tu,we,th,fr,su]]).
List of days or alldays
• route(P1, P2, Day, Route)
• flight(P1, P2, Day, Num, DepTime, ArrTime)• deptime(Route, Time)• transfer(T1, T2)
List of From / To / FlightNo / DepTime
route(P1, P2, Day, Route):- flight(P1,P2,Day,Fnum,DepTime,_).
route(P1, P2, Day, [(P1/P3/F1/Dep1)|RestRoute]):-route(P3,P2,Day,RestRoute), flight(P1,P3,Day,F1,Dep1,Arr1),deptime(RestRoute,Dep2),transfer(Arr1, Dep2).
flight(P1, P2, Day, Fnum, DepTime, ArrTime):-timetable(P1,P2, FlightList).member(DepTime / ArrTime / Fnum / Daylist, FlightList),flyday(Day,Daylist).
deptime([P1 / P2 / Fnum / Dep | _ ], Dep).
transfer(H1:M1, H2:M2):-60*(H2-H1) + M2 – M1 >= 40.
Logic circuit
A B
BA C
inv(0,1).inv(1,0).and(1,1,1).and(1,0,0).and(0,1,0).and(0,0,0).