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.helpers.Helper.InitBranchingLevelValue;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import uk.ac.manchester.cs.jfact.dep.DepSet;
import uk.ac.manchester.cs.jfact.helpers.FastSet;
import uk.ac.manchester.cs.jfact.helpers.FastSetFactory;
import uk.ac.manchester.cs.jfact.helpers.Helper;
import uk.ac.manchester.cs.jfact.helpers.LogAdapter;
import uk.ac.manchester.cs.jfact.helpers.Reference;
import uk.ac.manchester.cs.jfact.helpers.SaveStack;
import uk.ac.manchester.cs.jfact.helpers.Templates;
import uk.ac.manchester.cs.jfact.kernel.state.DLCompletionGraphSaveState;
import conformance.PortedFrom;
/** completion graph */
@PortedFrom(file = "dlCompletionGraph.h", name = "DlCompletionGraph")
public class DlCompletionGraph implements Serializable {
private static final long serialVersionUID = 11000L;
/** initial value of IR level */
@PortedFrom(file = "dlCompletionGraph.h", name = "initIRLevel")
private static final int initIRLevel = 0;
// XXX is this actually used?
/** allocator for edges */
@PortedFrom(file = "dlCompletionGraph.h", name = "CTEdgeHeap")
private final List<DlCompletionTreeArc> ctEdgeHeap = new ArrayList<DlCompletionTreeArc>();
/** heap itself */
@PortedFrom(file = "dlCompletionGraph.h", name = "NodeBase")
private final List<DlCompletionTree> nodeBase;
/** nodes, saved on current branching level */
@PortedFrom(file = "dlCompletionGraph.h", name = "SavedNodes")
private final List<DlCompletionTree> savedNodes = new ArrayList<DlCompletionTree>();
/** host reasoner */
@PortedFrom(file = "dlCompletionGraph.h", name = "pReasoner")
private final DlSatTester pReasoner;
/** remember the last generated ID for the node */
@PortedFrom(file = "dlCompletionGraph.h", name = "nodeId")
private int nodeId = 0;
/** index of the next unallocated entry */
@PortedFrom(file = "dlCompletionGraph.h", name = "endUsed")
private int endUsed;
/** current branching level (synchronised with resoner's one) */
@PortedFrom(file = "dlCompletionGraph.h", name = "branchingLevel")
private int branchingLevel;
/** current IR level (should be valid BP) */
@PortedFrom(file = "dlCompletionGraph.h", name = "IRLevel")
private int irLevel;
/** stack for rarely changed information */
@PortedFrom(file = "dlCompletionGraph.h", name = "RareStack")
private final SaveStackRare rareStack = new SaveStackRare();
/** stack for usual saving/restoring */
@PortedFrom(file = "dlCompletionGraph.h", name = "Stack")
private final SaveStack<DLCompletionGraphSaveState> stack = new SaveStack<DLCompletionGraphSaveState>();
// helpers for the output
/** bitmap to remember which node was printed */
// TODO change to regular
@PortedFrom(file = "dlCompletionGraph.h", name = "CPGFlag")
private final FastSet cgpFlag = FastSetFactory.create();
/** indent to print CGraph nodes */
@PortedFrom(file = "dlCompletionGraph.h", name = "CPGIndent")
private int cgpIndent;
// statistical members
/** number of node' saves */
@PortedFrom(file = "dlCompletionGraph.h", name = "nNodeSaves")
private int nNodeSaves;
/** number of node' saves */
@PortedFrom(file = "dlCompletionGraph.h", name = "nNodeRestores")
private int nNodeRestores;
/** maximal size of the graph */
@PortedFrom(file = "dlCompletionGraph.h", name = "maxGraphSize")
private int maxGraphSize = 0;
// flags
/** how many nodes skip before block; work only with FAIRNESS */
@PortedFrom(file = "dlCompletionGraph.h", name = "nSkipBeforeBlock")
private int nSkipBeforeBlock = 0;
/** use or not lazy blocking (ie test blocking only expanding exists) */
@PortedFrom(file = "dlCompletionGraph.h", name = "useLazyBlocking")
private boolean useLazyBlocking;
/** whether to use Anywhere blocking as opposed to an ancestor one */
@PortedFrom(file = "dlCompletionGraph.h", name = "useAnywhereBlocking")
private boolean useAnywhereBlocking;
/** check if session has inverse roles */
@PortedFrom(file = "dlCompletionGraph.h", name = "sessionHasInverseRoles")
private boolean sessionHasInverseRoles;
/** check if session has number restrictions */
@PortedFrom(file = "dlCompletionGraph.h", name = "sessionHasNumberRestrictions")
private boolean sessionHasNumberRestrictions;
/**
* init vector [B,E) with new objects T
*
* @param l
* l
* @param b
* b
* @param e
* e
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "initNodeArray")
private void initNodeArray(List<DlCompletionTree> l, int b, int e) {
for (int p = b; p < e; ++p) {
l.set(p, new DlCompletionTree(nodeId++, pReasoner.getOptions()));
}
}
/** increase heap size */
@PortedFrom(file = "dlCompletionGraph.h", name = "grow")
private void grow() {
int size = nodeBase.size();
Helper.resize(nodeBase, size * 2);
initNodeArray(nodeBase, size, nodeBase.size());
}
/** init root node */
@PortedFrom(file = "dlCompletionGraph.h", name = "initRoot")
private void initRoot() {
assert endUsed == 0;
getNewNode();
}
/**
* invalidate EDGE, save restoring info
*
* @param edge
* edge
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "invalidateEdge")
private void invalidateEdge(DlCompletionTreeArc edge) {
saveRareCond(edge.save());
}
/**
* check if d-blocked node is still d-blocked
*
* @param node
* node
* @return true if still blocked
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "isStillDBlocked")
private boolean isStillDBlocked(DlCompletionTree node) {
return node.isDBlocked() && isBlockedBy(node, node.blocker);
}
/**
* try to find d-blocker for a node
*
* @param node
* node
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "findDBlocker")
private void findDBlocker(DlCompletionTree node) {
saveNode(node, branchingLevel);
node.clearAffected();
if (node.isBlocked()) {
saveRareCond(node.setUBlocked());
}
if (useAnywhereBlocking) {
findDAnywhereBlocker(node);
} else {
findDAncestorBlocker(node);
}
}
/**
* unblock all the children of the node
*
* @param node
* node
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "unblockNodeChildren")
private void unblockNodeChildren(DlCompletionTree node) {
List<DlCompletionTreeArc> neighbour = node.getNeighbour();
int size = neighbour.size();
for (int i = 0; i < size; i++) {
DlCompletionTreeArc q = neighbour.get(i);
if (q.isSuccEdge() && !q.isIBlocked() && !q.isReflexiveEdge()) {
unblockNode(q.getArcEnd(), false);
}
}
}
/**
* mark NODE as a d-blocked by a BLOCKER
*
* @param node
* node
* @param blocker
* blocker
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "setNodeDBlocked")
private void
setNodeDBlocked(DlCompletionTree node, DlCompletionTree blocker) {
saveRareCond(node.setDBlocked(blocker));
propagateIBlockedStatus(node, node);
}
/**
* mark NODE as an i-blocked by a BLOCKER
*
* @param node
* node
* @param blocker
* blocker
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "setNodeIBlocked")
private void
setNodeIBlocked(DlCompletionTree node, DlCompletionTree blocker) {
// nominal nodes can't be blocked
if (node.isPBlocked() || node.isNominalNode()) {
return;
}
node.clearAffected();
// already iBlocked -- nothing changes
if (node.isIBlocked() && node.blocker.equals(blocker)) {
return;
}
// prevent node to be IBlocked due to reflexivity
if (node.equals(blocker)) {
return;
}
saveRareCond(node.setIBlocked(blocker));
propagateIBlockedStatus(node, blocker);
}
/**
* propagate i-blocked status to all children of NODE
*
* @param node
* node
* @param blocker
* blocker
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "propagateIBlockedStatus")
private void propagateIBlockedStatus(DlCompletionTree node,
DlCompletionTree blocker) {
List<DlCompletionTreeArc> neighbour = node.getNeighbour();
int size = neighbour.size();
for (int i = 0; i < size; i++) {
DlCompletionTreeArc q = neighbour.get(i);
if (q.isSuccEdge() && !q.isIBlocked()) {
setNodeIBlocked(q.getArcEnd(), blocker);
}
}
}
/**
* @param node
* node
* @return true iff node might became unblocked
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "canBeUnBlocked")
private boolean canBeUnBlocked(DlCompletionTree node) {
// in presence of inverse roles it is not enough
// to check the affected flag for both node and its blocker
// see tModal* for example
if (sessionHasInverseRoles) {
return true;
}
// if node is affected -- it can be unblocked;
// if blocker became blocked itself -- the same
return node.isAffected() || node.isIllegallyDBlocked();
}
/**
* print proper indentation
*
* @param o
* o
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "PrintIndent")
private void printIndent(LogAdapter o) {
o.print("\n|");
for (int i = 1; i < cgpIndent; ++i) {
o.print(" |");
}
}
/**
* c'tor: make INIT_SIZE objects
*
* @param initSize
* initSize
* @param p
* p
*/
public DlCompletionGraph(int initSize, DlSatTester p) {
nodeBase = new ArrayList<DlCompletionTree>();
Helper.resize(nodeBase, initSize);
pReasoner = p;
nodeId = 0;
endUsed = 0;
branchingLevel = InitBranchingLevelValue;
irLevel = initIRLevel;
initNodeArray(nodeBase, 0, nodeBase.size());
clearStatistics();
initRoot();
}
// flag setting
/**
* set flags for blocking
*
* @param nSkip
* nSkip
* @param useLB
* useLB
* @param useAB
* useAB
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "initContext")
public void initContext(int nSkip, boolean useLB, boolean useAB) {
nSkipBeforeBlock = nSkip;
useLazyBlocking = useLB;
useAnywhereBlocking = useAB;
}
/**
* set blocking method for a session
*
* @param hasInverse
* hasInverse
* @param hasQCR
* hasQCR
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "setBlockingMethod")
public void setBlockingMethod(boolean hasInverse, boolean hasQCR) {
sessionHasInverseRoles = hasInverse;
sessionHasNumberRestrictions = hasQCR;
}
/**
* add concept C of a type TAG to NODE; call blocking check if appropriate
*
* @param node
* node
* @param c
* c
* @param tag
* tag
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "addConceptToNode")
public void addConceptToNode(DlCompletionTree node, ConceptWDep c,
DagTag tag) {
node.addConcept(c, tag);
if (useLazyBlocking) {
node.setAffected();
} else {
detectBlockedStatus(node);
}
}
// access to nodes
/** @return root node (non-const) */
@PortedFrom(file = "dlCompletionGraph.h", name = "getRoot")
public DlCompletionTree getRoot() {
return nodeBase.get(0).resolvePBlocker();
}
/**
* @param i
* i
* @return dl completion tree at index i
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "getNode")
public DlCompletionTree getNode(int i) {
if (i >= endUsed) {
return null;
}
return nodeBase.get(i);
}
/** @return new node (with internal level) */
@PortedFrom(file = "dlCompletionGraph.h", name = "getNewNode")
public DlCompletionTree getNewNode() {
if (endUsed >= nodeBase.size()) {
grow();
}
DlCompletionTree ret = nodeBase.get(endUsed++);
ret.init(branchingLevel);
return ret;
}
// blocking
/**
* update blocked status for d-blocked node
*
* @param node
* node
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "updateDBlockedStatus")
public void updateDBlockedStatus(DlCompletionTree node) {
if (!canBeUnBlocked(node)) {
return;
}
if (isStillDBlocked(node)) {
// FIXME!! clear affected in all children
node.clearAffected();
} else {
detectBlockedStatus(node);
}
assert !node.isAffected();
}
/** retest every d-blocked node in the CG. Use it after the CG was build */
@PortedFrom(file = "dlCompletionGraph.h", name = "retestCGBlockedStatus")
public void retestCGBlockedStatus() {
boolean repeat = false;
do {
for (int i = 0; i < endUsed; i++) {
DlCompletionTree p = nodeBase.get(i);
if (p.isDBlocked()) {
updateDBlockedStatus(p);
}
}
/**
* we need to repeat the thing if something became unblocked and
* then blocked again, in case one of the blockers became blocked
* itself; see tModal3 for such an example
*/
repeat = false;
for (int i = 0; i < endUsed; i++) {
DlCompletionTree p = nodeBase.get(i);
if (p.isIllegallyDBlocked()) {
repeat = true;
break;
}
}
} while (repeat);
}
/**
* @param C
* fairness constant
* @return true if a fairness constraint C is violated in one of the loops
* in the CGraph
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "getFCViolator")
public DlCompletionTree getFCViolator(int C) {
for (DlCompletionTree p : nodeBase) {
if (p.isDBlocked() && !p.isLoopLabelled(C)) {
return p.blocker;
}
}
return null;
}
/** clear all the session statistics */
@PortedFrom(file = "dlCompletionGraph.h", name = "clearStatistics")
public void clearStatistics() {
nNodeSaves = 0;
nNodeRestores = 0;
if (maxGraphSize < endUsed) {
maxGraphSize = endUsed;
}
}
/** @return get number of nodes in the CGraph */
@PortedFrom(file = "dlCompletionGraph.h", name = "maxSize")
public int maxSize() {
return maxGraphSize;
}
/** mark all heap elements as unused */
@PortedFrom(file = "dlCompletionGraph.h", name = "clear")
public void clear() {
ctEdgeHeap.clear();
endUsed = 0;
branchingLevel = InitBranchingLevelValue;
irLevel = initIRLevel;
rareStack.clear();
stack.clear();
savedNodes.clear();
initRoot();
}
/**
* save rarely appeared info if P is non-null
*
* @param p
* p
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "saveRareCond")
public void saveRareCond(Restorer p) {
if (p == null) {
throw new IllegalArgumentException();
}
rareStack.push(p);
}
/**
* @param p
* p
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "saveRareCond")
public void saveRareCond(List<Restorer> p) {
for (int i = 0; i < p.size(); i++) {
rareStack.push(p.get(i));
}
}
/**
* get the rare stack
*
* @return rare stack
*/
public SaveStackRare getRareStack() {
return rareStack;
}
// role/node
/**
* add role R with dep-set DEP to the label of the TO arc
*
* @param from
* from
* @param to
* to
* @param isPredEdge
* isPredEdge
* @param R
* name of role (arc label)
* @param dep
* dep-set of the arc label
* @return completion tree arc
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "addRoleLabel")
public DlCompletionTreeArc addRoleLabel(DlCompletionTree from,
DlCompletionTree to, boolean isPredEdge, Role R, DepSet dep) {
// check if GCraph already has FROM.TO edge labelled with RNAME
DlCompletionTreeArc ret = from.getEdgeLabelled(R, to);
if (ret == null) {
ret = createEdge(from, to, isPredEdge, R, dep);
} else {
if (!dep.isEmpty()) {
saveRareCond(ret.addDep(dep));
}
}
return ret;
}
/**
* Create an empty R-neighbour of FROM;
*
* @param from
* from
* @param isPredEdge
* isPredEdge
* @param r
* name of role (arc label)
* @param dep
* dep-set of the arc label
* @return an edge to created node
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "createNeighbour")
public DlCompletionTreeArc createNeighbour(DlCompletionTree from,
boolean isPredEdge, Role r, DepSet dep) {
if (pReasoner.getOptions().isRKG_IMPROVE_SAVE_RESTORE_DEPSET()) {
assert branchingLevel == dep.level() + 1;
}
return createEdge(from, getNewNode(), isPredEdge, r, dep);
}
/**
* Create an R-loop of NODE wrt dep-set DEP;
*
* @param node
* node
* @param r
* r
* @param dep
* dep
* @return a loop edge
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "createLoop")
public DlCompletionTreeArc createLoop(DlCompletionTree node, Role r,
DepSet dep) {
return addRoleLabel(node, node, /* isPredEdge= */
false, r, dep);
}
/**
* save given node wrt level
*
* @param node
* node
* @param level
* level
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "saveNode")
public void saveNode(DlCompletionTree node, int level) {
if (node.needSave(level)) {
node.save(level);
savedNodes.add(node);
++nNodeSaves;
}
}
/**
* restore given node wrt level
*
* @param node
* node
* @param level
* level
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "restoreNode")
private void restoreNode(DlCompletionTree node, int level) {
if (node.needRestore(level)) {
node.restore(level);
++nNodeRestores;
}
}
@PortedFrom(file = "dlCompletionGraph.h", name = "isBlockedBy")
private boolean
isBlockedBy(DlCompletionTree node, DlCompletionTree blocker) {
assert !node.isNominalNode();
assert !blocker.isNominalNode();
if (blocker.isBlocked()) {
return false;
}
if (!blocker.canBlockInit(node.getInit())) {
return false;
}
boolean ret;
if (sessionHasInverseRoles) {
DLDag dag = pReasoner.getDAG();
if (sessionHasNumberRestrictions) {
ret = node.isBlockedBy_SHIQ(dag, blocker);
} else {
ret = node.isBlockedBy_SHI(dag, blocker);
}
} else {
ret = node.isBlockedBy_SH(blocker);
}
if (pReasoner.getOptions().isUSE_BLOCKING_STATISTICS() && !ret) {
pReasoner
.getOptions()
.getLog()
.printTemplate(Templates.IS_BLOCKED_FAILURE_BY,
node.getId(), blocker.getId());
}
return ret;
}
/**
* @param node
* node
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "detectBlockedStatus")
public void detectBlockedStatus(DlCompletionTree node) {
DlCompletionTree p = node;
boolean wasBlocked = node.isBlocked();
boolean wasDBlocked = node.isDBlocked();
node.setAffected();
while (p.hasParent() && p.isBlockableNode() && p.isAffected()) {
findDBlocker(p);
if (p.isBlocked()) {
// this.print(LL);
return;
}
p = p.getParentNode();
}
p.clearAffected();
if (wasBlocked && !node.isBlocked()) {
unblockNode(node, wasDBlocked);
}
}
@PortedFrom(file = "dlCompletionGraph.h", name = "unblockNode")
private void unblockNode(DlCompletionTree node, boolean wasDBlocked) {
if (node.isPBlocked() || !node.isBlockableNode()) {
return;
}
if (!wasDBlocked) {
saveRareCond(node.setUBlocked());
}
pReasoner.repeatUnblockedNode(node, wasDBlocked);
unblockNodeChildren(node);
}
@PortedFrom(file = "dlCompletionGraph.h", name = "findDAncestorBlocker")
private void findDAncestorBlocker(DlCompletionTree node) {
DlCompletionTree p = node;
if (pReasoner.getOptions().isRKG_USE_FAIRNESS() && nSkipBeforeBlock > 0) {
for (int n = nSkipBeforeBlock - 1; n >= 0 && p.hasParent()
&& p.isBlockableNode(); --n) {
p = p.getParentNode();
}
}
while (p.hasParent()) {
p = p.getParentNode();
if (!p.isBlockableNode()) {
return;
}
if (isBlockedBy(node, p)) {
setNodeDBlocked(node, p);
return;
}
}
}
@PortedFrom(file = "dlCompletionGraph.h", name = "findDAnywhereBlocker")
private void findDAnywhereBlocker(DlCompletionTree node) {
for (int i = 0; i < endUsed && i != node.getId(); i++) {
DlCompletionTree p = nodeBase.get(i);
if (!p.isBlockedPBlockedNominalNodeCached() && isBlockedBy(node, p)) {
setNodeDBlocked(node, p);
return;
}
}
}
/**
* Class for maintaining graph of CT nodes. Behaves like deleteless
* allocator for nodes, plus some obvious features
*/
/**
* @param p
* p
* @param q
* q
* @param dep
* dep
* @return whether p and q can be merged
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "nonMergable")
public boolean nonMergable(DlCompletionTree p, DlCompletionTree q,
Reference<DepSet> dep) {
return p.nonMergable(q, dep);
}
@PortedFrom(file = "dlCompletionGraph.h", name = "updateIR")
private void updateIR(DlCompletionTree p, DlCompletionTree q, DepSet toAdd) {
if (!q.inequalityRelation.isEmpty()) {
saveRareCond(p.updateIR(q, toAdd));
}
}
/** init IR */
@PortedFrom(file = "dlCompletionGraph.h", name = "initIR")
public void initIR() {
++irLevel;
}
/**
* @param node
* node
* @param ds
* ds
* @return true if IR alreadh has the label
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "setCurIR")
public boolean setCurIR(DlCompletionTree node, DepSet ds) {
return node.initIR(irLevel, ds);
}
/** fini IR */
@PortedFrom(file = "dlCompletionGraph.h", name = "finiIR")
public void finiIR() {}
@PortedFrom(file = "dlCompletionGraph.h", name = "createEdge")
private DlCompletionTreeArc createEdge(DlCompletionTree from,
DlCompletionTree to, boolean isPredEdge, Role roleName, DepSet dep) {
DlCompletionTreeArc forward = new DlCompletionTreeArc(roleName, dep, to);
ctEdgeHeap.add(forward);
forward.setSuccEdge(!isPredEdge);
DlCompletionTreeArc backward = new DlCompletionTreeArc(
roleName.inverse(), dep, from);
ctEdgeHeap.add(backward);
backward.setSuccEdge(isPredEdge);
forward.setReverse(backward);
saveNode(from, branchingLevel);
saveNode(to, branchingLevel);
from.addNeighbour(forward);
to.addNeighbour(backward);
if (pReasoner.getOptions().isLoggingActive()) {
pReasoner
.getOptions()
.getLog()
.printTemplate(Templates.CREATE_EDGE,
isPredEdge ? to.getId() : from.getId(),
isPredEdge ? "<-" : "->",
isPredEdge ? from.getId() : to.getId(),
roleName.getName());
}
return forward;
}
@PortedFrom(file = "dlCompletionGraph.h", name = "moveEdge")
private DlCompletionTreeArc moveEdge(DlCompletionTree node,
DlCompletionTreeArc edge, boolean isPredEdge, DepSet dep) {
if (edge.isIBlocked()) {
return null;
}
if (!isPredEdge && !edge.getArcEnd().isNominalNode()) {
return null;
}
Role R = edge.getRole();
if (edge.isReflexiveEdge()) {
return createLoop(node, R, dep);
}
DlCompletionTree to = edge.getArcEnd();
if (R != null) {
invalidateEdge(edge);
}
for (DlCompletionTreeArc p : node.getNeighbour()) {
if (p.getArcEnd().equals(to) && p.isPredEdge() != isPredEdge) {
return addRoleLabel(node, to, !isPredEdge, R, dep);
}
}
return addRoleLabel(node, to, isPredEdge, R, dep);
}
/**
* @param from
* from
* @param to
* to
* @param dep
* dep
* @param edges
* edges
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "merge")
public void merge(DlCompletionTree from, DlCompletionTree to, DepSet dep,
List<DlCompletionTreeArc> edges) {
edges.clear();
List<DlCompletionTreeArc> neighbour = from.getNeighbour();
int size = neighbour.size();
for (int i = 0; i < size; i++) {
DlCompletionTreeArc p = neighbour.get(i);
if (p.isPredEdge() || p.getArcEnd().isNominalNode()) {
DlCompletionTreeArc temp = moveEdge(to, p, p.isPredEdge(), dep);
if (temp != null) {
edges.add(temp);
}
}
if (p.isSuccEdge()) {
purgeEdge(p, to, dep);
}
}
updateIR(to, from, dep);
purgeNode(from, to, dep);
}
@PortedFrom(file = "dlCompletionGraph.h", name = "purgeNode")
private void
purgeNode(DlCompletionTree p, DlCompletionTree root, DepSet dep) {
if (p.isPBlocked()) {
return;
}
saveRareCond(p.setPBlocked(root, dep));
List<DlCompletionTreeArc> neighbour = p.getNeighbour();
int size = neighbour.size();
for (int i = 0; i < size; i++) {
DlCompletionTreeArc q = neighbour.get(i);
if (q.isSuccEdge() && !q.isIBlocked()) {
purgeEdge(q, root, dep);
}
}
}
@PortedFrom(file = "dlCompletionGraph.h", name = "purgeEdge")
private void purgeEdge(DlCompletionTreeArc e, DlCompletionTree root,
DepSet dep) {
if (e.getRole() != null) {
invalidateEdge(e);
}
if (e.getArcEnd().isBlockableNode()) {
purgeNode(e.getArcEnd(), root, dep);
}
}
/** save dl completion graph */
@PortedFrom(file = "dlCompletionGraph.h", name = "save")
public void save() {
DLCompletionGraphSaveState s = new DLCompletionGraphSaveState();
stack.push(s);
s.setnNodes(endUsed);
s.setsNodes(savedNodes.size());
s.setnEdges(ctEdgeHeap.size());
rareStack.incLevel();
++branchingLevel;
}
/**
* @param level
* level
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "restore")
public void restore(int level) {
assert level > 0;
branchingLevel = level;
rareStack.restore(level);
DLCompletionGraphSaveState s = stack.pop(level);
endUsed = s.getnNodes();
int nSaved = s.getsNodes();
if (endUsed < Math.abs(savedNodes.size() - nSaved)) {
for (int i = 0; i < endUsed; i++) {
// XXX check: it was taking into account also empty nodes
restoreNode(nodeBase.get(i), level);
}
} else {
for (int i = nSaved; i < savedNodes.size(); i++) {
if (savedNodes.get(i).getId() < endUsed) {
restoreNode(savedNodes.get(i), level);
}
}
}
Helper.resize(savedNodes, nSaved);
Helper.resize(ctEdgeHeap, s.getnEdges());
}
/**
* @param o
* o
*/
@PortedFrom(file = "dlCompletionGraph.h", name = "print")
public void print(LogAdapter o) {
cgpIndent = 0;
cgpFlag.clear();
List<DlCompletionTree> l = nodeBase;
for (int i = 1; i < endUsed && l.get(i).isNominalNode(); ++i) {
cgpFlag.add(i);
}
printNode(l.get(0), o);
for (int i = 1; i < endUsed && l.get(i).isNominalNode(); ++i) {
cgpFlag.remove(l.get(i).getId());
printNode(l.get(i), o);
}
o.print("\n");
}
@PortedFrom(file = "dlCompletionGraph.h", name = "PrintEdge")
private void printEdge(List<DlCompletionTreeArc> l, int pos,
DlCompletionTreeArc _edge, DlCompletionTree parent, LogAdapter o) {
DlCompletionTreeArc edge = _edge;
DlCompletionTree node = edge.getArcEnd();
boolean succEdge = edge.isSuccEdge();
printIndent(o);
if (edge.getArcEnd().equals(node) && edge.isSuccEdge() == succEdge) {
o.print(" ");
edge.print(o);
}
for (; pos < l.size(); pos++) {
edge = l.get(pos);
if (edge.getArcEnd().equals(node) && edge.isSuccEdge() == succEdge) {
o.print(" ");
edge.print(o);
}
}
if (node.equals(parent)) {
printIndent(o);
o.print("-loop to node ");
o.print(parent.getId());
} else {
printNode(node, o);
}
}
@PortedFrom(file = "dlCompletionGraph.h", name = "PrintNode")
private void printNode(DlCompletionTree node, LogAdapter o) {
if (cgpIndent > 0) {
printIndent(o);
o.print("-");
} else {
o.print("\n");
}
node.printBody(o);
if (cgpFlag.contains(node.getId())) {
o.print("d");
return;
}
cgpFlag.add(node.getId());
boolean wantPred = node.isNominalNode();
++cgpIndent;
List<DlCompletionTreeArc> l = node.getNeighbour();
for (int i = 0; i < l.size(); i++) {
if (l.get(i).isSuccEdge() || wantPred
&& l.get(i).getArcEnd().isNominalNode()) {
printEdge(l, i + 1, l.get(i), node, o);
}
}
--cgpIndent;
}
}