1 / 25

8. Higher Order Predicates

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 . Higher Order Predicates in PROLOG. PROLOG implements a subset of classical logic.

triage
Download Presentation

8. Higher Order Predicates

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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.

  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.

  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.

  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.

  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.

  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 | ?-

  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 = [_,_, ... ,_] | ?-

  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.

  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.

  10. Sets vs. Bags • Using bagof 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.

  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 | ?-

  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.

  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.

  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.

  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.

  16. asserting 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 | ?-

  17. asserting 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.

  18. asserting 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 asserting a rule. • asserted rules can be very memory hungry in some PROLOG systems (for example, in GNU PROLOG).

  19. retracting 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 retracting a rule. • To retract a fact or rule it must be listed in full.

  20. retracting 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 asserted at run time. Some PROLOGs will allow predicates from the original database to be retracted as well. • retract doesn’t affect the program on disk.

  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 | ?-

  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.

  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 asserted at run time. • With some PROLOG systems, a bug can be caused by a call of a fact or a rule which does exist in the original program but which was retracted at run time. • asserta, assertz and retract are less declarative than the C++ goto statement. • asserta, assertz, retract, =.. and call are extremely powerful constructs. They should be used with caution. • Caution = Don’t use them unless you have to.

  24. Summary • findall, bagof and setof return all the successful answers for a query. findall(Term[V], Query[V], L) • Term[V] is the selector term. • Query[V] is the generator query. • L is the result list. • bagof and setof have the same argument format as findall. • setof orders its results and removes duplicates. findall and bagof do not. • _ doesn’t work properly with setof and bagof. Must use the all values construct.

  25. Summary II • =.., call, asserta, assertz and retract allow us to write self modifying code. • =.. converts its list argument into a structure. • call treats its structure argument as a goal and solves it. • asserta treats its structure argument as a clause and adds it to the start of the database. • assertz treats its structure argument as a clause and adds it to the end of the database. • retract treats its structure argument as a clause and removes it from the database. • Using GNU PROLOG we can only retract clauses asserted at run time. • Self modifying code is dangerous.

More Related