Hello-

In my opinion, defmodules look a bit cumbersome, but I suppose the same
argument could be made for phase control facts.  I have never actually
used CLIPS however, so don't take my word for it.  To me, the appeal for
phase control facts is consistency of rule syntax.

Following are some rules that I based on the Expert Systems text you
mentioned.  I found that phase sequences, rather than cycles, are actually
quite helpful in organizing large rule sets.


;;;
;;; phase.clp
;;;

(defrule change-phase-in-cycle
  (declare (salience -10))
  ?phase <- (phase ?current-phase)
  ?list <- (phase-cycle ?next-phase $?other-phases)
  =>
  (retract ?phase ?list)
  (assert (phase ?next-phase))
  (assert (phase-cycle $?other-phases ?next-phase)))

(defrule change-phase-in-sequence
  (declare (salience -10))
  ?fact1 <- (phase ?current-phase)
  ?fact2 <- (phase-sequence ?next-phase $?other-phases)
  =>
  (printout t "--------" crlf)
  (printout t "----++++ phase change " ?current-phase " --> " ?next-phase
crlf)
  (printout t "++++++++" crlf)
  (retract ?fact1 ?fact2)
  (assert (phase ?next-phase))
  (assert (phase-sequence $?other-phases)))

(defrule new-phase-sequence
  (declare (salience -9))
  ?new-sequence <- (new-phase-sequence $?new-phase-list)
  ?old-sequence <- (phase-sequence $?old-phase-list)
  =>
  (retract ?new-sequence ?old-sequence)
  (assert (phase-sequence $?new-phase-list $?old-phase-list)))

(defrule initial-phase-sequence
  (declare (salience -9))
  ?new-sequence <- (new-phase-sequence $?new-phase-list)
  (not (phase-sequence $?phase-list))
  =>
  (retract ?new-sequence)
  (bind ?phase (first$ $?new-phase-list))
  (bind $?list (rest$ $?new-phase-list))
  (assert (phase ?phase))
  (assert (phase-sequence $?list)))

(defrule need-phase-for-sequence
  (declare (salience -8))
  (not (phase ?phase))
  (phase-sequence ?initial-phase $?remaining-phases)
  =>
  (assert (phase ?initial-phase)))

;;;
;;; EOF
;;;


To use:

(assert (new-phase-sequence
                initialize
                configure
                acquire
                evaluate
                conclude
                finalize
))

(defrule initialization-task
        (phase initialize)
        (...)
        =>
        (...))

...

(defrule conclusion
        (phase conclude)
        (...)
        =>
        (if (not ?done)
                (assert (new-phase-sequence acquire evaluate conclude)))

(defrule finalize
        (phase finalize)
        =>
        (exit))



You can assert (insert) a new sequence at any time, and any existing
sequence is just pushed on the stack.  This can be an extremely powerful
tool, and is rather tunable.  To simulate interrupts, push the current
phase back onto the stack.  It probably wouldn't be too hard to expand
upon this to include some form of context switching and such, but I
digress.

The phase change rules also offer a great breakpoint for debugging
purposes.  Phases that have no work to do are passed through with
negligible side effects, and removing a phase can be as simple as
commenting out a line.

The overhead is minimal, and adding a phase fact to the appropriate rules
can really help document and organize your system.  I find that I rarely
need to use salience other than what is found in the rules above.

An alternative might be to write your application in Java, and only use
the Rete engine for your evaluation phase.  Most control flow logic could
then be kept outside the scope of the engine.  You may want to do this
anyways and use some deffunctions to announce the new phase sequences when
appropriate.

Hope this helps--

-Dave Barnett



---------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the
list (use your own address!) List problems? Notify [EMAIL PROTECTED]
---------------------------------------------------------------------

Reply via email to