Prolog

=INTRODUCTION TO PROLOG PROGRAMMING = 
 * What is Prolog?**

> unlike most common programming languages. Alain Colmerauer ||  Robert Kowalski ||
 * * invented early seventies by Alain Colmerauer in France and Robert Kowalski in Britain. Note that historical information in these lectures is not examinable.
 * Prolog = Programmation en Logique (Programming in Logic).
 * Prolog is a declarative programming language
 * In a declarative language
 * the programmer specifies a goal to be achieved
 * the Prolog system works out how to achieve it
 * relational databases owe something to Prolog || [[image:http://www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/AlainColmerauer.jpg width="100"]]

===What is Prolog? (continued) === >> mix ingredients; >> beat until smooth; >> bake for 20 minutes in a moderate oven; >> remove tin from oven; >> put on bench; >> close oven; >> turn off oven;
 * traditional programming languages are said to be **procedural**
 * procedural programmer must specify in detail how to solve a problem:
 * in purely declarative languages, the programmer only states what the problem is and leaves the rest to the language system
 * We'll see specific, simple examples of cases where Prolog fits really well shortly

Applications of Prolog
Some applications of Prolog are:
 * intelligent data base retrieval
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">natural language understanding
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">expert systems
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">specification language
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">machine learning
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">robot planning
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">automated reasoning
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">problem solving

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: #a52a2a; font-family: Helvetica,sans-serif; font-size: 14px;">The Prolog Language
<span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;"> || <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;"> <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">Ivan Bratko ||
 * <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">**Reference:** || <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">Bratko, Chapter 1

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Relations
>>> they are both female **and** >>> they have the same parents.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Prolog programs specify //relationships// among objects and properties of objects.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">When we say, "John owns the book", we are declaring the ownership relationship between two objects: John and the book.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">When we ask, "Does John own the book?" we are trying to find out about a relationship.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Relationships can also rules such as:**if**
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A rule allows us to find out about a relationship even if the relationship isn't explicitly stated as a fact.

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">A little more on being sisters === >>> A and B are both female **and** >>> they have the same father **and** >>> they have the same mother **and** >>> A is not the same as B
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">As usual in programming, you need to be a bit careful how you phrase things:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The following would be better:**if**

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Programming in Prolog
<span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">One then uses the system by:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">declare facts describing explicit relationships between objects and properties objects might have (e.g. Mary likes pizza, grass has_colour green, Fido is_a_dog, Mizuki taught Paul Japanese )
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">define rules defining implicit relationships between objects (e.g. the sister rule above) and/or rules defining implicit object properties (e.g. X is a parent if there is a Y such that Y is a child of X).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">asking questions above relationships between objects, and/or about object properties (e.g. does Mary like pizza? is Joe a parent?)

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Facts

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Properties of objects, //or// relationships between objects;
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">"Dr Turing lectures in course 9020", is written in Prolog as: lectures(turing, 9020).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">//Notice that://
 * names of properties/relationships begin with lower case letters.
 * the relationship name appears as the first term
 * objects appear as comma-separated arguments within parentheses.
 * A period "." must end a fact.
 * objects also begin with lower case letters. They also can begin with digits (like 9020), and can be strings of characters enclosed in quotes (as in reads(fred, "War and Peace")).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">lectures(turing, 9020). is also called a //predicate//

<span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">Facts about a hypothetical computer science department: <span style="font-family: Times,serif;"> % lectures(X, Y): person X lectures in course Y lectures( <span style="color: black; font-family: Times,serif; font-size: 12pt;">[|turing] <span style="font-family: Times,serif;">, 9020). lectures( <span style="color: black; font-family: Times,serif; font-size: 12pt;">[|codd] <span style="font-family: Times,serif;">, 9311). lectures( <span style="color: black; font-family: Times,serif; font-size: 12pt;">[|backus] <span style="font-family: Times,serif;">, 9021). lectures( <span style="color: black; font-family: Times,serif; font-size: 12pt;">[|ritchie] <span style="font-family: Times,serif;">, 9201). lectures( <span style="color: black; font-family: Times,serif; font-size: 12pt;">[|minsky] <span style="font-family: Times,serif;">, 9414). lectures(codd, 9314). % studies(X, Y): person X studies in course Y studies(fred, 9020). studies(jack, 9311). studies(jill, 9314). studies(jill, 9414). studies(henry, 9414). studies(henry, 9314). %year(X, Y): person X is in year Y year(fred, 1). year(jack, 2). year(jill, 2). year(henry, 4). <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">Together, these facts form Prolog's //database//. Should you wish to experiment with them using Prolog, they are available at [].

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Queries

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Once we have a database of facts (and, soon, rules) we can ask questions about the stored information.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Suppose we want to know if Turing lectures in course 9020. We can ask:
 * % ** prolog -s facts03 ** (multi-line welcome message) ?- // lectures(turing, 9020). // true. ?- // <control-D> // % || facts03 loaded into Prolog "?-" is Prolog's prompt output from Prolog hold down control & press D to leave Prolog ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">//Notice that://
 * In SWI Prolog, queries are terminated by a full stop.
 * To answer this query, Prolog consults its database to see if this is a known fact.
 * In example dialogues with Prolog, the text in // green italics // is what the user types.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Another example query
<span style="font-family: Times,serif;">?- //<span style="color: black; font-family: Times,serif; font-size: 12pt;"> lectures(codd, 9020). //<span style="font-family: Times,serif;">false. > lectures(fred, 9020). or lectures(xyzzy, 9020). > though a person inspecting the database can see that fred is a student, not a lecturer, and that xyzzy is neither student nor lecturer.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">if answer is true., the query //succeeded//
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">if answer is false., the query //failed//. Note: many early versions of Prolog, including early versions of SWI-Prolog, say No instead of false. See the article on [|negation] in the [|Prolog dictionary] to find out why No. is a more accurate description of what is happening.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">In the latest version of SWI Prolog, it no longer says "No." but says "false." instead.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The use of lower case for codd is critical.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Prolog is not being intelligent about this - it would not see a difference between this query and

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Variables

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Suppose we want to ask, "What course does Turing teach"?
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">This could be written as: Is there a course, X, that Turing teaches?
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The variable X stands for an object that the questioner does not know about yet.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">To answer the question, Prolog has to find out the value of X, if it exists.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">As long as we do not know the value of a variable it is said to be //unbound//.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">When a value is found, the variable is said to //bound// to that value.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The name of a variable must begin with a capital letter or an underscore character, "_".

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Variables 2
>> ?- //lectures(turing, Course).// >> Course = 9020 ← output from Prolog >> ?- //lectures(codd, Course).// >> Course = 9311 // ; // ← type ";" to get next solution >> Course = 9314 >> ?- <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">If Prolog can tell that there are no more solutions, it just gives you the ?- prompt for a new query, as here. If Prolog can't tell, it will let you type ; again, and then if there is no further solution, reportfalse.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">To ask Prolog to find the course that Turing teaches, enter this:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">To ask which course(s) Prof. Codd teaches, we may ask,
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Prolog can find all possible ways to answer a query, unless you explicitly tell it not to (see //cut//, later).

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Conjunctions of Goals in Queries ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">How do we ask, "Does Turing teach Fred"?
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">This means finding out if Turing lectures in a course that Fred studies. ?- // lectures(turing, Course), studies(fred, Course) .//
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">i.e. "Turing lectures in course, Course **and** Fred studies (the same) Course".
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The question consists of two //goals//.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">To answer this question, Prolog must find a single value for Course, that satisfies both goals.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Read the comma, ",", as **and**.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">However, note that Prolog will evaluate the two goals left-to-right. In pure logic, P1 ∧ P2 is the same as P2 ∧ P1. In Prolog, there is the practical consideration of which goal should be evaluated first - the code might be more efficient one way or the other. In particular, in "P1, P2", if P1 fails, then P2 does not need to be evaluated at all. This is sometimes referred to as a "conditional-and".

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Disjunctions of Goals in Queries === <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">There is a way to write **or**: (";") > head :- body1. head :- body2.has the same effect ashead :- body1 ; body2.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">What about **or** (i.e. disjunction)? It turns out explicit **or**s aren't needed much in Prolog
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The reason **or**s aren't needed much is that
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Avoid using ; if you can, at least until you have learned how to manage without it. While some uses of ; are harmless, others can make your code hard to follow.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;"> To reinforce this message, you will be **penalised** if you use the **or** operator ; in the first (Prolog) assignment in COMP9414. This prohibition means you can't use the … -> … ; … construct either, in the first assignment. The … -> … ; … construct is not taught in COMP9414, but in the past, some people have found out about it.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Backtracking in Prolog

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Who does Codd teach? ?- // lectures(codd, Course), studies(Student, Course) .// Course = 9311 Student = jack // ; // Course = 9314 Student = jill // ; // Course = 9314 Student = henry // ; //
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Prolog solves this problem by proceeding left to right and then //backtracking//.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">When given the initial query, Prolog starts by trying to solve lectures(codd, Course)
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">There are six lectures clauses, but only two have codd as their first argument.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Prolog uses the first clause that refers to codd: lectures(codd, 9311).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">With Course = 9311, it tries to satisfy the next goal, studies(Student, 9311).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">It finds the fact studies(jack, 9311). and hence the first solution: (Course = 9311, Student = jack)

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Backtracking in Prolog 2
>> (Course = 9314, Student = jill) >> and (Course = 9314, Student = henry).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">After the first solution is found, Prolog retraces its steps up the tree and looks for alternative solutions.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">First it looks for other students studying 9311 (but finds none).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Then it
 * backs up
 * rebinds Course to 9314,
 * goes down the lectures(codd, 9314) branch
 * tries studies(Student, 9314),
 * finds the other two solutions:

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Backtracking in Prolog 3
<span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">To picture what happens when Prolog tries to find a solution and backtracks, we draw a "proof tree":

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Rules

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The previous question can be restated as a general rule: One person, Teacher, teaches another person, Student **if** Teacher lectures in a course, Course **and**Student studies Course.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">In Prolog this is written as: teaches(Teacher, Student) :- lectures(Teacher, Course), studies(Student, Course). ?- //teaches(codd, Student).//
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Facts are //unit clauses// and rules are //non-unit clauses//.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Clause Syntax

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">":-" means "if" or "is implied by". Also called the //neck// symbol.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The left hand side of the neck is called the //head//.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The right hand side of the neck is called the //body//.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The comma, ",", separating the goals, stands for //and//.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Another rule, using the //predefined predicate// ">".more_advanced(S1, S2) :- year(S1, Year1), year(S2, Year2), Year1 > Year2.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Tracing Execution
<span style="font-family: Times,serif;">more_advanced(S1, S2) :- year(S1, Year1), year(S2, Year2), Year1 > Year2. <span style="font-family: Times,serif;"> <span style="color: red; font-family: Times,serif; font-size: 12pt;">* <span style="font-family: Times,serif;"> The ? is a prompt. Press the return key at end of each line of tracing. Prolog will echo the as creep, and then print the next line of tracing. The "creep"s have been removed in the table above, to reduce clutter.
 * ?- //trace.// true. [trace] ?- //more_advanced(henry, fred).// Call: more_advanced(henry, fred) ? * Call: year(henry, _L205) ? Exit: year(henry, 4) ? Call: year(fred, _L206) ? Exit: year(fred, 1) ? ^ Call: 4>1 ? ^ Exit: 4>1 ? Exit: more_advanced(henry, fred) ? true. [debug] ?- //notrace.// || bind S1 to henry, S2 to fred test 1st goal in body of rule succeeds, binds Year1 to 4 test 2nd goal in body of rule succeeds, binds Year2 to 1 test 3rd goal: Year1 > Year2 succeeds succeeds ||

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">true., false., or More?

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Sometimes, Prolog says More? instead of true..
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Prolog does this when it believes it may be able to prove that the query is true in more than one way (and there are no variables in the query, that it can report bindings for).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Example: suppose we have the following facts and rule:bad_dog(fido). bad_dog(Dog) :- bites(Dog, Person), is_person(Person), is_dog(Dog). bites(fido, postman). is_person(postman). is_dog(fido). There are two ways to prove bad_dog(fido): (a) it's there as a fact; and (b) it can be proven using the bad_dog rule:?- //bad_dog(fido).// More? //;// true. More? means true. //and// it prompts us to type ; if we want to check for another proof. The true. that follows means that a second proof //was// found. Alternatively, we can just press the "return" key if we are not interested in whether there is another proof.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">You can find more details by looking up [|More] in the [|Prolog dictionary].

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Structures

 * **Reference:** || Bratko chapter 2 ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Functional terms can be used to construct complex data structures.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">If we want to say that John owns the novel Tehanu, we can write: owns(john, 'Tehanu').
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Often objects have a number of attributes: owns(john, book('Tehanu', leguin)).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The author LeGuin has attributes too: owns(john, book('Tehanu', author (leguin, ursula))).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The arity of a term is the number of arguments it takes.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">all versions of owns have arity 2, but the detailed structure of the arguments changes.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">gives(john, book, mary). is a term with arity 3.

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Asking Questions with Structures ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">How do we ask, "What books does John own that were written by someone called LeGuin"??- // owns(john, book(Title, author(leguin, GivenName))). //Title = 'Tehanu' GivenName = ursula
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">What books does John own??- // owns(john, Book). //Book = book('Tehanu', author(leguin, ursula))
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">What books does John own??- // owns(john, book(Title, Author)). //Title = 'Tehanu' Author = author(leguin, ursula)
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Prolog performs a complex matching operation between the structures in the query and those in the clause head.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Library Database Example

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A database of books in a library contains facts of the formbook(CatalogNo, Title, author(Family, Given)). libmember(MemberNo, name(Family, Given), Address). loan(CatalogNo, MemberNo, BorrowDate, DueDate).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A member of the library may borrow a book.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A "loan" records:
 * the catalogue number of the book
 * the number of the member
 * the date on which the book was borrowed
 * the due date

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Library Database Example 2 === > date(Year, Month, Day)
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Dates are stored as structures:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">e.g. date(2012, 6, 16) represents 16 June 2012.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">which books has a member borrowed?borrowed(MemFamily, Title, CatalogNo) :- libmember(MemberNo, name(MemFamily, _), _), loan(CatalogNo, MemberNo, _, _), book(CatalogNo, Title, _).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The underscore or "don't care" variables (_) are used because for the purpose of this query we don't care about the values in some parts of these structures.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Comparing Two Terms

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">we would like to know which books are overdue; how do we compare dates?%later(Date1, Date2) if Date1 is after Date2: later(date(Y, M, Day1), date(Y, M, Day2)) :- Day1 > Day2. later(date(Y, Month1, _), date(Y, Month2, _)) :- Month1 > Month2. later(date(Year1, _, _), date(Year2, _, _)) :- Year1 > Year2.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">This rule has three clauses: in any given case, only one clause is appropriate. They are tried in the given order.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">This is how disjunction (**or**) is often achieved in Prolog. In effect, we are saying that the first date is later than the second date if Day1 > Day2 and the Y and M are the same, **or** if the Y is the same and Month1 > Month2, **or** if Year1 > Year2.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">//Footnote//: if the year and month are the same, then the heads of all three rules match, and so, while the first rule is the appropriate one, all three will be tried in the course of backtracking. However, the condition "Month1 > Month2" in the second rule means that it will fail in this case, and similarly for the third rule.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">More on Comparisons
> - e.g. X + Y >= Z * W * 2. <span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">||~ Operator ||~ Meaning ||~ Syntax || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| > || greater than || Expression1 > Expression2 || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| < || less than || Expression1 < Expression2 || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| >= || greater than or equal to || Expression1 >= Expression2 || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| =< || less than or equal to || Expression1 =< Expression2 || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| =:= > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| =\=
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">In the code for later, again we are using the comparison operator ">"
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">More complex arithmetic expressions can be arguments of comparison operators
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The available //numeric// comparison operators are:
 * equal to || Expression1 =:= Expression2 ||
 * not equal to || Expression1 =\= Expression2 ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">All these numerical comparison operators evaluate both their arguments. That is, they evaluate Expression1 and Expression2.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Overdue Books
<span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">% overdue(Today, Title, CatalogNo, MemFamily): % given the date Today, produces the Title, CatalogNo, % and MemFamily of all overdue books. overdue(Today, Title, CatalogNo, MemFamily) :- loan(CatalogNo, MemberNo, _, DueDate), later(Today, DueDate), book(CatalogNo, Title, _), libmember(MemberNo, name(MemFamily, _), _).

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Due Date
<span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">You can find a copy of the code for all the library stuff, and a sample (toy) library database, at []
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Assume the loan period is one month:due_date(date(Y, Month1, D), date(Y, Month2, D)) :- Month1 < 12, Month2 is Month1 + 1. due_date(date(Year1, 12, D), date(Year2, 1, D)) :- Year2 is Year1 + 1.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">The is operator
> <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| X = 1 || || GOOD! || ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The right hand argument of is must be an arithmetic expression that can be evaluated right now (no unbound variables).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">This expression is evaluated and bound to the left hand argument.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">is is not a C-style assignment statement:
 * X is X + 1 won't work!
 * except via backtracking, variables can only be bound once, using is or any other way
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">= does not cause evaluation of its arguments: || ?- // X = 2, Y = X + 1. // X = 2 Y = 2+1 ||  || ?- // X = 2, Y is X + 1. // X = 2 Y = 3 ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Use is if and only if you need to evaluate something:
 * X is 1 ||  || BAD! || - nothing to evaluate ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;"> To reinforce the point about the meaning of is, you will be penalised in the first Prolog assignment if you use it where it is not needed.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Order of goals with is
> ?- X is Y + 1, Y = 3. ERROR: is/2: Arguments are not sufficiently instantiated vs?- Y = 3, X is Y + 1. Y = 3, X = 4.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Order of goals matters with is.<span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">Variables on the RHS of is //must// be instantiated at the time the is goal is tried by Prolog. This is why the following example fails:

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">is, = and =:=
> ERROR: =:=/2: Arguments are > not sufficiently instantiated || X is not currently bound, so can't be evaluated. || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| ?- X = 3+2. > <span style="color: black; font-family: Times,serif; font-size: 12pt;">X = 3+2. || = doesn't evaluate, so X is bound to 3+2. || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| ?- X is 3+2. > <span style="color: black; font-family: Times,serif; font-size: 12pt;">X = 5. || is //does// evaluate its right-hand side. || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| ?- 4+1 is 3+2. > <span style="color: black; font-family: Times,serif; font-size: 12pt;">false. || 3+2 is evaluated to 5. > <span style="color: black; font-family: Times,serif; font-size: 12pt;">4+1 is not evaluated. So 4+1 is different from 5. || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| ?- 4+1=3+2. > <span style="color: black; font-family: Times,serif; font-size: 12pt;">false. || Neither side is evaluated by =. > <span style="color: black; font-family: Times,serif; font-size: 12pt;">The two expressions are different. || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| ?- 4+1 =:= 3+2. > <span style="color: black; font-family: Times,serif; font-size: 12pt;">true. || Both sides are evaluated by =:= || > ?- likes(mary, X) = likes(Y, pizza). X = pizza, Y = mary.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">You can see the differences between these three Prolog constructs from the following example Prolog queries:
 * ?- X =:= 3+2.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">= is used for matching, so a more appropriate use would be:

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Recursive Programs

 * **Reference:** || Bratko section 1.3 (doesn't cover trees, though) ||

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Binary Trees

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">In the library database example, some complex terms contained other terms, for example, book contained name.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The following term also contains another term, this time one similar to itself:tree(tree(L1, jack, R1), fred, tree(L2, jill, R2))
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The variables L1, L2, R1, and R2 should be bound to sub-trees (this will be clarified shortly).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A structure like this could be used to represent a "binary tree" that looks like:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Binary because each "node" has two branches (our backtrack tree before had many branches at some nodes)

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Recursive Structures
> tree(tree(empty, jack, empty), fred, tree(empty, jill, empty)) <span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A term that contains another term that has the same principal functor (in this case tree) is said to be recursive.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Biological trees have leaves. For us, a //leaf//is a node with two empty branches:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">empty is an arbitrary symbol to represent the empty tree. In full, the tree above would be:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Usually, we wouldn't bother to draw the empty nodes:

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Another Tree Example
<span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">tree(tree(empty, 7, empty), '+', tree(tree(empty, 5, empty), '-', tree(empty, 3, empty)))

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Recursive Programs for Recursive Structures === > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| is_tree(tree(Left, Data, Right)) :- > <span style="color: black; font-family: Times,serif; font-size: 12pt;">is_tree(Left), > <span style="color: black; font-family: Times,serif; font-size: 12pt;">some_data(Data), > <span style="color: black; font-family: Times,serif; font-size: 12pt;">is_tree(Right). || recursive branch || The example at the heading "An Application of Lists", below, will show how the recursive branch and the trivial branch work together. However, you probably shouldn't try to look at it until we have studied lists.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A binary tree is either empty or contains some data and a left and right subtree that are also binary trees.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">In Prolog we express this as:
 * is_tree(empty). || trivial branch ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A non-empty tree is represented by a 3-arity term.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Any recursive predicate must have:
 * (at least) one **recursive branch/rule** (or it isn't recursive :-) ) and
 * (at least) one non-recursive or **trivial branch** (to stop the recursion going on for ever).

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Recursive Programs for Recursive Structures 2 ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Let us define (or measure) the size of tree (i.e. number of nodes):[[image:http://www.cse.unsw.edu.au/~billw/cs9414/notes/prolog/tree3.gif align="right" caption="tree size = number of nodes"]]tree_size(empty, 0). tree_size(tree(L, _, R), Total_Size) :- tree_size(L, Left_Size), tree_size(R, Right_Size), Total_Size is Left_Size + Right_Size + 1.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The size of an empty tree is zero.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The size of a non-empty tree is the size of the left sub-tree plus the size of the right sub-tree plus one for the current tree node.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The data does not contribute to the total size of the tree.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Recursive data structures need recursive programs. A recursive program is one that refers to itself, thus, tree_size contains goals that call for the tree_size of smaller trees.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Lists

 * **Reference:** || Bratko chapter 3 ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A list may be nil (i.e. empty) or it may be a term that has a head and a tail
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The head may be any term or atom.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The tail is another list.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">We could define lists as follows: is_list(nil). is_list(list(Head, Tail)) :- is_list(Tail).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A list of numbers [1, 2, 3] would look like: list(1, list(2, list(3, nil)))
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">This notation is understandable but clumsy. Prolog doesn't actually recognise it, and in fact uses . instead of list and [] instead of nil. So Prolog would recognise .(1, .(2, .(3, []))) as a list of three numbers. This is briefer but still looks strange, and is hard to work with.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Since lists are used so often, Prolog in fact has a special notation that encloses the list members in square brackets: [1, 2, 3] = .(1, .(2, .(3, []))) ?- // X = .(1, .(2, .(3, []))). //X = [1, 2, 3]

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">List Constructor |

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Within the square brackets [ ], the symbol | acts as an operator to construct a list from an item and another list.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">?- // X = [1 | [2, 3]]. //X = [1, 2, 3].
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">?- // Head = 1, Tail = [2, 3], List = [Head | Tail]. //List = [1, 2, 3].

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Examples of Lists and Pattern Matching === Lists "end" in an empty list! Note that [1] is a list with one element. || <span style="background-color: white; color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">The first several elements of the list can be selected before matching the tail: in the list on the right. ||
 * ?- // [X, Y, Z] = [1, 2, 3]. // || Match the terms on either side of = ||
 * X = 1 ||
 * Y = 2 ||
 * Z = 3 ||
 * ?- // [X | Y] = [1, 2, 3]. // || | separates head from tail of list. ||
 * X = 1 || So [First | Rest] is the usual way ||
 * Y = [2, 3] || of writing .(First, Rest) in Prolog ||
 * ?- // [X | Y] = [1]. // X = 1 Y = [] || The empty list is written as []
 * Y = [2, 3] || of writing .(First, Rest) in Prolog ||
 * ?- // [X | Y] = [1]. // X = 1 Y = [] || The empty list is written as []
 * ?- // [X | Y] = [1]. // X = 1 Y = [] || The empty list is written as []
 * ?- // [X | Y] = [1]. // X = 1 Y = [] || The empty list is written as []
 * ?- // [X, Y | Z] = [fred, jim, jill, mary]. // X = fred Y = jim Z = [jill, mary] || Must be at least two elements

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">More Complex List Matching === <span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">?- // [X | Y] = a, f(e)], [n, m, [2]. //X = [a, f(e)] Y = n, m, [2] <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">Notice that Y is shown with an extra pair of brackets: Y is the tail of the entire list: [n, m, [2]] is the sole element of Y.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">List Membership
> a rule with a head but no body || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| || > <span style="color: black; font-family: Times,serif; font-size: 12pt;">|| member(X, [_ | Y]) :- > <span style="color: black; font-family: Times,serif; font-size: 12pt;">member(X, Y). || || recursive branch || <span style="background-color: white; color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">The first rule has the same effect as: member(X, [Y|_]) :- X = Y. > <span style="color: black; font-family: Times,serif; font-size: 12pt;"> > > <span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">The form member(X, [X|_]). is preferred, as it avoids the extra calculation.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">A term is a member of a list if
 * the term is the same as the head of the list, or
 * the term is a member of the tail of the list.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">In Prolog:
 * member(X, [X | _]). ||  || trivial branch:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">member is actually predefined in Prolog. It is a built-in predicate . There are quite a few built-in predicates in Prolog. We do not have the time to find out about most of them in COMP9414. Look at the [|COMP9814 Prolog Extension notes] if you want to get an idea about some of the built-in predicates. "Pre-defined" means that you do not need to put the rules for member into your code - Prolog already knows the definition of member. //Do not re-define predefined predicates.//

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">= in goals
<span style="background-color: white; color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">Earlier, we said: > <span style="color: black; font-family: Times,serif; font-size: 12pt;">X = 1 GOOD! <span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">Actually, goals with = in them are mostly avoidable and //should// be avoided. Beginnner Prolog programmers are tempted to use = frequently, to tie together variables that they now realise should be the same:% length(List, LengthOfList) % binds LengthOfList to the number of elements in List. length([OnlyMember], Length) :- Length = 1. length([First | Rest], Length) :- length(Rest, LengthOfRest), Length is LengthOfRest + 1. This works, but involves an unnecessary unification. It is better for the base case to belength([OnlyMember], 1). In effect, we take the original version of the base case, and replace Length, in the head of the rule, with the thing that Length is = to. Programmers who fail to do this are usually still thinking procedurally.

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Programming Principles for Recursive Structures ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Only deal with one element at a time.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Believe that the recursive program you are writing has already been written.<span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">In the definition of member, we are already assuming that we know how to find a member in the tail.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Write definitions, not programs!
 * If you are used to writing programs for conventional languages, then you are used to giving instructions on how to perform certain operations.
 * In Prolog, you define relationships between objects and let the system do its best to construct objects that satisfy the given relationship.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Concatenating Two Lists
> ?- concat([1], [2], [1, 2]). > By the recursive branch:concat([ 1 | [] ], [2], [ 1 | [2] ]) :- concat( [] , [2] , [2] ). and concat([], [2], [2]) holds because of the trivial branch.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Suppose we want to take two lists, like [1, 3] and [5, 2] and concatenate them to make [1, 3, 5, 2]
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The header comment is:% concat(List1, List2, Concat_List1_List2) % Concat_List1_List2 is the concatenation of List1 & List2 There are two rules:
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">First, the trivial branch:concat([], List2, List2).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Next, the recursive branch:concat([ Item | Tail1 ], List2, [ Item | Concat_Tail1_List2 ]) :- concat( Tail1 , List2 , Concat_Tail1_List2 ).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">For example, consider
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The entire program is:% concat(List1, List2, Concat_List1_List2): % Concat_List1_List2 is the concatenation of List1 & List2 concat([], List2, List2). concat([Item | Tail1], List2, [Item | Concat_Tail1_List2]) :- concat(Tail1, List2, Concat_Tail1_List2).

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">An Application of Lists

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Find the total cost of a list of items:Cost data:cost(cornflakes, 230). cost(cocacola, 210). cost(chocolate, 250). cost(crisps, 190).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Rules:total_cost([], 0). % trivial branch total_cost([Item|Rest], Cost) :- % recursive branch cost(Item, ItemCost), total_cost(Rest, CostOfRest), Cost is ItemCost + CostOfRest.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Sample query:?- // total_cost([cornflakes, crisps], X). // X = 420

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Tracing total_cost
<span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">?- // trace. // true. [trace] ?- // total_cost([cornflakes, crisps], X). // Call: (7) total_cost([cornflakes, crisps], _G290) ? creep Call: (8) cost(cornflakes, _L207) ? creep Exit: (8) cost(cornflakes, 230) ? creep Call: (8) total_cost([crisps], _L208) ? creep Call: (9) cost(crisps, _L228) ? creep Exit: (9) cost(crisps, 190) ? creep Call: (9) total_cost([], _L229) ? creep Exit: (9) total_cost([], 0) ? creep ^ Call: (9) _L208 is 190+0 ? creep ^ Exit: (9) 190 is 190+0 ? creep Exit: (8) total_cost([crisps], 190) ? creep ^ Call: (8) _G290 is 230+190 ? creep ^ Exit: (8) 420 is 230+190 ? creep Exit: (7) total_cost([cornflakes, crisps], 420) ? creep X = 420 [debug] ?- // notrace. //

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Modifying total_cost
<span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;"><span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">This is an //optional// homework exercise.

What happens if we change the recursive branch rule for total_cost as shown below? total_cost([Item|Rest], Cost) :- total_cost(Rest, CostOfRest), cost(Item, ItemCost), Cost is ItemCost + CostOfRest. <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">The second and third lines have been swapped around.

You'll find that the rule still works. Try tracing the new version of this rule, work out what happens differently.

Which version do you find easier to understand? Why do think this is the case?

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Another list-processing procedure ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The next procedure removes duplicates from a list.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">It has //three rules//. This is an example of a common list-processing //template//.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Algorithm:
 * If the list is empty, there's nothing to do.
 * If the first item of the list is a member of the rest of the list, then discard it, and remove duplicates from the rest of the list.
 * Otherwise, keep the first item, and again, remove any duplicates from the rest of the list.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">% remove_dups(+List, -NewList): % New List isbound to List, but with duplicate items removed. remove_dups([], []). remove_dups([First | Rest], NewRest) :- member(First, Rest), remove_dups(Rest, NewRest). remove_dups([First | Rest], [First | NewRest]) :- not(member(First, Rest)), remove_dups(Rest, NewRest).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">?- //remove_dups([1,2,3,1,3,4], X).// X = [2, 1, 3, 4] //;// false.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Note the use of not to negate a condition. An alternative to not is \+. See the article on [|negation] in the [|Prolog dictionary] to find out why there are two names for not.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Singleton Variables

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">If Prolog finds a variable name that you only use once in a rule, it assumes that it may be a spelling mistake, and issues a **Warning** about a "singleton variable" when you load the code:% //prolog -q -s mycode.pl// Warning: .../mycode.pl:4: Singleton variables: [Item]The -q means "quiet" - i.e. don't print the SWI Prolog welcome message. This way, any warnings are easier to notice.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Here is the code that produced this (with line numbers added):1 % count(Item, List, Count) counts the number of times the 2 % Item occurs in the List, and binds Count to that number. 3 4 count(Item, [], 0). 5 count(Item, [Item | Rest], Count) :- 6 count(Item, Rest, RestCount), 7 Count is RestCount + 1. 8 count(Item, [Other | Rest], Count) :- 9 not(Item = Other), 10 count(Item, Rest, Count).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">To suppress the warning, put an _ in front of the word Item on line 4 (only). This makes it "don't care" variable. Check for the possible spelling error, first! 4 count(_Item, [], 0).<span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">See also the [|entry on singleton variables] in the [|Prolog dictionary].

<span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;"> ===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Controlling Execution === ===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">The Cut Operator (!) ===
 * **Reference:** || Bratko chapter 5 ||
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Sometimes we need a way to prevent Prolog finding all solutions, i.e. a way to stop backtracking.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The cut operator, written !, is a built-in goal that prevents backtracking.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">It turns Prolog from a nice declarative language into a hybrid monster.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Use cuts sparingly and with a sense of having sinned.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Cut Operator 2
<span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;"><span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">Recall this example: 

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Cut Prunes the Search Tree ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">If the goal(s) to the right of the cut fail then the entire clause fails and the the goal that caused this clause to be invoked fails.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">In particular, alternatives for Course are not explored.

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Cut Prunes the Search Tree 2 ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Another example: using the facts03 database, try?- // lectures(codd, X). // X = 9311 // ; // X = 9314. ?- // lectures(codd, X), ! . //X = 9311.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The cut in the second version of the query prevents Prolog from backtracking to find the second solution.

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Using cuts in later to improve efficiency === <span style="background-color: white; color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">Recall the code for later: ===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">later(date(Y, M, D1), date(Y, M, D2)) :- D1 > D2. later(date(Y, M1, _), date(Y, M2, _)) :- M1 > M2. later(date(Y1, _, _), date(Y2, _, _)) :- Y1 > Y2. We note that if year and month are the same, all three rules are tried while backtracking. This could be prevented by adding cuts:later(date(Y, M, D1), date(Y, M, D2)) :- D1 > D2, ! . later(date(Y, M1, _), date(Y, M2, _)) :- M1 > M2, ! . later(date(Y1, _, _), date(Y2, _, _)) :- Y1 > Y2. This would increase efficiency by eliminating unnecessary backtracking, though it is doubtful if it would be worth bothering about, unless you actually have code that is running too slowly. In that case you should first do an analysis of where the time is being spent, before putting in cuts everywhere! === <span style="background-color: white; color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">In other cases, adding cuts of this sort to multi-rule procedures might be a useful (if lazy) way of ensuring that only one rule is used in a particular case. Unless it makes the code very clumsy, it is better to use and rely on "condition" goals in each rule (like M1 > M2 in the second rule for later) to specify the case in which it is appropriate. More examples of this are below.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Another cut example

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">max, without cut:% max(A, B, C) binds C to the larger of A and B. max(A, B, A) :- A > B. max(A, B, B) :- A =< B.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">max, with cut:max(A, B, A) :- A > B, ! . max(A, B, B).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The first version has a negated test in the second rule ( = ). The second version substitutes a cut in the first rule for the negated test.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;"> Remember, no cuts in the first assignment unless they are essential! Hint: the first assignment can be done without cuts.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Another cut example 2

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">remove_dups, without cut:remove_dups([], []). remove_dups([First | Rest], NewRest) :- member(First, Rest), remove_dups(Rest, NewRest). remove_dups([First | Rest], [First | NewRest]) :- not(member(First, Rest)), remove_dups(Rest, NewRest).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">remove_dups, with cut:remove_dups([], []). remove_dups([First | Rest], NewRest) :- member(First, Rest), !, remove_dups(Rest, NewRest). remove_dups([First | Rest], [First | NewRest]) :- remove_dups(Rest, NewRest).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The first version has a negated test in the third rule ( not(member(First, Rest)) ). The second version substitutes a cut in the second rule for the negated test in the third rule.

<span style="background-color: white; color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;"> Recall this example:

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Cut Prunes the Search Tree ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">If the goal(s) to the right of the cut fail then the entire clause fails and the the goal that caused this clause to be invoked fails.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">In particular, alternatives for Course are not explored.

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Cut Prunes the Search Tree 2 ===
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">Another example: using the facts03 database, try?- // lectures(codd, X). // X = 9311 // ; // X = 9314. ?- // lectures(codd, X), ! . // X = 9311.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The cut in the second version of the query prevents Prolog from backtracking to find the second solution.

===<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Using cuts in later to improve efficiency === <span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;"><span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">Recall the code for later: later(date(Y, M, D1), date(Y, M, D2)) :- D1 > D2. later(date(Y, M1, _), date(Y, M2, _)) :- M1 > M2. later(date(Y1, _, _), date(Y2, _, _)) :- Y1 > Y2. We note that if year and month are the same, all three rules are tried while backtracking. This could be prevented by adding cuts:later(date(Y, M, D1), date(Y, M, D2)) :- D1 > D2, ! . later(date(Y, M1, _), date(Y, M2, _)) :- M1 > M2, ! . later(date(Y1, _, _), date(Y2, _, _)) :- Y1 > Y2. This would increase efficiency by eliminating unnecessary backtracking, though it is doubtful if it would be worth bothering about, unless you actually have code that is running too slowly. In that case you should first do an analysis of where the time is being spent, before putting in cuts everywhere! <span style="background-color: white; color: black; font-family: Times,serif; font-size: 12pt;">In other cases, adding cuts of this sort to multi-rule procedures might be a useful (if lazy) way of ensuring that only one rule is used in a particular case. Unless it makes the code very clumsy, it is better to use and rely on "condition" goals in each rule (like M1 > M2 in the second rule for later) to specify the case in which it is appropriate. More examples of this are below.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Another cut example

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">max, without cut:% max(A, B, C) binds C to the larger of A and B. max(A, B, A) :- A > B. max(A, B, B) :- A =< B.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">max, with cut:max(A, B, A) :- A > B, ! . max(A, B, B).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The first version has a negated test in the second rule ( = ). The second version substitutes a cut in the first rule for the negated test.
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;"> Remember, no cuts in the first assignment unless they are essential! Hint: the first assignment can be done without cuts.

<span style="color: black; font-family: Times,serif; font-size: 12pt;"><span style="background-color: white; color: red; font-family: Helvetica,sans-serif; font-size: 13pt;">Another cut example 2

 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">remove_dups, without cut:remove_dups([], []). remove_dups([First | Rest], NewRest) :- member(First, Rest), remove_dups(Rest, NewRest). remove_dups([First | Rest], [First | NewRest]) :- not(member(First, Rest)), remove_dups(Rest, NewRest).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">remove_dups, with cut:remove_dups([], []). remove_dups([First | Rest], NewRest) :- member(First, Rest), !, remove_dups(Rest, NewRest). remove_dups([First | Rest], [First | NewRest]) :- remove_dups(Rest, NewRest).
 * <span style="color: black; font-family: Times,serif; font-size: 12pt;">The first version has a negated test in the third rule ( not(member(First, Rest)) ). The second version substitutes a cut in the second rule for the negated test in the third rule.


 * **Summary:** Introduction to Prolog ||
 * We have introduced facts, queries, variables, conjunctions of goals, rules, structures, recursion, trees and lists, and controlling execution by means of the "cut". ||

<span style="color: black; display: block; font-family: Times,serif; font-size: 12pt; text-align: center;">CRICOS Provider Code No. 00098G Last updated on: 24 June 2011 Copyright © Bill Wilson, 1996-2011, except where another source is acknowledged: much of the material in these notes is based on an earlier edition by Claude Sammut. Certain improvements are due to Maurice Pagnucco. Images of Bratko, Kowalski, and Colmerauer were obtained from Google Images.