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

Reply via email to