There are numerous ways you can control execution of your program (e.g., control facts, salience, modules). This answer will use control facts (with salience) for the stages of application processing. I am also going to assume that you have a unique id
slot associated with each application.
Consider the following fact and rule:
(deffacts application-stages "ordered sequence of stages for an application"
(stages app-received app-accept-reject app-evaluate-grants
app-apply-grants app-complete))
(defrule go-to-next-stage "Advances to the next application stage"
?stage <- (app-stage ?id ?current-stage)
(stages $? ?current-stage ?next-stage $?)
=>
(retract ?stage)
(assert (app-stage ?id ?next-stage))
(printout t "Application " ?id " moved from stage " ?current-stage
" to " ?next-stage "." crlf))
The application-stages
deffact defines the sequence of stages for an application and the go-to-next-stage
rule advances the application stage. Since the rule has salience that is lower than the default (0), it will only be executed if there are no other rules corresponding to the current stage. So with no other rules in your program, you would get the following:
CLIPS> (reset)
CLIPS> (assert (app-stage app-001 app-received))
<Fact-2>
CLIPS> (run)
Application app-001 moved from stage app-received to app-accept-reject.
Application app-001 moved from stage app-accept-reject to app-evaluate-grants.
Application app-001 moved from stage app-evaluate-grants to app-apply-grants.
Application app-001 moved from stage app-apply-grants to app-complete.
CLIPS>
But if you have any rules associated with a particular stage, they will be executed first. So you can add rules to the app-evaluate-grants
stage like this:
(defrule female-finaid "rule for finaid applications for female students"
(app-stage ?id app-evaluate-grants)
(application (app-decision ACCEPTED) (id ?id)
(gender F) (grade-entry Freshman) (country USA)
=>
(assert (grant ?id female 5000)))
And you would similarly add a great-student-finaid
rule. Then, there is a single rule for the app-apply-grants
stage:
(defrule apply-grant "Adds the amount of a grant to an application"
(app-stage ?id app-apply-grants)
?grant <- (grant ?id ? ?amount)
?app <- (application (id ?id) (grant ?v_grant))
=>
(retract ?grant)
(modify (?app (grant (+ ?v_grant ?amount))))
One of the benefits of modeling it this way is that you don't have to include control facts (e.g., grant-eligible
) in the data for an application. That is, your control logic is separate from the data model. Note that you can achieve the same effect as what I've done here by using CLIPS modules (via defmodule
) and that is often preferable but it would require a lengthier answer (and this one is already fairly long).