Ocelot User's Guide

Although the Generic Frame Protocol (GFP) specification documents many aspects of the Ocelot Frame Representation System, some aspects of Ocelot are not described at the GFP level. This document provides additional information on Ocelot. An Ocelot programming example is also available.

Packages

Each KB is associated with a single Lisp package, which is specified using the initargs argument to create-kb. That package is called the "KB package", and can be retrieved from the kb-package slot of the kb object.

The names of all frames and all slots created within the KB must be symbols in the KB package.

Opening Ocelot Knowledge Bases

Ocelot can manage knowledge bases (KBs) that are stored persistently in two ways: within disk files, and within an Oracle database. From a user's point of view, the two types of KBs are treated identically, with the exceptions that they are opened differently, and that various setup operations are required to configure the Oracle database before it can be used. This manual currently focuses on KBs stored within files.

New and existing KBs can be opened using the standard GFP interface functions: create-kb and open-kb, as described later in this section. Or they can be opened using two Ocelot-specific shortcuts that we provide. These two functions reside in package ocelot (nickname oot), and provide simpler ways of opening file KBs.

open-file-kb (kb-name &key filename)

Opens an existing Ocelot KB named kb-name from the file whose name is filename, reads that KB into memory, and makes that KB the current KB. This function is a shorthand for performing a gfp:create-kb followed by a gfp:open-kb. Returns the KB.

make-ocelot-kb (kb-name &key filename package)

Creates and opens a new Ocelot KB named kb-name that will reside in the file whose name is filename. The kb-package will be specifed as package, which defaults to User package. This new KB becomes the current KB. This function is a shorthand for performing a gfp:create-kb followed by a gfp:open-kb. Returns the created KB.

Because the arguments to create-kb are somewhat complicated, we provide an example of its use here. The purpose of create-kb is to create a KB descriptor that describes a new or existing KB. Once the descriptor exists, the programmer calls open-kb to acutally construct a new KB, or to open an existing KB. An example call to create-kb is as follows.

    (setq kb
      (gfp:create-kb 'bird
                     :prototype (gfp:get-prototype 'gfp:ocelot-kb)
                     :initargs `(:package ,(find-package :user)
                                          :testfn ,#'gfp::fequal
                                          :dbms-type :file
                                          :dbms-host nil ;; ,dbms-server
                                          :filename "~/bird.ocelot"
                                          )
                     ) )
This call creates a KB whose name is "bird," and that is an Ocelot KB (as opposed to a KB managed by some other frame knowledge representation system. Its package is defined to be user package, and its test function for comparing frames for equality must be defined to be the function fequal, which properly compares both frame objects and symbol frame names for equality. The dbms-type argument defines the KB to be of type file, meaning it resides in a file, not in Oracle, and therefore no dbms-host needs to be specified (this argument is required only for Oracle KBs). The file in which the KB will be stored is "~/bird.ocelot".

File ocelot-example.lisp provides an extended example that shows how to open a KB once its descriptor has been created.

Ocelot Frame Names

Ocelot frame names must be Lisp symbols whose length does not exceed 40 characters. Frame name symbols must be in the kb-package for the Ocelot KB that the frame resides in.

Frame names may contain alphanumeric characters plus the following characters:
-_.:+?

Slot Frames

In Ocelot, for every slot defined within a KB, a frame called a slot frame is created in the KB that stores information about the properties of that slot. For example, if we created a slot called height, then a frame called height would be created in the KB. The slots in the height frame define properties of the slot, such as the class(es) to which it applies, encoded in a slot called :domain. Slots on slot frames are also called facets. Most Ocelot facets and their possible values are described in detailed in the section of the Generic Frame Protocol (GFP) specification called Standard Facets.

This section provides additional details on the facets employed by Ocelot, their meaning, and their possible values. The programmer can alter the values of facets on slot frames using standard GFP operations such as

    (put-slot-value 'height :value-type :integer)
or by using the GKB Editor frame editor to edit the slot frame.

The :Value-Type Facet

Valid value-types accepted by Ocelot are:

The :Inheritance-Type Facet

Different modes of inheritance may be specified for different slots using a single value of the :inheritance-type facet of the associated slotunit, as follows. If no inheritance type is specified, the default is :Override. This is the mechanism used by Ocelot to control inheritance of values from classes to their children. The notion of template slots versus own slots (see GFP spec) is not used in Ocelot. For example, a class cannot contain two sets of values for one slot, where one set of values are own-slot values and another set are template-slot values. The Ocelot GFP implementation ignores slot operations in which the slot-type is specified to be :template.

The :Domain Facet

The :domain slot of a slotunit specifies what classes the slot is defined to be present in, that is, it defines the scope of the slot within a KB. The value of the :domain slot of a slotunit is a set of one or more items D, where each D is either:

The slot is allowed to be used in the union of all class subtrees specified by all of the items D.

Examples of valid domains:

|Proteins|
(|Proteins| |Genes|)
((|Chemicals| :Except |Polynucleotides|))
((|Chemicals| :Except (DNA RNA)))

The :Inverse Facet

Ocelot provides full support for maintenance of inverse relationships.

Imagine that in a KB describing people, we define two slots called parent and child. Since these two slots describe inverse relationships, each slot should be marked as an inverse of the other:

    (put-slot-value 'child :inverse 'parent)
    (put-slot-value 'parent :inverse 'child)
Ocelot maintains inverse relationships for a pair of slots that are inverses of one another such that, when the user calls a GFP operation on one slot, Ocelot automatically performs the appropriate operation on its inverse. For example, imagine that the user has created two instances, John and Bill. If the user then executes that John is the parent of Bill:

    (put-slot-value 'john 'parent 'bill)
Ocelot will then automatically assert that Bill is the child of John, in effect automatically asserting:

    (put-slot-value 'bill 'child 'john)
If the user were to then execute:

    (remove-slot-value 'bill 'child 'john)
Ocelot will automatically remove the value Bill from the Parent slot of John.

Ocelot performs automatic updating for the GFP put, add, and remove operations.

Computed Slots -- the :Get-Methods Facet

An Ocelot slot can be configured so that its value is computed dynamically by Ocelot when the value of the slot is requested by an operation such as get-slot-value. Such computed slots are equivalent to database views, and are useful when the value of a slot can be inferred computationally from the values of other slots.

A computed slot is defined by storing the names of one or more Lisp functions that will be used to compute the slot value on the :get-methods slot of the slotunit for that slot. That function will be called with three mandatory arguments: the frame, slot, and KB for which a value is being requested.

For example, imagine that we wish to compute the value of the slot "siblings" for a given frame by taking the union of the values of its "sisters" and "brothers" slots. To do so, define a function called get-siblings(frame slot value). Its definition should return the union of the values of the sisters and brothers slots for frame. Then, assert (add-slot-value 'siblings :get-methods 'get-siblings), and values of this slot will now be computed.

Although it is not advisable to store values in a slot whose value is computed, Ocelot will not prevent such values from being stored. The existence of such values will prevent the associated method from being called -- Ocelot will return the stored slot values.

Annotations

Annotations are an Ocelot mechanism for attaching structured data to slot values. Annotations are an Ocelot extension to GFP, and are not an official part of GFP.

An annotation can be thought of a five-tuple of the form (Frame Slot Value Label Annot), where Label is analogous to a slot name, and Annot is analogous to a slot value.

An example use of Ocelot annotations within Pathway/Genome Databases (PGDBs) is for the coefficients of substrates in reaction frames. Consider a reaction A + 2B = C + D. In a PGDB, the reactants are stored in a slot called Left. This equation would be represented with a Left slot containing two values, A and B. To model this situation, the B value is given an annotation whose Label is "Coefficient" and whose Annot is 2.

When a value is removed from a slot, all of its associated annotations are also removed. However, when a slot value is replaced using replace-slot-value, all annotations that existed for the old slot value are retained by the new value.

The following GFP operations are provided for annotations.

Destructive Operations on Ocelot Data

Users who query Ocelot data using GFP Lisp functions need to be aware that these GFP functions return pointers to the actual Ocelot internal data structures. Therefore, applying destructive Lisp operations on those data structures will alter the underlying Ocelot data, which can have disastrous results. Users could unintentionally alter the DB content, or users who perform destructive operations with the intent of altering the DB content could find that their changes are not saved permanently.

For example, imagine that the call (get-slot-values 'Jim 'Brothers) returns a list of brothers: (Fred Joe Bill). The list returned by get-slot-values is in fact a Lisp pointer to the same physical memory location in which Ocelot stores the values of this slot.

It would be a mistake to think of the list returned by get-slot-values as distinct from the slot value list stored in Ocelot. If the user happened to want to sort the list of brothers alphabetically, and applied the sort function to this list, not only would the user see their list changed, but the list of slot values would also be changed. The reason is that the Lisp sort function is a destructive operation -- it rearranges the pointers in the physical Lisp list that is its input, rather than sorting a new list in a new region of memory. Similarly, applying other destructive Lisp operations such as rplaca, delete, or nconc would also alter the Ocelot slot value. On the other hand, non-destructive Lisp operations such as append, subseq, or remove would have no effect on the data stored in Ocelot because those functions create a copy of their input data before computing the result.

However, the user should not use destructive operations with the intent of altering the data stored within Ocelot. For example, do not use operations such as delete or nconc to intentionally alter the set of values within an Ocelot slot. One reason for this is that when it comes time to save your changes to an Oracle Ocelot KB, Ocelot only knows what frames to save to Oracle because GFP operations keep track of what frames they have changed. So even if you successfully alter a list of values using nconc, Ocelot will not know that those values have been changed, and it will not save the relevant frame to Oracle. The general rule is: Only use GFP operations to update Ocelot data.

Constraint Checker

Examples

File ocelot-example.lisp contains example GFP calls to operate on an Ocelot knowledge base.


Peter D. Karp