.. Copyright ÂŠ 2010 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.
crumb: Creating an Engine
How to create a Pyke *inference engine* object.
Creating an Inference Engine Object
The ``engine`` object is your gateway into Pyke. Each engine object manages
multiple `knowledge bases`_ related to accomplishing some task.
You may create multiple Pyke engines, each with it's own knowledge bases to
accomplish different disconnected tasks.
When you create a Pyke engine object, Pyke scans for Pyke `.kfb`_, `.krb`_
and `.kqb`_ source files and compiles these into .fbc pickle files,
Python .py source files and .qbc pickle files, respectively.
Each time a Pyke engine object is created it checks the file modification
times of the Pyke source files to see whether they need to be recompiled.
If you change a Pyke source file, you may create a new Pyke engine to compile
the changes and run with the new knowledge bases without having to restart
Pyke also lets you zip these compiled files into Python eggs and can load the
files from the egg. By including the compiled files in your application's
distribution, you don't need to include your Pyke source files if you don't
Once you have an ``engine`` object; generally, all of the Pyke functions that
you need are provided directly by this object:
.. this code is hidden and will set __file__ to the doc/examples directory.
>>> import os
>>> __file__ = \
Pyke recursively searches for Pyke source files (`.kfb files`_,
`.krb files`_, and `.kqb files`_) starting at each source directory
indicated in *paths* and places all of the compiled files in the
associated *target packages*. This causes all of the `knowledge bases`_
to be loaded and made ready to activate_.
Pyke source files may be spread out over multiple directories and may be
compiled into one or more target packages. Multiple target packages
would be used when more than one application wants to share a set of
`knowledge bases`_, perhaps adding some of its own knowledge that it
compiles into its own target package.
Each ``path`` argument specifies a Pyke source directory and an optional
target package. The source directories do not have to be Python package
directories, but the target packages do.
The target package defaults to ``.compiled_krb``. The leading dot (.)
indicates that the compiled_krb directory will be subordinate to the
lowest Python package directory on the path to the Pyke source directory.
This uses Python's `relative import`_ notation, so multiple dots go up to
higher directories (one per dot). If the target package does not start
with a dot, it is taken to be an absolute package path and will be located
using Python's sys.path like a normal Python ``import``.
The Pyke source directory may be specified as a path (a string) or by
passing a Python module. If a module is passed, its __file__ attribute
is used. If the path points to a file, rather than a directory, the final
filename is discarded. In the simple case, when the Pyke source files are
in the same directory as the module creating the ``engine`` object, you
can just pass ``__file__`` as the sole argument.
>>> from pyke import knowledge_engine
>>> my_engine = knowledge_engine.engine(__file__)
Passing a package instead, this example could also be written:
>>> import doc.examples
>>> my_engine = knowledge_engine.engine(doc.examples)
or, you can pass a module within the desired package:
>>> from doc.examples import some_module
>>> my_engine = knowledge_engine.engine(some_module)
In the all three cases, the final .py or .pyc file is stripped from the
value of the module's __file__ attribute to get the directory that the
package is in. This directory will then be recursively searched for Pyke
If you change some of your Pyke source files, you can create a new engine
object to compile and reload the generated Python modules without
restarting your program. But note that you'll need to rerun the
``add_universal_fact`` calls that you made (a reason to use `.kfb files`_
All of the compiled Python .py source files and .fbc/.qbc pickle files
generated from each source directory are placed, by default, in a
``compiled_krb`` target package. You may specify a different target
package for any source directory by passing that source directory
along with the target package name as a 2-tuple. Thus, specifying the
default target package explicitly would look like:
>>> my_engine = knowledge_engine.engine((__file__, '.compiled_krb'))
You may specify the same target package for multiple source directories.
The last component of the target package will be created automatically
if it does not already exist.
You will probably want to add ``compiled_krb`` (or whatever you've
chosen to call it) to your source code repository's list of files to
If you want to distribute your application *without* the knowledge bases,
you can use the 2-tuple notation with ``None`` as the source directory.
In this case, all of the Pyke source files must already be compiled,
and Pyke will simply load these files. Also, the target package must be
specified in absolute form (with no leading dots).
Finally, there are four optional keyword arguments that you may also pass
to the ``engine`` constructor. These are all booleans that default to
- ``load_fb`` -- load fact bases
- ``load_fc`` -- load forward-chaining rules
- ``load_bc`` -- load backward-chaining rules and
- ``load_qb`` -- load question bases
These parameters must be passed as keyword parameters and let you
selectively load the various kinds of compiled files.