Java tutorial
/** * 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.List; 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.core.owl.Axiom; import org.dllearner.core.owl.BooleanValueRestriction; import org.dllearner.core.owl.Constant; import org.dllearner.core.owl.DataRange; import org.dllearner.core.owl.DatatypeProperty; import org.dllearner.core.owl.DatatypeSomeRestriction; import org.dllearner.core.owl.DatatypeValueRestriction; import org.dllearner.core.owl.Description; import org.dllearner.core.owl.DoubleMaxValue; import org.dllearner.core.owl.DoubleMinValue; import org.dllearner.core.owl.Entity; import org.dllearner.core.owl.Individual; import org.dllearner.core.owl.Intersection; import org.dllearner.core.owl.NamedClass; import org.dllearner.core.owl.Negation; import org.dllearner.core.owl.Nothing; import org.dllearner.core.owl.ObjectAllRestriction; import org.dllearner.core.owl.ObjectCardinalityRestriction; import org.dllearner.core.owl.ObjectMaxCardinalityRestriction; import org.dllearner.core.owl.ObjectMinCardinalityRestriction; import org.dllearner.core.owl.ObjectProperty; import org.dllearner.core.owl.ObjectPropertyExpression; import org.dllearner.core.owl.ObjectSomeRestriction; import org.dllearner.core.owl.ObjectValueRestriction; import org.dllearner.core.owl.Thing; import org.dllearner.core.owl.Union; import org.dllearner.utilities.Helper; import org.dllearner.utilities.owl.ConceptTransformation; import org.dllearner.utilities.owl.DLLearnerDescriptionConvertVisitor; import org.semanticweb.owlapi.model.OWLClassExpression; import org.semanticweb.owlapi.model.OWLOntology; 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 = "materializable fast instance checker", shortName = "mat-fic", version = 0.9) public class MaterializableFastInstanceChecker extends AbstractReasonerComponent { private static Logger logger = Logger.getLogger(MaterializableFastInstanceChecker.class); // private boolean defaultNegation = true; private Set<NamedClass> atomicConcepts; private Set<ObjectProperty> atomicRoles; private SortedSet<DatatypeProperty> datatypeProperties; private SortedSet<DatatypeProperty> booleanDatatypeProperties = new TreeSet<DatatypeProperty>(); private SortedSet<DatatypeProperty> doubleDatatypeProperties = new TreeSet<DatatypeProperty>(); private SortedSet<DatatypeProperty> intDatatypeProperties = new TreeSet<DatatypeProperty>(); private SortedSet<DatatypeProperty> stringDatatypeProperties = new TreeSet<DatatypeProperty>(); private TreeSet<Individual> 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<NamedClass, TreeSet<Individual>> classInstancesPos = new TreeMap<NamedClass, TreeSet<Individual>>(); private Map<NamedClass, TreeSet<Individual>> classInstancesNeg = new TreeMap<NamedClass, TreeSet<Individual>>(); // object property mappings private Map<ObjectProperty, Map<Individual, SortedSet<Individual>>> opPos = new TreeMap<ObjectProperty, Map<Individual, SortedSet<Individual>>>(); // data property mappings private Map<DatatypeProperty, Map<Individual, SortedSet<Constant>>> dpPos = new TreeMap<DatatypeProperty, Map<Individual, SortedSet<Constant>>>(); // datatype property mappings // we have one mapping for true and false for efficiency reasons private Map<DatatypeProperty, TreeSet<Individual>> bdPos = new TreeMap<DatatypeProperty, TreeSet<Individual>>(); private Map<DatatypeProperty, TreeSet<Individual>> bdNeg = new TreeMap<DatatypeProperty, TreeSet<Individual>>(); // 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<DatatypeProperty, Map<Individual, SortedSet<Double>>> dd = new TreeMap<DatatypeProperty, Map<Individual, SortedSet<Double>>>(); private Map<DatatypeProperty, Map<Individual, SortedSet<Integer>>> id = new TreeMap<DatatypeProperty, Map<Individual, SortedSet<Integer>>>(); private Map<DatatypeProperty, Map<Individual, SortedSet<String>>> sd = new TreeMap<DatatypeProperty, Map<Individual, SortedSet<String>>>(); @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; private boolean materializeExistentialRestrictions = false; private boolean useCaching = true; private boolean handlePunning = true; 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 } /** * Creates an instance of the fast instance checker. */ public MaterializableFastInstanceChecker() { } public MaterializableFastInstanceChecker(TreeSet<Individual> individuals, Map<NamedClass, TreeSet<Individual>> classInstancesPos, Map<ObjectProperty, Map<Individual, SortedSet<Individual>>> opPos, Map<DatatypeProperty, Map<Individual, SortedSet<Integer>>> id, Map<DatatypeProperty, TreeSet<Individual>> bdPos, Map<DatatypeProperty, TreeSet<Individual>> 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.getNamedClasses(); datatypeProperties = rc.getDatatypeProperties(); booleanDatatypeProperties = rc.getBooleanDatatypeProperties(); doubleDatatypeProperties = rc.getDoubleDatatypeProperties(); intDatatypeProperties = rc.getIntDatatypeProperties(); stringDatatypeProperties = rc.getStringDatatypeProperties(); atomicRoles = rc.getObjectProperties(); for (NamedClass atomicConcept : rc.getNamedClasses()) { TreeSet<Individual> pos = classInstancesPos.get(atomicConcept); if (pos != null) { classInstancesNeg.put(atomicConcept, (TreeSet<Individual>) Helper.difference(individuals, pos)); } else { classInstancesPos.put(atomicConcept, new TreeSet<Individual>()); classInstancesNeg.put(atomicConcept, individuals); } } for (ObjectProperty p : atomicRoles) { if (opPos.get(p) == null) { opPos.put(p, new HashMap<Individual, SortedSet<Individual>>()); } } for (DatatypeProperty dp : booleanDatatypeProperties) { if (bdPos.get(dp) == null) { bdPos.put(dp, new TreeSet<Individual>()); } if (bdNeg.get(dp) == null) { bdNeg.put(dp, new TreeSet<Individual>()); } } } public MaterializableFastInstanceChecker(Set<KnowledgeSource> sources) { super(sources); } public MaterializableFastInstanceChecker(KnowledgeSource... sources) { super(new HashSet<KnowledgeSource>(Arrays.asList(sources))); } /** * @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.getNamedClasses(); datatypeProperties = rc.getDatatypeProperties(); booleanDatatypeProperties = rc.getBooleanDatatypeProperties(); doubleDatatypeProperties = rc.getDoubleDatatypeProperties(); intDatatypeProperties = rc.getIntDatatypeProperties(); stringDatatypeProperties = rc.getStringDatatypeProperties(); atomicRoles = rc.getObjectProperties(); individuals = (TreeSet<Individual>) rc.getIndividuals(); loadOrDematerialize(); } 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 { dematerialize(); 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 { dematerialize(); } } private void dematerialize() { long dematStartTime = System.currentTimeMillis(); //atomic concepts logger.debug("dematerialising concepts"); for (NamedClass atomicConcept : rc.getNamedClasses()) { SortedSet<Individual> pos = rc.getIndividuals(atomicConcept); classInstancesPos.put(atomicConcept, (TreeSet<Individual>) pos); if (isDefaultNegation()) { classInstancesNeg.put(atomicConcept, (TreeSet<Individual>) 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 Negation negatedAtomicConcept = new Negation(atomicConcept); classInstancesNeg.put(atomicConcept, (TreeSet<Individual>) rc.getIndividuals(negatedAtomicConcept)); } } //atomic object properties logger.debug("dematerialising object properties"); for (ObjectProperty atomicRole : atomicRoles) { opPos.put(atomicRole, rc.getPropertyMembers(atomicRole)); } //atomic datatype properties logger.debug("dematerialising datatype properties"); for (DatatypeProperty atomicRole : datatypeProperties) { dpPos.put(atomicRole, rc.getDatatypeMembers(atomicRole)); } //boolean datatype properties for (DatatypeProperty dp : booleanDatatypeProperties) { bdPos.put(dp, (TreeSet<Individual>) rc.getTrueDatatypeMembers(dp)); bdNeg.put(dp, (TreeSet<Individual>) rc.getFalseDatatypeMembers(dp)); } //integer datatype properties for (DatatypeProperty dp : intDatatypeProperties) { id.put(dp, rc.getIntDatatypeMembers(dp)); } //double datatype properties for (DatatypeProperty dp : doubleDatatypeProperties) { dd.put(dp, rc.getDoubleDatatypeMembers(dp)); } //String datatype properties for (DatatypeProperty dp : stringDatatypeProperties) { sd.put(dp, rc.getStringDatatypeMembers(dp)); } if (materializeExistentialRestrictions) { ExistentialRestrictionMaterialization materialization = new ExistentialRestrictionMaterialization( rc.getReasoner().getRootOntology()); for (NamedClass cls : atomicConcepts) { TreeSet<Individual> individuals = classInstancesPos.get(cls); Set<OWLClassExpression> superClass = materialization.materialize(cls.getName()); for (OWLClassExpression sup : superClass) { fill(individuals, DLLearnerDescriptionConvertVisitor.getDLLearnerDescription(sup)); } } } //materialize facts based on OWL punning, i.e.: //for each A in N_C if (handlePunning) { OWLOntology ontology = rc.getReasoner().getRootOntology(); Individual genericIndividual = new Individual("http://dl-learner.org/punning#genInd"); Map<Individual, SortedSet<Individual>> map = new HashMap<Individual, SortedSet<Individual>>(); for (Individual individual : individuals) { SortedSet<Individual> objects = new TreeSet<Individual>(); objects.add(genericIndividual); map.put(individual, objects); } for (NamedClass cls : atomicConcepts) { classInstancesNeg.get(cls).add(genericIndividual); if (OWLPunningDetector.hasPunning(ontology, cls)) { Individual clsAsInd = new Individual(cls.getName()); //for each x \in N_I with A(x) we add relatedTo(x,A) SortedSet<Individual> individuals = classInstancesPos.get(cls); for (Individual individual : individuals) { SortedSet<Individual> objects = map.get(individual); if (objects == null) { objects = new TreeSet<Individual>(); map.put(individual, objects); } objects.add(clsAsInd); } } } opPos.put(OWLPunningDetector.punningProperty, map); atomicRoles = new TreeSet<ObjectProperty>(atomicRoles); atomicRoles.add(OWLPunningDetector.punningProperty); atomicRoles = Collections.unmodifiableSet(atomicRoles); // individuals.add(genericIndividual); } long dematDuration = System.currentTimeMillis() - dematStartTime; logger.debug("TBox dematerialised in " + dematDuration + " ms"); } private void fill(SortedSet<Individual> individuals, Description d) { if (d instanceof Intersection) { List<Description> children = d.getChildren(); for (Description child : children) { fill(individuals, child); } } else if (d instanceof ObjectSomeRestriction) { ObjectProperty role = (ObjectProperty) ((ObjectSomeRestriction) d).getRole(); Map<Individual, SortedSet<Individual>> map = opPos.get(role); //create new individual as object value for each individual SortedSet<Individual> newIndividuals = new TreeSet<Individual>(); int i = 0; for (Individual individual : individuals) { Individual newIndividual = new Individual("http://dllearner.org#genInd_" + i++); newIndividuals.add(newIndividual); SortedSet<Individual> values = map.get(individual); if (values == null) { values = new TreeSet<Individual>(); map.put(individual, values); } values.add(newIndividual); } fill(newIndividuals, d.getChild(0)); } else if (d instanceof NamedClass) { classInstancesPos.get(d).addAll(individuals); } else { throw new UnsupportedOperationException("Should not happen."); } } @Override public boolean hasTypeImpl(Description description, Individual individual) throws ReasoningMethodUnsupportedException { // System.out.println("FIC: " + description + " " + individual); if (description instanceof NamedClass) { if (((NamedClass) description).getURI().equals(Thing.instance.getURI())) { return true; } else if (!atomicConcepts.contains(description)) { throw new ReasoningMethodUnsupportedException( "Class " + description + " is not contained in knowledge base."); } return classInstancesPos.get((NamedClass) description).contains(individual); } else if (description instanceof Negation) { Description child = description.getChild(0); if (child instanceof NamedClass) { return classInstancesNeg.get((NamedClass) child).contains(individual); } else { // default negation if (isDefaultNegation()) { return !hasTypeImpl(child, individual); } else { logger.debug( "Converting description to negation normal form in fast instance check (should be avoided if possible)."); Description nnf = ConceptTransformation.transformToNegationNormalForm(child); return hasTypeImpl(nnf, individual); } // throw new ReasoningMethodUnsupportedException("Instance check for description " // + description // + " unsupported. Description needs to be in negation normal form."); } } else if (description instanceof Thing) { return true; } else if (description instanceof Nothing) { return false; } else if (description instanceof Union) { // if the individual is instance of any of the subdescription of // the union, we return true List<Description> children = description.getChildren(); for (Description child : children) { if (hasTypeImpl(child, individual)) { return true; } } return false; } else if (description instanceof Intersection) { // if the individual is instance of all of the subdescription of // the union, we return true List<Description> children = description.getChildren(); for (Description child : children) { if (!hasTypeImpl(child, individual)) { return false; } } return true; } else if (description instanceof ObjectSomeRestriction) { ObjectPropertyExpression ope = ((ObjectSomeRestriction) description).getRole(); if (!(ope instanceof ObjectProperty)) { throw new ReasoningMethodUnsupportedException("Instance check for description " + description + " unsupported. Inverse object properties not supported."); } ObjectProperty op = (ObjectProperty) ope; Description child = description.getChild(0); if (handlePunning && op == OWLPunningDetector.punningProperty && child.equals(new NamedClass(Thing.uri.toString()))) { return true; } Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); if (mapping == null) { logger.warn("Instance check of a description with an undefined property (" + op + ")."); return false; } SortedSet<Individual> roleFillers = mapping.get(individual); if (roleFillers == null) { return false; } for (Individual roleFiller : roleFillers) { if (hasTypeImpl(child, roleFiller)) { return true; } } return false; } else if (description instanceof ObjectAllRestriction) { ObjectPropertyExpression ope = ((ObjectAllRestriction) description).getRole(); if (!(ope instanceof ObjectProperty)) { throw new ReasoningMethodUnsupportedException("Instance check for description " + description + " unsupported. Inverse object properties not supported."); } ObjectProperty op = (ObjectProperty) ope; Description child = description.getChild(0); Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); if (mapping == null) { logger.warn("Instance check of a description with an undefinied property (" + op + ")."); return true; } SortedSet<Individual> roleFillers = opPos.get(op).get(individual); if (roleFillers == null) { if (forallSemantics == ForallSemantics.Standard) { return true; } else { return false; } } boolean hasCorrectFiller = false; for (Individual roleFiller : roleFillers) { if (hasTypeImpl(child, roleFiller)) { hasCorrectFiller = true; } else { return false; } } if (forallSemantics == ForallSemantics.SomeOnly) { return hasCorrectFiller; } else { return true; } } else if (description instanceof ObjectMinCardinalityRestriction) { ObjectPropertyExpression ope = ((ObjectCardinalityRestriction) description).getRole(); if (!(ope instanceof ObjectProperty)) { throw new ReasoningMethodUnsupportedException("Instance check for description " + description + " unsupported. Inverse object properties not supported."); } ObjectProperty op = (ObjectProperty) ope; Description child = description.getChild(0); Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); if (mapping == null) { logger.warn("Instance check of a description with an undefinied property (" + op + ")."); return true; } int number = ((ObjectCardinalityRestriction) description).getNumber(); int nrOfFillers = 0; // SortedSet<Individual> roleFillers = opPos.get(op).get(individual); SortedSet<Individual> roleFillers = mapping.get(individual); // System.out.println(roleFillers); // special case: there are always at least zero fillers if (number == 0) { return true; } // return false if there are none or not enough role fillers if (roleFillers == null || (roleFillers.size() < number && op != OWLPunningDetector.punningProperty)) { return false; } int index = 0; for (Individual roleFiller : roleFillers) { index++; if (hasTypeImpl(child, roleFiller)) { nrOfFillers++; if (nrOfFillers == number || (handlePunning && op == 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 < number) { return false; } } } return false; } else if (description instanceof ObjectMaxCardinalityRestriction) { ObjectPropertyExpression ope = ((ObjectCardinalityRestriction) description).getRole(); if (!(ope instanceof ObjectProperty)) { throw new ReasoningMethodUnsupportedException("Instance check for description " + description + " unsupported. Inverse object properties not supported."); } ObjectProperty op = (ObjectProperty) ope; Description child = description.getChild(0); Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); if (mapping == null) { logger.warn("Instance check of a description with an undefinied property (" + op + ")."); return true; } int number = ((ObjectCardinalityRestriction) description).getNumber(); int nrOfFillers = 0; SortedSet<Individual> roleFillers = opPos.get(op).get(individual); // return true if there are none or not enough role fillers if (roleFillers == null || roleFillers.size() < number) { return true; } int index = 0; for (Individual roleFiller : roleFillers) { index++; if (hasTypeImpl(child, roleFiller)) { nrOfFillers++; if (nrOfFillers > number) { 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 <= number) { return true; } } } return true; } else if (description instanceof ObjectValueRestriction) { Individual i = ((ObjectValueRestriction) description).getIndividual(); ObjectProperty op = (ObjectProperty) ((ObjectValueRestriction) description) .getRestrictedPropertyExpression(); Set<Individual> inds = opPos.get(op).get(individual); return inds == null ? false : inds.contains(i); } else if (description instanceof BooleanValueRestriction) { DatatypeProperty dp = ((BooleanValueRestriction) description).getRestrictedPropertyExpression(); boolean value = ((BooleanValueRestriction) description).getBooleanValue(); if (value) { // check whether the individual 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 DatatypeSomeRestriction) { DatatypeSomeRestriction dsr = (DatatypeSomeRestriction) description; DatatypeProperty dp = (DatatypeProperty) dsr.getRestrictedPropertyExpression(); DataRange dr = dsr.getDataRange(); if (dr.isDatatype() // && ((Datatype)dr).isTopDatatype() ) { if (dpPos.get(dp).containsKey(individual)) { return true; } else { return false; } } SortedSet<Double> values = dd.get(dp).get(individual); // if there is no filler for this individual and property we // need to return false if (values == null) { return false; } if (dr instanceof DoubleMaxValue) { return (values.first() <= ((DoubleMaxValue) dr).getValue()); } else if (dr instanceof DoubleMinValue) { return (values.last() >= ((DoubleMinValue) dr).getValue()); } } else if (description instanceof DatatypeValueRestriction) { String i = ((DatatypeValueRestriction) description).getValue().getLiteral(); DatatypeProperty dp = ((DatatypeValueRestriction) description).getRestrictedPropertyExpression(); Set<String> inds = sd.get(dp).get(individual); return inds == null ? false : inds.contains(i); } throw new ReasoningMethodUnsupportedException( "Instance check for description " + description + " unsupported."); } @Override public SortedSet<Individual> getIndividualsImpl(Description concept) throws ReasoningMethodUnsupportedException { return getIndividualsImplFast(concept); } public SortedSet<Individual> getIndividualsImplStandard(Description concept) throws ReasoningMethodUnsupportedException { if (concept instanceof NamedClass) { return classInstancesPos.get((NamedClass) concept); } else if (concept instanceof Negation && concept.getChild(0) instanceof NamedClass) { return classInstancesNeg.get((NamedClass) concept.getChild(0)); } // return rs.retrieval(concept); SortedSet<Individual> inds = new TreeSet<Individual>(); for (Individual i : individuals) { if (hasType(concept, i)) { inds.add(i); } } return inds; } @SuppressWarnings("unchecked") public SortedSet<Individual> getIndividualsImplFast(Description 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 description tree) if (description instanceof NamedClass) { if (classInstancesPos.containsKey((NamedClass) description)) { return (TreeSet<Individual>) classInstancesPos.get((NamedClass) description).clone(); } else { return new TreeSet<Individual>(); } } else if (description instanceof Negation) { if (description.getChild(0) instanceof NamedClass) { return (TreeSet<Individual>) classInstancesNeg.get((NamedClass) description.getChild(0)).clone(); } // implement retrieval as default negation return Helper.difference((TreeSet<Individual>) individuals.clone(), getIndividualsImpl(description.getChild(0))); } else if (description instanceof Thing) { return (TreeSet<Individual>) individuals.clone(); } else if (description instanceof Nothing) { return new TreeSet<Individual>(); } else if (description instanceof Union) { // copy instances of first element and then subtract all others SortedSet<Individual> ret = getIndividualsImpl(description.getChild(0)); int childNr = 0; for (Description child : description.getChildren()) { if (childNr != 0) { ret.addAll(getIndividualsImpl(child)); } childNr++; } return ret; } else if (description instanceof Intersection) { // copy instances of first element and then subtract all others SortedSet<Individual> ret = getIndividualsImpl(description.getChild(0)); int childNr = 0; for (Description child : description.getChildren()) { if (childNr != 0) { ret.retainAll(getIndividualsImpl(child)); } childNr++; } return ret; } else if (description instanceof ObjectSomeRestriction) { SortedSet<Individual> targetSet = getIndividualsImpl(description.getChild(0)); SortedSet<Individual> returnSet = new TreeSet<Individual>(); ObjectPropertyExpression ope = ((ObjectSomeRestriction) description).getRole(); if (!(ope instanceof ObjectProperty)) { throw new ReasoningMethodUnsupportedException("Retrieval for description " + description + " unsupported. Inverse object properties not supported."); } ObjectProperty op = (ObjectProperty) ope; Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); // each individual is connected to a set of individuals via the property; // we loop through the complete mapping for (Entry<Individual, SortedSet<Individual>> entry : mapping.entrySet()) { SortedSet<Individual> inds = entry.getValue(); for (Individual ind : inds) { if (targetSet.contains(ind)) { returnSet.add(entry.getKey()); // once we found an individual, we do not need to check the others continue; } } } return returnSet; } else if (description instanceof ObjectAllRestriction) { // \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) SortedSet<Individual> targetSet = getIndividualsImpl(description.getChild(0)); ObjectPropertyExpression ope = ((ObjectAllRestriction) description).getRole(); if (!(ope instanceof ObjectProperty)) { throw new ReasoningMethodUnsupportedException("Instance check for description " + description + " unsupported. Inverse object properties not supported."); } ObjectProperty op = (ObjectProperty) ope; Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); // SortedSet<Individual> returnSet = new TreeSet<Individual>(mapping.keySet()); SortedSet<Individual> returnSet = (SortedSet<Individual>) individuals.clone(); // each individual is connected to a set of individuals via the property; // we loop through the complete mapping for (Entry<Individual, SortedSet<Individual>> entry : mapping.entrySet()) { SortedSet<Individual> inds = entry.getValue(); for (Individual ind : inds) { if (!targetSet.contains(ind)) { returnSet.remove(entry.getKey()); continue; } } } return returnSet; } else if (description instanceof ObjectMinCardinalityRestriction) { ObjectPropertyExpression ope = ((ObjectCardinalityRestriction) description).getRole(); if (!(ope instanceof ObjectProperty)) { throw new ReasoningMethodUnsupportedException("Instance check for description " + description + " unsupported. Inverse object properties not supported."); } ObjectProperty op = (ObjectProperty) ope; Description child = description.getChild(0); Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); SortedSet<Individual> targetSet = getIndividualsImpl(child); SortedSet<Individual> returnSet = new TreeSet<Individual>(); int number = ((ObjectCardinalityRestriction) description).getNumber(); for (Entry<Individual, SortedSet<Individual>> entry : mapping.entrySet()) { int nrOfFillers = 0; int index = 0; SortedSet<Individual> inds = entry.getValue(); // we do not need to run tests if there are not sufficiently many fillers if (inds.size() < number) { continue; } for (Individual 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 ObjectMaxCardinalityRestriction) { ObjectPropertyExpression ope = ((ObjectCardinalityRestriction) description).getRole(); if (!(ope instanceof ObjectProperty)) { throw new ReasoningMethodUnsupportedException("Instance check for description " + description + " unsupported. Inverse object properties not supported."); } ObjectProperty op = (ObjectProperty) ope; Description child = description.getChild(0); Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); SortedSet<Individual> targetSet = getIndividualsImpl(child); // initially all individuals are in the return set and we then remove those // with too many fillers SortedSet<Individual> returnSet = (SortedSet<Individual>) individuals.clone(); int number = ((ObjectCardinalityRestriction) description).getNumber(); for (Entry<Individual, SortedSet<Individual>> entry : mapping.entrySet()) { int nrOfFillers = 0; int index = 0; SortedSet<Individual> 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 (Individual 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 ObjectValueRestriction) { Individual i = ((ObjectValueRestriction) description).getIndividual(); ObjectProperty op = (ObjectProperty) ((ObjectValueRestriction) description) .getRestrictedPropertyExpression(); Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); SortedSet<Individual> returnSet = new TreeSet<Individual>(); for (Entry<Individual, SortedSet<Individual>> entry : mapping.entrySet()) { if (entry.getValue().contains(i)) { 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<Individual>) bdPos.get(dp).clone(); } else { return (TreeSet<Individual>) bdNeg.get(dp).clone(); } } else if (description instanceof DatatypeSomeRestriction) { DatatypeSomeRestriction dsr = (DatatypeSomeRestriction) description; DatatypeProperty dp = (DatatypeProperty) dsr.getRestrictedPropertyExpression(); DataRange dr = dsr.getDataRange(); Map<Individual, SortedSet<Double>> mapping = dd.get(dp); SortedSet<Individual> returnSet = new TreeSet<Individual>(); if (dr instanceof DoubleMaxValue) { for (Entry<Individual, SortedSet<Double>> entry : mapping.entrySet()) { if (entry.getValue().first() <= ((DoubleMaxValue) dr).getValue()) { returnSet.add(entry.getKey()); } } } else if (dr instanceof DoubleMinValue) { for (Entry<Individual, SortedSet<Double>> entry : mapping.entrySet()) { if (entry.getValue().last() >= ((DoubleMinValue) dr).getValue()) { returnSet.add(entry.getKey()); } } } } throw new ReasoningMethodUnsupportedException("Retrieval for description " + description + " unsupported."); // return rs.retrieval(concept); // SortedSet<Individual> inds = new TreeSet<Individual>(); // for (Individual i : individuals) { // if (hasType(concept, i)) { // inds.add(i); // } // } // return inds; } /* * (non-Javadoc) * * @see org.dllearner.core.Reasoner#getAtomicConcepts() */ @Override public Set<NamedClass> getNamedClasses() { return atomicConcepts; } /* * (non-Javadoc) * * @see org.dllearner.core.Reasoner#getAtomicRoles() */ @Override public Set<ObjectProperty> getObjectProperties() { return atomicRoles; } @Override public SortedSet<DatatypeProperty> getDatatypePropertiesImpl() { return datatypeProperties; } @Override public SortedSet<DatatypeProperty> getBooleanDatatypePropertiesImpl() { return booleanDatatypeProperties; } @Override public SortedSet<DatatypeProperty> getDoubleDatatypePropertiesImpl() { return doubleDatatypeProperties; } @Override public SortedSet<DatatypeProperty> getIntDatatypePropertiesImpl() { return intDatatypeProperties; } @Override public SortedSet<DatatypeProperty> getStringDatatypePropertiesImpl() { return stringDatatypeProperties; } @Override protected SortedSet<Description> getSuperClassesImpl(Description concept) throws ReasoningMethodUnsupportedException { return rc.getSuperClassesImpl(concept); } @Override protected SortedSet<Description> getSubClassesImpl(Description concept) throws ReasoningMethodUnsupportedException { return rc.getSubClassesImpl(concept); } @Override protected SortedSet<ObjectProperty> getSuperPropertiesImpl(ObjectProperty role) throws ReasoningMethodUnsupportedException { return rc.getSuperPropertiesImpl(role); } @Override protected SortedSet<ObjectProperty> getSubPropertiesImpl(ObjectProperty role) throws ReasoningMethodUnsupportedException { return rc.getSubPropertiesImpl(role); } @Override protected SortedSet<DatatypeProperty> getSuperPropertiesImpl(DatatypeProperty role) throws ReasoningMethodUnsupportedException { return rc.getSuperPropertiesImpl(role); } @Override protected SortedSet<DatatypeProperty> getSubPropertiesImpl(DatatypeProperty role) throws ReasoningMethodUnsupportedException { return rc.getSubPropertiesImpl(role); } /* * (non-Javadoc) * * @see org.dllearner.core.Reasoner#getIndividuals() */ @Override public SortedSet<Individual> 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<ObjectProperty> allowedRoles) { // rc.prepareRoleHierarchy(allowedRoles); // } // @Override // public ObjectPropertyHierarchy getRoleHierarchy() { // return rc.getRoleHierarchy(); // } // @Override // public void prepareDatatypePropertyHierarchyImpl(Set<DatatypeProperty> allowedRoles) { // rc.prepareDatatypePropertyHierarchyImpl(allowedRoles); // } // @Override // public DatatypePropertyHierarchy getDatatypePropertyHierarchy() { // return rc.getDatatypePropertyHierarchy(); // } @Override public boolean isSuperClassOfImpl(Description superConcept, Description 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 Description getDomainImpl(ObjectProperty objectProperty) { return rc.getDomain(objectProperty); } @Override public Description getDomainImpl(DatatypeProperty datatypeProperty) { return rc.getDomain(datatypeProperty); } @Override public Description getRangeImpl(ObjectProperty objectProperty) { return rc.getRange(objectProperty); } @Override public DataRange getRangeImpl(DatatypeProperty datatypeProperty) { return rc.getRange(datatypeProperty); } @Override public Map<Individual, SortedSet<Individual>> getPropertyMembersImpl(ObjectProperty atomicRole) { return opPos.get(atomicRole); } @Override public final SortedSet<Individual> getTrueDatatypeMembersImpl(DatatypeProperty datatypeProperty) { return bdPos.get(datatypeProperty); } @Override public final SortedSet<Individual> getFalseDatatypeMembersImpl(DatatypeProperty datatypeProperty) { return bdNeg.get(datatypeProperty); } @Override public Map<Individual, SortedSet<Integer>> getIntDatatypeMembersImpl(DatatypeProperty datatypeProperty) { return id.get(datatypeProperty); } @Override public Map<Individual, SortedSet<Double>> getDoubleDatatypeMembersImpl(DatatypeProperty datatypeProperty) { return dd.get(datatypeProperty); } @Override public Map<Individual, SortedSet<Constant>> getDatatypeMembersImpl(DatatypeProperty datatypeProperty) { return dpPos.get(datatypeProperty); // return rc.getDatatypeMembersImpl(datatypeProperty); } @Override public Set<Individual> getRelatedIndividualsImpl(Individual individual, ObjectProperty objectProperty) throws ReasoningMethodUnsupportedException { return rc.getRelatedIndividuals(individual, objectProperty); } @Override protected Map<ObjectProperty, Set<Individual>> getObjectPropertyRelationshipsImpl(Individual individual) { return rc.getObjectPropertyRelationships(individual); } @Override public Set<Constant> getRelatedValuesImpl(Individual individual, DatatypeProperty datatypeProperty) throws ReasoningMethodUnsupportedException { return rc.getRelatedValues(individual, datatypeProperty); } @Override public boolean isSatisfiableImpl() { return rc.isSatisfiable(); } @Override public Set<Constant> getLabelImpl(Entity 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<NamedClass> getTypesImpl(Individual individual) { return rc.getTypesImpl(individual); } /* (non-Javadoc) * @see org.dllearner.core.BaseReasoner#remainsSatisfiable(org.dllearner.core.owl.Axiom) */ @Override public boolean remainsSatisfiableImpl(Axiom axiom) { return rc.remainsSatisfiableImpl(axiom); } @Override protected Set<Description> getAssertedDefinitionsImpl(NamedClass 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 materializeExistentialRestrictions the materializeExistentialRestrictions to set */ public void setMaterializeExistentialRestrictions(boolean materializeExistentialRestrictions) { this.materializeExistentialRestrictions = materializeExistentialRestrictions; } /** * @param handlePunning the handlePunning to set */ public void setHandlePunning(boolean handlePunning) { this.handlePunning = handlePunning; } /** * @param useCaching the useCaching to set */ public void setUseMaterializationCaching(boolean useCaching) { this.useCaching = useCaching; } }