ruleset <nameOfRuleSet> {
< import Statement>* // Zero or more statements < library Statement>* // Zero or more statements < predicates Statement> // required when using Predicate inference engine void main() using <inferenceMethod>( options) { } ... } |
Ruleset processing options statements:
These statements allow you to import external Java classes for use in rules, add domain-specific user-defined function libraries, and define a list of predicates (for use with the Predicate engine only).
Processing options statements...
These statements allow you to specify which inference engine is used to process the rules in the main ruleblock and to set associated control parameters used by the selected inference engine.
For rulesets containing fuzzy variables and rules, specifies the manner in which a solution variable's fuzzy representation is updated.
For rulesets with no fuzzy variables and rules, specifies the type of inferencing to be performed.
If left unspecified, the default InferenceMethod is Script.
The specified InferenceMethod applies only to the main() rule block. All other rule blocks are processed with the Script engine.
Syntax
void main() using <inferenceMethod>( options ) void main() using FuzzyAdd | MinMax | ProductOr 1 void main() using Script | Forward | Forward2 | Forward3 | Mixed | Predicate | Backward 2
Inference Methods
This chart shows the degree of support that each inferencing engine provides for specific Able Rule Language features. Any feature marked NS is Not Supported, meaning the inferencing engine tolerates the presence of the feature in a ruleset but will not process it. These features will produce warnings. The presence of any feature marked NO will prevent a ruleset from executing so an error will be issued when the ruleset parses.
ARL Feature | All ruleblocks | Main ruleblock1 | |||||
---|---|---|---|---|---|---|---|
Inferencing method | Script | Fuzzy2 | Forward | Forward2 | Forward3 | Backward3 | Predicate3 |
Assertion rule | yes | yes | yes | yes | yes | yes | yes |
If/Then If/Then/Else If/Then{} rules4 | yes | yes | Else clause not supported | NS | NS | Else clause / multiple consequents not supported | Else clause / multiple consequents not supported |
While/Do or Until/Do loop rule | yes | yes | NS | NS | NS | NS | NS |
When/Do pattern match rule | yes | no | NS | yes | yes | NS | NS |
Predicate rule | no | no | no | no | no | no | yes |
Fuzzy variable | no | yes | no | no | no | no | no |
Processing order5 |
assertions, then sequential | assertions, then sequential | assertions, then sequential | assertions, priority, sequential | assertions, priority, sequential | assertions, then sequential | assertions, priority, sequential |
1 Some inferencing methods are used only in the main ruleblock. The Script inferencing method is used to process other ruleblocks for these inferencing engines.
2 ProductOr, MinMax and FuzzyAdd inferencing methods.
3 At runtime, Backward chaining and Predicate inferencing require a GoalVariable or GoalPredicate respectively. A warning is issued when the ruleset is parsed if no variable is provided. The variable may be set via API before the ruleset is processed.
4 If/Then conditional rules have three variants:
Simple | if x == 0 then y = 1 |
Else | if x == 0 then y = 1 else y = 2 |
Multiple consequents | if x==0 then y=0 z=1 else y=1 z=1 |
5 Rule processing order is generally assertions first, then rule priority (if supported), and finally in the sequence provided by the ruleset. See the JavaDoc for the appropriate inferencing engine for more details.
Examples
RuleSet <nameOfRuleSet> ( void main() using FuzzyAdd(alphaCut=0.1, correlationMetho=Product, defuzzifyMethod=Centroid) { } // For a ruleset with // fuzzy (and other) variables. void main() using Forward() { } // For a ruleset with // NO fuzzy variables. void main() using Backward(goalVariable=customerType) { } void main() using Script() { } void main() using Predicate(goalPredicate=son(X, John)) { } . . . ) |
1 Rulesets with fuzzy variables and rules.
2 Rulesets with no fuzzy variables or rules.
For rulesets with fuzzy clauses, specifies the threshold at which truth values become insignificant. If the truth value of any antecedent clause falls below the alphacut when the clause is evaluated, the inference engine stops evaluating the rule in which the clause appears.
If left unspecified, the default AlphaCut value is 0.1.
Syntax
alphaCut=<numericValue>
Parameters
Example
ruleset <nameOfRuleSet> { void main() using FuzzyAdd(alphaCut=0.20) { } . . . } |
For rulesets with fuzzy clauses, specifies the manner in which a rule's consequent fuzzy region is correlated with the rule's antecedent fuzzy truth value.
If left unspecified, the default CorrelationMethod is Product.
Syntax
CorrelationMethod=(Product | Minimum )
Parameters
Example
ruleset <nameOfRuleSet> { void main() using FuzzyAdd(CorrelationMethod=Minimum) { } . . . } |
For rulesets with fuzzy clauses, specifies the manner in which a fuzzy set is turned into a crisp numeric value.
If left unspecified, the default DefuzzifyMethod is Centroid.
Syntax
DefuzzifyMethod=Centroid | MaxHeight
Parameters
Example
ruleset <nameOfRuleSet> { void main() using FuzzyAdd(DefuzzifyMethod=Centroid) { } . . . } |
When InferenceMethod is predicate, specifies the names of predicates used in rules. All predicates referenced in rules must be pre-declared in this section.
This statement should not be used with other inference methods.
Syntax
predicates { <predicateName>* };
Parameters
Example
ruleset <nameOfRuleSet> { predicates { father, mother, sister, brother, aunt, uncle } ; . . . } |
Specifies the variable for which the backward chaining inference engine is to solve. GoalVariable is a required statement when using Backward is specified. For other inference methods, the statement must not be used.
Syntax
void main() using Backward(goalVariable=<variableName>) { }
Parameters
Example
ruleset <nameOfRuleSet> { variables { Diagnosis string("unknown"); ... } void main() using Backward(goalVariable=Diagnosis) { // The backward chaining inference engine // tries to determine the diagnosis. . . . } |
When InferenceMethod is Predicate, specifies the goal(s) of the predicate inference engine.
This option must immediately follow the using Predicates clause.
Syntax
GoalPredicates= <predicateClause>*
Parameters
Example
ruleset <nameOfRuleSet> { predicates { male, female, father, mother, parent, son, daughter, brother } // Who is the brother of Milcah? void main() using Predicate(goalPredicate=brother(milcah,X)) { } . . . void main() using Predicates(goalPredicate=brother(X, John)) { } } |
Allows you to import all the public methods in the specified classes (or libraries) as user-defined functions without having to declare each method explicitly. Imported methods then become available to be called from rules. Note that if two or more imported classes contain duplicate method names with an identical number of arguments, the last method imported is the method that is available to your rules. Also, when using imported methods in rules, you must use the number and types of arguments expected by the method. No checking is done, and improper use will result in runtime errors during ruleset processing. Remember that all numbers used in the rules package are implemented as doubles.
See also the functions statement.
See also the general section on interacting with functions. Among other things, the section describes some built-in method libraries that are available.
Note that built-in functions always take precedence over imported functions of the same name and arity.
Syntax
library package.class;
Parameters
Examples
ruleset <nameOfRuleSet> { library com.binford.Hammers; library com.binford.Saws; library com.tooltime.FirstAid; . . . } |
The first two statements loads and defines all the public methods in both Hammers and Saws as user-defined functions. The third statement additionally loads all the public methods in FirstAid. If the Hammers library contains the public method driveNail(), for example, then a rule such as the following can be coded:
rule: if (nail_length == 6) then rc = driveNail(); |
Allows you to define (import) your own data types so that you can declare and manipulate variables of those types. Each type you declare must be equated to a public Java class. Note: One import statement can define only a single Java class. Asterisks ("*") are not allowed in the import specification.
Syntax
import package.class; import com.yourCo.ClassName ; import com.yourCo.PackageName.* ; // NOT ALLOWED!
Parameters
The class name is an Identifier that names a new data type. Variables of this type can then be declared and used throughout your ruleset. You must not redefine the built-in data types.
Example
RuleSet <nameOfRuleSet> ( import hanoi.Puzzle; import hanoi.Ring; import hanoi.Logger; . . . ) |
The first statement imports the "hanoi.Puzzle" class, mapping the data type Puzzle to instances of objects of type "hanoi.Puzzle" and the data type Ring to instances of objects of type "hanoi.Ring." The second statement additionally equates the data type DataLog to instances of objects of type "hanoi.Logger".
These statements then allow the ruleset author to define variables such as shown below. Note that for each variable declaration an instance of the specified class is created and the constructor is passed the arguments in parentheses.
ruleset <nameOfRuleSet> { . . . variables { Puzzle easyPuzzle = new Puzzle("Puzzle1"); // Name Puzzle hardPuzzle = new Puzzle("Puzzle2"); // Name Ring smallRing = new Ring("RingA", 2); // Name, diameter Ring mediumRing = new Ring("RingB", 4); // Name, diameter Ring largeRing = new Ring("RingC", 6); // Name, diameter } . . . } |
In the example above, Puzzle (the hanoi.Puzzle class) must have a constructor that takes a string as a parameter. Ring (the hanoi.Ring class) must have a constructor that takes a string and a number as parameters. Variables as declared above will create an instance of the respective class.
Furthermore, depending on whether the Ring class has public members, or at least public getter and setter methods for internal members, rules such as the following might be allowed, where diameter is a publicly accessible member of class Ring.
ruleset <nameOfRuleSet> { . . . void main() using Script() { r1: if (smallRing.diameter >= mediumRing.diameter) then result = someAction(); } . . . } |