We added an extension to the AllegroGraph RDFS++ reasoner so that we now also can reason over hasValue restrictions in equivalent classes or subclasses.
Here is an example of an owl class definition where an AtlantisMission defined to be equivalent of something that is and a Spacemission and has a property 'shuttleUsed' with the value 'Antlantis'
<owl:Class rdf:ID="AtlantisMission">
<rdfs:subClassOf
rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
<rdfs:label
rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
Atlantis mission
</rdfs:label>
<owl:equivalentClass>
<owl:Class>
<owl:intersectionOf rdf:parseType="Collection">
<rdf:Description rdf:ID="SpaceMission"/>
<owl:Restriction>
<owl:onProperty rdf:resource="#shuttleUsed"/>
<owl:hasValue rdf:resource="#Atlantis"/>
</owl:Restriction>
</owl:intersectionOf>
</owl:Class>
</owl:equivalentClass>
</owl:Class>
We can make two types of inferences from this definition.
- We can derive the default value for 'shuttleUsed' when we have an Instance of an AtlantisMission. So say we have the above definition in an owl file that we loaded, then if we add the following triple to the triple-store
(add-triple !m:Mission4 !rdf:type !m:AtlantisMission)we can derive that the shuttleUsed must be Atlantis with the following query.
(select (?val) (qs !m:Mission3 !m:shuttleUsed ?val)) - In reverse: we can also derive the type of an instance to be an AtlantisMission if we added the following instance properties to a triple-store
(add-triple !m:Mission5 !m:shuttleUsed !m:Atlantis) (add-triple !m:Mission5 !rdf:type !m:SpaceMission)
then the following query would derive that ?x is an AtlantisMission.
(select (?x) (qs !m:Mission5 !rdf:type ?x))
Is this extension by default included in the reasoner? No, we decided that we have to do some more testing to make sure that it doesn't ruin the speed of the AllegroGraph RDFS++ reasoner. So currently, you have to tell AllegroGraph that you want to use this module.
How to use it from Java:
Please read the tutorial below to get a better understanding of how things are supposed to work with the hasValue restrictions. The one thing that is important for Java is that you add the hasValue reasoner after you opened a triple-store.. You do this by calling the method enableHasValueReasoning() from the AllegroGraphConnection class.
How to use it from the http-client interface
Not implemented yet.
How to use it from Lisp: a tutorial
In principle the following code will all run. Just evaluate every expression from top to bottom and you will see the results.
; load agraph into lisp
(require :agraph)
; Activate the hasValue restriction reasoning. (require :reasoner-has-value)
; makes printing of triples nicer in interactive mode
(db.agraph:enable-print-decoded t)
; go into the triple-store-user package
(in-package :triple-store-user)
The following will define the function to load the files SpaceMissions2.ntriples into the triple-store. This file is included in the distribution. It will help you understanding of the contents of this file to inspect it in TopBraid Composer.
(defun read-sm ()
(create-triple-store "test11" :directory "/tmp/"
:if-exists :supersede
:expected-unique-resources 200000)
(load-ntriples "./SpaceMissions2.ntriples")
(index-all-triples))
(time (read-sm)) ; do the actual read
We are lazy and don't want to type long namespaces:
(register-namespace "m"
"http://www.topbraid.org/spacemissions.owl#")
;; lets look at the triples..
(dolist (e (get-triples-list :limit nil))
(print e))
First we demo how we can derive default values from type information
(add-triple !m:Mission1 !rdf:type !m:SpaceMissionIn2000)
(add-triple !m:Mission1 !m:added-by !m:Jans)
(select (?x ?y)
(qs !m:Mission1 !m:startYear ?x)
(q !m:Mission1 !m:added-by ?y))
and some more examples:
(add-triple !m:Mission3 !rdf:type !m:DiscoveryMission)
(add-triple !m:Mission4 !rdf:type !m:AtlantisMission)
(select (?val)
(qs !m:Mission3 !m:shuttleUsed ?val))
(select (?val)
(qs !m:Mission4 !m:shuttleUsed ?val))
(select ()
(qs !m:Mission4 !m:shuttleUsed !m:Atlantis)
(write 'SUCCESS)))
Second, we demo how we can derive types from values. We add the shuttleUsed property to Mission5 and then we can automatically derive that Mission5 is an AtlantisMission.
(add-triple !m:Mission5 !m:shuttleUsed !m:Atlantis)
Please execute the following select and notice how
(select (?x) (qs !m:Mission5 !rdf:type ?x))
the reasoner finds two results
(("http://www.topbraid.org/spacemissions.owl#SpaceMission")
("http://www.topbraid.org/spacemissions.owl#AtlantisMission"))
The first result is due to the fact that the rdfs:range of the property shuttleUsed is 'SpaceMission'. So by adding the fact shuttleUsed to Mission5 the RDFS++ range reasoning will derive that Mission5 is a SpaceMission.
Then the hasValue reasoning module kicks in and derives from that fact that Misison5 is a SpaceMission and the shuttleUsed is Atlantis that Mission5 should be an AtlantisMission.
The following queries are also interesting. The first select will only return Mission4 because we use q and q looks only at the naked triples. It does return Mission4 because above we literally added that information
(select (?x) (q ?x !rdf:type !m:AtlantisMission))
-> (("http://www.topbraid.org/spacemissions.owl#Mission4"))
The following query also returns Mission 5 because of hasValue reasoning. (Note how we use qs here to use the reasoner)
(select (?x)
(qs ?x !rdf:type !m:AtlantisMission))
(("http://www.topbraid.org/spacemissions.owl#Mission4")
("http://www.topbraid.org/spacemissions.owl#Mission5"))
(add-triple !m:Mission6 !m:shuttleUsed !m:Columbia)
(add-triple !m:Mission6 !rdf:type !m:SpaceMission)
(select (?x)
(qs !m:Mission6 !rdf:type ?x))
(select (?x)
(qs ?x !rdf:type !m:DiscoveryMission))
(select (?val)
(qs !m:Mission6 !rdf:type !m:DiscoveryMission)
(lisp (print 'SUCCESS)))
And finally we show that we can do quite complex hasValue restrictions. Please look in TopBraidComposer or any other ontology browser how a MilitarySpaceMission is defined by multiple hasValue restrictions.
We add some values and everything should work.
(add-triple !m:Mission7 !rdf:type !m:SpaceMission)
(add-triple !m:Mission7 !m:hasMissionType !m:SpecialMissionType)
(add-triple !m:Mission7 !m:hasMissionType !m:MilitaryMissionType)
(select (?x ?y)
(qs !m:Mission7 ?x ?y))
(select (?type)
(qs !m:Mission7 !rdf:type ?type))
(select (?x)
(qs ?x !rdf:type !m:MilitarySpaceMission))
The end!