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

|= 

Information Sciences Institute ISI Intelligent Systems Division PowerLoom Home Page
Last modified: Nov 17, 1997