SPARQL - 查找 and/or 过滤 3 人之间的关系

SPARQL - find and/or filter relations between 3 persons

我有一个 ontology(内置 Protege)和几个家庭成员。像这张图片中的人之间可能有好(黄色)或坏(橙色)关系:

所有好的和坏的关系都是对称的!

我正在尝试查找所有人之间的所有 "triangle" 关系。问题是我得到的结果太多,而且我找不到使用 FILTER 函数减少结果的方法。

我的 SPARQL 查询:

SELECT *
WHERE {
{
     ?p1 g:hasGoodRel ?p2 . 

     OPTIONAL {?p1 g:hasBadRel  ?p3 . }
     OPTIONAL {?p2 g:hasBadRel  ?p3 . }
    }
}

结果是这样的:

:D  :C  :E  
:D  :D  :E  
:C  :D  :E  <-- 
:C  :D  :A  
:C  :B  :E  
:C  :B  :A  <--
:B  :C

我只想要这 2 个结果(三角形)

:A  :B  :C  
:C  :D  :E

我试过像这样的不同过滤器组合

 FILTER(?p1 != ?p2) 
 FILTER(?p1 != ?p3)
 FILTER(?p1 < ?p2)

但一直没有得到我想要的结果...我希望有人能指出正确的方向。

//编辑 这是 turtle

的例子
@prefix : <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@base <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186> .

<http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186> rdf:type owl:Ontology .

#################################################################
#    Object Properties
#################################################################

###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#hasBadRel
:hasBadRel rdf:type owl:ObjectProperty ;
           rdfs:subPropertyOf owl:topObjectProperty ;
           rdf:type owl:SymmetricProperty .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#hasGoodRel
:hasGoodRel rdf:type owl:ObjectProperty ;
            rdfs:subPropertyOf owl:topObjectProperty ;
            rdf:type owl:SymmetricProperty .


#################################################################
#    Classes
#################################################################

###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#Person
:Person rdf:type owl:Class .


#################################################################
#    Individuals
#################################################################

###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#A
:A rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :B ,
              :C ,
              :G .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#B
:B rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :A ;
   :hasGoodRel :C ,
               :G .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#C
:C rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :A ,
              :E ;
   :hasGoodRel :B ,
               :D .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#D
:D rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :E ;
   :hasGoodRel :C .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#E
:E rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :C ,
              :D .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#F
:F rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :C ,
              :D .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#G
:G rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :A ;
   :hasGoodRel :B .


###  Generated by the OWL API (version 4.2.8.20170104-2310) https://github.com/owlcs/owlapi

### 更新 2 ###

以下是我根据这张图进行的第二次测试的结果:

AKSW 的 Sparql 查询

:A  :B  :E  
:A  :B  :F  
:A  :C  :E  
:B  :D  :E
:C  :D  :E

以及 Stanislav Kralin 的查询

:A  :B  :E  
:A  :B  :F
:A  :C  :E  
:C  :D  :E  

区别只有:B :D :E

所以这两个查询都按预期工作。再次感谢。

如果有人想测试这张图,这里是ontology

@prefix : <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@base <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186> .

<http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186> rdf:type owl:Ontology .

#################################################################
#    Object Properties
#################################################################

###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#hasBadRel
:hasBadRel rdf:type owl:ObjectProperty ;
           rdfs:subPropertyOf owl:topObjectProperty .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#hasGoodRel
:hasGoodRel rdf:type owl:ObjectProperty ;
            rdfs:subPropertyOf owl:topObjectProperty .


#################################################################
#    Classes
#################################################################

###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#Person
:Person rdf:type owl:Class .


#################################################################
#    Individuals
#################################################################

###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#A
:A rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :E ;
   :hasGoodRel :B ,
               :C .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#B
:B rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :D ,
              :E ;
   :hasGoodRel :A .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#C
:C rdf:type owl:NamedIndividual ,
            :Person ;
   :hasGoodRel :E .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#D
:D rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :B ;
   :hasGoodRel :C .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#E
:E rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :A ,
              :B ,
              :D .


###  http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#F
:F rdf:type owl:NamedIndividual ,
            :Person ;
   :hasBadRel :A ,
              :B .


###  Generated by the OWL API (version 4.2.8.20170104-2310) https://github.com/owlcs/owlapi

我的想法是使用具有模式 :p1|:p2 的 SPARQL 1.1 属性 路径并检查三个节点之间的路径 n1 - n2 - n3 - n1:

PREFIX g: <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#> 
SELECT *
WHERE {
     ?p1 g:hasGoodRel|g:hasBadRel ?p2.
     ?p2 g:hasGoodRel|g:hasBadRel ?p3.
     ?p3 g:hasGoodRel|g:hasBadRel ?p1

     FILTER(str(?p1) < str(?p2) && str(?p2) < str(?p3))            
}

请注意,我的解决方案假定只允许使用其中一种关系的路径。例如

n1 --hasGoodRel--> n2 --hasGoodRel--> n3 --hasGoodRel--> n1

更新

为了考虑无向图,我们必须使用额外的 属性 路径表达式 p|^p,它通过 p

考虑传入和传出边
PREFIX g: <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#> 
SELECT DISTINCT *
WHERE {
     ?p1 (g:hasGoodRel|^g:hasGoodRel)|(g:hasBadRel|^g:hasBadRel) ?p2.
     ?p2 (g:hasGoodRel|^g:hasGoodRel)|(g:hasBadRel|^g:hasBadRel) ?p3.
     ?p3 (g:hasGoodRel|^g:hasGoodRel)|(g:hasBadRel|^g:hasBadRel) ?p1

     FILTER(str(?p1) < str(?p2) && str(?p2) < str(?p3))            
}

输出

+-----+-----+-----+
| p1  | p2  | p3  |
+-----+-----+-----+
|  :A |  :B |  :C |
|  :A |  :B |  :G |
|  :C |  :D |  :E |
|  :C |  :D |  :F |
+-----+-----+-----+

根据 ,关系应该是 "heterogeneous",我。 e.好关系和坏关系都应该出现在一个三角形中。因此,您的查询可能是:

PREFIX pref: <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#> 

SELECT DISTINCT ?s1 ?s2 ?s3
    WHERE { 
           {
           ?s1 pref:hasGoodRel|^pref:hasGoodRel ?s2 . 
           ?s1 pref:hasGoodRel|^pref:hasGoodRel ?s3 . 
           ?s2 pref:hasBadRel|^pref:hasBadRel ?s3 . 
           }
           UNION
           {
           ?s1 pref:hasBadRel|^pref:hasBadRel ?s2 . 
           ?s1 pref:hasBadRel|^pref:hasBadRel ?s3 . 
           ?s2 pref:hasGoodRel|^pref:hasGoodRel ?s3 .
           }
           FILTER (str(?s2) < str(?s3))
          }

思路是只有两种'situations':'two good, one bad'和'two bad, one good'。

在每个 'situation' 中,?s1 是单义绑定的,而 ?s2?s3 不是。然后 FILTER 子句强制 ?s2?s3.

的单义绑定

在不使用 UNION 的情况下,似乎很难找出合适的 FILTER 条件(检查 AKSW 的答案中的条件在这种情况下是否不合适)。然而这是可能的。

PREFIX pref: <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#> 

SELECT DISTINCT ?s1 ?s2 ?s3 WHERE { 
    ?s1 pref:hasGoodRel|^pref:hasGoodRel ?s2 . 
    ?s1 pref:hasBadRel|^pref:hasBadRel ?s3 . 
    ?s2 pref:hasBadRel|^pref:hasBadRel|pref:hasGoodRel|^pref:hasGoodRel ?s3 . 
    BIND ((str(?s1) > str(?s2)) AS ?x) .
    BIND ((str(?s2) > str(?s3)) AS ?y) .
    BIND ((str(?s1) < str(?s3)) AS ?z) .
    FILTER (( ?x || ?y ) && ( ?x || ?z ) && ( ?y || ?z ))
    } ORDER BY ASC(?s1)

下面是完整的RDF测试数据。正确的查询应该 return 12 个结果:每个字母 A–L 恰好有一个结果。

@prefix  pref: <http://www.semanticweb.org/anato/ontologies/2017/7/untitled-ontology-186#> 

pref:A1 pref:hasGoodRel pref:A2 .
pref:A1 pref:hasBadRel pref:A3 .
pref:A2 pref:hasBadRel pref:A3 .

pref:B1 pref:hasBadRel pref:B2 .
pref:B1 pref:hasGoodRel pref:B3 .
pref:B2 pref:hasBadRel pref:B3 .

pref:C1 pref:hasGoodRel pref:C2 .
pref:C1 pref:hasBadRel pref:C3 .
pref:C2 pref:hasBadRel pref:C3 .

pref:D1 pref:hasBadRel pref:D2 .
pref:D1 pref:hasGoodRel pref:D3 .
pref:D2 pref:hasBadRel pref:D3 .

pref:E1 pref:hasBadRel pref:E2 .
pref:E1 pref:hasBadRel pref:E3 .
pref:E2 pref:hasGoodRel pref:E3 .

pref:F1 pref:hasBadRel pref:F2 .
pref:F1 pref:hasBadRel pref:F3 .
pref:F2 pref:hasGoodRel pref:F3 .

#################

pref:G1 pref:hasBadRel pref:G2 .
pref:G1 pref:hasGoodRel pref:G3 .
pref:G2 pref:hasGoodRel pref:G3 .

pref:H1 pref:hasGoodRel pref:H2 .
pref:H1 pref:hasBadRel pref:H3 .
pref:H2 pref:hasGoodRel pref:H3 .

pref:I1 pref:hasBadRel pref:I2 .
pref:I1 pref:hasGoodRel pref:I3 .
pref:I2 pref:hasGoodRel pref:I3 .

pref:J1 pref:hasGoodRel pref:J2 .
pref:J1 pref:hasBadRel pref:J3 .
pref:J2 pref:hasGoodRel pref:J3 .

pref:K1 pref:hasGoodRel pref:K2 .
pref:K1 pref:hasGoodRel pref:K3 .
pref:K2 pref:hasBadRel pref:K3 .

pref:L1 pref:hasGoodRel pref:L2 .
pref:L1 pref:hasGoodRel pref:L3 .
pref:L2 pref:hasBadRel pref:L3 .

老实说,我已经使用 Wolfram Cloud Mathematica 生成了所有可能的 FILTER 特定类型的条件,然后半自动检查它们。

Do[Print[BooleanMinimize[BooleanFunction[i, {x,y,z}]]], {i, 1, 255, 1}]