package uk.ac.manchester.cs.jfact.kernel;
/* 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 static uk.ac.manchester.cs.jfact.kernel.ClassifiableEntry.resolveSynonym;
import java.util.ArrayList;
import java.util.List;
import uk.ac.manchester.cs.jfact.datatypes.DatatypeFactory;
import uk.ac.manchester.cs.jfact.dep.DepSet;
import uk.ac.manchester.cs.jfact.helpers.Helper;
import uk.ac.manchester.cs.jfact.helpers.Pair;
import uk.ac.manchester.cs.jfact.helpers.Templates;
import uk.ac.manchester.cs.jfact.kernel.options.JFactReasonerConfiguration;
import conformance.PortedFrom;
/** nominal reasoner */
@PortedFrom(file = "ReasonerNom.h", name = "NominalReasoner")
public class NominalReasoner extends DlSatTester {
private static final long serialVersionUID = 11000L;
/** all nominals defined in TBox */
@PortedFrom(file = "ReasonerNom.h", name = "Nominals")
protected final List<Individual> nominals = new ArrayList<Individual>();
/** there are nominals */
@Override
@PortedFrom(file = "ReasonerNom.h", name = "hasNominals")
public boolean hasNominals() {
return true;
}
/** internal nominal reasoning interface */
/**
* create cache entry for given singleton
*
* @param p
* p
*/
@PortedFrom(file = "ReasonerNom.h", name = "registerNominalCache")
protected void registerNominalCache(Individual p) {
dlHeap.setCache(p.getpName(), createModelCache(p.getNode()
.resolvePBlocker()));
}
/**
* init single nominal node
*
* @param nom
* nom
* @return true if inconsistent
*/
@PortedFrom(file = "ReasonerNom.h", name = "initNominalNode")
protected boolean initNominalNode(Individual nom) {
DlCompletionTree node = cGraph.getNewNode();
node.setNominalLevel();
// init nominal with associated node
nom.setNode(node);
// ABox is inconsistent
return initNewNode(node, DepSet.create(), nom.getpName());
}
/**
* use classification information for the nominal P
*
* @param p
* p
*/
@PortedFrom(file = "ReasonerNom.h", name = "updateClassifiedSingleton")
protected void updateClassifiedSingleton(Individual p) {
registerNominalCache(p);
if (p.getNode().isPBlocked()) {
// BP of the individual P is merged to
int bp = p.getNode().getBlocker().label().get_sc().get(0)
.getConcept();
Individual blocker = (Individual) dlHeap.get(bp).getConcept();
assert blocker.getNode().equals(p.getNode().getBlocker());
tBox.addSameIndividuals(p, new Pair(blocker, p.getNode()
.getPurgeDep().isEmpty()));
}
}
/**
* @param tbox
* tbox
* @param Options
* Options
* @param datatypeFactory
* datatypeFactory
*/
public NominalReasoner(TBox tbox, JFactReasonerConfiguration Options,
DatatypeFactory datatypeFactory) {
super(tbox, Options, datatypeFactory);
for (Individual pi : tBox.i_begin()) {
if (!pi.isSynonym()) {
nominals.add(pi);
}
}
}
/** prerpare Nominal Reasoner to a new job */
@Override
@PortedFrom(file = "ReasonerNom.h", name = "prepareReasoner")
protected void prepareReasoner() {
options.getLog().print("\nInitNominalReasoner:");
restore(1);
// check whether branching op is not a barrier...
if (!(bContext instanceof BCBarrier)) {
// replace it with a barrier
stack.pop();
createBCBarrier();
}
// save the barrier (also remember the entry to be produced)
save();
// clear last session information
resetSessionFlags();
}
/** @return check whether ontology with nominals is consistent */
@PortedFrom(file = "ReasonerNom.h", name = "consistentNominalCloud")
public boolean consistentNominalCloud() {
options.getLog().print(
"\n\nChecking consistency of an ontology with individuals:\n");
boolean result = false;
if (initNewNode(cGraph.getRoot(), DepSet.create(), Helper.bpTOP)
|| initNominalCloud()) {
options.getLog().print("\ninit done\n");
result = false;
} else {
options.getLog().print("\nrunning sat...");
result = runSat();
options.getLog().print(" done: ");
options.getLog().print(result);
options.getLog().print("\n");
}
if (result && noBranchingOps()) {
options.getLog().print("InitNominalReasoner[");
curNode = null;
createBCBarrier();
save();
nonDetShift = 1;
options.getLog().print("]");
}
options.getLog().printTemplate(Templates.CONSISTENT_NOMINAL,
result ? "consistent" : "INCONSISTENT");
if (!result) {
return false;
}
for (Individual p : nominals) {
updateClassifiedSingleton(p);
}
return true;
}
@PortedFrom(file = "ReasonerNom.h", name = "initNominalCloud")
private boolean initNominalCloud() {
for (Individual p : nominals) {
if (initNominalNode(p)) {
return true;
}
}
for (int i = 0; i < tBox.getRelatedI().size(); i += 2) {
if (initRelatedNominals(tBox.getRelatedI().get(i))) {
return true;
}
}
if (tBox.getDifferent().isEmpty()) {
return false;
}
DepSet dummy = DepSet.create();
for (List<Individual> r : tBox.getDifferent()) {
cGraph.initIR();
for (Individual p : r) {
if (cGraph.setCurIR(resolveSynonym(p).getNode(), dummy)) {
return true;
}
}
cGraph.finiIR();
}
return false;
}
@Override
@PortedFrom(file = "Reasoner.h", name = "isNNApplicable")
protected boolean isNNApplicable(Role r, int C, int stopper) {
if (!curNode.isNominalNode()) {
return false;
}
if (curNode.isLabelledBy(stopper)) {
return false;
}
List<DlCompletionTreeArc> neighbour = curNode.getNeighbour();
for (int i = 0; i < neighbour.size(); i++) {
DlCompletionTreeArc p = neighbour.get(i);
DlCompletionTree suspect = p.getArcEnd();
if (p.isPredEdge() && suspect.isBlockableNode() && p.isNeighbour(r)
&& suspect.isLabelledBy(C)) {
options.getLog().printTemplate(Templates.NN, suspect.getId());
return true;
}
}
return false;
}
@PortedFrom(file = "ReasonerNom.h", name = "initRelatedNominals")
private boolean initRelatedNominals(Related rel) {
DlCompletionTree from = resolveSynonym(rel.getA()).getNode();
DlCompletionTree to = resolveSynonym(rel.getB()).getNode();
Role R = resolveSynonym(rel.getRole());
DepSet dep = DepSet.create();
if (R.isDisjoint() && checkDisjointRoleClash(from, to, R, dep)) {
return true;
}
DlCompletionTreeArc pA = cGraph.addRoleLabel(from, to, false, R, dep);
return setupEdge(pA, dep, 0);
}
/** create BC for the barrier */
@PortedFrom(file = "Reasoner.h", name = "createBCBarrier")
private void createBCBarrier() {
bContext = stack.pushBarrier();
}
/** @return true if unsatisfiable */
@PortedFrom(file = "ConjunctiveQueryFolding.cpp", name = "checkExtraCond")
public boolean checkExtraCond() {
prepareReasoner();
DepSet dummy = DepSet.create();
for (int i = 0; i < tBox.getIV().size(); i++) {
if (addToDoEntry(tBox.getIV().get(i).getNode(), tBox
.getConceptsForQueryAnswering().get(i), dummy, "QA")) {
return true;
}
}
return !checkSatisfiability();
}
}