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}