All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.coode.suggestor.util.ReasonerHelper Maven / Gradle / Ivy

/**
 * Date: Dec 17, 2007
 *
 * code made available under Mozilla Public License (http://www.mozilla.org/MPL/MPL-1.1.html)
 *
 * copyright 2007, The University of Manchester
 *
 * @author Nick Drummond, The University Of Manchester, Bio Health Informatics Group
 */
package org.coode.suggestor.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Nonnull;

import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataPropertyExpression;
import org.semanticweb.owlapi.model.OWLDataRange;
import org.semanticweb.owlapi.model.OWLDataSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.parameters.Imports;
import org.semanticweb.owlapi.reasoner.Node;
import org.semanticweb.owlapi.reasoner.NodeSet;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.impl.OWLDatatypeNode;
import org.semanticweb.owlapi.reasoner.impl.OWLDatatypeNodeSet;
import org.semanticweb.owlapi.search.Searcher;

/** Utility methods for common reasoner tasks. */
public class ReasonerHelper {

    private final OWLReasoner r;
    private final OWLDataFactory df;

    /**
     * @param r
     *        reasoner to use
     */
    public ReasonerHelper(OWLReasoner r) {
        if (r == null) {
            throw new IllegalArgumentException("Reasoner cannot be null");
        }
        this.r = r;
        df = r.getRootOntology().getOWLOntologyManager().getOWLDataFactory();
    }

    /** @return referenced properties */
    public Set getReferencedObjectProperties() {
        final OWLOntology root = r.getRootOntology();
        Set p = new HashSet<>(
                root.getObjectPropertiesInSignature(Imports.INCLUDED));
        p.add(df.getOWLTopObjectProperty());
        p.add(df.getOWLBottomObjectProperty());
        return p;
    }

    /** @return referenced properties */
    public Set getReferencedDataProperties() {
        final OWLOntology root = r.getRootOntology();
        Set p = new HashSet<>(
                root.getDataPropertiesInSignature(Imports.INCLUDED));
        p.add(df.getOWLTopDataProperty());
        p.add(df.getOWLBottomDataProperty());
        return p;
    }

    /**
     * @param cls1
     *        class 1
     * @param cls2
     *        class 2
     * @return true if cls1 is a subclass of cls2
     */
    public boolean isDescendantOf(@Nonnull OWLClassExpression cls1,
            @Nonnull OWLClassExpression cls2) {
        // return isAncestorOf(cls2, cls1);
        if (!cls1.isAnonymous()) {
            return r.getSubClasses(cls2, false).containsEntity(
                    cls1.asOWLClass());
        }
        return r.isEntailed(df.getOWLSubClassOfAxiom(cls1, cls2));
    }

    /**
     * @param cls1
     *        class 1
     * @param cls2
     *        class 2
     * @return true if cls2 is a subclass of cls1
     */
    public boolean isAncestorOf(@Nonnull OWLClassExpression cls1,
            @Nonnull OWLClassExpression cls2) {
        if (!cls1.isAnonymous()) {
            return r.getSuperClasses(cls2, false).containsEntity(
                    cls1.asOWLClass());
        }
        return r.isEntailed(df.getOWLSubClassOfAxiom(cls2, cls1));
    }

    /**
     * @param clses
     *        classes
     * @return clses without classes with superclasses in the set
     */
    public Set filterClassExpressions(
            Set clses) {
        Set nonRedundantSet = new HashSet<>();
        List clsList = new ArrayList<>(clses);
        for (int i = 0; i < clsList.size(); i++) {
            final OWLClassExpression head = clsList.get(i);
            assert head != null;
            if (!containsSubclass(clsList.subList(i + 1, clsList.size()), head)
                    && !containsSubclass(nonRedundantSet, head)) {
                nonRedundantSet.add(head);
            }
        }
        return nonRedundantSet;
    }

    /**
     * @param potentialSubs
     *        potential subs
     * @param cls
     *        class
     * @return true if one of potentialSubs is a subclass of cls
     */
    public boolean containsSubclass(
            Collection potentialSubs,
            @Nonnull OWLClassExpression cls) {
        for (OWLClassExpression potentialSub : potentialSubs) {
            assert potentialSub != null;
            if (isDescendantOf(potentialSub, cls)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param c
     *        class
     * @param p
     *        property
     * @return true if c is a subclass of max 1 p
     */
    public boolean isLocallyFunctional(OWLClassExpression c,
            OWLObjectPropertyExpression p) {
        return isDescendantOf(c, df.getOWLObjectMaxCardinality(1, p));
    }

    /**
     * @param c
     *        class
     * @param p
     *        property
     * @return true if c is a subclass of max 1 p
     */
    public boolean isLocallyFunctional(OWLClassExpression c,
            @Nonnull OWLDataProperty p) {
        return isDescendantOf(c, df.getOWLDataMaxCardinality(1, p));
    }

    /**
     * 

* Check the ontologies for range assertions on p and all ancestors of p. *

* * @param p * the object property for which a range is wanted * @return an intersection of the non-redundant ranges or Thing if no range * assertions have been made */ @Nonnull public OWLClassExpression getGlobalAssertedRange( @Nonnull OWLObjectPropertyExpression p) { OWLClassExpression range = df.getOWLThing(); Set assertedRanges = new HashSet<>(); Set ancestors = new HashSet<>(r .getSuperObjectProperties(p, false).getFlattened()); ancestors.add(p); for (OWLOntology ont : r.getRootOntology().getImportsClosure()) { for (OWLObjectPropertyExpression ancestor : ancestors) { Collection searcher = Searcher.range(ont .getObjectPropertyRangeAxioms(ancestor)); assertedRanges.addAll(searcher); } } if (!assertedRanges.isEmpty()) { // filter to remove redundant ranges (supers of others) as // getRanges() just returns all of them assertedRanges = filterClassExpressions(assertedRanges); if (assertedRanges.size() == 1) { range = assertedRanges.iterator().next(); } else { range = df.getOWLObjectIntersectionOf(assertedRanges); } } return range; } /** *

* Find the asserted ranges on this property and all of its ancestors. *

*

* If multiple ranges are found, they are pulled together into an * intersection. *

* * @param p * the property we are querying * @return the range of this property or Top if none is found */ public OWLDataRange getGlobalAssertedRange(OWLDataProperty p) { OWLDataRange range = df.getTopDatatype(); Set assertedRanges = new HashSet<>(); Set ancestors = new HashSet<>(r .getSuperDataProperties(p, false).getFlattened()); ancestors.add(p); for (OWLOntology ont : r.getRootOntology().getImportsClosure()) { for (OWLDataProperty ancestor : ancestors) { Collection searcher = Searcher.range(ont .getDataPropertyRangeAxioms(ancestor)); assertedRanges.addAll(searcher); } } if (!assertedRanges.isEmpty()) { if (assertedRanges.size() == 1) { range = assertedRanges.iterator().next(); } else { range = df.getOWLDataIntersectionOf(assertedRanges); } } return range; } /** * Subsumption checking between dataranges/types. This will only work if * there is a suitable data property in the ontology. This must satisfy the * criteria in * {@link #getCandidatePropForRangeSubsumptionCheck(OWLDataRange)}. * * @param subRange * subRange * @param superRange * superRange * @return true if subRange is subsumed by superRange * @throws RuntimeException * if no suitable property can be found */ public boolean isSubtype(OWLDataRange subRange, OWLDataRange superRange) { OWLDataPropertyExpression p = getCandidatePropForRangeSubsumptionCheck(superRange); if (p == null) { throw new RuntimeException( "Cannot find a candidate property for datatype subsumption checking"); } return r.isEntailed(df.getOWLSubClassOfAxiom( df.getOWLDataSomeValuesFrom(p, subRange), df.getOWLDataSomeValuesFrom(p, superRange))); } /** * Subsumption between dataranges/types. This will only work if there is a * suitable data property in the ontology. This must satisfy the criteria in * {@link #getCandidatePropForRangeSubsumptionCheck(OWLDataRange)}. * * @param range * The data range for which we will retrieve subtypes * @return a NodeSet containing named datatypes that are known to be * subtypes of range * @throws RuntimeException * if no suitable property can be found */ @Nonnull public NodeSet getSubtypes(OWLDataRange range) { OWLDataPropertyExpression p = getCandidatePropForRangeSubsumptionCheck(range); if (p == null) { throw new RuntimeException( "Cannot find a candidate property for datatype subsumption checking"); } Set> subs = new HashSet<>(); OWLDataSomeValuesFrom pSomeRange = df .getOWLDataSomeValuesFrom(p, range); for (OWLDatatype dt : getDatatypesInSignature()) { if (!dt.equals(range)) { final OWLDataSomeValuesFrom pSomeDatatype = df .getOWLDataSomeValuesFrom(p, dt); if (!r.isSatisfiable(pSomeDatatype)) { // TODO can we protect against this? System.err .println("Warning: unsatisfiable concept in subtype checking: " + pSomeDatatype); } else if (r.isEntailed(df.getOWLSubClassOfAxiom(pSomeDatatype, pSomeRange))) { subs.add(new OWLDatatypeNode(dt)); } } } return new OWLDatatypeNodeSet(subs); } /** * Equivalence between dataranges/types. This will only work if there is a * suitable data property in the ontology. This must satisfy the criteria in * {@link #getCandidatePropForRangeSubsumptionCheck(OWLDataRange)}. * * @param range * The data range for which we will retrieve equivalents * @return a NodeSet containing named datatypes that are known to be * equivalent to range * @throws RuntimeException * if no suitable property can be found */ @Nonnull public Node getEquivalentTypes(OWLDataRange range) { OWLDataPropertyExpression p = getCandidatePropForRangeSubsumptionCheck(range); if (p == null) { throw new RuntimeException( "Cannot find a candidate property for datatype subsumption checking"); } Set subs = new HashSet<>(); if (range.isDatatype()) { subs.add(range.asOWLDatatype()); } OWLDataSomeValuesFrom pSomeRange = df .getOWLDataSomeValuesFrom(p, range); for (OWLDatatype dt : getDatatypesInSignature()) { if (!dt.equals(range)) { final OWLDataSomeValuesFrom pSomeDatatype = df .getOWLDataSomeValuesFrom(p, dt); if (!r.isSatisfiable(pSomeDatatype)) { // TODO can we protect against this? System.err .println("Warning: unsatisfiable concept in equiv type checking: " + pSomeDatatype); } else if (r.isEntailed(df.getOWLEquivalentClassesAxiom( pSomeDatatype, pSomeRange))) { subs.add(dt); } } } return new OWLDatatypeNode(subs); } /** *

* Find a candidate property for datatype subsumption checking. *

*

* If {O} is the set of ontologies loaded into the reasoner, a candidate is * ANY data property (APART FROM Top) in the signature of {O} that satifies * the criteria isSatisfiable(SomeValuesFrom(p, range). *

* * @param range * the data range from which will be used in the above test * @return a candidate property that fulfils the above criteria or null if * none can be found */ public OWLDataPropertyExpression getCandidatePropForRangeSubsumptionCheck( OWLDataRange range) { for (OWLOntology ont : r.getRootOntology().getImportsClosure()) { for (OWLDataProperty p : ont.getDataPropertiesInSignature()) { if (!p.isTopEntity() && r.isSatisfiable(df .getOWLDataSomeValuesFrom(p, range))) { return p; } } } return null; } /** @return all datatypes in the ontology import closure */ public Set getDatatypesInSignature() { Set dts = new HashSet<>(); for (OWLOntology ont : r.getRootOntology().getImportsClosure()) { dts.addAll(ont.getDatatypesInSignature()); } return dts; } /** * @param p * property * @param f * range * @return true if range is asserted */ public boolean isInAssertedRange(OWLObjectPropertyExpression p, OWLClassExpression f) { return isDescendantOf(f, getGlobalAssertedRange(p)); } /** * @param p * property * @param f * range * @return true if range is asserted */ public boolean isInAssertedRange(OWLDataProperty p, OWLDataRange f) { return isSubtype(f, getGlobalAssertedRange(p)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy