/******************************************************************************* * This file is part of ecco. * * ecco is distributed under the terms of the GNU Lesser General Public License (LGPL), Version 3.0. * * Copyright 2011-2014, The University of Manchester * * ecco is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * ecco is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with ecco. * If not, see http://www.gnu.org/licenses/. ******************************************************************************/ package uk.ac.manchester.cs.diff.concept; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.semanticweb.owlapi.apibinding.OWLManager; import org.semanticweb.owlapi.model.IRI; import org.semanticweb.owlapi.model.OWLAxiom; import org.semanticweb.owlapi.model.OWLClass; import org.semanticweb.owlapi.model.OWLClassExpression; import org.semanticweb.owlapi.model.OWLEntity; import org.semanticweb.owlapi.model.OWLObjectProperty; import org.semanticweb.owlapi.model.OWLOntology; import org.semanticweb.owlapi.model.OWLOntologyManager; import uk.ac.manchester.cs.diff.concept.changeset.ConceptChangeSet; import uk.ac.manchester.cs.diff.concept.sigma.Signature; import uk.ac.manchester.cs.diff.utils.SilentChangeBroadcastStrategy; /** * @author Rafael S. Goncalves <br> * Information Management Group (IMG) <br> * School of Computer Science <br> * University of Manchester <br> */ public class GrammarDiff extends SubconceptDiff { private OWLOntologyManager man; /** * Constructor for grammar diff w.r.t. sigma := sig(O1) U sig(O2) * @param ont1 Ontology 1 * @param ont2 Ontology 2 * @param verbose Verbose mode */ public GrammarDiff(OWLOntology ont1, OWLOntology ont2, boolean verbose) { super(ont1, ont2, verbose); man = OWLManager.createOWLOntologyManager(); man.setDefaultChangeBroadcastStrategy(new SilentChangeBroadcastStrategy()); } /** * Constructor for grammar diff w.r.t. given signature * @param ont1 Ontology 1 * @param ont2 Ontology 2 * @param sig Signature (set of concept names) * @param verbose Verbose mode */ public GrammarDiff(OWLOntology ont1, OWLOntology ont2, Set<OWLEntity> sig, boolean verbose) { super(ont1, ont2, sig, verbose); man = OWLManager.createOWLOntologyManager(); man.setDefaultChangeBroadcastStrategy(new SilentChangeBroadcastStrategy()); } /** * Get the concept-based change set between the given ontologies * @return Concept-based change set */ public ConceptChangeSet getDiff() { long start = System.currentTimeMillis(); if(verbose) System.out.println("Input signature: sigma contains " + sigma.size() + " terms"); Map<OWLClass,OWLClassExpression> map = getSubConceptsMapping(); classifyOntologies(ont1, ont2); Set<OWLClass> affected = computeChangeWitnesses(map); long mid = System.currentTimeMillis(); // Remove extra axioms and create fresh reasoner instances ont1.getOWLOntologyManager().removeAxioms(ont1, extraAxioms); ont2.getOWLOntologyManager().removeAxioms(ont2, extraAxioms); classifyOntologies(ont1, ont2); changeSet = splitDirectIndirectChanges(affected, ont1reasoner, ont2reasoner); long end = System.currentTimeMillis(); changeSet.setEntailmentDiffTime((mid-start)/1000.0); changeSet.setPartitioningTime((end-mid)/1000.0); if(verbose) printDiff(); System.out.println("finished (total diff time: " + (end-start)/1000.0 + " secs)"); return changeSet; } /** * Create a mapping between a new term "TempX" and each sub-concept, and add the appropriate * equivalence axioms to each ontology * @return Map of new terms to subconcepts */ private Map<OWLClass,OWLClassExpression> getSubConceptsMapping() { Set<OWLObjectProperty> roles = new Signature().getSharedRoles(ont1, ont2); Set<OWLClassExpression> scs = collectSCs(); Map<OWLClass,OWLClassExpression> map = new HashMap<OWLClass,OWLClassExpression>(); // Generate witnesses if(verbose) System.out.println("Inflating ontologies..."); Set<OWLClassExpression> wits = new HashSet<OWLClassExpression>(); wits.addAll(scs); for(OWLEntity e : sigma) { if(e.isOWLClass() && ont1.containsEntityInSignature(e) && ont2.containsEntityInSignature(e)) scs.add(e.asOWLClass()); } wits.addAll(getExistentialWitnesses(scs, roles)); wits.addAll(getUniversalWitnesses(scs, roles)); wits.addAll(getNegationWitnesses(scs)); if(verbose) System.out.println("\tTotal nr. of witnesses: " + wits.size()); // SyntacticLocalityEvaluator eval = new SyntacticLocalityEvaluator(LocalityClass.TOP_BOTTOM); int counter = 1; extraAxioms = new HashSet<OWLAxiom>(); for(OWLClassExpression ce : wits) { OWLClass c = df.getOWLClass(IRI.create("diffSubc_" + counter)); map.put(c, ce); OWLAxiom ax = df.getOWLEquivalentClassesAxiom(c, ce); extraAxioms.add(ax); counter++; } ont1.getOWLOntologyManager().addAxioms(ont1, extraAxioms); ont2.getOWLOntologyManager().addAxioms(ont2, extraAxioms); if(verbose) System.out.println("done (nr. of extra axioms: " + extraAxioms.size() + ")"); return map; } /** * Get the set of possible negation witnesses * @param sc Set of subconcepts * @return Set of negation witnesses */ private Set<OWLClassExpression> getNegationWitnesses(Set<? extends OWLClassExpression> sc) { Set<OWLClassExpression> out = new HashSet<OWLClassExpression>(); for(OWLClassExpression c : sc) out.add(df.getOWLObjectComplementOf(c)); if(verbose) System.out.println("\tNegation witnesses: " + out.size()); return out; } /** * Get the set of possible existential witnesses * @param sc Set of subconcepts * @param roles Set of role names * @return Set of existential witnesses */ private Set<OWLClassExpression> getExistentialWitnesses(Set<? extends OWLClassExpression> sc, Set<OWLObjectProperty> roles) { Set<OWLClassExpression> out = new HashSet<OWLClassExpression>(); for(OWLClassExpression c : sc) { for(OWLObjectProperty r : roles) out.add(df.getOWLObjectSomeValuesFrom(r, c)); } if(verbose) System.out.println("\tExistential witnesses: " + out.size()); return out; } /** * Get the set of possible universal witnesses * @param sc Set of subconcepts * @param roles Set of role names * @return Set of universal witnesses */ private Set<OWLClassExpression> getUniversalWitnesses(Set<? extends OWLClassExpression> sc, Set<OWLObjectProperty> roles) { Set<OWLClassExpression> out = new HashSet<OWLClassExpression>(); for(OWLClassExpression c : sc) { for(OWLObjectProperty r : roles) out.add(df.getOWLObjectAllValuesFrom(r, c)); } if(verbose) System.out.println("\tUniversal witnesses: " + out.size()); return out; } /** * Get the set of conjunction witnesses * @param sc Set of subconcepts within the modules * @return Set of conjunction witnesses */ @SuppressWarnings("unused") private Set<OWLClassExpression> getConjunctionWitnesses(Set<OWLClassExpression> sc) { Set<OWLClassExpression> out = new HashSet<OWLClassExpression>(); OWLClassExpression[] scarr = sc.toArray(new OWLClassExpression[sc.size()]); for(int i = 0; i < sc.size(); i++) { for(int j = i+1; j < sc.size(); j++) out.add(df.getOWLObjectIntersectionOf(scarr[i], scarr[j])); } if(verbose) System.out.println("\tConjunction witnesses: " + out.size()); return out; } /** * Get the set of disjunction witnesses * @param sc Set of subconcepts within the modules * @return Set of disjunction witnesses */ @SuppressWarnings("unused") private Set<OWLClassExpression> getDisjunctionWitnesses(Set<OWLClassExpression> sc) { Set<OWLClassExpression> out = new HashSet<OWLClassExpression>(); OWLClassExpression[] scarr = sc.toArray(new OWLClassExpression[sc.size()]); for(int i = 0; i < sc.size(); i++) { for(int j = i+1; j < sc.size(); j++) out.add(df.getOWLObjectUnionOf(scarr[i], scarr[j])); } if(verbose) System.out.println("\tDisjunction witnesses: " + out.size()); return out; } }