/** * Sorts the linear segments of the given layered graph by finding a topological ordering in the * corresponding segment ordering graph. * * @param layeredGraph layered graph to process * @return a sorted array of linear segments */ private LinearSegment[] sortLinearSegments(final LGraph layeredGraph) { // set the identifier and input / output priority for all nodes List<LinearSegment> segmentList = Lists.newArrayList(); for (Layer layer : layeredGraph) { for (LNode node : layer) { node.id = -1; int inprio = Integer.MIN_VALUE, outprio = Integer.MIN_VALUE; for (LPort port : node.getPorts()) { for (LEdge edge : port.getIncomingEdges()) { int prio = edge.getProperty(InternalProperties.PRIORITY); inprio = Math.max(inprio, prio); } for (LEdge edge : port.getOutgoingEdges()) { int prio = edge.getProperty(InternalProperties.PRIORITY); outprio = Math.max(outprio, prio); } } node.setProperty(INPUT_PRIO, inprio); node.setProperty(OUTPUT_PRIO, outprio); } } // create linear segments for the layered graph, ignoring odd port side dummies int nextLinearSegmentID = 0; for (Layer layer : layeredGraph) { for (LNode node : layer) { // Test for the node ID; calls to fillSegment(...) may have caused the node ID // to be != -1. if (node.id < 0) { LinearSegment segment = new LinearSegment(); segment.id = nextLinearSegmentID++; fillSegment(node, segment); segmentList.add(segment); } } } // create and initialize segment ordering graph List<List<LinearSegment>> outgoingList = Lists.newArrayListWithCapacity(segmentList.size()); List<Integer> incomingCountList = Lists.newArrayListWithCapacity(segmentList.size()); for (int i = 0; i < segmentList.size(); i++) { outgoingList.add(new ArrayList<LinearSegment>()); incomingCountList.add(0); } // create edges for the segment ordering graph createDependencyGraphEdges(layeredGraph, segmentList, outgoingList, incomingCountList); // turn lists into arrays LinearSegment[] segments = segmentList.toArray(new LinearSegment[segmentList.size()]); @SuppressWarnings("unchecked") List<LinearSegment>[] outgoing = outgoingList.toArray(new List[outgoingList.size()]); int[] incomingCount = new int[incomingCountList.size()]; for (int i = 0; i < incomingCount.length; i++) { incomingCount[i] = incomingCountList.get(i); } // gather the sources of the segment ordering graph int nextRank = 0; List<LinearSegment> noIncoming = Lists.newArrayList(); for (int i = 0; i < segments.length; i++) { if (incomingCount[i] == 0) { noIncoming.add(segments[i]); } } // find a topological ordering of the segment ordering graph int[] newRanks = new int[segments.length]; while (!noIncoming.isEmpty()) { LinearSegment segment = noIncoming.remove(0); newRanks[segment.id] = nextRank++; while (!outgoing[segment.id].isEmpty()) { LinearSegment target = outgoing[segment.id].remove(0); incomingCount[target.id]--; if (incomingCount[target.id] == 0) { noIncoming.add(target); } } } // apply the new ordering to the array of linear segments linearSegments = new LinearSegment[segments.length]; for (int i = 0; i < segments.length; i++) { assert outgoing[i].isEmpty(); LinearSegment ls = segments[i]; int rank = newRanks[i]; linearSegments[rank] = ls; ls.id = rank; for (LNode node : ls.nodes) { node.id = rank; } } return linearSegments; }