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.examples;
021
022 import java.util.Collection;
023 import java.util.SortedSet;
024 import java.util.TreeSet;
025
026 import org.apache.log4j.Logger;
027 import org.dllearner.core.ComponentManager;
028 import org.dllearner.core.AbstractReasonerComponent;
029 import org.dllearner.core.owl.Description;
030 import org.dllearner.core.owl.Individual;
031 import org.dllearner.core.owl.NamedClass;
032 import org.dllearner.core.owl.ObjectProperty;
033 import org.dllearner.utilities.datastructures.SetManipulation;
034
035 public class AutomaticNegativeExampleFinderOWL {
036
037 // LOGGER: ComponentManager
038 private static Logger logger = Logger.getLogger(ComponentManager.class);
039
040 private AbstractReasonerComponent reasoningService;
041
042 private SortedSet<Individual> fullPositiveSet;
043
044 private SortedSet<Individual> fromRelated = new TreeSet<Individual>();
045 private SortedSet<Individual> fromSuperclasses = new TreeSet<Individual>();
046 private SortedSet<Individual> fromParallelClasses = new TreeSet<Individual>();
047 private SortedSet<Individual> fromAllOther = new TreeSet<Individual>();
048 private SortedSet<Individual> fromDomain = new TreeSet<Individual>();
049 private SortedSet<Individual> fromRange = new TreeSet<Individual>();
050
051 static int poslimit = 10;
052 static int neglimit = 20;
053
054
055 /**
056 *
057 * takes as input a full positive set to make sure no negatives are added as positives
058 *
059 * @param fullPositiveSet
060 * @param reasoningService
061 */
062 public AutomaticNegativeExampleFinderOWL(
063 SortedSet<Individual> fullPositiveSet,
064 AbstractReasonerComponent reasoningService) {
065 super();
066 this.fullPositiveSet = new TreeSet<Individual>();
067 this.fullPositiveSet.addAll(fullPositiveSet);
068 this.reasoningService = reasoningService;
069
070 }
071
072 /**
073 * see <code> getNegativeExamples(int neglimit, boolean stable )</code>
074 * @param neglimit
075 */
076 public SortedSet<Individual> getNegativeExamples(int neglimit, boolean forceNegLimit ) {
077 return getNegativeExamples(neglimit, false, forceNegLimit);
078 }
079
080 /**
081 * aggregates all collected neg examples
082 * CAVE: it is necessary to call one of the make functions before calling this
083 * OTHERWISE it will choose random examples
084 *
085 * @param neglimit size of negative Example set, 0 means all, which can be quite large
086 * @param stable decides whether neg Examples are randomly picked, default false, faster for developing, since the cache can be used
087 * @param forceNegLimit forces that exactly neglimit instances are returned by adding more instances
088 */
089 public SortedSet<Individual> getNegativeExamples(int neglimit, boolean stable, boolean forceNegLimit ) {
090 SortedSet<Individual> negatives = new TreeSet<Individual>();
091 negatives.addAll(fromParallelClasses);
092 negatives.addAll(fromRelated);
093 negatives.addAll(fromSuperclasses);
094 if(negatives.size()< neglimit){
095 makeNegativeExamplesFromAllOtherInstances();
096
097 negatives.addAll(SetManipulation.stableShrinkInd(fromAllOther, neglimit-negatives.size()));
098 }
099
100
101
102 if(neglimit<=0){
103 logger.debug("neg Example size NO shrinking: " + negatives.size());
104 return negatives;
105 }
106
107
108 logger.debug("neg Example size before shrinking: " + negatives.size());
109 if (stable ) {
110 negatives = SetManipulation.stableShrinkInd(negatives,neglimit);
111 }
112 else {
113 negatives = SetManipulation.fuzzyShrinkInd(negatives,neglimit);
114 }
115 logger.debug("neg Example size after shrinking: " + negatives.size());
116 return negatives;
117 }
118
119
120 /**
121 * just takes all other instances from the ontology, except the ones
122 * in the fullPositiveSet (see Constructor)
123 */
124 public void makeNegativeExamplesFromAllOtherInstances() {
125 logger.debug("making random examples ");
126 fromAllOther.clear();
127 fromAllOther.addAll(reasoningService.getIndividuals());
128 fromAllOther.removeAll(fullPositiveSet);
129 logger.debug("|-negExample size from random: " + fromAllOther.size());
130 }
131
132 /**
133 * NOT IMPLEMENTED YET, DO NOT USE
134 * makes neg ex from related instances, that take part in a role R(pos,neg)
135 * filters all objects, that don't use the given namespace
136 * @param instances
137 * @param objectNamespace
138 */
139 public void makeNegativeExamplesFromRelatedInstances(SortedSet<Individual> instances,
140 String objectNamespace) {
141 logger.debug("making examples from related instances");
142 for (Individual oneInstance : instances) {
143 makeNegativeExamplesFromRelatedInstances(oneInstance, objectNamespace);
144 }
145 logger.debug("|-negExample size from related: " + fromRelated.size());
146 }
147
148 /**
149 * NOT IMPLEMENTED YET, DO NOT USE
150 * @param oneInstance
151 * @param objectnamespace
152 */
153 private void makeNegativeExamplesFromRelatedInstances(Individual oneInstance, String objectnamespace) {
154 // SortedSet<String> result = new TreeSet<String>();
155
156 //reasoningService.getRoleMembers(atomicRole)
157
158 //fromRelated.removeAll(fullPositiveSet);
159 throw new RuntimeException("method makeNegativeExamplesFromRelatedInstances not implemented yet");
160 }
161
162
163
164 /**
165 * NOT IMPLEMENTED YET, DO NOT USE
166 * makes negEx from classes, the posEx belong to.
167 * Gets all Classes from PosEx, gets Instances from these Classes, returns all
168 * @param positiveSet
169 */
170 public void makeNegativeExamplesFromParallelClasses(SortedSet<Individual> positiveSet){
171 makeNegativeExamplesFromClassesOfInstances(positiveSet);
172 }
173
174 /**
175 * NOT IMPLEMENTED YET, DO NOT USE
176 * see <code> makeNegativeExamplesFromParallelClasses</code>
177 * @param positiveSet
178 */
179 @SuppressWarnings("unused")
180 private void makeNegativeExamplesFromClassesOfInstances(SortedSet<Individual> positiveSet) {
181 logger.debug("making neg Examples from parallel classes");
182 SortedSet<Description> classes = new TreeSet<Description>();
183 this.fromParallelClasses.clear();
184
185 for (Individual instance : positiveSet) {
186 try{
187 // realization is not implemented in reasoningservice
188 //classes.addAll(reasoningService.realize()
189 }catch (Exception e) {
190 logger.warn("not implemented in "+this.getClass());
191 }
192 }
193 logger.debug("getting negExamples from " + classes.size() + " parallel classes");
194 for (Description oneClass : classes) {
195 logger.debug(oneClass);
196 // rsc = new
197 // JenaResultSetConvenience(queryConcept("\""+oneClass+"\"",limit));
198 try{
199 this.fromParallelClasses.addAll(reasoningService.getIndividuals(oneClass));
200 }catch (Exception e) {
201 logger.warn("not implemented in "+this.getClass());
202 }
203 }
204
205 fromParallelClasses.removeAll(fullPositiveSet);
206 logger.debug("|-neg Example size from parallelclass: " + fromParallelClasses.size());
207 throw new RuntimeException("not implemented in "+ this.getClass()+"method makeNegativeExamplesFromParallelClasses");
208 }
209
210
211
212
213
214 /**
215 * if pos ex derive from one class, then neg ex are taken from a superclass
216 * @param concept
217 */
218 public void makeNegativeExamplesFromSuperClasses(NamedClass concept) {
219 makeNegativeExamplesFromSuperClasses( concept, 0);
220 }
221
222 /**
223 * if pos ex derive from one class, then neg ex are taken from a superclass
224 * CURRENTLY SAME METHOD AS makeNegativeExamplesFromSuperClasses(NamedClass concept)
225 * but works quite often
226 * @param concept
227 * @param depth PARAMETER CURRENTLY NOT USED, ONLY DIRECT SUPERCLASSES
228 */
229 public void makeNegativeExamplesFromSuperClasses(NamedClass concept, int depth) {
230
231 fromSuperclasses.clear();
232 SortedSet<Description> superClasses = reasoningService.getSuperClasses(concept);
233 logger.debug("making neg Examples from " + superClasses.size() + " superclasses");
234
235 for (Description oneSuperClass : superClasses) {
236 logger.debug(oneSuperClass);
237 fromSuperclasses.addAll(reasoningService.getIndividuals(oneSuperClass));
238 }
239 this.fromSuperclasses.removeAll(fullPositiveSet);
240 logger.debug("|-neg Example from superclass: " + fromSuperclasses.size());
241 }
242
243 /**
244 * misleading method name,
245 * examples are all instances from the a-Part of the atomicRole(a,b)
246 * it has nothing to do with the actual Domain class
247 * @param atomicRole
248 */
249
250 public void makeNegativeExamplesFromDomain(ObjectProperty atomicRole){
251 fromDomain.clear();
252 logger.debug("making Negative Examples from Domain of : "+atomicRole);
253 fromDomain.addAll(reasoningService.getPropertyMembers(atomicRole).keySet());
254 fromDomain.removeAll(fullPositiveSet);
255 logger.debug("|-neg Example size from Domain: "+this.fromDomain.size());
256 }
257
258 /**
259 * misleading method name,
260 * examples are all instances from the b-Part of the atomicRole(a,b)
261 * it has nothing to do with the actual Range class
262 * @param atomicRole
263 */
264
265 public void makeNegativeExamplesFromRange(ObjectProperty atomicRole){
266 fromRange.clear();
267 logger.debug("making Negative Examples from Range of : "+atomicRole);
268 Collection<SortedSet<Individual>> tmp = reasoningService.getPropertyMembers(atomicRole).values();
269 for (SortedSet<Individual> set : tmp) {
270 fromRange.addAll(set);
271 }
272 fromRange.removeAll(fullPositiveSet);
273 logger.debug("|-neg Example size from Range: "+fromRange.size());
274 }
275 }