On Mon, Jul 8, 2013 at 2:52 PM, Dave Reynolds <[email protected]> wrote:
> On 08/07/13 16:14, Joshua TAYLOR wrote:
>>
>> Hi all,
>>
>> First off, my impression is that having a builtin do non-trivial query
>> of the graph (i.e., that depends on more inference), or modification
>> of the graph, is not supported.  That said, I'd like to do something
>> akin to it, and I'm looking for suggestions.
>
>
> Correct. Builtins are not supposed to modify the graph and there's no
> provision for invoking the inference engine as part of executing a builtin.
>
>
>> I have a simple expression evaluator (essentially a simple
>> lambda-calculus interpreter) whose expressions can be encoded in RDF.
>> In the simplest case, I have a builtin called Eval which takes two
>> arguments, an expression, which should be concrete, and a result which
>> may be either a variable or concrete node.  If the result is a
>> variable, then Eval binds the result of the evaluation to it, and
>> matches, and if the result is concrete, then Eval compares the
>> evaluation result with it, and succeeds if they are the same
>> (approximately with the primitive equal builtin).
>>
>> Now, the expression language that Eval can handle has some primitives
>> for querying RDF graphs.  The primitives are based on those presented
>> in a recent paper [1]. The idea here is to be able to write an
>> expression denoting a function of x, e.g., "the sum of the values of
>> the hasValue property for all the resources related to x by the
>> relatedTo property" and to store the result as a property of x.  E.g.,
>> with the data
>>
>> x relatedTo y, z .
>> y hasValue 3 .
>> z hasValue 4 .
>>
>> we would compute the value 7. This is generalized by a rule that says
>>
>> (?s ?p ?o) <-
>> (?s hasComputableProperty ?p)
>> (?s hasComputableExpression ?e)
>> Eval(?e,?o) .
>>
>> Now the problem of recursion comes up when the values of y and z are
>> not stated explicitly, but should also be computed by this same rule.
>> Eval doesn't have access to the InfModel directly, but through the
>> context can access the InfGraph, but simply querying it from within
>> Eval causes problems with recursive query.  (I assume that this is to
>> be expected.  If it is not, please let me know, and I can reply with
>> the particular errors that I'm encountering.)
>>
>> Has anyone done anything like this, or does anyone have any
>> suggestions for handling things like this?  So far, I've considered
>> adding some preconditions to the rule that would require that
>> computable properties of related resources must be computed first
>> (which would require more explicit connections in the data), or having
>> Eval return some sort of continuation or promise/delay type object, or
>> a new rule that could finish the computation when more information
>> becomes available.
>>
>> I think this is pushing the boundaries of the rule engine, but any and
>> all suggestions are welcome!
>
>
> Pushing the boundaries indeed!
>
> My inclination would be to use the precondition approach and forward rules.
> So any computation whose values are available will fire the appropriate rule
> which will assert new values. That in turn will unlock new rules. Thus you
> get bottom up data flow rather than top down recursion.
>
> Since your preconditions will amount to "all the values I need are
> available" that will be easiest to implement via another builtin.
>
> That combination will probably work (except where you have recursive
> dependencies but that will be a problem anyway!). However, it's not obvious
> to me what the rule engine is buying you in that case. You might want
> consider implementing a custom inference engine in code which can recurse
> directly.

Thanks for the reply!  The reasons for using builtins and the rule
engine have more to do with integration with work we've already done,
as well as piggybacking on the Jena OWL reasoners so that we can use
restriction classes to define which expressions (also OWL individuals)
should be associated with which individuals.  E.g.,

  SportsCar SubClassOf (hasPerformanceExpression formula1)
  FamilyCar SubClassOf (hasPerformanceExpression formula2)

You said, "Correct. Builtins are not supposed to modify the graph and
there's no provision for invoking the inference engine as part of
executing a builtin." To be clear though, it is OK if builtins access
the raw and deductions graph (without modifying them) to get data
/from/ the graph, right?  (I think this is OK, but I'd rather get
explicit confirmation now than surprise experimental confirmation
later. :) )  I assume that this is OK because the suggested builtin
that would implement "are all functions of dependencies computed yet?"
would have to be examining the graph.

A question about this approach though;  if a forward rule has such a
precondition, e.g.,

  (?s hasComputableProperty ?p)
  (?s hasComputableExpression ?e)
  AllPreconditionsComputed( ?s )
  Eval(?e,?o)
  ->
  (?s ?p ?o )

I see where the order that the rules would have fire in would be
bottom up, but will the rule keep getting considered for firing?
I.e., after the first time that it fails for a particular ?s, ?p, and
?e (since ?o won't be encountered until the Eval(?e,?o) is called,
will it still be available for firing later on, after some other
computable properties have been computed? And, since I won't be
working with larger data for a while where the performance difference
would be significant, assuming that it will still fire later even if
it failed the first time, will there be a performance hit for keeping
rules around that can't fire until the result of some builtin changes?
 I don't see how the engine could be "smart" about figuring out
"something changed, so it's time to consider this rule again" when the
earlier failure was a result of a *builtin* returning false (as
opposed to a triple pattern simply not matching).

Or, perhaps the condition for "all preconditions computed" is supposed
to be another triple pattern?  Something like

  (?s hasComputableProperty ?p)
  (?s hasComputableExpression ?e)
  (?s hasAllPreconditionsComputed 'true'^^xsd:boolean)
  Eval(?e,?o)
  ->
  (?s ?p ?o )

perhaps, though it seems like that might just push the problem elsewhere?

Again, thanks for your feedback!
Joshua
-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Reply via email to