9 Advanced Pattern Matching

The Game of Sticks

(deffacts initial-phase
   (phase choose-player))

(defrule player-select
   (phase choose-player) ; control pattern
   =>
   (printout t "Who moves first (Computer: c "
               "Human: h)? ")
   (assert (player-select (read))))

(defrule good-player-choice
   ?phase <- (phase choose-player)
   ?choice <- (player-select ?player&c | h)
   =>
   (retract ?phase ?choice)
   (assert (player-move ?player)))

(defrule bad-player-choice    ; if bad, then back to previous page
   ?phase <- (phase choose-player)
   ?choice <- (player-select ?player&~c&~h)
   =>
   (retract ?phase ?choice)
   (assert (phase choose-player))
   (printout t "Choose c or h only." crlf)
   )

Predicate Functions

test Conditional Element

(defrule get-human-move
   (player-move h)
   (pile-size ?size)
   (test (> ?size 1))
   =>
   (printout t "How many sticks do you wish to take? ")
   (assert (human-takes (read))))

(defrule good-human-move
   ?whose-turn <- (player-move h)
   (pile-size ?size)
   ?number-taken <- (human-takes ?choice)
   (test (and (integerp ?choice)
              (>= ?choice 1)
              (<= ?choice 3)
              (< ?choice ?size)))
   =>
   (retract ?whose-turn ?number-taken)
   (printout t "Human made a valid move." crlf)
   (assert (player-move c)))

(defrule bad-human-move
   ?whose-turn <- (player-move h)
   (pile-size ?size)
   ?number-taken <- (human-takes ?choice)
   (test (or (not (integerp ?choice))
             (< ?choice 1)
             (> ?choice 3)
             (>= ?choice ?size)))
   =>
   (printout t "Human made an invalid move." crlf)
   (retract ?whose-turn ?number-taken)
   (assert (player-move h)))

Predicate Field Constraint

(pile-size ?size)
(test (> ?size 1))

(pile-size ?size&:(> ?size 1))

(data ?item&:(stringp ?item)|(symbolp ?item))

Return Value Field Constraint

(deftemplate take-sticks
   (slot how-many)         ; Number of sticks to take.
   (slot for-remainder))   ; Remainder when stack is
                           ; divided by 4.
(deffacts take-sticks-information
   (take-sticks (how-many 1) (for-remainder 1))
   (take-sticks (how-many 1) (for-remainder 2))
   (take-sticks (how-many 2) (for-remainder 3))
   (take-sticks (how-many 3) (for-remainder 0)))

(defrule computer-move
   ?whose-turn <- (player-move c)
   ?pile <- (pile-size ?size&:(> ?size 1))
   (take-sticks (how-many ?number)
                (for-remainder ?X&:(= ?X (mod ?size 4))))
   =>
   (retract ?whose-turn ?pile)
   (assert (pile-size (- ?size ?number)))
   (assert (player-move h)))

Sticks Program

or Conditional Element

(defrule shut-off-electricity
    (or (emergency (type flood))
        (extinguisher-sysetem (type water-sprinkler)
                              (status on))
    =>
    (printout t "Shut off the electricity." crlf))

and Conditional Element

(defrule use-carbon-dioxide-extinguisher
    ?system <- (extingisher-system
                    (type carbon-dioxide)
                    (status off))
    (or (emergency (type class-B-fire))
        (and (emergency (type class-C-fire))
             (electrical-power (status off))))
    =>
    (modify ?system (status on))
    (printout t "Use carbon dioxide extinguisher" crlf))

not Conditional Element

(defrule largest-number
    (number ?x)
    (not (number ?y&:(> ?y ?x)))
    =>
    (printout t "Largest number is " ?x crlf))

Note: Variables bound within a not CE retain their value only within the scope of the not CE.

Example: Find the largest integer

exists Conditional Element

Pattern match based on the existence of at least one fact that matches a pattern.
(defrule operator-alert-for-emergency
    (exist (emergency))
    =>
    (printout t "Emergency: Operator Alert" crlf)
    (assert (operator-alert)))

Demo:

forall Conditional Element

(deftemplate emergency
    (slot type)
    (slot location))

(deftemplate fire-squad
    (slot name)
    (slot location))

(deftemplate evacuated
    (slot building))

(defrule all-fires-being-handled
    (forall (emergency (type fire)
                       (location ?where))
            (fire-squad (location ?where))
            (evacuated (building ?where)))
    =>
    (printout t
            "All buildings that are on fire " crlf
            "have been evacuated and " crlf
            "have firefighters on location." crlf))

Example:

logical Conditional Element

Logical CE allows a dependency to be created between the facts that match the patterns in the LHS of a rule and the facts that are asserted from the RHS of the rule.
(defrule noxious-fumes-present
    (emergency (type fire))
    (noxious-fumes-present)
    =>
    (assert (use-oxygen-mask)))

(defrule noxious-fumes-present
    (logical (emergency (type fire))
             (noxious-fumes-present))
    =>
    (assert (use-oxygen-mask)))

Example: logical CE

Previous Pattern Matching   Up TOC   Next Modular Design and Execution Control