/// <inheritdoc/>
            public UndirectedIndexedIncidenceGraph ToGraph()
            {
                int n = _vertexCount;
                int m = _tailByEdge.Count;

                Debug.Assert(_tailByEdge.Count == _headByEdge.Count, "_tailByEdge.Count == _headByEdge.Count");

                int dataLength = 2 + n + m + m + m + m;

#if NET5
                int[] data = GC.AllocateUninitializedArray <int>(dataLength);
#else
                int[] data = new int[dataLength];
#endif
                data[0] = n;
                data[1] = m;

                Span <int> destEdgesOrderedByTail = data.AsSpan(2 + n, m + m);
                int        invertedEdgeCount      = 0;
                for (int edge = 0; edge < m; ++edge)
                {
                    destEdgesOrderedByTail[edge] = edge;
                    int head = _headByEdge[edge];
                    int tail = _tailByEdge[edge];
                    if (head != tail)
                    {
                        destEdgesOrderedByTail[m + invertedEdgeCount++] = ~edge;
                    }
                }

                int directedEdgeCount = m + invertedEdgeCount;
                Array.Sort(data, 2 + n, directedEdgeCount,
                           new UndirectedIndexedEdgeComparer(_tailByEdge.Array, _headByEdge.Array));

                Span <int> destUpperBoundByVertex = data.AsSpan(2, n);
                destUpperBoundByVertex.Clear();
                for (int i = 0; i < directedEdgeCount; ++i)
                {
                    int edge = destEdgesOrderedByTail[i];
                    int tail = edge < 0 ? _headByEdge[~edge] : _tailByEdge[edge];
                    ++destUpperBoundByVertex[tail];
                }

                for (int vertex = 1; vertex < n; ++vertex)
                {
                    destUpperBoundByVertex[vertex] += destUpperBoundByVertex[vertex - 1];
                }

                Span <int> destHeadByEdge = data.AsSpan(2 + n + m + m, m);
                _headByEdge.AsSpan().CopyTo(destHeadByEdge);

                Span <int> destTailByEdge = data.AsSpan(2 + n + m + m + m, m);
                _tailByEdge.AsSpan().CopyTo(destTailByEdge);

                _headByEdge  = ArrayPrefixBuilder.Release(_headByEdge, false);
                _tailByEdge  = ArrayPrefixBuilder.Release(_tailByEdge, false);
                _vertexCount = 0;

                return(new UndirectedIndexedIncidenceGraph(data));
            }
Пример #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MutableUndirectedSimpleIncidenceGraph"/> class.
        /// </summary>
        /// <param name="initialVertexCount">The initial number of vertices.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="initialVertexCount"/> is less than zero.
        /// </exception>
        public MutableUndirectedSimpleIncidenceGraph(int initialVertexCount = 0)
        {
            if (initialVertexCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(initialVertexCount));
            }

            _outEdgesByVertex = ArrayPrefixBuilder.EnsureSize(_outEdgesByVertex, initialVertexCount, true);
        }
            /// <inheritdoc/>
            public IndexedIncidenceGraph ToGraph()
            {
                int n = _vertexCount;
                int m = _tailByEdge.Count;

                Debug.Assert(_tailByEdge.Count == _headByEdge.Count, "_tailByEdge.Count == _headByEdge.Count");

                int dataLength = 2 + n + m + m + m;

#if NET5
                int[] data = GC.AllocateUninitializedArray <int>(dataLength);
#else
                int[] data = new int[dataLength];
#endif
                data[0] = n;
                data[1] = m;

                Span <int> destReorderedEdges = data.AsSpan(2 + n, m);
                for (int edge = 0; edge < m; ++edge)
                {
                    destReorderedEdges[edge] = edge;
                }

                if (NeedsReordering)
                {
                    Array.Sort(data, 2 + n, m, new IndexedEdgeComparer(_tailByEdge.Array));
                }

                Span <int> destUpperBoundByVertex = data.AsSpan(2, n);
                destUpperBoundByVertex.Clear();
                for (int edge = 0; edge < m; ++edge)
                {
                    int tail = _tailByEdge[edge];
                    ++destUpperBoundByVertex[tail];
                }

                for (int vertex = 1; vertex < n; ++vertex)
                {
                    destUpperBoundByVertex[vertex] += destUpperBoundByVertex[vertex - 1];
                }

                Span <int> destHeadByEdge = data.AsSpan(2 + n + m, m);
                _headByEdge.AsSpan().CopyTo(destHeadByEdge);

                Span <int> destTailByEdge = data.AsSpan(2 + n + m + m, m);
                _tailByEdge.AsSpan().CopyTo(destTailByEdge);

                _currentMaxTail = 0;
                _headByEdge     = ArrayPrefixBuilder.Release(_headByEdge, false);
                _tailByEdge     = ArrayPrefixBuilder.Release(_tailByEdge, false);
                _vertexCount    = 0;

                return(new IndexedIncidenceGraph(data));
            }
            /// <inheritdoc/>
            public SimpleIncidenceGraph ToGraph()
            {
                int n = _vertexCount;
                int m = _edges.Count;

                Endpoints[] array = _edges.Array;
                Debug.Assert(array != null, nameof(array) + " != null");

                if (NeedsReordering)
                {
                    Array.Sort(array, 0, m, SimpleEdgeComparer.Instance);
                }

                Endpoints[] edgesOrderedByTail;
                if (array.Length == _edges.Count)
                {
                    edgesOrderedByTail = array;
                    _edges             = ArrayPrefix <Endpoints> .Empty;
                }
                else
                {
#if NET5
                    edgesOrderedByTail = GC.AllocateUninitializedArray <Endpoints>(m);
#else
                    edgesOrderedByTail = new Endpoints[m];
#endif
                    _edges.CopyTo(edgesOrderedByTail);
                    _edges = ArrayPrefixBuilder.Release(_edges, false);
                }

                int[] data = new int[2 + n];
                data[0] = n;
                data[1] = m;

                Span <int> destUpperBoundByVertex = data.AsSpan(2);
                foreach (Endpoints edge in edgesOrderedByTail)
                {
                    int tail = edge.Tail;
                    ++destUpperBoundByVertex[tail];
                }

                for (int vertex = 1; vertex < n; ++vertex)
                {
                    destUpperBoundByVertex[vertex] += destUpperBoundByVertex[vertex - 1];
                }

                _currentMaxTail = 0;
                _vertexCount    = 0;

                return(new SimpleIncidenceGraph(data, edgesOrderedByTail));
            }
            /// <summary>
            /// Initializes a new instance of the <see cref="Builder"/> class.
            /// </summary>
            /// <param name="initialVertexCount">The initial number of vertices.</param>
            /// <param name="edgeCapacity">The initial capacity of the internal backing storage for the edges.</param>
            /// <exception cref="ArgumentOutOfRangeException">
            /// <paramref name="initialVertexCount"/> is less than zero, or <paramref name="edgeCapacity"/> is less than zero.
            /// </exception>
            public Builder(int initialVertexCount = 0, int edgeCapacity = 0)
            {
                if (initialVertexCount < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(initialVertexCount));
                }

                if (edgeCapacity < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(edgeCapacity));
                }

                _edges       = ArrayPrefixBuilder.Create <Endpoints>(edgeCapacity);
                _vertexCount = initialVertexCount;
            }
            private Endpoints UncheckedAdd(int tail, int head)
            {
                _currentMaxTail = tail < _currentMaxTail ? int.MaxValue : tail;
                int newVertexCountCandidate = Math.Max(tail, head) + 1;

                if (newVertexCountCandidate > _vertexCount)
                {
                    _vertexCount = newVertexCountCandidate;
                }

                var edge = new Endpoints(tail, head);

                _edges = ArrayPrefixBuilder.Add(_edges, edge, false);

                return(edge);
            }
            private int UncheckedAdd(int tail, int head)
            {
                int newVertexCountCandidate = Math.Max(tail, head) + 1;

                if (newVertexCountCandidate > _vertexCount)
                {
                    _vertexCount = newVertexCountCandidate;
                }

                Debug.Assert(_tailByEdge.Count == _headByEdge.Count, "_tailByEdge.Count == _headByEdge.Count");
                int edge = _tailByEdge.Count;

                _tailByEdge = ArrayPrefixBuilder.Add(_tailByEdge, tail, false);
                _headByEdge = ArrayPrefixBuilder.Add(_headByEdge, head, false);

                return(edge);
            }
Пример #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MutableIndexedIncidenceGraph"/> class.
        /// </summary>
        /// <param name="initialVertexCount">The initial number of vertices.</param>
        /// <param name="edgeCapacity">The initial capacity of the internal backing storage for the edges.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="initialVertexCount"/> is less than zero, or <paramref name="edgeCapacity"/> is less than zero.
        /// </exception>
        public MutableIndexedIncidenceGraph(int initialVertexCount = 0, int edgeCapacity = 0)
        {
            if (initialVertexCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(initialVertexCount));
            }

            if (edgeCapacity < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(edgeCapacity));
            }

            int effectiveEdgeCapacity = Math.Max(edgeCapacity, DefaultInitialOutDegree);

            _tailByEdge       = ArrayPrefixBuilder.Create <int>(effectiveEdgeCapacity);
            _headByEdge       = ArrayPrefixBuilder.Create <int>(effectiveEdgeCapacity);
            _outEdgesByVertex = ArrayPrefixBuilder.Create <ArrayPrefix <int> >(initialVertexCount);
        }
Пример #9
0
            private Endpoints UncheckedAdd(int tail, int head)
            {
                int newVertexCountCandidate = Math.Max(tail, head) + 1;

                if (newVertexCountCandidate > _vertexCount)
                {
                    _vertexCount = newVertexCountCandidate;
                }

                var edge = new Endpoints(tail, head);

                _edges = ArrayPrefixBuilder.Add(_edges, edge, false);
                ++_edgeCount;

                if (tail != head)
                {
                    var invertedEdge = new Endpoints(head, tail);
                    _edges = ArrayPrefixBuilder.Add(_edges, invertedEdge, false);
                }

                return(edge);
            }