home *** CD-ROM | disk | FTP | other *** search
-
- Expert's Toolbox -- March 1987
- "Heuristic State Space Search"
- by Marc Rettig
-
- Listings 1 and 2
-
-
-
- Listing 1
-
- ; STATE-SPACE SEARCH PROCEDURE
- ; These functions provide a general control structure for
- ; solving problems using heuristic search. In order to apply
- ; this method to a particular problem, you must write the
- ; functions: initial-state, goal, successors, and print-solution.
- ; See the "Expert's Toolbox" column in the March AI-Expert
- ; for a description of this algorithm and an example of its use.
- ;
- ; Algorithm given by Dr. Ralph Grishman, New York University,
- ; after Nils Nilsson, "Principles of Artificial Intelligence".
- ; Adapted for Xlisp by Marc Rettig (76703,1037).
-
- (defun search ()
- (prog (open closed n m successor-list same)
-
- ; Step 1. Put initial state on open.
- (setq open (list (initial-state)))
-
- ; Step 2. If open is empty, exit with failure.
- expand:
- (cond ((null open) (print 'failure) (return nil)))
-
- ; Step 3. Remove state from open with minimum g + h and
- ; call it n. (open is sorted by increasing g + h, so
- ; this is first element.) Put n on closed.
- ; Exit with success if n is a goal node.
- (setq n (car open))
- (setq open (cdr open))
- (setq closed (cons n closed))
- (trace 'expanding n)
- (cond ((goal n) (print-solution n) (return t)))
-
- ; For each m in successors(m):
- (setq successor-list (successors n))
- next-successor:
- (cond ((null successor-list) (go expand:)))
- (setq m (car successor-list))
- (setq successor-list (cdr successor-list))
- (trace 'successor m)
- (cond ((setq same (find m open))
- ; if m is on open, reset g if new value is smaller
- (cond
- ((< (get m 'g) (get same 'g))
- (setq open (add m (remove same open))))))
- ((setq same (find m closed))
- ; If m is on closed and new value of g is smaller,
- ; remove state from closed and add it to open with new g.
- (cond
- ((< (get m 'g) (get same 'g))
- (setq closed (remove same closed))
- (setq open (add m open)))))
- (t
- ; else add m to open
- (setq open (add m open))))
- (go next-successor:)))
-
- (defun add (state s-list)
- ; Inserts state into s-list so that list remains ordered
- ; by increasing g + h.
- (cond ((null s-list) (list state))
- ((> (+ (get (car s-list) 'g) (get (car s-list) 'h))
- (+ (get state 'g) (get state 'h)))
- (cons state s-list))
- (t (cons (car s-list) (add state (cdr s-list))))))
-
- (defun find (state s-list)
- ; returns first entry on s-list whose position is same
- ; as that of state.
- (cond ((null s-list) nil)
- ((equal (get state 'position)
- (get (car s-list) 'position))
- (car s-list))
- (t (find state (cdr s-list)))))
-
-
-
- Listing 2
-
- ; M I S S I O N A R I E S A N D C A N N I B A L S
- ;
- ; The following routines, when used in conjunction with the state-space
- ; search procedure, solve the missionaries and cannibals problem. Three
- ; missionaries and 3 cannibals are located on the right bank of a river,
- ; along with a two-man rowboat. We must find a way of moving all the
- ; missionaries and cannibals to the left bank. However, if at any time
- ; there are more cannibals than missionaries on a bank, the cannibals will
- ; exhibit a consuming interest in the misssionaries; this must be avoided.
- ;
- ; Each state is represented by an atom with the following properties:
- ; position -- a list of three elements,
- ; the number of missionaries on the right bank
- ; the number of cannibals on the right bank
- ; the position of the boat (left or right)
- ; g -- the estimated g for that state
- ; h -- the estimated h (value of function heuristic)
- ; parent -- the preceding state on the path from the initial state
- ; (the preceding state which gives rise to the least g,
- ; if there are several)
-
- (defun initial-state ()
- ; return the initial state
- (build-state 3 3 'right 0 nil))
-
- (defun successors (state)
- ; returns the successors of state
- ; note that procedure try uses state and new-g, and modifies suc
- (prog (m c boat new-g suc)
- ; extract parameters of current position and put in m, c, and boat
- (setq m (car (get state 'position)))
- (setq c (cadr (get state 'position)))
- (setq boat (caddr (get state 'position)))
- ; g of new state = g of old state + 1 (all crossings are unit cost)
- (setq new-g (+ 1 (get state 'g)))
- (cond ((equal boat 'right)
- (try (- m 2) c 'left new-g)
- (try (- m 1) c 'left new-g)
- (try (- m 1) (- c 1) 'left new-g)
- (try m (- c 1) 'left new-g)
- (try m (- c 2) 'left new-g))
- (t ; boat is on left
- (try (+ m 2) c 'right)
- (try (+ m 1) c 'right)
- (try (+ m 1) (+ c 1) 'right)
- (try m (+ c 1) 'right)
- (try m (+ c 2) 'right)))
- (return suc)))
-
- (defun try (new-m new-c new-boat new-g)
- ; if position(new-m,new-c,new-boat) is valid, add new state to suc
- (cond ((valid new-m new-c)
- (setq suc (cons (build-state new-m new-c new-boat new-g state)
- suc)))))
-
- (defun valid (miss cann)
- ; returns true if having 'miss' missionaries and 'cann' cannibals
- ; on the right bank is a valid state
- (and (>= miss 0)
- (>= cann 0)
- (< miss 4)
- (< cann 4)
- (or (zerop miss) (>= miss cann))
- (or (zerop (- 3 miss)) (>= (- 3 miss) (- 3 cann)))))
-
- (defun build-state (miss cann boat g parent)
- ; creates a new state with parameters as specified by argument list
- (prog (newstate)
- (setq newstate (gensym))
- (putprop newstate (list miss cann boat) 'position)
- (putprop newstate g 'g)
- (putprop newstate (heuristic miss cann boat) 'h)
- (putprop newstate parent 'parent)
- (return newstate)))
-
- (defun heuristic (miss cann boat)
- ; our heuristic (h) function
- (cond ((equal boat 'left)
- (* 2 (+ miss cann)))
- (t ; boat is on right
- (* 2 (max 0 (+ miss cann -2))))))
-
- (defun goal (state)
- ; returns true if state is a goal state (no missionaries or cannibals on right)
- (and (zerop (car (get state 'position)))
- (zerop (cadr (get state 'position)))))
-
- (defun print-solution (state)
- ; invoked by search algorithm with goal state,
- ; prints sequence of states from initial state to goal.
- (cond ((null state)
- (print 'solution:))
- (t
- (print-solution (get state 'parent))
- (print (get state 'position))
- ))
- )
-
- (defun trace (comment state)
- ; if trace-switch is true, print out comment and position
- ; associated with state
- (cond
- (trace-switch
- (print `(,comment state ,state with position ,(get state 'position)
- h(x) = ,(get state 'h))))))
-