0

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);

    }
}
Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
user3563844
  • 113
  • 1
  • 8
  • 1
    "*but the new built-in does not seem to work. It is not recognized*" > I don't understand this description of your problem. What problem are you seeing? A compile error? A runtime error? Unexpected output? – Duncan Jones Apr 30 '14 at 09:37
  • My error is : Exception in thread "main" com.hp.hpl.jena.reasoner.rulesys.impl.LPRuleSyntaxException: Syntax error in backward rule: matematica Unknown builtin operation mysum. I do not know how I can set the reasoner, allowing it to recognise the new built-in. – user3563844 Apr 30 '14 at 10:08

1 Answers1

1

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.

Rob Hall
  • 2,693
  • 16
  • 22
  • 1
    Interesting that "Syntax error in **backward rule**: matematica Unknown builtin operation mysum". Isn't the rule as written in the question (with one thing in the body and five in the head) a forward rule? – Joshua Taylor Apr 30 '14 at 16:06
  • You are absolutely right. The toy example provided doesn't seem to reflect the actual rule in question. – Rob Hall May 02 '14 at 14:04
  • Hello everybody! Many thanks for your contribution. I have solved the problem thanks to you. I have built a customized built-in! – user3563844 May 05 '14 at 13:02
  • By the way, if the answer was helpful for this, and your other questions, you should [accept it](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). – Rob Hall May 05 '14 at 13:15