10 Modular Design and Execution Control

Deftemplate Attributes

Type

(deftemplate person
    (multislot name (type SYMBOL))
    (slot age (type INTEGER)))

(assert (person (name Fred Smith)
        (age four)))            ;wrong type

The type attribute is either ?VARIABLE for any data type, or one or more of SYMBOL, STRING, LEXEME, INTEGER, FLOAT, or NUMBER.

Static and Dynamic Constraint Checking

(defrule create-person
    =>
    (printout t "What's your name? ")
    (bind ?name (explode$ (readline)))
    (printout t "What's your age? ")
    (bind ?age (read))
    (assert (person (name ?name)
            (age ?age))) )

If age entered is of a wrong type, e.g. "four", it is not checked at parse time. Dynamic constraint checking can be enabled using

    (set-dynamic-constraint-checking TRUE)     ; FALSE if disable

Allowed Value

(deftemplate person
    (multislot name (type SYMBOL))
    (slot age (type INTEGER))
    (slot gender (type SYMBOL)
            (allowed-symbols male female)) )

Range

(deftemplate person
    (multislot name (type SYMBOL))
    (slot age (type INTEGER)
        (range 0 ?VARIABLE)) )

Cardinality

(deftemplate volleyball-team
    (slot name (type STRING))
    (multislot player (type STRING)
        (cardinality 6 6))
    (multislot alternates (type STRING)
        (cardinality 0 2)) )

Default

The default value is assigned in a slot if no value is explicitly stated in an assert command. The default value is determined when the slot definition is parsed.
(deftemplate example1                           ;default values
    (slot a)                                    ;  nil
    (slot b (type INTEGER))                     ;  0
    (slot c (allowed-values red green blue))    ;  red
    (multislot d)
    (multislot e (cardinality 0 2)              ;  3.5 3.5
        (type FLOAT)
        (range 3.5 10.0)) )

(deftemplate example2
    (slot a)
    (slot b (default ?NONE)) )                  ;no default value

(deftemplate example3
    (slot a (default 3))                        ; 3
    (slot b (default (+ 3 4)))                  ; 7
    (multislot c (default a b c))               ; a b c
    (multislot d (default (+ 1 2) (+ 3 4))) )   ; 3 7

Example: default.clp

Default-Dynamic

A slot with default-dynamic attribute will have its default value generated when the fact with that slot is asserted.
(deftemplate data
    (slot create-time (default-dynamic (time)))
    (slot value))

(defrule retract-data-facts-after-one-minute
    ?f <- (data (create-time ?t1))
    (current-time ?t2)
    (test (> (- ?t2 ?t1) 60))
    =>
    (retract ?f))

(assert (data (value 3)))

(assert (current-time (time)))

Example: time.clp

Salience

(deffacts init
    (priority first)
    (priority second)
    (priority third))

Without salience declaration

(defrule fire-first
    (priority first)
    =>
    (printout t "Print first" crlf))

(defrule fire-second
    (priority second)
    =>
    (printout t "Print second" crlf))

(defrule fire-third
    (priority third)
    =>
    (printout t "Print third" crlf))

with salience declaration

To assign a salience value to a rule, use the declare command,
(defrule fire-first
    (declare (salience 30))
    (priority first)
    =>
    (printout t "Print first" crlf))

(defrule fire-second
    (declare (salience 20))
    (priority second)
    =>
    (printout t "Print second" crlf))

(defrule fire-third
    (declare (salience 10))
    (priority third)
    =>
    (printout t "Print third" crlf))

Phases and Control Facts

(deffacts control-information
    (phase detection)
    (phase-seq detection isolation recovery))

(defrule change-phase
    (declare (salience -10))
    ?phase <- (phase ?current-phase)
    ?list  <- (phase-seq ?next-phase
                         $?other-phases)
    =>
    (retract ?phase ?list)
    (assert (phase ?next-phase))
    (assert (phase-seq ?other-phases
                       ?next-phase)))

Defmodule

A knowledge base can be partitioned using the defmodule construct.
(defmodule DETECTION)
(defmodule ISOLATION)
(defmodule RECOVERY)

(defrule example1 =>)               ; in current module
(defrule ISOLATION::example2 =>)    ; in module ISOLATION

(get-current-module)
(set-current-module DETECTION)

Example: defmodule.clp

Importing and Exporting Facts

(deftemplate DETECTION::fault
    (slot component))
(assert (fault (component A)))                 ; in module DETECTION

(deftemplate ISOLATION::possible-failure
    (slot component))
(assert (possible-failure (component B)))      ; in module ISOLATION

(facts DETECTION)      ; (fault (component A))
(facts ISOLATION)      ; (possible-failure (component B))
(facts RECOVERY)       ; none
(facts *)              ; list all facts

export and import

A fact is "owned" by the module in which its deftemplate is contained. To make facts visible to other modules, use the export in the owning module. In order to use the deftemplate defined in another module, a module must import the deftemplate.

The export attribute use one of the following formats:

(export ?ALL)
(export ?NONE)
(export deftemplate ?ALL)
(export deftemplate ?NONE)
(export deftemplate <deftemplate-name>+)

The import attribute use one of the following formats:

(import <module-name> ?ALL)
(import <module-name> ?NONE)
(import <module-name> deftemplate ?ALL)
(import <module-name> deftemplate ?NONE)
(import <module-name> deftemplate <deftemplate-name>+)

Example: defmodule.clp

Demo: phases.clp

Modules and Execution Control

(defrule DETECTION::rule-1
    (fault (component A | C))
    =>)

(defrule ISOLATION::rule-2
    (possible-failure (component B | D))
    =>)

(defrule RECOVERY::rule-3
    (fault (component A | C))
    (possible-failure (component B | D))
    =>)

Focus

The current focus determines which agenda the run command uses during execution. The reset and clear commands automatically set the current focus to the MAIN module.
(focus DETECTION)
(focus DETECTION ISOLATION RECOVERY)

Manipulating and Examining the Focus Stack

(list-focus-stack)
(get-focus-stack)
(clear-focus-stack)
(get-focus)         ;get current focus
(pop-focus)         ;remove current focus

Return

Terminate current module and return to the next module.
(defmodule MAIN
    (export deftemplate initial-fact))          ; must

(defmodule DETECTION
    (import MAIN deftemplate initial-fact))     ; must

(defrule MAIN::start
    =>
    (focus DETECTION))

(defrule DETECTION::example-1
    =>
    (return)
    (printout t "No printout!" crlf))           ; not printed

(defrule DETECTION::example-2                   ; no chance to fire
    =>
    (return)
    (printout t "No printout!" crlf))

Example: return.clp

note: Jess has no export/import mechanisms.

More Examples:

Auto-focus

A rule's module is automatically focused upon when that rule, being declared auto-focus, is activated.
(defmodule MAIN
    (export deftemplate initial-fact))

(defmodule DETECTION
    (import MAIN deftemplate initial-fact))

(defrule DETECTION::example
    (declare (auto-focus TRUE))
    =>)

Example: autofocus.clp

Replacing Phases and Control Facts

(defmodule DETECTION)
(defmodule ISOLATION)
(defmodule RECOVERY)

(deffacts MAIN::control-information
    (phase-seq DETECTION ISOLATION RECOVERY))

(defrule change-phase
    ?list  <- (phase-seq ?next-phase
                         $?other-phases)
    =>
    (focus ?next-phase)
    (retract ?list)
    (assert (phase-seq ?other-phases
                       ?next-phase)))

Example: control-2.clp

Previous Advanced Pattern Matching   Up TOC   Next Procedural Programming