Cognitive Tutor Authoring Tools 2.6 > Using the Tools > Cognitive Tutors (Jess) > Writing Jess Production Rules

4.3. Writing Jess Production Rules

4.3.1. Anatomy of a production rule
4.3.2. Naming a production rule
4.3.3. Predicting a student action
4.3.4. Providing hints or feedback messages
4.3.5. Jess Resources

In a Cognitive Tutor, production rules in Jess model student procedural knowledge and misconceptions. A single rule can model either correct knowledge or a misconception, but not both.

4.3.1. Anatomy of a production rule

A production rule begins with the Jess construct defrule. For example:

(defrule write-answer ...

In a single rule, a left-hand side (LHS) portion of the rule specifies a pattern to match against the contents of working memory. The right-hand side (RHS) portion of the rule specifies a function or functions to call when the LHS matches. This division is common to all Jess productions rules, not just rules in CTAT. The '=>' symbol separates the LHS (above the '=>') from the RHS (below the '=>').

(defrule add-first-column-no-carry
  ?problem <- (problem
    (interface-elements $? ?table $?)
    (subgoals ))
  ...
=>
  (bind ?sum (+ ?num1 ?num2))
  (modify ?result (value ?sum))
  ...
) 

4.3.2. Naming a production rule

Rules that model correct knowledge can be named anything you'd like. Ideally, they should reflect the production the student is to learn. Some example production rule names:

  • add-first-column-no-carry

  • determine-lcd

  • determine-reduction-factor

Rules that model a student misconception, however, must be named with the text bug+ (where "+" is any non-alphabetic character) or buggy at the beginning of the rule name. Some example incorrect, or buggy, production rule names:

  • BUG-reduce-numerator

  • buggy-add-next-column-did-not-write-carry

  • buggy-done

4.3.3. Predicting a student action

To predict an action that a student should take for a production rule to be fully activated, use the predict-observable-action function in the RHS of your production rule. The syntax of this function is:

(predict-observable-action <selection> <action> <input> <matcherType>?)

<matcherType> is optional. If omitted, an exact match will be used.

This function can also be invoked more concisely as (predict <selection> <action> <input> <matcherType>?).

Predict is a special Jess function provided by CTAT that limits whether or not a production rule can make changes to working memory. If predict returns false—if the student does not take the predicted action—then the rule will not modify working memory, the effects of other function calls on the RHS of that rule will be undone, and the student's input will be marked as incorrect. If predict returns true—if the model correctly predicts the student's action—then the rule will be allowed to make changes to working memory, and the student's input will be marked as correct.

Example 2.1. Example use of predict-observable-action

You suspect that for a given production to be true, the student must enter the number '5' in the field called 'firstNum'. You'd call this function in the RHS of the rule as follows:

(predict-observable-action firstNum UpdateTable 5)

In the above example, the <matcherType> argument is omitted.

A matcher is a type of comparison used when determining whether or not the student input matched the predicted input. When the matcherType argument is omitted, an 'exact' match will be used (ie, the predicted input must exactly match that entered by the student).

Other types of matching, defined in Section 3.2.1, “Input Matching”, are specified by using one of the names below:

  • AnyMatcher

  • ExactMatcher (default when matcherType is omitted)

  • RangeMatcher

  • RegexMatcher

  • WildcardMatcher

As each matcher takes different input parameters, the syntax for each matcher in (predict) is slightly different:

  • (predict <selection> <action> <dummyInput> AnyMatcher)

  • (predict <selection> <action> <input> ExactMatcher)

  • (predict <selection> <action> <input minimum> <input maximum> RangeMatcher)

  • (predict <selection> <action> <regular expression string for input> RegexMatcher)

  • (predict <selection> <action> <input containing wildcards> WildcardMatcher)

An example of calling each matcher is shown below:

  • (predict ?cell-name "UpdateTable" 999 AnyMatcher)

  • (predict ?cell-name "UpdateTable" 2 ExactMatcher)

  • (predict ?cell-name "UpdateTable" 12 14 RangeMatcher)

  • (predict ?cell-name "UpdateTable" "2[x,y,z]" RegexMatcher)

  • (predict ?cell-name "UpdateTable" "The quick brown fox * the lazy dog." WildcardMatcher)

In addition, you can create your own matcher as a Jess function. For details and an example for defining a new matcher as a Jess function, see Section 4.4.1, “Writing a matcher function”.

(Predict) returns false or throws an exception to halt Rete, the Jess pattern matching algorithm, if the student's action doesn't match the function's three arguments.

Special argument values

Special arguments to (predict) are values DONT-CARE (matches any student value for this selection, action, or input element) and NotSpecified (skips a check of this selection, action, or input element).

4.3.4. Providing hints or feedback messages

To add one or more messages to the list of hint or feedback messages available to the student, use the (construct-message) function in the RHS of your production rule.

(construct-message) works by concatenating its arguments to form messages: square brackets ([ ]) delimit one message from another.

Example 2.2. Adding hint messages

Below, we add a sequence of four hint messages for the student who is stuck on this rule:

(defrule done
 ?problem <- (problem (answer-fractions $? ?unreduced-answer $?))
    ?unreduced-answer <- (fraction (numerator ?num) (denominator ?denom))
 ?num <- (textField (value ?n&:(neq ?n nil)))
 ?denom <- (textField (value ?d&:(neq ?d nil)))
 (test (eq (gcd ?d ?n) 1))
=>
(predict done ButtonPressed -1)
    (construct-message
       [ Is there anything else to do?]
       [ If the greatest common divisor of a numerator and a denominator is 1, 
           then the fraction cannot be further reduced.]
       "[The greatest common divisor of " ?d " and " ?n " is 1.]"
       [ You are done. Press the done button.]
    )
)

[Note]Note

To reference variables in the construct-message function (as in the example above), explicitly set the surrounding message text as a string by using double-quotes.

To create a feedback message for an incorrect action by the student, use the same syntax of (construct-message), but in a buggy rule.

[Note]Note

Parentheses in construct-message are problematic for model tracing in CTAT. To use parentheses, you must surround the text containing the parentheses with double quotes. For example:

(construct-message 
    ["Start with the column on the right. (This 
    is the 'ones' column.)" ])

(construct-message 
    ["Move on to the" ?pos "column from the 
    right. (This is the" ?col-name "column.)"])

4.3.5. Jess Resources

For more information on writing production rules in Jess, see Chapter 6 "Making Your Own Rules" of the official Jess language reference.

For documentation of existing Jess functions, see the Jess Function List of the Jess language reference.