//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.debugging; import java.awt.BorderLayout; import java.awt.Container; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.URI; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JEditorPane; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.JToolBar; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.mindswap.pellet.debug.owlapi.Reasoner; import org.mindswap.swoop.SwoopFrame; import org.mindswap.swoop.SwoopModel; import org.mindswap.swoop.reasoner.PelletReasoner; import org.mindswap.swoop.renderer.SwoopCellRenderer; import org.mindswap.swoop.renderer.entity.ConciseFormatEntityRenderer; import org.mindswap.swoop.renderer.entity.OWLObjectContainer; import org.mindswap.swoop.utils.SetUtils; import org.mindswap.swoop.utils.SwoopLoader; import org.mindswap.swoop.utils.owlapi.EntailmentChecker; import org.mindswap.swoop.utils.owlapi.OWLDescriptionFinder; import org.mindswap.swoop.utils.owlapi.OWLOntBuilder; import org.mindswap.swoop.utils.ui.EntityComparator; import org.mindswap.swoop.utils.ui.JTabbedPaneWithCloseIcons; import org.semanticweb.owl.impl.model.OWLDataFactoryImpl; import org.semanticweb.owl.impl.model.OWLObjectPropertyRangeAxiomImpl; import org.semanticweb.owl.impl.model.OWLPropertyDomainAxiomImpl; import org.semanticweb.owl.model.OWLAnd; import org.semanticweb.owl.model.OWLClass; import org.semanticweb.owl.model.OWLClassAxiom; import org.semanticweb.owl.model.OWLDataFactory; import org.semanticweb.owl.model.OWLDataProperty; import org.semanticweb.owl.model.OWLDataType; import org.semanticweb.owl.model.OWLDescription; import org.semanticweb.owl.model.OWLDisjointClassesAxiom; import org.semanticweb.owl.model.OWLEntity; import org.semanticweb.owl.model.OWLEquivalentClassesAxiom; import org.semanticweb.owl.model.OWLException; import org.semanticweb.owl.model.OWLNot; import org.semanticweb.owl.model.OWLObject; import org.semanticweb.owl.model.OWLObjectProperty; import org.semanticweb.owl.model.OWLObjectPropertyRangeAxiom; import org.semanticweb.owl.model.OWLOntology; import org.semanticweb.owl.model.OWLOr; import org.semanticweb.owl.model.OWLProperty; import org.semanticweb.owl.model.OWLPropertyDomainAxiom; import org.semanticweb.owl.model.OWLSubClassAxiom; import org.semanticweb.owl.model.change.ChangeVisitor; import org.semanticweb.owl.model.change.RemoveClassAxiom; import org.semanticweb.owl.model.helper.OntologyHelper; /** * @author Aditya * */ public class RepairFrame extends JFrame implements HyperlinkListener, ListSelectionListener, ActionListener, ItemListener { // Main Swoop stuff: SwoopFrame swoopHandler; SwoopModel swoopModel; PelletReasoner pellet; OWLOntology ontology; Reasoner pelletDebug; // UI stuff: JSplitPane axiomTablePane; JEditorPane repTable, planPane, indentPane, keptPane, removedPane; JFrame keptFrame, removedFrame; Font tahoma = new Font("Tahoma", Font.PLAIN, 11); JList classList; JButton rankBtn, generateBtn, settingsBtn, clearBtn, execBtn, saveBtn, previewBtn; JButton keptBtn, removedBtn; JComboBox granularityCombo; JCheckBox rewriteChk, viewGlobalChk, updatePlanChk, impactUnsatChk; JTextField w_arityFld, w_impactFld, w_usageFld; JTabbedPaneWithCloseIcons planTabs; boolean displayMUPSUnion = true, rewriteEnabled = false, viewGlobal = false; int planCtr = 0; public Set[] planSolnAxioms = new HashSet[100]; final boolean DEBUG = true; String logFile = ""; String NEWLINE = System.getProperty("line.separator"); int logCtr = 0; // Core Repair Stuff: Set currUnsat, currRoots, currDerived; List currAxioms; HashMap claMUPSMap; // class->MUPS public HashMap axiomUnsatClaMap, axiomUsageMap, axiomSOSMap, axiomRanksMap; // ranking params public HashMap objectMap; // generically used to store contents of hyperlinked-popups public HashMap hcodeAxiomMap; public HashMap whyMap; public Set keptAxiomSet, removedAxiomSet, rewriteAxiomSet; private boolean enableImpactUnsat = true; private boolean turnOffUsage = false; private int baseRank = 10; // Repair Parameters: final int ARITY = 0; final int IMPACT = 1; final int USAGE = 2; final int RANK = 3; int CURR_METRIC = 3; double[] weights = new double[3]; /* * constructor: called from SwoopFrame */ public RepairFrame(SwoopFrame handler, SwoopModel model, PelletReasoner pelletReasoner) { // pass all required parameters this.swoopHandler = handler; this.swoopModel = model; this.pellet = pelletReasoner; // check if pellet has processed currently selected ontology if (pelletReasoner.getOntology()==null || !pellet.getOntology().equals(swoopModel.getSelectedOntology())) { try { pelletReasoner.setOntology(swoopModel.getSelectedOntology()); } catch (OWLException e) { e.printStackTrace(); } } this.ontology = swoopModel.getSelectedOntology(); // should be same as pellet.getOntology()! this.setWeights(0.9, 0.7, 0.1); this.resetSets(); setupUI(); if (DEBUG) try { logFile = "Launching Repair UI for Ontology "+swoopModel.shortForm(ontology.getURI())+" "+swoopModel.getTimeStamp(); } catch (OWLException e) { e.printStackTrace(); } // set log counter File file = null; do { logCtr++; file = new File("REPAIR-LOG_"+String.valueOf(logCtr)+".txt"); } while (file.exists()); } /* * set weights of parameters for computing axiom ranks */ private void setWeights(double arity, double impact, double usage) { weights[ARITY] = arity; weights[IMPACT] = impact; weights[USAGE] = usage; } private void resetSets() { this.keptAxiomSet = new HashSet(); this.removedAxiomSet = new HashSet(); this.rewriteAxiomSet = new HashSet(); } /* * reset (clear) all HashMaps */ private void resetMaps() { this.axiomUnsatClaMap = new HashMap(); this.axiomSOSMap = new HashMap(); this.axiomUsageMap = new HashMap(); this.axiomRanksMap = new HashMap(); this.claMUPSMap = new HashMap(); this.objectMap = new HashMap(); this.hcodeAxiomMap = new HashMap(); this.whyMap = new HashMap(); } /* * compute new root, derived unsatisfiable classes * also insert mups for roots into axiomClaMUPS map */ private void initRoots() { // initialization this.currUnsat = new HashSet(); this.currAxioms = new ArrayList(); this.currRoots = new HashSet(); this.currDerived = new HashSet(); // obtain root, derived and total unsatisfiable classes in ontology if (pellet.depFinder == null) pellet.autoRootDiscovery(); if (pellet.depFinder == null) { // no root classes! JOptionPane.showMessageDialog(this, "No More Unsatisfiable Concepts in Ontology", "Ontology Repair", JOptionPane.INFORMATION_MESSAGE); return; } this.currRoots = new HashSet(pellet.depFinder.rootClasses); this.currDerived = new HashSet(pellet.depFinder.derivedClasses); this.currUnsat.addAll(currRoots); this.currUnsat.addAll(currDerived); // get all mups for root classes and insert them in axiomClaMUPS for (Iterator iter = currRoots.iterator(); iter.hasNext();) { OWLClass root = (OWLClass) iter.next(); this.findMUPS(root); } // also dynamically set cell renderer based on currRoots classList.setCellRenderer(new SwoopCellRenderer(swoopModel, currRoots)); } public void launch() { // this.modifyEquivalence(); resetMaps(); this.refreshPelletDebuggerOntology(ontology); initRoots(); //*** Special Case: Compute impact and ranks for all root mups axioms *** if (!currRoots.isEmpty()) { // this.computeImpactSOS(); //EITHER USE THIS OR LINE BELOW // this.loadImpactSOSFile(); this.computeRanks(axiomUnsatClaMap.keySet()); } // UI changes: this.populateClassList(); planTabs.removeAll(); planSolnAxioms[0] = new HashSet(); planCtr = 0; planTabs.addTab("Main Plan", new JScrollPane(planPane)); this.refreshPlan(); } private void computeRanks(Set axioms) { for (Iterator iter = axioms.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); // get arity int arity = ((HashSet) this.axiomUnsatClaMap.get(axiom)).size(); // get impact int impact = 0; // *** special cases -- 2 types *** // Type 1: compute impact on entailments between unsatisfiable concepts if (this.enableImpactUnsat) this.computeImpactUnsat(); //*************** // Type 2: normal impact between satisfiable concepts try { if (axiom instanceof OWLSubClassAxiom) { OWLSubClassAxiom subAx = (OWLSubClassAxiom) axiom; if (subAx.getSubClass() instanceof OWLClass && subAx.getSuperClass() instanceof OWLClass) { OWLClass sub = (OWLClass) subAx.getSubClass(); OWLClass sup = (OWLClass) subAx.getSuperClass(); for (Iterator it = SetUtils.union(pellet.descendantClassesOf(sub)).iterator(); it.hasNext();) { OWLDescription s1 = (OWLDescription) it.next(); for (Iterator it2 = SetUtils.union(pellet.ancestorClassesOf(sup)).iterator(); it2.hasNext();) { OWLDescription s2 = (OWLDescription) it2.next(); if (!s2.equals(ontology.getOWLDataFactory().getOWLThing()) && !s1.equals(ontology.getOWLDataFactory().getOWLNothing())) { OWLSubClassAxiom ax = pellet.getOntology().getOWLDataFactory().getOWLSubClassAxiom(s1, s2); this.addAxiom(axiomSOSMap, axiom, ax); } } } } } else if (axiom instanceof OWLDisjointClassesAxiom) { Set dis = ((OWLDisjointClassesAxiom) axiom).getDisjointClasses(); boolean complex = false; for (Iterator d = dis.iterator(); d.hasNext();) { OWLDescription desc = (OWLDescription) d.next(); if (!(desc instanceof OWLClass)) { complex = true; break; } } if (!complex) { List disjoints= new ArrayList(dis); for (Iterator d = new ArrayList(disjoints).iterator(); d.hasNext();) { Object obj = d.next(); if (!obj.equals(ontology.getOWLDataFactory().getOWLNothing())) { disjoints.remove(obj); Set descendants = SetUtils.union(pellet.descendantClassesOf((OWLClass) obj)); descendants.removeAll(pellet.equivalentClassesOf(ontology.getOWLDataFactory().getOWLNothing())); if (enableImpactUnsat) { descendants.addAll(((OWLClass) obj).getSubClasses(ontology)); } for (Iterator it = descendants.iterator(); it.hasNext();) { OWLDescription desc1 = (OWLDescription) it.next(); if (!desc1.equals(ontology.getOWLDataFactory().getOWLNothing())) { if (enableImpactUnsat || !pellet.equivalentClassesOf(desc1).contains(ontology.getOWLDataFactory().getOWLNothing())) { for (Iterator it2 = disjoints.iterator(); it2.hasNext();) { OWLDescription desc2 = (OWLDescription) it2.next(); if (!desc2.equals(desc1)) { Set newDis = new HashSet(); newDis.add(desc1); newDis.add(desc2); OWLDisjointClassesAxiom ax = pellet.getOntology().getOWLDataFactory().getOWLDisjointClassesAxiom(newDis); this.addAxiom(axiomSOSMap, axiom, ax); } } } } } disjoints.add(obj); } } } } else if (axiom instanceof OWLPropertyDomainAxiom) { OWLPropertyDomainAxiom pd = (OWLPropertyDomainAxiom) axiom; Set onts = new HashSet(); onts.add(ontology); if (pd.getDomain() instanceof OWLClass) { OWLClass dom = (OWLClass) pd.getDomain(); Set sup = OWLDescriptionFinder.getSuperClasses(dom, onts); for (Iterator iter2 = sup.iterator(); iter2.hasNext();) { OWLDescription supCla = (OWLDescription) iter2.next(); OWLPropertyDomainAxiomImpl ax = new OWLPropertyDomainAxiomImpl((OWLDataFactoryImpl) ontology.getOWLDataFactory(), pd.getProperty(), supCla); this.addAxiom(axiomSOSMap, axiom, ax); } } } else if (axiom instanceof OWLObjectPropertyRangeAxiom) { OWLObjectPropertyRangeAxiom pd = (OWLObjectPropertyRangeAxiom) axiom; Set onts = new HashSet(); onts.add(ontology); if (pd.getRange() instanceof OWLClass) { OWLClass ran = (OWLClass) pd.getRange(); Set sup = OWLDescriptionFinder.getSuperClasses(ran, onts); for (Iterator iter2 = sup.iterator(); iter2.hasNext();) { OWLClass supCla = (OWLClass) iter2.next(); OWLObjectPropertyRangeAxiomImpl ax = new OWLObjectPropertyRangeAxiomImpl((OWLDataFactoryImpl) ontology.getOWLDataFactory(), pd.getProperty(), supCla); this.addAxiom(axiomSOSMap, axiom, ax); } } } } catch (OWLException ex) { ex.printStackTrace(); } if (axiomSOSMap.containsKey(axiom)) impact = ((HashSet) this.axiomSOSMap.get(axiom)).size(); // get usage int usage = ((HashSet) this.axiomUsageMap.get(axiom)).size(); double rank = this.calculateRank(arity, impact, usage); String rankStr = String.valueOf(rank); if (rankStr.length()>4) rankStr = rankStr.substring(0, 4); axiomRanksMap.put(axiom, rankStr); } } /* * Populate class list with unsat classes */ private void populateClassList() { Set claSet = new TreeSet(EntityComparator.INSTANCE); claSet.addAll(currUnsat); // claSet.add("<All Unsatisfiable>"); // claSet.add("<All Roots>"); classList.setListData(claSet.toArray()); // select root classes int[] indices = new int[currRoots.size()]; int i = 0; for (int ctr=0; ctr<classList.getModel().getSize(); ctr++) { if (currRoots.contains(classList.getModel().getElementAt(ctr))) indices[i++] = ctr; } classList.setSelectedIndices(indices); this.refreshClaListSelection(); } /* * refresh axiom results */ private void refreshTable(List order) { // set current Axioms displayed this.currAxioms = order; String html = "<html><body>"; String dispUnion = "Union (<a href=\":DISP_UNION\">Toggle</a>)"; if (!this.displayMUPSUnion) dispUnion = "Intersection (<a href=\":DISP_UNION\">Toggle</a>)"; html += insFont()+"Displaying Axioms in " + dispUnion + " of MUPS of Selected Classes <br>"; // html += insFont() + "<b>Root Classes: "; // for (Iterator iter = currRoots.iterator(); iter.hasNext();) { // OWLClass root = (OWLClass) iter.next(); // html += this.getOWLObjectHTML(root) + " "; // } html += "</b><hr><table border=\"1\">"; html += "<tr><td>"+insFont()+"<b>Erroneous Axioms</b></td><td>"+insFont()+"<b><a href=\":ARITY\">Arity</a></b></td><td>"+insFont()+"<b><a href=\":IMPACT\">Impact</a></b></td><td>"+insFont()+"<b><a href=\":USAGE\">Usage</a></b></td><td>"+insFont()+"<b><a href=\":RANK\">Rank</a></b></td><td>"+insFont()+"<b>Status</b></td></tr>"; for (Iterator iter = order.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); if (keptAxiomSet.contains(axiom)) html += "<tr bgcolor=\"C3FDB8\"><td>"; else if (removedAxiomSet.contains(axiom)) html += "<tr bgcolor=\"FFDDDD\"><td>"; else html += "<tr><td>"; html += insFont(); hcodeAxiomMap.put(String.valueOf(axiom.hashCode()), axiom); html += this.getOWLObjectHTML(axiom); html += "</td>"; int arity = ((HashSet) this.axiomUnsatClaMap.get(axiom)).size(); String hash = String.valueOf(this.axiomUnsatClaMap.get(axiom).hashCode()); objectMap.put(hash, this.axiomUnsatClaMap.get(axiom)); html += "<td>" + insFont()+ "<a href=\":HASH:Arity:"+hash+"\">"+String.valueOf(arity) + "</a></td>"; int impact = 0; Set impactSet = new HashSet(); if (axiomSOSMap.containsKey(axiom)) impactSet = (HashSet) this.axiomSOSMap.get(axiom); impact = impactSet.size(); hash = String.valueOf(impactSet.hashCode()); objectMap.put(hash, impactSet); html += "<td>" + insFont()+ "<a href=\":HASH:Impact:"+hash+"\">" + String.valueOf(impact) + "</td>"; int usage = ((HashSet) this.axiomUsageMap.get(axiom)).size(); hash = String.valueOf(this.axiomUsageMap.get(axiom).hashCode()); objectMap.put(hash, this.axiomUsageMap.get(axiom)); html += "<td>" + insFont()+ "<a href=\":HASH:Usage:"+hash+"\">" + String.valueOf(usage) + "</td>"; String rank = "-"; if (axiomRanksMap.containsKey(axiom)) rank = this.axiomRanksMap.get(axiom).toString(); html += "<td>" + insFont()+ rank + "</td>"; String rem = "Remove"; if (removedAxiomSet.contains(axiom)) rem="Undo"; html += "<td>"+insFont()+"<font color = \"red\">[<a href=\":FORCE:"+axiom.hashCode()+"\">"+rem+"</a>] </font>"; String keep = "Keep"; if (keptAxiomSet.contains(axiom)) keep = "Undo"; html += insFont()+"<font color = \"green\">[<a href =\":BLOCK:"+axiom.hashCode()+"\">"+keep+"</a>] </font>"; html += "</td>"; html += "</tr>"; } html += "</table>"; html += "</body></html>"; repTable.setText(html); repTable.setCaretPosition(0); } /* * Use ConciseFormatEntityRender to get HTML for a particular OWLObject */ private String getOWLObjectHTML(OWLObject object) { ConciseFormatEntityRenderer cfRend = new ConciseFormatEntityRenderer(); cfRend.setSwoopModel(swoopModel); cfRend.visitor = cfRend.createVisitor(); StringWriter st = new StringWriter(); PrintWriter buffer = new PrintWriter(st); cfRend.setWriter(buffer); try { cfRend.printObject(object); } catch (OWLException e) { e.printStackTrace(); } return st.toString(); } /* * Refresh the reasoner (debugger) over the ontology */ private void refreshPelletDebuggerOntology(OWLOntology ont) { pelletDebug = new Reasoner(); try { pelletDebug.setOntology(ont); } catch (OWLException e) { e.printStackTrace(); } pelletDebug.getKB().setDoExplanation(true); pelletDebug.getKB().doDependencyTracking = true; } private void findMUPS(OWLDescription desc) { this.findMUPS(desc, null); } /* * Find MUPS of a single unsat. concept * *** Store info in appropriate HashMaps: arity and usage *** */ private void findMUPS(OWLDescription desc, OWLObject entailment) { try { pelletDebug.isConsistent(desc); Set explSet = pelletDebug.getKB().getExplanationSet(); // prune the axioms in case there are additional axioms Set mups = new HashSet(explSet); for (Iterator iter2 = explSet.iterator(); iter2.hasNext();) { OWLObject axiom = (OWLObject) iter2.next(); mups.remove(axiom); boolean sat = false; sat = this.checkSatisfiability(mups, desc); if (sat) { mups.add(axiom); // add axiom-cla relationship to hashmap if (desc instanceof OWLClass) this.addAxiom(axiomUnsatClaMap, axiom, (OWLClass) desc); if (entailment!=null) this.addAxiom(axiomSOSMap, axiom, entailment); // compute usage of axiom when MUPS is found this.computeUsage(axiom); } } // also cross-references class with MUPS if (desc instanceof OWLClass) this.claMUPSMap.put((OWLClass) desc, mups); if (entailment!=null) this.whyMap.put(entailment, new HashSet(mups)); } catch (OWLException ex) { ex.printStackTrace(); } } /* * return set of all MUPS of all root classes */ private Set findRootsMUPS() { try { Set rootMUPS = new HashSet(); for (Iterator iter = currRoots.iterator(); iter.hasNext();) { OWLClass root = (OWLClass) iter.next(); if (!claMUPSMap.containsKey(root)) this.findMUPS(root); rootMUPS.add(claMUPSMap.get(root)); } return rootMUPS; } catch (Exception ex) { ex.printStackTrace(); } return new HashSet(); } /* * Add a pair of (axiom, ..) to the corresponding hashmap */ private void addAxiom(HashMap map, OWLObject axiom, Object desc) { Set elems = new HashSet(); elems.add(desc); if (map.containsKey(axiom)) elems.addAll((HashSet) map.get(axiom)); map.put(axiom, elems); } private void setupUI() { try { Container content = this.getContentPane(); JSplitPane mainPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); classList = new JList(); classList.setFont(tahoma); classList.addListSelectionListener(this); repTable = new JEditorPane(); repTable.setContentType("text/html"); repTable.setEditable(false); repTable.addHyperlinkListener(this); JPanel toprightPane = new JPanel(); toprightPane.setLayout(new BorderLayout()); JLabel wlbl = new JLabel("Weights: (Note: Rank = -W1 * arity + W2 * impact + W3 * usage)"); wlbl.setFont(tahoma); w_arityFld = new JTextField("0.9"); w_impactFld = new JTextField("0.7"); w_usageFld = new JTextField("0.1"); JLabel ariLbl = new JLabel(" W1: "); ariLbl.setFont(tahoma); JLabel impLbl = new JLabel(" W2: "); impLbl.setFont(tahoma); JLabel usaLbl = new JLabel(" W3: "); usaLbl.setFont(tahoma); Box box1 = Box.createHorizontalBox(); box1.add(ariLbl); box1.add(w_arityFld); Box box2 = Box.createHorizontalBox(); box2.add(impLbl); box2.add(w_impactFld); Box box3 = Box.createHorizontalBox(); box3.add(usaLbl); box3.add(w_usageFld); rankBtn = new JButton("Recompute Ranks"); rankBtn.setFont(tahoma); rankBtn.addActionListener(this); JToolBar bar = new JToolBar(); bar.add(wlbl); bar.add(box1); bar.add(box2); bar.add(box3); bar.add(rankBtn); viewGlobalChk = new JCheckBox("View Axioms Globally"); viewGlobalChk.setSelected(false); viewGlobalChk.addActionListener(this); bar.add(viewGlobalChk); toprightPane.add(bar, "North"); indentPane = new JEditorPane(); indentPane.setContentType("text/html"); indentPane.setEditable(false); indentPane.addHyperlinkListener(this); axiomTablePane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); toprightPane.add(axiomTablePane, "Center"); axiomTablePane.setLeftComponent(new JScrollPane(repTable)); axiomTablePane.setRightComponent(new JScrollPane(indentPane)); JSplitPane axiomAnalysisPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); axiomAnalysisPane.setRightComponent(toprightPane); axiomAnalysisPane.setLeftComponent(new JScrollPane(classList)); keptBtn = this.createButton("Kept Axioms (0)"); keptPane = new JEditorPane(); keptPane.setContentType("text/html"); keptPane.addHyperlinkListener(this); keptPane.setEditable(false); keptFrame = new JFrame("Axioms to be KEPT in Ontology"); keptFrame.getContentPane().add(new JScrollPane(keptPane)); keptFrame.setLocation(100, 100); keptFrame.setSize(500, 300); removedBtn = this.createButton("Removed Axioms (0)"); removedPane = new JEditorPane(); removedPane.setContentType("text/html"); removedPane.addHyperlinkListener(this); removedPane.setEditable(false); removedFrame = new JFrame("Axioms to be REMOVED from Ontology"); removedFrame.getContentPane().add(new JScrollPane(removedPane)); removedFrame.setLocation(100, 200); removedFrame.setSize(500, 300); impactUnsatChk = new JCheckBox("Extended Impact"); impactUnsatChk.setSelected(true); impactUnsatChk.setFont(tahoma); impactUnsatChk.addActionListener(this); generateBtn = this.createButton("Generate Plan"); granularityCombo = new JComboBox(); granularityCombo.setFont(tahoma); granularityCombo.addActionListener(this); granularityCombo.addItem("Repair All Unsatisfiable"); granularityCombo.addItem("Repair All Roots"); granularityCombo.addItem("Repair Selected (above)"); granularityCombo.setSelectedIndex(1); // DEFAULT granularityCombo.addItemListener(this); rewriteChk = new JCheckBox("Include Rewrites"); rewriteChk.setFont(tahoma); rewriteChk.addActionListener(this); updatePlanChk = new JCheckBox("Auto Recompute Plan"); // (when changes are made)"); updatePlanChk.setFont(tahoma); updatePlanChk.addActionListener(this); updatePlanChk.setSelected(true); settingsBtn = this.createButton("Settings"); JPanel toolBar = new JPanel(); toolBar.setLayout(new GridLayout(2,7)); toolBar.add(keptBtn); toolBar.add(removedBtn); toolBar.add(impactUnsatChk); toolBar.add(new JLabel("")); toolBar.add(new JLabel("")); toolBar.add(new JLabel("")); toolBar.add(new JLabel("")); toolBar.add(generateBtn); toolBar.add(granularityCombo); toolBar.add(rewriteChk); // toolBar.add(settingsBtn); toolBar.add(updatePlanChk); toolBar.add(new JLabel("")); toolBar.add(new JLabel("")); toolBar.add(new JLabel("")); JPanel topPanel = new JPanel(); topPanel.setLayout(new BorderLayout()); topPanel.add(axiomAnalysisPane, "Center"); topPanel.add(toolBar, "South"); mainPane.setTopComponent(topPanel); planTabs = new JTabbedPaneWithCloseIcons(); planPane = new JEditorPane(); planPane.setContentType("text/html"); planPane.setEditable(false); planPane.addHyperlinkListener(this); planTabs.addTab("Main Plan", new JScrollPane(planPane)); JPanel planPanel = new JPanel(); planPanel.setLayout(new BorderLayout()); planPanel.add(planTabs, "Center"); clearBtn = createButton("Clear"); saveBtn = createButton("Save"); previewBtn = createButton("Preview"); execBtn = createButton("Execute"); JToolBar btnPanel = new JToolBar(); btnPanel.add(clearBtn); btnPanel.add(saveBtn); btnPanel.add(previewBtn); btnPanel.add(execBtn); planPanel.add(btnPanel, "South"); mainPane.setBottomComponent(planPanel); content.add(mainPane); this.setSize(1024, 740); this.setLocation(1, 1); this.setTitle("Repairing Ontology "+swoopModel.shortForm(ontology.getURI())); this.show(); // set divider positions after displaying UI axiomAnalysisPane.setDividerLocation(150); mainPane.setDividerLocation(460); axiomTablePane.setDividerLocation(0); } catch (Exception ex) { ex.printStackTrace(); } } private JButton createButton(String lbl) { JButton btn = new JButton(lbl); btn.setFont(tahoma); btn.addActionListener(this); return btn; } /* * Used to prune explanation set obtained from Pellet */ public boolean checkSatisfiability(Set axioms, OWLDescription clazz) { // create a new ontology with axioms // and check satisfiability of clazz boolean sat = false; try { OWLOntBuilder ontBuilder = new OWLOntBuilder(); // create new ontology using axioms // use OWLOntBuilder to build a new ontology given axioms for (Iterator iter = axioms.iterator(); iter.hasNext();) { OWLObject obj = (OWLObject) iter.next(); obj.accept(ontBuilder); } // if clazz is not in ontology, return true OWLOntology newOnt = ontBuilder.currentOnt; if (clazz!=null && clazz instanceof OWLClass && newOnt.getClass(((OWLClass) clazz).getURI())==null) return true; else if (clazz!=null) { // get clazz in newOnt clazz = ontBuilder.visitDescription(clazz); } // create new instance of pellet and check sat. of clazz PelletReasoner newPellet = new PelletReasoner(); newPellet.setOntology(newOnt, false); if (clazz!=null) sat = newPellet.isConsistent(clazz); else sat = newPellet.isConsistent(); } catch (Exception ex) { System.out.println(ex.getMessage()); // clazz (description) may not be in ontology! // ex.printStackTrace(); return true; } return sat; } private String insFont() { return("<FONT FACE=\""+swoopModel.getFontFace()+"\" SIZE="+swoopModel.getFontSize()+">"); } /* (non-Javadoc) * @see javax.swing.event.HyperlinkListener#hyperlinkUpdate(javax.swing.event.HyperlinkEvent) */ public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { // if (e.getSource() == repTable || e.getSource() == planPane) { String hLink = e.getDescription(); if (isURI(hLink)) { try { if (DEBUG) logFile += NEWLINE + "Clicking URI: "+hLink+" "+swoopModel.getTimeStamp(); URI uri = new URI(hLink); // popup entity // if entity already displayed, return if (uri.equals(swoopModel.getSelectedObject().getURI())) return; if (swoopModel.getOntologyURIs().contains(uri)) { swoopHandler.ontDisplay.selectOntology(swoopModel.getOntology(uri)); } else { new SwoopLoader(swoopHandler, swoopModel).selectEntity(hLink); // popup entity ConciseFormatEntityRenderer cfRend = new ConciseFormatEntityRenderer(); boolean temp = swoopModel.getEditorEnabled(); swoopModel.setEditorEnabled(false); cfRend.setSwoopModel(swoopModel); cfRend.createVisitor(); StringWriter st = new StringWriter(); cfRend.render(swoopModel.getSelectedEntity(), swoopModel, st); displayPopup(st.toString(), swoopModel.shortForm(swoopModel.getSelectedEntity().getURI())); swoopModel.setEditorEnabled(temp); } } catch (Exception e1) { e1.printStackTrace(); } } else if (hLink.startsWith(":DISP_UNION")) { if (DEBUG) logFile += NEWLINE + "Switched MUPS Union: "+String.valueOf(!this.displayMUPSUnion)+ " "+swoopModel.getTimeStamp(); this.displayMUPSUnion = !this.displayMUPSUnion; this.refreshClaListSelection(); } else if (hLink.startsWith(":FORCE")) { // (un)force axiom into solution set if (DEBUG) logFile += NEWLINE + "REMOVED Axiom "+swoopModel.getTimeStamp(); String hcode = hLink.substring(hLink.lastIndexOf(":")+1, hLink.length()); OWLObject axiom = (OWLObject) hcodeAxiomMap.get(hcode); if (removedAxiomSet.contains(axiom)) { removedAxiomSet.remove(axiom); // solnAxiomSet.remove(axiom); ?? } else if (!keptAxiomSet.contains(axiom)) { removedAxiomSet.add(axiom); } removedBtn.setText("Removed Axioms ("+removedAxiomSet.size()+")"); this.refreshRemovedFrame(); if (this.updatePlanChk.isSelected()) { this.genPlan(); } this.sortAndDisplayAxioms(CURR_METRIC); this.refreshPlan(); planTabs.setSelectedIndex(0); } else if (hLink.startsWith(":BLOCK")) { if (DEBUG) logFile += NEWLINE + "KEPT Axiom "+swoopModel.getTimeStamp(); // toggle axiom blocked status (i.e. if blocked, it cannot be part of the solution) String hcode = hLink.substring(hLink.lastIndexOf(":")+1, hLink.length()); OWLObject axiom = (OWLObject) hcodeAxiomMap.get(hcode); if (!keptAxiomSet.contains(axiom)) { keptAxiomSet.add(axiom); // also remove axiom from forced set and soln set Set mainSolnSet = planSolnAxioms[0]; if (removedAxiomSet.contains(axiom) || mainSolnSet.contains(axiom)) { removedAxiomSet.remove(axiom); mainSolnSet.remove(axiom); } } else keptAxiomSet.remove(axiom); keptBtn.setText("Kept Axioms ("+keptAxiomSet.size()+")"); this.refreshKeptFrame(); if (this.updatePlanChk.isSelected()) { this.genPlan(); } this.sortAndDisplayAxioms(CURR_METRIC); this.refreshPlan(); planTabs.setSelectedIndex(0); } else if (hLink.startsWith(":REMOVE")) { if (DEBUG) logFile += NEWLINE + "DISCARDED Axiom "+swoopModel.getTimeStamp(); // remove axiom from soln set String hcode = hLink.substring(hLink.lastIndexOf(":")+1, hLink.length()); OWLObject remAxiom = (OWLObject) hcodeAxiomMap.get(hcode); int num = 0; String title = planTabs.getTitleAt(planTabs.getSelectedIndex()); if (title.indexOf("Main")==-1) num = Integer.parseInt(title.substring(title.lastIndexOf(" ")+1), title.length())-1; Set soln = planSolnAxioms[num]; soln.remove(remAxiom); // manualAxiomSet.remove(axiom); ?? if (planTabs.getSelectedIndex()!=0) { JEditorPane copyPane = (JEditorPane) planTabs.getSelectedComponent(); this.setCopyPaneText(copyPane, soln); } else { this.refreshPlan(); } } else if (hLink.equals(":ARITY")) { if (DEBUG) logFile += NEWLINE + "Sorting by ARITY "+swoopModel.getTimeStamp(); // sort axioms by arity CURR_METRIC = ARITY; this.sortAndDisplayAxioms(ARITY); } else if (hLink.equals(":IMPACT")) { if (DEBUG) logFile += NEWLINE + "Sorting by IMPACT "+swoopModel.getTimeStamp(); // sort axioms by impact CURR_METRIC = IMPACT; this.sortAndDisplayAxioms(IMPACT); } else if (hLink.equals(":USAGE")) { if (DEBUG) logFile += NEWLINE + "Sorting by USAGE "+swoopModel.getTimeStamp(); // sort axioms by usage CURR_METRIC = USAGE; this.sortAndDisplayAxioms(USAGE); } else if (hLink.equals(":RANK")) { if (DEBUG) logFile += NEWLINE + "Sorting by RANK "+swoopModel.getTimeStamp(); // sort axioms by rank CURR_METRIC = RANK; this.sortAndDisplayAxioms(RANK); } else if (hLink.startsWith(":REWRITE")) { String hashCode = hLink.substring(hLink.lastIndexOf(":")+1, hLink.length()); OWLObject axiom = (OWLObject) hcodeAxiomMap.get(hashCode); if (DEBUG) { if (rewriteAxiomSet.contains(axiom)) logFile += NEWLINE + "Chose to UNDO REWRITE "+swoopModel.getTimeStamp(); else logFile += NEWLINE + "Chose to REWRITE "+swoopModel.getTimeStamp(); } if (rewriteAxiomSet.contains(axiom)) rewriteAxiomSet.remove(axiom); else rewriteAxiomSet.add(axiom); // TODO // if (this.updatePlanChk.isSelected()) { // this.genPlan(); // } this.refreshPlan(); } else if (hLink.startsWith(":HASH")) { // display arity/impact in popup String param = hLink.substring(6, hLink.lastIndexOf(":")); if (DEBUG) logFile += NEWLINE + "Viewing Parameter: "+param+" "+swoopModel.getTimeStamp(); String hashCode = hLink.substring(hLink.lastIndexOf(":")+1, hLink.length()); Set disp = (HashSet) objectMap.get(hashCode); String html = "<html><body>"; int ctr = 1; for (Iterator iter = disp.iterator(); iter.hasNext();) { OWLObject obj = (OWLObject) iter.next(); swoopModel.repairColor = true; swoopModel.repairSet = new HashSet(currUnsat); html += insFont() + String.valueOf(ctr++) + ". "+this.getOWLObjectHTML(obj); swoopModel.repairColor = false; swoopModel.repairSet = new HashSet(); // also add why? link if present if (whyMap.containsKey(obj)) { this.hcodeAxiomMap.put(String.valueOf(obj.hashCode()), obj); html += "  (<a href=\":WHY:"+obj.hashCode()+"\">Why?</a>)"; } html += "<br>"; } displayPopup(html, param+" Details"); } else if (hLink.startsWith(":WHY")) { // display explanation for impact related to unsat. classes try { String param = hLink.substring(hLink.lastIndexOf(":")+1, hLink.length()); if (DEBUG) logFile += NEWLINE + "Viewing Entailment Explanation: "+param+" "+swoopModel.getTimeStamp(); OWLObject entailment = (OWLObject) this.hcodeAxiomMap.get(param); Set expl = (HashSet) whyMap.get(entailment); String html = "<html><body>"; html += "<font face=\"Verdana\" size=3><b>Explanation for "+ this.getOWLObjectHTML(entailment) +"</b><hr>"; // get indented explanation ConciseFormatEntityRenderer cfRend = new ConciseFormatEntityRenderer(); cfRend.setSwoopModel(swoopModel); cfRend.visitor = cfRend.createVisitor(); StringWriter st = new StringWriter(); PrintWriter buffer = new PrintWriter(st); cfRend.setWriter(buffer); OWLClass thing = ontology.getOWLDataFactory().getOWLThing(); OWLObjectContainer cont = new OWLObjectContainer(thing); cont.visit(entailment); OWLClass any = null; if (cont.getLHS().size()>0) any = (OWLClass) cont.getLHS().iterator().next(); else any = (OWLClass) cont.getRHS().iterator().next(); if (any==null) any = thing; cfRend.printRepairSOS(expl, any, this); String sosStr = st.toString().replaceAll("problem", "entailment"); html += "<font face=\"Verdana\" size=3>" + sosStr; displayPopup(html, "Why?", 600, 200); } catch (OWLException ex) { ex.printStackTrace(); } } // } } } private void refreshKeptFrame() { // print forced axioms first String planStr = "<html><head></head><body>"; if (!keptAxiomSet.isEmpty()) { planStr += insFont(); //+"<b>Axioms to be KEPT in Ontology</b><br>"; for (Iterator iter = keptAxiomSet.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); hcodeAxiomMap.put(String.valueOf(axiom.hashCode()), axiom); planStr += "<font color=\"green\">[<a href=\":BLOCK:"+axiom.hashCode()+"\">Undo Keep</a>]</font> "; planStr += this.getOWLObjectHTMLWithAttribs(axiom) + "<br>"; } planStr += "<br>"; } planStr += "</body></html>"; keptPane.setText(planStr); } private void refreshRemovedFrame() { // print blocked axioms String planStr = "<html><head></head><body>"; if (!removedAxiomSet.isEmpty()) { planStr += insFont(); //+"<b>Axioms to be REMOVED from Ontology</b><br>"; for (Iterator iter = removedAxiomSet.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); hcodeAxiomMap.put(String.valueOf(axiom.hashCode()), axiom); planStr += "<font color=\"red\">[<a href=\":FORCE:"+axiom.hashCode()+"\">Undo Remove</a>]</font> "; planStr += this.getOWLObjectHTMLWithAttribs(axiom) + "<br>"; } planStr += "<br>"; } planStr += "</body></html>"; removedPane.setText(planStr); } private void displayPopup(String html, String title) { this.displayPopup(html, title, 400, 300); } private void displayPopup(String html, String title, int width, int height) { JFrame popup = new JFrame(); JEditorPane pane = new JEditorPane(); pane.setContentType("text/html"); pane.setEditable(false); pane.addHyperlinkListener(this); pane.setText(html); pane.setCaretPosition(0); popup.getContentPane().add(new JScrollPane(pane)); popup.setSize(width, height); popup.setLocation(100, 100); popup.setTitle(title); popup.show(); } private void setCopyPaneText(JEditorPane copyPane, Set soln) { String html = "<html><body>"; for (Iterator iter = soln.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); hcodeAxiomMap.put(String.valueOf(axiom.hashCode()), axiom); html += insFont()+"<font color=\"blue\">[<a href=\":REMOVE:"+axiom.hashCode()+"\">X</a>]</font> "; String rem = "Remove"; if (removedAxiomSet.contains(axiom)) rem = "Undo-Remove"; html += "<font color=\"red\">[<a href=\":FORCE:"+axiom.hashCode()+"\">"+rem+"</a>]</font> "; html += "<font color=\"green\">[<a href=\":BLOCK:"+axiom.hashCode()+"\">Keep</a>]</font> "; if (removedAxiomSet.contains(axiom)) html += "<font color = \"red\">"; html += this.getOWLObjectHTMLWithAttribs(axiom) + "<br>"; if (removedAxiomSet.contains(axiom)) html += "</font>"; } html += "</body></html>"; copyPane.setText(html); } /* * sort axioms in table based on specified parameter */ private void sortAndDisplayAxioms(int param) { int numAxioms = currAxioms.size(); OWLObject[] sorted = new OWLObject[numAxioms]; HashMap sourceMap = null; boolean increase = false; switch (param) { case ARITY: sourceMap = axiomUnsatClaMap; increase = false; break; case IMPACT: increase = true; sourceMap = axiomSOSMap; break; case USAGE: increase = true; sourceMap = axiomUsageMap; break; case RANK: increase = true; sourceMap = axiomRanksMap; } // sort based on sourceMap selected for (Iterator iter = currAxioms.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); double metric = 0; if (sourceMap.containsKey(axiom)) { if (!sourceMap.equals(axiomRanksMap)) metric = ((HashSet) sourceMap.get(axiom)).size(); else { String m = sourceMap.get(axiom).toString(); metric = Double.parseDouble(m); } } for (int ctr=0; ctr<numAxioms; ctr++) { OWLObject ax = sorted[ctr]; if (ax!=null) { double metric2 = 0; if (sourceMap.containsKey(ax)) { if (!sourceMap.equals(axiomRanksMap)) metric2 = ((HashSet) sourceMap.get(ax)).size(); else { metric2 = Double.parseDouble(sourceMap.get(ax).toString()); } } if ((increase && metric<metric2) || (!increase && metric>metric2)) { insert(sorted, axiom, ctr); break; } } else { insert(sorted, axiom, ctr); break; } } } // refresh repair table after sorting List order = new ArrayList(); for (int ctr=0; ctr<numAxioms; ctr++) order.add(sorted[ctr]); this.refreshTable(order); } private void insert(Object[] array, Object obj, int pos) { int len = array.length; // System.out.println(array+" "+obj+" "+pos); for (int i=len-2; i>=pos; i--) { array[i+1] = array[i]; } array[pos] = obj; } /* * for each axiom, compute its relevance to the ontology based on usage */ private void computeUsage(OWLObject axiom) { try { OWLClass thing = ontology.getOWLDataFactory().getOWLThing(); OWLObjectContainer owlCont = new OWLObjectContainer(thing); owlCont.visit(axiom); List axiomElements = new ArrayList(); axiomElements.addAll(owlCont.getLHS()); axiomElements.addAll(owlCont.getRHS()); // get usage for each entity in axiom-elements Set usage = new HashSet(); for (Iterator iter2=axiomElements.iterator(); iter2.hasNext();) { Object obj = iter2.next(); if (obj instanceof OWLEntity) { usage.addAll(OntologyHelper.entityUsage(ontology, (OWLEntity) obj)); } } for (Iterator iter2 = new HashSet(usage).iterator(); iter2.hasNext();) { OWLObject obj = (OWLObject) iter2.next(); if (!(obj instanceof OWLEntity)) usage.remove(obj); } if (!turnOffUsage) axiomUsageMap.put(axiom, usage); } catch (Exception ex) { ex.printStackTrace(); } } private String getOWLObjectHTMLWithAttribs(OWLObject axiom) { String html = ""; html += this.getOWLObjectHTML(axiom) + "  ("; int arity = -1; if (axiomUnsatClaMap.containsKey(axiom)) arity = ((HashSet) this.axiomUnsatClaMap.get(axiom)).size(); if (arity!=-1) { String hash = String.valueOf(this.axiomUnsatClaMap.get(axiom).hashCode()); html += "Arity:<a href=\":HASH:Arity:"+hash+"\">"+String.valueOf(arity) + "</a>"; objectMap.put(hash, (HashSet) this.axiomUnsatClaMap.get(axiom)); } int impact = -1; Set impactSet = new HashSet(); if (axiomSOSMap.containsKey(axiom)) impactSet = (HashSet) this.axiomSOSMap.get(axiom); impact = impactSet.size(); if (impact!=-1) { String hash = String.valueOf(impactSet.hashCode()); objectMap.put(hash, impactSet); html += "  Impact: <a href=\":HASH:Impact:"+hash+"\">" + String.valueOf(impact)+"</a>"; } int usage = -1; if (axiomUsageMap.containsKey(axiom)) usage = ((HashSet) this.axiomUsageMap.get(axiom)).size(); if (usage!=-1) { String hash = String.valueOf(this.axiomUsageMap.get(axiom).hashCode()); objectMap.put(hash, this.axiomUsageMap.get(axiom)); html += "  Usage: <a href=\":HASH:Usage:"+hash+"\">" + String.valueOf(usage)+"</a>"; } html += ")"; return html; } public void refreshPlan() { refreshPlan(false); int pos = indentPane.getCaretPosition(); this.refreshIndentPane(); try { indentPane.setCaretPosition(pos); } catch (Exception ex) { indentPane.setCaretPosition(0); } } // refresh plan // plan axioms are present in planSolnAxioms[0] private void refreshPlan(boolean genPlans) { String planStr = "<html><body>"+insFont(); // print solution axioms Set mainSolnSet = planSolnAxioms[0]; if (!mainSolnSet.isEmpty()) { // planStr += "<b><u>GENERATED REPAIR PLAN:" + " to "+ granularityCombo.getSelectedItem().toString()+"</u></b><br>"; for (Iterator iter = mainSolnSet.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); hcodeAxiomMap.put(String.valueOf(axiom.hashCode()), axiom); planStr += insFont()+"<font color=\"blue\">[<a href=\":REMOVE:"+axiom.hashCode()+"\">X</a>]</font> "; String rem = "Remove"; if (removedAxiomSet.contains(axiom)) rem = "Undo-Remove"; planStr += "<font color=\"red\">[<a href=\":FORCE:"+axiom.hashCode()+"\">"+rem+"</a>]</font> "; planStr += "<font color=\"green\">[<a href=\":BLOCK:"+axiom.hashCode()+"\">Keep</a>]</font> "; if (removedAxiomSet.contains(axiom)) planStr += "<font color = \"red\">"; planStr += this.getOWLObjectHTMLWithAttribs(axiom); if (removedAxiomSet.contains(axiom)) planStr += "</font>"; // suggestions for rewrites? if (rewriteEnabled) planStr += suggestRewrites(axiom); planStr += "<br>"; } // also add preview information directly planStr += "<br>"+previewEffect(true); } else if (genPlans) { planStr += "<br><b>No Plan Found.</b> Try changing one or more of the KEPT or REMOVED axioms.<br>"; } planStr += "</body></html>"; planPane.setText(planStr); planPane.setCaretPosition(0); } private String suggestRewrites(OWLObject axiom) { String html = ""; try { if (axiom instanceof OWLEquivalentClassesAxiom) { // weaken equivalent to subclass OWLEquivalentClassesAxiom equ = (OWLEquivalentClassesAxiom) axiom; OWLClass cla = null; for (Iterator iter = equ.getEquivalentClasses().iterator(); iter.hasNext();) { OWLDescription desc = (OWLDescription) iter.next(); if (desc instanceof OWLClass) { cla = (OWLClass) desc; break; } } Set copy = new HashSet(equ.getEquivalentClasses()); copy.remove(cla); for (Iterator iter = copy.iterator(); iter.hasNext();) { OWLDescription desc = (OWLDescription) iter.next(); OWLSubClassAxiom sub = ontology.getOWLDataFactory().getOWLSubClassAxiom(cla, desc); hcodeAxiomMap.put(String.valueOf(sub.hashCode()), sub); String rewrite = "Undo Rewrite"; // rewriteAxiomSet.add(sub); if (!rewriteAxiomSet.contains(sub)) rewrite = "Rewrite?"; html += "<br>"+"<font face=\"Verdana\" size=2> |_[<a href=\":REWRITE:"+sub.hashCode()+"\">" + rewrite + "</a>] "+this.getOWLObjectHTML(sub)+"</font>"; } } else if (axiom instanceof OWLPropertyDomainAxiom) { // rewrite domain into local property restriction OWLPropertyDomainAxiom opd = (OWLPropertyDomainAxiom) axiom; OWLProperty prop = opd.getProperty(); OWLDescription dom = opd.getDomain(); OWLDescription all = null; if (prop instanceof OWLObjectProperty) { OWLObject ran = ontology.getOWLDataFactory().getOWLThing(); if (prop.getRanges(ontology).size()>0) ran = (OWLObject) prop.getRanges(ontology).iterator().next(); all = ontology.getOWLDataFactory().getOWLObjectAllRestriction((OWLObjectProperty) prop, (OWLDescription) ran); } else { OWLObject ran = ontology.getOWLDataFactory().getOWLConcreteDataType(new URI("http://www.w3.org/2001/XMLSchema#string")); if (prop.getRanges(ontology).size()>0) ran = (OWLObject) prop.getRanges(ontology).iterator().next(); all = ontology.getOWLDataFactory().getOWLDataAllRestriction((OWLDataProperty) prop, (OWLDataType) ran); } OWLSubClassAxiom sub = ontology.getOWLDataFactory().getOWLSubClassAxiom(dom, all); hcodeAxiomMap.put(String.valueOf(sub.hashCode()), sub); String rewrite = "Undo Rewrite"; // rewriteAxiomSet.add(sub); if (!rewriteAxiomSet.contains(sub)) rewrite = "Rewrite?"; html += "<br>"+"<font face=\"Verdana\" size=2> |_[<a href=\":REWRITE:"+sub.hashCode()+"\">" + rewrite + "</a>] "+this.getOWLObjectHTML(sub)+"</font>"; } } catch (Exception ex) { ex.printStackTrace(); } return html; } public void valueChanged(ListSelectionEvent e) { if (e.getSource() == classList) { refreshClaListSelection(); } } /* * refresh table based on class list selection * either display union or intersection of MUPS */ private void refreshClaListSelection() { if (classList.getSelectedValue()!=null) { // init the axiom set that is to be displayed // based on selected classes and union/intersection Set displayAxioms = new HashSet(); for (int i = 0; i < classList.getSelectedValues().length; i++) { OWLClass cla = (OWLClass) classList.getSelectedValues()[i]; if (!claMUPSMap.containsKey(cla)) this.findMUPS(cla); Set mups = new HashSet((Set) claMUPSMap.get(cla)); if (this.displayMUPSUnion) displayAxioms.addAll(mups); else { // display intersection if (displayAxioms.isEmpty()) displayAxioms = mups; else displayAxioms.retainAll(mups); } } this.refreshTable(new ArrayList(displayAxioms)); this.sortAndDisplayAxioms(CURR_METRIC); int pos = indentPane.getCaretPosition(); this.refreshIndentPane(); try { indentPane.setCaretPosition(pos); } catch (Exception ex) { indentPane.setCaretPosition(0); } } else this.refreshTable(new ArrayList()); } /* * display indented sos for selected classes */ private void refreshIndentPane() { try { ConciseFormatEntityRenderer cfRend = new ConciseFormatEntityRenderer(); cfRend.setSwoopModel(swoopModel); cfRend.visitor = cfRend.createVisitor(); Set claSet = new HashSet(); for (int i = 0; i < classList.getSelectedValues().length; i++) { claSet.add(classList.getSelectedValues()[i]); } List claList = new ArrayList(); while (claSet.size()>0) { // take any one class out of set OWLClass cla = (OWLClass) claSet.iterator().next(); claList.add(cla); claSet.remove(cla); // find all other classes that share atleast one axiom if (!claMUPSMap.containsKey(cla)) this.findMUPS(cla); Set mups = new HashSet((Set) claMUPSMap.get(cla)); for (Iterator iter = mups.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); for (Iterator iter2 = ((Set) axiomUnsatClaMap.get(axiom)).iterator(); iter2.hasNext(); ) { OWLClass sharedCla = (OWLClass) iter2.next(); if (claSet.contains(sharedCla)) { claList.add(sharedCla); claSet.remove(sharedCla); } } } } String html = "<html><body>"; for (int i = 0; i < claList.size(); i++) { OWLClass cla = (OWLClass) claList.get(i); Set mups = new HashSet((Set) claMUPSMap.get(cla)); StringWriter st = new StringWriter(); PrintWriter buffer = new PrintWriter(st); cfRend.setWriter(buffer); cfRend.printRepairSOS(mups, cla, false, this); String sosStr = st.toString(); sosStr = sosStr.replaceAll("problem:", "problem: "+swoopModel.shortForm(cla.getURI())); html += "<font face=\"Verdana\" size=2>"+ sosStr + "<br>"; } html += "</body></html>"; // System.out.println(html); indentPane.setText(html); } catch (Exception ex) { ex.printStackTrace(); } } /* * write logFile for user study */ private void writeLogFile() { try { String fname = "REPAIR-LOG_"+String.valueOf(logCtr)+".txt"; FileWriter fw = new FileWriter(new File(fname)); fw.write(logFile); fw.close(); System.out.println("Wrote Repair Log File: "+fname); } catch (IOException e1) { e1.printStackTrace(); } } public void genPlan() { List plans = this.generatePlans(); if (plans.size()>0) { Set mainSolnSet = new HashSet(); mainSolnSet.addAll((List) plans.get(plans.size()-1)); // *** last plan is most optimum *** planSolnAxioms[0] = mainSolnSet; } this.refreshPlan(true); } public void actionPerformed(ActionEvent e) { if (e.getSource() == generateBtn) { genPlan(); } else if (e.getSource() == rankBtn) { if (DEBUG) logFile += NEWLINE + "Recompute RANKS (WA: "+this.w_arityFld.getText()+" WI: "+this.w_impactFld.getText()+" WU: "+this.w_usageFld.getText()+" "+swoopModel.getTimeStamp(); this.refreshRanks(); } else if (e.getSource() == execBtn) { if (DEBUG) logFile += NEWLINE + "EXECUTE Plan "+swoopModel.getTimeStamp(); executePlan(); // ****** write log file here ******* if (DEBUG) this.writeLogFile(); } else if (e.getSource() == clearBtn) { if (DEBUG) logFile += NEWLINE + "CLEAR Plan "+swoopModel.getTimeStamp(); planSolnAxioms[0] = new HashSet(); this.refreshPlan(); } else if (e.getSource() == saveBtn) { // save plan in a new tab if (DEBUG) logFile += NEWLINE + "SAVE Plan "+swoopModel.getTimeStamp(); JEditorPane copyPane = new JEditorPane(); copyPane.setEditable(false); copyPane.setContentType("text/html"); copyPane.addHyperlinkListener(this); planCtr = planTabs.getTabCount()+1; Set copySoln = new HashSet(planSolnAxioms[0]); planSolnAxioms[planCtr-1] = copySoln; this.setCopyPaneText(copyPane, copySoln); planTabs.add("Saved Plan "+String.valueOf(planCtr), copyPane); } else if (e.getSource() == previewBtn) { if (DEBUG) logFile += NEWLINE + "PREVIEW Plan "+swoopModel.getTimeStamp(); this.previewEffect(false); } else if (e.getSource() == rewriteChk) { this.rewriteEnabled = rewriteChk.isSelected(); if (planSolnAxioms[0].size()>0 && this.updatePlanChk.isSelected()) { this.genPlan(); } } else if (e.getSource() == viewGlobalChk) { this.viewGlobal = viewGlobalChk.isSelected(); // indentPane.setVisible(!viewGlobal); if (viewGlobal) axiomTablePane.setDividerLocation(1000); else { axiomTablePane.setDividerLocation(0); this.refreshIndentPane(); indentPane.setCaretPosition(0); } } else if (e.getSource() == keptBtn) { keptFrame.setVisible(true); } else if (e.getSource() == removedBtn) { removedFrame.setVisible(true); } else if (e.getSource() == impactUnsatChk) { this.enableImpactUnsat = impactUnsatChk.isSelected(); this.axiomSOSMap.clear(); this.rankBtn.doClick(); } } /* * preview effect of executing current repair plan */ private String previewEffect(boolean concise) { String html = ""; int num = 0; String title = planTabs.getTitleAt(planTabs.getSelectedIndex()); if (title.indexOf("Main")==-1) num = Integer.parseInt(title.substring(title.lastIndexOf(" ")+1), title.length())-1; Set soln = planSolnAxioms[num]; OWLOntology copyOnt = swoopModel.cloneOntology(ontology); try { OWLOntBuilder ob = new OWLOntBuilder(copyOnt); ob.addAxiom = false; for (Iterator iter = soln.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); axiom.accept(ob); } // also consider rewrites! ob.addAxiom = true; for (Iterator iter = rewriteAxiomSet.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); axiom.accept(ob); } copyOnt = ob.currentOnt; PelletReasoner newPellet = new PelletReasoner(); newPellet.setOntology(copyOnt); Set copyUnsat = new HashSet(currUnsat); Set newUnsat = newPellet.equivalentClassesOf(copyOnt.getOWLDataFactory().getOWLNothing()); copyUnsat.removeAll(newUnsat); if (!concise) html = "<head><body>"+insFont(); else html += "PREVIEW:<br>"; html += "<b>Unsatisfiable</b> "; if (!concise) html += "<br>"; html += "Fixed:"+String.valueOf(copyUnsat.size())+" "; if (!concise) { for (Iterator iter = copyUnsat.iterator(); iter.hasNext();) { OWLClass cla = (OWLClass) iter.next(); html += " <a href=\""+cla.getURI()+"\">"+swoopModel.shortForm(cla.getURI())+"</a> "; } html += "<br><br>"; } html += "Remaining:" + String.valueOf(newUnsat.size())+" "; if (!concise) { for (Iterator iter = newUnsat.iterator(); iter.hasNext();) { OWLClass cla = (OWLClass) iter.next(); html += " <a href=\""+cla.getURI()+"\">"+swoopModel.shortForm(cla.getURI())+"</a>"; } } // JOptionPane.showMessageDialog(this, "Unsatisfiable Concepts Fixed: "+new JScrollPane(list1)+" Remaining: "+newUnsat.size(), "Preview Solution", JOptionPane.INFORMATION_MESSAGE); //*************************************************** // also preview cumulative impact Set entail = new HashSet(); for (Iterator iter = planSolnAxioms[0].iterator(); iter.hasNext();) { OWLObject ax = (OWLObject) iter.next(); if (axiomSOSMap.containsKey(ax)) { Set sos = (HashSet) axiomSOSMap.get(ax); entail.addAll(sos); } } // now compute lost entailments Set lost = new HashSet(); EntailmentChecker chk = new EntailmentChecker(newPellet, copyOnt); for (Iterator iter = entail.iterator(); iter.hasNext();) { OWLObject ent = (OWLObject) iter.next(); if (!chk.isEntailed(ent)) { lost.add(ent); } } entail.removeAll(lost); // also compute special case entailments retained // check equivalence between unsatisfiable concepts just turned satisfiable OWLClass[] list = new OWLClass[copyUnsat.size()]; int ctr = -1; for (Iterator iter = copyUnsat.iterator(); iter.hasNext();) { list[++ctr] = (OWLClass) iter.next(); } for (int i=0; i<ctr-1; i++) { for (int j = i+1; j<ctr; j++) { OWLClass cla1 = list[i]; OWLClass cla2 = list[j]; Set s = new HashSet(); s.add(cla1); s.add(cla2); OWLClassAxiom ax = ontology.getOWLDataFactory().getOWLEquivalentClassesAxiom(s); if (chk.isEntailed(ax)) { entail.add(ax); } // ax = ontology.getOWLDataFactory().getOWLSubClassAxiom(cla1, cla2); // if (chk.isEntailed(ax)) { // entail.add(ax); // } // ax = ontology.getOWLDataFactory().getOWLSubClassAxiom(cla2, cla1); // if (chk.isEntailed(ax)) { // entail.add(ax); // } } } // also check retaining of extended impact for (Iterator iter = axiomSOSMap.keySet().iterator(); iter.hasNext();) { OWLObject ax = (OWLObject) iter.next(); for (Iterator iter2= ((HashSet) axiomSOSMap.get(ax)).iterator(); iter2.hasNext();) { OWLObject ent = (OWLObject) iter2.next(); if (chk.isEntailed(ent)) { entail.add(ent); } } } // finally print if (!concise) html += "<hr>"+insFont(); else html += "<br>"; html += "<b>Entailments</b>"; if (concise) { html += " Lost: "+String.valueOf(lost.size())+" Retained: "+String.valueOf(entail.size()); } else { swoopModel.repairColor = true; swoopModel.repairSet = new HashSet(currUnsat); html += "<br>Lost:"; for (Iterator iter = lost.iterator(); iter.hasNext();) { OWLObject ax = (OWLObject) iter.next(); html += "<br>"+getOWLObjectHTML(ax); if (whyMap.containsKey(ax)) { this.hcodeAxiomMap.put(String.valueOf(ax.hashCode()), ax); html += "  (<a href=\":WHY:"+ax.hashCode()+"\">Why?</a>)"; } } html += "<br><br>Retained:"; for (Iterator iter = entail.iterator(); iter.hasNext();) { OWLObject ax = (OWLObject) iter.next(); html += "<br>"+getOWLObjectHTML(ax); if (whyMap.containsKey(ax)) { this.hcodeAxiomMap.put(String.valueOf(ax.hashCode()), ax); html += "  (<a href=\":WHY:"+ax.hashCode()+"\">Why?</a>)"; } } swoopModel.repairColor = false; swoopModel.repairSet = new HashSet(); } if (!concise) this.displayPopup(html, "Preview Effect of Repair Solution", 600, 400); } catch (OWLException ex) { ex.printStackTrace(); } return html; } /* * execute current repair plan */ private void executePlan() { try { // execute / apply current solution int num = 0; String title = planTabs.getTitleAt(planTabs.getSelectedIndex()); if (title.indexOf("Main")==-1) num = Integer.parseInt(title.substring(title.lastIndexOf(" ")+1), title.length())-1; Set soln = new HashSet(planSolnAxioms[num]); OWLOntBuilder ob = new OWLOntBuilder(ontology); ob.addAxiom = false; for (Iterator iter = soln.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); axiom.accept(ob); // also remove axiom from forced axiom set or blocked axiom set this.removedAxiomSet.remove(axiom); this.keptAxiomSet.remove(axiom); } // add rewritten axioms ob.addAxiom = true; for (Iterator iter = rewriteAxiomSet.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); axiom.accept(ob); } List changes = new ArrayList(ob.changes); swoopModel.addCommittedChanges(changes); ontology = ob.currentOnt; pellet.setOntology(ontology); swoopModel.clearCaches(ontology); // *** KEY CHANGE *** this.launch(); this.repaint(); if (this.updatePlanChk.isSelected()) { this.genPlan(); this.refreshPlan(); } } catch (OWLException ex) { ex.printStackTrace(); } } /* * recompute ranks when user changes weights of parameters */ private void refreshRanks() { double ari = Double.parseDouble(w_arityFld.getText()); double imp = Double.parseDouble(w_impactFld.getText()); double usa = Double.parseDouble(w_usageFld.getText()); this.setWeights(ari, imp, usa); this.computeRanks(axiomUnsatClaMap.keySet()); this.sortAndDisplayAxioms(CURR_METRIC); this.refreshIndentPane(); } /* * Load locally saved hashmap for SOS */ private void loadImpactSOSFile() { try { ObjectInputStream in = new ObjectInputStream(new FileInputStream("axiomSOSMap")); axiomSOSMap = (HashMap) in.readObject(); in.close(); } catch (Exception ex) { ex.printStackTrace(); } } /* * Save axiomSOSMap to disk */ private void saveImpactSOSFile(HashMap axiomSOSMap) { try { System.out.println("Saving file axiomSOSMap"); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("axiomSOSMap")); out.writeObject(axiomSOSMap); out.close(); System.out.println("SOS computed and stored"); } catch (Exception ex) { ex.printStackTrace(); } } /* * Compute SOS for all entailments..store in hashMap (and save locally?) */ private void computeImpactSOS() { try { System.out.println("Computing SOS for each relation.."); axiomSOSMap = new HashMap(); for (Iterator iter = ontology.getClasses().iterator(); iter.hasNext();) { OWLClass cla = (OWLClass) iter.next(); if (!pellet.isConsistent(cla)) continue; // get SOS for each superclass Set sup = pellet.superClassesOf(cla); System.out.println("For class: "+cla); for (Iterator iter2 = SetUtils.union(sup).iterator(); iter2.hasNext();) { OWLClass supCla = (OWLClass) iter2.next(); System.out.println("For superclass: "+supCla); OWLDescription notSupCla = ontology.getOWLDataFactory().getOWLNot(supCla); Set andSet = new HashSet(); andSet.add(cla); andSet.add(notSupCla); OWLDescription desc = ontology.getOWLDataFactory().getOWLAnd(andSet); OWLSubClassAxiom ax = ontology.getOWLDataFactory().getOWLSubClassAxiom(cla, supCla); this.findMUPS(desc, ax); } // get SOS for each disjoint Set disj = pellet.disjointClassesOf(cla); for (Iterator iter2 = SetUtils.union(disj).iterator(); iter2.hasNext();) { OWLClass disjCla = (OWLClass) iter2.next(); System.out.println("For disjoint: "+disjCla); // get SOS for relationship Set andSet = new HashSet(); andSet.add(cla); andSet.add(disjCla); OWLDescription desc = ontology.getOWLDataFactory().getOWLAnd(andSet); OWLDisjointClassesAxiom ax = ontology.getOWLDataFactory().getOWLDisjointClassesAxiom(andSet); this.findMUPS(desc, ax); } } // save axiomSOSMap to file // this.saveImpactSOSFile(axiomSOSMap); } catch (Exception ex) { ex.printStackTrace(); } } public boolean isURI(String str) { try { new URI(str); } catch (Exception ex) { return false; } return true; } /* * TESTING PURPOSES ONLY * Modify all equivalences in the ontology to subclass */ // private void modifyEquivalence() { // // rewrite all equivalences into one direction subclasses // try { // List changes = new ArrayList(); // for (Iterator iter = ontology.getClasses().iterator(); iter.hasNext();) { // OWLClass cla = (OWLClass) iter.next(); // for (Iterator iter2 = cla.getEquivalentClasses(ontology).iterator(); iter2.hasNext();) { // OWLDescription equ = (OWLDescription) iter2.next(); // if (!(equ instanceof OWLClass)) { // RemoveEquivalentClass rem = new RemoveEquivalentClass(ontology, cla, equ, null); // changes.add(rem); // AddSuperClass add = new AddSuperClass(ontology, cla, equ, null); // changes.add(add); // } // } // } // System.out.println("***** changes to equivalence: "+changes.size()); // for (Iterator iter = changes.iterator(); iter.hasNext();) { // OntologyChange oc = (OntologyChange) iter.next(); // oc.accept((ChangeVisitor) ontology); // } // // save locally // CorrectedRDFRenderer rdfRend = new CorrectedRDFRenderer(); // StringWriter st = new StringWriter(); // rdfRend.renderOntology(ontology, null, st); // FileWriter fw = new FileWriter(new File("tambis-MOD.owl")); // fw.write(st.toString()); // fw.close(); // } // catch (Exception ex) { // ex.printStackTrace(); // } // } private double calculateRank(double arity, double impact, double usage) { double rank = 0 ; if (weights[ARITY]!=0) rank = - (weights[ARITY]) * arity; rank += weights[IMPACT] * impact; rank += weights[USAGE] * usage; return rank; } /* * Use Modified Reiter's Hitting Set to generate repair plans * based on axiom ranks */ private List generatePlans() { List plans = new ArrayList(); // also rewrite axioms set rewriteAxiomSet = new HashSet(); try { if (this.granularityCombo.getSelectedIndex() == 0) { if (DEBUG) logFile += NEWLINE + "Generate Plans: ALL UNSAT. "+swoopModel.getTimeStamp(); // plan to fix all unsat. classes List soln = new ArrayList(); // backup everything OWLOntology copy = swoopModel.cloneOntology(ontology); HashMap temp1 = new HashMap(this.axiomUnsatClaMap); HashMap temp2 = new HashMap(this.claMUPSMap); Set temp3 = new HashSet(currRoots); Set temp4 = new HashSet(this.removedAxiomSet); Set temp5 = new HashSet(this.keptAxiomSet); Set rootMUPS = this.findRootsMUPS(); // iteratively fix all roots while (!rootMUPS.isEmpty()) { // get intermediate soln for all roots List pl = this.solveUsingHST(rootMUPS); if (pl.size()>0) { // remove all axioms in intermediate soln from ontology OWLOntBuilder ob = new OWLOntBuilder(copy); ob.addAxiom = false; for (Iterator iter = ((List) pl.get(pl.size()-1)).iterator(); iter.hasNext();) { // *** last plan is most optimum *** OWLObject solAxiom = (OWLObject) iter.next(); this.removedAxiomSet.remove(solAxiom); this.keptAxiomSet.remove(solAxiom); soln.add(solAxiom); solAxiom.accept(ob); } // pass new ontology into pellet copy = ob.currentOnt; pellet.setOntology(copy); rootMUPS.clear(); // temp store maps and then clear them this.axiomUnsatClaMap.clear(); this.claMUPSMap.clear(); // get new roots pellet.autoRootDiscovery(); if (pellet.depFinder == null) { break; } this.currRoots = new HashSet(pellet.depFinder.rootClasses); this.refreshPelletDebuggerOntology(copy); // needed for MUPS rootMUPS = this.findRootsMUPS(); // this.computeImpactSOS(); //EITHER USE THIS OR LINE BELOW // this.loadImpactSOSFile(); this.computeRanks(this.axiomUnsatClaMap.keySet()); } else { // something funky JOptionPane.showMessageDialog(this, "ERROR: Cannot find a complete plan", "Repair Plan", JOptionPane.ERROR_MESSAGE); System.out.println("ERROR: Cannot find a complete plan"); plans.add(soln); return plans; } } // end while loop // restore all maps (from temp) // this.ontology = swoopModel.cloneOntology(copy); this.axiomUnsatClaMap = new HashMap(temp1); this.claMUPSMap = new HashMap(temp2); this.currRoots = new HashSet(temp3); this.removedAxiomSet = new HashSet(temp4); this.keptAxiomSet = new HashSet(temp5); this.refreshPelletDebuggerOntology(ontology); pellet.setOntology(ontology); plans.add(soln); } else if (this.granularityCombo.getSelectedIndex() == 1) { // plan to fix all roots if (DEBUG) logFile += NEWLINE + "Generate Plans: ALL ROOTS "+swoopModel.getTimeStamp(); Set rootMUPS = this.findRootsMUPS(); plans = this.solveUsingHST(rootMUPS); } else if (this.granularityCombo.getSelectedIndex() == 2) { if (DEBUG) logFile += NEWLINE + "Generate Plans: SELECTED "+swoopModel.getTimeStamp(); // plan to fix selected classes alone Set mups = new HashSet(); for (int i = 0; i<classList.getSelectedValues().length; i++) { mups.add(this.claMUPSMap.get(classList.getSelectedValues()[i])); } plans = this.solveUsingHST(mups); } } catch (Exception ex) { ex.printStackTrace(); } return plans; } /* * Given a set of MUPS, return all minimal hitting sets * i.e. each HS contains a set of axioms that touch all mups * (optimization criteria: ranks as specified in axiomRanksMap) */ private List solveUsingHST(Set mups) { List plans = new ArrayList(); // remove all sets from mups that contain any of the forced axioms Set copyMups = new HashSet(mups); for (Iterator iter = removedAxiomSet.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); for (Iterator iter2=mups.iterator(); iter2.hasNext();) { Set m = (HashSet) iter2.next(); if (m.contains(axiom)) copyMups.remove(m); } } mups = copyMups; if (mups.isEmpty()) { List path = new ArrayList(this.removedAxiomSet); plans.add(path); return plans; } // select any random mups as root of HST Set root = (HashSet) mups.iterator().next(); // any random MUPS // order axioms and add to stack List stack = new ArrayList(); stack.addAll(orderAxioms(root)); // initialize all other variables before proceeding to main loop List path = new ArrayList(); double optimum = 1000; // some high value (upper bound) while (stack.size()!=0) { // always: last item on stack (i.e. tail of list) needs to be popped next OWLObject axiom = (OWLObject) stack.get(stack.size()-1); stack.remove(axiom); // when explored all options with this immediate edge from root // remove edge and proceed to next edge if (path.contains(axiom)) { path.remove(axiom); continue; } path.add(axiom); double pr = pathRank(path); // early path termination (check if it already exceeds optimum) if (pr >= optimum) { // remove from stack and backtrack path.remove(axiom); continue; } // special case: check for blocked axioms if (keptAxiomSet.contains(axiom)) { path.remove(axiom); continue; } // check if path is a Hitting Set (HS) Set left = checkPathHS(path, mups); if (left.isEmpty()) { // found new optimum path (plan) //TODO actually compute cumulative impact..hence new path rank // check if path contains manualAxioms // if (forceAxiomSet.isEmpty() || path.containsAll(forceAxiomSet)) { optimum = pr; path.addAll(new HashSet(this.removedAxiomSet)); plans.add(new ArrayList(path)); // } path.remove(axiom); } else { // found new node to add to HST stack.add(axiom); stack.addAll(orderAxioms(left)); } } return plans; } /* * Order axioms in a MUPS such that lowest ranked axioms are at the tail of the list */ private List orderAxioms(Set mups) { List m = new ArrayList(mups); OWLObject ordered[] = new OWLObject[m.size()]; int ord = 0; for (Iterator iter = m.iterator(); iter.hasNext();) ordered[ord++] = (OWLObject) iter.next(); for (int i=0; i < m.size()-1; i++) { OWLObject a = ordered[i]; //(OWLObject) m.get(i); for (int j=i+1; j < m.size(); j++) { OWLObject b = ordered[j]; //(OWLObject) m.get(j); double rankA = -1; double rankB = -1; if (axiomRanksMap.containsKey(a)) rankA = Double.parseDouble(axiomRanksMap.get(a).toString()); if (axiomRanksMap.containsKey(b)) rankB = Double.parseDouble(axiomRanksMap.get(b).toString()); if (rankA < rankB) { // swap a, b in ordered OWLObject temp = ordered[j]; ordered[j] = ordered[i]; ordered[i] = temp; } } } List result = new ArrayList(); for (int ctr = 0; ctr < ordered.length; ctr++) result.add(ordered[ctr]); return result; } /* * Check if a path of axioms is a Hitting Set (HS) for a collection of MUPS */ private Set checkPathHS(List path, Set allMUPS) { for (Iterator iter = allMUPS.iterator(); iter.hasNext();) { Set mups = (HashSet) iter.next(); boolean hit = false; for (Iterator iter2 = path.iterator(); iter2.hasNext();) { OWLObject axiom = (OWLObject) iter2.next(); if (mups.contains(axiom)) { hit = true; break; } } if (!hit) return mups; } return new HashSet(); // path is a HS } // /* // * Return the minRanked axiom from a given axiom set // */ // private OWLObject minRankedAxiom(Set axioms) { // double min = 100; // OWLObject minAxiom = null; // for (Iterator iter = axioms.iterator(); iter.hasNext();) { // OWLObject axiom = (OWLObject) iter.next(); // if (axiomRanksMap.containsKey(axiom)) { // double rank = Double.parseDouble(axiomRanksMap.get(axiom).toString()); // if (rank < min) { // min = rank; // minAxiom = axiom; // } // } // } // return minAxiom; // } public double pathRank(List path) { double pr = 0; for (Iterator iter = path.iterator(); iter.hasNext();) { OWLObject axiom = (OWLObject) iter.next(); if (axiomRanksMap.containsKey(axiom)) pr += Double.parseDouble(axiomRanksMap.get(axiom).toString()); } return pr; } /* * Compute impact (of removing axioms) on entailments related to unsatisfiable classes: * Brute Force: Given list of unsat classes and axioms in sos of each class, * generate a repair plan, compute entailments between previously * unsatisfiable classes, for each entailment, compute sos * and see if earlier axiom falls in this sos * Hueristic: inferredDependencyDetection */ private void computeImpactUnsat() { turnOffUsage = true; try { // using alternate method infDepDetection: remove disjoint axioms OWLOntology copy = swoopModel.cloneOntology(ontology); for (Iterator iter = new HashSet(copy.getClassAxioms()).iterator(); iter.hasNext();) { OWLClassAxiom axiom = (OWLClassAxiom) iter.next(); if (axiom instanceof OWLDisjointClassesAxiom) { OWLDisjointClassesAxiom dis = (OWLDisjointClassesAxiom) axiom; // check that dis contains atleast one root, otherwise dont remove it boolean check = true; //false; // for (Iterator iter2 = currRoots.iterator(); iter2.hasNext();) { // OWLClass root = (OWLClass) iter2.next(); // if (dis.getDisjointClasses().contains(root)) { // check = true; // break; // } // } if (check) { // remove disjoint axiom RemoveClassAxiom rem = new RemoveClassAxiom(copy, dis, null); rem.accept((ChangeVisitor) copy); } } } // now check for subsumption between unsatisfiable classes OWLDataFactory copyDF = copy.getOWLDataFactory(); OWLClass thing = copyDF.getOWLThing(); PelletReasoner pellet = new PelletReasoner(); pellet.setOntology(copy); // *** key step next to get correct MUPS (becos of call to findMUPS below) pelletDebug.setOntology(copy); // *** end of key step for (Iterator iter = currRoots.iterator(); iter.hasNext();) { OWLClass root = (OWLClass) iter.next(); if (pellet.isConsistent(root)) { // check equivalence to thing? if (pellet.equivalentClassesOf(thing).contains(root)) { OWLNot not = copyDF.getOWLNot(root); Set and = new HashSet(); and.add(not); and.add(thing); OWLAnd test = copyDF.getOWLAnd(and); Set equ = new HashSet(); equ.add(root); equ.add(thing); OWLEquivalentClassesAxiom ax = copyDF.getOWLEquivalentClassesAxiom(equ); System.out.println("checking equivalence between owl:Thing and " + swoopModel.shortForm(root.getURI())); this.findMUPS(test, ax); } else { for (Iterator iter2 = pellet.equivalentClassesOf(root).iterator(); iter2.hasNext();) { OWLClass equCla = (OWLClass) iter2.next(); // if (currRoots.contains(equCla)) { Set op1 = new HashSet(); OWLNot not1 = copyDF.getOWLNot(root); op1.add(equCla); op1.add(not1); OWLAnd t1 = copyDF.getOWLAnd(op1); Set op2 = new HashSet(); OWLNot not2 = copyDF.getOWLNot(equCla); op2.add(not2); op2.add(root); OWLAnd t2 = copyDF.getOWLAnd(op2); Set or = new HashSet(); or.add(t1); or.add(t2); OWLOr test = copyDF.getOWLOr(or); Set equ = new HashSet(); equ.add(root); equ.add(equCla); OWLEquivalentClassesAxiom ax = copyDF.getOWLEquivalentClassesAxiom(equ); System.out.println("check equivalence between " + swoopModel.shortForm(root.getURI()) + " and "+swoopModel.shortForm(equCla.getURI())); this.findMUPS(test, ax); // } } for (Iterator iter2 = SetUtils.union(pellet.ancestorClassesOf(root)).iterator(); iter2.hasNext();) { OWLClass supCla = (OWLClass) iter2.next(); // if (currRoots.contains(supCla)) { if (!pellet.equivalentClassesOf(thing).contains(supCla) && !supCla.equals(thing)) { Set op2 = new HashSet(); OWLNot not2 = copyDF.getOWLNot(supCla); op2.add(not2); op2.add(root); OWLAnd test = copyDF.getOWLAnd(op2); OWLSubClassAxiom ax = copyDF.getOWLSubClassAxiom(root, supCla); System.out.println("check subclass between " + swoopModel.shortForm(root.getURI()) + " and "+swoopModel.shortForm(supCla.getURI())); this.findMUPS(test, ax); } // } } } } } } catch (OWLException ex) { ex.printStackTrace(); } finally { turnOffUsage = false; try { // reset this after findMUPS has been called above pelletDebug.setOntology(ontology); } catch (OWLException e) { e.printStackTrace(); } } } public void itemStateChanged(ItemEvent e) { if (e.getSource() == granularityCombo && updatePlanChk.isSelected()) { this.genPlan(); this.refreshPlan(); } } }