8.1 8. Higher Order Predicates Higher order predicates in PROLOG. Higher order declarative predicates : – findall – bagof – setof – =.. Higher order non-declarative

  • View
    213

  • Download
    1

Embed Size (px)

Text of 8.1 8. Higher Order Predicates Higher order predicates in PROLOG. Higher order declarative...

  • Slide 1

8.1 8. Higher Order Predicates Higher order predicates in PROLOG. Higher order declarative predicates : findall bagof setof =.. Higher order non-declarative predicates : call. asserta, assertz. retract. Slide 2 8.2 Higher Order Predicates in PROLOG PROLOG implements a subset of classical logic. Horn Clause Predicate Calculus. Can only write facts and rules about terms. Cannot have facts and rules about predicates. PROLOG also provides a set of predicates which operate on other predicates : higher order predicates. Some are declarative : findall, bagof, setof, =... Some are not : call, asserta, assertz, retract. Slide 3 8.3 Back To The Romans Suppose we have the following database : consul(metellus, 80). consul(sulla, 80). consul(cicero, 63). consul(antonius, 63). consul(caesar, 59). consul(bibulus, 59). consul(pompeius, 55). consul(crassus, 55). consul(ahenobarabus,54). consul(pulcher, 54). consul(pompeius, 52). consul(metellus, 52). consul(caesar, 48). consul(servilius,48). consul(caesar, 46). consul(lepidus, 46). consul(caesar, 45). consul(caesar, 44). consul(antonius, 44). consul(pansa, 43). consul(octavius, 43). Some of the Consuls of the late Roman republic. Supposed to be two each year. Julius Caesar was sole Consul in 45BC. Julius Caesar was an unusual man. Slide 4 8.4 Finding Consuls Easy to write queries about Consuls : | ?- consul(C, _). C = metellus ; C = sulla ; C = cicero yes | ?- consul(C, 59). C = caesar ; C = bibulus ; no | ?- By using ; to force backtracking we can find all the Consuls in the database. A bit tedious. More convenient to have PROLOG give us all the answers at once in a list structure. Slide 5 8.5 Using findall The higher order predicate findall allows us to get all the answers at once. | ?- findall(C, consul(C, _), L). L = [metellus,..., octavius] | ?- findall(C, consul(C, 59), L). L = [caesar, bibulus] yes | ?- Instantiate L to be the list of all values of C for which the query (the second parameter of findall ) is true. If there are no such values then instantiate L to be the empty list. Slide 6 8.6 findall More Formally In general findall(Term[V], Query[V], L). means instantiate L to be the list of values of Term[V] for which the query Query[V] is true. If there are no such values then L is instantiated to []. Term[V] is an arbitrary term containing the logical variable V. Query[V] is an arbitrary query containing the logical variable V. | ?- findall([C,was,in,59,bc],consul(C,59),L). L = [[caesar,was,in,59,bc], [bibulus,was,in,59,bc]] yes | ?- Slide 7 8.7 findall More Formally II Term[V] is the selector term. Query[V] is the generator query. L is the result list. The selector term is often just a single logical variable but it can be any term. The variable in the selector does not have to appear in the generator. Not much point doing that though. The results are (usually) not useful. Using GNU PROLOG : | ?- findall(X,consul(C,_),L). L = [_,_,...,_] | ?- Slide 8 8.8 bagof and setof findall is actually a generalisation of two other higher-order predicates : bagof and setof. | ?- bagof(W, consul(caesar, W), L). W = [59,48,46,45,44] | ?- setof(W, consul(caesar, W), L). W = [44,45,46,48,59] | ?- bagof(C, consul(C, _), L). L = [pansa,octavius] ? ; L = [caesar,antonius] ? yes | ?- setof(C, consul(C, _), L). L = [octavius,pansa] ? ; L = [antonius,caesar] ? yes | ?- _ does not work properly with bagof or setof. Slide 9 8.9 The All Values Construct bagof and setof produce a separate solution for each of the different values of the second argument to consul even if the second argument is _. To make bagof and setof collect all the values regardless of the values of the parameters not mentioned in the selector term we must use ^. | ?- bagof(C,When^consul(C,When),L). L = [metellus,..., octavius] yes | ?- setof(C,When^consul(C,When),L). L = [ahenobarabus,..., sulla] yes | ?- setof produces its results in < order and with duplicates removed. Slide 10 8.10 Sets vs. Bags Using bago f the same answer may appear several times in the result list. e.g. Caesar was Consul several times. A bag is a mathematical concept meaning a collection of things. A set is a mathematical concept meaning a collection of things without duplicates. In mathematics a set is unordered. In PROLOG setof always orders its results since this makes removing duplicates easier. The ordering is almost always the ordering you would expect. Numerical for numbers. Lexicographical for alphanumerics. Slide 11 8.11 setof, bagof and findall If there are no values for which the generator term succeeds then findall succeeds and binds the result list to []. setof and bagof will fail in this case. | ?- findall(C,consul(C,79),L). L = [] yes | ?- bagof(C,consul(C,79),L). no | ?- setof(C,consul(C,79),L). no | ?- Slide 12 8.12 setof, bagof and findall II findall, bagof and setof will not work if the generator query is a logical variable. PROLOG cannot perform higher order matching. findall, bagof and setof are functional rather than relational. Still declarative though. | ?- findall(1, Q, [1]). uncaught exception :... | ?- findall, bagof and setof are similar to the list comprehension operators found in functional programming languages. Slide 13 8.13 Making Structures From Lists | ?- T =.. [consul, X, Y]. T = consul(X, Y). yes | ?- =.. converts its right hand argument from a list into a structure. The first element is used as the functor. The rest of the elements are the components. The structure is then matched with the left hand argument. =.. is declarative (but not relational). However, it is often used with call which is not declarative. Slide 14 8.14 Making Goals From Lists | ?- T =.. [consul, X, Y], call(T). T = consul(metellus, 80) X = metellus Y = 80 ; T = consul(sulla, 80) X = sulla Y = 80 yes | ?- The argument of call can be any structure. call treats the structure as a goal (i.e. a query) and solves it. Seems a lot of trouble to go to just to solve consul(X, Y). The pay off is that we can use =.. and call to evaluate any arbitrary list as a goal. e.g. a list generated by a previous goal. We can generate goals to solve as the program runs. Slide 15 8.15 Making Goals From Lists II In effect, we can write programs that compute goals for themselves as they go on. Very useful in AI where programs must exhibit adaptive behaviour. This can make debugging somewhat difficult : a program could produce incorrect results, or even crash, by attempting to solve a goal which did not exist in the text of the program when it was written. To make debugging even more fun PROLOG allows programs to actually add and remove predicates as they run by using the asserta, assertz and retract higher order predicates. Slide 16 8.16 assert ing Facts | ?- move(A, B). uncaught exception :... | ?- assertz(move(newcastle, durham)). yes | ?- move(A, B). A = newcastle B = durham ; no | ?- assertz(move(durham, sunderland)). yes | ?- move(A,B). A = newcastle B = durham ; A = durham B = sunderland ; no | ?- Slide 17 8.17 assert ing Facts II Initially there are no predicates about move in the database so the query causes an exception. We then use assertz to add the clause move(newcastle,durham) to the end of the database. The query now succeeds once. We then use assertz to add the clause move(durham, sunderland) to the end of the database. The query now succeeds twice. The two new facts are added to the database held within GNU PROLOG. The copy on disk is unaffected. In contrast, call does not modify the database. It throws away the goal once it has been solved. Slide 18 8.18 assert ing Rules | ?- assertz((move(X,Y):-move(X,Z),move(Z,Y))). yes | ?- move(A, B). A = newcastle B = durham ; A = durham B = sunderland ; A = newcastle B = sunderland ; yes | ?- Note that an extra pair of brackets are required when assert ing a rule. assert ed rules can be very memory hungry in some PROLOG systems (for example, in GNU PROLOG). Slide 19 8.19 retract ing Predicates Predicates can be removed from the database using retract. | ?- retract((move(X,Y):-move(X,Z),move(Z,Y))). yes | ?- move(A, B). A = newcastle B = durham ; A = durham B = sunderland yes | ?- Note that an extra pair of brackets are required when retract ing a rule. To retract a fact or rule it must be listed in full. Slide 20 8.20 retract ing Predicates II | ?- retract((move(durham,sunderland))). yes | ?- move(A, B). A = newcastle B = durham yes | ?- retract((consul(pansa,43)). uncaught exception :... | ?- GNU PROLOG only lets us retract predicates which we have assert ed at run time. Some PROLOGs will allow predicates from the original database to be retract ed as well. retract doesnt affect the program on disk. Slide 21 8.21 Using =.. With assert And retract Can use =.. to convert an arbitrary (i.e. program generated) list into a structure and then either assert or retract it. | ?- T =.. [move,london,newcastle], assertz(T). T = move(london,newcastle) yes | ?- move(A, B). A = newcastle B = durham ; A = london B = newcastle yes | ?- T =.. [move,newcastle,durham], retract(T). T = move(newcastle,durham) yes | ?- move(A, B). A = london B = newcastle yes | ?- Slide 22 8.22 Self Modifying Code : Advantages Using =.., asserta, assertz and retract we can write self modifying code. Code that changes its behaviour as it runs. This is very useful for AI systems as it supports adaptive behaviour. A similar facility is provided in LISP via the eval function. asserta, assertz and retract can be used in the same way as any other predicate. In particular, you can put calls to them in the rules in your program. Very flexible. Very powerful. Slide 23 8.23 Self Modifying Code : Disadvantages call is bad enough for debugging : a bug can be caused by a call of a goal which is not in the original program. asserta, assertz and retract are even worse. A bug can be caused by a fact or a rule which does not exist in the original program but which was assert ed at run time. With so