private int CrossingMinimizationBetweenLayers( [NotNull, ItemNotNull] ref AlternatingLayer alternatingLayer, int actualLayerIndex, int nextLayerIndex, bool enableSameMeasureOptimization, int prevCrossCount, int phase) { // Decide which way we are sweeping (up or down) // Straight = down, reverse = up bool straightSweep = actualLayerIndex < nextLayerIndex; AlternatingLayer nextAlternatingLayer = alternatingLayer.Clone(); // 1 AppendSegmentsToAlternatingLayer(nextAlternatingLayer, straightSweep); // 2 ComputeMeasureValues(alternatingLayer, nextLayerIndex, straightSweep); nextAlternatingLayer.SetPositions(); // 3 nextAlternatingLayer = InitialOrderingOfNextLayer(nextAlternatingLayer, _layers[nextLayerIndex], straightSweep); // 4 PlaceQVertices(nextAlternatingLayer, _layers[nextLayerIndex], straightSweep); nextAlternatingLayer.SetPositions(); // 5 int crossCount = DoCrossCountingAndOptimization( alternatingLayer, nextAlternatingLayer, straightSweep, enableSameMeasureOptimization, phase == 2, prevCrossCount); // 6 nextAlternatingLayer.EnsureAlternatingAndPositions(); alternatingLayer = nextAlternatingLayer; return(crossCount); }
private int DoCrossCountingAndOptimization( AlternatingLayer alternatingLayer, AlternatingLayer nextAlternatingLayer, bool straightSweep, bool enableSameMeasureOptimization, bool reverseVerticesWithSameMeasure, int prevCrossCount, CancellationToken cancellationToken) { IList <CrossCounterPair> virtualEdgePairs, realEdgePairs; IList <SugiEdge> realEdges; var topLayer = straightSweep ? alternatingLayer : nextAlternatingLayer; var bottomLayer = straightSweep ? nextAlternatingLayer : alternatingLayer; int firstLayerSize, secondLayerSize; var lastOnTopLayer = topLayer[topLayer.Count - 1]; var lastOnBottomLayer = bottomLayer[bottomLayer.Count - 1]; firstLayerSize = lastOnTopLayer.Position + (lastOnTopLayer is ISegmentContainer ? ((ISegmentContainer)lastOnTopLayer).Count : 1); secondLayerSize = lastOnBottomLayer.Position + (lastOnBottomLayer is ISegmentContainer ? ((ISegmentContainer)lastOnBottomLayer).Count : 1); virtualEdgePairs = FindVirtualEdgePairs(topLayer, bottomLayer); realEdges = FindRealEdges(topLayer, cancellationToken); if (enableSameMeasureOptimization || reverseVerticesWithSameMeasure) { IList <int> ranges; int maxRangeLength; var verticesWithSameMeasure = FindVerticesWithSameMeasure(cancellationToken, nextAlternatingLayer, straightSweep, out ranges, out maxRangeLength); var verticesWithSameMeasureSet = new HashSet <SugiVertex>(verticesWithSameMeasure); //initialize permutation indices for (int i = 0; i < verticesWithSameMeasure.Count; i++) { verticesWithSameMeasure[i].PermutationIndex = i; } int bestCrossCount = prevCrossCount; foreach (var realEdge in realEdges) { realEdge.SaveMarkedToTemp(); } List <SugiVertex> sortedVertexList = null; if (!reverseVerticesWithSameMeasure) { sortedVertexList = new List <SugiVertex>(verticesWithSameMeasure); } else { sortedVertexList = new List <SugiVertex>(verticesWithSameMeasure.Count); var stack = new Stack <SugiVertex>(verticesWithSameMeasure.Count); var rnd = new System.Random(DateTime.Now.Millisecond); foreach (var v in verticesWithSameMeasure) { if (stack.Count > 0 && (stack.Peek().MeasuredPosition != v.MeasuredPosition || rnd.NextDouble() > 0.8)) { while (stack.Count > 0) { sortedVertexList.Add(stack.Pop()); } } stack.Push(v); } while (stack.Count > 0) { sortedVertexList.Add(stack.Pop()); } } int maxPermutations = EfficientSugiyamaLayoutParameters.MAX_PERMUTATIONS; do { maxPermutations--; if (!reverseVerticesWithSameMeasure) { //sort by permutation index and measure sortedVertexList.Sort(new Comparison <SugiVertex>( (v1, v2) => { if (v1.MeasuredPosition != v2.MeasuredPosition) { return(Math.Sign(v1.MeasuredPosition - v2.MeasuredPosition)); } else { return(v1.PermutationIndex - v2.PermutationIndex); } })); } //reinsert the vertices into the layer ReinsertVerticesIntoLayer(nextAlternatingLayer, verticesWithSameMeasureSet, sortedVertexList); //set the positions nextAlternatingLayer.SetPositions(); realEdgePairs = ConvertRealEdgesToCrossCounterPairs(realEdges, true); var edgePairs = new List <CrossCounterPair>(); edgePairs.AddRange(virtualEdgePairs); edgePairs.AddRange(realEdgePairs); int crossCount = BiLayerCrossCount(edgePairs, firstLayerSize, secondLayerSize, cancellationToken); if (reverseVerticesWithSameMeasure) { return(crossCount); } //if the crosscount is better than the best known //save the actual state if (crossCount < bestCrossCount) { foreach (var vertex in verticesWithSameMeasure) { vertex.SavePositionToTemp(); } foreach (var edge in realEdges) { edge.SaveMarkedToTemp(); } bestCrossCount = crossCount; } if (crossCount == 0) { break; } } while (maxPermutations > 0 && Permutate(verticesWithSameMeasure, ranges)); //reload the best solution foreach (var vertex in verticesWithSameMeasure) { vertex.LoadPositionFromTemp(); } foreach (var edge in realEdges) { edge.LoadMarkedFromTemp(); } //sort by permutation index and measure sortedVertexList.Sort(new Comparison <SugiVertex>((v1, v2) => v1.Position - v2.Position)); //reinsert the vertices into the layer ReinsertVerticesIntoLayer(nextAlternatingLayer, verticesWithSameMeasureSet, sortedVertexList); nextAlternatingLayer.SetPositions(); return(bestCrossCount); } else { realEdgePairs = ConvertRealEdgesToCrossCounterPairs(realEdges, true); var edgePairs = new List <CrossCounterPair>(); edgePairs.AddRange(virtualEdgePairs); edgePairs.AddRange(realEdgePairs); return(BiLayerCrossCount(edgePairs, firstLayerSize, secondLayerSize, cancellationToken)); } }
/// <summary> /// Sweeps between the <paramref name="startLayerIndex"/> and <paramref name="endLayerIndex"/> /// in the way represented by the step. /// </summary> /// <param name="startLayerIndex">The index of the start layer (where the sweeping starts from).</param> /// <param name="endLayerIndex">The index of the last layer (where the sweeping ends).</param> /// <param name="step">Increment or decrement of the layer index. (1 or -1)</param> /// <param name="enableSameMeasureOptimization">Indicates if the same measure optimization is enabled.</param> /// <param name="changed">Indicates if layer has changed or not.</param> /// <param name="phase">Algorithm phase.</param> /// <returns>The number of the edge crossings.</returns> private int Sweeping( int startLayerIndex, int endLayerIndex, int step, bool enableSameMeasureOptimization, out bool changed, ref int phase) { int crossings = 0; changed = false; AlternatingLayer alternatingLayer; AlternatingLayer layer = _alternatingLayers[startLayerIndex]; if (layer is null) { alternatingLayer = new AlternatingLayer(); alternatingLayer.AddRange( _layers[startLayerIndex] #if !SUPPORTS_ENUMERABLE_COVARIANT .OfType <IData>() #endif ); alternatingLayer.EnsureAlternatingAndPositions(); AddAlternatingLayerToSparseCompactionGraph(alternatingLayer, startLayerIndex); _alternatingLayers[startLayerIndex] = alternatingLayer; } else { alternatingLayer = layer; } for (int i = startLayerIndex; i != endLayerIndex; i += step) { int ci = Math.Min(i, i + step); int prevCrossCount = _crossCounts[ci]; AlternatingLayer nextAlternatingLayer = _alternatingLayers[i + step]; if (nextAlternatingLayer != null) { alternatingLayer?.SetPositions(); nextAlternatingLayer.SetPositions(); prevCrossCount = DoCrossCountingAndOptimization( alternatingLayer, nextAlternatingLayer, i < i + step, false, phase == 2, int.MaxValue); _crossCounts[ci] = prevCrossCount; } int crossCount = CrossingMinimizationBetweenLayers( ref alternatingLayer, i, i + step, enableSameMeasureOptimization, prevCrossCount, phase); if (crossCount < prevCrossCount || phase == 2 || changed) { // Set the sparse compaction graph AddAlternatingLayerToSparseCompactionGraph(alternatingLayer, i + step); ReplaceLayer(alternatingLayer, i + step); _alternatingLayers[i + step] = alternatingLayer; _crossCounts[i] = crossCount; crossings += crossCount; changed = true; } else { alternatingLayer = nextAlternatingLayer; crossings += prevCrossCount; } } return(crossings); }
private int DoCrossCountingAndOptimization( [ItemNotNull] AlternatingLayer alternatingLayer, [ItemNotNull] AlternatingLayer nextAlternatingLayer, bool straightSweep, bool enableSameMeasureOptimization, bool reverseVerticesWithSameMeasure, int prevCrossCount) { AlternatingLayer topLayer = straightSweep ? alternatingLayer : nextAlternatingLayer; AlternatingLayer bottomLayer = straightSweep ? nextAlternatingLayer : alternatingLayer; IData lastOnTopLayer = topLayer[topLayer.Count - 1]; IData lastOnBottomLayer = bottomLayer[bottomLayer.Count - 1]; int firstLayerSize = lastOnTopLayer.Position + (lastOnTopLayer is ISegmentContainer topContainer ? topContainer.Count : 1); int secondLayerSize = lastOnBottomLayer.Position + (lastOnBottomLayer is ISegmentContainer bottomContainer ? bottomContainer.Count : 1); IList <CrossCounterPair> virtualEdgePairs = FindVirtualEdgePairs(topLayer, bottomLayer); IList <SugiEdge> realEdges = FindRealEdges(topLayer); if (enableSameMeasureOptimization || reverseVerticesWithSameMeasure) { IList <SugiVertex> verticesWithSameMeasure = FindVerticesWithSameMeasure( nextAlternatingLayer, straightSweep, out IList <int> ranges, out _); var verticesWithSameMeasureSet = new HashSet <SugiVertex>(verticesWithSameMeasure); // Initialize permutation indices for (int i = 0; i < verticesWithSameMeasure.Count; ++i) { verticesWithSameMeasure[i].PermutationIndex = i; } int bestCrossCount = prevCrossCount; foreach (SugiEdge realEdge in realEdges) { realEdge.SaveMarkedToTemp(); } List <SugiVertex> sortedVertexList = ComputeSortedVertexList( verticesWithSameMeasure, reverseVerticesWithSameMeasure); int maxPermutations = SugiyamaLayoutParameters.MaxPermutations; do { --maxPermutations; if (!reverseVerticesWithSameMeasure) { // Sort by permutation index and measure sortedVertexList.Sort((v1, v2) => { if (!NearEqual(v1.MeasuredPosition, v2.MeasuredPosition)) { return(Math.Sign(v1.MeasuredPosition - v2.MeasuredPosition)); } return(v1.PermutationIndex - v2.PermutationIndex); }); } // Reinsert the vertices into the layer ReinsertVerticesIntoLayer(nextAlternatingLayer, verticesWithSameMeasureSet, sortedVertexList); // Set the positions nextAlternatingLayer.SetPositions(); var edgePairs = new List <CrossCounterPair>(); edgePairs.AddRange(virtualEdgePairs); edgePairs.AddRange(ConvertRealEdgesToCrossCounterPairs(realEdges, true)); int crossCount = BiLayerCrossCount(edgePairs, firstLayerSize, secondLayerSize); if (reverseVerticesWithSameMeasure) { return(crossCount); } // If the cross count is better than the best known // save the actual state if (crossCount < bestCrossCount) { foreach (SugiVertex vertex in verticesWithSameMeasure) { vertex.SavePositionToTemp(); } foreach (SugiEdge edge in realEdges) { edge.SaveMarkedToTemp(); } bestCrossCount = crossCount; } if (crossCount == 0) { break; } } while (maxPermutations > 0 && Swap(verticesWithSameMeasure, ranges)); // Reload the best solution foreach (SugiVertex vertex in verticesWithSameMeasure) { vertex.LoadPositionFromTemp(); } foreach (SugiEdge edge in realEdges) { edge.LoadMarkedFromTemp(); } // Sort by permutation index and measure sortedVertexList.Sort((v1, v2) => v1.Position - v2.Position); // Reinsert the vertices into the layer ReinsertVerticesIntoLayer(nextAlternatingLayer, verticesWithSameMeasureSet, sortedVertexList); nextAlternatingLayer.SetPositions(); return(bestCrossCount); } var pairs = new List <CrossCounterPair>(); pairs.AddRange(virtualEdgePairs); pairs.AddRange(ConvertRealEdgesToCrossCounterPairs(realEdges, true)); return(BiLayerCrossCount(pairs, firstLayerSize, secondLayerSize)); }