What are hybrid inference engines?

435 views Asked by At

I've tried searching a lot for this, even so, if a similar post has been made I apologize.

I understand that a rule engine has basically two methods of inferences, forward and backward chaining. I also believe I understand how both work individually, however how will an engine with mixed inference function, will it first perform forward chaining then backwards or vice versa? Or is there a possibility for the engine to decide on which inference to use based on the knowledge base and facts in the working memory?

Also, if i'd like to build an engine with both methods of inference, is enhancing the matching algorithm being used(Rete, Treat etc) the way to start?

I know I asked a lot of questions and if any one can answer or refer me to some literature with reference to any part I'd really be grateful.

Thanks!

1

There are 1 answers

0
Gary Riley On

I'd suggest taking a look at Jess and Drools. Both of these tools implement forward and backward chaining, so you can take a look at how this is practically implemented.

One way to implement backward chaining in a forward chaining tool is to implement automatic goal generation in conjunction with providing patterns that can match these goals. For example, here are some rule excerpts from an automotive repair program written in CLIPS (that only supports forward chaining):

(defrule determine-engine-state ""
   (not (engine-starts ?))
   (not (repair ?))
   =>
   (assert (engine-starts (yes-or-no-p "Does the engine start (yes/no)? "))))

(defrule determine-rotation-state ""
   (engine-starts no)
   (not (repair ?))   
   =>
   (assert (engine-rotates (yes-or-no-p "Does the engine rotate (yes/no)? "))))

(defrule determine-gas-level ""
   (engine-starts no)
   (engine-rotates yes)
   (not (repair ?))
   =>
   (assert (tank-has-gas
              (yes-or-no-p "Does the tank have any gas in it (yes/no)? "))))

(defrule tank-out-of-gas ""
   (tank-has-gas no)
   (not (repair ?))
   =>
   (assert (repair "Add gas.")))

The rules for asking questions have the prerequisite information contained within the conditions which is more difficult to maintain.

With automatic goal generation, the rules could be rewritten like this:

(defrule determine-engine-state ""
   (goal (engine-starts ?))
   =>
   (assert (engine-starts (yes-or-no-p "Does the engine start (yes/no)? "))))

(defrule determine-rotation-state ""
   (goal (engine-rotates ?))
   =>
   (assert (engine-rotates (yes-or-no-p "Does the engine rotate (yes/no)? "))))

(defrule determine-gas-level ""
   (goal (tank-has-gas ?))
   =>
   (assert (tank-has-gas
              (yes-or-no-p "Does the tank have any gas in it (yes/no)? "))))

(defrule tank-out-of-gas ""
   (not (repair ?))
   (engine-starts no)
   (engine-rotates yes)
   (tank-has-gas no)
   =>
   (assert (repair "Add gas.")))

In this case, the rules asking questions are simplified and much easier to maintain. Whenever there is a goal for a specific type of fact, the user is queried for its value. There's no need to encode prerequisite information for the questions. Automatic goal generation allows the tank-out-of-gas rule to drive the rules containing goals. If a repair has not yet been determined, then the (engine-starts no) pattern automatically generates a goal if an engine-starts fact is not present (the rule engine can determine that there's another rule, determine-engine-state, that matches on this goal fact). If the user responds no, then the (engine-starts no) pattern will be matched causing a goal to be generated for the engine-rotates fact (triggering the determine-rotation-state rule). If the user had responded yes, then the (engine-starts no) pattern would not have been matched and since no other rules are applicable, execution would stop.

With this methodology of goal generation, backward chaining is basically used to fetch data needed by forward chaining rules.