PowerLoom Manual
Powerful knowledge representation and reasoning with delivery in Common-Lisp, C++, (and, eventually, Java)
This manual describes PowerLoom 1.0.alpha or later.
11 December 1997
The PowerLoom development team
Robert M. MacGregor
Hans Chalupsky
Eric R. Melz
{macgregor,hans,melz}@isi.edu
Copyright (C) 1997 University of Southern California, Information Sciences Institute, 4676 Admiralty Way, Marina Del Rey, CA 90292, USA
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
This document describes the PowerLoom knowledge representation and reasoning system. PowerLoom is the successor to the Loom knowledge representation system. It provides a language and environment for constructing intelligent applications. PowerLoom uses a fully expressive, logic-based representation language (a variant of KIF). It uses a Prolog-technology backward chainer as its deductive component. The backward chainer is (not yet) a complete theorem prover, but it can handle Horn rules, negation, and simple equality reasoning. Contrary to Prolog, it also handles recursive rules without the risk of infinite recursion. Once the classifier is completed, it will be able to classify descriptions expressed in full first order predicate calculus. PowerLoom uses modules as a structuring device for knowledge bases, and ultra-lightweight worlds to support hypothetical reasoning.
To implement PowerLoom we developed a new programming language called STELLA, which is a Strongly Typed, Lisp-like LAnguage that can be translated into Lisp and C++. STELLA tries to preserve those features of Lisp that facilitate symbolic programming and rapid prototyping, while still allowing translation into readable as well as efficient C++ code. By writing PowerLoom in STELLA, we are able to deliver it in Common-Lisp as well as in C++. Once the STELLA-to-Java translator has been completed, PowerLoom will also become available in Java.
PowerLoom uses a variant of KIF (the Knowledge Interchange Format) with
object-oriented extensions to express definitional and assertional
content. The sentential component of this variant is closest in flavor
to that of KIF 3.0 . The main differences are that relations in
PowerLoom are (by default) polymorphic, and that variables in quantified
sentences and terms can be typed. Not yet supported are logical terms
generated by if
or cond
, the biconditional <=>
, and
the holds
predicate. PowerLoom does not have sequence variables,
but it allows the definition of functions and relations with a variable
number of arguments. PowerLoom does not support quotation via
quote
, instead, it will support sentences that take propositional
arguments. PowerLoom's definitional language is somewhat more different
from its counterpart in KIF 3.0. It has similarities with parts of
Ontolingua and is described in more detail in the manual. Future
versions of PowerLoom will have translation frontends to support
knowledge bases and ontologies written in vanilla KIF or Ontolingua.
Write me.
Currently, the primary means for interacting with PowerLoom is its command interpreter. The command interpreter can be used either interactively, or it can be invoked directly from a program to evaluate individual commands. Future versions of PowerLoom will include additional APIs such as the Generic Frame Protocol (GFP). All PowerLoom commands (see section Commands) can be evaluated using the command interpreter.
The interactive command interpreter is invoked by calling the function
powerloom
without any arguments. In the distributed C++ version
of PowerLoom, this is the top-level function called within the
main
routine. In the Lisp version, (STELLA::powerloom)
has to be called explicitly. However, in Lisp it is not really
necessary to use the command interpreter, since all commands can also be
executed directly at the Lisp top level.
The interactive command interpreter functions as a simple
read/eval/print loop that prompts for input with a |=
prompt,
reads a user command from standard input, evaluates it, and prints the
result to standard output. To exit the command interpreter, type
quit
or stop
.
To evaluate commands directly from a program, the following evaluator functions can be used:
(evaluate (unstringify expression))
.
This chapter lists all available PowerLoom commands alphabetically.
Each command is documented with its name, a (possibly empty) list of
parameters specified as (<name> <type>)
pairs, its return
type, and its command type which can be either Command or
N-Command. Regular commands do evaluate their arguments (similar
to a Lisp or C++ function), while N-Commands do not (similar to a Lisp
macro). For example, the command in-dialect
is defined as follows:
- N-Command: in-dialect ((dialect NAME)) : KEYWORD
- Change the current logic dialect to dialect. Currently supported dialects are
KIF
,STELLA
, andPREFIX-STELLA
. The STELLA dialects are not recommended for the construction of knowledge bases, they are mainly used internally by PowerLoom.
This means that it takes one parameter called dialect of type NAME, returns a STELLA KEYWORD as its result, and, since it is an N-Command, does not evaluate its arguments.
Commands can also have &rest
parameters (similar to Lisp
functions). These are either used to allow a variable number of
arguments, or to handle optional arguments, since STELLA does not
directly support optional arguments.
Here is a list of important parameter types used in the command specifications below:
Fred
, a keyword
(similar to a Lisp keyword) such as :KIF
, or a STELLA surrogate
which is a symbol starting with an at-sign, e.g., @CONS
. STELLA
surrogates are used as names for objects of arbitrary types.
(happy Fred)
is a parse tree, and so are its components
happy
and Fred
.
Here is the list of all available PowerLoom commands:
(ask (happy Fred))
will return TRUE if Fred was indeed
found to be happy. Note, that for this query to run, the logic constant
Fred
and the relation (or slot) happy
must already be defined (see
assert
). Use (set/unset-feature goal-trace)
to en/disable goal tracing
of the inference engine.
(assert (happy Fred))
asserts that Fred is indeed happy.
Note, that for this assertion to succeed, the logic constant Fred
must
already be defined, e.g., as a side-effect of a type assertion such as
(assert (Person Fred))
, and the relation (or slot) happy
must be defined
on objects of Fred
s type, e.g., on the class Person
.
*context*
. cc
is a no-op if the context reference
cannot be successfully evaluated.
(conceive (happy Fred))
builds
the proposition expressing that Fred is happy without explictly asserting or
denying it. Note, that for this to succeed, the logic constant Fred
and
the relation (or slot) happy
must already be defined (see assert
).
(defclass <class-name> (<superclass-name>*) [:documentation <docstring>] [:self-variable <var>] [[{:definition | :is} <relation-expression>] | [<=> <sentence-with-argument-variables>]] [:axioms {<sentence> | (<sentence>+)}] [:constraints {<sentence-with-argument-variables> | (<sentence-with-argument-variables>+)}] [:sort? {TRUE | FALSE}] [:properties <list-of-properties>] [:meta-attributes <list-of-key-value-pairs>] [:slots ({(<slot-name> <slot-options>*)}*)] [<other-options>*])
<slot-options> is a list of keyword/value pairs. The set of legal slot
options is the same as those accepted by defrelation
. Unless the :sort?
option specifies otherwise, classes defined with defclass
are assumed
to be sorts, i.e., the extensions of two sibling classes that don't share
a common subclass are assumed to be disjoint.
CAUTION: The semantics of sorts is still somwhat in flux.
defclass
. The only difference
is that the value of the :sort?
option will always be forced to be FALSE.
This means that unrestricted inference might be used to determine whether
a particular object is an instance of a non-sortal class defined with
defconcept
, since no disjointness assumptions can be made. For example,
suppose a hierarchy contains the classes Human
and Featherless-Biped
which share a common superclass, say Living-Thing
. If the two classes
were defined as sorts, their extensions are assumed to be disjoint. Thus,
even if we have a rule
(forall (?x Living-Thing) (=> (and (Featherless ?x) (Biped ?x)) (Featherless-Biped ?x)))
and Human
s are in fact featherless and bipeds, we will not be able to
infer Human
s to be Featherless-Biped
s. However, if Featherless-Biped
was defined with defconcept
, the rule will become applicable, since now
Human
s and Featherless-Biped
s are not necessarily disjoint anymore.
CAUTION: The semantics of sorts is still somwhat in flux.
(deffunction {<function-name> | (<function-name> <value-type>)} (<var>+) [:documentation <docstring>] [:-> <value-variable>] [:type <value-type>] [[{:definition | :is} <relation-expression>] | [<=> <sentence-with-argument-variables>] | [:= <term-expression-with-argument-variables>]] [:polymorphic? {TRUE | FALSE}] [:axioms {<sentence> | (<sentence>+)}] [:constraints {<sentence-with-argument-variables> | (<sentence-with-argument-variables>+)}] [:properties <list-of-properties>] [:meta-attributes <list-of-key-value-pairs>] [<other-options>*])
Function parameters can be typed or untyped. An untyped first parameter
or a :polymorphic? FALSE
specification defines a non-polymorphic function.
Otherwise, the function will be polymorphic. If a value variable is
specified, it must be specified before any definition options, otherwise,
the expansions of definitions might be incorrect. The default KIF value
variable is ?value
.
(defmodule <module-name> [:documentation <docstring>] [:includes {<module-name> | (<module-name>*)}] [:uses {<module-name> | (<module-name>*)}] [:package <package-name-string>] [:case-sensitive? {TRUE | FALSE}] [:shadow (<symbol>*)]) [<other-options>*])
name can be a string or a symbol. The list of modules specified in the
:includes
option plus (if supplied) the parent in the path used for name
become the new module's parents. If no :uses
option was supplied, the
new module will use the STELLA
module by default, otherwise, it will use
the set of specified modules. :package
specifies the name of a native
package or name space in which symbols of the module should be allocated
when they get translated into a native language such as Lisp or C++.
By default, Lisp symbols are allocated in the STELLA
package, and C++ names
are translated without any prefixes. If :case-sensitive?
is supplied
as TRUE, symbols in the module will be interned case-sensitively, otherwise
(the default), they will be converted to uppercase before they get interned.
Modules can shadow definitions of functions and classes inherited from
parents or used modules. Shadowing is done automatically, but generates
a warning unless the shadowed type or function name is listed in the
:shadow
option of the module definition. CAUTION: The implementation of
shadowing is still somewhat fragile.
Examples:
(defmodule "/PL-USER" :uses ("LOGIC" "STELLA") :package "PL-USER") (defmodule /PL-USER/GENEALOGY)
Modules include objects from other modules via two separate mechanisms:
(1) they inherit from their parents specified via the :includes
option
and/or a fully qualified module name, and (2) they inherit from used
modules specified via the :uses
option. The main difference between
the two mechanisms is that inheritance from parents is transitive, while
uses-links are only followed one level deep. I.e., a module A that uses
B will see all objects of B (and any of B's parents) but not see anything
from modules used by B. Another difference is that only objects declared
as public can be inherited via uses-links (this is not yet enforced).
Note that - contrary to Lisp - there are separate name spaces for classes,
functions, and variables. For example, a module could inherit the class
CONS
from the STELLA
module, but shadow the function of the same name.
CAUTION: The implementation of this semantics has not yet been fully
completed.
(defrelation {<relation-name> | (<relation-name> BOOLEAN)} (<var>+) [:documentation <docstring>] [:type BOOLEAN] [[{:definition | :is} <relation-expression>] | [<=> <sentence-with-argument-variables>]] [:polymorphic? {TRUE | FALSE}] [:axioms {<sentence> | (<sentence>+)}] [:constraints {<sentence-with-argument-variables> | (<sentence-with-argument-variables>+)}] [:properties <list-of-properties>] [:meta-attributes <list-of-key-value-pairs>] [<other-options>*])
Relation parameters can be typed or untyped. An untyped first parameter
or a :polymorphic? FALSE
specification defines a non-polymorphic relation.
Otherwise, the relation will be polymorphic.
c
at the pause prompt.
Typing ?
at the pause prompt prints a list of available commands.
(deny (happy Fred))
asserts that Fred is not happy,
which could have been done equivalently by (assert (not (happy Fred)))
.
Note, that for this to succeed, the logic constant Fred
and the
relation (or slot) happy
must already be defined (see assert
).
KIF
, STELLA
, and PREFIX-STELLA
.
The STELLA dialects are not recommended for the construction of knowledge
bases, they are mainly used internally by PowerLoom.
(retract (happy Fred))
retracts that Fred is
happy. Note, that for this to succeed, the logic constant Fred
and the
relation (or slot) happy
must already be defined (see assert
).
(retrieve [<integer> | all] [{<variable-spec> | (<variable-spec>+)} [<proposition>]])
The variables and proposition are similar to an exists
sentence or
kappa
term without the quantifier. <proposition> usually contains
references to the listed variables. No other free variable references
are allowed. If <proposition> is omitted, it defaults to TRUE.
A solution is a set of bindings for the listed variables for which
<proposition> is true. The optional first argument controls how many
solutions should be generated before control is returned. The keyword
all
indicates that all solutions should be generated. By default,
retrieve
returns after it has found one new solution or if it cannot
find any more solutions.
retrieve
returns an iterator which saves all the necessary state of
a query and stores all generated solutions. When used interactively,
the returned iterator will print out with the set of solutions collected
so far. Calling retrieve
without any arguments (or only with the first
argument) will generate one (or more) solutions to the most recently
asked query.
KIF examples:
(retrieve (?x Person) (happy ?x))
will try to find the next happy person and store it in the returned query iterator.
(retrieve 10 (?x Person) (happy ?x))
will try to find 10 happy people.
(retrieve 10)
will try to find the next 10 happy people.
(retrieve all (?x Person) (happy ?x))
will find all happy people.
(retrieve all (?x Person))
will find all people.
(retrieve (?x Person) (or (happy ?x) (parent-of Fred ?x)))
will try to find the next person that is happy or has Fred as a parent.
(retrieve ((?x Person) (?y Person)) (parent-of ?x ?y))
will try to find the next pair of parent/child.
(retrieve all (?x Person) (exists (?y Person) (parent-of ?x ?y)))
will generate the set of all parents. Note, that for these queries to run,
the class Person
, the relations happy
and parent-of
, and the logic
constant Fred
must already be defined (see assert
).
Use (set/unset-feature goal-trace)
to en/disable goal tracing of the
inference engine.
set-feature
without any
arguments can be used to display the currently enabled features.
The following features are supported:
closed-world
: Enables closed-world reasoning. NOT YET IMPLEMENTED!
goal-trace
: Enables the generation of goal trace information during
inference.
retract
that also handles falsity.
unset-feature
without any
arguments can be used to display the currently enabled features.
See set-feature
for a description of supported features.
This document was generated on 11 December 1997 using the texi2html translator version 1.51.