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.reasoning;
021
022 import com.clarkparsia.pellet.owlapiv3.PelletReasonerFactory;
023 import org.apache.log4j.Level;
024 import org.apache.log4j.Logger;
025 import org.dllearner.core.ComponentInitException;
026 import org.dllearner.core.AbstractKnowledgeSource;
027 import org.dllearner.core.AbstractReasonerComponent;
028 import org.dllearner.core.configurators.OWLAPIReasonerConfigurator;
029 import org.dllearner.core.options.*;
030 import org.dllearner.core.owl.*;
031 import org.dllearner.kb.OWLAPIOntology;
032 import org.dllearner.kb.OWLFile;
033 import org.dllearner.kb.sparql.SparqlKnowledgeSource;
034 import org.dllearner.utilities.owl.*;
035 import org.semanticweb.HermiT.Reasoner.ReasonerFactory;
036 import org.semanticweb.owlapi.apibinding.OWLManager;
037 import org.semanticweb.owlapi.model.*;
038 import org.semanticweb.owlapi.owllink.OWLlinkHTTPXMLReasonerFactory;
039 import org.semanticweb.owlapi.owllink.OWLlinkReasonerConfiguration;
040 import org.semanticweb.owlapi.reasoner.*;
041 import org.semanticweb.owlapi.util.SimpleIRIMapper;
042 import org.semanticweb.owlapi.vocab.PrefixOWLOntologyFormat;
043 import uk.ac.manchester.cs.factplusplus.owlapiv3.FaCTPlusPlusReasonerFactory;
044
045 import java.io.File;
046 import java.net.MalformedURLException;
047 import java.net.URI;
048 import java.net.URISyntaxException;
049 import java.net.URL;
050 import java.util.*;
051 import java.util.Map.Entry;
052
053 /**
054 * Mapping to OWL API reasoner interface. The OWL API currently
055 * supports three reasoners: FaCT++, HermiT and Pellet. FaCT++ is connected
056 * using JNI and native libraries, while HermiT and Pellet are pure Java
057 * libraries.
058 *
059 * @author Jens Lehmann
060 */
061 public class OWLAPIReasoner extends AbstractReasonerComponent {
062
063 // private static Logger logger = Logger
064 // .getLogger(OWLAPIReasoner.class);
065
066 //private String reasonerType = "pellet";
067 private OWLAPIReasonerConfigurator configurator;
068
069 @Override
070 public OWLAPIReasonerConfigurator getConfigurator() {
071 return configurator;
072 }
073
074 private OWLReasoner reasoner;
075 private OWLOntologyManager manager;
076
077 private OWLOntology ontology;
078 // the data factory is used to generate OWL API objects
079 private OWLDataFactory factory;
080 // static factory
081 // private static OWLDataFactory staticFactory = OWLManager.createOWLOntologyManager().getOWLDataFactory();
082
083 private ConceptComparator conceptComparator = new ConceptComparator();
084 private RoleComparator roleComparator = new RoleComparator();
085 // private ClassHierarchy subsumptionHierarchy;
086 // private ObjectPropertyHierarchy roleHierarchy;
087 // private DatatypePropertyHierarchy datatypePropertyHierarchy;
088 // private Set<Description> allowedConceptsInSubsumptionHierarchy;
089
090 // primitives
091 Set<NamedClass> atomicConcepts = new TreeSet<NamedClass>(conceptComparator);
092 Set<ObjectProperty> atomicRoles = new TreeSet<ObjectProperty>(roleComparator);
093 SortedSet<DatatypeProperty> datatypeProperties = new TreeSet<DatatypeProperty>();
094 SortedSet<DatatypeProperty> booleanDatatypeProperties = new TreeSet<DatatypeProperty>();
095 SortedSet<DatatypeProperty> doubleDatatypeProperties = new TreeSet<DatatypeProperty>();
096 SortedSet<DatatypeProperty> intDatatypeProperties = new TreeSet<DatatypeProperty>();
097 SortedSet<DatatypeProperty> stringDatatypeProperties = new TreeSet<DatatypeProperty>();
098 SortedSet<Individual> individuals = new TreeSet<Individual>();
099
100 // namespaces
101 private Map<String, String> prefixes = new TreeMap<String, String>();
102 private String baseURI;
103
104 // references to OWL API ontologies
105 private List<OWLOntology> owlAPIOntologies = new LinkedList<OWLOntology>();
106
107 public OWLAPIReasoner(Set<AbstractKnowledgeSource> sources) {
108 super(sources);
109 this.configurator = new OWLAPIReasonerConfigurator(this);
110 }
111
112 public static String getName() {
113 return "OWL API reasoner";
114 }
115
116
117 public static Collection<ConfigOption<?>> createConfigOptions() {
118 Collection<ConfigOption<?>> options = new LinkedList<ConfigOption<?>>();
119 StringConfigOption type = new StringConfigOption("reasonerType", "FaCT++, HermiT, OWLlink or Pellet, which means \"fact\", \"hermit\", \"owllink\" or \"pellet\"", "pellet", false, true);
120 type.setAllowedValues(new String[]{"fact", "hermit", "owllink", "pellet"});
121
122 // closure option? see:
123 // http://owlapi.svn.sourceforge.net/viewvc/owlapi/owl1_1/trunk/tutorial/src/main/java/uk/ac/manchester/owl/tutorial/examples/ClosureAxiomsExample.java?view=markup
124 options.add(type);
125 try {
126 URLConfigOption owlLinkURL = new URLConfigOption("owlLinkURL", "the URL to the remote OWLlink server", new URL("http://localhost:8080/"), false, true);
127 options.add(owlLinkURL);
128 } catch (MalformedURLException e) {
129 e.printStackTrace();
130 }
131 return options;
132 }
133
134 /* (non-Javadoc)
135 * @see org.dllearner.core.Component#applyConfigEntry(org.dllearner.core.config.ConfigEntry)
136 */
137 @Override
138 public <T> void applyConfigEntry(ConfigEntry<T> entry) throws InvalidConfigOptionValueException {
139
140 }
141
142 @Override
143 public void init() throws ComponentInitException {
144 // reset variables (otherwise subsequent initialisation with
145 // different knowledge sources will merge both)
146 atomicConcepts = new TreeSet<NamedClass>(conceptComparator);
147 atomicRoles = new TreeSet<ObjectProperty>(roleComparator);
148 datatypeProperties = new TreeSet<DatatypeProperty>();
149 booleanDatatypeProperties = new TreeSet<DatatypeProperty>();
150 doubleDatatypeProperties = new TreeSet<DatatypeProperty>();
151 intDatatypeProperties = new TreeSet<DatatypeProperty>();
152 stringDatatypeProperties = new TreeSet<DatatypeProperty>();
153 individuals = new TreeSet<Individual>();
154
155 // create OWL API ontology manager
156 manager = OWLManager.createOWLOntologyManager();
157
158 // it is a bit cumbersome to obtain all classes, because there
159 // are no reasoner queries to obtain them => hence we query them
160 // for each ontology and add them to a set; a comparator avoids
161 // duplicates by checking URIs
162 Comparator<OWLNamedObject> namedObjectComparator = new Comparator<OWLNamedObject>() {
163 public int compare(OWLNamedObject o1, OWLNamedObject o2) {
164 return o1.getIRI().compareTo(o2.getIRI());
165 }
166 };
167 Set<OWLClass> classes = new TreeSet<OWLClass>(namedObjectComparator);
168 Set<OWLObjectProperty> owlObjectProperties = new TreeSet<OWLObjectProperty>(namedObjectComparator);
169 Set<OWLDataProperty> owlDatatypeProperties = new TreeSet<OWLDataProperty>(namedObjectComparator);
170 Set<OWLNamedIndividual> owlIndividuals = new TreeSet<OWLNamedIndividual>(namedObjectComparator);
171
172 Set<OWLOntology> allImports = new HashSet<OWLOntology>();
173 prefixes = new TreeMap<String, String>();
174
175 for (AbstractKnowledgeSource source : sources) {
176
177 if (source instanceof OWLFile || source instanceof SparqlKnowledgeSource || source instanceof OWLAPIOntology) {
178 URL url = null;
179 if (source instanceof OWLFile) {
180 url = ((OWLFile) source).getURL();
181 }
182
183 try {
184
185 if (source instanceof OWLAPIOntology) {
186 ontology = ((OWLAPIOntology) source).getOWLOntolgy();
187 manager = ontology.getOWLOntologyManager();
188 } else if (source instanceof SparqlKnowledgeSource) {
189 ontology = ((SparqlKnowledgeSource) source).getOWLAPIOntology();
190 manager = ontology.getOWLOntologyManager();
191 } else {
192 ontology = manager.loadOntologyFromOntologyDocument(IRI.create(url.toURI()));
193 }
194
195 owlAPIOntologies.add(ontology);
196 try {
197 // imports includes the ontology itself
198 //FIXME this line throws the strange error
199 Set<OWLOntology> imports = manager.getImportsClosure(ontology);
200 allImports.addAll(imports);
201
202 // System.out.println(imports);
203 for (OWLOntology ont : imports) {
204 classes.addAll(ont.getClassesInSignature());
205 owlObjectProperties.addAll(ont.getObjectPropertiesInSignature());
206 owlDatatypeProperties.addAll(ont.getDataPropertiesInSignature());
207 owlIndividuals.addAll(ont.getIndividualsInSignature());
208 }
209
210 } catch (UnknownOWLOntologyException uooe) {
211 logger.error("UnknownOWLOntologyException occured, imports were not loaded! This is a bug, which has not been fixed yet.");
212 }
213
214 // if several knowledge sources are included, then we can only
215 // guarantee that the base URI is from one of those sources (there
216 // can't be more than one); but we will take care that all prefixes are
217 // correctly imported
218 OWLOntologyFormat format = manager.getOntologyFormat(ontology);
219 if (format instanceof PrefixOWLOntologyFormat) {
220 prefixes.putAll(((PrefixOWLOntologyFormat) format).getPrefixName2PrefixMap());
221 baseURI = ((PrefixOWLOntologyFormat) format).getDefaultPrefix();
222 prefixes.remove("");
223 }
224
225 } catch (OWLOntologyCreationException e) {
226 e.printStackTrace();
227 } catch (URISyntaxException e) {
228 e.printStackTrace();
229 }
230 // all other sources are converted to KB and then to an
231 // OWL API ontology
232 } else {
233 KB kb = source.toKB();
234 // System.out.println(kb.toString(null,null));
235
236 IRI ontologyURI = IRI.create("http://example.com");
237 ontology = null;
238 try {
239 ontology = manager.createOntology(ontologyURI);
240 } catch (OWLOntologyCreationException e) {
241 e.printStackTrace();
242 }
243 OWLAPIAxiomConvertVisitor.fillOWLOntology(manager, ontology, kb);
244 owlAPIOntologies.add(ontology);
245 allImports.add(ontology);
246 atomicConcepts.addAll(kb.findAllAtomicConcepts());
247 atomicRoles.addAll(kb.findAllAtomicRoles());
248 individuals.addAll(kb.findAllIndividuals());
249 // TODO: add method to find datatypes
250 }
251 }
252 try {
253 ontology = manager.createOntology(IRI.create("http://dl-learner/all"), new HashSet<OWLOntology>(owlAPIOntologies));
254 } catch (OWLOntologyCreationException e1) {
255 e1.printStackTrace();
256 }
257
258 //configure reasoner
259 ReasonerProgressMonitor progressMonitor = new NullReasonerProgressMonitor();
260 FreshEntityPolicy freshEntityPolicy = FreshEntityPolicy.ALLOW;
261 long timeOut = Integer.MAX_VALUE;
262 IndividualNodeSetPolicy individualNodeSetPolicy = IndividualNodeSetPolicy.BY_NAME;
263 OWLReasonerConfiguration conf = new SimpleConfiguration(progressMonitor, freshEntityPolicy, timeOut, individualNodeSetPolicy);
264
265 // create actual reasoner
266 if (configurator.getReasonerType().equals("fact")) {
267 try {
268 reasoner = new FaCTPlusPlusReasonerFactory().createNonBufferingReasoner(ontology, conf);
269 } catch (Exception e) {
270 e.printStackTrace();
271 }
272 System.out.println("Using FaCT++.");
273 } else if (configurator.getReasonerType().equals("hermit")) {
274 // instantiate HermiT reasoner
275 reasoner = new ReasonerFactory().createNonBufferingReasoner(ontology, conf);
276 } else if (configurator.getReasonerType().equals("pellet")) {
277 // instantiate Pellet reasoner
278 reasoner = PelletReasonerFactory.getInstance().createNonBufferingReasoner(ontology, conf);
279
280 // change log level to WARN for Pellet, because otherwise log
281 // output will be very large
282 Logger pelletLogger = Logger.getLogger("org.mindswap.pellet");
283 pelletLogger.setLevel(Level.WARN);
284 } else {
285 try {
286 OWLlinkHTTPXMLReasonerFactory factory = new OWLlinkHTTPXMLReasonerFactory();
287 URL url = getConfigurator().getOwlLinkURL();//Configure the server end-point
288 OWLlinkReasonerConfiguration config = new OWLlinkReasonerConfiguration(url);
289 reasoner = factory.createNonBufferingReasoner(ontology, config);
290 System.out.println(reasoner.getReasonerName());
291 } catch (Exception e) {
292 // e.printStackTrace();
293 throw new ComponentInitException(e);
294 }
295 }
296
297 /*
298 Set<OWLOntology> importsClosure = manager.getImportsClosure(ontology);
299 System.out.println("imports closure : " + importsClosure);
300 try {
301 reasoner.loadOntologies(importsClosure);
302 } catch (OWLReasonerException e1) {
303 // TODO Auto-generated catch block
304 e1.printStackTrace();
305 }*/
306
307 // System.out.println(classes);
308 // System.out.println(properties);
309 // System.out.println(individuals);
310
311 // compute class hierarchy and types of individuals
312 // (done here to speed up later reasoner calls)
313 boolean inconsistentOntology = !reasoner.isConsistent();
314
315 if (!inconsistentOntology) {
316 reasoner.precomputeInferences(InferenceType.CLASS_HIERARCHY, InferenceType.CLASS_ASSERTIONS);
317 } else {
318 throw new ComponentInitException("Inconsistent ontologies.");
319 }
320
321 factory = manager.getOWLDataFactory();
322
323 // try {
324 // if(reasoner.isDefined(factory.getOWLIndividual(URI.create("http://example.com/father#female"))))
325 // System.out.println("DEFINED.");
326 // else
327 // System.out.println("NOT DEFINED.");
328 // } catch (OWLReasonerException e) {
329 // // TODO Auto-generated catch block
330 // e.printStackTrace();
331 // }
332
333 // read in primitives
334 for (OWLClass owlClass : classes)
335 atomicConcepts.add(new NamedClass(owlClass.toStringID()));
336 for (OWLObjectProperty owlProperty : owlObjectProperties)
337 atomicRoles.add(new ObjectProperty(owlProperty.toStringID()));
338 for (OWLDataProperty owlProperty : owlDatatypeProperties) {
339 DatatypeProperty dtp = new DatatypeProperty(owlProperty.toStringID());
340 Set<OWLDataRange> ranges = owlProperty.getRanges(allImports);
341 Iterator<OWLDataRange> it = ranges.iterator();
342 if (it.hasNext()) {
343 OWLDataRange range = it.next();
344 if (range.isDatatype()) {
345 URI uri = ((OWLDatatype) range).getIRI().toURI();
346 if (uri.equals(OWL2Datatype.BOOLEAN.getURI())) booleanDatatypeProperties.add(dtp);
347 else if (uri.equals(OWL2Datatype.DOUBLE.getURI())) doubleDatatypeProperties.add(dtp);
348 else if (uri.equals(OWL2Datatype.INT.getURI())) intDatatypeProperties.add(dtp);
349 else if (uri.equals(OWL2Datatype.STRING.getURI())) stringDatatypeProperties.add(dtp);
350 }
351 } else {
352 stringDatatypeProperties.add(dtp);
353 }
354 datatypeProperties.add(dtp);
355 }
356 for (OWLNamedIndividual owlIndividual : owlIndividuals) {
357 individuals.add(new Individual(owlIndividual.toStringID()));
358 }
359
360 // remove top and bottom properties (for backwards compatibility)
361 // atomicRoles.remove(new ObjectProperty("http://www.w3.org/2002/07/owl#bottomObjectProperty"));
362 // atomicRoles.remove(new ObjectProperty("http://www.w3.org/2002/07/owl#topObjectProperty"));
363 }
364
365 /* (non-Javadoc)
366 * @see org.dllearner.core.Reasoner#getAtomicConcepts()
367 */
368 public Set<NamedClass> getNamedClasses() {
369 return Collections.unmodifiableSet(atomicConcepts);
370 }
371
372 /* (non-Javadoc)
373 * @see org.dllearner.core.Reasoner#getAtomicRoles()
374 */
375 public Set<ObjectProperty> getObjectProperties() {
376 return Collections.unmodifiableSet(atomicRoles);
377 }
378
379 @Override
380 public SortedSet<DatatypeProperty> getDatatypePropertiesImpl() {
381 return datatypeProperties;
382 }
383
384 /* (non-Javadoc)
385 * @see org.dllearner.core.Reasoner#getIndividuals()
386 */
387 public SortedSet<Individual> getIndividuals() {
388 return individuals;
389 }
390
391 /* (non-Javadoc)
392 * @see org.dllearner.core.Reasoner#getReasonerType()
393 */
394 @Override
395 public ReasonerType getReasonerType() {
396 if (configurator.getReasonerType().equals("fact")) {
397 return ReasonerType.OWLAPI_FACT;
398 } else if (configurator.getReasonerType().equals("hermit")) {
399 return ReasonerType.OWLAPI_HERMIT;
400 } else {
401 return ReasonerType.OWLAPI_PELLET;
402 }
403 }
404
405 // @Override
406 // public ObjectPropertyHierarchy prepareRoleHierarchy() {
407 // // code copied from DIG reasoner
408 //
409 // TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyUp = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
410 // roleComparator);
411 // TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyDown = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
412 // roleComparator);
413 //
414 // // refinement of atomic concepts
415 // for (ObjectProperty role : atomicRoles) {
416 // roleHierarchyDown.put(role, getMoreSpecialRolesImpl(role));
417 // roleHierarchyUp.put(role, getMoreGeneralRolesImpl(role));
418 // }
419 //
420 // roleHierarchy = new ObjectPropertyHierarchy(atomicRoles, roleHierarchyUp,
421 // roleHierarchyDown);
422 // return roleHierarchy;
423 // }
424
425 /* (non-Javadoc)
426 * @see org.dllearner.core.Reasoner#prepareRoleHierarchy(java.util.Set)
427 */
428 // public void prepareRoleHierarchy(Set<ObjectProperty> allowedRoles) {
429 // // code copied from DIG reasoner
430 //
431 // TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyUp = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
432 // roleComparator);
433 // TreeMap<ObjectProperty, TreeSet<ObjectProperty>> roleHierarchyDown = new TreeMap<ObjectProperty, TreeSet<ObjectProperty>>(
434 // roleComparator);
435 //
436 // // refinement of atomic concepts
437 // for (ObjectProperty role : atomicRoles) {
438 // roleHierarchyDown.put(role, getMoreSpecialRolesImpl(role));
439 // roleHierarchyUp.put(role, getMoreGeneralRolesImpl(role));
440 // }
441 //
442 // roleHierarchy = new ObjectPropertyHierarchy(allowedRoles, roleHierarchyUp,
443 // roleHierarchyDown);
444 // }
445
446 // @Override
447 // public ObjectPropertyHierarchy getRoleHierarchy() {
448 // return roleHierarchy;
449 // }
450
451 // public void prepareDatatypePropertyHierarchyImpl(Set<DatatypeProperty> allowedRoles) {
452 // // code copied from DIG reasoner
453 //
454 // TreeMap<DatatypeProperty, TreeSet<DatatypeProperty>> datatypePropertyHierarchyUp = new TreeMap<DatatypeProperty, TreeSet<DatatypeProperty>>(
455 // roleComparator);
456 // TreeMap<DatatypeProperty, TreeSet<DatatypeProperty>> datatypePropertyHierarchyDown = new TreeMap<DatatypeProperty, TreeSet<DatatypeProperty>>(
457 // roleComparator);
458 //
459 // // refinement of atomic concepts
460 // for (DatatypeProperty role : datatypeProperties) {
461 // datatypePropertyHierarchyDown.put(role, getMoreSpecialDatatypePropertiesImpl(role));
462 // datatypePropertyHierarchyUp.put(role, getMoreGeneralDatatypePropertiesImpl(role));
463 // }
464 //
465 // datatypePropertyHierarchy = new DatatypePropertyHierarchy(allowedRoles, datatypePropertyHierarchyUp,
466 // datatypePropertyHierarchyDown);
467 // }
468
469 // @Override
470 // public DatatypePropertyHierarchy getDatatypePropertyHierarchy() {
471 // return datatypePropertyHierarchy;
472 // }
473
474 @Override
475 public boolean isSuperClassOfImpl(Description superConcept, Description subConcept) {
476 return reasoner.isEntailed(factory.getOWLSubClassOfAxiom(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(subConcept), OWLAPIDescriptionConvertVisitor.getOWLClassExpression(superConcept)));
477 }
478
479 @Override
480 protected boolean isEquivalentClassImpl(Description class1, Description class2) {
481 return reasoner.isEntailed(factory.getOWLEquivalentClassesAxiom(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(class1), OWLAPIDescriptionConvertVisitor.getOWLClassExpression(class2)));
482 }
483
484 @Override
485 protected TreeSet<Description> getSuperClassesImpl(Description concept) {
486 NodeSet<OWLClass> classes = null;
487
488 classes = reasoner.getSuperClasses(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept), true);
489
490 return getFirstClasses(classes);
491 }
492
493 @Override
494 protected TreeSet<Description> getSubClassesImpl(Description concept) {
495 NodeSet<OWLClass> classes = null;
496
497 classes = reasoner.getSubClasses(OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept), true);
498
499 return getFirstClasses(classes);
500 }
501
502 @Override
503 protected TreeSet<ObjectProperty> getSuperPropertiesImpl(ObjectProperty role) {
504 NodeSet<OWLObjectPropertyExpression> properties = null;
505
506 properties = reasoner.getSuperObjectProperties(OWLAPIConverter.getOWLAPIObjectProperty(role), true);
507
508 return getFirstObjectProperties(properties);
509 }
510
511 @Override
512 protected TreeSet<ObjectProperty> getSubPropertiesImpl(ObjectProperty role) {
513 NodeSet<OWLObjectPropertyExpression> properties = null;
514
515 properties = reasoner.getSubObjectProperties(OWLAPIConverter.getOWLAPIObjectProperty(role), true);
516
517 return getFirstObjectProperties(properties);
518 }
519
520 @Override
521 protected TreeSet<DatatypeProperty> getSuperPropertiesImpl(DatatypeProperty role) {
522 NodeSet<OWLDataProperty> properties = null;
523
524 properties = reasoner.getSuperDataProperties(OWLAPIConverter.getOWLAPIDataProperty(role), true);
525
526 return getFirstDatatypeProperties(properties);
527 }
528
529 @Override
530 protected TreeSet<DatatypeProperty> getSubPropertiesImpl(DatatypeProperty role) {
531 NodeSet<OWLDataProperty> properties = null;
532
533 properties = reasoner.getSubDataProperties(OWLAPIConverter.getOWLAPIDataProperty(role), true);
534
535 return getFirstDatatypeProperties(properties);
536 }
537
538 @Override
539 public boolean hasTypeImpl(Description concept, Individual individual) {
540 OWLClassExpression d = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept);
541 OWLIndividual i = factory.getOWLNamedIndividual(IRI.create(individual.getName()));
542 return reasoner.isEntailed(factory.getOWLClassAssertionAxiom(d, i));
543 }
544
545 @Override
546 public SortedSet<Individual> getIndividualsImpl(Description concept) {
547 // OWLDescription d = getOWLAPIDescription(concept);
548 OWLClassExpression d = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(concept);
549 Set<OWLNamedIndividual> individuals = reasoner.getInstances(d, false).getFlattened();
550 SortedSet<Individual> inds = new TreeSet<Individual>();
551 for (OWLNamedIndividual ind : individuals)
552 //ugly code
553 if (ind != null) inds.add(new Individual(ind.toStringID()));
554 return inds;
555 }
556
557 @Override
558 public Set<NamedClass> getTypesImpl(Individual individual) {
559 Set<Node<OWLClass>> result = null;
560
561 result = reasoner.getTypes(factory.getOWLNamedIndividual(IRI.create(individual.getName())), false).getNodes();
562
563 return getFirstClassesNoTopBottom(result);
564 }
565
566 @Override
567 public boolean isSatisfiableImpl() {
568 return reasoner.isSatisfiable(factory.getOWLThing());
569 }
570
571 @Override
572 public Description getDomainImpl(ObjectProperty objectProperty) {
573 OWLObjectProperty prop = OWLAPIConverter.getOWLAPIObjectProperty(objectProperty);
574
575 // Pellet returns a set of nodes of named classes, which are more
576 // general than the actual domain/range
577 NodeSet<OWLClass> set = reasoner.getObjectPropertyDomains(prop, false);
578 return getDescriptionFromReturnedDomain(set);
579
580 }
581
582 @Override
583 public Description getDomainImpl(DatatypeProperty datatypeProperty) {
584 OWLDataProperty prop = OWLAPIConverter.getOWLAPIDataProperty(datatypeProperty);
585
586 NodeSet<OWLClass> set = reasoner.getDataPropertyDomains(prop, true);
587 return getDescriptionFromReturnedDomain(set);
588
589 }
590
591 @Override
592 public Description getRangeImpl(ObjectProperty objectProperty) {
593 OWLObjectProperty prop = OWLAPIConverter.getOWLAPIObjectProperty(objectProperty);
594
595 NodeSet<OWLClass> set = reasoner.getObjectPropertyRanges(prop, true);
596 if (set.isEmpty()) return new Thing();
597 OWLClass oc = set.iterator().next().getRepresentativeElement();
598 if (oc.isOWLThing()) {
599 return Thing.instance;
600 }
601 return new NamedClass(oc.toStringID());
602
603 }
604
605 private Description getDescriptionFromReturnedDomain(NodeSet<OWLClass> set) {
606 if (set.isEmpty()) return new Thing();
607
608 Set<OWLClassExpression> union = new HashSet<OWLClassExpression>();
609 Set<OWLClassExpression> domains = new HashSet<OWLClassExpression>();
610
611 for (Node<OWLClass> descs : set) {
612 for (OWLClassExpression desc : descs) {
613 union.add(desc);
614 }
615 }
616 for (OWLClassExpression desc : union) {
617 boolean isSuperClass = false;
618 for (Description d : getClassHierarchy().getSubClasses(OWLAPIConverter.convertClass(desc.asOWLClass()))) {
619 if (union.contains(OWLAPIConverter.getOWLAPIDescription(d))) {
620 isSuperClass = true;
621 break;
622 }
623 }
624 if (!isSuperClass) {
625 domains.add(desc);
626 }
627 }
628
629 OWLClass oc = (OWLClass) domains.iterator().next();
630 if (oc.isOWLThing()) {
631 return new Thing();
632 } else {
633 return new NamedClass(oc.toStringID());
634 }
635 }
636
637 @Override
638 public Map<Individual, SortedSet<Individual>> getPropertyMembersImpl(ObjectProperty atomicRole) {
639 OWLObjectProperty prop = OWLAPIConverter.getOWLAPIObjectProperty(atomicRole);
640 Map<Individual, SortedSet<Individual>> map = new TreeMap<Individual, SortedSet<Individual>>();
641 for (Individual i : individuals) {
642 OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(i.getName()));
643
644 // get all related individuals via OWL API
645 Set<OWLNamedIndividual> inds = reasoner.getObjectPropertyValues(ind, prop).getFlattened();
646
647 // convert data back to DL-Learner structures
648 SortedSet<Individual> is = new TreeSet<Individual>();
649 for (OWLNamedIndividual oi : inds)
650 is.add(new Individual(oi.toStringID()));
651 map.put(i, is);
652 }
653 return map;
654 }
655
656 @Override
657 protected Map<ObjectProperty, Set<Individual>> getObjectPropertyRelationshipsImpl(Individual individual) {
658 OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(individual.getName()));
659 Map<OWLObjectPropertyExpression, Set<OWLNamedIndividual>> mapAPI = new HashMap<OWLObjectPropertyExpression, Set<OWLNamedIndividual>>();
660
661 // Map<OWLObjectPropertyExpression, Set<OWLIndividual>> mapAPI = ind.getObjectPropertyValues(ontology);
662 //no method found in the new reasoner interface, so we have to ask the reasoner for each property in the ontology
663 for (OWLObjectProperty prop : ontology.getObjectPropertiesInSignature(true)) {
664 mapAPI.put(prop, reasoner.getObjectPropertyValues(ind, prop).getFlattened());
665 }
666
667 Map<ObjectProperty, Set<Individual>> map = new TreeMap<ObjectProperty, Set<Individual>>();
668 for (Entry<OWLObjectPropertyExpression, Set<OWLNamedIndividual>> entry : mapAPI.entrySet()) {
669 ObjectProperty prop = OWLAPIConverter.convertObjectProperty(entry.getKey().asOWLObjectProperty());
670 Set<Individual> inds = OWLAPIConverter.convertIndividuals(entry.getValue());
671 map.put(prop, inds);
672 }
673 return map;
674 }
675
676 @Override
677 public Set<Individual> getRelatedIndividualsImpl(Individual individual, ObjectProperty objectProperty) {
678 OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(individual.getName()));
679 OWLObjectProperty prop = OWLAPIConverter.getOWLAPIObjectProperty(objectProperty);
680 Set<OWLNamedIndividual> inds = null;
681
682 inds = reasoner.getObjectPropertyValues(ind, prop).getFlattened();
683
684 // convert data back to DL-Learner structures
685 SortedSet<Individual> is = new TreeSet<Individual>();
686 for (OWLNamedIndividual oi : inds) {
687 is.add(new Individual(oi.toStringID()));
688 }
689 return is;
690 }
691
692 @Override
693 public Set<Constant> getRelatedValuesImpl(Individual individual, DatatypeProperty datatypeProperty) {
694 OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(individual.getName()));
695 OWLDataProperty prop = OWLAPIConverter.getOWLAPIDataProperty(datatypeProperty);
696 Set<OWLLiteral> constants = null;
697
698 constants = reasoner.getDataPropertyValues(ind, prop);
699
700 return OWLAPIConverter.convertConstants(constants);
701 }
702
703 public Map<Individual, SortedSet<Double>> getDoubleValues(DatatypeProperty datatypeProperty) {
704 OWLDataProperty prop = OWLAPIConverter.getOWLAPIDataProperty(datatypeProperty);
705 Map<Individual, SortedSet<Double>> map = new TreeMap<Individual, SortedSet<Double>>();
706 for (Individual i : individuals) {
707 OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(i.getName()));
708
709 // get all related individuals via OWL API
710 Set<OWLLiteral> inds = null;
711
712 inds = reasoner.getDataPropertyValues(ind, prop);
713
714 // convert data back to DL-Learner structures
715 SortedSet<Double> is = new TreeSet<Double>();
716 for (OWLLiteral oi : inds) {
717 Double d = Double.parseDouble(oi.getLiteral());
718 is.add(d);
719 }
720 map.put(i, is);
721 }
722 return map;
723 }
724
725 @Override
726 public Map<Individual, SortedSet<Constant>> getDatatypeMembersImpl(DatatypeProperty datatypeProperty) {
727 OWLDataProperty prop = OWLAPIConverter.getOWLAPIDataProperty(datatypeProperty);
728 Map<Individual, SortedSet<Constant>> map = new TreeMap<Individual, SortedSet<Constant>>();
729 for (Individual i : individuals) {
730 OWLNamedIndividual ind = factory.getOWLNamedIndividual(IRI.create(i.getName()));
731
732 // get all related values via OWL API
733 Set<OWLLiteral> constants = null;
734
735 constants = reasoner.getDataPropertyValues(ind, prop);
736
737 // convert data back to DL-Learner structures
738 SortedSet<Constant> is = new TreeSet<Constant>();
739 for (OWLLiteral literal : constants) {
740 // for typed constants we have to figure out the correct
741 // data type and value
742 if (!literal.isRDFPlainLiteral()) {
743 Datatype dt = OWLAPIConverter.convertDatatype(literal.getDatatype());
744 is.add(new TypedConstant(literal.getLiteral(), dt));
745 // for untyped constants we have to figure out the value
746 // and language tag (if any)
747 } else {
748 if (literal.hasLang()) is.add(new UntypedConstant(literal.getLiteral(), literal.getLang()));
749 else is.add(new UntypedConstant(literal.getLiteral()));
750 }
751 }
752 // only add individuals using the datatype property
753 if (is.size() > 0) map.put(i, is);
754 }
755 return map;
756 }
757
758 // OWL API returns a set of nodes of classes, where each node
759 // consists of equivalent classes; this method picks one class
760 // from each node to flatten the set of nodes
761 private TreeSet<Description> getFirstClasses(NodeSet<OWLClass> nodeSet) {
762 TreeSet<Description> concepts = new TreeSet<Description>(conceptComparator);
763 for (Node<OWLClass> node : nodeSet) {
764 // take one element from the set and ignore the rest
765 // (TODO: we need to make sure we always ignore the same concepts)
766 OWLClass concept = node.getRepresentativeElement();
767 if (concept.isOWLThing()) {
768 concepts.add(new Thing());
769 } else if (concept.isOWLNothing()) {
770 concepts.add(new Nothing());
771 } else {
772 concepts.add(new NamedClass(concept.toStringID()));
773 }
774 }
775 return concepts;
776 }
777
778 private Set<NamedClass> getFirstClassesNoTopBottom(Set<Node<OWLClass>> nodeSet) {
779 Set<NamedClass> concepts = new HashSet<NamedClass>();
780 for (Node<OWLClass> node : nodeSet) {
781 // take one element from the set and ignore the rest
782 // (TODO: we need to make sure we always ignore the same concepts)
783 OWLClass concept = node.getRepresentativeElement();
784 if (!concept.isOWLThing() && !concept.isOWLNothing()) concepts.add(new NamedClass(concept.toStringID()));
785 }
786 return concepts;
787 }
788
789 private TreeSet<ObjectProperty> getFirstObjectProperties(NodeSet<OWLObjectPropertyExpression> nodeSet) {
790 TreeSet<ObjectProperty> roles = new TreeSet<ObjectProperty>(roleComparator);
791 for (Node<OWLObjectPropertyExpression> node : nodeSet) {
792 if (node.isBottomNode() || node.isTopNode()) {
793 continue;
794 }
795 // take one element from the set and ignore the rest
796 // (TODO: we need to make sure we always ignore the same concepts)
797 OWLObjectPropertyExpression property = node.getRepresentativeElement();
798 roles.add(new ObjectProperty(property.asOWLObjectProperty().toStringID()));
799 }
800 roles.remove(new ObjectProperty(factory.getOWLTopObjectProperty().toStringID()));
801 roles.remove(new ObjectProperty(factory.getOWLBottomObjectProperty().toStringID()));
802 return roles;
803 }
804
805 private TreeSet<DatatypeProperty> getFirstDatatypeProperties(NodeSet<OWLDataProperty> nodeSet) {
806 TreeSet<DatatypeProperty> roles = new TreeSet<DatatypeProperty>(roleComparator);
807 for (Node<OWLDataProperty> node : nodeSet) {
808 if (node.isBottomNode() || node.isTopNode()) {
809 continue;
810 }
811 OWLDataProperty property = node.getRepresentativeElement();
812 roles.add(new DatatypeProperty(property.toStringID()));
813 }
814 roles.remove(new DatatypeProperty(factory.getOWLTopDataProperty().toStringID()));
815 roles.remove(new DatatypeProperty(factory.getOWLBottomDataProperty().toStringID()));
816 return roles;
817 }
818
819 @SuppressWarnings({"unused"})
820 private Set<Description> owlClassesToAtomicConcepts(Set<OWLClass> owlClasses) {
821 Set<Description> concepts = new HashSet<Description>();
822 for (OWLClass owlClass : owlClasses)
823 concepts.add(OWLAPIConverter.convertClass(owlClass));
824 return concepts;
825 }
826
827 public static void exportKBToOWL(File owlOutputFile, KB kb, IRI ontologyIRI) {
828 OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
829 //URI ontologyURI = URI.create("http://example.com");
830 IRI physicalIRI = IRI.create(owlOutputFile.toURI());
831 SimpleIRIMapper mapper = new SimpleIRIMapper(ontologyIRI, physicalIRI);
832 manager.addIRIMapper(mapper);
833 OWLOntology ontology;
834 try {
835 ontology = manager.createOntology(ontologyIRI);
836 // OWLAPIReasoner.fillOWLAPIOntology(manager, ontology, kb);
837 OWLAPIAxiomConvertVisitor.fillOWLOntology(manager, ontology, kb);
838 manager.saveOntology(ontology);
839 } catch (OWLOntologyCreationException e) {
840 // TODO Auto-generated catch block
841 e.printStackTrace();
842 } catch (UnknownOWLOntologyException e) {
843 // TODO Auto-generated catch block
844 e.printStackTrace();
845 } catch (OWLOntologyStorageException e) {
846 // TODO Auto-generated catch block
847 e.printStackTrace();
848 }
849 }
850
851 /**
852 * Test
853 *
854 * @param args
855 */
856 public static void main(String[] args) {
857 String iri = "http://www.co-ode.org/ontologies/pizza/2007/02/12/pizza.owl";
858
859 OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
860 try {
861 OWLOntology ontology = manager.loadOntologyFromOntologyDocument(IRI.create(iri));
862 new PelletReasonerFactory().createReasoner(ontology);
863 System.out.println("Reasoner loaded succesfully.");
864 } catch (Exception e) {
865 e.printStackTrace();
866 }
867 }
868
869 /**
870 * @return the booleanDatatypeProperties
871 */
872 @Override
873 public SortedSet<DatatypeProperty> getBooleanDatatypePropertiesImpl() {
874 return booleanDatatypeProperties;
875 }
876
877 /**
878 * @return the doubleDatatypeProperties
879 */
880 @Override
881 public SortedSet<DatatypeProperty> getDoubleDatatypePropertiesImpl() {
882 return doubleDatatypeProperties;
883 }
884
885 /**
886 * @return the intDatatypeProperties
887 */
888 @Override
889 public SortedSet<DatatypeProperty> getIntDatatypePropertiesImpl() {
890 return intDatatypeProperties;
891 }
892
893 /**
894 * @return the intDatatypeProperties
895 */
896 @Override
897 public SortedSet<DatatypeProperty> getStringDatatypePropertiesImpl() {
898 return stringDatatypeProperties;
899 }
900
901 /* (non-Javadoc)
902 * @see org.dllearner.core.Reasoner#getBaseURI()
903 */
904 public String getBaseURI() {
905 return baseURI;
906 }
907
908 /* (non-Javadoc)
909 * @see org.dllearner.core.Reasoner#getPrefixes()
910 */
911 public Map<String, String> getPrefixes() {
912 return prefixes;
913 }
914
915 /* (non-Javadoc)
916 * @see org.dllearner.core.ReasonerComponent#releaseKB()
917 */
918 @Override
919 public void releaseKB() {
920 reasoner.dispose();
921 }
922
923 public List<OWLOntology> getOWLAPIOntologies() {
924 return owlAPIOntologies;
925 }
926
927 /*public void setReasonerType(String type){
928 configurator.setReasonerType(type);
929 }*/
930
931 // @Override
932 // public boolean hasDatatypeSupport() {
933 // return true;
934 // }
935
936 @Override
937 public Set<NamedClass> getInconsistentClassesImpl() {
938 Set<NamedClass> concepts = new HashSet<NamedClass>();
939
940 for (OWLClass concept : reasoner.getUnsatisfiableClasses().getEntities()) {
941 concepts.add(new NamedClass(concept.toStringID()));
942 }
943
944 return concepts;
945 }
946
947
948 public Set<OWLClass> getInconsistentOWLClasses() {
949 return reasoner.getUnsatisfiableClasses().getEntities();
950 }
951
952 @Override
953 public Set<Constant> getLabelImpl(Entity entity) {
954 OWLEntity owlEntity = OWLAPIConverter.getOWLAPIEntity(entity);
955 Set<OWLAnnotation> labelAnnotations = owlEntity.getAnnotations(owlAPIOntologies.get(0), factory.getRDFSLabel());
956 Set<Constant> annotations = new HashSet<Constant>();
957 for (OWLAnnotation label : labelAnnotations) {
958 OWLLiteral c = (OWLLiteral) label.getValue();
959 annotations.add(OWLAPIConverter.convertConstant(c));
960 }
961 return annotations;
962 }
963
964 /* (non-Javadoc)
965 * @see org.dllearner.core.BaseReasoner#remainsSatisfiable(org.dllearner.core.owl.Axiom)
966 */
967 @Override
968 public boolean remainsSatisfiableImpl(Axiom axiom) {
969 boolean consistent = true;
970 OWLAxiom axiomOWLAPI = OWLAPIAxiomConvertVisitor.convertAxiom(axiom);
971
972 try {
973 manager.applyChange(new AddAxiom(ontology, axiomOWLAPI));
974 } catch (OWLOntologyChangeException e1) {
975 e1.printStackTrace();
976 }
977
978 consistent = reasoner.isConsistent();
979
980 try {
981 manager.applyChange(new RemoveAxiom(ontology, axiomOWLAPI));
982 } catch (OWLOntologyChangeException e) {
983 e.printStackTrace();
984 }
985
986 return consistent;
987 }
988
989 /**
990 * Returns asserted class definitions of given class
991 *
992 * @param nc the class
993 * @return the asserted class definitions
994 */
995 @Override
996 protected Set<Description> getAssertedDefinitionsImpl(NamedClass nc) {
997 OWLClass owlClass = OWLAPIDescriptionConvertVisitor.getOWLClassExpression(nc).asOWLClass();
998 Set<OWLClassExpression> owlAPIDescriptions = owlClass.getEquivalentClasses(new HashSet<OWLOntology>(owlAPIOntologies.get(0).getImportsClosure()));
999 Set<Description> definitions = new HashSet<Description>();
1000 for (OWLClassExpression owlAPIDescription : owlAPIDescriptions) {
1001 definitions.add(DLLearnerDescriptionConvertVisitor.getDLLearnerDescription(owlAPIDescription));
1002 }
1003 return definitions;
1004 }
1005
1006 /**
1007 * Gets the OWL API ontology manager. Use with great caution.
1008 *
1009 * @return The OWL API ontology manager.
1010 */
1011 public OWLOntologyManager getManager() {
1012 return manager;
1013 }
1014
1015 /**
1016 * Gets the internal OWL API ontology. Use with great caution.
1017 *
1018 * @return The internal OWL API ontology.
1019 */
1020 public OWLOntology getOntology() {
1021 return ontology;
1022 }
1023
1024 /**
1025 * Gets the internal OWL API reasoner. Use with great caution.
1026 *
1027 * @return The internal OWL API reasoner.
1028 */
1029 public OWLReasoner getReasoner() {
1030 return reasoner;
1031 }
1032
1033 }