home *** CD-ROM | disk | FTP | other *** search
- ; 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))))))
-
-