.. $Id: rule_bases.txt a2119c07028f 2008-10-27 mtnyogi $
.. 
.. Copyright © 2007-2008 Bruce Frederiksen
.. 
.. Permission is hereby granted, free of charge, to any person obtaining a copy
.. of this software and associated documentation files (the "Software"), to deal
.. in the Software without restriction, including without limitation the rights
.. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
.. copies of the Software, and to permit persons to whom the Software is
.. furnished to do so, subject to the following conditions:
.. 
.. The above copyright notice and this permission notice shall be included in
.. all copies or substantial portions of the Software.
.. 
.. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
.. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
.. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
.. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
.. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
.. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
.. THE SOFTWARE.

restindex
    crumb: Rule Bases
    page-description:
        Explanation of rule bases, overview of .krb files and how these files
        are compiled and loaded into your Python program.
    /description
    format: rest
    encoding: utf8
    output-encoding: utf8
    include: yes
    initialheaderlevel: 2
/restindex

uservalues
    filedate: $Id: rule_bases.txt a2119c07028f 2008-10-27 mtnyogi $
/uservalues

==========
Rule Bases
==========

Rule bases are collections of rules_.  Rule bases are created by writing a
*knowledge rule base* (`.krb`_) file with your favorite text editor.

A single rule base may contain both forward-chaining_ and backward-chaining_
rules.

The forward-chaining rules are run automatically when the rule base is
activated_ to assert new statements_ of fact_.  Thus, forward-chaining rules
are not directly used to determine whether any particular statement_ is true.

But backward-chaining rules *are* directly used to determine whether a
particular statement is true.  Thus, when a rule base name (or, more properly,
a `rule base category`_ name, explained below) is used as the
*knowledge base name* in a statement, it refers to the backward-chaining
rules within that rule base.

.. note::

   Pyke runs all forward-chaining rules before running any backward-chaining
   rules.

   Thus, using rule base names as the *knowledge base name* in statements
   within a forward-chaining rule is prohibited, as this would cause
   backward-chaining rules to run in order to process the forward-chaining
   rule.

Why Multiple Rule Bases?
========================

There are two reasons to have more than one rule base (i.e., more than one
`.krb file`_):

#. To divide a large set of rules into human manageable units.

   In this case, you want Pyke to use all of the rule bases combined.

   For example, you may have rules governing the automatic generation of SQL
   statements, and other rules governing the generation of HTML documents.
   You want to keep these rules in different rule bases to make them more
   manageable.

#. To enable your Python program to choose between different rule bases
   that are tailored to different specific situations.

   For example, some of the rules governing the automatic generation of SQL
   statements may vary depending upon the target database (e.g., ``mysql``,
   ``postgresql``, ``oracle``).

   In this case, you want to be able to tell Pyke which of several rule bases
   to use on each invocation, depending upon which target database you will
   be accessing.  You would never use more than one of these rule bases at
   the same time, so these rule bases are mutually exclusive.

These two goals are met by three capabilities:

- `Rule Base Categories`_
- `Rule Base Inheritance`_
- `Rule Base Activation`_

Rule Base Categories
====================

All rule bases are grouped into categories.  Each rule base category only gets
to have **one** active_ rule base.

Thus, you place rule bases that you want to have active simultaneously into
*different* rule base categories; and place rule bases that are mutually
exclusive with each other (e.g., the ``mysql``, ``postgresql`` and ``oracle``
rule bases) into the *same* rule base category.

Each rule base category has a unique name.  In the example above you would
want two rule base categories: ``database`` and ``html_generation``.

The rule base category name is used as the *knowledge base name* for
statements within rules of one rule base category that want to refer to
rules within another rule base category.  For example, rule bases in the
``html_generation`` category would need to use ``database.insert(...)`` to
refer to the ``insert`` rules in the ``database`` category.

Rule Base Inheritance
=====================

The rule bases within the same category_ share rules amongst themselves
through rule base inheritance.

Rule bases use single inheritance to inherit the rules_ from one other rule
base.  This can go on to any depth.  Both forward-chaining_ and
backward-chaining_ rules_ are inherited.

This allows mutually exclusive rule bases to share common rules in a parent
rule base without having to duplicate these rules amongst themselves.

Here is the definition, then, of a `rule base category`_:

    Each *root* rule base (through rule base inheritance) defines a unique
    rule base category.  All rule bases derived (directly or indirectly)
    from that root rule base are in the same rule base category.

    The name of the rule base category is simply the name of its root
    rule base.

So, our ``database`` and ``html_generation`` example would look like this:

.. figure:: ../images/rule_base_categories.png
   :width: 450
   :height: 424
   :scale: 100
   :align: center

   Rule Base Categories

We have one root rule base called ``database`` and it has derived rule bases
called ``mysql``, ``postgresql`` and ``oracle``.  And a second root rule base
called ``html_generation`` with ``firefox`` and ``internet_explorer``.

The two root rule bases define two rule base categories:

- database, which includes:

  - database
  - mysql
  - postgresql
  - oracle

- html_generation, which includes:

  - html_generation
  - firefox
  - internet_explorer

.. note::

   The `.krb files`_ for these rule bases may be placed anywhere you want
   them within your Pyke source directory structure -- in other words, your
   directory structure is not required to match your rule base inheritance
   structure.

Only one rule base from each rule base category may be active_ at any point in
time.

Within each of these rule bases, if the knowledge base name is omitted from a
statement within a `backward-chaining rule`_, it defaults to the
`rule base category`_ of that rule base, *not* the rule base itself.
Thus, ``insert(...)`` within ``postgresql`` would mean
``database.insert(...)``, and ``make_tag(...)`` within ``firefox`` would mean
``html_generation.make_tag(...)``.

.. important::

   Note that referring to a rule base category (either explicitly or
   implicitly) *always* refers to the active_ rule base within that category.
   This may not be the rule base with that name (the root rule base), or even
   the rule base making implicit use of the rule base category.  For example,
   ``insert(...)`` within ``postgresql`` will end up referring to ``insert``
   rules within the ``oracle`` rule base when ``oracle`` is the active rule
   base.

All rules referring to foreign `rule base categories`_ must explicitly use the
rule base category name.  For example, to refer to the ``insert`` rule for
databases, within the ``html_generation`` category, you would have to say
``database.insert(...)``.

In this way, all of the rules will work no matter which rule base is active
within each rule base category.

Rule Inheritance
----------------

There is an important difference between how backward-chaining_ rule
inheritance works within Pyke rule bases and how method inheritance works
within Python classes:

* When a derived class in Python defines a method by the same name as a
  method in its parent class, the derived method *overrides* the parent
  method.  I.e., only the derived method is used when a call is made
  to it.

* In contrast, when a derived rule base in Pyke defines
  `backward-chaining rules`_ for a goal that also has backward-chaining rules
  defined for it in the parent rule base, the derived rule *extends* the
  set of rules that may be used to try to prove this goal_.  All of the
  derived rules will be tried first.  If all of these fail, then the parent
  rules are tried.

  If you don't want the parent rules to be used for a particular goal_,
  you must list that goal name in the ``without`` clause of the extending_
  statement at the beginning of the derived rule base.
 
.. note::

   All `forward-chaining rules`_ in the parent rule base are always included
   in the derived rule base.  The ``without`` clause only applies to
   backward-chaining rules.

Rule Base Activation
=====================

Loading_ rule bases only makes them available for use.  It does not
automatically activate_ any of them.  This must be done explicitly by your
Python program.  Your program may decide to activate different rule bases
in different situations.

Additionally, `forward-chaining rules`_ may be used to activate more specific
rule bases, based upon their inferencing.  But once a rule base has been
activated for a `rule base category`_, only children of the currently active
rule base may be activated from that point on.  Because these children
inherit_ the rules of the currently active rule base; activating child
rule bases only adds new rules, and doesn't take any away.  Thus, any
forward-chaining rule run during the activation of the first rule base
are not invalidated by activating the second rule base.

In our database example, your program could activate the root ``database``
rule base and let the forward-chaining rules within the ``database`` rule
base figure out which derived rule base to activate depending on the
particular database in use at the time the program is run.


