package uk.ac.manchester.cs.jfact.split; /* This file is part of the JFact DL reasoner Copyright 2011-2013 by Ignazio Palmisano, Dmitry Tsarkov, University of Manchester This library 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 2.1 of the License, or (at your option) any later version. This library 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 this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*/ import java.util.Collection; import java.util.List; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomConceptInclusion; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDRoleDomain; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDRoleFunctional; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDRoleRange; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDRoleSubsumption; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDeclaration; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDifferentIndividuals; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDisjointConcepts; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDisjointDRoles; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDisjointORoles; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomDisjointUnion; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomEquivalentConcepts; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomEquivalentDRoles; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomEquivalentORoles; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomFairnessConstraint; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomInstanceOf; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomORoleDomain; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomORoleFunctional; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomORoleRange; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomORoleSubsumption; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRelatedTo; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRelatedToNot; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRoleAsymmetric; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRoleInverse; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRoleInverseFunctional; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRoleIrreflexive; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRoleReflexive; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRoleSymmetric; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomRoleTransitive; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomSameIndividuals; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomValueOf; import uk.ac.manchester.cs.jfact.kernel.dl.axioms.AxiomValueOfNot; import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.AxiomInterface; import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.ConceptExpression; import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.Expression; import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.NAryExpression; import uk.ac.manchester.cs.jfact.visitors.DLAxiomVisitor; import conformance.Original; import conformance.PortedFrom; /** syntactic locality checker for DL axioms */ @PortedFrom(file = "GeneralSyntacticLocalityChecker.h", name = "GeneralSyntacticLocalityChecker") public abstract class GeneralSyntacticLocalityChecker extends SigAccessor implements DLAxiomVisitor, LocalityChecker { private static final long serialVersionUID = 11000L; /** top evaluator */ @PortedFrom(file = "SyntacticLocalityChecker.h", name = "TopEval") protected final TopEquivalenceEvaluator TopEval; /** bottom evaluator */ @PortedFrom(file = "SyntacticLocalityChecker.h", name = "BotEval") protected final BotEquivalenceEvaluator BotEval; /** remember the axiom locality value here */ @PortedFrom(file = "SyntacticLocalityChecker.h", name = "isLocal") protected boolean isLocal; /** * processing method for all Equivalent axioms * * @param axiom * axiom to process * @return true if axiom is local */ @PortedFrom(file = "GeneralSyntacticLocalityChecker.h", name = "processEquivalentAxiom") boolean processEquivalentAxiom( NAryExpression<? extends Expression> axiom) { // 1 element => local if (axiom.size() <= 1) { return true; } // axiom is local iff all the elements are either top- or bot-local List<? extends Expression> list = axiom.getArguments(); if (isBotEquivalent(list.get(0))) { // all should be \bot-eq for (int i = 1; i < list.size(); i++) { if (!isBotEquivalent(list.get(i))) { return false; } } } else if (isTopEquivalent(list.get(0))) { // all should be \top-eq for (int i = 1; i < list.size(); i++) { if (!isTopEquivalent(list.get(i))) { return false; } } } else { // neither \bot- no \top-eq: non-local return false; } // all elements have the same locality return true; } /** * processing method for all Disjoint axioms * * @param axiom * axiom to process * @return true if axiom is local */ @PortedFrom(file = "GeneralSyntacticLocalityChecker.h", name = "processDisjointAxiom") boolean processDisjointAxiom( NAryExpression<? extends Expression> axiom) { // local iff at most 1 element is not bot-equiv boolean hasNBE = false; List<? extends Expression> list = axiom.getArguments(); for (int i = 0; i < list.size(); i++) { if (!isBotEquivalent(list.get(i))) { if (hasNBE) { // already seen one non-bot-eq element // non-local return false; } else { // record that 1 non-bot-eq element was found hasNBE = true; } } } return true; } /** * @param expr * expr * @return true iff EXPR is top equivalent */ @PortedFrom(file = "SyntacticLocalityChecker.h", name = "isTopEquivalent") protected boolean isTopEquivalent(Expression expr) { return TopEval.isTopEquivalent(expr); } /** * @param expr * expr * @return true iff EXPR is bottom equivalent */ @PortedFrom(file = "SyntacticLocalityChecker.h", name = "isBotEquivalent") protected boolean isBotEquivalent(Expression expr) { return BotEval.isBotEquivalent(expr); } /** * @param expr * expr * @return true iff role expression in equivalent to const wrt locality */ @PortedFrom(file = "SyntacticLocalityChecker.h", name = "isREquivalent") private boolean isREquivalent(Expression expr) { return sig.topRLocal() ? isTopEquivalent(expr) : isBotEquivalent(expr); } /** @return true iff an AXIOM is local wrt defined policy */ @Override @PortedFrom(file = "SyntacticLocalityChecker.h", name = "local") public boolean local(AxiomInterface axiom) { axiom.accept(this); return isLocal; } /** set a new value of a signature (without changing a locality parameters) */ @Override @Original public void setSignatureValue(TSignature Sig) { sig = Sig; TopEval.sig = sig; BotEval.sig = sig; } // set fields @Override @Original public void preprocessOntology(Collection<AxiomInterface> s) { sig = new TSignature(); for (AxiomInterface ax : s) { sig.add(ax.getSignature()); } } /** * init c'tor * * @param sig * sig */ public GeneralSyntacticLocalityChecker(TSignature sig) { this.sig = sig; TopEval = new TopEquivalenceEvaluator(); BotEval = new BotEquivalenceEvaluator(); TopEval.setBotEval(BotEval); BotEval.setTopEval(TopEval); } /** init c'tor */ public GeneralSyntacticLocalityChecker() { this(null); } @Override @Original public TSignature getSignature() { return sig; } @Override public void visit(AxiomDeclaration axiom) { isLocal = true; } @Override public void visit(AxiomEquivalentConcepts axiom) { isLocal = processEquivalentAxiom(axiom); } @Override public void visit(AxiomDisjointConcepts axiom) { isLocal = processDisjointAxiom(axiom); } @Override public void visit(AxiomDisjointUnion axiom) { // DisjointUnion(A, C1,..., Cn) is local if // (1) A and all of Ci are bot-equivalent, // or (2) A and one Ci are top-equivalent and the remaining Cj are // bot-equivalent isLocal = false; boolean lhsIsTopEq; if (isTopEquivalent(axiom.getConcept())) { lhsIsTopEq = true; } else if (isBotEquivalent(axiom.getConcept())) { lhsIsTopEq = false; } else { return; } // neither (1) nor (2) boolean topEqDesc = false; for (ConceptExpression p : axiom.getArguments()) { if (!isBotEquivalent(p)) { if (lhsIsTopEq && isTopEquivalent(p)) { if (topEqDesc) { return; } else { topEqDesc = true; } } else { return; } } } isLocal = true; } @Override public void visit(AxiomEquivalentORoles axiom) { isLocal = processEquivalentAxiom(axiom); } @Override public void visit(AxiomEquivalentDRoles axiom) { isLocal = processEquivalentAxiom(axiom); } @Override public void visit(AxiomDisjointORoles axiom) { isLocal = processDisjointAxiom(axiom); } @Override public void visit(AxiomDisjointDRoles axiom) { isLocal = processDisjointAxiom(axiom); } @Override public void visit(AxiomSameIndividuals axiom) { isLocal = false; } @Override public void visit(AxiomDifferentIndividuals axiom) { isLocal = false; } /** * FaCT++ extension: there is no such axiom in OWL API, but I hope nobody * would use Fairness here */ @Override public void visit(AxiomFairnessConstraint axiom) { isLocal = true; } @Override public void visit(AxiomRoleInverse axiom) { isLocal = isBotEquivalent(axiom.getRole()) && isBotEquivalent(axiom.getInvRole()) || isTopEquivalent(axiom.getRole()) && isTopEquivalent(axiom.getInvRole()); } @Override public void visit(AxiomORoleSubsumption axiom) { isLocal = isTopEquivalent(axiom.getRole()) || isBotEquivalent(axiom.getSubRole()); } @Override public void visit(AxiomDRoleSubsumption axiom) { isLocal = isTopEquivalent(axiom.getRole()) || isBotEquivalent(axiom.getSubRole()); } @Override public void visit(AxiomORoleDomain axiom) { isLocal = isTopEquivalent(axiom.getDomain()) || isBotEquivalent(axiom.getRole()); } @Override public void visit(AxiomDRoleDomain axiom) { isLocal = isTopEquivalent(axiom.getDomain()) || isBotEquivalent(axiom.getRole()); } @Override public void visit(AxiomORoleRange axiom) { isLocal = isTopEquivalent(axiom.getRange()) || isBotEquivalent(axiom.getRole()); } @Override public void visit(AxiomDRoleRange axiom) { isLocal = isTopEquivalent(axiom.getRange()) || isBotEquivalent(axiom.getRole()); } @Override public void visit(AxiomRoleTransitive axiom) { isLocal = isBotEquivalent(axiom.getRole()) || isTopEquivalent(axiom.getRole()); } /** as BotRole is irreflexive, the only local axiom is topEquivalent(R) */ @Override public void visit(AxiomRoleReflexive axiom) { isLocal = isTopEquivalent(axiom.getRole()); } @Override public void visit(AxiomRoleIrreflexive axiom) { isLocal = isBotEquivalent(axiom.getRole()); } @Override public void visit(AxiomRoleSymmetric axiom) { isLocal = isBotEquivalent(axiom.getRole()) || isTopEquivalent(axiom.getRole()); } @Override public void visit(AxiomRoleAsymmetric axiom) { // XXX why is this necessarily non local? isLocal = false; } @Override public void visit(AxiomORoleFunctional axiom) { isLocal = isBotEquivalent(axiom.getRole()); } @Override public void visit(AxiomDRoleFunctional axiom) { isLocal = isBotEquivalent(axiom.getRole()); } @Override public void visit(AxiomRoleInverseFunctional axiom) { isLocal = isBotEquivalent(axiom.getRole()); } @Override public void visit(AxiomConceptInclusion axiom) { isLocal = isBotEquivalent(axiom.getSubConcept()) || isTopEquivalent(axiom.getSupConcept()); } @Override public void visit(AxiomInstanceOf axiom) { isLocal = isTopEquivalent(axiom.getC()); } @Override public void visit(AxiomRelatedTo axiom) { isLocal = isTopEquivalent(axiom.getRelation()); } @Override public void visit(AxiomRelatedToNot axiom) { isLocal = isBotEquivalent(axiom.getRelation()); } @Override public void visit(AxiomValueOf axiom) { isLocal = isTopEquivalent(axiom.getAttribute()); } @Override public void visit(AxiomValueOfNot axiom) { isLocal = isBotEquivalent(axiom.getAttribute()); } }