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

Lab*_*bra 2 recursion rdf constraints sparql

想象一下,你有一个简单的社交网络,人们必须只有一个rdfs:label有价值的财产,"Person"并且任何数量的foaf:knows人也必须是具有相同结构的人.一些示例数据可能是:

:peter foaf:knows :john; 
       foaf:knows :anna;
       rdfs:label "Person" .

:john  foaf:knows :anna;
       rdfs:label "Person" .

:anna  rdfs:label "Person" .
Run Code Online (Sandbox Code Playgroud)

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

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

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

我能够表达部分查询而没有递归引用foaf:knowsas:

PREFIX ex: <http://xmlns.com/foaf/0.1/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>

select ?person {

    # Ensure there is only one rdfs:label
    { SELECT ?person {
      ?person rdfs:label ?o .
    } GROUP BY ?person HAVING (COUNT(*)=1)}

    # Ensure the rdfs:label value is "Person"
    { SELECT ?person {
      ?person rdfs:label ?o . 
      FILTER ((?o = "Person"))
    } GROUP BY ?person HAVING (COUNT(*)=1)}

    # Count the number of foaf:knows
    { SELECT ?person (COUNT(*) AS ?p_c0) { 
       ?person foaf:knows [] . 
      } GROUP BY ?person
    }

    # Count the number of foaf:knows with a value that has the structure of a person
    { SELECT ?person (COUNT(*) AS ?p_c1) { 
       ?person foaf:knows ?person1 . # How can I express that person1 has the structure of people?
      } GROUP BY ?person
    }
    FILTER (?p_c0 = ?p_c1)
}
Run Code Online (Sandbox Code Playgroud)

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

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

Jos*_*lor 7

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

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

男人
⊑人人⊑⊑hasName

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

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

  1. 有完全标签"人"
  2. 只知道其他人.

在约束验证中,您将编写一个查找有问题的个体的查询(例如,应该是人,但不是的人),但在您的任务中,您将找到好的个体.

寻找符合您规格的人

通常,您不能在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 .
Run Code Online (Sandbox Code Playgroud)
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" )
  }
}
Run Code Online (Sandbox Code Playgroud)
----------
| person |
==========
| :anna  |
| :john  |
| :peter |
----------
Run Code Online (Sandbox Code Playgroud)

约束检查

现在,假设上述条件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 }
  }
}
Run Code Online (Sandbox Code Playgroud)