OWL ontology: SPARQL query a range or domain of an ObjectProperty when they're unionOf classes - sparql

I have to query an ontology version 1.4, with a SPARQL 1.1 endpoint, so I can't use the OWL 2 semantic like ClassAssertion etc...
several properties in the ontology have this format:
<owl:ObjectProperty rdf:about="&km4c;hasGeometry">
<rdfs:comment>some services and all railway elements have a specific geometry like polygons or linestrings</rdfs:comment>
<rdfs:range rdf:resource="&gis;Geometry"/>
<rdfs:domain>
<owl:Class>
<owl:unionOf rdf:parseType="Collection">
<rdf:Description rdf:about="&km4c;RailwayElement"/>
<rdf:Description rdf:about="&km4c;Service"/>
</owl:unionOf>
</owl:Class>
</rdfs:domain>
</owl:ObjectProperty>
with domain or range that is a Union of more than one class. The problem is that i want to retrieve all the classes with a certain domain and range, but with the following query:
SELECT DISTINCT ?p
{
?p rdfs:range gis:Geometry.
?p rdfs:domain km4c:Service
}
i get no result, instead of km4c:hasGeometry.
Is there a way to somehow look inside the Collection with this kind of goal?

First, note that the semantics of union of domains and ranges may not be what you expect. In OWL, when you say that class D is a domain of property P, it means that whenever you have an assertion P(x,y), you can infer that D(x). That means that if a domain of P is a union C &sqcup; D, then from P(x,y), you can infer that x is an element of C &sqcup; D; i.e., that x is either a C or a D, but you don't necessarily know which. For instance, you might define:
hasWings rdfs:domain (Airplane &sqcup; Bird)
Then, from hasWings(x,2), you could infer that x is an Airplane or a Bird, but you still wouldn't know which.
Anyhow, if you still want a union class as a domain, you can do that. In the RDF serialization of the mapping of the OWL ontology, the unioned classes are in an RDF list. It's a little bit more complicated to query over those, but you can certainly do it. Since you didn't provide a complete OWL ontology, we can't query over your actual data (in the future, please provide complete, minimal working data that we can use), but we can create a simple ontology. There are two classes, A and B, and two properties, p and q. The domain of p is A, and the domain of q is A or B:
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://example.org/"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
<owl:Ontology rdf:about="http://example.org/"/>
<owl:Class rdf:about="http://example.org/#A"/>
<owl:Class rdf:about="http://example.org/#B"/>
<owl:ObjectProperty rdf:about="http://example.org/#q">
<rdfs:domain>
<owl:Class>
<owl:unionOf rdf:parseType="Collection">
<owl:Class rdf:about="http://example.org/#A"/>
<owl:Class rdf:about="http://example.org/#B"/>
</owl:unionOf>
</owl:Class>
</rdfs:domain>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:about="http://example.org/#p">
<rdfs:domain rdf:resource="http://example.org/#A"/>
</owl:ObjectProperty>
</rdf:RDF>
SPARQL syntax is much more like the N3/Turtle serialization of RDF, so it's helpful to see that serialization, too. The unionOf list is much clearer here:
#prefix : <http://example.org/> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://example.org/#A>
a owl:Class .
<http://example.org/#p>
a owl:ObjectProperty ;
rdfs:domain <http://example.org/#A> .
<http://example.org/#B>
a owl:Class .
<http://example.org/#q>
a owl:ObjectProperty ;
rdfs:domain [ a owl:Class ;
owl:unionOf ( <http://example.org/#A> <http://example.org/#B> )
] .
: a owl:Ontology .
Now you can use a query like this to find properties and their domains, or the unioned classes if one of the domains is a union class:
prefix : <http://example.org/>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
select ?p ?d where {
?p rdfs:domain/(owl:unionOf/rdf:rest*/rdf:first)* ?d
filter isIri(?d)
}
-----------------------------------------------------
| p | d |
=====================================================
| <http://example.org/#q> | <http://example.org/#A> |
| <http://example.org/#q> | <http://example.org/#B> |
| <http://example.org/#p> | <http://example.org/#A> |
-----------------------------------------------------
The interesting parts of that query are:
?p rdfs:domain/(owl:unionOf/rdf:rest*/rdf:first)* ?d
which says you follow a path from ?p to ?d, and the path:
starts with rdfs:domain
and is followed by zero or more repetitions of:
owl:unionOf
followed by zero or more rdf:rest
followed by a single rdf:first
It's not exactly related to this question, but you may find the discussion of querying RDF lists in this answer (disclosure: my answer) to Is it possible to get the position of an element in an RDF Collection in SPARQL? useful.
Then, I also added
filter isIri(?d)
because otherwise we get the node that represents the union class, but that's a blank node that you (probably) don't want.

Related

How to query implicit properties of owl:equivalentclass

I want to query an ontology which contains implicit properties hold by owl:equivalentclass objects. How can I achieve this?
The ontology holds triples like this:
<plantURI> rdf:type <http://purl.obolibrary.org/obo/FLOPO_0004148>.
The class <http://purl.obolibrary.org/obo/FLOPO_0004148> has the following definition:
<owl:Class rdf:about="http://purl.obolibrary.org/obo/FLOPO_0004148">
<owl:equivalentClass>
<owl:Restriction>
<owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/BFO_0000051"/>
<owl:someValuesFrom>
<owl:Class>
<owl:intersectionOf rdf:parseType="Collection">
<rdf:Description rdf:about="http://purl.obolibrary.org/obo/PO_0009046"/>
<owl:Restriction>
<owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/RO_0000053"/>
<owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/PATO_0000320"/>
</owl:Restriction>
</owl:intersectionOf>
</owl:Class>
</owl:someValuesFrom>
</owl:Restriction>
</owl:equivalentClass>
<rdfs:label rdf:datatype="http://www.w3.org/2001/XMLSchema#string">flower green</rdfs:label>
</owl:Class>
However, I don't want to query simply for the URI like this:
SELECT * {
?s rdf:type <http://purl.obolibrary.org/obo/FLOPO_0004148>
}
but I want to query sometimes only for one of its implicit properties, for example the property <http://purl.obolibrary.org/obo/PATO_0000320> ("green") - searching for all plants that are green in any way.
So, the best query would look like this:
SELECT * {
?s ?p <http://purl.obolibrary.org/obo/PATO_0000320>
}
Which gives me the object, because implicitly the object holds this property.
This probably involves reasoning in Virtuoso. However, after some hours I cannot come up with any solution how to do this in SPARQL.
Virtuoso provides reasoning and inference in two forms.
1. Built-in -- this is based on canned rules covering the relations semantics for owl:equivalentClass, owl:equivalentProperty, owl:inverseOf, owl:sameAs, owl:InverseFunctionalProperty, owl:SymmetricProperty, rdfs:subClassOf, rdfs:subPropertyOf (this is supported in both open source and commercial editions)
Custom -- this is based on custom rules crafted using SPARQL and the Rules Language, courtesy of terms from the SPIN Ontology (this is a commercial edition only feature).
You appear right now to simply require owl:equivalentClass reasoning, so you can look at the following built-in inference and reasoning examples:
Equivalent Class Reasoning Enabled
DEFINE input:inference 'urn:owl:equivalent:class:inference:rules'
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX bmo: <http://purl.org/bmo/ns#>
PREFIX fibo: <https://spec.edmcouncil.org/fibo/ontology/FND/AgentsAndPeople/People/Person>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?s
WHERE {
?s a fibo:person .
}
LIMIT 20
Live Query Results Page (solution is produced based on effects of reasoning and inference)
Equivalent Class Reasoning Disabled (notice DEFINE input:inference pragma commented out)
# DEFINE input:inference 'urn:owl:equivalent:class:inference:rules'
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX bmo: <http://purl.org/bmo/ns#>
PREFIX fibo: <https://spec.edmcouncil.org/fibo/ontology/FND/AgentsAndPeople/People/Person>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT DISTINCT ?s
WHERE {
?s a fibo:person .
}
LIMIT 20
Live Query Results Page (should be empty)
Example source code document from our Github Repository.

Logical error in this query?

I have two where clauses.
PREFIX tourister: <PREFIX_VALUE>
SELECT ?a
WHERE {
{?a tourister:hasRating ?b .
?b ?c '5'#string } .
{?a tourister:hasFeature ?b .
?b ?c 'Pool'#string }
}
They work fine, when executed on their own, or if there is a UNION clause between them, however, I am looking for Intersection. From what I have read online, I came to find out, that '.' can be used for intersection. However, with the ., I get 0 results. No, Syntax Error, something wrong with the Logic.
And, please note, the PREFIX_VALUE in the above query is not an error, I have omitted it intentionally.
<!-- http://tourister.space/ontologies/tourism#TESTInd -->
<owl:NamedIndividual rdf:about="http://tourister.space/ontologies/tourism#TESTInd">
<rdf:type rdf:resource="http://tourister.space/ontologies/tourism#Hotel"/>
<hasFeature rdf:resource="http://tourister.space/ontologies/tourism#TESTIndFeature"/>
<hasRating rdf:resource="http://tourister.space/ontologies/tourism#TESTIndRating"/>
</owl:NamedIndividual>
<!-- http://tourister.space/ontologies/tourism#TESTIndFeature -->
<owl:NamedIndividual rdf:about="http://tourister.space/ontologies/tourism#TESTIndFeature">
<rdf:type rdf:resource="http://tourister.space/ontologies/tourism#Feature"/>
<hasName xml:lang="string">Pool</hasName>
</owl:NamedIndividual>
<!-- http://tourister.space/ontologies/tourism#TESTIndRating -->
<owl:NamedIndividual rdf:about="http://tourister.space/ontologies/tourism#TESTIndRating">
<rdf:type rdf:resource="http://tourister.space/ontologies/tourism#Rating"/>
<hasStarRating xml:lang="string">5</hasStarRating>
</owl:NamedIndividual>
Many things unclear about the data and the query. Here's an alternative in the more readable, and SPARQL-friendly, Turtle text serialization. I also simplified the model, as it isn't clear that the Rating and Feature classes are needed (they could be, and can easily be added back in):
#prefix tourister: <http://example.org/ex#> .
tourister:TESTInd
rdf:type tourister:Hotel ;
tourister:hasFeature "Pool"^^xsd:string ;
tourister:hasStarRating 5 .
tourister:Hotel
rdf:type owl:Class ;
rdfs:subClassOf owl:Thing .
tourister:hasFeature
rdf:type owl:DatatypeProperty ;
rdfs:range xsd:string .
tourister:hasStarRating
rdf:type owl:DatatypeProperty ;
rdfs:range xsd:integer .
From this it seems that the SPARQL to find Hotels with a star rating of 5 and a Pool is taken almost directly from the first set of triples:
SELECT ?hotel
WHERE {
?hotel tourister:hasFeature "Pool"^^xsd:string ;
tourister:hasStarRating 5 .
}
That's just a start, and I won't be the first to suggest doing a bit of homework on RDF and SPARQL before proceeding further. I think you'll find that path more productive for getting started than piecemeal questions on SO.

How to write a SPARQL query to take the values from an OWL file

I've got an OWL file with a subclass of owl:Thing "Objects".
<rdf:RDF xmlns="http://www.semanticweb.org/PredefinedOntology#"
xml:base="http://www.semanticweb.org/PredefinedOntology"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:swrlb="http://www.w3.org/2003/11/swrlb#"
xmlns:swrl="http://www.w3.org/2003/11/swrl#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="http://www.semanticweb.org/PredefinedOntology"/>
This subclass has three individuals (Door1, Coridor1, Window1) with DataProperty assertions (X and Y coordinates with the values). One of the individuals looks like this:
<!-- http://www.semanticweb.org/PredefinedOntology#Door1 -->
<owl:NamedIndividual rdf:about="http://www.semanticweb.org/PredefinedOntology#Door1">
<rdf:type rdf:resource="http://www.semanticweb.org/PredefinedOntology#Objects"/>
<X rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">2</X>
<Y rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">20</Y>
</owl:NamedIndividual>
I need to get the values of the individual (let's say Door1).
How can I do this with SPARQL? I was trying:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?X ?datatype
WHERE {?X rdf:datatype ?datatype}
But it seems like my query is completely wrong. Could some one please explain to me how to write (or even more important how to read or think) this query to find the values X=2 and Y=20 from the ontology?
Thank you
OK, step 1 is to lose the RDF/XML text serialization. Use anything else, but Turtle is closest to SPARQL. Any RDF editor can be used to convert to Turtle. The equivalent text serialization for Door1 in Turtle is:
:Door1
rdf:type :Objects ;
rdf:type owl:NamedIndividual ;
:X 2 ;
:Y 20 .
One part of this syntax that may not be obvious is that each line is a triple (subject, predicate, object), and the ; means that the subject from the previous line is used. An advantage of this syntax is that RDF resources can be viewed as an object with properties.
Step 2 is that the SPARQL query becomes obvious because you can line up the triple patterns with the triples specified in Turtle:
SELECT ?X ?Y ?inst
WHERE {
?inst rdf:type owl:NamedIndividual ;
:X ?X ;
:Y ?Y .
}

How to define a class that does not have two equivalent predicate objects?

I'm trying to define class of intervals. Each interval object may have (optionally) at most two boundary points. One of them - lower boundary, and another - upper boundary. How can I restrict my class of intervals, so that lower and upper individual boundary points must be different (if provided)?
You can declare that the hasLowerBound and hasUpperBound properties are disjoint. This means that an individual with values for both cannot have the same value for both. Here's an example. I've used an object property here, but you can use disjoint property axioms with datatype properties, too.
#prefix : <http://stackoverflow.com/q/36043590/1281433/> .
#prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
#prefix owl: <http://www.w3.org/2002/07/owl#> .
#prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
#prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
<http://stackoverflow.com/q/36043590/1281433/#hasLowerBound>
a owl:ObjectProperty ;
owl:propertyDisjointWith <http://stackoverflow.com/q/36043590/1281433/#hasUpperBound> .
<http://stackoverflow.com/q/36043590/1281433/#hasUpperBound>
a owl:ObjectProperty .
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://stackoverflow.com/q/36043590/1281433/"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#">
<owl:ObjectProperty rdf:about="http://stackoverflow.com/q/36043590/1281433/#hasUpperBound"/>
<owl:ObjectProperty rdf:about="http://stackoverflow.com/q/36043590/1281433/#hasLowerBound">
<owl:propertyDisjointWith rdf:resource="http://stackoverflow.com/q/36043590/1281433/#hasUpperBound"/>
</owl:ObjectProperty>
</rdf:RDF>

SPARQL "ASK" query to check if object property exist between two classes (Not b/w individuals)

I want to query, if certain ObjectPropery (OP) exist between two classes inside an OWL2 file. I'm using JENA API to construct the SPARQL queries.
What I have tried till now:
First I used the SELECT query to check the classes for a given OP:
" { SELECT ?domain ?range WHERE {\n" +
":isManagedBy rdfs:domain ?domain; \n" +
" rdfs:range ?range. \n } }" +
"}";
Then I wrapped it with ASK query
" ASK WHERE { \n" +
" { SELECT ?domain ?range WHERE {\n" +
":isManagedBy rdfs:domain ?domain; \n" +
" rdfs:range ?range. \n } }" +
"}";
It seems to give me the answer, but I think, I'm mixing up so many things in this query:
My Goal: Is to query if certain fact exist inside the OWL file or not (Boolean Answer)
Eg: OWL Snippet
<owl:ObjectProperty rdf:ID="isManagedBy">
<rdf:type rdf:resource="owl#FunctionalProperty" />
<rdfs:domain rdf:resource="#FunctionManagement" />
<rdfs:range rdf:resource="#SymposiumPlanner2013"/>
</owl:ObjectProperty>
What I would like to check: isManagedBy(FunctionManagement, SymposiumPlanner2013) exists or not.
I think that the possible duplicate (How to query Classes with Object Property in Sparql) I linked may be close enough to answer your question, but there's no need to wrap a select query in an ask query here. You're asking about whether your data contains the triples:
:isManagedBy rdfs:domain :FunctionManagement .
:isManagedBy rdfs:range :SymposiumPlanner2013 .
You just want a query that asks whether that data is present:
prefix : <…>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
ask {
:isManagedBy rdfs:domain :FunctionManagement .
:isManagedBy rdfs:range :SymposiumPlanner2013 .
}
You can even use some abbreviations to make that a bit more concise:
prefix : <…>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
ask {
:isManagedBy rdfs:domain :FunctionManagement ;
rdfs:range :SymposiumPlanner2013 .
}
It seems to me that you want to get the domain and range for a certain property, and you want to verify that they match some other specific values. If that is the case, and given your sample data, your second query is correct.
One thing to note is that there seems to be a small bit of confusion between the idea of a predicate holding between two classes, and a predicate holding between two members of a class.
What your sample data indicates, is that if you see an instance of :isManagedBy, say in the triple :steve :isManagedBy :bill, then we can infer that :steve rdf:type :FunctionManagement and :bill rdf:type :SymposiumPlanner2013. This doesn't say anything about the classes themselves, only about the subject and object of instances of the property.
If you are trying to see if some property holds about the class, such as "all members of :FunctionManagement :isManagedBy some :SymposiumPlanner2013", then you would use an owl:minCardinality restriction to express that in your data. Your query would then change to reflect the constructs used in explaining it. Below is an example of a small ontology specifying that constraint.
<owl:ObjectProperty rdf:about="#isManagedBy"/>
<owl:Class rdf:about="#FunctionManagement">
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="#isManagedBy"/>
<owl:someValuesFrom rdf:resource="#SymposiumPlanner2013"/>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
<owl:Class rdf:about="#SymposiumPlanner2013"/>