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