是否可以在SPARQL中表达递归定义?

时间:2014-08-12 05:00:15

标签: recursion constraints rdf sparql

想象一下,您拥有一个简单的社交网络,其中人们必须只拥有一个值为rdfs:label的{​​{1}}个属性,并且可以包含任意数量的"Person",其值也必须是相同的人结构体。一些示例数据可能是:

foaf:knows

在逻辑术语中,定义可能类似于:

∀x(Person(x)≡rdfs:label(x,“Person”)∧∀y(rdfs:label(x,y)→y =“Person”)∧∀y(foaf:knows(x, Y)→人(Y)))

是否可以在SPARQL中表达这些递归定义?

我能够在没有:peter foaf:knows :john; foaf:knows :anna; rdfs:label "Person" . :john foaf:knows :anna; rdfs:label "Person" . :anna rdfs:label "Person" . 的递归引用的情况下表达部分查询:

foaf:knows

是否可以在SPARQL中表达这样的递归定义?

  

注意:我按照约书亚的建议编辑了用“定义”改变术语“约束”的问题

2 个答案:

答案 0 :(得分:7)

这是一个定义,而不是一对约束

我们经常根据必要和充分的条件来考虑定义。足够的条件是那些给我们“足够”的信息来推断某事物是某一特定集合的元素,而必要的条件是那些告诉我们更多关于个体的条件。例如,在OWL中,我们可能有公理:

  

男人⊑人   人⊑⊑hasName

第一个是Person的充分条件:知道某个东西是一个人就足以确定它也是一个人。第二个是人的必要条件:如果某人是某个人,那么它必须有一个名字。 (双重地,我们也可以注意到第一个公理是人的必要条件:如果某个人是人,那么它必须是一个人。第二个公理是∃hasName的充分条件;如果某个人是人,那么它必须有一个名字。)

约束检查通常是找到满足类的充分条件但不满足所有必要条件的个体的任务。那不是你想要做的。相反,你正在寻找符合人格必要和充分条件的人:

  1. 正好有“人物”标签
  2. 只知道其他人。
  3. 在约束验证中,您将编写一个查找有问题的个人的查询(例如,应该是人,但不是的人),但在您的任务中,您将找到好人。

    寻找符合您规范的人

    通常,您无法在SPARQL中指定递归定义,但在这种情况下,可以编写将选择所有人的查询。诀窍是首先使用一个模式来识别图中的所有节点。然后,从概念上讲,我们假设每个人都是一个人,然后过滤掉那些不符合条件的人。在这种情况下,这是可能的,因为条件只是由foaf链:可知的(包括零长度链)所有的一切都应该有标签“Person”,而不是别的。这是一些示例数据(包括您的答案中的示例),查询,最后是结果。

    @prefix : <http://stackoverflow.com/q/25256452/1281433/>.
    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    @prefix foaf: <http://xmlns.com/foaf/0.1/>.
    
    :peter foaf:knows :john; 
           foaf:knows :anna;
           rdfs:label "Person" .
    
    :john  foaf:knows :anna;
           rdfs:label "Person" .
    
    :anna  rdfs:label "Person" .
    
    :mary rdfs:label "Person" .
    
    :tom rdfs:label "Cat" .
    
    :pluto rdfs:label "Dog" ; foaf:knows :tom .
    
    :ben rdfs:label "Wolf"; rdfs:label "Person" .
    
    :mary rdfs:label "Person"; foaf:knows :ben .
    
    :sam rdfs:label "Person"; foaf:knows :mary .
    
    prefix : <http://stackoverflow.com/q/25256452/1281433/>
    prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    prefix foaf: <http://xmlns.com/foaf/0.1/>
    
    select ?person where { 
      #-- each node in the graph
      ?person :? ?person .
    
      #-- except those that foaf:know* some ?x
      #-- (and since * includes the zero length
      #-- path, ?x is also bound to ?person)
      #-- that don't meet the labeling condition.
      filter not exists {
        ?person foaf:knows* ?x
        optional { ?x rdfs:label ?label }
        filter ( !bound(?label) || ?label != "Person" )
      }
    }
    
    ----------
    | person |
    ==========
    | :anna  |
    | :john  |
    | :peter |
    ----------
    

    约束检查

    现在,假设上述条件1和2实际上是人格的必要条件。然后,根据充分条件,我们可以编写不同的查询来查找违规。您可能希望在图中包含非人员节点,因此您可能具有足够的条件,即节点具有rdf:type:Person。然后你可以使用这样的查询:

    prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    prefix : <http://stackoverflow.com/q/25256452/1281433/>
    
    #-- There are two way something with type :Person
    #-- can be invalid.  (i) it can lack a label, or 
    #-- have a label other than "Person";  (ii) it 
    #-- can have a value of foaf:knows* that doesn't
    #-- have rdf:type :Person.
    
    select ?person where {
      #-- Examine each person in the graph.
      ?person a :Person .
    
      { #-- Check that ?person has a label, and that
        #-- that it has no label other than "Person"
        optional { ?person rdfs:label ?label } 
        filter ( !bound(?label) || ?label != "Person" )
      } UNION
      { #-- Check that every value of foaf:knows 
        #-- also has type :Person.  If some value
        #-- has type :Person, but violates the constraints,
        #-- we'll catch it separately.
        ?person foaf:knows ?x .
        filter not exists { ?x a :Person }
      }
    }
    

答案 1 :(得分:1)

上一个答案的一个问题是它需要一个额外的谓词来获取类型的值:Person。

然而,问题在于我们希望通过其结构来识别Person,在这种情况下意味着:

  1. 它只有一个rdfs:label属性,其值为"Person"
  2. 它具有零个或多个foaf:knows属性,其值遵循这些约束。
  3. 请注意,第二个约束具有递归性质,因为它是一个自引用。

    部分解决方案(没有递归约束)可以是:

    prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    prefix foaf: <http://xmlns.com/foaf/0.1/>
    prefix : <http://stackoverflow.com/q/25256452/1281433/>
    
    select ?person where {
      #-- Examine each non-literal node in the graph.
      ?person :* ?person .
      filter ( !isLiteral(?person) )
    
      { #-- Check that ?person has a label, and that
        #-- it has no label other than "Person"
        optional { ?person rdfs:label ?label } 
        filter ( !bound(?label) || ?label != "Person" )
      } UNION
      { #-- Check that every value of foaf:knows 
        #-- satisfies the constraints of Person
        ?person foaf:knows ?x .
        filter not exists { 
          ?x rdfs:label "Person" .
          # Here I would like to also express that ?x only knows 
          # values that satisfy the constraints of Person 
          # but this would be recursive
        }
      }
    }
    

    我们可以添加一些更错误的值来检查它是否检测到它们:

    :tom rdfs:label "Cat" .
    
    :pluto rdfs:label "Dog" ; foaf:knows :tom .
    
    :ben rdfs:label "Wolf"; rdfs:label "Person" .
    
    :mary rdfs:label "Person"; foaf:knows :ben .
    
    :sam rdfs:label "Person"; foaf:knows :mary .
    

    之前的SPARQL查询检测到:pluto:tom:ben,但它未检测到不符合约束的:mary:sam