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 を使用したリンクト データ アプリケーションの数学的計算」。OpenMath に関する第 24 回ワークショップと数学ユーザー インターフェイス (MathUI) に関する第 7 回ワークショップの共同議事録。2012年。

…しかし、このケースはまだ実行できます。

とはいえ、SPARQL で RDF リストを操作するのはそれほど難しくなく、SPARQL にはこの式に必要な数学関数が含まれているため、この特定のケースを実行するのはそれほど難しくありません。最初に、RDF リスト表現について少し説明します。これにより、ソリューションが理解しやすくなります。(すでにこれに精通している場合は、次の段落または 2 つの段落をスキップできます。)

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

リストの先頭、つまり を持つ要素が識別されると、そこから偶数回の繰り返し (0 を含む) によって到達可能rdf:first :x1なリストlrdf:rest/rdf:restは、リストrdf:firstの奇数番号の要素であるリストです ( 1 での索引付け)。lから始めてone に進むと、リストの偶数番号の要素で あるrdf:restl 'にいます。rdf:first

SPARQL 1.1 プロパティ パス(rdf:rest/rdf:rest)*では、 の偶数番号の繰り返しを表すように記述できるため、の奇数番号の要素とそれに続く偶数番号の要素の値をrdf:restバインドする次のクエリを作成できます。N-1を取得するには、実際には を使用しますが、フォームの数学は単純です。これは、行の数 (それぞれが要素nn+1をバインドする) が N/2 であるためです。:value?n?nPlusOneSELECT2*COUNT(*)-1

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 に答える