private static int BiLayerCrossCount(IEnumerable<CrossCounterPair> pairs, int firstLayerVertexCount, int secondLayerVertexCount)
        {
            if (pairs == null)
                return 0;

            //radix sort of the pair, order by First asc, Second asc

            #region Sort by Second ASC
            var radixBySecond = new List<CrossCounterPair>[secondLayerVertexCount];
            List<CrossCounterPair> r;
            int pairCount = 0;
            foreach (var pair in pairs)
            {
                //get the radix where the pair should be inserted
                r = radixBySecond[pair.Second];
                if (r == null)
                {
                    r = new List<CrossCounterPair>();
                    radixBySecond[pair.Second] = r;
                }
                r.Add(pair);
                pairCount++;
            }
            #endregion

            #region Sort By First ASC
            var radixByFirst = new List<CrossCounterPair>[firstLayerVertexCount];
            foreach (var list in radixBySecond)
            {
                if (list == null)
                    continue;

                foreach (var pair in list)
                {
                    //get the radix where the pair should be inserted
                    r = radixByFirst[pair.First];
                    if (r == null)
                    {
                        r = new List<CrossCounterPair>();
                        radixByFirst[pair.First] = r;
                    }
                    r.Add(pair);
                }
            }
            #endregion

            //
            // Build the accumulator tree
            //
            int firstIndex = 1;
            while (firstIndex < pairCount)
                firstIndex *= 2;
            int treeSize = 2 * firstIndex - 1;
            firstIndex -= 1;
            CrossCounterTreeNode[] tree = new CrossCounterTreeNode[treeSize];
            for (int i = 0; i < treeSize; i++)
                tree[i] = new CrossCounterTreeNode();

            //
            // Count the crossings
            //
            int crossCount = 0;
            int index;
            foreach (var list in radixByFirst)
            {
                if (list == null)
                    continue;

                foreach (var pair in list)
                {
                    index = pair.Second + firstIndex;
                    tree[index].Accumulator += pair.Weight;
                    switch (pair.Markable)
                    {
                        case false:
                            tree[index].InnerSegmentMarker = true;
                            break;
                        case true:
                            tree[index].NonInnerSegmentQueue.Enqueue(pair);
                            break;
                        default:
                            break;
                    }
                    while (index > 0)
                    {
                        if (index % 2 > 0)
                        {
                            crossCount += tree[index + 1].Accumulator * pair.Weight;
                            switch (pair.Markable)
                            {
                                case false:
                                    var queue = tree[index + 1].NonInnerSegmentQueue;
                                    while (queue.Count > 0)
                                    {
                                        queue.Dequeue().Marked = true;
                                    }
                                    break;
                                case true:
                                    if (tree[index+1].InnerSegmentMarker)
                                    {
                                        pair.Marked = true;
                                    }
                                    break;
                                default:
                                    break;
                            }
                        }
                        index = (index - 1) / 2;
                        tree[index].Accumulator += pair.Weight;
                        switch (pair.Markable)
                        {
                            case false:
                                tree[index].InnerSegmentMarker = true;
                                break;
                            case true:
                                tree[index].NonInnerSegmentQueue.Enqueue(pair);
                                break;
                            default:
                                break;
                        }
                    }
                }
            }

            return crossCount;
        }
Ejemplo n.º 2
0
        private static int BiLayerCrossCount(IEnumerable <CrossCounterPair> pairs, int firstLayerVertexCount, int secondLayerVertexCount, CancellationToken cancellationToken)
        {
            if (pairs == null)
            {
                return(0);
            }

            //radix sort of the pair, order by First asc, Second asc

            #region Sort by Second ASC
            var radixBySecond = new List <CrossCounterPair> [secondLayerVertexCount];
            List <CrossCounterPair> r;
            int pairCount = 0;
            foreach (var pair in pairs)
            {
                //get the radix where the pair should be inserted
                r = radixBySecond[pair.Second];
                if (r == null)
                {
                    r = new List <CrossCounterPair>();
                    radixBySecond[pair.Second] = r;
                }
                r.Add(pair);
                pairCount = Math.Max(pairCount, pair.Second);
            }
            pairCount += 1;
            #endregion

            #region Sort By First ASC
            var radixByFirst = new List <CrossCounterPair> [firstLayerVertexCount];
            foreach (var list in radixBySecond)
            {
                if (list == null)
                {
                    continue;
                }

                foreach (var pair in list)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    //get the radix where the pair should be inserted
                    r = radixByFirst[pair.First];
                    if (r == null)
                    {
                        r = new List <CrossCounterPair>();
                        radixByFirst[pair.First] = r;
                    }
                    r.Add(pair);
                }
            }
            #endregion

            //
            // Build the accumulator tree
            //
            int firstIndex = 1;
            while (firstIndex < pairCount)
            {
                firstIndex *= 2;
            }
            int treeSize = 2 * firstIndex - 1;
            firstIndex -= 1;
            CrossCounterTreeNode[] tree = new CrossCounterTreeNode[treeSize];
            for (int i = 0; i < treeSize; i++)
            {
                tree[i] = new CrossCounterTreeNode();
            }

            //
            // Count the crossings
            //
            int crossCount = 0;
            int index;
            foreach (var list in radixByFirst)
            {
                if (list == null)
                {
                    continue;
                }

                foreach (var pair in list)
                {
                    index = pair.Second + firstIndex;
                    tree[index].Accumulator += pair.Weight;
                    switch (pair.Type)
                    {
                    case EdgeTypes.InnerSegment:
                        tree[index].InnerSegmentMarker = true;
                        break;

                    case EdgeTypes.NonInnerSegment:
                        tree[index].NonInnerSegmentQueue.Enqueue(pair.NonInnerSegment);
                        break;

                    default:
                        break;
                    }
                    while (index > 0)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (index % 2 > 0)
                        {
                            crossCount += tree[index + 1].Accumulator * pair.Weight;
                            switch (pair.Type)
                            {
                            case EdgeTypes.InnerSegment:
                                var queue = tree[index + 1].NonInnerSegmentQueue;
                                while (queue.Count > 0)
                                {
                                    queue.Dequeue().Marked = true;
                                }
                                break;

                            case EdgeTypes.NonInnerSegment:
                                if (tree[index + 1].InnerSegmentMarker)
                                {
                                    pair.NonInnerSegment.Marked = true;
                                }
                                break;

                            default:
                                break;
                            }
                        }
                        index = (index - 1) / 2;
                        tree[index].Accumulator += pair.Weight;
                        switch (pair.Type)
                        {
                        case EdgeTypes.InnerSegment:
                            tree[index].InnerSegmentMarker = true;
                            break;

                        case EdgeTypes.NonInnerSegment:
                            tree[index].NonInnerSegmentQueue.Enqueue(pair.NonInnerSegment);
                            break;

                        default:
                            break;
                        }
                    }
                }
            }

            return(crossCount);
        }
Ejemplo n.º 3
0
        private int BiLayerCrossCount(
            [CanBeNull, ItemNotNull] IEnumerable <CrossCounterPair> pairs,
            int firstLayerVertexCount,
            int secondLayerVertexCount)
        {
            if (pairs is null)
            {
                return(0);
            }

            // Radix sort of the pairs, order by First asc, Second asc

            #region Sort by Second ASC

            var radixBySecond = new List <CrossCounterPair> [secondLayerVertexCount];
            List <CrossCounterPair> r;
            int pairCount = 0;
            foreach (CrossCounterPair pair in pairs)
            {
                // Get the radix where the pair should be inserted
                r = radixBySecond[pair.Second];
                if (r is null)
                {
                    r = new List <CrossCounterPair>();
                    radixBySecond[pair.Second] = r;
                }
                r.Add(pair);
                pairCount = Math.Max(pairCount, pair.Second);
            }

            ++pairCount;

            #endregion

            #region Sort By First ASC

            var radixByFirst = new List <CrossCounterPair> [firstLayerVertexCount];
            foreach (List <CrossCounterPair> list in radixBySecond)
            {
                if (list is null)
                {
                    continue;
                }

                foreach (CrossCounterPair pair in list)
                {
                    ThrowIfCancellationRequested();

                    // Get the radix where the pair should be inserted
                    r = radixByFirst[pair.First];
                    if (r is null)
                    {
                        r = new List <CrossCounterPair>();
                        radixByFirst[pair.First] = r;
                    }
                    r.Add(pair);
                }
            }

            #endregion

            // Build the accumulator tree
            int firstIndex = 1;
            while (firstIndex < pairCount)
            {
                firstIndex *= 2;
            }
            int treeSize = 2 * firstIndex - 1;
            --firstIndex;
            var tree = new CrossCounterTreeNode[treeSize];
            for (int i = 0; i < treeSize; ++i)
            {
                tree[i] = new CrossCounterTreeNode();
            }

            // Count the crossings
            int crossCount = 0;
            foreach (List <CrossCounterPair> list in radixByFirst)
            {
                if (list is null)
                {
                    continue;
                }

                foreach (CrossCounterPair pair in list)
                {
                    int index = pair.Second + firstIndex;
                    tree[index].Accumulator += pair.Weight;
                    switch (pair.Type)
                    {
                    case EdgeTypes.InnerSegment:
                        tree[index].InnerSegmentMarker = true;
                        break;

                    case EdgeTypes.NonInnerSegment:
                        tree[index].NonInnerSegmentQueue.Enqueue(pair.NonInnerSegment);
                        break;
                    }

                    while (index > 0)
                    {
                        ThrowIfCancellationRequested();

                        if (index % 2 > 0)
                        {
                            crossCount += tree[index + 1].Accumulator * pair.Weight;
                            switch (pair.Type)
                            {
                            case EdgeTypes.InnerSegment:
                                Queue <SugiEdge> queue = tree[index + 1].NonInnerSegmentQueue;
                                while (queue.Count > 0)
                                {
                                    queue.Dequeue().Marked = true;
                                }
                                break;

                            case EdgeTypes.NonInnerSegment:
                                if (tree[index + 1].InnerSegmentMarker)
                                {
                                    pair.NonInnerSegment.Marked = true;
                                }
                                break;
                            }
                        }

                        index = (index - 1) / 2;
                        tree[index].Accumulator += pair.Weight;

                        switch (pair.Type)
                        {
                        case EdgeTypes.InnerSegment:
                            tree[index].InnerSegmentMarker = true;
                            break;

                        case EdgeTypes.NonInnerSegment:
                            tree[index].NonInnerSegmentQueue.Enqueue(pair.NonInnerSegment);
                            break;
                        }
                    }
                }
            }

            return(crossCount);
        }