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.core; 020 021import org.dllearner.core.annotations.NoConfigOption; 022import org.dllearner.core.config.ConfigOption; 023import org.dllearner.core.owl.ClassHierarchy; 024import org.dllearner.core.owl.DatatypePropertyHierarchy; 025import org.dllearner.core.owl.ObjectPropertyHierarchy; 026import org.dllearner.accuracymethods.AccMethodFMeasure; 027import org.dllearner.accuracymethods.AccMethodPredAcc; 028import org.dllearner.accuracymethods.AccMethodTwoValued; 029import org.dllearner.learningproblems.PosNegLP; 030import org.dllearner.utilities.Helper; 031import org.dllearner.utilities.ReasoningUtils; 032import org.dllearner.utilities.datastructures.DescriptionSubsumptionTree; 033import org.dllearner.utilities.owl.ConceptTransformation; 034import org.dllearner.utilities.owl.EvaluatedDescriptionSet; 035import org.dllearner.utilities.owl.OWLClassExpressionMinimizer; 036import org.joda.time.Period; 037import org.joda.time.format.PeriodFormatter; 038import org.joda.time.format.PeriodFormatterBuilder; 039import org.semanticweb.owlapi.io.OWLObjectRenderer; 040import org.semanticweb.owlapi.model.*; 041import org.semanticweb.owlapi.util.OWLObjectDuplicator; 042import org.semanticweb.owlapi.vocab.OWLRDFVocabulary; 043import org.slf4j.Logger; 044import org.slf4j.LoggerFactory; 045import org.springframework.beans.factory.annotation.Autowired; 046import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl; 047import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl; 048 049import java.text.DecimalFormat; 050import java.util.*; 051import java.util.concurrent.TimeUnit; 052 053/** 054 * Abstract superclass of all class expression learning algorithm implementations. 055 * Includes support for anytime learning algorithms and resumable 056 * learning algorithms. Provides methods for filtering the best 057 * descriptions found by the algorithm. As results of the algorithm, 058 * you can either get only descriptions or evaluated descriptions. 059 * Evaluated descriptions have information about accuracy and 060 * example coverage associated with them. However, retrieving those 061 * may require addition reasoner queries, because the learning 062 * algorithms usually use but do not necessarily store this information. 063 * 064 * Changes (March/April 2011): Learning algorithms no longer have to use 065 * this class, but it still serves as a prototypical template for class 066 * expression learning algorithms. 067 * 068 * @author Jens Lehmann 069 * 070 */ 071public abstract class AbstractCELA extends AbstractComponent implements ClassExpressionLearningAlgorithm, StoppableLearningAlgorithm { 072 073 private static final Logger logger = LoggerFactory.getLogger(AbstractCELA.class); 074 075 @NoConfigOption 076 protected OWLObjectRenderer renderer = StringRenderer.getRenderer(); 077 078 protected EvaluatedDescriptionSet bestEvaluatedDescriptions = new EvaluatedDescriptionSet(AbstractCELA.MAX_NR_OF_RESULTS); 079 protected DecimalFormat dfPercent = new DecimalFormat("0.00%"); 080 protected String baseURI; 081 protected Map<String, String> prefixes; 082 protected OWLDataFactory dataFactory = new OWLDataFactoryImpl(); 083 084 protected static final OWLClass OWL_THING = new OWLClassImpl(OWLRDFVocabulary.OWL_THING.getIRI()); 085 protected static final OWLClass OWL_NOTHING = new OWLClassImpl(OWLRDFVocabulary.OWL_NOTHING.getIRI()); 086 087 protected long nanoStartTime; 088 protected boolean isRunning = false; 089 protected boolean stop = false; 090 091 protected OWLClassExpressionMinimizer minimizer; 092 093 @ConfigOption(defaultValue="true", description="Specifies whether returned expressions should " + 094 "be minimised by removing those parts, which are not needed. (Basically the minimiser tries to find the " + 095 "shortest expression which is equivalent to the learned expression). Turning this feature off may improve " + 096 "performance.") 097 private boolean useMinimizer = true; 098 099 @ConfigOption(defaultValue = "10", description = "maximum execution of the algorithm in seconds") 100 protected long maxExecutionTimeInSeconds = 10; 101 102 /** 103 * The learning problem variable, which must be used by 104 * all learning algorithm implementations. 105 */ 106 @ConfigOption(description="The Learning Problem variable to use in this algorithm") 107 protected AbstractClassExpressionLearningProblem<? extends Score> learningProblem; 108 109 /** 110 * The reasoning service variable, which must be used by 111 * all learning algorithm implementations. 112 */ 113 @ConfigOption(description="The reasoner variable to use for this learning problem") 114 protected AbstractReasonerComponent reasoner; 115 116 protected OWLObjectDuplicator duplicator = new OWLObjectDuplicator(new OWLDataFactoryImpl()); 117 118 @ConfigOption(description="List of classes that are allowed") 119 protected Set<OWLClass> allowedConcepts = null; 120 @ConfigOption(description="List of classes to ignore") 121 protected Set<OWLClass> ignoredConcepts = null; 122 @ConfigOption(description="List of object properties to allow") 123 protected Set<OWLObjectProperty> allowedObjectProperties = null; 124 @ConfigOption(description="List of object properties to ignore") 125 protected Set<OWLObjectProperty> ignoredObjectProperties = null; 126 @ConfigOption(description="List of data properties to allow") 127 protected Set<OWLDataProperty> allowedDataProperties = null; 128 @ConfigOption(description="List of data properties to ignore") 129 protected Set<OWLDataProperty> ignoredDataProperties = null; 130 131 /** 132 * Default Constructor 133 */ 134 public AbstractCELA(){} 135 136 /** 137 * Each learning algorithm gets a learning problem and 138 * a reasoner as input. 139 * @param learningProblem The learning problem to solve. 140 * @param reasoningService The reasoner connecting to the 141 * underlying knowledge base. 142 */ 143 public AbstractCELA(AbstractClassExpressionLearningProblem learningProblem, AbstractReasonerComponent reasoningService) { 144 this.learningProblem = learningProblem; 145 this.reasoner = reasoningService; 146 } 147 148 /** 149 * Call this when you want to change the learning problem, but 150 * leave everything else as is. Method can be used to apply 151 * a configured algorithm to different learning problems. 152 * Implementations, which do not only use the provided learning 153 * algorithm variable, must make sure that a call to this method 154 * indeed changes the learning problem. 155 * @param learningProblem The new learning problem. 156 */ 157 public void changeLearningProblem(AbstractClassExpressionLearningProblem learningProblem) { 158 this.learningProblem = learningProblem; 159 } 160 161 /** 162 * Call this when you want to change the reasoning service, but 163 * leave everything else as is. Method can be used to use 164 * a configured algorithm with different reasoners. 165 * Implementations, which do not only use the provided reasoning 166 * service class variable, must make sure that a call to this method 167 * indeed changes the reasoning service. 168 * @param reasoningService The new reasoning service. 169 */ 170 public void changeReasonerComponent(AbstractReasonerComponent reasoningService) { 171 this.reasoner = reasoningService; 172 } 173 174 /** 175 * This is the maximum number of results, which the learning 176 * algorithms are asked to store. (Note, that algorithms are not 177 * required to store any results except the best one, so this limit 178 * is used to limit the performance cost for those which 179 * choose to store results.) 180 */ 181 public static final int MAX_NR_OF_RESULTS = 100; 182 183 /** 184 * @see #getCurrentlyBestEvaluatedDescription() 185 * @return The best class OWLClassExpression found by the learning algorithm so far. 186 */ 187 public OWLClassExpression getCurrentlyBestDescription() { 188 return getCurrentlyBestEvaluatedDescription().getDescription(); 189 } 190 191 /** 192 * @see #getCurrentlyBestEvaluatedDescriptions() 193 * @return The best class descriptions found by the learning algorithm so far. 194 */ 195 public List<OWLClassExpression> getCurrentlyBestDescriptions() { 196 return bestEvaluatedDescriptions.toDescriptionList(); 197 } 198 199 /** 200 * @see #getCurrentlyBestEvaluatedDescriptions(int) 201 * @param nrOfDescriptions Limit for the number or returned descriptions. 202 * @return The best class descriptions found by the learning algorithm so far. 203 */ 204 @Override 205 public synchronized List<OWLClassExpression> getCurrentlyBestDescriptions(int nrOfDescriptions) { 206 return getCurrentlyBestDescriptions(nrOfDescriptions, false); 207 } 208 209 /** 210 * @see #getCurrentlyBestEvaluatedDescriptions(int,double,boolean) 211 * @param nrOfDescriptions Limit for the number or returned descriptions. 212 * @param filterNonMinimalDescriptions Remove non-minimal descriptions (e.g. those which can be shortened 213 * to an equivalent concept) from the returned set. 214 * @return The best class descriptions found by the learning algorithm so far. 215 */ 216 public synchronized List<OWLClassExpression> getCurrentlyBestDescriptions(int nrOfDescriptions, boolean filterNonMinimalDescriptions) { 217 List<OWLClassExpression> currentlyBest = getCurrentlyBestDescriptions(); 218 List<OWLClassExpression> returnList = new LinkedList<>(); 219 for(OWLClassExpression ed : currentlyBest) { 220 if(returnList.size() >= nrOfDescriptions) { 221 return returnList; 222 } 223 224 if(!filterNonMinimalDescriptions || ConceptTransformation.isDescriptionMinimal(ed)) { 225 returnList.add(ed); 226 } 227 228 } 229 return returnList; 230 } 231 232 /** 233 * Returns the best descriptions obtained so far. 234 * @return Best class class expression found so far. 235 */ 236 public EvaluatedDescription<? extends Score> getCurrentlyBestEvaluatedDescription() { 237 return bestEvaluatedDescriptions.getSet().last(); 238 } 239 240 /** 241 * Returns a sorted set of the best descriptions found so far. We 242 * assume that they are ordered such that the best ones come in 243 * last. (In Java, iterators traverse a SortedSet in ascending order.) 244 * @return Best class descriptions found so far. 245 */ 246 public NavigableSet<? extends EvaluatedDescription<? extends Score>> getCurrentlyBestEvaluatedDescriptions() { 247 return bestEvaluatedDescriptions.getSet(); 248 } 249 250 /** 251 * Returns a filtered list of currently best class descriptions. 252 * 253 * @param nrOfDescriptions Maximum number of restrictions. Use Integer.MAX_VALUE 254 * if you do not want this filter to be active. 255 * 256 * @param accuracyThreshold Minimum accuracy. All class descriptions with lower 257 * accuracy are disregarded. Specify a value between 0.0 and 1.0. Use 0.0 if 258 * you do not want this filter to be active. 259 * 260 * @param filterNonMinimalDescriptions If true, non-minimal descriptions are 261 * filtered, e.g. ALL r.TOP (being equivalent to TOP), male AND male (can be 262 * shortened to male). Currently, non-minimal descriptions are just skipped, 263 * i.e. they are completely omitted from the return list. Later, implementation 264 * might be changed to return shortened versions of those descriptions. 265 * 266 * @return A list of currently best class descriptions. 267 */ 268 public synchronized List<? extends EvaluatedDescription<? extends Score>> getCurrentlyBestEvaluatedDescriptions(int nrOfDescriptions, double accuracyThreshold, boolean filterNonMinimalDescriptions) { 269 NavigableSet<? extends EvaluatedDescription<? extends Score>> currentlyBest = getCurrentlyBestEvaluatedDescriptions(); 270 List<EvaluatedDescription<? extends Score>> returnList = new LinkedList<>(); 271 for(EvaluatedDescription<? extends Score> ed : currentlyBest.descendingSet()) { 272 // once we hit a OWLClassExpression with a below threshold accuracy, we simply return 273 // because learning algorithms are advised to order descriptions by accuracy, 274 // so we won't find any concept with higher accuracy in the remaining list 275 if(ed.getAccuracy() < accuracyThreshold) { 276 return returnList; 277 } 278 279 // return if we have sufficiently many descriptions 280 if(returnList.size() >= nrOfDescriptions) { 281 return returnList; 282 } 283 284 if(!filterNonMinimalDescriptions || ConceptTransformation.isDescriptionMinimal(ed.getDescription())) { 285 // before we add the OWLClassExpression we replace EXISTS r.TOP with 286 // EXISTS r.range(r) if range(r) is atomic 287 // (we need to clone, otherwise we change descriptions which could 288 // be in the search of the learning algorithm, which leads to 289 // unpredictable behaviour) 290 OWLClassExpression d = duplicator.duplicateObject(ed.getDescription()); 291 292 //commented out because reasoner is called. leads in swing applications sometimes to exceptions 293// ConceptTransformation.replaceRange(d, reasoner); 294 ed.setDescription(d); 295 296 returnList.add(ed); 297 } 298 299 } 300 return returnList; 301 } 302 303 /** 304 * Return the best currently found concepts up to some maximum 305 * count (no minimality filter used). 306 * @param nrOfDescriptions Maximum number of descriptions returned. 307 * @return Return value is getCurrentlyBestDescriptions(nrOfDescriptions, 0.0, false). 308 */ 309 @Override 310 public synchronized List<? extends EvaluatedDescription<? extends Score>> getCurrentlyBestEvaluatedDescriptions(int nrOfDescriptions) { 311 return getCurrentlyBestEvaluatedDescriptions(nrOfDescriptions, 0.0, false); 312 } 313 314 /** 315 * Returns a fraction of class descriptions with sufficiently high accuracy. 316 * @param accuracyThreshold Only return solutions with this accuracy or higher. 317 * @return Return value is getCurrentlyBestDescriptions(Integer.MAX_VALUE, accuracyThreshold, false). 318 */ 319 public synchronized List<? extends EvaluatedDescription<? extends Score>> getCurrentlyBestEvaluatedDescriptions(double accuracyThreshold) { 320 return getCurrentlyBestEvaluatedDescriptions(Integer.MAX_VALUE, accuracyThreshold, false); 321 } 322 323 public synchronized List<? extends EvaluatedDescription<? extends Score>> getCurrentlyBestMostGeneralEvaluatedDescriptions() { 324 List<? extends EvaluatedDescription<? extends Score>> l = getCurrentlyBestEvaluatedDescriptions(getCurrentlyBestEvaluatedDescriptions().last().getAccuracy()); 325 DescriptionSubsumptionTree t = new DescriptionSubsumptionTree(reasoner); 326 t.insert(l); 327 return t.getMostGeneralDescriptions(true); 328 } 329 330 /** 331 * Returns all learning problems supported by this component. This can be used to indicate that, e.g. 332 * an algorithm is only suitable for positive only learning. 333 * @return All classes implementing learning problems, which are supported by this learning algorithm. 334 */ 335 public static Collection<Class<? extends AbstractClassExpressionLearningProblem>> supportedLearningProblems() { 336 return new LinkedList<>(); 337 } 338 339 // central function for printing description 340 protected String descriptionToString(OWLClassExpression description) { 341 return renderer.render(description); 342 } 343 344 345 protected String getSolutionString() { 346 int current = 1; 347 String str = ""; 348 for(EvaluatedDescription<? extends Score> ed : getCurrentlyBestEvaluatedDescriptions().descendingSet()) { 349 // temporary code 350 OWLClassExpression description = ed.getDescription(); 351 String descriptionString = descriptionToString(description); 352 if(learningProblem instanceof PosNegLP) { 353 Set<OWLIndividual> positiveExamples = ((PosNegLP)learningProblem).getPositiveExamples(); 354 Set<OWLIndividual> negativeExamples = ((PosNegLP)learningProblem).getNegativeExamples(); 355 ReasoningUtils reasoningUtil = learningProblem.getReasoningUtil(); 356 357 str += current + ": " + descriptionString + " (pred. acc.: " 358 + dfPercent.format(reasoningUtil.getAccuracyOrTooWeak2(new AccMethodPredAcc(true), description, positiveExamples, negativeExamples, 1)) 359 + ", F-measure: "+ dfPercent.format(reasoningUtil.getAccuracyOrTooWeak2(new AccMethodFMeasure(true), description, positiveExamples, negativeExamples, 1)); 360 361 AccMethodTwoValued accuracyMethod = ((PosNegLP)learningProblem).getAccuracyMethod(); 362 if ( !(accuracyMethod instanceof AccMethodPredAcc) 363 && !(accuracyMethod instanceof AccMethodFMeasure) ) { 364 str += ", " + AnnComponentManager.getName(accuracyMethod) + ": " + dfPercent.format(ed.getAccuracy()); 365 } 366 str += ")\n"; 367 } else { 368 str += current + ": " + descriptionString + " " + dfPercent.format(ed.getAccuracy()) + "\n"; 369// System.out.println(ed); 370 } 371 current++; 372 } 373 return str; 374 } 375 376 /** 377 * Computes an internal class hierarchy that only contains classes 378 * that are allowed. 379 * @return optimized class hierarchy 380 */ 381 protected ClassHierarchy initClassHierarchy() { 382 // we ignore all unsatisfiable classes 383 Set<OWLClass> unsatisfiableClasses = null; 384 try { 385 unsatisfiableClasses = reasoner.getInconsistentClasses(); 386 } catch (UnsupportedOperationException e) { 387 logger.warn("Ignoring unsatisfiable check due to "+e.getStackTrace()[0]); 388 } 389 if(unsatisfiableClasses != null && !unsatisfiableClasses.isEmpty()) { 390 logger.warn("Ignoring unsatisfiable classes " + unsatisfiableClasses); 391 if(ignoredConcepts == null) { 392 ignoredConcepts = unsatisfiableClasses; 393 } else { 394 ignoredConcepts.addAll(unsatisfiableClasses); 395 } 396 } 397 398 399 Set<OWLClass> usedConcepts; 400 if(allowedConcepts != null) { 401 // sanity check to control if no non-existing concepts are in the list 402 Helper.checkConcepts(reasoner, allowedConcepts); 403 usedConcepts = allowedConcepts; 404 } else if(ignoredConcepts != null) { 405 usedConcepts = Helper.computeConceptsUsingIgnoreList(reasoner, ignoredConcepts); 406 } else { 407 usedConcepts = Helper.computeConcepts(reasoner); 408 } 409 410 ClassHierarchy hierarchy = (ClassHierarchy) reasoner.getClassHierarchy().cloneAndRestrict(new HashSet<OWLClassExpression>(usedConcepts)); 411// hierarchy.thinOutSubsumptionHierarchy(); 412 return hierarchy; 413 } 414 415 /** 416 * Computes an internal object property hierarchy that only contains 417 * object properties that are allowed. 418 * @return optimized object property hierarchy 419 */ 420 protected ObjectPropertyHierarchy initObjectPropertyHierarchy() { 421 Set<OWLObjectProperty> usedProperties; 422 if(allowedObjectProperties != null) { 423 // sanity check to control if no non-existing object properties are in the list 424 Helper.checkRoles(reasoner, allowedObjectProperties); 425 usedProperties = allowedObjectProperties; 426 } else if(ignoredObjectProperties != null) { 427 usedProperties = Helper.computeEntitiesUsingIgnoreList(reasoner, EntityType.OBJECT_PROPERTY, ignoredObjectProperties); 428 } else { 429 usedProperties = Helper.computeEntities(reasoner, EntityType.OBJECT_PROPERTY); 430 } 431 432 ObjectPropertyHierarchy hierarchy = (ObjectPropertyHierarchy) reasoner.getObjectPropertyHierarchy().cloneAndRestrict(usedProperties); 433// hierarchy.thinOutSubsumptionHierarchy(); 434 435 return hierarchy; 436 } 437 438 /** 439 * Computes an internal data property hierarchy that only contains 440 * data properties that are allowed. 441 * @return optimized data property hierarchy 442 */ 443 protected DatatypePropertyHierarchy initDataPropertyHierarchy() { 444 Set<OWLDataProperty> usedProperties; 445 if(allowedDataProperties != null) { 446 // sanity check to control if no non-existing data properties are in the list 447 Helper.checkEntities(reasoner, allowedDataProperties); 448 usedProperties = allowedDataProperties; 449 } else if(ignoredDataProperties != null) { 450 usedProperties = Helper.computeEntitiesUsingIgnoreList(reasoner, EntityType.DATA_PROPERTY, ignoredDataProperties); 451 } else { 452 usedProperties = Helper.computeEntities(reasoner, EntityType.DATA_PROPERTY); 453 } 454 455 DatatypePropertyHierarchy hierarchy = (DatatypePropertyHierarchy) reasoner.getDatatypePropertyHierarchy().cloneAndRestrict(usedProperties); 456// hierarchy.thinOutSubsumptionHierarchy(); 457 return hierarchy; 458 } 459 460 protected boolean isTimeExpired() { 461 return getCurrentRuntimeInMilliSeconds() >= TimeUnit.SECONDS.toMillis(maxExecutionTimeInSeconds); 462 } 463 464 protected long getCurrentRuntimeInMilliSeconds() { 465 return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - nanoStartTime); 466 } 467 468 protected long getRemainingRuntimeInMilliseconds() { 469 return Math.max(0, TimeUnit.SECONDS.toMillis(maxExecutionTimeInSeconds) - getCurrentRuntimeInMilliSeconds()); 470 } 471 472 protected String getDurationAsString(long durationInMillis) { 473 PeriodFormatter formatter = new PeriodFormatterBuilder() 474 .appendDays().appendSuffix("d") 475 .appendHours().appendSuffix("h") 476 .appendMinutes().appendSuffix("m") 477 .appendSeconds().appendSuffix("s") 478 .appendMillis().appendSuffix("ms") 479 .printZeroNever() 480 .toFormatter(); 481 482 return formatter.print(new Period(durationInMillis)); 483 } 484 485 protected OWLClassExpression rewrite(OWLClassExpression ce) { 486 // minimize class expression (expensive!) - also performs some human friendly rewrites 487 OWLClassExpression niceDescription; 488 if (useMinimizer) { 489 niceDescription = minimizer.minimizeClone(ce); 490 } else { 491 niceDescription = ce; 492 } 493 494 // replace \exists r.\top with \exists r.range(r) which is easier to read for humans 495 niceDescription = ConceptTransformation.replaceRange(niceDescription, reasoner); 496 497 niceDescription = ConceptTransformation.appendSomeValuesFrom(niceDescription); 498 499 return niceDescription; 500 } 501 502 /** 503 * The learning problem variable, which must be used by 504 * all learning algorithm implementations. 505 */ 506 @Override 507 public AbstractClassExpressionLearningProblem<? extends Score> getLearningProblem() { 508 return learningProblem; 509 } 510 511 @Autowired 512 @Override 513 public void setLearningProblem(LearningProblem learningProblem) { 514 this.learningProblem = (AbstractClassExpressionLearningProblem<? extends Score>)learningProblem; 515 } 516 517 /** 518 * The reasoning service variable, which must be used by 519 * all learning algorithm implementations. 520 */ 521 public AbstractReasonerComponent getReasoner() { 522 return reasoner; 523 } 524 525 @Autowired 526 public void setReasoner(AbstractReasonerComponent reasoner) { 527 this.reasoner = reasoner; 528 529 baseURI = reasoner.getBaseURI(); 530 prefixes = reasoner.getPrefixes(); 531 } 532 533 @Override 534 public void stop() { 535 stop = true; 536 } 537 538 @Override 539 public boolean isRunning() { 540 return isRunning; 541 } 542 543 public Set<OWLClass> getAllowedConcepts() { 544 return allowedConcepts; 545 } 546 547 public void setAllowedConcepts(Set<OWLClass> allowedConcepts) { 548 this.allowedConcepts = allowedConcepts; 549 } 550 551 public Set<OWLClass> getIgnoredConcepts() { 552 return ignoredConcepts; 553 } 554 555 public void setIgnoredConcepts(Set<OWLClass> ignoredConcepts) { 556 this.ignoredConcepts = ignoredConcepts; 557 } 558 559 /** 560 * @param allowedObjectProperties the allowed object properties to set 561 */ 562 public void setAllowedObjectProperties(Set<OWLObjectProperty> allowedObjectProperties) { 563 this.allowedObjectProperties = allowedObjectProperties; 564 } 565 566 /** 567 * @return the allowed object properties 568 */ 569 public Set<OWLObjectProperty> getAllowedObjectProperties() { 570 return allowedObjectProperties; 571 } 572 573 /** 574 * @param ignoredObjectProperties the ignored object properties to set 575 */ 576 public void setIgnoredObjectProperties(Set<OWLObjectProperty> ignoredObjectProperties) { 577 this.ignoredObjectProperties = ignoredObjectProperties; 578 } 579 580 /** 581 * @return the ignored object properties 582 */ 583 public Set<OWLObjectProperty> getIgnoredObjectProperties() { 584 return ignoredObjectProperties; 585 } 586 587 /** 588 * @param allowedDataProperties the allowed data properties to set 589 */ 590 public void setAllowedDataProperties(Set<OWLDataProperty> allowedDataProperties) { 591 this.allowedDataProperties = allowedDataProperties; 592 } 593 594 /** 595 * @return the allowed data properties 596 */ 597 public Set<OWLDataProperty> getAllowedDataProperties() { 598 return allowedDataProperties; 599 } 600 601 /** 602 * @param ignoredDataProperties the ignored data properties to set 603 */ 604 public void setIgnoredDataProperties(Set<OWLDataProperty> ignoredDataProperties) { 605 this.ignoredDataProperties = ignoredDataProperties; 606 } 607 608 /** 609 * @return the ignored data properties 610 */ 611 public Set<OWLDataProperty> getIgnoredDataProperties() { 612 return ignoredDataProperties; 613 } 614 615 public boolean isUseMinimizer() { 616 return useMinimizer; 617 } 618 619 public void setUseMinimizer(boolean useMinimizer) { 620 this.useMinimizer = useMinimizer; 621 } 622 623 public long getMaxExecutionTimeInSeconds() { 624 return maxExecutionTimeInSeconds; 625 } 626 627 /** 628 * Set the max. execution time in seconds of the algorithm. It's expected that the 629 * algorithm will terminate gracefully. 630 * 631 * @param maxExecutionTimeInSeconds max. execution time in seconds 632 */ 633 public void setMaxExecutionTimeInSeconds(long maxExecutionTimeInSeconds) { 634 this.maxExecutionTimeInSeconds = maxExecutionTimeInSeconds; 635 } 636 637 /** 638 * Set the max. execution time of the algorithm. It's expected that the 639 * algorithm will terminate gracefully. 640 * 641 * @param maxExecutionTime max. execution time 642 * @param timeUnit the time unit 643 */ 644 public void setMaxExecutionTime(long maxExecutionTime, TimeUnit timeUnit) { 645 this.maxExecutionTimeInSeconds = timeUnit.toSeconds(maxExecutionTime); 646 } 647 648 /** 649 * @param renderer the renderer of OWL objects to set 650 */ 651 public void setRenderer(OWLObjectRenderer renderer) { 652 this.renderer = renderer; 653 } 654 655 /** 656 * The goal of this method is to rewrite the class expression CE, to get a more informative one by e.g. 657 * <ul><li>replacing the role fillers in CE with the range of the property, if exists.</li></ul> 658 * @param ce the class expression 659 * @return the modified class expression 660 */ 661 protected OWLClassExpression getNiceDescription(OWLClassExpression ce){ 662 OWLClassExpression rewrittenClassExpression = ce; 663 if(ce instanceof OWLObjectIntersectionOf){ 664 Set<OWLClassExpression> newOperands = new TreeSet<>(((OWLObjectIntersectionOf) ce).getOperands()); 665 for (OWLClassExpression operand : ((OWLObjectIntersectionOf) ce).getOperands()) { 666 newOperands.add(getNiceDescription(operand)); 667 } 668 rewrittenClassExpression = dataFactory.getOWLObjectIntersectionOf(newOperands); 669 } else if(ce instanceof OWLObjectSomeValuesFrom) { 670 // \exists r.\bot \equiv \bot 671 OWLObjectProperty property = ((OWLObjectSomeValuesFrom) ce).getProperty().asOWLObjectProperty(); 672 OWLClassExpression filler = ((OWLObjectSomeValuesFrom) ce).getFiller(); 673 if(filler.isOWLThing()) { 674 OWLClassExpression range = reasoner.getRange(property); 675 filler = range; 676 } else if(filler.isAnonymous()){ 677 filler = getNiceDescription(filler); 678 } 679 rewrittenClassExpression = dataFactory.getOWLObjectSomeValuesFrom(property, filler); 680 } 681 return rewrittenClassExpression; 682 } 683}