You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jena.apache.org by Dave Reynolds <da...@gmail.com> on 2018/09/04 10:40:58 UTC

Re: [GenericRuleReasoner] multi-headed backward chaining

Hi,

On 03/09/18 13:05, Nouwt, B. (Barry) wrote:
> Hi all,
> 
> We are using Apache Jena's GenericRuleReasoner in our project with backward chaining to selectively apply rules relevant to answer a particular SPARQL question. We learned that backward chaining in Jena's GenericRuleReasoner currently only supports single headed backward rules. However, we are facing quite some limitations due to this single-headedness and would like to know whether there have been or are attempts to overcome this limitation. 

No, there have been no such attempts to my knowledge. Single headed 
rules are the norm. The forward engine provides multi headed as a 
convenience because that's slightly more efficient in the forward case 
than having N single-headed rules but in the backward case there would 
be no such saving.

> Currently we split N-headed forward rules to N single-headed backward rules, but this limits the amount of bound variables (from the initial SPARQL query) available in a single rule's body. This is an important requirement in our use case.

This is the way I would do it. I don't understand what you mean by the 
limitation. If you are replicating the rules bodies then each body has 
all the variables.

> So, could someone with knowledge about the internals of the backward chaining process in the GenericRuleReasoner shed some light on whether it would (in principle) be possible to support multi-headed backward rules in Apache Jena's GenericRuleReasoner. We are even considering/investigating whether we can implement this feature ourselves.

If someone wanted to do this I would advise them to do it by a syntactic 
transformation of the sources rules in the way you are already doing, 
not by messing with the engine.

If you *really* wanted engine support then I guess one way to do this 
would be to allow goals which can bind more values than are available in 
a triple. So you could have things like (pseudo rule code only):

    head1(A)   <- intermediate(A,B,C...X,Y,Z)
    head2(X,Y) <- intermediate(A,B,C...X,Y,Z)
    head3(Z)   <- intermediate(A,B,C...X,Y,Z)

    intermediate(A,B,C...X,Y,Z) <- ... body clauses ...

Extending the backward rule engine to allow for general tuple goals and 
terms (but hide non-triple terms from the jena interface) is probably 
possible but a pretty substantial amount of work.

Syntactically it might be possible to use the "Functor" 
hack^h^h^h^hmachinery supported in the rule engines. But adding 
match/unification over functors would probably end up being as much work 
as generalizing the engine to non-triples.

Probably easier to find an alternative general purpose backward rule 
engine and wire it up to jena.

Dave


Re: [GenericRuleReasoner] multi-headed backward chaining

Posted by Dave Reynolds <da...@gmail.com>.
Hi Barry,

On 04/09/18 12:47, Nouwt, B. (Barry) wrote:
> Hi Dave,
> 
> Thanks for your answers and the pointer towards implementing such feature. I assume the syntactical solution you mention would not solve the limitation I describe below. I'm unsure how to circumvent this limitation without multi-headed backward rule support, but I'm of course open to suggestions.

See below ...

> Do you maybe have "alternative general purpose backward rule engine" in mind that either already supports multiple heads, or that might be easier to extend to support it? I've also been looking into other engines, like TopQuadrant's SHACL engine (https://github.com/TopQuadrant/shacl/issues/44) or Openllet (https://github.com/Galigator/openllet), but for now none of them beats the Jena's GenericRuleEngine 😊.

I was thinking of non-RDF rule engines which would then need 
(non-trivial) work to wire up to a triple representation.

If you want serious backward chaining then XSB is the one to look at. 
The jena backward engine is based loosely on a simplified version of the 
SLG-WAM approach that XSB uses.

The alternative is Drools, which has in general a good reputation, but I 
know nothing about it's backward rule support (indeed next to nothing 
about it at all).

> I'll try to explain one of the limitations we encounter in more detail. Imagine the following (untested and not that useful) scenario with a SPARQL query that retrieves a particular measured value based on a start and end date:
> 
> SELECT ?value
> WHERE {
> 	?measurement :hasValue ?value .
> 	?measurement :validFor ?interval .
> 	?interval rdf:type :DateInterval .
> 	?interval :startDate "2018-06-10"^^xsd:date .
> 	?interval :endDate "2018-07-07"^^xsd:date .
> 	?interval :valid "true"^^xsd:boolean .
> }
> 
> The data could look like this (note the missing ":interval1 :valid "true"^^xsd:boolean" triple):
> 
> 	:measure1 :hasValue "123" .
> 	:measure1 :validFor :interval1 .
> 	:interval1 rdf:type :DateInterval .
> 	:interval1 :startDate "2018-06-10"^^xsd:date .
> 	:interval1 :endDate "2018-07-07"^^xsd:date .
> 
> Now we would like to have a backward rule that checks whether the start lies before the end date of the intervals and adds the valid = "true" triple.
> 
> [IntRule:
> 	(?int rdf:type :DateInterval)
> 	(?int :startDate ?start)
> 	(?int :endDate ?end)
> <-
> 	lessThan(?start, ?end)
> 	(?int :valid "true"^^xsd:boolean)
> ]

Not sure I follow that. If you want to conclude that a measurement with 
correctly ordered dates is valid, and do so using a forward rule then 
you would use:

[IntRule:
     (?int rdf:type :DateInterval)
     (?int :startDate ?start)
     (?int :endDate ?end)
     lessThan(?start, ?end)
   ->
     (?int :valid "true"^^xsd:boolean)
]

That rule is valid both forward and backward. There is only one head 
(conclusion) from a set of three body terms and a condition. So you 
could set the engine to run in backward mode and run that same rule 
backwards with no problems.

If you want to use the explicit backward rule syntax, so you can use the 
generic reasoner in default hybrid mode, then the corresponding backward 
rule syntax is:

[IntRule:
     (?int :valid "true"^^xsd:boolean)
     <-
     (?int rdf:type :DateInterval)
     (?int :startDate ?start)
     (?int :endDate ?end)
     lessThan(?start, ?end)
]

That's valid and works for me on a trivial test case.

Maybe I'm misunderstanding what you are trying to do, or maybe there's 
some confusion caused by the backward rule syntax.

Dave

> So, to answer the above query, the head of the backward rule would match with the corresponding goal triples from the SPARQL query and bind the ?start and ?end variable in the rule to the dates mentioned in the SPARQL query. We have difficulties getting this to work with single-headed backward rules, since the splitted single-headed backward rules look like below and this means none of the rules can make the lessThan(?start, ?end) comparison since none of them has more than one triple in its head.
> 
> [IntRule1:
> 	(?int rdf:type :DateInterval)
> <-
> 	lessThan(?start, ?end)	#MISSES BOTH ?start AND ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> [IntRule2:
> 	(?int :startDate ?start)
> <-
> 	lessThan(?start, ?end)	#MISSES ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> [IntRule3:
> 	(?int :endDate ?end)
> <-
> 	lessThan(?start, ?end) 	#MISSES ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> Thanks in advance!
> 
> Regards, Barry
> 
> -----Original Message-----
> From: Dave Reynolds <da...@gmail.com>
> Sent: dinsdag 4 september 2018 12:41
> To: users@jena.apache.org
> Subject: Re: [GenericRuleReasoner] multi-headed backward chaining
> 
> Hi,
> 
> On 03/09/18 13:05, Nouwt, B. (Barry) wrote:
>> Hi all,
>>
>> We are using Apache Jena's GenericRuleReasoner in our project with backward chaining to selectively apply rules relevant to answer a particular SPARQL question. We learned that backward chaining in Jena's GenericRuleReasoner currently only supports single headed backward rules. However, we are facing quite some limitations due to this single-headedness and would like to know whether there have been or are attempts to overcome this limitation.
> 
> No, there have been no such attempts to my knowledge. Single headed rules are the norm. The forward engine provides multi headed as a convenience because that's slightly more efficient in the forward case than having N single-headed rules but in the backward case there would be no such saving.
> 
>> Currently we split N-headed forward rules to N single-headed backward rules, but this limits the amount of bound variables (from the initial SPARQL query) available in a single rule's body. This is an important requirement in our use case.
> 
> This is the way I would do it. I don't understand what you mean by the limitation. If you are replicating the rules bodies then each body has all the variables.
> 
>> So, could someone with knowledge about the internals of the backward chaining process in the GenericRuleReasoner shed some light on whether it would (in principle) be possible to support multi-headed backward rules in Apache Jena's GenericRuleReasoner. We are even considering/investigating whether we can implement this feature ourselves.
> 
> If someone wanted to do this I would advise them to do it by a syntactic transformation of the sources rules in the way you are already doing, not by messing with the engine.
> 
> If you *really* wanted engine support then I guess one way to do this would be to allow goals which can bind more values than are available in a triple. So you could have things like (pseudo rule code only):
> 
>      head1(A)   <- intermediate(A,B,C...X,Y,Z)
>      head2(X,Y) <- intermediate(A,B,C...X,Y,Z)
>      head3(Z)   <- intermediate(A,B,C...X,Y,Z)
> 
>      intermediate(A,B,C...X,Y,Z) <- ... body clauses ...
> 
> Extending the backward rule engine to allow for general tuple goals and terms (but hide non-triple terms from the jena interface) is probably possible but a pretty substantial amount of work.
> 
> Syntactically it might be possible to use the "Functor"
> hack^h^h^h^hmachinery supported in the rule engines. But adding match/unification over functors would probably end up being as much work as generalizing the engine to non-triples.
> 
> Probably easier to find an alternative general purpose backward rule engine and wire it up to jena.
> 
> Dave
> 
> This message may contain information that is not intended for you. If you are not the addressee or if this message was sent to you by mistake, you are requested to inform the sender and delete the message. TNO accepts no liability for the content of this e-mail, for the manner in which you use it and for damage of any kind resulting from the risks inherent to the electronic transmission of messages.
> 

RE: [GenericRuleReasoner] multi-headed backward chaining

Posted by "Nouwt, B. (Barry)" <ba...@tno.nl.INVALID>.
Hi Dave/others, I would like to bring new life to the discussion below, since I might have a better example to illustrate the limitation we experience with single-headed backward rules and the GenericRuleReasoner. Before I start, I want to make clear that I do realize that I am using the GenericRuleReasoner for a slightly different purpose than what it was designed to be used for. That being said, until now I have I have always been able to circumvent any limitations I encountered due the flexibility of the GenericRuleReasoner.

Imagine the following dummy data of three observations at different moments in time:

@prefix test: <https://www.tno.nl/test/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix time: <http://www.w3.org/2006/time#> .
@prefix sosa: <http://www.w3.org/ns/sosa/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

test:m1 rdf:type sosa:Observation .
test:m1 sosa:hasSimpleResult "1"^^xsd:integer .
test:m1 test:measureTime test:mt1 .
test:mt1 rdf:type time:Instant .
test:mt1 time:inXSDDateTime "2020-05-01T12:00:00Z"^^xsd:dateTime .

test:m2 rdf:type sosa:Observation .
test:m2 sosa:hasSimpleResult "2"^^xsd:integer .
test:m2 test:measureTime test:mt2 .
test:mt2 rdf:type time:Instant .
test:mt2 time:inXSDDateTime "2020-05-02T12:00:00Z"^^xsd:dateTime .

test:m3 rdf:type sosa:Observation .
test:m3 sosa:hasSimpleResult "3"^^xsd:integer .
test:m3 test:measureTime test:mt3 .
test:mt3 rdf:type time:Instant .
test:mt3 time:inXSDDateTime "2020-05-03T12:00:00Z"^^xsd:dateTime .

Now, I would like to be able to execute the following SPARQL query on this data whose ResultSet contains only the last two observations. Note how we do not want to use a FILTER keyword to limit the query, but we would like to use the W3C Time ontology (https://www.w3.org/TR/owl-time/) and the time:after property.

PREFIX test: <https://www.tno.nl/test/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX sosa: <http://www.w3.org/ns/sosa/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

SELECT ?timeValue ?result WHERE {
	
	?mea rdf:type sosa:Observation .
	?mea sosa:hasSimpleResult ?result .
	?mea test:measureTime ?time1 .

	?time1 rdf:type time:Instant .
	?time1 time:inXSDDateTime ?timeValue .

	?time2 rdf:type time:Instant .
	?time2 time:inXSDDateTime "2020-05-01T13:00:00Z"^^xsd:dateTime .

	# Cyndi Lauper reference: https://www.youtube.com/watch?v=Hb3Sx1Z-7rk
	?time1 time:after ?time2 .
}

What rules would we need to get the desired results given the above data and query? If multi headed backward rules would be possible, I would try something like this:

[imaginaryRule:
	(?time1 time:after ?time2)
	(?time1 rdf:type time:Instant)
	(?time1 time:inXSDDateTime ?timeValue1)
	(?time2 rdf:type time:Instant)
	(?time2 time:inXSDDateTime ?timeValue2)
<-
	bound(?timeValue1 ?timeValue2)
	isDType(?timeValue1, xsd:dateTime)
	isDType(?timeValue2, xsd:dateTime)
	greaterThan(?timeValue1, ?timeValue2)
	makeTemp(?time2)
]

Note that the ?timeValue2 within this rule's head would bind with the "2020-05-01T13:00:00Z"^^xsd:dateTime literal in the SPARQL query, while the other ?timeValue1 would bind the different dateTime literals in the data.

With the single headed backward rules limitation, this becomes a lot harder. One of the rules I use, for example, is the following:

[timeRule5.1:
	(?x  time:inXSDDateTime ?y)
<-
	bound(?y)
	isDType(?y, xsd:dateTime)
	makeTemp(?x)
]

One of the problems I experience with this rule, is that once this backward rule successfully produces a triple that matches with the '?time2 time:inXSDDateTime "2020-05-01T13:00:00Z"^^xsd:dateTime .' triple pattern in the SPARQL query above, the reasoner somehow forgets the existence of this triple when applying subsequent rules like:

[timeRule1:
	(?time1 time:after ?time2)
<-  
	(?time1 rdf:type time:Instant)
	(?time1 time:inXSDDateTime ?val1)
	(?time2 rdf:type time:Instant)
	(?time2 time:inXSDDateTime ?val2)
	notEqual(?time1 ?time2)
	greaterThan(?val1, ?val2)
]

I do get it to work in the end, by creating a builtin that adds the triple to the graph manually using a RuleContext.add() , but apart from it not really being an elegant solution, it also gives additional problems with deleting those manually added triples at a later stage.

Thanks in advance for anyone willing to help me out!

Regards, Barry

-----Original Message-----
From: Nouwt, B. (Barry) <ba...@tno.nl.INVALID> 
Sent: dinsdag 4 september 2018 15:29
To: users@jena.apache.org
Subject: RE: [GenericRuleReasoner] multi-headed backward chaining

Hi Dave, thanks for the pointers about XSB. You are right, my example is not strong enough, I will try to find a better one to illustrate the limitation (or I will find out that there is not a real limitation which would be even better 😉).

Regards, Barry

-----Original Message-----
From: Dave Reynolds <da...@gmail.com> 
Sent: dinsdag 4 september 2018 15:12
To: users@jena.apache.org
Subject: Re: [GenericRuleReasoner] multi-headed backward chaining

Hi Barry,

On 04/09/18 12:47, Nouwt, B. (Barry) wrote:
> Hi Dave,
> 
> Thanks for your answers and the pointer towards implementing such feature. I assume the syntactical solution you mention would not solve the limitation I describe below. I'm unsure how to circumvent this limitation without multi-headed backward rule support, but I'm of course open to suggestions.

See below ...

> Do you maybe have "alternative general purpose backward rule engine" in mind that either already supports multiple heads, or that might be easier to extend to support it? I've also been looking into other engines, like TopQuadrant's SHACL engine (https://github.com/TopQuadrant/shacl/issues/44) or Openllet (https://github.com/Galigator/openllet), but for now none of them beats the Jena's GenericRuleEngine 😊.

I was thinking of non-RDF rule engines which would then need
(non-trivial) work to wire up to a triple representation.

If you want serious backward chaining then XSB is the one to look at. 
The jena backward engine is based loosely on a simplified version of the SLG-WAM approach that XSB uses.

The alternative is Drools, which has in general a good reputation, but I know nothing about it's backward rule support (indeed next to nothing about it at all).

> I'll try to explain one of the limitations we encounter in more detail. Imagine the following (untested and not that useful) scenario with a SPARQL query that retrieves a particular measured value based on a start and end date:
> 
> SELECT ?value
> WHERE {
> 	?measurement :hasValue ?value .
> 	?measurement :validFor ?interval .
> 	?interval rdf:type :DateInterval .
> 	?interval :startDate "2018-06-10"^^xsd:date .
> 	?interval :endDate "2018-07-07"^^xsd:date .
> 	?interval :valid "true"^^xsd:boolean .
> }
> 
> The data could look like this (note the missing ":interval1 :valid "true"^^xsd:boolean" triple):
> 
> 	:measure1 :hasValue "123" .
> 	:measure1 :validFor :interval1 .
> 	:interval1 rdf:type :DateInterval .
> 	:interval1 :startDate "2018-06-10"^^xsd:date .
> 	:interval1 :endDate "2018-07-07"^^xsd:date .
> 
> Now we would like to have a backward rule that checks whether the start lies before the end date of the intervals and adds the valid = "true" triple.
> 
> [IntRule:
> 	(?int rdf:type :DateInterval)
> 	(?int :startDate ?start)
> 	(?int :endDate ?end)
> <-
> 	lessThan(?start, ?end)
> 	(?int :valid "true"^^xsd:boolean)
> ]

Not sure I follow that. If you want to conclude that a measurement with correctly ordered dates is valid, and do so using a forward rule then you would use:

[IntRule:
     (?int rdf:type :DateInterval)
     (?int :startDate ?start)
     (?int :endDate ?end)
     lessThan(?start, ?end)
   ->
     (?int :valid "true"^^xsd:boolean)
]

That rule is valid both forward and backward. There is only one head
(conclusion) from a set of three body terms and a condition. So you could set the engine to run in backward mode and run that same rule backwards with no problems.

If you want to use the explicit backward rule syntax, so you can use the generic reasoner in default hybrid mode, then the corresponding backward rule syntax is:

[IntRule:
     (?int :valid "true"^^xsd:boolean)
     <-
     (?int rdf:type :DateInterval)
     (?int :startDate ?start)
     (?int :endDate ?end)
     lessThan(?start, ?end)
]

That's valid and works for me on a trivial test case.

Maybe I'm misunderstanding what you are trying to do, or maybe there's some confusion caused by the backward rule syntax.

Dave

> So, to answer the above query, the head of the backward rule would match with the corresponding goal triples from the SPARQL query and bind the ?start and ?end variable in the rule to the dates mentioned in the SPARQL query. We have difficulties getting this to work with single-headed backward rules, since the splitted single-headed backward rules look like below and this means none of the rules can make the lessThan(?start, ?end) comparison since none of them has more than one triple in its head.
> 
> [IntRule1:
> 	(?int rdf:type :DateInterval)
> <-
> 	lessThan(?start, ?end)	#MISSES BOTH ?start AND ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> [IntRule2:
> 	(?int :startDate ?start)
> <-
> 	lessThan(?start, ?end)	#MISSES ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> [IntRule3:
> 	(?int :endDate ?end)
> <-
> 	lessThan(?start, ?end) 	#MISSES ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> Thanks in advance!
> 
> Regards, Barry
> 
> -----Original Message-----
> From: Dave Reynolds <da...@gmail.com>
> Sent: dinsdag 4 september 2018 12:41
> To: users@jena.apache.org
> Subject: Re: [GenericRuleReasoner] multi-headed backward chaining
> 
> Hi,
> 
> On 03/09/18 13:05, Nouwt, B. (Barry) wrote:
>> Hi all,
>>
>> We are using Apache Jena's GenericRuleReasoner in our project with backward chaining to selectively apply rules relevant to answer a particular SPARQL question. We learned that backward chaining in Jena's GenericRuleReasoner currently only supports single headed backward rules. However, we are facing quite some limitations due to this single-headedness and would like to know whether there have been or are attempts to overcome this limitation.
> 
> No, there have been no such attempts to my knowledge. Single headed rules are the norm. The forward engine provides multi headed as a convenience because that's slightly more efficient in the forward case than having N single-headed rules but in the backward case there would be no such saving.
> 
>> Currently we split N-headed forward rules to N single-headed backward rules, but this limits the amount of bound variables (from the initial SPARQL query) available in a single rule's body. This is an important requirement in our use case.
> 
> This is the way I would do it. I don't understand what you mean by the limitation. If you are replicating the rules bodies then each body has all the variables.
> 
>> So, could someone with knowledge about the internals of the backward chaining process in the GenericRuleReasoner shed some light on whether it would (in principle) be possible to support multi-headed backward rules in Apache Jena's GenericRuleReasoner. We are even considering/investigating whether we can implement this feature ourselves.
> 
> If someone wanted to do this I would advise them to do it by a syntactic transformation of the sources rules in the way you are already doing, not by messing with the engine.
> 
> If you *really* wanted engine support then I guess one way to do this would be to allow goals which can bind more values than are available in a triple. So you could have things like (pseudo rule code only):
> 
>      head1(A)   <- intermediate(A,B,C...X,Y,Z)
>      head2(X,Y) <- intermediate(A,B,C...X,Y,Z)
>      head3(Z)   <- intermediate(A,B,C...X,Y,Z)
> 
>      intermediate(A,B,C...X,Y,Z) <- ... body clauses ...
> 
> Extending the backward rule engine to allow for general tuple goals and terms (but hide non-triple terms from the jena interface) is probably possible but a pretty substantial amount of work.
> 
> Syntactically it might be possible to use the "Functor"
> hack^h^h^h^hmachinery supported in the rule engines. But adding match/unification over functors would probably end up being as much work as generalizing the engine to non-triples.
> 
> Probably easier to find an alternative general purpose backward rule engine and wire it up to jena.
> 
> Dave
> 
> This message may contain information that is not intended for you. If you are not the addressee or if this message was sent to you by mistake, you are requested to inform the sender and delete the message. TNO accepts no liability for the content of this e-mail, for the manner in which you use it and for damage of any kind resulting from the risks inherent to the electronic transmission of messages.
> 

RE: [GenericRuleReasoner] multi-headed backward chaining

Posted by "Nouwt, B. (Barry)" <ba...@tno.nl.INVALID>.
Hi Dave, thanks for the pointers about XSB. You are right, my example is not strong enough, I will try to find a better one to illustrate the limitation (or I will find out that there is not a real limitation which would be even better 😉).

Regards, Barry

-----Original Message-----
From: Dave Reynolds <da...@gmail.com> 
Sent: dinsdag 4 september 2018 15:12
To: users@jena.apache.org
Subject: Re: [GenericRuleReasoner] multi-headed backward chaining

Hi Barry,

On 04/09/18 12:47, Nouwt, B. (Barry) wrote:
> Hi Dave,
> 
> Thanks for your answers and the pointer towards implementing such feature. I assume the syntactical solution you mention would not solve the limitation I describe below. I'm unsure how to circumvent this limitation without multi-headed backward rule support, but I'm of course open to suggestions.

See below ...

> Do you maybe have "alternative general purpose backward rule engine" in mind that either already supports multiple heads, or that might be easier to extend to support it? I've also been looking into other engines, like TopQuadrant's SHACL engine (https://github.com/TopQuadrant/shacl/issues/44) or Openllet (https://github.com/Galigator/openllet), but for now none of them beats the Jena's GenericRuleEngine 😊.

I was thinking of non-RDF rule engines which would then need
(non-trivial) work to wire up to a triple representation.

If you want serious backward chaining then XSB is the one to look at. 
The jena backward engine is based loosely on a simplified version of the SLG-WAM approach that XSB uses.

The alternative is Drools, which has in general a good reputation, but I know nothing about it's backward rule support (indeed next to nothing about it at all).

> I'll try to explain one of the limitations we encounter in more detail. Imagine the following (untested and not that useful) scenario with a SPARQL query that retrieves a particular measured value based on a start and end date:
> 
> SELECT ?value
> WHERE {
> 	?measurement :hasValue ?value .
> 	?measurement :validFor ?interval .
> 	?interval rdf:type :DateInterval .
> 	?interval :startDate "2018-06-10"^^xsd:date .
> 	?interval :endDate "2018-07-07"^^xsd:date .
> 	?interval :valid "true"^^xsd:boolean .
> }
> 
> The data could look like this (note the missing ":interval1 :valid "true"^^xsd:boolean" triple):
> 
> 	:measure1 :hasValue "123" .
> 	:measure1 :validFor :interval1 .
> 	:interval1 rdf:type :DateInterval .
> 	:interval1 :startDate "2018-06-10"^^xsd:date .
> 	:interval1 :endDate "2018-07-07"^^xsd:date .
> 
> Now we would like to have a backward rule that checks whether the start lies before the end date of the intervals and adds the valid = "true" triple.
> 
> [IntRule:
> 	(?int rdf:type :DateInterval)
> 	(?int :startDate ?start)
> 	(?int :endDate ?end)
> <-
> 	lessThan(?start, ?end)
> 	(?int :valid "true"^^xsd:boolean)
> ]

Not sure I follow that. If you want to conclude that a measurement with correctly ordered dates is valid, and do so using a forward rule then you would use:

[IntRule:
     (?int rdf:type :DateInterval)
     (?int :startDate ?start)
     (?int :endDate ?end)
     lessThan(?start, ?end)
   ->
     (?int :valid "true"^^xsd:boolean)
]

That rule is valid both forward and backward. There is only one head
(conclusion) from a set of three body terms and a condition. So you could set the engine to run in backward mode and run that same rule backwards with no problems.

If you want to use the explicit backward rule syntax, so you can use the generic reasoner in default hybrid mode, then the corresponding backward rule syntax is:

[IntRule:
     (?int :valid "true"^^xsd:boolean)
     <-
     (?int rdf:type :DateInterval)
     (?int :startDate ?start)
     (?int :endDate ?end)
     lessThan(?start, ?end)
]

That's valid and works for me on a trivial test case.

Maybe I'm misunderstanding what you are trying to do, or maybe there's some confusion caused by the backward rule syntax.

Dave

> So, to answer the above query, the head of the backward rule would match with the corresponding goal triples from the SPARQL query and bind the ?start and ?end variable in the rule to the dates mentioned in the SPARQL query. We have difficulties getting this to work with single-headed backward rules, since the splitted single-headed backward rules look like below and this means none of the rules can make the lessThan(?start, ?end) comparison since none of them has more than one triple in its head.
> 
> [IntRule1:
> 	(?int rdf:type :DateInterval)
> <-
> 	lessThan(?start, ?end)	#MISSES BOTH ?start AND ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> [IntRule2:
> 	(?int :startDate ?start)
> <-
> 	lessThan(?start, ?end)	#MISSES ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> [IntRule3:
> 	(?int :endDate ?end)
> <-
> 	lessThan(?start, ?end) 	#MISSES ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> Thanks in advance!
> 
> Regards, Barry
> 
> -----Original Message-----
> From: Dave Reynolds <da...@gmail.com>
> Sent: dinsdag 4 september 2018 12:41
> To: users@jena.apache.org
> Subject: Re: [GenericRuleReasoner] multi-headed backward chaining
> 
> Hi,
> 
> On 03/09/18 13:05, Nouwt, B. (Barry) wrote:
>> Hi all,
>>
>> We are using Apache Jena's GenericRuleReasoner in our project with backward chaining to selectively apply rules relevant to answer a particular SPARQL question. We learned that backward chaining in Jena's GenericRuleReasoner currently only supports single headed backward rules. However, we are facing quite some limitations due to this single-headedness and would like to know whether there have been or are attempts to overcome this limitation.
> 
> No, there have been no such attempts to my knowledge. Single headed rules are the norm. The forward engine provides multi headed as a convenience because that's slightly more efficient in the forward case than having N single-headed rules but in the backward case there would be no such saving.
> 
>> Currently we split N-headed forward rules to N single-headed backward rules, but this limits the amount of bound variables (from the initial SPARQL query) available in a single rule's body. This is an important requirement in our use case.
> 
> This is the way I would do it. I don't understand what you mean by the limitation. If you are replicating the rules bodies then each body has all the variables.
> 
>> So, could someone with knowledge about the internals of the backward chaining process in the GenericRuleReasoner shed some light on whether it would (in principle) be possible to support multi-headed backward rules in Apache Jena's GenericRuleReasoner. We are even considering/investigating whether we can implement this feature ourselves.
> 
> If someone wanted to do this I would advise them to do it by a syntactic transformation of the sources rules in the way you are already doing, not by messing with the engine.
> 
> If you *really* wanted engine support then I guess one way to do this would be to allow goals which can bind more values than are available in a triple. So you could have things like (pseudo rule code only):
> 
>      head1(A)   <- intermediate(A,B,C...X,Y,Z)
>      head2(X,Y) <- intermediate(A,B,C...X,Y,Z)
>      head3(Z)   <- intermediate(A,B,C...X,Y,Z)
> 
>      intermediate(A,B,C...X,Y,Z) <- ... body clauses ...
> 
> Extending the backward rule engine to allow for general tuple goals and terms (but hide non-triple terms from the jena interface) is probably possible but a pretty substantial amount of work.
> 
> Syntactically it might be possible to use the "Functor"
> hack^h^h^h^hmachinery supported in the rule engines. But adding match/unification over functors would probably end up being as much work as generalizing the engine to non-triples.
> 
> Probably easier to find an alternative general purpose backward rule engine and wire it up to jena.
> 
> Dave
> 
> This message may contain information that is not intended for you. If you are not the addressee or if this message was sent to you by mistake, you are requested to inform the sender and delete the message. TNO accepts no liability for the content of this e-mail, for the manner in which you use it and for damage of any kind resulting from the risks inherent to the electronic transmission of messages.
> 

Re: [GenericRuleReasoner] multi-headed backward chaining

Posted by Dave Reynolds <da...@gmail.com>.
Hi Barry,

On 04/09/18 12:47, Nouwt, B. (Barry) wrote:
> Hi Dave,
> 
> Thanks for your answers and the pointer towards implementing such feature. I assume the syntactical solution you mention would not solve the limitation I describe below. I'm unsure how to circumvent this limitation without multi-headed backward rule support, but I'm of course open to suggestions.

See below ...

> Do you maybe have "alternative general purpose backward rule engine" in mind that either already supports multiple heads, or that might be easier to extend to support it? I've also been looking into other engines, like TopQuadrant's SHACL engine (https://github.com/TopQuadrant/shacl/issues/44) or Openllet (https://github.com/Galigator/openllet), but for now none of them beats the Jena's GenericRuleEngine 😊.

I was thinking of non-RDF rule engines which would then need 
(non-trivial) work to wire up to a triple representation.

If you want serious backward chaining then XSB is the one to look at. 
The jena backward engine is based loosely on a simplified version of the 
SLG-WAM approach that XSB uses.

The alternative is Drools, which has in general a good reputation, but I 
know nothing about it's backward rule support (indeed next to nothing 
about it at all).

> I'll try to explain one of the limitations we encounter in more detail. Imagine the following (untested and not that useful) scenario with a SPARQL query that retrieves a particular measured value based on a start and end date:
> 
> SELECT ?value
> WHERE {
> 	?measurement :hasValue ?value .
> 	?measurement :validFor ?interval .
> 	?interval rdf:type :DateInterval .
> 	?interval :startDate "2018-06-10"^^xsd:date .
> 	?interval :endDate "2018-07-07"^^xsd:date .
> 	?interval :valid "true"^^xsd:boolean .
> }
> 
> The data could look like this (note the missing ":interval1 :valid "true"^^xsd:boolean" triple):
> 
> 	:measure1 :hasValue "123" .
> 	:measure1 :validFor :interval1 .
> 	:interval1 rdf:type :DateInterval .
> 	:interval1 :startDate "2018-06-10"^^xsd:date .
> 	:interval1 :endDate "2018-07-07"^^xsd:date .
> 
> Now we would like to have a backward rule that checks whether the start lies before the end date of the intervals and adds the valid = "true" triple.
> 
> [IntRule:
> 	(?int rdf:type :DateInterval)
> 	(?int :startDate ?start)
> 	(?int :endDate ?end)
> <-
> 	lessThan(?start, ?end)
> 	(?int :valid "true"^^xsd:boolean)
> ]

Not sure I follow that. If you want to conclude that a measurement with 
correctly ordered dates is valid, and do so using a forward rule then 
you would use:

[IntRule:
     (?int rdf:type :DateInterval)
     (?int :startDate ?start)
     (?int :endDate ?end)
     lessThan(?start, ?end)
   ->
     (?int :valid "true"^^xsd:boolean)
]

That rule is valid both forward and backward. There is only one head 
(conclusion) from a set of three body terms and a condition. So you 
could set the engine to run in backward mode and run that same rule 
backwards with no problems.

If you want to use the explicit backward rule syntax, so you can use the 
generic reasoner in default hybrid mode, then the corresponding backward 
rule syntax is:

[IntRule:
     (?int :valid "true"^^xsd:boolean)
     <-
     (?int rdf:type :DateInterval)
     (?int :startDate ?start)
     (?int :endDate ?end)
     lessThan(?start, ?end)
]

That's valid and works for me on a trivial test case.

Maybe I'm misunderstanding what you are trying to do, or maybe there's 
some confusion caused by the backward rule syntax.

Dave

> So, to answer the above query, the head of the backward rule would match with the corresponding goal triples from the SPARQL query and bind the ?start and ?end variable in the rule to the dates mentioned in the SPARQL query. We have difficulties getting this to work with single-headed backward rules, since the splitted single-headed backward rules look like below and this means none of the rules can make the lessThan(?start, ?end) comparison since none of them has more than one triple in its head.
> 
> [IntRule1:
> 	(?int rdf:type :DateInterval)
> <-
> 	lessThan(?start, ?end)	#MISSES BOTH ?start AND ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> [IntRule2:
> 	(?int :startDate ?start)
> <-
> 	lessThan(?start, ?end)	#MISSES ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> [IntRule3:
> 	(?int :endDate ?end)
> <-
> 	lessThan(?start, ?end) 	#MISSES ?end
> 	(?int :valid "true"^^xsd:boolean)
> ]
> 
> Thanks in advance!
> 
> Regards, Barry
> 
> -----Original Message-----
> From: Dave Reynolds <da...@gmail.com>
> Sent: dinsdag 4 september 2018 12:41
> To: users@jena.apache.org
> Subject: Re: [GenericRuleReasoner] multi-headed backward chaining
> 
> Hi,
> 
> On 03/09/18 13:05, Nouwt, B. (Barry) wrote:
>> Hi all,
>>
>> We are using Apache Jena's GenericRuleReasoner in our project with backward chaining to selectively apply rules relevant to answer a particular SPARQL question. We learned that backward chaining in Jena's GenericRuleReasoner currently only supports single headed backward rules. However, we are facing quite some limitations due to this single-headedness and would like to know whether there have been or are attempts to overcome this limitation.
> 
> No, there have been no such attempts to my knowledge. Single headed rules are the norm. The forward engine provides multi headed as a convenience because that's slightly more efficient in the forward case than having N single-headed rules but in the backward case there would be no such saving.
> 
>> Currently we split N-headed forward rules to N single-headed backward rules, but this limits the amount of bound variables (from the initial SPARQL query) available in a single rule's body. This is an important requirement in our use case.
> 
> This is the way I would do it. I don't understand what you mean by the limitation. If you are replicating the rules bodies then each body has all the variables.
> 
>> So, could someone with knowledge about the internals of the backward chaining process in the GenericRuleReasoner shed some light on whether it would (in principle) be possible to support multi-headed backward rules in Apache Jena's GenericRuleReasoner. We are even considering/investigating whether we can implement this feature ourselves.
> 
> If someone wanted to do this I would advise them to do it by a syntactic transformation of the sources rules in the way you are already doing, not by messing with the engine.
> 
> If you *really* wanted engine support then I guess one way to do this would be to allow goals which can bind more values than are available in a triple. So you could have things like (pseudo rule code only):
> 
>      head1(A)   <- intermediate(A,B,C...X,Y,Z)
>      head2(X,Y) <- intermediate(A,B,C...X,Y,Z)
>      head3(Z)   <- intermediate(A,B,C...X,Y,Z)
> 
>      intermediate(A,B,C...X,Y,Z) <- ... body clauses ...
> 
> Extending the backward rule engine to allow for general tuple goals and terms (but hide non-triple terms from the jena interface) is probably possible but a pretty substantial amount of work.
> 
> Syntactically it might be possible to use the "Functor"
> hack^h^h^h^hmachinery supported in the rule engines. But adding match/unification over functors would probably end up being as much work as generalizing the engine to non-triples.
> 
> Probably easier to find an alternative general purpose backward rule engine and wire it up to jena.
> 
> Dave
> 
> This message may contain information that is not intended for you. If you are not the addressee or if this message was sent to you by mistake, you are requested to inform the sender and delete the message. TNO accepts no liability for the content of this e-mail, for the manner in which you use it and for damage of any kind resulting from the risks inherent to the electronic transmission of messages.
> 

RE: [GenericRuleReasoner] multi-headed backward chaining

Posted by "Nouwt, B. (Barry)" <ba...@tno.nl.INVALID>.
Hi Dave, 

Thanks for your answers and the pointer towards implementing such feature. I assume the syntactical solution you mention would not solve the limitation I describe below. I'm unsure how to circumvent this limitation without multi-headed backward rule support, but I'm of course open to suggestions.

Do you maybe have "alternative general purpose backward rule engine" in mind that either already supports multiple heads, or that might be easier to extend to support it? I've also been looking into other engines, like TopQuadrant's SHACL engine (https://github.com/TopQuadrant/shacl/issues/44) or Openllet (https://github.com/Galigator/openllet), but for now none of them beats the Jena's GenericRuleEngine 😊.

I'll try to explain one of the limitations we encounter in more detail. Imagine the following (untested and not that useful) scenario with a SPARQL query that retrieves a particular measured value based on a start and end date:

SELECT ?value
WHERE {
	?measurement :hasValue ?value .
	?measurement :validFor ?interval .
	?interval rdf:type :DateInterval .
	?interval :startDate "2018-06-10"^^xsd:date .
	?interval :endDate "2018-07-07"^^xsd:date .
	?interval :valid "true"^^xsd:boolean .
}

The data could look like this (note the missing ":interval1 :valid "true"^^xsd:boolean" triple):

	:measure1 :hasValue "123" .
	:measure1 :validFor :interval1 .
	:interval1 rdf:type :DateInterval .
	:interval1 :startDate "2018-06-10"^^xsd:date .
	:interval1 :endDate "2018-07-07"^^xsd:date .

Now we would like to have a backward rule that checks whether the start lies before the end date of the intervals and adds the valid = "true" triple.

[IntRule:
	(?int rdf:type :DateInterval) 
	(?int :startDate ?start) 
	(?int :endDate ?end) 
<- 
	lessThan(?start, ?end) 
	(?int :valid "true"^^xsd:boolean)
]
So, to answer the above query, the head of the backward rule would match with the corresponding goal triples from the SPARQL query and bind the ?start and ?end variable in the rule to the dates mentioned in the SPARQL query. We have difficulties getting this to work with single-headed backward rules, since the splitted single-headed backward rules look like below and this means none of the rules can make the lessThan(?start, ?end) comparison since none of them has more than one triple in its head.

[IntRule1:
	(?int rdf:type :DateInterval) 
<- 
	lessThan(?start, ?end)	#MISSES BOTH ?start AND ?end
	(?int :valid "true"^^xsd:boolean)
]

[IntRule2:
	(?int :startDate ?start) 
<- 
	lessThan(?start, ?end)	#MISSES ?end
	(?int :valid "true"^^xsd:boolean)
]

[IntRule3:
	(?int :endDate ?end) 
<- 
	lessThan(?start, ?end) 	#MISSES ?end
	(?int :valid "true"^^xsd:boolean)
]

Thanks in advance!

Regards, Barry

-----Original Message-----
From: Dave Reynolds <da...@gmail.com> 
Sent: dinsdag 4 september 2018 12:41
To: users@jena.apache.org
Subject: Re: [GenericRuleReasoner] multi-headed backward chaining

Hi,

On 03/09/18 13:05, Nouwt, B. (Barry) wrote:
> Hi all,
> 
> We are using Apache Jena's GenericRuleReasoner in our project with backward chaining to selectively apply rules relevant to answer a particular SPARQL question. We learned that backward chaining in Jena's GenericRuleReasoner currently only supports single headed backward rules. However, we are facing quite some limitations due to this single-headedness and would like to know whether there have been or are attempts to overcome this limitation. 

No, there have been no such attempts to my knowledge. Single headed rules are the norm. The forward engine provides multi headed as a convenience because that's slightly more efficient in the forward case than having N single-headed rules but in the backward case there would be no such saving.

> Currently we split N-headed forward rules to N single-headed backward rules, but this limits the amount of bound variables (from the initial SPARQL query) available in a single rule's body. This is an important requirement in our use case.

This is the way I would do it. I don't understand what you mean by the limitation. If you are replicating the rules bodies then each body has all the variables.

> So, could someone with knowledge about the internals of the backward chaining process in the GenericRuleReasoner shed some light on whether it would (in principle) be possible to support multi-headed backward rules in Apache Jena's GenericRuleReasoner. We are even considering/investigating whether we can implement this feature ourselves.

If someone wanted to do this I would advise them to do it by a syntactic transformation of the sources rules in the way you are already doing, not by messing with the engine.

If you *really* wanted engine support then I guess one way to do this would be to allow goals which can bind more values than are available in a triple. So you could have things like (pseudo rule code only):

    head1(A)   <- intermediate(A,B,C...X,Y,Z)
    head2(X,Y) <- intermediate(A,B,C...X,Y,Z)
    head3(Z)   <- intermediate(A,B,C...X,Y,Z)

    intermediate(A,B,C...X,Y,Z) <- ... body clauses ...

Extending the backward rule engine to allow for general tuple goals and terms (but hide non-triple terms from the jena interface) is probably possible but a pretty substantial amount of work.

Syntactically it might be possible to use the "Functor" 
hack^h^h^h^hmachinery supported in the rule engines. But adding match/unification over functors would probably end up being as much work as generalizing the engine to non-triples.

Probably easier to find an alternative general purpose backward rule engine and wire it up to jena.

Dave

This message may contain information that is not intended for you. If you are not the addressee or if this message was sent to you by mistake, you are requested to inform the sender and delete the message. TNO accepts no liability for the content of this e-mail, for the manner in which you use it and for damage of any kind resulting from the risks inherent to the electronic transmission of messages.