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.reasoning; 020 021import com.google.common.base.StandardSystemProperty; 022import org.dllearner.kb.OWLAPIOntology; 023import org.dllearner.kb.OWLOntologyKnowledgeSource; 024import org.joda.time.Period; 025import org.joda.time.format.PeriodFormat; 026import org.semanticweb.owlapi.apibinding.OWLManager; 027import org.semanticweb.owlapi.model.*; 028import org.semanticweb.owlapi.model.parameters.AxiomAnnotations; 029import org.semanticweb.owlapi.reasoner.*; 030import org.semanticweb.owlapi.reasoner.impl.*; 031import org.semanticweb.owlapi.search.EntitySearcher; 032import org.semanticweb.owlapi.util.CollectionFactory; 033import org.semanticweb.owlapi.util.OWLObjectPropertyManager; 034import org.semanticweb.owlapi.util.Version; 035 036import javax.annotation.Nonnull; 037import java.io.File; 038import java.util.*; 039import java.util.stream.Stream; 040 041import static org.semanticweb.owlapi.model.parameters.Imports.INCLUDED; 042 043/** 044 * Author: Matthew Horridge<br> 045 * The University of Manchester<br> 046 * Information Management Group<br> 047 * Date: 04-Dec-2009 048 * </p> 049 * This is a simple structural reasoner that essentially answers with told information. It is incomplete. 050 */ 051public class StructuralReasonerExtended extends OWLReasonerBase { 052 053 private final ClassHierarchyInfo classHierarchyInfo = new ClassHierarchyInfo(); 054 055 private final ObjectPropertyHierarchyInfo objectPropertyHierarchyInfo = new ObjectPropertyHierarchyInfo(); 056 057 private final DataPropertyHierarchyInfo dataPropertyHierarchyInfo = new DataPropertyHierarchyInfo(); 058 059 private static final Version version = new Version(1, 0, 0, 0); 060 061 private boolean interrupted = false; 062 063 protected final ReasonerProgressMonitor pm; 064 065 private boolean prepared = false; 066 067 private OWLDataFactory df; 068 069 /** 070 * @param rootOntology the ontology 071 * @param configuration the reasoner configuration 072 * @param bufferingMode the buffering mode 073 */ 074 public StructuralReasonerExtended(OWLOntology rootOntology, OWLReasonerConfiguration configuration, BufferingMode bufferingMode) { 075 super(rootOntology, configuration, bufferingMode); 076 pm = configuration.getProgressMonitor(); 077 prepareReasoner(); 078 df = rootOntology.getOWLOntologyManager().getOWLDataFactory(); 079 } 080 081 @Nonnull 082 @Override 083 public String getReasonerName() { 084 return "Structural Reasoner"; 085 } 086 087 @Nonnull 088 @Override 089 public FreshEntityPolicy getFreshEntityPolicy() { 090 return FreshEntityPolicy.ALLOW; 091 } 092 093 @Nonnull 094 @Override 095 public IndividualNodeSetPolicy getIndividualNodeSetPolicy() { 096 return IndividualNodeSetPolicy.BY_NAME; 097 } 098 099 @Nonnull 100 @Override 101 public Version getReasonerVersion() { 102 return version; 103 } 104 105 @Override 106 protected void handleChanges(@Nonnull Set<OWLAxiom> addAxioms, @Nonnull Set<OWLAxiom> removeAxioms) { 107 handleChanges(addAxioms, removeAxioms, classHierarchyInfo); 108 handleChanges(addAxioms, removeAxioms, objectPropertyHierarchyInfo); 109 handleChanges(addAxioms, removeAxioms, dataPropertyHierarchyInfo); 110 } 111 112 private <T extends OWLObject> void handleChanges(Set<OWLAxiom> added, Set<OWLAxiom> removed, HierarchyInfo<T> hierarchyInfo) { 113 Set<T> sig = hierarchyInfo.getEntitiesInSignature(added); 114 sig.addAll(hierarchyInfo.getEntitiesInSignature(removed)); 115 hierarchyInfo.processChanges(sig, added, removed); 116 117 } 118 119 @Override 120 public void interrupt() { 121 interrupted = true; 122 } 123 124 private void ensurePrepared() { 125 if (!prepared) { 126 prepareReasoner(); 127 } 128 } 129 130 /** 131 * @throws ReasonerInterruptedException on interruption 132 * @throws TimeOutException on timeout 133 */ 134 public void prepareReasoner() throws ReasonerInterruptedException, TimeOutException { 135 classHierarchyInfo.computeHierarchy(); 136 objectPropertyHierarchyInfo.computeHierarchy(); 137 dataPropertyHierarchyInfo.computeHierarchy(); 138 prepared = true; 139 } 140 141 @Override 142 143 public void precomputeInferences(@Nonnull InferenceType... inferenceTypes) throws ReasonerInterruptedException, TimeOutException, InconsistentOntologyException { 144 prepareReasoner(); 145 } 146 147 @Override 148 149 public boolean isPrecomputed(@Nonnull InferenceType inferenceType) { 150 return true; 151 } 152 153 @Nonnull 154 @Override 155 public Set<InferenceType> getPrecomputableInferenceTypes() { 156 return CollectionFactory.createSet(InferenceType.CLASS_HIERARCHY, InferenceType.OBJECT_PROPERTY_HIERARCHY, InferenceType.DATA_PROPERTY_HIERARCHY); 157 } 158 159 protected void throwExceptionIfInterrupted() { 160 if (interrupted) { 161 interrupted = false; 162 throw new ReasonerInterruptedException(); 163 } 164 } 165 166 ////////////////////////////////////////////////////////////////////////////////////////////////////// 167 168 @Override 169 public boolean isConsistent() throws ReasonerInterruptedException, TimeOutException { 170 return true; 171 } 172 173 @Override 174 public boolean isSatisfiable(@Nonnull OWLClassExpression classExpression) throws ReasonerInterruptedException, TimeOutException, ClassExpressionNotInProfileException, FreshEntitiesException, InconsistentOntologyException { 175 return !classExpression.isAnonymous() && !getEquivalentClasses(classExpression.asOWLClass()).contains(getDataFactory().getOWLNothing()); 176 } 177 178 @Nonnull 179 @Override 180 public Node<OWLClass> getUnsatisfiableClasses() throws ReasonerInterruptedException, TimeOutException { 181 return OWLClassNode.getBottomNode(); 182 } 183 184 @Override 185 public boolean isEntailed(@Nonnull OWLAxiom axiom) throws ReasonerInterruptedException, UnsupportedEntailmentTypeException, TimeOutException, AxiomNotInProfileException, FreshEntitiesException, InconsistentOntologyException { 186 boolean containsAxiom = getRootOntology().containsAxiom(axiom, INCLUDED, AxiomAnnotations.IGNORE_AXIOM_ANNOTATIONS); 187 188 if(containsAxiom){ 189 return true; 190 } 191 192 if (axiom instanceof OWLClassAssertionAxiom) {// extension of OWL API code 193 ensurePrepared(); 194 195 OWLClassExpression ce = ((OWLClassAssertionAxiom) axiom).getClassExpression(); 196 OWLIndividual individual = ((OWLClassAssertionAxiom) axiom).getIndividual(); 197 198 if (ce.isOWLThing()) { 199 return true; 200 } else if (ce.isOWLNothing()) { 201 return false; 202 } else if (!ce.isAnonymous()) { 203 return getSubClasses(ce.asOWLClass(), false).getFlattened().stream() 204 .anyMatch(sub -> getRootOntology().containsAxiom(df.getOWLClassAssertionAxiom(sub, individual), INCLUDED, AxiomAnnotations.IGNORE_AXIOM_ANNOTATIONS)); 205 } else { 206 if (ce instanceof OWLObjectIntersectionOf) { 207 return ((OWLObjectIntersectionOf) ce).getOperands().stream() 208 .allMatch(op -> isEntailed(df.getOWLClassAssertionAxiom(op, individual))); 209 } else if (ce instanceof OWLObjectUnionOf) { 210 return ((OWLObjectUnionOf) ce).getOperands().stream() 211 .anyMatch(op -> isEntailed(df.getOWLClassAssertionAxiom(op, individual))); 212 } else if (ce instanceof OWLObjectSomeValuesFrom) { 213 OWLObjectPropertyExpression ope = ((OWLObjectSomeValuesFrom) ce).getProperty(); 214 215 OWLClassExpression filler = ((OWLObjectSomeValuesFrom) ce).getFiller(); 216 217 Set<OWLIndividualAxiom> axioms = getRootOntology().getAxioms(individual, INCLUDED); 218 219 for (OWLIndividualAxiom curAx : axioms) { 220 if(curAx instanceof OWLObjectPropertyAssertionAxiom && 221 ope.equals(((OWLObjectPropertyAssertionAxiom) curAx).getProperty())) { 222 223 OWLIndividual object = ((OWLObjectPropertyAssertionAxiom) curAx).getObject(); 224 return isEntailed(df.getOWLClassAssertionAxiom(filler, object)); 225 } 226 } 227 return false; 228 } 229 } 230 } 231 232 return false; 233 } 234 235 @Override 236 public boolean isEntailed(@Nonnull Set<? extends OWLAxiom> axioms) throws ReasonerInterruptedException, UnsupportedEntailmentTypeException, TimeOutException, AxiomNotInProfileException, FreshEntitiesException, InconsistentOntologyException { 237 for (OWLAxiom ax : axioms) { 238 assert ax != null; 239 if (!getRootOntology().containsAxiom(ax, INCLUDED, AxiomAnnotations.IGNORE_AXIOM_ANNOTATIONS)) { 240 return false; 241 } 242 } 243 return true; 244 } 245 246 @Override 247 248 public boolean isEntailmentCheckingSupported(@Nonnull AxiomType<?> axiomType) { 249 return false; 250 } 251 252 @Nonnull 253 @Override 254 public Node<OWLClass> getTopClassNode() { 255 ensurePrepared(); 256 return classHierarchyInfo.getEquivalents(getDataFactory().getOWLThing()); 257 } 258 259 @Nonnull 260 @Override 261 public Node<OWLClass> getBottomClassNode() { 262 ensurePrepared(); 263 return classHierarchyInfo.getEquivalents(getDataFactory().getOWLNothing()); 264 } 265 266 @Nonnull 267 @Override 268 public NodeSet<OWLClass> getSubClasses(@Nonnull OWLClassExpression ce, boolean direct) throws InconsistentOntologyException, ClassExpressionNotInProfileException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 269 OWLClassNodeSet ns = new OWLClassNodeSet(); 270 if (!ce.isAnonymous()) { 271 ensurePrepared(); 272 return classHierarchyInfo.getNodeHierarchyChildren(ce.asOWLClass(), direct, ns); 273 } 274 return ns; 275 } 276 277 @Nonnull 278 @Override 279 public NodeSet<OWLClass> getSuperClasses(@Nonnull OWLClassExpression ce, boolean direct) throws InconsistentOntologyException, ClassExpressionNotInProfileException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 280 OWLClassNodeSet ns = new OWLClassNodeSet(); 281 if (!ce.isAnonymous()) { 282 ensurePrepared(); 283 return classHierarchyInfo.getNodeHierarchyParents(ce.asOWLClass(), direct, ns); 284 } 285 return ns; 286 } 287 288 @Nonnull 289 @Override 290 public Node<OWLClass> getEquivalentClasses(@Nonnull OWLClassExpression ce) throws InconsistentOntologyException, ClassExpressionNotInProfileException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 291 ensurePrepared(); 292 if (!ce.isAnonymous()) { 293 return classHierarchyInfo.getEquivalents(ce.asOWLClass()); 294 } 295 else { 296 return new OWLClassNode(); 297 } 298 } 299 300 @Nonnull 301 @Override 302 public NodeSet<OWLClass> getDisjointClasses(@Nonnull OWLClassExpression ce) { 303 ensurePrepared(); 304 OWLClassNodeSet nodeSet = new OWLClassNodeSet(); 305 if (!ce.isAnonymous()) { 306 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 307 for (OWLDisjointClassesAxiom ax : ontology.getDisjointClassesAxioms(ce.asOWLClass())) { 308 for (OWLClassExpression op : ax.getClassExpressions()) { 309 if (!op.isAnonymous()) { 310 nodeSet.addNode(getEquivalentClasses(op)); 311 } 312 } 313 } 314 } 315 } 316 return nodeSet; 317 } 318 319 @Nonnull 320 @Override 321 public Node<OWLObjectPropertyExpression> getTopObjectPropertyNode() { 322 ensurePrepared(); 323 return objectPropertyHierarchyInfo.getEquivalents(getDataFactory().getOWLTopObjectProperty()); 324 } 325 326 @Nonnull 327 @Override 328 public Node<OWLObjectPropertyExpression> getBottomObjectPropertyNode() { 329 ensurePrepared(); 330 return objectPropertyHierarchyInfo.getEquivalents(getDataFactory().getOWLBottomObjectProperty()); 331 } 332 333 @Nonnull 334 @Override 335 public NodeSet<OWLObjectPropertyExpression> getSubObjectProperties(@Nonnull OWLObjectPropertyExpression pe, boolean direct) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 336 OWLObjectPropertyNodeSet ns = new OWLObjectPropertyNodeSet(); 337 ensurePrepared(); 338 return objectPropertyHierarchyInfo.getNodeHierarchyChildren(pe, direct, ns); 339 } 340 341 @Nonnull 342 @Override 343 public NodeSet<OWLObjectPropertyExpression> getSuperObjectProperties(@Nonnull OWLObjectPropertyExpression pe, boolean direct) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 344 OWLObjectPropertyNodeSet ns = new OWLObjectPropertyNodeSet(); 345 ensurePrepared(); 346 return objectPropertyHierarchyInfo.getNodeHierarchyParents(pe, direct, ns); 347 } 348 349 @Nonnull 350 @Override 351 public Node<OWLObjectPropertyExpression> getEquivalentObjectProperties(@Nonnull OWLObjectPropertyExpression pe) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 352 ensurePrepared(); 353 return objectPropertyHierarchyInfo.getEquivalents(pe); 354 } 355 356 @Nonnull 357 @Override 358 359 public NodeSet<OWLObjectPropertyExpression> getDisjointObjectProperties(@Nonnull OWLObjectPropertyExpression pe) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 360 return new OWLObjectPropertyNodeSet(); 361 } 362 363 @Nonnull 364 @Override 365 public Node<OWLObjectPropertyExpression> getInverseObjectProperties(@Nonnull OWLObjectPropertyExpression pe) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 366 ensurePrepared(); 367 OWLObjectPropertyExpression inv = pe.getInverseProperty(); 368 return getEquivalentObjectProperties(inv); 369 } 370 371 @Nonnull 372 @Override 373 public NodeSet<OWLClass> getObjectPropertyDomains(@Nonnull OWLObjectPropertyExpression pe, boolean direct) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 374 375 ensurePrepared(); 376 DefaultNodeSet<OWLClass> result = new OWLClassNodeSet(); 377 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 378 for (OWLObjectPropertyDomainAxiom axiom : ontology.getObjectPropertyDomainAxioms(pe)) { 379 result.addNode(getEquivalentClasses(axiom.getDomain())); 380 if (!direct) { 381 result.addAllNodes(getSuperClasses(axiom.getDomain(), false).getNodes()); 382 } 383 } 384 385 for (OWLObjectPropertyExpression invPe : getInverseObjectProperties(pe).getEntities()) { 386 for (OWLObjectPropertyRangeAxiom axiom : ontology.getObjectPropertyRangeAxioms(invPe)) { 387 result.addNode(getEquivalentClasses(axiom.getRange())); 388 if (!direct) { 389 result.addAllNodes(getSuperClasses(axiom.getRange(), false).getNodes()); 390 } 391 } 392 } 393 } 394 return result; 395 } 396 397 @Nonnull 398 @Override 399 public NodeSet<OWLClass> getObjectPropertyRanges(@Nonnull OWLObjectPropertyExpression pe, boolean direct) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 400 ensurePrepared(); 401 DefaultNodeSet<OWLClass> result = new OWLClassNodeSet(); 402 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 403 for (OWLObjectPropertyRangeAxiom axiom : ontology.getObjectPropertyRangeAxioms(pe)) { 404 result.addNode(getEquivalentClasses(axiom.getRange())); 405 if (!direct) { 406 result.addAllNodes(getSuperClasses(axiom.getRange(), false).getNodes()); 407 } 408 } 409 for (OWLObjectPropertyExpression invPe : getInverseObjectProperties(pe).getEntities()) { 410 for (OWLObjectPropertyDomainAxiom axiom : ontology.getObjectPropertyDomainAxioms(invPe)) { 411 result.addNode(getEquivalentClasses(axiom.getDomain())); 412 if (!direct) { 413 result.addAllNodes(getSuperClasses(axiom.getDomain(), false).getNodes()); 414 } 415 } 416 } 417 } 418 return result; 419 } 420 421 @Nonnull 422 @Override 423 public Node<OWLDataProperty> getTopDataPropertyNode() { 424 ensurePrepared(); 425 return dataPropertyHierarchyInfo.getEquivalents(getDataFactory().getOWLTopDataProperty()); 426 } 427 428 @Nonnull 429 @Override 430 public Node<OWLDataProperty> getBottomDataPropertyNode() { 431 ensurePrepared(); 432 return dataPropertyHierarchyInfo.getEquivalents(getDataFactory().getOWLBottomDataProperty()); 433 } 434 435 @Nonnull 436 @Override 437 public NodeSet<OWLDataProperty> getSubDataProperties(@Nonnull OWLDataProperty pe, boolean direct) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 438 ensurePrepared(); 439 OWLDataPropertyNodeSet ns = new OWLDataPropertyNodeSet(); 440 return dataPropertyHierarchyInfo.getNodeHierarchyChildren(pe, direct, ns); 441 } 442 443 @Nonnull 444 @Override 445 public NodeSet<OWLDataProperty> getSuperDataProperties(@Nonnull OWLDataProperty pe, boolean direct) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 446 ensurePrepared(); 447 OWLDataPropertyNodeSet ns = new OWLDataPropertyNodeSet(); 448 return dataPropertyHierarchyInfo.getNodeHierarchyParents(pe, direct, ns); 449 } 450 451 @Nonnull 452 @Override 453 public Node<OWLDataProperty> getEquivalentDataProperties(@Nonnull OWLDataProperty pe) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 454 ensurePrepared(); 455 return dataPropertyHierarchyInfo.getEquivalents(pe); 456 } 457 458 @Nonnull 459 @Override 460 public NodeSet<OWLDataProperty> getDisjointDataProperties(@Nonnull OWLDataPropertyExpression pe) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 461 ensurePrepared(); 462 DefaultNodeSet<OWLDataProperty> result = new OWLDataPropertyNodeSet(); 463 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 464 for (OWLDisjointDataPropertiesAxiom axiom : ontology.getDisjointDataPropertiesAxioms(pe.asOWLDataProperty())) { 465 for (OWLDataPropertyExpression dpe : axiom.getPropertiesMinus(pe)) { 466 if (!dpe.isAnonymous()) { 467 result.addNode(dataPropertyHierarchyInfo.getEquivalents(dpe.asOWLDataProperty())); 468 result.addAllNodes(getSubDataProperties(dpe.asOWLDataProperty(), false).getNodes()); 469 } 470 } 471 } 472 } 473 return result; 474 } 475 476 @Nonnull 477 @Override 478 public NodeSet<OWLClass> getDataPropertyDomains(@Nonnull OWLDataProperty pe, boolean direct) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 479 ensurePrepared(); 480 DefaultNodeSet<OWLClass> result = new OWLClassNodeSet(); 481 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 482 for (OWLDataPropertyDomainAxiom axiom : ontology.getDataPropertyDomainAxioms(pe)) { 483 result.addNode(getEquivalentClasses(axiom.getDomain())); 484 if (!direct) { 485 result.addAllNodes(getSuperClasses(axiom.getDomain(), false).getNodes()); 486 } 487 } 488 } 489 return result; 490 } 491 492 @Nonnull 493 @Override 494 public NodeSet<OWLClass> getTypes(@Nonnull OWLNamedIndividual ind, boolean direct) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 495 ensurePrepared(); 496 DefaultNodeSet<OWLClass> result = new OWLClassNodeSet(); 497 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 498 for (OWLClassAssertionAxiom axiom : ontology.getClassAssertionAxioms(ind)) { 499 OWLClassExpression ce = axiom.getClassExpression(); 500 if (!ce.isAnonymous()) { 501 result.addNode(classHierarchyInfo.getEquivalents(ce.asOWLClass())); 502 if (!direct) { 503 result.addAllNodes(getSuperClasses(ce, false).getNodes()); 504 } 505 } 506 } 507 } 508 return result; 509 } 510 511 @Nonnull 512 @Override 513 public NodeSet<OWLNamedIndividual> getInstances(@Nonnull OWLClassExpression ce, boolean direct) throws InconsistentOntologyException, ClassExpressionNotInProfileException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 514 ensurePrepared(); 515 DefaultNodeSet<OWLNamedIndividual> result = new OWLNamedIndividualNodeSet(); 516 if (!ce.isAnonymous()) { 517 OWLClass cls = ce.asOWLClass(); 518 Set<OWLClass> clses = new HashSet<>(); 519 clses.add(cls); 520 if (!direct) { 521 clses.addAll(getSubClasses(cls, false).getFlattened()); 522 } 523 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 524 for (OWLClass curCls : clses) { 525 for (OWLClassAssertionAxiom axiom : ontology.getClassAssertionAxioms(curCls)) { 526 OWLIndividual individual = axiom.getIndividual(); 527 if (!individual.isAnonymous()) { 528 if (getIndividualNodeSetPolicy().equals(IndividualNodeSetPolicy.BY_SAME_AS)) { 529 result.addNode(getSameIndividuals(individual.asOWLNamedIndividual())); 530 } 531 else { 532 result.addNode(new OWLNamedIndividualNode(individual.asOWLNamedIndividual())); 533 } 534 } 535 } 536 } 537 } 538 } else { // extension of OWL API implementation 539 if(ce instanceof OWLObjectIntersectionOf){ 540 List<OWLClassExpression> operands = ((OWLObjectIntersectionOf) ce).getOperandsAsList(); 541 542 Set<Node<OWLNamedIndividual>> tmp = new HashSet<>(); 543 544 tmp.addAll(getInstances(operands.get(0), direct).getNodes()); 545 546 for (int i = 1; i < operands.size(); i++) { 547 tmp.retainAll(getInstances(operands.get(i), direct).getNodes()); 548 } 549 result.addAllNodes(tmp); 550 } else if(ce instanceof OWLObjectUnionOf){ 551 Set<OWLClassExpression> operands = ((OWLObjectUnionOf) ce).getOperands(); 552 553 for (OWLClassExpression op : operands) { 554 result.addAllNodes(getInstances(op, direct).getNodes()); 555 } 556 } else if(ce instanceof OWLObjectSomeValuesFrom){ 557 System.out.println(ce); 558 OWLObjectPropertyExpression ope = ((OWLObjectSomeValuesFrom) ce).getProperty(); 559 OWLClassExpression filler = ((OWLObjectSomeValuesFrom) ce).getFiller(); 560 Set<OWLObjectPropertyExpression> properties = new HashSet<>(); 561 properties.add(ope.asOWLObjectProperty()); 562 if (!direct) { 563 properties.addAll(getSubObjectProperties(ope, false).getFlattened()); 564 } 565 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 566 for (OWLObjectPropertyExpression curProp : properties) { 567 Set<OWLAxiom> referencingAxioms = ontology.getReferencingAxioms(curProp.asOWLObjectProperty()); 568 569 for (OWLAxiom axiom : referencingAxioms) { 570 if(axiom instanceof OWLObjectPropertyAssertionAxiom){ 571 // check if object is instance of filler 572 OWLIndividual object = ((OWLObjectPropertyAssertionAxiom) axiom).getObject(); 573 if(!object.isAnonymous()){ 574 if(filler.isOWLThing() || getInstances(filler, false).containsEntity(object.asOWLNamedIndividual())){ 575 OWLIndividual subject = ((OWLObjectPropertyAssertionAxiom) axiom).getSubject(); 576 if (!subject.isAnonymous()) { 577 if (getIndividualNodeSetPolicy().equals(IndividualNodeSetPolicy.BY_SAME_AS)) { 578 result.addNode(getSameIndividuals(subject.asOWLNamedIndividual())); 579 } 580 else { 581 result.addNode(new OWLNamedIndividualNode(subject.asOWLNamedIndividual())); 582 } 583 } 584 } 585 } 586 } 587 } 588 } 589 } 590 } else if(ce instanceof OWLObjectAllValuesFrom){ 591 592 } 593 } 594 return result; 595 } 596 597 @Nonnull 598 @Override 599 public NodeSet<OWLNamedIndividual> getObjectPropertyValues(@Nonnull OWLNamedIndividual ind, @Nonnull OWLObjectPropertyExpression pe) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 600 ensurePrepared(); 601 OWLNamedIndividualNodeSet result = new OWLNamedIndividualNodeSet(); 602 Node<OWLObjectPropertyExpression> inverses = getInverseObjectProperties(pe); 603 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 604 for (OWLObjectPropertyAssertionAxiom axiom : ontology.getObjectPropertyAssertionAxioms(ind)) { 605 if (!axiom.getObject().isAnonymous()) { 606 if (axiom.getProperty().equals(pe)) { 607 if (getIndividualNodeSetPolicy().equals(IndividualNodeSetPolicy.BY_SAME_AS)) { 608 result.addNode(getSameIndividuals(axiom.getObject().asOWLNamedIndividual())); 609 } 610 else { 611 result.addNode(new OWLNamedIndividualNode(axiom.getObject().asOWLNamedIndividual())); 612 } 613 } 614 } 615 // Inverse of pe 616 if (axiom.getObject().equals(ind) && !axiom.getSubject().isAnonymous()) { 617 OWLObjectPropertyExpression invPe = axiom.getProperty().getInverseProperty(); 618 if (!invPe.isAnonymous() && inverses.contains(invPe.asOWLObjectProperty())) { 619 if (getIndividualNodeSetPolicy().equals(IndividualNodeSetPolicy.BY_SAME_AS)) { 620 result.addNode(getSameIndividuals(axiom.getObject().asOWLNamedIndividual())); 621 } 622 else { 623 result.addNode(new OWLNamedIndividualNode(axiom.getObject().asOWLNamedIndividual())); 624 } 625 } 626 } 627 628 } 629 } 630 // Could do other stuff like inspecting owl:hasValue restrictions 631 return result; 632 } 633 634 @Nonnull 635 @Override 636 public Set<OWLLiteral> getDataPropertyValues(@Nonnull OWLNamedIndividual ind, @Nonnull OWLDataProperty pe) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 637 ensurePrepared(); 638 Set<OWLLiteral> literals = new HashSet<>(); 639 Set<OWLDataProperty> superProperties = getSuperDataProperties(pe, false).getFlattened(); 640 superProperties.addAll(getEquivalentDataProperties(pe).getEntities()); 641 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 642 for (OWLDataPropertyAssertionAxiom axiom : ontology.getDataPropertyAssertionAxioms(ind)) { 643 if (superProperties.contains(axiom.getProperty().asOWLDataProperty())) { 644 literals.add(axiom.getObject()); 645 } 646 } 647 } 648 return literals; 649 } 650 651 @Nonnull 652 @Override 653 public Node<OWLNamedIndividual> getSameIndividuals(@Nonnull OWLNamedIndividual ind) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 654 ensurePrepared(); 655 Set<OWLNamedIndividual> inds = new HashSet<>(); 656 Set<OWLSameIndividualAxiom> processed = new HashSet<>(); 657 List<OWLNamedIndividual> stack = new ArrayList<>(); 658 stack.add(ind); 659 while (!stack.isEmpty()) { 660 OWLNamedIndividual currentInd = stack.remove(0); 661 for (OWLOntology ontology : getRootOntology().getImportsClosure()) { 662 for (OWLSameIndividualAxiom axiom : ontology.getSameIndividualAxioms(currentInd)) { 663 if (!processed.contains(axiom)) { 664 processed.add(axiom); 665 for (OWLIndividual i : axiom.getIndividuals()) { 666 if (!i.isAnonymous()) { 667 OWLNamedIndividual namedInd = i.asOWLNamedIndividual(); 668 if (!inds.contains(namedInd)) { 669 inds.add(namedInd); 670 stack.add(namedInd); 671 } 672 } 673 } 674 } 675 } 676 } 677 } 678 679 return new OWLNamedIndividualNode(inds); 680 } 681 682 @Nonnull 683 @Override 684 685 public NodeSet<OWLNamedIndividual> getDifferentIndividuals(@Nonnull OWLNamedIndividual ind) throws InconsistentOntologyException, FreshEntitiesException, ReasonerInterruptedException, TimeOutException { 686 return new OWLNamedIndividualNodeSet(); 687 } 688 689 protected OWLDataFactory getDataFactory() { 690 return getRootOntology().getOWLOntologyManager().getOWLDataFactory(); 691 } 692 /** 693 * @param showBottomNode true if bottom node is to be showed 694 */ 695 public void dumpClassHierarchy(boolean showBottomNode) { 696 dumpClassHierarchy(OWLClassNode.getTopNode(), 0, showBottomNode); 697 } 698 699 private void dumpClassHierarchy(Node<OWLClass> cls, int level, boolean showBottomNode) { 700 if (!showBottomNode && cls.isBottomNode()) { 701 return; 702 } 703 printIndent(level); 704 OWLClass representative = cls.getRepresentativeElement(); 705 System.out.println(getEquivalentClasses(representative)); 706 for (Node<OWLClass> subCls : getSubClasses(representative, true)) { 707 dumpClassHierarchy(subCls, level + 1, showBottomNode); 708 } 709 } 710 711 /** 712 * @param showBottomNode true if bottom node is to be showed 713 */ 714 public void dumpObjectPropertyHierarchy(boolean showBottomNode) { 715 dumpObjectPropertyHierarchy(OWLObjectPropertyNode.getTopNode(), 0, showBottomNode); 716 } 717 718 private void dumpObjectPropertyHierarchy(Node<OWLObjectPropertyExpression> cls, int level, boolean showBottomNode) { 719 if (!showBottomNode && cls.isBottomNode()) { 720 return; 721 } 722 printIndent(level); 723 OWLObjectPropertyExpression representative = cls.getRepresentativeElement(); 724 System.out.println(getEquivalentObjectProperties(representative)); 725 for (Node<OWLObjectPropertyExpression> subProp : getSubObjectProperties(representative, true)) { 726 dumpObjectPropertyHierarchy(subProp, level + 1, showBottomNode); 727 } 728 } 729 730 /** 731 * @param showBottomNode true if bottom node is to be showed 732 */ 733 public void dumpDataPropertyHierarchy(boolean showBottomNode) { 734 dumpDataPropertyHierarchy(OWLDataPropertyNode.getTopNode(), 0, showBottomNode); 735 } 736 737 private void dumpDataPropertyHierarchy(Node<OWLDataProperty> cls, int level, boolean showBottomNode) { 738 if (!showBottomNode && cls.isBottomNode()) { 739 return; 740 } 741 printIndent(level); 742 OWLDataProperty representative = cls.getRepresentativeElement(); 743 System.out.println(getEquivalentDataProperties(representative)); 744 for (Node<OWLDataProperty> subProp : getSubDataProperties(representative, true)) { 745 dumpDataPropertyHierarchy(subProp, level + 1, showBottomNode); 746 } 747 } 748 749 private void printIndent(int level) { 750 for (int i = 0; i < level; i++) { 751 System.out.print(" "); 752 } 753 } 754 755 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 756 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 757 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 758 ////// 759 ////// HierarchyInfo 760 ////// 761 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 762 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 763 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 764 765 private abstract class HierarchyInfo<T extends OWLObject> { 766 767 private RawHierarchyProvider<T> rawParentChildProvider; 768 769 /** 770 * The entity that always appears in the top node in the hierarchy 771 */ 772 T topEntity; 773 774 /** 775 * The entity that always appears as the bottom node in the hierarchy 776 */ 777 T bottomEntity; 778 779 private Set<T> directChildrenOfTopNode = new HashSet<>(); 780 781 private Set<T> directParentsOfBottomNode = new HashSet<>(); 782 783 private NodeCache<T> nodeCache; 784 785 private String name; 786 787 private int classificationSize; 788 789 public HierarchyInfo(String name, T topEntity, T bottomEntity, RawHierarchyProvider<T> rawParentChildProvider) { 790 this.topEntity = topEntity; 791 this.bottomEntity = bottomEntity; 792 this.nodeCache = new NodeCache<>(this); 793 this.rawParentChildProvider = rawParentChildProvider; 794 this.name = name; 795 } 796 797 public RawHierarchyProvider<T> getRawParentChildProvider() { 798 return rawParentChildProvider; 799 } 800 801 /** 802 * Gets the set of relevant entities from the specified ontology 803 * @param ont The ontology 804 * @return A set of entities to be "classified" 805 */ 806 protected abstract Set<T> getEntities(OWLOntology ont); 807 808 /** 809 * Creates a node for a given set of entities 810 * @param cycle The set of entities 811 * @return A node 812 */ 813 protected abstract DefaultNode<T> createNode(Set<T> cycle); 814 815 protected abstract DefaultNode<T> createNode(); 816 817 /** 818 * Gets the set of relevant entities in a particular axiom 819 * @param ax The axiom 820 * @return The set of relevant entities in the signature of the specified axiom 821 */ 822 protected abstract Set<? extends T> getEntitiesInSignature(OWLAxiom ax); 823 824 Set<T> getEntitiesInSignature(Set<OWLAxiom> axioms) { 825 Set<T> result = new HashSet<>(); 826 for (OWLAxiom ax : axioms) { 827 result.addAll(getEntitiesInSignature(ax)); 828 } 829 return result; 830 } 831 832 public void computeHierarchy() { 833 pm.reasonerTaskStarted("Computing " + name + " hierarchy"); 834 pm.reasonerTaskBusy(); 835 nodeCache.clear(); 836 Map<T, Collection<T>> cache = new HashMap<>(); 837 Set<T> entities = new HashSet<>(); 838 for (OWLOntology ont : getRootOntology().getImportsClosure()) { 839 entities.addAll(getEntities(ont)); 840 } 841 classificationSize = entities.size(); 842 pm.reasonerTaskProgressChanged(0, classificationSize); 843 updateForSignature(entities, cache); 844 pm.reasonerTaskStopped(); 845 } 846 847 private void updateForSignature(Set<T> signature, Map<T, Collection<T>> cache) { 848 HashSet<Set<T>> cyclesResult = new HashSet<>(); 849 Set<T> processed = new HashSet<>(); 850 nodeCache.clearTopNode(); 851 nodeCache.clearBottomNode(); 852 nodeCache.clearNodes(signature); 853 854 directChildrenOfTopNode.removeAll(signature); 855 856 Set<T> equivTopOrChildrenOfTop = new HashSet<>(); 857 Set<T> equivBottomOrParentsOfBottom = new HashSet<>(); 858 for (T entity : signature) { 859 if (!processed.contains(entity)) { 860 pm.reasonerTaskProgressChanged(processed.size(), signature.size()); 861 tarjan(entity, 0, new Stack<>(), new HashMap<>(), new HashMap<>(), cyclesResult, processed, new HashSet<>(), cache, equivTopOrChildrenOfTop, equivBottomOrParentsOfBottom); 862 throwExceptionIfInterrupted(); 863 } 864 } 865 // Store new cycles 866 for (Set<T> cycle : cyclesResult) { 867 nodeCache.addNode(cycle); 868 } 869 870 directChildrenOfTopNode.addAll(equivTopOrChildrenOfTop); 871 directChildrenOfTopNode.removeAll(nodeCache.getTopNode().getEntities()); 872 873 directParentsOfBottomNode.addAll(equivBottomOrParentsOfBottom); 874 directParentsOfBottomNode.removeAll(nodeCache.getBottomNode().getEntities()); 875 876 // Now check that each found cycle has a proper parent an child 877 for (Set<T> node : cyclesResult) { 878 if (!node.contains(topEntity) && !node.contains(bottomEntity)) { 879 boolean childOfTop = true; 880 for (T element : node) { 881 Collection<T> parents = rawParentChildProvider.getParents(element); 882 parents.removeAll(node); 883 parents.removeAll(nodeCache.getTopNode().getEntities()); 884 if (!parents.isEmpty()) { 885 childOfTop = false; 886 break; 887 } 888 } 889 if (childOfTop) { 890 directChildrenOfTopNode.addAll(node); 891 } 892 893 boolean parentOfBottom = true; 894 for (T element : node) { 895 Collection<T> children = rawParentChildProvider.getChildren(element); 896 children.removeAll(node); 897 children.removeAll(nodeCache.getBottomNode().getEntities()); 898 if (!children.isEmpty()) { 899 parentOfBottom = false; 900 break; 901 } 902 } 903 if (parentOfBottom) { 904 directParentsOfBottomNode.addAll(node); 905 } 906 } 907 908 } 909 910 } 911 912 /** 913 * Processes the specified signature that represents the signature of potential changes 914 * @param signature The signature 915 * @param added added axioms 916 * @param removed removed axioms 917 */ 918 @SuppressWarnings("unused") 919 public void processChanges(Set<T> signature, Set<OWLAxiom> added, Set<OWLAxiom> removed) { 920 updateForSignature(signature, null); 921 } 922 923 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 924 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 925 926 /** 927 * Applies the tarjan algorithm for a given entity. This computes the cycle that the entity is involved in (if 928 * any). 929 * @param entity The entity 930 * @param index index 931 * @param stack stack 932 * @param indexMap index map 933 * @param lowlinkMap low link map 934 * @param result result 935 * @param processed processed 936 * @param stackEntities stack entities 937 * @param cache A cache of children to parents - may be <code>null</code> if no caching is to take place. 938 * @param childrenOfTop A set of entities that have a raw parent that is the top entity 939 * @param parentsOfBottom A set of entities that have a raw parent that is the bottom entity 940 */ 941 public void tarjan(T entity, int index, Stack<T> stack, Map<T, Integer> indexMap, Map<T, Integer> lowlinkMap, Set<Set<T>> result, Set<T> processed, Set<T> stackEntities, Map<T, Collection<T>> cache, Set<T> childrenOfTop, Set<T> parentsOfBottom) { 942 throwExceptionIfInterrupted(); 943 if (processed.add(entity)) { 944 Collection<T> rawChildren = rawParentChildProvider.getChildren(entity); 945 if (rawChildren.isEmpty() || rawChildren.contains(bottomEntity)) { 946 parentsOfBottom.add(entity); 947 } 948 } 949 pm.reasonerTaskProgressChanged(processed.size(), classificationSize); 950 indexMap.put(entity, index); 951 lowlinkMap.put(entity, index); 952 index = index + 1; 953 stack.push(entity); 954 stackEntities.add(entity); 955 956 // Get the raw parents - cache if necessary 957 Collection<T> rawParents = null; 958 if (cache != null) { 959 // We are therefore caching raw parents of children. 960 rawParents = cache.get(entity); 961 if (rawParents == null) { 962 // Not in cache! 963 rawParents = rawParentChildProvider.getParents(entity); 964 // Note down if our entity is a 965 if (rawParents.isEmpty() || rawParents.contains(topEntity)) { 966 childrenOfTop.add(entity); 967 } 968 cache.put(entity, rawParents); 969 970 } 971 } 972 else { 973 rawParents = rawParentChildProvider.getParents(entity); 974 // Note down if our entity is a 975 if (rawParents.isEmpty() || rawParents.contains(topEntity)) { 976 childrenOfTop.add(entity); 977 } 978 } 979 980 for (T superEntity : rawParents) { 981 if (!indexMap.containsKey(superEntity)) { 982 tarjan(superEntity, index, stack, indexMap, lowlinkMap, result, processed, stackEntities, cache, childrenOfTop, parentsOfBottom); 983 lowlinkMap.put(entity, Math.min(lowlinkMap.get(entity), lowlinkMap.get(superEntity))); 984 } 985 else if (stackEntities.contains(superEntity)) { 986 lowlinkMap.put(entity, Math.min(lowlinkMap.get(entity), indexMap.get(superEntity))); 987 } 988 } 989 if (lowlinkMap.get(entity).equals(indexMap.get(entity))) { 990 Set<T> scc = new HashSet<>(); 991 while (true) { 992 T clsPrime = stack.pop(); 993 stackEntities.remove(clsPrime); 994 scc.add(clsPrime); 995 if (clsPrime.equals(entity)) { 996 break; 997 } 998 } 999 if (scc.size() > 1) { 1000 // We ADD a cycle 1001 result.add(scc); 1002 } 1003 } 1004 } 1005 1006 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1007 ////////////////////////////////////////////////////////////////////////////////////////////////////////// 1008 1009 public NodeSet<T> getNodeHierarchyChildren(T parent, boolean direct, DefaultNodeSet<T> ns) { 1010 Node<T> node = nodeCache.getNode(parent); 1011 1012 if (node.isBottomNode()) { 1013 return ns; 1014 } 1015 1016 Set<T> directChildren = new HashSet<>(); 1017 for (T equiv : node) { 1018 directChildren.addAll(rawParentChildProvider.getChildren(equiv)); 1019 if(directParentsOfBottomNode.contains(equiv)) { 1020 ns.addNode(nodeCache.getBottomNode()); 1021 } 1022 } 1023 directChildren.removeAll(node.getEntities()); 1024 1025 if (node.isTopNode()) { 1026 // Special treatment 1027 directChildren.addAll(directChildrenOfTopNode); 1028 } 1029 1030 for (Node<T> childNode : nodeCache.getNodes(directChildren)) { 1031 ns.addNode(childNode); 1032 } 1033 1034 if (!direct) { 1035 for (T child : directChildren) { 1036 getNodeHierarchyChildren(child, direct, ns); 1037 } 1038 } 1039 return ns; 1040 } 1041 1042 public NodeSet<T> getNodeHierarchyParents(T child, boolean direct, DefaultNodeSet<T> ns) { 1043 Node<T> node = nodeCache.getNode(child); 1044 1045 if (node.isTopNode()) { 1046 return ns; 1047 } 1048 1049 Set<T> directParents = new HashSet<>(); 1050 for (T equiv : node) { 1051 directParents.addAll(rawParentChildProvider.getParents(equiv)); 1052 if(directChildrenOfTopNode.contains(equiv)) { 1053 ns.addNode(nodeCache.getTopNode()); 1054 } 1055 } 1056 directParents.removeAll(node.getEntities()); 1057 1058 if (node.isBottomNode()) { 1059 // Special treatment 1060 directParents.addAll(directParentsOfBottomNode); 1061 } 1062 1063 for (Node<T> parentNode : nodeCache.getNodes(directParents)) { 1064 ns.addNode(parentNode); 1065 } 1066 1067 if (!direct) { 1068 for(T parent : directParents) { 1069 getNodeHierarchyParents(parent, direct, ns); 1070 } 1071 } 1072 return ns; 1073 } 1074 1075 public Node<T> getEquivalents(T element) { 1076 return nodeCache.getNode(element); 1077 } 1078 } 1079 1080 private static class NodeCache<T extends OWLObject> { 1081 1082 private HierarchyInfo<T> hierarchyInfo; 1083 1084 private Node<T> topNode; 1085 1086 private Node<T> bottomNode; 1087 1088 private Map<T, Node<T>> map = new HashMap<>(); 1089 1090 protected NodeCache(HierarchyInfo<T> hierarchyInfo) { 1091 this.hierarchyInfo = hierarchyInfo; 1092 clearTopNode(); 1093 clearBottomNode(); 1094 } 1095 1096 public void addNode(Node<T> node) { 1097 for (T element : node.getEntities()) { 1098 map.put(element, node); 1099 if (element.isTopEntity()) { 1100 topNode = node; 1101 } 1102 else if (element.isBottomEntity()) { 1103 bottomNode = node; 1104 } 1105 } 1106 } 1107 1108 public Set<Node<T>> getNodes(Set<T> elements) { 1109 Set<Node<T>> result = new HashSet<>(); 1110 for (T element : elements) { 1111 result.add(getNode(element)); 1112 } 1113 return result; 1114 } 1115 1116 public Node<T> getNode(T containing) { 1117 Node<T> parentNode = map.get(containing); 1118 if (parentNode != null) { 1119 return parentNode; 1120 } 1121 else { 1122 return hierarchyInfo.createNode(Collections.singleton(containing)); 1123 } 1124 } 1125 1126 public void addNode(Set<T> elements) { 1127 addNode(hierarchyInfo.createNode(elements)); 1128 } 1129 1130 public Node<T> getTopNode() { 1131 return topNode; 1132 } 1133 1134 public Node<T> getBottomNode() { 1135 return bottomNode; 1136 } 1137 1138 public void clearTopNode() { 1139 removeNode(hierarchyInfo.topEntity); 1140 topNode = hierarchyInfo.createNode(Collections.singleton(hierarchyInfo.topEntity)); 1141 addNode(topNode); 1142 } 1143 1144 public void clearBottomNode() { 1145 removeNode(hierarchyInfo.bottomEntity); 1146 bottomNode = hierarchyInfo.createNode(Collections.singleton(hierarchyInfo.bottomEntity)); 1147 addNode(bottomNode); 1148 } 1149 1150 public void clearNodes(Set<T> containing) { 1151 for (T entity : containing) { 1152 removeNode(entity); 1153 } 1154 } 1155 1156 public void clear() { 1157 map.clear(); 1158 clearTopNode(); 1159 clearBottomNode(); 1160 } 1161 1162 public void removeNode(T containing) { 1163 Node<T> node = map.remove(containing); 1164 if (node != null) { 1165 for (T object : node.getEntities()) { 1166 map.remove(object); 1167 } 1168 } 1169 } 1170 } 1171 1172 private class ClassHierarchyInfo extends HierarchyInfo<OWLClass> { 1173 1174 public ClassHierarchyInfo() { 1175 super("class", getDataFactory().getOWLThing(), getDataFactory().getOWLNothing(), new RawClassHierarchyProvider()); 1176 } 1177 1178 @Override 1179 protected Set<OWLClass> getEntitiesInSignature(OWLAxiom ax) { 1180 return ax.getClassesInSignature(); 1181 } 1182 1183 @Override 1184 protected DefaultNode<OWLClass> createNode(Set<OWLClass> cycle) { 1185 return new OWLClassNode(cycle); 1186 } 1187 1188 @Override 1189 protected Set<OWLClass> getEntities(OWLOntology ont) { 1190 return ont.getClassesInSignature(); 1191 } 1192 1193 @Override 1194 protected DefaultNode<OWLClass> createNode() { 1195 return new OWLClassNode(); 1196 } 1197 } 1198 1199 private class ObjectPropertyHierarchyInfo extends HierarchyInfo<OWLObjectPropertyExpression> { 1200 1201 public ObjectPropertyHierarchyInfo() { 1202 super("object property", getDataFactory().getOWLTopObjectProperty(), getDataFactory().getOWLBottomObjectProperty(), new RawObjectPropertyHierarchyProvider()); 1203 } 1204 1205 @Override 1206 protected Set<OWLObjectPropertyExpression> getEntitiesInSignature(OWLAxiom ax) { 1207 Set<OWLObjectPropertyExpression> result = new HashSet<>(); 1208 for (OWLObjectProperty property : ax.getObjectPropertiesInSignature()) { 1209 result.add(property); 1210 result.add(property.getInverseProperty()); 1211 } 1212 return result; 1213 } 1214 1215 @Override 1216 protected Set<OWLObjectPropertyExpression> getEntities(OWLOntology ont) { 1217 Set<OWLObjectPropertyExpression> result = new HashSet<>(); 1218 for (OWLObjectPropertyExpression property : ont.getObjectPropertiesInSignature()) { 1219 result.add(property); 1220 result.add(property.getInverseProperty()); 1221 } 1222 return result; 1223 } 1224 1225 @Override 1226 protected DefaultNode<OWLObjectPropertyExpression> createNode(Set<OWLObjectPropertyExpression> cycle) { 1227 return new OWLObjectPropertyNode(cycle); 1228 } 1229 1230 @Override 1231 protected DefaultNode<OWLObjectPropertyExpression> createNode() { 1232 return new OWLObjectPropertyNode(); 1233 } 1234 1235 @Override 1236 public void processChanges(Set<OWLObjectPropertyExpression> signature, Set<OWLAxiom> added, Set<OWLAxiom> removed) { 1237 boolean rebuild = false; 1238 for (OWLAxiom ax : added) { 1239 if(ax instanceof OWLObjectPropertyAxiom) { 1240 rebuild = true; 1241 break; 1242 } 1243 } 1244 if(!rebuild) { 1245 for(OWLAxiom ax : removed) { 1246 if(ax instanceof OWLObjectPropertyAxiom) { 1247 rebuild = true; 1248 break; 1249 } 1250 } 1251 } 1252 if(rebuild) { 1253 ((RawObjectPropertyHierarchyProvider) getRawParentChildProvider()).rebuild(); 1254 } 1255 super.processChanges(signature, added, removed); 1256 } 1257 } 1258 1259 private class DataPropertyHierarchyInfo extends HierarchyInfo<OWLDataProperty> { 1260 1261 public DataPropertyHierarchyInfo() { 1262 super("data property", getDataFactory().getOWLTopDataProperty(), getDataFactory().getOWLBottomDataProperty(), new RawDataPropertyHierarchyProvider()); 1263 } 1264 1265 @Override 1266 protected Set<OWLDataProperty> getEntitiesInSignature(OWLAxiom ax) { 1267 return ax.getDataPropertiesInSignature(); 1268 } 1269 1270 @Override 1271 protected Set<OWLDataProperty> getEntities(OWLOntology ont) { 1272 return ont.getDataPropertiesInSignature(); 1273 } 1274 1275 @Override 1276 protected DefaultNode<OWLDataProperty> createNode(Set<OWLDataProperty> cycle) { 1277 return new OWLDataPropertyNode(cycle); 1278 } 1279 1280 @Override 1281 protected DefaultNode<OWLDataProperty> createNode() { 1282 return new OWLDataPropertyNode(); 1283 } 1284 } 1285 1286 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 1287 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 1288 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 1289 1290 /** 1291 * An interface for objects who can provide the parents and children of some object. 1292 * @param <T> 1293 */ 1294 private interface RawHierarchyProvider<T> { 1295 1296 /** 1297 * Gets the parents as asserted. These parents may also be children (resulting in equivalences). 1298 * @param child The child whose parents are to be retrieved 1299 * @return The raw asserted parents of the specified child. If the child does not have any parents 1300 * then the empty set can be returned. 1301 */ 1302 Collection<T> getParents(T child); 1303 1304 /** 1305 * Gets the children as asserted 1306 * @param parent The parent whose children are to be retrieved 1307 * @return The raw asserted children of the speicified parent 1308 */ 1309 Collection<T> getChildren(T parent); 1310 1311 } 1312 1313 private class RawClassHierarchyProvider implements RawHierarchyProvider<OWLClass> { 1314 public RawClassHierarchyProvider() {} 1315 1316 @Override 1317 public Collection<OWLClass> getParents(OWLClass child) { 1318 Collection<OWLClass> result = new HashSet<>(); 1319 for (OWLOntology ont : getRootOntology().getImportsClosure()) { 1320 Stream.concat( 1321 ont.getSubClassAxiomsForSubClass(child).stream().map(OWLSubClassOfAxiom::getSuperClass), 1322 ont.getEquivalentClassesAxioms(child).stream().flatMap(ax -> ax.getClassExpressionsMinus(child).stream()) 1323 ).forEach(ce -> { 1324 if (!ce.isAnonymous()) { 1325 result.add(ce.asOWLClass()); 1326 } else if (ce instanceof OWLObjectIntersectionOf) { 1327 OWLObjectIntersectionOf intersectionOf = (OWLObjectIntersectionOf) ce; 1328 for (OWLClassExpression conjunct : intersectionOf.asConjunctSet()) { 1329 if (!conjunct.isAnonymous()) { 1330 result.add(conjunct.asOWLClass()); 1331 } 1332 } 1333 } 1334 }); 1335 } 1336 return result; 1337 } 1338 1339 @Override 1340 public Collection<OWLClass> getChildren(OWLClass parent) { 1341 Collection<OWLClass> result = new HashSet<>(); 1342 for (OWLOntology ont : getRootOntology().getImportsClosure()) { 1343 for (OWLAxiom ax : ont.getReferencingAxioms(parent)) { 1344 if (ax instanceof OWLSubClassOfAxiom) { 1345 OWLSubClassOfAxiom sca = (OWLSubClassOfAxiom) ax; 1346 if (!sca.getSubClass().isAnonymous()) { 1347 Set<OWLClassExpression> conjuncts = sca.getSuperClass().asConjunctSet(); 1348 if (conjuncts.contains(parent)) { 1349 result.add(sca.getSubClass().asOWLClass()); 1350 } 1351 } 1352 } 1353 else if (ax instanceof OWLEquivalentClassesAxiom) { 1354 OWLEquivalentClassesAxiom eca = (OWLEquivalentClassesAxiom) ax; 1355 for (OWLClassExpression ce : eca.getClassExpressions()) { 1356 if (ce.containsConjunct(parent)) { 1357 for (OWLClassExpression sub : eca.getClassExpressions()) { 1358 if (!sub.isAnonymous() && !sub.equals(ce)) { 1359 result.add(sub.asOWLClass()); 1360 } 1361 } 1362 } 1363 } 1364 } 1365 } 1366 } 1367 return result; 1368 } 1369 } 1370 1371 private class RawObjectPropertyHierarchyProvider implements RawHierarchyProvider<OWLObjectPropertyExpression> { 1372 1373 private OWLObjectPropertyManager propertyManager; 1374 1375 private Map<OWLObjectPropertyExpression, Set<OWLObjectPropertyExpression>> sub2Super; 1376 1377 private Map<OWLObjectPropertyExpression, Set<OWLObjectPropertyExpression>> super2Sub; 1378 1379 public RawObjectPropertyHierarchyProvider() { 1380 rebuild(); 1381 } 1382 1383 public void rebuild() { 1384 propertyManager = new OWLObjectPropertyManager(getRootOntology().getOWLOntologyManager(), getRootOntology()); 1385 sub2Super = propertyManager.getPropertyHierarchy(); 1386 super2Sub = new HashMap<>(); 1387 for(Map.Entry<OWLObjectPropertyExpression, Set<OWLObjectPropertyExpression>> entry : sub2Super.entrySet()) { 1388 for(OWLObjectPropertyExpression superProp : entry.getValue()) { 1389 super2Sub 1390 .computeIfAbsent(superProp, k -> new HashSet<>()) 1391 .add(entry.getKey()); 1392 } 1393 } 1394 } 1395 1396 @Override 1397 public Collection<OWLObjectPropertyExpression> getParents(OWLObjectPropertyExpression child) { 1398 if(child.isBottomEntity()) { 1399 return Collections.emptySet(); 1400 } 1401 Set<OWLObjectPropertyExpression> propertyExpressions = sub2Super.get(child); 1402 if(propertyExpressions == null) { 1403 return Collections.emptySet(); 1404 } 1405 else { 1406 return new HashSet<>(propertyExpressions); 1407 } 1408 1409 } 1410 1411 @Override 1412 public Collection<OWLObjectPropertyExpression> getChildren(OWLObjectPropertyExpression parent) { 1413 if(parent.isTopEntity()) { 1414 return Collections.emptySet(); 1415 } 1416 Set<OWLObjectPropertyExpression> propertyExpressions = super2Sub.get(parent); 1417 if(propertyExpressions == null) { 1418 return Collections.emptySet(); 1419 } 1420 else { 1421 return new HashSet<>(propertyExpressions); 1422 } 1423 1424 } 1425 } 1426 1427 private class RawDataPropertyHierarchyProvider implements RawHierarchyProvider<OWLDataProperty> { 1428 public RawDataPropertyHierarchyProvider() {} 1429 @Override 1430 public Collection<OWLDataProperty> getParents(OWLDataProperty child) { 1431 Set<OWLDataProperty> properties = new HashSet<>(); 1432 for (OWLDataPropertyExpression prop : EntitySearcher.getSuperProperties(child, getRootOntology().getImportsClosure())) { 1433 properties.add(prop.asOWLDataProperty()); 1434 } 1435 return properties; 1436 } 1437 1438 @Override 1439 public Collection<OWLDataProperty> getChildren(OWLDataProperty parent) { 1440 Set<OWLDataProperty> properties = new HashSet<>(); 1441 for (OWLDataPropertyExpression prop : EntitySearcher.getSubProperties(parent, getRootOntology().getImportsClosure())) { 1442 properties.add(prop.asOWLDataProperty()); 1443 } 1444 return properties; 1445 } 1446 } 1447 1448 public static void main(String[] args) throws Exception { 1449 OWLOntologyManager man = OWLManager.createOWLOntologyManager(); 1450 OWLOntology schema = //man.loadOntology(IRI.create("http://downloads.dbpedia.org/2016-10/dbpedia_2016-10.nt")); 1451 man.loadOntology(IRI.create("file://" + System.getProperty("java.io.tmpdir") + "/merged.ttl")); 1452 1453 OWLOntologyKnowledgeSource sampleKS = new OWLAPIOntology(schema); 1454 sampleKS.init(); 1455 1456 1457 final long start = System.currentTimeMillis(); 1458 1459 OWLAPIReasoner baseReasoner = new OWLAPIReasoner(sampleKS); 1460 baseReasoner.setReasonerImplementation(ReasonerImplementation.STRUCTURAL); 1461 baseReasoner.init(); 1462 1463 ClosedWorldReasoner reasoner = new ClosedWorldReasoner(baseReasoner); 1464 reasoner.init(); 1465 1466 System.out.println(PeriodFormat.getDefault().print(new Period(System.currentTimeMillis() - start))); 1467 } 1468 1469}