检索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 

不一定存在于OWL本体的RDF序列化中。 例如,考虑Protégé中这个非常简单的本体及其在RDF / XML和Turtle中的RDF序列化:

在此处输入图像描述

                
 @prefix :  . @prefix rdfs:  . @prefix owl:  . @prefix xsd:  . @prefix rdf:  .  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

听起来你有一个类是某个交集类的子类。 例如,你可能有

学生某些课程中 注册

在ProtégéOWL本体编辑器中,这看起来像:

Protege中学生的定义

如果为子类编写SPARQL查询,例如,

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

并且您没有推理器推断其他数据,您不会在结果中看到Student作为子类,但您可能会看到一个空白(匿名)节点:

 --------------------------------------------------------- | subclass | superclass | ========================================================= |  | _:b0 | --------------------------------------------------------- 

要了解为什么会出现这种情况,您需要查看本体的RDF序列化。 在这种情况下,它是(在RDF / XML中):

                     

或者更易读的Turtle(也更像是SPARQL查询语法):

 @prefix :  . @prefix rdfs:  . @prefix owl:  . @prefix xsd:  . @prefix rdf:  . :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 .  a owl:Ontology . 

事实上,数据中有一个Student rdfs:subClassOf [ ... ]三元组,但[ ... ]是一个空白节点; 它是一个匿名的owl:Class是其他一些类的交集。 一个推理者可以告诉你,如果X⊑( YZ )那么X⊑Y和X⊑Z,但是SPARQL查询本身就不会这样做。 你可以制作一个更复杂的SPARQL查询,但是:

 prefix rdfs:  prefix owl:  prefix rdf:  select ?subclass ?superclass where { { ?subclass rdfs:subClassOf ?superclass } union { ?subclass rdfs:subClassOf [ owl:intersectionOf [ rdf:rest* [ rdf:first ?superclass ] ] ] } } 
 -------------------------------------------------------------------------------------- | subclass | superclass | ====================================================================================== |  | _:b0 | |  |  | |  | _:b1 | -------------------------------------------------------------------------------------- 

两个空白节点是匿名交集类,以及匿名限制类(在某些课程中注册)。 如果您只想要IRI结果,可以使用filter

 prefix rdfs:  prefix owl:  prefix rdf:  select ?subclass ?superclass where { { ?subclass rdfs:subClassOf ?superclass } union { ?subclass rdfs:subClassOf [ owl:intersectionOf [ rdf:rest* [ rdf:first ?superclass ] ] ] } filter( isIRI( ?superclass ) ) } 
 -------------------------------------------------------------------------------------- | subclass | superclass | ====================================================================================== |  |  | -------------------------------------------------------------------------------------- 

现在,作为最后的触摸,如果你想让你的查询更小一点,因为这两个union ed模式的唯一区别是连接的路径?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:  prefix owl:  prefix rdf:  select ?subclass ?superclass where { ?subclass rdfs:subClassOf/(owl:intersectionOf/rdf:rest*/rdf:first)+ ?superclass filter( isIRI( ?superclass ) ) } 
 -------------------------------------------------------------------------------------- | subclass | superclass | ====================================================================================== |  |  | --------------------------------------------------------------------------------------