001/** 002 * Copyright (C) 2007 - 2016, Jens Lehmann 003 * 004 * This file is part of DL-Learner. 005 * 006 * DL-Learner is free software; you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation; either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * DL-Learner is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.dllearner.refinementoperators; 020 021import org.apache.log4j.Logger; 022import org.dllearner.algorithms.el.*; 023import org.dllearner.core.AbstractReasonerComponent; 024import org.dllearner.core.ComponentInitException; 025import org.dllearner.core.config.ConfigOption; 026import org.dllearner.core.owl.ClassHierarchy; 027import org.dllearner.core.owl.DatatypePropertyHierarchy; 028import org.dllearner.core.owl.ObjectPropertyHierarchy; 029import org.semanticweb.owlapi.model.*; 030import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl; 031 032import java.util.*; 033 034//import com.jamonapi.Monitor; 035//import com.jamonapi.MonitorFactory; 036 037/** 038 * EL downward refinement operator constructed by Jens Lehmann 039 * and Christoph Haase. It takes an EL description tree as input 040 * and outputs a set of EL description trees. 041 * 042 * <p>Properties: 043 * <ul> 044 * <li>weakly complete (can be extended to guarantee completeness if desired)</li> 045 * <li>proper</li> 046 * <li>finite</li> 047 * <li>uses class/property hierarchy</li> 048 * <li>takes domain/range into account</li> 049 * <li>uses disjoint classes/classes without common instances</li> 050 * <li>all refinements are minimal (i.e. cannot be shortened without changing semantics)</li> 051 * </ul> 052 * 053 * @author Jens Lehmann 054 * 055 */ 056//@ComponentAnn(name = "EL Downward refinement operator", shortName = "eldown", version = 0.1) 057public class ELDown extends RefinementOperatorAdapter { 058 059 private static Logger logger = Logger.getLogger(ELDown.class); 060 061 private AbstractReasonerComponent rs; 062 063 // hierarchies 064 private ClassHierarchy classHierarchy; 065 private ObjectPropertyHierarchy opHierarchy; 066 private DatatypePropertyHierarchy dpHierarchy; 067 068 // domains and ranges 069 private Map<OWLObjectProperty,OWLClassExpression> opDomains = new TreeMap<>(); 070 private Map<OWLObjectProperty,OWLClassExpression> opRanges = new TreeMap<>(); 071 private Map<OWLDataProperty,OWLClassExpression> dpDomains = new TreeMap<>(); 072 private Map<OWLDataProperty,OWLDataRange> dpRanges = new TreeMap<>(); 073 074 // app_A set of applicable properties for a given class 075 private Map<OWLClassExpression, Set<OWLObjectProperty>> appOP = new TreeMap<>(); 076 private Map<OWLClassExpression, Set<OWLDataProperty>> appDP = new TreeMap<>(); 077 078 // most general applicable properties 079 private Map<OWLClassExpression,Set<OWLObjectProperty>> mgrOP = new TreeMap<>(); 080 private Map<OWLClassExpression,Set<OWLDataProperty>> mgrDP = new TreeMap<>(); 081 082 // utility class 083 private Utility utility; 084 085 // comparators 086 private ELDescriptionTreeComparator treeComp = new ELDescriptionTreeComparator(); 087 private ELDescriptionEdgeComparator edgeComp = new ELDescriptionEdgeComparator(); 088 private TreeAndRoleSetComparator mComp = new TreeAndRoleSetComparator(); 089 090 @ConfigOption(description = "maximum depth", defaultValue = "2") 091 private int maxClassExpressionDepth = 2; 092 093 private OWLDataFactory df = new OWLDataFactoryImpl(); 094 095 private boolean instanceBasedDisjoints; 096 097 public ELDown(AbstractReasonerComponent rs) { 098 this(rs, true); 099 } 100 101 public ELDown(AbstractReasonerComponent rs, boolean instanceBasedDisjoints) { 102 this.rs = rs; 103 this.instanceBasedDisjoints = instanceBasedDisjoints; 104 } 105 106 public ELDown(AbstractReasonerComponent rs, boolean instanceBasedDisjoints, ClassHierarchy classHierarchy, 107 ObjectPropertyHierarchy opHierarchy, DatatypePropertyHierarchy dpHierarchy) { 108 this.rs = rs; 109 this.instanceBasedDisjoints = instanceBasedDisjoints; 110 this.classHierarchy = classHierarchy; 111 this.opHierarchy = opHierarchy; 112 this.dpHierarchy = dpHierarchy; 113 } 114 115 @Override 116 public void init() throws ComponentInitException { 117 if(classHierarchy == null) { 118 classHierarchy = rs.getClassHierarchy(); 119 } 120 121 if(opHierarchy == null) { 122 opHierarchy = rs.getObjectPropertyHierarchy(); 123 } 124 125 if(dpHierarchy == null) { 126 dpHierarchy = rs.getDatatypePropertyHierarchy(); 127 } 128 129 130 // query reasoner for domains and ranges 131 // (because they are used often in the operator) 132 for(OWLObjectProperty op : rs.getObjectProperties()) { 133 opDomains.put(op, rs.getDomain(op)); 134 opRanges.put(op, rs.getRange(op)); 135 } 136 for(OWLDataProperty dp : rs.getDatatypeProperties()) { 137 dpDomains.put(dp, rs.getDomain(dp)); 138 dpRanges.put(dp, rs.getRange(dp)); 139 } 140 141 utility = new Utility(rs, opDomains, dpDomains, instanceBasedDisjoints); 142 143 initialized = true; 144 } 145 146 /* (non-Javadoc) 147 * @see org.dllearner.refinementoperators.RefinementOperator#refine(org.dllearner.core.owl.Description) 148 */ 149 @Override 150 public Set<OWLClassExpression> refine(OWLClassExpression concept) { 151 logger.trace("refining " + concept); 152 ELDescriptionTree tree = new ELDescriptionTree(rs, concept); 153 List<ELDescriptionTree> refinementTrees = refine(tree); 154 Set<OWLClassExpression> refinements = new HashSet<>(); 155 for(ELDescriptionTree refinementTree : refinementTrees) { 156 refinements.add(refinementTree.transformToClassExpression()); 157 } 158 return refinements; 159 } 160 161 /** 162 * Performs downward refinement for the given tree. The operator 163 * works directly on EL description trees (which differ from the 164 * the tree structures build by descriptions). 165 * 166 * @param tree Input EL description tree. 167 * @return Set of refined EL description trees. 168 */ 169 public List<ELDescriptionTree> refine(ELDescriptionTree tree) { 170 logger.trace("applying \\rho on " + tree.toDescriptionString()); 171 List<ELDescriptionTree> refinements = new LinkedList<>(); 172 // loop over all nodes of the tree and perform one of the 173 // transformations on it (we make a copy of all nodes, because 174 // the transformations can, of course, add new nodes) 175 List<ELDescriptionNode> nodes = new LinkedList<>(tree.getNodes()); 176 for(ELDescriptionNode v : nodes) { 177 logger.trace("picked node v: " + v); 178 179 // the position of the node within the tree (needed for getting 180 // the corresponding node in a cloned tree) 181 int[] position = v.getCurrentPosition(); 182// logger.trace(" at position " + Helper.arrayContent(position)); 183 184 // perform operations 185 if(v.isClassNode()){ 186 refinements.addAll(extendLabel(tree, v, position)); 187 refinements.addAll(refineLabel(tree, v, position)); 188 } 189 refinements.addAll(refineEdge(tree, v, position)); 190 if(v.isClassNode() && v.getLevel() <= maxClassExpressionDepth){ 191 refinements.addAll(attachSubtree2(tree, v, position)); 192 refinements.addAll(attachSubtreeDatatypeProperties(tree, v, position)); 193 } 194 195 } 196 197 return refinements; 198 } 199 200 // operation 1: label extension 201 private List<ELDescriptionTree> extendLabel(ELDescriptionTree tree, ELDescriptionNode v, int[] position) { 202// Monitor mon = MonitorFactory.start("extend label"); 203 List<ELDescriptionTree> refinements = new LinkedList<>(); 204 205 // the index is the range of role in the edge pointing to the parent of this node 206 OWLClassExpression index = v.isRoot() ? df.getOWLThing() : opRanges.get(v.getParentEdge().getLabel()); 207 208 // call ncc (see paper) 209 Set<OWLClass> candidates = utility.getClassCandidates(index, v.getLabel()); 210 211// System.out.println("index: " + index + " label: " + v.getLabel()); 212// System.out.println("candidates: " + candidates); 213 214 for(OWLClass nc : candidates) { 215 // clone operation 216 ELDescriptionTree clonedTree = tree.clone(); 217 ELDescriptionNode clonedNode = clonedTree.getNode(position); 218 // extend label 219 clonedNode.extendLabel(nc); 220 if(clonedTree.isMinimal()) { 221 refinements.add(clonedTree); 222 } 223 } 224 225// mon.stop(); 226 return refinements; 227 } 228 229 // operation 2: label refinement 230 private List<ELDescriptionTree> refineLabel(ELDescriptionTree tree, ELDescriptionNode v, int[] position) { 231// Monitor mon = MonitorFactory.start("refine label"); 232 List<ELDescriptionTree> refinements = new LinkedList<>(); 233 234 // loop through all classes in label 235 for(OWLClass nc : v.getLabel()) { 236 // find all more special classes for the given label 237 for(OWLClassExpression moreSpecial : rs.getSubClasses(nc)) { 238 if(moreSpecial instanceof OWLClass) { 239 // clone operation 240 ELDescriptionTree clonedTree = tree.clone(); 241 ELDescriptionNode clonedNode = clonedTree.getNode(position); 242 243 // create refinements by replacing class 244 clonedNode.replaceInLabel(nc, (OWLClass) moreSpecial); 245 246 if(clonedTree.isMinimal()) { 247 refinements.add(clonedTree); 248 } 249 } 250 } 251 } 252// mon.stop(); 253 return refinements; 254 } 255 256 // operation 3: refine edge 257 private List<ELDescriptionTree> refineEdge(ELDescriptionTree tree, ELDescriptionNode v, int[] position) { 258// Monitor mon = MonitorFactory.start("refine edge"); 259 List<ELDescriptionTree> refinements = new LinkedList<>(); 260 261 for(int edgeNumber = 0; edgeNumber < v.getEdges().size(); edgeNumber++) { 262 ELDescriptionEdge edge = v.getEdges().get(edgeNumber); 263 OWLProperty op = edge.getLabel(); 264 // find all more special properties 265 if(op.isOWLObjectProperty()){ 266 for(OWLObjectProperty op2 : rs.getSubProperties(op.asOWLObjectProperty())) { 267 // we check whether the range of this property is not disjoint 268 // with the existing child node (we do not perform a full disjointness 269 // check, but only compare with the flattened concept to keep the number 270 // of possible disjointness checks finite) 271 if(!utility.isDisjoint(getFlattenedConcept(edge.getNode()), opRanges.get(op2))) { 272 // clone operation 273 ELDescriptionTree clonedTree = tree.clone(); 274 // find cloned edge and replace its label 275 clonedTree.getNode(position).refineEdge(edgeNumber, op2); 276// ELDescriptionEdge clonedEdge = clonedTree.getNode(position).getEdges().get(edgeNumber); 277// clonedEdge.setLabel(op2); 278 if(clonedTree.isMinimal()) { 279 refinements.add(clonedTree); 280 } 281 } 282 } 283 } else { 284 for(OWLDataProperty op2 : rs.getSubProperties(op.asOWLDataProperty())) { 285 // we check whether the range of this property is not disjoint 286 // with the existing child node 287 if(edge.getNode().getDataRange().equals(dpRanges.get(op2))) { 288 // clone operation 289 ELDescriptionTree clonedTree = tree.clone(); 290 // find cloned edge and replace its label 291 clonedTree.getNode(position).refineEdge(edgeNumber, op2); 292// ELDescriptionEdge clonedEdge = clonedTree.getNode(position).getEdges().get(edgeNumber); 293// clonedEdge.setLabel(op2); 294 if(clonedTree.isMinimal()) { 295 refinements.add(clonedTree); 296 } 297 } 298 } 299 } 300 301 } 302// mon.stop(); 303 return refinements; 304 } 305 306 307 308 // new version of as 309 private Collection<ELDescriptionTree> attachSubtree2(ELDescriptionTree tree, ELDescriptionNode v, int[] position) { 310// Monitor mon = MonitorFactory.start("attach tree"); 311 Set<ELDescriptionTree> refinements = new TreeSet<>(treeComp); 312 313 // create and initialise M 314 TreeSet<TreeAndRoleSet> m = new TreeSet<>(mComp); 315 ELDescriptionTree topTree = new ELDescriptionTree(rs, df.getOWLThing()); 316 OWLClassExpression index = getIndex(v); 317 SortedSet<? extends OWLProperty> appOPs = utility.computeApplicableObjectProperties(index); 318 m.add(new TreeAndRoleSet(topTree, (Set<OWLProperty>) appOPs)); 319 320// logger.trace("M initialised: " + m); 321 322 while(!m.isEmpty()) { 323 324 // pick first element of M 325 TreeAndRoleSet tars = m.pollFirst(); 326 ELDescriptionTree tp = tars.getTree(); 327 Set<OWLProperty> rSet = tars.getRoles(); 328// logger.trace("selected first element of M: " + tars); 329 330 331 // init sets R' and R'' 332 // more efficient 333 Set<OWLObjectProperty> rpSet = utility.computeMgr((Set<OWLObjectProperty>) appOPs); 334 rpSet.retainAll(rSet); 335// SortedSet<OWLObjectProperty> rpSet = new TreeSet<OWLObjectProperty>(); 336// for(OWLObjectProperty rEl : rSet) { 337// if(!containsSuperProperty(rEl, rSet)) { 338// rpSet.add(rEl); 339// } 340// } 341 342// logger.trace("R': " + rpSet); 343 Set<OWLProperty> rppSet = new TreeSet<>(); 344 345 while(!rpSet.isEmpty()) { 346 // pick an element r from R' 347 Iterator<OWLObjectProperty> it = rpSet.iterator(); 348 OWLObjectProperty r = it.next(); 349 it.remove(); 350// logger.trace("picked role r: " + r); 351 ELDescriptionTree tpp = mergeTrees(tree, v, position, r, tp); 352// logger.trace("merged tree:\n" + tpp); 353 // the position of w is the position of v + #edges outgoing from v 354 int[] wPosition = new int[position.length+1]; 355 System.arraycopy(position, 0, wPosition, 0, position.length); 356 wPosition[position.length] = v.getEdges().size(); 357 ELDescriptionNode w = tpp.getNode(wPosition); 358 359 boolean minimal = tpp.isMinimal(); 360// MonitorFactory.add("as.minimal", "boolean", minimal ? 1 : 0); 361 if(minimal) { 362 refinements.add(tpp); 363// logger.trace("tree is minimal; added to T"); 364 } else { 365 boolean check = asCheck(w); 366// MonitorFactory.add("as.check", "boolean", check ? 1 : 0); 367// logger.trace("tree is not minimal; result of complex check: " + check); 368 369 if(check) { 370 371// Monitor mon2 = MonitorFactory.start("as.tmp"); 372 // add role to R' if it is in R (allowed) 373 for(OWLObjectProperty subRole : rs.getSubProperties(r)) { 374 if(rSet.contains(subRole)) { 375 rpSet.add(subRole); 376 } 377 } 378 rppSet.add(r); 379// logger.trace("updated R' to: " + rpSet); 380// logger.trace("updated R'' to: " + rppSet); 381// mon2.stop(); 382 } 383 } 384 } 385 386 if(rppSet.size() != 0) { 387 // recursive call 388// mon.stop(); 389// logger.trace("recursive call start"); 390 List<ELDescriptionTree> recRefs = refine(tp); 391// logger.trace("recursive call end"); 392// mon.start(); 393 394 for(ELDescriptionTree tStar : recRefs) { 395 m.add(new TreeAndRoleSet(tStar, rppSet)); 396 } 397// logger.trace("M after recursion: " + m); 398 } 399 400 } 401// mon.stop(); 402 return refinements; 403 } 404 405 // new version of as 406 private Collection<ELDescriptionTree> attachSubtreeDatatypeProperties(ELDescriptionTree tree, ELDescriptionNode v, int[] position) { 407// Monitor mon = MonitorFactory.start("attach tree"); 408 Set<ELDescriptionTree> refinements = new TreeSet<>(treeComp); 409 // create and initialise M 410 TreeSet<TreeAndRoleSet> m = new TreeSet<>(mComp); 411 ELDescriptionTree topTree = new ELDescriptionTree(rs, df.getOWLThing()); 412 OWLClassExpression index = getIndex(v); 413 SortedSet<? extends OWLProperty> appOPs = utility.computeApplicableDatatypeProperties(index); 414 m.add(new TreeAndRoleSet(topTree, (Set<OWLProperty>) appOPs)); 415 416// logger.trace("M initialised: " + m); 417 418 while(!m.isEmpty()) { 419 420 // pick first element of M 421 TreeAndRoleSet tars = m.pollFirst(); 422 ELDescriptionTree tp = tars.getTree(); 423 Set<OWLProperty> rSet = tars.getRoles(); 424// logger.trace("selected first element of M: " + tars); 425 426 427 // init sets R' and R'' 428 // more efficient 429 Set<OWLDataProperty> rpSet = utility.computeMgrDP((Set<OWLDataProperty>) appOPs); 430 rpSet.retainAll(rSet); 431// SortedSet<OWLObjectProperty> rpSet = new TreeSet<OWLObjectProperty>(); 432// for(OWLObjectProperty rEl : rSet) { 433// if(!containsSuperProperty(rEl, rSet)) { 434// rpSet.add(rEl); 435// } 436// } 437 438// logger.trace("R': " + rpSet); 439 Set<OWLProperty> rppSet = new TreeSet<>(); 440 441 while(!rpSet.isEmpty()) { 442 // pick an element r from R' 443 Iterator<OWLDataProperty> it = rpSet.iterator(); 444 OWLDataProperty r = it.next(); 445 it.remove(); 446// logger.trace("picked role r: " + r); 447 ELDescriptionTree tpp = mergeTrees(tree, v, position, r, tp); 448// logger.trace("merged tree:\n" + tpp); 449 // the position of w is the position of v + #edges outgoing from v 450 int[] wPosition = new int[position.length+1]; 451 System.arraycopy(position, 0, wPosition, 0, position.length); 452 wPosition[position.length] = v.getEdges().size(); 453 ELDescriptionNode w = tpp.getNode(wPosition); 454 455 boolean minimal = tpp.isMinimal(); 456// MonitorFactory.add("as.minimal", "boolean", minimal ? 1 : 0); 457 if(minimal) { 458 refinements.add(tpp); 459// logger.trace("tree is minimal; added to T"); 460 } else { 461 boolean check = asCheck(w); 462// MonitorFactory.add("as.check", "boolean", check ? 1 : 0); 463// logger.trace("tree is not minimal; result of complex check: " + check); 464 465 if(check) { 466 467// Monitor mon2 = MonitorFactory.start("as.tmp"); 468 // add role to R' if it is in R (allowed) 469 for(OWLDataProperty subRole : rs.getSubProperties(r)) { 470 if(rSet.contains(subRole)) { 471 rpSet.add(subRole); 472 } 473 } 474 rppSet.add(r); 475// logger.trace("updated R' to: " + rpSet); 476// logger.trace("updated R'' to: " + rppSet); 477// mon2.stop(); 478 } 479 } 480 } 481 482 if(rppSet.size() != 0) { 483 // recursive call 484// mon.stop(); 485// logger.trace("recursive call start"); 486 List<ELDescriptionTree> recRefs = refine(tp); 487// logger.trace("recursive call end"); 488// mon.start(); 489 490 for(ELDescriptionTree tStar : recRefs) { 491 m.add(new TreeAndRoleSet(tStar, rppSet)); 492 } 493// logger.trace("M after recursion: " + m); 494 } 495 496 } 497// mon.stop(); 498 return refinements; 499 } 500 501 502 // create a new tree which is obtained by attaching the new tree at the given node in the tree via role r 503 private ELDescriptionTree mergeTrees(ELDescriptionTree tree, ELDescriptionNode node, int[] position, OWLProperty r, ELDescriptionTree newTree) { 504// Monitor mon = MonitorFactory.start("as.merge trees"); 505// System.out.println("merge start"); 506// System.out.println(tree); 507// System.out.println(newTree); 508 // merged tree = tree + new node with role pointing to a new node 509 ELDescriptionTree mergedTree = tree.clone(); 510 ELDescriptionNode clonedNode = mergedTree.getNode(position); 511// ELDescriptionNode nodeNew = new ELDescriptionNode(clonedNode, r); 512// logger.trace("node: " + node); 513// logger.trace("cloned node: " + clonedNode); 514// logger.trace("node position: " + arrayContent(position)); 515// logger.trace("merge start: " + mergedTree); 516 517 // create a list of nodes we still need to process 518 LinkedList<ELDescriptionNode> toProcess = new LinkedList<>(); 519 toProcess.add(newTree.getRootNode()); 520 521 // map from nodes to cloned nodes 522 Map<ELDescriptionNode,ELDescriptionNode> cloneMap = new HashMap<>(); 523 524// Monitor mon2 = MonitorFactory.start("as.tmp"); 525 526 // loop until the process list is empty 527 while(!toProcess.isEmpty()) { 528 // process a node 529 ELDescriptionNode v = toProcess.pollFirst(); 530 // find parent 531 ELDescriptionNode vp; 532 if(v.isRoot()) { 533 // root is connected to main tree via role r 534 if(r instanceof OWLObjectProperty){ 535 vp = new ELDescriptionNode(clonedNode, r.asOWLObjectProperty(), newTree.getRootNode().getLabel()); 536 } else { 537 vp = new ELDescriptionNode(clonedNode, r.asOWLDataProperty(), dpRanges.get(r)); 538 } 539 540 } else if(v.isClassNode()){ 541 ELDescriptionNode parent = cloneMap.get(v.getParent()); 542 OWLProperty role = v.getParentEdge().getLabel(); 543 Set<OWLClass> label = v.getLabel(); 544 // create new node 545 vp = new ELDescriptionNode(parent, role.asOWLObjectProperty(), label); 546 } else { 547 ELDescriptionNode parent = cloneMap.get(v.getParent()); 548 OWLProperty role = v.getParentEdge().getLabel(); 549 OWLDataRange label = v.getDataRange(); 550 // create new node 551 vp = new ELDescriptionNode(parent, role.asOWLDataProperty(), label); 552 } 553 cloneMap.put(v, vp); 554 // attach children of node to process list 555 for(ELDescriptionEdge edge : v.getEdges()) { 556 toProcess.add(edge.getNode()); 557 } 558 } 559 560// mon2.stop(); 561 562// mon.stop(); 563 return mergedTree; 564 } 565 566 // TODO: variables have been renamed in article 567 public boolean asCheck(ELDescriptionNode v) { 568// Monitor mon = MonitorFactory.start("as.complex check"); 569// System.out.println("asCheck: " + v.getTree().toSimulationString()); 570 571 // find all edges up to the root node 572 List<ELDescriptionEdge> piVEdges = new LinkedList<>(); 573 ELDescriptionNode tmp = v; 574 while(!tmp.isRoot()) { 575 piVEdges.add(tmp.getParentEdge()); 576 tmp = tmp.getParent(); 577 } 578 579// System.out.println(piVEdges); 580 581 // go through all edges 582 for(ELDescriptionEdge piVEdge : piVEdges) { 583 // collect (w,r',w') 584 ELDescriptionNode wp = piVEdge.getNode(); 585 OWLProperty rp = piVEdge.getLabel(); 586 ELDescriptionNode w = wp.getParent(); 587 588// System.out.println("w: " + w); 589// System.out.println("rp: " + rp); 590// System.out.println("wp: " + wp); 591 592 // go through all (w,s,w'') 593 for(ELDescriptionEdge wEdge : w.getEdges()) { 594 OWLProperty rpp = wEdge.getLabel(); 595 ELDescriptionNode wpp = wEdge.getNode(); 596 if(wp != wpp && rs.isSubPropertyOf(rp, rpp)) { 597// System.out.println("wp: " + wp); 598// System.out.println("wpp: " + wpp); 599 if(wp.getIn().contains(wpp)) { 600 return false; 601 } 602 } 603 } 604 } 605 606// mon.stop(); 607 return true; 608 } 609 610 // simplifies a potentially nested tree in a flat conjunction by taking 611 // the domain of involved roles, e.g. for 612 // C = Professor \sqcap \exists hasChild.Student 613 // the result would be Professor \sqcap Human (assuming Human is the domain 614 // of hasChild) 615 // TODO: used in both EL operators => move to utility class 616 private OWLClassExpression getFlattenedConcept(ELDescriptionNode node) { 617 Set<OWLClassExpression> operands = new HashSet<>(); 618 619 // add all named classes to intersection 620 operands.addAll(node.getLabel()); 621 622 // add domain of all roles to intersection 623 for(ELDescriptionEdge edge : node.getEdges()) { 624 operands.add(opDomains.get(edge.getLabel())); 625 } 626 627 int size = operands.size(); 628 // size = 0 means we have the top concept 629 if(size == 0) { 630 return df.getOWLThing(); 631 } 632 // if the intersection has just one element, we return 633 // the element itself instead 634 else if(size == 1) { 635 return operands.iterator().next(); 636 } 637 638 return df.getOWLObjectIntersectionOf(operands); 639 } 640 641 private OWLClassExpression getIndex(ELDescriptionNode v) { 642 if(v.isRoot()) { 643 return df.getOWLThing(); 644 } else { 645 return opRanges.get(v.getParentEdge().getLabel()); 646 } 647 } 648 649 private boolean containsSuperProperty(OWLObjectProperty prop, Set<OWLObjectProperty> props) { 650 for(OWLObjectProperty p : props) { 651 if(!p.equals(prop)) { 652 if(opHierarchy.isSubpropertyOf(prop, p)) { 653 return true; 654 } 655 } 656 } 657 return false; 658 } 659 660 /** 661 * @param maxClassExpressionDepth the max. depth of generated class expressions 662 */ 663 public void setMaxClassExpressionDepth(int maxClassExpressionDepth) { 664 this.maxClassExpressionDepth = maxClassExpressionDepth; 665 } 666}