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 <[email protected]> Sent: dinsdag 4 september 2018 12:41 To: [email protected] 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.
