CPSC 322 - Lecture 27 - November 10, 2004

CPSC 322 - Lecture 27

Rule-Based Systems


I.  Rule-based systems

The Oska player that you're constructing has a lot of 
knowledge about how to play Oska, but it's not exactly 
obvious by looking at the program just what that knowledge 
is, as it's represented in some fairly obscure ways.  Some 
functions return numbers, other functions propagate 
numbers...it's not easy to follow.

This kind of knowledge is often called "how-to" or 
"procedural" knowledge---knowledge about how to perform some 
task.  This is different from "what-is-it" or "declarative" 
knowledge, like that encoded in an inheritance hierarchy for 
dogs and birds.

Procedural knowledge doesn't necessarily have to be encoded 
as cryptically as it is in your Oska program.  Another way 
to represent this kind of knowledge is as a set of "if-then 
expressions" or "rules".  These rules take the form:

  IF some condition(s) exist THEN perform some action(s)

A set of test-action or if-then rules is often called a 
"production system"---if the left side holds true, the right 
side is produced.

We see production systems used a lot in computer science.  If 
you should take a compiler course, for example, you'll see 
production systems used to describe programming languages:

  [expression] := [expression] [arithmetic-op] [expression]

This is the stuff that compilers and compiler generators are 
made of.  It's also the backbone of natural language 
understanding system.  In the world of artificial 
intelligence, production systems are often called "rule-based 
systems", and are used not only for building flexible 
intelligent systems, but also for modelling human cognition.


II. Components of a rule-based system

A computational implementation of a rule-based system needs 
three parts:

1.  The rule base (also known as the knowledge base or 
    production memory).  This is the place where the rules
    are stored (the procedural knowledge).

2.  The rule interpreter (a.k.a. the control mechanism or the
    inference engine).  This is a means of determining which
    rules have tests that are satisfied, and then selecting
    one of those rules to have its associated action 
    performed.

3.  The data base (a.k.a. working memory, short term memory,
    the world model, or context).  This is an abstracted 
    representation of the world that this system "cares"
    about.  It represents the current state of the world.
    The left-hand sides of the rules look at this to see if
    they're satisfied; the right-hand sides act operate on
    this information.  This is where the facts or declarative
    knowledge is stored.

If you put enough knowledge into the rule base so that it can 
perform some interesting, complex task at the same 
performance level as a human, we could call this an "expert 
system".  


III.  Designing a simple rule-based system for tic-tac-toe

You might get a better feel for rule-based systems if you 
actually go through the design of one.  Here's a half-baked 
attempt at a rule-based system for playing tic-tac-toe.  We 
won't worry much about implementation details; we'll just do 
some handwaving and describe the knowledge in English.

Here are some rules which might be useful, but these aren't 
necessarily all the rules.  Oh, and assume "row" means any 
adjacent squares, whether horizontal, vertical, or diagonal:

IF I have three tokens in a row      THEN I win; quit

IF the opponent has three tokens     THEN I lose; quit
   in a row

IF I have two tokens in a row and    THEN put my token in
   the third square in the row is         the third square
   empty

IF the opponent has two tokens in    THEN put my token in
   a row and the third square in          the third square
   the row is empty

IF the center square is empty        THEN put my token in
                                          the center square

IF a corner square is empty          THEN put my token in 
                                          that corner square

IF a side square is empty            THEN put my token in 
                                          that side square

And so on, and so on.  The first thing to note is that more 
than one of these rules may have tests that are satisfied at 
the same time.  We'll talk about how to select which rule to 
use later on.  The second thing to note is that these rules 
are described at a very high level.  There aren't many 
details, and certainly none that a computer could understand 
without a lot of help.  Nevertheless, we want to maintain 
that high-level description, as one of the things we want to 
accomplish with a rule-based system is to make the procedural 
knowledge more accessible, or more easily understandable, to 
us.  That is we want our rules to look more like something 
that people read as opposed to rules that Scheme or Prolog 
interpreters read.

To make this happen, we must construct a rule interpreter, 
which interprets the language of if-then rules that describes 
the procedural knowledge for playing tic-tac-toe.  In other 
words, these if-then rules are yet another way of building a 
language on top of a language.


IV.  The rule interpreter

The rule interpreter is just a simple loop:

do until no left-hand-side is satisfied

  begin

    find all the rules whose tests (or preconditions or
    antecedents or left-hand-sides) are satisfied

    from that group, use a conflict resolution strategy
    (hang on, we'll get there) to select the most appropriate
    rule to be used

    execute that rule's actions (or postconditions or 
    consequents or right-hand-sides) and update the
    data base accordingly

  end

In addition to all this, you'll need a data base, so...


V.  The data base

In the case of our tic-tac-toe game player, the data base is 
going to be really simple.  We just need to represent the 
current state of a game, so a board that looks like this:

      | |o
     -+-+-
      |x| 
     -+-+-
      | | 

might be represented like this:

[[e,e,o],[e,x,e],[e,e,e]]

or one of any of a number of other possible representations.  
But of course, you'd employ such nice data abstraction 
techniques that only some simple accessor and constructor 
functions would have to know the details of the 
representation, right?

Last revised: December 7, 2004