Sophie

Sophie

distrib > Fedora > 14 > x86_64 > by-pkgid > b935a2b65501208cb2c31e83c68a477b > files > 16

clips-doc-6.30.0-0.1.20090722svn.fc12.noarch.rpm

;;;======================================================
;;;   Farmer's Dilemma Problem
;;;
;;;     Another classic AI problem (cannibals and the 
;;;     missionary) in agricultural terms. The point is
;;;     to get the farmer, the fox the cabbage and the
;;;     goat across a stream.
;;;        But the boat only holds 2 items. If left 
;;;     alone with the goat, the fox will eat it. If
;;;     left alone with the cabbage, the goat will eat
;;;     it.
;;;        This example uses COOL classes and 
;;;     message-handlers to solve the problem.
;;;
;;;     CLIPS Version 6.0 Example
;;; 
;;;     To execute, merely load and enter (solve-dilemma).
;;;======================================================

;;;**************
;;;* DEFCLASSES *
;;;**************

(defclass status
   (is-a USER)
   (role concrete)
   (slot farmer
      (create-accessor write)
      (default shore-1))
   (slot fox
      (create-accessor write)
      (default shore-1))
   (slot goat
      (create-accessor write)
      (default shore-1))
   (slot cabbage
      (create-accessor write)
      (default shore-1))
   (slot parent
      (create-accessor write)
      (default no-parent))
   (slot search-depth
      (create-accessor write)
      (default 1))
   (slot last-move
      (create-accessor write)
      (default no-move)))

;;;****************
;;;* DEFFUNCTIONS *
;;;****************

(deffunction contradiction
   (?f ?x ?g ?c ?d)
   (if (or (and (eq ?x ?g) (neq ?f ?x)) (and (eq ?g ?c) (neq ?f ?g)))
      then
      TRUE
      else
      (any-instancep ((?s status))
        (and (eq ?s:farmer ?f) 
          (eq ?s:fox ?x)
          (eq ?s:goat ?g)
          (eq ?s:cabbage ?c)
          (< ?s:search-depth ?d)))))

(deffunction opposite-shore
   (?value)
   (if (eq ?value shore-1)
      then
      shore-2
      else
      shore-1))

(deffunction solve-dilemma ()
   (do-for-all-instances ((?a status))
      TRUE
      (send ?a delete))  
   (make-instance start of status)
   (send [start] generate-moves))

;;;**************
;;;* DEFRULES *
;;;**************

(defrule start-it
  =>
  (solve-dilemma))

;;;***********************
;;;* DEFMESSAGE-HANDLERS *
;;;***********************

(defmessage-handler status move-farmer
   ()
   (if (not (contradiction (opposite-shore ?self:farmer) ?self:fox 
                           ?self:goat ?self:cabbage ?self:search-depth))
      then
      (bind ?x (make-instance (gensym) of status
         (farmer (opposite-shore ?self:farmer))
         (fox ?self:fox)
         (goat ?self:goat)
         (cabbage ?self:cabbage)
         (last-move farmer)
         (parent ?self)
         (search-depth (+ ?self:search-depth 1))))
      (if (not (send ?x solution?))
         then
         (send ?x generate-moves))))

(defmessage-handler status move-goat
   ()
   (if (and (eq ?self:farmer ?self:goat) (not (contradiction 
      (opposite-shore ?self:farmer) ?self:fox (opposite-shore ?self:goat) 
       ?self:cabbage ?self:search-depth)))
      then
      (bind ?x (make-instance (gensym) of status
         (farmer (opposite-shore ?self:farmer))
         (fox ?self:fox)
         (goat (opposite-shore ?self:farmer))
         (cabbage ?self:cabbage)
         (last-move goat)
         (parent ?self)
         (search-depth (+ ?self:search-depth 1))))
      (if (not (send ?x solution?))
         then
         (send ?x generate-moves))))

(defmessage-handler status move-fox
   ()
   (if (and (eq ?self:farmer ?self:fox) 
            (not (contradiction (opposite-shore ?self:farmer) 
                                (opposite-shore ?self:fox) 
                                ?self:goat ?self:cabbage ?self:search-depth)))
      then
      (bind ?x (make-instance (gensym) of status
         (farmer (opposite-shore ?self:farmer))
         (fox (opposite-shore ?self:farmer))
         (goat ?self:goat)
         (cabbage ?self:cabbage)
         (last-move fox)
         (parent ?self)
         (search-depth (+ ?self:search-depth 1))))
      (if (not (send ?x solution?))
         then
         (send ?x generate-moves))))

(defmessage-handler status move-cabbage
   ()
   (if (and (eq ?self:farmer ?self:cabbage) 
            (not (contradiction (opposite-shore ?self:farmer) 
                                ?self:fox ?self:goat 
                                (opposite-shore ?self:cabbage) 
                                ?self:search-depth)))
      then
      (bind ?x (make-instance (gensym) of status
         (farmer (opposite-shore ?self:farmer))
         (fox ?self:fox)
         (goat ?self:goat)
         (cabbage (opposite-shore ?self:farmer))
         (last-move cabbage)
         (parent ?self)
         (search-depth (+ ?self:search-depth 1))))
      (if (not (send ?x solution?))
         then
         (send ?x generate-moves))))

(defmessage-handler status generate-moves
   ()
   (send ?self move-farmer)
   (send ?self move-fox)
   (send ?self move-goat)
   (send ?self move-cabbage))

(defmessage-handler status print-solution
   ()
   (if (neq ?self:parent no-parent)
      then
      (send ?self:parent print-solution)
      (bind ?move-dest (dynamic-get ?self:last-move))
      (if (eq ?self:last-move farmer)
         then
         (printout t "Farmer moves alone to " ?move-dest "." crlf)
         else
         (printout t "Farmer moves with " ?self:last-move " to " ?move-dest "." crlf))))

(defmessage-handler status solution?
   ()
   (if (and (eq ?self:farmer shore-2) (eq ?self:fox shore-2) 
            (eq ?self:goat shore-2) (eq ?self:cabbage shore-2))
      then
      (printout t crlf "Solution found:" crlf crlf)
      (send ?self print-solution)
      TRUE
      else
      FALSE))