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