KNOWBEL MANUAL


Bryan M. Kramer


University of Toronto, Toronto, ON, M5S 1A4


1.0  Introduction


This is a user's guide to the implementation of Telos done by the author. This implementation is called 
KNOWBEL.


KNOWBEL is implemented in Franz's Allegro Common Lisp. However, except for the graphical interface 
code, the implementation uses only vanilla Common Lisp and should run in any version. The program has 
been run successfully on a MacIntosh as well as a Sun SPARCStation1+ and a Silicon Graphics 4d.


The manual begins with three sections that provide a brief overview of Telos, a brief over view of the 
KNOWBEL implementation, and a sample interaction with the system. These sections are taken from a 
paper submitted to the 1991 AAAI Symposium on Implemented Knowledge Representations. Finally there 
are a large number of sections describing various details of the use of the system.


2.0  Overview of Telos


Telos was originally designed as a language for requirements modelling. It combines a language for structur-
ing objects, a first order logic language for expressing integrity constraints, a logic programming language 
for expressing deductions, and an interval-based representation of time for handling temporal knowledge. 


The object representation language describes the world in terms of classes and instances of those classes. An 
object may have attribute values for attributes defined in the classes of which it is an instance. Classes partic-
ipate in an IsA (specialization) hierarchy with strict inheritance and multiple parents. Classes, their 
instances, and attribute relationships are all Telos propositions. Propositions are treated uniformly, and every 
proposition must be an instance of some other proposition. This leads to some interesting properties. First, 
classes themselves must be instances of other classes (called metaclasses). Secondly, attribute propositions 
are instances of classes which are themselves attribute propositions. This provides the link between the 
attribute description in a class and the assertion in an instance. For example, the link from John to 25 might 
be an attribute proposition that is an instance of the proposition linking Person to Number with label age. 
This continues up into the metaclass level thereby enabling the definition of attribute categories. Thirdly, 
attribute propositions may themselves have attribute values.


The second ingredient of Telos is a subset of first order logic that is used for stating integrity constraints. 
Integrity constraints are logical expressions that must be true at all times. An example might be that a per-
son's birth date must follow her parents' birth dates by at least 10 years.


Next there is a more restricted subset of logic for expressing deductions that can be made in the knowledge 
base. The deductive inference engine is reflective in the sense of [Smi82] and [Kra87]. Reflection provides 
the ability to control the inference process through the use of objects in the knowledge base. This will be dis-
cussed in more detail in the next session.


Finally, Telos has integrated support for reasoning about time. Every relationship has two associated times: 
the belief time and the history time. The belief time is the time interval in which the knowledge base took the 
fact to be true. In general, the belief time of a fact begins when the fact is asserted and ends at the earlier of 
the present time and the time at which the knowledge base was told that the fact was no longer true. The his-
tory time is the time in history when the fact is true. For example, one might state that John is an instance of 
Student before Mary is an instance of Professor.


Interaction with a Telos knowledge base is through the five commands Ask, Retrieve, Tell, Untell, 
and Retell. Ask is used to pose a query to the knowledge base while Retrieve answers a query without 
recourse to deductive rules. Tell is used to add facts to the knowledge base, Untell is used to tell the 
knowledge base that a fact is no longer believed, and Retell combines Untell and Tell.


A complete description of Telos and a formalization is presented in [KMSB89]. The formalization provides 
a translation of Telos knowledge bases to theories in a many sorted first order language. [Ple90] provides a 
possible-worlds semantics for the language.


3.0  Description of the Implementation


The implementation consists of three major components: a sorted clausal resolution theorem prover built 
specifically to support Telos, an object module, and a temporal reasoner. The integrity constraint checking, 
deduction, and reflective reasoning capabilities of Telos are implemented in the context of the theorem 
prover. This section describes how the three components are linked and then continues with a short descrip-
tion of integrity constraint checking and reflective reasoning.


The theorem prover is linked to the object module in two ways. First, all variables in logical clauses have a 
sort which is an object from the object module (e.g. [Fri89]). Secondly, atoms corresponding to Telos objects 
are resolved through calls to the object module. For example, atoms that query relationships such as Instan-
ceOf that are stored in the object module, for example (not (instance-of flight1334 $x/
class...)), are handled by that module. It is important to note that the linkage between the two modules 
is designed so that all classes of which flight1334 is an instance can be successively bound to the vari-
able $x if necessary. This is a form of theory resolution [Sti85]. Finally, the theorem prover has indices that 
are Telos specific; in particular, some atoms are indexed on their first argument as well as the predicate.


The linkage between the theorem prover and the temporal reasoner is similar. First, times are represented in 
the theorem prover as sorts on variables. When two time variables are unified, the substitution maps these 
variables to a new time variable whose sort is the intersection of the intervals of the original variables. Of 
course, if the time reasoner can show that the two intervals do not intersect, the unification fails. Secondly, 
several predicates such as before involving time variables are handled via theory resolution using the tem-
poral reasoner. The use of sorts to distinguish temporal variables has also been described in [BTK89].


The temporal reasoner makes use of a time point representation of intervals as suggested in [VKvB89]. At 
present, however, the module does not compute and store the consequences of each time relation. Instead, a 
simple search through the network is done at the time of a query. As pointed out in [GA89], the former 
makes updates relatively expensive and consumes a great deal of storage, while the latter makes queries rel-
atively expensive. All of the approaches suggested in [VKvB89], [GA89], and [MS88] are complicated by 
the fact that in Telos the relationships between intervals have individual belief times. Thus heuristics for 
improving the performance of the time reasoner have yet to be implemented.


Integrity constraint checking is based on ideas proposed in [BDM88]. Since the knowledge base can be 
assumed to be consistent before an update, integrity constraint checking involves identifying those con-
straints that might be affected by the current update and testing simplified versions of the constraints con-
structed from the current update. In addition, any deductive rules that match the current update and that are 
possibly relevant to some integrity constraint must also be included in the set of clauses to be tested. In order 
to avoid testing all deductive rules, a dependency checking algorithm is run each time an integrity constraint 
or a deductive rule is added. A deductive rule is relevant to an integrity constraint if there is some sequence 
of inferences from the deductive rule that results in a resolvent one of whose atoms unifies with an atom in 
the integrity constraint.


 Reflective reasoning is a form of meta-level reasoning in which a portion of the knowledge base consisting 
of control knowledge is used to influence the course of an inference. This is implemented through a level 
shifting inference engine which under certain circumstances shifts its attention from the inference at hand to 
the control knowledge in order to make decisions about the lower level inference. Since it is would be very 
costly to reason about every control decision, level shifting must be restricted to those occasions in which it 
may be of use. In Telos, a shift is made when the atom which is the theorem prover's focus of attention has a 
meta-rule property. When this is the case, a control query is formulated and evaluated in the context of 
the meta-rule. If the result of this query is true, the bindings of variables in the query are used to change the 
state of the original inference. Example control actions include setting the priority of a resolvent, declaring a 
clause unresolvable, and forming a new resolvant. For example, one might have a meta-rule that returns a 
default value for an attribute if a depth bound is exceeded.


4.0  Interaction With Telos


End user interaction with a system built on a Telos knowledge-base will typically be through a graphical 
user interface. An example of such an interface is the interface to the alarm filtering system (see figure 1). 
For interactive development of a knowledge base, on the other hand, a knowledge engineer will want to 
interact through the Lisp-based Ask - Tell interface. A sample interaction with Telos in this mode is pre-
sented below.


For the example assume that a knowledge base containing information about airline flights has been loaded. 
Some attributes of a flight are its origin, destination, and cost. In the first example the user asks Telos for the 
destination of flight3402:


<cl> (ask `(exists ($x/city $t@-^+) (attr flight3402 * "destination" $x * $t)) `(now +))


True


	$x	<new-york>


	$t	$0@-,1986/1/1-0:0:0


<state>


The query language is a version of first order logic that is readable by Lisp. Variables are symbols beginning 
with a $.A variable may be given a sort at its first occurrence in the sentence by using the notation $var/
sort where sort is a class name. Temporal variables are identified by the syntax $var@time-expr, 
again at the first occurrence. Note that the value bound to $t in the result above is itself a temporal variable. 
In the example, this is bound to the interval from minus infinity (represented by -) to the beginning of 1986, 
this being the time associated with the attribute value. The second argument to is an optional belief time 
against which the query is to be evaluated. Finally, ask returns a state which can be used in subsequent 
calls to ask to generate the next answer. For our example one could continue with:


<cl> (ask *)


True


	$x	<tokyo>


	$t	$0@1986/12/31-11:59:59,+


<state>


Here, the destination of flight3402 is Tokyo from the end of 1986 until plus infinity.


Now suppose that the user's goal is to add some classes that can be used to find a minimum cost path 
between two cities. The first class, proto-Flight-path, is created as below:


<cl> (tell `(proto-Flight-path instance ((M1-Class)) with


	((attribute


		(from city)


		(flight flight)


		(to city)


		(cost number)


		(subpath proto-flight-path)


		(flight-gen flight


			:with (meta-rule(flight-path-mr


				(=> (and (varp $v)			(time-of $h $ih)


					(instance-of $obj/flight flight $ih)


					(attr $proto * "from" $origin * $ih)


					(attr $obj * "origin" $origin * $ih)


					(attr $obj * "price" $price * $ih)


					(current-clause-value $state $current)


					(+ $current $price $new-val)


			 	 (goal (attr $proto/proto-flight-path * "flight-gen" $v * $h) $state


					 (sigma (val $v $obj))			 (:value $new-val))))))))))


<proto-Flight-path>


In addition to the obvious attributes describing a path, the class as an attribute, flight-gen, that has an 
associated meta-rule. The purpose of this meta-rule is to find an instance of flight and to assign an evalu-
ation to the resulting resolvent. The predicate (goal <goal> <state> <substitution> <prop-
erties>) is true when <goal> can resolve to nil in the theorem prover state <state> with the given 
substitution, and resulting resolvent will have the properties <properties>. In the example, the :value 
property is assigned the cost of the partial path ending with the generated flight. When the theorem prover is 
in best-first mode, it chooses the resolvent with the lowest value as the next candidate for resolution.


Next, the subclass Flight-path of proto-Flight-path is defined. Note that in the assertion lan-
guage variables are universally quantified if there are no quantifiers. Note also that the construct 
#@((proto-flight-path)...) is a description of an object and can appear whereever an object may 
appear. These structures are important because they may contain variables thereby allowing the inference 
engine to construct descriptions of objects that are not already in the knowledge base. Note that in the exam-
ples of descriptions, the history time value for attributes is made explicit. In contrast, the attributes of proto-
Flight-path and Flight-path are taking on default values.


<cl> (tell `(Flight-path 	instance ((M1-Class)) isa ((proto-flight-path)) with


	((deductive-rule


		(path-recursive (=> 


		 (and (instance-of $p/proto-flight-path proto-flight-path $t@-^+)


		 	 (attr $p * "from" $origin * $t)


		 	 (attr $p * "to" $to * $t)


		 	 (attr $p * "flight-gen" $f/flight * $t)


		 	 (attr $f * "origin" $origin * $t)


		 	 (attr $f * "destination" $dest * $t)


		 	 (= $subpath/proto-flight-path


							 #@((proto-flight-path)(("from" (_ $dest $t))


							 ("to" (_ $to $t))


							 ("flight" (_ $subflight $t))


							 ("cost" (_ $subcost $t))


							 ("subpath" (_ $sp $t)))))


			 (= $path-class flight-path)


		 	 (instance-of $subpath $path-class $t)


			 (attr $p * "subpath" $subpath * $t)


			 (attr $p * "flight" $f * $t)


			 (attr $f * "price" $price * $t)


			 (+ $price $subcost $cost)


			 (attr $p * "cost" $cost * $t))


		 (instance-of $p flight-path $t))))





 (path-base (=> (and (attr $p * "flight-gen" $f/flight * $t@-^+)


		 	 (attr $f * "origin" $origin * $t)


		 	 (attr $f * "destination" $dest * $t)


			 (instance-of $p/proto-flight-path proto-flight-path $t)


			 (attr $p * "from" $origin * $t)


			 (attr $p * "to" $dest * $t)


			 (attr $p * "subpath" null-flight-path * $t)


			 (attr $p * "flight" $f * $t)


			 (attr $f * "price" $price * $t)


			 (attr $p * "cost" $price * $t))


		(instance-of $p flight-path $t)))))))
<flight-path>


This class contains two deductive rules for determining whether a particular proto-flight-path, $p, 
is in fact a valid flight path. The first rule picks a flight that originates at the from attribute value $p, then 
recursively attempts to find a path from the destination of that flight to the to attribute value of $p. The sec-
ond rule succeeds if there is a direct flight and terminates the recursion. What is important here is that both 
rules generate flights through the flight-gen attribute which invokes the meta-rule discussed above. One 
would ask for a path from Toronto to Chengdu in China using ask as follows:


<cl> (setq state


	 (ask `(and (= $x #@((proto-flight-path)


		 			(("from" toronto |$t(-,+)|))


					("to" (_ chengdu $t))


					("flight" (_ $flight $t))


					("cost" (_ $cost $t))


					("subpath" (_ $p $t)))))


			(instance-of $x flight-path $t)) :vars `($x))





True


	$x	@/desc12/(((<proto-flight-path> $0-,+))


			((from (_ <toronto> $41988/12/31-11:59:59,+))


 			 (to(_ <chengdu> $41988/12/31-11:59:59,+))


 			 (flight (_ <flight3502> $41988/12/31-11:59:59,+))


			 (cost (_ 1600 $41988/12/31-11:59:59,+))


			 (subpath (_ @/desc13/(((<proto-flight-path> $1-,+))


					 ((# #) (# #) (# #) (# #) (# #))))


<state>


Please be aware that the printed representation of a Telos structure differs slightly from the input representa-
tion. For example, the value of $x here is a description and temporal variables are missing the @ symbol. A 
subsequent call results in:


<cl> (Ask state)


True


	$x	@/desc21/(((<proto-flight-path> $0-,+)) 


			((from (_ <toronto> $31988/12/31-11:59:59,+))


			 (to (_ <chengdu> $31988/12/31-11:59:59,+))


			 (flight (_ <flight3502> $31988/12/31-11:59:59,+))


			 (cost (_ 1620 $31988/12/31-11:59:59,+))


			 (subpath (_ @/desc22/(((<proto-flight-path> $1-,+))


					 ((# #) (# #) (# #) (# #) (# #)))


					 $31988/12/31-11:59:59,+))))


<state>


Note the slightly higher value for the cost attribute of the path.


In addition to the interface at the Lisp level, there is also a graphical user interface (see figure 2) having but-
tons for loading and saving knowledge bases, for displaying the IsA and InstanceOf hierarchies graphically, 
editing objects, and making queries. 


5.0  A Note on Printing


The data structures used by KNOWBEL are all circular and generally incomprehensible when Lisp prints 
them. KNOWBEL supplies a read macro, #n, at the top level which attempts to provide a useful human 
readable interpretation of the structures that are its arguments. For example, the interpretation of a Telos 
object is its name. An example is


<cl> #n(tell `(John instance ...))


<john>


The expression #n<x> expands to (normal-clause <x>). normal-clause is a function that may 
be used by applications to translate KNOWBEL structures into human readable structures. The depth of the 
translation is controlled by the Common Lisp variables *print-level* and *print-length*. The 
author typically has these set to 10 and 20 respectively, and also sets the value *print-pretty* to T in 
order to make output more readable.


6.0  Initialization


The knowledge base is cleared and initialized by calling


(init-kb)


This creates all of the built in Telos classes and objects. The global variable 


*theory*


becomes a reference to the knowledge base. init-kb returns the theory structure so that an application 
might deal with multiple theories.


7.0  Tell


The tell operation asserts a number of propositions into the knowledge base. Its syntax is:


(tell expr &optional (theory *theory*) default-history (belief (std-belief)))


The expression is a representation of the Telos tell command in s-expr format. The format is


(name instance ((class1 [time1]) (class2 [time2]) ...)


	 isa ((isa-class1 [isa-time1]) (isa-class2 [isa-time2]) ...)


	 with ((attribute-name1
			(attribute-label1-1 value1-1 [time1-1 [with ...]])


			(attribute-label1-2 value1-2 ...)


			...)


		 (attribute-name2 ...)


		 ...)


	)


Apart from the object name, everything is optional. Times are all history times in a syntax to be described 
below.


The theory argument is a theory as returned by init-kb and defaults to *theory*. The default-
history argument is the history time that is used for all times that are not specified in expr and should be 
a time interval structure (see below) and defaults to an interval representing (includes now). This is not a 
good value for the history time since it tells the temporal reasoner almost nothing about the time and results 
in the proliferation of time intervals during reasoning. The belief argument is the belief time for all prop-
ositions created in the command and defaults to the interval from now to + infinity. The belief time represen-
tation is different from the history time representation and will be described below.


tell returns either the object named in its argument or a list of error messages. 


If the object named does not exist tell creates it. Otherwise, the effect of the operation is to add proposi-
tions concerning the object to the knowledge base. The following are the actions carried out:


1.	Locate the object named. If it does not exist, create it.


2.	Check that all objects named in the instance of clause exist and are at the same instance level.


3.	Assert that the object is an instance of all the objects of 2.


4.	Check that all the objects named in the isa clause exist and are at the correct instance level.


5.	Assert the isa links.


6.	For each attribute-name, check that the name is an attribute label in some parent class.


7.	For each attribute description, parse the value and check that its type is correct.


8.	Assert the attribute proposition and make it an instance of the appropriate attribute definition.


9.	Check the attribute proposition for compatibility with attribute propositions with the same name that are 
inherited from IsA parents. Make any attribute that is inherited an IsA ancestor of the new attribute prop-
osition.


10.	Recursively apply the attribute's with clause, if any.


11.	 Check integrity constraints.


Integrity constraint checking can be disabled by setting the global variable *ic-checking* to nil.


Parsing attribute values is fairly complicated. The process depends either on the type expected for the 
attribute or some properties of the expression itself. Some things to watch are:


1.	If the expected type is string, all values are made into strings using (format nil "~a" ...) if 
necessary.


2.	If the expected type is a number type or boolean, appropriate actions are taken.


3.	If the expected type is theory, the input should be the lisp form of a first order sentence which will be 
stored internally as a theory in disjunctive normal form.


4.	If the attribute class is integrity-constraint or deductive-rule the input is turned into a list of disjunctive 
normal form clauses. The parser is not very good at recognizing symbols that are names for objects that 
have not yet been created yet. A safe way to handle forward references is to surround all symbol names 
that are to be objects with the form (object <name>). Alternatively, add these constraints and rules 
at the end of the file.


5.	If the item is a symbol, it is interpreted as an object name. If the object does not exist, a vanilla object of 
that name and the expected type is created. Since it is often important to know when this happens the out-
put of tell will be an error list containing a warning that this was done. For example, one might have 
misspelled an object name.


6.	 If the value is an s-expression that can be interpreted as a first order sentence, it becomes a list of dis-
junctive normal form clauses.


7.	 If the value is a string, a unique reference to that string is used (see the section on object names and 
strings below).


8.	 If the value is a number, the number is used.


9.	 Otherwise, the value is used as is.


 If there is an error or integrity constraint failure, all of the actions should be undone. All objects and links 
that are created are stored, but at present this is not implemented.


8.0  Ask


There are several forms of ask which are appropriate for different situations. The function that is used at the 
lisp top level is called as follows:


(ask <query-or-state> &key (vars :all) (belief (std-belief)) 


			(theory *theory*) (horn t) (search :depth))


The first argument is either the lisp form of a first order sentence which represents a query, or a state. The 
lisp form of first order sentences will be described in a following section. A state is an object returned by a 
previous call to ask. In addition to returning a state,ask prints out the values for the requested variables 
should the query succeed. The state encapsulates the state of the inference so that ask can be used to print 
out additional answers by continuing the inference.


The vars argument is used to describe which variables in the query should be printed out. If the default 
value :all is used, no variable names will appear in the print out. There is a cost during inference for track-
ing variables.


The belief argument specifies the belief time at which to evaluate the query (see belief times below). The 
theory argument identifies the knowledge base to use (see theories below). When horn is t, as it should 
be for Telos, the theorem prover becomes a horn-clause theorem prover assuming that all of the clauses in 
the theory are in fact horn clauses. No check is done to see if all clauses are in fact horn.


The search argument decides the search strategy that is to be used. This can be one of :depth, :best, or 
:breadth. :best is a version of best first search in which the open resolvent in the set of support having 
the lowest node value is selected. Node values may be set by meta-rules. Note that :best acts like 
:breadth if there are no meta-rules for setting node values. 


The following is an example call to ask:


<cl> #n(setq state (ask `(attr bo1 * "water-level" $v * $t@-^+) :vars `($v)))


True


	$V	2.32


"#( nd-success9688 NIL #STATE:DEPTH)" 


<cl> #n(ask state :vars `($v))


True


	$V	2.42


"#( nd-success9688 NIL #STATE:DEPTH)" 





The functions ask1 and ask-all take the same arguments (except that the first must always be a query) 
and return lists of variable values. ask1 returns the first solution, and ask-all returns all solutions.


<cl> #n(ask1 `(attr bo1 * "water-level" $v * $t@-^+) :vars `($v))


((2.32)) 


<cl> #n(ask-all `(attr bo1 * "water-level" $v * $t@-^+) :vars `($v))


((2.32) (2.42) (2.62)) 


 T 


All of these functions are implemented using the function eval-query which can be used by an applica-
tion to develop different forms of interaction.


9.0  Tracing


A very detailed trace of the theorem prover operation can be had by calling (ptrace t) before calling 
ask. Tracing is deactivated using (ptrace nil).


10.0  Object Names and Strings


All object names are strings. However, for convenience, KNOWBEL reads symbols as object names. When 
a symbol is read, its name is converted to a string and changed to lower case. Names which are to have 
mixed or upper case must be entered in string quotes. This will work for functions such as tell and the 
utility functions described below, but not in queries. The query processor assumes that strings are meant to 
be strings. Its heuristic for object names is to assume that any symbol that identifies a Telos object is in fact 
a Telos object. This heuristic can be explicitly overridden using the functions object and symbol (see 
below).


Attribute labels are also strings. In general, any two strings that are equal are in fact the same string so that 
eq testing is possible in inference. This is accomplished by comparing each string that is read with a list of 
known strings and returning a unique representation. Symbols can be used for attribute labels in tell oper-
ations since the parser can determine by the context that attribute labels are meant. In query processing, 
attribute labels must be strings.


11.0  Theories


The theory data structure serves two purposes. Most important, a theory points at a knowledge base descrip-
tor. All theories for a given knowledge base point at the same knowledge base descriptor. The second pur-
pose is to partition axioms into different contexts through the use of multiple theories. For example, every 
KNOWBEL knowledge base has a theory called deductive-rules and a theory called integrity-
constraints. Theories have names which are Lisp symbols. These theory names can be used, for exam-
ple, in unprovable and provable in the query language. One can retrieve the theory structure corre-
sponding to a given name using


(theory-find-theory theory name)


where theory is any known theory and name is a string or a symbol (strings are converted to symbols).


Theories can be arranged into a tree of inclusions using the command


(includes parent child)


which includes the child theory into the parent theory. This makes the theorem prover behave as if the axi-
oms of the child theory are axioms of the parent theory. The call


(unincludes parent child)


removes the child from the parent.


12.0  Assertion / Query Language


KNOWBEL accepts as input an s-expr representation of a sorted first-order logical language. A sentence is 
one of the following:


1.	(predicate-name arg1 arg2 ...)


2.	(and sentence1 sentence2 sentence3 ...)


3.	(or sentence1 sentence2 sentence3 ...)


4.	(not sentence)


5.	(forall variable sentence)


6.	(forall (variable1 variable2 variable3 ...) sentence)


7.	(exists variable sentence)


8.	(exists (variable1 variable2 variable3 ...) sentence)


9.	(unprovable sentence [belief-time [ theory-name [ search-strategy [ no-meta]]]])


10.	(provable sentence [belief-time [ theory-name [ search-strategy [ no-meta]]]])


11.	(quote sentence)


12.	(bquote comma-sentence)


A comma-sentence is a sentence in which any component c of a regular sentence can be replaced by the list 
(comma c). Forms 10 and 11 exist to selectively prevent the interpretation of variables when forming 
meta-rules and using meta-language forms such as unprovable. The arguments to provable and 
unprovable are a belief time, a theory name, a theorem prover search strategy as described for ask (one 
of :best, :breadth, :depth), and no-meta which if non-nil causes meta-level reasoning to be dis-
abled on the first goal. All of these are optional with reasonable defaults and may not be unbound variables 
when the goal is encountered.


An expression that can appear as an argument to a predicate is one of:


1.	a symbol


2.	a string


3.	a number


4.	a variable


5.	the wild card symbol *


6.	(object arg)


7.	(symbol arg)


8.	(function-symbol expression1 expression2 expression3 ...)


9.	(quote expression)


10.	(bquote comma-expression)


11.	#@description


12.	(belief [start [end [constraint]]])


Variables are lisp symbols whose first character is $. The first occurrence of a variable in a sentence may 
have a sort. There are several kinds of sorts: simple sorts, meta-sorts, and temporal constraints. A simple sort 
is introduced with one of the following notations:


1.	$var/class-name


2.	$var(class-name)


The class name is the name of a class in the knowledge base. Note that for form 2, either the parentheses or 
the entire symbol must be quoted (e.g. |$x(person)|).


Meta-sorts are similar accept that the class name is enclosed in square brackets, for example $y/[neces-
sary]. This sort constraint means that the type of the type of the value bound to the variable is the chosen 
class. Higher levels of meta-class may be indicated using further levels of square brackets. Sorts and meta-
sorts are very useful in restricting the number of potential resolvents in an inference step.


A temporal constraint is either a conventional interval indicated by the notations|$t(start-
point,end-point)| or $t@start-point^end-point or a time expression indicated by the 
notation |$t@history-time-expression| both of which are described in more detail in the section 
on history times. Start times and end times are dates as described in that section. The variable need not be 
quoted if there are no special characters in the expression. Parentheses must not appear around the time 
expression in the @ notation. Examples are |$t@:before (1990 1991)| and |$t@:during 
:inst john person|. The special notation $t@ is provided to identify an unconstrained temporal vari-
able. In the assertion language, temporal reasoning is always done using temporally constrained variables.


The special function symbol object forces its argument to be interpreted as an object name. If the object 
does not exist, a vanilla object is created. The function symbol is used to indicate that its argument is meant 
to be a symbol, not an object. The function quote indicates that no compilation is to be done within its 
argument. bquote is similar except that quoting can be selectively turned off within expressions sur-
rounded by the function comma. All of these constructs disappear during clause compilation. 


The wild card symbol *will unify with any expression. Note however, that some of the primitive predicates 
desribed in the next section may not accept wild cards in any or all object positions.


Form 11, #@description defines a description object. The description is similar to the object descrip-
tion argument to tell. It differs in that attribute names must be quoted and that variables may appear. A 
description object will unify with variables whose types subsume the types of the description. InstanceOf 
and attribute requests treat descriptions as regular objects. Descriptions allow clauses to build structures 
describing objects that do not actually appear in the knowledge base. An example is


		 #@((proto-flight-path)(("from" (_ $dest $t))


							 ("to" (_ $to $t))


							 ("flight" (_ $subflight $t))


							 ("cost" (_ $subcost $t))


							 ("subpath" (_ $sp $t)))))


The precise syntax of a description is (<list-of-types> <list-of-attribute-groups>) where a type is either a 
class name or a two element list of a class name and a time variable. An attribute group is a list consisting of 
an attribute name and any number of attribute descriptions consisting of a label, a value, and a time variable.


Form 12 is useful for introducing belief times into queries. Please see the section on belief times below for 
appropriate arguments. Note that if now is used in a belief time, the time when the expression is compiled is 
used. Execution time belief times can be generated with the special predicate belief-now.


13.0  Propositions


For efficiency reasons, Telos propositions map into several different kinds of objects in Knowbel.


 First, Telos tokens and classes such as <John, John, John, time> map into Knowbel objects with 
names. The lisp data structure is called a kb-token. Note that the time of this proposition disappears in the 
mapping. Knowbel objects make it easy to reach parents, descendants, and attributes.


Secondly, instance and isa relationships are represented by special objects called prop-objects. These 
objects consist of the type of the link, the source, the destination, a history time and a belief time.


Finally, attribute propositions such as <John, age, 23, time> are represented as Knowbel objects 
(kb-tokens) with additional properties. These properties are the value, the history time, and the belief time. 
The label of the proposition, e.g. age, becomes the name of the object. It is useful to represent attributes as 
regular objects because Telos treats these propositions as first class objects.


Knowbel supplies a function for locating propositions directly (i.e. not through ask). The function call is


(find-prop expression theory belief state)


The function is a generator: on the first call, the state argument should be :init. The value returned will be 
a result cons'd to a state. This state can be used in a subsequent call to return the next value for the generator. 
The theory and belief are as usual. The expression is one of the following:


1.	(:inst <obj> <class> <history time>)


2.	(:isa <class1> <class2> <history time>)


3.	(:attr <object> <label> <class-label> <value> <history time>)


In all cases, all arguments except the first may be the wild card *. The time arguments need not be supplied. 
If they are, they must be instances of the time-interval data structure. Matching of history times must 
be exact in the sense that the temporal reasoner finds the given interval equal to the candidate interval. The 
history time can specified by a time interval structure, a temporal variable, or a prop-object. find-prop 
generates all propositions that both match the pattern and are explicitly stored in the knowledge base.


14.0  Standard Predicates


The assertion language has several predicates that deal with the structure of the knowledge base. In Knowbel 
these are implemented via primitive connections to the object module rather than axioms in the theory. The 
predicates are the following:


1.	(= <arg1> <arg2>) is true if the two arguments unify successfully.


2.	(instance-of <obj> <class> <time>): This is true if <obj> is an instance of <class> at <time>.


3.	(is-a <class1> <class2> <time>): This is true if <class1> is a specialization of <class2> at <time>.


4.	(attr <obj> <label> <class-label> <value> <prop> <time>): This is true if <value> is an attribute value 
of <object> at time for the attribute named <class-label>. <label> is the label of the attribute proposition 
and <prop> is the proposition itself. In practice, * is frequently used for <label> and <prop> because the 
values are not needed. One might ask for John's age via (ask `(attr john * "age" $v * 
$t@)).


5.	(find-prop <pattern> <prop>) is true if <pattern> describes <prop> where <prop> is an explicitly 
stored proposition as described in the previous section. The pattern is exactly as described for the lisp 
function find-prop.


6.	(time-test <time-exp1> <op> <time-exp2>) is true if the time represented by <time-exp1> stands in 
relation <op> to <time-exp2>. This predicate will not further constrain time variables. The time expres-
sions are either variables with temporal sorts or propositions as in the second argument to find-prop 
or the second last argument to attr. <op> is one of the Telos interval relations as described in the sec-
tion on history times.


7.	(time-constrain <time-var1> <op> <time-exp2>) is the same as time-test except that the first argu-
ment must be a temporal variable and the resulting substitution will constrain the variable in a resolution 
step.


8.	(time-of <thing> <var>) transfers the time constraint from <thing> to <var>. <thing> can be a vari-
able in any context, an explicit interval data structure, or a prop-object. <thing> as a variable is useful in 
meta-rules where it might be bound to a variable at a lower meta-level.


9.	(print <anything> <anything> ...) is always true and has the side effect that all of its arguments are 
printed.


10.	(current-clause-value <state> <val>) is true if the node value of the current clause of the infer-
ence state is <val>. This can be used by meta-rules.


11.	(<op> <arg1> <arg2> <result>) for arithmetic operations +, -, /, * is true if <arg1> <op> <arg2> = 
<result> for arithmetic.


12.	(<rel-op> <arg1> <arg2>) for relation operations >, <, >=, <= is true if the relationship holds between the 
arguments.


13.	(belief-now <var>) is true if <var> is bound to the belief time (now +).


15.0  History Times


Every :inst, :isa, and :attr proposition has an associated interval known as its history time. A proposition can 
be assigned a history time relative to the time of some other proposition. This relationship is expressed using 
one of the following interval relations: equals, during, over, startsbefore, startsafter, endsbefore, endsafter, 
rightbefore, rightafter, before, after, costarts, coends, overlaps, and overlapped-by. History times are 
expressed by history time expressions which have one of the following forms:


1.	date, e.g. 1990_11_10_15_33


2.	(date date), e.g. (1990_11_10 1990_11_13)


3.	(interval-op date) e.g. (:during 1990)


4.	(interval-op (date date)), e.g. (:before (1990 1991))


5.	(interval-op . find-prop-expression), e.g. (:after :inst flight1334 flight)


A date is a symbol consisting of numbers and underscores, where the right most number is interpreted as the 
year, the next the month, and so on down to hours, minutes, and seconds. Knowbel supplies defaults for any 
numbers not specified. The defaults depend on whether the date is at the start or the end of an interval: for 
example at the start of an interval, 1990 defaults to 1990_1_1_0_0_0 while at the end of an interval it 
defaults to 1990_12_31_11_59_59. A second date notation is a symbol or string consisting of two or 
three numbers separated by colons, for example |11:59:33|. This represents the represented time on the 
current date. Finally the symbol or string now refers the date and time when the history time is parsed, the 
symbol - represents minus infinity, and + represents plus infinity.


A single date as in form 1 represents an interval a the resolution of the interval. Thus the notation 1990 rep-
resents the year 1990, i.e. (1990_1_1_0_0_0 1990_12_31_11_59_59), while a date specified to 
the minute represents the interval of a minute.


Times represented by dates are known as conventional times. Since they are represented internally as com-
mon lisp universal times, they cannot presently represent times before the year 1900. The interval-ops 
are the interval relation names preceded by colons. There are many abbreviations for these names.


For form 5, the find-prop-expression is an expression that would be a suitable argument to find-
prop as discussed earlier. Note that the parentheses should be removed. Also, when the pattern matches 
many propositions, the time relation is asserted between the new interval and all of the propositions.


The utility function parse-history-time can be used to turn a time expression into a time interval. 
The function (get-time-var op arg) creates a temporal variable. The op is the car of a time 
expression and the arg is either another temporal variable or the cdr of a time expression.


An interval consists of two end points called time points. Time points can be either numeric representing 
conventional times, or symbolic when all that is known about the point is its relationship to other points. All 
relationships between intervals are stored as relations between time points.


The human readable printed form of time intervals is somewhat awkward. The representation is


(descriptive-information)start,end


where start and end are representations of the time points, and descriptive-information is some information 
that is stored to describe the interval. The descriptive information can frequently be the history time expres-
sion that was parsed to create the interval, but need not be. For intervals that are shared, the descriptive 
information will be NIL and the interval will be represented by start,end. For conventional time points, 
a natural date-time representation is used. If the date is the current date (at time of printing), the date is sup-
pressed. For symbolic time points, the notation tp<n> is used where <n> is an integer which depends on 
the sequence in which time points are printed.


16.0  Belief Times


For efficiency reasons, the representation of beleif times is quite different from the representation of history 
times. Belief times must be conventional intervals, and stored belief times do not require a temporal operator 
since facts are taken to be true throughout the entire belief-time interval. For queries, the operators :during 
and :intersects are the only valid operators. 


(parse-belief-time [start [end [operator]]])


is a function for creating belief times. start and end are dates , end defaults to +, and operator 
defaults to :during. With no arguments, the belief time is the interval from now to +. 


One will use belief times only as arguments to queries and in belief time directives in load files.


17.0  Untell


At present untell can only take a proposition existing in the knowledge base (e.g. generated by find-
prop) and set its belief time to end at the current time. The general form of untell described in the Telos 
reports would be very time consuming to implement. The problem is that turning off an attribute or Instan-
ceOf link could result in a large number other links that are no longer valid. The action to take under these 
circumstances is not well defined.


18.0  Retrieve, Retell


Retrieve and Retell are not implemented. Note that find-prop is a form of Retrieve.


19.0  Utilities


The function (lookup-type name theory) returns the object in theory (which defaults to *the-
ory*) which has name name. The function print-kb-token prints a detailed description of the object. 
The macro (tok name1 name2 name3 ...) where none of the arguments is evaluated, combines the 
look up and printing operations.


The function (print-theory theory) will print a representation of the clauses stored in a theory. 
Note that in general the theory *theory* does not contain any clauses. For a Telos theory, the function 
(print-dr [theory]) will print out the deductive rules and (print-ic [theory]) will print out 
the integrity constraints.


20.0  Loading Knowledge Bases


The form


(loadkb file-name &optional (init t) (verbose nil) default-history)


can be used to read in ascii files describing knowledge bases. The init argument determines whether the 
knowledge base is initialized before reading. verbose controls whether anything, including error mes-
sages is printed, and the default-history is the same as for tell. The default history will be the 
default for all objects described in the file unless the default is changed from within the file.


The knowledge base file consists of lisp expressions that would be suitable arguments to tell.


Additionally, expressions of the form


(time <history-time-expression>)


can be used to change the default history time.


Similarily, expressions of the form


(belief [start [end [constraint]]])


cause the belief time at which subsequent objects are stored to be changed. For example,


(belief 1973 1978)


sets the belief time to be the interval 1973 to 1978.


21.0  Dump and Restore


This is not yet working.


(dump-kb-file <theory> <file>) will dump the entire knowledge base in a special dump format.


(restore-kb-file <file>) will restore a dumped kb, setting the global variable *theory* and 
returning the theory structure.


Note that the dump file format results in files about twice the size of the loadkb file format that created it. 
It is also not human readable.


Special representation definitions are not dumped.


22.0  Meta-Rules


KNOWBEL has a meta-level control of inference facility. Meta-level inferencing is invoked in response to a 
goal for which the theorem prover can determine that there exists a set of meta-rules. This is occurs when the 
goal is of the form (not (attr <object> <label> <class-label> <val> <prop> <t>)) 
where there is sufficient information to determine the object defining an attribute definition and where that 
attribute definition has a value for its meta-rule property. This might occur where <object> and <class-
label> are bound or where <object> has a type and <class-label> is bound. An example of a meta-rule decla-
ration is the following:


(proto-Flight-path


 instance ((M1-Class))


 with


 ((attribute


 (flight-gen flight


		 :with


		 (meta-rule


		 (flight-path-mr


		 	(and <meta-rule1> <meta-rule2> ...)))


		 )))	


 )


Notice that a number of meta-rules can be entered as a conjunction. The meta-rule is a property value of the 
object that defines the attribute flight. As is the case with all clauses in the assertion language, it is a good 
idea to the label the attribute (here it is flight-path-mr) so that the clauses have a meaningful name in 
theorem prover output and justifications.


When shifting to level n + 1, the theorem prover attempts to find a contradiction to the sentence


(and (not (goal <goal> <state> $sigma))


	(not (goal <goal> <state> $sigma $props))


	(not (state <state> <active-clause> $state))


	(not (resolvent <state> <active-clause> $resolvent)))


where <goal>, <state>, and <active-clause> are bound to representations of the corresponding objects in the 
proof at level n. When a contradiction is found for one of the atoms in the sentence, it is expected that the 
variable or variables be bound to an expression which describes to the inference engine how to continue the 
prove at level n. The various meta-level goals serve different functions:


1.	contradicting (not (goal ...)) is used to resolve <goal> to nil. With the $props argument 
properties can be assigned to the resulting resolvent. Currently the theorem prover recognizes the prop-
erty :value as the priority of a resolvent.


2.	contradicting (not (state ...)) is used to change the level n state parameters of the inference 
engine. Not implemented yet.


3.	contradicting (not (resolvent ...)) is used to explicitly construct a resolvent. Not 
implemented yet.


A sample meta-rule is 


(=> (= $v 5) (goal (attr $x * "foo" $v * $t@) $state (:value 15)))


which when-ever invoked sets the value of the "foo" attribute of any object to 5 and sets the priority of the 
resulting resolvent to 15.


23.0  Graphical Browser


For users having Franz's Allegro Common Windows several graphical browsing facilities are available. 
The facilities include several different ways of graphing the knowledge base, time points, and theorem 
prover explanations plus a facility for displaying the propositions within an object for the purpose of 
untelling some of them. These functions are defined in wi.lisp and require that cw-init.lisp is 
loaded first.


The graphical display of relations is horizontal from left to right; i.e. a subclass will be drawn to the right of 
its parent. The layout algorithm can display only trees, so cycles are broken by displaying a second copy of 
some node in the cycle. This second copy is displayed in a different style in order to draw attention to the 
fact that it occurs elsewhere in the graph.


All of the graphs may be depth limited: the depth to which a transitive relation is displayed can be con-
trolled. For example, if the IS-A depth is 3 and the graph is rooted at A, and D IS-A C IS-A B IS-A 
A, A, B, and C will be displayed, but not D since it is at IS-A depth 4.


The user interacts with the display using the left mouse button. When the left button is down and the mouse 
cursor is on a mouse sensitive object, the object will be high lighted. Releasing the button over such an 
object will cause an auxiliary pop up menu to appear. A selection is made in this menu using the left button. 
The menu options will be described below the discussion of the various display options.


The macro


(browse <object> [:subclasses <is-a-depth>] [:instances <inst-depth>]


			[:attributes <attr-depth>] [:belief <belief-time>])


is a general interface to the graphing system. It will display a graph rooted at <object> with the specified 
depth in each of three structuring dimensions. Arguments of 0 in any dimension will ensure no display in 
that dimension. IS-A, INSTANCE-OF, attribute source, and attribute destination arcs have distinct appear-
ances. Similarily, there is a visual difference between nodes for tokens, classes, m1-classes, and m2-classes. 
The default operation is to display IS-A to a depth of 4 with one level of instance-of relationships. 
<object> can be either an object structure or an object name. The following is a portion of such a 
browser: 


The objects in solid boxes are classes while those in gray boxes are tokens. Careful examination will show 
that the INSTANCE-OF links from tokens to classes are lighter than the IS-A links between classes (in 
colour the former are red and the latter blue).


The macro


(browse-instances <object> [:subclasses <is-a-depth>] [:instances <inst-depth>]


			[:attributes <attr-depth>] [:belief <belief-time>])


is a version of browse that by default displays only the direct instances of the <object>.


The macro


(browse-parents <object> [:belief <belief-time>])


displays the transitive closure of the "IS-A parents" relation from <object>. That is, <object>, its IS-A 
parents, their parents, etc. are displayed. browse-ancestors does the same for the INSTANCE-OF rela-
tionship.


For graphing portions of the time graph, the function (display-time-point <time-point>) may 
be used. This displays all of the time graph reachable from the input point.


(display-explanation <clause> [<depth>]) provides a depth-limited display of the justifica-
tions of the active clause <clause>.


Finally, the macro (edit-object <object>) presents a representation of the object that can be used 
to untell various propositions contained therein.


Although the pop up menu for various kinds of nodes varies, the operations are drawn from the following 
set:


o	edit --- for a KNOWBEL object, open an edit-object window.


o	subgraph --- display a browse-style graph rooted at the clicked on object. If invoked in a browser, use 
the depth parameters from that browser.


o	parents --- invoke browse-parents from the clicked on object.


o	ancestors --- invoke a browse-ancestors browser from the clicked on object.


o	attributes --- invoke browse with only a non-zero attributes parameter to show the attribute struc-
ture of the object.


o	detail (for clauses only) --- print a detailed representation of the clause on the output window (lisp stan-
dard output)


o	untell (edit-object only) --- if the belief time of the proposition is + infinity, set the belief time of the 
proposition to end at the current time.


o	undo (edit-object only) --- restore the belief time to + infinity.


The display of graphs is done using a layout algorithm based on the ISI grapher [Robbins].


The package assumes a colour X windows server. For black and white servers, some editting of the styles in 
wi.lisp will be necessary. The styles are global variables ending in the sequence -style* and the 
colour names are obvious. The simplest way of changing the colours is to set the common windows global 
colour variables all to the value of black before loading wi.lisp. 


24.0  Generators


Several functions such as ask and eval-query are generators, functions that take and return a state value 
so that a number of values can be returned through a number of calls to the function. The idea is that the state 
value records enough information so that the function can generate the next value.


The system includes a package called the ndprog package for building generators that are fairly easy to 
understand. Note that this is a technique for generators that avoids object oriented programming. ndprog 
is a macro that may appear anywhere a prog may appear. Its syntax is


(ndprog <state> (<prog-vars>) <body-form1> <body-form2> ...)


It looks exactly like a prog except that the generator state value is supplied before the variable list. Within 
an ndprog when the form (success <value>) is encountered control returns from the ndprog and the 
value returned is a pair whose car is <value> and whose cdr is the state which should be given to the 
ndprog to generate the next value. For example,


(defun gen-numbers (state)


	(ndprog state nil


		(success 1)


		(success 2)


		(success 3)


		)


	)


)


is designed to return the numbers 1, 2, and 3. A generator is initialized by the special state :init. The fol-
lowing dialogue would result from gen-numbers:


<cl> (setq state (gen-numbers :init))


(1 . <state>)


<cl> (gen-numbers (cdr state))


(2 . <state>)


<cl> (gen-numbers (cdr state))


(3 . <state>)


<cl> (gen-numbers (cdr state))


nil


The printout of the state structure has been suppressed. Note that once the generator has been initialized, the 
same state structure can be used in all subsequent calls. When the generator is called with the state structure, 
execution resumes immediately after the call to success that returned the previous value. 


success is an example of an nd-macro, a form that is recognized in the expansion of the ndprog. All nd-
macros must appear at the top level of an ndprog or another nd-macro. The following are several important 
nd-macros:


o	(nd-if <expr> <if-form> <else-form>) - a version of if that allows nd-macros to be expanded within 
its body.


o	(nd-progn <expr1> <expr2> ...) - a version of progn that allows nd-macros to be expanded within its 
body.


o	(nd-loop (<var> <form>) <expr1> <expr2> ...) - a simple loop nd-macro in which <form> must evalu-
ate to a list and <var> takes on subsequent values from this list on subsequent iterations. The body of the 
ndprog in gen-numbers above is equivalent to (nd-loop (x `(1 2 3)) (success x)). 


o	(nd-for <var> <state-var> <generator-form> <body1> <body2> ...) - this form is used to iterate over 
ndprog-based generators within an ndprog. The <state-var> is automatically initialized to :init 
and must be passed to the generator in the <generator-form>. The variable <var> receives subsequent 
values from the generator on subsequent iterations. For example, to print subsequent values from 
gen-numbers above, one could use the following:


	<cl> (ndprog :init nil


			(nd-for var num-state (gen-numbers num-state)


				(print var)


			))


	1


	2


	3


	nil


	<cl>


25.0  Defining Theorem Prover Primitives


New primitive predicates can be defined for the theorem prover. Strictly speaking, this should not be neces-
sary in Telos applications, but it is described here in case primitive predicates are missing. The mechanism is 
unique in that the Lisp function implementing the predicate is a generator. 


Primitives are defined using


 (defresolve predicate-name (atom sigma state belief clause theory)


	<body>)


atom will be the current goal of the theorem prover. When running horn clauses, the atom will always be of 
the form (not (predicate-name ...)). For generality, however, the code must allow for positive 
atoms. sigma is a substitution data structure which the Lisp code may modify in order to inform the theo-
rem prover of bindings for variables. state is the generator state; on the first call it will be :init. On sub-
sequent calls it will be the state value returned by the procedure. Typically this will be an ndprog state. 
belief is the belief time of the query, clause is the current active clause (containing atom), and 
theory is the current theory.


If a resolve procedure succeeds, it should return three values. The first should be t, the second a state for 
continuing generation (continuation), and the third a list of justifications. If it fails it simply returns either 
nil or :fail. nil indicates that although the resolve procedure did not come up with an answer, an 
answer may still be deduced from the theory. :fail indicates that no further attempt to satisfy the goal 
should occur.


The procedure can test whether a part of the atom is a variable using


(unify-var-p <part> (ac-clause clause) nil)


The arguments will not be described here. A value is assigned to a variable in the subsitution sigma using


(setf (aref sigma (var-number <var>) 0) <value>)


Should the procedure need to set the type of a variable in the substitution (usually in the case of history 
times), the form


(setf (aref sigma (var-number <var>) 1) <value>)


should be used.


The following example shows a predicate foo that is true if its argument is 1, 2, or 3. If the argument is a 
variable, the values 1, 2, and 3 are subsituted on subsequent calls.


(defresolve foo (atom sigma state belief clause theory)
	(if (eq (car atom) `not)			 	 	 	 	;; check for negative atom


		(let ((arg (cadr (cadr atom))))


			(if (unify-var-p arg (ac-clause clause) nil) ;; is arg a variable


				(let ((cont


					(ndprog state nil


						(nd-loop (val `(1 2 3))


							;; set the value in the substitution


							(setf (aref sigma (var-number arg) 0) val)


							(success t)


							)


						)))


					(if cont (success t (cdr cont) `(foo)))


					)


				(if (member arg `(1 2 3) :test #'eql)


					(success t nil `(foo))


					)


				))))


		


26.0  Special Attribute Representations


The KNOWBEL implementation provides a mechanism where-by the standard representation of attributes 
can be circumvented. This is useful in cases where attribute values may exist in some other form (on a file or 
a database or some other server), or where the cost of representing an attribute value as an object might need 
to be avoided for performance reasoning. The mechanism is called the lisp-rep or special representation 
mechanism. Special representations are declared via


(declare-lisp-rep <class-name> <attr-label> <lookup-function> <tell-function>


			 <theory> [<arg1> <arg2> ...])


There must not be any previous values for any instance of the class for <attr-label>, otherwise the sys-
tem will behave as if the declaration had never occurred. The attribute must have been defined in the class. If 
these conditions are met, <lookup-function> is installed as the function used by the system for access-
ing attribute values and <tell-function> is used by the system for asserting values. The <theory> is 
the usual theory argument and <arg1>, <arg2>, ... are always passed as arguments to both the look up 
and tell functions. These arguments can be used to allow one function to be used for several different 
attributes (for example to identify a field in a relational database).


The tell function is invoked each time that tell encounters a special attribute value for some instance of the 
corresponding class. The form of the tell function is:


(defun <tell-fn> (<object> <class-label> <value> <history> <belief>


					 [&optional arg1 arg2 ...])


	...


	)


The arguments are the object in question, the attribute definition (class) label, the value to be stored, the 
times, and the optional arguments which are bound to the values <arg1>, <arg2>, ... of the declaration. 
Note that no individual attribute label is provided.


An attribute value is looked up when the theorem prover encounters a literal of the form


(not (attr <object> <label> <class-label> <value> <prop> <history>))


where <object> and <class-label> are bound (i.e. not variables). The look up function is a generator 
whose form is:


(defun <lookup-fn> (object class-label value valuev history belief state


				[&optional arg1 arg2 ...])


	...


	)


This function is passed the object for which the attribute value is desired, the attribute definition (class) label 
(the same as <attr-label> in the declaration), the value, if any, that is bound in the value position of the 
attr request in the goal, the variable, if any, that is in the value position of the goal, the history time, the 
belief time of the query, the state of the generator (:init if it is the first call), and optional arguments 
which will be bound to the corresponding <argi> from the special representation declaration. Note that no 
proposition object is returned to the goal ... that argument is essentially ignored. This function, as a genera-
tor, should return a pair consisting of a value and a state. The value should be a list of three values: a value to 
bind to <label> in the goal should it be a variable, a value to bind to <value> in the goal should it be a 
variable, and a history time which will become the constraint of the <history> field of the goal. If the 
value is nil, the goal fails.


An example is the following:


(defun test-lisp-rep (object label value valuev history belief state &optional field)


 (let (h)


 (ndprog state (i)


 (setf i 0)


 (nd-loop (x (<get list of values from object and label>))


	(setf h (time-intersect history (car x) belief))


	(nd-if h


	 (nd-if valuev


	 	(nd-progn


	 		(success (list i (cdr x) h))


	 		(setf i (+ 1 i))


	 	)


	 (nd-if (eql value (cdr x))


	 	(success (list i nil h)))


	 	)


	 )


	)


 )


 )


 )





(defun set-test-lisp-rep (object label value history belief &rest optional)


 (<store value>)


 )








(tell `(alarm with ((attribute (sss number)))) *theory* (theory-all-time *theory*)) 


(declare-lisp-rep `alarm "sss" #'test-lisp-rep #'set-test-lisp-rep *theory* 1)


 


where the actual location of the stored values is left to the reader's imagination. Note however that that the 
retrieval loop expects a list of pairs where the car is a history time and the cdr is the stored value.

