07/10/04 AIPP Lecture 5: List Processing1 List Processing Artificial Intelligence Programming in Prolog Lecturer: Tim Smith Lecture 5 07/10/04.

Slides:



Advertisements
Similar presentations
Artificial Intelligence: Natural Language and Prolog
Advertisements

Formal Models of Computation Part II The Logic Model
Declarative Programming Lists in PROLOG Autumn 2014.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 6: More Lists Theory –Define append/3, a predicate for concatenating two lists, and illustrate.
LING 388: Language and Computers Sandiway Fong Lecture 5: 9/5.
Introduction to PROLOG ME 409 Lab - 1. Introduction to PROLOG.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Lecture 6: More Lists Theory –Define append/3, a predicate for concatenating two lists, and illustrate.
11/10/04 AIPP Lecture 6: Built-in Predicates1 Combining Lists & Built-in Predicates Artificial Intelligence Programming in Prolog Lecturer: Tim Smith Lecture.
Prolog: List © Patrick Blackburn, Johan Bos & Kristina Striegnitz.
Prolog The language of logic. History Kowalski: late 60’s Logician who showed logical proof can support computation. Colmerauer: early 70’s Developed.
1 Introduction to Prolog References: – – Bratko, I., Prolog Programming.
1 Logic Programming. 2 A little bit of Prolog Objects and relations between objects Facts and rules. Upper case are variables. parent(pam, bob).parent(tom,bob).
About prolog  History  Symbolic Programming Language  Logic Programming Language  Declarative Programming Language.
For Friday Read “lectures” 1-5 of Learn Prolog Now: prolog-now/
Recursion Great fleas have little fleas upon their backs to bite 'em, And little fleas have lesser fleas, and so ad infinitum. And the great fleas themselves,
Constraint Logic Programming Ryan Kinworthy. Overview Introduction Logic Programming LP as a constraint programming language Constraint Logic Programming.
16-Jun-15 Recursion. 2 Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example:
LING 388: Language and Computers Sandiway Fong Lecture 4: 8/31.
LING 388: Language and Computers Sandiway Fong Lecture 3: 8/29.
Recursion.
28-Jun-15 Recursion. 2 Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example:
Recursion Chapter 7. Chapter 7: Recursion2 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method To learn.
Recursion Chapter 7. Chapter 7: Recursion2 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method To learn.
Recursion. Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example: A list.
Conditionals and Recursion "To iterate is human, to recurse divine." - L. Peter Deutsch.
Formal Models of Computation Part II The Logic Model
CS 321 Programming Languages and Compilers Prolog part 2.
Evolution of Programming Languages Generations of PLs.
Recursion Chapter 7. Chapter Objectives  To understand how to think recursively  To learn how to trace a recursive method  To learn how to write recursive.
COP4020 Programming Languages Logical programming with Prolog Prof. Xin Yuan.
CS 403: Programming Languages Lecture 19 Fall 2003 Department of Computer Science University of Alabama Joel Jones.
1 CS 177 Week 16 Recitation Recursion. 2 Objective To understand and be able to program recursively by breaking down a problem into sub problems and joining.
Chapter 13 Recursion. Learning Objectives Recursive void Functions – Tracing recursive calls – Infinite recursion, overflows Recursive Functions that.
14/10/04 AIPP Lecture 7: The Cut1 Controlling Backtracking: The Cut Artificial Intelligence Programming in Prolog Lecturer: Tim Smith Lecture 7 14/10/04.
30/09/04 AIPP Lecture 3: Recursion, Structures, and Lists1 Recursion, Structures, and Lists Artificial Intelligence Programming in Prolog Lecturer: Tim.
15/11/04 AIPP Lecture 14: Database Manipulation1 Database Manipulation Artificial Intelligence Programming in Prolog Lecturer: Tim Smith Lecture 14 15/11/04.
CSIS 123A Lecture 9 Recursion Glenn Stevenson CSIS 113A MSJC.
For Wednesday Read “lectures” 7-10 of Learn Prolog Now Chapter 9, exs 4 and 6. –6 must be in Horn clause form Prolog Handout 2.
Introduction To PROLOG World view of imperative languages. World view of relational languages. A PROLOG program. Running a PROLOG program. A PROLOG.
Functional Programming With examples in F#. Pure Functional Programming Functional programming involves evaluating expressions rather than executing commands.
1 Knowledge Based Systems (CM0377) Lecture 3 (Last modified 5th February 2001)
1 Prolog and Logic Languages Aaron Bloomfield CS 415 Fall 2005.
CMP-MX21: Lecture 5 Repetitions Steve Hordley. Overview 1. Repetition using the do-while construct 2. Repetition using the while construct 3. Repetition.
Logic Programming and Prolog Goal: use formalism of first-order logic Output described by logical formula (theorem) Input described by set of formulae.
Ch. 13 Ch. 131 jcmt CSE 3302 Programming Languages CSE3302 Programming Languages (notes?) Dr. Carter Tiernan.
Introduction to Loops Iteration Repetition Counting Loops Also known as.
Negation Chapter 5. Stating Negative Conditions n Sometimes you want to say that some condition does not hold n Prolog allows this –not/1this is a predicate.
Lists in Prolog Sections 3.1, 3.2. Lists n List = sequence of values –[1, 2, 3, 4, 5] –[bob, brian, cathy, mark, david, loretta] –[birds(4, calling),
LING/C SC/PSYC 438/538 Lecture 15 Sandiway Fong. Did you install SWI Prolog?
Lecture course: Heuristics & Prolog for Artificial Intelligence Applications Notes on Prolog from Professor Bruce Batchelor, DSc.
In The Name Of Allah Lab 03 1Tahani Aldweesh. objectives Searching for the solution’s. Declaration. Query. Comments. Prolog Concepts. Unification. Disjunction.
1 Artificial Intelligence CS370D Prolog programming List operations.
For Friday No reading Prolog Handout 2. Homework.
Prolog 3 Tests and Backtracking 1. Arithmetic Operators Operators for arithmetic and value comparisons are built-in to Prolog = always accessible / don’t.
Recursion. Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example: A list.
From Conventional Languages to Prolog –What we can do in conventional languages but not in Prolog –What we can do in Prolog but not in conventional languages.
Prolog Fundamentals. 2 Review Last Lecture A Prolog program consists of a database of facts and rules, and queries (questions). –Fact:.... –Rule:... :-....
CS 116 Object Oriented Programming II Lecture 13 Acknowledgement: Contains materials provided by George Koutsogiannakis and Matt Bauer.
COSC 2P93 Prolog: Debugging
Recursion Topic 5.
For Friday No reading Prolog handout 3 Chapter 9, exercises 9-11.
For Wednesday Read “lectures” 7-10 of Learn Prolog Now:
Tests, Backtracking, and Recursion
Prolog Lists.
Programming Paradigms and Languages
Prolog Lists.
Programming Techniques
Chapter 13 Recursion Copyright © 2010 Pearson Addison-Wesley. All rights reserved.
Presentation transcript:

07/10/04 AIPP Lecture 5: List Processing1 List Processing Artificial Intelligence Programming in Prolog Lecturer: Tim Smith Lecture 5 07/10/04

AIPP Lecture 5: List Processing2 Identifying a list Last lecture we introduced lists: [a,[],green(bob)] We said that lists are recursively defined structures: “An empty list, [ ], is a list. A structure of the form [X, …] is a list if X is a term and […] is a list, possibly empty.” This can be tested using the Head and Tail notation, [H|T], in a recursive rule. is_a_list([]).  A term is a list if it is an empty list. is_a_list([_|T]):-  A term is a list if it has two is_a_list(T). elements and the second is a list.

07/10/04AIPP Lecture 5: List Processing3 Base and Recursive Cases A recursive definition, whether in prolog or some other language (including English!) needs two things. A definition of when the recursion terminates. –Without this the recursion would never stop! –This is called the base case: is_a_list([]). –Almost always comes before recursive clause A definition of how we can define the problem in terms of a similar, smaller problem. –This is called the recursive case : is_a_list([_|T]):- is_a_list(T). There might be more than one base or recursive case.

07/10/04AIPP Lecture 5: List Processing4 Focussed Recursion To ensure that the predicate terminates, the recursive case must move the problem closer to a solution. –If it doesn’t it will loop infinitely. With list processing this means stripping away the Head of a list and recursing on the Tail. is_a_list([_|T]):- is_a_list(T). The same focussing has to occur when recursing to find a property or fact. is_older(Ancestor,Person):- is_older(Someone,Person), is_older(Ancestor,Someone). Doesn’t focus Head is replaced with an underscore as we don’t want to use it.

07/10/04AIPP Lecture 5: List Processing5 Focussed Recursion (2) Given this program: parent(tom,jim). parent(mary,tom). is_older(Old,Young):- parent(Old,Young). is_older(Ancestor,Young):- is_older(Someone,Young), is_older(Ancestor,Someone). A query looking for all solutions will loop. | ?-is_older(X,Y). X = tom, Y = jim ? ; X = mary, Y = tom ? ; X = mary, Y = jim ? ; *loop* It loops because the recursive clause does not focus the search it just splits it. If the recursive is_older/2 doesn’t find a parent it just keeps recursing on itself

07/10/04AIPP Lecture 5: List Processing6 Focussed Recursion (3) The correct program: parent(tom,jim). parent(mary,tom). is_older(Old,Young):- parent(Old,Young). is_older(Ancestor,Young):- parent(Someone,Young), is_older(Ancestor,Someone). Can generate all valid matches without looping. | ?-is_older(X,Y). X = tom, Y = jim ? ; X = mary, Y = tom ? ; X = mary, Y = jim ? ; no To make the problem space smaller we need to check that Young has a parent before recursion. This way we are not looking for something that isn’t there.

07/10/04AIPP Lecture 5: List Processing7 List Processing Predicates: Member/2 Member/2 is possibly the most used user-defined predicate (i.e. you have to define it every time you want to use it!) It checks to see if a term is an element of a list. –it returns yes if it is –and fails if it isn’t. | ?- member(c,[a,b,c,d]). yes member(H,[H|_]). member(H,[_|T]):- member(H,T). It 1 st checks if the Head of the list unifies with the first argument. If yes then succeed. If no then fail first clause. The 2 nd clause ignores the head of the list (which we know doesn’t match) and recurses on the Tail.

07/10/04AIPP Lecture 5: List Processing8 |?- member(ringo,[john,paul,ringo,george]). Fail(1): member(ringo,[john|_]). (2): member(ringo,[_|paul,ringo,george]):- Call: member(ringo,[paul,ringo,george]). Fail(1): member(ringo,[paul|_]). (2): member(ringo,[_|ringo,george]):- Call: member(ringo,[ringo,george]). Succeed(1): member(ringo,[ringo|_]]). List Processing Predicates: Member/2 1) member(H,[H|_]). 2) member(H,[_|T]):- member(H,T).

07/10/04AIPP Lecture 5: List Processing9 Quick Aside: Tracing Prolog To make Prolog show you its execution of a goal type trace. at the command line. –Prolog will show you: which goal is Call ed with which arguments, whether the goal succeeds ( Exit ), has to be Redo ne, or Fail s. –The tracer also indicates the level in the search tree from which a goal is being called. The number next to the goal indicates the level in the tree (top level being 0). The leftmost number is the number assigned to the goal (every new goal is given a new number). To turn off the tracer type notrace.

07/10/04AIPP Lecture 5: List Processing10 | ?- trace. | ?- member(ringo,[john,paul,ringo,george]). 11 Call: member(ringo,[john,paul,ringo,george]) ? 22 Call: member(ringo,[paul,ringo,george]) ? 33 Call: member(ringo,[ringo,george]) ? 33 Exit: member(ringo,[ringo,george]) ? 22 Exit: member(ringo,[paul,ringo,george]) ? 11 Exit: member(ringo,[john,paul,ringo,george]) ? yes | ?- member(stuart,[john,paul,ringo,george]). 11 Call: member(ringo,[john,paul,ringo,george]) ? 22 Call: member(ringo,[paul,ringo,george]) ? 33 Call: member(ringo,[ringo,george]) ? 44 Call: member(stuart,[george]) ? 55 Call: member(stuart,[]) ?  [ ] does not match [H|T] 55 Fail: member(stuart,[]) ? 44 Fail: member(stuart,[george]) ? 33 Fail: member(ringo,[ringo,george]) ? 22 Fail: member(ringo,[paul,ringo,george]) ? 11 Fail: member(ringo,[john,paul,ringo,george]) ? no Tracing Member/2

07/10/04AIPP Lecture 5: List Processing11 Collecting Results When processing data in Prolog there are three ways to collect the results: 1.Compute result at base case first, then use this result as you backtrack through the program. 2.Accumulate a result as you recurse into the program and finalise it at the base case. 3.Recurse on an uninstantiated variable and accumulate results on backtracking. These all have different uses, effect the order of the accumulated data differently, and require different degrees of processing.

07/10/04AIPP Lecture 5: List Processing12 We want to define a predicate, length/2, which takes a list as its first argument and returns a number as the second argument that is equal to the length of the list. We can use recursion to move through the list element by element and is/2 to count as it goes. To make a counter we need to initialise it at a value i.e. zero. As the counter increases during backtracking it needs to be initialised in the base case. Compute lower result first. listlength([_|T],N1):- listlength(T,N), N1 is N+1. listlength([],0).

07/10/04AIPP Lecture 5: List Processing13 Compute lower result first: trace. listlength([],0). listlength([_|T],N1):- listlength(T,N), N1 is N+1. | ?- listlength([a,b,c],N). 1 1 Call: listlength([a,b,c],_489) ? 2 2 Call: listlength([b,c],_1079) ? 3 3 Call: listlength([c],_1668) ? 4 4 Call: listlength([],_2257) ? 4 4 Exit: listlength([],0) ? 5 4 Call: _1668 is 0+1 ? 5 4 Exit: 1 is 0+1 ? 3 3 Exit: listlength([c],1) ? 6 3 Call: _1079 is 1+1 ? 6 3 Exit: 2 is 1+1 ? 2 2 Exit: listlength([b,c],2) ? 7 2 Call: _489 is 2+1 ? 7 2 Exit: 3 is 2+1 ? 1 1 Exit: listlength([a,b,c],3) ? N = 3 ? yes

07/10/04AIPP Lecture 5: List Processing14 Why compute lower result first? |?-listlength([a,b,c],0). 1 Call: listlength([a,b,c],0) ? 2 2 Call: _1055 is 0+1 ? 2 2 Exit: 1 is 0+1 ? 3 2 Call: listlength([b,c],1) ? 4 3 Call: _2759 is 1+1 ? 4 3 Exit: 2 is 1+1 ? 5 3 Call: listlength([c],2) ? 6 4 Call: _4463 is 2+1 ? 6 4 Exit: 3 is 2+1 ? 7 4 Call: listlength([],3) ? 7 4 Exit: listlength([],3) ? 5 3 Exit: listlength([c],2) ? 3 2 Exit: listlength([b,c],1) ? 1 1 Exit: listlength([a,b,c],0)? yes listlength([],0). listlength([_|T],N1):- N1 is N+1, listlength(T,N). listlength([],_). listlength([_|T],N):- N1 is N+1, listlength(T,N1). |?-listlength([a,b,c],N). Instantiation error in is/2 fail

07/10/04AIPP Lecture 5: List Processing15 Using an Accumulator You can also accumulate results as you recurse into the program, finalising the result at the base. Once the result is finalised we need someway of getting it back out of the program. listlength([],Acc,Acc). listlength([_|T],Acc,Out):- Acc1 is Acc+1, listlength(T,Acc1,Out). Finalise result. Increase Accumulator as we recurse Instantiate result to Output variable in base case and pass back.

07/10/04AIPP Lecture 5: List Processing16 Using an Accumulator (2) listlength([a,b,c],0,N). 1 1 Call: listlength([a,b,c],0,_501) ? 2 2 Call: _1096 is 0+1 ? 2 2 Exit: 1 is 0+1 ? 3 2 Call: listlength([b,c],1,_501) ? 4 3 Call: _2817 is 1+1 ? 4 3 Exit: 2 is 1+1 ? 5 3 Call: listlength([c],2,_501)? 6 4 Call: _4538 is 2+1 ? 6 4 Exit: 3 is 2+1 ? 7 4 Call: listlength([],3,_501) ? 7 4 Exit: listlength([],3,3) ? 5 3 Exit: listlength([c],2,3) ? 3 2 Exit: listlength([b,c],1,3) ? 1 1 Exit: listlength([a,b,c],0,3) ? N = 3 ? yes listlength([],A,A). listlength([_|T],A,O):- A1 is A+1, listlength(T,A1,O).

07/10/04AIPP Lecture 5: List Processing17 Using an auxiliary predicate When using an accumulator it needs to be initialised at the right value (e.g. [] or 0). Make the predicate with the accumulator an auxiliary to the predicate that the user will call. This ensures that the accumulator is initialise correctly and that the user doesn’t have to understand the workings of your code to use it. listlength(List,Length):- listlength2(List,0,Length). listlength2([],A,A). listlength2([_|T],A,O):- A1 is A+1, listlength2(T,A1,O). Auxiliary to main predicate Initialise Accumulator

07/10/04AIPP Lecture 5: List Processing18 Combining lists A common use of an accumulator is to construct lists. If we want to make a new list out of the combined elements of two lists we can’t just make one list the Head of a new list and the other the tail as: | ?- L1=[a,b], L2=[c,d], Z=[L1|L2]. L1 = [a,b], L2 = [c,d], Z = [[a,b],c,d] ? We need to take each element from L1 and add them to L2 one at a time. There are two ways we can do this –during recursion, or –backtracking.

07/10/04AIPP Lecture 5: List Processing19 |?- pred([a,b],[c,d],Out). Out = [a,b,c,d]. To add L1 to L2 during recursion we can use the bar notation to decompose L1 and add the Head to L2. pred([H|T],L2,Out):- pred(T,[H|L2],Out). We need to have an extra variable ( Out ) which can be used to pass back the new list once L1 is empty. pred([],L2,L2).  base case: when L1 is empty make the new list equal to the Output list. The base case must go before the recursive case. Desired behaviour Constructing a list during Recursion Accumulator

07/10/04AIPP Lecture 5: List Processing20 | ?- pred([a,b],[c,d],Out). 1 1 Call: pred([a,b],[c,d],_515) ? 2 2 Call: pred([b],[a,c,d],_515) ? 3 3 Call: pred([],[b,a,c,d],_515) ? 3 3 Exit: pred([],[b,a,c,d],[b,a,c,d]) ? 2 2 Exit: pred([b],[a,c,d],[b,a,c,d]) ? 1 1 Exit: pred([a,b],[c,d],[b,a,c,d]) ? Out = [b,a,c,d] ? yes pred([],L2,L2). pred([H|T],L2,Out):- pred(T,[H|L2],Out). If you construct a list through recursion (on the way down) and then pass the answer back the elements will be in reverse order. Constructing a list during Recursion (2) Always the same variable

07/10/04AIPP Lecture 5: List Processing21 reverse/3 | ?- pred([a,b],[c,d],Out). 1 1 Call: pred([a,b],[c,d],_515) ? 2 2 Call: pred([b],[a,c,d],_515) ? 3 3 Call: pred([],[b,a,c,d],_515) ? 3 3 Exit: pred([],[b,a,c,d],[b,a,c,d]) ? 2 2 Exit: pred([b],[a,c,d],[b,a,c,d]) ? 1 1 Exit: pred([a,b],[c,d],[b,a,c,d]) ? Out = [b,a,c,d] ? yes reverse([],L2,L2). reverse([H|T],L2,Out):- reverse(T,[H|L2],Out). If you construct a list through recursion (on the way down) and then pass the answer back the elements will be in reverse order.

07/10/04AIPP Lecture 5: List Processing22 To maintain the order of list elements we need to construct the list on the way out of the program, i.e. through backtracking. Use the same bar deconstruction as before but add the head element of L1 to Out in the Head of the clause. pred([H|T],L2,[H|Out]):-  Head is not added pred(T,L2,Out). until backtracking. Now when we reach the base case we make L2 the foundation for the new Out list and add our L1 elements to it during backtracking. pred([],L2,L2).  base case: when L1 is empty make the new list equal to the Output list. Constructing a list in backtracking

07/10/04AIPP Lecture 5: List Processing23 append/3 | ?- pred2([a,b],[c,d],Out). 1 1 Call: pred2([a,b],[c,d],_515) ? 2 2 Call: pred2([b],[c,d],_1131) ? 3 3 Call: pred2([],[c,d],_1702) ? 3 3 Exit: pred2([],[c,d],[c,d]) ? 2 2 Exit: pred2([b],[c,d],[b,c,d]) ? 1 1 Exit: pred2([a,b],[c,d],[a,b,c,d]) ? Out = [a,b,c,d] ? yes append([],L2,L2). append([H|T],L2,[H|Rest]):- append(T,L2,Rest). * append/3 is another very common user-defined list processing predicate. Variable changes at every Call.

07/10/04AIPP Lecture 5: List Processing24 append([],L2,L2). append([H|T],L2,[H|Rest]):- append(T,L2,Rest). Computing in reverse Both reverse/3 and append/3 can be used backwards to make two lists out of one. This can be a useful way to strip lists apart and check their contents. | ?- append(X,Y,[a,b,c,d]). X = [], Y = [a,b,c,d] ? ; X = [a], Y = [b,c,d] ? ; X = [a,b], Y = [c,d] ? ; X = [a,b,c], Y = [d] ? ; X = [a,b,c,d], Y = [] ? ; no |?-append(X,[c,d],[a,b,c,d]). X = [a,b] ? ; no

07/10/04AIPP Lecture 5: List Processing25 reverse([],L2,L2). reverse([H|T],L2,Out):- reverse(T,[H|L2],Out). Computing in reverse Both reverse/3 and append/3 can be used backwards to make two lists out of one. This can be a useful way to strip lists apart and check their contents. | ?- reverse(X,Y,[a,b,c,d]). X = [], Y = [a,b,c,d] ? ; X = [a], Y = [b,c,d] ? ; X = [b,a], Y = [c,d] ? ; X = [c,b,a], Y = [d] ? ; X = [d,c,b,a], Y = [] ? ; *loop* |?-reverse([d,c,b,a],Y,[a,b,c,d]). Y = [] ? yes

07/10/04AIPP Lecture 5: List Processing26 Summary Base and recursive cases Using focused recursion to stop infinite loops. List processing through recursion: member/2 Introduced the Prolog tracer. Showed three techniques for collecting results: –Recursively find a result, then revise it at each level. listlength/3 –Use an accumulator to build up result during recursion. reverse/3 –Build result in the head of the clause during backtracking. append/3