Пусть A = {x1,x2,,xn}. Мы хотим вычислить разницу между xi и xj, где xj равно min{x A x > xi }. Можно ли перевести такое выражение в правило Йены?
От математического выражения к правилу Йены
Ответы (1)
Да, вы можете сделать это как в Jena Rules, так и в Jena ARQ (механизм обработки запросов для SPARQL).
Настройка
Предположим, вы определили структурированное представление ваших данных. Для Xi у вас есть объект, который соответствует примерно этому (N3):
[ a :Entry
; :hasEntryValue 4.3
]
Затем для вашего набора A вы можете определить его значения как коллекцию RDF, например rdf:List. Следующий N3 будет описывать, например, набор A={4.3, 4.2}.
[ a :Set
; dct:identifier "A"
; entries ( [ a :Entry
; :hasEntryValue 4.3
][ a :Entry
; :hasEntryValue 4.2
] )
] .
Правила Йены
В правилах Йены вы могли бы написать что-то вроде:
[calculate: ( ?set rdf:type :Set ),
( ?set rdfs:member ?x0 ),
nextSmallest( ?set ?x0 ?x1 ),
makeSkolem( ?calculated ?x0 ?set),
difference( ?difference ?x0 ?x1)
-> (?calculated :hasValue ?difference),
(?calculated :derivedFrom ?x0),
(?calculated :derivedFrom ?x1)
]
Это потребует от вас создания Jena Builtin для nextSmallest
части запроса. Приведенное выше правило для данного значения ?x0
в определенном наборе ?set
попытается идентифицировать элемент nextSmallest
?x1
и (если это удастся) построить новый узел ?calculated
и связать с ним ?difference
посредством некоторых доменное свойство :hasValue
. В качестве примечания к стилю я также ввел свойство :derivedFrom
, чтобы отслеживать, откуда взялся этот узел, чтобы он не был бесполезен в результате вычислений.
В ARQ/SPARQL
Первый вопрос заключается в том, хотите ли вы, чтобы результаты были на вашем графике с вашими данными (как в подходе, основанном на правилах), или вы просто хотите получить результаты. Если вам просто нужны результаты, у вас есть выбор, будут ли результаты представлены в виде графика. Самым простым подходом было бы просто SELECT
результаты:
SELECT ?set ?x0Val (BIND(?x1Val-?x0Val) AS ?difference) WHERE {
?set rdf:type :Set .
?set rdfs:member ?x0 .
?set rdfs:member ?x1 .
?x0 :hasEntryValue ?x0Val .
?x1 :hasEntryValue ?x1Val .
FILTER( ?x0Val < ?x1Val )
FILTER NOT EXISTS {
?set rdfs:member ?otherEntry .
?otherEntry :hasEntryValue ?otherVal .
FILTER( ?x0Val < ?otherVal && ?otherVal < ?x1Val ) .
}
}
Вышеупомянутый запрос был списан с головы, поэтому он может потребовать некоторых настроек. Суть в том, что вы извлекаете любые два члена коллекции и ориентируете их так, чтобы ?x0
было меньшим из двух. Затем вы отбрасываете связанные пары, если между ними существует какая-либо пара. Механизм запросов будет учитывать декартово произведение набора при выборе привязок для ?x0
и ?x1
, в том числе для sameTerm(?x0, ?x1)
, поэтому использование FILTER( ?x0Val < ?x1Val )
обеспечивает быстрый способ отбросить тривиально плохие привязки.