Извлечение суперклассов, подразумеваемых классами пересечения OWL

Онтология OWL может иметь классы A, B и C и аксиому (в нотации DL):

A ⊑ (B ⊓ C)

или в приблизительном синтаксисе Манчестер OWL:

SubClassOf (B и C)

Логически верно, что A является подклассом B, и что A является подклассом C, но утраивает

A rdfs:subClassOf B
A rdfs:subClassOf C

не обязательно присутствуют в сериализации RDF онтологии OWL. Например, рассмотрим эту очень простую онтологию в Protégé и ее сериализацию RDF в RDF/XML и Turtle:

<rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="http://stackru.com/q/19924861/1281433/sample.owl#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
  <owl:Ontology rdf:about="http://stackru.com/q/19924861/1281433/sample.owl"/>
  <owl:Class rdf:about="http://stackru.com/q/19924861/1281433/sample.owl#C"/>
  <owl:Class rdf:about="http://stackru.com/q/19924861/1281433/sample.owl#B"/>
  <owl:Class rdf:about="http://stackru.com/q/19924861/1281433/sample.owl#A">
    <rdfs:subClassOf>
      <owl:Class>
        <owl:intersectionOf rdf:parseType="Collection">
          <owl:Class rdf:about="http://stackru.com/q/19924861/1281433/sample.owl#B"/>
          <owl:Class rdf:about="http://stackru.com/q/19924861/1281433/sample.owl#C"/>
        </owl:intersectionOf>
      </owl:Class>
    </rdfs:subClassOf>
  </owl:Class>
</rdf:RDF>
@prefix :      <http://stackru.com/q/19924861/1281433/sample.owl#> .
@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#> .

<http://stackru.com/q/19924861/1281433/sample.owl>
        a       owl:Ontology .

:B      a       owl:Class .

:C      a       owl:Class .

:A      a                owl:Class ;
        rdfs:subClassOf  [ a                   owl:Class ;
                           owl:intersectionOf  ( :B :C )
                         ] .

Сериализация имеет тройку с rdfs:subClassOf, но объект не :B или же :Cтак что запрос как

:A rdfs:subClassOf ?superclass

не вернет суперклассы :A, Как я могу написать запрос SPARQL, который будет возвращать эти суперклассы :A?

1 ответ

Решение

Похоже, у вас есть класс, который является подклассом некоторого класса пересечения. Например, вы могли бы иметь

СтудентЧеловекзаписался на какой-то курс

В редакторе онтологий Protégé OWL это будет выглядеть так:

Определение студента в Протеже

Если вы пишете запрос SPARQL для подклассов, например,

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>

select ?subclass ?superclass where { 
  ?subclass rdfs:subClassOf ?superclass
}

и у вас нет аргумента, выводящего дополнительные данные, вы не увидите Student в качестве подкласса в своих результатах, но вы можете увидеть пустой (анонимный) узел:

---------------------------------------------------------
| subclass                                 | superclass |
=========================================================
| <http://www.examples.org/school#Student> | _:b0       |
---------------------------------------------------------

Чтобы понять, почему это так, вам нужно взглянуть на сериализацию RDF онтологии. В этом случае это (в RDF/XML):

<rdf:RDF
    xmlns="http://www.examples.org/school#"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:owl="http://www.w3.org/2002/07/owl#"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
    xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
  <owl:Ontology rdf:about="http://www.examples.org/school"/>
  <owl:Class rdf:about="http://www.examples.org/school#Course"/>
  <owl:Class rdf:about="http://www.examples.org/school#Person"/>
  <owl:Class rdf:about="http://www.examples.org/school#Student">
    <rdfs:subClassOf>
      <owl:Class>
        <owl:intersectionOf rdf:parseType="Collection">
          <owl:Class rdf:about="http://www.examples.org/school#Person"/>
          <owl:Restriction>
            <owl:onProperty>
              <owl:ObjectProperty rdf:about="http://www.examples.org/school#enrolledIn"/>
            </owl:onProperty>
            <owl:someValuesFrom rdf:resource="http://www.examples.org/school#Course"/>
          </owl:Restriction>
        </owl:intersectionOf>
      </owl:Class>
    </rdfs:subClassOf>
  </owl:Class>
</rdf:RDF>

Или в более удобочитаемой черепахе (которая также больше похожа на синтаксис запроса SPARQL):

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

:Student  a              owl:Class ;
        rdfs:subClassOf  [ a                   owl:Class ;
                           owl:intersectionOf  ( :Person [ a                   owl:Restriction ;
                                                           owl:onProperty      :enrolledIn ;
                                                           owl:someValuesFrom  :Course
                                                         ] )
                         ] .

:Person  a      owl:Class .

:enrolledIn  a  owl:ObjectProperty .

:Course  a      owl:Class .

<http://www.examples.org/school>
        a       owl:Ontology .

На самом деле, есть Student rdfs:subClassOf [ ... ] тройной в данных, но [ ... ] является пустым узлом; это аноним owl:Class это пересечение некоторых других классов. Разумник сможет сказать вам, что если X ⊑ (Y и Z), то XY и XZ, но сам по себе запрос SPARQL этого не сделает. Вы могли бы сделать более сложный SPARQL-запрос, как это, хотя бы:

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 ?subclass ?superclass where {
  { ?subclass rdfs:subClassOf ?superclass }
  union
  { ?subclass rdfs:subClassOf [ owl:intersectionOf [ rdf:rest* [ rdf:first ?superclass ] ] ] }
}
--------------------------------------------------------------------------------------
| subclass                                 | superclass                              |
======================================================================================
| <http://www.examples.org/school#Student> | _:b0                                    |
| <http://www.examples.org/school#Student> | <http://www.examples.org/school#Person> |
| <http://www.examples.org/school#Student> | _:b1                                    |
--------------------------------------------------------------------------------------

Два пустых узла - это класс анонимного пересечения и класс анонимного ограничения (enrolledIn некоторый курс). Если вы хотите только результаты IRI, вы можете использовать filter:

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 ?subclass ?superclass where {
  { ?subclass rdfs:subClassOf ?superclass }
  union
  { ?subclass rdfs:subClassOf [ owl:intersectionOf [ rdf:rest* [ rdf:first ?superclass ] ] ] }

  filter( isIRI( ?superclass ) )
}
--------------------------------------------------------------------------------------
| subclass                                 | superclass                              |
======================================================================================
| <http://www.examples.org/school#Student> | <http://www.examples.org/school#Person> |
--------------------------------------------------------------------------------------

Теперь, как последний штрих, если вы хотите сделать ваш запрос немного меньше, так как единственная разница в этих двух unionEd шаблоны - это путь, который соединяет ?subclass а также ?superclassВы можете написать это только одним путем к свойству. (Хотя, как отмечено в запросе Sparql Subclass или EquivalentTo, при этом вы можете столкнуться с некоторыми проблемами с Protégé.) Идея состоит в том, что вы можете переписать это:

{ ?subclass rdfs:subClassOf ?superclass }
union
{ ?subclass rdfs:subClassOf [ owl:intersectionOf [ rdf:rest* [ rdf:first ?superclass ] ] ] }

как это, используя пути свойств, что также устраняет необходимость в пустых узлах:

?subclass ( rdfs:subClassOf |
            ( rdfs:subClassOf / owl:intersectionOf / rdf:rest* / rdf:first ) ) ?superclass

и вы можете упростить это немного больше, чтобы

?subclass rdfs:subClassOf/((owl:intersectionOf/rdf:rest*/rdf:first)+) ?superclass

и вы можете даже удалить один уровень скобок от этого, чтобы сделать его

?subclass rdfs:subClassOf/(owl:intersectionOf/rdf:rest*/rdf:first)+ ?superclass

но тогда вам придется начинать вспоминать правила предшествования, и это не очень весело. Запрос работает, хотя:

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 ?subclass ?superclass where {
  ?subclass rdfs:subClassOf/(owl:intersectionOf/rdf:rest*/rdf:first)+ ?superclass
  filter( isIRI( ?superclass ) )
}
--------------------------------------------------------------------------------------
| subclass                                 | superclass                              |
======================================================================================
| <http://www.examples.org/school#Student> | <http://www.examples.org/school#Person> |
--------------------------------------------------------------------------------------
Другие вопросы по тегам