Reasoning is a topic of discussion that suffers (like most things related to the Semantic Web vision) unduely due to poor narratives and simple examples.
The predicates we used in this exercise have been sourced from the relationship vocabulary at: <http://purl.org/vocab/relationship/> . In this guide we make specific use of the following:
rel:siblingOf
. rel:ancestorOf
.Using Turtle [1] notation we can use a RDF based Linked Data graph to express how the royals are related:
## Turtle based Data Representation Start ## @prefix rel: <http://purl.org/vocab/relationship/> . <http://dbpedia.org/resource/Prince_William_of_Wales> rel:siblingOf <http://dbpedia.org/resource/Prince_Harry_of_Wales> . <http://dbpedia.org/resource/Elizabeth_Bowes-Lyon> rel:ancestorOf <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> . <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> rel:ancestorOf <http://dbpedia.org/resource/Charles%2C_Prince_of_Wales> . <http://dbpedia.org/resource/Charles%2C_Prince_of_Wales> rel:ancestorOf <http://dbpedia.org/resource/Prince_William_of_Wales> . ## End ##
Now that we have raw data (in the form of a Turtle based entity relationship graph) in place, we can now proceed to load this data into a SPARQL 1.1 compliant Virtuoso DBMS. Virtuoso enables us load data using any of the following methods:
## Create Instance Data for Relationship Ontology PREFIX rel: <http://purl.org/vocab/relationship/> INSERT { GRAPH <urn:owl:inference:tests> { <http://dbpedia.org/resource/Prince_William_of_Wales> rel:siblingOf <http://dbpedia.org/resource/Prince_Harry_of_Wales> . <http://dbpedia.org/resource/Elizabeth_Bowes-Lyon> rel:ancestorOf <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> . <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> rel:ancestorOf <http://dbpedia.org/resource/Charles%2C_Prince_of_Wales> . <http://dbpedia.org/resource/Charles%2C_Prince_of_Wales> rel:ancestorOf <http://dbpedia.org/resource/Prince_William_of_Wales> . } }
## Create Instance Data for Relationship Ontology PREFIX rel: <http://purl.org/vocab/relationship/> INSERT into GRAPH <urn:owl:inference:tests> { <http://dbpedia.org/resource/Prince_William_of_Wales> rel:siblingOf <http://dbpedia.org/resource/Prince_Harry_of_Wales> . <http://dbpedia.org/resource/Elizabeth_Bowes-Lyon> rel:ancestorOf <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> . <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> rel:ancestorOf <http://dbpedia.org/resource/Charles%2C_Prince_of_Wales> . <http://dbpedia.org/resource/Charles%2C_Prince_of_Wales> rel:ancestorOf <http://dbpedia.org/resource/Prince_William_of_Wales> . }
To verify that your data has been created, execute the following basic SPARQL query:
## Verify Data SELECT * FROM <urn:owl:inference:tests> WHERE { ?s ?p ?o . }
We are using terms from the relationship vocabulary to drive this exercise, so we need to make Virtuoso aware of this through the use of an inference rule declaration that binds said rule to the relationship vocabulary. To complete this particular task you need to execute the commands that follow via Virtuoso's SQL interfaces (command-line, ODBC, JDBC, ADO.NET, or XMLA):
sparql clear graph <http://vocab.org/relationship/>; sparql load <http://vocab.org/relationship/rel-vocab-20100607.rdf> into <http://vocab.org/relationship/>; rdfs_rule_set ('urn:owl:inference:rules:tests', 'http://vocab.org/relationship/') ;
SELECT * FROM sys_rdf_schema
In this case we will use a Virtuoso SPARQL pragma to conditionally invoke Virtuoso's in-built reasoner against the rule created earlier:
DEFINE input:inference 'urn:owl:inference:rules:tests' PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Elizabeth_Bowes-Lyon> rel:ancestorOf ?o }
In this case, we will use SPARQL 1.1 Property Paths to achieve the same goal via the "+"
unary operator applied to the rel:ancestorOf
predicate in the SPARQL query pattern:
PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Elizabeth_Bowes-Lyon> rel:ancestorOf+ ?o. }
In this case, neither the use of a SPARQL inference rules pragma nor a SPARQL 1.1 property paths are put to use, so you end up with in incomplete result (or solution):
PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Elizabeth_Bowes-Lyon> rel:ancestorOf ?o . }
This collection of queries leverages with the semantics of the rel:siblingOf
predicate.
This particular predicate's semantics imply that the subject and object positions in triples have no effect on the query result.
Thus, the position of the DBpedia Identifier: <http://dbpedia.org/resource/Prince_Harry_of_Wales> in the SPARQL triple pattern has no effect on the eventual query result, when reasoning is in use.
Using the Virtuoso inference rule SPARQL pragma approach the query would be as follows:
DEFINE input:inference 'urn:owl:inference:rules:tests' PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Prince_Harry_of_Wales> rel:siblingOf ?o . }
Using SPARQL 1.1 property paths approach to get the same effect via combined use of the following operators with the rel:siblingOf
query pattern predicate: "/"
(path sequence operator), "^"
inverse operator, a one or more ("+")
.
The resulting SPARQL query takes the following form:
PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Prince_Harry_of_Wales> (rel:siblingOf+|^rel:siblingOf) ?o . }
Executing the SPARQL query without inference rules pragmas or SPARQL 1.1 property paths results in an empty results set. The query in question would take the form below. Of course, you can simply comment out the Virtuoso SPARQL pragma declaration too.
PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Prince_Harry_of_Wales> rel:siblingOf ?o . }
This collection of queries leverage the inverseOf
semantics that underly the rel:descendantOf
predicate.
Basically, this is about the opposite (inverse) implications of an ancestor and a descendant.
The object of an ancestor triple is the subject of a descendant triple which implies that my raw data doesn't need to explicitly include any rel:descendantOf
triples.
Using the Virtuoso SPARQL inference rules pragma your SPARQL query would be as follows:
DEFINE input:inference 'urn:owl:inference:rules:tests' PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> rel:descendantOf ?o . }
Using SPARQL 1.1 property paths to achieve the same result via use of the alternative paths operator ("|")
combined with the inverse ("^")
operator leads to the following query:
PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> rel:descendantOf|^rel:ancestorOf ?o . }
Executing the SPARQL query without a Virtuoso inference rule pragma or SPARQL 1.1 query paths alternative, you will get an empty result for the following:
PREFIX rel: <http://purl.org/vocab/relationship/> SELECT * FROM <urn:owl:inference:tests> WHERE { <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> rel:descendantOf ?o . }