Question

Suppose I have a class (cls), an object property (has_part) and an individual (ind). The individual is rdf:type'd to be (in manchester syntax) (has_part only cls). Basically, the individual is said to be typed as the anonymous class which has as part cls.

Using stardog as the triple store, how would I write a query that pulled all individuals which are of the type (has_part only cls)?

Using OWLIM as the triple store, I was able to write the following:

select ?ind where {
    ?ind rdf:type ?restriction .
    ?restriction owl:onProperty has_part .
    ?restriction owl:allValuesFrom cls
}

This doesn't work in Stardog, as far as I can tell, regardless of what reasoning level I use. How should this query look?

Thanks!

EDIT 1

I think I over simplified. If the individual has a more complex type, e.g. (clsa and (has_part only clsb)), should the below query work?

select ?ind where {
    ?ind rdf:type ?restriction .
    ?restriction owl:onProperty has_part .
    ?restriction owl:allValuesFrom clsB
}

If so, then perhaps stardog has taken issue with another part of my representation.

EDIT 2

Joshua Taylor provided an excellent answer below. I'm still in the process of working it out, but it seems sound.

I wanted to write down why the above query works in OWLIM but not in Stardog. OWLIM precomputes all inferences as they are inserted. This means that, using the above example, (clsa and (has_part only clsb)), ind is asserted to be of type clsa and (has_part only clsb) directly. Stardog does not do this, meaning that ind is only inferred to be (has_part only clsb) and, since (as noted below) Stardog does not support retrieving instances of anonymous classes through reasoning, these are not picked up.

An equivalent query for Stardog might be

select ?ind where {
    ?ind rdf:type ?anon.
    ?anon owl:intersectionOf ?a .
    ?a rdf:first clsa .
    ?a rdf:rest ?b .
    ?b rdf:first ?restriction .
    ?b rdf:rest rdf:nil . 
    ?restriction owl:onProperty has_part .
    ?restriction owl:allValuesFrom clsB
}

As Joshua notes below, however, this will only pick up individuals that are specified to be that type specifically, meaning that a individual that was asserted to be clsa and then asserted to be (has_part only clsb) would not be picked up, which isn't what we want most likely.

I'm still trying to get Joshua's query to work, but it looks good to me. (I'm a bit of a SPARQL newbie, but I'm getting there.)

Thanks for the help!

EDIT 3

The query above without all the intermediate variables:

select ?ind where {
    ?ind rdf:type [
        owl:intersectionOf [
            rdf:first clsa ;
            rdf:rest [
                rdf:rest rdf:nil ; 
                rdf:first [
                    owl:onProperty has_part ;
                    owl:allValuesFrom clsB ;
                ] ;
            ] ;
        ] ;
    ] ;
}
Était-ce utile?

La solution 2

If you're looking for individuals that have a type that is a complex class expression, and you're doing this in SPARQL, you'll need to know how the OWL class expression is serialized in RDF. As an example, consider the following ontology in which an individual, barrel42 has a complex type:

barrel42 : Barrel ⊓ (hasApple only GoodApple)

It's actually sort of mythical, since there's a bad apple in every barrel, but that's besides the point. Here's the ontology:

@prefix :      <https://stackoverflow.com/q/21607859/1281433/example#> .
@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl:   <http://www.w3.org/2002/07/owl#> .
@prefix xsd:   <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

<https://stackoverflow.com/q/21607859/1281433/example>
        a       owl:Ontology .

:barrel42  a    owl:NamedIndividual ;
        a       [ a                   owl:Class ;
                  owl:intersectionOf  ( :Barrel [ a                  owl:Restriction ;
                                                  owl:allValuesFrom  :GoodApple ;
                                                  owl:onProperty     :hasApple
                                                ] )
                ] .

:GoodApple  a            owl:Class ;
        rdfs:subClassOf  :Apple .

:Apple  a       owl:Class .

:hasApple  a    owl:ObjectProperty .

:BadApple  a             owl:Class ;
        rdfs:subClassOf  :Apple .

:Barrel  a      owl:Class .

Now, you've got some options here. You could ask for things that actually have that intersection type, but that's probably not the best route, since if something had been declared as a Barrel and declared as a hasApple only GoodApple, you'd still probably want to select it. Based on the answer to Retrieving superclasses implied by OWL intersection classes, we can write a query like this:

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

select ?individual where { 
  ?individual                                    
     a/(owl:intersectionOf/rdf:rest*/rdf:first)*
       :Barrel,
        [ owl:allValuesFrom :GoodApple ;
          owl:onProperty :hasApple ;
          a owl:Restriction ] .
}
--------------
| individual |
==============
| :barrel42  |
--------------

The property path

a/(owl:intersectionOf/rdf:rest*/rdf:first)*

is really the important part here. We're looking for types of ?individual, and we're also will to through intersection classes to find superclasses of the intersection class. There are other "inference paths" that we might want to include too. E.g., we might incorporate rdfs:subClassOf links:

a/((owl:intersectionOf/rdf:rest*/rdf:first)|rdfs:subClassOf)*

If you look at other class expressions, you can come up with other ways to extend the path. This can't get you all OWL inferences, but you can get more than you might expect initially.

References

As I mentioned in a comment, there have been a number of related questions lately, and it might be useful to at least skim over them to get an idea of what you can do. Here are some that I was able to find quickly:

Autres conseils

Stardog (as of version 2.1) does not support retrieving instances of anonymous classes through reasoning. However, in your example, you can simply run the query without reasoning and you should get the expected result since the individual is directly typed with the restriction.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top