Primitive and Defined Classes
This example demonstrates some definition facilities for primitive
and non-primitive (or defined) classes, and how such classes can
be used in queries of various kinds.
|= (defmodule "/PL-USER/CLASSES")
|MDL|/PL-USER/CLASSES
|= (in-module "/PL-USER/CLASSES")
|= (clear-module "/PL-USER/CLASSES")
|= (reset-features)
|i|()
|= (in-dialect :KIF)
:KIF
;; We start by defining a class `Person' with the already familiar
;; `happy' and `age' slots and a new slot called `friends'. Since
;; `SET' is a collection type, we can restrict a person's friends to
;; be people by supplying a parameter type `PERSON' in the STELLA
;; syntax `(<collection-type> OF <element-type>)' for parametric types:
|= (defclass PERSON (STANDARD-OBJECT)
:documentation "The class of human beings."
:slots
((happy :type BOOLEAN)
(age :type INTEGER)
(friends :type (SET OF PERSON))))
|C|PERSON
|= (defclass ARMED-SERVICE (STANDARD-OBJECT)
:documentation "The class of armed services, for example, the US Navy.")
|C|ARMED-SERVICE
;; Some instances of armed services:
|= (assert (Armed-Service US-Army))
|P|(ARMED-SERVICE US-ARMY)
|= (assert (Armed-Service US-Navy))
|P|(ARMED-SERVICE US-NAVY)
|= (assert (Armed-Service US-Airforce))
|P|(ARMED-SERVICE US-AIRFORCE)
;; A primitive subclass of `Person' (note, how individual slots can
;; also have documentation strings):
|= (defclass WARFIGHTER (PERSON)
:documentation "People involved in military operations."
:slots
((service :type ARMED-SERVICE
:documentation
"The armed service to which a warfighter belongs.")))
|C|WARFIGHTER
;; Below we define a non-primitve (or defined) subclass of `Person'.
;; One way of defining a class is to supply a set-valued term to the
;; `:definition' keyword. The KIF term used below denotes the set of
;; all people who are not warfighters. PowerLoom slightly extends the
;; KIF syntax for `setofall' to allow typed variables. In this case,
;; we could have done without the type specification, since it can be
;; inherited from the specified superclass. Alternatively, we could
;; have left out the specification of a superclass and supplied only a
;; type restriction on the variable. Note, that the definition is
;; if-and-only-if, i.e., every person who is not a warfighter is a
;; civilian and vice versa.
|= (defclass CIVILIAN (PERSON)
:documentation "People who are not warfighters."
:definition (setofall (?p PERSON) (not (Warfighter ?p))))
|C|CIVILIAN
;; Since most class definitions will use the
;; `(setofall (?<var> <super>) <predicate>)'
;; idiom, there is an abbreviated syntax that only requires the
;; specification of the qualifying predicate and fills in the
;; remaining parts automatically. The keyword for this predicate-only
;; definition is `:<=>'. For the KIF dialect, the default variable
;; used to refer to elements of the class is `?self'. The class below
;; is defined using this idiom. Note, that a class defined with the
;; `:<=>' syntax almost always needs to specify a superclass,
;; otherwise, polymorphic functions or relations (e.g., the `service'
;; slot used below) can't be found, since they are indexed on the type
;; of their first argument.
|= (defclass ARMY-PERSON (WARFIGHTER)
:<=> (= (service ?self) US-Army))
|C|ARMY-PERSON
;; If one wants to use a "self-variable" different from the default,
;; it has to be specified with the keyword `:self-variable'. The
;; definition below uses the variable `?p' to refer to elements of the
;; defined class:
|= (defclass NAVY-PERSON (WARFIGHTER)
:self-variable ?p
:<=> (= (service ?p) US-Navy))
|C|NAVY-PERSON
;; Some instances of the above classes:
|= (assert (Warfighter Buck))
|P|(WARFIGHTER BUCK)
|= (assert (= (service Buck) US-Army))
|P|(= (SERVICE BUCK) US-ARMY)
|= (assert (Person John))
|P|(PERSON JOHN)
|= (assert (member Buck (friends John)))
|P|(member BUCK (FRIENDS JOHN))
;; Note, that PowerLoom allows `in' as an alternative to the KIF `member':
|= (assert (in John (friends Buck)))
|P|(member JOHN (FRIENDS BUCK))
|= (assert (Person Judy))
|P|(PERSON JUDY)
;; Since so far we only know that Judy is a person, the following two
;; queries cannot derive any answers:
|= (ask (Warfighter Judy))
|= (ask (Civilian Judy))
;; So, let us assert that Judy is a member of the US-Navy:
|= (assert (Warfighter Judy))
|P|(WARFIGHTER JUDY)
|= (assert (= (service Judy) US-Navy))
|P|(= (SERVICE JUDY) US-NAVY)
;; Now we can successfully determine that she is a warfighter:
|= (ask (Warfighter Judy))
|L|TRUE
;; The next query does not return a result, since (currently) PowerLoom
;; does not simultaneously try to answer a query and its negation:
|= (ask (Civilian Judy))
;; However, if we ask the negated question explicitly, we get the
;; expected result:
|= (ask (not (Civilian Judy)))
|L|TRUE
;; The same should work in the opposite direction, but see the note below.
|= (assert (Civilian Blimpy))
|P|(CIVILIAN BLIMPY)
|= (ask (Civilian Blimpy))
|L|TRUE
|= (ask (Warfighter Blimpy))
;;; This does not (yet) work, since the definition of a defined class does
;;; not get inverted. The classifier will eventually fix this:
|= (ask (not (Warfighter Blimpy)))
;; Yet another warfighter:
|= (assert (Warfighter Fred))
|P|(WARFIGHTER FRED)
|= (assert (= (service Fred) US-Airforce))
|P|(= (SERVICE FRED) US-AIRFORCE)
;; Now, let us retrieve various sets of instances:
|= (retrieve all (?p PERSON))
There are 5 solutions:
#1: ?P=|i|FRED
#2: ?P=|i|BLIMPY
#3: ?P=|i|JUDY
#4: ?P=|i|JOHN
#5: ?P=|i|BUCK
|= (retrieve all (?w WARFIGHTER))
There are 3 solutions:
#1: ?W=|i|FRED
#2: ?W=|i|JUDY
#3: ?W=|i|BUCK
|= (retrieve all (?p PERSON) (not (Civilian ?p)))
There are 3 solutions:
#1: ?P=|i|FRED
#2: ?P=|i|JUDY
#3: ?P=|i|BUCK
;; This does not (yet) work (see similar `ask' problem above):
|= (retrieve all (?p PERSON) (not (Warfighter ?p)))
No solutions.
;; Retrieval of instances of defined classes:
|= (retrieve all (?p CIVILIAN))
There is 1 solution:
#1: ?P=|i|BLIMPY
|= (retrieve all (?w ARMY-PERSON))
There is 1 solution:
#1: ?W=|i|BUCK
|= (retrieve all (?w NAVY-PERSON))
There is 1 solution:
#1: ?W=|i|JUDY
;; Let us retrieve everybody who is either in the US-Navy or US-Airforce:
|= (retrieve all (?w WARFIGHTER) (or (= (service ?w) US-Navy)
(= (service ?w) US-Airforce)))
There are 2 solutions:
#1: ?W=|i|FRED
#2: ?W=|i|JUDY
;; Alternatively, this can be done like this:
|= (retrieve all (?w WARFIGHTER) (in (service ?w) (setof US-Navy US-Airforce)))
There are 2 solutions:
#1: ?W=|i|FRED
#2: ?W=|i|JUDY
;; Retrieve all people and their friends:
|= (retrieve all ((?p PERSON) (?f PERSON)) (in ?f (friends ?p)))
There are 2 solutions:
#1: ?P=|i|JOHN, ?F=|i|BUCK
#2: ?P=|i|BUCK, ?F=|i|JOHN
;; Retrieve all armed services with some members who have friends:
|= (retrieve all (?s ARMED-SERVICE)
(exists ((?p PERSON) (?w WARFIGHTER))
(and (in ?p (friends ?w))
(= (service ?w) ?s))))
There is 1 solution:
#1: ?S=|i|US-ARMY
|=
Last modified:
Nov 17, 1997