001package org.dllearner.utilities; 002 003import com.google.common.collect.Sets; 004import org.apache.jena.graph.Node; 005import org.dllearner.core.AbstractReasonerComponent; 006import org.semanticweb.owlapi.model.*; 007 008import java.util.SortedSet; 009import java.util.TreeSet; 010import java.util.function.Function; 011import java.util.stream.Collectors; 012 013/** 014 * A collection of services that are known as non-standard reasoning. 015 * 016 * @author Lorenz Buehmann 017 */ 018public class NonStandardReasoningServices { 019 020 /** 021 * Computes the least common subsumer (LCS) of the given entities <code>e1</code> and <code>e2</code> if exists, 022 * otherwise <code>null</code> 023 * 024 * @param reasoner the reasoner used to compute the direct parents 025 * @param n1 first entity 026 * @param n2 second entity 027 * @param entityType the entity type 028 * @param <E> the entity type 029 * @return the LCS if exists 030 */ 031 public static <E extends OWLEntity> Node getLeastCommonSubsumer(AbstractReasonerComponent reasoner, Node n1, Node n2, 032 EntityType<E> entityType) { 033 // trivial case 034 if(n1.equals(n2)) { 035 return n1; 036 } 037 038 E lcs = getLeastCommonSubsumer(reasoner, 039 OwlApiJenaUtils.asOWLEntity(n1, entityType), 040 OwlApiJenaUtils.asOWLEntity(n2, entityType)); 041 042 if(lcs != null) { 043 return OwlApiJenaUtils.asNode(lcs); 044 } 045 046 return null; 047 } 048 049 /** 050 * Computes the least common subsumer (LCS) of the given entities <code>e1</code> and <code>e2</code> if exists, 051 * otherwise <code>null</code> 052 * 053 * @param reasoner the reasoner used to compute the direct parents 054 * @param e1 first entity 055 * @param e2 second entity 056 * @param <E> the entity type 057 * @return the LCS if exists 058 */ 059 @SuppressWarnings("unchecked") 060 public static <E extends OWLEntity> E getLeastCommonSubsumer(AbstractReasonerComponent reasoner, E e1, E e2) { 061 // check if both entities are of the same type 062 if(e1.getEntityType() != e2.getEntityType()) { 063 throw new IllegalArgumentException("LCS operation only defined for entities of the same type!"); 064 } 065 066 // trivial case 067 if(e1.equals(e2)) { 068 return e1; 069 } 070 071 // depending on the entity type define the method to get the direct parents 072 EntityType<?> entityType = e1.getEntityType(); 073 Function<E, SortedSet<E>> f; 074 if(entityType == EntityType.CLASS) { 075 f = e -> (SortedSet<E>) reasoner.getSuperClasses((OWLClass) e).stream() 076 .filter(ce -> !ce.isAnonymous()) 077 .map(OWLClassExpression::asOWLClass) 078 .collect(Collectors.toCollection(TreeSet::new)); 079 } else if(entityType == EntityType.OBJECT_PROPERTY) { 080 f = e -> (SortedSet<E>) reasoner.getSuperProperties((OWLObjectProperty) e); 081 } else if(entityType == EntityType.DATA_PROPERTY) { 082 f = e -> (SortedSet<E>) reasoner.getSuperProperties((OWLDataProperty) e); 083 } else { 084 throw new RuntimeException("LCS for " + entityType.getPluralPrintName() + " not implemented!"); 085 } 086 087 // compute the LCS 088 return getLeastCommonSubsumer(e1, e2, f); 089 } 090 091 private static <E extends OWLEntity> E getLeastCommonSubsumer(E e1, E e2, Function<E, SortedSet<E>> f) { 092 // e1 = e2 -> e1 093 if(e1.equals(e2)) { 094 return e1; 095 } 096 097 // e2 contained in direct parents(e1) -> e2 098 SortedSet<E> superEntities1 = f.apply(e1); 099 if(superEntities1.contains(e2)) { 100 return e2; 101 } 102 103 // e1 contained in direct parents(e2) -> e1 104 SortedSet<E> superEntities2 = f.apply(e2); 105 if(superEntities2.contains(e1)) { 106 return e1; 107 } 108 109 // parents(e1) â© parents(e2) != empty -> an element of the intersection 110 Sets.SetView<E> intersection = Sets.intersection(superEntities1, superEntities2); 111 if(!intersection.isEmpty()) { 112 return intersection.iterator().next(); 113 } 114 115 // recursive call using the parents 116 for (E sup1 : superEntities1) { 117 for (E sup2 : superEntities2) { 118 E lcs = getLeastCommonSubsumer(sup1, sup2, f); 119 120 if(lcs != null) { 121 return lcs; 122 } 123 } 124 } 125 126 // no LCS found 127 return null; 128 } 129}