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