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
          )

          GoalVariable   ( <variableName> )        // Backward chaining only
          InputVariables ( <variableName>* )       // Exactly one statement, zero or more names
          OutputVariables( <variableName>* )       // Exactly one statement, zero or more names
          UserDefinedFunctions ( <name/arity>* )*  // Zero or more statements, zero or more names

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

        ) ;End of ruleset

On this page...

- About Rules
- General Rule Syntax

- Rule Types

- Assertion Rules
- If-Then Rules
- When-Do Rules
- Predicate Rules
- While-Do Rules
- Do-Until Rules

- Clauses: Rule Building Blocks

- Assignment Clauses
- Comparison Clauses
- Pattern Match Clauses
- Predicate Clauses

- Hedges for Fuzzy Clauses

### 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

          .
          .
          .

        Rules <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
- If-Then
- When-Do
- Predicate
- While-Do
- Do-Until

#### 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

        Rules <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 (case insensitive), 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.

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 whitespace.

Example

        Rules <nameOfRuleBlock> (

          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

        Rules <nameOfRuleBlock> (
        .
        .
        .

        : 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

        Rules <nameOfRuleBlock> (

           InferenceMethod(Predicate)

           Predicates(male, female)
           Predicates(father mother parent)
           Predicates(son, daughter, brother)

           GoalPredicate ( brother(milcah,X) )  // Who is the brother of Milcah?

          .
          .
          .

          Rules (

            : 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

        Rules <nameOfRuleBlock> (

          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-Until Rules

Do-Until 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-Until rules have any number of test conditions separated by the keyword and (case insensitive) in the Until part of the rule, and one or more consequent clauses appearing in the Do part of the rule.

Syntax

        Until (
               <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

        Rules <nameOfRuleBlock> (

          Check_and_Lower_Temp:        // Label, no priority
              Until (
                     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

### Clauses: Rule Building Blocks

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

- Assignment
- Comparison
- Pattern Match
- Predicate

#### 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

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

Parameters

<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.

<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.

!
  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

        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'
                 )

        p Puzzle ! (                   // 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'
                   )

        p Puzzle (                     // 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:

  - cut() cut and backtrack
  - fail() fail the rule

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

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

  - A symbol beginning with an uppercase character; these are variables completely local to the current rule.
  - A symbol beginning with a lowercase character; these may be the name of a declared global variable or, if a global variable of the specified name doesn't exist, a simple symbol.
  - A boolean literal.
  - A numeric literal.
  - A string literal.
  - A list enclosed in square brackets; for example, [a , b, c]. A list may contain any of the elements enumerated here, including other lists and predicates. The special character bar (|) denotes the "tail" of the list.
  - Other predicates.
  - The "don't care" symbol, which is the underscore character (_).

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.

- About
- Above
- Below
- CloseTo
- Extremely
- Generally
- InVicinityOf
- Not
- Positively
- Slightly
- Somewhat
- Very

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