0
votes

I have a problem with creating universal query for little different owl. I have owl:

((ClassA MyProperty only (ClassX or ClassY)) AND
(ClassA MyProperty exactly 1 ClassX) AND 
(ClassA MyProperty exactly 1 ClassY))

and sometimes class has this too (its combination, ClassA can have XY or XZ)

OR
((ClassA MyProperty only (ClassX or ClassZ)) AND
(ClassA MyProperty exactly 1 ClassX) AND 
(ClassA MyProperty exactly 1 ClassZ))

full owl:

<owl:Class rdf:about="ClassA">
    <rdfs:subClassOf>
        <owl:Class>
            <owl:unionOf rdf:parseType="Collection">
                <owl:Class>
                    <owl:intersectionOf rdf:parseType="Collection">
                        <owl:Restriction>
                            <owl:onProperty rdf:resource="MyProperty"/>
                            <owl:allValuesFrom>
                                <owl:Class>
                                    <owl:unionOf rdf:parseType="Collection">
                                        <rdf:Description rdf:about="ClassX"/>
                                        <rdf:Description rdf:about="ClassY"/>
                                    </owl:unionOf>
                                </owl:Class>
                            </owl:allValuesFrom>
                        </owl:Restriction>
                        <owl:Restriction>
                            <owl:onProperty rdf:resource="MyProperty"/>
                            <owl:onClass rdf:resource="ClassX"/>
                            <owl:qualifiedCardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:qualifiedCardinality>
                        </owl:Restriction>
                        <owl:Restriction>
                            <owl:onProperty rdf:resource="MyProperty"/>
                            <owl:onClass rdf:resource="ClassY"/>
                            <owl:qualifiedCardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:qualifiedCardinality>
                        </owl:Restriction>
                    </owl:intersectionOf>
                </owl:Class>
                <owl:Class>
                    <owl:intersectionOf rdf:parseType="Collection">
                        <owl:Restriction>
                            <owl:onProperty rdf:resource="MyProperty"/>
                            <owl:allValuesFrom>
                                <owl:Class>
                                    <owl:unionOf rdf:parseType="Collection">
                                        <rdf:Description rdf:about="ClassX"/>
                                        <rdf:Description rdf:about="ClassZ"/>
                                    </owl:unionOf>
                                </owl:Class>
                            </owl:allValuesFrom>
                        </owl:Restriction>
                        <owl:Restriction>
                            <owl:onProperty rdf:resource="MyProperty"/>
                            <owl:onClass rdf:resource="ClassX"/>
                            <owl:qualifiedCardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:qualifiedCardinality>
                        </owl:Restriction>
                        <owl:Restriction>
                            <owl:onProperty rdf:resource="MyProperty"/>
                            <owl:onClass rdf:resource="ClassZ"/>
                            <owl:qualifiedCardinality rdf:datatype="&xsd;nonNegativeInteger">1</owl:qualifiedCardinality>
                        </owl:Restriction>
                    </owl:intersectionOf>
                </owl:Class>
            </owl:unionOf>
        </owl:Class>
    </rdfs:subClassOf>
</owl:Class>

The problem is, that I dont know which class has only one combination and which one has more than one.

Query for single sources:

PREFIX my: <http://www.semanticweb.org/MyOnto#>

SELECT ?myClass ?prop (str(?numInt) as ?number) ?source
WHERE { 
?myClass rdfs:subClassOf my:Classes ;
         rdfs:subClassOf ?x .
?x owl:intersectionOf ?array.
?array rdf:rest*/rdf:first ?triples.
?triples owl:onProperty ?prop ;
        owl:onClass ?source;
        owl:qualifiedCardinality ?numInt.
?source rdfs:subClassOf my:Sources .
}

Query works with intersection in top, but in case I have 2 or more combination, its wrapped in union of this concepts. So its easy to wrap query too and I get result for combination, but than I dont get result for single use. So the Q is, how to write universal query that work with e.g. only ClassA and MyProperty or ... THX

1
Can you clarify exactly what the results that you're looking for are? It's not quite clear what you're asking for yet… - Joshua Taylor

1 Answers

2
votes

It's almost always easier to solve these kinds of problems when you (i) provide complete working data that we can work with (in this case, you haven't provided a complete ontology, so it's much harder to work with), and (ii) use the Turtle serialization of RDF, because it's much closer to the SPARQL syntax.

Your ontology

Here's a complete minimal ontology with the structures you describe:

@prefix :      <http://example.org/> .
@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#> .

:universals  a  owl:Ontology .

:MyProperty  a  owl:ObjectProperty .

:ClassY  a      owl:Class .
:ClassX  a      owl:Class .
:ClassZ  a      owl:Class .

:ClassA  a               owl:Class ;
        rdfs:subClassOf  [ a            owl:Class ;
                           owl:unionOf  ( [ a                   owl:Class ;
                                            owl:intersectionOf  ( [ a                  owl:Restriction ;
                                                                    owl:allValuesFrom  [ a            owl:Class ;
                                                                                         owl:unionOf  ( :ClassX :ClassY )
                                                                                       ] ;
                                                                    owl:onProperty     :MyProperty
                                                                  ] [ a                         owl:Restriction ;
                                                                      owl:onClass               :ClassX ;
                                                                      owl:onProperty            :MyProperty ;
                                                                      owl:qualifiedCardinality  "1"^^xsd:nonNegativeInteger
                                                                    ] [ a                         owl:Restriction ;
                                                                        owl:onClass               :ClassY ;
                                                                        owl:onProperty            :MyProperty ;
                                                                        owl:qualifiedCardinality  "1"^^xsd:nonNegativeInteger
                                                                      ] )
                                          ] [ a                   owl:Class ;
                                              owl:intersectionOf  ( [ a                  owl:Restriction ;
                                                                      owl:allValuesFrom  [ a            owl:Class ;
                                                                                           owl:unionOf  ( :ClassX :ClassZ )
                                                                                         ] ;
                                                                      owl:onProperty     :MyProperty
                                                                    ] [ a                         owl:Restriction ;
                                                                        owl:onClass               :ClassX ;
                                                                        owl:onProperty            :MyProperty ;
                                                                        owl:qualifiedCardinality  "1"^^xsd:nonNegativeInteger
                                                                      ] [ a                         owl:Restriction ;
                                                                          owl:onClass               :ClassZ ;
                                                                          owl:onProperty            :MyProperty ;
                                                                          owl:qualifiedCardinality  "1"^^xsd:nonNegativeInteger
                                                                        ] )
                                            ] )
                         ] .

SPARQL queries

The query you provided isn't legal, because it doesn't define all the prefixes you're using. If we suppose that they've got the "standard" definitions, it still won't return anything on your data, since you're asking for subclasses of my:Classes, and my:Classes doesn't appear in the data that you've shown us. Similarly, we've got nothing with my:Sources. I stress again that it's very important to provide complete working examples as starting points. Otherwise you're just asking people to figure out not only a solution, but what the data should be, too.

It's not perfectly clear from your question what sort of results you're looking to get here, but with the data I've provided, you can use a query like the following to get results that organize the intersection classes underneath each union class:

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

select ?class ?orClass ?andClass ?p ?n where { 
  ?class rdfs:subClassOf/owl:unionOf/rdf:rest*/rdf:first ?orClass .
  ?orClass owl:intersectionOf/rdf:rest*/rdf:first ?andClass .
  ?andClass owl:onProperty ?p ;
            owl:onClass ?onClass;
            owl:qualifiedCardinality ?n .
}
order by ?class ?orClass ?andClass
-----------------------------------------------------------------------------------------------------------
| class   | orClass | andClass | p           | n                                                          |
===========================================================================================================
| :ClassA | _:b0    | _:b1     | :MyProperty | "1"^^<http://www.w3.org/2001/XMLSchema#nonNegativeInteger> |
| :ClassA | _:b0    | _:b2     | :MyProperty | "1"^^<http://www.w3.org/2001/XMLSchema#nonNegativeInteger> |
| :ClassA | _:b3    | _:b4     | :MyProperty | "1"^^<http://www.w3.org/2001/XMLSchema#nonNegativeInteger> |
| :ClassA | _:b3    | _:b5     | :MyProperty | "1"^^<http://www.w3.org/2001/XMLSchema#nonNegativeInteger> |
-----------------------------------------------------------------------------------------------------------