clear-kb
to reset the kb between separate groups of tests,
and that practice has uncovered several bugs in the retraction/revision
code that are now history (in the past, clear-kb
has been
hard to fix because revision bugs are notoriously hard to reproduce).
Other problems fixed include bugs in production rules, in the
backtracker, in save-kb
, and in default rules. Some of
these fixes have found their way into the 2.0b patches, but some of them
have not. If something has not worked for you in the past, we suggest
trying it again on this new release.
get-value
and set-value
has
changed slightly: Previously, calls such as (get-value 'I
'R)
and (set-value 'I 'R 'V)
could be applied to
both single-valued and multiple-valued relations R. Now, these two
functions are intended to be used only for single valued relations. The
motivation for this change is (i) that it makes asserting and retrieving
a role pointing to a list much more straightforward, and (ii) it
eliminates some coercion that made these routines overly clever.
Before, when get-value
returned a list, that value could
represent a single role filler or a list of fillers, depending on
whether or not the role was single- or multiple-valued. Now,
get-value
always returns a value representing a single role
filler. The new semantics is slightly more forgiving than just described
-- the new get-value
permits retrieval from a
multiple-valued role in the cases when the role contains zero or one
filler. Two new functions, get-values
and
set-values
have been introduced to accommodate
multiple-valued roles. get-values
returns a list of
fillers, and set-values
assigns from a list of fillers.
These new functions also work with single-valued relations. The
functions all-role-values
, the-role-value
, and
some-role-value
still exist, but we recommend not using
them (they don't automatically advance the state of a knowledge base
before retrieval). get-values
makes
all-role-values
obsolete, and get-value
makes
the-role-value
obsolete (and no one seemed to like
some-role-value
).
We have also modified the semantics for computing the roles of a Loom
concept. This affects the generation of slots when CLOS classes are
created from the definitions of Loom concepts. Because this is coupled
with a new feature (a :roles
declaration), the new
semantics is described under the ENHANCEMENTS heading.
We have also made a small modification to the macro
list-kb
. Previously, the argument to the
:partitions
keyword was implicitly quoted -- now its not
(and should never have been).
Note: Before making changes to get/set-value
and
role computations, we solicited opinions from the Loom user community,
and the above-mentioned changes are compatible with the answers we
received. In general, we try to avoid making incompatible upgrades to
Loom, but we will make them when (i) we feel that the previous semantics
represented a bad choice, and (ii) when no user claims to be
inconvenienced by the change.
(defconcept A) (create 'Fred 'A :clos-instance-p t)
causes a CLOS class named A
to be created in response to
the attempt to create the instance Fred. Furthermore, Loom now supports
automatic revision of CLOS classes -- when a Loom concept is redefined,
the corresponding class (if such exists) gets redefined the next time it
is instantiated. For example, if we now say
(defrelation R) (defconcept A :is-primitive (at-least 1 R)) (create 'Sue 'A :clos-instance-p t)
Loom will redefine the CLOS class A
to include a slot named R
.
Previously, Loom took its cue for generating the slots for a class based
on the :domain
constraints attached to roles. If a role
relation R had domain A
, then a slot was assigned to the
class A
(and inherited by its subclasses). This has been
changed. There are two new ways to assign a slot to a class via the
concept declaration. First, Loom now creates a slot corresponding to
any relation that is restricted by a concept definition. In the above
example, when we restricted the concept A
with the clause
(at-least 1 R)
, that caused Loom to generate a slot
R
for the class A
. A :roles
option provides a second means for generating slots on a class. For
example, let us redefine A again:
(defconcept A :roles (R S)) (create 'Joe 'A :clos-instance-p t)
Now the class A
has two slots, R
and
S
. Oops, we forgot to define a relation named
S
! Not to worry. Loom automatically defines a
multiple-valued binary relation corresponding to each member of
:roles
that is not already declared. These definitions can
be overridden after the fact by subsequent defrelation
definitions. This means that you can now use Loom without ever
explicitly defining a relation, if that suits your fancy. However, you
still need to call defrelation
if you want to make a
relation single-valued (I was glad to get an endorsement from Mark
Burstein at BBN in making that decision).
The old role semantics can be enabled by setting the loom feature
:domain-implies-role
. However, while this setting causes
Loom to infer roles based on domain information, it does not disable
either of the two new role-inducing mechanisms. We expect that users may
wish for a capability for disabling the inference of roles/slots based
on restrictions. However, when we conducted a poll, no one asked for
such a feature. Hence, we have decided to defer the introduction of such
a disabling feature until such time as users ask for it. In any case,
the :roles
option now gives users much greater control over
allocation of slots. (Note: In the laboratory version of Loom, roles are
first-class objects, and the :roles
option controls more
than just the generation of CLOS slots. Thats why its called
:roles
rather than :slots
).
Loom now provides two new query functions: GET-MATCHING-INSTANCES and QUERY. These were described in a message to Loom forum. A summary follows:
(get-matching-instances '(A B) '((R 4 5) (S 4) (S 5)))
(let ((?v 3)) (retrieve (?x ?y) (:and (C ?x) (R ?x ?y) (S ?x ?v)))) (let ((?v 3)) (declare (special ?v)) (query '(?x ?y) '(:and (C ?x) (R ?x ?y) (S ?x ?v))))
Loom provides two more new defconcept options: :keys
and
:indices
. The :indices
option causes Loom to
create a hash index(es) that accelerates retrieval based on the values
of role fillers. The :keys
option declares sets of roles
that collectively define a key on a concept. The difference between
keys and indices are that the set of values of roles in a key must be
unique for each instance in the corresponding concept, and that the
specification of keys without indices doesn't provide accelerated
access. Roles referenced by the :keys
and/or
:indices
options must be single-valued. The function
get-matching-instances
knows how to take advantage of role
indices. For example
(defconcept A :roles (R S T) :indices (R (S T))) (defrelation R :characteristics :single-valued) (defrelation S :characteristics :single-valued) (defrelation T :characteristics :single-valued) (tell (about Ann (create A) (R 3) (S 4) (T 5))) (get-matching-instances nil '((R 3))) (get-matching-instances nil '((S 4) (T 5)))
The concept A has two independent indices. One index is the value of
the role R
. The second index is a list of the values of
the roles S
and T
. Here, Ann is retrieved by
each of the above calls to get-matching-instances
, using
two different hash indices. The function query
calls
get-matching-instances
to execute simple queries, such as
the following:
(query '?x '(R ?x 3)) (query '?x '(and (A ?x) (R ?x 3)))
However, we have not yet had time to upgrade retrieve
to
use role indices. Hence, on the above queries, retrieve
will not use the indices to accelerate the retrieval.
The :keys option allows one to specify sets of keys for instances of a concept. In this example
(defconcept A :roles (R S) :keys ((R S)) :indices ((R S))) (defrelation R :characteristics :single-valued) (defrelation S :characteristics :single-valued) (tellm (about Jack (create A) (R 4) (S 3)) (about Jill (create A) (R 4) (S 3)) (about Mary (create A) (R 4)))
Loom emits a warning that Jack and Jill have duplicate values
for the key (R S)
, and also warns that Mary is supposed to
have filled in its value for the role S
. Note: Checking for
duplicate keys only happens if there is an index declared that matches
the key being monitored.
loomftp
has
been established. This account will require a password for connection.
The password will be distributed to all current license holders. The loom files will be stored in a special directory accessible to the loomftp user, but not accessible from the anonymous ftp server. After ftp'ing into the loomftp account, the Loom files can be retrieved in the normal manner. We will distribute the sources in Unix tar format as well as Macintosh stuffed and binhex'd format. Remember to use binary mode to retrieve tar files!!
Procedure: Unix % ftp isi.edu (...) Name (your name here): loomftp (...) Password: _________ (...) ftp> binary (...) ftp> get loom2.0.tar (...)
For Macintosh users, the files are also available in binhex format as a
self-extracting archive in the file Loom2.0.sea.hqx
.