OWL inference engine using XSLT and JESS

Authors:  Dr. Fabien L. Gandon (Fabien.Gandon@cs.cmu.edu), Dr. Norman M. Sadeh (Norman.Sadeh@cs.cmu.edu)
Copyright: See the bottom of this page.
Date: July 16, 2003
Configuration used:
Sun JDK 1.4, XSLT 1.0,JESS 6

 This page contains source code and instructions to load OWL ontologies and annotations into a JESS knowledge base. Using JESS, an open-source Java-based inference engine, one can infer new knowledge and solve queries. In the following we suppose that you are familiar with:

 The source files provided herein are duly commented and should be self-explanatory. These files are being made available as part of the DAML initiative in an effort to promote broader, more rapid adoption of the semantic Web. No warranty is being made, whatsoever, on the reliability or correctness of this implementation. Results obtained by running this implementation on the OWL test-cases are available onlineThe code provided herein has been successfully used in the myCampus project, a semantic Web environment for context awareness where agents automatically access and reason about the context of their users.

 Overview

  The code provided herein will help you load OWL ontologies and annotations into JESS, an inference engine that uses a CLIPS-like language. Using JESS you will then be able to reason about these ontologies and annotations. The code is organized into three main files:

 As shown in figure 1, these three files are used to provide the basis of an OWL inference engine based on JESS and they can be complemented with other stylesheets and other sources to add assertions and rules to the base (e.g. formal definitions, queries in QOWL, security enforcement, etc.)

Principle behind the engine

Figure 1. Overall architecture

 Comments on the code

  Below are further details on each of the three files.

 OWL Meta-model

  First, the JESS code of  the OWL meta-model is given in figure 2:

(1)
;;; RDFS ans OWL Meta model ----------------------------------------------------------------

;;; Declaring the triple template ---------------------------------
(deftemplate triple "Template representing a triple"
 (slot predicate (default ""))
 (slot subject   (default ""))
 (slot object    (default ""))
)
(2)
;;; Declaring facts of the meta-model of OWL ----------------------
(deffacts OWLModel "Facts of the meta-model of RDFS and OWL"

  ;;; Resource is a Class
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2000/01/rdf-schema#Resource")
   (object    "http://www.w3.org/2002/07/owl#Class")
  )
 
  ;;; Class is a subtype of Resource
  (triple
   (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf")
   (subject   "http://www.w3.org/2002/07/owl#Class")
   (object    "http://www.w3.org/2000/01/rdf-schema#Resource")
  )
 
  ;;; Class is a Class
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#Class")
   (object    "http://www.w3.org/2002/07/owl#Class")
  )

  ;;; owl:Thing is a Class
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#Thing")
   (object    "http://www.w3.org/2002/07/owl#Class")
  )

  ;;; owl:Nothing is a Class
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#Nothing")
   (object    "http://www.w3.org/2002/07/owl#Class")
  )

  ;;; Property is a Class
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")
   (object    "http://www.w3.org/2002/07/owl#Class")
  )
 
  ;;; Domain is a Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2000/01/rdf-schema#domain")
   (object    "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")
  )
 
  ;;; Range is a Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2000/01/rdf-schema#range")
   (object    "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")
  )
 
  ;;; 'Data Type Property' is a Class
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#DatatypeProperty")
   (object    "http://www.w3.org/2002/07/owl#Class")
  )
 
  ;;; 'Data Type Property' is a subtype of Property
  (triple
   (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf")
   (subject   "http://www.w3.org/2002/07/owl#DatatypeProperty")
   (object    "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")
  )
 
  ;;; 'Object Property' is a Class
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#ObjectProperty")
   (object    "http://www.w3.org/2002/07/owl#Class")
  )
 
  ;;; 'Object Property' is a subtype of Property
  (triple
   (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf")
   (subject   "http://www.w3.org/2002/07/owl#ObjectProperty")
   (object    "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")
  )
 
  ;;; Type is an 'Object Property'
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (object    "http://www.w3.org/2002/07/owl#ObjectProperty")
  )
 
  ;;; 'Transitive Property' is a subtype of ObjectProperty
  (triple
   (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf")
   (subject   "http://www.w3.org/2002/07/owl#TransitiveProperty")
   (object    "http://www.w3.org/2002/07/owl#ObjectProperty")
  )
 
  ;;; 'Sub Class Of' is a 'Transitive Property'
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2000/01/rdf-schema#subClassOf")
   (object    "http://www.w3.org/2002/07/owl#TransitiveProperty")
  )
 
  ;;; 'Sub Property Of' is a 'Transitive Property'
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2000/01/rdf-schema#subPropertyOf")
   (object    "http://www.w3.org/2002/07/owl#TransitiveProperty")
  )
 
  ;;; 'Symmetric Property' is a subtype of ObjectProperty
  (triple
   (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf")
   (subject   "http://www.w3.org/2002/07/owl#SymmetricProperty")
   (object    "http://www.w3.org/2002/07/owl#ObjectProperty")
  )

  ;;; 'Inverse Of' is a Symmetric Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#inverseOf")
   (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
  )

  ;;; 'Equivalent Property' is a Symmetric Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#equivalentProperty")
   (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
  )

  ;;; 'Equivalent Class' is a Symmetric Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#equivalentClass")
   (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
  )

  ;;; 'Same Individual' is a Symmetric Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#sameIndividualAs")
   (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
  )

  ;;; 'Complement Of' is a Symmetric Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#complementOf")
   (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
  )

  ;;; 'Different From' is a Symmetric Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#differentFrom")
   (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
  )

  ;;; 'Disjoint With' is a Symmetric Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#disjointWith")
   (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
  )


  ;;; 'Equivalent Property' is a Transitive Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#equivalentProperty")
   (object    "http://www.w3.org/2002/07/owl#TransitiveProperty")
  )

  ;;; 'Equivalent Class' is a Transitive Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#equivalentClass")
   (object    "http://www.w3.org/2002/07/owl#TransitiveProperty")
  )

  ;;; 'Same Individual' is a Transitive Property
  (triple
   (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
   (subject   "http://www.w3.org/2002/07/owl#sameIndividualAs")
   (object    "http://www.w3.org/2002/07/owl#TransitiveProperty")
  )

 
  ;;; 'Functional Property' is a subtype of Property
  (triple
   (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf")
   (subject   "http://www.w3.org/2002/07/owl#FunctionalProperty")
   (object    "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")
  )
 
  ;;; 'Inverse Functional Property' is a subtype of Property
  (triple
   (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf")
   (subject   "http://www.w3.org/2002/07/owl#InverseFunctionalProperty")
   (object    "http://www.w3.org/1999/02/22-rdf-syntax-ns#Property")
  )
 
  ;;; sameAs is equivalent to sameIndividualAs
   (triple
           (predicate "http://www.w3.org/2002/07/owl#equivalentProperty")
           (subject   "http://www.w3.org/2002/07/owl#sameAs")
           (object    "http://www.w3.org/2002/07/owl#sameIndividualAs")
   )
)
(3)
;;; Adding rules for forward completion of the base ----------------------------

;;; Propagate transitive properties
(defrule transitivity (declare (salience 100))
   (triple (predicate ?p) (subject ?x) (object ?y))
   (triple (predicate ?p) (subject ?z) (object ?x))
   (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject   ?p)
           (object    "http://www.w3.org/2002/07/owl#TransitiveProperty")
   )
   =>
   (assert (triple (predicate ?p) (subject ?z) (object ?y)))
)

;;; Complete typing of instances of objects with inherited types
(defrule subClassOf_transitive_typing  (declare (salience 100))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf") (subject ?y) (object ?z))
   (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?x) (object ?y))
   (not (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?x) (object ?z)))
   =>
   (assert (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?x) (object ?z)))
)

;;; Complete typing of instances of properties with inherited types
(defrule subPropertyOf_transitive_typing  (declare (salience 100))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subPropertyOf") (subject ?y) (object ?z))
   (triple (predicate ?y) (subject ?a) (object ?b))
   (not (triple (predicate ?z) (subject ?a) (object ?b)))
   =>
   (assert (triple (predicate ?z) (subject ?a) (object ?b)))
)

;;; Default behavior for signature propagation
(defrule rdfs_domain_signature_transitivity  (declare (salience 100))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subPropertyOf") (subject ?x) (object ?y))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#domain") (subject ?y) (object ?z))
   (not (triple (predicate "http://www.w3.org/2000/01/rdf-schema#domain") (subject ?x) (object ?z)))
   =>
   (assert (triple (predicate "http://www.w3.org/2000/01/rdf-schema#domain") (subject ?x) (object ?z)))
)

(defrule rdfs_range_signature_transitivity  (declare (salience 100))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subPropertyOf") (subject ?x) (object ?y))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#range") (subject ?y) (object ?z))
   (not (triple (predicate "http://www.w3.org/2000/01/rdf-schema#range") (subject ?x) (object ?z)))
   =>
   (assert (triple (predicate "http://www.w3.org/2000/01/rdf-schema#range") (subject ?x) (object ?z)))
)

;;; Complete with instances of symmetric properties
(defrule symmetry (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject   ?p)
           (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
   )
   (triple (predicate ?p) (subject ?x) (object ?y))
   (not (triple (predicate ?p) (subject ?y) (object ?x)))
   =>
   (assert (triple (predicate ?p) (subject ?y) (object ?x)))
)

;;; Complete with instances of inverse properties
(defrule inverse (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#inverseOf")
           (subject   ?p1)
           (object    ?p2)
   )
   (triple (predicate ?p1) (subject ?x) (object ?y))
   (not (triple (predicate ?p2) (subject ?y) (object ?x)))
   =>
   (assert (triple (predicate ?p2) (subject ?y) (object ?x)))
)

;;; The inverse property of a functional property is an inverse functional property
(defrule inverse-of-functional (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#inverseOf")
           (subject   ?p1)
           (object    ?p2)
   )
   (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject ?p1)
           (object "http://www.w3.org/2002/07/owl#FunctionalProperty")
   )
   (not (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject ?p2)
           (object "http://www.w3.org/2002/07/owl#InverseFunctionalProperty")
         )
   )
   =>
   (assert
     (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject ?p2)
           (object "http://www.w3.org/2002/07/owl#InverseFunctionalProperty")
     )
   )
)

;;; The inverse property of an inverse functional property is a functional property
(defrule inverse-of-inverse-functional (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#inverseOf")
           (subject   ?p1)
           (object    ?p2)
   )
   (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject ?p1)
           (object "http://www.w3.org/2002/07/owl#InverseFunctionalProperty")
   )
   (not (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject ?p2)
           (object "http://www.w3.org/2002/07/owl#FunctionalProperty")
         )
   )
   =>
   (assert
     (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject ?p2)
           (object "http://www.w3.org/2002/07/owl#FunctionalProperty")
     )
   )
)

;;; Complete with instances of equivalent classes
(defrule equivalent-class-one (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#equivalentClass")
           (subject   ?t1)
           (object    ?t2)
   )
   (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?x) (object ?t1))
   (not (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?x) (object ?t2)))
   =>
   (assert (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?x) (object ?t2)))
)

;;; Complete hierarchy with equivalent classes: if t1 <=> t2 then t1 < t2
;;; by symmetry we also get t2 < t1
(defrule equivalent-class-two (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#equivalentClass")
           (subject   ?t1)
           (object    ?t2)
   )
   (not (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf") (subject ?t1) (object ?t2)))
   =>
   (assert (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf") (subject ?t1) (object ?t2)))
)

;;; Members of disjoint classes are different instances
(defrule members-of-disjoint-classes-are-different (declare (salience 100))
   (triple (predicate "http://www.w3.org/2002/07/owl#disjointWith") (subject   ?c1) (object    ?c2))
   (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?o1) (object ?c1))
   (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?o2) (object ?c2))
   (test (neq ?c1 ?c2))
   (not (triple (predicate "http://www.w3.org/2002/07/owl#differentFrom") (subject ?o1) (object ?o2)))
   =>
   (assert (triple (predicate "http://www.w3.org/2002/07/owl#differentFrom") (subject ?o1) (object ?o2)))
)

;;; Two classes subsuming each other are equivalent
(defrule two-classes-subsuming-each-other-are-equivalent (declare (salience 100))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf") (subject ?c1) (object ?c2))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subClassOf") (subject ?c2) (object ?c1))
   (test (neq ?c1 ?c2))
   (not (triple (predicate "http://www.w3.org/2002/07/owl#equivalentClass") (subject ?c1) (object ?c2)))
   =>
   (assert (triple (predicate "http://www.w3.org/2002/07/owl#equivalentClass") (subject ?c1) (object ?c2)))
)

;;; Complete instances with properties of equivalent instances
(defrule equivalent-instance-one (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#sameIndividualAs")
           (subject   ?s1)
           (object    ?s2)
   )
   (triple (predicate ?p) (subject ?s1) (object ?o))
   (not (triple (predicate ?p) (subject ?s2) (object ?o)))
   =>
   (assert (triple (predicate ?p) (subject ?s2) (object ?o)))
)

(defrule equivalent-instance-two (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#sameIndividualAs")
           (subject   ?o1)
           (object    ?o2)
   )
   (triple (predicate ?p) (subject ?s) (object ?o1))
   (not (triple (predicate ?p) (subject ?s) (object ?o2)))
   =>
   (assert (triple (predicate ?p) (subject ?s) (object ?o2)))
)

;;; Complete instances of properties with instances of equivalent properties
(defrule equivalent-property-one (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#equivalentProperty")
           (subject   ?p1)
           (object    ?p2)
   )
   (triple (predicate ?p1) (subject ?s) (object ?o))
   (not (triple (predicate ?p2) (subject ?s) (object ?o)))
   =>
   (assert (triple (predicate ?p2) (subject ?s) (object ?o)))
)

;;; Complete hierarchy with equivalent properties: if p1 <=> p2 then p1 < p2
;;; by symmetry we also get p2 < p1
(defrule equivalent-property-two (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/2002/07/owl#equivalentProperty")
           (subject   ?p1)
           (object    ?p2)
   )
   (not (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subPropertyOf") (subject ?p1) (object ?p2)))
   =>
   (assert (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subPropertyOf") (subject ?p1) (object ?p2)))
)

;;; Two properties subsuming each other are equivalent
(defrule two-properties-subsuming-each-other-are-equivalent (declare (salience 100))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subPropertyOf") (subject ?p1) (object ?p2))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#subPropertyOf") (subject ?p2) (object ?p1))
   (test (neq ?p1 ?p2))
   (not (triple (predicate "http://www.w3.org/2002/07/owl#equivalentProperty") (subject ?p1) (object ?p2)))
   =>
   (assert (triple (predicate "http://www.w3.org/2002/07/owl#equivalentProperty") (subject ?p1) (object ?p2)))
)

;;; Derive equivalence from multiple instantiations of a functional property with the same subject
(defrule functional-property-equivalence (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject   ?p)
           (object    "http://www.w3.org/2002/07/owl#FunctionalProperty")
   )
   (triple (predicate ?p) (subject ?s) (object ?o1))
   (triple (predicate ?p) (subject ?s) (object ?o2))
   (test (neq ?o1 ?o2))
   (not (triple (predicate "http://www.w3.org/2002/07/owl#sameIndividualAs") (subject ?o1) (object ?o2)))
   =>
   (assert (triple (predicate "http://www.w3.org/2002/07/owl#sameIndividualAs") (subject ?o1) (object ?o2)))
)

;;; Derive equivalence from multiple instantiations of inverse functional property with the same object
(defrule inverse-functional-property-equivalence (declare (salience 100))
   (triple
           (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
           (subject   ?p)
           (object    "http://www.w3.org/2002/07/owl#InverseFunctionalProperty")
   )
   (triple (predicate ?p) (subject ?s1) (object ?o))
   (triple (predicate ?p) (subject ?s2) (object ?o))
   (test (neq ?s1 ?s2))
   (not (triple (predicate "http://www.w3.org/2002/07/owl#sameIndividualAs") (subject ?s1) (object ?s2)))
   =>
   (assert (triple (predicate "http://www.w3.org/2002/07/owl#sameIndividualAs") (subject ?s1) (object ?s2)))
)

;;; Complete the extension of the Thing class with all other classes
(defrule everything-is-a-thing  (declare (salience 100))
   (triple (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") (subject ?s) (object ?o))
   (not (triple
          (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
          (subject ?s) (object "http://www.w3.org/2002/07/owl#Thing")
        )
   )
   =>
   (assert (triple
          (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
          (subject ?s) (object "http://www.w3.org/2002/07/owl#Thing")
        )
   )
)

;;; A property inverse of it-self is symmetric
(defrule a-property-inverse-of-it-self-is-symmetric (declare (salience 100))
   (triple (predicate "http://www.w3.org/2000/01/rdf-schema#inverseOf") (subject ?p) (object ?p))
   (not    (triple
             (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
             (subject   ?p)
             (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
           )
   )
   =>
   (assert (triple
             (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
             (subject   ?p)
             (object    "http://www.w3.org/2002/07/owl#SymmetricProperty")
           )
   )
)

(4)
;;; Adding rule for coherence checking  ----------------------------------

;;; Check the extension of Nothing is empty
(defrule nothing-is-nothing  (declare (salience 100))
   (triple
          (predicate "http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
          (subject ?s) (object "http://www.w3.org/2002/07/owl#Nothing")
        )
   =>
   (printout t "Error: " ?s " was found to be of type Nothing, which is not possible." crlf)
)

;;; A resource cannot be different from it-self
(defrule different-from-it-self  (declare (salience 100))
   (triple (predicate "http://www.w3.org/2002/07/owl#differentFrom") (subject ?o) (object ?o))
   =>
   (printout t "Error: " ?o " was found to be different from it-self, which is not possible." crlf)
)

;;; Two resources cannot be different and identical
(defrule different-and-identical  (declare (salience 100))
   (triple (predicate "http://www.w3.org/2002/07/owl#differentFrom") (subject ?o1) (object ?o2))
   (triple (predicate "http://www.w3.org/2002/07/owl#sameIndividualAs") (subject ?o1) (object ?o2))
   (test (neq ?o1 ?o2))
   =>
   (printout t "Error: " ?o1 " and " ?o2 " were found to be different and the same, which is not possible." crlf)
)

;;; A class cannot be disjoint with it-self
(defrule disjoint-with-it-self  (declare (salience 100))
   (triple (predicate "http://www.w3.org/2002/07/owl#disjointWith") (subject ?c) (object ?c))
   =>
   (printout t "Error: " ?c " was found to be disjoint with it-self, which is not possible." crlf)
)

;;; Two classes cannot be disjoint and equivalent
(defrule disjoint-and-equivalent  (declare (salience 100))
   (triple (predicate "http://www.w3.org/2002/07/owl#disjointWith") (subject ?c1) (object ?c2))
   (triple (predicate "http://www.w3.org/2002/07/owl#equivalentClass") (subject ?c1) (object ?c2))
   (test (neq ?c1 ?c2))
   =>
   (printout t "Error: " ?c1 " and " ?c2 " were found to be disjoint and equivalent, which is not possible." crlf)
)
Figure 2. JESS code for the meta-model of OWL

 Ontology stylesheet

  Then comes the stylesheet to transform an ontology into a set of triples based on the pre-loaded OWLmeta-model:
(1)
<!DOCTYPE uridef[
  <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns">
  <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema">
  <!ENTITY owl "http://www.w3.org/2002/07/owl">
  <!ENTITY xsd "http://www.w3.org/2000/10/XMLSchema">
  <!ENTITY nbsp "&#160;">
]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
 xmlns:rdf="&rdf;#"
 xmlns:rdfs="&rdfs;#"
 xmlns:owl="&owl;#"
 xmlns:xsd="&xsd;#"
 >
  <!-- get the namespace of the ontology e.g. 'http://sadehlab.cs.cmu.edu/mycampus#' -->
  <xsl:param name='namespace' select="concat(/rdf:RDF/@xml:base,'#')"/>
 
  <xsl:output method="text" media-type="text/plain" encoding="ISO-8859-1" omit-xml-declaration="yes"/>

  <xsl:template match="/"><xsl:apply-templates /></xsl:template>
  <xsl:template match="rdf:RDF"><xsl:apply-templates /></xsl:template>
 
(2)
 <!-- transform ontology into Jess triples - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <!-- descriptions are ignored -->
  <xsl:template match="rdf:Description"><xsl:apply-templates /></xsl:template>

  <!-- declare classes -->
  <xsl:template match="owl:Class">
(assert
 (triple
  (predicate "&rdf;#type")
  (subject   "<xsl:call-template name="get-ID"/>")
  (object    "&owl;#Class")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare types -->
  <xsl:template match="rdf:type">
(assert
 (triple
  (predicate "&rdf;#type")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>


  <!-- declare sub classes -->
  <xsl:template match="rdfs:subClassOf">
(assert
 (triple
  (predicate "&rdfs;#subClassOf")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare complementOf -->
  <xsl:template match="owl:complementOf">
(assert
 (triple
  (predicate "&owl;#complementOf")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare sameAs -->
  <xsl:template match="owl:sameAs">
(assert
 (triple
  (predicate "&owl;#sameAs")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare sameIndividualAs -->
  <xsl:template match="owl:sameIndividualAs">
(assert
 (triple
  (predicate "&owl;#sameIndividualAs")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare differentFrom -->
  <xsl:template match="owl:differentFrom">
(assert
 (triple
  (predicate "&owl;#differentFrom")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare disjointWith -->
  <xsl:template match="owl:disjointWith">
(assert
 (triple
  (predicate "&owl;#disjointWith")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare equivalentClass -->
  <xsl:template match="owl:equivalentClass">
(assert
 (triple
  (predicate "&owl;#equivalentClass")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>


  <!-- declare Properties -->
  <xsl:template match="rdf:Property">
(assert
 (triple
  (predicate "&rdf;#type")
  (subject   "<xsl:call-template name="get-ID"/>")
  (object    "&rdf;#Property")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare Object Properties -->
  <xsl:template match="owl:ObjectProperty">
(assert
 (triple
  (predicate "&rdf;#type")
  (subject   "<xsl:call-template name="get-ID"/>")
  (object    "&owl;#ObjectProperty")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare Functional Properties -->
  <xsl:template match="owl:FunctionalProperty">
(assert
 (triple
  (predicate "&rdf;#type")
  (subject   "<xsl:call-template name="get-ID"/>")
  (object    "&owl;#FunctionalProperty")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare Inverse Functional Properties -->
  <xsl:template match="owl:InverseFunctionalProperty">
(assert
 (triple
  (predicate "&rdf;#type")
  (subject   "<xsl:call-template name="get-ID"/>")
  (object    "&owl;#InverseFunctionalProperty")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare Symmetric Properties -->
  <xsl:template match="owl:SymmetricProperty">
(assert
 (triple
  (predicate "&rdf;#type")
  (subject   "<xsl:call-template name="get-ID"/>")
  (object    "&owl;#SymmetricProperty")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare Datatype Properties -->
  <xsl:template match="owl:DatatypeProperty">
(assert
 (triple
  (predicate "&rdf;#type")
  (subject   "<xsl:call-template name="get-ID"/>")
  (object    "&owl;#DatatypeProperty")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare sub properties -->
  <xsl:template match="rdfs:subPropertyOf">
(assert
 (triple
  (predicate "&rdfs;#subPropertyOf")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare inverseOf -->
  <xsl:template match="owl:inverseOf">
(assert
 (triple
  (predicate "&owl;#inverseOf")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare equivalentProperty -->
  <xsl:template match="owl:equivalentProperty">
(assert
 (triple
  (predicate "&owl;#equivalentProperty")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare domain -->
  <xsl:template match="rdfs:domain">
(assert
 (triple
  (predicate "&rdfs;#domain")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

  <!-- declare range -->
  <xsl:template match="rdfs:range">
(assert
 (triple
  (predicate "&rdfs;#range")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-range-ID"/>")
 )
)<xsl:apply-templates /></xsl:template>

(3)
  <!-- named templates - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 
  <!-- normalize local URIs -->
  <xsl:template name="local-ID" >
    <xsl:param name="id" />
    <xsl:choose>
      <xsl:when test="starts-with($id,'#')">
        <xsl:value-of select="concat($namespace,substring-after($id,'#'))"/>
      </xsl:when>
      <xsl:when test="contains($id,'/') or contains($id,'#') or contains($id,':')">
        <xsl:value-of select="$id" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($namespace,$id)"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- get ID or About of the current node -->
  <xsl:template name="get-ID" >
    
    <xsl:choose>
      <xsl:when test="@rdf:ID">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="@rdf:ID"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:when test="@rdf:about">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="@rdf:about"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($namespace,generate-id(.))"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
 
  <!-- get the ID or About of the parent node -->
  <xsl:template name="get-father-ID" >
    
    <xsl:choose>
      <xsl:when test="../@rdf:ID">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="../@rdf:ID"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:when test="../@rdf:about">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="../@rdf:about"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($namespace,generate-id(..))"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
 
  <!-- get the ID or About of the first child  -->
  <xsl:template name="get-range-ID" >
    <xsl:choose>
      <xsl:when test="@rdf:resource">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="@rdf:resource"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:when test="*[position()=1]/@rdf:ID">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="*[position()=1]/@rdf:ID"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:when test="*[position()=1]/@rdf:about">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="*[position()=1]/@rdf:about"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($namespace,generate-id(*[position()=1]))"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
   
  <xsl:template match="*" />
 
</xsl:stylesheet>
Figure 3. Stylesheet used to transform an ontology in OWL into instances of the template for triples in JESS


 Annotation stylesheet

  Finally comes the stylesheet to transform an annotation into a set of triples supposing that the OWL meta-model and the ontologies used by the annotation have been pre-loaded:

(1)
<!DOCTYPE uridef[
  <!ENTITY rdf "http://www.w3.org/1999/02/22-rdf-syntax-ns">
  <!ENTITY rdfs "http://www.w3.org/2000/01/rdf-schema">
  <!ENTITY owl "http://www.w3.org/2002/07/owl">
  <!ENTITY xsd "http://www.w3.org/2000/10/XMLSchema">
  <!ENTITY nbsp "&#160;">
]>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
 xmlns:rdf="&rdf;#"
 xmlns:rdfs="&rdfs;#"
 xmlns:owl="&owl;#"
 xmlns:xsd="&xsd;#"
 >
  <!-- get the namespace of the annotation e.g. http://www-2.cs.cmu.edu/Web/People/fgandon# -->
  <xsl:param name='namespace' select="concat(/rdf:RDF/@xml:base,'#')"/>
 
  <xsl:output method="text" media-type="text/plain" encoding="ISO-8859-1" omit-xml-declaration="yes"/>

  <xsl:template match="/"><xsl:apply-templates /></xsl:template>
  <xsl:template match="rdf:RDF"><xsl:apply-templates /></xsl:template>
 
(2)
 <!-- named templates - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

  <!-- process an instance of a class -->
  <xsl:template name="process-class-instance" >
(assert
  (triple
    (predicate "&rdf;#type")
    (subject   "<xsl:call-template name="get-ID"/>")
    (object    "<xsl:value-of select="concat(namespace-uri(.),local-name(.))"/>")
  )
)
  <xsl:for-each select="*"><xsl:call-template name="process-property-instance"/></xsl:for-each>
  </xsl:template>

  <!-- process an instance of a property -->
  <xsl:template name="process-property-instance" >
    <xsl:choose>
      <xsl:when test='count(*)=1'> <!-- has element nodes as children -->
        <xsl:call-template name="process-objectproperty-instance"/>
      </xsl:when>
      <xsl:when test='count(text())=1'> <!-- has text nodes as children -->
        <xsl:call-template name="process-dataproperty-instance"/>
      </xsl:when>
      <xsl:when test='@rdf:resource'> <!-- has a reference -->
        <xsl:call-template name="process-referenceproperty-instance"/>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

  <!-- process an instance of a objectproperty -->
  <xsl:template name="process-objectproperty-instance" >
(assert
 (triple
  (predicate "<xsl:value-of select="concat(namespace-uri(.),local-name(.))"/>")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="get-child-ID"/>")
 )
) <xsl:for-each select="*[position()=1]"><xsl:call-template name="process-class-instance"/></xsl:for-each>
  </xsl:template>

  <!-- process an instance of a dataproperty -->
  <xsl:template name="process-dataproperty-instance" >
(assert
 (triple
  (predicate "<xsl:value-of select="concat(namespace-uri(.),local-name(.))"/>")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:value-of select="normalize-space(.)"/>")
 )
)
  </xsl:template>

  <!-- process an instance of a property referencing a resource in its range-->
  <xsl:template name="process-referenceproperty-instance" >
(assert
 (triple
  (predicate "<xsl:value-of select="concat(namespace-uri(.),local-name(.))"/>")
  (subject   "<xsl:call-template name="get-father-ID"/>")
  (object    "<xsl:call-template name="local-Ref"><xsl:with-param name="ref"><xsl:value-of select="@rdf:resource"/></xsl:with-param></xsl:call-template>")
 )
)
  </xsl:template>

(3)
 <!-- normalize local IDs -->
  <xsl:template name="local-ID" >
    <xsl:param name="id" />
    <xsl:choose>
      <xsl:when test="starts-with($id,'#')">
        <xsl:value-of select="concat($namespace,substring-after($id,'#'))"/>
      </xsl:when>
      <xsl:when test="contains($id,'/') or contains($id,'#') or contains($id,':')">
        <xsl:value-of select="$id" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($namespace,$id)"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- normalize local References (including the #) -->
  <xsl:template name="local-Ref" >
    <xsl:param name="ref" />
    <xsl:choose>
      <xsl:when test="starts-with($ref,'#')">
        <xsl:value-of select="concat($namespace,substring-after($ref,'#'))"/>
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="$ref" /></xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- get ID or About of current node -->
  <xsl:template name="get-ID" >
   
    <xsl:choose>
      <xsl:when test="@rdf:ID">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="@rdf:ID"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:when test="@rdf:about">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="@rdf:about"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($namespace,generate-id(.))"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
 
  <!-- get ID or About of parent node  -->
  <xsl:template name="get-father-ID" >
   
    <xsl:choose>
      <xsl:when test="../@rdf:ID">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="../@rdf:ID"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:when test="../@rdf:about">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="../@rdf:about"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($namespace,generate-id(..))"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- get ID or About of the first child -->
  <xsl:template name="get-child-ID" >
   
    <xsl:choose>
      <xsl:when test="*[position()=1]/@rdf:ID">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="*[position()=1]/@rdf:ID"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:when test="*[position()=1]/@rdf:about">
        <xsl:call-template name="local-ID"><xsl:with-param name="id"><xsl:value-of select="*[position()=1]/@rdf:about"/></xsl:with-param></xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat($namespace,generate-id(*[position()=1]))"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
    
</xsl:stylesheet>
Figure 4. Stylesheet used to transform an ontology in OWL into instances of the template for triples in JESS

 

 Copyright Notice and Disclaimer

  COPYRIGHT (C) 2001-2003 Mobile Commerce Laboratory -  School of Computer Science - Carnegie Mellon University 5000 Forbes Avenue - Pittsburgh, PA 15213-3890 - ALL RIGHTS RESERVED.

 By downloading the files provided herein you indicate your agreement with this copyright notice and disclaimer. Permission to use, copy and modify this version of the software or any parts of it and its documentation is hereby granted for RESEARCH ONLY purposes and provided that the above copyright notice and this permission notice appear intact in all copies of the software, that you do not sell the software, nor include the software in a commercial package.

 The release of this software into the public domain does not imply any obligation on the part of the authors to release future versions into the public domain. The authors are free to make upgraded or improved versions of the software available for a fee or commercially only. Commercial licensing of the software is available by contacting Dr. Norman M. Sadeh (Norman.Sadeh@cs.cmu.edu) . The software is provided "as is" and without warranty of any kind, express, implied or otherwise, including without limitation, any warranty of merchantability or fitness for a particular purpose. The software is experimental only and has not been designed for, tested or approved for hazardous use. The use of the software is at the user's own risk. Any conclusions you may draw based on the software or its use are your own. We expressly disclaim any responsibility or liability for any and all adverse effects, including personal, bodily, property or business injury, and for damages or loss of any kind whatsoever, resulting directly or indirectly, whether from negligence, intent or otherwise, from the use or disuse of the software, from errors in the software, or from misunderstandings arising from the software itself, its use or its documentation.

Acknowledgements

  This material is based on research conducted at Carnegie Mellon University's Mobile Commerce Lab. (School of Computer Science) as part of the DAML initiative. This work has been sponsored by the Air Force Research Laboratory under contract F30602-02-2-0035 and by the Defense Advanced Research Project Agency  under contract F30602-98-2-0135. The US Government is authorized to reproduce and distribute reprints for Governmental purposes notwithstanding any copyright notation thereon. This work was also in part supported by grants from IBM, HP, Symbol, Boeing, Fujitsu and the IST Program (SWAP project). The views and conclusions contained herein are those of the authors and should not be interpreted as necessarily representing the official policies or endorsements, either expressed or implied, of the Air Force Research Laboratory or the U.S. Government.