5.  RDFS Vocabularies and Semantics

The elemental RDF ontology description language, RDF Schema (RDFS), is a semantic extension of RDF. It provides mechanisms for describing groups of related resources and the relationships between these resources. RDFS involves the minimal set for describing concepts for ontology. The vocabularies contain rdfs:Resource and rdfs:Class, which provide the classification concept together with the property rdf:type, and the subsumption concept of classification with the property rdfs:subClassOf. These semantics of RDFS is very similar to CLOS perspectives. Therefore, RDFS classes are mapped onto CLOS classes and RDFS instances are mapped onto CLOS instances.

5.1  Resource Classes, Metaclasses, and Instances

Figure 5.1 shows the relationship among RDFS vocabularies. A broken curve line stands for rdf:type relation, and a solid straight line stands for rdfs:subClassOf relation. rdfs:Resource is a superclass of all other classes, and rdfs:Class is a class of all classes, including itself. A class of classes is called metaclass in CLOS. So, rdfs:Class and rdfs:Datatype are metaclasses.

RDFS Graph

Figure 5.1 RDFS Hierarchy Graph

The notion of metaclass, class, and instance is very important in CLOS. Therefore, predicates for this category on RDF resources are prepared. See the followings.

gx-user(37): (resource-p rdfs:Class)
t
gx-user(38): (resource-p rdfs:Resource)
t
gx-user(39): (resource-p rdf:Property)
t
gx-user(40): (resource-p rdfs:comment)
t
gx-user(41): (resource-p "This is comment.")
common-lisp:nil
gx-user(42): (rdf-class-p rdfs:Class)
t
gx-user(43): (rdf-class-p rdfs:Resource)
t
gx-user(44): (rdf-class-p rdf:Property)
t
gx-user(45): (rdf-class-p rdfs:comment)
common-lisp:nil
gx-user(46): (rdf-metaclass-p rdfs:Class)
t
gx-user(47): (rdf-metaclass-p rdfs:Resource)
common-lisp:nil
gx-user(48): (instance-p rdf:Property)
common-lisp:nil
gx-user(49): (instance-p rdfs:comment)
t
gx-user(50): (rdf-class-p rdf:List)
t
gx-user(51): (instance-p rdf:nil)
t
resource-p thing [Function]
Returns true, if thing is an resource but literal in RDF. Actually, this function returns true, if thing is an instance of rdfs:Resource in CLOS.

rdf-class-p thing [Function]
Returns true, if thing is a class of resource in RDF. Actually, this function returns true, if thing is rdfs:Class or an instance of rdfs:Class in CLOS.

rdf-metaclass-p thing [Function]
Returns true, if thing is a metaclass of resource. Actually, this function returns true, if thing is rdfs:Class or an instance and simultaneously subclass of rdfs:Class in CLOS.

strict-class-p thing [Function]
Returns true, if thing is a class but not a metaclass of resource.

instance-p thing [Function]
Returns true, if thing is an instance of rdfs:Resource but not an instance of rdfs:Class.

resource? symbol [Function]
Returns true, if symbol is a symbol and its value is a resource.

class? symbol [Function]
Returns true, if symbol is a symbol and its value is a class of resource.

metaclass? symbol [Function]
Returns true, if symbol is a symbol and its value is a meta class of resource.

strict-class? symbol [Function]
Returns true, if symbol is a symbol and its value is a class but not a metaclass of resource.

instance? symbol [Function]
Returns true, if symbol is a symbol and its value is an instance of resource.



5.2  rdf:type, rdfs:subClassOf, and rdfs:subPropertyOf

Figure 5.1 depicts class-instance relations described with rdf:type property, class-subclass relations described with rdfs:subClassOf property, and superproperty-subproperty relations described with rdfs:subPropertyOf among RDFS vocabularies.

To get rdf:type property value of resources, you may use gx:type-of and cl:class-of function. Note that gx:type-of is customized type-of function for resources instead of cl:type-of so that it brings RDFS semantics, but cl:class-of is native function in CLOS. Therefore, while gx:type-of for rdfs:Class returns rdfs:Class in RDFS semantics, cl:class-of for rdfs:Class returns actual metalcass object for rdfs:Class in CLOS as shown below.

gx-user(12): (type-of rdfs:Resource)
rdfs:Class
gx-user(13): (class-of rdfs:Resource)
#<RDFSclass rdfs:Class>
gx-user(14): (type-of rdf:Property)
rdfs:Class
gx-user(15): (class-of rdf:Property)
#<RDFSclass rdfs:Class>
gx-user(16): (type-of rdfs:comment)
rdf:Property
gx-user(17): (class-of rdfs:comment)
#<rdfs:Class rdf:Property>
gx-user(18): (type-of rdfs:Datatype)
rdfs:Class
gx-user(19): (class-of rdfs:Datatype)
#<RDFSclass rdfs:Class>
gx-user(20): (type-of rdfs:Class)
rdfs:Class
gx-user(21): (class-of rdfs:Class)
#<metaRDFSclass RDFSclass>

type-of resource [Function]
Returns the name of the class of resource. This function is almost same as cl:type-of, but exactly obeys RDFS semantics. For example, the class of rdfs:Class is itself.

In order to get instances of a class, the function collect-direct-instances retrieves the direct instances of a class, and the function collect-all-instances collects all instances from the class and its subclasses.

gx-user(31): (collect-direct-instances rdf:List)  
(#<rdf:List rdf:nil>)
gx-user(32): (collect-all-instances rdfs:Class)
(#<rdfs:Class rdf:Alt> #<rdfs:Class rdf:Seq> #<rdfs:Class rdf:Bag>
 #<rdfs:Class rdfs:Container> #<rdfs:Class rdfs:ContainerMembershipProperty>
 #<rdfs:Class rdf:List> #<rdfs:Class rdfs:Datatype> #<rdfs:Class rdf:Statement>
 #<rdfs:Class rdf:Property> #<rdfs:Datatype xsd:unsignedByte> ...)


collect-direct-instances class [Method]
class is a symbol or a class object. This generic function returns instances that are directly defined to class. Note that this does not affect literal classes.

collect-all-instances class [Method]
class is a symbol or a class object. This generic function returns instances that are defined to class and subclasses of class. For owl classes, this method collects not only direct instances of class and its subclasses but also indirect instances by owl entailments.

The class-instance relation in RDF is directly defined with rdf:type property. The notion of RDF class is different from the class notion in CLOS, but the rdf:type relation among objects is quite same as that in CLOS. The straightforward mapping of rdf:type relation to CLOS class-instance relation conveys the gains that the potential of CLOS is available. However, this straightforward mapping causes only one obstacle to implement RDF on top of CLOS, namely rdfs:Class that is an instance of rdfs:Class itself. CLOS rejects such membership loop among classes, while cl:standard-object is an instance of itself in CLOS. Therefore, to work around this obstacle, the internal class, RDFSclass, is introduced as a class of rdfs:Class, and gx:typep, that is a customized type predicate, is introduced to pretend the relation in RDF. gx:typep also accepts URIs, QName symbols, and literal data in different way from cl:typep. See the followings.

gx-user(2): (typep rdfs:Class rdfs:Class)
t
gx-user(3): (cl:typep rdfs:Class rdfs:Class)
common-lisp:nil
gx-user(4): (typep <http://somewhere/> rdfs:Resource)
t
gx-user(5): (typep "This is literal." rdfs:Resource)
t
gx-user(6): (typep 1 rdfs:Resource)
t
gx-user(7): (typep "This is literal." rdfs:Literal)
t
gx-user(8): (typep 1 rdfs:Literal)
t
typep resource type [Function]
Returns true if resource is a member of type in RDF semantics.


The class-subclass relation in RDF is defined with rdfs:subClassOf property, and the relation is similar to the CLOS class-subclass relation as well as rdf:type. However, gx:subtypep is available to test class-subclass relation in the sense of RDF. Namely, it accepts URIs, QName symbols, and data types in different way from cl:subtypep. See the followings.


gx-user(35): (subtypep rdf:Alt rdfs:Container)
t
gx-user(36): (subtypep rdf:Alt rdfs:Resource)
t
gx-user(37): (subtypep <http://www.w3.org/1999/02/22-rdf-syntax-ns#Alt>
                       rdfs:Resource)
t
gx-user(38): (subtypep xsd:integer rdfs:Literal)
t
gx-user(39): (subtypep xsd:integer rdfs:Resource)
t
subtypep type1 type2 [Function]
Returns true if type1 is a subtype of type2 in RDF semantics.


The rdfs:subClassOf value of a resource class is retrieved using slot-value with slot-name rdfs:subClassOf. On the other hand, superclasses-of retrieves superclasses in the sense of CLOS, and subclasses-of retrieves subclasses in the sense of CLOS.

gx-user(40): (slot-value rdf:Alt 'rdfs:subClassOf)
#<rdfs:Class rdfs:Container>
gx-user(41): (superclasses-of rdf:Alt)
(#<rdfs:Class rdfs:Container>)
gx-user(42): (superclasses-of rdfs:Container)
(#<rdfs:Class rdfs:Resource>)
gx-user(43): (subclasses-of rdfs:Container)
(#<rdfs:Class rdf:Alt> #<rdfs:Class rdf:Seq> #<rdfs:Class rdf:Bag>)
superclasses-of class [Function]
Returns mop:class-direct-superclasses slot value of class. This returns direct superclasses of class. It is almost same as (slot-value class 'rdfs:subClassOf) in RDF, except that it is listed. In OWL, it returns very different values from rdfs:subClassOf. See the OWL section for details.

subclasses-of class [Function]
Returns direct subclasses of class.


The properties, which are instances of rdf:Property, have super-property and sub-property concepts, although CLOS instances do not have the super-sub relation. Therefore, the super-sub notion upon properties is implemented in SWCLOS. subproperty-p tests the super-sub relation on property. superproperty-of and subproperty-of functions retrieve super-properties and sub-properties of a parameter. The detail of property is explained at Section 8.

gx-user(3): (subproperty-p rdfs:isDefinedBy rdfs:seeAlso)
t
gx-user(4): (subproperty-of rdfs:seeAlso)
(#<rdf:Property rdfs:isDefinedBy>)
gx-user(5): (superproperty-of rdfs:isDefinedBy)
(#<rdf:Property rdfs:seeAlso>)

subproperty-p property1 property2 [Function]
Returns true, if property1 is an subproperty of property2. Otherwise, cl:nil is returned.

superproperty-of property [Function]
Returns a direct superproperty of property, if exists. Otherwise, cl:nil is returned.

subproperty-of property [Function]
Returns a direct subproperty of property, if exists. Otherwise, cl:nil is returned.


5.3  Properties and Slots

In RDF, the property is the first-class entity that exists as resource. Therefore, the property resource exists as CLOS object, an instance of the class rdf:Property, in SWCLOS.

Ontologies are modeled as graphs with nodes and directed arcs in RDF. The arrow tail node on a directed arc is called subject, the arrow head node is called object, and the arc is called predicate in this triple set. A subject in triple is a non-literal resource in RDF, an object is either non-literal resource or literal, and a predicate is a property.

From the perspective of Object-Oriented Programming, a subject in RDF is captured as an object in OOP, and a pair of an arc and the head-node is deemed a slot of the tail-node (subjective) object, where a slot-name corresponds to a property name. Therefore, getting a property value pointed by a property arc in RDF graph is equal to getting a slot value of the slot name corresponding to the property name.

Note that the line 2 in the following example just demonstrated rdfs:comment resource object as the first-class entity. The line 3 and 4 shows the role of property that corresponds to an arc in RDF graph. Please see the difference and discriminate a property as an object and a property as a role of binary relationship.

gx-user(2): rdfs:comment
#<rdf:Property rdfs:comment>
gx-user(3): (slot-value rdfs:Resource 'rdfs:comment)
"The class resource, everything."
gx-user(4): (slot-value rdfs:comment 'rdfs:comment)
"A description of the subject resource."

However, rdf:type property is very special in SWCLOS. It specifies the type of object, and it is transformed to a class-instance relation in CLOS. Therefore, we need an accessor that handles rdf:type as same way as other properties. The function '->' allows users to traverse over an RDF graph according to a given path and return the value (node name or literal) at the arrival point.

gx-user(3): (class-of rdfs:subPropertyOf)
#<rdfs:Class rdf:Property>
gx-user(4): (type-of rdfs:subPropertyOf)
rdf:Property
gx-user(5): (-> rdfs:subPropertyOf rdf:type)
rdf:Property
gx-user(6): (-> rdfs:subPropertyOf rdf:type rdf:type)
rdfs:Class
gx-user(7): (-> rdfs:subPropertyOf rdf:type rdf:type rdfs:comment)
"The class of classes."
gx-user(8): (-> rdfs:subPropertyOf rdf:type rdf:type rdfs:comment rdf:type)
rdfs:Literal

-> node arc1 ... [Function]
Starting at node, this function traverses over the RDF graph according to the path given as parameters, arc1 ... , and returns the arrival node. In case of multiple paths is possible, this function takes one route encountered firstly. If there is no route which coincides with path, cl:nil is returned. If an arc is a list, i.e., a specifier for arc, in which the first is a property name and the second is a type specifier for filter, then a route where the designated type satisfies the arc value as type is chosen. Note that this search has no backtrack.

5.4  Adding Resource Objects

In CLOS, a class must be defined before making the instance. A CLOS programmer cannot add a slot value to an instance object without the slot definition upon the class. In contrast, adding a triple, subject/predicate/object, is a basic manner in constructing ontology in RDF. It implies that SWCLOS must add a slot value without the slot definition in the class. Therefore, SWCLOS enabled the piecewise slot addition for objects. Furthermore, the capability for forward referencing is required. Namely, SWCLOS must be able to accept undefined classes and instances as referent. Fortunately we have the principle of monotonicity in Semantic Webs and many entailment rules in RDF, RDFS and OWL. SWCLOS exploited the principle of monotonicity and a number of entailment rules in order to realize the forward referencing for objects. See SWCLOS paper1, paper2, and the paper at ASWC2006 on theoretical details. In this document, we explain the usage of this piecewise adding functionality.

Figure 5.2 illustrates a part of Wine Ontology described in RDFS rather than OWL. You may make this RDF graph in a usual manner of CLOS object definition, namely from abstract classes to special classes and from classes to instances. However, SWCLOS allows you to define any object in any order with the premise of monotonicity principle. SWCLOS ensures the final result shown in Figure 5.2, when all pieces of knowledge are inputted.

RDF Graph in Wine Ontology

Figure 5.2 RDF Graph in Wine Ontology

The followings are an example to create the RDF graph shown in Figure 5.2.

gx-user(2): (defpackage vin)
#<The vin package>
gx-user(3): (defIndividual vin::ElyseZinfandel 
               (rdf:type vin::Zinfandel)
               (vin::hasMaker vin::Elyse))
Warning: Special Entailing as default: vin::Zinfandel is a rdfs:Class.
Warning: Entail by rdf1: vin::hasMaker rdf:type rdf:Property.
Warning: Entail by rdfs4b: vin::Elyse rdf:type rdfs:Resource.
#<vin:Zinfandel vin:ElyseZinfandel>
gx-user(4): vin:Elyse
#<rdfs:Resource vin:Elyse>
gx-user(5): (defIndividual vin:Elyse (rdf:type vin::Winery))
Warning: Special Entailing as default: vin::Winery is a rdfs:Class.
#<vin:Winery vin:Elyse>
gx-user(6): (superclasses-of vin:Zinfandel)
(#<rdfs:Class rdfs:Resource>)
gx-user(7): (defResource vin:Zinfandel (rdfs:subClassOf vin::Wine))
Warning: Range entail by rdfs:subClassOf: vin::Wine rdf:type rdfs:Class
#<rdfs:Class vin:Zinfandel>
gx-user(8): (superclasses-of vin:Zinfandel)
(#<rdfs:Class vin:Wine>)
gx-user(9): (subtypep vin:Zinfandel rdfs:Resource)
t

At the beginning of the above example, a lisp package named 'vin' was created for Wine Ontology. Then, vin:ElyseZinfandel, whose maker is vin:Elyse, was defined. Note that all of 'vin' vocabulary in Wine Ontology are to be interned in 'vin' package by lisp reader. When you input a new symbol as QName, you must use double colons, because you have no way to make exported symbols directly with neither calling export function nor defining them at same time of the package definition. Since SWCLOS interprets lisp symbols at the position of resources as QName and exports them, then you may specify the QName symbols with one colon afterwards.

The macro defIndividual is used to define an individual or an instance of resource. At line 3, vin:Zinfandel, vin:hasMaker, and vin:Elyse are referred but not defined as QName yet. So, SWCLOS reasoned out at least that vin:Zinfandel must be an instance of rdfs:Class, vin:hasMaker must be an instance of rdf:Property, and vin:Elyse must be an instance of rdfs:Resource using some of entailment rules in RDF and RDFS. The line 3 in the above not only made an instance slot for vin:ElyseZinfandel, vin:hasMaker and vin:Elyse, but also automatically defined the CLOS slot definition of vin:hasMaker at the class vin:Zinfandel.

The line 4 to 5 shows the type of vin:Elyse is changed from rdfs:Resource to vin:Winery. Note that vin:Winery is a subclass of rdfs:Resource and shares rdfs:Class as its type with rdfs:Resource. The line 6 to 8 demonstrates that vin:Wine is added into the rdfs:subClassOf slot of vin:Zinfandel. Exactly, the superclass of vin:Zinfandel is refined from rdfs:Resource to vin:Wine, because it is directed, and rdfs:Resource as superclass of vin:Zinfandel is involved by the transitivity of subsumption. Thus, the automatic redefinition in SWCLOS is possible and knowledge monotonously increases. The forward reference involves the entailment through the various entailment rules, and the statement of explicit assertion refines the results of entailing. If you want to reveal the inside, you can use the function inspect to browse them as CLOS object.

defIndividual name (role1 filler1) ... [Macro]
name is a QName symbol of this individual, and role is a property name (symbol) including rdf:type etc., and filler is a value of the property. This macro generates and evaluates the form like '(addForm (:name name) (role1 filler1) ... )'. If an rdf:type value is not supplied, the most specific concepts of domain restrictions are calculated and used. If there is no rdf:type indication and no domain restrictions, the default value is rdfs:Resource in RDFS and owl:Thing in OWL. A filler is a sub form in addForm calling sequence. See addForm.

defResource name (role1 filler1) ... [Macro]
This macro works as same as defIndividual but the default rdf:type value is rdfs:Class in RDFS and owl:Class in OWL.

defProperty name (role1 filler1) ... [Macro]
This macro works as same as defIndividual but the default rdf:type value is rdf:Property.

5.5  Adding Slots

In usual Object-Oriented Programming, slot structures in an instance must be defined when the class of the instance is defined, before making the instance. However, in RDF, a property (predicate) and its value (object) is put at any RDF graph node (subject) within the range restriction on the property. This gap is very serious. Then, SWCLOS has solved it. You can add any slot (pair of role and filler) to any resource object without the slot definition in the class. SWCLOS adds the new slot definition in the class with the demand of new slot creation when a new slot is being added to an individual.

There is no special function to add new slots into objects in SWCLOS. Instead you can add new slots using defIndividual or defResource macro, piecewisely. SWCLOS accepts such piecewise and multiple definitions for multiple slots on a resource. After the above example at the line number 3, you can add a new slot (vin:hasColor vin:Red) to vin:ElyseZinfandel as follows.

gx-user(10): (defIndividual vin:ElyseZinfandel (vin::hasColor vin::Red))
Warning: Entail by rdf1: vin::hasColor rdf:type rdf:Property.
Warning: Entail by rdfs4b: vin::Red rdf:type rdfs:Resource.
#<vin:Zinfandel vin:ElyseZinfandel>
gx-user(11): (get-form vin:ElyseZinfandel)
(vin:Zinfandel vin:ElyseZinfandel (vin:hasMaker vin:Elyse)
               (vin:hasColor vin:Red))


5.6  Adding Slot Values

Setting a slot value shows very different behaviors in SWCLOS. (setf slot-value) is available but it does not overwrite an old value. It just adds a new value into the slot value. Precisely, if both an old value and a new value are not a list, the result of adding is a list of old and new value. If both are a list, the result is a union of both. If one of them is not a list, it is added (adjoin) to another value as a set element. This is from the monotonicity principle in Semantic Webs. The detail is discussed again, later.

gx-user(17): (defIndividual MyResource (rdf:type rdfs:Resource)
               (myProp "original one"))
Warning: Entail by rdf1: myProp rdf:type rdf:Property.
#<rdfs:Resource MyResource>
gx-user(18): (slot-value MyResource 'myProp)
"original one"
gx-user(19): (setf (slot-value MyResource 'myProp) "added 1st")
("added 1st" "original one")
gx-user(20): (setf (slot-value MyResource 'myProp) "added 2nd")
("added 2nd" "added 1st" "original one")
gx-user(21): (slot-value MyResource 'myProp)
("added 2nd" "added 1st" "original one")

When you add same value that is already stored in the slot, nothing happened.

gx-user(17): (setf (slot-value MyResource 'myProp) "added 1st")
("added 2nd" "added 1st" "original one")
gx-user(18): (slot-value MyResource 'myProp)
("added 2nd" "added 1st" "original one")


5.7  Adding Multiple Types

A CLOS object belongs to only one class. However, an instance in RDF may be a member of multiple classes. In order to solve this problem, we set up a shadow class that is an instance of metaclass gx::shadow-class. For example, suppose SaucelitoCanyonZinfandel1998 in Wine Ontology is an instance of Zinfandel and Vintage, SWCLOS set a shadow-class named Zinfandel.0 that has Zinfandel and Vintage as its superclass.

gx-user(2): (defpackage vin)
#<The vin package>
gx-user(3): (defIndividual vin::SaucelitoCanyonZinfandel1998 
                (rdf:type vin::Zinfandel)
              (rdf:type vin::Vintage))
Warning: Range entail by rdf:type: vin::Vintage rdf:type rdfs:Class
Warning: Special Entailing with domain: vin::Zinfandel is a rdfs:Class.
Warning: Multiple classing with (#<rdfs:Class vin:Zinfandel> 
#<rdfs:Class vin:Vintage>) for vin:SaucelitoCanyonZinfandel1998
#<vin:Zinfandel.0 vin:SaucelitoCanyonZinfandel1998>
gx-user(4): (typep vin:SaucelitoCanyonZinfandel1998 vin:Zinfandel)
t
gx-user(5): (typep vin:SaucelitoCanyonZinfandel1998 vin:Vintage)
t
gx-user(6): (type-of vin:SaucelitoCanyonZinfandel1998)
(vin:Zinfandel vin:Vintage)


5.8  Extension of property and slot definition

The set of all triples whose predicate is a specific property is called the extension of the property in RDF. The slot structure in instance of CLOS is captured as one element of the extension of property object in RDF. On the other hand, in CLOS, we have the slot-definition objects in class object for its instance structure. A slot definition object in a class holds a slot-name and a type constraint for the slot value. SWCLOS also keeps the subject information on the property extension in the slot-definition objects. Function collect-all-extensions-of collects all extensions of a property and lists up them.

gx-user(53): rdfs:comment
#<rdf:Property rdfs:comment>
gx-user(54): (find 'rdfs:comment (mop:class-slots rdfs:Class)
                   :key #'name)
#<gx::Property-effective-slot-definition rdfs:comment @ #x20a9520a>
gx-user(55): (cl:typep
               (find 'rdfs:comment (mop:class-slots rdfs:Class)
                     :key #'name)
               'mop:slot-definition)
t
gx-user(56): (collect-all-extensions-of rdfs:comment)
((#<rdf:List rdf:nil>
  "The empty list, with no items in it. If the rest of a list is nil then the list has no more items in it.")
 (#<rdf:Property rdfs:label> "A human-readable name for the subject.")
 (#<rdf:Property rdfs:isDefinedBy> "The definition of the subject resource.")
 (#<rdf:Property rdfs:comment> "A description of the subject resource.")
 (#<rdf:Property rdfs:domain> "A domain of the subject property.")
 (#<rdf:Property rdfs:range> "A range of the subject property.")
 (#<rdf:Property rdfs:subPropertyOf> "The subject is a subproperty of a property.")
 (#<rdf:Property rdfs:subClassOf> "The subject is a subclass of a class.")
 (#<rdf:Property rdfs:seeAlso> "Further information about the subject resource.")
 (#<rdf:Property rdf:type> "The subject is an instance of a class.") ...)

collect-all-extensions-of property [Function]
Collects an element of the extension of property and returns a list of role and filler pairs.


Author:
Seiji Koide. Copyright (c) 2005, 2006 GALAXY EXPRESS CORPORATION. Feb. 2006
Copyright (c) 2007 Seiji Koide. Feb. 2007