Exemple #1
0
        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);
        }
Exemple #2
0
        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));
            }
        }
Exemple #3
0
        /// <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);
        }
Exemple #4
0
        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));
        }