ARL Master Index


Rule Statements

All rule statements within a ruleset are grouped within one or more rule block statements.


    ruleset <nameOfRuleSet> {
  
     <Processing Options Statement>*          // Zero or more statements 

  variables {
      <Variable Declaration Statement>+      // One or more statements 

   } 

   inputs { <variableName>*  }   // Exactly one statement, zero or more names 

   outputs { <variableName>* } // Exactly one statement, zero or more names 


  functions ( <name/arity>* )*  // Zero or more statements, zero or more names


  void <nameOfRuleBlock>() {
       <rule>+                                // One or more rules in a rule block 
  }  // One or more rule blocks 
}    

On this page...


About Rules

ABLE provides many different types of rules, from simple assertion statements, to If-Then rules, to more complex When-Do pattern matching rules. Rules in most rule blocks are processed sequentially, so the order in which you enter them is important. Rules appearing in the MAIN rule block are always processed in an order that is determined by the inference engine, so it doesn't matter at all what order is used.

All rules may have a priority, but not all inference engines use the priority, even if specified. Other inference engines rely on priority to do a good job. Rules may also have a label, but these are only for the author's use; they are completely ignored by the inference engines.

The number of rules you can have in a rule block is limited only by the amount of memory you have in your computer.

Return to top

General Rule Syntax

Syntax


   <label> <[priority]> : <ruleBody> ;
     
      

Parameters

       <label>
Is an optional Identifier that you can use to tag your rule with meaningful information. Labels show up in trace and debug output, but are not otherwise used by Able.
       <[priority]>
Is an optional number, in square brackets, that represents the priority of the rule. Priorities are represented as doubles in Able and have meaning only to inference engines that use them. When omitted, a rule's default priority is 1.0.
       :
The colon is a required element, even if the rule label and priority are omittted.
       <ruleBody>
Is a basic rule type, either an assertion rule, an If-Then rule, a When-Do rule, or a Predicate rule, all of which are made up of common rule clauses. Common clauses are assignment clauses, comparison clauses, pattern match clauses, and predicate clauses.

Example

      .
      .
      .

    void <nameOfRuleBlock>() {
       A1: someVar = someOtherVar ;          // Label is...... 'A1'
                                            // Priority is... omitted, defaults to 1.0
                                            // RuleBody is... 'someVar = someOtherVar'

       r2 [5] : if (someVar == true) then x=y; // Label is...... 'r2'
                                            // Priority is... '5'
                                            // RuleBody is... 'if someVar == true then x=y'

       :female=false;                        // Label is...... omitted
                                            // Priority is... omitted
                                            // RuleBody is... 'female=false'
    }

      .
      .
      .
     
      
Return to top

Rule Types

The body of a rule can be one of several different types. The basic rule bodies are:

Assertion Rules

Assertions are simply assignment statements. Since the inference engines evaluate all assertions before evaluating any conditional rules, you can use assertions to give initial values to variables. However, if you use assertions simply to assign initial values to variables, it is preferable, in most cases, to accomplish this through an external input buffer (and values assigned in this way always take precedence over any assertion rules in a ruleset).

There are two useful ways to use assertions:

  1. You may want to use assertions to test a ruleset from within the ruleset editor; you can quickly change asserted values, re-verify the ruleset, and then re-run it, repeating the test cycle quickly and easily. When you are done testing, comment-out the assertions and create an InputVariables statement so that values can be assigned through the external input buffer.


  2. You may want to assign a variable the value of a user-defined function. In this case, do not pass a value through an input buffer, but let the user-defined function determine the initial value.

Syntax

   See Assignment Clauses
      

Example


    void <nameOfRuleBlock>() {

      A1: someVar = someOtherVar ;          // Label, but no priority
      :isMale=determineIfMale(person);      // Neither label nor priority

    }
     
      
Return to top

If-Then Rules

If-Then rules are evaluated conditionally, based on known data. The order of evaluation is determined by the inference engine, but if your ruleset is a pure fuzzy ruleset, all rules are essentially evaluated in parallel, each rule playing a part in the solution.

If-Then rules have any number of antecedent clauses separated by the keyword and, and one or more consequent clauses appearing in the then part of the rule. The else part of the rule is optional and, if present, contains one or more clauses. The then keyword is optional. Braces must be used when more than one consequent clause appears in the then or else part of the rule.

Syntax


    if (
          <comparisonClause>+ )
    then {
          <assignmentClause>+
    } else {
          <assignmentClause>+

Parameters

       <comparisonClause>
Is a list of one or more comparison clauses, each clause separated by the keyword "and". At least one clause is required.
       <assignmentClause>
Is a list of one or more assignment clauses separated by semicolons.

Example


    void <nameOfRuleBlock> using Script() (

      Test_the_Temperature:            // Label, no priority
          if
               ( temp is very hot and   // Comparison clause, connector 'and'
                switch == "on" [0.5])   // Comparison clause
          then
                pressure is high ;      // Assignment clause

      F1: if (a>=b) then c=d ;

      :   if  ( c < d )
          then
               x = z(parm1, parm2);

    )
     
      
Return to top

When-Do Rules

When-Do rules are evaluated conditionally, based on known data. The order of evaluation is determined by the inference engine.

When-Do rules may have any number of pattern match clauses separated by the keyword and (case insensitive), and multiple assignment clauses.

Syntax


    when (
          <patternMatchClause>+
         )
    do   {
          <assignmentClause>+
         }
     
    

Parameters

       <patternMatchClause>
Is a list of one or more pattern match clauses, each clause separated by an optional ampersand ('&') character. The entire set of clauses must be within the parentheses that make up the When block. At least one clause is required.
       <assignmentClause>
Is a list of one or more assignment clauses separated only by whitespace. The entire set of clauses must be within the parentheses that make up the Do block. At least one clause is required.

Example


    void <nameOfRuleBlock> using Forward2() (
    .
    .
    .

    : when (
        p Puzzle (                   // There must exist some Puzzle 'p' such that
                  p.level == "hard", // p's level is equal to 'hard' and
                  p.start == postN   // p's start is equal to the value of variable 'postN'
                 ) &
        r Ring   (                   // There must exist some Ring 'r' such that
                  r.diam > 0         // r's diameter is greater than zero
                 )
           )
      do {
          solution.level = p.level;
          solution.ringSize = r.diam;
         }
    .
    .
    .
    )
     
      
Return to top

Predicate Rules

Predicate rules are valid only in rulesets whose InferenceMethod is set to Predicate.

Syntax


    <predicateClause>.                // Fact

    <predicateClause> <- <clause>+ .  // Rule
     

    

Parameters

       <predicateClause>
Is a predicate clause.
       <clause>
Is a list of one or more predicate clauses, comparison clauses, or assignment clauses, all separated by ampersands ("&") or commas.

Example


    predicates { male, female, father, mother, parent, son,
                 daughter, brother }



    void main() using predicate(goalPredicate= brother(milcah,X)) {


        : father(abraham, isaac).    // Abraham is the father of Issac
        : father(haran, lot).        // Haran is the father of Lot
        : father(haran, milcah).     // Haran is the father of Milcah
        : father(haran, yiscah).     // Haran is the father of Yiscah
        : male(isaac).               // Issac is male
        : male(lot).                 // Lot is male
        : female(milcah).            // Milcah is female
        : female(yiscah).            // Yiscah is female

        R1: son (X, Y) <- male(X) & father(Y, X).
        R2: daughter(X, Y) <- female(X) & father(Y, X).
        R3: brother (X, Y) <- male(Y)   & parent(P,X) & parent(P, Y) & X != Y
        R4: parent (X, Y) <- father(X, Y).
        R5: parent  (X, Y) <- mother(X, Y).

      )

    )
     
      
Return to top

While-Do Rules

While-Do rules are looping rules, evaluated conditionally, based on known data. The test conditions are evaluated, and, if true, the body of the rule is processed. The cycle repeats until the test conditions are no longer true.

While-Do rules have any number of test conditions separated by the keyword and (case insensitive) in the While part of the rule, and one or more consequent clauses appearing in the Do part of the rule.

Syntax


    while (
           <comparisonClause>*
          )
       do {
           <assignmentClause>+
          }
     
    

Parameters

       <comparisonClause>
Is a list of zero or more comparison clauses, each clause separated by the keyword "and" (or a comma, if you prefer). If no test conditions are specified, the rule will loop forever with no means of escape.
       <assignmentClause>
Is a list of one or more assignment clauses separated by whitespace.

Example


    void <nameOfRuleBlock> using Script() (

      Check_and_Lower_Temp:        // Label, no priority
          while (
                 temp >= 212 and   // Comparison clause, connector 'and'
                 switch == "on"    // Comparison clause
                )
             do {
                 rc = invokeRuleBlock("lowerTemp");  // Assignment clause
                }

    )
     
      

In the above example it is to be hoped that the invoked rule block, lowerTemp, will set the global variable temp to a new temperature, or set the global variable switch to "off".

Return to top

Do-While Rules

Do-While rules are looping rules, evaluated at least once. The Do body of the rule is always processed first and then the test conditions are evaluated. If the test conditions are true, the cycle repeats until the test conditions are no longer true.

Do-While rules have any number of test conditions separated by the keyword and (case insensitive) in the While part of the rule, and one or more consequent clauses appearing in the Do part of the rule.

Syntax

       do {
           <assignmentClause>+
          }
       while (
           <comparisonClause>*
          )
     
    

Parameters

       <comparisonClause>
Is a list of zero or more comparison clauses, each clause separated by the keyword "and" (or a comma, if you prefer). If no test conditions are specified, the rule will loop forever with no means of escape.
       <assignmentClause>
Is a list of one or more assignment clauses separated by whitespace.

Example


    void <nameOfRuleBlock> using Script() {

      Check_and_Lower_Temp:        // Label, no priority
           Do {
                 rc = invokeRuleBlock("lowerTemp");  
} while ( temp >= 212 and // Comparison clause, connector 'and'
switch == "on" // Comparison clause )


}
 

In the above example it is to be hoped that the invoked rule block, lowerTemp, will set the global variable temp to a new temperature, or set the global variable switch to "off".

Return to top

Clauses: Rule Building Blocks

All rules are made up of clauses. The basic clauses are:

Assignment Clauses

Assignment clauses are used to assign a value to some variable; therefore, only a variable may appear on the lefthand side of an assignment clause. The righthand side of an assignment clause can be one of several things, but not all combinations are allowable. For example, a numeric variable cannot be assigned from a boolean literal.


  booleanVariable      = variable | typedVariable.field | functionName(arg*) | booleanLiteral
  categoricalVariable  =            typedVariable.field | functionName(arg*) |                                   stringLiteral 
  continuousVariable   =            typedVariable.field | functionName(arg*) |                  numericLiteral
  discreteVariable     =            typedVariable.field | functionName(arg*) |                  numericLiteral
  fuzzyVariable        =            typedVariable.field | functionName(arg*) |                  numericLiteral
  fuzzyVariable       Is hedge* fuzzySet
  listVariable         = variable | typedVariable.field | functionName(arg*) | booleanLiteral | numericLiteral | stringLiteral 
  numericVariable      = variable | typedVariable.field | functionName(arg*) |                  numericLiteral
  objectVariable       = variable | typedVariable.field | functionName(arg*) | booleanLiteral | numericLiteral | stringLiteral 
  stringVariable       = variable | typedVariable.field | functionName(arg*) |                                   stringLiteral 
  typedVariable        = variable | typedVariable.field | functionName(arg*) | booleanLiteral | numericLiteral | stringLiteral 
  typedVariable.field  = variable | typedVariable.field | functionName(arg*) | booleanLiteral | numericLiteral | stringLiteral 
     
    
Return to top

Comparison Clauses

Comparison clauses are used to test the current value of one object against the current value of another object. All of the usual comparison operators are available and have their standard meanings.

Comparison clauses can be suffixed by an optional WEIGHT, which is a number between 0.0 and 1.0. Weights are used by only the fuzzy inference engines, and can keep a boolean comparison from wildly skewing a fuzzy result. Weights are ignored by other inference engines. When omitted, a clause's default weight is 1.0.

Note that <> can be used in place of != for "not equal to".


  booleanVariable     ( == | !=                   ) (variable | typedVariable.field | functionName(arg*) | booleanLiteral                                 ) weight 
  booleanLiteral      ( == | !=                   ) (variable | typedVariable.field | functionName(arg*) | booleanLiteral                                 ) weight 
  categoricalVariable ( == | !=                   ) (           typedVariable.field | functionName(arg*) |                                   stringLiteral) weight 
  continuousVariable  ( == | != | < | <= | > | >= ) (variable | typedVariable.field | functionName(arg*) |                  numericLiteral                ) weight 
  discreteVariable    ( == | !=                   ) (           typedVariable.field | functionName(arg*) |                  numericLiteral                ) weight
  functionValue       ( == | != | < | <= | > | >= ) (variable | typedVariable.field | functionName(arg*) |                  numericLiteral | stringLiteral) weight 
  fuzzyVariable       ( == | != | < | <= | > | >= ) (variable | typedVariable.field | functionName(arg*) |                  numericLiteral                ) weight 
  fuzzyVariable       Is  hedge*  fuzzySet
  listVariable        ( == | !=                   ) (variable | typedVariable.field | functionName(arg*) | booleanLiteral | numericLiteral | stringLiteral) weight
  numericVariable     ( == | != | < | <= | > | >= ) (variable | typedVariable.field | functionName(arg*) |                  numericLiteral                ) weight 
  numericLiteral      ( == | != | < | <= | > | >= ) (variable | typedVariable.field | functionName(arg*) |                  numericLiteral                ) weight 
  objectVariable      ( == | !=                   ) (variable | typedVariable.field | functionName(arg*) | booleanLiteral | numericLiteral | stringLiteral) weight
  stringVariable      ( == | != | < | <= | > | >= ) (variable | typedVariable.field | functionName(arg*) |                                   stringLiteral) weight 
  stringLiteral       ( == | != | < | <= | > | >= ) (variable | typedVariable.field | functionName(arg*) |                                   stringLiteral) weight 
  typedVariable       ( == | !=                   ) (variable | typedVariable.field | functionName(arg*) | booleanLiteral | numericLiteral | stringLiteral) weight
  typedVariable.field ( == | != | < | <= | > | >= ) (variable | typedVariable.field | functionName(arg*) | booleanLiteral | numericLiteral | stringLiteral) weight 
     
          
Return to top

Pattern Match Clauses

Pattern match clauses look for the existence of variables such that the listed conditions are true.

Syntax

 <dataType> <variableName> [!] ( <comparisonClause>* )
     
      

Parameters

  <dataType>
Is either a user-defined data type that was declared with a UserTypes statement in the processing options section of the ruleset, or a Boolean, List, Numeric, Object, or String Able data type.
       <variableName>
Is an identifier that names a new variable. This variable is referenced in subsequent comparison clauses. Note that the first letter of the variable name specifies whether the variable is local to the rule or global. If the first character is uppercase, the variable is local to the current rule and cannot be referenced outside of the rule. If a global variable with the same name exists, it is ignored within this rule as the local variable takes precedence. If the first character of the variable name is lowercase, the variable is global and must have been previously declared in the Variables section of the ruleset.
      
       !
Is optional and means that no such object in working memory matches the pattern represented in the comparison clause(s). The tilde character (~) may be used instead of the exclamation point.
       <comparisonClause>
Is a list of zero or more comparison clauses, each clause separated by a comma. The entire set of clauses must appear between parentheses. If no comparison clauses are specified, all instances of the specified data type are selected for binding.

Examples


    Puzzle p (                   // There must exist some Puzzle 'p' such that
              p.level == "hard", // p's level is equal to 'hard' and
              p.start == postN   // p's start is equal to the value of variable 'postN'
             ) 
     
      


    Puzzle p ! (                   // There must not exist some Puzzle 'p' such that
                p.level == "hard", // p's level is equal to 'hard' and
                p.start == postN   // p's start is equal to the value of variable 'postN'
               ) 
     
      


    Puzzle p (                     // All puzzles are selected.
             ) 
     
      
Return to top

Predicate Clauses

Syntax



    <predicateName> ( <arg>* )
     
    

Parameters

       <predicateName>
Is the name of a pre-declared predicate. All predicate names must be pre-declared in the Predicates section of a ruleset.

There are some special predicate names:

       <arg>
Is a list of zero or more arguments to the predicate.

Predicates can take any number of arguments. Arguments may be any of:

Examples


    foo().               // No args
    foo(X).              // Local variable 'X'
    foo(bar, baz).       // Either global vars or simple symbols
    foo( [a, b | c] ).   // A list of 2 elements followed by any number of additional elements
    foo(X, _, bar(Y), "3", 4.4, true, z, [a,b] ).   // Something for everyone!
     
      
Return to top

Hedges for Fuzzy Clauses

The following hedges are available for qualifying a fuzzy set in a fuzzy clause. Multiple hedges may be used in any combination, but the rule author must be fully aware of what each hedge can do to the shape of a fuzzy set.

Approximation Hedges -- useful for all bell-shaped sets
CloseTo (1.2) Narrow approximation.
About (2.0) General approximation; slightly broadens the fuzzy region
InVicinityOf (4.0) Broad approximation; produces a very wide fuzzy space.

Restriction Hedges
Above Useful for decreasing linear and sigmoidal sets and for all bell-shaped sets; do not use with increasing linear and sigmoidal sets.
Below Useful for increasing linear and sigmoidal sets and for all bell-shaped sets; do not use with decreasing linear and sigmoidal sets.

Concentration Hedges -- these hedges depress the surface of linear sets and concentrate or intensify bell-shaped sets; the candidate space is reduced; a domain element must occur farther to the right for an equivalent truth value.
Very (2.0)  
Extremely (3.0)  

Dilution Hedges -- these hedges raise the surface of linear sets and dilute bell-shaped sets; the candidate space is increased; a domain element must occur farther to the left for an equivalent truth value.
Somewhat (0.5) Complement of very.
Slightly (0.3)  

Contrast Intensification Hedge
Positively (n2) Truth values less than .5 are decreased, truth values greater than .5 are increased; complement of generally.

Contrast Diffusion Hedge
Generally (n0.5) Truth values less than .5 are increased, truth values greater than .5 are decreased; complement of positively.

Negation Hedge
Not The fuzzy region is inversed.

Return to top


Able Rule Language master index.
Able RuleSet Editor master index.
Rules package table of contents.

Last modified: Thu Oct 11 13:55:09 Central Daylight Time 2001