1
AI 08226
Prolog
(PROgramming in LOGic)
Dr Darryl N. DavisDr Darryl N. Davis
Department of Computer ScienceDepartment of Computer Science
University of HullUniversity of Hull
2
Bibliography
�� Prolog Programming for AI, Ivan Prolog Programming for AI, Ivan BratkoBratko, ,
��3/e, Addison3/e, Addison--Wesley, 2001.Wesley, 2001.
�� The Art of Prolog, Sterling, L. and Shapiro, E.,The Art of Prolog, Sterling, L. and Shapiro, E.,
��MIT Press, 1986. MIT Press, 1986.
�� Mastering Prolog, Rob LucasMastering Prolog, Rob Lucas
��UCL Press; ISBN: 1857284003, 1996. UCL Press; ISBN: 1857284003, 1996.
�� Programming in PROLOG, W.F. Programming in PROLOG, W.F. ClocksinClocksin, C.S. , C.S. MellishMellish
��SpringerSpringer--VerlagVerlag, ISBN: 3540583505, 1994. , ISBN: 3540583505, 1994.
�� PROLOG for Students, David H. PROLOG for Students, David H. CallearCallear,,
��LettsLetts Educational Ltd; ISBN: 1858050936, 1994. Educational Ltd; ISBN: 1858050936, 1994.
3
Introduction
�� Prolog is a declarative languageProlog is a declarative language
�� It is not procedural or objectIt is not procedural or object--basedbased
��But can build objects in itBut can build objects in it
�� Prolog works in terms of pattern instantiationProlog works in terms of pattern instantiation
�� Prolog does not have global variablesProlog does not have global variables
��Other than predicate (or Other than predicate (or functorfunctor) names) names
�� Programs typically built from facts and rulesPrograms typically built from facts and rules
��a fact is a bodiless rulea fact is a bodiless rule
�� its_sunny.its_sunny.
��weather(sunny).weather(sunny).
4
Prolog
�� Programs built from predicatesPrograms built from predicates
��which have the value which have the value truetrue or or fail (fail (akaaka false)false)
�� Prolog makes use ofProlog makes use of Closed World AssumptionClosed World Assumption
�� If predicate name exists and cannot match to it If predicate name exists and cannot match to it
�� then predicate assumed to be false.then predicate assumed to be false.
�� Prolog concerned with relationships between Prolog concerned with relationships between
objects and the truth of theseobjects and the truth of these
�� Prolog programming concernedProlog programming concerned
��with defining relations with defining relations
��and querying relationsand querying relations
5
Predicates and Functors
�� Prolog predicates called Prolog predicates called functorsfunctors
�� the name of the predicate, the name of the predicate, costcost(robot, 2000)(robot, 2000)
�� functorfunctor names are alphanames are alpha--numeric numeric
�� begin with lowercase alphabegin with lowercase alpha
�� testtest, , relationrelation, , test123test123, , relation1Arelation1A are acceptableare acceptable
��TestTest, , 123123, , TESTTEST, , !!££$$ are not acceptableare not acceptable
��Typically predicates relate set of objectsTypically predicates relate set of objects
�� color(robot, green).color(robot, green).
�� cost(robot, affordable).cost(robot, affordable).
��Predicates have 0, 1, 2, 3, etc. argumentsPredicates have 0, 1, 2, 3, etc. arguments
�� cost. cost.
�� cost(doshcost(dosh).). cost(spaceship, expensive).cost(spaceship, expensive).
6
Predicate Functors and Arity
�� Predicates have Predicates have functorfunctor and and arityarity
��No space between predicate name & first parenthesisNo space between predicate name & first parenthesis
��%color(1)%color(1)
��color(red).color(red).
��color(green).color(green).
��%color/2%color/2
��color(robot, red).color(robot, red).
��color(grass, green).color(grass, green).
��%color/3%color/3
��color(robot, red, shiny).color(robot, red, shiny).
��color(sea, green, dull).color(sea, green, dull).
7
Terms and variables
�� NO such thing as GLOBAL variableNO such thing as GLOBAL variable
��nearest is set of predicates as nearest is set of predicates as functor/arityfunctor/arity
combinationscombinations
�� Terms beginning with Uppercase Alpha Terms beginning with Uppercase Alpha
characters are variablescharacters are variables�� cost(Thing, X, Y).cost(Thing, X, Y).
�� Tokens starting with lower case characters are Tokens starting with lower case characters are
not.not.�� cost(robot, X, Y).cost(robot, X, Y).
�� cost(amigabotcost(amigabot, X, Y)., X, Y).
8
Use of Prolog
�� Calling prologCalling prolog
��click on the click on the plwinplwin icon in icon in WindowsNTWindowsNT
��on on unix/solarisunix/solaris use pl (or prolog)use pl (or prolog)
�� Loading a fileLoading a file
��consult(Filename).consult(Filename).
�� If all prolog have .pl extensions can doIf all prolog have .pl extensions can do
��??-- consult(myfileconsult(myfile). OR ?). OR ?-- [[myfilemyfile].].
�� If notIf not
��??-- consult(consult(‘‘mybizrrefile.txtmybizrrefile.txt’’).).
�� Exiting prologExiting prolog
��^d or halt.^d or halt.
9
Hints
�� Which prologWhich prolog
��available for free from module available for free from module webpageswebpages
�� Use the DOT <CR> to finish prolog sequenceUse the DOT <CR> to finish prolog sequence
��does not work otherwise!does not work otherwise!
�� Use the SEMIUse the SEMI--COLON for multiple answersCOLON for multiple answers
��when using the interpreterwhen using the interpreter
�� use halt. to prologuse halt. to prolog
��also ^dalso ^d
�� interrupting programsinterrupting programs
��use ^cuse ^c
10Online Help (html manual available)
�� help(<TERM>)help(<TERM>)
��??-- help(atom).help(atom).
�� atom(+Term)atom(+Term)
�� Succeeds if Term is bound to an atom.Succeeds if Term is bound to an atom.
�� apropos(<TERM>)apropos(<TERM>)
��??-- apropos(atom).apropos(atom).
�� atom/1 Type check for an atomatom/1 Type check for an atom
�� atomic/1 Type check for primitiveatomic/1 Type check for primitive
�� explain(<TERM>)explain(<TERM>)
��??-- explain(help).explain(help).
�� "help" is an atom"help" is an atom
��Referenced from 1Referenced from 1--th clause of online_help:help/0th clause of online_help:help/0
11
Use Comments in Code
�� Use Comments to document your codeUse Comments to document your code
�� Two formsTwo forms
��% Percent Sign % Percent Sign -- all to right is commentall to right is comment
�� /* In/* In--between these delimiters is a comment */between these delimiters is a comment */
�� For example:For example:
�� /* File : /* File : comments.plcomments.pl */*/
�� /* Author: D.N.Davis *//* Author: D.N.Davis */
�� /* 11:19 AM 11/* 11:19 AM 11--SeptSept--2002 */2002 */
�� /* AI 08226 Example for Prolog Lectures *//* AI 08226 Example for Prolog Lectures */
��% go/0 % go/0 -- predicate to start the program, it stops Prologpredicate to start the program, it stops Prolog
��go:go:-- halt.halt.
12Prolog-AI-L2 (From Here)�� L1 L1 –– Prolog basics and interpreterProlog basics and interpreter
�� L2 L2 –– Writing Prolog Code (Getting it do things)Writing Prolog Code (Getting it do things)
13
Prolog Syntax�� ConstantConstant
�� Integer:Integer: 0, 42, 0, 42, --1717
��Real:Real: 1.07, 1.07, --0.029, 917.10.029, 917.1
��Atoms:Atoms: wine, x, x1wine, x, x1
�� ‘‘FredFred’’, , ‘‘file.plfile.pl’’
�� not not ““fredfred”” -- that is a list [102, 114, 101, 100] that is a list [102, 114, 101, 100]
�� Variable:Variable:
�� initial upper caseinitial upper case X, Value, V12a, X, Value, V12a, UniqueToClauseUniqueToClause
�� initial underscoreinitial underscore _result, _2_result, _2
��anonymousanonymous __
14
Assignment and testing on numbers�� X is 22+1.X is 22+1.
X = 23 X = 23
�� ??-- X is X+1.X is X+1.
ERROR: Arguments are not sufficiently instantiatedERROR: Arguments are not sufficiently instantiated
�� ??-- X = X+1.X = X+1.
X = ... +... +1+1+1+1+1+1+1+1+1 X = ... +... +1+1+1+1+1+1+1+1+1
�� ??-- X = X = 1.X = X = 1.
ERROR: Syntax error: Operator priority clashERROR: Syntax error: Operator priority clash
ERROR: X =ERROR: X =
ERROR: ** here **ERROR: ** here **
ERROR: X = 1 . ERROR: X = 1 .
15
Prolog Syntax�� OperatorsOperators
��many built in binary and unary operatorsmany built in binary and unary operators
��Arithmetic Infix Arithmetic Infix { /, *, { /, *, --, +, // , mod}, +, // , mod}
�� ??-- A is 3+4*7.A is 3+4*7.
��A = 31A = 31
��Arithmetic Prefix (unary)Arithmetic Prefix (unary) {truncate, floor, round}{truncate, floor, round}
�� ??-- A is round( 34/31). A is round( 34/31).
��A = 1 A = 1
��Cannot use variable name for more than one valueCannot use variable name for more than one value
�� ??-- A is 3*5, A is A*5, A is A is 3*5, A is A*5, A is sqrt(Asqrt(A).).
�� Need to use differently named variablesNeed to use differently named variables
�� ??-- A1 is 3*5, A2 is A1*5, A3 is sqrt(A2).A1 is 3*5, A2 is A1*5, A3 is sqrt(A2).
16
Prolog Syntax - Facts
�� Relation Relation -- a predicate with a predicate with functorfunctor and and arityarity
��university/0university/0
�� university.university.
��cycle/1cycle/1
�� cycle(cycle(‘‘Not StartedNot Started’’).).
�� cycle(1).cycle(1).
�� thing/2thing/2
�� thing(agent1, agent).thing(agent1, agent).
�� ting(object1, obstacle).ting(object1, obstacle).
��distance/3distance/3
�� distance(agent1, object1, 10).distance(agent1, object1, 10).
�� distance(agent1, agent2, 15).distance(agent1, agent2, 15).
17
Example Facts – greek.pl
�� male(cronusmale(cronus).).male(zeusmale(zeus).). male(hadesmale(hades).).
�� male(aresmale(ares).). male(hermesmale(hermes).). male(apollomale(apollo).).
�� female(herafemale(hera).). female(maiafemale(maia).). female(letofemale(leto).).
�� female(artemisfemale(artemis).). female(irisfemale(iris).).
�� parent(cronusparent(cronus, , zeuszeus).). parent(cronusparent(cronus, , hadeshades).).
�� parent(zeusparent(zeus, , aresares).). parent(zeusparent(zeus, , hermeshermes).).
�� parent(zeusparent(zeus, , apolloapollo).). parent(zeusparent(zeus, , artemisartemis).).
�� parent(zeusparent(zeus, iris)., iris). parent(heraparent(hera, , aresares).).
�� parent(heraparent(hera, iris)., iris). parent(letoparent(leto, , apolloapollo).).
�� parent(letoparent(leto, , artemisartemis).). parent(maiaparent(maia, , hermeshermes).).
18
Loading Files into SWI-Prolog�� ??-- [[greekgreek].].
�� % d:/Teaching/AI/Code/GREEK.PL compiled 0.00 sec, 2,336 bytes% d:/Teaching/AI/Code/GREEK.PL compiled 0.00 sec, 2,336 bytes
�� % Accessing the data% Accessing the data
�� ??-- listing(malelisting(male).).
�� ??-- listing(femalelisting(female).).
�� ??-- listing(parentlisting(parent).).
�� ??-- male(Amale(A).).
�� 2 ?2 ?-- male(Amale(A).).
�� A = A = cronuscronus
�� 3?3?-- female(Afemale(A).).
�� A = hera ;A = hera ;
�� A = maia ;A = maia ;
�� A = leto ;A = leto ;
�� A = artemis ;A = artemis ;
�� A = iris ;A = iris ;
�� NoNo
19
More on the use of not
�� female(athenefemale(athene).). male(hermesmale(hermes).).
�� not(male(X)).not(male(X)).
�� not(female(X)).not(female(X)).
�� not(male(X)), not(female(X)).not(male(X)), not(female(X)).
�� not( (male(X) , female(X) ) ).not( (male(X) , female(X) ) ).
�� male(X) , female(X).male(X) , female(X).
�� not( (male(X) ; female(X) ) ).not( (male(X) ; female(X) ) ).
�� male(X) ; female(X).male(X) ; female(X).
�� % now add% now add
�� female(hermaphrodite). male(hermaphrodite).female(hermaphrodite). male(hermaphrodite).
20
Negation of Facts�� Logic Unary (Infix)Logic Unary (Infix)
�� not/1, not/1, not(predicatenot(predicate).).
�� If predicate known then negation can be doneIf predicate known then negation can be done�� not(male(hermesnot(male(hermes)).)). NoNo
�� not(female(hermesnot(female(hermes)).)). YesYes
�� If predicate not known then negation is an errorIf predicate not known then negation is an error�� not(greek(hermesnot(greek(hermes)).)). Fail Fail –– greek/1 undefinedgreek/1 undefined
�� Can use not to surround more than one clause BUTCan use not to surround more than one clause BUT……�� ??-- not( not( male(hermesmale(hermes), ), female(hermesfemale(hermes)).)).
�� ERROR: Undefined procedure: not/2ERROR: Undefined procedure: not/2
�� ERROR: However, there are definitions for:ERROR: However, there are definitions for:
�� ERROR: not/1ERROR: not/1
�� NoNo
�� 3 ?3 ?-- not( ( not( ( male(hermesmale(hermes), ), female(hermesfemale(hermes) ) ).) ) ).
�� YesYes
21
Prolog and logic (in later lectures)
�� Prolog based on first order predicate calculusProlog based on first order predicate calculus
��constants, variables, compound terms,constants, variables, compound terms,
��not ( not ( ¬¬ ), and ( ), and ( ∧∧ ), or ( ), or ( ∨∨ ), ),
�� implies ( implies ( ⇐⇐ ) (( ) (( ⇒⇒ )), equivalence ()), equivalence (⇔⇔ ))
�� for all (for all (∀∀∀∀∀∀∀∀ ), there exists (), there exists (∃∃∃∃∃∃∃∃ ))
�� ∃∃∃∃∃∃∃∃ •• woman(y) woman(y) ∧∧ parent(y, x) parent(y, x)
⇐⇐ ∀∀x x •• man(x) man(x) ∧∧ ¬¬(x = ash)(x = ash)
�� ∃∃∃∃∃∃∃∃ •• woman(y) woman(y) ∧∧ parent(y, x) parent(y, x)
⇐⇐ ∀∀x x •• woman(x) woman(x) ∧∧ ¬¬(x = elm)(x = elm)
22
Clauses and Programs
�� Unit ClauseUnit Clause
��constant or relation terminated with a constant or relation terminated with a fullstopfullstop
�� toolkit_initialisedtoolkit_initialised..
�� perceives(agent1, [agent2, object1]).perceives(agent1, [agent2, object1]).
�� knows(agent1, nothing).knows(agent1, nothing).
�� NonNon--unit Clauseunit Clause
��constructed from constants and relations using, binary constructed from constants and relations using, binary
operators, operators, ““::--”” ““,,””
�� knows(A, B):knows(A, B):-- perceives(A, B).perceives(A, B).
�� agent( A ) :agent( A ) :-- thing( A, agent ).thing( A, agent ).
�� perceived( A ) :perceived( A ) :-- perceives( _wildcard, A).perceives( _wildcard, A).
23
The use of the Semi-colon - or
�� Alternative matchesAlternative matches
�� state(wet):state(wet):--
�� (fell_in_the_sea(fell_in_the_sea ;; raining_heavily).raining_heavily).
��On many occasions this becomes unclearOn many occasions this becomes unclear
��with more complex clauseswith more complex clauses
��Alternatively produce multiple clauses (preferable)Alternatively produce multiple clauses (preferable)
�� state(wet):state(wet):--
�� fell_in_the_sea.fell_in_the_sea.
�� state(wet):state(wet):--
�� raining_heavily.raining_heavily.
24Predicates: Multiple Instances Allowed
�� Unit Clauses (Facts) Unit Clauses (Facts) % male/1% male/1
male(apollomale(apollo).).
male(zeusmale(zeus).).
�� NonNon--Unit Clauses (Rules) Unit Clauses (Rules) % sibling/2% sibling/2
sibling(Xsibling(X, Y):, Y):--
father(Zfather(Z, X),, X),
father(Zfather(Z, Y)., Y).
sibling(Xsibling(X, Y):, Y):--
mother(Zmother(Z, X),, X),
mother(Zmother(Z, Y)., Y).
25
Prolog programs
�� Consist of clauses of facts, rules and questionsConsist of clauses of facts, rules and questions
��Facts (unit clauses)Facts (unit clauses)
�� thing(agent1, agent).thing(agent1, agent).
�� agent(agent2, static, up, 55, 67).agent(agent2, static, up, 55, 67).
��Rules (nonRules (non--unit clauses)unit clauses)
�� agent(Name) :agent(Name) :-- thing(Name, agent).thing(Name, agent).
�� agent(Nameagent(Name):):-- agent(Nameagent(Name, _state, _direction, _x, _y)., _state, _direction, _x, _y).
��Questions (via the interpreter or other code)Questions (via the interpreter or other code)
�� ??-- agent(A).agent(A).
�� A is agent1.A is agent1.
�� Yes.Yes.
�� A relation is specified by facts and rulesA relation is specified by facts and rules
�� A procedure is set of clauses about the same relationA procedure is set of clauses about the same relation
26
Example Prolog File: program1.pl��% An example about agent and objects% An example about agent and objects
�� thing(agent1, agent). thing(agent2, agent).thing(agent1, agent). thing(agent2, agent).
�� thing(object1, object). thing(object1, object).
�� location(agent1, 10, 10). location(agent2, 15, 35).location(agent1, 10, 10). location(agent2, 15, 35).
�� location(object1, 10, 30).location(object1, 10, 30).
��% Distance/3 evaluates distance between things% Distance/3 evaluates distance between things
��distance(Thing1, Thing2, Distance):distance(Thing1, Thing2, Distance):--
location(Thing1, X1, Y1),location(Thing1, X1, Y1),
location(Thing2, X2, Y2),location(Thing2, X2, Y2),
XdiffXdiff is X1is X1--X2, X2, XsqXsq is is XdiffXdiff**XdiffXdiff,,
YdiffYdiff is Y1is Y1--Y2, Y2, YsqYsq is is YdiffYdiff**YdiffYdiff,,
Distance is Distance is sqrt(Xdiff+Ydiffsqrt(Xdiff+Ydiff).).
27
Querying the program in swi-prolog% PROGRAM1.PL compiled 0.00 sec, 4,700 bytes% PROGRAM1.PL compiled 0.00 sec, 4,700 bytes
??-- distance(agent1, agent2, X).distance(agent1, agent2, X).
X = 25.4951 X = 25.4951
??-- distance(A,B,0).distance(A,B,0).
A = agent1A = agent1
B = agent1 B = agent1
??-- distance(A,B,C).distance(A,B,C).
A = agent1A = agent1
B = agent1B = agent1
C = 0 ;C = 0 ;
A = agent1A = agent1
B = agent2B = agent2
C = 25.4951 ;C = 25.4951 ;
etc.etc.
28
Hints about Debug
�� ^c results in the help prompt^c results in the help prompt
��Action (h for help) ?Action (h for help) ?
��Typing an 'h' gets us:Typing an 'h' gets us:
�� a: abort a: abort b: breakb: break
�� c: continue c: continue e: e:
�� g: goals g: goals t: tracet: trace
�� 'e' s the program immediately'e' s the program immediately
�� 'a' aborts whatever you've type so far'a' aborts whatever you've type so far
�� 'c' continues where you left off'c' continues where you left off
�� 'h' gets us the 'Action' help menu, again'h' gets us the 'Action' help menu, again
29
Program Execution
�� Prolog tries to satisfy goals (questions) byProlog tries to satisfy goals (questions) by
��Matching the head of a ruleMatching the head of a rule
��Satisfying the body of the ruleSatisfying the body of the rule
�� (unification is from left to right)(unification is from left to right)
•• success success →→
��Head :Head :-- TermTerm11, Term, Term22, , ……, , TermTermnn..
•• ←← failurefailure
�� If a specific instance of a term fails, If a specific instance of a term fails,
�� Prolog looks for another instance to matchProlog looks for another instance to match
�� If a term fails, Prolog backtracks andIf a term fails, Prolog backtracks and
�� attempts to reattempts to re--evaluate previous terms.evaluate previous terms.
�� If a rule failsIf a rule fails
�� Prolog tries to find another matching head (in sequence)Prolog tries to find another matching head (in sequence)
30
Example Prolog Execution 0
�� % example prolog database using fact/2 % example prolog database using fact/2
�� fact(grass, green).fact(grass, green).
�� fact(sky, blue).fact(sky, blue).
�� fact(sun, yellow).fact(sun, yellow).
�� fact(sea, green).fact(sea, green).
�� fact(desert, yellow).fact(desert, yellow).
�� % example rules using rule/1% example rules using rule/1
�� rule(X):rule(X):-- fact(X, Color), fact(Y, Color), X fact(X, Color), fact(Y, Color), X \\= Y.= Y.
�� rule(X):rule(X):-- fact(T1, X), fact(T2, X), T1 fact(T1, X), fact(T2, X), T1 \\= T2.= T2.
31Example Prolog Execution I�� ??-- rule(A). rule(A).
��Matches against first instance of rule/1Matches against first instance of rule/1
��AA unified to unified to XX
��Look to first term of body i.e.Look to first term of body i.e. fact(X, Color),fact(X, Color),
��matches to first instance of fact/2matches to first instance of fact/2
��XX unified to unified to grassgrass, , ColorColor unified to unified to greengreen
��Look to second term of body i.e. Look to second term of body i.e. fact(Y, Color),fact(Y, Color),
��Color Color is instantiated to is instantiated to greengreen from first termfrom first term
��matches to first instance of fact/2matches to first instance of fact/2
��YY unified to unified to grassgrass
��Look to third term of body, i.e. Look to third term of body, i.e. X X \\= Y.= Y.
�� both both XX and and YY unified to unified to grassgrass, it fails, it fails
�� backtracks to retry second termbacktracks to retry second term
32Example Prolog Execution II
��Rematch second term of body i.e. Rematch second term of body i.e. fact(Y, Color),fact(Y, Color),
��ColorColor is instantiated to is instantiated to greengreen from first termfrom first term
�� tries to match serially to fact/2tries to match serially to fact/2
��matches to fourth instance of fact/2matches to fourth instance of fact/2
��YY unified to unified to seasea
��Look to third term of body, i.e. Look to third term of body, i.e. X X \\= Y.= Y.
��XX unified to unified to grassgrass, , YY unified to unified to seasea
�� these are different so comparison succeedsthese are different so comparison succeeds
��Body now fully instantiatedBody now fully instantiated
��X = grassX = grass
��At this point can press return or type in At this point can press return or type in ““;;””
�� if latter now looks for further matchesif latter now looks for further matches
33
Example Prolog Execution III
��Look to first term of body i.e.Look to first term of body i.e. fact(X, Color),fact(X, Color),
�� looks to second instance of fact/2looks to second instance of fact/2
��XX unified to unified to skysky, , ColorColor unified to unified to blueblue
��Look to second term of body i.e. Look to second term of body i.e. fact(Y, Color),fact(Y, Color),
��ColorColor is instantiated to is instantiated to blueblue from first termfrom first term
��matches to second instance of fact/2matches to second instance of fact/2
��YY unified to unified to skysky
��Look to third term of body, i.e. Look to third term of body, i.e. X X \\= Y.= Y.
�� both both XX and and YY unified to unified to skysky, it fails, it fails
�� backtracks to retry second termbacktracks to retry second term
��Cannot find another match to Cannot find another match to fact(VAR, blue)fact(VAR, blue)
�� backtracks to retry first termbacktracks to retry first term
34Example Prolog Execution IV
��Look to first term of body i.e.Look to first term of body i.e. fact(X, Color),fact(X, Color),
�� looks to third instance of fact/2looks to third instance of fact/2
��XX unified to sun, unified to sun, ColorColor unified to unified to yellowyellow
��Look to second term of body i.e. Look to second term of body i.e. fact(Y, Color),fact(Y, Color),
��ColorColor is instantiated to is instantiated to yellowyellow from first termfrom first term
��matches to fifth instance of fact/2matches to fifth instance of fact/2
��YY unified to unified to desertdesert
��Look to third term of body, i.e. Look to third term of body, i.e. X X \\= Y.= Y.
��XX unified to unified to sunsun, and , and YY unified to unified to desertdesert, it succeeds, it succeeds
��Body now fully instantiatedBody now fully instantiated
��X = sunX = sun
��At this point can press return or type in At this point can press return or type in ““;;””
�� if latter now looks for further matchesif latter now looks for further matches
35Example Prolog Execution V��Look to first term of body i.e.Look to first term of body i.e. fact(X, Color),fact(X, Color),
�� looks to fourth instance of fact/2looks to fourth instance of fact/2
��XX unified to unified to seasea, , ColorColor unified to unified to greengreen
��Look to second term of body i.e. Look to second term of body i.e. fact(Y, Color),fact(Y, Color),
��ColorColor is instantiated to is instantiated to greengreen from first termfrom first term
��matches to first instance of fact/2matches to first instance of fact/2
��YY unified to unified to grassgrass
��Look to third term of body, i.e. Look to third term of body, i.e. X X \\= Y.= Y.
��XX unified to unified to seasea and and YY unified to unified to grassgrass, it succeeds, it succeeds
��Body now fully instantiatedBody now fully instantiated
��X = seaX = sea
��At this point can press return or type in At this point can press return or type in ““;;””
�� if latter now looks for further matchesif latter now looks for further matches
36
Full Set of Results:�� d:SEA.PL compiled, 0.11 sec, 1,328 bytes.d:SEA.PL compiled, 0.11 sec, 1,328 bytes.
�� ??-- rule(X).rule(X).
�� X = grass ;X = grass ; % rule/1 (1)% rule/1 (1)
�� X = sun ;X = sun ; % rule/1 (1)% rule/1 (1)
�� X = sea ;X = sea ; % rule/1 (1)% rule/1 (1)
�� X = desert ;X = desert ; % rule/1 (1)% rule/1 (1)
�� X = green ;X = green ; % rule/1 (2)% rule/1 (2)
�� X = yellow ;X = yellow ; % rule/1 (2)% rule/1 (2)
�� X = green ;X = green ; % rule/1 (2)% rule/1 (2)
�� X = yellow ;X = yellow ; % rule/1 (2)% rule/1 (2)
�� NoNo % exhausted possibilities% exhausted possibilities
�� ??--
37
On Prolog Execution
�� Prolog explores choices in orderProlog explores choices in order
��backtracking ensures that all possibilities are triedbacktracking ensures that all possibilities are tried
�� if necessaryif necessary
�� Backtracking is an activity under control of Backtracking is an activity under control of
Prolog not the programmerProlog not the programmer
��Programmer can force backtracking or stop itProgrammer can force backtracking or stop it
��using repeat, fail, true and ! (cut) operatorsusing repeat, fail, true and ! (cut) operators
�� covered in later lecturescovered in later lectures
�� Prolog has no global variablesProlog has no global variables
��Scope of a variable is a clauseScope of a variable is a clause
38
Pictures of program execution
�� Trees can be used to represent space Trees can be used to represent space
��of possible solutions to a goalof possible solutions to a goal
�� Consider:Consider:
fact(grassfact(grass, green)., green).
fact(skyfact(sky, blue)., blue).
fact(seafact(sea, green)., green).
�� % example rules using rule/1% example rules using rule/1
rule(Xrule(X):):-- fact(Xfact(X, Color), , Color), fact(Yfact(Y, Color), , Color), not(Xnot(X == Y).== Y).
�� with the goal with the goal
??-- rule(Arule(A).).
39
Tree1
rule(A)
fact(Xfact(X, Color), , Color), fact(Yfact(Y, , Color),not(XColor),not(X==Y).==Y).
fact(grass, green),
fact(grass,green),
not(grass==grass)
This path fails - try another
40
Tree2
This path fails too!
fact(Xfact(X, Color), , Color), fact(Yfact(Y, , Color),not(XColor),not(X==Y).==Y).
fact(grass, green),
fact(grass,green),
not(grass==grass)
fact(grass, green),
fact(sky,blue),
not(X==Y)
fact(grassfact(grass, green), , green), fact(Yfact(Y, , green),not(grassgreen),not(grass==Y).==Y).
41
Tree3 – first of the succeeds
Many other paths, some succeed, most fail!
rule(A)
fact(Xfact(X, Color), , Color), fact(Yfact(Y, , Color),not(XColor),not(X==Y).==Y).
fact(grass, green),
fact(grass,green),
not(grass==grass)
fact(grass, green),
fact(sky,blue),
not(X==Y)
fact(grass, green),
fact(sea, green),
not(grass==sea)
fact(grassfact(grass, green), , green), fact(Yfact(Y, , green),not(grassgreen),not(grass==Y).==Y).
42
Agents in a Discrete World: See CWK
43
Modelling Automata
�� A Finite State Machine has a logical structureA Finite State Machine has a logical structure
��Can be used for Very Simple AgentsCan be used for Very Simple Agents
�� Defined on its input and internal stateDefined on its input and internal state
��InputInput: : SpaceFreeSpaceFree | | SpaceBlockSpaceBlock
��State: AKSF | AKSB | StaticState: AKSF | AKSB | Static
��Output: Output: Nothing|TurnLeft|MoveAheadNothing|TurnLeft|MoveAhead
��StateChangeFunctionStateChangeFunction : :
Input+InternalInput+Internal→→InternalInternal
��OutputFunctionOutputFunction : :
Input+Internal Input+Internal →→OutputOutput
44
Specification of FSM as Table
Input State Change Output
SpaceFree AKSF AKSF Ahead
SpaceFree AKSB AKSF Ahead
SpaceFree Static AKSF Nothing
SpaceBlock AKSF AKSB Nothing
SpaceBlock AKSB AKSB TurnLeft
SpaceBlock Static AKSB Nothing
45
FSM as prolog - state change function
%statechange/3%statechange/3
% % statechange(inputstatechange(input, state, , state, newstatenewstate).).
statechange(spacefree,aksf,aksfstatechange(spacefree,aksf,aksf).).
statechange(spacefree,aksb,aksfstatechange(spacefree,aksb,aksf).).
statechange(spacefree,static,aksfstatechange(spacefree,static,aksf).).
statechange(spaceblock,aksf,aksbstatechange(spaceblock,aksf,aksb).).
statechange(spaceblock,aksbstatechange(spaceblock,aksb, , aksbaksb).).
statechange(spaceblock,static,aksbstatechange(spaceblock,static,aksb).).
�� % many alternative codes% many alternative codes
46
FSM as prolog - output function
% output/3% output/3
% output(input, state, output).% output(input, state, output).
output(spacefree,aksf,aheadoutput(spacefree,aksf,ahead).).
output(spacefree,aksb,aheadoutput(spacefree,aksb,ahead).).
output(spacefree,static,nothingoutput(spacefree,static,nothing).).
output(spaceblock,aksf,nothingoutput(spaceblock,aksf,nothing).).
output(spaceblock,aksboutput(spaceblock,aksb, , turnleftturnleft).).
output(spaceblock,static,nothingoutput(spaceblock,static,nothing).).
�� % many alternative codes% many alternative codes
47
THE Full FSM in prolog : fsm1.pl
% fsm/4% fsm/4
% % fsm(inputfsm(input, state, , state, newstatenewstate, output)., output).
% defined over % defined over statechangestatechange and outputand output
fsm(Inputfsm(Input, State, , State, NewStateNewState, Output):, Output):--
statechange(Inputstatechange(Input, State, , State, NewStateNewState),),
output(Input, output(Input, NewStateNewState, Output)., Output).
??-- [fsm1].[fsm1].
% FSM1.PL compiled 0.00 sec, 1,812 bytes% FSM1.PL compiled 0.00 sec, 1,812 bytes
??-- fsm(A,B,C,Dfsm(A,B,C,D).).
A = A = spacefreespacefree B = B = aksfaksf C = C = aksfaksf D = aheadD = ahead
48
Clause Order
�� Matching determines which clauses can be used to Matching determines which clauses can be used to
solve a goalsolve a goal
�� Clauses tried in orderClauses tried in order
��sequentially in consulted ordersequentially in consulted order
�� left to right in bodiesleft to right in bodies
�� If progress halts, backtracking is triedIf progress halts, backtracking is tried
�� Matching (clause instantiation) is depthMatching (clause instantiation) is depth--first first
search through prolog clausessearch through prolog clauses
49
Matching
�� General rules for matching two terms S and T;General rules for matching two terms S and T;
�� If S and T are constantsIf S and T are constants
�� Then they match only if they are the same entityThen they match only if they are the same entity
��??-- 2 == 2.2 == 2.
��YesYes
��??-- a = a.a = a.
��YesYes
��??-- 'Term1' == 'Term2'.'Term1' == 'Term2'.
��NoNo
��??-- "String1" = "String1"."String1" = "String1".
��YesYes
50
Matching
�� General rules for matching two terms S and T;General rules for matching two terms S and T;
�� If S is a variable and T is anythingIf S is a variable and T is anything
�� Then they match.Then they match.
��??-- S = _var.S = _var.
�� S = _G147 S = _G147
�� YesYes
��??-- S= _.S= _.
�� S = _G123 S = _G123
�� YesYes
��??-- S = a.S = a.
�� S = a S = a
�� YesYes
51
Matching of Variables
�� Order of clauses mattersOrder of clauses matters
��??-- A = B, A = 1, B = 1.A = B, A = 1, B = 1.
�� YesYes
��??-- A = 1, B = 1, A = B.A = 1, B = 1, A = B.
�� YesYes
��??-- A = 1, B = 1, A == B.A = 1, B = 1, A == B.
�� YesYes
��??-- A == B, A = 1, B = 1.A == B, A = 1, B = 1.
�� NoNo
��? A = B, A == B.? A = B, A == B.
�� YesYes
��So? So? ??-- A == B, A = B. ?A == B, A = B. ?-- A = B, A == B.A = B, A == B.
52
Matching
�� General rules for matching two terms S and T;General rules for matching two terms S and T;
�� If S and T are clauses then they match only if If S and T are clauses then they match only if
�� S and T have the same principal S and T have the same principal functorfunctor andand
�� all their corresponding components match.all their corresponding components match.
��??-- date(D, M, 2001) = date(D1, date(D, M, 2001) = date(D1, januaryjanuary, Y1)., Y1).
�� D = _G339D = _G339
�� M = M = januaryjanuary
�� D1 = _G339D1 = _G339
�� Y1 = 2001 Y1 = 2001
�� YesYes
��??-- date(D, M, 2001) = date(D1, date(D, M, 2001) = date(D1, januaryjanuary, 2020)., 2020).
�� NoNo
53
Matching
�� Matching in prolog always results in the most Matching in prolog always results in the most
general instantiationgeneral instantiation
��committing variables to the least possible extentcommitting variables to the least possible extent
��??-- date(D, M, 2001) = date(D1, date(D, M, 2001) = date(D1, januaryjanuary, Y1),, Y1),
�� date(D, M, 2001) = date(1, M, Y).date(D, M, 2001) = date(1, M, Y).
�� InstantiationsInstantiations
��First GoalFirst Goal Second GoalSecond Goal Third GoalThird Goal
�� D = D1D = D1 D = 1D = 1 D = 1, D1 = 1D = 1, D1 = 1
�� M = M = januaryjanuary M = MM = M M = M = januaryjanuary
�� Y1 = 2001Y1 = 2001 Y = 2001Y = 2001 Y1 = 2000, Y = 2001Y1 = 2000, Y = 2001
��Consecutive goals leading to more specific valuesConsecutive goals leading to more specific values
54
Unification
�� Position in unification is the same as in matchingPosition in unification is the same as in matching
�� two atoms unify if they are equaltwo atoms unify if they are equal
��one variable and one atomone variable and one atom
�� the variable is instantiated to the value of the atomthe variable is instantiated to the value of the atom
��structures unify if:structures unify if:
�� they have the same they have the same functorfunctor
�� they have the same number of componentsthey have the same number of components
�� corresponding components unifycorresponding components unify
��E.g. p(X, b) and p(a, Y) unify with {a/X, b/Y}E.g. p(X, b) and p(a, Y) unify with {a/X, b/Y}
�� p(X, X) and p(a, b) do not unifyp(X, X) and p(a, b) do not unify
�� p(X, f(Y) and p(Y, f(a)) unify with {a/X, a/Y}p(X, f(Y) and p(Y, f(a)) unify with {a/X, a/Y}
55
Unification & The occurs check
�� Unification is indeterminate for two componentsUnification is indeterminate for two components
�� IF one being a variable and another being a termIF one being a variable and another being a term
�� if the variable appears in the termif the variable appears in the term
�� occurs(X):occurs(X):-- p(X) = p(f(X)).p(X) = p(f(X)).
��X = f(f(f(f(f(f(f(f(f(f(...)))))))))) X = f(f(f(f(f(f(f(f(f(f(...))))))))))
�� MatchingMatching: :
�� a process that determines whether a clause can be a process that determines whether a clause can be
used to solve goal.used to solve goal.
��Many prologs do not include occurs checksMany prologs do not include occurs checks
�� If two terms unify they matchIf two terms unify they match
�� If two terms match, they may not unify.If two terms match, they may not unify.
56
Exploiting matching
�� Achieve computation by clause application, Achieve computation by clause application,
selection and constructionselection and construction
summary(item(book,
author(pratchett),
title(the_colour_of_magic),
code(124753)),
book(pratchett, the_color_of_magic) ).
opus(O):-
summary(item(book,author(_A), title(_T),code(_)), O).
?- opus(O).
O = book(pratchett, the_color_of_magic)
57
Testing data
�� valid(day, Day):valid(day, Day):--
�� Day > 0, Day < 32.Day > 0, Day < 32.
�� valid(month, Month):valid(month, Month):--
�� Month > 0, Month < 13.Month > 0, Month < 13.
�� ??-- valid(day, 0).valid(day, 0). nono
�� ??-- valid(month, 0).valid(month, 0). nono
�� ??-- valid(day, 29).valid(day, 29). yesyes
�� ??-- valid(month, 11).valid(month, 11). yesyes
�� ??-- valid(day, 32).valid(day, 32). nono
�� ??-- valid(month, 13).valid(month, 13). nono
58
Procedural programming - I/O�� write(Text) and write(Text) and nlnl
��outputs text (wrapped in single apostrophes)outputs text (wrapped in single apostrophes)
�� ??-- write(write(‘‘Hi Hi -- some meaningless textsome meaningless text’’).).
��??-- write(write(‘‘Yet some more textYet some more text’’), nl.), nl.
��careful with the apostrophes, I.e. do not writecareful with the apostrophes, I.e. do not write
��write(write(‘‘FredaFreda’’ss piece of textpiece of text’’).).
�� read(Term) read(Term) -- reads a term from the input.reads a term from the input.
��??-- read(Term).read(Term).
�� |: a.|: a.
��Term = a Term = a
��YesYes
59
Example :Month Conversion program�� go:go:-- write(write(‘‘Integers to Names of MonthsIntegers to Names of Months’’), ), nlnl,,
�� write(write(‘‘Enter the month as an integer: Enter the month as an integer: ‘‘),),
�� read(Month),read(Month),
�� write(write(‘‘The month is The month is ‘‘),),
�� month(Month), month(Month), nlnl..
�� month(1):month(1):-- write(write(‘‘JanuaryJanuary’’).).
�� month(2):month(2):-- write(write(‘‘FebuaryFebuary’’).).
�� month(12):month(12):-- write(write(‘‘DecemberDecember’’).).
�� month(_):month(_):-- write(write(‘‘Unknown Unknown -- Incorrect EntryIncorrect Entry’’).).
60�� ??-- go.go.
�� Integers to Names of MonthsIntegers to Names of Months
�� Enter the month as an integer: 9.Enter the month as an integer: 9.
�� The month is SeptemberThe month is September
�� ??-- go.go.
�� Integers to Names of MonthsIntegers to Names of Months
�� Enter the month as an integer: Enter the month as an integer: --1.1.
�� The month is Unknown The month is Unknown -- Incorrect EntryIncorrect Entry
�� ??-- go.go.
�� Integers to Names of MonthsIntegers to Names of Months
�� Enter the month as an integer: a.Enter the month as an integer: a.
�� The month is Unknown The month is Unknown -- Incorrect EntryIncorrect Entry
61
Arithmetic Program�� run:run:-- get_a_number(Num1),get_a_number(Num1),
�� get_a_number(Num2), get_a_number(Num2), nlnl,,
�� write(write(‘‘a : Add.a : Add.’’), ), nlnl,,
�� write(write(‘‘b: Subtract.b: Subtract.’’), ), nlnl,,
�� write(write(‘‘c: Multiply.c: Multiply.’’), ), nlnl,,
�� write(write(‘‘d: Divide.d: Divide.’’), ), nlnl,,
�� write(write(‘‘e: .e: .’’), ), nlnl,,
�� write(write(‘‘Your choice: Your choice: ‘‘), read(Choice), ), read(Choice), nlnl,,
�� choice(Num1, Num2, Choice), choice(Num1, Num2, Choice), nlnl..
�� get_a_number(N):get_a_number(N):-- write(write(‘‘Enter a number: Enter a number: ‘‘),),
�� read(N).read(N).
62�� % choice/3 % choice/3 -- now perform what was asked with checksnow perform what was asked with checks
�� choice(_,N1, N2):choice(_,N1, N2):--
�� ( not(number(N1)); not(number(N2))),( not(number(N1)); not(number(N2))),
�� write('Numbers not entered when asked'), write('Numbers not entered when asked'), nlnl..
�� choice(a, N1, N2):choice(a, N1, N2):-- X is N1+N2,X is N1+N2,
�� write('Answer = '), write(X), write('Answer = '), write(X), nlnl..
�� choice(b,N1, N2):choice(b,N1, N2):-- X is N1X is N1--N2,N2,
�� write('Answer = '), write(X), write('Answer = '), write(X), nlnl..
�� choice(c,N1, N2):choice(c,N1, N2):-- X is N1*N2,X is N1*N2,
�� write('Answer = '), write(X), write('Answer = '), write(X), nlnl..
�� choice(d,N1, N2):choice(d,N1, N2):-- X is N1/N2,X is N1/N2,
�� write('Answer = '), write(X), write('Answer = '), write(X), nlnl..
�� choice(e,_,_):choice(e,_,_):-- halt.halt.
�� choice(_,_,_):choice(_,_,_):-- write('Strange Values Entered'), write('Strange Values Entered'), nlnl..
63
Unacceptable Prolog!�� The following will not be accepted by PrologThe following will not be accepted by Prolog
�� run:run:-- Total = 0,Total = 0,
�� write(write(‘‘Enter a number: Enter a number: ‘‘), ), read(Numread(Num),),
�� Total is Total + Num,Total is Total + Num,
�� write(write(‘‘Enter another number: Enter another number: ‘‘), ), read(Numread(Num ),),
�� Total is Total + Num ,Total is Total + Num ,
�� write(write(‘‘Total is Total is ‘‘), write(Total ), ), write(Total ), nlnl..
� A major difference between declarative and procedural
programming languages
� While subgoals may appear like instructions
�� They remain goals with unification & matching rulesThey remain goals with unification & matching rules
�� ieie variable names can be used once in a callvariable names can be used once in a call
64
Programming Techniques : Recursion
Programming Techniques : RecursionProgramming Techniques : Recursion
�� In procedural languagesIn procedural languages
��recursion is a procedure or subroutine calling itselfrecursion is a procedure or subroutine calling itself
�� In PrologIn Prolog
��recursion involves a rule calling itself as a recursion involves a rule calling itself as a subgoalsubgoal
�� Example:Example:
�� loop:- write(‘This is a loop’), loop.loop:- write(‘This is a loop’), loop.
�� Problem : how does this stop?Problem : how does this stop?
�� Many ways of doing this in PrologMany ways of doing this in Prolog
Programming Techniques : RecursionProgramming Techniques : Recursion
�� In procedural languagesIn procedural languages
��recursion is a procedure or subroutine calling itselfrecursion is a procedure or subroutine calling itself
�� In PrologIn Prolog
��recursion involves a rule calling itself as a recursion involves a rule calling itself as a subgoalsubgoal
�� Example:Example:
�� loop:- write(‘This is a loop’), loop.loop:- write(‘This is a loop’), loop.
�� Problem : how does this stop?Problem : how does this stop?
�� Many ways of doing this in PrologMany ways of doing this in Prolog
Programming Techniques : RecursionProgramming Techniques : Recursion
�� In procedural languagesIn procedural languages
��recursion is a procedure or subroutine calling itselfrecursion is a procedure or subroutine calling itself
�� In PrologIn Prolog
��recursion involves a rule calling itself as a recursion involves a rule calling itself as a subgoalsubgoal
�� Example:Example:
�� loop:- write(‘This is a loop’), loop.loop:- write(‘This is a loop’), loop.
�� Problem : how does this stop?Problem : how does this stop?
�� Many ways of doing this in PrologMany ways of doing this in Prolog
Programming Techniques : RecursionProgramming Techniques : Recursion
�� In procedural languagesIn procedural languages
��recursion is a procedure or subroutine calling itselfrecursion is a procedure or subroutine calling itself
�� In PrologIn Prolog
��recursion involves a rule calling itself as a recursion involves a rule calling itself as a subgoalsubgoal
�� Example:Example:
�� loop:- write(‘This is a loop’), loop.loop:- write(‘This is a loop’), loop.
�� Problem : how does this stop?Problem : how does this stop?
�� Many ways of doing this in PrologMany ways of doing this in Prolog
Programming Techniques : RecursionProgramming Techniques : Recursion
�� In procedural languagesIn procedural languages
��recursion is a procedure or subroutine calling itselfrecursion is a procedure or subroutine calling itself
�� In PrologIn Prolog
��recursion involves a rule calling itself as a recursion involves a rule calling itself as a subgoalsubgoal
�� Example:Example:
�� loop:- write(‘This is a loop’), loop.loop:- write(‘This is a loop’), loop.
�� Problem : how does this stop?Problem : how does this stop?
�� Many ways of doing this in PrologMany ways of doing this in Prolog
Programming Techniques : RecursionProgramming Techniques : Recursion
�� In procedural languagesIn procedural languages
��recursion is a procedure or subroutine calling itselfrecursion is a procedure or subroutine calling itself
�� In PrologIn Prolog
��recursion involves a rule calling itself as a recursion involves a rule calling itself as a subgoalsubgoal
�� Example:Example:
�� loop:- write(‘This is a loop’), loop.loop:- write(‘This is a loop’), loop.
�� Problem : how does this stop?Problem : how does this stop?
�� Many ways of doing this in PrologMany ways of doing this in Prolog
Programming Techniques : RecursionProgramming Techniques : Recursion
�� In procedural languagesIn procedural languages
��recursion is a procedure or subroutine calling itselfrecursion is a procedure or subroutine calling itself
�� In PrologIn Prolog
��recursion involves a rule calling itself as a recursion involves a rule calling itself as a subgoalsubgoal
�� Example:Example:
�� loop:- write(‘This is a loop’), loop.loop:- write(‘This is a loop’), loop.
�� Problem : how does this stop?Problem : how does this stop?
�� Many ways of doing this in PrologMany ways of doing this in Prolog
65
Programming Techniques : Recursion
�� In procedural languagesIn procedural languages
�� recursion is a procedure or subroutine calling itselfrecursion is a procedure or subroutine calling itself
�� In PrologIn Prolog
�� recursion involves a rule calling itself as a recursion involves a rule calling itself as a subgoalsubgoal
�� Example:Example:
�� loop:loop:-- write(write(‘‘This is a loopThis is a loop’’), loop.), loop.
�� Problem : how does this stop?Problem : how does this stop?
�� Many ways of doing this in PrologMany ways of doing this in Prolog
66
Conditional Recursion�� loop :loop :-- write(write(‘‘TYPE end TO ENDTYPE end TO END’’), read(Word),), read(Word),
�� ( Word = end; loop).( Word = end; loop).
�� This is equivalent to a REPEAT This is equivalent to a REPEAT …… UNTIL loop.UNTIL loop.
�� Usual way in Prolog is to place terminating Usual way in Prolog is to place terminating
condition before recursive loopcondition before recursive loop
��Called Head RecursionCalled Head Recursion
�� loop(end).loop(end).
�� loop(_):loop(_):-- write(write(‘‘Type end to END: Type end to END: ‘‘),),
�� read(Word), loop(Word).read(Word), loop(Word).
�� Equivalent to a WHILE Equivalent to a WHILE …… DO DO
�� terminating condition tested at start of the loopterminating condition tested at start of the loop
67
Prolog So Far�� L1 L1 –– Prolog basics and interpreterProlog basics and interpreter
�� L2 L2 –– Atoms, Numbers, Arithmetic, Clause TypesAtoms, Numbers, Arithmetic, Clause Types
�� L3 L3 –– Programs, Matching and ExecutionPrograms, Matching and Execution
�� L4 L4 –– ModellingModelling Finite State Automata, MatchingFinite State Automata, Matching
�� L5 L5 –– Unification, Numbers, Testing, ProceduralUnification, Numbers, Testing, Procedural
�� L6 L6 –– Recursion and ListsRecursion and Lists
68Counted Recursion*�� % Bad Style making use of % Bad Style making use of ““;;””
�� loop(Nloop(N):):-- write(write(‘‘The value of N is: The value of N is: ‘‘),),
�� write(N), write(N), nlnl, M is N, M is N--1, (M = 0; loop(M)).1, (M = 0; loop(M)).
�� % Preferred Style% Preferred Style
�� loop(0).loop(0).
�� loop(N):loop(N):--write(write(‘‘The value of N is: The value of N is: ‘‘),),
�� write(N), write(N), nlnl, M is N, M is N--1, 1, loop(Mloop(M).).
�� % With extra checks on value of N% With extra checks on value of N
�� loop(0).loop(0).
�� loop(N):loop(N):-- N > N > --1,1,
�� write(write(‘‘The value of N is: The value of N is: ‘‘),),
�� write(N), write(N), nlnl, ,
�� M is NM is N--1, loop(M).1, loop(M).
�� loop(Xloop(X):):-- write(write(‘‘LoopLoop Error Error –– Undefined Undefined ArgArg: : ‘‘), ),
�� write*X), write*X), nlnl..
69
Example of Recursion*�� factorial(1, 1).factorial(1, 1).
�� factorial(N, Factorial):factorial(N, Factorial):-- M is NM is N--1,1,
�� factorial(M, Factorial1),factorial(M, Factorial1),
�� Factorial is Factorial1*N.Factorial is Factorial1*N.
�� ??-- trace, factorial(3,F).trace, factorial(3,F).
�� factorial(3, _G352) , _L146 is 3factorial(3, _G352) , _L146 is 3--1 ?, 2 is 31 ?, 2 is 3--1 ?1 ?
�� factorial(2, _L147) ?, _L159 is 2factorial(2, _L147) ?, _L159 is 2--1 ?, 1 is 21 ?, 1 is 2--1 ?1 ?
�� factorial(1, _L160) ? factorial(1, 1) ?factorial(1, _L160) ? factorial(1, 1) ?
�� _L147 is 1*2 ?, 2 is 1*2 ?, factorial(2, 2) ?, _L147 is 1*2 ?, 2 is 1*2 ?, factorial(2, 2) ?,
�� _G352 is 2*3 ?, 6 is 2*3 ?, factorial(3, 6) ?,_G352 is 2*3 ?, 6 is 2*3 ?, factorial(3, 6) ?,
�� F = 6 F = 6
70�� power2(0, 1).power2(0, 1).
�� power2(N, Result):power2(N, Result):-- M is NM is N--1,1,
�� power2(M, power2(M, PartialResPartialRes),),
�� Result is Result is PartialResPartialRes*2.*2.
�� ??-- trace, power2(3,R).trace, power2(3,R).
�� power2(3, _G208) ? power2(3, _G208) ? _L133 is 3_L133 is 3--1 ? 2 is 31 ? 2 is 3--1 ?1 ?
�� power2(2, _L134) ?power2(2, _L134) ? _L146 is 2_L146 is 2--1 ? 1 is 21 ? 1 is 2--1 ?1 ?
�� power2(1, _L147) ? power2(1, _L147) ? _L159 is 1_L159 is 1--1 ? 0 is 11 ? 0 is 1--1 ?1 ?
�� power2(0, _L160) ?power2(0, _L160) ? power2(0, 1) ?power2(0, 1) ?
�� _L147 is 1*2 ?_L147 is 1*2 ? 2 is 1*2 ?2 is 1*2 ? power2(1, 2) ?power2(1, 2) ?
�� _L134 is 2*2 ?_L134 is 2*2 ? 4 is 2*2 ? 4 is 2*2 ? power2(2, 4) ?power2(2, 4) ?
�� _G208 is 4*2 ?_G208 is 4*2 ? 8 is 4*2 ?8 is 4*2 ? power2(3, 8) ?power2(3, 8) ?
�� R = 8 R = 8
71
Lists in Prolog*
�� List: an ordered sequence of elements List: an ordered sequence of elements (of any length)(of any length)
�� Elements of a list can be:Elements of a list can be:
��constants: integer, real, atomconstants: integer, real, atom
��variablesvariables
�� factsfacts
��other listsother lists
�� rulesrules
�� Elements of a list are enclosed in square bracketsElements of a list are enclosed in square brackets
�� [1, 2, 3][1, 2, 3] [a, b, c, d][a, b, c, d]
�� [peach, pear, plum][peach, pear, plum] [peach, 2, b, [3, 5, 7, 9]][peach, 2, b, [3, 5, 7, 9]]
�� [ ][ ] % the empty list% the empty list
72
Lists, characters and “strings”
�� note:note:
��??-- A = A = ““A StringA String””. .
�� A = [65, 32, 83, 116, 114, 105, 110, 103] A = [65, 32, 83, 116, 114, 105, 110, 103]
�� YesYes
�� name/2name/2
��a standard Prolog predicate that converts atoms into a standard Prolog predicate that converts atoms into
lists of ASCII characters and vicelists of ASCII characters and vice--versaversa
��Remember when using this that Atom is not an atomRemember when using this that Atom is not an atom
��But But ‘‘AtomAtom’’ isis
��As is atom, As is atom, aTomaTom, , aTOMaTOM etc.etc.
73
Lists, characters and “strings”
�� ??-- name(mrRustyname(mrRusty, A)., A).
�� A = [109, 114, 82, 117, 115, 116, 121] A = [109, 114, 82, 117, 115, 116, 121]
�� ??-- name(Atom, [82, 117, 115, 116, 121]).name(Atom, [82, 117, 115, 116, 121]).
�� Atom = 'Rusty' Atom = 'Rusty'
�� ??-- name('Atom', A).name('Atom', A).
�� A = [65, 116, 111, 109] A = [65, 116, 111, 109]
�� ??-- name(atom, A).name(atom, A).
�� A = [97, 116, 111, 109] A = [97, 116, 111, 109]
�� ??-- name(Atom,[]).name(Atom,[]).
�� Atom = ''Atom = ''
74
Handling Lists*�� Lists are manipulated by separating the Head from the TailLists are manipulated by separating the Head from the Tail
�� [Head | Tail ][Head | Tail ]
�� [1 | [2, 3, 4, 5] ][1 | [2, 3, 4, 5] ]
�� [a | [b, c, d] ][a | [b, c, d] ]
�� [pear | [peach, plum] ][pear | [peach, plum] ]
�� The [ H | T] notation can be used to build new listsThe [ H | T] notation can be used to build new lists
�� ??-- Z = [ a, b, c, d, e], Z = [H|T].Z = [ a, b, c, d, e], Z = [H|T].
�� Z = [a, b, c, d, e], H is a, T is [b, c, d, e]Z = [a, b, c, d, e], H is a, T is [b, c, d, e]
�� ??-- Z = [a, b, c, d], X is [1 | Z]Z = [a, b, c, d], X is [1 | Z]
�� X = [1, a, b, c, d ]X = [1, a, b, c, d ]
75
Handling Lists*
�� The [Head | Tail ] notation can be used to separate The [Head | Tail ] notation can be used to separate
the first few elements of a list from the Tailthe first few elements of a list from the Tail
�� [First, Second | Tail ][First, Second | Tail ]
�� [1, 2 | [3, 4, 5] ][1, 2 | [3, 4, 5] ]
�� [a, b | [c, d] ][a, b | [c, d] ]
�� [pear, peach | [plum] ][pear, peach | [plum] ]
�� [ a, b, c | [] ][ a, b, c | [] ]
��??-- [ F, S | Tail ] = [ a, b, c, d, e].[ F, S | Tail ] = [ a, b, c, d, e].
�� F = aF = a
�� S = bS = b
�� Tail = [c, d, e]Tail = [c, d, e]
76
Accessing Elements of A List*
�� Lists are sequential structuresLists are sequential structures
��Access is via recursionAccess is via recursion
��Remove head, then head from tail, ... , until empty listRemove head, then head from tail, ... , until empty list
�� writelistwritelist([]).([]).
�� writelist([H|Tailwritelist([H|Tail]):]):-- write(H), write(H), nlnl, , writelist(Tailwritelist(Tail).).
�� ??-- trace, writelist([5, 4, 3]).trace, writelist([5, 4, 3]).
�� writelist([5, 4, 3]) ? write(5) ? writelist([5, 4, 3]) ? write(5) ? nlnl ? writelist([4, 3]) ? ? writelist([4, 3]) ?
�� writelist([4, 3])?writelist([4, 3])? write(4) ?write(4) ? nlnl ? ? writelist([3]) ? writelist([3]) ?
�� writelist([3])?writelist([3])? write(3) ? write(3) ? nlnl ? ? writelistwritelist([]) ? ([]) ?
�� writelistwritelist([]) ?([]) ?
77
Building a List from Input*�� buildlist([H|Tailbuildlist([H|Tail]):]):-- read(H), not (H = end),read(H), not (H = end),
�� buildlist(Tailbuildlist(Tail).).
�� buildlistbuildlist([]).([]).
�� ??-- buildlist(Alistbuildlist(Alist).).
�� : : zebadeezebadee..
�� : : dylandylan..
�� : : florenceflorence..
�� : : brianbrian..
�� : end.: end.
�� AlistAlist = [= [zebadeezebadee, , dylandylan, , florenceflorence, , brianbrian] ]
�� YesYes
78
Tracing Buildlist�� ??-- trace, trace, buildlist(Alistbuildlist(Alist).).
�� buildlist(_G237) ? read(a) ? not a=end ? buildlist(_G237) ? read(a) ? not a=end ?
�� buildlist(_G328) ? read(b) ? not b=end ? buildlist(_G328) ? read(b) ? not b=end ?
�� buildlist(_G334) ? read(end) ? not end=end ? buildlist(_G334) ? read(end) ? not end=end ?
�� end=end ? end=end ?
�� Fail: ( 11) not end=end ? Fail: ( 11) not end=end ?
�� Redo: buildlist(_G334) ? Redo: buildlist(_G334) ? buildlistbuildlist([]) ? ([]) ?
�� AlistAlist = [a, b] = [a, b]
�� YesYes
�� buildlistbuildlist works becauseworks because
��AlistAlist = [a, b, | []] unifies with = [a, b, | []] unifies with AlistAlist = [a, b]= [a, b]
79
Testing for a list - is_list/1 (built-in)
�� is_list([]).is_list([]).
�� is_list([ _ | Tail ]):is_list([ _ | Tail ]):-- is_list(Tail).is_list(Tail).
��??-- is_list(a).is_list(a). NoNo
��??-- is_list("a").is_list("a"). YesYes
��??-- is_list([a, b, c, d]).is_list([a, b, c, d]). YesYes
��??-- is_list([a | b, c, d]).is_list([a | b, c, d]). NO!NO!
��??-- is_list([a | [b, c, d]]).is_list([a | [b, c, d]]). YesYes
��??-- is_list([ is_list([ fredfred | | fredafreda ]).]). YesYes
��??-- is_list([atom|List]).is_list([atom|List]). NO!NO!
80
Useful List Predicates*
�� Reversing a list Reversing a list -- reverse/2 (builtreverse/2 (built--in)in)
��List elements transferred from front of first list to headList elements transferred from front of first list to head
�� of second listof second list
��When first list is empty, the second list is the final listWhen first list is empty, the second list is the final list
��reverse(L1, L2):reverse(L1, L2):-- rev(L1, [], L2).rev(L1, [], L2).
��rev([], L, L).rev([], L, L).
��rev([H | T], L2, L3):rev([H | T], L2, L3):-- rev(T, [H | L2], L3).rev(T, [H | L2], L3).
�� ??-- reverse([1, 2, 3, 4], L).reverse([1, 2, 3, 4], L).
�� L = [4, 3, 2, 1]L = [4, 3, 2, 1]
81
Useful List Predicates*
�� Testing for list membership Testing for list membership -- member/2 (builtmember/2 (built--in)in)
��Predicate succeeds when element matches to head of Predicate succeeds when element matches to head of
listlist
��Otherwise recursively calls itself with the tail of the Otherwise recursively calls itself with the tail of the
list until the list is emptylist until the list is empty
��member(X, [X | _member(X, [X | _varvar ]).]).
��member(X, [ _member(X, [ _varvar | T]):| T]):-- member(X, T).member(X, T).
�� ??-- member(heron, [bat, heron, owl]).member(heron, [bat, heron, owl]).
�� YesYes
82
Useful List Predicates*
�� Appending to lists Appending to lists -- append/3 (builtappend/3 (built--in)in)
��Predicate appends list L2 onto end of list L1 to give L3Predicate appends list L2 onto end of list L1 to give L3
��append( [ ] , L, L).append( [ ] , L, L).
��append( [H | L1], L2, [ H | L3]):append( [H | L1], L2, [ H | L3]):--
�� append(L1, L2, L3).append(L1, L2, L3).
�� ??-- append([1, 2], [3, 4], L).append([1, 2], [3, 4], L).
�� L = [1, 2, 3, 4]L = [1, 2, 3, 4]
83
Useful List Predicates
�� Appending to lists Appending to lists -- reverse/2 (builtreverse/2 (built--in)in)
��Predicate reverses list order from L1 to L2 or inversePredicate reverses list order from L1 to L2 or inverse
% reverse/2 makes use of reverse/3% reverse/2 makes use of reverse/3
reverse( [ ] , [ ]).reverse( [ ] , [ ]).
reverse( [H | L], Reverse):reverse( [H | L], Reverse):--
reverse(Lreverse(L, [H], Reverse)., [H], Reverse).
reverse( [ ], Reverse, Reverse).reverse( [ ], Reverse, Reverse).
reverse([Hreverse([H | L], L2, Reverse):| L], L2, Reverse):--
reverse(Lreverse(L, [H | L2], Reverse)., [H | L2], Reverse).
84
Useful List Predicates*
�� Delete item from lists Delete item from lists -- delete/3 (builtdelete/3 (built--in)in)��Takes list and deletes all instances of item to build second lisTakes list and deletes all instances of item to build second listt
��delete( [ ] , _delete( [ ] , _varvar , [ ])., [ ]).
��delete( [ X | L1] , X, L2):delete( [ X | L1] , X, L2):-- delete(L1, X, L2).delete(L1, X, L2).
��delete( [ H | L1] , X, [ H | L2]):delete( [ H | L1] , X, [ H | L2]):-- delete(L1, X, L2).delete(L1, X, L2).
�� ??-- delete([a, b, c], a, L).delete([a, b, c], a, L).
�� L = [b, c] L = [b, c]
�� ??-- delete([a, b, c], [a], L).delete([a, b, c], [a], L).
�� L = [a, b, c] L = [a, b, c]
�� ??-- delete([a, b, c, a], a, L).delete([a, b, c, a], a, L).
�� L = [b, c] L = [b, c]
85
Deleting the elements of a list
�� A different delete predicateA different delete predicate
��delete1(Item, [Item|Tail], Tail).delete1(Item, [Item|Tail], Tail).
��delete1(Item, [H | Tail], [H | List]):delete1(Item, [H | Tail], [H | List]):--
�� delete1(Item, Tail, List).delete1(Item, Tail, List).
��??-- delete1(a, [a, b, c], L).delete1(a, [a, b, c], L).
�� L = [b, c] L = [b, c]
��??-- delete1(I, [a, b, c], L).delete1(I, [a, b, c], L).
�� I = aI = a L = [b, c] ;L = [b, c] ;
�� I = bI = b L = [a, c] ;L = [a, c] ;
�� I = cI = c L = [a, b] ; L = [a, b] ;
�� NoNo
86
Permuting the elements of a list
permutation([ ], [ ]).permutation([ ], [ ]).
permutation(List, [ H | Tail ]):permutation(List, [ H | Tail ]):--
delete1(H, List, Rest),delete1(H, List, Rest),
permutation( Rest, Tail ).permutation( Rest, Tail ).
��??-- permutation([a, b, c], L).permutation([a, b, c], L).
�� L = [a, b, c] ;L = [a, b, c] ;
�� L = [a, c, b] ;L = [a, c, b] ;
�� L = [b, a, c] ;L = [b, a, c] ;
�� L = [b, c, a] ;L = [b, c, a] ;
�� L = [c, a, b] ;L = [c, a, b] ;
�� L = [c, b, a] ;L = [c, b, a] ;
87��??-- trace, permutation([a, b, c], L).trace, permutation([a, b, c], L).
��delete1(a, [a, b, c], [b, c]) ? permutation([b, c], [b, c]) ?delete1(a, [a, b, c], [b, c]) ? permutation([b, c], [b, c]) ?
��L = [a, b, c] ;L = [a, b, c] ;
��delete1(c, [b, c], [b]) ? creep permutation([b], [b]) ?delete1(c, [b, c], [b]) ? creep permutation([b], [b]) ?
��permutation([b, c], [c, b]) ?permutation([b, c], [c, b]) ?
��permutation([a, b, c], [a, c, b]) ?permutation([a, b, c], [a, c, b]) ?
��L = [a, c, b] ;L = [a, c, b] ;
��delete1(b, [a, b, c], [a, c]) ? permutation([a, c], [a, c]) ? delete1(b, [a, b, c], [a, c]) ? permutation([a, c], [a, c]) ?
��L = [b, a, c] ;L = [b, a, c] ;
��delete1(c, [a, c], [a]) ? permutation([a], [a]) ?delete1(c, [a, c], [a]) ? permutation([a], [a]) ?
��permutation([a, c], [c, a]) ? permutation([a, c], [c, a]) ?
��permutation([a, b, c], [b, c, a]) ? permutation([a, b, c], [b, c, a]) ?
��L = [b, c, a] L = [b, c, a]
88
Built-In List Predicates*�� =../2=../2 ``Univ.'' Term to list conversion``Univ.'' Term to list conversion
�� atom_chars/2atom_chars/2 Convert between atom and list of ASCII valuesConvert between atom and list of ASCII values
�� name/2name/2 Convert between atom and list of ASCII charactersConvert between atom and list of ASCII characters
�� concat_atom/2concat_atom/2 Append a list of atomsAppend a list of atoms
�� concat_atom/3concat_atom/3 Append a list of atoms with separatorAppend a list of atoms with separator
�� string_to_list/2string_to_list/2 Conversion between string and list of ASCIIConversion between string and list of ASCII
�� is_list/1is_list/1 Type check for a listType check for a list
�� proper_list/1proper_list/1 Type check for listType check for list
�� append/3append/3 Concatenate listsConcatenate lists
�� member/2member/2 Element is member of a listElement is member of a list
�� delete/3delete/3 Delete all matching members from a listDelete all matching members from a list
�� select/3select/3 Select element of a listSelect element of a list
89
More Built-in List Predicates*�� nth0/3nth0/3 NN--thth element of a list (0element of a list (0--based)based)
�� nth1/3nth1/3 NN--thth element of a list (1element of a list (1--based)based)
�� last/2 last/2 Last element of a listLast element of a list
�� reverse/2reverse/2 Inverse the order of the elements in a listInverse the order of the elements in a list
�� flatten/2flatten/2 Transform nested list into flat listTransform nested list into flat list
�� length/2length/2 Length of a listLength of a list
�� merge/3merge/3 Merge two sorted listsMerge two sorted lists
�� list_to_set/2list_to_set/2 Remove duplicatesRemove duplicates
�� sort/2sort/2 Sort elements in a listSort elements in a list
�� checklist/2checklist/2 Invoke goal on all members of a listInvoke goal on all members of a list
�� maplist/3maplist/3 Transform all elements of a listTransform all elements of a list
�� sublist/3sublist/3 Determine elements that meet conditionDetermine elements that meet condition
90
Asserting Predicates
�� assert/1 assert/1 -- assert(?Term)assert(?Term)
��adds term to predicate databaseadds term to predicate database
��??-- listing(fish).listing(fish).
�� fish(tuna, big).fish(tuna, big).
�� fish(shark, big).fish(shark, big).
��??-- assert( fish(guppy, small) ).assert( fish(guppy, small) ).
��??-- listing(fish).listing(fish).
�� fish(tuna, big).fish(tuna, big).
�� fish(shark, big).fish(shark, big).
�� fish(guppy, small).fish(guppy, small).
��Adds asserted term to end of database of predicatesAdds asserted term to end of database of predicates
91
Asserting Predicates
�� assert/1 assert/1 -- will duplicate term in predicate databasewill duplicate term in predicate database
��??-- listing(fish).listing(fish).
�� fish(tuna, big).fish(tuna, big).
�� fish(shark, big).fish(shark, big).
��??-- assert( fish(tuna, big) ).assert( fish(tuna, big) ).
��??-- listing(fish).listing(fish).
�� fish(tuna, big).fish(tuna, big).
�� fish(shark, big).fish(shark, big).
�� fish(tuna, big).fish(tuna, big).
��Adds asserted term to end of database of predicatesAdds asserted term to end of database of predicates
92
Asserting Predicates
�� assert/1 assert/1 -- can assert rules toocan assert rules too
��??-- listing(big).listing(big).
�� [WARNING: No predicates for `big'][WARNING: No predicates for `big']
�� NoNo
��??-- assert( big(X):assert( big(X):-- fish(X, big) ).fish(X, big) ).
�� X = _G279 X = _G279
��??-- listing(big).listing(big).
�� big(A) :big(A) :-- fish(A, big).fish(A, big).
��??-- big(F).big(F).
�� F = tuna ;F = tuna ;
�� F = sharkF = shark
93
Static and Dynamic Clauses
�� Cannot assert and retract Cannot assert and retract functor/arityfunctor/arity
�� IF static clauseIF static clause
fact( apple, fruit, edible).fact( apple, fruit, edible).
fact( jackfruit, fruit, disgusting ).fact( jackfruit, fruit, disgusting ).
�� fact/3 cannot be asserted or retractedfact/3 cannot be asserted or retracted
�� Have to make dynamic using HEADHave to make dynamic using HEAD--Less RuleLess Rule
::-- dynamic( fact/3).dynamic( fact/3).
�� Then the above codeThen the above code
�� Can now retract or assert fact/3Can now retract or assert fact/3
94
Asserting Predicates - Variations��??-- apropos(assert).apropos(assert).
�� assert/1assert/1 Add a clause to the databaseAdd a clause to the database
�� asserta/1asserta/1 Add a clause to the database (first)Add a clause to the database (first)
�� assertz/1assertz/1 Add a clause to the database (last)Add a clause to the database (last)
�� ??-- listing(fish).listing(fish).
�� fish(guppy, small).fish(guppy, small).
�� fish(tuna, big).fish(tuna, big).
�� ??-- asserta(fish(sharkasserta(fish(shark, big))., big)).
�� ??-- listing(fish).listing(fish).
�� fish(shark, big).fish(shark, big).
�� fish(guppy, small).fish(guppy, small).
�� fish(tuna, big).fish(tuna, big).
95
Retracting Predicates
�� retract/1 retract/1 -- retract(?Term)retract(?Term)
��deletes term to predicate databasedeletes term to predicate database
��??-- listing(fish).listing(fish).
�� fish(tuna, big).fish(tuna, big).
�� fish(shark, big).fish(shark, big).
��??-- retract( fish(shark, big) ).retract( fish(shark, big) ).
��??-- listing(fish).listing(fish).
�� fish(tuna, big).fish(tuna, big).
��??-- retract( fish(tuna, _) ).retract( fish(tuna, _) ).
��??-- listing(fish).listing(fish).
�� YesYes
96
Retracting Predicates
�� Can give different levels of specificityCan give different levels of specificity
��??-- listing(fish).listing(fish).
�� fish(tuna, big).fish(tuna, big).
�� fish(shark, big).fish(shark, big).
�� fish(marlin, big).fish(marlin, big).
��??-- retract( fish(shark, _) ).retract( fish(shark, _) ).
�� retracts first instance matching to fish(shark, _)retracts first instance matching to fish(shark, _)
��??-- retract( fish( _, _) ).retract( fish( _, _) ).
�� retracts first instance matching to fish( _, _)retracts first instance matching to fish( _, _)
��??-- listing(fish).listing(fish).
�� fish(marlin, big).fish(marlin, big).
97
Retracting Predicates
�� Can use retract to delete rules tooCan use retract to delete rules too
�� retract( ( big(X):retract( ( big(X):-- fish(X, big) ) ).fish(X, big) ) ).
�� X = _G291 X = _G291
��??-- listing(big).listing(big).
�� YesYes
�� Retractall/1 Retractall/1 -- remove all instances matching termremove all instances matching term
��??-- retractall(fishretractall(fish(_,_)).(_,_)).
��??-- listing(fish).listing(fish).
�� YesYes
98
Does a clause exist?
�� clause/2clause/2
�� clause(?Head, ?Body)clause(?Head, ?Body)
��Succeeds when Head can be unified with a clause head Succeeds when Head can be unified with a clause head
and Body with the corresponding clause body. and Body with the corresponding clause body.
��Gives alternative clauses on backtracking.Gives alternative clauses on backtracking.
��For facts Body is unified with the atom true. For facts Body is unified with the atom true.
��Normally clause/2 is used to find clause definitions for Normally clause/2 is used to find clause definitions for
a predicate, but it can also be used to find clause heads a predicate, but it can also be used to find clause heads
for some body template.for some body template.
99
Does a clause exist?��??-- listing.listing.
�� big(X):big(X):-- fish(X, big) .fish(X, big) .
�� fish(tuna, big).fish(tuna, big).
�� fish(marlin, big).fish(marlin, big).
��??-- clause(fish(F, S), Body).clause(fish(F, S), Body).
�� F = tunaF = tuna
�� S = bigS = big
�� Body = true ;Body = true ;
�� F = marlinF = marlin
�� S = bigS = big
�� Body = true ;Body = true ;
100
Does a clause exist?��??-- listing.listing.
�� big(X):big(X):-- fish(X, big) .fish(X, big) .
�� fish(tuna, big).fish(tuna, big).
�� fish(marlin, big).fish(marlin, big).
��What Rules Exist with given BodyWhat Rules Exist with given Body
��??-- clause(Head, fish(F,S)).clause(Head, fish(F,S)).
�� Head = big(_G237)Head = big(_G237)
�� F = _G237F = _G237
�� S = big ;S = big ;
�� NoNo
101
Combining clause and retract��??-- listing.listing.
�� big(X):big(X):-- fish(X, big) .fish(X, big) .
�� fish(tuna, big).fish(tuna, big).
�� fish(marlin, big).fish(marlin, big).
�� If rule with fish/2 as body exists retract itIf rule with fish/2 as body exists retract it
��??-- clause(Head, fish(F,S)), retract(Head:clause(Head, fish(F,S)), retract(Head:-- fish(F, S)).fish(F, S)).
�� Head = big(_G237)Head = big(_G237)
�� F = _G237F = _G237
�� S = big ;S = big ;
�� NoNo
102
Finding all occurrences of a predicate
�� findall/3 findall/3 -- built in predicatebuilt in predicate
�� findall(+Varfindall(+Var, +Goal, , +Goal, --Bag)Bag)
��Creates a list of the instantiations Creates a list of the instantiations VarVar gets gets
successively on backtracking over Goal and unifies the successively on backtracking over Goal and unifies the
result with Bag. Succeeds with an empty list if Goal result with Bag. Succeeds with an empty list if Goal
has no solutions. has no solutions.
��Also see:Also see: help( help( setofsetof ), help( ), help( bagofbagof ))
�� fish(shark, big). fish(guppy, small). fish(tuna, big).fish(shark, big). fish(guppy, small). fish(tuna, big).
��??-- findall(Fishfindall(Fish, fish(Fish, _), Fishes)., fish(Fish, _), Fishes).
�� Fish = _G315Fish = _G315
�� Fishes = [shark, guppy, tuna]Fishes = [shark, guppy, tuna]
103
More on Findall��??-- assert( fish(shark, big) ).assert( fish(shark, big) ).
��??-- assert( fish(tuna, big) ).assert( fish(tuna, big) ).
��??-- assert( fish(guppy, small) ).assert( fish(guppy, small) ).
��??-- findall(Fishfindall(Fish, fish(Fish, big), Fishes)., fish(Fish, big), Fishes).
�� Fish = _G327Fish = _G327
�� Fishes = [shark, tuna]Fishes = [shark, tuna]
��Now add further factNow add further fact
��??-- assert( fish(shark, big) ).assert( fish(shark, big) ).
��??-- findall(Fishfindall(Fish, fish(Fish, big), Fishes)., fish(Fish, big), Fishes).
�� Fish = _G327Fish = _G327
�� Fishes = [shark, tuna, shark]Fishes = [shark, tuna, shark]
104
Compound Terms - Findall
�� CompundCompund terms can be used to associate itemsterms can be used to associate items
��??-- (A:B) = (atom1:atom2).(A:B) = (atom1:atom2).
�� A = atom1A = atom1
�� B = atom2 B = atom2
�� Can be used to pull items together in listsCan be used to pull items together in lists
�� Multiple joining characters permittedMultiple joining characters permitted
��atom1:atom2, atom1atom1:atom2, atom1--atom2, at1+at2, at1/at2 etcatom2, at1+at2, at1/at2 etc
�� Compare: question of programming preferenceCompare: question of programming preference
�� [ [[ [bertbert, , frenchfrench, singer], [, singer], [jakejake, , dutchdutch, , djdj] ]] ]
�� [ [ bertbert--frenchfrench--singersinger, , jakejake--dutchdutch--djdj]]
105
Compound Terms via Findall�� fish(shark, big)fish(shark, big)
�� fish(tuna, big) fish(tuna, big)
�� fish(guppy, small)fish(guppy, small)
��??-- findall(Fishfindall(Fish--Size, fish(Fish, Size), Size, fish(Fish, Size), AListAList).).
�� Fish = _G327Fish = _G327
�� Size = _G329Size = _G329
�� AListAList = [shark= [shark--big, tunabig, tuna--big, guppybig, guppy--small]small]
��??-- findall([Afindall([A, B], fish(A, B), As)., B], fish(A, B), As).
�� A = _G157A = _G157
�� B = _G160B = _G160
�� As = [[shark, big], [guppy, small], [tuna, big]] As = [[shark, big], [guppy, small], [tuna, big]]
106
Using a FSM to Control a simple agent
�� logical structurelogical structure
Senses
Input FSM
Actions
Output
State
107
% FSM Controller Agent% FSM Controller Agent
% agent/5 % agent/5 -- agent(Name, X, Y, State, Direction).agent(Name, X, Y, State, Direction).
% object/3 % object/3 -- object(Name, X, Y).object(Name, X, Y).
% define thing over agent/5 and object/3% define thing over agent/5 and object/3
thing(X):thing(X):-- agent(X, _v2, _v3, _v4, _v5).agent(X, _v2, _v3, _v4, _v5).
thing(X):thing(X):-- object(X, _v2, _v3).object(X, _v2, _v3).
% define sense/2 over all things other than agent% define sense/2 over all things other than agent
senses(Agent, Things):senses(Agent, Things):--
agent(Agent, _v2, _v3, _v4, _v5),agent(Agent, _v2, _v3, _v4, _v5),
findall(Xfindall(X, (thing(X), not(X==Agent)), Things)., (thing(X), not(X==Agent)), Things).
Prolog for Senses for FSM-Agent
108input(_Agent, [], input(_Agent, [], spacefreespacefree):):-- !.!.
input(Agent, [Thing | _rest], input(Agent, [Thing | _rest], spaceblockspaceblock):):--
spaceblock(Agentspaceblock(Agent, Thing), !., Thing), !.
input(Agent, [_head|Rest], Input):input(Agent, [_head|Rest], Input):--
input(Agent, Rest, Input).input(Agent, Rest, Input).
spaceblock(Agentspaceblock(Agent, Thing):, Thing):--
agent(Agent,Xagentagent(Agent,Xagent, , Yagent,_stateYagent,_state, Direction),, Direction),
object(Thing, object(Thing, XobjectXobject, , YobjectYobject),),
block(Xagentblock(Xagent, , YagentYagent, Direction, , Direction, XobjectXobject, , YobjectYobject).).
spaceblock(Agentspaceblock(Agent, Thing):, Thing):--
agent(Agent,Xagentagent(Agent,Xagent, , Yagent,_stateYagent,_state, Direction),, Direction),
agent(Thing, agent(Thing, XobjectXobject, , YobjectYobject, _state2, _direction),, _state2, _direction),
block(Xagentblock(Xagent, , YagentYagent, Direction, , Direction, XobjectXobject, , YobjectYobject).).
109
% block/5% block/5
% % block(Xagentblock(Xagent, , YagentYagent, Direction, , Direction, XobjectXobject, , YobjectYobject). ).
% Only need to define % Only need to define spaceblockspaceblock casescases
% Top left is origin in this world% Top left is origin in this world
block(X, Y1, up, X, Y2):block(X, Y1, up, X, Y2):-- Y2 is Y1Y2 is Y1--1, !.1, !.
block(X, Y1, down, X, Y2):block(X, Y1, down, X, Y2):-- Y2 is Y1+1, !.Y2 is Y1+1, !.
block(X1, Y, left, X2, Y):block(X1, Y, left, X2, Y):-- X2 is X1X2 is X1--1, !.1, !.
block(X1, Y, right, X2, Y):block(X1, Y, right, X2, Y):-- X2 is X1X2 is X1--1, !.1, !.
When is a thing a block?
110
% actions/5% actions/5
% actions(Direction, Output, X,Y, NX, % actions(Direction, Output, X,Y, NX, NY,NewDirectionNY,NewDirection),),
actions(up, ahead, X, Y, X, NY, up):actions(up, ahead, X, Y, X, NY, up):-- NY is YNY is Y--1.1.
actions(right, ahead, X, Y, NX, Y, right):actions(right, ahead, X, Y, NX, Y, right):-- NX is X+1. NX is X+1.
actions(down, ahead, X, Y, X, NY, down):actions(down, ahead, X, Y, X, NY, down):-- NY is Y+1. NY is Y+1.
actions(left, ahead, X, Y, NX, Y, left):actions(left, ahead, X, Y, NX, Y, left):-- NX is XNX is X--1. 1.
actions(up, actions(up, turnleftturnleft, X, Y, X, Y, left):, X, Y, X, Y, left):-- !.!.
actions(right, actions(right, turnleftturnleft, X, Y, X, Y, up):, X, Y, X, Y, up):-- !. !.
actions(down, actions(down, turnleftturnleft, X, Y, X, Y, right):, X, Y, X, Y, right):-- !. !.
actions(left, actions(left, turnleftturnleft, X, Y, X, Y, down):, X, Y, X, Y, down):-- !. !.
actions(Direction, nothing, X, Y, X, Y, Direction):actions(Direction, nothing, X, Y, X, Y, Direction):-- !.!.
Mapping Output to Actions
111
% run_agent/1% run_agent/1
run_agent(Agent):run_agent(Agent):--
agent(Agent, X, Y, State, Direction),agent(Agent, X, Y, State, Direction),
senses(Agent, Things),senses(Agent, Things),
input(Agent, Things, Input),input(Agent, Things, Input),
fsm(Inputfsm(Input, State, , State, NewStateNewState, Output),, Output),
actions(Direction, Output, X,Y, NX, actions(Direction, Output, X,Y, NX, NY,NewDirectionNY,NewDirection),),
retract( agent(Agent, X, Y, State, Direction) ),retract( agent(Agent, X, Y, State, Direction) ),
assert( agent(Agent, assert( agent(Agent, NewXNewX, , NewYNewY,,
NewStateNewState, , NewDirectionNewDirection)).)).
How is an agent run?
112
Full FSM-Agent Execution
FSM1.PL compiled 0.00 sec, 8,128 bytesFSM1.PL compiled 0.00 sec, 8,128 bytes
??-- assert(agent(a1, 10,19, assert(agent(a1, 10,19, aksfaksf, up))., up)).
??-- assert(agent(a2,10,20,aksf,up)).assert(agent(a2,10,20,aksf,up)).
??-- run_agent(a2), listing(agent).run_agent(a2), listing(agent).
agent(a2, 10, 20, agent(a2, 10, 20, aksbaksb, up)., up).
??-- run_agent(a2), listing(agent).run_agent(a2), listing(agent).
agent(a2, 10, 20, agent(a2, 10, 20, aksbaksb, up)., up).
??-- run_agent(a2), listing(agent).run_agent(a2), listing(agent).
agent(a2, 9, 20, agent(a2, 9, 20, aksfaksf, left)., left).
113
Compound Terms
�� Can use simple terms as arguments to predicatesCan use simple terms as arguments to predicates
��??-- assert(predicate(arg1, arg2, 8)).assert(predicate(arg1, arg2, 8)).
��??-- predicate(A,B,C), atom(A), atom(B), integer(C).predicate(A,B,C), atom(A), atom(B), integer(C).
�� YesYes
��??-- predicate(A,B,C), atom(A), atom(B), atom(C).predicate(A,B,C), atom(A), atom(B), atom(C).
�� NoNo
�� Can use simple terms as list elementsCan use simple terms as list elements
��??-- assert(predicate([a, b, c, d])).assert(predicate([a, b, c, d])).
��??-- predicate([H|R]), atom(H).predicate([H|R]), atom(H).
�� YesYes
114
Compound Terms As Associations�� However in some situations want to associateHowever in some situations want to associate
�� For example, sense For example, sense -- associate distance and objectassociate distance and object
��assert(sense(agent1, [agent2, object1], [25, 50])).assert(sense(agent1, [agent2, object1], [25, 50])).
�� is one way but need to manipulate both listsis one way but need to manipulate both lists
��output(_agoutput(_ag, [ ], [ ]). , [ ], [ ]).
��output(Agent, [H1|R1], [H2|R2]):output(Agent, [H1|R1], [H2|R2]):--
�� write(write(‘‘Distance from Distance from ‘‘), write(Agent), write(), write(Agent), write(‘‘ to to ‘‘),),
�� write(H1), write(write(H1), write(‘‘ is is ‘‘), write(H2), ), write(H2), nlnl,,
�� output(Agent, R1, R2).output(Agent, R1, R2).
�� ??-- sense(A,B,C), output(A,B,C).sense(A,B,C), output(A,B,C).
��Distance from agent1 to agent2 is 25Distance from agent1 to agent2 is 25
��Distance from agent1 to object1 is 50Distance from agent1 to object1 is 50
115
Alternative is to use compound terms
�� Advantage is sort only one listAdvantage is sort only one list
��assert(sense(agent1, [(agent2, 15), (object1,5)])).assert(sense(agent1, [(agent2, 15), (object1,5)])).
��But need to manipulate compound termBut need to manipulate compound term
��output(_agoutput(_ag, [ ]). , [ ]).
��output(Agent, [(H1,H2)|R]):output(Agent, [(H1,H2)|R]):--
�� write(write(‘‘Distance from Distance from ‘‘), write(Agent), write(), write(Agent), write(‘‘ to to ‘‘),),
�� write(H1), write(write(H1), write(‘‘ is is ‘‘), write(H2), ), write(H2), nlnl,,
�� output(Agent, R).output(Agent, R).
�� ??-- sense(A,B), output(A,B).sense(A,B), output(A,B).
��Distance from agent1 to agent2 is 15Distance from agent1 to agent2 is 15
��Distance from agent1 to object1 is 5Distance from agent1 to object1 is 5
��See file: See file: compound.plcompound.pl
116
Alternative: Lists as compound terms
�� Syntax of Compound terms up to userSyntax of Compound terms up to user
��assert(sense(agent1, [[agent2, 15], [object1,5]])).assert(sense(agent1, [[agent2, 15], [object1,5]])).
��Need to manipulate nested list compound termNeed to manipulate nested list compound term
��output(_agoutput(_ag, [ ]). , [ ]).
��output(Agent, [[H1,H2]|R]):output(Agent, [[H1,H2]|R]):--
�� write(write(‘‘Distance from Distance from ‘‘), write(Agent), write(), write(Agent), write(‘‘ to to ‘‘),),
�� write(H1), write(write(H1), write(‘‘ is is ‘‘), write(H2), ), write(H2), nlnl,,
�� output(Agent, R).output(Agent, R).
�� ??-- sense(A,B), output(A,B).sense(A,B), output(A,B).
��Distance from agent1 to agent2 is 15Distance from agent1 to agent2 is 15
��Distance from agent1 to object1 is 5Distance from agent1 to object1 is 5
117
Alternative: Structure it yourself
�� Syntax of Compound terms up to userSyntax of Compound terms up to user
��assert(sense(agent1, [agent2assert(sense(agent1, [agent2--5, object15, object1--15])).15])).
��Need to manipulate this form of compound termNeed to manipulate this form of compound term
��output(_agoutput(_ag, [ ]). , [ ]).
��output(Agent, [H1output(Agent, [H1--H2|R]):H2|R]):--
�� write(write(‘‘Distance from Distance from ‘‘), write(Agent), write(), write(Agent), write(‘‘ to to ‘‘),),
�� write(H1), write(write(H1), write(‘‘ is is ‘‘), write(H2), ), write(H2), nlnl,,
�� output(Agent, R).output(Agent, R).
�� ??-- sense(A,B), output(A,B).sense(A,B), output(A,B).
��Distance from agent1 to agent2 is 5Distance from agent1 to agent2 is 5
��Distance from agent1 to object1 is 15Distance from agent1 to object1 is 15
�� Note some constructors NOT allowedNote some constructors NOT allowed
118
Programming Practice
�� Write a program to determine number of Write a program to determine number of
occurrences of given item in a listoccurrences of given item in a list
frequency(_, [ ], 0).frequency(_, [ ], 0).
frequency(Item, [ Item | Rest ], N):frequency(Item, [ Item | Rest ], N):--
frequency(Item, Rest, N1),frequency(Item, Rest, N1),
N is N1 +1.N is N1 +1.
frequency(Item, [ H | Rest ], N):frequency(Item, [ H | Rest ], N):--
not( Item = H ),not( Item = H ), % An optional line?% An optional line?
frequency(Item, Rest, N).frequency(Item, Rest, N).
��??-- frequency(A, [a, b, c, a], N).frequency(A, [a, b, c, a], N).
�� A = aA = a N = 2 N = 2
119
�� trace, frequency(b, [a, b, c, b], N).trace, frequency(b, [a, b, c, b], N).
��not b=a ?not b=a ? frequency(b, [b, c, b], _G329) ?frequency(b, [b, c, b], _G329) ?
�� frequency(b, [c, b], _L149) ?frequency(b, [c, b], _L149) ?
��not b=c ? frequency(b, [b], _L149) ?not b=c ? frequency(b, [b], _L149) ?
�� frequency(b, [], _L177) ?frequency(b, [], _L177) ? frequency(b, [], 0) ?frequency(b, [], 0) ?
��1 is 0+1 ?1 is 0+1 ? frequency(b, [b], 1) ?frequency(b, [b], 1) ?
�� frequency(b, [c, b], 1) ?frequency(b, [c, b], 1) ?
��2 is 1+1 ?2 is 1+1 ? frequency(b, [b, c, b], 2) ?frequency(b, [b, c, b], 2) ?
�� frequency(b, [a, b, c, b], 2) ?frequency(b, [a, b, c, b], 2) ?
�� N = 2;N = 2;
�� NoNo
Tracing Frequency
120Variation1 on Frequencyfrequency(_term, [ ], 0).frequency(_term, [ ], 0).
frequency(Item, [ Item | Rest ], N):frequency(Item, [ Item | Rest ], N):--
frequency(Item, Rest, N1),frequency(Item, Rest, N1),
N is N1 +1.N is N1 +1.
frequency(Item, [ _term | Rest ], N):frequency(Item, [ _term | Rest ], N):--
frequency(Item, Rest, N).frequency(Item, Rest, N).
��??-- frequency(a,[a, b, a, c], N).frequency(a,[a, b, a, c], N).
�� N = 2 ;N = 2 ;
�� N = 1 ;N = 1 ;
�� N = 1 ;N = 1 ;
�� N = 0 ;N = 0 ;
�� NoNo
121Variation 2 on Frequency with Cut (!)frequency(_term, [ ], 0).frequency(_term, [ ], 0).
frequency(Item, [ Item | Rest ], N):frequency(Item, [ Item | Rest ], N):--
!, frequency(Item, Rest, N1),!, frequency(Item, Rest, N1),
N is N1 +1.N is N1 +1.
frequency(Item, [ _term | Rest ], N):frequency(Item, [ _term | Rest ], N):--
frequency(Item, Rest, N).frequency(Item, Rest, N).
��??-- frequency(a,[a, b, a, c], N).frequency(a,[a, b, a, c], N).
�� N = 2 ;N = 2 ;
�� NoNo
��??-- frequency(A,[a, b, a, c], N).frequency(A,[a, b, a, c], N).
�� A = aA = a N = 2 ;N = 2 ;
�� NoNo
122
Controlling Backtracking - the Cut !�� The cut ! is an operator that halts backtrackingThe cut ! is an operator that halts backtracking
��The matching to the left cannot be undone for a goalThe matching to the left cannot be undone for a goal
??-- trace, frequency(a,[a, b, a, c], N).trace, frequency(a,[a, b, a, c], N).
N = 2 ;N = 2 ;
Redo: ( 12) frequency(a, [], _L162) ? creepRedo: ( 12) frequency(a, [], _L162) ? creep
Fail: ( 12) frequency(a, [], _L162) ? creepFail: ( 12) frequency(a, [], _L162) ? creep
Fail: ( 11) frequency(a, [c], _L162) ? creepFail: ( 11) frequency(a, [c], _L162) ? creep
Fail: ( 10) frequency(a, [a, c], _L135) ? creepFail: ( 10) frequency(a, [a, c], _L135) ? creep
Fail: ( 9) frequency(a, [b, a, c], _L135) ? creepFail: ( 9) frequency(a, [b, a, c], _L135) ? creep
Fail: ( 8) frequency(a, [a, b, a, c], _G323) ? creepFail: ( 8) frequency(a, [a, b, a, c], _G323) ? creep
NoNo
123
Goals and Cut�� Suppose rule Suppose rule pp with with subgoalssubgoals q, r, s, tq, r, s, t
��SubgoalSubgoal ss has has subgoalssubgoals a, b, c, da, b, c, d
p:p:-- q, r, s, t.q, r, s, t.
s:s:-- a, b, !, c, d.a, b, !, c, d.
��Suppose Suppose ss succeeds as far as succeeds as far as dd, which fails, which fails
��backtracking among backtracking among c, dc, d until they all failuntil they all fail
��unable to pass cut and because rule unable to pass cut and because rule ss has not failed as has not failed as
a whole yeta whole yet
��Prolog moves to Prolog moves to ss in the parent rule, then in the parent rule, then rr
�� if if rr succeeds a second time, execution moves forwardsucceeds a second time, execution moves forward
��and and ss is tried afresh (from the top of the database)is tried afresh (from the top of the database)
124
Repetition using the cut
�� Using Using repeat/0repeat/0 -- a standard Prolog predicatea standard Prolog predicate
�� Always succeed, provide an infinite number of choice Always succeed, provide an infinite number of choice
points.points.
input1:input1:-- read(X),read(X),
write(write(‘‘You typed: You typed: ‘‘), write(X), ), write(X), nlnl, X = end., X = end.
loop1:loop1:-- repeat, input1.repeat, input1.
input2:input2:-- read(X),read(X),
write('You typed: '), write(X), write('You typed: '), write(X), nlnl, !, X = end., !, X = end.
loop2:loop2:-- repeat, input2.repeat, input2.
�� loop2 (the cut) has the advantage of continuing with loop2 (the cut) has the advantage of continuing with
no stack problems no stack problems -- data is thrown away on lhs of cutdata is thrown away on lhs of cut
125
Running the two versions??-- input1.input1. ??-- input1. input1.
: hi.: hi. : end.: end.
You typed: hiYou typed: hi You typed: endYou typed: end
NoNo YesYes
??-- loop1.loop1. ??-- loop2.loop2.
: hi.: hi. :hi.:hi.
You typed: hiYou typed: hi You typed: hiYou typed: hi
: hi2.: hi2. :hi2.:hi2.
You typed: hi2You typed: hi2 You typed: hi2.You typed: hi2.
: end.: end. :end.:end.
You typed: endYou typed: end You typed: end.You typed: end.
YesYes YesYes
126
Mutually Exclusive Rules
�� If cuts are placed at the end of a clauseIf cuts are placed at the end of a clause
��Whether unit or nonWhether unit or non--unit, it succeeds at most just onceunit, it succeeds at most just once
�� Useful for one and only one match requiredUseful for one and only one match required
fish(marlin, big).fish(marlin, big).
fish(sailfish, big).fish(sailfish, big).
% same_rule/2 no cut% same_rule/2 no cut
same_rule(1, F):same_rule(1, F):-- fish(F, big).fish(F, big).
same_rule(2, F):same_rule(2, F):-- fish(F, big).fish(F, big).
% cut_rule % cut_rule -- same as above but with terminating cutsame as above but with terminating cut
cut_rule(1, F):cut_rule(1, F):-- fish(F, big), !.fish(F, big), !.
cut_rule(2, F):cut_rule(2, F):-- fish(F, big), !.fish(F, big), !.
127
So what happens?��??-- same_rule(X,Y).same_rule(X,Y).
��X = 1X = 1 Y = marlin ;Y = marlin ;
��X = 1X = 1 Y = sailfish ;Y = sailfish ;
��X = 2X = 2 Y = marlin ;Y = marlin ;
��X = 2X = 2 Y = sailfish ;Y = sailfish ;
��NoNo
��??-- cut_rule(X,Y).cut_rule(X,Y).
��X = 1X = 1 Y = marlin ;Y = marlin ;
��NoNo
128
Forcing new solutions & using cut
member1(X, [X|_]).member1(X, [X|_]).
member1(X, [ _term |T]):member1(X, [ _term |T]):-- member1(X, T).member1(X, T).
�� member1 will succeed for every occurrence of X member1 will succeed for every occurrence of X
in the listin the list
member2(X, [X| _term ]):member2(X, [X| _term ]):-- !.!.
member2(X, [ _term |T]):member2(X, [ _term |T]):-- member2(X, T).member2(X, T).
�� member2 will succeed just the once if X in list at member2 will succeed just the once if X in list at
least once or moreleast once or more
129
Run Time��member1 will succeed four times heremember1 will succeed four times here
??-- member1(a, [a, b, c, a, a, a, b]), write('hi'), member1(a, [a, b, c, a, a, a, b]), write('hi'), nlnl, fail., fail.
hihi
hihi
hihi
hihi
NoNo
��member2 will succeed just the oncemember2 will succeed just the once
??-- member2(a, [a, b, c, a, a, a, b]), write('hi'), member2(a, [a, b, c, a, a, a, b]), write('hi'), nlnl, fail., fail.
hihi
NoNo
130
The use of cut in negation�� Represent Represent ““Mary likes all animals but snakesMary likes all animals but snakes””
animal(snake).animal(snake).
animal(tiger).animal(tiger).
likes(marylikes(mary, snake):, snake):-- !, fail.!, fail.
likes(marylikes(mary, X):, X):-- animal(X).animal(X).
??-- likes(mary,tigerlikes(mary,tiger).).
YesYes
??-- likes(mary,snakelikes(mary,snake).).
NoNo
??-- likes(A,B).likes(A,B).
NoNo
131
The use of cut in negation - version2�� Represent Represent ““Mary likes all animals but snakesMary likes all animals but snakes””
animal(snake).animal(snake).
animal(tiger).animal(tiger).
likes(marylikes(mary, X):, X):-- animal(X), not(X=snake).animal(X), not(X=snake).
??-- likes(A,B).likes(A,B).
A = A = marymary
B = tiger ;B = tiger ;
NoNo
??-- likes(mary,snakelikes(mary,snake).).
NoNo
132
Negation as failure
�� Defining the relation different(X, Y)Defining the relation different(X, Y)
�� Different as in:Different as in:
��X and Y are not literally the sameX and Y are not literally the same
��X and Y do not matchX and Y do not match
�� the values of arithmetic expressions X and Y differthe values of arithmetic expressions X and Y differ
�� Take Second DefinitionTake Second Definition
different(X, X):different(X, X):-- !, fail.!, fail.
different(X, Y).different(X, Y).
??-- different(a, b).different(a, b). ??-- different(a, a).different(a, a).
YesYes No No
133
Negation as failure��??-- animal(X), animal(Y), different(X, Y).animal(X), animal(Y), different(X, Y).
X = snakeX = snake Y = tiger ;Y = tiger ;
X = tigerX = tiger Y = snake ;Y = snake ;
NoNo
�� Alternative definition for different/2Alternative definition for different/2
different(X, Y):different(X, Y):-- not( X = Y ).not( X = Y ).
134
Principles of Good Programming
�� CorrectnessCorrectness
��Above all a program should be correctAbove all a program should be correct
�� EfficiencyEfficiency
��Good programs do not needlessly waste computer time Good programs do not needlessly waste computer time
and memory spaceand memory space
�� Transparency (readability)Transparency (readability)
��Avoid tricks that obscure the meaning of a programAvoid tricks that obscure the meaning of a program
135
Principles of Good Programming
�� ModifiabilityModifiability
��Good programs should be easy to modify and extendGood programs should be easy to modify and extend
�� RobustnessRobustness
��Programs should not crash immediately the user enters Programs should not crash immediately the user enters
incorrect or unexpected dataincorrect or unexpected data
�� DocumentationDocumentation
��A minimal documentation program comments and A minimal documentation program comments and
headerheader
136
Guidelines for achieving above
�� THINKTHINK about the problem to be solved. about the problem to be solved.
��When the problem is understood and solution well When the problem is understood and solution well
thought through, the actual coding is faster and easierthought through, the actual coding is faster and easier
�� Use Use STEPWISE REFINEMENTSTEPWISE REFINEMENT. .
��From topFrom top--level to bottomlevel to bottom--level solution.level solution.
��Each refinement step should intellectually manageableEach refinement step should intellectually manageable
�� i.e. small and clear enoughi.e. small and clear enough
�� Programming is CREATIVE, especially for Programming is CREATIVE, especially for
beginners new to specific programming conceptsbeginners new to specific programming concepts
��With experience becomes less of an art and more of a With experience becomes less of an art and more of a
craft. Ideas from similar problems we already know of.craft. Ideas from similar problems we already know of.
137
Thinking about prolog programs
�� Ontological DelineationOntological Delineation
��How do we find ideas for reducing problems to more How do we find ideas for reducing problems to more
easier easier subproblemssubproblems??
��How do we find proper How do we find proper subproblemssubproblems??
�� Problem P solved by solving {PProblem P solved by solving {P11, P, P22, , ……PPii,... ,... PPnn}}
�� Aspects to considerAspects to consider
��RecursionRecursion
��GeneralisationGeneralisation
��StructuralisationStructuralisation
��PicturesPictures
138
Use of Recursion
�� Principle is to split the given problem into casesPrinciple is to split the given problem into cases
�� Two groupsTwo groups
��1. Trivial or 1. Trivial or boundaryboundary casescases
��2. General cases whose solution is constructed from 2. General cases whose solution is constructed from
solutions of simpler versions of the problemsolutions of simpler versions of the problem
�� Recursion applies so naturally to prologRecursion applies so naturally to prolog
��Basic representation (lists) have recursive structureBasic representation (lists) have recursive structure
��A list is either empty A list is either empty
�� boundaryboundary casecase
��Or has a head and a tail that is itself a listOr has a head and a tail that is itself a list
�� general casegeneral case
139
Consider intersection of sets problem
�� intersection( Set1, Set2, Result).intersection( Set1, Set2, Result).
�� This can be split into two cases:This can be split into two cases:
��Boundary case: Boundary case: Set1 = [ ] or Set2 = []Set1 = [ ] or Set2 = []
�� If If Set1 = [ ]Set1 = [ ] then then Result = [Result = [ ]], regardless of , regardless of Set2Set2..
��General Case: General Case: Set1 = [ Head | Tail ]Set1 = [ Head | Tail ]
��To transform a list of this form do:To transform a list of this form do:
��Transform head of the listTransform head of the list
•• If If HeadHead membermember of of Set2Set2 then then ResultResult →→ [ Head | Result ][ Head | Result ]
��Then recursively call with Then recursively call with TailTail
•• Tail Tail →→ [ [ NewHeadNewHead | | NewTailNewTail ]]
��Eventually problem reduces to Eventually problem reduces to Boundary CaseBoundary Case [ ][ ]
140
Testing your code: Set UNION
�� Set union Set union -- sets can be represented as listssets can be represented as lists
��{ a, b, c, d } { a, b, c, d } ∪∪∪∪∪∪∪∪ { c, d, e }{ c, d, e } ⇒⇒⇒⇒⇒⇒⇒⇒ { a, b, c, d, e }{ a, b, c, d, e }
% Base case for recursion% Base case for recursion
setunionsetunion( [ ], X, X).( [ ], X, X).
% % RecurseRecurse without Head if member of L1without Head if member of L1
setunionsetunion( [H | T ], L1, L2):( [H | T ], L1, L2):--
member(H, L1), member(H, L1),
setunion(Tsetunion(T, L1, L2)., L1, L2).
% Otherwise % Otherwise RecurseRecurse with Head with Head
setunionsetunion( [ H | T ], L1, [ H | L2 ] ):( [ H | T ], L1, [ H | L2 ] ):--
setunionsetunion( T, L1, L2).( T, L1, L2).
141
Test cases: Set UNION without not
setunion([],[a],Lsetunion([],[a],L).).
L = [a] ;L = [a] ;
NoNo
??-- setunion([a],[],Lsetunion([a],[],L).).
L = [a] L = [a]
YesYes
??-- setunion([a],[a],Lsetunion([a],[a],L).).
L = [a] ;L = [a] ;
L = [a, a] ;L = [a, a] ;
NoNo
Here is a
problem
142
So Use CUT - Set UNION with cut
setunionsetunion( [ ], X, X).( [ ], X, X).
% Add cut so cannot backtrack% Add cut so cannot backtrack
setunionsetunion( [H | T ], L1, L2):( [H | T ], L1, L2):--
member(H, L1),member(H, L1),
!, !,
setunion(Tsetunion(T, L1, L2)., L1, L2).
setunionsetunion( [ H | T ], L1, [ H | L2 ] ):( [ H | T ], L1, [ H | L2 ] ):--
setunionsetunion( T, L1, L2).( T, L1, L2).
��Goal only succeeds the onceGoal only succeeds the once
143
Testing setunion with The CUT??-- setunion([a],[],Lsetunion([a],[],L).).
L = [a] ;L = [a] ;
NoNo
??-- setunion([a],[a],Lsetunion([a],[a],L).).
L = [a] ;L = [a] ;
NoNo
??-- setunion([bsetunion([b, a],[a, b],L)., a],[a, b],L).
L = [a, b] ;L = [a, b] ;
NoNo
??-- setunion([bsetunion([b, a],[a, b, c, d],L)., a],[a, b, c, d],L).
L = [a, b, c, d] L = [a, b, c, d]
YesYes
144
Set UNION using not
setunionsetunion( [ ], X, X).( [ ], X, X).
setunionsetunion( [ H | T ], L1, [ H | L2 ] ):( [ H | T ], L1, [ H | L2 ] ):--
not(member(H, L1)),not(member(H, L1)),
setunionsetunion( T, L1, L2).( T, L1, L2).
setunionsetunion( [_H | T ], L1, L2):( [_H | T ], L1, L2):--
setunion(Tsetunion(T, L1, L2)., L1, L2).
��Goal succeeds just the onceGoal succeeds just the once
��??-- setunion([asetunion([a, b, c], [a, d, e], L)., b, c], [a, d, e], L).
L = [b, c, a, d, e] ;L = [b, c, a, d, e] ;
NoNo
145
Set Intersection using not
�� Set intersection Set intersection -- sets can be represented as listssets can be represented as lists
��{ a, b, c, d } { a, b, c, d } ∩∩∩∩∩∩∩∩ { c, d, e }{ c, d, e } ⇒⇒⇒⇒⇒⇒⇒⇒ { c, d }{ c, d }
intersect( [ ], X, [ ]).intersect( [ ], X, [ ]).
intersect( [H | T ], L1, [ H | L2 ] ):intersect( [H | T ], L1, [ H | L2 ] ):--
member(H, L1), delete(L1, H, L3),member(H, L1), delete(L1, H, L3),
intersect(T, L3, L2).intersect(T, L3, L2).
intersect( [ H | T ], L1, L2 ):intersect( [ H | T ], L1, L2 ):--
not(member(H, L1)), intersect( T, L1, L2).not(member(H, L1)), intersect( T, L1, L2).
��??-- intersect([a, b, c], [a, c, d, e], L).intersect([a, b, c], [a, c, d, e], L).
L = [a, c] ;L = [a, c] ;
NoNo
146
Set Difference using not
�� Set intersection Set intersection -- sets can be represented as listssets can be represented as lists
��{ a, b, c, d } { a, b, c, d } ⊗⊗⊗⊗⊗⊗⊗⊗ { c, d, e }{ c, d, e } ⇒⇒⇒⇒⇒⇒⇒⇒ { a, b, e }{ a, b, e }
difference( [ ], X, X).difference( [ ], X, X).
difference( [H | T ], L1, L2 ):difference( [H | T ], L1, L2 ):--
member(H, L1), delete(L1, H, L3),member(H, L1), delete(L1, H, L3),
difference(T, L3, L2).difference(T, L3, L2).
difference( [ H | T ], L1, [H | L2] ):difference( [ H | T ], L1, [H | L2] ):--
not member(H, L1), difference( T, L1, L2).not member(H, L1), difference( T, L1, L2).
��??-- difference([a, b, c], [a, c, d, e], L).difference([a, b, c], [a, c, d, e], L).
L = [b, d, e] ;L = [b, d, e] ;
NoNo
147
Generalisation
�� The idea is to The idea is to generalisegeneralise a problem such that its a problem such that its
solution can be formulated recursivelysolution can be formulated recursively
�� GeneralisationGeneralisation of a relation involves the of a relation involves the
introduction of one or more extra argumentsintroduction of one or more extra arguments
�� Paradoxically, for some problems, the Paradoxically, for some problems, the generalisedgeneralised
version of the problem is easier to solveversion of the problem is easier to solve
��See See BratkoBratko and the Eight Queens [pp 103]and the Eight Queens [pp 103]
�� Add constraints on general problem so it becomesAdd constraints on general problem so it becomes
�� The original problemThe original problem
148
Structuralisation
�� What are the objects and relations of the problemWhat are the objects and relations of the problem
�� Try drawing figures of the problem or aspects of it Try drawing figures of the problem or aspects of it
��These can map onto semantic networksThese can map onto semantic networks
��Semantic networks can map onto logic and then prologSemantic networks can map onto logic and then prolog
�� As prolog is logic based As prolog is logic based
��So try and represent them using predicate logicSo try and represent them using predicate logic
��Where this breaks down Where this breaks down analyseanalyse whywhy
�� Is a more trivial or general case of the problem easier?Is a more trivial or general case of the problem easier?
��Solve that and modify solution to fitSolve that and modify solution to fit
��Do we need lists Do we need lists -- if so what formif so what form
��What alternatives are?What alternatives are?
149
Example of structuralisation
�� Consider GO boardConsider GO board
�� How to represent it?How to represent it?
��predicates or listspredicates or lists
�� Predicates of formPredicates of form
��grid(X,Y, Color)grid(X,Y, Color)
�� or List of form or List of form
�� [1[1--11--grey, 1grey, 1--22--white | Tail]white | Tail]
�� What are the benefitsWhat are the benefits
��Try running a small board of 5 by 5 for bothTry running a small board of 5 by 5 for both
��What are the benefits of either representation?What are the benefits of either representation?
150
Using Pictures
�� Graphical representations may help in the Graphical representations may help in the
perception of some essential relations and perception of some essential relations and
qualities of the problemqualities of the problem
�� Problems can be illustrated by Problems can be illustrated by
��nodes denoting objectsnodes denoting objects
��with connections between nodes representing relationswith connections between nodes representing relations
�� Structured data objects in Prolog can be pictured Structured data objects in Prolog can be pictured
as treesas trees
�� Declarative nature of Prolog facilitates the Declarative nature of Prolog facilitates the
translation of pictorial representations into prolog translation of pictorial representations into prolog
Code Code -- see lectures on semantic networkssee lectures on semantic networks
151
Some rules of good Prolog style
�� Program clauses should be shortProgram clauses should be short
�� Procedures should be shortProcedures should be short
�� Mnemonic names should be usedMnemonic names should be used
�� Layout is importantLayout is important
��Use space, blank lines and indentationUse space, blank lines and indentation
�� The cut operator should be used with careThe cut operator should be used with care
��better avoidedbetter avoided
�� The not procedure can sometimes lead to The not procedure can sometimes lead to
surprising behavior surprising behavior -- but preferable to cutbut preferable to cut
�� The use of a semiThe use of a semi--colon may obscure the meaningcolon may obscure the meaning
152
merge - bad style
merge1(List1, List2, List3):merge1(List1, List2, List3):--
List1=[ ], !, List1=[ ], !,
List3=List2;List3=List2; % 1st list empty% 1st list empty
List2=[ ], !, List2=[ ], !,
List3=List1;List3=List1; % 2nd list empty% 2nd list empty
List1=[X|List4],List1=[X|List4],
List2=[Y|List5],List2=[Y|List5],
(X<Y, !, Z=X, merge1(List4,List2, List6);(X<Y, !, Z=X, merge1(List4,List2, List6);
Z=Y, merge1(List1, List5, List6)),Z=Y, merge1(List1, List5, List6)),
List3 = [Z|List6].List3 = [Z|List6].
153
merge - better style
merge2([ ], L, L):merge2([ ], L, L):-- !. %prevent redundant solutions!. %prevent redundant solutions
merge2(L, [ ], L).merge2(L, [ ], L). % boundary cases% boundary cases
% following clause does ordering test% following clause does ordering test
merge2([H1|Rest1],[H2|Rest2],[H1|Rest3]):merge2([H1|Rest1],[H2|Rest2],[H1|Rest3]):--
H1 < H2, !, H1 < H2, !, %prevent backtracking%prevent backtracking
merge2(Rest1, [H2|Rest2], Rest3).merge2(Rest1, [H2|Rest2], Rest3).
% No ordering test needed on this clause% No ordering test needed on this clause
merge2(List1,[H|Rest2],[H|Rest3]):merge2(List1,[H|Rest2],[H|Rest3]):--
merge2(List1, Rest2, Rest3).merge2(List1, Rest2, Rest3).
154
Debugging
�� Prolog provides a special debugging aid for Prolog provides a special debugging aid for
tracing a goaltracing a goal
�� Tracing is activated using the predicate Tracing is activated using the predicate tracetrace
��displays useful information during executiondisplays useful information during execution
�� Entry infoEntry info: predicate name and values of : predicate name and values of argsargs
�� Exit infoExit info::
�� if success the value of arguments that satisfy goalif success the value of arguments that satisfy goal
��otherwise an indication of failureotherwise an indication of failure
�� ReRe--entry info:entry info:
�� invocation of the same goal caused by backtrackinginvocation of the same goal caused by backtracking
155
�� ??-- trace, merge2([1,2],[1],L).trace, merge2([1,2],[1],L).
�� Call: ( 8) merge2([1, 2], [1], _G266) ? creepCall: ( 8) merge2([1, 2], [1], _G266) ? creep
�� Call: ( 9) 1<1 ? creepCall: ( 9) 1<1 ? creep
�� Fail: ( 9) 1<1 ? creepFail: ( 9) 1<1 ? creep
�� Redo: ( 8) merge2([1, 2], [1], _G266) ? creepRedo: ( 8) merge2([1, 2], [1], _G266) ? creep
�� Call: ( 9) merge2([1, 2], [], _G383) ? creepCall: ( 9) merge2([1, 2], [], _G383) ? creep
�� Exit: ( 9) merge2([1, 2], [], [1, 2]) ? creepExit: ( 9) merge2([1, 2], [], [1, 2]) ? creep
�� Exit: ( 8) merge2([1, 2], [1], [1, 1, 2]) ? creepExit: ( 8) merge2([1, 2], [1], [1, 1, 2]) ? creep
�� L = [1, 1, 2] L = [1, 1, 2]
�� YesYes
156
Sorting lists - Bubble Sort
�� bubblesort(Listbubblesort(List, Sorted, Sorted).).
��Assume ordering relation Assume ordering relation gt(X,Ygt(X,Y))
��meaning meaning XX is greater than is greater than YY
�� IfIf X X andand Y Y are numbers then could useare numbers then could use
�� gt(Xgt(X, Y) :, Y) :-- X > Y.X > Y.
�� find two adjacent elements find two adjacent elements XX, , YY in in ListList
��such that such that gt(Xgt(X, Y), Y) -- swap swap XX and and YY in in ListList to get to get List1List1
��sort sort List1List1
�� if there no pair if there no pair XX, Y such that , Y such that gt(X,Ygt(X,Y))
�� then then ListList is is SortedSorted
157
Bubble Sort
bubblesort(Listbubblesort(List, Sorted):, Sorted):--
swap(List, List1), !, swap(List, List1), !, % A Useful Swap?% A Useful Swap?
bubblesort(List1, Sorted).bubblesort(List1, Sorted).
bubblesort(Sortedbubblesort(Sorted, Sorted)., Sorted). % Boundary% Boundary
swap( [ X, Y | Rest], [Y, X | Rest] ):swap( [ X, Y | Rest], [Y, X | Rest] ):--
gt(Xgt(X, Y)., Y).
swap( [ Z | Rest1 ], [ Z | Rest2 ]):swap( [ Z | Rest1 ], [ Z | Rest2 ]):--
swap(Rest1, Rest2).swap(Rest1, Rest2).
158
Insert Sort�� To sort a nonTo sort a non--empty list, L = [H | T]empty list, L = [H | T]
��sort the tail T of Lsort the tail T of L
�� Insert the head H into a position in the sorted tail such Insert the head H into a position in the sorted tail such
that the result is sortedthat the result is sorted
insertsortinsertsort( [ ], [ ] ).( [ ], [ ] ).
insertsortinsertsort( [ X | T ], Sorted ):( [ X | T ], Sorted ):--
insertsortinsertsort( T, ( T, SortedTSortedT ),), % sort tail% sort tail
insert(X, insert(X, SortedTSortedT, Sorted )., Sorted ). % insert and sort% insert and sort
insert(X, [Y | Sorted], [ Y | Sorted1 ]):insert(X, [Y | Sorted], [ Y | Sorted1 ]):-- gt(Xgt(X, Y), !,, Y), !,
insert(X, Sorted, Sorted1).insert(X, Sorted, Sorted1).
insert( X, Sorted, [ X | Sorted ]).insert( X, Sorted, [ X | Sorted ]).
159
Running swap.pl - with time/1
�� ??-- bubblesort([1, 3, 9, 0, 6, 8, 4, 5, 7, 2],S).bubblesort([1, 3, 9, 0, 6, 8, 4, 5, 7, 2],S).
S = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] S = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
�� ??-- insertsort([1, 3, 9, 0, 6, 8, 4, 5, 7, 2],S).insertsort([1, 3, 9, 0, 6, 8, 4, 5, 7, 2],S).
S = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] S = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
�� ??-- time(bubblesort([1, 3, 9, 0, 6, 8, 4, 5, 7, 2],S)).time(bubblesort([1, 3, 9, 0, 6, 8, 4, 5, 7, 2],S)).
556 inferences in 0.00 seconds (Infinite Lips)556 inferences in 0.00 seconds (Infinite Lips)
S = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] S = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
�� ??-- time(insertsort([1, 3, 9, 0, 6, 8, 4, 5, 7, 2],S)).time(insertsort([1, 3, 9, 0, 6, 8, 4, 5, 7, 2],S)).
107 inferences in 0.00 seconds (Infinite Lips)107 inferences in 0.00 seconds (Infinite Lips)
S = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]S = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
160
Running the merges with time/1
�� ??-- time(merge1([0, 2, 4, 6, 8], [1, 3, 5, 7, 9], L)).time(merge1([0, 2, 4, 6, 8], [1, 3, 5, 7, 9], L)).
131 inferences in 0.00 seconds (Infinite Lips)131 inferences in 0.00 seconds (Infinite Lips)
L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
YesYes
�� ??-- time(merge2([0, 2, 4, 6, 8], [1, 3, 5, 7, 9], L)).time(merge2([0, 2, 4, 6, 8], [1, 3, 5, 7, 9], L)).
25 inferences in 0.00 seconds (Infinite Lips)25 inferences in 0.00 seconds (Infinite Lips)
L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] L = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
YesYes
161
Manipulating Characters�� atom_chars/2atom_chars/2
��Convert between atom and list of ASCII valuesConvert between atom and list of ASCII values
�� atom_char/2atom_char/2
��Convert between atom and ASCII valueConvert between atom and ASCII value
�� name/2name/2
��Convert between atom and list of ASCII charactersConvert between atom and list of ASCII characters
�� string_to_list/2string_to_list/2
��Conversion between string and list of ASCIIConversion between string and list of ASCII
�� put/1put/1 places ASII value on output streamplaces ASII value on output stream
�� get0/1get0/1 Read next characterRead next character
�� get/1 Read first nonget/1 Read first non--blank characterblank character
162
Manipulating Characters�� atom_chars/2atom_chars/2
��??-- atom_chars(atom, Chars).atom_chars(atom, Chars).
Chars = [97, 116, 111, 109]Chars = [97, 116, 111, 109]
��??-- atom_chars(Atom, atom_chars(Atom, ““CharsChars””).).
Atom = Atom = ‘‘CharsChars’’
�� atom_char/2atom_char/2
��??-- atom_char(a, Char).atom_char(a, Char).
Char = 97 Char = 97
��??-- atom_char(Atom, 97).atom_char(Atom, 97).
Atom = aAtom = a
163
Manipulating Characters
�� name/2name/2
��??-- name(atom, List).name(atom, List).
Chars = [97, 116, 111, 109] Chars = [97, 116, 111, 109]
��??-- name(Atom, "name(Atom, "abcabc").").
Atom = Atom = abcabc
�� string_to_list/2string_to_list/2
��??-- string_to_list('Atom',L).string_to_list('Atom',L).
L = [65, 116, 111, 109] L = [65, 116, 111, 109]
��??-- string_to_list(String, "string_to_list(String, "StringOfAsciiStringOfAscii").").
String = "String = "StringOfAsciiStringOfAscii" "
164
Manipulating Characters��??-- string_to_list(String, [65, 111]), atom(String).string_to_list(String, [65, 111]), atom(String).
NoNo
��??-- String = 'atom', string_to_list(S, List), atom(S).String = 'atom', string_to_list(S, List), atom(S).
S = atomS = atom
List = [97, 116, 111, 109] List = [97, 116, 111, 109]
YesYes
��??-- string_to_list(String, [65, 111]), string_to_list(String, [65, 111]),
string_to_atom(String,Atom), atom(Atom).string_to_atom(String,Atom), atom(Atom).
String = "String = "AoAo""
Atom = 'Atom = 'AoAo' '
YesYes
165
Manipulating Characters
�� Input and Output of ASCII valuesInput and Output of ASCII values
��??-- put(65), put(66), put(67).put(65), put(66), put(67).
ABCABC
��??-- get0(C).get0(C). ??-- get0(C), get0(A).get0(C), get0(A).
: : aa :: asas
C = 97 C = 97 C = 97C = 97
A = 115A = 115
��??-- get(C).get(C).
: a: a
C = 97 C = 97
166
Testing the Type of Terms
�� var/1var/1 Type check for unbound variableType check for unbound variable
�� nonvar/1nonvar/1 Type check for bound termType check for bound term
�� ground/1ground/1 Verify term holds no unbound variablesVerify term holds no unbound variables
�� atom/1atom/1 Type check for an atomType check for an atom
�� atomic/1atomic/1 Type check for primitiveType check for primitive
�� integer/1integer/1 Type check for integerType check for integer
�� number/1number/1 Type check for integer or floatType check for integer or float
�� float/1float/1 Type check for a floating point numberType check for a floating point number
167��??-- var(Xvar(X), X = 2.), X = 2. ??-- nonvar(Xnonvar(X), X = 2.), X = 2.
X = 2 X = 2 NoNo
YesYes
��??-- X = 2, X = 2, var(Xvar(X).). ??-- X = 2, X = 2, nonvar(Xnonvar(X) )
NoNo X =2X =2
YesYes
��??-- integer(X), X =2. integer(X), X =2. ??-- X = 2, integer(X).X = 2, integer(X).
NoNo X = 2X = 2
YesYes
��??-- X = 2, atomic(X). X = 2, atomic(X). ??-- X = 2, atom(X).X = 2, atom(X).
X = 2 X = 2 NoNo
YesYes ??-- X = a, atom(X).X = a, atom(X).
X = a X = a YesYes
168�� ??-- var(Xvar(X), X = 2.), X = 2.
X = 2X = 2
YesYes
�� ??-- X = 2, X = 2, var(Xvar(X).).
NoNo
�� ??-- nonvar(Xnonvar(X), X = 2), X = 2
NoNo
�� ??-- X = 2, X = 2, nonvar(Xnonvar(X).).
X = 2.X = 2.
YesYes
�� ??-- integer(X), X =2.integer(X), X =2.
NoNo
�� ??-- X = 2, integer(X).X = 2, integer(X).
X =2X =2
YesYes
�� ??-- X = 2, atom(X).X = 2, atom(X).
NoNo
�� ??-- X = a, atom(X).X = a, atom(X).
X = aX = a
YesYes
�� ??-- atom(X), X =a.atom(X), X =a.
NoNo
�� ??-- X = 2, atomic(X).X = 2, atomic(X).
X = 2X = 2
YesYes
169
What does the following code do?
�� enigma( [ ] ):enigma( [ ] ):-- write( write( ‘‘..’’), ), nlnl..
�� enigma( [ L | Lt ]):enigma( [ L | Lt ]):-- write(write(‘‘ ‘‘),),
name(L, [ Z | name(L, [ Z | ZtZt ]),]),
Y is Z Y is Z -- 32,32,
name(X, [ Y | name(X, [ Y | ZtZt ]),]),
write(X),write(X),
enigma( Lt ).enigma( Lt ).
170
Comments
�� % This is a comment % This is a comment
�� /* This is another Comment *//* This is another Comment */
�� LayoutLayout
% File:% File: mycomments.plmycomments.pl
% author:% author: fredfred platocratesplatocrates
% date:% date: 04:15am 10 04:15am 10 JunusJunus 350BC350BC
% updated:% updated: Thursday, April 13, 2000Thursday, April 13, 2000
% purpose:% purpose: Header for basic comments fileHeader for basic comments file
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% go/0 this starts the program which exits prolog% go/0 this starts the program which exits prolog
go:go:-- halt.halt.
171
Getting a listing
�� listing/0 lists all the loaded code listing/0 lists all the loaded code
��some of which is not yourssome of which is not yours
d:/LECTURES/AI1/PROLOG/MYCOMM~1.PL d:/LECTURES/AI1/PROLOG/MYCOMM~1.PL
compiled, 0.00 sec, 640 bytes.compiled, 0.00 sec, 640 bytes.
??-- listing.listing.
'$user_query'(1, []) :'$user_query'(1, []) :--
listing.listing.
go :go :--
halt.halt.
% Foreign: window_title/2% Foreign: window_title/2
YesYes
172
Getting a listing
�� listing/1 lists all the predicate clauses that matchlisting/1 lists all the predicate clauses that match
??-- listing(merge2).listing(merge2).
merge2([], A, A) :merge2([], A, A) :-- !.!.
merge2(A, [], A).merge2(A, [], A).
merge2([A|B], [C|D], [A|E]) :merge2([A|B], [C|D], [A|E]) :--
A<C, !,A<C, !,
merge2(B, [C|D], E).merge2(B, [C|D], E).
merge2(A, [B|C], [B|D]) :merge2(A, [B|C], [B|D]) :--
merge2(A, C, D).merge2(A, C, D).
YesYes