In a forward chaining system the facts in the system are represented in a working memory which is continually updated. Rules in the system represent possible actions to take when specified conditions hold on items in the working memory - they are sometimes called condition-action rules. The conditions are usually patterns that must match items in the working memory, while the actions usually involve adding or deleting items from the working memory.
The interpreter controls the application of the rules, given the working memory, thus controlling the system's activity. It is based on a cycle of activity sometimes known as a recognise-act cycle. The system first checks to find all the rules whose conditions hold, given the current state of working memory. It then selects one and performs the actions in the action part of the rule. (The selection of a rule to fire is based on fixed strategies, known as conflict resolution strategies.) The actions will result in a new working memory, and the cycle begins again. This cycle will be repeated until either no rules fire, or some specified goal state is satisfied.
Rule-based systems vary greatly in their details and syntax, so the following examples are only illustrative.
First we'll look at a very simple set of rules:
Here we use capital letters to indicate variables. In other representations variables may be indicated in different ways, such as by a ? or a ^ (e.g., ?person, ^person).
Let us assume that initially we have a working memory with the following elements:
(month february)
(happy alison)
(researching alison)
Our system will first go through all the rules checking which ones apply given the current working memory. Rules 2 and 3 both apply, so the system has to choose between them, using its conflict resolution strategies. Let us say that rule 2 is chosen. So, (lecturing alison) is added to the working memory, which is now:
(lecturing alison)
(month february)
(happy alison)
(researching alison)
Now the cycle begins again. This time rule 3 and rule 6 have their preconditions satisfied. Lets say rule 3 is chosen and fires, so (marking-practicals alison) is added to the working memory. On the third cycle rule 1 fires, so, with X bound to alison, (overworked alison) is added to working memory which is now:
(overworked alison)
(marking-practicals alison)
(lecturing alison)
(month february)
(happy alison)
(researching alison)
Now rules 4 and 6 can apply. Suppose rule 4 fires, and (bad-mood alison) is added to the working memory. And in the next cycle rule 5 is chosen and fires, with (happy alison) removed from the working memory. Finally, rule 6 will fire, and (researching alison) will be removed from working memory, to leave:
(bad-mood alison)
(overworked alison)
(marking-practicals alison)
(lecturing alison)
(month february)
(This example is not meant to a reflect my attitude to lecturing!)
The order that rules fire may be crucial, especially when rules may result in items being deleted from working memory. (Systems which allow items to be deleted are known as nonmonotonic). Anyway, suppose we have the following further rule in the rule set:
If this rule fires BEFORE (happy alison) is removed from working memory then the system will conclude that I'll give high marks. However, if rule 5 fires first then rule 7 will no longer apply. Of course, if we fire rule 7 and then later remove its preconditions, then it would be nice if its conclusions could then be automatically removed from working memory. Special systems called truth maintenance systems have been developed to allow this.
A number of conflict resolution strategies are typically used to decide which rule to fire. These include:
These strategies may help in getting reasonable behaviour from a forward chaining system, but the most important thing is how we write the rules. They should be carefully constructed, with the preconditions specifying as precisely as possible when different rules should fire. Otherwise we will have little idea or control of what will happen. Sometimes special working memory elements are used to help to control the behaviour of the system. For example, we might decide that there are certain basic stages of processing in doing some task, and certain rules should only be fired at a given stage - we could have a special working memory element (stage 1) and add (stage 1) to the preconditions of all the relevant rules, removing the working memory element when that stage was complete.