Reputation: 31840
I have defined an "if-and-only-if" rule in a CLIPS expert system, but it requires two rules instead of one rule:
;the rules are doIfOil and doIfBlackAndFlammable
(deftemplate Object
(slot type)
(slot color)
(slot flammable)
)
(defrule doIfOil
(Object (type oil))
=>
(assert (Object (color black) (flammable yes)))
)
(defrule doIfBlackAndFlammable
(Object (color black) (flammable yes))
=>
(assert (Object (type oil)))
)
(deffacts Result
(Object
(type oil)
)
)
Would it be possible to re-write this rule in a less redundant way?
Upvotes: 0
Views: 285
Reputation: 10757
Since facts can't be duplicated, you can have the conditions of the rule check for either fact and then have the actions of the rule assert both:
(defrule oilIfAndOnlyIfBlackAndFlammable
(or (Object (type oil))
(Object (color black) (flammable yes)))
=>
(assert (Object (type oil))
(Object (color black) (flammable yes))))
Alternately, you can write a general rule (which is more complicated) that matches a fact (in a simpler representation) representing the if and only if relationship:
(deftemplate Object
(slot type (default unspecified))
(slot color (default unspecified))
(slot flammable (default unspecified)))
(deftemplate iff
(slot type1 (default unspecified))
(slot color1 (default unspecified))
(slot flammable1 (default unspecified))
(slot type2 (default unspecified))
(slot color2 (default unspecified))
(slot flammable2 (default unspecified)))
(deffacts Result
(Object
(type oil)))
(deffacts iff
(iff (type1 oil) (color2 black) (flammable2 yes)))
(defrule iff
(iff (type1 ?type1) (color1 ?color1) (flammable1 ?flammable1)
(type2 ?type2) (color2 ?color2) (flammable2 ?flammable2))
(Object (type ?type)
(color ?color)
(flammable ?flammable))
(test (or (and (or (eq ?type ?type1) (eq ?type1 unspecified))
(or (eq ?color ?color1) (eq ?color1 unspecified))
(or (eq ?flammable ?flammable1) (eq ?flammable1 unspecified)))
(and (or (eq ?type ?type2) (eq ?type2 unspecified))
(or (eq ?color ?color2) (eq ?color2 unspecified))
(or (eq ?flammable ?flammable2) (eq ?flammable2 unspecified)))))
=>
(assert (Object (type ?type1) (color ?color1) (flammable ?flammable1))
(Object (type ?type2) (color ?color2) (flammable ?flammable2))))
Upvotes: 1