You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@jena.apache.org by Chris Snyder <cs...@mind-tap.net> on 2015/12/09 18:31:20 UTC

Need help getting Jena rule to work

Hello,

I could use some input on getting my first Jena rule working.

I have a simple test ontology here:  http://mind-tap.net/kbswt/ruletest.ttl

I apply this rule:

@prefix : <http://mind-tap.net/kbswt/ruletest#>.
[ chris1: (?s :isOutput ?p) -> (?s :meOutput ?p) ]

And I run this SPARQL query

PREFIX : <http://mind-tap.net/kbswt/ruletest#>
select * where {?s :isOutput ?o.
OPTIONAL {?s :meOutput ?x} } 

I was expecting to see a :meOutput value for ?x but I’m not. 

I have tried the different built in reasoners and in my test application I can see that the rules are applied to the reasoner that my SPARQL query is executing against.

The application is basically following these steps

#create my ontModel
OntModelSpec ontModelSpec = new OntModelSpec(
				ModelFactory.createMemModelMaker(), null,
				RDFSRuleReasonerFactory.theInstance(),
				ProfileRegistry.OWL_DL_LANG);

		OntModel m = ModelFactory.createOntologyModel(ontModelSpec);
		m.read("http://mind-tap.net/kbswt/ruletest.ttl");

Then I use my ruleFromString class (a copy of the rulesFromURL updated to handle strings and show down below) to parse the rules and 
ontModel.getReasoner().setRules( [parsed rules list])

I next verify that the rules are applied to the reasoner by reading them back using a call to: 
reasoner.getRules();

and then I run my SPARQL on the ontModel.

I have my code in the GUI and common folders in a GIT repository here: https://bitbucket.org/blackburnphd/ontometa/src.
To use:
1) GUI has the main method. Run it
2) Setup the options on the Main tab and click init repository
3) Click the rule tab enter the rule and click “Replace” to clear the rules and add the rules listed in the rule text area
4) Click the SPARQL tab to enter and execute the SPARQL query.

Hopefully it is simply a mis-understanding of how to create the rules.

Any guidance would be appreciated.

Thank you,
Chris


BTW, I think this class should be added to the Rule class. It took me a while to figure out that the Rule.parse(string) call did not handle prefixes. 

/**
	 * Answer the list of rules parsed from the given string.
	 * 
	 * @throws RulesetNotFoundException
	 */
	public static List<Rule> rulesFromString(String ruleInput) {
		BufferedReader br = null;
		try {
			StringReader sr = new StringReader(ruleInput);
			br = new BufferedReader(sr);
			return Rule.parseRules(Rule.rulesParserFromReader(br));
		} finally {
			if (br != null)
				try {
					br.close();
				} catch (IOException e2) {
				}
		}
	}


Mindtap Inc
Chris Snyder
csnyder@mind-tap.net
561-374-8772
4769 Pepper Bush Ln
Boynton Beach, FL 33436




Re: Need help getting Jena rule to work

Posted by Chris Snyder <cs...@mind-tap.net>.
Thanks Dave your responses explained a lot. 

My goal is to setup a GUI that I can use to experiment with the built and reasoners and optionally add/remove rules from their rule sets. 

I updated my code to use your suggestions and I now have this:

OntModel oldModel = getRepository().getOntModel();
							OntModelSpec ontModelSpec = new OntModelSpec(
									ModelFactory.createMemModelMaker(), null,
									null, getRepository()
											.getRepositoryConfiguration()
											.getLanguageURI());

							ReasonerFactory rf = getRepository()
									.getRepositoryConfiguration()
									.getJenaReasonerFactory();
							RuleReasoner rr = (RuleReasoner) rf.create(null);
							rr.setRules(existingRules);

							ontModelSpec.setReasoner(rr);

							OntModel newModel = ModelFactory
									.createOntologyModel(ontModelSpec,
											oldModel.getBaseModel());
							getRepository().setOntModel(newModel);


where the existingRules list is built from the set of rules on the current ontModel reasoner and adding any new ones that were specified in the GUI. In this case what is really happening is that the options from the initial chosen reasoner are preserved while the rules are completely changed.

I don’t understand yet why adding my rule does not appear to have an affect when using the the OWLFBRule reasoner after running the above code and executing a SPARQL query against the new ontModel. I’m sure this probably has something to do with OWLFBRule not inheriting from the GenericRuleReasoner. I can at least experiment with the other reasoners now.

Otherwise my application seems to be working as expected and the implementation makes much more sense.

Thanks for your help,
Chris


> On Dec 10, 2015, at 3:51 AM, Dave Reynolds <da...@gmail.com> wrote:
> 
> On 09/12/15 23:12, Chris Snyder wrote:
>> I was finally able to get my rule to work. I’m not sure this is the best way to do it though as it seems very clunky.
>> 
>> It appears that the reasoner is applied only at the time of the ontModel creation. Since i was updating the reasoner rules after the ontModel was created the model and its inferred axioms were not regenerated. I tried just a plain rebind on the ontModel but that did not work either.
> 
> The rules are not run at OntModel creation. Forward rule are run when you first ask for any result or via an explicit prepare(). Backward rules are run in response to each query.
> 
> Dyanamically changing the forward rules associated with an InfModel is not supported (which I think is what you mean here). If you have a new ruleset then create a new InfModel (or OntModel with inference).
> 
>> What I finally did was:
>> 1) rebind the reasoner that is associated to the current ontModel (which already had its rules updated) with the base model of the ontModel
>> 2) create an InfModel using the updated reasoner and the base model
>> 3) rebind the current ontModel to reset it (not sure why this did not use the update reasoner rules)
>> 4) add the deduced triples from the infModel into the ontModel
> 
> This seems roundabout but I can't figure out what you are trying to achieve.
> 
> Assuming you have some base model, and then receive a new rule set, simply create a reasoner from that rule set, create an InfModel (or OntModel with inference) over the base model and consult that.
> 
>> I’m haven’t looked into why the ontModel.rebind() doesn’t seem to redo the reasoning but at least I have something to demo now.
>> 
>> Curiously, the rule update works with the RDFSReasoner and the GenericRuleReasoner but not the OWLFBRULE reasoner. I’m not sure why that is the case either although I expect that my rule is not valid for some option set with the OWLFBRule reasoner.
>> 
>> Here is the relevant bit of code. If someone has a better way of doing this please let me know.
>> 
>> ruleReasoner.setRules(existingRules);
> 
> This is OK but (as it says in the javadoc) this does not side effect any inference models that were already using the reasoner.
> 
>> 							ruleReasoner.bind(getRepository().getOntModel().getBaseModel().getGraph());
> 
> This is not doing what you think. GenericRuleReasoner.bind takes a base model and returns a new InfModel which applies the reasoner to the base triples. It does not side effect either the reasoner or the base model. Since you are doing nothing with the result of the bind this is essentially a no op.
> 					
>> 							InfModel inf = ModelFactory.createInfModel(ruleReasoner, getRepository().getOntModel().getBaseModel());
> 
> This is fine but if want a work with OntModels then why not create a new OntModel at this stage?
> 
>> 							getRepository().getOntModel().rebind();
> 
> Not sure why this step. If the OntModel has a reasoner attached then this will cause it to notice any under-the-covers data changes. However, you haven't changed the data and, as already mentioned, your changes to the rule reasoner apply to new Inf/OntModels not this one.
> 
>> 							getRepository().getOntModel().add(inf.getDeductionsModel());
> 
> This will only see the forward deductions, which would be fine for your earlier example.
> 
> Seems to me the easier sequence is something like:
> 
>    OntModel oldModel = getRepository().getOntModel();
>    OntModelSpec os = new OntModelSpec(ontModelSpec);
>    os.setReasoner( new GenericRuleReasoner(rules) );
>    OntModel newModel = ModelFactory.createOntologyModel(os, oldModel.getBaseModel());
>    getRepository().putOntModel(newModel);
> 
> Dave


Re: Need help getting Jena rule to work

Posted by Dave Reynolds <da...@gmail.com>.
On 09/12/15 23:12, Chris Snyder wrote:
> I was finally able to get my rule to work. I’m not sure this is the best way to do it though as it seems very clunky.
>
> It appears that the reasoner is applied only at the time of the ontModel creation. Since i was updating the reasoner rules after the ontModel was created the model and its inferred axioms were not regenerated. I tried just a plain rebind on the ontModel but that did not work either.

The rules are not run at OntModel creation. Forward rule are run when 
you first ask for any result or via an explicit prepare(). Backward 
rules are run in response to each query.

Dyanamically changing the forward rules associated with an InfModel is 
not supported (which I think is what you mean here). If you have a new 
ruleset then create a new InfModel (or OntModel with inference).

> What I finally did was:
> 1) rebind the reasoner that is associated to the current ontModel (which already had its rules updated) with the base model of the ontModel
> 2) create an InfModel using the updated reasoner and the base model
> 3) rebind the current ontModel to reset it (not sure why this did not use the update reasoner rules)
> 4) add the deduced triples from the infModel into the ontModel

This seems roundabout but I can't figure out what you are trying to achieve.

Assuming you have some base model, and then receive a new rule set, 
simply create a reasoner from that rule set, create an InfModel (or 
OntModel with inference) over the base model and consult that.

> I’m haven’t looked into why the ontModel.rebind() doesn’t seem to redo the reasoning but at least I have something to demo now.
>
> Curiously, the rule update works with the RDFSReasoner and the GenericRuleReasoner but not the OWLFBRULE reasoner. I’m not sure why that is the case either although I expect that my rule is not valid for some option set with the OWLFBRule reasoner.
>
> Here is the relevant bit of code. If someone has a better way of doing this please let me know.
>
> ruleReasoner.setRules(existingRules);

This is OK but (as it says in the javadoc) this does not side effect any 
inference models that were already using the reasoner.

> 							ruleReasoner.bind(getRepository().getOntModel().getBaseModel().getGraph());

This is not doing what you think. GenericRuleReasoner.bind takes a base 
model and returns a new InfModel which applies the reasoner to the base 
triples. It does not side effect either the reasoner or the base model. 
Since you are doing nothing with the result of the bind this is 
essentially a no op.
  					
> 							InfModel inf = ModelFactory.createInfModel(ruleReasoner, getRepository().getOntModel().getBaseModel());

This is fine but if want a work with OntModels then why not create a new 
OntModel at this stage?

> 							getRepository().getOntModel().rebind();

Not sure why this step. If the OntModel has a reasoner attached then 
this will cause it to notice any under-the-covers data changes. However, 
you haven't changed the data and, as already mentioned, your changes to 
the rule reasoner apply to new Inf/OntModels not this one.

> 							getRepository().getOntModel().add(inf.getDeductionsModel());

This will only see the forward deductions, which would be fine for your 
earlier example.

Seems to me the easier sequence is something like:

     OntModel oldModel = getRepository().getOntModel();
     OntModelSpec os = new OntModelSpec(ontModelSpec);
     os.setReasoner( new GenericRuleReasoner(rules) );
     OntModel newModel = ModelFactory.createOntologyModel(os, 
oldModel.getBaseModel());
     getRepository().putOntModel(newModel);

Dave

Re: Need help getting Jena rule to work

Posted by Chris Snyder <cs...@mind-tap.net>.
I was finally able to get my rule to work. I’m not sure this is the best way to do it though as it seems very clunky.

It appears that the reasoner is applied only at the time of the ontModel creation. Since i was updating the reasoner rules after the ontModel was created the model and its inferred axioms were not regenerated. I tried just a plain rebind on the ontModel but that did not work either. What I finally did was:
1) rebind the reasoner that is associated to the current ontModel (which already had its rules updated) with the base model of the ontModel
2) create an InfModel using the updated reasoner and the base model
3) rebind the current ontModel to reset it (not sure why this did not use the update reasoner rules)
4) add the deduced triples from the infModel into the ontModel 


I’m haven’t looked into why the ontModel.rebind() doesn’t seem to redo the reasoning but at least I have something to demo now. 

Curiously, the rule update works with the RDFSReasoner and the GenericRuleReasoner but not the OWLFBRULE reasoner. I’m not sure why that is the case either although I expect that my rule is not valid for some option set with the OWLFBRule reasoner.

Here is the relevant bit of code. If someone has a better way of doing this please let me know.

ruleReasoner.setRules(existingRules);

							ruleReasoner.bind(getRepository().getOntModel().getBaseModel().getGraph());
							
							InfModel inf = ModelFactory.createInfModel(ruleReasoner, getRepository().getOntModel().getBaseModel());
						
							getRepository().getOntModel().rebind();
							getRepository().getOntModel().add(inf.getDeductionsModel());


Thanks,
Chris

> On Dec 9, 2015, at 12:31 PM, Chris Snyder <cs...@mind-tap.net> wrote:
> 
> Hello,
> 
> I could use some input on getting my first Jena rule working.
> 
> I have a simple test ontology here:  http://mind-tap.net/kbswt/ruletest.ttl
> 
> I apply this rule:
> 
> @prefix : <http://mind-tap.net/kbswt/ruletest#>.
> [ chris1: (?s :isOutput ?p) -> (?s :meOutput ?p) ]
> 
> And I run this SPARQL query
> 
> PREFIX : <http://mind-tap.net/kbswt/ruletest#>
> select * where {?s :isOutput ?o.
> OPTIONAL {?s :meOutput ?x} } 
> 
> I was expecting to see a :meOutput value for ?x but I’m not. 
> 
> I have tried the different built in reasoners and in my test application I can see that the rules are applied to the reasoner that my SPARQL query is executing against.
> 
> The application is basically following these steps
> 
> #create my ontModel
> OntModelSpec ontModelSpec = new OntModelSpec(
> 				ModelFactory.createMemModelMaker(), null,
> 				RDFSRuleReasonerFactory.theInstance(),
> 				ProfileRegistry.OWL_DL_LANG);
> 
> 		OntModel m = ModelFactory.createOntologyModel(ontModelSpec);
> 		m.read("http://mind-tap.net/kbswt/ruletest.ttl");
> 
> Then I use my ruleFromString class (a copy of the rulesFromURL updated to handle strings and show down below) to parse the rules and 
> ontModel.getReasoner().setRules( [parsed rules list])
> 
> I next verify that the rules are applied to the reasoner by reading them back using a call to: 
> reasoner.getRules();
> 
> and then I run my SPARQL on the ontModel.
> 
> I have my code in the GUI and common folders in a GIT repository here: https://bitbucket.org/blackburnphd/ontometa/src.
> To use:
> 1) GUI has the main method. Run it
> 2) Setup the options on the Main tab and click init repository
> 3) Click the rule tab enter the rule and click “Replace” to clear the rules and add the rules listed in the rule text area
> 4) Click the SPARQL tab to enter and execute the SPARQL query.
> 
> Hopefully it is simply a mis-understanding of how to create the rules.
> 
> Any guidance would be appreciated.
> 
> Thank you,
> Chris
> 
> 
> BTW, I think this class should be added to the Rule class. It took me a while to figure out that the Rule.parse(string) call did not handle prefixes. 
> 
> /**
> 	 * Answer the list of rules parsed from the given string.
> 	 * 
> 	 * @throws RulesetNotFoundException
> 	 */
> 	public static List<Rule> rulesFromString(String ruleInput) {
> 		BufferedReader br = null;
> 		try {
> 			StringReader sr = new StringReader(ruleInput);
> 			br = new BufferedReader(sr);
> 			return Rule.parseRules(Rule.rulesParserFromReader(br));
> 		} finally {
> 			if (br != null)
> 				try {
> 					br.close();
> 				} catch (IOException e2) {
> 				}
> 		}
> 	}
> 
> 
> Mindtap Inc
> Chris Snyder
> csnyder@mind-tap.net
> 561-374-8772
> 4769 Pepper Bush Ln
> Boynton Beach, FL 33436
> 
> 
>