defrelation [Macro]
Purpose
The defrelation macro defines or redefines a binary or n-ary relation.
Syntax
defrelation name &optional documentation
&key is is-primitive implies domain domains range arity predicate function
inheritance-link inheritance-method annotations identifier kb characteristics
Arguments
The name argument is a symbol. If name is null, the relation is given a system-generated name.
The documentation argument is a string which attaches a comment to the relation being defined. This string can be retrieved by calling the Lisp documentation function with variable as the doc-type argument. The is and is-primitive arguments are relation-forming expressions (see Remarks below) that define the relation---that is, they specify a condition that is both necessary and sufficient for a tuple to satisfy the relation. These arguments are identical except that is-primitive introduces primitiveness into the definition. If neither argument is provided, then the relation is assumed to be a primitive specialization of the built-in relation Binary-Tuple or N-Ary-Tuple.
The implies argument is a relation-forming expression (see Remarks below) that attaches a rule to the relation---that is, it specifies a condition which is necessary for a tuple to satisfy the relation.
The domain and range arguments are concept-forming expressions (see defconcept Remarks). Supplying these arguments is equivalent to using :domain and :range expressions in the implies argument.
The domains argument is only used in the definition of n-ary relations. It is a list of concept-forming expressions whose length is equal to one less than the arity of the relation being defined. Supplying this argument is equivalent to using a :domains expression in the implies argument. The arity argument is an integer which specifies the arity of an n-ary relation. A relation with an arity of n has n-1 domains and one range.
The predicate argument consists of a two-variable lambda list followed by a body of Lisp expressions (more variables are required for n-ary relations). When the variables are bound to objects, the Lisp expressions can be evaluated to determine whether the relation being defined holds between those objects. This test supercedes the definition given in the is or is-primitive argument.
The function argument consists of a one-variable lambda list followed by a body of Lisp expressions (more variables are required for n-ary relations). When the variable is bound to an object I, the Lisp expressions can be evaluated to generate other objects which are linked to I by the relation being defined. This function supercedes the definition given in the is or is-primitive argument.
The inheritance-link argument is the name of an inter-concept link across which annotations are inherited. Typically, this link is the metarelation direct-subrelations. For example, if relation R is declared to have the direct-subrelations inheritance link, and concept B is a subconcept of A, then when (R A x) is asserted, Loom will infer (R B x).
The inheritance-method argument is either :nearest-neighbor or :union. The :nearest-neighbor option indicates that annotations are inherited across inheritance-link only from the nearest concept (e.g., the most-specific superconcept) which has such annotations. The :union option indicates that annotations are inherited transitively across the inheritance link.
The annotations argument is a list of facts to be asserted about the relation being defined. Each element of the list is either a concept-name or an expression of the form (RelationName instance), where instance is either a constant or a symbol that identifies a Loom instance.
The identifier argument is the name under which the relation will be interned in the :instances partition of its knowledge base. This argument defaults to name.
The kb argument is a string or symbol that names the knowledge base in which the relation is to be interned. This defaults to the current knowledge base.
The characteristics argument is a keyword or list of keywords which specify various characteristics of the relation. Relations may have the following user-settable characteristics:
- The :single-valued characteristic indicates that the relation, when used as a role, may have only one value. If two (or more) different instances are asserted to be fillers of a single-valued role, Loom automatically retracts all but the last assertion. This clipping behavior can be globally overridden by unsetting the :clip-roles feature (see set-features), and it can then be locally restored by setting the :clip-roles characteristic.
- The :multiple-valued characteristic is used with relations whose definition contains the :function option. It declares that the relation, when used as a role, will return more than one value. By default, :function relations are :single-valued, while ordinary relations are :multiple-valued.
- The :clip-roles characteristic is used with :single-valued relations. It causes clipping to be performed on such relations even though the :clip-roles feature has been unset globally.
- The :symmetric characteristic indicates that the relation is its own inverse. For example, if R is :symmetric, then (R x y) implies (R y x).
- The :commutative characteristic indicates that a relation of arity n holds regardless of the ordering of its first n-1 arguments. For example, if R is :commutative, then (R x y z) implies (R y x z).
- The :read-only characteristic indicates that the relation, when used as a role, cannot be asserted to. Such roles are not monitored by productions, and they cannot be used to generate (or filter) instances unless they are defined with the :function (or :predicate) option.
- The :read-write characteristic overrides the :read-only characteristic in roles that would otherwise inherit :read-only status from their supers or their inverses.
- The :cache-computation characteristic is used with binary relations whose definition contains the :function option. It causes computed values to be cached as ordinary role fillers, so that subsequent accesses do not require recomputation. The cached values are not truth-maintained. Retracting with forget *, or calling set-value with a null filler argument, clears the cache.
- The :hash-on-domains characteristic is used with n-ary relations. It indicates that the values satisfying the relation are to be stored as hashed tuples.
- The :non-exported characteristic prevents the name of the relation from being exported, thus overriding the :export-names-p mark on the relation's knowledge base.
- The :open-world characteristic indicates that open-world semantics are to apply to the relation, even if closed-world semantics prevail globally because the :closed-world-roles feature has been set. In Loom, relations have open-world semantics by default.
- The :closed-world characteristic indicates that closed-world semantics are to apply to the relation, even if open-world semantics are assumed globally (which is the default).
- The :monotonic characteristic indicates that when the relation, used as a role, assumes a certain value, it will always have that value. Monotonic relations are easier for Loom to truth-maintain. Also, the :monotonic characteristic can cause derived inferences to have the force of assertions.
- The :perfect characteristic indicates that if the relation, used as a role, is filled by certain instances, it always has and always will be filled by those instances. The instances must be asserted to fill the role at the time they are created. Perfect roles are not truth-maintained, and the Loom production facility does not monitor them.
Relations may also have the following Loom-assigned characteristics:
- The :system-defined characteristic indicates that the relation has been created by Loom.
- The :undefined characteristic indicates that the relation has been referenced in a definition, but has not yet been defined itself.
Value
The defined or redefined relation is returned.
Remarks
Negation and disjunction are not yet supported in relation definitions.
There should only be one is or is-primitive keyword argument.
Relations referenced in the is or is-primitive clause should not refer (directly or indirectly) to the relation being defined, since cycles are not permitted in definitions.
Currently, Loom automatically makes a relation closed-world if any of the following conditions hold:
- it is defined with the :closed-world characteristic;
- it is primitive (or defined as an inverse or composition), and it does not have the :open-world characteristic, and the global :closed-world feature is set;
- recursively, all of its definitional referents are closed.
If a relation definition refers to a concept or relation that has not yet been defined, that concept or relation is immediately created by Loom.
In normal operation, a newly-defined relation is immediately classified, provided that all the concepts and relations it references have been classified.
relation-expr ::=
RelationName |
( :AND relation-expr+ ) |
( {:DOMAIN | :RANGE} concept-expr ) |
( :DOMAINS concept-expr concept-expr+ ) |
( :INVERSE relation-expr ) |
( :COMPOSE relation-expr+ ) |
( :SATISFIES ( ?Var ?Var+ ) query-expr ) ;
The relation-forming expressions that appear in the is, is-primitive, and implies arguments above have the following syntax:
The relation-forming operators have the following semantics:
- If R = (:and R1...Rn), and tuple t is an instance of R, then t is an instance of each of the relations R1...Rn.
- If R = (:domain C), and <I1,I2> is an instance of R, then I1 is an instance of C.
- If R = (:range C), and <I1,I2> is an instance of R, then I2 is an instance of C.
- If R = (:domains C1...Cn), and <I1,...,In> is an instance of R, then for i from 1 to n-1, Ii is an instance of Ci.
- If R = (:inverse RI), and <I1,I2> is an instance of R, then <I2,I1> is an instance of RI.
- If R = (:compose R1...Rn), and <I1,In> is an instance of R, then for i from 1 to n-1, there is an <Ii,Ii+1> that is an instance of Ri.
- If R = (:satisfies (?X1...?Xn) Q), and <I1,...,In> is an instance of R, then the Loom query Q is satisfied when the variables ?X1...?Xn are bound (in order) to I1...In.
The auxiliary-definition keyword arguments have the following semantics:
- If R = :predicate ((X1...Xn) F1...Fj), and <I1,...,In> is an instance of R, then the Lisp forms F1...Fj return a non-nil value when they are evaluated with X1...Xn bound (in order) to I1...In.
- If R = :function ((X1...Xn) F1...Fj), and <I1,...,In,In+1> is an instance of R, then In+1 is a member of the values returned when the Lisp forms F1...Fn are evaluated.
Examples
(defrelation nil "Loom assigns name") ==> |R|BINARY-TUPLE_4
(defrelation r0) ==> |R|R0
(defrelation r1 :is-primitive r0)
(defrelation r2 :is (:and relative friend))
(defrelation r3 :is (:and president (:domain Corporation)))
(defrelation daughter :is (:and child (:range Female)))
(defrelation husband :is (:inverse wife))
(defrelation grandparent :is (:compose parent parent))
(defrelation r* :is (:satisfies (?x ?z)
(:or (r ?x ?z)
(:for-some ?y (:and (r ?x ?y)
(r* ?y ?z))))))
(defrelation s0 :implies (:and super (:range Concept)))
(defrelation s1 :domain Person)
(defrelation spj :arity 3 :domains (Supplier Part))
(defrelation s2 :range Number)
(defrelation s3 :predicate ((n1 n2) (> n1 n2)))
(defrelation s4 :function ((n1 n2) (+ n1 n2)))
(defrelation s5 :inheritance-link direct-subrelations
:inheritance-method nearest-neighbor)
(defrelation s6 :annotations (Verb (past "-ed")))
(defrelation s7 :identifier age-as-relation :kb user-kb)
(defrelation s8 :characteristics (:single-valued :closed-world))
See Also
Last modified: Dec 28 1995