30 September 2005 Foundations of Logic and Constraint Programming 1
Prolog by Example
APrologprogramiscomposedbyfactsandrules,whicharespecialcasesofdefinite(orHorn)clauses,i.e.clauseswithatmostonepositiveliteral(theheadoftheclause).
Thispredicatemayhaveseveralalternativedefinitions(bothfactsandrules).
A fact has no negative literals and expresses positive knowledge that is definite (nodisjunctions).Example:TheknowledgethatJohnisachildofAnnandAlex,andthatAnnisachildofBob,isexpressedbytwofacts,namely
child_of(john, ann).child_of(john, alex).child_of(ann, bob).
A rule has one or more negative literals (the body of the clause), and is used to inferpredicatesfromotherpredicates.Example:Agrandchildisthechildofthechild,i.e.
grand_child_of(X,Y) :- child_of (X,Z), child_of(Z,Y).
Thenameruleisduetothefactthatadefiniteclause,H B1 B2 ... Bkcanbewritten in the formofan ifexpressionH ← B1 B2 ... Bk, which i thesyntaxadoptedinProlog.
30 September 2005 Foundations of Logic and Constraint Programming 2
Prolog by Example
child_of(john, ann).child_of(john, alex).child_of(ann,bob).grand_child_of(X,Y) :- child_of(X,Z), child_of(Z,Y).
Allvariables(startingwithcapital letters)areuniversallyquantified.Therulecanberead“ForanyX,YandZ,ifXisachildofZandZisachildofY,thenXisagrandchildofY”.
Rules can be rephrased such that variables appearing only in the body of a rule areexistenciallyquantfied.Inthiscase,“XisagrandchildofY,ifthereissomeZ,ofwhichXisachild,andisachildofY”.
Aprogrammayberegardedasaknowledgebase,combiningexplicitknowledgeoffactsas well as implicit knowledge by means of rules. This knowledge may be queried bynegativerules(nohead).Noticethatduetothenegation,variablesarereadexistenctially.
Examples:
ArethereanyparentsofAlex(anyXofwhichJohnisaparent)?
?- child_of(X,alex).
ArethereanyAandBsuchthatAisagrandparentofB(orBisagrandchildofA)?
?- grand_child_of(A,B).
30 September 2005 Foundations of Logic and Constraint Programming 3
Prolog by Example
child_of(john, ann).child_of(john, alex).child_of(bob, john).
grand_child_of(X,Y) :- child_of(X,Z), child_of(Z,Y).
A Prolog engine is able to answer the queries (by implementing resolution on Hornclauses),findingallsolutionsandpresentingthemoneatatime.
?- child_of(X, alex).
X = john; no.
?- grand_child_of(A,B).
A = bob, B = ann ;
A = bob, B = alex; no.
In practice, to program in Prolog, it is important to understand the options that Prologenginesassume,inapplyingresolution.
Informally, tosearch forall solutions,Prologuses thequeryasan initial resolvent,andorganisesalltheotherresolventsinanexecutiontree.
Solutions,ifany,arethesuccessleafsofthetree(theotherleafsarefailed).
30 September 2005 Foundations of Logic and Constraint Programming 4
child_of(john, ann).child_of(john, alex).child_of(bob, john).
grand_child_of(X,Y) :- child_of(X,Z), child_of(Z,Y).
Forexample,query?- grand_child_of(A,B),expandsintotheexecutiontree
Noticethat Instancesof theanswersareobtainedbycomposingthesubstitutions inapath toasuccessfulleaf
Thetreeissearcheddepth-first,left-to-right.
Prolog by Example
grand_child_of(A,B)
child_of(A,Z), child_of(Z,B)
child_of(ann,B) child_of(alex,B) child_of(john,B)
X/A, Y/B
A/john Z/alex
A/john Z/ann
A/bob Z/john
B/ann B/alex
30 September 2005 Foundations of Logic and Constraint Programming 5
Letusassumesomeelementsfromthelargerfamilytree.
Thebasicrelationshipthatmustberecordedisparent-child(theonekeptintheIDcardsanddatabases),modeledbythebinarypredicateparent_of/2.
Prolog by Example: Family relationships
child_of(john,doug).child_of(john,carol).child_of(mary,carol).child_of(tess,mary).child_of(fred,tess).child_of(peter,john).child_of(bob,john).
child_of(alex,john).child_of(peter,ann).child_of(bob,ann).child_of(alex,ann).child_of(alice, peter).child_of(alice,vicky).
john
doug carol
peter bob alex
ann
alice
vicky
mary
tess
fred
30 September 2005 Foundations of Logic and Constraint Programming 6
Otheruseful informationcanbe introduced,suchassex (althoughusually implicit in thename–butstill this info isexplicit in IDcardsandpassports).This isexpressedby theunarypredicateis_male/1andis_female/1.
Once the basic relationships are established among the elements of the family, otherfamily relationsships and predicates. For example, the relationship parent_of is theoppositeofchild_of:
parent_of(X,Y):- child_of(Y,X).
Thepredicatemotherisassignedtoanyone,ofsexfemalethatistheparentofsomeone.
mother_of(X,Y):- parent_of(X,Y), is_female(X).
Amotheristhemotherofsomeone.
is_mother_of(X):- mother_of(X,_).
Prolog by Example: Family relationships
is_male(doug).is_male(john).is_male(fred).is_male(peter).is_male(bob).is_male(alex).
is_female(mary).is_female(carol).is_female(tess).is_female(ann).is_female(alice).is_female(vicky).
john
doug carol
peter bob alex
ann
alice
vicky
mary
tess
fred
30 September 2005 Foundations of Logic and Constraint Programming 7
Foranymotherwithmanychildren,thepredicateis_mother/1maybededucedseveraltimes,onceforeachchild.Thisleadstorepeatedanswerstoquery
Prolog by Example: Repeated Answers
?- is_mother(X). X= carol ? ;X = carol ? ;X = mary ? ;X = tess ? ;X = ann ? ;X = ann ? ;
X = ann ? ;X = vicky ? ;no.
is_mother_of(X)
mother_of(X,Y)
parent_of(X,Y), is_female(X).
X/johnY/doug
child_of(Y,X), is_female(X).
is_female(doug) is_female(carol)
X/johnY/carol
child_of(john,doug).child_of(john,carol).child_of(mary,carol).child_of(tess,mary).child_of(fred,tess).child_of(peter,john).child_of(bob,john).child_of(alex,john).child_of(peter,ann).child_of(bob,ann).child_of(alex,ann).child_of(alice, peter).child_of(alice,vicky).
30 September 2005 Foundations of Logic and Constraint Programming 8
Otherindirectrelationshipsmaybederivedfromtheirdefinition,namely
grand_child_of/2
sibling_of/2, brother_of/2, sister_of/2
uncle_of/2, aunt_of/2,
great_uncle_of, great_aunt_of/2,
cousin_of, second_cousin_of/2, third_cousin_of/2, ...
Althoughmost definitions are direct, some caremust be takenFor example, siblings arechildrenofacommonparent
sibling_of(X,Y):- child_of(X,Z), child_of(Y,Z).
This definition suffers from a quite common mistake: to assume that different variablesshouldstandfordifferentvalues.Inthedefinitionaboveapersonisasiblingofhim/herself!
Hereisthecorrectdefinition,wherethedifference(\=)ismadeexplicitely::sibling_of(X,Y):- child_of(X,Z), child_of(Y,Z). X \= Y.
Prolog by Example: Different Variables
30 September 2005 Foundations of Logic and Constraint Programming 9
Prolog by Example: Different Variables
john
doug carol
peter bob alex
ann
alice
vicky
mary
tess
fred
sibling_of(X,Y):- child_of(X,Z), child_of(Y,Z), X \= Y.
child_of(john,doug).child_of(john,carol).child_of(mary,carol).child_of(tess,mary).child_of(fred,tess).child_of(peter,john).child_of(bob,john).child_of(alex,john).child_of(peter,ann).child_of(bob,ann).child_of(alex,ann).child_of(alice, peter).child_of(alice,vicky).
sibling_of(X,Y)
child_of(X,Z), child_of(Y,Z), X \= Y.
child_of(Y,doug), john\= Y
X/johnZ/doug
child_of(Y,carol), john\= Y
john\= john john\= mary
X/johnZ/carol
Y/john Y/mary
30 September 2005 Foundations of Logic and Constraint Programming 10
Care must also be taken to avoid definitions, that correct as they might be, eventuallybecomecircular,leadingtonontermination.
For example, the simetric property of the sibling_of relationship could, in principle be,explicitelydefined,bytheadditionaldefinition
sibling_of(X,Y):- sibling_of(Y,X).
Butthisdefinitionwouldlead,whenXandYarenon-ground,toaninfinitetree:
Prolog by Example: Non-termination
sibling_of(X,Y):- child_of(X,Z), child_of(Y,Z), X \= Y.sibling_of(X,Y):- sibling_of(Y,X).
sibling_of(X,Y)
child_of(X,Z), child_of(Y,Z), X \= Y.
sibling_of(Y,X)
sibling_of(X,Y)
sibling_of(Y,X)
sibling_of(X,Y)
30 September 2005 Foundations of Logic and Constraint Programming 11
Logic has been used to formalise arithmetics, and a number of interesting (mostlytheoretucal) results where obtained from this effort (for example, the famous Gödel incompletnesstheorem).
The“standard”formalisationisduetoPeano(endof19thcentury),thatproposedasimplesetofaxioms,forthispurpose.
Tobeginwith, integersaredefined inductively: an integer iseither0or thesucessorofanothernumber.
Thebasicalgebraicoperationscanalsobeformalised,againinductively.Forexampletheadditionoftwointegers:
Baseclause:Thesumof0andsomeintegerM,isthatinteger.
Inductiveclause:ThesumofthesuccessorofanintegerMandanotherintegerNisthesuccessorofthesumoftheintegersMandN.
Similardefinitionscanbeusedtodefinetheoperationsofmultiplicationandpotentiation.
Logicprogrammingcanthusbeusedtodirectlyimplementarithmetics(althoughinaveryinneficientway).
Prolog by Example: Peano Arithmetics
30 September 2005 Foundations of Logic and Constraint Programming 12
Thedefinitionof integersisstraighgtforward.Belowthepredicateint/1isusedtoassignthepropertyintehger,andthefunctors/1todenotethesuccessorofaninteger.
int(0). % 0 is an integer int(s(M)):- int(M). % the successor of an integer is integer.
Theadditionfollowsdirectlythedefinition. sum(0,M,M). % The sum of 0 and any integer M is M sum(s(N),M,s(K)):- % The sum the successor of N and M is the sum(N,M,K). % successor of the sum of N and M.
Theproduct,asarepeatedsum,ismodelledbymeansofaddition. prod(0,M,0). % The product of 0 with any integer is 0. prod(s(N),M,P):- % The product of the successor of N and M is prod(N,M,K), % the sum of M with the product of M and N. sum(K,M,P).
Andsoisthepower,asarepeatedmultiplication(theexponentisthefirstargument) pow(0,0, s(0)). % 0 raised to 0 is 0. pow(0,s(_),s(0)). % Integer M (>0) raised to 0 is 1 (i.e. S(0)). pow(s(N),M,P):- % Integer M raised to the successor of N pow(N,M,K), % is the product of M with M raised to N. prod(K,M,P).
Prolog by Example: Peano Arithmetics
30 September 2005 Foundations of Logic and Constraint Programming 13
ItisinterestingtonotethefunctioningofProlog,withthesepredicates.
First,thepredicateintegercanbeusedeithertocheckwhetheranargumentisaninteger,eithertogenerateintegers.
Notice in the lastcase, that theargumentsof int thatarereported in theanswersare2,3,...
Prolog by Example: Peano Arithmetics
| ?- int(s(s(0))).yes| ?- int(X). X = 0 ? ; % X=0 X = s(0) ? ; % X=1 X = s(s(0)) ? ; % X=2 X = s(s(s(0))) ? % X=3| ?- int(s(s(X))). X = 0 ? ; % X = s(0) ? ;
30 September 2005 Foundations of Logic and Constraint Programming 14
The predicate sum performs as expected. Given two numbers to be summed, thepredicatereturnstheirsum.Letussum3with2
Thecorrespondingexecutiontreecanbedisplayed
Prolog by Example: Peano Arithmetics
| ?- sum(s(s(0)),s(s(s(0))),X). X = s(s(s(s(s(0))))) ? ;no
sum(0,M,M). sum(s(N),M,s(K)):- sum(N,M,K).
TheresultXisthenobtainedbycompositionofsubstitutions
X/s(K1)butK1/s(K2)) soX/s(s(K2))butK2/s(s(s(0)))soX/s(s(s(s(s(0)))))i.e.X = 5
sum(s(s(0)))),s(s(s(0))),X)
M1 / s(s(s(0)))N1 / s(0); X / s(K1)
sum(s(0),s(s(s(0))),s(K1))
sum(s(s(s(0))),0,s(K2))
M2 / s(s(s(0)))N2 / 0 ; K1 / s(K2)
K2 / s(s(s(0)))
30 September 2005 Foundations of Logic and Constraint Programming 15
Logicprogrammingisflexible.Predicatesumalsodefinessubtraction!Giventwonumberstobesubtracted,thepredicatealsoreturnstheirdifference.Letussubtract2from5
Prolog by Example: Peano Arithmetics
| ?- sum(s(s((0)),s(s(s(0))),X). X = s(s(s(s(s(0))))) ? ;no
sum(0,M,M). sum(s(N),M,s(K)):- sum(N,M,K).
sum(s(s(0)),X,s(s(s(s(s(0))))))
M1 / X ; N1 / s(0)K1 / s(s(s(s(0))))
sum(s(0),X, s(s(s(s(0))))
sum(0,X,s(s(s(s(s(0)))))
X / s(s(s(0)))
M2 / X ; N2 / 0K2 / s(s(s(0)))
30 September 2005 Foundations of Logic and Constraint Programming 16
Theflexibilityof logicprogrammingallowsthatstill thesamedefinitionenablestofindalloperandswhosesumis5.
Prolog by Example: Peano Arithmetics
| ?- sum(Y,S, sum(s(s(s((0)))). Y = s(s(s(s(s(0))))) , X = 0? ; Y = s(s(s(s(0)))) , X = s(0)? ;Y = s(s(s(0))) , X = s(s(0))? ;Y = s(s(0)) , X = s(s(s(0)))? ;Y = s(0) , X = s(s(s(s(0))))? ;Y = 0 , X = s(s(s(s(s(0)))))? ; no
sum(0,M,M). sum(s(N),M,s(K)):- sum(N,M,K).
sum(Y,X,s(s(s(s(s(0))))))
M1 / X ; Y / s(N1)K1 / s(s(s(s(0))))
sum(N1,X,s(s(s(s(0)))))
sum(N2,X,s(s(s(0))))
M2 / X ; N1 / s(N2)K2 / s(s(s(0)))
X / s(s(s(s(s(0)))))Y / 0
X / s(s(s(s(0))))N1 / 0
X / s(s(s(0)))N2 / 0
30 September 2005 Foundations of Logic and Constraint Programming 17
The other predicates, for product and potentiation, behave similarly to the predicate forsum.However,ifnosolutionsexisttheremightbeterminationproblems,iftherecursionisperformedinthe“wrong”argument.Forexample,therearenoproblemswith“2 * X = 3”
Prolog by Example: Peano Arithmetics
prod(0,M,0). prod(s(N),M,P):- prod(N,M,K) sum(K,M,P).
sum(0,M,M). sum(s(N),M,s(K)):- sum(N,M,K).
prod(s(s(0)),X,s(s(s(0))))
prod(s(0),X,K1), sum(X,K1,s(s(s(0))))
prod(0,X,K2), sum(X,K2,K1), sum(X,K1,s(s(s(0))))
sum(0,X,K1), sum(X,K1,s(s(s(0))))
sum(M1,M1,s(s(s(0))))
sum(N2, s(N2), s(s(0)))
sum(N3, s(s(N3)), s(0))
sum(N4, s(s(s(s(N4)), 0)
N2 / s(N3)
N3 / s(N4)
X / M1, K1 / M1 )
M1 / s(N2)
30 September 2005 Foundations of Logic and Constraint Programming 18
However, thesame isnot true for “X * 2 = 3”,where theunknownargument is theoneusedintherecursion.
It is left as an exercise to check what types of calls do not terminate with the abovedefinitions.
Prolog by Example: Peano Arithmetics
prod(X,s(s(0)),s(s(s(0))))
prod(N1,s(s(0)),K1), sum(N1,s(s(0)),s(s(s(0))))
sum(0,s(s(0)),s(s(s(0))))
M1/s(s(0)), X /s(N1)
N1 / 0, K1 / 0
prod(N2,s(s(0)),K2), sum(K2,s(s(0)),P2), sum(P2,s(s(0)),s(s(s(0))))
M2/s(s(0)) ; N1/s(N2), K1 / P2
prod(N3,s(s(0)),K3), sum(K3,s(s(0)),P3), sum(...), sum(...)
prod(N4,s(s(0)),K4), sum(K4,s(s(0)),P4), sum(...), sum(...), sum(...)
M3/s(s(0)) ; N2/s(N3), K2 / P3
M4/s(s(0)) ; N3/s(N4), K3 / P4
prod(0,M,0). prod(s(N),M,P):- prod(N,M,K) sum(K,M,P).
sum(0,M,M). sum(s(N),M,s(K)):- sum(N,M,K).
30 September 2005 Foundations of Logic and Constraint Programming 19
Although important from a theoretical viewpoint, Peano arithmetics is not very useful inpractice due to the complexity of both the representation of numbers and the basicoperations.
Forexample,theusualrepretsentationofanintegerNintheusualbase2or10requiresO(lg2N)orO(lg10N)bits.Incontrast,PeanorepresentationrequiresO(N)symbols(morepreciselyNs´s+2Nparenthesis+1zero,whichissignificantlylarger.
Astothesumoperation,sayNplusN,theusualmethodisproportionaltothenumberofbits/digitsi.e.ithascomplexityO(lgN).
Incontrast,peanosumrequiresNcallstothesumdefinition,i.e.IthascomplexityO(N)
Prolog by Example: Peano Arithmetics
sum(M,0,M). sum(s(N),M,s(K)):- sum(N,M,K).
sum(s(s(s(0))),X,P)
sum(s(s(0)),X,P)
sum(s(0),X,P)
sum(0,X,P)
30 September 2005 Foundations of Logic and Constraint Programming 20
IfPeanoarithmeticsisnotveryuseful inpractice,thesamekindofdefinitionsarewidelyapplicable,namelyinstructureslikelists.
Assuming the peano representation of integers, the following definition of predicate p_lenght/2highlightsthecorrespondencebetween0andtheemptylistaswellasbetweenthesandthelistfunctors
Ofcourse,iftheusualarithmeticssused,thedefinitionhastobeadapted,suchthatthenotionofsuccessorisreplacedbytheusual“+1”operation
There are however disadvantages in this formulation, namely non-termination. This isillustratedbytheexecutiontreesofbothpredicatestoobtainlistsofsize2.
List Processing in Prolog: Length
P_length([],0). p_length([_|T],s(N)):- p_lenght(T,N).
a_length([],0). a_length([_|T], M):- a_lenght(T,N), M is N+1.
30 September 2005 Foundations of Logic and Constraint Programming 21
There are however disadvantages in this formulation, namely non-termination. This isillustratedbytheexecutiontreesofbothpredicatestoobtainlistsofsize2.
Inthepeanomodelling,
thegoalisofcourse?- p_length(L,s(s(0))).
andtheexecutiontreeisasfollows
List Processing in Prolog : Length
P_length([],0). P_length([_|T],s(N)):- p_lenght(T,N).
p_length(L,s(s(0)))
L/ [_|T1]
p_length(T1,s(0)))
p_length(T2,0)
L1/ [_|T2]
T2/ []
Composingsubstitutions,thevalueofLisobtained T2 = [] T1 = [_|T2] = [_] L = [_|T1] = [_,_]
30 September 2005 Foundations of Logic and Constraint Programming 22
With the modelling with standard arithmentics, the corresponding tree, for query?- a_length(L,2),ismorecomplex
Thecorrectanswerisobtainedasbefore,intheleftpartofthetree
T2 = [] ; T1 = [_|T2] = [_]; L = [_|T1] = [_,_]
However,thereisnowarightpartofthetree...
List Processing in Prolog : Length
a_length([],0). a_length([_|T],M):- a_lenght(T,N), M is N+1.
a_length(L,2)
L/ [_|T1] , M / 2
a_length(T1,N1), 2 is N1+1
2 is 0+1
T1/ [] , N1 / 0
a_length(T2,N2), N1 is N2+1, 2 is N1+1
T1/ [_|T2] , M2 / N1
N1 is 0+1, 2 is N1+1
T2/[] , N2/0
2 is 1+1
N1/1
a_length(T3,N3), N2 is N3+1, ...
T2/ [_|T3] , M3 / N2
30 September 2005 Foundations of Logic and Constraint Programming 23
However,therightpartoftheexecutiontreeisinfinite!
List Processing in Prolog : Length
a_length([],0). a_length([_|T],M):- a_lenght(T,N), M is N+1.
a_length(T3,N3), N2 is N3+1, ...
T4/ [_|T3] , M3 / N2
N3 is 0+1,..., 2 is N1+1 a_length(T4,N4), N3 is N4+1, ...
T4/ [_|T3] , M3 / N2
N4 is 0+1,..., 2 is N1+1 a_length(T5,N5), N4 is N5+1, ...
T4/ [_|T3] , M3 / N2
N5 is 0+1,..., 2 is N1+1 a_length(T6,N6), N5 is N6+1, ...
30 September 2005 Foundations of Logic and Constraint Programming 24
A very common operation between lists is their concatenation. Predicate cat/3 below istrue,when the list in the third argument is the concatenationof the lists in the first andsecondarguments.
Asusual,thedefinitionbelowreliesontheinductivestructureofthefirstlist,andconsidersthecaseswhereitisempty(thebaseclause)ornot(theinductionclause).
It is interesting tonotice in theexecution tree, thatconcatenatinga listwithN1elementswithalistwithN2elements,requires
N1callstotherecursiveclause,forlistswithsizesN1,N1-1,N1-2,...,2,1.
N1 trivial failed calls to the base clause, for these lists (in fact, implementations ofprologindexingonthefirstargumentdonotmakethesecalls).
1successfulcallwithanemptylistasfirstargument.
The concatenation of a list requires thus N1+1 (non-trivial) calls, and presents thus acomplexityofO(N),whereNisthesizeofthefirstlistargument.
List Processing in Prolog: Concatenation
cat([],L,L). cat([H|T],L,[H|R]):- cat(T,L,R).
30 September 2005 Foundations of Logic and Constraint Programming 25
Fromanalgorithmicviewpoint, thiscomplexity is theonethatcanbeexpected for lists,maintainedassimplylinkedlists,withapointertoitshead(firstelement).
This is in fact thecasewithProlog,where listsaremaintained in this form.However,adifferent form of representation, difference lists, allow the tail append to be a simpleoperation,asiflistswereimplenmentedwithapointertotheirtail.
Inanycase,thedeclarativityofthisdefinitionallowstheuseofthiscat/3predicateeither toconcatenatetwolistsintoathirdone,or toremoveasublist(prefixorpostfix)fromalist.
List Processing in Prolog: Concatenation
cat([],L,L). cat([H|T],L,[H|R]):- cat(T,L,R).
?- cat([1,2],[3,4,5],L). L = [1,2,3,4,5]; no.?- cat(L,[3,4,5],[1,2,3,4,5]). L = [1,2]; no.?- cat([1,2],L,[1,2,3,4,5]). L = [3,4,5]; no.?- cat(L1,L2,[1,2,3]). L1 = [], L2 = [1,2,3]; L1 = [1], L2 = [2,3]; L1 = [1,2], L2 = [3]; L1 = [1,2,3], L2 = []; no.
30 September 2005 Foundations of Logic and Constraint Programming 26
The declarativity of logic programming, makes it possible to reuse the definition ofconcatenation,todefineotherrelationsbetweenalistandits(non-empty)sublists.
Prefix:ListPisa(non-empty)prefixoflistLifthereissomeotherlistXsuchthatListheconcatenationofPandX(inProlog,Xmaybedeclaredasananonimouslist).
Posfix:ListPisa(non-empty)postfixoflistLifthereissomeotherlistXsuchthatListheconcatenationofXandP(inProlog,Xmaybedeclaredasananonimouslist).
Sublist:Thesublistrelationcanbedefinedupontheprefixandposfixrelations:listSisa(non-empty)sublistofLifthereisaprefixPoflistL,ofwhichSisaposfix.
List Processing in Prolog: Sublists
prefix([H|T],L):- cat([H|T],_,L).
sublist(S,L):- prefix(P,L), posfix(S,P).
posfix_of([H|T],L):- cat(_,[H|T],L).
30 September 2005 Foundations of Logic and Constraint Programming 27
In addition to relationships bewteen lists, it is often important to consider relationshipsbetweenlistsandtheirmembers.
Themostusefulpredicate,member/2,relatesalistwithanyofitsmembers
Another important predicate relates two lists, L1 and L2, with an element X. Given thedeclarativenessoflogicprogrammingthispredicatecaneitherbeinterpretedas
InsertingXintoL1toobtainL2 RemovingXfromL2tootainL1
Thedefinitionissimilartothatabove,consideringthecaseswheretheinsertionisdoneinthebeginningornotoflistL1.
List Processing in Prolog: Membership and Append
member(X,[X|_]). member(X,[_|T]). member(X,T).
append(X,L,[X|L]). append(X,[H|T], [H|R]). append(X,T,R).
30 September 2005 Foundations of Logic and Constraint Programming 28
Other interesting predicates relate a list with any of its permutations. As usual thedefinitionconsiderstwocases
The(only)permutationofanemptrylistisanemptylist A permutation of a non-empty list is a permutation of its tail, to which the head isinserted.
Asimilardefinitionisusedtorelatealistwithitsreverse. The(only)reversionofanemptylistisanemptylist Areversionofanon-emptylistisareversionofitstail,towhichtheheadisinsertedattheend(thisappendattheendcanbeobtainedbyconcatenationofthelistwithalistcomposedoftheelementtobeappended)
Noticethenonterminationproblemswhenthefirstargumentisavariable.Why?
List Processing in Prolog: Permutation and Reversion
perm([],[]). perm([H|T],L). perm(T,P), append(H,P,L).
reverse([],[]). reverse([H|T], L):- reverse(T, R), cat(R,[H], L).
30 September 2005 Foundations of Logic and Constraint Programming 29
The reversion of a list is not very efficient. Analysing the execution tree (left as anexercise),thereversionofalistofsizeNrequires
One(non-trivial)calltorevertalist(oflengthN-1) Onecall to “append”anelement to theendof this list,which requiresN “non-trivialcalls”topredicatecat/3.
Hence,thecomplexityofthis“algorithm”measuredbythenumberofnon-trivial“calls”,is 1calltoreverseandacalltocatforalistoflengthN(i.e.N+1callstocat) 1calltoreverseandacalltocatforalistoflengthN-1(i.e.(N-1)+1callstocat) ... 1calltoreverseandacalltocatforalistoflength1(i.e.1+1callstocat) 0calltoreverseand1calltocatforalistoflength0(i.e.0+1callstocat)
Thenumberofcallsisthus N(non-trivial)callstopredicatereverse [N+1]+[(N-1)+1]+...+2+1=(N+1)(N+2)/2(non-trivial)callstopredicatecat
The complexity of thealgorithm is thenO(N2)which isquite inneficient, since it is quiteeasytogetanalgorithmtoperformreversionofalistinO(N)steps.
List Processing in Prolog : Permutation and Reversion
30 September 2005 Foundations of Logic and Constraint Programming 30
Asseenbefore,concatenationoflistscouldbemademoreefficientifapointertotheendofthelistismaintained.Thisisthebasicideaofthecodingoflistsasdifferencelists.
AdifferencelistisastructureL-TwhereLandTarelistsandTisthetailofL.
This structure represents a list whose elements are those belonging to L but not to T,(hencethenameandthefunctorused).Forexample,thedifferencelist[1,2,3,4,5,6]-[5,6]encodeslist[1,2,3,4].
The interesting case for processing is the case where T is a variable. In this case,appendingtotheendofthelistrequiresprocessingT.
For example, assume list [1,2,3,4], encoded as [1,2,3,4|T]-T. Appending 5 to this list,correspondsto
ObtaininganewtailT=[5|S] SubtractingLbyS.
Thisisthedeclarativemeaningofpredicatetd_app/3
whichcanbesimplifiedwithheadunification
List Processing in Prolog: Difference Lists
td_app(X,L-T,L-S):- T = [X|S].
td_app(X,L-[X|S],L-S).
30 September 2005 Foundations of Logic and Constraint Programming 31
Thesametechniquecanbeusedtoconcatenatetwodifferencelists,L1-T1andL2-T2,intoathirdoneL3-T3.
Toexemplify, letusconcatenatelists[1,2,3]to[4,5]resultinginto[1,2,3,4,5],allencodedasdifferencelists
[1,2,3|T1]-T1+[4,5|T2]-T2=[1,2,3,4,5|T3]–T3
Byanalysingthisexample,itisclearthat WecanmakeL1 = L3ifthesubstitutionT1=[4,5|T3]isimposed SinceL2=[4,5|T2],theabovesubstitutionisimposedwhenT2 = T3andT1 = L2
Hencepredicatecat_diff/3,describestheconcatenationofdifferencelists
Byusingheadunificationtheconcatenationbecomesquite“intuitive”
List Processing in Prolog: Difference Lists
cat_diff(L1-T1,L2-T2,L3-T3):- L3 = L1, T3 = T2, L2 = T1
cat_diff(L1-T1,T1-T2,L1-T2).
30 September 2005 Foundations of Logic and Constraint Programming 32
Theconcatenationofdifferencelistsisthusperformedthroughsimpleunification,insteadofrequiringtheinneficientrecursionoftheusuallists.
Thisresultcanthusbeusedtoreversedifferencelists,byadaptingthepreviousdefinitionof reverse/2 (for standard lists) to the new encoding as difference lists (the specialencodingoftheemptydifferencelistisexaplainedinthenextslide)
Thedefinitioncanbe“improved”byheadunification.Sincethecalltocat_diff/3performssubstitutionsLx = L2,Tx = [H|T] andT = T2, such substitutions canbemadedirectly,avoidingtheexplicitcalltocat_diff/3
List Processing in Prolog: Difference Lists
reverse([],[]). reverse([H|T], L):- reverse(T, R), cat(R,[H], L).
rev_diff(L-T,L-T):- L == T. rev_diff([H1|L1]-T1, L2-T2):- rev_diff (L1-T1, Lx-Tx), cat_diff(Lx-Tx,[H|T]-T,L2-T2).
rev_diff(L-T,L-T):- L == T. rev_diff([H1|L1]-T1, L2-T):- rev_diff (L1-T1, T1-[H|T]).
30 September 2005 Foundations of Logic and Constraint Programming 33
Inprinciple, theencodingofanemptydifference list isL-L.Assuch the reversionofanemptydifferencelistcouldbemadewithaclausesuchas
Hence,whenthisclauseistestedtoreverseanon-emptylist,sayrev_diff([1,2|Z]-Z,X-Y),thecallshouldfail,since[1,2|Z]-Zdoesnotencodeanemptylist(itencodesofcourselist[1,2])andshouldnotunifywithL-L.
Moreprecisely,itisnotpossibletounifyL=[1,2|Z]andL=Z,becausethatwouldrequireZ=[1,2|Z],i.e.tosubstituteavariable,Z,byaterm,[1,2|Z],wherethevariableoccurs.
This“occurs-check”failuredoesnotoccurinmostPrologsystemsthatdonotimplementitcorrectly(endinginaninfiniteloopX=f(X)=f(f(X))=f(f(f(X)))=...).
For this reason, instead of checking if the two variable L-T are the same throughunification(i.e.withpredicate“=/2”), theclauseteststhiscasewithpredicate“==/2”, thatonlysucceedsifthetermsarealreadythesameatthetimeofcall.
List Processing in Prolog: Difference Lists
rev_diff(L-L,L-L). rev_diff(L-T,L-T):- L = T
rev_diff(L-T,L-T):- L == T
30 September 2005 Foundations of Logic and Constraint Programming 34
ThedeclarativityofPrologallows thatsimpleprogramsarespecified tosolveapparentlycomplexproblems.
TheLangford(M,N)problemaimsatfindingalistofM*Nelements,suchthattheintegers1toMeachappearNtimes,insuchpositionsthatbetweentwooccurrencesofanyJ(intherange1..M)areseparatedbyJdifferentelements.
ThespecificationoftheLangford(4,2)isquiteobvioususwhenthesublist/2predicateisused
Of course, such simple specification is only possible due to the flexibility of logicprogramming,namelythelackoffixedinput-outputarguments.
List Processing in Prolog: Langford
langford42(L):- L = [_,_,_,_,_,_,_,_], sublist([1,_,1], L), sublist([2,_,_,2], L), sublist([3,_,_,_,3], L), sublist([4,_,_,_,_,4], L).
30 September 2005 Foundations of Logic and Constraint Programming 35
Amorechallengingproblemistheclassiczebrapuzzle:
1. Therearefivehouses,eachofadifferentcolorandinhabitedbymenofdifferentnationalities,withdifferentpets,drinks,andcigarettes.
2. TheEnglishmanlivesintheredhouse.3. TheSpaniardownsthedog.4. Coffeeisdrunkinthegreenhouse.5. TheUkrainiandrinkstea.6. Thegreenhouseisimmediatelytotherightoftheivoryhouse.7. TheOldGoldsmokerownssnails.8. Koolsaresmokedintheyellowhouse.9. Milkisdrunkinthemiddlehouse.10.TheNorwegianlivesinthefirsthouseontheleft.11.ThemanwhosmokesChesterfieldslivesinthehousenexttothemanwiththefox.12.Koolsaresmokedinthehousenexttothehousewherethehorseiskept.13.TheLuckyStrikesmokerdrinksorangejuice.14.TheJapanesesmokeParliaments.15.TheNorwegianlivesnexttothebluehouse.
16.NOW,whodrinkswater?Andwhoownsthezebra?
List Processing in Prolog: Zebra
30 September 2005 Foundations of Logic and Constraint Programming 36
Again, this problem is solved with a very simple program, but requires slightly moreinvolveddatastructures.Hereisapossiblesolution Asolution is a list of 5entities, eachcomposedofahouse,anationality, apet, a
drinkandacigarrettebrand. Thesedifferentcomponentscanbeassociatedinasingleterm,h(H,N,P,D,C). InlistL,anelementAthatisbeforeanotherelementB,encodesthefactthathouse
HAistotheleftofhouseHB.
Once this isdone, theprogramhas the followingstructure,where theconstraintsarestilltobespecified
List Processing in Prolog: Zebra
zebra(L):- L = [h(H1,N1,P1,D1,C1), h(H2,N2,P2,D2,C2), h(H3,N3,P3,D3,C3), h(H4,N4,P4,D4,C4), h(H5,N5,P5,D5,C5)],
... constraints...
30 September 2005 Foundations of Logic and Constraint Programming 37
Mostconstraintsassociatetwoentitiesinthesamehouse.Forexample
2.TheEnglishmanlivesintheredhouse.
This typeof constraint (common toconstraints2,3,4,5,7,8,13,14and the implicitconstraints in thequery) issimplymodelledby imposing thata termwith thespecifiedassociationisamemberoflistL
Constraints9and10statefactsaboutthehouseinthemiddleandtheleftmosthouse,whicharerespectivelythethirdandthefirtsmemberoflistL.
9.Milkisdrunkinthemiddlehouse.
10.TheNorwegianlivesinthefirsthouseontheleft.
List Processing in Prolog: Zebra
member(h(red,english,_,_,_),L), %2
L = [_,_,h(_,_,_,milk,_),_,_], % 9 L = [h(_,norwegian,_,_,_)| _], % 10
30 September 2005 Foundations of Logic and Constraint Programming 38
Anotherconstraintsreferstoahouselefttoanother
6.Thegreenhouseisimmediatelytotherightoftheivoryhouse.
Thistypeofconstraintissimplymodelledwiththesublistrelation
Otherconstraintsrefertohousesnexttoeacother,butnotspecifingwhichistotheleftandwhich is to the right. Hence, thepredicatenext/3maybedefinedspecifyingbothalternatives
Now,constraints11,12and15maybeexpresseddeclaratively.Forexample.
15.TheNorwegianlivesnexttothebluehouse.
List Processing in Prolog: Zebra
sublist([h(ivory,_,_,_,_),h(green,_,_,_,_)],L), % 6
next(A,B,L):- sublist([A,B],L). next(A,B,L):- sublist([B,A],L).
next(h(_,norwegian,_,_,_),h(blue,_,_,_,_),L), % 15
30 September 2005 Foundations of Logic and Constraint Programming 39
List Processing in Prolog: Zebra
Hereisthefullprogram
zebra(L):- L = [h(H1,N1,P1,D1,C1), h(H2,N2,P2,D2,C2), h(H3,N3,P3,D3,C3), h(H4,N4,P4,D4,C4), h(H5,N5,P5,D5,C5)], member(h(red,english,_,_,_),L), % 2 member(h(_,spanish,dog,_,_),L), % 3 member(h(green,_,_,coffee,_),L), % 4 member(h(_,ukrainian,_,tea,_),L), % 5 sublist([h(ivory,_,_,_,_),h(green,_,_,_,_)],L), % 6 member(h(_,_,snails,_,old_gold),L), % 7 member(h(yellow,_,_,_,kool),L), % 8 L = [_,_,h(_,_,_,milk,_),_,_], % 9 L = [h(_,norwegian,_,_,_)|_], % 10 next(h(_,_,_,_,chesterfields),h(_,_,fox,_,_),L), % 11 next(h(_,_,_,_,kool),h(_,_,horse,_,_),L), % 12 member(h(_,_,_,orange,lucky_strike),L), % 13 member(h(_,japanese,_,_,parliaments),L), % 14 next(h(_,norwegian,_,_,_),h(blue,_,_,_,_),L), % 15 member(h(_,_,zebra,_,_),L), % Q1 member(h(_,_,_,water,_),L). % Q2