Search code examples
sparqlowlsemantic-webontologylinked-data

Classes and subclasses in OWL for SPARQL queries with inference


I have a question with OWL and SPARQL that I can't resolve. I have defined several classes, but for the question in question only 3 are the important ones: People, Men and Women; and its definitions would be the following:

<#People> a owl:Class ;
    rdfs:label "People"@en .

<#Men> a owl:Class ;
    rdfs:subClassOf <#People> ;
    rdfs:label "Men"@en .

<#Women> a owl:Class ;
    rdfs:subClassOf <#People> ;
    rdfs:label "Women"@en .

And then a data in RDF for example:

<rdf:Description rdf:about="Registration#1">
    <rdfs:label>ARCHEOLOGY GRADUATE</rdfs:label>
    <ex:BranchKnowledge>ARTS AND HUMANITIES</ex:BranchKnowledge>
    <ex:Degree>ARCHEOLOGY GRADUATE</ex:Degree>
    <ex:Men rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">63</ex:Men>
    <ex:Women rdf:datatype="http://www.w3.org/2001/XMLSchema#nonNegativeInteger">99</ex:Women>
    <dcterms:coverage>2015/2016</dcterms:coverage>
</rdf:Description>

If I wanted to obtain the number of Men and Women of each data, I get it with the following query:

SELECT ?X ?degree ?branch ?men ?women
WHERE {
  ?X ex:Degree ?degree .
  ?X ex:BranchKnowledge ?branch .
  ?X ex:Men ?men .
  ?X ex:Women ?women
}

If I now want to get the total number of Men and Women inferring that both are People, I had thought that since both are subclasses of People, I could make the following query:

SELECT ?X ?degree ?branch ?people
WHERE {
  ?X ex:Degree ?degree .
  ?X ex:BranchKnowledge ?branch .
  ?X ex:People ?people
}

However I don't get any results.

Have I misconstructed the relationship between classes and subclasses for what I want to do or what would be the problem? (I'm working on a Virtuoso server).


Solution

  • You should be aware of the fact that you're using punning, i.e. the same URI for Men and Women as OWL classes and OWL data properties. I don't understand why you're doing this. Why don't you introduce properties like numberOfMen, numberOfWomen and numberOfPeople?

    Next, you're using ex:People as a property, thus, you would have to define that ex:Men and ex:Women are sub-properties of ex:People.

    <#People> a owl:DatatypeProperty ;
        rdfs:label "People"@en .
    
    <#Men> a owl:DatatypeProperty ;
        rdfs:subPropertyOf <#People> ;
        rdfs:label "Men"@en .
    
    <#Women> a owl:DatatypeProperty ;
        rdfs:subPropertyOf <#People> ;
        rdfs:label "Women"@en .
    

    And then you have to enable reasoning in the triple store if supported or use SPARQL 1.1 property paths.

    But, more important, this would only lead to two rows, which means you have to do the aggregation in your SPARQL query by using the sum function, e.g.:

    SELECT ?X ?degree ?branch (sum(?_people) as ?people)
    WHERE {
      ?X ex:Degree ?degree .
      ?X ex:BranchKnowledge ?branch .
      ?p rdfs:subPropertyOf* ex:People .
      ?X  ?p ?_people
    }
    GROUP BY ?X ?degree ?branch
    

    Note, this query only works if there is just a single degree and branch, otherwise it would sum duplicate values.