www.openlinksw.com
docs.openlinksw.com

Book Home

Contents
Preface

RDF Database and SPARQL

Overview
Data Representation
RDF and SPARQL API and SQL
SPARUL -- an Update Language For RDF Graphs
RDF Insert Methods in Virtuoso
Virtuoso Sponger
Dereferencable IRIs and RDF Linked Data
RDF Views -- Mapping Relational Data to RDF
RDF Inference in Virtuoso
Introduction Making Rule Sets Changing Rule Sets Subclasses and Subproperties OWL same-as Support Implementation Enabling Inferencing Examples
Using Full Text Search in SPARQL
Virtuoso SPARQL Query Service
Business Intelligence Extensions for SPARQL
Debugging SPARQL queries
Virtuoso RDF Performance Tuning
RDF Store Benchmarks
SPARQL Implementation Details
Native RDF Storage Providers

15.9. RDF Inference in Virtuoso

15.9.1. Introduction

Virtuoso SPARQL can use an inference context for inferring triples that are not physically stored. This functionality applies to physically stored quads and not to virtual triples generated from relational data with RDF views. Such an inference context can be built from one or more graphs containing RDF Schema triples. The supported RDF Schema or OWL constraints are imported from these graphs and are grouped together into rule bases. A rule base is a persistent entity that can be referenced by a SPARQL query or end point. Queries running with a given rule base work as if the triples asserted by this rule base were included in the graph or graphs accessed by the query.

As of version 5.0, Virtuoso recognizes rdfs:subClassOf and rdfs:subPropertyOf. owl:sameAs is considered for arbitrary subjects and objects if specially enabled by a pragme in the query. As of 5.00.3031, owl:sameAs, owl:equivalentClass and owl:equivalentProperty are also considered when determining subclass or subproperty relations. If two classes are equivalent, they share all instances, subclasses and superclasses directly or indirectly stated in the data for either class. Other RDF Schema or OWL information is not taken into account.


15.9.2. Making Rule Sets

Since RDF Schema and OWL schemas are RDF graphs, these can be loaded into the triple store. Thus, in order to use such a schema as query context, one first loads the corresponding document into the triple store using ttlp or rdf_load_rdfxml or related functions. After the schema document is loaded, one can add the assertions therein into an inference context with the rdfs_rule_set function. This function specifies a logical name for the rule set plus a graph URI. It is possible to combine multiple schema graphs into a single rule set. A single schema graph may also independently participate in multiple rule sets.

rdfs_rule_set (in name varchar, in uri varchar, in remove int := 0)

This function adds the applicable facts of the graph into a rule set. The graph URI must correspond to the graph IRI of a graph stored in the triple store of the Virtuoso instance. If the remove argument is true, the specified graph is removed from the rule set instead.


15.9.3. Changing Rule Sets

Changing a rule set affects queries made after the change. Some queries may have been previously compiled and will not be changed as a result of modifying the rule set. When a rule set is changed, i.e. when rdfs_rule_set is called with the first argument set to a pre-existing rule set's name, all the graphs associated with this name are read and the relevant facts are added to a new empty rule set. Thus, if triples are deleted from or added to the graphs comprising the rule set, calling rdfs_rule_set will refresh the rule set to correspond to the state of the stored graphs.


15.9.4. Subclasses and Subproperties

Virtuoso SPARQL supports RDF Schema subclasses and subproperties.

The predicates rdfs:subClassOf and rdfs:subPropertyOf are recognized when they appear in graphs included in a rule set. When such a rule set is specified as a context for a SPARQL query, the following extra triples are generated as needed.

For every ?s rdf:type ?class, a triple ?s rdf:type ?superclass is considered to exist, such that ?superclass is a direct or indirect superclass of ?class. Direct superclasses are declared with the rdfs:subClassOf predicate in the rule set graph. Transitivity of superclasses is automatically taken into account, meaning that if a is a superclass of b and b a superclass of c, then a is a superclass of c also. Cyclic superclass relations are not allowed. If such occur in the rule set data, the behavior is undefined but will not involve unterminating recursion.

For every ?s ?subpredicate ?o, a triple ?s ?superpredicate ?o is considered to exist if the rule context declares ?superpredicate to be a superpredicate of ?predicate. This is done by having the triple ?subpredicate rdfs:subPropertyOf ?superpredicate as part of the graphs making up the rule context. Transitivity is observed, thus if a is a subpredicate of b and b a subpredicate of c, then a is also a subpredicate of c.


15.9.5. OWL same-as Support

Virtuoso has limited support for the OWL same-as predicate.

In the following, the abbreviation owl:sameAs is used for the IRI http://www.w3.org/2002/07/owl#same-as .

If same-as traversal is enabled and a triple pattern with a given subject or object is being matched, all the synonyms of the S and O will be tried and results generated for all the tried bindings of S and O. The set of synonyms is generated at run time by following all owl:sameAs triples where the IRI in question is either the subject or the object. These are followed recursively from object to subject and subject to object until the complete transitive closure is generated. All same-as triples from all the graphs applicable to instantiating the triple pattern at hand are considered.

Thus, if we have

<thing> <owl:sameAs> <gizmo> .
<thing> <label> "thingy" .

and we instantiate ?s <label> "thingy" we get ?s bound to <thing>.

If we instantiate <gizmo> <label> ?l we get ?l bound to "thingy" because the subject was given and it was expanded to its synonyms.

If binding a variable in a pattern where the variable was free, we do not expand the value to the complete set of its synonyms.

Same-as expansion is enabled in a query by define input:same-as "yes" in the beginning of the SPARQL query. This has a significant run time cost but is in some cases useful when joining data between sets which are mapped to each other with same-as.

We note that the number of same-as expansions will depend on the join order used for the SPARQL query. The compiler does not know the number of synonyms and cannot set the join order accordingly. Regardless of the join order we will however get at least one IRI of the each synonym set as answer. Also when interactively navigating a graph with a browser, the same-as expansion will take all synonyms into account.

For getting the complete entailment of same-as, a forward chaining approach should be used, effectively asserting all the implied triples.


15.9.6. Implementation

Triples entailed by subclass or subproperty statements in an inference context are not physically stored. Such triples are added to the result set by the query run time as needed. Also queries involving subclass or subproperty rules are not rewritten into unions of all the possible triple patterns that might imply the pattern that is requested. Instead, the SQL compiler adds special nodes that iterate over subclasses or subproperties at run time. The cost model also takes subclasses and subproperties into account when determining the approximate cardinality of triple patterns.

In essence, Virtuoso's support for subclasses and subproperties is backward chaining, i.e. it does not materialize all implied triples but rather looks for the basic facts implying these triples at query evaluation time.


15.9.7. Enabling Inferencing

In a SPARQL query, the define input:inference clause is used to instruct the compiler to use the rules in the named rule set. For example:

SQL> rdfs_rule_set ('sample', 'rule_graph');

SQL> sparql define input:inference "sample" select * from <g> where {?s ?p ?o};

will include all the implied triples in the result set, using the rules in the sample rule set.

Inference can be enabled triple pattern by triple pattern. This is done with the option (inference 'rule_set') clause after the triple pattern concerned. Specifying option (inference none) will disable inference for the pattern concerned while the default inference context applies to the rest of the patterns. Note that the keyword is input:inference in the query header and simply inference in the option clause. See the examples section below for examples.

In SQL, if RDF_QUAD occurs in a select from clause, inference can be added with the table option WITH, as follows:

select * from rdf_quad table option (with 'sample') where g = iri_to_id ('xx', 0);

This is about the same as:

define input:inference "sample" select * from <xx> where {?s ?p ?o}

15.9.8. Examples

ttlp ('
   <http://localhost:8890/dataspace>  	                        <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://rdfs.org/sioc/ns#Space>.
   <http://localhost:8890/dataspace/test2/weblog/test2tWeblog>  <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://rdfs.org/sioc/types#Weblog> .
   <http://localhost:8890/dataspace/discussion/oWiki-test1Wiki> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://rdfs.org/sioc/types#MessageBoard>.
   <http://localhost:8890/dataspace>                            <http://rdfs.org/sioc/ns#link>                     <http://localhost:8890/ods> .
   <http://localhost:8890/dataspace/test2/weblog/test2tWeblog>  <http://rdfs.org/sioc/ns#link>                     <http://localhost:8890/dataspace/test2/weblog/test2tWeblog>.
   <http://localhost:8890/dataspace/discussion/oWiki-test1Wiki> <http://rdfs.org/sioc/ns#link>                     <http://localhost:8890/dataspace/discussion/oWiki-test1Wiki> .
   ', '', 'http://localhost:8890/test');

This loads data space instance data Triples into a Named Graph: <http://localhost:8890/test>

ttlp (' @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
  <http://rdfs.org/sioc/ns#Space> rdfs:subClassOf <http://www.w3.org/2000/01/rdf-schema#Resource> .
  <http://rdfs.org/sioc/ns#Container> rdfs:subClassOf <http://rdfs.org/sioc/ns#Space> .
  <http://rdfs.org/sioc/ns#Forum> rdfs:subClassOf <http://rdfs.org/sioc/ns#Container> .
  <http://rdfs.org/sioc/types#Weblog> rdfs:subClassOf <http://rdfs.org/sioc/ns#Forum> .
  <http://rdfs.org/sioc/types#MessageBoard> rdfs:subClassOf <http://rdfs.org/sioc/ns#Forum> .
  <http://rdfs.org/sioc/ns#link> rdfs:subPropertyOf <http://rdfs.org/sioc/ns> .
  ', '', 'http://localhost:8890/schema/test');

This loads a Triples into a Named Graph for schema/ontology data called: <http://localhost:8890/schema/test> that expresses assertions about subclasses and subproperties.

rdfs_rule_set ('http://localhost:8890/schema/property_rules1', 'http://localhost:8890/schema/test');

This defines the rule context http://localhost:8890/schema/property_rules1 that is initialized from the contents of graph http://localhost:8890/schema/test.

SQL>sparql define input:inference 'http://localhost:8890/schema/property_rules1' select ?s from <http://localhost:8890/test> where {?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>  <http://rdfs.org/sioc/ns#Space> };
s
VARCHAR
_______________________________________________________________________________

http://localhost:8890/dataspace/test2/weblog/test2tWeblog
http://localhost:8890/dataspace/discussion/oWiki-test1Wiki
http://localhost:8890/dataspace

3 Rows. -- 0 msec.

This returns the instances of http://rdfs.org/sioc/ns#Space. Since http://rdfs.org/sioc/types#Weblog and http://rdfs.org/sioc/types#MessageBoard are subclasses of http://rdfs.org/sioc/ns#Space, instances of http://rdfs.org/sioc/ns#Space, http://rdfs.org/sioc/types#Weblog and http://rdfs.org/sioc/types#MessageBoard are all returned. This results in the subjects http://localhost:8890/dataspace, http://localhost:8890/dataspace/test2/weblog/test2tWeblog and http://localhost:8890/dataspace/discussion/oWiki-test1Wiki.

SQL>select id_to_iri (s)
from rdf_quad table option (with 'http://localhost:8890/schema/property_rules1')
where g = iri_to_id ('http://localhost:8890/test',0)
  and p = iri_to_id ('http://www.w3.org/1999/02/22-rdf-syntax-ns#type', 0)
  and o = iri_to_id ('http://rdfs.org/sioc/ns#Space', 0);
callret
VARCHAR
_______________________________________________________________________________

http://localhost:8890/dataspace/test2/weblog/test2tWeblog
http://localhost:8890/dataspace/discussion/oWiki-test1Wiki
http://localhost:8890/dataspace

3 Rows. -- 10 msec.

This is the corresponding SQL query, internally generated by the SPARQL query.

Below we first look for all instances of http://rdfs.org/sioc/ns#Space with some property set to http://localhost:8890/dataspace/test2/weblog/test2tWeblog. We get the subject http://localhost:8890/dataspace/test2/weblog/test2tWeblog and the properties http://rdfs.org/sioc/ns#link and http://rdfs.org/sioc/ns. The join involves both subclass and subproperty inference. Then we turn off the inference for the second pattern and only get the property http://rdfs.org/sioc/ns#link. Then we do the same but now specify that inference should apply only to the first triple pattern.


SQL>sparql define input:inference  'http://localhost:8890/schema/property_rules1' select * from <http://localhost:8890/test>
where { ?s ?p <http://rdfs.org/sioc/ns#Space> . ?s ?p1 <http://localhost:8890/dataspace/test2/weblog/test2tWeblog> . };


s             p              p1
VARCHAR       VARCHAR       VARCHAR
_______________________________________________________________________________

http://localhost:8890/dataspace/test2/weblog/test2tWeblog  http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://rdfs.org/sioc/ns#link
http://localhost:8890/dataspace/test2/weblog/test2tWeblog  http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://rdfs.org/sioc/ns

2 Rows. -- 0 msec.


SQL>sparql  select * from <http://localhost:8890/test>
where { ?s ?p <http://rdfs.org/sioc/ns#Space> option (inference 'http://localhost:8890/schema/property_rules1') . ?s ?p1 <http://localhost:8890/dataspace/test2/weblog/test2tWeblog> . };

s             p              p1
VARCHAR       VARCHAR        VARCHAR
_______________________________________________________________________________

http://localhost:8890/dataspace/test2/weblog/test2tWeblog  http://www.w3.org/1999/02/22-rdf-syntax-ns#type http://rdfs.org/sioc/ns#link

1 Rows. -- 10 msec.

DBpedia example
ttlp ('
 prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
 <http://dbpedia.org/property/birthcity> rdfs:subPropertyOf <http://dbpedia.org/property/birthPlace> .
 <http://dbpedia.org/property/birthcountry> rdfs:subPropertyOf  <http://dbpedia.org/property/birthPlace> .
 <http://dbpedia.org/property/cityofbirth> rdfs:subPropertyOf <http://dbpedia.org/property/birthPlace> .
 <http://dbpedia.org/property/countryofbirth> rdfs:subPropertyOf <http://dbpedia.org/property/birthPlace> .
 <http://dbpedia.org/property/countyofbirth> rdfs:subPropertyOf <http://dbpedia.org/property/birthPlace> .
 <http://dbpedia.org/property/cityofdeath> rdfs:subPropertyOf <http://dbpedia.org/property/deathPlace> .
 <http://dbpedia.org/property/countryofdeath> rdfs:subPropertyOf <http://dbpedia.org/property/deathPlace> . "",
 'http://dbpedia.org/inference/rules#') ;

rdfs_rule_set ('http://dbpedia.org/schema/property_rules1', 'http://dbpedia.org/inference/rules#');
sparql
define input:inference 'http://dbpedia.org/schema/property_rules1'
prefix p: <http://dbpedia.org/property/>
select ?s from <http://dbpedia.org> where {?s p:birthcity ?o }
limit 50
s
VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/Britt_Janyk
http://dbpedia.org/resource/Chiara_Costazza
http://dbpedia.org/resource/Christoph_Gruber
http://dbpedia.org/resource/Daron_Rahlves
http://dbpedia.org/resource/Finlay_Mickel
http://dbpedia.org/resource/Genevi%C3%A8ve_Simard
http://dbpedia.org/resource/Johann_Grugger
http://dbpedia.org/resource/Kalle_Palander
http://dbpedia.org/resource/Marc_Gini
http://dbpedia.org/resource/Mario_Scheiber
http://dbpedia.org/resource/Prince_Hubertus_of_Hohenlohe-Langenburg
http://dbpedia.org/resource/Resi_Stiegler
http://dbpedia.org/resource/Steven_Nyman
http://dbpedia.org/resource/Hannes_Reichelt
http://dbpedia.org/resource/Jeremy_Transue

15 Rows. -- 167 msec.

sparql
define input:inference 'http://dbpedia.org/schema/property_rules1'
prefix p: <http://dbpedia.org/property/>
select ?s from <http://dbpedia.org> where {?s p:countryofbirth ?o }
limit 50
s
VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/A._J._Wood
http://dbpedia.org/resource/A._J._Godbolt
http://dbpedia.org/resource/Ac%C3%A1cio_Casimiro
http://dbpedia.org/resource/Adam_Fry
http://dbpedia.org/resource/Adam_Gilchrist
http://dbpedia.org/resource/Adam_Griffin
http://dbpedia.org/resource/Adam_Gross
...

50 Rows. -- 324 msec.

sparql
define input:inference 'http://dbpedia.org/schema/property_rules1'
prefix p: <http://dbpedia.org/property/>
select ?s from <http://dbpedia.org> where {?s p:countyofbirth ?o }
limit 50

s
VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/Eddie_Colman

1 Rows. -- 163 msec.

sparql
define input:inference 'http://dbpedia.org/schema/property_rules1'
prefix p: <http://dbpedia.org/property/>
select ?s from <http://dbpedia.org> where {?s p:birthPlace ?o }

s
VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/Eddie_Colman
http://dbpedia.org/resource/Jeremy_Transue
http://dbpedia.org/resource/Finlay_Mickel
http://dbpedia.org/resource/Prince_Hubertus_of_Hohenlohe-Langenburg
http://dbpedia.org/resource/Hannes_Reichelt
http://dbpedia.org/resource/Johann_Grugger
http://dbpedia.org/resource/Chiara_Costazza
...
155287 Rows. -- 342179 msec.

Loading script of the Yago Class hierarchy as inference rules example
--- Load Class Hierarchy into a Named Graph
select ttlp_mt (file_to_string_output ('yago-class-hierarchy_en.nt'),
'', 'http://dbpedia.org/resource/classes/yago#');

-- Create an  Inference Rule that references the Yago Class Hierarchy
Named Graph

SQL>rdfs_rule_set ('http://dbpedia.org/resource/inference/rules/yago#',
'http://dbpedia.org/resource/classes/yago#');

-- Query for the "The Lord of the Rings" which is a "Book" as
-- explicitly claimed in the DBpedia data set (instance data)

SQL>SPARQL
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dbpedia: <http://dbpedia.org/property/>
PREFIX yago: <http://dbpedia.org/class/yago/>

SELECT ?s
FROM <http://dbpedia.org>
WHERE {
?s a yago:Book106410904 .
?s dbpedia:name "The Lord of the Rings"@en .
};

s
VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/The_Lord_of_the_Rings

1 Rows. -- 321 msec.

-- Query aimed at Books via query scoped to the "Publication" class
-- of which it is a subclass in the Yago Hierarchy
SQL>SPARQL
define input:inference
'http://dbpedia.org/resource/inference/rules/yago#'
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dbpedia: <http://dbpedia.org/property/>
PREFIX yago: <http://dbpedia.org/class/yago/>

SELECT ?s
FROM <http://dbpedia.org>
WHERE {
?s a yago:Publication106589574 .
?s dbpedia:name "The Lord of the Rings"@en .
};

s
VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/The_Lord_of_the_Rings


-- # Variant of query with Virtuoso's Full Text Index extension: bif:contains
SQL>SPARQL
define input:inference
'http://dbpedia.org/resource/inference/rules/yago#'
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dbpedia: <http://dbpedia.org/property/>
PREFIX yago: <http://dbpedia.org/class/yago/>

SELECT ?s ?n
FROM <http://dbpedia.org>
WHERE {
?s a yago:Publication106589574 .
?s dbpedia:name ?n .
?n bif:contains 'Lord and Rings'
};

s                                                                                 n
VARCHAR                                                                           VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/The_Lord_of_the_Rings                                 The Lord of the Rings
http://dbpedia.org/resource/Journeys_of_Frodo                                     Journeys of Frodo: An Atlas of J. R. R. Tolkien's The Lord of the Ri
ngs
http://dbpedia.org/resource/The_Lord_of_the_Rings:_A_Reader%27s_Companion         The Lord of the Rings: A Reader's Companion
http://dbpedia.org/resource/Tolkien:_A_Look_Behind_%22The_Lord_of_the_Rings%22    A Look Behind "The Lord of the Rings""

4 Rows. -- 29573 msec.

-- Retrieve all individuals instances of the Book Class
SQL>SPARQL
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dbpedia: <http://dbpedia.org/property/>
PREFIX yago: <http://dbpedia.org/class/yago/>

SELECT ?s ?n
FROM <http://dbpedia.org>
WHERE {
?s a yago:Book106410904 .
?s dbpedia:name ?n .
}
limit 10;
s                                                                                 n
VARCHAR                                                                           VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/.hack//AI_buster                                      .hack// AI buster
http://dbpedia.org/resource/1000_Love_and_Sex_Quiz                                1000 Love and Sex Quiz
http://dbpedia.org/resource/1491:_New_Revelations_of_the_Americas_Before_Columbus  1491: New Revelations of the Americas Before Columbus
http://dbpedia.org/resource/.hack//AI_buster_2                                    .hack// AI buster 2
http://dbpedia.org/resource/100_Books_by_August_Derleth                           100 Books by August Derleth
http://dbpedia.org/resource/1634:_The_Baltic_War                                  1634: The Baltic War
http://dbpedia.org/resource/003%C2%BD:_The_Adventures_of_James_Bond_Junior        003-+: The Adventures of James Bond Junior"
http://dbpedia.org/resource/1001_Movies_You_Must_See_Before_You_Die               1001 Movies You Must See Before You Die
http://dbpedia.org/resource/1066_and_All_That                                     1066 and All That
http://dbpedia.org/resource/14%2C000_Things_to_be_Happy_About                     14,000 Things to be Happy About

10 Rows. -- 1422 msec.

-- Retrieve all individuals instances of Publication Class which
-- should include all Books.
SQL>SPARQL
define input:inference
'http://dbpedia.org/resource/inference/rules/yago#'
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dbpedia: <http://dbpedia.org/property/>
PREFIX yago: <http://dbpedia.org/class/yago/>

SELECT ?s ?n
FROM <http://dbpedia.org>
WHERE {
?s a yago:Publication106589574 .
?s dbpedia:name ?n .
};
s                                                                                 n
VARCHAR                                                                           VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/461_Ocean_Boulevard                                   461 Ocean Boulevard
http://dbpedia.org/resource/A_Love_Supreme                                        A Love Supreme
http://dbpedia.org/resource/A_Night_at_Red_Rocks_with_the_Colorado_Symphony_Orchestra  A Night at Red Rocks with the Colorado Symphony Orchestra
http://dbpedia.org/resource/At_Fillmore_East                                      At Fillmore East
http://dbpedia.org/resource/August_and_Everything_After                           August and Everything After
...