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.refinementoperators; 020 021import java.util.HashSet; 022import java.util.Iterator; 023import java.util.LinkedList; 024import java.util.List; 025import java.util.Set; 026import java.util.TreeSet; 027 028import org.dllearner.core.AbstractReasonerComponent; 029import org.dllearner.core.ComponentInitException; 030import org.dllearner.core.owl.OWLObjectIntersectionOfImplExt; 031import org.dllearner.core.owl.OWLObjectUnionOfImplExt; 032import org.dllearner.learningproblems.PosNegLP; 033import org.semanticweb.owlapi.model.OWLClassExpression; 034import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom; 035import org.semanticweb.owlapi.model.OWLObjectComplementOf; 036import org.semanticweb.owlapi.model.OWLObjectIntersectionOf; 037import org.semanticweb.owlapi.model.OWLObjectProperty; 038import org.semanticweb.owlapi.model.OWLObjectPropertyExpression; 039import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom; 040import org.semanticweb.owlapi.model.OWLObjectUnionOf; 041 042import com.google.common.collect.Lists; 043 044public class PsiUp extends RefinementOperatorAdapter { 045 046 PosNegLP learningProblem; 047 AbstractReasonerComponent reasoningService; 048 049 private TreeSet<OWLClassExpression> bottomSet; 050 051 public PsiUp(PosNegLP learningProblem, AbstractReasonerComponent reasoningService) { 052 this.learningProblem = learningProblem; 053 this.reasoningService = reasoningService; 054 055 // Top-Menge erstellen 056 createBottomSet(); 057 } 058 059 private void createBottomSet() { 060 bottomSet = new TreeSet<>(); 061 062 // BOTTOM AND BOTTOM 063 List<OWLClassExpression> operands = Lists.<OWLClassExpression>newArrayList(df.getOWLNothing(), df.getOWLNothing()); 064 OWLObjectIntersectionOf mc = new OWLObjectIntersectionOfImplExt(operands); 065 bottomSet.add(mc); 066 067 // speziellste Konzepte 068 bottomSet.addAll(reasoningService.getSuperClasses(df.getOWLNothing())); 069 070 // negierte allgemeinste Konzepte 071 Set<OWLClassExpression> tmp = reasoningService.getSubClasses(df.getOWLThing()); 072 for(OWLClassExpression c : tmp) 073 bottomSet.add(df.getOWLObjectComplementOf(c)); 074 075 // EXISTS r.BOTTOM und ALL r.BOTTOM für alle r 076 for(OWLObjectProperty r : reasoningService.getObjectProperties()) { 077 bottomSet.add(df.getOWLObjectAllValuesFrom(r, df.getOWLNothing())); 078 bottomSet.add(df.getOWLObjectSomeValuesFrom(r, df.getOWLNothing())); 079 } 080 } 081 082 @Override 083 @SuppressWarnings("unchecked") 084 public Set<OWLClassExpression> refine(OWLClassExpression concept) { 085 086 Set<OWLClassExpression> refinements = new HashSet<>(); 087 Set<OWLClassExpression> tmp = new HashSet<>(); 088 089 if (concept.isOWLThing()) { 090 return new TreeSet<>(); 091 } else if (concept.isOWLNothing()) { 092 return (Set<OWLClassExpression>) bottomSet.clone(); 093 } else if (!concept.isAnonymous()) { 094 // Top darf hier mit dabei sein 095 refinements.addAll(reasoningService.getSuperClasses(concept)); 096 097 // negiertes atomares Konzept 098 } else if (concept instanceof OWLObjectComplementOf) { 099 OWLClassExpression operand = ((OWLObjectComplementOf) concept).getOperand(); 100 if(!operand.isAnonymous()){ 101 tmp.addAll(reasoningService.getSubClasses(operand)); 102 103 // Bottom rausschmeissen 104 boolean containsBottom = false; 105 Iterator<OWLClassExpression> it = tmp.iterator(); 106 while(it.hasNext()) { 107 OWLClassExpression c = it.next(); 108 if(c instanceof OWLObjectComplementOf) { 109 it.remove(); 110 containsBottom = true; 111 } 112 } 113 // es soll z.B. NOT male auch zu NOT BOTTOM d.h. zu TOP verfeinert 114 // werden können 115 if(containsBottom) 116 refinements.add(df.getOWLThing()); 117 118 for(OWLClassExpression c : tmp) { 119 refinements.add(df.getOWLObjectComplementOf(c)); 120 } 121 } 122 } else if (concept instanceof OWLObjectIntersectionOf) { 123 List<OWLClassExpression> operands = ((OWLObjectIntersectionOf) concept).getOperandsAsList(); 124 // refine one of the elements 125 for(OWLClassExpression child : operands) { 126 127 // Refinement für das Kind ausführen 128 tmp = refine(child); 129 130 // neue MultiConjunction konstruieren 131 for(OWLClassExpression c : tmp) { 132 // TODO: müssen auch alle Konzepte geklont werden?? 133 // hier wird nur eine neue Liste erstellt 134 // => eigentlich muss nicht geklont werden (d.h. deep copy) da 135 // die Konzepte nicht verändert werden während des Algorithmus 136 List<OWLClassExpression> newChildren = new LinkedList<>(operands); 137 // es muss genau die vorherige Reihenfolge erhalten bleiben 138 // (zumindest bis die Normalform definiert ist) 139 int index = newChildren.indexOf(child); 140 newChildren.add(index, c); 141 newChildren.remove(child); 142 OWLClassExpression mc = new OWLObjectIntersectionOfImplExt(newChildren); 143 refinements.add(mc); 144 } 145 } 146 147 // ein Element der Konjunktion kann weggelassen werden 148 for(OWLClassExpression child : operands) { 149 List<OWLClassExpression> newChildren = new LinkedList<>(operands); 150 newChildren.remove(child); 151 if(newChildren.size()==1) 152 refinements.add(newChildren.get(0)); 153 else { 154 OWLClassExpression md = new OWLObjectIntersectionOfImplExt(newChildren); 155 refinements.add(md); 156 } 157 } 158 } else if (concept instanceof OWLObjectUnionOf) { 159 // refine one of the elements 160 List<OWLClassExpression> operands = ((OWLObjectUnionOf) concept).getOperandsAsList(); 161 for(OWLClassExpression child : operands) { 162 163 // Refinement für das Kind ausführen 164 // tmp = refine(child); 165 tmp = refine(child); 166 // neue MultiConjunction konstruieren 167 for(OWLClassExpression c : tmp) { 168 List<OWLClassExpression> newChildren = new LinkedList<>(operands); 169 // es muss genau die vorherige Reihenfolge erhalten bleiben 170 // (zumindest bis die Normalform definiert ist) 171 int index = newChildren.indexOf(child); 172 newChildren.add(index, c); 173 newChildren.remove(child); 174 OWLObjectUnionOf md = new OWLObjectUnionOfImplExt(newChildren); 175 refinements.add(md); 176 } 177 } 178 } else if (concept instanceof OWLObjectSomeValuesFrom) { 179 OWLObjectPropertyExpression role = ((OWLObjectSomeValuesFrom) concept).getProperty(); 180 OWLClassExpression filler = ((OWLObjectSomeValuesFrom) concept).getFiller(); 181 182 tmp = refine(filler); 183 for(OWLClassExpression c : tmp) { 184 refinements.add(df.getOWLObjectSomeValuesFrom(role, c)); 185 } 186 187 if(filler.isOWLThing()) 188 refinements.add(df.getOWLThing()); 189 } else if (concept instanceof OWLObjectAllValuesFrom) { 190 OWLObjectPropertyExpression role = ((OWLObjectAllValuesFrom) concept).getProperty(); 191 OWLClassExpression filler = ((OWLObjectAllValuesFrom) concept).getFiller(); 192 193 tmp = refine(filler); 194 for(OWLClassExpression c : tmp) { 195 refinements.add(df.getOWLObjectAllValuesFrom(role, c)); 196 } 197 198 if(concept.isOWLThing()) 199 refinements.add(df.getOWLThing()); 200 201 // falls es keine spezielleren atomaren Konzepte gibt, dann wird 202 // bottom angehangen => nur wenn es ein atomares Konzept (insbesondere != bottom) 203 // ist 204 // if(tmp.size()==0) { 205 // if(concept.getChild(0) instanceof AtomicConcept && tmp.size()==0) { 206 // refinements.add(new All(((Quantification)concept).getRole(),new Bottom())); 207 //} 208 } else 209 throw new RuntimeException(concept.toString()); 210 211 if(concept instanceof OWLObjectUnionOf || 212 !concept.isAnonymous() || 213 concept instanceof OWLObjectComplementOf || 214 concept instanceof OWLObjectSomeValuesFrom || 215 concept instanceof OWLObjectAllValuesFrom) { 216 217 // es wird OR BOTTOM angehangen 218 List<OWLClassExpression> operands = Lists.newArrayList(concept, df.getOWLThing()); 219 OWLClassExpression md = new OWLObjectUnionOfImplExt(operands); 220 refinements.add(md); 221 } 222 223 // Refinements werden jetzt noch bereinigt, d.h. Verschachtelungen von Konjunktionen 224 // werden entfernt; es wird eine neue Menge erzeugt, da die Transformationen die 225 // Ordnung des Konzepts ändern könnten 226 // TODO: eventuell geht das noch effizienter, da die meisten Refinement-Regeln Refinements 227 // von Child-Konzepten sind, die bereits geordnet sind, d.h. man könnte dort eventuell 228 // gleich absichern, dass alle neu hinzugefügten Refinements in geordneter Negationsnormalform 229 // sind 230 // SortedSet<Concept> returnSet = new TreeSet<Concept>(conceptComparator); 231 /* 232 Set<Concept> returnSet = new HashSet<Concept>(); 233 for(Concept c : refinements) { 234 ConceptTransformation.cleanConcept(c); 235 // ConceptTransformation.transformToOrderedNegationNormalForm(c, conceptComparator); 236 returnSet.add(c); 237 } 238 239 return returnSet; 240 */ 241 return refinements; 242 } 243 244 @Override 245 public Set<OWLClassExpression> refine(OWLClassExpression concept, int maxLength, 246 List<OWLClassExpression> knownRefinements) { 247 throw new RuntimeException(); 248 } 249 250 @Override 251 public void init() throws ComponentInitException { 252 initialized = true; 253 } 254 255}