I'm experiencing some confusion about how tabling and the side effects
(or required computation) of builtins interact.  In particular, here's
a set of rules that implicitly describes a list structure (a -> b ->
c) where a value for each element can be computed only after the value
for its successor (if any) has been computed).  I've represented this
with three backwards chaining rules.  The computed value is simply a
string concatenation of 'value ' and the node's URI.


[rule_a: (a value ?value) <- (b value ?value0) (a compute ?value)]
[rule_b: (b value ?value) <- (c value ?value0) (b compute ?value)]
[rule_c: (c value ?value) <- (c compute ?value)]
[tableAndHide: -> tableAll() hide(compute)]
[compute: (?s compute ?o) <- bound(?s) print( ## computing value for
?s ) strConcat('value ', ?s, ?o)]


When I write the inference model built on a reasoner with these rules,
the print builtin is called more times than I would have expected.
The output is


## computing value for c
## computing value for b
## computing value for a
## computing value for a
<a>   <value> "value a" .

## computing value for b
<b>   <value> "value b" .

## computing value for c
<c>   <value> "value c" .


In the very beginning, it's good that the print values are called in
the order c, b, a, but I'm confused as to why when each node in the
graph is printed, the corresponding print statement from the compute
rule is executed again.  I had expected the tabling to memoize the
value.  What am I missing here?  A complete working example (whose
output is the above) is included here.

Thanks in advance!
Joshua Taylor


import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.vocabulary.ReasonerVocabulary;

public class RepeatedBuiltinExample {

        private final static String rules = "\n" +
                        // Given a list structure, a -> b -> c, for each 
element, the
element to its right
                        // must have a value before its own value can be 
computed.
                        "[rule_a: (a value ?value) <- (b value ?value0) (a 
compute ?value)]\n" +
                        "[rule_b: (b value ?value) <- (c value ?value0) (b 
compute ?value)]\n" +
                        "[rule_c: (c value ?value) <- (c compute ?value)]\n" +
                        // Table everything, and don't show compute in the model
                        "[tableAndHide: -> tableAll() hide(compute)]\n" +
                        // The value of the compute property for a node is 
'value [node]'.
                        "[compute: (?s compute ?o) <- bound(?s) print( ## 
computing value
for ?s ) strConcat('value ', ?s, ?o)]";

        public static void main( final String[] args ) {
                final GenericRuleReasoner reasoner = new GenericRuleReasoner(
Rule.parseRules( rules ));
                reasoner.setMode( GenericRuleReasoner.HYBRID );
                reasoner.setParameter(ReasonerVocabulary.PROPtraceOn, false);
                final InfModel infModel = ModelFactory.createInfModel( reasoner,
ModelFactory.createDefaultModel() );
                infModel.write( System.out, "N3" );
        }
}

-- 
Joshua Taylor, http://www.cs.rpi.edu/~tayloj/

Reply via email to