SPARQL:返回由指定或等效类完成的所有交叉点

如果我将ABC和CDE类定义为A,B,C,D,E类的交叉点,如下所示:

                                        

如何查询SPARQL中给定输入类集满足其限制的所有交集类? 例如,如果我将A,B,C,D,E,F,G输入此查询,我希望能够回来

 ABC A B C CDE C D E 

另外两个皱纹:如果我查询A,Z,C,其中Z是B的等价类,那么这应该匹配并理想地返回

 ABC A Z C 

其次,结果应该只返回最大匹配; 因此,如果存在ABCD类并且我在A,B,C,D之间进行查询,则它将返回ABCD而不是ABC。

提前致谢!

更新:

为了澄清,除非所有组成类都在提供的输入列表中,否则我不希望与交集类匹配。 例如,如果我向查询提供A,B,我不想让ABC回来。 如果我提供A,B,C,D,我确实希望得到ABC。

我的用例是这样的:我有一组数据点,在每个数据点中我都识别出一些任意的基本概念A,B,C,D等等,每个都具有不同的可能性。 我想问一下本体“这个列表包含哪些更高级别的概念(即交叉点)?”

目前,我的查询看起来像这样(考虑到我在上面概述的本体中的限制和onProperty):

 SELECT DISTINCT ?intclass ?inputclasses WHERE { ?intclass owl:equivalentClass / owl:intersectionOf / rdf:rest*/rdf:first / owl:someValuesFrom ?inputclasses } ORDER BY ?intclass BINDINGS ?inputclasses { (:A) (:B) (:C) (:D) } 

不幸的是,这回馈了我的本体中包含任何输入类的每个交集。 我认为这是因为rest / first依次对输入列表依次评估每个交集的组成类,如果找到它们中的任何一个则进行匹配。

我想要做的是(a)只有当交集中的所有类都存在于输入列表中时才匹配, (b)推断与输入列表中的类相等的类的匹配,以及(c)返回交集class以及与输入列表匹配的类的子集。 也许这只是通过SPARQL不可行?

首先,我认为你不能做你想做的事,但我认为你能够相当接近。 特别是,我认为你提到的最大限度约束将特别难以实现。 通过这种方式处理SPARQL中的一组内容通常很困难。 尽管如此,我们可以看到我们能做些什么。

要使用的数据

使用我们可以实际使用的一些示例数据来回答这些问题要容易得多。 我也从简化问题开始,因此ABC只是A,B和C以及C,D和E的CDE的交集。目前还没有限制类(它们不会增加太多的复杂性,其实)。 出于测试目的(能够确保我们的查询不会返回不需要的值),我还添加了类F和DEF。 查看Turtle序列化中的数据也更容易,因为它更接近SPARQL模式语法。 这是简化的本体:

 @prefix :  . @prefix rdfs:  . @prefix owl:  . @prefix xsd:  . @prefix rdf:  .  a owl:Ontology . :A a owl:Class . :B a owl:Class . :C a owl:Class . :D a owl:Class . :E a owl:Class . :F a owl:Class . :ABC a owl:Class ; owl:equivalentClass [ a owl:Class ; owl:intersectionOf ( :A :B :C ) ] . :CDE a owl:Class ; owl:equivalentClass [ a owl:Class ; owl:intersectionOf ( :C :D :E ) ] . :DEF a owl:Class ; owl:equivalentClass [ a owl:Class ; owl:intersectionOf ( :D :E :F ) ] . 

找到类的交叉点

对于每个等同于交集类的类,都有一个从类到每个相交类的路径。 我们可以利用这个事实来找到相当于包含A,B和C的交叉点的任何类:

 prefix :  prefix rdfs:  prefix owl:  prefix xsd:  prefix rdf:  select distinct ?class where { ?class owl:equivalentClass/ owl:intersectionOf/ rdf:rest*/rdf:first :A, :B, :C . } 
 --------- | class | ========= | :ABC | --------- 

但是,这不会找到CDE,因为此查询要求具有所有指定值的事物。 听起来你想要的是要求至少具有一些指定值的东西,而不是非指定值。 您可能需要两次编写类列表,但是您可以这样做:

 prefix :  prefix rdfs:  prefix owl:  prefix xsd:  prefix rdf:  select ?class ?i where { values ?i { :A :B :C :D :E } ?class owl:equivalentClass/ owl:intersectionOf/ rdf:rest*/rdf:first ?i . filter not exists { ?class owl:equivalentClass/ owl:intersectionOf/ rdf:rest*/rdf:first ?j . filter( !(?j in (:A, :B, :C, :D, :E )) ) } } order by ?class ?i 
 -------------- | class | i | ============== | :ABC | :A | | :ABC | :B | | :ABC | :C | | :CDE | :C | | :CDE | :D | | :CDE | :E | -------------- 

请注意,DEF不在结果中,因为虽然它有D和E,但它的值也不是任何指定的类,F。

由于我们过滤掉了每个具有不在输入列表中的元素的交集类,因此我们保证我们保留的每个交集类包含输入列表中的元素。 鉴于这种措辞,我们实际上可以使查询更简单:

 prefix :  prefix owl:  prefix rdf:  select ?class ?i where { # find each ?class that's equivalent to an intersection ?class owl:equivalentClass/owl:intersectionOf ?list . # and grab the intersecting classes for the results ?list rdf:rest*/rdf:first ?i . # but filter out any ?class that has an intersecting # class that's not in the input list. filter not exists { ?list rdf:rest*/rdf:first ?element . filter( !(?element in (:A, :B, :C, :D, :E )) ) } } 
 -------------- | class | i | ============== | :ABC | :A | | :ABC | :B | | :ABC | :C | | :CDE | :C | | :CDE | :D | | :CDE | :E | -------------- 

这可能效率较低,因为现在你找到每个交集类并过滤掉不合格的交集类,而不是只找到那些可能被接受的交集类,然后过滤掉一些。 这有多重要取决于您的实际数据。

我认为这回答了你问题的主要部分。 要处理限制的交集,您只需要注意所讨论的类之间的路径有点不同。 您希望匹配列表元素的owl:someValuesFrom属性的值,而不是匹配列表中的元素,因此路径需要最终的owl:someValuesFrom

 ?class owl:equivalentClass/ owl:intersectionOf/ rdf:rest*/rdf:first/ owl:someValuesFrom ?i . 

超越这个

处理其他等价物

如果我查询A,Z,C,其中Z是B的等价类,那么这应该匹配并理想地返回

 ABC A Z C 

这里的查询开始变得有点复杂,但它仍然可以管理。 诀窍在于,不是选择?i作为交集列表的简单成员,而是需要选择?i作为输入的成员,列出交集列表的元素相当于。 然后,滤除交叉点也有点复杂。 您需要确保没有元素,使得输入列表中没有与交集元素等效的元素。 把这一切放在一起,你得到这个查询:

 prefix :  prefix owl:  prefix rdf:  select ?class ?i where { ?class owl:equivalentClass/ owl:intersectionOf ?list . ?list rdf:rest*/rdf:first/(owl:equivalentClass|^owl:equivalentClass)* ?i . filter( ?i in (:A, :B, :C, :D, :E )) filter not exists { ?list rdf:rest*/rdf:first ?element . filter not exists { ?element (owl:equivalentClass|^owl:equivalentClass)* ?j filter( ?j in (:A, :B, :C, :D, :E )) } } } 

如果添加以下数据

 :Z a owl:Class ; owl:equivalentClass :B . :AZC a owl:Class ; owl:equivalentClass [ a owl:Class ; owl:intersectionOf ( :A :Z :C ) ] . 

然后你得到这些结果:

 -------------- | class | i | ============== | :ABC | :A | | :ABC | :B | | :ABC | :C | | :AZC | :A | | :AZC | :B | | :AZC | :C | | :CDE | :C | | :CDE | :D | | :CDE | :E | -------------- 

这可能不会太难(尽管获得最终查询会有点棘手)。 重要的部分是等价的类将通过路径相关联(owl:equivalentClass|^owl:equivalentClass)*

最大的结果

其次,结果应该只返回最大匹配; 因此,如果存在ABCD类并且我在A,B,C,D之间进行查询,则它将返回ABCD而不是ABC。

如果你能做到的话,这部分可能会相当困难。 SPARQL真的不是为处理这种查询而设计的。 计算交集类相交的类数是很容易的,但是如果可以的话,比较这些子集关系的集合会相当困难。