//The MIT License // // Copyright (c) 2004 Mindswap Research Group, University of Maryland, College Park // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. package org.mindswap.swoop.reasoner; import java.net.URI; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TimeZone; import org.mindswap.pellet.EconnectedKB; import org.mindswap.pellet.owlapi.Reasoner; import org.mindswap.pellet.taxonomy.ClassifyProgress; import org.mindswap.pellet.taxonomy.DefaultClassifyProgress; import org.mindswap.pellet.taxonomy.Taxonomy; import org.mindswap.pellet.taxonomy.TaxonomyNode; import org.mindswap.pellet.utils.ATermUtils; import org.mindswap.pellet.utils.Timer; import org.mindswap.swoop.utils.ExpressivityChecker; import org.mindswap.swoop.utils.exceptions.UserCanceledException; import org.semanticweb.owl.io.ShortFormProvider; import org.semanticweb.owl.io.vocabulary.OWLVocabularyAdapter; import org.semanticweb.owl.model.OWLClass; import org.semanticweb.owl.model.OWLDescription; import org.semanticweb.owl.model.OWLException; import org.semanticweb.owl.model.OWLIndividual; import org.semanticweb.owl.model.OWLIndividualAxiom; import org.semanticweb.owl.model.OWLOntology; import org.semanticweb.owl.model.OWLSameIndividualsAxiom; import org.semanticweb.owl.model.helper.OntologyHelper; import aterm.ATermAppl; //import com.vladium.utils.IObjectProfileNode; //import com.vladium.utils.ObjectProfiler; /** * @author Evren Sirin */ public class PelletReasoner extends Reasoner implements SwoopReasoner { public static boolean AUTO_CLASSIFY = true; public boolean doExplanation = false; // glass box - clash detection // and for dependency axioms public DependencyReasoner depFinder; private HashMap sameAs, differentFrom; public synchronized void setOntologyWithoutClassif(OWLOntology ontology) throws OWLException { // default call is to show progress bar (3rd argument) setOntology( ontology, false, false); } public synchronized void setOntology(OWLOntology ontology) throws OWLException { Timer timers = new Timer("Pellet Processing"); timers.start(); depFinder = null; setOntology(ontology, true); timers.stop(); System.out.println(timers); } public synchronized void setOntology(OWLOntology ontology, boolean realize) throws OWLException { // default call is to show progress bar (3rd argument) setOntology( ontology, realize, true); } public synchronized void setOntologyWithoutClassif(OWLOntology ontology, boolean realize) throws OWLException { // default call is to show progress bar (3rd argument) setOntology( ontology, false, false); } public synchronized void setOntology(OWLOntology ontology, boolean realize, boolean showProgress) throws OWLException { // System.out.println("Explanation: " + getDoExplanation()); super.setOntology(ontology); // PelletOptions.USE_PSEUDO_NOMINALS = true; Taxonomy.DEBUG = false; // PelletOptions.SHOW_CLASSIFICATION_PROGRESS = true; if(isConsistent() && AUTO_CLASSIFY) { // setDoExplanation(true); if(realize) { System.out.print("Pellet classifying..."); // if showing progress, use DefaultClassifyProgress if ( showProgress ) { ClassifyProgress progress = new DefaultClassifyProgress(); kb.getTaxonomyBuilder().setListener( progress ); } else // if not showing progress, use SilentClassifyProgress (by passing in null) kb.getTaxonomyBuilder().setListener( null ); kb.realize(); System.out.println( "done " ); if( !kb.isRealized() ) { kb = null; System.out.println( "User canceled" ); throw new UserCanceledException( "User canceled classification " ); } } } kb.setOntology(ontology.getURI().toString()); if(realize) { //Aditya: This stuff for obtaining relations between individuals // sameAs and differentFrom has been taken from the RDFS reasoner // We need to use Pellet to infer same/different b/w individuals sameAs = new HashMap(); differentFrom = new HashMap(); this.computeIndividualRelations(ontology); } // size of expTable // ExplanationTable expTable = kb.getExplanationTable(); //// expTable = new ExplanationTable(); // IObjectProfileNode profile = ObjectProfiler.profile (expTable); // System.out.println ("ExplanationTable size = " + profile.size () + " bytes"); } public String getName() { return "Pellet"; } public synchronized boolean isConsistent() { return kb.isConsistent(); } public void printClassTree(){ kb.getTaxonomy().print(); } public void printPropertyTree(){ kb.getRoleTaxonomy().print(); } public Taxonomy getRoleTaxonomy(){ return kb.getRoleTaxonomy(); } public Taxonomy getTaxonomy(){ return kb.getTaxonomy(); } /* (non-Javadoc) * @see org.mindswap.swoop.SwoopReasoner#disjointClassesOf(org.semanticweb.owl.model.OWLClass) */ public Set disjointClassesOf(OWLClass c) throws OWLException { // tw7 OWLClass owlNothing = this.getOntology().getOWLDataFactory().getOWLNothing(); ATermAppl aa = ATermUtils.makeTermAppl( c.getURI().toString() ); Set disjointAtermSets = kb.getDisjoints( aa ); // now convert Aterms to OWLClasss // a set of sets (sets of equivalent OWLClasses that are disjoint with c) HashSet disjoints = new HashSet(); try { for ( Iterator it = disjointAtermSets.iterator(); it.hasNext(); ) { // this is a set of sets (sets of equivalent ATerms that are disjoint with c) Set disjointAtermSet = (Set)it.next(); // build one that contains OWLClasses as opposed to ATerms HashSet oneDisjointEquivalents = new HashSet(); for ( Iterator iter = disjointAtermSet.iterator(); iter.hasNext(); ) { ATermAppl aterm = (ATermAppl)iter.next(); String representation = aterm.toString(); URI uri = new URI( representation ); OWLClass aClass = super.getClass( uri ); if ( representation.equals("not(_TOP_)") ) aClass = owlNothing; if ( aClass == null ) throw new Exception("Cannot convert aterm to class with <" + uri + ">"); else { oneDisjointEquivalents.add( aClass ); } } disjoints.add( oneDisjointEquivalents ); } return disjoints; } catch ( Exception e ) { e.printStackTrace(); } // if exception occurred return Collections.EMPTY_SET; } /* (non-Javadoc) * @see org.mindswap.swoop.SwoopReasoner#complementClassesOf(org.semanticweb.owl.model.OWLClass) */ public Set complementClassesOf(OWLClass c) throws OWLException { // tw7 OWLClass owlNothing = this.getOntology().getOWLDataFactory().getOWLNothing(); OWLClass owlThing = this.getOntology().getOWLDataFactory().getOWLThing(); ATermAppl aa = ATermUtils.makeTermAppl( c.getURI().toString() ); Set complementAtermSet = kb.getComplements( aa ); // now convert Aterms to OWLClasss // a set of sets (sets of equivalent OWLClasses that are complment of c) HashSet complements = new HashSet(); try { for ( Iterator it = complementAtermSet.iterator(); it.hasNext(); ) { // this is a set ATerms that are complement with c ATermAppl aterm = (ATermAppl)it.next(); String representation = aterm.toString(); URI uri = new URI( representation ); OWLClass aClass = super.getClass( uri ); if ( representation.equals("not(_TOP_)") ) aClass = owlNothing; if ( representation.equals("_TOP_") ) aClass = owlThing; if ( aClass == null ) throw new Exception("Cannot convert aterm to class with <" + uri + ">"); complements.add( aClass ); } return complements; } catch ( Exception e ) { e.printStackTrace(); } // if exception occurred return Collections.EMPTY_SET; } /* (non-Javadoc) * @see org.mindswap.swoop.SwoopReasoner#isConsistent(org.semanticweb.owl.model.OWLClass) */ public synchronized boolean isConsistent(OWLClass c) throws OWLException { // in an inconsistent ontology every class is inconsistent // Timer timers = new Timer("Pellet Consistency Check"); // timers.start(); if(!isConsistent()) return false; // System.out.println("DEBUG: Remove me!"); // return true; boolean cons = isConsistent((OWLDescription) c); // timers.stop(); // System.out.println(timers); return cons; } public Set equivalentClassesOf(OWLDescription c) throws OWLException { if(!isConsistent()) return new HashSet(); return super.equivalentClassesOf(c); } public Set equivalentClassesOf(OWLClass c) throws OWLException { if(!isConsistent()) return new HashSet(); return super.equivalentClassesOf(c); } public Set subClassesOf(OWLClass c) throws OWLException { if(!isConsistent()) return new HashSet(); return super.subClassesOf(c); } public Set superClassesOf(OWLClass c) throws OWLException { if(!isConsistent()) return new HashSet(); return super.superClassesOf(c); } public Set allInstancesOf(OWLClass c) throws OWLException { if(!isConsistent()) return new HashSet(); return super.allInstancesOf(c); } /* (non-Javadoc) * @see org.semanticweb.owl.inference.OWLIndividualReasoner#instancesOf(org.semanticweb.owl.model.OWLDescription) */ public Set instancesOf(OWLClass c) throws OWLException { if(!isConsistent()) return new HashSet(); return super.instancesOf(c); } public Set typesOf(OWLIndividual ind) throws OWLException { if(!isConsistent()) return new HashSet(); return super.typesOf(ind); } public Set allTypesOf(OWLIndividual ind) throws OWLException { if(!isConsistent()) return new HashSet(); return super.allTypesOf(ind); } /* (non-Javadoc) * @see org.mindswap.swoop.SwoopReasoner#supportsExplanation() */ public boolean supportsExplanation() { return true; } /* (non-Javadoc) * @see org.mindswap.swoop.SwoopReasoner#setDoExplanation(boolean) */ public void setDoExplanation(boolean explain) { this.doExplanation = explain; if(kb != null) kb.setDoExplanation(explain); } public void setDoDependencyTracking(boolean depTracking) { if(kb != null) kb.setDoDependencyAxioms( depTracking ); } public boolean getDoExplanation() { // if(kb != null) // return kb.doExplanation(); return this.doExplanation; } public Set getExplanationSet() { if(kb != null) return kb.getExplanationSet(); return Collections.EMPTY_SET; } public String parseExplanation(ShortFormProvider shortForms, String explanation) { StringBuffer buffer = new StringBuffer(); // TODO fix this horrible hack // the string is a multi line string so first split it String[] lines = explanation.split(System.getProperty("line.separator")); for(int j = 0; j < lines.length; j++) { // each line has a header and a content int index = lines[j].indexOf(':'); String header = "Reason"; //lines[j].substring(0, index); String content = lines[j]; //lines[j].substring(index + 1); buffer.append("<b>" + header + "</b>: "); //BJP: Hideous string replacement hacks...but I got tired of waiting! content = content.replaceAll("\\[", "[ "); content = content.replaceAll("\\]", " ]"); content = content.replaceAll("\\(", "( "); content = content.replaceAll("\\)", " )"); content = content.replaceAll(",", " , "); content = content.replaceAll("forced to belong to class", "forced to belong to class<blockquote><FONT FACE=\"Verdana\" SIZE=2> "); content = content.replaceAll("and its complement", " </FONT></blockquote> <FONT FACE=\"Verdana\" SIZE=2>and its complement</FONT>"); String[] parts = content.split("\\s"); for(int k = 0; k < parts.length; k++) { if(parts[k].startsWith("http:") || parts[k].startsWith("file:")) buffer.append("<a href=\"" + parts[k] + "\">" + shortForms.shortForm(URI.create(parts[k])) + "</a> "); else buffer.append(parts[k] + " "); } buffer.append("<br><FONT FACE=\"Verdana\" SIZE=2>"); } String formattedExplanation = buffer.toString(); formattedExplanation = formattedExplanation.replaceAll("\\[ ", "["); formattedExplanation = formattedExplanation.replaceAll(" \\]", "]"); formattedExplanation = formattedExplanation.replaceAll("\\( ", "("); formattedExplanation = formattedExplanation.replaceAll(" \\)", ")"); formattedExplanation = formattedExplanation.replaceAll(" , ", ", "); formattedExplanation = formattedExplanation.replaceAll("\\),", "),<br>"); return formattedExplanation; } /* (non-Javadoc) * @see org.mindswap.swoop.SwoopReasoner#getExplanation() */ public String getExplanation(ShortFormProvider shortForms) { String explanation = kb.getExplanation(); // System.out.println(explanation); return this.parseExplanation(shortForms, explanation); } public String getExpressivity() throws OWLException { //******************************************************** //Added for Econnections //******************************************************** String expressivity = ""; if(!(kb instanceof EconnectedKB )) expressivity = kb.getExpressivity().toString(); else{ expressivity = ((EconnectedKB)kb).getEconnExpressivity().toString(); expressivity += "<br>" + "C(...) - EConnection"; if (((EconnectedKB)kb).getEconnExpressivity().hasInverses()) expressivity += "<br>" + "C(...)I - Inverses on links"; // if (((EconnectedKB)kb).getEconnExpressivity().hasLinkNumberRestrictions()) // expressivity += "<br>" + "C(...)N - Number restrictions on links"; // FIXME Evren: temporarily disabled so old pellet can be used // if (((EconnectedKB)kb).getEconnExpressivity().hasLinkFunctionalRestrictions()) // expressivity += "<br>" + "C(...)F - Functional Number restrictions on links"; expressivity += "<br>" + "---------------------------------------------------"; } return ExpressivityChecker.getExplanation(expressivity); } /** * Return a set of sameAs individuals given a specific individual * based on axioms in the ontology * @param ind - specific individual to test * @return * @throws OWLException */ // public Set getSameAsIndividuals(OWLIndividual ind) { // try { // return super.getSameAsIndividuals(ind); // } catch(OWLException e) { // return (Set) sameAs.get(ind); // } // } // TODO: Need to use Pellet for this public Set getDifferentFromIndividuals(OWLIndividual ind) { return (HashSet) differentFrom.get(ind); } /* (non-Javadoc) * @see org.mindswap.swoop.reasoner.SwoopReasoner#setLoadImports(boolean, boolean) */ public void setLoadImports(boolean useImports, boolean refreshOntology) throws OWLException { super.setLoadImports(useImports, refreshOntology); } /** * Check for assertions/relations involving all individuals in the ontology: * 1. sameAs or differentFrom (axioms) * */ private void computeIndividualRelations(OWLOntology ontology) throws OWLException { Set ontologies = null; if(this.loadImports()) ontologies = OntologyHelper.importClosure(ontology); else ontologies = Collections.singleton(ontology); // iterate through each ontology Iterator ont = ontologies.iterator(); // check axioms for sameAs and differentFrom assertions b/w individuals while(ont.hasNext()) { OWLOntology o = (OWLOntology) ont.next(); // get individual axioms for each ontology for (Iterator iter = o.getIndividualAxioms().iterator(); iter.hasNext(); ){ OWLIndividualAxiom indAxiom = (OWLIndividualAxiom) iter.next(); // get the set of individuals participating in each axiom Set inds = indAxiom.getIndividuals(); Map map = null; if (indAxiom instanceof OWLSameIndividualsAxiom) map = sameAs; else map = differentFrom; // add it to the corresponding map for (Iterator iter2 = inds.iterator(); iter2.hasNext(); ) { Set copyInds = new HashSet(inds); // create copy of set OWLIndividual ind = (OWLIndividual) iter2.next(); copyInds.remove(ind); if (map.get(ind)==null) { // put new set map.put(ind, copyInds); } else { // add to existing set Set current = (HashSet) map.get(ind); current.addAll(copyInds); map.put(ind, current); } } } } } /** * Given a set of unsat. classes in the ontology, separate * the root from the derived classes. Also identify connecting * axioms if any. Generate appropriate output data structures */ public void autoRootDiscovery() { try { OWLClass owlNothing = this.getOntology().getOWLDataFactory().getOWLNothing(); Set unsat = this.equivalentClassesOf(owlNothing); if(!unsat.isEmpty()) { // create instanceof DependencyReasoner depFinder = new DependencyReasoner(this.getOntologies(), this.getOntology(), unsat); // depFinder.DEBUG = true; System.out.println("---------------------------------"); System.out.println("Finding dependencies using Structural Tracing..."); Timer timer = new Timer("Structural Tracing"); timer.start(); depFinder.findDependencies(); System.out.println("Move mutual dependencies to potential roots"); depFinder.mutualToRoot(); timer.stop(); System.out.println(timer.toString()); System.out.println("Potential Roots: "+depFinder.rootClasses.size()+" Derived: "+depFinder.derivedClasses.size()); Timer timer2 = new Timer("Root Pruning"); timer2.start(); // depFinder.findAllRoots(); depFinder.infDepOntApprox(); timer2.stop(); System.out.println(timer2.toString()); depFinder.countDependencies(); System.out.println("No. of satisfiability tests: "+depFinder.numSatTests); System.out.println("---------------------------------"); System.out.println("No. of roots:"+depFinder.rootClasses.size()); for (Iterator iter = depFinder.rootClasses.iterator(); iter.hasNext();) { OWLClass root = (OWLClass) iter.next(); System.out.println("Root Unsat.:" + getName(root)); } System.out.println("---------------------------------"); System.out.println("Total No. of derived:"+depFinder.derivedClasses.size()); for (Iterator iter = depFinder.derivedClasses.iterator(); iter.hasNext();) { OWLClass derived = (OWLClass) iter.next(); System.out.println("Derived Unsat.:" + getName(derived)); } System.out.println("---------------------------------"); } } catch (OWLException ex) { ex.printStackTrace(); } } private String getName(OWLClass cla) { try { String uri = cla.getURI().toString(); if (uri.indexOf("#")>=0) uri = uri.substring(uri.indexOf("#")+1, uri.length()); else uri = uri.substring(uri.lastIndexOf("/")+1, uri.length()); return uri; } catch (OWLException ex) { ex.printStackTrace(); } return ""; } public String getTimeStamp() { Calendar cal = Calendar.getInstance(TimeZone.getDefault()); String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(DATE_FORMAT); sdf.setTimeZone(TimeZone.getDefault()); String ts = sdf.format(cal.getTime()).toString(); return ts; } public Map getDataPropertyValues(OWLIndividual ind) throws OWLException { return super.getDataPropertyValues(ind); } public Map getObjectPropertyValues(OWLIndividual ind) throws OWLException { return super.getObjectPropertyValues(ind); } public Set getSameAsIndividuals(OWLIndividual ind) throws OWLException { return super.getSameAsIndividuals( ind ); } }