On 18/08/16 06:42, Niels Andersen wrote:
Dear Apache Jena users group,

We are using Apache Jena with a combination of a persistent TDB database and an 
in memory inference model. Our implementation is based on the Jena API.

We are using Jena rules to drive the reasoner. We are using 
GenericRuleReasoner.FORWARD_RETE for performance reasons.

Given the following example data in ttl format:

ex:Invoice_1
rdf:type ex:Invoice;
ex:customer ex:Customer_1;
.
ex:InvoiceItem_1
rdf:type ex:InvoiceItem;
ex:invoice ex:Invoice_1;
ex:invoiceItem_Product ex:Product_1;
ex:invoiceItem_Amount "30.0"^^xsd:decimal;
.
ex:InvoiceItem_2
rdf:type ex:InvoiceItem;
ex:invoice ex:Invoice_1;
ex:invoiceItem_Product ex:Product_1;
ex:invoiceItem_Amount "30.0"^^xsd:decimal;
.
ex:InvoiceItem_3
rdf:type ex:InvoiceItem;
ex:invoice ex:Invoice_1;
ex:invoiceItem_Product ex:Product_4;
ex:invoiceItem_Amount "105.0"^^xsd:decimal;
.

The example above shows one invoice (ex:Invoice_1) with three invoice line 
items. Each invoice line item has an associated amount.

I want to set the amount of the invoice to the sum of the amounts of the line 
items. My preferred approach would be to use Jena rules to do this, but I 
cannot see how that is possible. The reason that I would prefer to use a rule 
over a SPARQL construct is that the rule has to be called iteratively many 
times (our actual implementation is a lot more demanding than the example 
above).

Looking at the Jena Builtin functions 
(https://jena.apache.org/documentation/inference/#builtin-primitives ) I see 
that there is a sum function, but this is sum(?a, ?b, ?c) that results in ?c = 
?a + ?b, not the sum of all values that meet a certain criteria (aggregate 
function).

Is it possible to create a rule like this (sumByGroup is a made up function 
with the first argument being the group, the second being what should be 
summed, and the third being the return variable):

[InvoiceSumAmountRule:
(?Invoice rdf:type ex:Invoice), (?InvoiceItem ex:invoice ?Invoice), 
(?InvoiceItem ex:invoiceItem_Amount ?Amount), sumByGroup(?Invoice, ?Amount, 
?SumAmount)
->
(?Invoice ex:invoice_Amount ?SumAmount)
]

Any suggestions about how to solve this would be appreciated. It does not have 
to be done with rules (even though that is preferred), it could also be done in 
Java (Jena API) or using SPARQL / ARQ.

Short answer on rules is don't use them for this. Something like "sum of all invoice items present" is a non-monotonic operation and JenaRules are really not suited to this. It is *possible* to do by JenaRules but you have to keep track of whether all the items are in the sum yet, remove partial sums and effectively create a mini iterative loop using rules - this ends up being really clunky, slow and hard to maintain. It's perfectly possible to have rule systems which handle this sort of thing well but JenaRules isn't one of them.

Not sure I understand what the problem is with using SPARQL or the API.

Dave

Reply via email to