Hi Justin,

I'm not the developer of the rule engine, might I will try do answer your question with my limited knowledge:

Using Generic rule reasoner (in FORWARD mode), say I have a rule with this
in the head:
(?reportA ex:supercededBy ?reportB)

Then another rule with this in the body:
noValue(?reportA ex:supercededBy ?reportB)

Shouldn't there be an implicit rule fire ordering since we can see that the
second rule depends on the first rule firing until completion.

As far as I know, there is nothing for

- guaranteed rule ordering
- stratification
- dependency analysis
- truth maintenance

Under the hood, the forward GenericRuleReasoner is implemented using a RETE network. What RETE does not imply rule ordering, stratification, or safe negation. It just makes matching fast.

Your specific example

Rule A (producer):

... -> (?reportA ex:supercededBy ?reportB)


Rule B (consumer):

noValue(?reportA ex:supercededBy ?reportB) ... -> ...


Your expectation is basically:

“Rule B should wait until Rule A has fully fired.”

That expectation assumes stratified negation (like in Datalog or SQL), but Jena does not do that.


So, why do I think that Jena can’t safely do implicit ordering?

Because the builtIn noValue is non-monotonic.

At the moment Rule B fires:

- The triple might not exist yet
- But it might be inferred later
- Jena has no way to know that in advance

So from the engine’s perspective:

"Absence of a triple right now is not stable information."

That’s why:

- noValue is evaluated against the current graph snapshot
- Results may become logically invalid later
- Jena will not retract them

This is probably one reason why the documentation quietly treats noValue as dangerous but useful.

And a related question...

Say I have triples like:
:thingA :hasValue 8 .
:thingA :hasValue 4 .
:thingA :hasValue 9 .
...

Using FORWARD mode, is it possible to write a set of rules that do the
equivalent of:
```
CONSTRUCT
   {
     ?thing :hasMaxValue ?max_value .
   }
WHERE
   { SELECT  ?thing (MAX(?value) AS ?max_value)
     WHERE
       { ?thing  :hasValue  ?value }
     GROUP BY ?thing
   }
```

No, I don't think this is possible. The Generic Rule Reasoner cannot express aggregation semantics like MAX in a sound way.

Why aggregation doesn’t work in Jena forward rules, is basically because those:

- Fire on local pattern matches
- Have no global view
- Cannot “see all values” for a thing at once
- Cannot retract previously inferred triples


For example when we have

:thingA :hasValue 8 .
:thingA :hasValue 4 .
:thingA :hasValue 9 .

A forward rule might see:

- 8 first -> infer hasMaxValue 8
- then 9 later -> infer hasMaxValue 9

but cannot remove the 8

So we would end up with

:thingA :hasMaxValue 8 .
:thingA :hasMaxValue 9 .


I know that other rule languages might have extensions for aggregates, but we could maybe better think of Jena FORWARD rules as:

“RDFS with custom Horn clauses — not SQL, not Datalog with negation, not a rule engine with agenda control.”



Hope this answers your questions to some extent, although that wouldn't solve your problem. A combination of rules + SPARQL CONSTRUCT (INSERTs) might solve your use-case


Cheers,

Lorenz

--
Lorenz Bühmann
Research Associate/Scientific Developer

[email protected]

Institute for Applied Informatics e.V. (InfAI) | Goerdelerring 9 | 04109 
Leipzig | Germany

Reply via email to