4

我想知道是否有一些函数可以在 SPARQL 中操作 RDF 集合。

一个激励问题如下。

假设你有:

@prefix : <http://example.org#> .
:x1 :value 3 .
:x2 :value 5 .
:x3 :value 6 .
:x4 :value 8 .

:list :values (:x1 :x2 :x3 :x4) .

并且您要计算以下公式: ((Xn - Xn-1) + ... (X2 - X1)) / (N - 1)

有什么通用的计算方法吗?

到目前为止,我只能为一组固定的值计算它。例如,对于 4 个值,我可以使用以下查询:

prefix : <http://example.org#> 
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?r { 
 ?list :values ?ls .
 ?ls rdf:first ?x1 .
 ?ls rdf:rest/rdf:first ?x2 .
 ?ls rdf:rest/rdf:rest/rdf:first ?x3 .
 ?ls rdf:rest/rdf:rest/rdf:rest/rdf:first ?x4 .
 ?x1 :value ?v1 .
 ?x2 :value ?v2 .
 ?x3 :value ?v3 .
 ?x4 :value ?v4 .
 BIND ( ((?v4 - ?v3) + (?v3 - ?v2) + (?v2 - ?v1)) / 3 as ?r)
}

我想要的是某种访问第 N 个值并定义某种递归函数来计算该表达式的方法。我认为这是不可能的,但也许有人有一个很好的解决方案。

4

2 回答 2

7

没有使公式更容易的内置插件......</h3>

SPARQL 确实包含一些用于算术和聚合计算的数学函数。但是,我不知道在 SPARQL 中简明地表示数学表达式的任何特别方便的方法。我最近一直在看一篇论文,该论文讨论了一种表示数学对象(如表达式和定义)的本体。他们实现了一个系统来评估这些,但我认为它没有使用 SPARQL(或者至少,它不仅仅是 SPARQL 的简单扩展)。

文泽尔、肯和海纳·莱因哈特。“使用 OpenMath 进行关联数据应用程序的数学计算。” 第 24 届 OpenMath 研讨会和第 7 届数学用户界面 (MathUI) 研讨会的联合论文集。2012 年。

......但我们仍然可以这样做。

也就是说,这种特殊情况并不太难做到,因为在 SPARQL 中使用 RDF 列表并不难,而且 SPARQL 包含此表达式所需的数学函数。首先,关于 RDF 列表表示,这将使解决方案更容易理解。(如果你已经熟悉这个,你可以跳过下一段或两段。)

RDF 列表是链表,每个列表通过rdf:first属性与其第一个元素相关联,通过rdf:rest. 所以方便的表示法(:x1 :x2 :x3 :x4)实际上是以下的简写:

_:l1 rdf:first :x1 ; rdf:rest _:l2 .
_:l2 rdf:first :x2 ; rdf:rest _:l3 .
_:l3 rdf:first :x3 ; rdf:rest _:l4 .
_:l3 rdf:first :x4 ; rdf:rest rdf:nil .

用 表示空白节点[],我们可以更清楚一点:

[ rdf:first :x1 ;
  rdf:rest [ rdf:first :x2 ;
             rdf:rest [ rdf:first :x3 ;
                        rdf:rest [ rdf:first :x4 ;
                                   rdf:rest rdf:nil ]]]]

一旦确定了列表的头部,即带有 的元素rdf:first :x1,那么任何从它可以通过偶数重复(包括 0)到达的列表lrdf:rest/rdf:rest都是一个列表,其rdf:first是列表的奇数元素(因为你开始索引为 1)。从l开始并向前推进 one rdf:rest,我们处于一个l' ,它是列表的rdf:first偶数元素。

由于 SPARQL 1.1 属性路径允许我们编写(rdf:rest/rdf:rest)*来表示 的任何偶数重复rdf:rest,我们可以编写以下查询,将:value的奇数元素的?n和后续偶数元素的值绑定到?nPlusOne。表格中的数学SELECT很简单,尽管要获得N-1,我们实际上使用2*COUNT(*)-1,因为行数(每行都绑定元素nn+1)是 N/2。

prefix : <http://example.org#> 
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ( SUM(?nPlusOne-?n)/(2*COUNT(*)-1) as ?result) {
 ?list :values [ (rdf:rest/rdf:rest)* [ rdf:first [ :value ?n ] ; 
                                        rdf:rest  [ rdf:first [ :value ?nPlusOne ]]]] .
}

结果(使用 Jena 的命令行 ARQ):

$ arq --query query.sparql --data data.n3 
------------------------------
| result                     |
==============================
| 1.333333333333333333333333 |
------------------------------

这是预期的,因为

 (5 - 3) + (8 - 6)     2 + 2     4      _ 
------------------- = ------- = --- = 1.3
      (4 - 1)            3       3

更新

我刚刚意识到,上面的实现是基于我对求和是否正确的问题的评论,因为它很容易简化。也就是上面的实现

(x2 - x1) + (x4 - x3) + ... + (xN - xN-1) / (N - 1)

而最初的问题要求

(x2 - x1) + (x3 - x2) + … + (xN-1 - xN-2) + (xN - xN-1) / (N - 1)

原始的甚至更简单,因为这些对由每个rdf:rest原始列表标识,而不仅仅是偶数重复。使用与上述相同的方法,此查询可以表示为:

prefix : <http://example.org#> 
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ( SUM(?nPlusOne-?n)/COUNT(*) as ?result) {
 ?list :values [ rdf:rest* [ rdf:first [ :value ?n ] ; 
                             rdf:rest  [ rdf:first [ :value ?nPlusOne ]]]] .
}

结果:

$ arq --query query.sparql --data data.n3 
------------------------------
| result                     |
==============================
| 1.666666666666666666666666 |
------------------------------

当然,由于表达式可以简化为

xN - x1 / (N - 1)

我们也可以只使用绑定?x1到列表的?xn第一个元素、最后一个元素和?xi列表的每个元素的查询(因此COUNT(?xi)(以及COUNT(*))是列表中的项目数):

prefix : <http://example.org#> 
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT (((?xn-?x1)/(COUNT(?xi)-1)) as ?result) WHERE {
 ?list :values [ rdf:rest*/rdf:first [ :value ?xi ] ;
                 rdf:first [ :value ?x1 ] ;
                 rdf:rest* [ rdf:first [ :value ?xn ] ; 
                             rdf:rest  rdf:nil ]] .
}
GROUP BY ?x1 ?xn

结果:

$ arq --query query.sparql --data data.n3 
------------------------------
| result                     |
==============================
| 1.666666666666666666666666 |
------------------------------
于 2013-06-26T12:05:58.013 回答
0

您还可以查看在 RDF 中描述/表示列表的替代方法,例如,借助Ordered List Ontology。我认为使用此模型,您可以更轻松地查询您想要的内容;)

于 2013-07-03T17:10:28.937 回答