Recursion 可以在SPARQL中表达递归定义吗?

Recursion 可以在SPARQL中表达递归定义吗?,recursion,constraints,rdf,sparql,Recursion,Constraints,Rdf,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

假设您有一个简单的社交网络,其中人们必须只有一个属性
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" .
从逻辑上讲,定义可以是:

∀x(人(x)≡ rdfs:标签(x,“人”)∧∀y(rdfs:label(x,y)→y=“个人”)∧∀y(foaf:knows(x,y)→个人(y)))

可以在SPARQL中表达这些递归定义吗

我能够在没有递归引用的情况下将查询的一部分表示为:

前缀ex:
前缀foaf:
前缀rdfs:
选择人{
#确保只有一个rdfs:label
{选择人{
?人员rdfs:标签?o。
}分组依据?具有(计数(*)=1)的人员
#确保rdfs:label值为“Person”
{选择人{
?人员rdfs:标签?o。
过滤器((?o=“Person”))
}分组依据?具有(计数(*)=1)的人员
#计算foaf的数量:知道
{选择人员(计数(*)作为p_c0){
?foaf人员:知道[]。
}按人分组
}
#计算foaf的数量:使用具有个人结构的值进行了解
{选择人员(计数(*)作为p_c1){
人物foaf:知道?人物1.#我如何表达人物1具有人物结构?
}按人分组
}
过滤器(?p_c0=?p_c1)
}
有可能在SPARQL中表达这样的递归定义吗

注:根据Joshua的建议,我对问题进行了编辑,将“约束”一词改为“定义”

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

Man&SQQ子部分;人
人员和SQQ子部分;∃哈斯名称

第一个是人的充分条件:知道某事物是人就足以决定它也是人。第二个是人的必要条件:如果某物是人,那么它必须有一个名字。(同时,我们还可以注意到,第一条公理是人的必要条件:如果某物是人,那么它一定是人。第二条公理是人的充分条件∃hasName;如果某事物是人,那么它必须有一个名称。)

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

  • 贴有“人”的标签
  • 只认识其他人
  • 在约束验证中,您将编写一个查询来查找有问题的个体(例如,应该是人但不是人的事物),但在您的任务中,您将找到好的个体

    寻找符合您规范的个人 一般来说,您不能在SPARQL中指定递归定义,但在本例中,您可以编写一个选择所有人的查询。诀窍是首先使用标识图中所有节点的模式。然后,在概念上,我们假设每个人都是一个人,然后过滤掉那些不符合条件的人。在这种情况下这是可能的,因为条件很简单,foaf:knows链(包括零长度链)可以访问的所有内容都应该有标签“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 .
    
    约束检查 现在,假设上面的条件1和2实际上是做人的必要条件。然后,根据充分条件,我们可以编写不同的查询来查找冲突。您可能希望在图中有非person节点,因此您可能有一个充分条件,即节点具有rdf:type:person。然后可以使用如下查询:

    前缀rdfs:
    前缀:
    #--有两种类型的东西:Person
    #--可能是无效的。(i) 它可能缺少标签,或者
    #--有“人”以外的标签;(ii)资讯科技
    #--可以有一个值foaf:knows*这不是
    #--拥有rdf:type:Person。
    选择?人在哪里{
    #--检查图表中的每个人。
    ?人a:人。
    {#--检查一下?这个人有标签,而且
    #--除了“人”之外,它没有其他标签
    可选{个人rdfs:label?label}
    过滤器(!bound(?label)| |?label!=“Person”)
    }联合
    {#--检查foaf:的每个值是否都知道
    #--还有类型:Person.If某个值
    #--具有类型:Person,但违反了约束,
    #--我们分开来接。
    foaf人员:知道?x。
    筛选器不存在{?x a:Person}
    }
    }
    
    前面的答案的一个问题是,它需要一个额外的谓词来获取Person类型的值

    然而,问题是我们想通过结构来识别一个人,在这种情况下,这意味着:

  • 它只有一个
    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" .
    
    前缀rdfs:
    前缀foaf:
    前缀:
    选择?人在哪里{
    #--检查图中的每个非文字节点。
    人:*?人。
    过滤器(!isLiteral(?person))
    {#--检查一下?这个人有标签,而且
    #--除了“Pers”之外,它没有其他标签