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.utilities.learn; 020 021import java.util.Comparator; 022import java.util.Iterator; 023import java.util.Map; 024import java.util.Map.Entry; 025import java.util.Set; 026import java.util.TreeMap; 027import java.util.TreeSet; 028 029import org.dllearner.core.AbstractReasonerComponent; 030import org.semanticweb.owlapi.model.OWLClass; 031import org.semanticweb.owlapi.model.OWLIndividual; 032import org.semanticweb.owlapi.model.OWLObjectProperty; 033 034/** 035 * This class takes a reasoner and individuals as input and detects 036 * the relevant (wrt. a learning process) classes and properties 037 * at a certain distance of the examples. 038 * 039 * @author Jens Lehmann 040 * 041 */ 042public class UsedEntitiesDetection { 043 044 Comparator<Set<OWLObjectProperty>> keyComp = new Comparator<Set<OWLObjectProperty>>() { 045 046 @Override 047 public int compare(Set<OWLObjectProperty> key1, Set<OWLObjectProperty> key2) { 048 // first criterion: size of key 049 int sizeDiff = key1.size() - key2.size(); 050 if(sizeDiff == 0) { 051 Iterator<OWLObjectProperty> it1 = key1.iterator(); 052 Iterator<OWLObjectProperty> it2 = key2.iterator(); 053 // compare elements one by one (assumes that both use the same 054 // ordering, which is the case) 055 while(it1.hasNext()) { 056 OWLObjectProperty prop1 = it1.next(); 057 OWLObjectProperty prop2 = it2.next(); 058 int comp = prop1.compareTo(prop2); 059 if(comp != 0) { 060 return comp; 061 } 062 } 063 // all elements of the set are equal 064 return 0; 065 } else { 066 return sizeDiff; 067 } 068 } 069 070 }; 071 072 private Map<Set<OWLObjectProperty>,Set<OWLClass>> usedClasses; 073 074 private Map<Set<OWLObjectProperty>,Set<OWLObjectProperty>> usedObjectProperties; 075 076 private AbstractReasonerComponent reasoner; 077 private int maxDepth; 078 079 /** 080 * Computes used properties in classes. 081 * TODO more explanation 082 * 083 * @param reasoner A reasoner. 084 * @param individuals A set of individuals to start from. 085 * @param maxDepth The maximum depth for the search. 086 */ 087 public UsedEntitiesDetection(AbstractReasonerComponent reasoner, Set<OWLIndividual> individuals, int maxDepth) { 088 this.reasoner = reasoner; 089 this.maxDepth = maxDepth; 090 usedClasses = new TreeMap<>(keyComp); 091 usedObjectProperties = new TreeMap<>(keyComp); 092 093 Set<OWLObjectProperty> startKey = new TreeSet<>(); 094 computeUsedEntitiesRec(startKey, individuals); 095 096 } 097 098 private void computeUsedEntitiesRec(Set<OWLObjectProperty> key, Set<OWLIndividual> individuals) { 099 Set<OWLClass> types = new TreeSet<>(); 100// Set<ObjectProperty> properties = new TreeSet<ObjectProperty>(); 101 // we must use the object property comparator to avoid double occurences of properties 102 Map<OWLObjectProperty,Set<OWLIndividual>> relations = new TreeMap<>(); 103 104 for(OWLIndividual individual : individuals) { 105 // add all types 106 types.addAll(reasoner.getTypes(individual)); 107 108 // compute outgoing properties 109 Map<OWLObjectProperty,Set<OWLIndividual>> map = reasoner.getObjectPropertyRelationships(individual); 110 for(Entry<OWLObjectProperty,Set<OWLIndividual>> entry : map.entrySet()) { 111 OWLObjectProperty prop = entry.getKey(); 112 // we must use the individual comparator to avoid 113 // multiple occurrences of the same individual 114 Set<OWLIndividual> inds = new TreeSet<>(entry.getValue()); 115 116 // if property exists, add the found individuals 117 if(relations.containsKey(prop)) { 118 relations.get(prop).addAll(inds); 119 // if property not encountered before, add it 120 } else { 121 relations.put(prop, inds); 122 } 123 } 124 } 125 126 // store all found relations 127 usedClasses.put(key, types); 128 usedObjectProperties.put(key, relations.keySet()); 129 130 // recurse if limit not reached yet 131 if(key.size() < maxDepth) { 132 for(Entry<OWLObjectProperty,Set<OWLIndividual>> entry : relations.entrySet()) { 133 // construct new key (copy and add) 134 Set<OWLObjectProperty> newKey = new TreeSet<>(key); 135 newKey.add(entry.getKey()); 136 137 // recursion 138 computeUsedEntitiesRec(newKey, entry.getValue()); 139 } 140 } 141 142 } 143 144 public Set<Set<OWLObjectProperty>> getKeys() { 145 return usedClasses.keySet(); 146 } 147 148 /** 149 * @return the usedClasses 150 */ 151 public Map<Set<OWLObjectProperty>, Set<OWLClass>> getUsedClasses() { 152 return usedClasses; 153 } 154 155 /** 156 * @return the usedObjectProperties 157 */ 158 public Map<Set<OWLObjectProperty>, Set<OWLObjectProperty>> getUsedObjectProperties() { 159 return usedObjectProperties; 160 } 161 162 @Override 163 public String toString() { 164 String str = ""; 165 Set<Set<OWLObjectProperty>> keys = getKeys(); 166 for(Set<OWLObjectProperty> key : keys) { 167 str += key.toString() + ": \n"; 168 str += " classes: " + usedClasses.get(key) + "\n"; 169 str += " object properties: " + usedObjectProperties.get(key) + "\n"; 170 } 171 return str; 172 } 173 174}