From: <lor...@us...> - 2010-06-13 14:06:31
|
Revision: 2162 http://dl-learner.svn.sourceforge.net/dl-learner/?rev=2162&view=rev Author: lorenz_b Date: 2010-06-13 14:06:21 +0000 (Sun, 13 Jun 2010) Log Message: ----------- Started refactoring Protege plugin to be able to use the internal reasoners of Protege instead of a separate Pellet reasoner, included in the plugin libraries - actually we can use the internal reasoner, but something goes wrong when a new reasoner is selected in Protege. Modified Paths: -------------- trunk/build.xml trunk/doc/configOptions.txt trunk/src/dl-learner/org/dllearner/components.ini trunk/src/dl-learner/org/dllearner/core/configurators/ComponentFactory.java trunk/src/dl-learner/org/dllearner/reasoning/PelletReasoner.java trunk/src/dl-learner/org/dllearner/reasoning/ReasonerType.java trunk/src/dl-learner/org/dllearner/scripts/evaluation/StatsGenerator.java trunk/src/dl-learner/org/dllearner/tools/evaluationplugin/EvaluationPlugin.java trunk/src/dl-learner/org/dllearner/tools/protege/ActionHandler.java trunk/src/dl-learner/org/dllearner/tools/protege/DLLearnerModel.java trunk/src/dl-learner/org/dllearner/tools/protege/DLLearnerView.java trunk/src/dl-learner/org/dllearner/tools/protege/GraphicalCoveragePanelHandler.java trunk/src/dl-learner/org/dllearner/tools/protege/HyperLinkHandler.java trunk/src/dl-learner/org/dllearner/tools/protege/META-INF/MANIFEST.MF trunk/src/dl-learner/org/dllearner/tools/protege/META-INF/plugin.xml trunk/src/dl-learner/org/dllearner/tools/protege/ProtegePlugin.java trunk/src/dl-learner/org/dllearner/tools/protege/ReadingOntologyThread.java Added Paths: ----------- trunk/src/dl-learner/org/dllearner/core/configurators/ProtegeReasonerConfigurator.java trunk/src/dl-learner/org/dllearner/reasoning/ProtegeReasoner.java trunk/src/dl-learner/org/dllearner/tools/protege/Manager.java trunk/src/dl-learner/org/dllearner/tools/protege/StatusBar.java Removed Paths: ------------- trunk/src/dl-learner/org/dllearner/tools/protege/StatusBar2.java Modified: trunk/build.xml =================================================================== --- trunk/build.xml 2010-06-06 18:30:16 UTC (rev 2161) +++ trunk/build.xml 2010-06-13 14:06:21 UTC (rev 2162) @@ -355,25 +355,17 @@ <mkdir dir="${release}" /> <mkdir dir="${temp}/META-INF" /> <mkdir dir="${temp}/lib" /> - <mkdir dir="${temp}/lib/pellet" /> <mkdir dir="${temp}/lib/jena" /> <mkdir dir="${temp}/lib/ore-tool" /> - <mkdir dir="${temp}/lib/owlapi" /> <copy toDir="${temp}/META-INF" > <fileset dir="${source}/META-INF" includes="MANIFEST.MF," /> </copy> - <copy toDir="${temp}/lib/owlapi" > - <fileset dir="${lib_dir}/owlapi" includes="owlapiV3-bin.jar" /> - </copy> <copy toDir="${temp}/lib/ore-tool" > - <fileset dir="${lib_dir}/ore-tool" includes="BrowserLauncher2-all-1_3.jar, swingx-1.6.jar" /> + <fileset dir="${lib_dir}/ore-tool" includes="swingx-1.6.jar" /> </copy> <copy toDir="${temp}/lib" > <fileset dir="${lib_dir}" includes="junit-4.4.jar,jamon-2.7.jar" /> </copy> - <copy toDir="${temp}/lib/pellet" > - <fileset dir="${lib_dir}/pellet" includes="**/*.jar" /> - </copy> <copy toDir="${temp}/lib/jena" > <fileset dir="${lib_dir}/jena" includes="commons-logging-1.1.1.jar,json.jar" /> </copy> Modified: trunk/doc/configOptions.txt =================================================================== --- trunk/doc/configOptions.txt 2010-06-06 18:30:16 UTC (rev 2161) +++ trunk/doc/configOptions.txt 2010-06-13 14:06:21 UTC (rev 2162) @@ -30,6 +30,12 @@ default value: true conf file usage: sparql.useCache = true; +option name: useCacheDatabase +description: If true, H2 database is used, otherwise one file per query is written. +allowed values: boolean +default value: false +conf file usage: sparql.useCacheDatabase = false; + option name: instances description: relevant instances e.g. positive and negative examples in a learning problem allowed values: Set<String> @@ -215,8 +221,8 @@ conf file usage: owlAPIReasoner.reasonerType = pellet; -component: unnamed component (org.dllearner.reasoning.PelletReasoner) -===================================================================== +component: Pellet reasoner (org.dllearner.reasoning.PelletReasoner) +=================================================================== conf file usage: reasoner = null; @@ -227,6 +233,18 @@ conf file usage: null.defaultNegation = true; +component: Protege internal reasoner (org.dllearner.reasoning.ProtegeReasoner) +============================================================================== + +conf file usage: reasoner = null; + +option 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. +allowed values: boolean +default value: true +conf file usage: null.defaultNegation = true; + + ********************* * Learning Problems * ********************* @@ -254,7 +272,25 @@ default value: true conf file usage: classLearning.useApproximations = true; +option name: approxAccuracy +description: accuracy of the approximation (only for expert use) +allowed values: double +default value: 0.05 +conf file usage: classLearning.approxAccuracy = 0.05; +option name: accuracyMethod +description: Specifies, which method/function to use for computing accuracy. +allowed values: String [fmeasure, generalised_fmeasure, jaccard, pred_acc, standard] +default value: standard +conf file usage: classLearning.accuracyMethod = standard; + +option name: checkConsistency +description: Specify whether to check consistency for solution candidates. This is convenient for user interfaces, but can be performance intensive. +allowed values: boolean +default value: true +conf file usage: classLearning.checkConsistency = true; + + component: pos neg learning problem (org.dllearner.learningproblems.PosNegLPStandard) ===================================================================================== @@ -290,7 +326,25 @@ default value: twoChecks conf file usage: posNegLPStandard.useMultiInstanceChecks = twoChecks; +option name: useApproximations +description: whether to use stochastic approximations for computing accuracy +allowed values: boolean +default value: false +conf file usage: posNegLPStandard.useApproximations = false; +option name: approxAccuracy +description: accuracy of the approximation (only for expert use) +allowed values: double +default value: 0.05 +conf file usage: posNegLPStandard.approxAccuracy = 0.05; + +option name: accuracyMethod +description: Specifies, which method/function to use for computing accuracy. +allowed values: String [fmeasure, predacc] +default value: predacc +conf file usage: posNegLPStandard.accuracyMethod = predacc; + + component: three valued definition learning problem (org.dllearner.learningproblems.PosNegLPStrict) =================================================================================================== @@ -420,6 +474,12 @@ default value: false conf file usage: celoe.useHasValueConstructor = false; +option name: useDataHasValueConstructor +description: specifies whether the hasValue constructor is used in the learning algorithm in combination with data properties +allowed values: boolean +default value: false +conf file usage: celoe.useDataHasValueConstructor = false; + option name: valueFrequencyThreshold description: specifies how often an object must occur as value in order to be considered for hasValue restrictions allowed values: int @@ -480,13 +540,43 @@ default value: 10 conf file usage: celoe.maxNrOfResults = 10; +option name: singleSuggestionMode +description: Use this if you are interested in only one suggestion and your learning problem has many (more than 1000) examples. +allowed values: boolean +default value: false +conf file usage: celoe.singleSuggestionMode = false; +option name: instanceBasedDisjoints +description: Specifies whether to use real disjointness checks or instance based ones (no common instances) in the refinement operator. +allowed values: boolean +default value: true +conf file usage: celoe.instanceBasedDisjoints = true; + +option name: filterDescriptionsFollowingFromKB +description: If true, then the results will not contain suggestions, which already follow logically from the knowledge base. Be careful, since this requires a potentially expensive consistency check for candidate solutions. +allowed values: boolean +default value: false +conf file usage: celoe.filterDescriptionsFollowingFromKB = false; + +option name: reuseExistingDescription +description: If true, the algorithm tries to find a good starting point close to an existing definition/super class of the given class in the knowledge base. +allowed values: boolean +default value: false +conf file usage: celoe.reuseExistingDescription = false; + + component: standard EL learning algorithm (org.dllearner.algorithms.el.ELLearningAlgorithm) =========================================================================================== conf file usage: algorithm = el; +option name: instanceBasedDisjoints +description: Specifies whether to use real disjointness checks or instance based ones (no common instances) in the refinement operator. +allowed values: boolean +default value: true +conf file usage: el.instanceBasedDisjoints = true; + component: disjunctive EL learning algorithm (org.dllearner.algorithms.el.ELLearningAlgorithmDisjunctive) ========================================================================================================= @@ -504,7 +594,13 @@ default value: not set conf file usage: disjunctiveEL.startClass = ; +option name: instanceBasedDisjoints +description: Specifies whether to use real disjointness checks or instance based ones (no common instances) in the refinement operator. +allowed values: boolean +default value: true +conf file usage: disjunctiveEL.instanceBasedDisjoints = true; + component: genetic programming learning algorithm (org.dllearner.algorithms.gp.GP) ================================================================================== @@ -613,6 +709,120 @@ conf file usage: gp.maxConceptLength = 75; +component: ISLE (org.dllearner.algorithms.isle.ISLE) +==================================================== + +conf file usage: algorithm = null; + +option name: useAllConstructor +description: specifies whether the universal concept constructor is used in the learning algorithm +allowed values: boolean +default value: true +conf file usage: null.useAllConstructor = true; + +option name: useExistsConstructor +description: specifies whether the existential concept constructor is used in the learning algorithm +allowed values: boolean +default value: true +conf file usage: null.useExistsConstructor = true; + +option name: useHasValueConstructor +description: specifies whether the hasValue constructor is used in the learning algorithm +allowed values: boolean +default value: false +conf file usage: null.useHasValueConstructor = false; + +option name: useDataHasValueConstructor +description: specifies whether the hasValue constructor is used in the learning algorithm in combination with data properties +allowed values: boolean +default value: false +conf file usage: null.useDataHasValueConstructor = false; + +option name: valueFrequencyThreshold +description: specifies how often an object must occur as value in order to be considered for hasValue restrictions +allowed values: int +default value: 3 +conf file usage: null.valueFrequencyThreshold = 3; + +option name: useCardinalityRestrictions +description: specifies whether CardinalityRestrictions is used in the learning algorithm +allowed values: boolean +default value: true +conf file usage: null.useCardinalityRestrictions = true; + +option name: cardinalityLimit +description: Gives the maximum number used in cardinality restrictions. +allowed values: int +default value: 5 +conf file usage: null.cardinalityLimit = 5; + +option name: useNegation +description: specifies whether negation is used in the learning algorothm +allowed values: boolean +default value: false +conf file usage: null.useNegation = false; + +option name: useBooleanDatatypes +description: specifies whether boolean datatypes are used in the learning algorothm +allowed values: boolean +default value: true +conf file usage: null.useBooleanDatatypes = true; + +option name: useDoubleDatatypes +description: specifies whether boolean datatypes are used in the learning algorothm +allowed values: boolean +default value: true +conf file usage: null.useDoubleDatatypes = true; + +option name: maxExecutionTimeInSeconds +description: algorithm will stop after specified seconds +allowed values: int +default value: 10 +conf file usage: null.maxExecutionTimeInSeconds = 10; + +option name: noisePercentage +description: the (approximated) percentage of noise within the examples +allowed values: double min 0.0 max 100.0 +default value: 0.0 +conf file usage: null.noisePercentage = 0.0; + +option name: maxDepth +description: maximum depth of description +allowed values: int +default value: 7 +conf file usage: null.maxDepth = 7; + +option name: maxNrOfResults +description: Sets the maximum number of results one is interested in. (Setting this to a lower value may increase performance as the learning algorithm has to store/evaluate/beautify less descriptions). +allowed values: int min 1 max 100 +default value: 10 +conf file usage: null.maxNrOfResults = 10; + +option name: singleSuggestionMode +description: Use this if you are interested in only one suggestion and your learning problem has many (more than 1000) examples. +allowed values: boolean +default value: false +conf file usage: null.singleSuggestionMode = false; + +option name: instanceBasedDisjoints +description: Specifies whether to use real disjointness checks or instance based ones (no common instances) in the refinement operator. +allowed values: boolean +default value: true +conf file usage: null.instanceBasedDisjoints = true; + +option name: filterDescriptionsFollowingFromKB +description: If true, then the results will not contain suggestions, which already follow logically from the knowledge base. Be careful, since this requires a potentially expensive consistency check for candidate solutions. +allowed values: boolean +default value: false +conf file usage: null.filterDescriptionsFollowingFromKB = false; + +option name: reuseExistingDescription +description: If true, the algorithm tries to find a good starting point close to an existing definition/super class of the given class in the knowledge base. +allowed values: boolean +default value: false +conf file usage: null.reuseExistingDescription = false; + + component: refinement operator based learning algorithm (org.dllearner.algorithms.refinement.ROLearner) ======================================================================================================= @@ -768,7 +978,13 @@ default value: DEBUG conf file usage: refinement.logLevel = DEBUG; +option name: instanceBasedDisjoints +description: Specifies whether to use real disjointness checks or instance based ones (no common instances) in the refinement operator. +allowed values: boolean +default value: true +conf file usage: refinement.instanceBasedDisjoints = true; + component: refinement operator based learning algorithm II (org.dllearner.algorithms.refinement2.ROLComponent2) =============================================================================================================== @@ -852,18 +1068,6 @@ default value: not set conf file usage: refexamples.ignoredConcepts = ; -option name: allowedRoles -description: roles the algorithm is allowed to use -allowed values: Set<String> -default value: not set -conf file usage: refexamples.allowedRoles = ; - -option name: ignoredRoles -description: roles the algorithm must ignore -allowed values: Set<String> -default value: not set -conf file usage: refexamples.ignoredRoles = ; - option name: useAllConstructor description: specifies whether the universal concept constructor is used in the learning algorithm allowed values: boolean @@ -882,6 +1086,12 @@ default value: false conf file usage: refexamples.useHasValueConstructor = false; +option name: useDataHasValueConstructor +description: specifies whether the hasValue constructor is used in the learning algorithm in combination with data properties +allowed values: boolean +default value: false +conf file usage: refexamples.useDataHasValueConstructor = false; + option name: valueFrequencyThreshold description: specifies how often an object must occur as value in order to be considered for hasValue restrictions allowed values: int @@ -1008,4 +1218,10 @@ default value: 0.02 conf file usage: refexamples.expansionPenaltyFactor = 0.02; +option name: instanceBasedDisjoints +description: Specifies whether to use real disjointness checks or instance based ones (no common instances) in the refinement operator. +allowed values: boolean +default value: true +conf file usage: refexamples.instanceBasedDisjoints = true; + Modified: trunk/src/dl-learner/org/dllearner/components.ini =================================================================== --- trunk/src/dl-learner/org/dllearner/components.ini 2010-06-06 18:30:16 UTC (rev 2161) +++ trunk/src/dl-learner/org/dllearner/components.ini 2010-06-13 14:06:21 UTC (rev 2162) @@ -10,6 +10,7 @@ org.dllearner.reasoning.DIGReasoner org.dllearner.reasoning.FastRetrievalReasoner org.dllearner.reasoning.FastInstanceChecker +org.dllearner.reasoning.ProtegeReasoner org.dllearner.reasoning.PelletReasoner # learning problems org.dllearner.learningproblems.PosNegLPStandard Modified: trunk/src/dl-learner/org/dllearner/core/configurators/ComponentFactory.java =================================================================== --- trunk/src/dl-learner/org/dllearner/core/configurators/ComponentFactory.java 2010-06-06 18:30:16 UTC (rev 2161) +++ trunk/src/dl-learner/org/dllearner/core/configurators/ComponentFactory.java 2010-06-13 14:06:21 UTC (rev 2162) @@ -48,6 +48,7 @@ import org.dllearner.reasoning.FastRetrievalReasoner; import org.dllearner.reasoning.OWLAPIReasoner; import org.dllearner.reasoning.PelletReasoner; +import org.dllearner.reasoning.ProtegeReasoner; /** * automatically generated, do not edit manually. @@ -129,6 +130,14 @@ } /** +* @param knowledgeSource see KnowledgeSource +* @return a component ready for initialization ProtegeReasoner +**/ +public static ProtegeReasoner getProtegeReasoner(Set<KnowledgeSource> knowledgeSource) { +return ProtegeReasonerConfigurator.getProtegeReasoner(knowledgeSource); +} + +/** * @param classToDescribe class of which a description should be learned * @param reasoningService see ReasoningService * @return a component ready for initialization ClassLearningProblem Added: trunk/src/dl-learner/org/dllearner/core/configurators/ProtegeReasonerConfigurator.java =================================================================== --- trunk/src/dl-learner/org/dllearner/core/configurators/ProtegeReasonerConfigurator.java (rev 0) +++ trunk/src/dl-learner/org/dllearner/core/configurators/ProtegeReasonerConfigurator.java 2010-06-13 14:06:21 UTC (rev 2162) @@ -0,0 +1,84 @@ +/** + * Copyright (C) 2007-2008, 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.core.configurators; + +import java.util.Set; +import org.dllearner.core.ComponentManager; +import org.dllearner.core.KnowledgeSource; +import org.dllearner.reasoning.ProtegeReasoner; + +/** +* automatically generated, do not edit manually. +* run org.dllearner.scripts.ConfigJavaGenerator to update +**/ +public class ProtegeReasonerConfigurator implements Configurator { + +private boolean reinitNecessary = false; +@SuppressWarnings("unused") + +private ProtegeReasoner protegeReasoner; + +/** +* @param protegeReasoner see ProtegeReasoner +**/ +public ProtegeReasonerConfigurator(ProtegeReasoner protegeReasoner){ +this.protegeReasoner = protegeReasoner; +} + +/** +* @param knowledgeSource see knowledgeSource +* @return ProtegeReasoner +**/ +public static ProtegeReasoner getProtegeReasoner(Set<KnowledgeSource> knowledgeSource) { +ProtegeReasoner component = ComponentManager.getInstance().reasoner(ProtegeReasoner.class, knowledgeSource); +return component; +} + +/** +* defaultNegation Whether to use default negation, i.e. an instance not being in a class means that it is in the negation of the class.. +* mandatory: false| reinit necessary: true +* default value: true +* @return boolean +**/ +public boolean getDefaultNegation() { +return (Boolean) ComponentManager.getInstance().getConfigOptionValue(protegeReasoner, "defaultNegation") ; +} + +/** +* @param defaultNegation Whether to use default negation, i.e. an instance not being in a class means that it is in the negation of the class.. +* mandatory: false| reinit necessary: true +* default value: true +**/ +public void setDefaultNegation(boolean defaultNegation) { +ComponentManager.getInstance().applyConfigEntry(protegeReasoner, "defaultNegation", defaultNegation); +reinitNecessary = true; +} + +/** +* true, if this component needs reinitializsation. +* @return boolean +**/ +public boolean isReinitNecessary(){ +return reinitNecessary; +} + + +} Modified: trunk/src/dl-learner/org/dllearner/reasoning/PelletReasoner.java =================================================================== --- trunk/src/dl-learner/org/dllearner/reasoning/PelletReasoner.java 2010-06-06 18:30:16 UTC (rev 2161) +++ trunk/src/dl-learner/org/dllearner/reasoning/PelletReasoner.java 2010-06-13 14:06:21 UTC (rev 2162) @@ -1281,7 +1281,6 @@ NodeSet<OWLClass> set = reasoner.getObjectPropertyRanges(prop, true); if (set.isEmpty()) return new Thing(); -// OWLClass oc = set.iterator().next().getRepresentativeElement(); return getDescriptionFromReturnedDomain(set); } Added: trunk/src/dl-learner/org/dllearner/reasoning/ProtegeReasoner.java =================================================================== --- trunk/src/dl-learner/org/dllearner/reasoning/ProtegeReasoner.java (rev 0) +++ trunk/src/dl-learner/org/dllearner/reasoning/ProtegeReasoner.java 2010-06-13 14:06:21 UTC (rev 2162) @@ -0,0 +1,1449 @@ +package org.dllearner.reasoning; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Map.Entry; + +import org.dllearner.core.ComponentInitException; +import org.dllearner.core.KnowledgeSource; +import org.dllearner.core.ReasonerComponent; +import org.dllearner.core.ReasoningMethodUnsupportedException; +import org.dllearner.core.configurators.ProtegeReasonerConfigurator; +import org.dllearner.core.options.BooleanConfigOption; +import org.dllearner.core.options.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.Datatype; +import org.dllearner.core.owl.DatatypeProperty; +import org.dllearner.core.owl.DatatypeSomeRestriction; +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.KB; +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.TypedConstant; +import org.dllearner.core.owl.Union; +import org.dllearner.core.owl.UntypedConstant; +import org.dllearner.kb.OWLAPIOntology; +import org.dllearner.kb.OWLFile; +import org.dllearner.kb.sparql.SparqlKnowledgeSource; +import org.dllearner.utilities.Helper; +import org.dllearner.utilities.owl.ConceptComparator; +import org.dllearner.utilities.owl.ConceptTransformation; +import org.dllearner.utilities.owl.DLLearnerDescriptionConvertVisitor; +import org.dllearner.utilities.owl.OWLAPIAxiomConvertVisitor; +import org.dllearner.utilities.owl.OWLAPIConverter; +import org.dllearner.utilities.owl.OWLAPIDescriptionConvertVisitor; +import org.dllearner.utilities.owl.RoleComparator; +import org.semanticweb.owlapi.apibinding.OWLManager; +import org.semanticweb.owlapi.model.AddAxiom; +import org.semanticweb.owlapi.model.IRI; +import org.semanticweb.owlapi.model.OWLAnnotation; +import org.semanticweb.owlapi.model.OWLAxiom; +import org.semanticweb.owlapi.model.OWLClass; +import org.semanticweb.owlapi.model.OWLClassExpression; +import org.semanticweb.owlapi.model.OWLDataFactory; +import org.semanticweb.owlapi.model.OWLDataProperty; +import org.semanticweb.owlapi.model.OWLDataRange; +import org.semanticweb.owlapi.model.OWLEntity; +import org.semanticweb.owlapi.model.OWLLiteral; +import org.semanticweb.owlapi.model.OWLNamedIndividual; +import org.semanticweb.owlapi.model.OWLNamedObject; +import org.semanticweb.owlapi.model.OWLObjectProperty; +import org.semanticweb.owlapi.model.OWLObjectPropertyExpression; +import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.model.OWLOntologyChangeException; +import org.semanticweb.owlapi.model.OWLOntologyCreationException; +import org.semanticweb.owlapi.model.OWLOntologyFormat; +import org.semanticweb.owlapi.model.OWLOntologyManager; +import org.semanticweb.owlapi.model.OWLOntologyStorageException; +import org.semanticweb.owlapi.model.OWLTypedLiteral; +import org.semanticweb.owlapi.model.RemoveAxiom; +import org.semanticweb.owlapi.model.UnknownOWLOntologyException; +import org.semanticweb.owlapi.reasoner.Node; +import org.semanticweb.owlapi.reasoner.NodeSet; +import org.semanticweb.owlapi.reasoner.OWLReasoner; +import org.semanticweb.owlapi.util.SimpleIRIMapper; +import org.semanticweb.owlapi.vocab.PrefixOWLOntologyFormat; + +import uk.ac.manchester.cs.owl.owlapi.OWLStringLiteralImpl; + +public class ProtegeReasoner extends ReasonerComponent { + + private OWLOntologyManager manager; + private OWLOntology ontology; + private OWLDataFactory factory; + private OWLReasoner reasoner; + + private ProtegeReasonerConfigurator configurator; + + private Set<OWLOntology> loadedOntologies; + + private ConceptComparator conceptComparator = new ConceptComparator(); + private RoleComparator roleComparator = new RoleComparator(); + + Set<NamedClass> atomicConcepts = new TreeSet<NamedClass>(conceptComparator); + Set<ObjectProperty> atomicRoles = new TreeSet<ObjectProperty>(roleComparator); + SortedSet<DatatypeProperty> datatypeProperties = new TreeSet<DatatypeProperty>(); + SortedSet<DatatypeProperty> booleanDatatypeProperties = new TreeSet<DatatypeProperty>(); + SortedSet<DatatypeProperty> doubleDatatypeProperties = new TreeSet<DatatypeProperty>(); + SortedSet<DatatypeProperty> intDatatypeProperties = new TreeSet<DatatypeProperty>(); + SortedSet<DatatypeProperty> stringDatatypeProperties = new TreeSet<DatatypeProperty>(); + TreeSet<Individual> individuals = new TreeSet<Individual>(); + + + //CWA + // 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>>>(); + // 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>>>(); + + + // namespaces + private Map<String, String> prefixes = new TreeMap<String,String>(); + private String baseURI; + + // references to OWL API ontologies + private List<OWLOntology> owlAPIOntologies = new LinkedList<OWLOntology>(); + + public ProtegeReasoner(Set<KnowledgeSource> sources) { + super(sources); + this.configurator = new ProtegeReasonerConfigurator(this); + } + + public ProtegeReasoner(Set<KnowledgeSource> sources, OWLReasoner reasoner) { + this(sources); + this.reasoner = reasoner; + } + + + public boolean isConsistent(){ + return reasoner.isConsistent(); + } + + @Override + public ReasonerType getReasonerType() { + return ReasonerType.PROTEGE; + } + + @Override + public void releaseKB() { + reasoner.dispose(); + } + + @Override + public ProtegeReasonerConfigurator getConfigurator() { + return configurator; + } + + /** + * @return The options of this component. + */ + public static Collection<ConfigOption<?>> createConfigOptions() { + Collection<ConfigOption<?>> options = new LinkedList<ConfigOption<?>>(); + + options.add(new BooleanConfigOption("defaultNegation", "Whether to use default negation, i.e. an instance not being in a class means that it is in the negation of the class.", true, false, true)); + + return options; + } + + public OWLOntologyManager getOWLOntologyManager(){ + return manager; + } + + public void setOWLReasoner(OWLReasoner owlReasoner){ + this.reasoner = owlReasoner; + } + + @Override + public void init() throws ComponentInitException { + // reset variables (otherwise subsequent initialisation with + // different knowledge sources will merge both) + atomicConcepts = new TreeSet<NamedClass>(conceptComparator); + atomicRoles = new TreeSet<ObjectProperty>(roleComparator); + datatypeProperties = new TreeSet<DatatypeProperty>(); + booleanDatatypeProperties = new TreeSet<DatatypeProperty>(); + doubleDatatypeProperties = new TreeSet<DatatypeProperty>(); + intDatatypeProperties = new TreeSet<DatatypeProperty>(); + individuals = new TreeSet<Individual>(); + + // create OWL API ontology manager + manager = OWLManager.createOWLOntologyManager(); + factory = manager.getOWLDataFactory(); + + + ////////////////////////////////////////// + // + // + // + Comparator<OWLNamedObject> namedObjectComparator = new Comparator<OWLNamedObject>() { + public int compare(OWLNamedObject o1, OWLNamedObject o2) { + return o1.getIRI().compareTo(o2.getIRI()); + } + }; + Set<OWLClass> classes = new TreeSet<OWLClass>(namedObjectComparator); + Set<OWLObjectProperty> owlObjectProperties = new TreeSet<OWLObjectProperty>( + namedObjectComparator); + Set<OWLDataProperty> owlDatatypeProperties = new TreeSet<OWLDataProperty>( + namedObjectComparator); + Set<OWLNamedIndividual> owlIndividuals = new TreeSet<OWLNamedIndividual>( + namedObjectComparator); + loadedOntologies = new HashSet<OWLOntology>(); + Set<OWLOntology> allImports = new HashSet<OWLOntology>(); + prefixes = new TreeMap<String, String>(); + + for (KnowledgeSource source : sources) { + + if (source instanceof OWLFile + || source instanceof SparqlKnowledgeSource + || source instanceof OWLAPIOntology) { + URL url = null; + if (source instanceof OWLFile) { + url = ((OWLFile) source).getURL(); + } + +// try { + + if (source instanceof OWLAPIOntology) { + ontology = ((OWLAPIOntology) source).getOWLOntolgy(); + } else if (source instanceof SparqlKnowledgeSource) { + ontology = ((SparqlKnowledgeSource) source).getOWLAPIOntology(); + manager = ontology.getOWLOntologyManager(); + } else { + try { + ontology = manager.loadOntologyFromOntologyDocument(IRI.create(url + .toURI())); + } catch (OWLOntologyCreationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (URISyntaxException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + owlAPIOntologies.add(ontology); + classes.addAll(ontology.getClassesInSignature(true)); + owlObjectProperties.addAll(ontology.getObjectPropertiesInSignature(true)); + owlDatatypeProperties.addAll(ontology.getDataPropertiesInSignature(true)); + owlIndividuals.addAll(ontology.getIndividualsInSignature(true)); + + // if several knowledge sources are included, then we can + // only + // guarantee that the base URI is from one of those sources + // (there + // can't be more than one); but we will take care that all + // prefixes are + // correctly imported + OWLOntologyFormat format = manager.getOntologyFormat(ontology); + if (format instanceof PrefixOWLOntologyFormat) { + prefixes.putAll(((PrefixOWLOntologyFormat) format).getPrefixName2PrefixMap()); + baseURI = ((PrefixOWLOntologyFormat) format).getDefaultPrefix(); + prefixes.remove(""); + } + + // read in primitives + for(OWLClass owlClass : classes) + atomicConcepts.add(new NamedClass(owlClass.toStringID())); + for(OWLObjectProperty owlProperty : owlObjectProperties) + atomicRoles.add(new ObjectProperty(owlProperty.toStringID())); + for(OWLDataProperty owlProperty : owlDatatypeProperties) { + DatatypeProperty dtp = new DatatypeProperty(owlProperty.toStringID()); + Set<OWLDataRange> ranges = owlProperty.getRanges(allImports); + for(OWLDataRange range : ranges){ + if(range.isDatatype()) { + if(range.asOWLDatatype().isBoolean()) + booleanDatatypeProperties.add(dtp); + else if(range.asOWLDatatype().isDouble()) + doubleDatatypeProperties.add(dtp); + else if(range.asOWLDatatype().isInteger()) + intDatatypeProperties.add(dtp); + else if(range.asOWLDatatype().isString()) + stringDatatypeProperties.add(dtp); + } + } + datatypeProperties.add(dtp); + } + for(OWLNamedIndividual owlIndividual : owlIndividuals) { + individuals.add(new Individual(owlIndividual.toStringID())); + } + +// } catch (OWLOntologyCreationException e) { +// e.printStackTrace(); +// } catch (URISyntaxException e) { +// e.printStackTrace(); +// } + // all other sources are converted to KB and then to an + // OWL API ontology + } else { + KB kb = source.toKB(); + // System.out.println(kb.toString(null,null)); + + IRI ontologyIRI = IRI.create("http://example.com"); + ontology = null; + try { + ontology = manager.createOntology(ontologyIRI); + } catch (OWLOntologyCreationException e) { + e.printStackTrace(); + } + OWLAPIAxiomConvertVisitor + .fillOWLOntology(manager, ontology, kb); + owlAPIOntologies.add(ontology); + allImports.add(ontology); + atomicConcepts.addAll(kb.findAllAtomicConcepts()); + atomicRoles.addAll(kb.findAllAtomicRoles()); + individuals.addAll(kb.findAllIndividuals()); + // TODO: add method to find datatypes + } + } + dematerialise(); + } + + private void dematerialise(){ + long dematStartTime = System.currentTimeMillis(); + logger.debug("dematerialising concepts"); + + for (NamedClass atomicConcept : atomicConcepts) { + + SortedSet<Individual> pos = getIndividualsWithPellet(atomicConcept); + classInstancesPos.put(atomicConcept, (TreeSet<Individual>) pos); + if (configurator.getDefaultNegation()) { + classInstancesNeg.put(atomicConcept, (TreeSet<Individual>) Helper.difference(individuals, pos)); + } else { + Negation negatedAtomicConcept = new Negation(atomicConcept); + classInstancesNeg.put(atomicConcept, (TreeSet<Individual>) getIndividuals(negatedAtomicConcept)); + } + + } + + logger.debug("dematerialising object properties"); + + for (ObjectProperty atomicRole : atomicRoles) { + opPos.put(atomicRole, getPropertyMembers(atomicRole)); + } + + logger.debug("dematerialising datatype properties"); + + for (DatatypeProperty dp : booleanDatatypeProperties) { + bdPos.put(dp, (TreeSet<Individual>) getTrueDatatypeMembers(dp)); + bdNeg.put(dp, (TreeSet<Individual>) getFalseDatatypeMembers(dp)); + } + + for (DatatypeProperty dp : intDatatypeProperties) { + id.put(dp, getIntDatatypeMembers(dp)); + } + + for (DatatypeProperty dp : doubleDatatypeProperties) { + dd.put(dp, getDoubleDatatypeMembers(dp)); + } + + long dematDuration = System.currentTimeMillis() - dematStartTime; + logger.debug("TBox dematerialised in " + dematDuration + " ms"); + } + + + @Override + public String getBaseURI() { + return baseURI; + } + + @Override + public SortedSet<Individual> getIndividuals() { + return individuals; + } + + @Override + public Set<NamedClass> getNamedClasses() { + return Collections.unmodifiableSet(atomicConcepts); + } + + @Override + public Set<ObjectProperty> getObjectProperties() { + return Collections.unmodifiableSet(atomicRoles); + } + + @Override + public Map<String, String> getPrefixes() { + return prefixes; + } + + public Set<Description> getComplementClasses(Description desc){ + OWLClassExpression owlDesc = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(desc); + Set<Description> complements = new HashSet<Description>(); + for(OWLClass comp : reasoner.getDisjointClasses(owlDesc, false).getFlattened()){ + complements.add(OWLAPIConverter.convertClass(comp)); + } + return complements; + + } + + @Override + public SortedSet<DatatypeProperty> getDatatypePropertiesImpl() { + return datatypeProperties; + } + + @Override + public boolean isSuperClassOfImpl(Description superConcept, Description subConcept) { + return reasoner.isEntailed(factory.getOWLSubClassOfAxiom(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(subConcept), + OWLAPIDescriptionConvertVisitor.getOWLClassExpression(superConcept))); + } + + @Override + protected boolean isEquivalentClassImpl(Description class1, Description class2) { + return reasoner.isEntailed(factory.getOWLEquivalentClassesAxiom(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(class1), + OWLAPIDescriptionConvertVisitor.getOWLClassExpression(class2))); + } + + @Override + protected TreeSet<Description> getSuperClassesImpl(Description concept) { + NodeSet<OWLClass> classes = null; + + classes = reasoner.getSuperClasses(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept), true); + + return getFirstClasses(classes); + } + + @Override + protected TreeSet<Description> getSubClassesImpl(Description concept) { + NodeSet<OWLClass> classes = null; + + classes = reasoner.getSubClasses(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept), true); + + return getFirstClasses(classes); + } + + @Override + protected TreeSet<ObjectProperty> getSuperPropertiesImpl(ObjectProperty role) { + NodeSet<OWLObjectProperty> properties = null; + + properties = reasoner.getSuperObjectProperties(OWLAPIConverter.getOWLAPIObjectProperty(role), true); + + return getFirstObjectProperties(properties); + } + + @Override + protected TreeSet<ObjectProperty> getSubPropertiesImpl(ObjectProperty role) { + NodeSet<OWLObjectProperty> properties = null; + + properties = reasoner.getSubObjectProperties(OWLAPIConverter.getOWLAPIObjectProperty(role), true); + + return getFirstObjectProperties(properties); + } + + @Override + protected TreeSet<DatatypeProperty> getSuperPropertiesImpl(DatatypeProperty role) { + NodeSet<OWLDataProperty> properties = null; + + properties = reasoner.getSuperDataProperties(OWLAPIConverter.getOWLAPIDataProperty(role), true); + + return getFirstDatatypeProperties(properties); + } + + @Override + protected TreeSet<DatatypeProperty> getSubPropertiesImpl(DatatypeProperty role) { + NodeSet<OWLDataProperty> properties = null; + + properties = reasoner.getSubDataProperties(OWLAPIConverter.getOWLAPIDataProperty(role), true); + + return getFirstDatatypeProperties(properties); + } + + @Override + public boolean hasTypeImpl(Description description, Individual individual) throws ReasoningMethodUnsupportedException { +// OWLClassExpression d = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept); +// OWLIndividual i = factory.getOWLIndividual(URI.create(individual.getName())); +// try { +// return reasoner.hasType(i,d,false); +// } catch (OWLReasonerException e) { +// e.printStackTrace(); +// throw new Error("Instance check error in OWL API."); +// } + if (description instanceof NamedClass) { + 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(configurator.getDefaultNegation()) { + 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); + Map<Individual, SortedSet<Individual>> mapping = opPos.get(op); + + if (mapping == null) { + logger.warn("Instance check of a description with an undefinied property (" + op + + ")."); + return false; + } + SortedSet<Individual> roleFillers = opPos.get(op).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) { + return true; + } + for (Individual roleFiller : roleFillers) { + if (!hasTypeImpl(child, roleFiller)) { + return false; + } + } + 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) { + return false; + } + + int index = 0; + for (Individual roleFiller : roleFillers) { + index++; + if (hasTypeImpl(child, roleFiller)) { + nrOfFillers++; + if (nrOfFillers == number) { + 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(); + 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()); + } + } + + throw new ReasoningMethodUnsupportedException("Instance check for description " + + description + " unsupported."); + + } + + private SortedSet<Individual> getIndividualsWithPellet(Description concept){ + + OWLClassExpression d = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept); + Set<OWLNamedIndividual> individuals = reasoner.getInstances(d, false).getFlattened(); + SortedSet<Individual> inds = new TreeSet<Individual>(); + for(OWLNamedIndividual ind : individuals) + inds.add(new Individual(ind.toStringID())); + return inds; + } + + @Override + public SortedSet<Individual> getIndividualsImpl(Description concept) throws ReasoningMethodUnsupportedException{ +// +// OWLClassExpression d = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept); +// Set<OWLIndividual> individuals = null; +// +// individuals = reasoner.getIndividuals(d, false); +// +// SortedSet<Individual> inds = new TreeSet<Individual>(); +// for(OWLIndividual ind : individuals) +// inds.add(new Individual(ind.getURI().toString())); +// return inds; + 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) { + return (TreeSet<Individual>) classInstancesPos.get((NamedClass) description).clone(); + } 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... [truncated message content] |