In your example code you have an OntModel which is specified to include
a reasoner using the default OWL rules. You then have an InfModel on top
of that with your own rule. So the OWL rules are generating entailments
from the domain declarations for born_in which are then visible through
your enclosing rule InfModel.
I'm not sure exactly want you want to achieve ...
If you want an OntModel interface but with just your rule(s) then one
easy way is to generate your own OntModelSpec based off OWL_MEM and
attach your reasoner to it using setReasoner, then use that to create
your OntModel. Don't bother with a separate InfModel. That way you just
have one layer of model and avoid any confusion from nesting models.
If you just want a plaing InfModel interface with just your rules then
you can create the InfModel as you are doing over either a plain Model
or over an OntModel with no second reasoning layer.
If you want OWL inference and then want to run your own rules on top of
that then the setup you have is one way to do that.
Comments inline below ...
On 20/01/2020 10:06, Luis Enrique Ramos García wrote:
Dear friends of jena community,
I am testing the syntax of apache jena rules, with a very simple example,
where I create the following model and classes:
OntModel m = ModelFactory.createOntologyModel();
OntClass c0 = m.createClass( NS + "c0" );
OntClass c1 = m.createClass( NS + "c1" );
OntClass c2 = m.createClass( NS + "c2" );
and the following individuals as members of the its respective classes:
//creation of individual
Individual i0 = m.createIndividual( NS + "individual0", c0 );
Individual i1 = m.createIndividual( NS + "individual1", c1 );
when I run the rule, that says:
if individual* i? *is member of c0, then has to be member of *c2*
String *ruleSrc* = "[rule1: (?a
http://www.w3.org/1999/02/22-rdf-syntax-ns#type www.example.com#c0) -> "
+ "(?a http://www.w3.org/1999/02/22-rdf-syntax-ns#type www.example.com#c2)
]";
More readable if you use the builtin prefixes like rdf:type
Also www.example.com# is a (scheme-) relative URL, not that it matters
in this case but better to get used to using absolute URLs including the
http:// bit.
the rule is triggered as expected and give me the following result:
[www.example.com#individual0,
http://www.w3.org/1999/02/22-rdf-syntax-ns#type, www.example.com#c2]>
Nevertheless, when I add more information to the model, and say that
individuals i0 and i1 have birthday:
i0.addProperty(born_in, date1.toString());
i1.addProperty(born_in, date2.toString());
The behavior of rule output changed, and I obtain a different result:
<ModelCom org.apache.jena.reasoner.rulesys.impl [
www.example.com#individual1, http://www.w3.org/1999/02/22-rdf-syntax-ns#type,
www.example.com#c2] [www.example.com#individual0,
http://www.w3.org/1999/02/22-rdf-syntax-ns#type, www.example.com#c2]>
Where individual 1 is declared as member of c2, it means that individual1
is member of c0, something that I did not declared.
You did but indirectly. You declared that the domain of born_in includes
c0 and c1. So the with-OWL-inference OntModel will deduce, among other
things:
:i0 rdf:type :c0
Then your own rule, runing in the InfModel, sees that and since it
states that anything of type c0 is also of type c2 it deduces that:
:i0 rdf:type :c2
I changed model declaration as follows:
OntModel m = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
and obtained the expected result, however the documentation says there is
not reasoning there,
Correct. That way the OntModel itself is not doing any reasoning, so the
only reasoning you see out of your InfModel is from your own rule set
and nothing more. Just one reasoner in play.
thus I implemented a reasoner model and obtained an
unexpected result again.
Don't follow what you did but it shoulds no different from what you show
below with two layers of inference one on top of the other.
My main concern is that when I inspect the *asserted model , *I see it
contains individual 1 declared as part of c0, something that, according to
my understanding should not occur, because I have not declared that.
The based model you are giving to the InfModel is the OntModel *with OWL
inference* (by virtue of the OWL_DL_MEM_RULE_INF spec). It is not an
"asserted model".
In general avoid having lots of layers of different models with multiple
reasoners runing other the top of each other unless that is absolutely
what you need.
Dave
Any comment and recommendation is welcomed.
Bellow is the whole java code.
Luis Ramos
****************************************CODE
**********************************************
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.jena.ontology.DatatypeProperty;
import org.apache.jena.ontology.Individual;
import org.apache.jena.ontology.OntClass;
import org.apache.jena.ontology.OntModel;
import org.apache.jena.ontology.OntModelSpec;
import org.apache.jena.rdf.model.InfModel;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.reasoner.Reasoner;
import org.apache.jena.reasoner.rulesys.GenericRuleReasoner;
import org.apache.jena.reasoner.rulesys.Rule;
import org.apache.jena.vocabulary.XSD;
public class OntGenRule {
public static void main(String[] args) throws ParseException {
String URL = "www.example.com";
String NS = URL+"#";
String rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns";
String rdf_ns = rdf+"#";
//creation of the model
OntModel m = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
//addition of classes
OntClass c0 = m.createClass( NS + "c0" );
OntClass c1 = m.createClass( NS + "c1" );
OntClass c2 = m.createClass( NS + "c2" );
//creation of individual
Individual i0 = m.createIndividual( NS + "individual0", c0 );
Individual i1 = m.createIndividual( NS + "individual1", c1 );
//date property
DatatypeProperty born_in = m.createDatatypeProperty( NS + "birthday" );
born_in.addDomain( m.getOntClass( NS + "c0" ) );
born_in.addDomain( m.getOntClass( NS + "c1" ) );
born_in.addRange( XSD.dateTime );
//create a date
SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy
hh:mm:ss");//-uncomment for test
String date1toString = "31-08-1982 10:20:56";//-uncomment for test
String date2toString = "12-02-1977 10:20:56";//-uncomment for test
Date date1 = sdf.parse(date1toString);//-uncomment for test
Date date2 = sdf.parse(date2toString);//-uncomment for test
//addition of date to individuals
i0.addProperty(born_in, date1.toString());//-uncomment for test
i1.addProperty(born_in, date2.toString());//-uncomment for test
//System.out.println(p0.getProperty(born_in).getObject());
//System.out.println(p1.getProperty(born_in).getObject());
OntModel testModel =
ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF,
m);//onto model, to hold ontology
String ruleSrc = "[rule1: (?a
http://www.w3.org/1999/02/22-rdf-syntax-ns#type www.example.com#c0) -> "
+ "(?a http://www.w3.org/1999/02/22-rdf-syntax-ns#type www.example.com#c2)
]";
List rules = Rule.parseRules(ruleSrc);
Reasoner reasoner = new GenericRuleReasoner(rules);
InfModel inf = ModelFactory.createInfModel(reasoner, testModel);
Model deducedM = ModelFactory.createOntologyModel();
deducedM = inf.getDeductionsModel();
System.out.println(testModel);
System.out.println(deducedM);
}
}