org.dllearner.reasoning.FastInstanceChecker.java Source code

Java tutorial

Introduction

Here is the source code for org.dllearner.reasoning.FastInstanceChecker.java

Source

/**
 * Copyright (C) 2007-2011, Jens Lehmann
 *
 * This file is part of DL-Learner.
 *
 * DL-Learner is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * DL-Learner is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.dllearner.reasoning;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.log4j.Logger;
import org.dllearner.core.AbstractReasonerComponent;
import org.dllearner.core.ComponentAnn;
import org.dllearner.core.ComponentInitException;
import org.dllearner.core.KnowledgeSource;
import org.dllearner.core.ReasoningMethodUnsupportedException;
import org.dllearner.core.config.ConfigOption;
import org.dllearner.utilities.Helper;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataHasValue;
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.OWLDatatypeRestriction;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLFacetRestriction;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectHasValue;
import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectUnionOf;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.vocab.OWLFacet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;

import com.google.common.hash.HashFunction;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;

/**
 * Reasoner for fast instance checks. It works by completely dematerialising the
 * knowledge base to speed up later reasoning requests. It then continues by
 * only considering one model of the knowledge base (TODO: more explanation),
 * which is neither correct nor complete, but sufficient in many cases. A big
 * advantage of the algorithm is that it does not need even need to perform any
 * set modifications (union, intersection, difference), so it avoids any Java
 * object creation, which makes it extremely fast compared to standard
 * reasoners.
 * 
 * Meanwhile, the algorithm has been extended to also perform fast retrieval
 * operations. However, those need write access to memory and potentially have
 * to deal with all individuals in a knowledge base. For many knowledge bases,
 * they should still be reasonably fast. 
 * 
 * @author Jens Lehmann
 * 
 */
@ComponentAnn(name = "fast instance checker", shortName = "fic", version = 0.9)
public class FastInstanceChecker extends AbstractReasonerComponent {

    private static Logger logger = Logger.getLogger(FastInstanceChecker.class);

    //   private boolean defaultNegation = true;

    private Set<OWLClass> atomicConcepts;
    private Set<OWLObjectProperty> atomicRoles;
    private Set<OWLDataProperty> datatypeProperties;
    private Set<OWLDataProperty> booleanDatatypeProperties = new TreeSet<OWLDataProperty>();
    private Set<OWLDataProperty> doubleDatatypeProperties = new TreeSet<OWLDataProperty>();
    private Set<OWLDataProperty> intDatatypeProperties = new TreeSet<OWLDataProperty>();
    private Set<OWLDataProperty> stringDatatypeProperties = new TreeSet<OWLDataProperty>();
    private TreeSet<OWLIndividual> individuals;

    // private ReasonerComponent rs;

    private OWLAPIReasoner rc;

    // we use sorted sets (map indices) here, because they have only log(n)
    // complexity for checking whether an element is contained in them
    // instances of classes
    private Map<OWLClass, TreeSet<OWLIndividual>> classInstancesPos = new TreeMap<OWLClass, TreeSet<OWLIndividual>>();
    private Map<OWLClass, TreeSet<OWLIndividual>> classInstancesNeg = new TreeMap<OWLClass, TreeSet<OWLIndividual>>();
    // object property mappings
    private Map<OWLObjectProperty, Map<OWLIndividual, SortedSet<OWLIndividual>>> opPos = new TreeMap<OWLObjectProperty, Map<OWLIndividual, SortedSet<OWLIndividual>>>();
    // data property mappings
    private Map<OWLDataProperty, Map<OWLIndividual, SortedSet<OWLLiteral>>> dpPos = new TreeMap<OWLDataProperty, Map<OWLIndividual, SortedSet<OWLLiteral>>>();

    // datatype property mappings
    // we have one mapping for true and false for efficiency reasons
    private Map<OWLDataProperty, TreeSet<OWLIndividual>> bdPos = new TreeMap<OWLDataProperty, TreeSet<OWLIndividual>>();
    private Map<OWLDataProperty, TreeSet<OWLIndividual>> bdNeg = new TreeMap<OWLDataProperty, TreeSet<OWLIndividual>>();
    // for int and double we assume that a property can have several values,
    // althoug this should be rare,
    // e.g. hasValue(object,2) and hasValue(object,3)
    private Map<OWLDataProperty, Map<OWLIndividual, SortedSet<Double>>> dd = new TreeMap<OWLDataProperty, Map<OWLIndividual, SortedSet<Double>>>();
    private Map<OWLDataProperty, Map<OWLIndividual, SortedSet<Integer>>> id = new TreeMap<OWLDataProperty, Map<OWLIndividual, SortedSet<Integer>>>();
    private Map<OWLDataProperty, Map<OWLIndividual, SortedSet<String>>> sd = new TreeMap<OWLDataProperty, Map<OWLIndividual, SortedSet<String>>>();

    private Map<OWLDataProperty, Map<OWLIndividual, SortedSet<Number>>> numericValueMappings = new TreeMap<OWLDataProperty, Map<OWLIndividual, SortedSet<Number>>>();

    @ConfigOption(name = "defaultNegation", description = "Whether to use default negation, i.e. an instance not being in a class means that it is in the negation of the class.", defaultValue = "true", required = false)
    private boolean defaultNegation = true;

    @ConfigOption(name = "forAllRetrievalSemantics", description = "This option controls how to interpret the all quantifier in forall r.C. The standard option is"
            + "to return all those which do not have an r-filler not in C. The domain semantics is to use those"
            + "which are in the domain of r and do not have an r-filler not in C. The forallExists semantics is to"
            + "use those which have at least one r-filler and do not have an r-filler not in C.", defaultValue = "standard", propertyEditorClass = StringTrimmerEditor.class)
    private ForallSemantics forallSemantics = ForallSemantics.Standard;

    public enum ForallSemantics {
        Standard, // standard all quantor
        NonEmpty, // p only C for instance a returns false if there is no fact p(a,x) for any x  
        SomeOnly // p only C for instance a returns false if there is no fact p(a,x) with x \ in C  
    }

    private boolean materializeExistentialRestrictions = false;

    private boolean useCaching = true;
    private boolean handlePunning = false;

    /**
     * Creates an instance of the fast instance checker.
     */
    public FastInstanceChecker() {
    }

    public FastInstanceChecker(TreeSet<OWLIndividual> individuals,
            Map<OWLClass, TreeSet<OWLIndividual>> classInstancesPos,
            Map<OWLObjectProperty, Map<OWLIndividual, SortedSet<OWLIndividual>>> opPos,
            Map<OWLDataProperty, Map<OWLIndividual, SortedSet<Integer>>> id,
            Map<OWLDataProperty, TreeSet<OWLIndividual>> bdPos, Map<OWLDataProperty, TreeSet<OWLIndividual>> bdNeg,
            KnowledgeSource... sources) {
        super(new HashSet<KnowledgeSource>(Arrays.asList(sources)));
        this.individuals = individuals;
        this.classInstancesPos = classInstancesPos;
        this.opPos = opPos;
        this.id = id;
        this.bdPos = bdPos;
        this.bdNeg = bdNeg;

        if (rc == null) {
            rc = new OWLAPIReasoner(new HashSet<KnowledgeSource>(Arrays.asList(sources)));
            try {
                rc.init();
            } catch (ComponentInitException e) {
                e.printStackTrace();
            }
        }

        atomicConcepts = rc.getClasses();
        datatypeProperties = rc.getDatatypeProperties();
        booleanDatatypeProperties = rc.getBooleanDatatypeProperties();
        doubleDatatypeProperties = rc.getDoubleDatatypeProperties();
        intDatatypeProperties = rc.getIntDatatypeProperties();
        stringDatatypeProperties = rc.getStringDatatypeProperties();
        atomicRoles = rc.getObjectProperties();

        for (OWLClass atomicConcept : atomicConcepts) {
            TreeSet<OWLIndividual> pos = classInstancesPos.get(atomicConcept);
            if (pos != null) {
                classInstancesNeg.put(atomicConcept, (TreeSet<OWLIndividual>) Helper.difference(individuals, pos));
            } else {
                classInstancesPos.put(atomicConcept, new TreeSet<OWLIndividual>());
                classInstancesNeg.put(atomicConcept, individuals);
            }
        }

        for (OWLObjectProperty p : atomicRoles) {
            if (opPos.get(p) == null) {
                opPos.put(p, new HashMap<OWLIndividual, SortedSet<OWLIndividual>>());
            }
        }

        for (OWLDataProperty dp : booleanDatatypeProperties) {
            if (bdPos.get(dp) == null) {
                bdPos.put(dp, new TreeSet<OWLIndividual>());
            }
            if (bdNeg.get(dp) == null) {
                bdNeg.put(dp, new TreeSet<OWLIndividual>());
            }

        }
    }

    public FastInstanceChecker(Set<KnowledgeSource> sources) {
        super(sources);
    }

    public FastInstanceChecker(KnowledgeSource... sources) {
        super(new HashSet<KnowledgeSource>(Arrays.asList(sources)));
    }

    public FastInstanceChecker(KnowledgeSource source) {
        super(new HashSet<KnowledgeSource>(Arrays.asList(source)));
    }

    /**
    * @return The name of this component.
    */
    public static String getName() {
        return "fast instance checker";
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dllearner.core.Component#init()
     */
    @Override
    public void init() throws ComponentInitException {

        if (rc == null) {
            rc = new OWLAPIReasoner(sources);
            rc.init();
        }
        atomicConcepts = rc.getClasses();
        datatypeProperties = rc.getDatatypeProperties();
        booleanDatatypeProperties = rc.getBooleanDatatypeProperties();
        doubleDatatypeProperties = rc.getDoubleDatatypeProperties();
        intDatatypeProperties = rc.getIntDatatypeProperties();
        stringDatatypeProperties = rc.getStringDatatypeProperties();
        atomicRoles = rc.getObjectProperties();
        individuals = (TreeSet<OWLIndividual>) rc.getIndividuals();

        //      loadOrDematerialize();
        materialize();
    }

    private void loadOrDematerialize() {
        if (useCaching) {
            File cacheDir = new File("cache");
            cacheDir.mkdirs();
            HashFunction hf = Hashing.md5();
            Hasher hasher = hf.newHasher();
            hasher.putBoolean(materializeExistentialRestrictions);
            hasher.putBoolean(handlePunning);
            for (OWLOntology ont : rc.getOWLAPIOntologies()) {
                hasher.putInt(ont.getLogicalAxioms().hashCode());
                hasher.putInt(ont.getAxioms().hashCode());
            }
            String filename = hasher.hash().toString() + ".obj";

            File cacheFile = new File(cacheDir, filename);
            if (cacheFile.exists()) {
                logger.debug("Loading materialization from disk...");
                try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(cacheFile))) {
                    Materialization mat = (Materialization) ois.readObject();
                    classInstancesPos = mat.classInstancesPos;
                    classInstancesNeg = mat.classInstancesNeg;
                    opPos = mat.opPos;
                    dpPos = mat.dpPos;
                    bdPos = mat.bdPos;
                    bdNeg = mat.bdNeg;
                    dd = mat.dd;
                    id = mat.id;
                    sd = mat.sd;
                } catch (ClassNotFoundException | IOException e) {
                    e.printStackTrace();
                }
                logger.debug("done.");
            } else {
                materialize();
                Materialization mat = new Materialization();
                mat.classInstancesPos = classInstancesPos;
                mat.classInstancesNeg = classInstancesNeg;
                mat.opPos = opPos;
                mat.dpPos = dpPos;
                mat.bdPos = bdPos;
                mat.bdNeg = bdNeg;
                mat.dd = dd;
                mat.id = id;
                mat.sd = sd;
                try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(cacheFile))) {
                    oos.writeObject(mat);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            materialize();
        }
    }

    private void materialize() {
        long dematStartTime = System.currentTimeMillis();

        logger.debug("materialising concepts");
        for (OWLClass atomicConcept : atomicConcepts) {
            if (!atomicConcept.getIRI().isReservedVocabulary()) {
                SortedSet<OWLIndividual> pos = rc.getIndividuals(atomicConcept);
                classInstancesPos.put(atomicConcept, (TreeSet<OWLIndividual>) pos);

                if (isDefaultNegation()) {
                    classInstancesNeg.put(atomicConcept,
                            (TreeSet<OWLIndividual>) Helper.difference(individuals, pos));
                } else {
                    // Pellet needs approximately infinite time to answer
                    // negated queries
                    // on the carcinogenesis data set (and probably others), so
                    // we have to
                    // be careful here
                    OWLObjectComplementOf negatedAtomicConcept = df.getOWLObjectComplementOf(atomicConcept);
                    classInstancesNeg.put(atomicConcept,
                            (TreeSet<OWLIndividual>) rc.getIndividuals(negatedAtomicConcept));
                }
            } else {
                System.err.println(atomicConcept);
            }
        }

        logger.debug("materialising object properties");

        for (OWLObjectProperty atomicRole : atomicRoles) {
            //         System.out.println(atomicRole + " " + rc.getPropertyMembers(atomicRole));
            opPos.put(atomicRole, rc.getPropertyMembers(atomicRole));
        }

        logger.debug("materialising datatype properties");

        for (OWLDataProperty atomicRole : datatypeProperties) {
            dpPos.put(atomicRole, rc.getDatatypeMembers(atomicRole));
        }

        for (OWLDataProperty dp : booleanDatatypeProperties) {
            bdPos.put(dp, (TreeSet<OWLIndividual>) rc.getTrueDatatypeMembers(dp));
            bdNeg.put(dp, (TreeSet<OWLIndividual>) rc.getFalseDatatypeMembers(dp));
        }

        for (OWLDataProperty dp : intDatatypeProperties) {
            id.put(dp, rc.getIntDatatypeMembers(dp));
        }

        for (OWLDataProperty dp : doubleDatatypeProperties) {
            dd.put(dp, rc.getDoubleDatatypeMembers(dp));
        }

        for (OWLDataProperty dp : stringDatatypeProperties) {
            sd.put(dp, rc.getStringDatatypeMembers(dp));
        }

        if (materializeExistentialRestrictions) {
            ExistentialRestrictionMaterialization materialization = new ExistentialRestrictionMaterialization(
                    rc.getReasoner().getRootOntology());
            for (OWLClass cls : atomicConcepts) {
                TreeSet<OWLIndividual> individuals = classInstancesPos.get(cls);
                Set<OWLClassExpression> superClass = materialization.materialize(cls.toStringID());
                for (OWLClassExpression sup : superClass) {
                    fill(individuals, sup);
                }
            }
        }

        //materialize facts based on OWL punning, i.e.:
        //for each A in N_C
        if (handlePunning && OWLPunningDetector.hasPunning(rc.getReasoner().getRootOntology())) {
            OWLOntology ontology = rc.getReasoner().getRootOntology();

            OWLIndividual genericIndividual = df
                    .getOWLNamedIndividual(IRI.create("http://dl-learner.org/punning#genInd"));
            Map<OWLIndividual, SortedSet<OWLIndividual>> map = new HashMap<OWLIndividual, SortedSet<OWLIndividual>>();
            for (OWLIndividual individual : individuals) {
                SortedSet<OWLIndividual> objects = new TreeSet<OWLIndividual>();
                objects.add(genericIndividual);
                map.put(individual, objects);
            }
            for (OWLClass cls : atomicConcepts) {
                classInstancesNeg.get(cls).add(genericIndividual);
                if (OWLPunningDetector.hasPunning(ontology, cls)) {
                    OWLIndividual clsAsInd = df.getOWLNamedIndividual(IRI.create(cls.toStringID()));
                    //for each x \in N_I with A(x) we add relatedTo(x,A)
                    SortedSet<OWLIndividual> individuals = classInstancesPos.get(cls);
                    for (OWLIndividual individual : individuals) {
                        SortedSet<OWLIndividual> objects = map.get(individual);
                        if (objects == null) {
                            objects = new TreeSet<OWLIndividual>();
                            map.put(individual, objects);
                        }
                        objects.add(clsAsInd);

                    }
                }
            }
            opPos.put(OWLPunningDetector.punningProperty, map);
            atomicRoles = new TreeSet<OWLObjectProperty>(atomicRoles);
            atomicRoles.add(OWLPunningDetector.punningProperty);
            atomicRoles = Collections.unmodifiableSet(atomicRoles);
            //               individuals.add(genericIndividual);
        }

        long dematDuration = System.currentTimeMillis() - dematStartTime;
        logger.debug("TBox materialised in " + dematDuration + " ms");
    }

    private void fill(SortedSet<OWLIndividual> individuals, OWLClassExpression d) {
        if (!d.isAnonymous()) {
            classInstancesPos.get(d).addAll(individuals);
        } else if (d instanceof OWLObjectIntersectionOf) {
            Set<OWLClassExpression> operands = ((OWLObjectIntersectionOf) d).getOperands();
            for (OWLClassExpression operand : operands) {
                fill(individuals, operand);
            }
        } else if (d instanceof OWLObjectSomeValuesFrom) {
            OWLObjectProperty role = ((OWLObjectSomeValuesFrom) d).getProperty().asOWLObjectProperty();
            OWLClassExpression filler = ((OWLObjectSomeValuesFrom) d).getFiller();
            Map<OWLIndividual, SortedSet<OWLIndividual>> map = opPos.get(role);
            //create new individual as object value for each individual
            SortedSet<OWLIndividual> newIndividuals = new TreeSet<OWLIndividual>();
            int i = 0;
            for (OWLIndividual individual : individuals) {
                OWLIndividual newIndividual = df
                        .getOWLNamedIndividual(IRI.create("http://dllearner.org#genInd_" + i++));
                newIndividuals.add(newIndividual);
                SortedSet<OWLIndividual> values = map.get(individual);
                if (values == null) {
                    values = new TreeSet<OWLIndividual>();
                    map.put(individual, values);
                }
                values.add(newIndividual);
            }
            fill(newIndividuals, filler);

        } else {
            throw new UnsupportedOperationException("Should not happen.");
        }
    }

    @Override
    public boolean hasTypeImpl(OWLClassExpression description, OWLIndividual individual)
            throws ReasoningMethodUnsupportedException {

        if (description.isOWLThing()) {
            return true;
        } else if (description.isOWLNothing()) {
            return false;
        } else if (!description.isAnonymous()) {
            return classInstancesPos.get(description).contains(individual);
        } else if (description instanceof OWLObjectComplementOf) {
            OWLClassExpression operand = ((OWLObjectComplementOf) description).getOperand();
            if (!operand.isAnonymous()) {
                return classInstancesNeg.get(operand).contains(individual);
            } else {
                if (isDefaultNegation()) {
                    return !hasTypeImpl(operand, individual);
                } else {
                    logger.debug(
                            "Converting OWLClassExpression to negation normal form in fast instance check (should be avoided if possible).");
                    return hasTypeImpl(description.getNNF(), individual);
                }
            }
        } else if (description instanceof OWLObjectUnionOf) {
            for (OWLClassExpression operand : ((OWLObjectUnionOf) description).getOperands()) {
                if (hasTypeImpl(operand, individual)) {
                    return true;
                }
            }
            return false;
        } else if (description instanceof OWLObjectIntersectionOf) {
            for (OWLClassExpression operand : ((OWLObjectIntersectionOf) description).getOperands()) {
                if (!hasTypeImpl(operand, individual)) {
                    return false;
                }
            }
            return true;
        } else if (description instanceof OWLObjectSomeValuesFrom) {
            OWLObjectPropertyExpression property = ((OWLObjectSomeValuesFrom) description).getProperty();
            OWLClassExpression fillerConcept = ((OWLObjectSomeValuesFrom) description).getFiller();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            if (handlePunning && property == OWLPunningDetector.punningProperty && fillerConcept.isOWLThing()) {
                return true;
            }

            SortedSet<OWLIndividual> roleFillers = opPos.get(property.asOWLObjectProperty()).get(individual);

            if (roleFillers == null) {
                return false;
            }

            for (OWLIndividual roleFiller : roleFillers) {
                if (hasTypeImpl(fillerConcept, roleFiller)) {
                    return true;
                }
            }

            return false;
        } else if (description instanceof OWLObjectAllValuesFrom) {
            OWLObjectPropertyExpression property = ((OWLObjectAllValuesFrom) description).getProperty();
            OWLClassExpression fillerConcept = ((OWLObjectAllValuesFrom) description).getFiller();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property);

            SortedSet<OWLIndividual> roleFillers = mapping.get(individual);

            if (roleFillers == null) {
                return forallSemantics == ForallSemantics.Standard;
            }
            boolean hasCorrectFiller = false;
            for (OWLIndividual roleFiller : roleFillers) {
                if (hasTypeImpl(fillerConcept, roleFiller)) {
                    hasCorrectFiller = true;
                } else {
                    return false;
                }
            }

            if (forallSemantics == ForallSemantics.SomeOnly) {
                return hasCorrectFiller;
            } else {
                return true;
            }
        } else if (description instanceof OWLObjectMinCardinality) {
            OWLObjectPropertyExpression property = ((OWLObjectMinCardinality) description).getProperty();
            OWLClassExpression fillerConcept = ((OWLObjectMinCardinality) description).getFiller();
            int cardinality = ((OWLObjectMinCardinality) description).getCardinality();

            // special case: there are always at least zero fillers
            if (cardinality == 0) {
                return true;
            }

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property);

            int nrOfFillers = 0;

            SortedSet<OWLIndividual> roleFillers = mapping.get(individual);

            // return false if there are none or not enough role fillers
            if (roleFillers == null
                    || (roleFillers.size() < cardinality && property != OWLPunningDetector.punningProperty)) {
                return false;
            }

            int index = 0;
            for (OWLIndividual roleFiller : roleFillers) {
                index++;
                if (hasTypeImpl(fillerConcept, roleFiller)) {
                    nrOfFillers++;
                    if (nrOfFillers == cardinality
                            || (handlePunning && property == OWLPunningDetector.punningProperty)) {
                        return true;
                    }
                    // early abort: e.g. >= 10 hasStructure.Methyl;
                    // if there are 11 fillers and 2 are not Methyl, the result
                    // is false
                } else {
                    if (roleFillers.size() - index < cardinality) {
                        return false;
                    }
                }
            }
            return false;
        } else if (description instanceof OWLObjectMaxCardinality) {
            OWLObjectPropertyExpression property = ((OWLObjectMaxCardinality) description).getProperty();
            OWLClassExpression fillerConcept = ((OWLObjectMaxCardinality) description).getFiller();
            int cardinality = ((OWLObjectMaxCardinality) description).getCardinality();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property);

            int nrOfFillers = 0;

            SortedSet<OWLIndividual> roleFillers = mapping.get(individual);

            // return true if there are none or not enough role fillers
            if (roleFillers == null || roleFillers.size() < cardinality) {
                return true;
            }

            int index = 0;
            for (OWLIndividual roleFiller : roleFillers) {
                index++;
                if (hasTypeImpl(fillerConcept, roleFiller)) {
                    nrOfFillers++;
                    if (nrOfFillers > cardinality) {
                        return false;
                    }
                    // early abort: e.g. <= 5 hasStructure.Methyl;
                    // if there are 6 fillers and 2 are not Methyl, the result
                    // is true
                } else {
                    if (roleFillers.size() - index <= cardinality) {
                        return true;
                    }
                }
            }
            return true;
        } else if (description instanceof OWLObjectHasValue) {
            OWLObjectPropertyExpression property = ((OWLObjectHasValue) description).getProperty();
            OWLIndividual value = ((OWLObjectHasValue) description).getValue();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property.asOWLObjectProperty());

            SortedSet<OWLIndividual> values = mapping.get(individual);

            return values != null && values.contains(value);
        }
        //      else if (OWLClassExpression instanceof BooleanValueRestriction) {
        //         DatatypeProperty dp = ((BooleanValueRestriction) description)
        //               .getRestrictedPropertyExpression();
        //         boolean value = ((BooleanValueRestriction) description).getBooleanValue();
        //
        //         if (value) {
        //            // check whether the OWLIndividual is in the set of individuals
        //            // mapped
        //            // to true by this datatype property
        //            return bdPos.get(dp).contains(individual);
        //         } else {
        //            return bdNeg.get(dp).contains(individual);
        //         }
        //      } 
        else if (description instanceof OWLDataSomeValuesFrom) {
            OWLDataPropertyExpression property = ((OWLDataSomeValuesFrom) description).getProperty();
            OWLDataRange filler = ((OWLDataSomeValuesFrom) description).getFiller();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            if (filler.isDatatype()) {
                return dpPos.get(property).containsKey(individual);
            } else if (filler instanceof OWLDatatypeRestriction) {
                OWLDatatype datatype = ((OWLDatatypeRestriction) filler).getDatatype();
                Set<OWLFacetRestriction> facetRestrictions = ((OWLDatatypeRestriction) filler)
                        .getFacetRestrictions();

                if (datatype.isDouble()) {
                    SortedSet<Double> values = dd.get(property).get(individual);

                    if (values == null) {
                        return false;
                    }

                    double min = -Double.MAX_VALUE;
                    double max = Double.MAX_VALUE;
                    for (OWLFacetRestriction facet : facetRestrictions) {
                        if (facet.getFacet() == OWLFacet.MIN_INCLUSIVE) {
                            min = facet.getFacetValue().parseDouble();
                        } else if (facet.getFacet() == OWLFacet.MAX_INCLUSIVE) {
                            max = facet.getFacetValue().parseDouble();
                        }
                    }

                    //we can return false if largest number is below minimum or lowest number is above maximum
                    if (values.last() < min || values.first() > max) {
                        return false;
                    }

                    //search a value which is in the interval
                    for (Double value : values) {
                        if (value >= min && value <= max) {
                            return true;
                        }
                    }
                } else if (datatype.isInteger()) {
                    SortedSet<Integer> values = id.get(property).get(individual);

                    int min = Integer.MIN_VALUE;
                    int max = Integer.MAX_VALUE;
                    for (OWLFacetRestriction facet : facetRestrictions) {
                        if (facet.getFacet() == OWLFacet.MIN_INCLUSIVE) {
                            min = facet.getFacetValue().parseInteger();
                        } else if (facet.getFacet() == OWLFacet.MAX_INCLUSIVE) {
                            max = facet.getFacetValue().parseInteger();
                        }
                    }

                    //we can return false if largest number is below minimum or lowest number is above maximum
                    if (values.last() < min || values.first() > max) {
                        return false;
                    }

                    //search a value which is in the interval
                    for (Integer value : values) {
                        if (value >= min && value <= max) {
                            return true;
                        }
                    }
                }
            }
        } else if (description instanceof OWLDataHasValue) {
            OWLDataPropertyExpression property = ((OWLDataHasValue) description).getProperty();
            OWLLiteral value = ((OWLDataHasValue) description).getValue();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = dpPos.get(property);

            SortedSet<OWLLiteral> values = mapping.get(individual);

            return values != null && values.contains(value);
        }

        throw new ReasoningMethodUnsupportedException(
                "Instance check for OWLClassExpression " + description + " unsupported.");
    }

    @Override
    public SortedSet<OWLIndividual> getIndividualsImpl(OWLClassExpression concept)
            throws ReasoningMethodUnsupportedException {
        return getIndividualsImplFast(concept);
    }

    public SortedSet<OWLIndividual> getIndividualsImplStandard(OWLClassExpression concept)
            throws ReasoningMethodUnsupportedException {
        if (!concept.isAnonymous()) {
            return classInstancesPos.get((OWLClass) concept);
        } else if (concept instanceof OWLObjectComplementOf) {
            OWLClassExpression operand = ((OWLObjectComplementOf) concept).getOperand();
            if (!operand.isAnonymous()) {
                return classInstancesNeg.get(operand);
            }
        }

        // return rs.retrieval(concept);
        SortedSet<OWLIndividual> inds = new TreeSet<OWLIndividual>();
        for (OWLIndividual i : individuals) {
            if (hasType(concept, i)) {
                inds.add(i);
            }
        }
        return inds;
    }

    @SuppressWarnings("unchecked")
    public SortedSet<OWLIndividual> getIndividualsImplFast(OWLClassExpression description)
            throws ReasoningMethodUnsupportedException {
        // policy: returned sets are clones, i.e. can be modified
        // (of course we only have to clone the leafs of a class OWLClassExpression tree)
        if (description.isOWLThing()) {
            return (TreeSet<OWLIndividual>) individuals.clone();
        } else if (description.isOWLNothing()) {
            return new TreeSet<OWLIndividual>();
        } else if (!description.isAnonymous()) {
            if (classInstancesPos.containsKey(description.asOWLClass())) {
                return (TreeSet<OWLIndividual>) classInstancesPos.get(description).clone();
            } else {
                return new TreeSet<OWLIndividual>();
            }
        } else if (description instanceof OWLObjectComplementOf) {
            OWLClassExpression operand = ((OWLObjectComplementOf) description).getOperand();
            if (!operand.isAnonymous()) {
                return (TreeSet<OWLIndividual>) classInstancesNeg.get(operand).clone();
            }
            // implement retrieval as default negation
            return Helper.difference((TreeSet<OWLIndividual>) individuals.clone(), getIndividualsImpl(operand));
        } else if (description instanceof OWLObjectUnionOf) {
            SortedSet<OWLIndividual> ret = new TreeSet<OWLIndividual>();
            for (OWLClassExpression operand : ((OWLObjectUnionOf) description).getOperands()) {
                ret.addAll(getIndividualsImpl(operand));
            }
            return ret;
        } else if (description instanceof OWLObjectIntersectionOf) {
            Iterator<OWLClassExpression> iterator = ((OWLObjectIntersectionOf) description).getOperands()
                    .iterator();
            // copy instances of first element and then subtract all others
            SortedSet<OWLIndividual> ret = getIndividualsImpl(iterator.next());
            while (iterator.hasNext()) {
                ret.retainAll(getIndividualsImpl(iterator.next()));
            }
            return ret;
        } else if (description instanceof OWLObjectSomeValuesFrom) {
            SortedSet<OWLIndividual> returnSet = new TreeSet<OWLIndividual>();

            OWLObjectPropertyExpression property = ((OWLObjectSomeValuesFrom) description).getProperty();
            OWLClassExpression filler = ((OWLObjectSomeValuesFrom) description).getFiller();

            //get instances of filler concept
            SortedSet<OWLIndividual> targetSet = getIndividualsImpl(filler);

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }
            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property.asOWLObjectProperty());

            // each individual is connected to a set of individuals via the property;
            // we loop through the complete mapping
            for (Entry<OWLIndividual, SortedSet<OWLIndividual>> entry : mapping.entrySet()) {
                SortedSet<OWLIndividual> inds = entry.getValue();
                for (OWLIndividual ind : inds) {
                    if (targetSet.contains(ind)) {
                        returnSet.add(entry.getKey());
                        // once we found an individual, we do not need to check the others
                        break;
                    }
                }
            }
            return returnSet;
        } else if (description instanceof OWLObjectAllValuesFrom) {
            // \forall restrictions are difficult to handle; assume we want to check
            // \forall hasChild.male with domain(hasChild)=Person; then for all non-persons
            // this is satisfied trivially (all of their non-existing children are male)
            //         if(!configurator.getForallRetrievalSemantics().equals("standard")) {
            //            throw new Error("Only forallExists semantics currently implemented.");
            //         }

            // problem: we need to make sure that \neg \exists r.\top \equiv \forall r.\bot
            // can still be reached in an algorithm (\forall r.\bot \equiv \bot under forallExists
            // semantics)

            OWLObjectPropertyExpression property = ((OWLObjectAllValuesFrom) description).getProperty();
            OWLClassExpression filler = ((OWLObjectAllValuesFrom) description).getFiller();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            //get instances of filler concept
            SortedSet<OWLIndividual> targetSet = getIndividualsImpl(filler);

            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property.asOWLObjectProperty());
            //         SortedSet<OWLIndividual> returnSet = new TreeSet<OWLIndividual>(mapping.keySet());
            SortedSet<OWLIndividual> returnSet = (SortedSet<OWLIndividual>) individuals.clone();

            // each individual is connected to a set of individuals via the property;
            // we loop through the complete mapping
            for (Entry<OWLIndividual, SortedSet<OWLIndividual>> entry : mapping.entrySet()) {
                SortedSet<OWLIndividual> inds = entry.getValue();
                for (OWLIndividual ind : inds) {
                    if (!targetSet.contains(ind)) {
                        returnSet.remove(entry.getKey());
                        break;
                    }
                }
            }
            return returnSet;
        } else if (description instanceof OWLObjectMinCardinality) {
            OWLObjectPropertyExpression property = ((OWLObjectMinCardinality) description).getProperty();
            OWLClassExpression filler = ((OWLObjectMinCardinality) description).getFiller();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            //get instances of filler concept
            SortedSet<OWLIndividual> targetSet = getIndividualsImpl(filler);

            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property.asOWLObjectProperty());

            SortedSet<OWLIndividual> returnSet = new TreeSet<OWLIndividual>();

            int number = ((OWLObjectMinCardinality) description).getCardinality();

            for (Entry<OWLIndividual, SortedSet<OWLIndividual>> entry : mapping.entrySet()) {
                int nrOfFillers = 0;
                int index = 0;
                SortedSet<OWLIndividual> inds = entry.getValue();

                // we do not need to run tests if there are not sufficiently many fillers
                if (inds.size() < number) {
                    continue;
                }

                for (OWLIndividual ind : inds) {
                    // stop inner loop when nr of fillers is reached
                    if (nrOfFillers >= number) {
                        returnSet.add(entry.getKey());
                        break;
                    }
                    // early abort when too many instance checks failed
                    if (inds.size() - index < number) {
                        break;
                    }
                    if (targetSet.contains(ind)) {
                        nrOfFillers++;
                    }
                    index++;
                }
            }

            return returnSet;
        } else if (description instanceof OWLObjectMaxCardinality) {
            OWLObjectPropertyExpression property = ((OWLObjectMaxCardinality) description).getProperty();
            OWLClassExpression filler = ((OWLObjectMaxCardinality) description).getFiller();
            int number = ((OWLObjectMaxCardinality) description).getCardinality();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            //get instances of filler concept
            SortedSet<OWLIndividual> targetSet = getIndividualsImpl(filler);

            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property.asOWLObjectProperty());

            // initially all individuals are in the return set and we then remove those
            // with too many fillers         
            SortedSet<OWLIndividual> returnSet = (SortedSet<OWLIndividual>) individuals.clone();

            for (Entry<OWLIndividual, SortedSet<OWLIndividual>> entry : mapping.entrySet()) {
                int nrOfFillers = 0;
                int index = 0;
                SortedSet<OWLIndividual> inds = entry.getValue();

                // we do not need to run tests if there are not sufficiently many fillers
                if (number < inds.size()) {
                    returnSet.add(entry.getKey());
                    continue;
                }

                for (OWLIndividual ind : inds) {
                    // stop inner loop when nr of fillers is reached
                    if (nrOfFillers >= number) {
                        break;
                    }
                    // early abort when too many instance are true already
                    if (inds.size() - index < number) {
                        returnSet.add(entry.getKey());
                        break;
                    }
                    if (targetSet.contains(ind)) {
                        nrOfFillers++;
                    }
                    index++;
                }
            }

            return returnSet;
        } else if (description instanceof OWLObjectHasValue) {
            OWLObjectPropertyExpression property = ((OWLObjectHasValue) description).getProperty();
            OWLIndividual value = ((OWLObjectHasValue) description).getValue();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            Map<OWLIndividual, SortedSet<OWLIndividual>> mapping = opPos.get(property.asOWLObjectProperty());

            SortedSet<OWLIndividual> returnSet = new TreeSet<OWLIndividual>();

            for (Entry<OWLIndividual, SortedSet<OWLIndividual>> entry : mapping.entrySet()) {
                if (entry.getValue().contains(value)) {
                    returnSet.add(entry.getKey());
                }
            }
            return returnSet;
        }
        //      else if (description instanceof BooleanValueRestriction) {
        //         DatatypeProperty dp = ((BooleanValueRestriction) description)
        //               .getRestrictedPropertyExpression();
        //         boolean value = ((BooleanValueRestriction) description).getBooleanValue();
        //
        //         if (value) {
        //            return (TreeSet<OWLIndividual>) bdPos.get(dp).clone();
        //         } else {
        //            return (TreeSet<OWLIndividual>) bdNeg.get(dp).clone();
        //         }
        //      } 
        else if (description instanceof OWLDataSomeValuesFrom) {
            OWLDataPropertyExpression property = ((OWLDataSomeValuesFrom) description).getProperty();
            OWLDataRange filler = ((OWLDataSomeValuesFrom) description).getFiller();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            if (filler.isDatatype()) {
                //we assume that the values are of the given datatype
                return new TreeSet<OWLIndividual>(dpPos.get(property).keySet());
                //            OWLDatatype dt = filler.asOWLDatatype();
                //            if(dt.isDouble()){
                //               return new TreeSet<OWLIndividual>(dd.get(property).keySet());
                //            } else if(dt.isInteger()){
                //               return new TreeSet<OWLIndividual>(id.get(property).keySet());
                //            } else if(dt.isBoolean()){
                //               return bdPos.get(property);
                //            }
            } else if (filler instanceof OWLDatatypeRestriction) {
                OWLDatatype datatype = ((OWLDatatypeRestriction) filler).getDatatype();
                Set<OWLFacetRestriction> facetRestrictions = ((OWLDatatypeRestriction) filler)
                        .getFacetRestrictions();

                if (datatype.isDouble()) {
                    double min = -Double.MAX_VALUE;
                    double max = Double.MAX_VALUE;
                    for (OWLFacetRestriction facet : facetRestrictions) {
                        if (facet.getFacet() == OWLFacet.MIN_INCLUSIVE) {
                            min = facet.getFacetValue().parseDouble();
                        } else if (facet.getFacet() == OWLFacet.MAX_INCLUSIVE) {
                            max = facet.getFacetValue().parseDouble();
                        }
                    }
                    Map<OWLIndividual, SortedSet<Double>> mapping = dd.get(property);
                    SortedSet<OWLIndividual> returnSet = new TreeSet<OWLIndividual>();

                    for (Entry<OWLIndividual, SortedSet<Double>> entry : mapping.entrySet()) {
                        //we can skip of largest number is below minimum or lowest number is above maximum
                        if (entry.getValue().last() < min || entry.getValue().first() > max) {
                            continue;
                        }

                        //search a value which is in the interval
                        for (Double value : entry.getValue()) {
                            if (value >= min && value <= max) {
                                returnSet.add(entry.getKey());
                                break;
                            }
                        }
                    }
                    return returnSet;
                }
            }
        } else if (description instanceof OWLDataHasValue) {
            OWLDataPropertyExpression property = ((OWLDataHasValue) description).getProperty();
            OWLLiteral value = ((OWLDataHasValue) description).getValue();

            if (property.isAnonymous()) {
                throw new ReasoningMethodUnsupportedException("Retrieval for OWLClassExpression " + description
                        + " unsupported. Inverse object properties not supported.");
            }

            SortedSet<OWLIndividual> returnSet = new TreeSet<OWLIndividual>();

            Map<OWLIndividual, SortedSet<OWLLiteral>> mapping = dpPos.get(property);

            for (Entry<OWLIndividual, SortedSet<OWLLiteral>> entry : mapping.entrySet()) {
                if (entry.getValue().contains(value)) {
                    returnSet.add(entry.getKey());
                }
            }

            return returnSet;
        }

        throw new ReasoningMethodUnsupportedException(
                "Retrieval for OWLClassExpression " + description + " unsupported.");

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dllearner.core.Reasoner#getAtomicConcepts()
     */
    @Override
    public Set<OWLClass> getClasses() {
        return atomicConcepts;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dllearner.core.Reasoner#getAtomicRoles()
     */
    @Override
    public Set<OWLObjectProperty> getObjectPropertiesImpl() {
        return atomicRoles;
    }

    @Override
    public Set<OWLDataProperty> getDatatypePropertiesImpl() {
        return datatypeProperties;
    }

    @Override
    public Set<OWLDataProperty> getBooleanDatatypePropertiesImpl() {
        return booleanDatatypeProperties;
    }

    @Override
    public Set<OWLDataProperty> getDoubleDatatypePropertiesImpl() {
        return doubleDatatypeProperties;
    }

    @Override
    public Set<OWLDataProperty> getIntDatatypePropertiesImpl() {
        return intDatatypeProperties;
    }

    @Override
    public Set<OWLDataProperty> getStringDatatypePropertiesImpl() {
        return stringDatatypeProperties;
    }

    @Override
    protected SortedSet<OWLClassExpression> getSuperClassesImpl(OWLClassExpression concept)
            throws ReasoningMethodUnsupportedException {
        return rc.getSuperClassesImpl(concept);
    }

    @Override
    protected SortedSet<OWLClassExpression> getSubClassesImpl(OWLClassExpression concept)
            throws ReasoningMethodUnsupportedException {
        return rc.getSubClassesImpl(concept);
    }

    @Override
    protected SortedSet<OWLObjectProperty> getSuperPropertiesImpl(OWLObjectProperty role)
            throws ReasoningMethodUnsupportedException {
        return rc.getSuperPropertiesImpl(role);
    }

    @Override
    protected SortedSet<OWLObjectProperty> getSubPropertiesImpl(OWLObjectProperty role)
            throws ReasoningMethodUnsupportedException {
        return rc.getSubPropertiesImpl(role);
    }

    @Override
    protected SortedSet<OWLDataProperty> getSuperPropertiesImpl(OWLDataProperty role)
            throws ReasoningMethodUnsupportedException {
        return rc.getSuperPropertiesImpl(role);
    }

    @Override
    protected SortedSet<OWLDataProperty> getSubPropertiesImpl(OWLDataProperty role)
            throws ReasoningMethodUnsupportedException {
        return rc.getSubPropertiesImpl(role);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dllearner.core.Reasoner#getIndividuals()
     */
    @Override
    public SortedSet<OWLIndividual> getIndividuals() {
        return individuals;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dllearner.core.Reasoner#getReasonerType()
     */
    @Override
    public ReasonerType getReasonerType() {
        return ReasonerType.FAST_INSTANCE_CHECKER;
    }

    //   @Override
    //   public ClassHierarchy getClassHierarchy() {
    //      return rc.getClassHierarchy();
    //   }

    //   @Override
    //   public void prepareRoleHierarchyImpl(Set<OWLObjectProperty> allowedRoles) {
    //      rc.prepareRoleHierarchy(allowedRoles);
    //   }

    //   @Override
    //   public ObjectPropertyHierarchy getRoleHierarchy() {
    //      return rc.getRoleHierarchy();
    //   }

    //   @Override
    //   public void prepareDatatypePropertyHierarchyImpl(Set<OWLDataProperty> allowedRoles) {
    //      rc.prepareDatatypePropertyHierarchyImpl(allowedRoles);
    //   }

    //   @Override
    //   public DatatypePropertyHierarchy getDatatypePropertyHierarchy() {
    //      return rc.getDatatypePropertyHierarchy();
    //   }

    @Override
    public boolean isSuperClassOfImpl(OWLClassExpression superConcept, OWLClassExpression subConcept) {
        // Negation neg = new Negation(subConcept);
        // Intersection c = new Intersection(neg,superConcept);
        // return fastRetrieval.calculateSets(c).getPosSet().isEmpty();
        return rc.isSuperClassOfImpl(superConcept, subConcept);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dllearner.core.Reasoner#getBaseURI()
     */
    @Override
    public String getBaseURI() {
        return rc.getBaseURI();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dllearner.core.Reasoner#getPrefixes()
     */
    @Override
    public Map<String, String> getPrefixes() {
        return rc.getPrefixes();
    }

    public void setPrefixes(Map<String, String> prefixes) {
        rc.setPrefixes(prefixes);
    }

    /**
     * @param baseURI the baseURI to set
     */
    public void setBaseURI(String baseURI) {
        rc.setBaseURI(baseURI);
    }

    @Override
    public OWLClassExpression getDomainImpl(OWLObjectProperty objectProperty) {
        return rc.getDomain(objectProperty);
    }

    @Override
    public OWLClassExpression getDomainImpl(OWLDataProperty datatypeProperty) {
        return rc.getDomain(datatypeProperty);
    }

    @Override
    public OWLClassExpression getRangeImpl(OWLObjectProperty objectProperty) {
        return rc.getRange(objectProperty);
    }

    @Override
    public OWLDataRange getRangeImpl(OWLDataProperty datatypeProperty) {
        return rc.getRange(datatypeProperty);
    }

    @Override
    public Map<OWLIndividual, SortedSet<OWLIndividual>> getPropertyMembersImpl(OWLObjectProperty atomicRole) {
        return opPos.get(atomicRole);
    }

    @Override
    public final SortedSet<OWLIndividual> getTrueDatatypeMembersImpl(OWLDataProperty datatypeProperty) {
        return bdPos.get(datatypeProperty);
    }

    @Override
    public final SortedSet<OWLIndividual> getFalseDatatypeMembersImpl(OWLDataProperty datatypeProperty) {
        return bdNeg.get(datatypeProperty);
    }

    @Override
    public Map<OWLIndividual, SortedSet<Integer>> getIntDatatypeMembersImpl(OWLDataProperty datatypeProperty) {
        return id.get(datatypeProperty);
    }

    @Override
    public Map<OWLIndividual, SortedSet<Double>> getDoubleDatatypeMembersImpl(OWLDataProperty datatypeProperty) {
        return dd.get(datatypeProperty);
    }

    @Override
    public Map<OWLIndividual, SortedSet<OWLLiteral>> getDatatypeMembersImpl(OWLDataProperty datatypeProperty) {
        return dpPos.get(datatypeProperty);
        //      return rc.getDatatypeMembersImpl(OWLDataProperty);
    }

    @Override
    public Set<OWLIndividual> getRelatedIndividualsImpl(OWLIndividual individual, OWLObjectProperty objectProperty)
            throws ReasoningMethodUnsupportedException {
        return rc.getRelatedIndividuals(individual, objectProperty);
    }

    @Override
    protected Map<OWLObjectProperty, Set<OWLIndividual>> getObjectPropertyRelationshipsImpl(
            OWLIndividual individual) {
        return rc.getObjectPropertyRelationships(individual);
    }

    @Override
    public Set<OWLLiteral> getRelatedValuesImpl(OWLIndividual individual, OWLDataProperty datatypeProperty)
            throws ReasoningMethodUnsupportedException {
        return rc.getRelatedValues(individual, datatypeProperty);
    }

    @Override
    public boolean isSatisfiableImpl() {
        return rc.isSatisfiable();
    }

    @Override
    public Set<OWLLiteral> getLabelImpl(OWLEntity entity) throws ReasoningMethodUnsupportedException {
        return rc.getLabel(entity);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dllearner.core.ReasonerComponent#releaseKB()
     */
    @Override
    public void releaseKB() {
        rc.releaseKB();
    }

    //   @Override
    //   public boolean hasDatatypeSupport() {
    //      return true;
    //   }

    /* (non-Javadoc)
     * @see org.dllearner.core.ReasonerComponent#getTypesImpl(org.dllearner.core.owl.Individual)
     */
    @Override
    protected Set<OWLClass> getTypesImpl(OWLIndividual individual) {
        return rc.getTypesImpl(individual);
    }

    /* (non-Javadoc)
     * @see org.dllearner.core.BaseReasoner#remainsSatisfiable(org.dllearner.core.owl.Axiom)
     */
    @Override
    public boolean remainsSatisfiableImpl(OWLAxiom axiom) {
        return rc.remainsSatisfiableImpl(axiom);
    }

    @Override
    protected Set<OWLClassExpression> getAssertedDefinitionsImpl(OWLClass nc) {
        return rc.getAssertedDefinitionsImpl(nc);
    }

    public OWLAPIReasoner getReasonerComponent() {
        return rc;
    }

    @Autowired(required = false)
    public void setReasonerComponent(OWLAPIReasoner rc) {
        this.rc = rc;
    }

    public boolean isDefaultNegation() {
        return defaultNegation;
    }

    public void setDefaultNegation(boolean defaultNegation) {
        this.defaultNegation = defaultNegation;
    }

    public ForallSemantics getForAllSemantics() {
        return forallSemantics;
    }

    public void setForAllSemantics(ForallSemantics forallSemantics) {
        this.forallSemantics = forallSemantics;
    }

    /**
     * @param useCaching the useCaching to set
     */
    public void setUseMaterializationCaching(boolean useCaching) {
        this.useCaching = useCaching;
    }

    /**
     * @param handlePunning the handlePunning to set
     */
    public void setHandlePunning(boolean handlePunning) {
        this.handlePunning = handlePunning;
    }

}