AI 08226 Prolog (PROgramming in LOGic)

Preview:

Citation preview

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

Recommended