/** Propagate the results of creating a new SCC with this node as lead. */ public void propagateSCC() { Set<GraphNode> visited = new HashSet<>(); visited.add(this); // Scan predecessors not including ourselves doVisitPredecessors( new Visitor<Set<GraphNode>, Object>() { @Override public List<GraphNode> visit( GraphNode node, GraphNode processing, Set<GraphNode> sc, Object ignored) { // Add closure node.succClosed.addAll(sc); // Scan for redundant links List<GraphNode> kill = null; for (Iterator<GraphNode> i = node.succ.iterator(); i.hasNext(); ) { GraphNode s = i.next(); if (sc.contains(s)) { i.remove(); // s.pred.remove(node); if (s == processing) { // Can't remove immediately w/o beaking the visitor loop if (kill == null) kill = new ArrayList<>(); kill.add(node); } else { s.pred.remove(node); } } } return kill; } }, succClosed, null, visited); }
/** Propagate the results of adding a link from this node to the target node. */ public void propagateAdd(GraphNode target) { Set<GraphNode> sc = new HashSet<>(target.succClosed); sc.add(target); visitPredecessors( new Visitor<Set<GraphNode>, GraphNode>() { @Override public List<GraphNode> visit( GraphNode node, GraphNode processing, Set<GraphNode> sc, GraphNode target) { // Add closure node.succClosed.addAll(sc); // Scan for redundant links List<GraphNode> kill = null; for (Iterator<GraphNode> i = node.succ.iterator(); i.hasNext(); ) { GraphNode s = i.next(); if (sc.contains(s)) { i.remove(); if (s == processing) { // Can't remove immediately w/o beaking the visitor loop if (kill == null) kill = new ArrayList<>(); kill.add(node); } else { s.pred.remove(node); } } } return kill; } }, sc, target); }
/** Visit each predecessor of this node applying the given visitor. Breadth first. */ private <Alpha, Beta> void doVisitPredecessors( Visitor<Alpha, Beta> visitor, Alpha arg1, Beta arg2, Set<GraphNode> seen) { if (seen.add(this)) { Collection<GraphNode> allKill = null; for (Iterator<GraphNode> i = pred.iterator(); i.hasNext(); ) { GraphNode pred = i.next(); List<GraphNode> kill = visitor.visit(pred, this, arg1, arg2); if (kill != null) { if (allKill == null) allKill = new ArrayList<GraphNode>(); allKill.addAll(kill); } } if (allKill != null) pred.removeAll(allKill); for (Iterator<GraphNode> i = pred.iterator(); i.hasNext(); ) { GraphNode pred = i.next(); pred.doVisitPredecessors(visitor, arg1, arg2, seen); } } }
void addInto(Set<GraphNode> nodes, GraphNode m) { nodes.add(m); }
/** Assert an inferred indirect link from this node to the given traget */ public void assertIndirectLinkTo(GraphNode target) { // if (this == target) return; succClosed.add(target); clearTripleCache(); }
/** * Assert a direct link between this node and this given target. Does not update the closed * successor cache */ public void assertLinkTo(GraphNode target) { if (this == target) return; succ.add(target); target.pred.add(this); clearTripleCache(); }