没有使公式更容易的内置插件......</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
,因为行数(每行都绑定元素n和n+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 |
------------------------------