www.openlinksw.com
docs.openlinksw.com

Book Home

Contents
Preface

RDF Data Access and Data Management

Data Representation
SPARQL
Extensions
RDF Graphs Security
Linked Data Views over RDBMS Data Source
Automated Generation of Linked Data Views over Relational Data Sources
Virtuoso R2RML Support
Examples of Linked Data Views
RDF Insert Methods in Virtuoso
RDFizer Middleware (Sponger)
Virtuoso Faceted Browser Installation and configuration
Virtuoso Faceted Web Service
Linked Data
Inference Rules & Reasoning
Introduction Making Rule Sets Changing Rule Sets Subclasses and Subproperties OWL sameAs Support Implementation Enabling Inferencing Examples Identity With Inverse Functional Properties Inference Rules and SPARQL with Transitivity Option Inference Rules, OWL Support and Relationship Ontology
RDF and Geometry
RDF Performance Tuning
RDF Data Access Providers (Drivers)
RDF Graph Replication

16.14. Inference Rules & Reasoning

16.14.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 Linked Data 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 pragma 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.


16.14.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 there 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.

The DB.DBA.SYS_RDF_SCHEMA table contains information for all RDF rule sets in a Virtuoso instance. This table may be queried to, for instance, verify rdfs_rule_set() activity:

CREATE TABLE DB.DBA.SYS_RDF_SCHEMA (
  RS_NAME VARCHAR,  -- The name of the rdf rule set
  RS_URI  VARCHAR,  -- The name of the graph
  RS_G    VARCHAR,  -- Column for system usage only
  PRIMARY KEY (RS_NAME, RS_URI))
)

16.14.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.


16.14.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.

Two methods can be used for typical recursions, transitivity on inference and plain transitive patterns (or subqueries).

The advantage of inference is that queries are short and one inference rule set may be maintained for numerous queries.

If queries are about trees of classes or properties, or about equivalences of nodes, consider using inference rule sets.

Transitive patterns are inconvenient and may easily result in queries that runs too long or hard to debug, but they're unavoidable in traversing social networks or plain querying of RDF lists.

So consider a rule set, a handful of nodes with classes from the rule set and a couple of RDF Lisp-style lists defined on demo.openlinksw.com:

SQL> SPARQL CLEAR GRAPH <http://example.com/2/owl>;
callret-0
VARCHAR
_______________________________________________________________________________

Clear <http://example.com/2/owl>  -- done

1 Rows. -- 0 msec.

SQL> TTLP (' @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
  @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>  .
  @prefix owl: <http://www.w3.org/2002/07/owl#>  .
  @prefix e: <http://example.com/e/>  .
  e:c1 rdfs:subClassOf e:c1or2 .
  e:c2 rdfs:subClassOf e:c1or2 .
  e:c1-10 rdfs:subClassOf e:c1 .
  e:c1-20 rdfs:subClassOf e:c1 .
  e:c2-30 rdfs:subClassOf e:c2 .
  e:c2-40 rdfs:subClassOf e:c2 .
  ', 'http://example.com/2/owl', 'http://example.com/2/owl' );

Done. -- 0 msec.

You can also use the SPARUL equivalent variant:

SPARQL
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX e: <http://example.com/e/>

INSERT IN GRAPH <http://example.com/2/owl>
  {
    e:c1 rdfs:subClassOf e:c1or2 .
    e:c2 rdfs:subClassOf e:c1or2 .
    e:c1-10 rdfs:subClassOf e:c1 .
    e:c1-20 rdfs:subClassOf e:c1 .
    e:c2-30 rdfs:subClassOf e:c2 .
    e:c2-40 rdfs:subClassOf e:c2 .
  } ;

Define the inference rule:

SQL> rdfs_rule_set ('http://example.com/2/owl', 'http://example.com/2/owl');

Done. -- 0 msec.

SQL> SPARQL CLEAR GRAPH <http://example.com/2/data> ;
callret-0
VARCHAR
_______________________________________________________________________________

Clear <http://example.com/2/data>  -- done

1 Rows. -- 0 msec.

SQL>  TTLP ('
  @prefix e: <http://example.com/e/>  .
  @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
  @prefix owl: <http://www.w3.org/2002/07/owl#>  .
  e:s1 a e:c1 ; e:p1 "Value of p1 for s1" .
  e:s2 a e:c2 ; e:p1 "Value of p1 for s2" .
  e:s1-10 a e:c1-10 ; e:p1 "Value of p1 for s1-10" .
  e:s1-20 a e:c1-20 ; e:p1 "Value of p1 for s1-20" .
  e:s2-30 a e:c2-30 ; e:p1 "Value of p1 for s2-30" .
  e:s2-40 a e:c2-40 ; e:p1 "Value of p1 for s2-40" .
  e:lists
       rdf:_1 ( e:list1-item1 e:list1-item2 e:list1-item3 ) ;
       rdf:_2 (
           [ e:p2 "Value of p2 of item1 of list2" ; e:p3 "Value of p3 of item1 of list2" ]
           [ e:p2 "Value of p2 of item2 of list2" ; e:p3 "Value of p3 of item2 of list2" ]
           [ e:p2 "Value of p2 of item3 of list2" ; e:p3 "Value of p3 of item3 of list2" ] ) .
  ', 'http://example.com/2/data', 'http://example.com/2/data' );

Done. -- 0 msec.

You can also use the SPARUL equivalent variant:

SPARQL
PREFIX e: <http://example.com/e/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>

INSERT IN GRAPH <http://example.com/2/data>
  {
    e:s1 a e:c1 ; e:p1 "Value of p1 for s1" .
    e:s2 a e:c2 ; e:p1 "Value of p1 for s2" .
    e:s1-10 a e:c1-10 ; e:p1 "Value of p1 for s1-10" .
    e:s1-20 a e:c1-20 ; e:p1 "Value of p1 for s1-20" .
    e:s2-30 a e:c2-30 ; e:p1 "Value of p1 for s2-30" .
    e:s2-40 a e:c2-40 ; e:p1 "Value of p1 for s2-40" .
    e:lists
      rdf:_1 ( e:list1-item1 e:list1-item2 e:list1-item3 ) ;
      rdf:_2 (
           [ e:p2 "Value of p2 of item1 of list2" ; e:p3 "Value of p3 of item1 of list2" ]
           [ e:p2 "Value of p2 of item2 of list2" ; e:p3 "Value of p3 of item2 of list2" ]
           [ e:p2 "Value of p2 of item3 of list2" ; e:p3 "Value of p3 of item3 of list2" ] )
  };

SPARQL DESCRIBE works fine with inference, deriving additional type information:

DEFINE input:inference <http://example.com/2/owl>
DESCRIBE <http://example.com/e/s1>
FROM <http://example.com/2/data>

fmtaggret-
LONG VARCHAR
_______________________________________________________________________________

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
@prefix ns1: <http://example.com/e/>  .
ns1:s1 rdf:type ns1:c1or2 ,
ns1:c1 ;
ns1:p1 "Value of p1 for s1" .

1 Rows. -- 0 msec.

Example links against Virtuoso Demo Server SPARQL Endpoint with SPARQl Protocol URLs:

DEFINE input:inference <http://example.com/2/owl>
DESCRIBE <http://example.com/e/s2>
FROM <http://example.com/2/data>
fmtaggret-
LONG VARCHAR
_______________________________________________________________________________

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>  .
@prefix ns1: <http://example.com/e/>  .
ns1:s2 rdf:type ns1:c1or2 ,
ns1:c2 ;
ns1:p1 "Value of p1 for s2" .

1 Rows. -- 0 msec.

Example links against Virtuoso Demo Server SPARQL Endpoint with SPARQl Protocol URLs:

Querying is simple as well:

SQL>SPARQL DEFINE input:inference <http://example.com/2/owl>
PREFIX e:<http://example.com/e/>
SELECT *
FROM <http://example.com/2/data>
WHERE
  {
    ?s a e:c1or2 ;
          e:p1 ?o
  }

s                            o
VARCHAR                      VARCHAR
___________________________

http://example.com/e/s1      Value of p1 for s1
http://example.com/e/s1-10   Value of p1 for s1-10
http://example.com/e/s1-20   Value of p1 for s1-20
http://example.com/e/s2-30   Value of p1 for s2-30
http://example.com/e/s2-40   Value of p1 for s2-40
http://example.com/e/s2      Value of p1 for s2

6 Rows. -- 0 msec.

Example links against Virtuoso Demo Server SPARQL Endpoint with SPARQl Protocol URLs:

SQL>SPARQL DEFINE input:inference <http://example.com/2/owl>
PREFIX e:<http://example.com/e/>
SELECT * FROM <http://example.com/2/data>
WHERE
  {
    ?s a e:c1 ;
       e:p1 ?o
  }

s                            o
VARCHAR                      VARCHAR
___________________________

http://example.com/e/s1      Value of p1 for s1
http://example.com/e/s1-10   Value of p1 for s1-10
http://example.com/e/s1-20   Value of p1 for s1-20

3 Rows. -- 0 msec.

Example links against Virtuoso Demo Server SPARQL Endpoint with SPARQl Protocol URLs:

However you should care about duplicates if both types and properties are queried: the join will result in all combinations of types and property values.

SQL>SPARQL DEFINE input:inference <http://example.com/2/owl>
PREFIX e:<http://example.com/e/>
SELECT * FROM <http://example.com/2/data>
WHERE
  {
    ?s a ?t ;
     e:p1 ?o
  }

s                            t                            o
VARCHAR                      VARCHAR                      VARCHAR
___________________________

http://example.com/e/s1      http://example.com/e/c1      Value of p1 for s1
http://example.com/e/s1      http://example.com/e/c1or2   Value of p1 for s1
http://example.com/e/s1-10   http://example.com/e/c1-10   Value of p1 for s1-10
http://example.com/e/s1-10   http://example.com/e/c1      Value of p1 for s1-10
http://example.com/e/s1-10   http://example.com/e/c1or2   Value of p1 for s1-10
http://example.com/e/s1-20   http://example.com/e/c1-20   Value of p1 for s1-20
http://example.com/e/s1-20   http://example.com/e/c1      Value of p1 for s1-20
http://example.com/e/s1-20   http://example.com/e/c1or2   Value of p1 for s1-20
http://example.com/e/s2-30   http://example.com/e/c2-30   Value of p1 for s2-30
http://example.com/e/s2-30   http://example.com/e/c2      Value of p1 for s2-30
http://example.com/e/s2-30   http://example.com/e/c1or2   Value of p1 for s2-30
http://example.com/e/s2-40   http://example.com/e/c2-40   Value of p1 for s2-40
http://example.com/e/s2-40   http://example.com/e/c2      Value of p1 for s2-40
http://example.com/e/s2-40   http://example.com/e/c1or2   Value of p1 for s2-40
http://example.com/e/s2      http://example.com/e/c2      Value of p1 for s2
http://example.com/e/s2      http://example.com/e/c1or2   Value of p1 for s2

16 Rows. -- 0 msec.

Example links against Virtuoso Demo Server SPARQL Endpoint with SPARQl Protocol URLs:

Transitive queries are convenient as SPARQL 1.1 "predicate+" equivalent. The equivalent of "predicate*" requires the use of a union:

SQL>SPARQL PREFIX e:<http://example.com/e/>
SELECT ?item
FROM <http://example.com/2/data>
WHERE
  {
    {
      ?lists rdf:_1 ?node
    }
    UNION
    {
      ?lists rdf:_1 ?l .
      ?l rdf:rest ?node option (transitive) .
    }
    ?node rdf:first ?item
  }

item
VARCHAR
_______________________________________________________________________________

http://example.com/e/list1-item1
http://example.com/e/list1-item2
http://example.com/e/list1-item3

3 Rows. -- 0 msec.

Example links against Virtuoso Demo Server SPARQL Endpoint with SPARQl Protocol URLs:

SQL> SPARQL PREFIX e:<http://example.com/e/>
SELECT ?p ?o
FROM <http://example.com/2/data>
WHERE
  {
    {
      ?lists rdf:_2 ?node
    }
    UNION
    {
      ?lists rdf:_2 ?l .
      ?l rdf:rest ?node option (transitive) .
    }
    ?node rdf:first ?item .
    ?item ?p ?o
  }

p                         o
VARCHAR                   VARCHAR
________________________

http://example.com/e/p2   Value of p2 of item1 of list2
http://example.com/e/p3   Value of p3 of item1 of list2
http://example.com/e/p2   Value of p2 of item2 of list2
http://example.com/e/p3   Value of p3 of item2 of list2
http://example.com/e/p2   Value of p2 of item3 of list2
http://example.com/e/p3   Value of p3 of item3 of list2

6 Rows. -- 0 msec.

Example links against Virtuoso Demo Server SPARQL Endpoint with SPARQl Protocol URLs:

Note that the result set can be in order of items in the list, but it don't have to. If the order should be preserved, then fix the direction of transitive scan, get step number as a variable, order by that variable.

-- Line 82:
SQL> SPARQL PREFIX e:<http://example.com/e/>
SELECT ?p ?o bif:coalesce(?step_no, 0)
FROM <http://example.com/2/data>
WHERE
  {
    {
      ?lists rdf:_2 ?node
    }
    UNION
    {
      ?lists rdf:_2 ?l .
      ?l rdf:rest ?node OPTION (transitive, t_direction 1, t_step("step_no") as ?step_no) .
    }
    ?node rdf:first ?item .
    ?item ?p ?o
  }
ORDER BY ASC (?step_no)

p                         o                               callret-2
VARCHAR                   VARCHAR                         VARCHAR
________________________

http://example.com/e/p2   Value of p2 of item1 of list2   0
http://example.com/e/p3   Value of p3 of item1 of list2   0
http://example.com/e/p2   Value of p2 of item2 of list2   1
http://example.com/e/p3   Value of p3 of item2 of list2   1
http://example.com/e/p2   Value of p2 of item3 of list2   2
http://example.com/e/p3   Value of p3 of item3 of list2   2

6 Rows. -- 7 msec.

Example links against Virtuoso Demo Server SPARQL Endpoint with SPARQl Protocol URLs:


16.14.5. OWL sameAs Support

Virtuoso has limited support for the OWL sameAs predicate.

If sameAs 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 sameAs triples from all the graphs applicable to instantiating the triple pattern at hand are considered.

Thus for example:

The inital SPARQL query:

SQL>SPARQL
prefix foaf: <http://xmlns.com/foaf/0.1/>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix sioc: <http://rdfs.org/sioc/ns#>
SELECT *
from <http://myopenlink.net/dataspace>
where
 {
    ?person a foaf:Person FILTER REGEX(?person ,"http://myopenlink.net/dataspace/person/kidehen#this").
    ?person foaf:name ?name .
    ?person owl:sameAs ?sameas .
  }
limit 10;
person                                               name             sameas
VARCHAR                                              VARCHAR          VARCHAR
_______________________________________________________________________________

http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://www.openlinksw.com/dataspace/person/kidehen@openlinksw.com#this
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://my.openlinksw.com/dataspace/person/kidehen@openlinksw.com#this
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://kidehen.idehen.net/dataspace/person/kidehen#this
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://qdos.com/user/e922b748a2eb667bf37b188018002dec
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://knowee.net/kidehen/ids/id3684976382
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://dbpedia.org/resource/Kingsley_Idehen
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://dbtune.org/last-fm/kidehen
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://revyu.com/people/kidehen
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://identi.ca/user/14092
http://myopenlink.net/dataspace/person/kidehen#this  Kingsley Idehen  http://myopenlink.net/proxy?url=http%3A%2F%2Fwww.facebook.com%2Fpeople%2FKingsley_Idehen%2F605980750&force=rdf&login=kidehen

10 Rows. -- 181 msec.

So if we have:

<http://myopenlink.net/dataspace/person/kidehen#this>  	<http://www.w3.org/2002/07/owl#sameAs> <http://www.openlinksw.com/dataspace/person/kidehen@openlinksw.com#this> .
<http://myopenlink.net/dataspace/person/kidehen#this>  	<http://xmlns.com/foaf/0.1/name>  	Kingsley Idehen

and we instantiate ?s <http://xmlns.com/foaf/0.1/name> "Kingsley Idehen" we get ?s bound to <http://myopenlink.net/dataspace/person/kidehen#this>.

If we instantiate <http://www.openlinksw.com/dataspace/person/kidehen@openlinksw.com#this> <http://xmlns.com/foaf/0.1/name> ?l we get ?l bound to "Kingsley Idehen" 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.

16.14.5.1. OWL sameAs Example

SQL>SPARQL
DEFINE input:same-as "yes"
SELECT *
WHERE
 {
   ?s <http://xmlns.com/foaf/0.1/name> "Kingsley Idehen" .
 }
LIMIT 10;

s
VARCHAR
___________________________________________________
http://myopenlink.net/dataspace/person/kidehen#this
http://myopenlink.net/dataspace/person/kidehen#this
http://myopenlink.net/dataspace/person/kidehen#this
http://myopenlink.net/dataspace/person/kidehen#this
http://myopenlink.net/dataspace/person/kidehen#this
http://myopenlink.net/dataspace/person/kidehen#this
http://demo.openlinksw.com/dataspace/kingsley#person
http://myopenlink.net/dataspace/person/kidehen#this
http://myopenlink.net/dataspace/person/kidehen#this
http://myopenlink.net/dataspace/person/kidehen#this
No. of rows in result: 10


16.14.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.


16.14.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:

SPARQL
SELECT *
FROM rdf_quad table OPTION (with 'sample')
WHERE g = iri_to_id ('xx', 0);

This is about the same as:

SPARQL
define input:inference "sample"
SELECT *
FROM <xx>
WHERE {?s ?p ?o}

16.14.8. Examples

16.14.8.1. Example for loading data space instance data Triples into a Named Graph for schema/ontology data

The following example shows how to load data space instance data Triples into a Named Graph: <http://localhost:8890/test>, for schema/ontology data called: <http://localhost:8890/schema/test> that expresses assertions about subclasses and subproperties.

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');
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');
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.


16.14.8.2. 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#');
SQL>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.

SQL>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.

SQL>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.

SQL>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.


16.14.8.3. Example for loading script of the Yago Class hierarchy as inference rules

--- 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 "Fantasy Novel" 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 <http://dbpedia.org/class/yago/FantasyNovels> .
  ?s dbpedia:name "The Lord of the Rings"@en .
};

s
VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/The_Lord_of_the_Rings

1 Rows. -- 241 msec.

-- Query aimed at Novel via query scoped to the "Fiction" 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 <http://dbpedia.org/class/yago/Fiction106367107> .
?s dbpedia:name "The Lord of the Rings"@en .
};

s
VARCHAR
_______________________________________________________________________________


http://dbpedia.org/resource/The_Lord_of_the_Rings
http://dbpedia.org/resource/The_Lord_of_the_Rings
http://dbpedia.org/resource/The_Lord_of_the_Rings
http://dbpedia.org/resource/The_Lord_of_the_Rings

4 Rows. -- 4767 msec.


-- # 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 <http://dbpedia.org/class/yago/Fiction106367107> .
?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/The_Lord_of_the_Rings    The Lord of the Rings
http://dbpedia.org/resource/The_Lord_of_the_Rings    The Lord of the Rings
http://dbpedia.org/resource/The_Lord_of_the_Rings    The Lord of the Rings

4 Rows. -- 5538 msec.

-- Retrieve all individuals instances of the FantasyNovels 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 <http://dbpedia.org/class/yago/FantasyNovels> .
  ?s dbpedia:name ?n .
}
limit 10;
s                                                                                 n
VARCHAR                                                                           VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/ATLA_-_A_Story_of_the_Lost_Island                     Atla
http://dbpedia.org/resource/A_Crown_of_Swords                                     A Crown of Swords
http://dbpedia.org/resource/A_Game_of_Thrones                                     A Game of Thrones
http://dbpedia.org/resource/A_Secret_Atlas                                        A Secret Atlas
http://dbpedia.org/resource/A_Storm_of_Swords                                     A Storm of Swords
http://dbpedia.org/resource/A_Voyage_to_Arcturus                                  A Voyage to Arcturus
http://dbpedia.org/resource/A_Wizard_Alone                                        A Wizard Alone
http://dbpedia.org/resource/Above_the_Veil                                        Above the Veil
http://dbpedia.org/resource/Black_Easter                                          Black Easter
http://dbpedia.org/resource/Lord_of_Chaos                                         Lord of Chaos

10 Rows. -- 781 msec.

-- Retrieve all individuals instances of Fiction Class which should
-- include all Novels.
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 <http://dbpedia.org/class/yago/Fiction106367107> .
?s dbpedia:name ?n .
};
s                                                                                 n
VARCHAR                                                                           VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/Last_Son_of_Krypton                                   Last Son of Krypton
http://dbpedia.org/resource/Tuvaluan_language                                     Tuvaluan
http://dbpedia.org/resource/Card_Walker                                           E. Cardon Walker
http://dbpedia.org/resource/Les_Clark                                             Les Clark
http://dbpedia.org/resource/Marc_Davis                                            Marc Davis
http://dbpedia.org/resource/Eric_Larson                                           Eric Larson
http://dbpedia.org/resource/Marty_Sklar                                           Marty Sklar
http://dbpedia.org/resource/Peter_Ellenshaw                                       Peter Ellenshaw
http://dbpedia.org/resource/Adriana_Caselotti                                     Adriana Caselotti
http://dbpedia.org/resource/Jimmie_Dodd                                           Jimmie Dodd
...
15296 Rows.

16.14.8.4. Pure SPARQL Example

-- Query aimed at Fantasy Novel via query scoped to the "Fiction" 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 <http://dbpedia.org/class/yago/Fiction106367107> .
?s dbpedia:name "The Lord of the Rings"@en .
};
s
VARCHAR
_______________________________________________________________________________

http://dbpedia.org/resource/The_Lord_of_the_Rings
http://dbpedia.org/resource/The_Lord_of_the_Rings
http://dbpedia.org/resource/The_Lord_of_the_Rings
http://dbpedia.org/resource/The_Lord_of_the_Rings

4 Rows. -- 150 msec.

16.14.8.5. Example for equivalence between classes

This example is based on UMBEL and DBpedia integration:

-- Load UMBEL & DBpedia Instance Level Cross-Links (owl:sameAs) Triples
SELECT ttlp_mt (file_to_string_output ('umbel_dbpedia_linkage_v071.n3'), '', 'http://dbpedia.org');

-- Load UMBEL and DBpedia Type (rdf:type) association Triples
SELECT ttlp_mt (file_to_string_output ('umbel_dbpedia_types_v071.n3'), '', 'http://dbpedia.org');

--- Load UMBEL Subject Concept Class Hierarchy into a Named Graph
SELECT ttlp_mt (file_to_string_output ('umbel_class_hierarchy_v071.n3'), '', 'http://dbpedia.org/resource/classes/umbel#');

--- load UMBEL Subject Concepts Instance Data
SELECT ttlp_mt (file_to_string_output ('umbel_subject_concepts.n3'), '', 'http://dbpedia.org/resource/classes/umbel#');

--- Load UMBEL Abstract Concepts Instance Data
SELECT ttlp_mt (file_to_string_output ('umbel_abstract_concepts.n3'), '', 'http://dbpedia.org/resource/classes/umbel#');


-- Load UMBEL External Ontology Mapping into a Named Graph
SELECT ttlp_mt (file_to_string_output ('umbel_external_ontologies_linkage.n3'), '', 'http://dbpedia.org/resource/classes/umbel#');

-- Create UMBEL Inference Rules

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

Now let's execute the following queries:

SQL>SPARQL define input:inference "http://dbpedia.org/resource/inference/rules/umbel#"
prefix umbel: <http://umbel.org/umbel/sc/>
PREFIX dbpedia: <http://dbpedia.org/property/>
prefix opencyc: <http://sw.opencyc.org/2008/06/10/concept/en/>
SELECT ?s
where
{
 ?s a opencyc:Motorcycle.
 ?s dbpedia:name ?n.
 ?n bif:contains "BMW".
};

s
____________________________________________
http://dbpedia.org/resource/BMW_K1200GT
http://dbpedia.org/resource/BMW_F650CS
http://dbpedia.org/resource/BMW_C1
http://dbpedia.org/resource/BMW_R75
4 Rows. -- 26 msec.
SQL>SPARQL define input:inference "http://dbpedia.org/resource/inference/rules/umbel#"
prefix umbel: <http://umbel.org/umbel/sc/>
PREFIX dbpedia: <http://dbpedia.org/property/>
prefix opencyc: <http://sw.opencyc.org/2008/06/10/concept/en/>
SELECT ?s
where
{
 ?s a umbel:Motorcycle.
 ?s dbpedia:name ?n.
 ?n bif:contains "BMW".
};

s
____________________________________________
http://dbpedia.org/resource/BMW_K1200GT
http://dbpedia.org/resource/BMW_F650CS
http://dbpedia.org/resource/BMW_C1
http://dbpedia.org/resource/BMW_R75
4 Rows. -- 26 msec.

16.14.8.6. Example for finding celebrities which are not fans of their own fans

SQL>SPARQL
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX sioc: <http://rdfs.org/sioc/ns#>
INSERT INTO GRAPH <urn:rules.skos> { foaf:knows rdfs:subPropertyOf sioc:follows . };

callret-0
VARCHAR
Insert into <urn:rules.skos>, 1 triples -- done
No. of rows in result: 1

SQL>rdfs_rule_set ('foaf-trans', 'urn:rules.skos');

Done.

SPARQL>SPARQL
DEFINE input:inference "foaf-trans"
PREFIX sioc: <http://rdfs.org/sioc/ns#>
SELECT ?celeb COUNT (*)
WHERE
  {
    ?claimant sioc:follows ?celeb .
    FILTER
      (
        !bif:exists
         (
           ( SELECT (1)
             WHERE
               {
                 ?celeb sioc:follows ?claimant
               }
           )
         )
      )
  }
GROUP BY ?celeb
ORDER BY DESC 2
LIMIT 10

celeb                                                                            callret-1
ANY 	                                                                         ANY
__________________________________________________________________________________________
http://localhost.localdomain/about/id/entity/http/twitter.com/kidehen	         100
http://localhost.localdomain/about/id/entity/http/twitter.com/shawnafennell	 77
http://localhost.localdomain/about/id/entity/http/twitter.com/thines01	         71
http://localhost.localdomain/about/id/entity/http/twitter.com/mhausenblas	 50
http://localhost.localdomain/about/id/entity/http/twitter.com/DirDigEng	         2
http://localhost.localdomain/about/id/entity/http/twitter.com/SarahPalinUSA	 1
http://localhost.localdomain/about/id/entity/http/twitter.com/zbrox	         1
http://localhost.localdomain/about/id/entity/http/twitter.com/LamarLee	         1
http://localhost.localdomain/about/id/entity/http/twitter.com/HackerChick	 1
http://localhost.localdomain/about/id/entity/http/twitter.com/programmingfeed	 1
No. of rows in result: 10


16.14.9. Identity With Inverse Functional Properties

A graph used used with rdfs_rule_set may declare certain properties to be inversely functional. If one or more inverse functional properties (IFP's) are declared in the inference context used with the query, enabled with define input:inference = "context_name", then the following semantics apply:

  1. If a literal is compared with an IRI, then the literal is substituted by all the subject IRI's where this literal occurs as a value of an IFP.
  2. If two IRI's are compared for equality, they will be considered the same if there is an IFP P such that the same P has the same value on both subjects.
  3. If an IRI is processed for distinctness in either distinct or group by, the IRI is first translated to be the IRI with the lowest ID among all IRI's that share an IFP value with this IRI.

Thus, if two IRI's are compared for distinctness, they will count as one if there is an IFP P with the same value with both IRI's. Literal data types are not translated into IRI's even if these literals occurred as IFP values of some subject.

It is possible to declare that specific values, even if they occur as values of an IFP in more than onme subject do not constitute identity between the subjects. For example, if two subjects were inferred to be the same because they had the same foaf:mbox_sha1sum, the SHA1 hash of mailto:// would be excluded. Two individuals have an email address that has a common default value are not the same.

In an ontology graph, a property IRI is declared to be inversely functional by making it an instance of the owl:InverseFunctionalProperty class. A value of an IFP can be declared null, i.e. sharing the value does not imply identity by by giving the IFP IRI a <http://www.openlinksw.com/schemas/virtrdf#nullIFPValue> property with the value to be ignored as the object.

Example
  SQL>ttlp ('
  <john1> a <person> .
  <john2> a <person> .
  <mary> a <person> .
  <mike> a <person> .
  <john1> <name> "John" .
  <john2> <name> "John" .
  <john1> <address> "101 A street" .
  <john2> <address> "102 B street" .
  <john2> <knows> <mike> .
  <john1> <http://www.w3.org/2002/07/owl#sameAs> <john2> .
  <mary> <knows> "John" .
  <mike> <knows> <john1> .
  <mike> <knows> <john2> .
  <john1> <name> "Tarzan" .
  <mike> <nam> "Tarzan" .
  ', '', 'ifps');


  SQL>ttlp ('
  <name> a <http://www.w3.org/2002/07/owl#InverseFunctionalProperty> .
  <name> <http://www.openlinksw.com/schemas/virtrdf#nullIFPValue> "Tarzan" .
  ', '', 'ifp_list');

  SQL>rdfs_rule_set ('ifps', 'ifp_list');

  SQL>SPARQL define input:inference "ifps"  SELECT * FROM <ifps> WHERE {<john1> ?p ?o};

  p                                                                                 o
  VARCHAR                                                                           VARCHAR
  _______________________________________________________________________________

  address                                                                           101 A street
  name                                                                              John
  http://www.w3.org/2002/07/owl#sameAs                                              john2
  http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                   person
  name                                                                              Tarzan
  name                                                                              John
  knows                                                                             mike
  http://www.w3.org/1999/02/22-rdf-syntax-ns#type                                   person
  address                                                                           102 B street
  

We see that we get the properties of <john2> also.

  SQL>SPARQL define input:inference "ifps" SELECT distinct ?p FROM <ifps> WHERE { ?p a <person>};

  john2
  mike
  mary
  

We see that we get only one John. But John is not the same as Mike because they share the name Tarzan which is not considered as implying identity. Which John we get is a matter of which gets the lowest internal ID. This is variable and arbitrary at load time but once loaded this is permanent as long as the set of subjects with the name John does not change.


16.14.10. Inference Rules and SPARQL with Transitivity Option


16.14.11. Inference Rules, OWL Support and Relationship Ontology

This section provides queries usage for inference rules, owl support and Relationship Vocabulary.

16.14.11.1. Example 1

Example based on Relationship Vocab:

## Verify Ontology Data is in Quad Store
## Ontology: <http://vocab.org/relationship/> (Relationship Ontology)
## Use pragma to put latest in Quad store.

DEFINE get:soft "replace"
SELECT *
FROM <http://vocab.org/relationship/>
WHERE {?s ?p ?o}

## Clean up

CLEAR GRAPH <urn:owl.tests>

## Create Instance Data for Relationship Ontology
PREFIX rel: <http://purl.org/vocab/relationship/>

INSERT into GRAPH <urn:owl.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>.
  };

## Verify

SELECT *
FROM  <urn:owl.tests>
WHERE
  {
    ?s ?p ?o
  }

## Create an  Inference Rule that references the Relationship Ontology Named Graph

rdfs_rule_set ('urn:owl.tests', 'http://vocab.org/relationship') ;

## Verify Rule's existence

SELECT * FROM SYS_RDF_SCHEMA ;

16.14.11.2. Example 2

## Test owl:TransitiveProperty Reasoning
## Start with a specific URI
## Goal: See inferred Triples
## In this case, relationship between: <http://dbpedia.org/resource/Elizabeth_Bowes-Lyon>
## and her descendants: Queen Elizabeth, Prince Charles, Prince William, and Prince Harry)


DEFINE input:inference 'urn:owl.tests'
PREFIX rel: <http://purl.org/vocab/relationship/>
SELECT *
FROM <urn:owl.tests>
WHERE
  {
    <http://dbpedia.org/resource/Elizabeth_Bowes-Lyon> rel:ancestorOf ?o
  }

16.14.11.3. Example 3

## Test owl:SymmetricalProperty Reasoning
## Should show same result irrespective of rel:siblingOf URI in Subject or Object slots of Triple

DEFINE input:inference 'urn:owl.tests'
PREFIX rel: <http://purl.org/vocab/relationship/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

SELECT *
FROM <urn:owl.tests>
WHERE
  {
    <http://dbpedia.org/resource/Prince_William_of_Wales> rel:siblingOf ?o
  }

## OR

DEFINE input:inference 'urn:owl.tests'
PREFIX rel: <http://purl.org/vocab/relationship/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

SELECT *
FROM <urn:owl.tests>
WHERE
  {
    ?s rel:siblingOf <http://dbpedia.org/resource/Prince_William_of_Wales>
  }

16.14.11.4. Example 4

## Test owl:inverseOf Reasoning
## Should show triples exposing the inverseOf relation.
## In this case rel:ancestorOf instance data triples exist,so the system must infer rel:descendant Of triples

DEFINE input:inference 'urn:owl.tests'
PREFIX rel: <http://purl.org/vocab/relationship/>

SELECT *
FROM <urn:owl.tests>
WHERE
  {
    <http://dbpedia.org/resource/Elizabeth_II_of_the_United_Kingdom> rel:descendantOf ?o
  }

## OR with Transitivity Option applied

DEFINE input:inference 'urn:owl.tests'
PREFIX rel: <http://purl.org/vocab/relationship/>

SELECT *
FROM <urn:owl.tests>
WHERE
  {
    <http://dbpedia.org/resource/Prince_William_of_Wales> rel:descendantOf ?o
    OPTION (T_DISTINCT)
  }

16.14.11.5. Example 5

## Test owl:inverseOf Reasoning
## Should show triples exposing the inverseOf relation.
## In this case rel:employedBy instance data triples exist,
## the system must infer rel:employerOf triples.

DEFINE input:inference 'urn:owl.tests'
PREFIX rel: <http://purl.org/vocab/relationship/>

SELECT *
FROM <urn:owl.tests>
WHERE
  {
    ?s rel:employerOf ?o
  }

16.14.11.6. Example 6

Example based on Relationship Vocab and SKOS

Assume the following test10.rdf file:

<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
	xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
	xmlns:daml="http://www.daml.org/2001/03/daml+oil#"
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:skos="http://www.w3.org/2004/02/skos/core#"
	xmlns:owl="http://www.w3.org/2002/07/owl#"
	xmlns:turnguard="http://www.turnguard.com#"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:sea="http://www.2sea.org/"
	xmlns:foaf="http://xmlns.com/foaf/0.1/"
	xmlns:dct="http://purl.org/dc/terms/">

<rdf:Description rdf:about="http://www.turnguard.com/Music">
	<rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
	<skos:prefLabel xml:lang="en">Music</skos:prefLabel>
	<skos:narrower rdf:resource="http://www.turnguard.com/Pop" />
</rdf:Description>
<rdf:Description rdf:about="http://www.turnguard.com/Pop">
      <rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
		<skos:prefLabel xml:lang="en">POP</skos:prefLabel>
      <skos:narrower rdf:resource="http://www.turnguard.com/TechnoPop" />
</rdf:Description>
<rdf:Description rdf:about="http://www.turnguard.com/TechnoPop">
        <rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
        <skos:prefLabel xml:lang="en">TECHNOPOP</skos:prefLabel>
        <skos:narrower rdf:resource="http://www.turnguard.com/ElectroPop" />
</rdf:Description>

<rdf:Description rdf:about="http://www.turnguard.com/ElectroPop">
        <rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
        <skos:prefLabel xml:lang="en">ELECTROPOP</skos:prefLabel>
</rdf:Description>
<rdf:Description rdf:about="http://www.turnguard.com/KrautRock">
        <rdf:type rdf:resource="http://www.w3.org/2004/02/skos/core#Concept"/>
        <skos:prefLabel xml:lang="en">KrautRock</skos:prefLabel>
	<skos:related rdf:resource="http://www.turnguard.com/ElectroPop" />
</rdf:Description>
</rdf:RDF>

Execute the following steps:

## Graph Cleanup
CLEAR GRAPH <urn:owl.test2.tbox>
CLEAR GRAPH <http://turnguard.com/virtuoso/test10.rdf>

## Load Instance Data into Quad Store
## PL Procedure

## SQL realm
DB.DBA.RDF_LOAD_RDFXML
  (
    http_get('http://www.w3.org/2009/08/skos-reference/skos-owl1-dl.rdf'),
    'no',
    'urn:owl.test2.tbox'
  );
DB.DBA.RDF_LOAD_RDFXML
  (
    http_get ('http://www.w3.org/2002/07/owl.rdf'),
    'no',
    'urn:owl.test2.tbox'
  );
DB.DBA.RDF_LOAD_RDFXML
  (
    file_to_string ('test10.rdf'),
    'no',
    'http://turnguard.com/virtuoso/test10.rdf'
  );



SELECT *
FROM <http://www.w3.org/2004/02/skos/core>
WHERE
  {
    {
      <http://www.w3.org/2004/02/skos/core#related> ?p ?o
    }
    UNION
    {
      ?s ?p <http://www.w3.org/2004/02/skos/core#related>
    }
  }


## Create Rules
## SQL Realm

rdfs_rule_set ('urn:owl.test2.rules', 'urn:owl.test2.tbox');


## Transitivity Query re. SKOS concept hierarchy

DEFINE input:inference "urn:owl.test2.rules"
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>

SELECT *
FROM <http://turnguard.com/virtuoso/test10.rdf>
WHERE
  {
    <http://www.turnguard.com/ElectroPop> skos:broaderTransitive ?o
    OPTION  (T_DISTINCT).
  }