Here are code snipets that should fill in the missing parts:
kbModel =
ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM_MICRO_RULE_INF);
// kbModel =
ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_TRANS_INF);
// kbModel =
ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
kbModel.read(kbOntInputStream, null);
logger.info("Conducting inference over ontology...");
kbModel.prepare();
logger.info("Completed inference over ontology.");
.
.
.
// (Statement input)
// (NamedGraphModel inputDataModel)
Property typePredicate = inputDataModel
.getProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
Property stmtPredicate = input.getPredicate();
OntProperty stmtOntProperty =
kbModel.getOntProperty(stmtPredicate.toString());
if (stmtPredicate != null && stmtOntProperty != null &&
!stmtOntProperty.equals(typePredicate)) {
// get domain and range of ontology property
OntResource propDomain = stmtOntProperty.getDomain();
OntResource propRange = stmtOntProperty.getRange();
boolean pd = false;
// get type of input statement subject
Statement domainTypeStatement =
inputDataModel.getProperty(input.getSubject(), typePredicate);
// ensure input statement subject has a type
if (domainTypeStatement != null) {
if (domainTypeStatement.getObject().isResource()) {
pd =
propDomain.asClass().hasSubClass(domainTypeStatement.getObject().asResource());
} else {
// subject of a statement should always be a resource
}
} else {
// check whether input statement subject is a Named Graph
// serving as a statement about a statement (Ontology type is
StatementGraph)
pd =
inputStatementSet.containsGraph(input.getSubject().toString());
}
boolean pr = false;
// get type of input statement object
Statement rangeTypeStatement = null;
RDFDatatype rangeDatatype = null;
if (input.getObject().isResource()) {
rangeTypeStatement =
inputDataModel.getProperty(input.getObject().asResource(), typePredicate);
} else if (input.getObject().isLiteral() ){
rangeDatatype = input.getObject().asLiteral().getDatatype();
if (rangeDatatype == null)
;// set range data type to some default type
// rangeDatatype = new
BaseDatatype("http://www.w3.org/2001/XMLSchema#string");
rangeTypeStatement = input;
} else {
// handle anonymous (or blank node) type
}
// ensure input statement object has a type
if (rangeTypeStatement != null) {
if (rangeTypeStatement.getObject().isResource()) {
pr =
propRange.asClass().hasSubClass(hltkbModel.createClass(rangeTypeStatement.getObject().toString()));
} else if (rangeTypeStatement.getObject().isLiteral()) {
if (rangeDatatype != null)
pr = propRange.getURI().equals(rangeDatatype.getURI());
else
// assuming range is a literal string and range type is
a string
pr = true;
}
} else {
// check whether input statement object is a Named Graph
// serving as a statement about a statement
pr =
inputStatementSet.containsGraph(input.getObject().toString());
}
}
This code is intended to do a closed world domain and range check on a
property. When using the RULE OntModelSpecs (e.g. OWL_MEM_MICRO_RULE_INF as you
suggest) the stmtOntProperty.getDomain() and stmtOntProperty.getRange() methods
consistently return "http://www.w3.org/2002/07/owl#Thing" as the domain and
range for properties. Thus, all checks for correct domain and range return
true. When using the TRANS OntModelSpecs (e.g. OWL_DL_MEM_TRANS_INF) the
stmtOntProperty.getDomain() and stmtOntProperty.getRange() methods return the
domains and ranges specified in the ontology, but the
propDomain.asClass().hasSubClass(domainTypeStatement.getObject().asResource())
and
propRange.asClass().hasSubClass(hltkbModel.createClass(rangeTypeStatement.getObject().toString()))
methods don't handle (do the expected subclass inference) for
complex/anonymous classes.
Hopefully this sheds more light on my challenge.
- Wayne
-----Original Message-----
From: Dave Reynolds [mailto:[email protected]]
Sent: Tuesday, February 21, 2012 5:17 PM
To: [email protected]
Cc: Bethea, Wayne L.
Subject: Re: Jena Subclass/Subsumption Inference
On 21/02/12 21:37, Bethea, Wayne L. wrote:
> In my code I attempt to do OWL subclass inference by creating a Jena OntModel
> using the code:
>
> - OntModel hModel =
> ModelFactory.creatOntologyModel(OntModelSpec.OWL_DL_MEM_TRANS_INF);
>
> And checking for subclass existence using the code:
>
> - Boolean pd =
> propDomain.asClass().hasSubClass(domainTypeStatement.getObject().asResource());
>
> OWL_DL_MEM_TRANS_INF - is a specification for OWL DL models that are stored
> in memory and use the transitive inference for additional entailments. This
> is sufficient for subclass inference of simple classes
> (Entity<-AbstractEntity<-Account<-FinancialAccount<-BankAccount), but is not
> sufficient for subclass inference of more complex classes:
Correct, it only implements rdfs:subClassOf and rdfs:subPropertyOf.
> <owl:Class>
> <owl:unionOf rdf:parseType="Collection">
> <rdf:Description rdf:about="#Device"/>
> <rdf:Description rdf:about="#FacilityRegion"/>
> </owl:unionOf>
> </owl:Class>
>
> and CommunicationDevice.
I don't follow that example, too many bits missing.
> I've tried to use different OntModelSpecs to get the subclass inference that
> I am looking for but I haven't been able to identify the correct one. I've
> tried:
>
> - OntModel hModel =
> ModelFactory.creatOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF);
>
> but it seems to have the opposite effect where it can capture the subclass
> inference involving more complex classes but not the simple class subclass
> inference.
It certainly should be a superset of the simple cases.
Do you have a specific, minimal example of an entailment RULE_INF misses
but which is handled by one of the simpler configurations?
> Any advice on the correct Jena OntModelSpec to use to capture relatively easy
> subclass inference would be appreciated.
My general advice is to use OWL_MICRO (which in OntModel terms is
OWL_MEM_MICRO_RULE_INF) as the best trade-off for power and efficiency.
I seem to remember that it handles unionOf. Otherwise go for OWL_MINI.
Dave