/** * Given an checker and a set of explanations this method determines how many explanations * contain the checker. * * @param ax The checker that will be counted. * @param axiomSets The explanations to count from * @return the number of occurrences of the specified checker in the explanation */ protected static <E> int getOccurrences(OWLAxiom ax, Set<Explanation<E>> axiomSets) { int count = 0; for (Explanation<E> explanation : axiomSets) { if (explanation.getAxioms().contains(ax)) { count++; } } return count; }
@Override public int compare(Explanation<E> o1, Explanation<E> o2) { if(o1.equals(o2)) { return 0; } int size1 = o1.getAxioms().size(); int size2 = o1.getAxioms().size(); // We want the smallest one to come first int sizeDifference = size2 - size1; if(sizeDifference != 0) { return sizeDifference; } // Same size // Now we would prefer ones that contained return -1; } }
private Set<ClassExpressionType> getClassExpressionTypes(Explanation<OWLAxiom> explanation) { Set<ClassExpressionType> result = new HashSet<>(); for (OWLAxiom ax : explanation.getAxioms()) { result.addAll(ax.getNestedClassExpressions().stream() .map(OWLClassExpression::getClassExpressionType) .collect(Collectors.toList())); } return result; }
private static Set<OWLAxiom> getSourceAxioms(Explanation<OWLAxiom> expl, OPlusGenerator oPlusGenerator) { Set<OWLAxiom> result = new HashSet<>(); for (OWLAxiom ax : expl.getAxioms()) { Set<OWLAxiom> sourceAxioms = oPlusGenerator.getAxiom2SourceMap().get(ax); if (sourceAxioms != null) { result.addAll(sourceAxioms); } } return result; }
private static Set<OWLAxiom> getSourceAxioms(Explanation<OWLAxiom> expl, OPlusGenerator oPlusGenerator) { Set<OWLAxiom> result = new HashSet<>(); for (OWLAxiom ax : expl.getAxioms()) { Set<OWLAxiom> sourceAxioms = oPlusGenerator.getAxiom2SourceMap().get(ax); if (sourceAxioms != null) { result.addAll(sourceAxioms); } } return result; }
private Set<AxiomType<?>> getAxiomTypes(Explanation<OWLAxiom> explanation) { Set<AxiomType<?>> result = new HashSet<>(); for (OWLAxiom ax : explanation.getAxioms()) { result.add(ax.getAxiomType()); } return result; }
private static Set<OWLAxiom> getSourceAxioms(Explanation<OWLAxiom> expl, OPlusGenerator oPlusGenerator) { Set<OWLAxiom> result = new HashSet<>(); for(OWLAxiom ax : expl.getAxioms()) { Set<OWLAxiom> sourceAxioms = oPlusGenerator.getAxiom2SourceMap().get(ax); if (sourceAxioms != null) { result.addAll(sourceAxioms); } } return result; }
@Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Explanation)) { return false; } Explanation<?> other = (Explanation<?>) obj; return other.getEntailment().equals(entailment) && other.getAxioms().equals(justification); }
public int getIndentation(Explanation<?> explanation, OWLAxiom axiom) { if(!explanation.getAxioms().contains(axiom) && !explanation.getEntailment().equals(axiom)) { throw new IllegalArgumentException("The explanation does not contain the specified axiom: " + axiom + " " + explanation); } initIfNecessary(explanation); Integer i = indentMap.get(explanation).get(axiom); if(i != null) { return i; } else { return 0; } }
@Override public Explanation<E> generateExplanation(E entailment) { for (Explanation<E> expl : cache) { if (expl.getEntailment().equals(entailment) && module.containsAll(expl.getAxioms())) { cacheHitCounter++; return expl; } } Explanation<E> expl = computeExplanation(entailment); if (!expl.isEmpty()) { cache.add(expl); } return expl; }
private static void removeWeakerExplanations(OWLDataFactory dataFactory, OPlusGenerator transformation, Set<Explanation<OWLAxiom>> laconicExplanations) { for(Explanation<OWLAxiom> explA : new ArrayList<>(laconicExplanations)) { for(Explanation<OWLAxiom> explB : new ArrayList<>(laconicExplanations)) { if(explA != explB && laconicExplanations.contains(explA) && laconicExplanations.contains(explB)) { Set<OWLAxiom> sourceAxiomsA = getSourceAxioms(explA, transformation); Set<OWLAxiom> sourceAxiomsB = getSourceAxioms(explB, transformation); OPlusGenerator gen2 = new OPlusGenerator(dataFactory, OPlusSplitting.NONE); Set<OWLAxiom> oPlusA = gen2.transform(explA.getAxioms()); Set<OWLAxiom> oPlusB = gen2.transform(explB.getAxioms()); if(oPlusA.containsAll(oPlusB) && sourceAxiomsA.containsAll(sourceAxiomsB)) { // We can get B from A laconicExplanations.remove(explB); } else if(oPlusB.containsAll(oPlusA) && sourceAxiomsB.containsAll(sourceAxiomsA)) { // A is weaker than B laconicExplanations.remove(explA); } } } } }
private void init(Explanation<?> explanation) { ExplanationOrderer orderer = new ProtegeExplanationOrderer(OWLManager.createOWLOntologyManager()); ExplanationTree tree = orderer.getOrderedExplanation((OWLAxiom) explanation.getEntailment(), explanation.getAxioms()); List<OWLAxiom> ordering = new ArrayList<>(); Map<OWLAxiom, Integer> im = new HashMap<>(); fill(tree, ordering, im); indentMap.put(explanation, im); orderingMap.put(explanation, ordering); }
/** * Checks to see if a justification for a given entailment is laconic. * @param justification The justification to be checked * @return <code>true</code> if the justification is laconic, otherwise <code>false</code> * @throws ExplanationException If there was a problem. The details of this are implementation specific. */ public boolean isLaconic(Explanation<E> justification) throws ExplanationException { // OBSERVATION: If a justification is laconic, then given its O+, there should be // one justification that is equal to itself. // Could optimise more here - we know that a laconic justification won't contain // equivalent classes axioms, inverse properties axioms etc. If an checker doesn't // appear in O+ then it's not laconic! Set<OWLAxiom> justificationSigmaClosure = computeOPlus(justification.getAxioms()); ExplanationGenerator<E> gen2 = explanationGeneratorFactory.createExplanationGenerator(justificationSigmaClosure); Set<Explanation<E>> exps = gen2.getExplanations(justification.getEntailment(), 2); return Collections.singleton(justification).equals(exps); }
@Override public boolean isMaskingPresent(Explanation<OWLAxiom> explanation) { OWLDataFactory dataFactory = manager.getOWLDataFactory(); StructuralTransformation st = new StructuralTransformation(dataFactory); Set<OWLAxiom> axioms = st.getTransformedAxioms(explanation.getAxioms()); ExplanationGenerator<OWLAxiom> expGen = expGenFac.createExplanationGenerator(axioms); Set<Explanation<OWLAxiom>> expls = expGen.getExplanations(explanation.getEntailment()); return expls.size() > 1; } }
/** * Stores the specified explanation to the specified output stream * @param explanation The explanation to be stored * @param os The output stream to store the explanation to * @throws IOException if there was a problem writing out the explanation */ public static void store(Explanation<OWLAxiom> explanation, OutputStream os, Supplier<OWLOntologyManager> m) throws IOException { try { OWLOntology ontology = m.get().createOntology(explanation.getAxioms()); OWLDataFactory df = ontology.getOWLOntologyManager().getOWLDataFactory(); OWLAnnotationProperty entailmentMarkerAnnotationProperty = df.getOWLAnnotationProperty(ENTAILMENT_MARKER_IRI); OWLAnnotation entailmentAnnotation = df.getOWLAnnotation(entailmentMarkerAnnotationProperty, df.getOWLLiteral(true)); OWLAxiom annotatedEntailment = explanation.getEntailment().getAnnotatedAxiom(Collections.singleton(entailmentAnnotation)); ontology.add(annotatedEntailment); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(os); OWLXMLDocumentFormat justificationOntologyFormat = new OWLXMLDocumentFormat(); ontology.saveOntology(justificationOntologyFormat, bufferedOutputStream); bufferedOutputStream.flush(); } catch (OWLOntologyStorageException | OWLOntologyCreationException e) { throw new RuntimeException(e); } }
/** * Render an Explanation object as Markdown text, linking text labels to term IRIs and indenting * axioms. * * @param explanation explanation to render * @param manager OWLOntologyManager containing source ontologies for explanation axioms * @return Markdown-formatted explanation text */ public static String renderExplanationAsMarkdown( Explanation<OWLAxiom> explanation, OWLOntologyManager manager) { ExplanationOrderer orderer = new ProtegeExplanationOrderer(manager); ExplanationTree tree = orderer.getOrderedExplanation(explanation.getEntailment(), explanation.getAxioms()); ShortFormProvider labelProvider = new AnnotationValueShortFormProvider( Collections.singletonList(OWLManager.getOWLDataFactory().getRDFSLabel()), Collections.emptyMap(), manager); ShortFormProvider linkProvider = new MarkdownLinkShortFormProvider(labelProvider); ManchesterOWLSyntaxOWLObjectRendererImpl axiomRenderer = new ManchesterOWLSyntaxOWLObjectRendererImpl(); axiomRenderer.setShortFormProvider(linkProvider); return renderTree(tree, axiomRenderer); }
private Set<Explanation<OWLAxiom>> computeLaconicExplanations(Explanation<OWLAxiom> explanation, int limit) throws ExplanationException { try { if(modelManager.getReasoner().isConsistent()) { OWLReasonerFactory rf = getReasonerFactory(); ExplanationGenerator<OWLAxiom> g = org.semanticweb.owl.explanation.api.ExplanationManager.createLaconicExplanationGeneratorFactory(rf).createExplanationGenerator(explanation.getAxioms()); return g.getExplanations(explanation.getEntailment(), limit); } else { OWLReasonerFactory rf = getReasonerFactory(); InconsistentOntologyExplanationGeneratorFactory fac = new InconsistentOntologyExplanationGeneratorFactory(rf, Long.MAX_VALUE); LaconicExplanationGeneratorFactory<OWLAxiom> lacFac = new LaconicExplanationGeneratorFactory<>(fac); ExplanationGenerator<OWLAxiom> g = lacFac.createExplanationGenerator(explanation.getAxioms()); return g.getExplanations(explanation.getEntailment(), limit); } } catch (ExplanationException e) { throw new ExplanationException(e); } }
public void buildHittingSetTree(HittingSetTree<E> hittingSetTree, int limit, ExplanationGeneratorMediator<E> handler, HittingSetTreeNode<E> currentNode) { for (OWLAxiom ax : currentNode.getExplanation().getAxioms()) { handler.removeAxiom(ax); Set<OWLAxiom> pathContents = new HashSet<>(currentNode.getPathToRoot()); pathContents.add(ax); if (hittingSetTree.addExploredPath(pathContents)) { // Look to reuse a justification Explanation<E> expl = getNonIntersectingExplanation(hittingSetTree, pathContents); boolean reuse = true; if (expl == null) { reuse = false; expl = handler.generateExplanation(currentNode.getExplanation().getEntailment()); hittingSetTree.addExplanation(expl); if(hittingSetTree.getExplanations().size() == limit) { return; } } if (!expl.isEmpty()) { HittingSetTreeNode<E> hittingSetTreeNode = new HittingSetTreeNode<>(ax, currentNode, expl, reuse); currentNode.addChild(ax, hittingSetTreeNode); buildHittingSetTree(hittingSetTree, limit, handler, hittingSetTreeNode); } else { hittingSetTree.addClosedPath(new HashSet<>(pathContents)); } } handler.addAxiom(ax); } }
public static void saveExplanationAsOntology(OWLEditorKit editorKit, Explanation<?> explanation) throws OWLOntologyCreationException, OWLOntologyChangeException, OWLOntologyStorageException { File f = UIUtil.saveFile( SwingUtilities.getAncestorOfClass(JFrame.class, editorKit.getWorkspace()), "Save ontology as", "Save justification as ontology", CollectionFactory.createSet("owl", "txt", "rdf"), "justification.owl"); if(f == null) { return; } OWLOntologyManager man = OWLManager.createOWLOntologyManager(); OWLOntology ont = man.createOntology(explanation.getAxioms()); OWLDataFactory df = man.getOWLDataFactory(); IRI annotationIRI = IRI.create("http://owl.cs.manchester.ac.uk/explanation/annotations/inferredAxiom"); String entailmentRendering = editorKit.getOWLModelManager().getRendering((OWLAxiom) explanation.getEntailment()); OWLAnnotationProperty prop = df.getOWLAnnotationProperty(annotationIRI); OWLAnnotation anno = df.getOWLAnnotation(prop, df.getOWLLiteral(entailmentRendering)); man.applyChange(new AddOntologyAnnotation(ont, anno)); man.saveOntology(ont, IRI.create(f)); } }