Dave Reed more Prolog test vs find builtin
Dave Reed more Prolog § test vs. find § built-in predicates list operations: member, append, nth 0, reverse, … not, default vs. logical negation comparison operators, arithmetic § user-defined operators position, precedence, associativity
Test vs. find Prolog programs define relations: § § query w/ constants: "test" whether relation holds between the constants query w/ variables: "find" values for which the relation holds ? - member(X, [a, b, c]). X = a ; X = b ; with a variable as first argument, the query is used to "find" members of the given list X = c ; No ? - member(a, X). X = [a|_G 260] ; X = [_G 259, a|_G 262] Yes with a variable as the second argument, the query is used to "find" lists that have the given item as member ? - member(X, Y). X = _G 209 Y = [_G 209|_G 270] ; X = _G 209 Y = [_G 275, _G 209|_G 278] Yes with both variables, the query is used to "find" general schemas for list membership
Append predicate another useful predefined predicate for list manipulation append(L 1, L 2, L 3): L 3 is the result of ? - append([a, b], [c, d], L). L = [a, b, c, d] placing the items in L 1 at the front of L 2 Yes can be used in reverse to partition a list ? - append(L 1, L 2, [a, b, c, d]). L 1 = [] L 2 = [a, b, c, d] ; again, we could define append ourselves: append([], L, L). append([H|T], L, [H|A]) : append(T, L, A). as we saw with ancestor example, clause ordering is important with recursive definitions § if put rule first, infinite loop possible L 1 = [a] L 2 = [b, c, d] ; L 1 = [a, b] L 2 = [c, d] ; L 1 = [a, b, c] L 2 = [d] ; L 1 = [a, b, c, d] L 2 = [] ; No
Other list predicates is_list(Term): succeeds if Term is a list length(List, Len): Len is the number of items in List nth 0(Index, List, Item): Item is the item at index Index of List(starting at 0) nth 1(Index, List, Item): Item is the item at index Index of List(starting at 1) reverse(List, Rev. List): Rev. List is List with the items in reverse order delete(List, Item, New. List): New. List is the result of deleting every occurrence of Item from List select(Item, List, Remain): Remain is the List with an occurrence of Item removed ? - L = [a, b, c, d], length(L, Len), nth 1(Len, L, X). L = [a, b, c, d] Len = 4 X = d Yes ? - reverse([a, b, a, c], Rev), delete(Rev, a, Del). Rev = [c, a, b, a] Del = [c, b] Yes ? - select(a, [a, b, a, c], R). R = [b, a, c] ; R = [a, b, c] ; No ? - select(a, L, [b, c]). L = [a, b, c] ; L = [b, a, c] ; L = [b, c, a] ; No
? - is_list([]). not predicate Yes ? - not(is_list([])). No defines the (default) negation of conditional statements not ? - member(d, [a, b, c]). No ? - not(member(d, [a, b, c])). Yes ? - member(X, [a, b, c]). X = a Yes ? - not(member(X, [a, b, c])). No § when applied to relations with no variables, it is equivalent to logical negation ( ) § in reality, it returns the opposite of whatever its argument would return if X would succeed as a query, then not(X) fails if X would fail as a query, then not(X) succeeds ? - X = d, not(member(X, [a, b, c])). X = d Yes ? - not(member(X, [a, b, c])), X = d. No anything Prolog can't prove true it assumes to be false!
Programming exercises suppose we want to define a relation to test if a list is palindromic palindrome(List): succeeds if List is a list whose elements are the same backwards & forwards palindrome([]). palindrome(List) : - reverse(List, Rev), List = Rev. suppose we want to define relation to see if a list has duplicates has_dupes(List): succeeds if List has at least one duplicate element has_dupes([H|T]) : - member(H, T). has_dupes([_|T]) : - has_dupes(T). suppose we want the opposite relation, that a list has no dupes no_dupes(List): succeeds if List has no duplicate elements no_dupes(List) : - not( has_dupes(List) ).
Built-in comparison operators ? - foo = foo. Yes X = Y does more than test equality, it matches X with Y, instantiating variables if necessary ? - X = foo Yes determines whether X & Y are not X = Y unifiable ? - [H|T] = [a, b, c]. – for ground terms, this means inequality – can think of as: not(X = Y) – again, doesn't make a lot of sense for variables H = a T = [b, c] Yes ? - foo = bar. Yes ? - X = foo. No ? - 4+2 = 6. No Note: arithmetic operators (+, -, *, /) are not evaluated 4 + 2 +(4, 2) can force evaluation using 'is' ? - X = 4 + 2. ? - X is 4 + 2. X = 4+2 Yes X = 6 Yes
Arithmetic operations arithmetic comparisons automatically evaluate expressions X X X =: = Y == Y >= Y < Y =< Y X and Y must both be arithmetic expressions (no variables) ? - 12 =: = 6+6. Yes ? - X =: = 6+6. ERROR: Arguments are not sufficiently instantiated Example: sum_of_list(List. Of. Nums, Sum): Sum is the sum of numbers in List. Of. Nums sum_of_list([], 0). sum_of_list([H|T], Sum) : sum_of_list(T, Tail. Sum), Sum is H + Tail. Sum.
Programming exercise suppose we want to define relation to see how many times an item occurs in a list num_occur(Item, List, N): Item occurs N times in List num_occur(_, [], 0). num_occur(H, [H|T], num_occur(H, T, num_occur(H, [_|T], num_occur(H, T, N) : Tail. N), N is Tail. N+1. N) : Tail. N), N is Tail. N. is the first answer supplied by this relation correct? are subsequent answers obtained via backtracking correct?
User-defined operators it is sometimes convenient to write functors/predicates as operators predefined: +(2, 3) 2 + 3 user defined? likes(dave, cubs) dave likes cubs operators have the following characteristics § position of appearance prefix infix postfix e. g. , -3 e. g. , 2 + 3 e. g. , 5! § precedence 2 + 3 * 4 2 + (3 * 4) § associativity 8 – 5 - 2 8 – (5 – 2)
op new operators may be defined as follows : - op(Prec, Pos. Assoc, Name). Name is a constant Prec is an integer in range 0 – 1200 (lower number binds tighter) Pos. Assoc is a constant of the form xf, yf fx, fy xfx, xfy, yfx, yfy (postfix) (prefix) (infix) the location of f denotes the operator position x means only operators of lower precedence may appear here y allows operators of lower or equal precedence Example: : - op(300, xfx, likes).
Operator example %%% likes. pro likes(dave, cubs). likes(kelly, and(java, and(scheme, prolog))). : - op(300, xfx, likes). : - op(250, xfy, and). dave likes cubs. kelly likes java and scheme and prolog. ? - likes(dave, X). ? - dave likes X. X = cubs Yes ? - likes(Who, What). ? - Who likes What. Who = dave What = cubs ; Who = kelly What = and(java, and(scheme, prolog)) ; Who = kelly What = java and scheme and prolog ; No No by defining functors/predicates as operators, can make code more English-like
SWI-Prolog operators the following standard operators are predefined in SWI-Prolog to define new operators § Name & Type are easy § Precedence is tricky, must determine place in hierarchy Note: always define ops at top of the program (before use) 1200 xfx -->, : - 1200 fx : -, ? - 1150 fx dynamic, multifile, module_transparent, discontiguous, volatile, initialization 1100 xfy ; , | 1050 xfy -> 1000 xfy , 954 xfy 900 fy + 900 fx ~ 700 xfx <, =, =. . , =@=, =: =, =<, ==, ==, >, >=, @<, @=<, @>=, ==, is 600 xfy : 500 yfx +, -, /, /, xor 500 fx +, -, ? , 400 yfx *, /, //, <<, >>, mod, rem 200 xfx ** 200 xfy ^
Question 1: IQ Test choose the most likely answer by analogy Question 3: Question 2:
Analogy reasoner want to write a Prolog program for reasoning by analogy (Evans, 1968) § need to decide on a representation of pictures constants: small, large, triangle, square, circle functor/operator: sized(small, triangle) sized(large, square) OR OR small sized triangle large sized square functors: inside, above inside(small sized circle, large sized square). above(large sized triangle, small sized square). § need to represent questions as well operators: is_to, as (bind looser than sized, so higher prec #) predicate: question(Name, F 1 is_to F 2 as F 3 is_to [A 1, A 2, A 3]).
IQ test questions : - op(200, xfy, is_to). : - op(200, xfy, as). : - op(180, xfy, sized). question(q 1, inside(small sized square, large sized triangle) is_to inside(small sized triangle, large sized square) as inside(small sized circle, large sized square) is_to [inside(small sized circle, large sized triangle), inside(small sized square, large sized circle), inside(small sized triangle, large sized square)]). question(q 2, inside(small sized circle, large sized square) is_to inside(small sized square, large sized circle) as above(small sized triangle, large sized triangle) is_to [above(small sized circle, large sized circle), inside(small sized triangle, large sized triangle), above(large sized triangle, small sized triangle)]). question(q 3, above(small sized square, large sized circle) is_to above(large sized square, small sized circle) as above(small sized circle, large sized triangle) is_to [above(large sized circle, small sized triangle), inside(small sized circle, large sized triangle), above(large sized triangle, small sized square)]).
Analogy transformations § also need to represent transformations predicate: transform(Name, F 1 is_to F 2). transform(invert. Position, inside(small sized Figure 1, large sized Figure 2) is_to inside(small sized Figure 2, large sized Figure 1)). transform(invert. Position, above(Size 1 sized Figure 1, Size 2 sized Figure 2) is_to above(Size 2 sized Figure 2, Size 1 sized Figure 1)). transform(invert. Sizes, inside(small sized Figure 1, large sized Figure 2) is_to inside(small sized Figure 2, large sized Figure 1)). transform(invert. Sizes, above(Size 1 sized Figure 1, Size 2 sized Figure 2) is_to above(Size 2 sized Figure 1, Size 1 sized Figure 2)). Note: different but related transformations can have the same name
Analogy reasoner %%%%%%%%%%%%%%%%%%%%%%%%%%% %%% analogy. pro Dave Reed 1/23/02 %%% A program based on Evans' analogy reasoner. %%%%%%%%%%%%%%%%%%%%%%%%%%% : - op(200, xfy, is_to). : - op(200, xfy, as). : - op(180, xfy, sized). analogy(Question, Solution) : question(Question, F 1 is_to F 2 as F 3 is_to Answers), transform(Rule, F 1 is_to F 2), transform(Rule, F 3 is_to Solution), member(Solution, Answers). %%% questions (as before) %%% transformations (as before) to find an answer: 1. look up the question based on its name 2. find a transformation that takes F 1 to F 2 3. apply that rule to F 3 to obtain a potential solution 4. test to see if that solution is among the answers to choose from
Analogy reasoner ? - analogy(q 1, Answer). Answer = inside(small sized square, large sized circle) ; No ? - analogy(q 2, Answer). Answer = above(large sized triangle, small sized triangle) ; No ? - analogy(q 3, Answer). Answer = above(large sized circle, small sized triangle) ; No Note: Questions 1 & 2 yield the same answer twice. WHY? Is it possible for a questions to have different answers?
Handling ambiguities Question 4: it is possible for 2 different transformations to produce different answers must either 1. refine the transformations (difficult) 2. use heuristics to pick most likely answer (approach taken by Green) ? - analogy(q 4, Answer). Answer = above(small sized triangle, large sized circle) ; Answer = above(small sized circle, large sized triangle) ; No
- Slides: 20