Question

This is the code I have written but the new built-in does not seem to work. I get the error:

Exception in thread "main" com.hp.hpl.jena.reasoner.rulesys.impl.LPRuleSyntaxException: Syntax error in backward rule: matematica Unknown builtin operation mysum

Can anyone tell me where the error is? Here is my code:

package JenaRules;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;

import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyStorageException;

import com.hp.hpl.jena.graph.Node;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.reasoner.Reasoner;
import com.hp.hpl.jena.reasoner.rulesys.*;
import com.hp.hpl.jena.reasoner.rulesys.builtins.BaseBuiltin;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.vocabulary.RDFS;
import com.hp.hpl.jena.vocabulary.ReasonerVocabulary;

public class RulesOntology_MT {

    public static void main(String[] args) throws OWLOntologyStorageException,
    OWLOntologyCreationException, IOException  {

        BuiltinRegistry.theRegistry.register(new BaseBuiltin() {
             @Override
             public String getName() {
                    return "mysum";
                }
             @Override
                public int getArgLength() {
                    return 2;
                }
             @Override
                public boolean bodyCall(Node[] args, int length, RuleContext context) {
                    checkArgs(length, context);
                    BindingEnvironment env = context.getEnv();
                    Node n1 = getArg(0, args, context);
                    Node n2 = getArg(1, args, context);
                    if (n1.isLiteral() && n2.isLiteral()) {
                        Object v1 = n1.getLiteralValue();
                        Object v2 = n2.getLiteralValue();
                        Node sum = null;
                        if (v1 instanceof Number && v2 instanceof Number) {
                            Number nv1 = (Number)v1;
                            Number nv2 = (Number)v2;
                            int sumInt = nv1.intValue()+nv2.intValue();
                            sum = Util.makeIntNode(sumInt);
                            return env.bind(args[2], sum);
                        }
                    }
                    return false;
                }

        });

        // NON SERVE

        //      final String exampleRuleString2 =
        //              "[mat1: equal(?s ?p )\n\t-> print(?s ?p ?o),\n\t   (?s ?p ?o)\n]"+
        //                      "";

        final String exampleRuleString =    
                "[matematica:"+
                        "(?p http://www.semanticweb.org/prova_rules_M#totale_crediti ?x)"+
                        " -> " +
                        "(?p rdf:type  http://www.semanticweb.org/prova_rules_M#:Persona)"+
                        "(?e rdf:type  http://www.semanticweb.org/prova_rules_M#:Esame)"+
                        "(?p  http://www.semanticweb.org/prova_rules_M#:haSostenutoEsameDi ?e)"+
                        "(?e http://www.semanticweb.org/prova_rules_M/persona#crediti_esame ?cr)"+
                        "mysum(?cr,2)"+
                        "]";

        System.out.println(exampleRuleString);

        /* I tend to use a fairly verbose syntax for parsing out my rules when I construct them
         * from a string. You can read them from whatever other sources.
         */
        final List<Rule> rules;
        try( final BufferedReader src = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(exampleRuleString.getBytes()))) ) {
            rules = Rule.parseRules(Rule.rulesParserFromReader(src));
        }


        /* Construct a reasoner and associate the rules with it  */
        // create an empty non-inferencing model

        GenericRuleReasoner reasoner = (GenericRuleReasoner) GenericRuleReasonerFactory.theInstance().create(null);
        reasoner.setRules(rules);


        /* Create & Prepare the InfModel. If you don't call prepare, then
         * rule firings and inference may be deferred until you query the
         * model rather than happening at insertion. This can make you think
         * that your Builtin is not working, when it is.
         */

        InfModel infModel = ModelFactory.createInfModel(reasoner, ModelFactory.createDefaultModel());
        infModel.prepare();
        infModel.createResource(RDFS.Class);

        //write down the result in RDFXML form
        infModel.write(System.out);

    }
}
Was it helpful?

Solution

Using the code that you provided, and Apache Jena 2.11.1, I cannot replicate the exception you are getting. Do note that when you call BuiltinRegistry.theRegistry.register(...), you are telling the reasoner that the builtin exists.

Solution

The exception that you are getting is likely because, in your actual code, you are not calling BuiltinRegistry.theRegistry.register(...) prior to calling Rule.parseRules(Rule.rulesParserFromReader(src));, so as far as the rule parser is concerned, you are using a Builtin which doesn't exist. To fix it, merely call register before parsing your rules. The toy example provided does not have this problem.

Using the example provided

I also noted that the provided code example did not include anything that would actually stimulate the rule to fire, so, in lieu of infModel.createResource(RDFS.Class);, I added the following lines:

final Resource s = infModel.createResource();
final Property p = infModel.createProperty("http://www.semanticweb.org/prova_rules_M#totale_crediti");
final Resource o = infModel.createResource();
infModel.add(s,p,o);

This stimulated the rule to fire, and led to the following exception trace:

com.hp.hpl.jena.reasoner.rulesys.BuiltinException: Error in clause of rule (matematica) mysum: builtin mysum not usable in rule heads
    at com.hp.hpl.jena.reasoner.rulesys.builtins.BaseBuiltin.headAction(BaseBuiltin.java:86)
    at com.hp.hpl.jena.reasoner.rulesys.impl.RETEConflictSet.execute(RETEConflictSet.java:184)
    at com.hp.hpl.jena.reasoner.rulesys.impl.RETEConflictSet.add(RETEConflictSet.java:81)
    at com.hp.hpl.jena.reasoner.rulesys.impl.RETEEngine.requestRuleFiring(RETEEngine.java:249)
    at com.hp.hpl.jena.reasoner.rulesys.impl.RETETerminal.fire(RETETerminal.java:80)
    at com.hp.hpl.jena.reasoner.rulesys.impl.RETEClauseFilter.fire(RETEClauseFilter.java:227)
    at com.hp.hpl.jena.reasoner.rulesys.impl.RETEEngine.inject(RETEEngine.java:469)
    at com.hp.hpl.jena.reasoner.rulesys.impl.RETEEngine.runAll(RETEEngine.java:451)
    at com.hp.hpl.jena.reasoner.rulesys.impl.RETEEngine.add(RETEEngine.java:174)
    at com.hp.hpl.jena.reasoner.rulesys.FBRuleInfGraph.performAdd(FBRuleInfGraph.java:654)
    at com.hp.hpl.jena.graph.impl.GraphBase.add(GraphBase.java:202)
    at com.hp.hpl.jena.rdf.model.impl.ModelCom.add(ModelCom.java:1138)
    at SO.test(SO.java:108)

As a note: my test class is SO.java and line 108 is where we call infModel.add(s,p,o).

The exception that I get is different than the exception you encountered, but it is worth explaining. The implementation that you provided implements Builtin#bodyCall(...), but not Builtin#headAction(...). We can see the exception is thrown from BaseBuiltin#headAction(...). This default behavior assumes that you didn't implement the method because your Builtin doesn't support it. In the toy problem, this is correct behavior because the example implementation cannot be used in rule heads.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top