/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT 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.
HermiT 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 HermiT. If not, see <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT.tableau;
import java.io.Serializable;
import org.semanticweb.HermiT.model.AnnotatedEquality;
/**
* Implements the nominal introduction rule.
*/
public final class NominalIntroductionManager implements Serializable {
private static final long serialVersionUID=5863617010809297861L;
protected final Tableau m_tableau;
protected final DependencySetFactory m_dependencySetFactory;
protected final InterruptFlag m_interruptFlag;
protected final MergingManager m_mergingManager;
protected final TupleTable m_annotatedEqualities;
protected final Object[] m_bufferForAnnotatedEquality;
protected final TupleTable m_newRootNodesTable;
protected final TupleTableFullIndex m_newRootNodesIndex;
protected final Object[] m_bufferForRootNodes;
protected int[] m_indicesByBranchingPoint;
protected int m_firstUnprocessedAnnotatedEquality;
public NominalIntroductionManager(Tableau tableau) {
m_tableau=tableau;
m_dependencySetFactory=m_tableau.m_dependencySetFactory;
m_interruptFlag=m_tableau.m_interruptFlag;
m_mergingManager=m_tableau.m_mergingManager;
m_annotatedEqualities=new TupleTable(5);
m_bufferForAnnotatedEquality=new Object[5];
m_newRootNodesTable=new TupleTable(4);
m_newRootNodesIndex=new TupleTableFullIndex(m_newRootNodesTable,3);
m_bufferForRootNodes=new Object[4];
m_indicesByBranchingPoint=new int[10*2];
m_firstUnprocessedAnnotatedEquality=0;
}
public void clear() {
m_annotatedEqualities.clear();
for (int index=m_bufferForAnnotatedEquality.length-1;index>=0;--index)
m_bufferForAnnotatedEquality[index]=null;
m_newRootNodesTable.clear();
m_newRootNodesIndex.clear();
for (int index=m_bufferForRootNodes.length-1;index>=0;--index)
m_bufferForRootNodes[index]=null;
m_firstUnprocessedAnnotatedEquality=0;
}
public void branchingPointPushed() {
int start=m_tableau.getCurrentBranchingPoint().getLevel()*3;
int requiredSize=start+3;
if (requiredSize>m_indicesByBranchingPoint.length) {
int newSize=m_indicesByBranchingPoint.length*3/2;
while (requiredSize>newSize)
newSize=newSize*3/2;
int[] newIndicesByBranchingPoint=new int[newSize];
System.arraycopy(m_indicesByBranchingPoint,0,newIndicesByBranchingPoint,0,m_indicesByBranchingPoint.length);
m_indicesByBranchingPoint=newIndicesByBranchingPoint;
}
m_indicesByBranchingPoint[start]=m_firstUnprocessedAnnotatedEquality;
m_indicesByBranchingPoint[start+1]=m_annotatedEqualities.getFirstFreeTupleIndex();
m_indicesByBranchingPoint[start+2]=m_newRootNodesTable.getFirstFreeTupleIndex();
}
public void backtrack() {
int start=m_tableau.getCurrentBranchingPoint().getLevel()*3;
m_firstUnprocessedAnnotatedEquality=m_indicesByBranchingPoint[start];
int firstFreeAnnotatedEqualityShouldBe=m_indicesByBranchingPoint[start+1];
for (int tupleIndex=m_annotatedEqualities.getFirstFreeTupleIndex()-1;tupleIndex>=firstFreeAnnotatedEqualityShouldBe;--tupleIndex)
m_dependencySetFactory.removeUsage((PermanentDependencySet)m_annotatedEqualities.getTupleObject(tupleIndex,4));
m_annotatedEqualities.truncate(firstFreeAnnotatedEqualityShouldBe);
int firstFreeNewRootNodeShouldBe=m_indicesByBranchingPoint[start+2];
for (int tupleIndex=m_newRootNodesTable.getFirstFreeTupleIndex()-1;tupleIndex>=firstFreeNewRootNodeShouldBe;--tupleIndex)
m_newRootNodesIndex.removeTuple(tupleIndex);
m_newRootNodesTable.truncate(firstFreeNewRootNodeShouldBe);
}
public boolean processAnnotatedEqualities() {
boolean result=false;
while (m_firstUnprocessedAnnotatedEquality<m_annotatedEqualities.getFirstFreeTupleIndex()) {
m_annotatedEqualities.retrieveTuple(m_bufferForAnnotatedEquality,m_firstUnprocessedAnnotatedEquality);
m_firstUnprocessedAnnotatedEquality++;
AnnotatedEquality annotatedEquality=(AnnotatedEquality)m_bufferForAnnotatedEquality[0];
Node node0=(Node)m_bufferForAnnotatedEquality[1];
Node node1=(Node)m_bufferForAnnotatedEquality[2];
Node node2=(Node)m_bufferForAnnotatedEquality[3];
DependencySet dependencySet=(DependencySet)m_bufferForAnnotatedEquality[4];
if (applyNIRule(annotatedEquality,node0,node1,node2,dependencySet))
result=true;
m_interruptFlag.checkInterrupt();
}
return result;
}
public boolean canForgetAnnotation(AnnotatedEquality annotatedEquality,Node node0,Node node1,Node node2) {
return node0.isRootNode() || node1.isRootNode() || !node2.isRootNode() || (node2.isParentOf(node0) && node2.isParentOf(node1));
}
public boolean addAnnotatedEquality(AnnotatedEquality annotatedEquality,Node node0,Node node1,Node node2,DependencySet dependencySet) {
if (!node0.isActive() || !node1.isActive() || !node2.isActive())
return false;
else if (canForgetAnnotation(annotatedEquality,node0,node1,node2))
return m_mergingManager.mergeNodes(node0,node1,dependencySet);
else if (annotatedEquality.getCaridnality()==1)
return applyNIRule(annotatedEquality,node0,node1,node2,dependencySet);
else {
PermanentDependencySet permanentDependencySet=m_dependencySetFactory.getPermanent(dependencySet);
m_bufferForAnnotatedEquality[0]=annotatedEquality;
m_bufferForAnnotatedEquality[1]=node0;
m_bufferForAnnotatedEquality[2]=node1;
m_bufferForAnnotatedEquality[3]=node2;
m_bufferForAnnotatedEquality[4]=permanentDependencySet;
m_dependencySetFactory.addUsage(permanentDependencySet);
m_annotatedEqualities.addTuple(m_bufferForAnnotatedEquality);
return true;
}
}
protected boolean applyNIRule(AnnotatedEquality annotatedEquality,Node node0,Node node1,Node node2,DependencySet dependencySet) {
if (node0.isPruned() || node1.isPruned() || node2.isPruned())
return false;
dependencySet=node0.addCanonicalNodeDependencySet(dependencySet);
dependencySet=node1.addCanonicalNodeDependencySet(dependencySet);
dependencySet=node2.addCanonicalNodeDependencySet(dependencySet);
node0=node0.getCanonicalNode();
node1=node1.getCanonicalNode();
node2=node2.getCanonicalNode();
if (canForgetAnnotation(annotatedEquality,node0,node1,node2))
return m_mergingManager.mergeNodes(node0,node1,dependencySet);
else {
Node niTargetNode;
Node otherNode;
if (!node0.isRootNode() && !node2.isParentOf(node0)) {
niTargetNode=node0;
otherNode=node1;
}
else {
niTargetNode=node1;
otherNode=node0;
}
if (m_tableau.m_tableauMonitor!=null)
m_tableau.m_tableauMonitor.nominalIntorductionStarted(node2,niTargetNode,annotatedEquality,node0,node1);
if (annotatedEquality.getCaridnality()>1) {
BranchingPoint branchingPoint=new NominalIntroductionBranchingPoint(m_tableau,node2,niTargetNode,otherNode,annotatedEquality);
m_tableau.pushBranchingPoint(branchingPoint);
dependencySet=m_tableau.getDependencySetFactory().addBranchingPoint(dependencySet,branchingPoint.getLevel());
}
Node newRootNode=getNIRootFor(dependencySet,node2,annotatedEquality,1);
if (!newRootNode.isActive()) {
assert newRootNode.isMerged();
dependencySet=newRootNode.addCanonicalNodeDependencySet(dependencySet);
newRootNode=newRootNode.getCanonicalNode();
}
m_mergingManager.mergeNodes(niTargetNode,newRootNode,dependencySet);
if (!otherNode.isPruned()) {
dependencySet=otherNode.addCanonicalNodeDependencySet(dependencySet);
m_mergingManager.mergeNodes(otherNode.getCanonicalNode(),newRootNode,dependencySet);
}
if (m_tableau.m_tableauMonitor!=null)
m_tableau.m_tableauMonitor.nominalIntorductionFinished(node2,niTargetNode,annotatedEquality,node0,node1);
return true;
}
}
protected Node getNIRootFor(DependencySet dependencySet,Node rootNode,AnnotatedEquality annotatedEquality,int number) {
m_bufferForRootNodes[0]=rootNode;
m_bufferForRootNodes[1]=annotatedEquality;
m_bufferForRootNodes[2]=number;
int tupleIndex=m_newRootNodesIndex.getTupleIndex(m_bufferForRootNodes);
if (tupleIndex==-1) {
Node newRootNode=m_tableau.createNewNINode(dependencySet);
m_bufferForRootNodes[3]=newRootNode;
m_newRootNodesIndex.addTuple(m_bufferForRootNodes,m_newRootNodesTable.getFirstFreeTupleIndex());
m_newRootNodesTable.addTuple(m_bufferForRootNodes);
return newRootNode;
}
else
return (Node)m_newRootNodesTable.getTupleObject(tupleIndex,3);
}
protected class NominalIntroductionBranchingPoint extends BranchingPoint {
private static final long serialVersionUID=6678113479704184263L;
protected final Node m_rootNode;
protected final Node m_niTargetNode;
protected final Node m_otherNode;
protected final AnnotatedEquality m_annotatedEquality;
protected int m_currentRootNode;
public NominalIntroductionBranchingPoint(Tableau tableau,Node rootNode,Node niTargetNode,Node otherNode,AnnotatedEquality annotatedEquality) {
super(tableau);
m_rootNode=rootNode;
m_niTargetNode=niTargetNode;
m_otherNode=otherNode;
m_annotatedEquality=annotatedEquality;
m_currentRootNode=1; // This reflects the assumption that the first merge is performed from the NominalIntroductionManager
}
public void startNextChoice(Tableau tableau,DependencySet clashDepdendencySet) {
m_currentRootNode++;
assert m_currentRootNode<=m_annotatedEquality.getCaridnality();
DependencySet dependencySet=clashDepdendencySet;
if (m_currentRootNode==m_annotatedEquality.getCaridnality())
dependencySet=tableau.getDependencySetFactory().removeBranchingPoint(dependencySet,m_level);
Node newRootNode=getNIRootFor(dependencySet,m_rootNode,m_annotatedEquality,m_currentRootNode);
if (!newRootNode.isActive()) {
assert newRootNode.isMerged();
dependencySet=newRootNode.addCanonicalNodeDependencySet(dependencySet);
newRootNode=newRootNode.getCanonicalNode();
}
m_mergingManager.mergeNodes(m_niTargetNode,newRootNode,dependencySet);
if (!m_otherNode.isPruned()) {
dependencySet=m_otherNode.addCanonicalNodeDependencySet(dependencySet);
m_mergingManager.mergeNodes(m_otherNode.getCanonicalNode(),newRootNode,dependencySet);
}
}
}
}