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.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.semanticweb.owlapi.vocab.OWLRDFVocabulary;
import uk.ac.manchester.cs.jfact.kernel.ExpressionManager;
import uk.ac.manchester.cs.jfact.kernel.ReasoningKernel;
import uk.ac.manchester.cs.jfact.kernel.dl.ObjectRoleChain;
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.DataRoleExpression;
import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.Expression;
import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.NamedEntity;
import uk.ac.manchester.cs.jfact.kernel.dl.interfaces.ObjectRoleExpression;
import uk.ac.manchester.cs.jfact.visitors.DLAxiomVisitor;
import conformance.Original;
import conformance.PortedFrom;
/** semantic locality checker for DL axioms */
@PortedFrom(file = "SemanticLocalityChecker.h", name = "SemanticLocalityChecker")
public class SemanticLocalityChecker implements DLAxiomVisitor,
LocalityChecker, Serializable {
private static final long serialVersionUID = 11000L;
/** Reasoner to detect the tautology */
@PortedFrom(file = "SemanticLocalityChecker.h", name = "Kernel")
private final ReasoningKernel Kernel;
/** Expression manager of a kernel */
@PortedFrom(file = "SemanticLocalityChecker.h", name = "pEM")
private final ExpressionManager pEM;
/** map between axioms and concept expressions */
@PortedFrom(file = "SemanticLocalityChecker.h", name = "ExprMap")
private final Map<AxiomInterface, ConceptExpression> ExprMap = new HashMap<AxiomInterface, ConceptExpression>();
/**
* @param axiom
* axiom
* @return expression necessary to build query for a given type of an axiom; @return
* NULL if none necessary
*/
@PortedFrom(file = "SemanticLocalityChecker.h", name = "getExpr")
protected ConceptExpression getExpr(AxiomInterface axiom) {
// everything else doesn't require expression to be build
return axiom.accept(new ExpressionFromAxiomBuilder(null, pEM));
}
/** signature to keep */
@PortedFrom(file = "LocalityChecker.h", name = "sig")
private TSignature sig;
@Override
@Original
public TSignature getSignature() {
return sig;
}
/** set a new value of a signature (without changing a locality parameters) */
@Override
@Original
public void setSignatureValue(TSignature Sig) {
sig = Sig;
Kernel.setSignature(sig);
}
/** remember the axiom locality value here */
@PortedFrom(file = "SemanticLocalityChecker.h", name = "isLocal")
private boolean isLocal;
/**
* init c'tor
*
* @param k
* k
*/
public SemanticLocalityChecker(ReasoningKernel k) {
Kernel = k;
isLocal = true;
pEM = Kernel.getExpressionManager();
// for tests we will need TB names to be from the OWL 2 namespace
pEM.setTopBottomRoles(
OWLRDFVocabulary.OWL_TOP_OBJECT_PROPERTY.getIRI(),
OWLRDFVocabulary.OWL_BOTTOM_OBJECT_PROPERTY.getIRI(),
OWLRDFVocabulary.OWL_TOP_DATA_PROPERTY.getIRI(),
OWLRDFVocabulary.OWL_BOTTOM_DATA_PROPERTY.getIRI());
}
// set fields
/** @return true iff an AXIOM is local wrt defined policy */
@Override
@Original
public boolean local(AxiomInterface axiom) {
axiom.accept(this);
return isLocal;
}
/** init kernel with the ontology signature */
@Override
@PortedFrom(file = "SemanticLocalityChecker.h", name = "preprocessOntology")
public
void preprocessOntology(Collection<AxiomInterface> axioms) {
TSignature s = new TSignature();
ExprMap.clear();
for (AxiomInterface q : axioms) {
ExprMap.put(q, getExpr(q));
s.add(q.getSignature());
}
Kernel.clearKB();
// register all the objects in the ontology signature
for (NamedEntity p : s.begin()) {
Kernel.getOntology()
.add(new AxiomDeclaration(null, (Expression) p));
}
// prepare the reasoner to check tautologies
Kernel.realiseKB();
// after TBox appears there, set signature to translate
Kernel.setSignature(getSignature());
// disallow usage of the expression cache as same expressions will lead
// to different translations
Kernel.setIgnoreExprCache(true);
}
@Override
public void visit(AxiomDeclaration axiom) {
isLocal = true;
}
@Override
public void visit(AxiomEquivalentConcepts axiom) {
isLocal = false;
List<ConceptExpression> arguments = axiom.getArguments();
int size = arguments.size();
ConceptExpression C = arguments.get(0);
for (int i = 1; i < size; i++) {
ConceptExpression p = arguments.get(i);
if (!Kernel.isEquivalent(C, p)) {
return;
}
}
isLocal = true;
}
@Override
public void visit(AxiomDisjointConcepts axiom) {
isLocal = false;
List<ConceptExpression> arguments = axiom.getArguments();
int size = arguments.size();
for (int i = 0; i < size; i++) {
ConceptExpression p = arguments.get(i);
for (int j = i + 1; j < size; j++) {
ConceptExpression q = arguments.get(j);
if (!Kernel.isDisjoint(p, q)) {
return;
}
}
}
isLocal = true;
}
@Override
public void visit(AxiomDisjointUnion axiom) {
isLocal = false;
// check A = (or C1... Cn)
List<ConceptExpression> arguments = axiom.getArguments();
if (!Kernel.isEquivalent(axiom.getConcept(), pEM.or(arguments))) {
return;
}
// check disjoint(C1...Cn)
int size = arguments.size();
for (int i = 0; i < size; i++) {
for (int j = i + 1; j < size; j++) {
if (!Kernel.isDisjoint(arguments.get(i), arguments.get(j))) {
return;
}
}
}
isLocal = true;
}
@Override
public void visit(AxiomEquivalentORoles axiom) {
isLocal = false;
List<ObjectRoleExpression> arguments = axiom.getArguments();
int size = arguments.size();
ObjectRoleExpression R = arguments.get(0);
for (int i = 1; i < size; i++) {
if (!(Kernel.isSubRoles(R, arguments.get(i)) && Kernel.isSubRoles(
arguments.get(i), R))) {
return;
}
}
isLocal = true;
}
// tautology if all the subsumptions Ri [= Rj holds
@Override
public void visit(AxiomEquivalentDRoles axiom) {
isLocal = false;
List<DataRoleExpression> arguments = axiom.getArguments();
DataRoleExpression R = arguments.get(0);
for (int i = 1; i < arguments.size(); i++) {
if (!(Kernel.isSubRoles(R, arguments.get(i)) && Kernel.isSubRoles(
arguments.get(i), R))) {
return;
}
}
isLocal = true;
}
@Override
public void visit(AxiomDisjointORoles axiom) {
isLocal = Kernel.isDisjointRoles(axiom.getArguments());
}
@Override
public void visit(AxiomDisjointDRoles axiom) {
isLocal = Kernel.isDisjointRoles(axiom.getArguments());
}
// never local
@Override
public void visit(AxiomSameIndividuals axiom) {
isLocal = false;
}
// never local
@Override
public void visit(AxiomDifferentIndividuals axiom) {
isLocal = false;
}
/**
* there is no such axiom in OWL API, but I hope nobody would use Fairness
* here
*/
@Override
public void visit(AxiomFairnessConstraint axiom) {
isLocal = true;
}
// R = inverse(S) is tautology iff R [= S- and S [= R-
@Override
public void visit(AxiomRoleInverse axiom) {
isLocal = Kernel.isSubRoles(axiom.getRole(),
pEM.inverse(axiom.getInvRole()))
&& Kernel.isSubRoles(axiom.getInvRole(),
pEM.inverse(axiom.getRole()));
}
@Override
public void visit(AxiomORoleSubsumption axiom) {
// check whether the LHS is a role chain
if (axiom.getSubRole() instanceof ObjectRoleChain) {
isLocal = Kernel.isSubChain(axiom.getRole(),
((ObjectRoleChain) axiom.getSubRole()).getArguments());
return;
}
// check whether the LHS is a plain rle or inverse
if (axiom.getSubRole() instanceof ObjectRoleExpression) {
isLocal = Kernel.isSubRoles(axiom.getSubRole(), axiom.getRole());
return;
}
// here we have a projection expression. FIXME!! for now
isLocal = true;
}
@Override
public void visit(AxiomDRoleSubsumption axiom) {
isLocal = Kernel.isSubRoles(axiom.getSubRole(), axiom.getRole());
}
// Domain(R) = C is tautology iff ER.Top [= C
@Override
public void visit(AxiomORoleDomain axiom) {
isLocal = Kernel.isSubsumedBy(ExprMap.get(axiom), axiom.getDomain());
}
@Override
public void visit(AxiomDRoleDomain axiom) {
isLocal = Kernel.isSubsumedBy(ExprMap.get(axiom), axiom.getDomain());
}
// Range(R) = C is tautology iff ER.~C is unsatisfiable
@Override
public void visit(AxiomORoleRange axiom) {
isLocal = !Kernel.isSatisfiable(ExprMap.get(axiom));
}
@Override
public void visit(AxiomDRoleRange axiom) {
isLocal = !Kernel.isSatisfiable(ExprMap.get(axiom));
}
@Override
public void visit(AxiomRoleTransitive axiom) {
isLocal = Kernel.isTransitive(axiom.getRole());
}
@Override
public void visit(AxiomRoleReflexive axiom) {
isLocal = Kernel.isReflexive(axiom.getRole());
}
@Override
public void visit(AxiomRoleIrreflexive axiom) {
isLocal = Kernel.isIrreflexive(axiom.getRole());
}
@Override
public void visit(AxiomRoleSymmetric axiom) {
isLocal = Kernel.isSymmetric(axiom.getRole());
}
@Override
public void visit(AxiomRoleAsymmetric axiom) {
isLocal = Kernel.isAsymmetric(axiom.getRole());
}
@Override
public void visit(AxiomORoleFunctional axiom) {
isLocal = Kernel.isFunctional(axiom.getRole());
}
@Override
public void visit(AxiomDRoleFunctional axiom) {
isLocal = Kernel.isFunctional(axiom.getRole());
}
@Override
public void visit(AxiomRoleInverseFunctional axiom) {
isLocal = Kernel.isInverseFunctional(axiom.getRole());
}
@Override
public void visit(AxiomConceptInclusion axiom) {
isLocal = Kernel.isSubsumedBy(axiom.getSubConcept(),
axiom.getSupConcept());
}
// for top locality, this might be local
@Override
public void visit(AxiomInstanceOf axiom) {
isLocal = Kernel.isInstance(axiom.getIndividual(), axiom.getC());
}
@Override
public void visit(AxiomRelatedTo axiom) {
isLocal = Kernel.isInstance(axiom.getIndividual(), ExprMap.get(axiom));
}
@Override
public void visit(AxiomRelatedToNot axiom) {
isLocal = Kernel.isInstance(axiom.getIndividual(), ExprMap.get(axiom));
}
@Override
public void visit(AxiomValueOf axiom) {
isLocal = Kernel.isInstance(axiom.getIndividual(), ExprMap.get(axiom));
}
@Override
public void visit(AxiomValueOfNot axiom) {
isLocal = Kernel.isInstance(axiom.getIndividual(), ExprMap.get(axiom));
}
}