From: <jen...@us...> - 2008-08-14 19:12:52
|
Revision: 1078 http://dl-learner.svn.sourceforge.net/dl-learner/?rev=1078&view=rev Author: jenslehmann Date: 2008-08-14 19:12:46 +0000 (Thu, 14 Aug 2008) Log Message: ----------- - more unit tests for EL refinement operator - comparator for EL description trees - some bug fixes Modified Paths: -------------- trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionNode.java trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionTree.java trunk/src/dl-learner/org/dllearner/core/owl/KB.java trunk/src/dl-learner/org/dllearner/core/owl/ObjectPropertyDomainAxiom.java trunk/src/dl-learner/org/dllearner/core/owl/ObjectPropertyRangeAxiom.java trunk/src/dl-learner/org/dllearner/reasoning/FastInstanceChecker.java trunk/src/dl-learner/org/dllearner/refinementoperators/ELDown.java trunk/src/dl-learner/org/dllearner/test/junit/ELDescriptionTreeTests.java trunk/src/dl-learner/org/dllearner/test/junit/ELDownTests.java Added Paths: ----------- trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionNodeComparator.java trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionTreeComparator.java Modified: trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionNode.java =================================================================== --- trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionNode.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionNode.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -19,8 +19,10 @@ */ package org.dllearner.algorithms.el; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.NavigableSet; import java.util.SortedSet; import java.util.TreeSet; @@ -47,12 +49,13 @@ * @author Jens Lehmann * */ +@SuppressWarnings("unused") public class ELDescriptionNode { // the reference tree for storing values, must not be null private ELDescriptionTree tree; - private SortedSet<NamedClass> label; + private NavigableSet<NamedClass> label; private List<ELDescriptionEdge> edges; @@ -62,6 +65,14 @@ // null indicates that this node is a root node private ELDescriptionNode parent = null; + // simulation information (list or set?) + private List<ELDescriptionNode> in = new ArrayList<ELDescriptionNode>(); + private List<ELDescriptionNode> inSC1 = new ArrayList<ELDescriptionNode>(); + private List<ELDescriptionNode> inSC2 = new ArrayList<ELDescriptionNode>(); + private List<ELDescriptionNode> out = new ArrayList<ELDescriptionNode>(); + private List<ELDescriptionNode> outSC1 = new ArrayList<ELDescriptionNode>(); + private List<ELDescriptionNode> outSC2 = new ArrayList<ELDescriptionNode>(); + /** * Constructs an EL description tree with empty root label. */ @@ -73,15 +84,17 @@ * Constructs an EL description tree given its root label. * @param label Label of the root node. */ - public ELDescriptionNode(ELDescriptionTree tree, SortedSet<NamedClass> label) { + public ELDescriptionNode(ELDescriptionTree tree, NavigableSet<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; } - public ELDescriptionNode(ELDescriptionNode parentNode, ObjectProperty parentProperty, SortedSet<NamedClass> label) { + public ELDescriptionNode(ELDescriptionNode parentNode, ObjectProperty parentProperty, NavigableSet<NamedClass> label) { this.label = label; this.edges = new LinkedList<ELDescriptionEdge>(); parent = parentNode; @@ -185,11 +198,11 @@ * @return The position number of this node within the tree as described above. */ public int[] getCurrentPosition() { - int[] position = new int[level]; + int[] position = new int[level-1]; ELDescriptionNode root = this; while(root.parent != null) { - position[root.level-1] = getChildNumber(); - root = parent; + position[root.level-2] = getChildNumber(); + root = root.parent; } return position; } @@ -229,7 +242,7 @@ * but use the provided methods instead! * @return The label of root node of this subtree. */ - public SortedSet<NamedClass> getLabel() { + public NavigableSet<NamedClass> getLabel() { return label; } @@ -243,11 +256,29 @@ } /** - * Gets the level (distance from root) of this node. + * 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.getTree().toString(indent + 2); + } + return str; + } } Added: trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionNodeComparator.java =================================================================== --- trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionNodeComparator.java (rev 0) +++ trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionNodeComparator.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -0,0 +1,94 @@ +/** + * 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.algorithms.el; + +import java.util.Comparator; +import java.util.Iterator; + +import org.dllearner.core.owl.NamedClass; +import org.dllearner.core.owl.ObjectProperty; + +/** + * 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 { + // 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(); + int compare = nc1.getName().compareTo(nc2.getName()); + if(compare != 0) + return compare; + } + + // recursively compare all edges + for(int i=0; i<nrOfChildren1; i++) { + // compare by edge name + ObjectProperty op1 = node1.getEdges().get(i).getLabel(); + ObjectProperty op2 = node2.getEdges().get(i).getLabel(); + int compare = op1.getName().compareTo(op2.getName()); + if(compare != 0) + return compare; + + // compare child nodes + ELDescriptionNode child1 = node1.getEdges().get(i).getTree(); + ELDescriptionNode child2 = node2.getEdges().get(i).getTree(); + int compare2 = compare(child1, child2); + if(compare2 != 0) + return compare2; + } + + // trees are identical + return 0; + } + } + } + +} Modified: trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionTree.java =================================================================== --- trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionTree.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionTree.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -26,7 +26,11 @@ import java.util.TreeSet; 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.ObjectSomeRestriction; +import org.dllearner.core.owl.Thing; import org.dllearner.core.owl.UnsupportedLanguageException; /** @@ -45,7 +49,7 @@ private int maxLevel = 1; - private ELDescriptionNode rootNode; + protected ELDescriptionNode rootNode; private Map<Integer,Set<ELDescriptionNode>> levelNodeMapping = new HashMap<Integer,Set<ELDescriptionNode>>(); @@ -58,11 +62,38 @@ * @param description A description */ public ELDescriptionTree(Description description) { - // TODO not implemented - // throw an exception if the description is not in EL - throw new UnsupportedLanguageException(description.toString(), "EL"); + // 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 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, 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 @@ -144,8 +175,14 @@ // loop through all edges and clone the subtrees for(ELDescriptionEdge edge : node.getEdges()) { ELDescriptionNode tmp = new ELDescriptionNode(nodeClone, edge.getLabel(), new TreeSet<NamedClass>(edge.getTree().getLabel())); + // TODO if we want to avoid recomputing simulation information, a special protected ELDescriptionNode + // constructor should be created cloneRecursively(edge.getTree(), tmp); } } + @Override + public String toString() { + return rootNode.toString(); + } } Added: trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionTreeComparator.java =================================================================== --- trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionTreeComparator.java (rev 0) +++ trunk/src/dl-learner/org/dllearner/algorithms/el/ELDescriptionTreeComparator.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -0,0 +1,49 @@ +/** + * 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.algorithms.el; + +import java.util.Comparator; + +/** + * Compares two EL description trees by calling {@link ELDescriptionNodeComparator} + * on their root nodes. + * + * @author Jens Lehmann + * + */ +public class ELDescriptionTreeComparator implements Comparator<ELDescriptionTree> { + + private ELDescriptionNodeComparator nodeComp; + + public ELDescriptionTreeComparator() { + nodeComp = new ELDescriptionNodeComparator(); + } + + /* (non-Javadoc) + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @Override + public int compare(ELDescriptionTree tree1, ELDescriptionTree tree2) { + ELDescriptionNode node1 = tree1.getRootNode(); + ELDescriptionNode node2 = tree2.getRootNode(); + return nodeComp.compare(node1, node2); + } + +} Modified: trunk/src/dl-learner/org/dllearner/core/owl/KB.java =================================================================== --- trunk/src/dl-learner/org/dllearner/core/owl/KB.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/core/owl/KB.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -205,15 +205,15 @@ public String toKBSyntaxString(String baseURI, Map<String,String> prefixes) { StringBuffer strbuff = new StringBuffer(); - strbuff.append("TBox["+tbox.size()+"]:\n"); + strbuff.append("// TBox["+tbox.size()+"]:\n"); for(Axiom a : tbox) - strbuff.append(" " + a.toString(baseURI, prefixes)+"\n"); - strbuff.append("\nRBox["+rbox.size()+"]:\n"); + strbuff.append(" " + a.toKBSyntaxString(baseURI, prefixes)+"\n"); + strbuff.append("\n// RBox["+rbox.size()+"]:\n"); for(Axiom a : rbox) - strbuff.append(" " + a.toString(baseURI, prefixes)+"\n"); - strbuff.append("\nABox["+abox.size()+"]:\n"); + strbuff.append(" " + a.toKBSyntaxString(baseURI, prefixes)+"\n"); + strbuff.append("\n// ABox["+abox.size()+"]:\n"); for(Axiom a : abox) - strbuff.append(" " + a.toString(baseURI, prefixes)+"\n"); + strbuff.append(" " + a.toKBSyntaxString(baseURI, prefixes)+"\n"); return strbuff.toString(); } Modified: trunk/src/dl-learner/org/dllearner/core/owl/ObjectPropertyDomainAxiom.java =================================================================== --- trunk/src/dl-learner/org/dllearner/core/owl/ObjectPropertyDomainAxiom.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/core/owl/ObjectPropertyDomainAxiom.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -55,8 +55,7 @@ public String toKBSyntaxString(String baseURI, Map<String, String> prefixes) { - // TODO Auto-generated method stub - return null; + return "OPDOMAIN(" + property.toKBSyntaxString(baseURI, prefixes) + ") = " + domain.toKBSyntaxString(baseURI, prefixes); } @Override Modified: trunk/src/dl-learner/org/dllearner/core/owl/ObjectPropertyRangeAxiom.java =================================================================== --- trunk/src/dl-learner/org/dllearner/core/owl/ObjectPropertyRangeAxiom.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/core/owl/ObjectPropertyRangeAxiom.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -48,8 +48,7 @@ } public String toKBSyntaxString(String baseURI, Map<String, String> prefixes) { - // TODO Auto-generated method stub - return null; + return "OPRANGE(" + property.toKBSyntaxString(baseURI, prefixes) + ") = " + range.toKBSyntaxString(baseURI, prefixes); } @Override Modified: trunk/src/dl-learner/org/dllearner/reasoning/FastInstanceChecker.java =================================================================== --- trunk/src/dl-learner/org/dllearner/reasoning/FastInstanceChecker.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/reasoning/FastInstanceChecker.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -160,12 +160,8 @@ @Override public void init() throws ComponentInitException { rc = new OWLAPIReasoner(sources); - //TODO make it nice - - rc.setReasonerType(reasonerType); rc.init(); - try { atomicConcepts = rc.getAtomicConcepts(); Modified: trunk/src/dl-learner/org/dllearner/refinementoperators/ELDown.java =================================================================== --- trunk/src/dl-learner/org/dllearner/refinementoperators/ELDown.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/refinementoperators/ELDown.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -84,6 +84,7 @@ private Utility utility; public ELDown(ReasoningService rs) { + this.rs = rs; utility = new Utility(rs); subsumptionHierarchy = rs.getSubsumptionHierarchy(); opHierarchy = rs.getRoleHierarchy(); @@ -105,6 +106,7 @@ // the tree (not yet implemented) ELDescriptionTree tree = new ELDescriptionTree(concept); Set<ELDescriptionTree> refinementTrees = refine(tree); +// System.out.println("Refinements finished."); Set<Description> refinements = new HashSet<Description>(); for(ELDescriptionTree refinementTree : refinementTrees) { refinements.add(refinementTree.transformToDescription()); @@ -129,7 +131,7 @@ Set<ELDescriptionTree> refinements = new HashSet<ELDescriptionTree>(); // the position of the node within the tree (needed for getting // the corresponding node in a cloned tree) - int[] position = node.getCurrentPosition(); + int[] position = node.getCurrentPosition(); // option 1: label extension Set<NamedClass> candidates = utility.getClassCandidates(index, node.getLabel()); @@ -191,17 +193,18 @@ } } } - + // option 4: edge refinement refinements.addAll(refineEdges(tree, node, position)); - + // option 5: child refinement for(ELDescriptionEdge edge : node.getEdges()) { // recursive call on child node and property range as index Description range = rs.getRange(edge.getLabel()); +// System.out.println(tree + "\nrecurse to:\n" + edge.getTree()); refinements.addAll(refine(tree, edge.getTree(), range, minimize)); } - + return refinements; } Modified: trunk/src/dl-learner/org/dllearner/test/junit/ELDescriptionTreeTests.java =================================================================== --- trunk/src/dl-learner/org/dllearner/test/junit/ELDescriptionTreeTests.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/test/junit/ELDescriptionTreeTests.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -25,10 +25,15 @@ import org.dllearner.algorithms.el.ELDescriptionNode; import org.dllearner.algorithms.el.ELDescriptionTree; +import org.dllearner.algorithms.el.ELDescriptionTreeComparator; import org.dllearner.algorithms.el.Simulation; import org.dllearner.algorithms.el.TreeTuple; +import org.dllearner.core.owl.Description; import org.dllearner.core.owl.NamedClass; import org.dllearner.core.owl.ObjectProperty; +import org.dllearner.parser.KBParser; +import org.dllearner.parser.ParseException; +import org.dllearner.utilities.owl.ConceptTransformation; import org.junit.Test; /** @@ -58,4 +63,14 @@ assertTrue(tree1.getMaxLevel() == 2); } + @Test + public void cloneTest() throws ParseException { + Description d = KBParser.parseConcept("(male AND (human AND EXISTS hasChild.(female AND EXISTS hasChild.male)))"); + ConceptTransformation.cleanConcept(d); + ELDescriptionTree tree = new ELDescriptionTree(d); + ELDescriptionTree treeCloned = tree.clone(); + ELDescriptionTreeComparator comparator = new ELDescriptionTreeComparator(); + assertTrue(comparator.compare(tree, treeCloned) == 0); + } + } Modified: trunk/src/dl-learner/org/dllearner/test/junit/ELDownTests.java =================================================================== --- trunk/src/dl-learner/org/dllearner/test/junit/ELDownTests.java 2008-08-14 18:09:20 UTC (rev 1077) +++ trunk/src/dl-learner/org/dllearner/test/junit/ELDownTests.java 2008-08-14 19:12:46 UTC (rev 1078) @@ -23,6 +23,7 @@ import java.util.SortedSet; import java.util.TreeSet; +import org.dllearner.core.ComponentInitException; import org.dllearner.core.ComponentManager; import org.dllearner.core.ReasonerComponent; import org.dllearner.core.ReasoningService; @@ -53,44 +54,52 @@ * * @throws ParseException Thrown if concept syntax does not correspond * to current KB syntax. + * @throws ComponentInitException */ @Test - public void refinementTest() throws ParseException { + public void refinementTest() throws ParseException, ComponentInitException { ComponentManager cm = ComponentManager.getInstance(); // background knowledge String kbString = ""; - kbString += "OP_DOMAIN(hasChild) = human."; - kbString += "OP_RANGE(hasChild) = human."; - kbString += "OP_DOMAIN(hasPet) = human."; - kbString += "OP_RANGE(hasPet) = animal."; - kbString += "Subrole(hasChild, has)."; - kbString += "Subrole(hasPet, has)."; - kbString += "bird SUB animal."; - kbString += "cat SUB animal."; - kbString += "cat SUB animal."; + kbString += "OPDOMAIN(hasChild) = human.\n"; + kbString += "OPRANGE(hasChild) = human.\n"; + kbString += "OPDOMAIN(hasPet) = human.\n"; + kbString += "OPRANGE(hasPet) = animal.\n"; + kbString += "Subrole(hasChild, has).\n"; + kbString += "Subrole(hasPet, has).\n"; + kbString += "bird SUB animal.\n"; + kbString += "cat SUB animal.\n"; + kbString += "(human AND animal) = BOTTOM.\n"; KB kb = KBParser.parseKBFile(kbString); // input description - Description input = KBParser.parseConcept("human AND EXISTS has.animal"); + Description input = KBParser.parseConcept("(human AND EXISTS has.animal)"); // create reasoner KBFile source = new KBFile(kb); ReasonerComponent rc = cm.reasoner(FastInstanceChecker.class, source); ReasoningService rs = cm.reasoningService(rc); + source.init(); + rc.init(); + // TODO there shouldn't be a need to call this explicitly! + // (otherwise we get a NullPointerException, because the hierarchy is not created) + rs.prepareSubsumptionHierarchy(); + rs.prepareRoleHierarchy(); + ELDown operator = new ELDown(rs); // desired refinements as strings Set<String> desiredString = new TreeSet<String>(); - desiredString.add("human AND EXISTS hasPet.animal"); - desiredString.add("human AND EXISTS has.bird"); - desiredString.add("human AND EXISTS has.cat"); - desiredString.add("(human AND EXISTS hasPet.TOP) AND EXISTS has.animal"); - desiredString.add("(human AND EXISTS hasChild.TOP) AND EXISTS has.animal"); - desiredString.add("(human AND EXISTS hasPet.TOP) AND EXISTS has.animal"); - desiredString.add("(human AND EXISTS has.person) AND EXISTS has.animal"); - desiredString.add("(human AND EXISTS has.EXISTS has.TOP) AND EXISTS has.animal"); - desiredString.add("human AND EXISTS has.(animal AND EXISTS has.TOP)"); + desiredString.add("(human AND EXISTS hasPet.animal)"); + desiredString.add("(human AND EXISTS has.bird)"); + desiredString.add("(human AND EXISTS has.cat)"); + desiredString.add("((human AND EXISTS hasPet.TOP) AND EXISTS has.animal)"); + desiredString.add("((human AND EXISTS hasChild.TOP) AND EXISTS has.animal)"); + desiredString.add("((human AND EXISTS hasPet.TOP) AND EXISTS has.animal)"); + desiredString.add("((human AND EXISTS has.person) AND EXISTS has.animal)"); + desiredString.add("((human AND EXISTS has.EXISTS has.TOP) AND EXISTS has.animal)"); + desiredString.add("(human AND EXISTS has.(animal AND EXISTS has.TOP))"); ConceptComparator cc = new ConceptComparator(); SortedSet<Description> desired = new TreeSet<Description>(cc); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |