Using SPARQL for limited RDFS and OWL reasoning

2.8k views Asked by At

What I'm currently using rdflib for creating and managing RDF graphs in Python. RDFlib doesn't do any RDFS or OWL reasoning, though. This leads to results like the following:

  1. If I have

    A rdf:type MyType .
    MyType rdfs:subClassOf SuperType .
    

    and I ask

    select ?x where {?x rdf:type SuperType}
    

    then I get nothing, but I'd like to get A (by RDFS semantics).

  2. The same thing happens with owl:equivalentClass. If I have

    A rdf:type MyType .
    MyType owl:equivalentClass SiblingType .
    

    and I ask

    select ?x where {?x rdf:type SiblingType}
    

    I'd like to get A, but I get nothing.

Is there a way to get these results?

2

There are 2 answers

0
Vasiliy Faronov On

Edit: this answer was posted in response to the original, different question.

I should get A, but I get nothing!

No, you shouldn’t. RDF itself does not include anything about ontologies, it’s just a dumb graph, and that is what RDFLib does.

Going beyond this is called reasoning over the data. It’s an extra layer. Bare RDFLib does not do reasoning because it is complex and, in general, very computationally expensive. There are third-party solutions for reasoning, but before you employ them, you ought to understand what they do and what performance impact they will have.

A naive approach to RDFS and OWL 2 reasoning over an RDFLib graph is Ivan Herman’s OWL 2 RL implementation. It’s very easy to use, but you almost certainly don’t want it unless you’re doing a toy application, because it’s a dumb algorithm that takes very long on a graph of a realistic size.

FuXi is a more powerful library, implementing the smarter Rete-UL algorithm. But I’m not sure if it is maintained or if it’s usable with the current versions of RDFLib.

There is also a wealth of non-Python-based solutions for reasoning, such as Pellet, but integrating them with RDFLib—or any other RDF library—may be a chore.

You should also consider what kind of inference your application actually requires. Do you need to infer that subclass membership? If you do, maybe it’s all you need? — then maybe you could do it manually by iterating over the X rdfs:subClassOf Y triples with RDFLib and inserting the new A rdf:type Y triples.

In any case, remember that Semantic Web reasoning is a complex topic that depends heavily on the application.

5
Joshua Taylor On

Although this is a library request problem and, as such, off topic for StackOverflow, I would like to point out that for many cases, you can answer both of these queries using sightly more sophisticated SPARQL queries. For both of these cases, you could use the following query to get the results you want, where <class-of-interest> is :SuperClass or :SiblingClass:

select ?x where {
  ?x rdf:type/(rdfs:subClassOf|owl:equivalentClass)* <class-of-interest> .
}

This finds ?xs that have a path to starting with rdf:type and followed by zero or more of rdfs:subClassOf or owl:equivalentClass and eventually gets to :SuperType.

For instance, consider the following data in Turtle/N3. (As an aside, if you're asking questions about running queries against data, provide data that we can work with. You provided something sort of like RDF data in your question, but nothing that we could copy and paste and write a query against.)

@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix : <http://stackoverflow.com/q/20474862/1281433/>

:i1 a :C .
:C rdfs:subClassOf :D .
:D rdfs:subClassOf :E .

:i2 a :F .
:F rdfs:subClassOf :G1 .
:G1 owl:equivalentClass :G2 .
:G2 rdfs:subClassOf :H .

You can run a query like the one above to select individuals and their types (note that a is shorthand in SPARQL and Turtle/N3 for rdf:type):

prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix : <http://stackoverflow.com/q/20474862/1281433/>

select ?i ?type where {
  ?i a/(rdfs:subClassOf|owl:equivalentClass)* ?type
}
--------------
| i   | type |
==============
| :i2 | :F   |
| :i2 | :G1  |
| :i2 | :G2  |
| :i2 | :H   |
| :i1 | :C   |
| :i1 | :D   |
| :i1 | :E   |
--------------