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 ;
] ;
] ;
] ;
] ;
}