private static <T> int strongConnect( InferenceGraphNode<T> currentNode, int index, Stack<InferenceGraphNode<T>> currentStack, ArrayList<List<InferenceGraphNode<T>>> result) { currentNode.index = index; currentNode.lowlink = index; index++; currentStack.push(currentNode); for (InferenceGraphNode<T> dependantNode : currentNode.getDependencies()) { if (dependantNode.index == -1) { strongConnect(dependantNode, index, currentStack, result); currentNode.lowlink = Math.min(currentNode.lowlink, dependantNode.lowlink); } else if (currentStack.contains(dependantNode)) { currentNode.lowlink = Math.min(currentNode.lowlink, dependantNode.index); } } if (currentNode.lowlink == currentNode.index) { final ArrayList<InferenceGraphNode<T>> arrayList = new ArrayList<InferenceGraphNode<T>>(); InferenceGraphNode<T> cyclicNode; do { cyclicNode = currentStack.pop(); arrayList.add(cyclicNode); } while (cyclicNode != currentNode); result.add(arrayList); } return index; }
public static List<List<InferenceVariable>> resolveOrder( Collection<InferenceVariable> vars, InferenceSession session) { Map<InferenceVariable, InferenceGraphNode<InferenceVariable>> nodes = new HashMap<InferenceVariable, InferenceGraphNode<InferenceVariable>>(); for (InferenceVariable var : vars) { nodes.put(var, new InferenceGraphNode<InferenceVariable>(var)); } for (InferenceVariable var : vars) { if (var.getInstantiation() != PsiType.NULL) continue; final InferenceGraphNode<InferenceVariable> node = nodes.get(var); final Set<InferenceVariable> dependencies = var.getDependencies(session); for (InferenceVariable dependentVariable : dependencies) { final InferenceGraphNode<InferenceVariable> dependency = nodes.get(dependentVariable); if (dependency != null) { node.addDependency(dependency); } } } final ArrayList<InferenceGraphNode<InferenceVariable>> acyclicNodes = initNodes(nodes.values()); return ContainerUtil.map( acyclicNodes, new Function<InferenceGraphNode<InferenceVariable>, List<InferenceVariable>>() { @Override public List<InferenceVariable> fun(InferenceGraphNode<InferenceVariable> node) { return node.getValue(); } }); }
public static <T> ArrayList<InferenceGraphNode<T>> initNodes( Collection<InferenceGraphNode<T>> allNodes) { final List<List<InferenceGraphNode<T>>> nodes = tarjan(allNodes); final ArrayList<InferenceGraphNode<T>> acyclicNodes = new ArrayList<InferenceGraphNode<T>>(); for (List<InferenceGraphNode<T>> cycle : nodes) { acyclicNodes.add(InferenceGraphNode.merge(cycle, allNodes)); } return acyclicNodes; }
private static <T> InferenceGraphNode<T> merge( final List<InferenceGraphNode<T>> cycle, final Collection<InferenceGraphNode<T>> allNodes) { assert !cycle.isEmpty(); final InferenceGraphNode<T> root = cycle.get(0); if (cycle.size() > 1) { for (int i = 1; i < cycle.size(); i++) { final InferenceGraphNode<T> cycleNode = cycle.get(i); root.copyFrom(cycleNode); root.filterInterCycleDependencies(); for (InferenceGraphNode<T> node : allNodes) { if (node.myDependencies.remove(cycleNode)) { node.myDependencies.add(root); } } } } return root; }
public static <T> List<List<InferenceGraphNode<T>>> tarjan( Collection<InferenceGraphNode<T>> nodes) { final ArrayList<List<InferenceGraphNode<T>>> result = new ArrayList<List<InferenceGraphNode<T>>>(); final Stack<InferenceGraphNode<T>> currentStack = new Stack<InferenceGraphNode<T>>(); int index = 0; for (InferenceGraphNode<T> node : nodes) { if (node.index == -1) { index += InferenceGraphNode.strongConnect(node, index, currentStack, result); } } return result; }