| Prev | Next | Start of Chapter | End of Chapter | Contents | Glossary | Index | Comments | (5 out of 7)

Using Rule-Based Processing

Once you have decided you need to use a rule as opposed to a procedure, you need to decide the type of rule to use. G2 supports two basic types of rules, which you use for the following purposes:

A rule-based system maps out a multi-threaded path of execution, which is potentially different each time the rule is invoked. For this reason, rule-based systems are often more complex, harder to test, debug, and maintain, and less efficient than procedure-based systems based on methods. Thus, you should only use rules for specific purposes in your application.

For information about other types of rules, see Guidelines for Implementing Rule-Based Processing.

Using "Whenever" Rules to Detect Events

Often, your application needs to detect and respond to events. For example, you might need to detect an event such as a tank overheating or a network connection dropping. Based on detecting the event, you might trigger a method on a class, which would invoke some type of sequential processing.

This is an example of event detection, which you implement by using a "whenever" rule.

You can also use "if" rules for event detection when the event is a data value changing, as described in Using "If" Rules for Data-Driven Processing.

Each time an event occurs that causes a rule to be invoked, G2 creates a new process, which executes independently of any other process. For example, if you have a rule that detects the event of a user moving an item on a workspace, G2 creates a new independent process.

The Five Types of "Whenever" Rule Events

You use "whenever" rules to compute and infer data based on these types of triggering events:

Specifically, "whenever" rules support these five categories of events:

Triggering event Example of whenever rule
Movement of an object on a workspace
whenever computer-1 is moved by the user
Creating or deleting a connection
whenever computer-1 is connected to any server whenever computer-1 is disconnected from any server
Establishing or breaking a relation
whenever computer-1 becomes in-communication-with any server whenever computer-1 ceases to be in-communication-with any server
Activating/deactivating or enabling/disabling items
whenever computer-1 is activated whenever computer-1 is enabled
Attributes receiving or failing to receive a value
whenever the sensor-data of any robot receives a value whenever sensor-data of any robot loses its value

Example of Event Detection

The most common form of event detection is a rule that detects an event and initiates some form of procedural processing, as this figure illustrates:


For example, you might create this rule:

In this example, G2 creates two distinct processes:

Using "If" Rules for Data-Driven Processing

Sometimes, your applications needs to perform some kind of decision-making in response to changes in one or more data values. This is another form of event detection in which the event is a change in the value of a piece of data. Thus, this type of event detection is called data-driven processing.

You implement data-driven processing by creating a series of "if" rules that test data values and trigger other "if" rules based on the outcome of the test. G2 triggers the "if" rule whenever the data value changes, by using a mechanism called forward chaining. When G2 detects a change in the value of a piece of data, it forward chains to any "if" rule that refers to the data value in its antecedent.

Each time G2 forward chains to a rule, it creates a new process. Thus, if you have a series of "if" rules that implement some kind of decision-making, G2 creates a separate process for each "if" rule in the chain each time a specific data value changes.

While forward chaining represents a powerful way of representing complex decision-making logic in an application, forward chaining can also be the source of a great deal of unnecessary complexity. An application that has a large number of "if" rules that follow a complex path of execution is much harder to debug, test, and maintain because the number of possible outcomes is so vast. Thus, you need to be thoughtful in the way you use forward chaining in your application, and you should always consider whether you can implement the same type of decision-making more efficiently by using a method.

Example of Data-Driven Processing

This diagram illustrates data-driven processing, using several "if" rules. When a data value changes, G2 triggers the first "if" rule, which tests the data value in its antecedent. If the test is true, the rule concludes a value for an attribute, which, in turn, triggers another "if" rule, and so on:


For example:

Summary of Forward Chaining Options for Parameters and Variables

While simple typed attributes always forward chain to "if" rules, not all variables and parameters allow forward chaining, by default. This table summarizes the default forward chaining options for the various types of parameters and variables:

Symbolic and Logical Numeric and Text
Parameter
do forward chain
do not forward chain
Variable
do forward chain
do not forward chain

To override the default forward chaining options for a variable or parameter:

For more information, see Creating a Subclass of Variable or Parameter.

Summary of When Attributes, Parameters, and Variables Forward Chain

Typed attributes, variables, and parameters have different behavior for forward chaining to "if" rules, which this table summarizes:

For this type of value...
Forward chaining occurs...
Typed attribute
Whenever the attribute receives a new value, even if the value does not change
Parameter
When the parameter receives a new value and the value has changed
Variable
When the variable receives a new value and when the value has changed or the expiration time has changed; does not forward chain when the value expires

Using Backward Chaining

If the application does not know the value of a variable that is required to invoke a rule via forward chaining or event detection, G2 uses another form of chaining called backward chaining to determine its value. In backward chaining, when G2 requires a value for a piece of data, G2 invokes any rule that concludes the data value in its consequent. For example, G2 might use backward chaining to obtain additional data values that support the diagnosis of a failure.

Unlike forward chaining, backward chaining does not initiate a new process; instead, it initiates a new subthread of the initiating process.

For more information about backward chaining, see Minimize Backward Chaining.

Detecting When the Value of a Variable Changes

If you are detecting changes in the value of a variable, you can either use data-driven processing ("if" rules) or event detection ("whenever" rules). Depending on the type of rule you choose and whether or not the value of the variable changes, G2 invokes the rules differently, as this table describes:

G2 invokes this
type of rule...

Under these circumstances...
"If" rule
Through forward chaining, only when the value of the variable changes, unless the variable specifies a Validity-interval
"Whenever" rule
Whenever the variable receives a new value, even if the value has not changed and even if the variable specifies a Validity-interval.

Thus, if your variable does not specify a validity interval, it is generally more efficient to use an "if" rule as opposed to a "whenever" rule to detect changes in the value of a variable.

On the other hand, if the value of the variable in the antecedent of the "if" rule changes very often, for example, once a second, forward chaining to the "if" rule is analogous to scanning the rule, which can be very inefficient. In such cases, you should change the scan interval for the variable so that forward chaining occurs less frequently, or disable forward chaining for the rule and use some other technique for invoking the rule, such as conditional scanning, described in Avoid Scanning Rules.

When Different Types of Rules Initiate New Processes

This table lists the various types of rule-based processing and when G2 creates a new process:

Type of Rule When G2 Creates a New Process
"Whenever" rule
Whenever the event in the antecedent is detected; in the case of detecting whenever a variable receives a value, creates a new process even if the data value has not changed
"If" rule
When the attribute, parameter, or variable referenced in the antecedent receives a value, which causes forward chaining to the rule Note: Backward chaining does not initiate a new process; it initiates a new subthread.
Scanned rule
Each time the rule is scanned and for each instance to which the scanned rule applies
Rule with focus
Each time a rule is explicitly invoked by using the focus on action or the invoke ... for action, and for each instance to which the rule with focus applies
Rule category
Each time a rule is explicitly invoked by using the invoke action and for each instance to which the rule in the specified category applies
Other types of rules
"Initially" rules, "when" rules, and "unconditionally" rules all create new processes when they are invoked

For example, suppose you have a set of "if" rules that implement some sort of decision-making. Each time G2 forward chains to an "if" rule, it creates and schedules a new process.

On the other hand, suppose you have a single "whenever" rule that detects an event, which invokes a method that implements the same type of decision-making, using if-then statements. If the method maintains a single thread of processing, G2 only creates and schedules two processes: one for the event detector and one for the method. Thus, using a "whenever" rule to invoke a single processing thread to perform decision-making is usually more efficient than using a set of "if" rules.

Similarly, if you have a generic scanned rule, G2 creates a new process for each instance of the class, each time the rule is scanned. Whereas, if you have a generic rule that is invoked by forward chaining or event detection, G2 only creates a new process each time an event occurs for a specific instance of the class to which the rule applies. Thus, forward chaining and event detection are more efficient than scanning. If you must use scanning, you can narrow the scope by using focal classes, focal objects, and rule categories.

Note that backward chaining does not create a new process; it creates a new subthread of the initiating process.


Note: In addition to these forms of rule-based processing, G2 also creates new processes under these circumstances: each time you use a start action; each time G2 computes a generic or specific formula; each time G2 updates a display by evaluating an expression, for example, to update a chart, readout table; and each time G2 evaluates an expression when a user clicks a button or user menu choice.

For more information, see the references in this table:

For information on... See...
Using focal classes, focal objects, and rule categories
Narrow the Scope of Rules to Minimize Rule Invocations
Backward chaining
Minimize Backward Chaining
Initiating processing, using the start action
Initiating Procedural Processing

Guidelines for Implementing Rule-Based Processing

Given the relatively limited need for rules in an application, you should follow these guidelines when creating rules.

Emphasize "Whenever" Rules Over "If" Rules

In general, you should use "whenever" rules to implement event detection. You should only use "if" rules and forward chaining when you cannot implement the decision-making by using some other technique, such as by creating a method.

One common use of "if" rules is detecting when the value of an external variable changes, that is, a variable that obtains its data from an external data source, such as the G2 Gateway or some other bridge process.

Encapsulate the Consequent of a "Whenever" Rule

You use the consequent of a "whenever" rule to invoke methods and procedures that implement sequential processing based on the initial triggering event. The consequent of the "whenever" rule should invoke only a small number of methods or procedures. If the consequent of the "whenever" rule becomes too large, or if you need to control the order in which the processing occurs, you should encapsulate the consequent into a smaller number of methods or procedures.

Avoid Scanning Rules

You can invoke "if" rules by scheduling periodic processing. This technique of rule invocation is called scanning and is a feature that only rules support.

Although scanning represents an easy way of invoking a rule, scanning is also an extremely inefficient technique for triggering rules. In general, you should avoid scanning rules, except when the application specifically requires periodic processing. For example, you might use scanning to check for system anomalies on a regular basis or under alarm conditions.

To implement scanning, you specify a Scan-interval for the rule.

Before you use scanning in a deployed application, you should always give a consideration to alternative techniques for invoking a rule. If you must scan a rule because no suitable event detector exists, follow these guidelines:


Caution: Scanning can create serious performance problems for applications running in as-fast-as-possible mode.

Write Rules that are as Generic as Possible

The syntax for rules allows you to specify the level in the class hierarchy to which the rule applies. You do this by providing a for prefix in the rule or by referring directly to the generic class within the body of the rule. This type of rule is called a generic rule, because it applies generically to a wide set of instance of a class at a particular level in the class hierarchy. For example, these two rules are equivalent:

For maximum efficiency, you should always write generic rules at the appropriate level in the class hierarchy. This implies these two guidelines:

Do Not Use "Initially" Rules

"Initially" rules invoke when the KB starts. Historically, applications used "initially" rules to perform startup procedures. However, in modularized KBs, conflicts in startup procedures often arise due to the order in which G2 loads and initializes the modules. The only way of controlling the precedence of "initially" rules across module boundaries is to specify a priority for each rule, which is often unreliable due to conflicting priorities in different modules.

To control the startup behavior of different modules reliably, use the startup objects that the G2 Foundation Resources (GFR) utility module provides. This object allows you to control the exact order in which each startup procedure in each module executes.

For more information on controlling startup behavior, see the G2 Foundation Resources User's Guide.

Use "Unconditionally" Rules with Caution

You should use "unconditionally" rules with caution because they take the actions in the consequent regardless of any test in the antecedent. If you misuse this type of rule, you can unknowingly create a potentially large number of rule invocations.

Minimize Backward Chaining

Backward chaining represents another way of invoking rules by chaining. If the application requires the value of a variable that appears in the consequent of a rule, G2 invokes the rule by backward chaining to that rule. Due to the added complexity that backward chaining introduces to the path of execution of rules, we recommend that you limit the use of backward chaining as the primary means of invoking a rule.

For guidelines on using backward chaining, see Guidelines for Using Variables.

Narrow the Scope of Rules to Minimize Rule Invocations

G2 allows you to use these features to narrow the scope of any rule:

Whenever possible, specify rule categories, focal classes, and/or focal objects to provide fine-tuned control over rule invocations and to minimize unnecessary rule invocations.

Disable Rule Highlighting

As a diagnostic tool, G2 allows you to highlight rules when they are executed by choosing Main Menu > Run Options > Highlight Invoked Rules. When this option is enabled, each rule that G2 invokes highlights for about 0.2 seconds, which is enough time to perceive the color change as a flash. During that time, no other activities take place within G2. Therefore, every rule that invokes when highlighting is enabled takes up about 20% of the available CPU. If you use this option during development, do not forget to disable it in the deployed KB.

| Prev | Next | Start of Chapter | End of Chapter | Contents | Glossary | Index | Comments | (5 out of 7)

Copyright © 1997 Gensym Corporation, Inc.