public static IEnumerable <GraphNodeGrouping> ConnectedComponentLayering(this ExpressionBuilderGraph source) { int layerOffset = 0; GraphNodeGrouping singletonLayer = null; List <GraphNodeGrouping> layers = new List <GraphNodeGrouping>(); var connectedComponents = FindConnectedComponents(source); foreach (var component in connectedComponents) { var layeredComponent = component .LongestPathLayering() .SortLayerEdgeLabels() .RemoveSuccessorKinks() .ToList(); if (component.Count == 1) { if (singletonLayer == null) { singletonLayer = layeredComponent[0]; } else { var layer = layeredComponent[0]; singletonLayer.Add(layer[0]); } continue; } MergeSingletonComponentLayers(ref singletonLayer, layers, ref layerOffset); MergeConnectedComponentLayers(layeredComponent, layers, ref layerOffset); } MergeSingletonComponentLayers(ref singletonLayer, layers, ref layerOffset); return(layers); }
static bool RemoveBranchKinks(GraphNodeGrouping[] layers) { // Backward pass var removed = false; for (int i = 0; i < layers.Length; i++) { var layer = layers[i]; if (i > 0) { var sortedLayer = new GraphNodeGrouping(layer.Key); foreach (var node in layer) { if (node.Successors != Enumerable.Empty <GraphEdge>()) { var minSuccessorLayer = node.Successors.Min(edge => edge.Node.LayerIndex); while (sortedLayer.Count < minSuccessorLayer) { var dummyNode = new GraphNode(null, layer.Key, Enumerable.Empty <GraphEdge>()); sortedLayer.Add(dummyNode); removed = true; } } sortedLayer.Add(node); } layers[i] = sortedLayer; } } return(removed); }
public static IEnumerable <GraphNodeGrouping> SortLayerEdgeLabels(this IEnumerable <GraphNodeGrouping> source) { var layers = source.ToArray(); for (int i = 0; i < layers.Length; i++) { var layer = layers[i]; if (i > 0) { var nodeOrder = from node in layer from edge in node.Successors orderby edge.Node.LayerIndex, edge.Label group node by node into g select g.Key; var sortedLayer = new GraphNodeGrouping(layer.Key); foreach (var node in nodeOrder) { sortedLayer.Add(node); } layers[i] = sortedLayer; } } return(layers); }
public static IEnumerable <GraphNodeGrouping> LongestPathLayering(this ExpressionBuilderGraph source) { Dictionary <int, GraphNodeGrouping> layers = new Dictionary <int, GraphNodeGrouping>(); foreach (var layeredNode in ComputeLongestPathLayering(source)) { if (!layers.TryGetValue(layeredNode.Layer, out GraphNodeGrouping layer)) { layer = new GraphNodeGrouping(layeredNode.Layer); layers.Add(layer.Key, layer); } layer.Insert(0, layeredNode); } return(layers.Values); }
static void MergeSingletonComponentLayers(ref GraphNodeGrouping singletonLayer, List <GraphNodeGrouping> layers, ref int layerOffset) { if (singletonLayer != null) { var layeredSingleton = new List <GraphNodeGrouping>(); for (int i = 0; i < singletonLayer.Count; i++) { var node = singletonLayer[i]; var group = new GraphNodeGrouping(singletonLayer.Count - i - 1); node.Layer = group.Key; group.Add(node); layeredSingleton.Insert(0, group); } MergeConnectedComponentLayers(layeredSingleton, layers, ref layerOffset); singletonLayer = null; } }
static bool RemoveMergeGaps(GraphNodeGrouping[] layers) { // Forward pass var removed = false; var predecessorMap = new Dictionary <GraphNode, IEnumerable <GraphEdge> >(); for (int i = layers.Length - 1; i >= 0; i--) { var layer = layers[i]; if (i < layers.Length - 1) { var sortedLayer = new GraphNodeGrouping(layer.Key); foreach (var node in layer) { if (predecessorMap.TryGetValue(node, out IEnumerable <GraphEdge> nodePredecessors)) { var minSuccessorLayer = nodePredecessors.Min(edge => edge.Node.LayerIndex); while (sortedLayer.Count < minSuccessorLayer) { var dummyNode = new GraphNode(null, layer.Key, Enumerable.Empty <GraphEdge>()); sortedLayer.Add(dummyNode); removed = true; } } sortedLayer.Add(node); } layers[i] = sortedLayer; } predecessorMap.Clear(); foreach (var group in (from node in layers[i] from successor in node.Successors group new GraphEdge(null, null, node) by successor.Node)) { predecessorMap.Add(group.Key, group); } } return(removed); }