在 SPARQL 中操作 RDF 集合的函数 [英] Functions to manipulate RDF collections in SPARQL

查看:65
本文介绍了在 SPARQL 中操作 RDF 集合的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to know if there are some functions to manipulate RDF Collections in SPARQL.

一个激励问题如下.

假设你有:

@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)

And you want to calculate the following formula: ((Xn - Xn-1) + ... (X2 - X1)) / (N - 1)

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

Is there some general way to calculate it?

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

Up until now, I was only able to calculate it for a fixed set of values. For example, for 4 values, I can use the following query:

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 个值并定义某种递归函数来计算该表达式.我认为这是不可能的,但也许有人有一个很好的解决方案.

What I would like is some way to access the Nth value and to define some kind of recursive function to calculate that expression. I think it is not possible, but maybe, someone has a nice solution.

推荐答案

没有使公式更容易的内置函数......

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

No built-ins that make formulas easier…

SPARQL does include some mathematical functions for arithmetic and aggregate computations. However, I don't know of any particularly convenient ways of concisely representing mathematical expressions in SPARQL. I've been looking at a paper lately that discusses an ontology for representing mathematical objects like expressions and definitions. They implemented a system to evalute these, but I don't think it used SPARQL (or at least, it wasn't just a simple extension of SPARQL).

Wenzel、Ken 和 Heiner Reinhardt."使用 OpenMath 进行关联数据应用程序的数学计算."第 24 届 OpenMath 研讨会和第 7 届数学用户界面 (MathUI) 研讨会的联合论文集.2012.

Wenzel, Ken, and Heiner Reinhardt. "Mathematical Computations for Linked Data Applications with OpenMath." Joint Proceedings of the 24th Workshop on OpenMath and the 7th Workshop on Mathematical User Interfaces (MathUI). 2012.

……但我们仍然可以做这个案例.

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

…but we can still do this case.

That said, this particular case isn't too hard to do, since it's not too hard to work with RDF lists in SPARQL, and SPARQL includes the mathematical functions needed for this expression. First, a bit about RDF list representation, that will make the solution easier to understand. (If you're already familiar with this, you can skip the next paragraph or two.)

RDF 列表是链表,每个列表通过 rdf:first 属性与它的第一个元素相关,并通过 rdf:rest 与列表的其余部分相关.所以方便的符号 (:x1 :x2 :x3 :x4) 实际上是:

RDF lists are linked lists, and each list is related to it's first element by the rdf:first property, and to the rest of the list by rdf:rest. So the convenient notation (:x1 :x2 :x3 :x4) is actually shorthand for:

_: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 .

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

Representing blank nodes with [], we can make this a bit clearer:

[ 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 的元素,那么任何列表 l 都可以通过偶数到达rdf:rest/rdf:rest 的重复次数(包括 0)是一个列表,其 rdf:first 是列表的奇数元素(因为您从 1 开始索引).从 l 开始,再往前走一个 rdf:rest,我们在 rdf:firstl'是列表的偶数元素.

Once the head of the list has been identified, that is, the element with rdf:first :x1, then any list l reachable from it by an even number repetitions (including 0) of rdf:rest/rdf:rest is a list whose rdf:first is an odd numbered element of the list (since you started indexing at 1). Starting at l and going forward one rdf:rest, we're at an l' whose rdf:first is an even numbered element of the list.

由于 SPARQL 1.1 属性路径让我们写 (rdf:rest/rdf:rest)* 来表示 rdf:rest 的任何偶数重复,我们可以写以下查询将 ?n 的奇数元素的 :value 和以下偶数元素的值绑定到 ?nPlusOne.SELECT 形式中的数学很简单,虽然为了得到 N-1,我们实际上使用了 2*COUNT(*)-1,因为行数(每行绑定元素 nn+1)是 N/2.

Since SPARQL 1.1 property paths let us write (rdf:rest/rdf:rest)* to denote any even numbered repetitions of rdf:rest, we can write up the following query that binds the :value of odd numbered elements of ?n and the value of the following even numbered elements to ?nPlusOne. The math in the SELECT form is straightforward, although to get N-1, we actually use 2*COUNT(*)-1, because the number of rows (each of which binds elements n and n+1) is 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):

Results (using Jena's command line ARQ):

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

这是自

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

更新

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

Update

I just realized that what is implemented above was based on my comment on the question about whether the summation was correct, because it simplified very easily. That is, the above implements

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

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

而原始问题要求

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

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

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

The original is even simpler, since the pairs are identified by each rdf:rest of the original list, not just even numbers of repetitions. Using the same approach as above, this query can be represented by:

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 |
------------------------------

当然,既然表达式可以简化为

Of course, since the expression can be simplified to

xN - x1/(N - 1)

xN - x1 / (N - 1)

我们也可以使用一个查询,将 ?x1 绑定到列表的第一个元素,?xn 绑定到最后一个元素,?xi 到列表的每个元素(这样 COUNT(?xi)(还有 COUNT(*))是列表中的项目数):

we can also just use a query which binds ?x1 to the first element of the list, ?xn to the last element, and ?xi to each element of the list (so that COUNT(?xi) (and also COUNT(*)) is the number of items in the list):

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 |
------------------------------

这篇关于在 SPARQL 中操作 RDF 集合的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆