Download
slide1 n.
Skip this Video
Loading SlideShow in 5 Seconds..
The Farmer, Wolf, Goat and Cabbage Revisited PowerPoint Presentation
Download Presentation
The Farmer, Wolf, Goat and Cabbage Revisited

The Farmer, Wolf, Goat and Cabbage Revisited

1313 Views Download Presentation
Download Presentation

The Farmer, Wolf, Goat and Cabbage Revisited

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

    1. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 1 The Farmer, Wolf, Goat and Cabbage Revisited Recall that we have already solved this problem in Prolog A farmer with his wolf, goat, and cabbage come to the edge of a river they wish to cross. There is a boat at the rivers edge, but, of course, only the farmer can row. The boat also can carry only two things (including the rower) at a time. If the wolf is ever left alone with the goat, the wolf will eat the goat; similarly, if the goat is left alone with the cabbage, the goat will eat the cabbage. Devise a sequence of crossings of the river so that all four characters arrive safely on the other side of the river.

    2. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 2 States of the World as Lists Each state is a list of four atoms, each with the value of e (for east) or w (for west) In LISP, we construct these lists and access each element as follows

    3. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 3 Implementing FWGC in LISP We define a function opposite, so that characters can cross the river (defun opposite (side) (cond ((equal side 'e) 'w) ((equal side 'w) 'e))) We also need a function safe, so that nothing gets eaten. A safe input state is returned unchanged, while nil is returned for an unsafe state.

    4. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 4 The Four Move Functions There are four possible moves, just as there were in Prolog The farmer can row himself, the wolf, the goat or the cabbage across the river To move something other than himself, that thing must be on the same side of the river as he is. Otherwise, an attempted move returns nil. For the farmer to move the wolf, for example, we have:

    5. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 5 Backtracking Search of the State Space Backtracking is a built-in search strategy in Prolog, but not in LISP This is both advantageous and disadvantageous When you want backtracking search, you have to implement it yourself When you want some other search strategy, you can flexibly implement it A simple (but incomplete) path function is:

    6. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 6 Improving the Path Function Three improvements are necessary to implement a working function We need a test for nil, since you cant reach the goal from nil We need to keep track of where weve been, so we dont loop We need to return the path taken, rather than just success or nil The improved version is:

    7. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 7 Putting it All Together A top level function to start the search is defined: (defun solve-fwgc (state goal) (path state goal nil) ; we call path with our current state, ) ; the goal state, and an empty been list This implementation now works like the one we built in Prolog Code is available online Running and tracing the code is instructive!

    8. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 8 Higher Order Functions One advantage of functional programming languages is the ability to use higher order functions A higher order function may take functions as parameters and may return a function as a result A filter is a function that tests each element of a list and removes those elements that fail the test We have already seen filter-negatives. Here is filter-evens:

    9. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 9 A Higher Order Filter Function We can write a higher order filter function to filter based on any test, using funcall Funcalls first argument is the name of a function to call, and its remaining arguments are the arguments for the called function The filter function is: (defun filter (list-of-elements test) (cond ((null list-of-elements) nil) ((funcall test (car list-of-elements)) (cons (car list-of-elements) (filter (cdr list-of-elements) test))) (t (filter (cdr list-of-elements) test))))

    10. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 10 Using filter and funcall Now we can filter a list using different tests Ex: > (filter (1 3 -9 5 -2 -7 6) #plusp) (1 3 5 6) > (filter (1 2 3 4 5 6 7 8 9) #evenp) (2 4 6 8) > (filter (1 a b 3 c 4 7 d) #numberp) (1 3 4 7) Note that when the name of a function is passed in as a parameter, it is preceded by #, rather than just a quote, to indicate that it is a function Note, too, that the result of evaluating a funcall is just what you would get if you evaluated the passed in function with the passed in arguments Ex: > (member 2 (1 2 3)) (2 3) > (funcall #member 2 (1 2 3)) (2 3)

    11. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 11 Maps A map takes a list of elements and applies a function to each element in the list. It then returns a list of the results. Example (defun map-simple (func list) (cond ((null list) nil) (t (cons (funcall func (car list)) (map-simple func (cdr list)))))) > (map-simple #1+ (1 2 3 4 5 6)) (2 3 4 5 6 7) > (map-simple #listp (1 2 (3 4) 5 (6 7 8))) (NIL NIL T NIL T)

    12. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 12 More on Maps and Functions as Arguments mapcar is a built in mapping function that applies a function with one or more arguments to one or more argument lists Ex: > (mapcar #'< '(5 8 3 7) '(2 9 5 6)) (NIL T T NIL) > (mapcar #'+ '(2 4 3) '(4 1 1) '(3 2 1)) (9 7 5) When you have a small and/or simple function you want to apply, you can use a lambda expression instead of defining a function with defun A lambda expression is a nameless throwaway function Ex: >(funcall #'(lambda (x y z) (list x x y y z z)) 'cat 'dog 'fish)) (CAT CAT DOG DOG FISH FISH) >(funcall #'(lambda (x) (append x (reverse x))) '(1 2 3)) (1 2 3 3 2 1) >(mapcar #'(lambda (x y) (/ (+ x y) 2)) '(7 4 9) '(3 2 5)) (5 3 7)

    13. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 13 You Try It! What will the LISP interpreter reply? 1. (funcall #'cdr '(LISP is fun)) 2. (mapcar #'numberp '(CS 480 580 AI)) 3. (mapcar #'* '(1 2 3) '(4 5 6)) 4. (funcall #'(lambda (x) (list x x x)) '(a b)) 5. (mapcar #'(lambda (x y z) (* x y z)) '(2 3) '(1 5) '(4 2)) 6. (mapcar #'(lambda (x) (and (plusp x) (evenp x))) '(2 3 -6 8 -5))

    14. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 14 Search in LISP We now know enough LISP to implement breadth-first, depth-first and best-first search We will review only breadth-first search together. All three searches are available in the example LISP code directory. Recall that the algorithm for breadth-first search was presented in Chapter 3

    15. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 15 Breadth-First Search Algorithm

    16. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 16 Breadth-First Search in LISP: Initial Outline (defun run-breadth (start goal) (setq *open* (list start)) (setq *closed* nil) (setq *goal* goal) (breadth-first)) (defun breadth-first () (cond ((null *open*) nil) (t (let ((state (car *open*))) (cond ((equal state *goal*) 'success) (t (setq *closed* (cons state *closed*)) (setq *open* (append (cdr *open*) (generate-descendants state *moves*))) (breadth-first))))))) Here, global variables (denoted *<variable-name>*) are used for the open and closed lists, for possible moves, and for the goal state We still need to see how to specify allowable moves, how to generate descendents, and how to return the path from start to goal

    17. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 17 More LISP Implementation Since moves are functions and we can use functions as parameters, we can establish legal moves by listing available functions Ex: For the Farmer, Wolf, Goat and Cabbage problem, we have: (setq *moves* '(farmer-takes-self farmer-takes-wolf farmer-takes-goat farmer-takes-cabbage)) This allows us to use the same breadth-first search algorithm to solve different problems We keep the breadth-first search code and just write new functions for the allowable moves

    18. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 18 Defining State Records In order to print out the path to a solution, rather than just success, we need to keep track of each states parent as we traverse the state space graph We do this the same way we built and accessed database records

    19. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 19 Using State Records Now we can use the state records to track where weve been as we generate descendents

    20. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 20 Printing out the Solution Path Now that we have tracked each childs parent, we are able to trace a path from the start state to the goal state When we reach the goal state, we trace this path as follows:

    21. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 21 The Final Version of Breadth-First Search (defun run-breadth (start goal moves) (setq *open* (list (build-record start nil))) (setq *closed* nil) (setq *goal* goal) (setq *moves* moves) (breadth-first))

    22. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 22 Pattern Matching in LISP Pattern matching has many uses, in applications like text processing and cryptography, as well as for AI problems like unification and natural language understanding (including fun things like chat bots) The matching process given here is a simplification of Prolog unification Instead of named variables, it allows only the variable ? (question mark) We can then easily see if a pattern is a variable with the predicate: (defun variable-p (x) (equal x '?) ) The code for testing if two atomic patterns match is: (defun match-atom (pattern1 pattern2) (or (equal pattern1 pattern2) ; both patterns are the same, or (variable-p pattern1) ; one of them is a variable (variable-p pattern2)))

    23. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 23 Matching Arbitrary Patterns Any pattern can be represented as an S-expression. This allows matching of any arbitrary patterns. (defun match (pattern1 pattern2) (cond (or (atom pattern1) (atom pattern2)) ; a pattern is atomic (match-atom pattern1 pattern2) ; so match atoms (t (and (match (car pattern1) (car pattern2)) ; otherwise, recurse (match (cdr pattern1) (cdr pattern2)))))) ; to match car and cdr > (match (likes cindy chocolate) (likes cindy chocolate)) T > (match (likes cindy chocolate) (likes cindy cats)) NIL > (match (likes cindy ?) (likes cindy chocolate)) T > (match (likes ? chocolate) (likes cindy ?)) T

    24. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 24 A Matching Application for Databases Simple matching capabilities can be combined to implement useful systems The database example we discussed previously can be enhanced by adding a function to retrieve matching records A global employee database is first established > (setq *database* (((lovelace ada) 50000.00 1234) ((turing alan) 45000.00 3927) ((shelley mary) 35000.00 2850) ((vonNeumann john) 40000.00 7955) ((simon herbert) 50000.00 1374) ((mccarthy john) 48000.00 2864) ((russell bertrand) 35000.00 2950)) *DATABASE*

    25. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 25 Finding Matching Database Records (defun get-matches (pattern database) (cond ((null database) ()) ((match pattern (car database)) ; match found, add to result (cons (car database) (get-matches pattern (cdr database)))) (t (get-matches (cdr database))))) > (get-matches ((turing alan) 45000.00 3927) *database*) ((TURING ALAN) 45000.00 3927) > (get-matches (? 50000.00 ?) *database*) ; everyone who makes $50,000 (((LOVELACE ADA) 50000.00 1234) ((SIMON HERBERT) 50000.00 1374)) > (get-matches ((? John) ? ?) *database*) ; everyone named John (((VONNEUMANN JOHN) 40000.00 7955) ((MCCARTHY JOHN) 48000.00 2864))

    26. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 26 A Recursive Unification Function in LISP Recall from Chapter 2 that unification is a type of pattern matching Unification is an algorithm for determining the substitutions that make two predicate calculus expressions match Ex: (likes ted holidays) unifies with (likes ted X) under the substitution {holidays/X} To unify, the expressions must have the same predicate and the same number of terms Different constants do not match each other, but identical ones do A variable can match a constant, another variable, or a function expression, as long as the variable does not appear within that expression substituting (p X) for X would lead to the infinite (p (p (pX))) Implementing this algorithm in LISP is not hard. Because LISP is not case sensitive, we just need another way to indicate variables, perhaps by starting their names with special characters or by preceding their names with the marker var

    27. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 27 Unification Algorithm

    28. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 28 Implementation in LISP The LISP function unify has three arguments, two patterns to be matched, and a list of bindings (previously made substitutions) We need to know the substitutions that have already been made, so that, for example, once holidays is substituted for X, X keeps that value throughout the whole expression At the start, the list of bindings is an empty list The LISP function returns a list of substitutions made, or nil, when the patterns already match without any substitutions, or failed, when it is not possible to unify the two expressions

    29. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 29 Examples of Unification Function Output > (unify (p a (var x)) (p a b) ()) (((VAR X) . B)) ; returns substitution of b for (var x) > (unify (p (var y) b) (p a (var x)) ()) ; variables appear in both patterns (((VAR X) . B) ((VAR Y) . A) > (unify (p a) (p a)) ()) NIL ; NIL indicates no substitution required > (unify (p a) (q a) ()) FAILED ; The atom FAILED is returned to ; indicate unification is not possible

    30. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 30 The unify Function (defun unify (pattern1 pattern2 substitution-list) (cond ((equal substitution-list 'failed) 'failed) ((varp pattern1) (match-var pattern1 pattern2 substitution-list)) ((varp pattern2) (match-var pattern2 pattern1 substitution-list)) ((is-constant-p pattern1) (cond ((equal pattern1 pattern2) substitution-list) (t 'failed))) ((is-constant-p pattern2) 'failed) (t (unify (cdr pattern1) (cdr pattern2) (unify (car pattern1) (car pattern2) substitution-list)))))

    31. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 31 The varp, is-constant-p, and match-var Functions (defun match-var (var pattern substitution-list) (cond ((equal var pattern) substitution-list) (t (let ((binding (get-binding var substitution-list))) (cond (binding (unify (get-binding-value binding) pattern substitution-list)) ((occursp var pattern) 'failed) (t (acons var pattern substitution-list)))))))

    32. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 32 The occurs-p Function and Association Lists An association list, or a-list, is a built-in LISP data type It is a list of key/data records, represented as lists or dotted pairs There is a built in function assoc, which returns a record based on its key > (assoc 3 ((1 a) (2 b) (3 c) (4 d))) (3 C) > (assoc d ((a b c) (b c d e) (d e f) (c d e))) (D E F) >(assoc c ((a . 1) (b . 2) (c . 3) (d . 4))) (c . 3)

    33. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 33 Dotted Pairs A dotted pair is just the result of consing one s-expression onto another We usually prefer not to use dotted pair notation Ex: (1 2 3) looks better than (1 . (2 . (3 . nil))) The a-list is one place dotted pairs are useful, because they allow you to cons together two atoms to associate a key with one value > (cons 'senior 2005) (SENIOR . 2005) > (car '(senior . 2005)) SENIOR > (cdr '(senior . 2005)) 2005 Note that this allows the cdr of a list to be an atom We use cdr to get the value(s) associated with a key in an a-list

    34. CS 480/580: Artificial Intelligence, Prof. Cindy Marling 34 The acons Function and Using a-lists for Bindings The acons function inserts a key and some data as a record at the beginning of an a-list > (acons 'ai 480 nil) ((AI . 480)) > (acons 'ai 480 '((db . 462) (pl . 320))) ((AI . 480) (DB . 462) (PL . 320)) > (cdr (assoc 'ai '((AI . 480) (DB . 462) (PL . 320))))) 480 a-lists help manage the bindings in unification