Object-Oriented Programming Support for CLASSIC - Semantic Scholar

1 downloads 0 Views 22KB Size Report
function is created (a simple Common Lisp function). This “wrapper” function calls another function with the same name concatenated with the suffix METHOD.
Object-Oriented Programming Support for CLASSIC Ralf Möller University of Hamburg, Computer Science Department Vogt-Kölln-Str. 30, D-22527 Hamburg, Germany [email protected] Abstract: The main thesis of this paper is that in order to use Description Logics in practical applications, a seamless integration with object-oriented system development methodologies must be realized. It presents an object-oriented programming layer for CLASSIC.

1. Introduction Although the logical semantics of Description Logics (DL) modeling constructs is a big plus, to ensure decidability of the subsumption problem, the expressiveness of the logical language must be limited. The consequence is that in a real application without toy problems, currently not all aspects can be formally modeled with DL constructs. This means that programming is still necessary. As a DL we use the CLASSIC system [9]. Reducing CLASSIC to practice [1] means that the DL can be integrated into the whole system development approach which, at the current state of the art, uses object-oriented modeling. In this paper, the CLOS OOP perspective will be used [10]. The paper presents an object-oriented programming layer for CLASSIC. It assumes basic knowledge about CLOS [3].1 The integration of CLASSIC and CLOS requires that generic functions and methods can be written for CLASSIC individuals. The procedural parts of an application should be able to use CLASSIC individuals just like CLOS instances. The “services” of an object are accessed only by the use of generic functions. This means that the relational part of CLASSIC should be hidden behind a functional layer because, from a software engineering point of view, dealing with individuals and relations can be quite cumbersome for at least two reasons: First of all, from a func-

1. This paper is a shortened and rewritten version of a paper presented at OOPSLA’96 [5]. The extensions for the CLASSIC system presented in this paper are available from the author [6].

tional programming point of view it is irrelevant whether a result of a function call is defined by merely looking up a set of instances in a relation table or by actually computing instances with complex algorithms and auxiliary data structures. Second, using generic accessor functions for retrieving the objects that are directly set into relation to a specific individual allows a lot of error checking code to be automatically generated. A unified interface for accessing the services that an object provides hides many representation details which are irrelevant from a more abstract perspective. For example, in a graphical user interface, the drawing function for an object might depend on the object’s concepts. User interface programming is one of the best examples for the application of object-oriented programming techniques. For rapid user interface development however, an existing UIMS must be reused. UIMSs provide powerful programming abstractions which are modeled with the object-oriented representation techniques (e.g. for CLOS the UIMS CLIM might be used [7]). There is no way to rebuild these software libraries with CLASSIC or any other DL in a reasonable time. So what can be done? Copying information associated with a DL object into a CLOS object which is used for UI part of an application is inadequate as well. Unfortunately, managing multiple “copies” of the same object is a direct contradiction to the principles of object-oriented programming. Thus, for rapid application development, object-oriented programming techniques must be made available to CLASSIC individuals. The next chapter discusses an approach that demonstrates how this can be achieved with an extension to CLASSIC that uses CLOS-like generic functions to access information about an individual. It will be shown that the implementation of CLASSIC method dispatch can be surprisingly simple.

Dieses Dokument wurde erstellt mit FrameMaker 4.0.2.

2. Integrating OOP and DL Generic functions for Description Logics have also been developed in the Loom System [2]. Method dispatch for individuals is provided by specific generic functions which dispatch on ABox objects but not on CLOS objects. Loom also supports CLOS classes for the implementation of ABox individuals but only a limited sort of reasoning is implemented on these instances (no dynamic reclassification by forward inferences). The approach presented in this paper clearly separates CLASSIC and CLOS but provides a unified way to access the services of both systems.

2.1. Accessors: A Functional Interface to a Knowledge Base CLASSIC itself provides a relational interface for retrieving and adding role fillers. Given an individual and a role, the set of fillers can be retrieved: (clfillers ). In many cases only one filler is returned. However, the result will always be a set (actually a list) and the function first must be applied to get the list element itself. To hide the repeating access to the first element, an additional function will have to be written. Furthermore, in some circumstances, it will be considered as an error if the filler is not known. Unfortunately, additional code must be written to check this. If nil (the empty set) is returned, an error is likely to occur in subsequent function calls when an individual is expected. Again, code must be written to avoid this. Instead of writing this code manually, a more general mechanism is advantageous. The way to access individuals should be declaratively defined using generic functions and corresponding low-level code for methods should be automatically generated. The declaration form define-accessors has been introduced to specify the access to individuals in that way. (define-accessors ( [ :single-value-p ] [ :error-if-null ] ) ...)

For each role description mentioned after the concept name, a reader method and a setf writer method for the generic function is gener-

ated. If they do not already exist, corresponding generic functions are automatically generated.2 The first role option :single-value-p specifies whether a single value or a set of values should be returned by the role reader function. The other option :error-if-null is used to insert code for error checking to avoid an empty set to be returned. The following example illustrates the use of defineaccessor. For concept and role declarations the KRSS syntax is used [8]. (define-primitive-concept ship classic-thing) (define-primitive-role has-position-x nil) (define-primitive-role has-position-y nil) (define-accessors ship (has-position-x position-x :single-value-p t :error-if-null t) (has-position-y position-y :single-value-p t :error-if-null t))

As in CLOS, for accessing information of an object, define-accessors defines methods for generic functions. Additional methods might be written by the programmer (e.g. around methods or after and before methods). CLASSIC individuals require another dispatch mechanism which is realized by extended generic functions.

2.2. Generic Functions and Methods The extended generic functions presented in this paper can dispatch on CLASSIC concepts or CLOS classes or both. The form define-generic-function is used to define a generic function with dispatching extended to CLASSIC individuals. The argument list of define-generic-function indicates which arguments expect CLASSIC dispatch and which arguments use standard CLOS dispatch. (define-generic-function ( ... [ ... ] ) [ ...] )

A description for a dispatching argument is a list consisting of an argument name and a dispatch indicator

2. The explicit declaration of a generic accessor function is necessary, for instance, when a special method combination that differs from the standard method combination is to be used [10].

(either :clos or :classic). Just as defgeneric from CLOS, define-generic-function also supports ordinary arguments without specializer (called other-arguments). The options for definegeneric-function are the same as for defgeneric. Note that method combinations are also supported. Methods can be defined with the form definemethod. (define-method [ ] ( ... [ ... ] ) ... )

The syntax of a dispatched argument in a method parameter list is identical to the syntax of arguments for defmethod of CLOS. The indicates the kind of method combination. In addition to names for CLOS classes, CLASSIC concept names can be used as specializers. The following declarations continue the example from above. (define-generic-function pos ((ship :classic))) (define-method pos ((s ship)) (values (position-x s) (position-y s))) (define-generic-function draw ((ship :classic) (stream :clos))) (define-method draw ((ship ship) (stream graphic-stream)) ...)

Ship is a CLASSIC concept (see above) and graphic-stream is a CLOS class.

2.3. Individual Creation and Initialization Creating individuals using the primitives supplied by CLASSIC (or KRSS) is somewhat crude. From a software engineering point of view, a protocol for individual initialization is needed. For individual creation, a function create-individual with parameters (concept-name &optional (indname (gensym)) &rest initargs) has been supplied.

function can be defined as follows (compare this to initialize-instance from CLOS). (define-method initialize-individual :after ((ind ) &rest initargs) ...)

Initialization arguments can also be given to create-individual. The list of “initargs” is a sequence of role names and corresponding sets of initial fillers.3

2.4. Computation of the Concept Precedence List The TBox defines a partial order relation between concepts (subsumption relation). In order to define how method dispatch is handled, the multiple inheritance lattice must be serialized by a concept precedence list which represents a total order between concepts. A concept precedence list is used for the same purposes as a CLOS class precedence list, it defines how an effective method for a specific function call is computed (see the detailed introduction in [3]). A valid concept precedence list is any total ordering that obeys all partial orders defined by the TBox. However, by this requirement only a small set of constraints are defined. There are still several different approaches to serialize a concept lattice. In CLOS the notational order of superclasses in a class definition defines a set of additional order constraints. However, from the viewpoint of Description Logics, the direct superconcepts (the least general subsumers) are unordered. Therefore, in the approach presented in this paper, the relation of parents with respect to method dispatch is left undefined. Procedural code must not depend on any notational order between concept parents.

3. Implementation of Method Dispatch A straightforward implementation for method dispatch with individuals can be provided. CLASSIC dispatch is reduced to CLOS dispatch.

When an individual is created with create-individual, the generic function initialize-individual is automatically called. A method for this 3. The set of initial fillers for a role is represented by a list. If a non-list is used, a singleton list is automatically created.

3.1. Reducing CLASSIC dispatch to CLOS dispatch The implementation of generic functions and method dispatch for CLASSIC is quite simple.4 The form define-generic-function is used to declare which parameters are handled as ordinary CLOS instances and which parameters are CLASSIC individuals. As a side effect of this declaration, a new function is created (a simple Common Lisp function). This “wrapper” function calls another function with the same name concatenated with the suffix METHOD. This function internally represents the generic function and implements the method dispatch. For instance, the macro form: (define-generic-function f ((a :classic) (b :clos)))

expands into (PROGN (SETF (GET 'F :ARGUMENT-SIGNATURE) '(:CLASSIC :CLOS)) (DEFGENERIC F-METHOD (A #:TYPE6806 B)) (DEFUN F (A B) (FUNCALL (FUNCTION F-METHOD) A (COMPUTE-TYPE-ARG A) B)))

(DEFMETHOD F-METHOD ((A T) (#:TYPE6807 ) (B )) ...)

The method is defined for the “real” generic function with suffix METHOD. In the example, the specializer ship has been “moved” to the second parameter. For the original parameter no specializer is defined. It specializes on t, the most general type in Common Lisp, and therefore, this parameter has no “discriminating power”. Nevertheless, the original instance must be passed as an argument. In the body of the method, the CLASSIC individual must be bound to IND. The corresponding additional parameter is used only for dispatching (its system-generated name is uninterned). Since the substitute specializer must be a CLOS class (here the class A is used), for every named CLASSIC concept a corresponding CLOS class is automatically created. The set of superclasses of such a class is computed on the basis of the TBox classification process. Note that the list of superclasses of a class might dynamically change when a defined concept is automatically inserted into the subsumption hierarchy by TBox classification.

expands into

The function compute-type-arg (see the expansion of define-generic-function) computes a CLOS placeholder for a CLASSIC individual. The idea behind compute-type-arg is to get the concept of a CLASSIC individual (classic:cl-indparents), to derive a corresponding CLOS class, and to use the class prototype of this class. One problem is that a CLASSIC individual may be subsumed by more than one named concept, i.e. classic:clind-parents returns a list of concepts. When this happens, a new anonymous CLOS class with corresponding superclasses must be created on the fly. The prototype object of this class will then be used. A memoization scheme (with a hash-table *classtable*) is used to avoid inflationary class creation.

4. The main idea is inspired by the implementation of presentation type dispatch in CLIM (define-presentationgeneric-function and define-presentationmethod).

(defun compute-type-arg (ind) (or (classic::di-clos-instance ind) (let ((class-names (mapcar #'classic:cl-name (classic:cl-ind-parents ind)))) (if (null (rest class-names)) (find-class-prototype

The internal function F-METHOD is applied to the same arguments as the wrapper function, but for each parameter, which uses CLASSIC dispatch, an additional parameter is inserted (for a this will be #:type6806). For each CLASSIC individual, an associated CLOS instance is computed with compute-type-arg. In a method definition, the additional arguments are used for the “real dispatching”. Note that normal CLOS arguments are treated as usual. The method definition (define-method f ((a ) (b )) ...)

(find-class (first class-names))) (let ((class (gethash class-names *class-table*))) (if class (find-class-prototype class) (let* ((class-name (gensym)) (class (find-class class-name))) (ensure-clos-class :name class-name :superclasses class-names) (setf (classic::di-clos-instance ind) (find-class-prototype (find-class type-name))) (setf (gethash class-names *class-table*) class) (find-class-prototype class)))))))

With access to the internal data structures of CLASSIC (classic::di-clos-instance), an individual can be directly associated with its CLOS counterpart, i.e. the procedure compute-type-arg is used only when the individual is reclassified. CLASSIC has been extended to reset the association between an individual and its CLOS representative when the individual is reclassified. The definition of compute-type-arg indicates that the straightforward implementation of CLASSIC dispatch comes at a certain cost. In addition to static costs for the definition of CLOS classes for named CLASSIC concepts, there are some initial dynamic costs:

• some calls to retrieval functions (classic:clname, classic:cl-ind-parents),

• a complex hashing operation over a list of symbols,

• possibly a dynamic creation of a CLOS class, • the access to the CLOS class prototype, • and an additional CLOS dispatch step for the substitute argument. Furthermore, a lot of garbage is created (mapcar). Measurements on a Symbolics MacIvory-Model-3 indicate that a dispatched access to a relation with a generic function created by define-accessors takes less than one millisecond. This is approximately

three times slower than directly using CLASSIC’s retrieval functions on the same processor.

4. Summary The main thesis of this paper is that in order to use Description Logics in practical applications, a seamless integration with object-oriented system development methodologies must be realized. Extended generic functions and multimethods with CLASSIC dispatch not only allow an incremental way of software definition. In addition to this, they can even been seen as a form of defining assertions that enforce a safer system architecture also for the procedural parts (the same holds for CLOS [4]).

References [1]

Brachman, R.J., “Reducing” CLASSIC to Practice: Knowledge Representation Theory Meets Reality, in: Proc. KR’92 Principles of Knowledge Representation and Reasoning, Nebel, B., Rich, C., Swartout, W. (Eds.) Morgan Kaufmann Publ., 1992, pp. 247-258. [2] Brill, D., Loom Reference Manual, Version 2.0, USC/ISI, 4676 Admiralty Way, Marina del Rey, CA 90292, December, 1993. [3] Keene, S.E., Object-Oriented Programming in CLOS: A Programmer’s Guide to CLOS, AddisonWesley, 1989. [4] Lamping, J., Abadi, M., Methods as Assertions, Xerox Palo Alto Research Center, available as: ftp://parcftp.xerox.com/pub/ openimplementations/methods-asassertions.ps.Z. [5] Möller, R., A Functional Layer for Description Logics: Knowledge Representation Meets ObjectOriented Programming, in: Proc. OOPSLA’96, in press. [6] Möller, R., Extending CLASSIC with Generic Functions and Methods, http://kogswww.informatik.uni-hamburg.de/ ~moeller/, 1996. [7] Möller, R., User Interface Management Systems: The CLIM Perspective, http://kogswww.informatik.uni-hamburg.de/ ~moeller/uims-clim/clim-intro.html, 1996. [8] Patel-Schneider, P.F., Swartout, B., Description Logic Specification from the KRSS Effort, ksl.stanford.edu:/pub/knowledgesharing/papers/dl-spec.ps. [9] Resnick, L.A., Borgida, A., Brachman, R.J., McGuiness, D.L., Patel-Schneider, P.F., Zalondek, K.C., CLASSIC Description and Reference Manual for the Common Lisp Implementation, Version 2.2, 1993. [10] Steele, G.L., Common Lisp - The Language, Second Edition, Digital Press, 1990.

Suggest Documents