Advanced Jena Rules
From Wiki
Using negation
RDF does not allows representation of negative facts. Generally speaking we can represent negative information, but under the form of two properties, one representing the positive extension and one representing the negative estension (i.e. likes and notLikes), we can simulate this situation. In JenaRules we can not represent also negative information, but we can simulate the weak-negation using a special built-in, namely noValue. It has two forms: one with three parameters (i.e. noValue(?x rdf:type ex:Student)), and one with two parameters (i.e. noValue(?x ex:likes)). It's purpose is to check the working memory for triples represented by the parameters of the built-in. For the two parameters form of the noValue built-in, the third parameter si considered to be a free universal variable, meaning that the third parameter can be anything. This built-in has no meaning into the head of the rule. In Example 9 we can see a rule using noValue built-in.
Example 9 : Using weak neagation in JenaRules
If a student is not diligent and is not a medium student then it is an mediocre student.
@prefix ex: http://example.com/school#
[mediocreStudent: (?s rdf:type ex:MediocreStudent)
<-
(?s rdf:type ex:Student)
noValue(?s rdf:type ex:MediumStudent)
noValue(?s rdf:type ex:DiligentStudent)]
This rule looks after all instances of type ex:Student which does not have also the type 'ex:MediumStudent nor ex:DiligentStudent.
See also: Web rules need two kinds of negation
Managing non-monotonic forward rules
JenaRules was designed to be used with monotonic rules. This can be uncomfortable if you not only need to add new data in your model, but, also you want to modify existent data. If you try for example to modify a new fact regarding a new value for a property, this will result in adding a new fact corresponding to that value, but also the old fact is still in memory. In Example 10 we consider some facts and a rule example which is intended to modify one of the facts.
Example 10 (Facts and rule)
<ex:Student rdf:about="student">
<ex:name>John Doe</ex:name>
<ex:passedExam rdf:resource="ex:SemanticWeb" />
<ex:totalCredits rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">12</ex:totalCredits>
</ex:Student>
If a student has passed the SemanticWeb exam, then he's total credits is increased by 6.
[totalCredits: (?s rdf:type ex:Student)
(?s ex:passedExam ex:SemanticWeb)
(?s ex:totalCredits ?c)
sum(?c,6,?newC)
->
(?s ex:totalCredits ?newC)]
The result for rule from Example 10 is not the one expected. The value of the ex:totalCredits property is not modified, but in place a new vale for this property is added, like in Example 11.
Example 11 (Result for the totalCredits rule)
<ex:Student rdf:about="student">
<ex:name>John Doe</ex:name>
<ex:passedExam rdf:resource="ex:SemanticWeb" />
<ex:totalCredits rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">12</ex:totalCredits>
<ex:totalCredits rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">18</ex:totalCredits>
</ex:Student>
In order to solve this problem, we have to remove first the old fact regarding the value of ex:totalCredits property, then we can add the new one. This is accomplished by using remove built-in, which take parameters the number (starting to count from 0) of the triple from conditions part which has to be removed. In our example, this triple is the third one, so we call: remove(2)(see Example 12).
Example 12 (Forward rule using remove built-in)
[totalCredits: (?s rdf:type ex:Student)
(?s ex:passedExam ex:SemanticWeb)
(?s ex:totalCredits ?c)
sum(?c,6,?newC)
->
remove(2)
(?s ex:totalCredits ?newC)]
Trying to execute the rule using the engine, we have an other problem, since the engine enter in an infinite cycle. This occurs because the actions from the rule head reactivate the rule, and since the conditions are accomplished, the rule execute again and again. In order to solve this, we propose the following solution: guard the remove built-in with a suplimentar condition, checked using noValue and the rule fire only in the case of that is accomplished, and in the rule's head, we add add a triple which make that condition false for the next execution of the rule (see Example 12).
Example 13 (Controlled forward rule)
[totalCredits: (?s rdf:type ex:Student)
(?s ex:passedExam ex:SemanticWeb)
(?s ex:totalCredits ?c)
sum(?c,6,?newC)
noValue(?s ex:ruleFiredFor ex:SemanticWeb)
->
remove(2)
(?s ex:totalCredits ?newC)
(?s ex:ruleFiredFor ex:SemanticWeb)]
This solution is tricky, but the result is now the expected one, like the Example 13 shows.
Example 14 (Results)
<ex:Student rdf:about="student">
<ex:name>John Doe</ex:name>
<ex:passedExam rdf:resource="ex:SemanticWeb" />
<ex:totalCredits rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">18</ex:totalCredits>
<ex:ruleFiredFor rdf:resource="ex:SemanticWeb" />
</ex:Student>
If you wish that the ex:rulesFiredFor property does not appears in the final result, the hide built-in can be used. This built-in hide the result, so it will be invisible outside the rules. In the Example 15, we can see the complete rule.
Example 15 (Using remove and hide built-ins)
[totalCredits: (?s rdf:type ex:Student)
(?s ex:passedExam ex:SemanticWeb)
(?s ex:totalCredits ?c)
sum(?c,6,?newC)
noValue(?s ex:ruleFiredFor ex:SemanticWeb)
->
remove(2)
(?s ex:totalCredits ?newC)
(?s ex:ruleFiredFor ex:SemanticWeb)
hide(ex:ruleFiredFor)]

