0

Let A = {x1,x2,…,xn}. We want to calculate the difference between xi and xj, where xj is min{x ∈ A : x > xi }. It is possible to translate this kind of expression into a Jena rule?

Stephan Muller
  • 27,018
  • 16
  • 85
  • 126
paolo789
  • 3
  • 4
  • 2
    You can do math with Jena rules. You'll need to explain how you are representing the set of numbers, and where you want to store the result. That said, this would probably be *much* easier if you use SPARQL. You could use a single query to get all the results that you want, and you could even use a construct query to build the results in RDF, which could be added back to your model. – Joshua Taylor Oct 14 '14 at 12:07

1 Answers1

2

Yes you can do this in both Jena Rules and in Jena ARQ (the query processing engine for SPARQL).

The Setup

Let us assume that you have defined a structured representation of your data. For Xi, you have an object that corresponds to something like this (N3):

[ a :Entry
; :hasEntryValue 4.3
]

Then, for your set, A, you can define its values as an RDF Collection such as rdf:List. The following N3 woudl describe the set A={4.3, 4.2}, for example.

[ a :Set
; dct:identifier "A"
; entries ( [  a :Entry
            ;  :hasEntryValue 4.3
            ][ a :Entry
            ;  :hasEntryValue 4.2
            ] )
] .

In Jena Rules

In Jena rules, you could write something along the lines of:

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

This would require you to construct a Jena Builtin for the nextSmallest portion of the query. The above rule would, for a given value, ?x0, within a particular set ,?set, attempt to identify the nextSmallest element, ?x1, and (if that succeeds) construct a new node, ?calculated and associate the ?difference with it by means of some domain-specific :hasValue property. As a style note, I also introduced a :derivedFrom property in order to trace where that node came from so it wouldn't be useless as a calculation result.

In ARQ / SPARQL

The first question is whether or not you want the results to be in your graph with your data (as in the rule-based approach) or if you simply want the results. If you simply want the results, you have a choice as to whether or not the results are in a graph form. The simplest approach would be to simply SELECT the results:

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 ) .
    }
}

The above query was written off the top of my head so it may need some tweaks. The gist of it is that you retrieve any two members of the collection, and orient them such that ?x0 is the smaller of the two. You then throw out the bound pairs if there exists any pair between them. The query engine will consider the cartesian product of the set when selecting bindings for ?x0 and ?x1 including when sameTerm(?x0, ?x1), so using FILTER( ?x0Val < ?x1Val ) provides a quick way to discard trivially poor bindings.

Community
  • 1
  • 1
Rob Hall
  • 2,693
  • 16
  • 22