From: <lor...@us...> - 2014-01-29 14:24:21
|
Revision: 4214 http://sourceforge.net/p/dl-learner/code/4214 Author: lorenz_b Date: 2014-01-29 14:24:16 +0000 (Wed, 29 Jan 2014) Log Message: ----------- Added copy of EL algorithm able to handle data properties. Modified Paths: -------------- trunk/components-core/src/main/java/org/dllearner/algorithms/celoe/CELOE.java trunk/components-core/src/main/java/org/dllearner/algorithms/celoe/PCELOE.java trunk/components-core/src/main/java/org/dllearner/algorithms/el/ELLearningAlgorithm.java trunk/components-core/src/main/java/org/dllearner/algorithms/el/ELLearningAlgorithmDisjunctive.java trunk/components-core/src/main/java/org/dllearner/algorithms/fuzzydll/FuzzyCELOE.java trunk/components-core/src/main/java/org/dllearner/algorithms/isle/metrics/PMIRelevanceMetric.java trunk/components-core/src/main/java/org/dllearner/core/AbstractCELA.java trunk/components-core/src/main/java/org/dllearner/core/AbstractReasonerComponent.java trunk/components-core/src/main/java/org/dllearner/core/ComponentManager.java trunk/components-core/src/main/java/org/dllearner/core/owl/BooleanDataRange.java trunk/components-core/src/main/java/org/dllearner/core/owl/DataRange.java trunk/components-core/src/main/java/org/dllearner/core/owl/Datatype.java trunk/components-core/src/main/java/org/dllearner/core/owl/DatatypePropertyHierarchy.java trunk/components-core/src/main/java/org/dllearner/core/owl/DatatypeQuantorRestriction.java trunk/components-core/src/main/java/org/dllearner/core/owl/DatatypeSomeRestriction.java trunk/components-core/src/main/java/org/dllearner/core/owl/Description.java trunk/components-core/src/main/java/org/dllearner/core/owl/DoubleMaxValue.java trunk/components-core/src/main/java/org/dllearner/core/owl/DoubleMinValue.java trunk/components-core/src/main/java/org/dllearner/kb/sparql/CachingConciseBoundedDescriptionGenerator.java trunk/components-core/src/main/java/org/dllearner/kb/sparql/ConciseBoundedDescriptionGenerator.java trunk/components-core/src/main/java/org/dllearner/kb/sparql/ConciseBoundedDescriptionGeneratorImpl.java trunk/components-core/src/main/java/org/dllearner/kb/sparql/SymmetricConciseBoundedDescriptionGeneratorImpl.java trunk/components-core/src/main/java/org/dllearner/reasoning/FastInstanceChecker.java trunk/components-core/src/main/java/org/dllearner/reasoning/OWLAPIReasoner.java trunk/components-core/src/main/java/org/dllearner/reasoning/SPARQLReasoner.java trunk/components-core/src/main/java/org/dllearner/refinementoperators/RhoDRDown.java trunk/components-core/src/main/java/org/dllearner/refinementoperators/Utility.java trunk/components-core/src/main/java/org/dllearner/utilities/examples/AutomaticNegativeExampleFinderSPARQL2.java trunk/components-core/src/main/java/org/dllearner/utilities/owl/ConceptComparator.java trunk/components-core/src/main/java/org/dllearner/utilities/owl/DescriptionMinimizer.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/DBpediaExperiment.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/ISLETestCorpus.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/ISLETestNoCorpus.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/KnowledgebaseSampleGenerator.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/SemanticBibleExperiment.java Added Paths: ----------- trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/DisjunctiveHeuristic.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionEdge.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionEdgeComparator.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionNode.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionNodeComparator.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionTree.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionTreeComparator.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELHeuristic.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELLearningAlgorithm.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELLearningAlgorithmDisjunctive.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/SearchTreeNode.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/Simulation.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/StableHeuristic.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/TreeAndRoleSet.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/TreeAndRoleSetComparator.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/TreeTuple.java trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/package.html trunk/components-core/src/main/java/org/dllearner/refinementoperators/ELDown3.java Removed Paths: ------------- trunk/components-core/src/main/java/org/dllearner/algorithms/isle/ISLE.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/DBpediaPlainExperiment.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/DBpediaSemanticIndexExperiment.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/DBpediaSyntacticIndexBasedExperiment.java trunk/components-core/src/test/java/org/dllearner/algorithms/isle/Experiment.java Modified: trunk/components-core/src/main/java/org/dllearner/algorithms/celoe/CELOE.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/celoe/CELOE.java 2014-01-21 12:49:51 UTC (rev 4213) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/celoe/CELOE.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -20,12 +20,10 @@ package org.dllearner.algorithms.celoe; import java.io.File; -import java.text.DecimalFormat; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -50,7 +48,6 @@ import org.dllearner.kb.OWLFile; import org.dllearner.learningproblems.ClassLearningProblem; import org.dllearner.learningproblems.PosNegLP; -import org.dllearner.learningproblems.PosNegLPStandard; import org.dllearner.learningproblems.PosOnlyLP; import org.dllearner.reasoning.FastInstanceChecker; import org.dllearner.refinementoperators.CustomHierarchyRefinementOperator; @@ -108,7 +105,6 @@ // all descriptions in the search tree plus those which were too weak (for fast redundancy check) private TreeSet<Description> descriptions; - private EvaluatedDescriptionSet bestEvaluatedDescriptions; // if true, then each solution is evaluated exactly instead of approximately // private boolean exactBestDescriptionEvaluation = false; @@ -140,10 +136,6 @@ private boolean forceMutualDifference = false; // utility variables - private String baseURI; - private Map<String, String> prefixes; - private DecimalFormat dfPercent = new DecimalFormat("0.00%"); - private ConceptComparator descriptionComparator = new ConceptComparator(); // statistical variables private int expressionTests = 0; @@ -305,8 +297,7 @@ } // operator = new RhoDRDown(reasoner, classHierarchy, startClass, configurator); - baseURI = reasoner.getBaseURI(); - prefixes = reasoner.getPrefixes(); + if(writeSearchTree) { File f = new File(searchTreeFile ); Files.clearFile(f); @@ -797,7 +788,7 @@ // check whether the node is a potential solution candidate private Description rewriteNode(OENode node) { Description description = node.getDescription(); - // minimize description (expensive!) - also performes some human friendly rewrites + // minimize description (expensive!) - also performs some human friendly rewrites Description niceDescription; if(useMinimizer) { niceDescription = minimizer.minimizeClone(description); @@ -809,6 +800,21 @@ return niceDescription; } + // check whether the node is a potential solution candidate + private Description rewriteNodeSimple(OENode node) { + Description description = node.getDescription(); + // minimize description (expensive!) - also performs some human friendly rewrites + Description niceDescription; + if(useMinimizer) { + niceDescription = minimizer.minimizeClone(description); + } else { + niceDescription = description; + } + // replace \exists r.\top with \exists r.range(r) which is easier to read for humans + ConceptTransformation.replaceRange(niceDescription, reasoner); + return niceDescription; + } + private boolean terminationCriteriaSatisfied() { return stop || @@ -843,33 +849,12 @@ return startNode; } - // central function for printing description - private String descriptionToString(Description description) { - return description.toManchesterSyntaxString(baseURI, prefixes); - } - @SuppressWarnings("unused") private String bestDescriptionToString() { EvaluatedDescription best = bestEvaluatedDescriptions.getBest(); return best.getDescription().toManchesterSyntaxString(baseURI, prefixes) + " (accuracy: " + dfPercent.format(best.getAccuracy()) + ")"; } - private String getSolutionString() { - int current = 1; - String str = ""; - for(EvaluatedDescription ed : bestEvaluatedDescriptions.getSet().descendingSet()) { - // temporary code - if(learningProblem instanceof PosNegLPStandard) { - str += current + ": " + descriptionToString(ed.getDescription()) + " (pred. acc.: " + dfPercent.format(((PosNegLPStandard)learningProblem).getPredAccuracyOrTooWeakExact(ed.getDescription(),1)) + ", F-measure: "+ dfPercent.format(((PosNegLPStandard)learningProblem).getFMeasureOrTooWeakExact(ed.getDescription(),1)) + ")\n"; - } else { - str += current + ": " + descriptionToString(ed.getDescription()) + " " + dfPercent.format(ed.getAccuracy()) + "\n"; -// System.out.println(ed); - } - current++; - } - return str; - } - // private String getTemporaryString(Description description) { // return descriptionToString(description) + " (pred. acc.: " + dfPercent.format(((PosNegLPStandard)learningProblem).getPredAccuracyOrTooWeakExact(description,1)) + ", F-measure: "+ dfPercent.format(((PosNegLPStandard)learningProblem).getFMeasureOrTooWeakExact(description,1)) + ")"; // } Modified: trunk/components-core/src/main/java/org/dllearner/algorithms/celoe/PCELOE.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/celoe/PCELOE.java 2014-01-21 12:49:51 UTC (rev 4213) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/celoe/PCELOE.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -20,15 +20,12 @@ package org.dllearner.algorithms.celoe; import java.io.File; -import java.text.DecimalFormat; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -41,7 +38,6 @@ import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; -import org.dllearner.algorithms.celoe.PCELOE.Worker; import org.dllearner.core.AbstractCELA; import org.dllearner.core.AbstractKnowledgeSource; import org.dllearner.core.AbstractLearningProblem; @@ -60,7 +56,6 @@ import org.dllearner.kb.OWLFile; import org.dllearner.learningproblems.ClassLearningProblem; import org.dllearner.learningproblems.PosNegLP; -import org.dllearner.learningproblems.PosNegLPStandard; import org.dllearner.learningproblems.PosOnlyLP; import org.dllearner.reasoning.FastInstanceChecker; import org.dllearner.refinementoperators.CustomHierarchyRefinementOperator; @@ -153,11 +148,6 @@ // but it can also suppress quite useful expressions private boolean forceMutualDifference = false; - // utility variables - private String baseURI; - private Map<String, String> prefixes; - private DecimalFormat dfPercent = new DecimalFormat("0.00%"); - private ConceptComparator descriptionComparator = new ConceptComparator(); // statistical variables private int expressionTests = 0; @@ -804,33 +794,12 @@ return startNode; } - // central function for printing description - private String descriptionToString(Description description) { - return description.toManchesterSyntaxString(baseURI, prefixes); - } - @SuppressWarnings("unused") private String bestDescriptionToString() { EvaluatedDescription best = bestEvaluatedDescriptions.getBest(); return best.getDescription().toManchesterSyntaxString(baseURI, prefixes) + " (accuracy: " + dfPercent.format(best.getAccuracy()) + ")"; } - private String getSolutionString() { - int current = 1; - String str = ""; - for(EvaluatedDescription ed : bestEvaluatedDescriptions.getSet().descendingSet()) { - // temporary code - if(learningProblem instanceof PosNegLPStandard) { - str += current + ": " + descriptionToString(ed.getDescription()) + " (pred. acc.: " + dfPercent.format(((PosNegLPStandard)learningProblem).getPredAccuracyOrTooWeakExact(ed.getDescription(),1)) + ", F-measure: "+ dfPercent.format(((PosNegLPStandard)learningProblem).getFMeasureOrTooWeakExact(ed.getDescription(),1)) + ")\n"; - } else { - str += current + ": " + descriptionToString(ed.getDescription()) + " " + dfPercent.format(ed.getAccuracy()) + "\n"; -// System.out.println(ed); - } - current++; - } - return str; - } - // private String getTemporaryString(Description description) { // return descriptionToString(description) + " (pred. acc.: " + dfPercent.format(((PosNegLPStandard)learningProblem).getPredAccuracyOrTooWeakExact(description,1)) + ", F-measure: "+ dfPercent.format(((PosNegLPStandard)learningProblem).getFMeasureOrTooWeakExact(description,1)) + ")"; // } Modified: trunk/components-core/src/main/java/org/dllearner/algorithms/el/ELLearningAlgorithm.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/el/ELLearningAlgorithm.java 2014-01-21 12:49:51 UTC (rev 4213) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/el/ELLearningAlgorithm.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -34,6 +34,9 @@ import org.dllearner.core.config.BooleanEditor; import org.dllearner.core.config.ConfigOption; import org.dllearner.core.owl.Description; +import org.dllearner.core.owl.Nothing; +import org.dllearner.core.owl.ObjectProperty; +import org.dllearner.core.owl.ObjectSomeRestriction; import org.dllearner.core.owl.Thing; import org.dllearner.learningproblems.EvaluatedDescriptionPosNeg; import org.dllearner.learningproblems.PosNegLP; @@ -62,16 +65,22 @@ private boolean isRunning = false; private boolean stop = false; - private double treeSearchTimeSeconds = 1.0; + private double treeSearchTimeSeconds = 10.0; private long treeStartTime; // "instanceBasedDisjoints", "Specifies whether to use real disjointness checks or instance based ones (no common instances) in the refinement operator." @ConfigOption(name="instanceBasedDisjoints", required=false, defaultValue="true", description="Specifies whether to use real disjointness checks or instance based ones (no common instances) in the refinement operator.", propertyEditorClass=BooleanEditor.class) private boolean instanceBasedDisjoints = true; + @ConfigOption(name = "stopOnFirstDefinition", defaultValue="false", description="algorithm will terminate immediately when a correct definition is found") + private boolean stopOnFirstDefinition = false; + + @ConfigOption(name = "noisePercentage", defaultValue="0.0", description="the (approximated) percentage of noise within the examples") + private double noisePercentage = 0.0; + + private double noise; + // a set with limited size (currently the ordering is defined in the class itself) - private EvaluatedDescriptionSet bestEvaluatedDescriptions = new EvaluatedDescriptionSet(AbstractCELA.MAX_NR_OF_RESULTS); - private SearchTreeNode startNode; private ELHeuristic heuristic; private TreeSet<SearchTreeNode> candidates; @@ -80,7 +89,7 @@ } - public ELLearningAlgorithm(PosNegLP problem, AbstractReasonerComponent reasoner) { + public ELLearningAlgorithm(AbstractLearningProblem problem, AbstractReasonerComponent reasoner) { super(problem, reasoner); // configurator = new ELLearningAlgorithmConfigurator(this); } @@ -116,6 +125,8 @@ candidates = new TreeSet<SearchTreeNode>(heuristic); operator = new ELDown2(reasoner, instanceBasedDisjoints); + + noise = noisePercentage/100d; } @Override @@ -151,29 +162,29 @@ } // print solution(s) - logger.info("solution : " + bestEvaluatedDescriptions.getBest() + " [time: " + Helper.prettyPrintNanoSeconds(System.nanoTime()-treeStartTime) + "]"); + logger.info("solutions[time: " + Helper.prettyPrintNanoSeconds(System.nanoTime()-treeStartTime) + "]\n" + getSolutionString()); isRunning = false; } // evaluates a description in tree form private void addDescriptionTree(ELDescriptionTree descriptionTree, SearchTreeNode parentNode) { - // create search tree node SearchTreeNode node = new SearchTreeNode(descriptionTree); // convert tree to standard description Description description = descriptionTree.transformToDescription(); + description = getNiceDescription(description); -// double accuracy = getLearningProblem().getAccuracyOrTooWeak(description, 0); + double accuracy = getLearningProblem().getAccuracyOrTooWeak(description, noise); int negCovers = ((PosNegLP)getLearningProblem()).coveredNegativeExamplesOrTooWeak(description); - if(negCovers == -1) { -// if(accuracy == -1) { +// if(negCovers == -1) { + if(accuracy == -1) { node.setTooWeak(); } else { node.setCoveredNegatives(negCovers); } - +// System.out.println(descriptionTree.transformToDescription() + "|" + negCovers); // link to parent (unless start node) if(parentNode == null) { startNode = node; @@ -205,6 +216,26 @@ } + private Description getNiceDescription(Description d){ + Description description = d.clone(); + List<Description> children = description.getChildren(); + for(int i=0; i<children.size(); i++) { + description.replaceChild(i, getNiceDescription(children.get(i))); + } + if(children.size()==0) { + return description; + } else if(description instanceof ObjectSomeRestriction) { + // \exists r.\bot \equiv \bot + if(description.getChild(0) instanceof Thing) { + Description range = reasoner.getRange((ObjectProperty) ((ObjectSomeRestriction) description).getRole()); + description.replaceChild(0, range); + } else { + description.replaceChild(0, getNiceDescription(description.getChild(0))); + } + } + return description; + } + private boolean stoppingCriteriaSatisfied() { // in some cases, there could be no candidate left ... if(candidates.isEmpty()) { @@ -222,7 +253,7 @@ // stop if we have a node covering all positives and none of the negatives SearchTreeNode bestNode = candidates.last(); - return (bestNode.getCoveredNegatives() == 0); + return stopOnFirstDefinition && (bestNode.getCoveredNegatives() == 0); } private void reset() { @@ -270,11 +301,40 @@ return bestEvaluatedDescriptions.getSet(); } + /** + * @param stopOnFirstDefinition the stopOnFirstDefinition to set + */ + public void setStopOnFirstDefinition(boolean stopOnFirstDefinition) { + this.stopOnFirstDefinition = stopOnFirstDefinition; + } + + /** + * @return the stopOnFirstDefinition + */ + public boolean isStopOnFirstDefinition() { + return stopOnFirstDefinition; + } + + /** * @return the startNode */ public SearchTreeNode getStartNode() { return startNode; } + + /** + * @return the noisePercentage + */ + public double getNoisePercentage() { + return noisePercentage; + } + + /** + * @param noisePercentage the noisePercentage to set + */ + public void setNoisePercentage(double noisePercentage) { + this.noisePercentage = noisePercentage; + } } Modified: trunk/components-core/src/main/java/org/dllearner/algorithms/el/ELLearningAlgorithmDisjunctive.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/el/ELLearningAlgorithmDisjunctive.java 2014-01-21 12:49:51 UTC (rev 4213) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/el/ELLearningAlgorithmDisjunctive.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -130,7 +130,7 @@ } - public ELLearningAlgorithmDisjunctive(PosNegLP problem, AbstractReasonerComponent reasoner) { + public ELLearningAlgorithmDisjunctive(AbstractLearningProblem problem, AbstractReasonerComponent reasoner) { super(problem, reasoner); } Added: trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/DisjunctiveHeuristic.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/DisjunctiveHeuristic.java (rev 0) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/DisjunctiveHeuristic.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -0,0 +1,38 @@ +/** + * 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.algorithms.elcopy; + +public class DisjunctiveHeuristic implements ELHeuristic { + + ELDescriptionTreeComparator edt = new ELDescriptionTreeComparator(); + + public int compare(SearchTreeNode tree1, SearchTreeNode tree2) { + double diff = tree1.getScore()-tree2.getScore(); + if(diff < 0.00001 && diff > -0.00001) { + return edt.compare(tree1.getDescriptionTree(), tree2.getDescriptionTree()); + } else if(diff > 0){ + return 1; +// return (int)Math.signum(diff); + } else { + return -1; + } + } + +} Added: trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionEdge.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionEdge.java (rev 0) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionEdge.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -0,0 +1,79 @@ +/** + * 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.algorithms.elcopy; + +import org.dllearner.core.owl.ObjectProperty; +import org.dllearner.core.owl.Property; + +/** + * A (directed) edge in an EL description tree. It consists of an edge + * label, which is an object property, and the EL description tree + * the edge points to. + * + * @author Jens Lehmann + * + */ +public class ELDescriptionEdge { + + private Property label; + + private ELDescriptionNode node; + + /** + * Constructs and edge given a label and an EL description tree. + * @param label The label of this edge. + * @param tree The tree the edge points to (edges are directed). + */ + public ELDescriptionEdge(Property label, ELDescriptionNode tree) { + this.label = label; + this.node = tree; + } + + /** + * @param label the label to set + */ + public void setLabel(Property label) { + this.label = label; + } + + /** + * @return The label of this edge. + */ + public Property getLabel() { + return label; + } + + /** + * @return The EL description tree + */ + public ELDescriptionNode getNode() { + return node; + } + + public boolean isObjectProperty(){ + return label instanceof ObjectProperty; + } + + @Override + public String toString() { + return "--" + label + "--> " + node.toDescriptionString(); + } + +} Added: trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionEdgeComparator.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionEdgeComparator.java (rev 0) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionEdgeComparator.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -0,0 +1,47 @@ +/** + * 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.algorithms.elcopy; + +import java.util.Comparator; + +/** + * @author Jens Lehmann + * + */ +public class ELDescriptionEdgeComparator implements Comparator<ELDescriptionEdge> { + + private ELDescriptionNodeComparator nodeComp; + + public ELDescriptionEdgeComparator() { + nodeComp = new ELDescriptionNodeComparator(); + } + + @Override + public int compare(ELDescriptionEdge edge1, ELDescriptionEdge edge2) { + // perform string comparison on node labels + int comp = edge1.getLabel().getURI().compareTo(edge2.getLabel().getURI()); + if(comp==0) { + return nodeComp.compare(edge1.getNode(), edge2.getNode()); + } else { + return comp; + } + } + +} Added: trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionNode.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionNode.java (rev 0) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionNode.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -0,0 +1,768 @@ +/** + * 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.algorithms.elcopy; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.NavigableSet; +import java.util.Set; +import java.util.TreeSet; + +import org.dllearner.core.owl.DataRange; +import org.dllearner.core.owl.DatatypeProperty; +import org.dllearner.core.owl.DatatypeSomeRestriction; +import org.dllearner.core.owl.Description; +import org.dllearner.core.owl.Intersection; +import org.dllearner.core.owl.NamedClass; +import org.dllearner.core.owl.ObjectProperty; +import org.dllearner.core.owl.ObjectPropertyExpression; +import org.dllearner.core.owl.ObjectSomeRestriction; +import org.dllearner.core.owl.Property; +import org.dllearner.core.owl.Thing; + +/** + * Represents an EL description tree, which corresponds to a + * description in the EL description logic. Note that an EL description tree + * can be a subtree of another EL description tree. In general, + * an EL description tree is a tree where the node label is a set + * of named classes and the edges are labelled with a property. + * + * In the documentation below "this node" refers to the root node + * of this EL description (sub-)tree. One tree cannot be reused, + * i.e. used as subtree in several description trees, as some of + * the associated variables (level, simulation) depend on the overall + * tree. + * + * @author Jens Lehmann + * + */ +@SuppressWarnings("unused") +public class ELDescriptionNode { + + // the reference tree for storing values, must not be null + protected ELDescriptionTree tree; + + protected TreeSet<NamedClass> label = new TreeSet<NamedClass>(); + + protected List<ELDescriptionEdge> edges = new LinkedList<ELDescriptionEdge>(); + + protected int level; + + // parent node in the tree; + // null indicates that this node is a root node + protected ELDescriptionNode parent = null; + + // simulation information (list or set?) + protected Set<ELDescriptionNode> in = new HashSet<ELDescriptionNode>(); + protected Set<ELDescriptionNode> inSC1 = new HashSet<ELDescriptionNode>(); + protected Set<ELDescriptionNode> inSC2 = new HashSet<ELDescriptionNode>(); + protected Set<ELDescriptionNode> out = new HashSet<ELDescriptionNode>(); + protected Set<ELDescriptionNode> outSC1 = new HashSet<ELDescriptionNode>(); + protected Set<ELDescriptionNode> outSC2 = new HashSet<ELDescriptionNode>(); + + protected boolean isClassNode; + protected DataRange dataRange; + + /** + * Internal constructor used for cloning nodes. + */ + protected ELDescriptionNode() { + + } + + /** + * Constructs an EL description tree with empty root label. + */ + public ELDescriptionNode(ELDescriptionTree tree) { + this(tree, new TreeSet<NamedClass>()); + } + + // convenience constructor + public ELDescriptionNode(ELDescriptionTree tree, NamedClass... label) { + this(tree, new TreeSet<NamedClass>(Arrays.asList(label))); + } + + /** + * Constructs an EL description tree given its root label. + * @param label Label of the root node. + */ + public ELDescriptionNode(ELDescriptionTree tree, TreeSet<NamedClass> label) { + this.label = label; + this.edges = new LinkedList<ELDescriptionEdge>(); + this.tree = tree; + level = 1; + parent = null; + // this is the root node of the overall tree + tree.rootNode = this; + tree.addNodeToLevel(this, level); + tree.size += label.size(); + + isClassNode = true; + } + + /** + * Constructs an EL description tree given its root label. + * @param label Label of the root node. + */ + public ELDescriptionNode(ELDescriptionTree tree, DataRange dataRange) { + this.dataRange = dataRange; + this.edges = new LinkedList<ELDescriptionEdge>(); + this.tree = tree; + level = 1; + parent = null; + // this is the root node of the overall tree + tree.rootNode = this; + tree.addNodeToLevel(this, level); + tree.size += label.size(); + + isClassNode = false; + } + + // convenience constructor + public ELDescriptionNode(ELDescriptionNode parentNode, Property parentProperty, NamedClass... label) { + this(parentNode, parentProperty, new TreeSet<NamedClass>(Arrays.asList(label))); + } + + public ELDescriptionNode(ELDescriptionNode parentNode, Property parentProperty, Set<NamedClass> label) { +// this.label = label; + // we first need to add the edge and update the simulation and then add + // all classes iteratively to the label (each time updating the simulation again) + this.edges = new LinkedList<ELDescriptionEdge>(); + parent = parentNode; + // the reference tree is the same as for the parent tree + tree = parentNode.tree; + // level increases by 1 + level = parentNode.level + 1; + // we add an edge from the parent to this node + ELDescriptionEdge edge = new ELDescriptionEdge(parentProperty, this); + parent.edges.add(edge); + // we need to update the set of nodes on a particular level + tree.addNodeToLevel(this, level); + + // simulation update +// Monitor mon = MonitorFactory.start("simulation update"); + // the nodes, which need to be updated + Set<ELDescriptionNode> update = new HashSet<ELDescriptionNode>(); + + // loop over all nodes on the same level, which are not in the in set + Set<ELDescriptionNode> nodes = tree.getNodesOnLevel(level); + for(ELDescriptionNode w : nodes) { + // to save space, we do not add reflexive relations + if(w != this) { + // (w,v') is automatically added + tree.extendSimulation(w, this); + + // check conditions for (v',w) + boolean sc1 = false, sc2 = false; + + if(w.label.size() == 0) { + tree.extendSimulationSC1(this, w); + sc1 = true; + } + + if(w.edges.size() == 0) { + tree.extendSimulationSC2(this, w); + sc2 = true; + } + + if(sc1 && sc2) { + tree.extendSimulationSC12(this, w); + } + + update.add(w.parent); + } + } + update.add(this.parent); + +// if(inSC1.contains(w) && tree.checkSC2(this, w)) { +// tree.extendSimulation(this, w); +// update.add(w.parent); +// } + + // loop over all nodes in out set +// for(ELDescriptionNode w : out) { +// if(!tree.checkSC1(this, w)) { +// tree.shrinkSimulation(this, w); +// update.add(w.parent); +// } +// } + +// System.out.println(update); + + // apply updates recursively top-down + tree.updateSimulation(update); +// mon.stop(); + + // add all classes in label + for(NamedClass nc : label) { + extendLabel(nc); + } + + // 1 for the edge (labels are already taken care of by extendLabel) + tree.size += 1; + + isClassNode = true; + } + + public ELDescriptionNode(ELDescriptionNode parentNode, Property parentProperty, DataRange dataRange) { + this.dataRange = dataRange; + // this.label = label; + // we first need to add the edge and update the simulation and then add + // all classes iteratively to the label (each time updating the simulation again) + this.edges = new LinkedList<ELDescriptionEdge>(); + parent = parentNode; + // the reference tree is the same as for the parent tree + tree = parentNode.tree; + // level increases by 1 + level = parentNode.level + 1; + // we add an edge from the parent to this node + ELDescriptionEdge edge = new ELDescriptionEdge(parentProperty, this); + parent.edges.add(edge); + // we need to update the set of nodes on a particular level + tree.addNodeToLevel(this, level); + + // simulation update +// Monitor mon = MonitorFactory.start("simulation update"); + // the nodes, which need to be updated + Set<ELDescriptionNode> update = new HashSet<ELDescriptionNode>(); + + // loop over all nodes on the same level, which are not in the in set + Set<ELDescriptionNode> nodes = tree.getNodesOnLevel(level); + for(ELDescriptionNode w : nodes) { + // to save space, we do not add reflexive relations + if(w != this) { + // (w,v') is automatically added + tree.extendSimulation(w, this); + + // check conditions for (v',w) + boolean sc1 = false, sc2 = false; + + if(w.label.size() == 0) { + tree.extendSimulationSC1(this, w); + sc1 = true; + } + + if(w.edges.size() == 0) { + tree.extendSimulationSC2(this, w); + sc2 = true; + } + + if(sc1 && sc2) { + tree.extendSimulationSC12(this, w); + } + + update.add(w.parent); + } + } + update.add(this.parent); + +// if(inSC1.contains(w) && tree.checkSC2(this, w)) { +// tree.extendSimulation(this, w); +// update.add(w.parent); +// } + + // loop over all nodes in out set +// for(ELDescriptionNode w : out) { +// if(!tree.checkSC1(this, w)) { +// tree.shrinkSimulation(this, w); +// update.add(w.parent); +// } +// } + +// System.out.println(update); + + // apply updates recursively top-down + tree.updateSimulation(update); +// mon.stop(); + + + // 1 for the edge (labels are already taken care of by extendLabel) + tree.size += 1; + + isClassNode = false; + } + + /** + * @return the isClassNode + */ + public boolean isClassNode() { + return isClassNode; + } + + /** + * @return the dataRange + */ + public DataRange getDataRange() { + return dataRange; + } + + + /** + * Constructs an EL description tree given its root label and edges. + * @param label Label of the root node. + * @param edges Edges connected to the root node. + */ +// TODO: probably delete as this constructor is not straightforward to +// implement within the new structure +// public ELDescriptionNode(SortedSet<NamedClass> label, List<ELDescriptionEdge> edges) { +// this.label = label; +// this.edges = edges; +// } + + /** + * Checks whether this node has a parent. If the parent link + * is null, the node is considered to be a root node. + * @return True of this is the root node and false otherwise. + */ + public boolean isRoot() { + return parent == null; + } + + /** + * Traverses the EL description tree upwards until it finds + * the root and returns it. + * @return The root node of this EL description tree. + */ + public ELDescriptionNode getRoot() { + ELDescriptionNode root = this; + while(root.parent != null) { + root = parent; + } + return root; + } + + /** + * Traverses the tree until the root node and counts how + * many edges are traversed. If this node does not have a parent, + * zero is returned. This method is used for checking the integrity + * of the tree in unit tests. Use {@link #getLevel()} to get the + * level of the tree. + * @return The level of this node (or more specifically the root + * node of this subtree) within the overall EL description tree. + */ + public int computeLevel() { + ELDescriptionNode root = this; + int level = 0; + while(root.parent != null) { + root = parent; + level++; + } + return level; + } + + /** + * This method transform the tree to an EL description. The + * node labels are transformed to an {@link Intersection} + * of {@link NamedClass}. Each edge is transformed to an + * {@link ObjectSomeRestriction}, where the property is the edge + * label and the child description the subtree the edge points + * to. Edges are also added to the intersection. If the intersection + * is empty, {@link Thing} is returned. + * @return The description corresponding to this EL description tree. + */ + public Description transformToDescription() { + int nrOfElements = label.size() + edges.size(); + // leaf labeled with \emptyset stands for owl:Thing + if(nrOfElements == 0) { + return new Thing(); + // we want to avoid intersections with only 1 element, so in this + // case we return either the NamedClass or ObjectSomeRestriction directly + } else if(nrOfElements == 1) { + if(label.size()==1) { + return label.first(); + } else { + ELDescriptionEdge edge = edges.get(0); + if(edge.isObjectProperty()){ + Description child = edge.getNode().transformToDescription(); + return new ObjectSomeRestriction((ObjectProperty) edge.getLabel(), child); + } else { + DataRange range = edge.getNode().getDataRange(); + return new DatatypeSomeRestriction((DatatypeProperty) edge.getLabel(), range); + } + + } + // return an intersection of labels and edges + } else { + Intersection is = new Intersection(); + for(NamedClass nc : label) { + is.addChild(nc); + } + for(ELDescriptionEdge edge : edges) { + if(edge.isObjectProperty()){ + Description child = edge.getNode().transformToDescription(); + ObjectSomeRestriction osr = new ObjectSomeRestriction((ObjectProperty) edge.getLabel(),child); + is.addChild(osr); + } else { + DataRange range = edge.getNode().getDataRange(); + DatatypeSomeRestriction dsr = new DatatypeSomeRestriction((DatatypeProperty) edge.getLabel(), range); + is.addChild(dsr); + } + } + return is; + } + } + + /** + * Gets a list describing the position of this node within the + * tree. If the list is e.g. [2,5,1], then the node can be reached + * by picking the second child of the root node, then picking the + * 5th child of this node and finally selecting the first child of + * the previous node. + * @return The position number of this node within the tree as described above. + */ + public int[] getCurrentPosition() { + int[] position = new int[level-1]; + ELDescriptionNode root = this; + while(root.parent != null) { + position[root.level-2] = root.getChildNumber(); + root = root.parent; + } + return position; + } + + // returns the child number of this node, i.e. whether it is + // the first, second, third etc. child; + // TODO: might be a bit faster to store this explicitly + private int getChildNumber() { + int count = 0; + for(ELDescriptionEdge edge : parent.edges) { + if(edge.getNode() == this) { + return count; + } + count++; + } + throw new RuntimeException("Inconsistent tree. Child tree not reachable from parent."); + } + + /** + * Replaces an entry in the node label. + * @param oldClass Class to remove from label. + * @param newClass Class to add to label. + */ + public void replaceInLabel(NamedClass oldClass, NamedClass newClass) { + label.remove(oldClass); + label.add(newClass); + labelSimulationUpdate(); + } + + /** + * Adds an entry to the node label. + * @param newClass Class to add to label. + */ + public void extendLabel(NamedClass newClass) { + label.add(newClass); + labelSimulationUpdate(); + tree.size += 1; +// System.out.println(tree); +// System.out.println(tree.size); + } + + // simulation update when extending or refining label + // (same in both cases) + private void labelSimulationUpdate() { +// Monitor mon = MonitorFactory.start("simulation update"); + // compute the nodes, which need to be updated + Set<ELDescriptionNode> update = new HashSet<ELDescriptionNode>(); + + Set<ELDescriptionNode> tmp = tree.getNodesOnLevel(level); + for(ELDescriptionNode w : tmp) { + if(w != this) { + // SC1(v,w) can only change from false to true + if(!inSC1.contains(w) && tree.checkSC1(this, w)) { + tree.extendSimulationSC1(this, w); + if(inSC2.contains(w)) { + tree.extendSimulationSC12(this, w); + } + update.add(w.getParent()); + } + // SC1(w,v) can only change from true to false + if(outSC1.contains(w) && !tree.checkSC1(w, this)) { + tree.shrinkSimulationSC1(w, this); + if(outSC2.contains(w)) { + tree.shrinkSimulationSC12(w, this); + } + update.add(w.getParent()); + } + } + } + if(parent != null) { + update.add(parent); + } + + /* + // loop over all nodes on the same level, which are not in the in set + Set<ELDescriptionNode> tmp = new HashSet<ELDescriptionNode>(tree.getNodesOnLevel(level)); + tmp.removeAll(in); + for(ELDescriptionNode w : tmp) { + if(w != this) { + // we only need to recompute SC1 + if(inSC1.contains(w) && tree.checkSC2(this, w)) { + System.out.println("satisfied"); + tree.extendSimulation(this, w); + update.add(w.parent); + } + } + } + + // loop over all nodes in out set (we make a copy, because out + // is potentially modified, so we cannot safely iterate over it) + tmp = new HashSet<ELDescriptionNode>(out); + for(ELDescriptionNode w : tmp) { + if(w != this) { + if(!tree.checkSC1(w, this)) { +// tree.shrinkSimulation(w, this); + tree.shrinkSimulationSC1(w, this); + tree.shrinkSimulationSC12(w, this); + update.add(w.parent); + } + } + } + */ + + // apply updates recursively top-down + tree.updateSimulation(update); +// mon.stop(); + } + + public void refineEdge(int edgeNumber, Property op) { + edges.get(edgeNumber).setLabel(op); + +// Monitor mon = MonitorFactory.start("simulation update"); + // compute the nodes, which need to be updated + Set<ELDescriptionNode> update = new HashSet<ELDescriptionNode>(); + update.add(this); + + /* + // loop over all nodes on the same level, which are not in the in set + Set<ELDescriptionNode> tmp = new HashSet<ELDescriptionNode>(tree.getNodesOnLevel(level)); + tmp.removeAll(in); + for(ELDescriptionNode w : tmp) { + if(w != this) { + // we only need to recompute SC1 + if(inSC2.contains(w) && tree.checkSC1(this, w)) { + tree.extendSimulation(this, w); + update.add(w.parent); + } + } + } + + // loop over all nodes in out set + for(ELDescriptionNode w : out) { + if(w != this) { + if(!tree.checkSC2(this, w)) { + tree.shrinkSimulation(this, w); + update.add(w.parent); + } + } + } + */ + +// update.add(this.parent); + + // apply updates recursively top-down + tree.updateSimulation(update); +// mon.stop(); + } + + /** + * Gets the label of this node. Do not modify the returned object, + * but use the provided methods instead! + * @return The label of root node of this subtree. + */ + public NavigableSet<NamedClass> getLabel() { + return label; + } + + /** + * Gets the edges of this node. Do not modify the + * returned object, but use the provided methods instead! + * @return The outgoing edges of this subtree. + */ + public List<ELDescriptionEdge> getEdges() { + return edges; + } + + /** + * Gets the level (distance from root) of this node. The root node + * has level 1. + * @return The level of the (root node of) this subtree in the overall tree. + */ + public int getLevel() { + return level; + } + + @Override + public String toString() { + return toString(0); + } + + private String toString(int indent) { + String indentString = ""; + for(int i=0; i<indent; i++) + indentString += " "; + + String str = indentString + label.toString() + "\n"; + for(ELDescriptionEdge edge : edges) { + str += indentString + "-- " + edge.getLabel() + " -->\n"; + str += edge.getNode().toString(indent + 2); + } + return str; + } + + public String toDescriptionString() { + String str = ""; + if(isClassNode()){ + if(label.isEmpty()) { + str = "TOP"; + } else { + Iterator<NamedClass> it = label.iterator(); + while(it.hasNext()) { + NamedClass nc = it.next(); + if(it.hasNext()) { + str += nc.toString() + " AND "; + } else { + str += nc.toString(); + } + } + } + } else { + str += dataRange; + } + for(ELDescriptionEdge edge : edges) { + str += " AND EXISTS " + edge.getLabel().toString() + ".("; + str += edge.getNode().toDescriptionString() + ")"; + } + return str; + } + + private String toDescriptionString(Set<ELDescriptionNode> nodes) { + String str = ""; + // comma separated list of descriptions + for(ELDescriptionNode node : nodes) { + str += node.toDescriptionString() + ","; + } + // remove last comma + if(str.length() > 0) { + str = str.substring(0, str.length()-1); + } + return str; + } + + public String toSimulationString() { + String str = ""; + str += "in: " + toDescriptionString(in) + "\n"; + str += "inSC1: " + toDescriptionString(inSC1) + "\n"; + str += "inSC2: " + toDescriptionString(inSC2) + "\n"; + str += "out: " + toDescriptionString(out) + "\n"; + str += "outSC1: " + toDescriptionString(outSC1) + "\n"; + str += "outSC2: " + toDescriptionString(outSC2) + "\n"; + return str; + } + + /** + * A convenience method (for debugging purposes) to get a comma separated list of nodes, where the + * nodes are given names (to make them readable). + * @param nodes The node objects. + * @param nodeNames A mapping to node names. + * @return A comma separated list of the node names. + */ + public static String toString(Set<ELDescriptionNode> nodes, Map<ELDescriptionNode,String> nodeNames) { + String str = ""; + // comma separated list of descriptions + for(ELDescriptionNode node : nodes) { + str += nodeNames.get(node) + ","; + } + // remove last comma + if(str.length() > 0) { + str = str.substring(0, str.length()-1); + } + return str; + } + + public String toSimulationString(Map<ELDescriptionNode,String> nodeNames) { + String str = ""; + str += " in: " + toString(in, nodeNames) + "\n"; + str += " inSC1: " + toString(inSC1, nodeNames) + "\n"; + str += " inSC2: " + toString(inSC2, nodeNames) + "\n"; + str += " out: " + toString(out, nodeNames) + "\n"; + str += " outSC1: " + toString(outSC1, nodeNames) + "\n"; + str += " outSC2: " + toString(outSC2, nodeNames) + "\n"; + return str; + } + + public ELDescriptionNode getParent() { + return parent; + } + + public ELDescriptionEdge getParentEdge() { + int childNr = getChildNumber(); + return parent.edges.get(childNr); + } + + /** + * @return the in + */ + public Set<ELDescriptionNode> getIn() { + return in; + } + + /** + * @return the inSC1 + */ + public Set<ELDescriptionNode> getInSC1() { + return inSC1; + } + + /** + * @return the inSC2 + */ + public Set<ELDescriptionNode> getInSC2() { + return inSC2; + } + + /** + * @return the out + */ + public Set<ELDescriptionNode> getOut() { + return out; + } + + /** + * @return the outSC1 + */ + public Set<ELDescriptionNode> getOutSC1() { + return outSC1; + } + + /** + * @return the outSC2 + */ + public Set<ELDescriptionNode> getOutSC2() { + return outSC2; + } + + public ELDescriptionTree getTree() { + return tree; + } +} Added: trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionNodeComparator.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionNodeComparator.java (rev 0) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionNodeComparator.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -0,0 +1,103 @@ +/** + * 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.algorithms.elcopy; + +import java.util.Comparator; +import java.util.Iterator; + +import org.dllearner.core.owl.NamedClass; +import org.dllearner.core.owl.Property; + +/** + * Compares two EL description trees. It is a lexicographic order + * according to the following criteria: + * - number of children + * - size of label + * - string comparison for each class in the label + * - recursive call on each child (first compare edge label, then child node) + * + * @author Jens Lehmann + * + */ +public class ELDescriptionNodeComparator implements Comparator<ELDescriptionNode> { + + /* (non-Javadoc) + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @Override + public int compare(ELDescriptionNode node1, ELDescriptionNode node2) { + int nrOfChildren1 = node1.getEdges().size(); + int nrOfChildren2 = node2.getEdges().size(); + if(nrOfChildren1 > nrOfChildren2) { + return 1; + } else if(nrOfChildren1 < nrOfChildren2) { + return -1; + } else { + int labelSize1 = node1.getLabel().size(); + int labelSize2 = node2.getLabel().size(); + if(labelSize1 > labelSize2) { + return 1; + } else if(labelSize1 < labelSize2) { + return -1; + } else { + int compare = 0; + if(node1.isClassNode() && node2.isClassNode()){ + // navigate through both labels + Iterator<NamedClass> it1 = node1.getLabel().descendingIterator(); + Iterator<NamedClass> it2 = node2.getLabel().descendingIterator(); + while(it1.hasNext()) { + NamedClass nc1 = it1.next(); + NamedClass nc2 = it2.next(); + compare = nc1.getName().compareTo(nc2.getName()); + + } + } else if(!node1.isClassNode() && !node2.isClassNode()){ + compare = node1.getDataRange().toString().compareTo(node2.getDataRange().toString()); + } else { + compare = -1; + } + + if(compare != 0) + return compare; + + // recursively compare all edges + for(int i=0; i<nrOfChildren1; i++) { + // compare by edge name + Property op1 = node1.getEdges().get(i).getLabel(); + Property op2 = node2.getEdges().get(i).getLabel(); + int compare1 = op1.getName().compareTo(op2.getName()); + if(compare1 != 0) + return compare1; + + // compare child nodes + ELDescriptionNode child1 = node1.getEdges().get(i).getNode(); + ELDescriptionNode child2 = node2.getEdges().get(i).getNode(); + int compare2 = compare(child1, child2); + if(compare2 != 0) + return compare2; + } + + // trees are identical + return 0; + } + } + } + +} Added: trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionTree.java =================================================================== --- trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionTree.java (rev 0) +++ trunk/components-core/src/main/java/org/dllearner/algorithms/elcopy/ELDescriptionTree.java 2014-01-29 14:24:16 UTC (rev 4214) @@ -0,0 +1,621 @@ +/** + * 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.algorithms.elcopy; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableSet; +import java.util.Set; +import java.util.TreeSet; + +import org.apache.log4j.Logger; +import org.dllearner.core.AbstractReasonerComponent; +import org.dllearner.core.owl.ClassHierarchy; +import org.dllearner.core.owl.DatatypeProperty; +import org.dllearner.core.owl.DatatypeSomeRestriction; +import org.dllearner.core.owl.Description; +import org.dllearner.core.owl.Intersection; +import org.dllearner.core.owl.NamedClass; +import org.dllearner.core.owl.ObjectProperty; +import org.dllearner.core.owl.ObjectPropertyHierarchy; +import org.dllearner.core.owl.ObjectSomeRestriction; +import org.dllearner.core.owl.Property; +import org.dllearner.core.owl.Thing; +import org.dllearner.core.owl.UnsupportedLanguageException; + +/** + * Represents an EL description tree. Unlike {@link ELDescriptionNode}, this is + * a tree-wide structure, i.e. it does not implement the tree structure itself, + * but is used to store information about the tree. + * + * @author Jens Lehmann + * + */ +public class ELDescriptionTree implements Cloneable { + + @SuppressWarnings("unused") + private static Logger logger = Logger.getLogger(ELDescriptionTree.class); + + // to simplify equivalence checks and minimisation, we + // attach a simulation relation to the description tree + // private Simulation simulation; + + // max level = 0 means that there is no tree at all + // (max level = 1 means the root node exists) + private int maxLevel = 0; + + protected int size = 1; + + protected ELDescriptionNode rootNode; + + // the set of all nodes in the tree + private Collection<ELDescriptionNode> nodes = new LinkedList<ELDescriptionNode>(); + + // nodes on a given level of the tree + private Map<Integer, Set<ELDescriptionNode>> levelNodeMapping = new HashMap<Integer, Set<ELDescriptionNode>>(); + + // the background knowledge (we need to have it explicitly here, + // since we store simulation information in the tree and simulation + // updates depend on background knowledge) + protected AbstractReasonerComponent rs; + protected ClassHierarchy subsumptionHierarchy; + protected ObjectPropertyHierarchy roleHierarchy; + + public ELDescriptionTree(AbstractReasonerComponent rs) { + this.rs = rs; + subsumptionHierarchy = rs.getClassHierarchy(); + roleHierarchy = rs.getObjectPropertyHierarchy(); + } + + /** + * Constructs an EL description tree from an EL description. + * + * @param description + * A description + */ + public ELDescriptionTree(AbstractReasonerComponent rs, Description description) { + this(rs); + // construct root node and recursively build the tree + rootNode = new ELDescriptionNode(this); + constructTree(description, rootNode); + } + + private void constructTree(Description description, ELDescriptionNode node) { + if (description instanceof NamedClass) { + node.extendLabel((NamedClass) description); + } else if (description instanceof ObjectSomeRestriction) { + ObjectProperty op = (ObjectProperty) ((ObjectSomeRestriction) description).getRole(); + ELDescriptionNode newNode = new ELDescriptionNode(node, op, new TreeSet<NamedClass>()); + constructTree(description.getChild(0), newNode); + } else if (description instanceof DatatypeSomeRestriction) { + DatatypeProperty op = (DatatypeProperty) ((DatatypeSomeRestriction) description).getRole(); + ELDescriptionNode newNode = new ELDescriptionNode(node, op, ((DatatypeSomeRestriction) description).getDataRange()); + } else if (description instanceof Thing) { + // nothing needs to be done as an empty set is owl:Thing + } else if (description instanceof Intersection) { + // loop through all elements of the intersection + for (Description child : description.getChildren()) { + if (child instanceof NamedClass) { + node.extendLabel((NamedClass) child); + } else if (child instanceof ObjectSomeRestriction) { + ObjectProperty op = (ObjectProperty) ((ObjectSomeRestriction) child).getRole(); + ELDescriptionNode newNode = new ELDescriptionNode(node, op, + new TreeSet<NamedClass>()); + constructTree(child.getChild(0), newNode); + } else { + throw new UnsupportedLanguageException(description + " specifically " + child, + "EL"); + } + } + } else { + throw new UnsupportedLanguageException(description.toString(), "EL"); + } + } + + /** + * Gets the nodes on a specific level of the tree. This information is + * cached here for performance reasons. + * + * @param level + * ... [truncated message content] |