/// <summary>
            /// Fills the given array with the dynamic part of the edge-data.
            /// </summary>
            public int FillWithDynamicData(ref uint[] data)
            {
                var p = _currentEdgePointer + _graph._fixedEdgeDataSize;

                if (DirectedDynamicGraph.IsLastField(_graph._edges[p]))
                { // no dynamic data!
                    return(0);
                }

                var i = 0;

                p++;
                do
                {
                    data[i] = _graph._edges[p];
                    if (DirectedDynamicGraph.IsLastField(data[i]))
                    {
                        data[i] = DirectedDynamicGraph.RemoveFlags(data[i]);
                        break;
                    }
                    i++;
                    p++;
                } while (true);
                return(i + 1);
            }
        /// <summary>
        /// Moves to the next edge and returns the pointer of that next edge. Returns NO_EDGE if no next edge was found.
        ///
        /// The given pointer is expected to be the first position of an edge.
        /// </summary>
        private uint MoveNextEdge(uint edgePointer)
        {
            // move past first fixed-data fields to the last one.
            var data = _edges[edgePointer];

            if (data == NO_EDGE)
            { // just move to the first non-NO_EDGE field.
                while (data == NO_EDGE)
                {
                    edgePointer++;
                    data = _edges[edgePointer];
                }
                return(edgePointer);
            }
            edgePointer += (uint)_fixedEdgeDataSize;
            data         = _edges[edgePointer];
            while (!DirectedDynamicGraph.IsLastField(data))
            { // move until the last data field.
                edgePointer++;
                data = _edges[edgePointer];
            }
            if (DirectedDynamicGraph.IsLastFieldInLastEdge(data))
            { // if the last data field is the last edge then just stop.
                return(NO_EDGE);
            }
            edgePointer++;
            data = _edges[edgePointer];
            while (data == NO_EDGE)
            {
                edgePointer++;
                data = _edges[edgePointer];
            }
            return(edgePointer);
        }
 /// <summary>
 /// Fills the given array with the fixed data.
 /// </summary>
 public int FillWithData(ref uint[] data)
 {
     for (var i = 0; i < _graph._fixedEdgeDataSize && i < data.Length; i++)
     {
         data[i] = DirectedDynamicGraph.RemoveFlags(_graph._edges[_currentEdgePointer + 1 + i]);
     }
     return(System.Math.Min(_graph._fixedEdgeDataSize, data.Length));
 }
Exemplo n.º 4
0
        /// <summary>
        /// Returns enumerator for the given vertex. Throws an exception if the vertex is not in the graph.
        /// </summary>
        public static DirectedDynamicGraph.EdgeEnumerator GetEdgeEnumerator(this DirectedDynamicGraph graph, uint vertex)
        {
            var enumerator = graph.GetEdgeEnumerator();

            if (!enumerator.MoveTo(vertex))
            {
                throw new Exception("Vertex does not exist.");
            }
            return(enumerator);
        }
        /// <summary>
        /// Marks the edge at the given location as the last edge.
        /// </summary>
        /// <returns>False if there is no data at the given location, true otherwise.</returns>
        private bool MarkAsLast(uint edgePointer)
        {
            var data = _edges[edgePointer];

            if (data == NO_EDGE)
            {
                return(false);
            }
            while (!DirectedDynamicGraph.IsLastField(data))
            {
                edgePointer++;
                data = _edges[edgePointer];
            }
            data = DirectedDynamicGraph.RemoveFlags(data);
            _edges[edgePointer] = DirectedDynamicGraph.AddLastEdgeAndLastFieldFlag(
                data);
            return(true);
        }
        /// <summary>
        /// Removes an edge and moves to the next edge after the removed edge. Returns NO_EDGE if no next edge was found.
        ///
        /// The given pointer is expected to be the first position of an edge starting a the given vertex. The previous edge pointer is NO_EDGE if there is not previous edge.
        /// </summary>
        private uint RemoveEdge(uint vertex, uint previousEdgePointer, uint edgePointer, uint nextPointer)
        {
            var originalEdgePointer = edgePointer;

            if (previousEdgePointer == NO_EDGE && nextPointer == NO_EDGE)
            { // only one edge left.
                _vertices[vertex] = NO_EDGE;
                return(NO_EDGE);
            }

            var startPointer = edgePointer;

            // remove the fixed-data.
            for (var i = 0; i < _fixedEdgeDataSize - 1; i++)
            {
                _edges[edgePointer] = NO_EDGE;
                edgePointer++;
            }
            var data = _edges[edgePointer];

            while (!DirectedDynamicGraph.IsLastField(data))
            { // move until the last data field.
                _edges[edgePointer] = NO_EDGE;
                edgePointer++;
                data = _edges[edgePointer];
            }
            if (DirectedDynamicGraph.IsLastFieldInLastEdge(data))
            {     // if the last data field is the last edge then just stop.
                if (!this.MarkAsLast(previousEdgePointer))
                { // there is no data at the previous edge, this can only mean one thing: no more edges left.
                    _vertices[vertex] = NO_EDGE;
                }
                return(NO_EDGE);
            }
            _edges[edgePointer] = NO_EDGE;
            return(edgePointer + 1);
        }
 /// <summary>
 /// Gets all commonly used data fields in on go.
 /// </summary>
 public void GetData(out uint neighbour, out uint data0, out uint data1)
 {
     neighbour = _graph._edges[_currentEdgePointer];
     data0     = DirectedDynamicGraph.RemoveFlags(_graph._edges[_currentEdgePointer + 0 + 1]);
     data1     = DirectedDynamicGraph.RemoveFlags(_graph._edges[_currentEdgePointer + 1 + 1]);
 }
 /// <summary>
 /// Creates a new edge enumerator.
 /// </summary>
 public EdgeEnumerator(DirectedDynamicGraph graph)
 {
     _graph = graph;
     _currentEdgePointer = NO_EDGE;
     _startPointer       = NO_EDGE;
 }
        /// <summary>
        /// Compresses the data in this graph to it's smallest size.
        /// </summary>
        public void Compress(bool toReadonly, out long maxEdgeId)
        {
            // trim first.
            this.Trim();

            // build a list of all vertices sorted by their first position.
            var sortedVertices = new MemoryArray <uint>(_vertices.Length);

            for (uint i = 0; i < sortedVertices.Length; i++)
            {
                sortedVertices[i] = i;
            }

            // sort vertices and coordinates.
            QuickSort.Sort((i) => _vertices[sortedVertices[i]] * sortedVertices.Length +
                           sortedVertices[i],
                           (i, j) =>
            {
                var tempRef       = sortedVertices[i];
                sortedVertices[i] = sortedVertices[j];
                sortedVertices[j] = tempRef;
            }, 0, this.VertexCount - 1);

            // move data down.
            uint pointer = 0;

            for (uint i = 0; i < sortedVertices.Length; i++)
            {
                var vertex        = sortedVertices[i];
                var vertexPointer = _vertices[vertex];
                if (vertexPointer == NO_EDGE)
                {
                    continue;
                }
                _vertices[vertex] = pointer;

                // skip removed data.
                var pointerBefore = pointer;
                while (_edges[vertexPointer] == NO_EDGE)
                {
                    vertexPointer++;
                }
                do
                {
                    // copy fixed-data.
                    for (var e = 0; e < _fixedEdgeDataSize; e++)
                    {
                        _edges[pointer + e] = _edges[vertexPointer + e];
                    }
                    pointer       += (uint)_fixedEdgeDataSize;
                    vertexPointer += (uint)_fixedEdgeDataSize;
                    while (!DirectedDynamicGraph.IsLastField(_edges[pointer - 1]))
                    {
                        _edges[pointer] = _edges[vertexPointer];
                        pointer++;
                        vertexPointer++;
                    }
                } while (!DirectedDynamicGraph.IsLastFieldInLastEdge(_edges[pointer - 1]));

                var count = pointer - pointerBefore;
                if (!toReadonly && count > 2 && !((count & (count - 1)) == 0))
                { // next power of 2, don't do this on readonly to save space.
                    count |= count >> 1;
                    count |= count >> 2;
                    count |= count >> 4;
                    count |= count >> 8;
                    count |= count >> 16;
                    count++;

                    pointer += (count - (pointer - pointerBefore));
                }
            }
            _nextEdgePointer = pointer;
            _readonly        = toReadonly;

            // store the max edge id.
            _edges.Resize(_nextEdgePointer);
            maxEdgeId = _edges.Length;
        }
Exemplo n.º 10
0
        /// <summary>
        /// Adds an edge with the associated data.
        /// </summary>
        public uint AddEdge(uint vertex1, uint vertex2, params uint[] data)
        {
            if (_readonly)
            {
                throw new Exception("Graph is readonly.");
            }
            if (vertex1 == vertex2)
            {
                throw new ArgumentException("Given vertices must be different.");
            }
            if (data == null || data.Length == 0)
            {
                throw new ArgumentException("Data payload must contain at least one entry.");
            }
            for (var i = 0; i < data.Length; i++)
            {
                if (data[i] > MAX_DYNAMIC_PAYLOAD)
                {
                    throw new ArgumentOutOfRangeException("data", "One of the entries in the data payload is too big.");
                }
            }
            while (vertex1 > _vertices.Length - 1)
            {
                this.IncreaseVertexSize();
            }
            while (vertex2 > _vertices.Length - 1)
            {
                this.IncreaseVertexSize();
            }

            var vertexPointer = vertex1;
            var edgePointer   = _vertices[vertexPointer];
            var edgeId        = uint.MaxValue;

            if (edgePointer == NO_EDGE)
            { // no edge yet, just add the end.
                _vertices[vertexPointer] = _nextEdgePointer;
                edgeId = _nextEdgePointer;

                if (_nextEdgePointer + data.Length >= _edges.Length)
                { // make sure we can add another edge.
                    this.IncreaseEdgeSize();
                }

                _edges[_nextEdgePointer] = vertex2;
                for (var i = 0; i < data.Length - 1; i++)
                {
                    _edges[_nextEdgePointer + i + 1] = data[i];
                }
                _edges[_nextEdgePointer + data.Length - 1 + 1] = DirectedDynamicGraph.AddLastEdgeAndLastFieldFlag(data[data.Length - 1]);
                _nextEdgePointer += DirectedDynamicGraph.NextPowerOfTwoOrPowerOfTwo((uint)(1 + data.Length));
            }
            else
            { // there are already edges present for this vertex.
                var startPointer = edgePointer;
                edgePointer += (uint)(_fixedEdgeDataSize - 1);
                while (true)
                {
                    var e = _edges[edgePointer];
                    if (e != NO_EDGE && IsLastFieldInLastEdge(e))
                    {
                        break;
                    }
                    edgePointer++;
                }

                // check size and allocate new space or move if needed.
                var size          = edgePointer - startPointer + 1;
                var totalSpace    = NextPowerOfTwoOrPowerOfTwo(size);
                var requiredSpace = size + 1 + (uint)data.Length;
                if (requiredSpace > totalSpace)
                { // allocate enough space.
                    var newTotalSpace = NextPowerOfTwoOrPowerOfTwo(requiredSpace);
                    if (startPointer + totalSpace == _nextEdgePointer)
                    { // at the end, just make sure the edges array is big enough.
                        while (newTotalSpace + startPointer >= _edges.Length)
                        {
                            this.IncreaseEdgeSize();
                        }
                        _nextEdgePointer += (newTotalSpace - totalSpace);
                    }
                    else
                    { // move everything to the end, there isn't enough free space here.
                        // make sure the edges array is big enough.
                        while (newTotalSpace + _nextEdgePointer >= _edges.Length)
                        {
                            this.IncreaseEdgeSize();
                        }

                        // move existing data to the end and update pointer.
                        _vertices[vertexPointer] = _nextEdgePointer;
                        for (uint i = 0; i < size; i++)
                        {
                            _edges[_nextEdgePointer + i] = _edges[startPointer + i];
                        }
                        edgePointer       = _nextEdgePointer + size - 1;
                        _nextEdgePointer += newTotalSpace;
                    }
                }

                // mark the current field as the non-last field.
                _edges[edgePointer] = RemoveLastEdgeFlag(_edges[edgePointer]);

                // add new data.
                _edges[edgePointer + 1] = vertex2;
                for (var i = 0; i < data.Length - 1; i++)
                {
                    _edges[edgePointer + i + 2] = data[i];
                }
                _edges[edgePointer + data.Length - 1 + 2] = DirectedDynamicGraph.AddLastEdgeAndLastFieldFlag(data[data.Length - 1]);
            }
            _edgeCount++;

            return(edgeId);
        }
Exemplo n.º 11
0
        /// <summary>
        /// Adds an edge with the associated data.
        /// </summary>
        public uint AddEdge(uint vertex1, uint vertex2, uint data)
        {
            if (_readonly)
            {
                throw new Exception("Graph is readonly.");
            }
            if (vertex1 == vertex2)
            {
                throw new ArgumentException("Given vertices must be different.");
            }
            if (data > MAX_DYNAMIC_PAYLOAD)
            {
                throw new ArgumentOutOfRangeException("data", "Data payload too big.");
            }
            _vertices.EnsureMinimumSize(Math.Max(vertex1, vertex2) + 1, NO_EDGE);

            var vertexPointer = vertex1;
            var edgePointer   = _vertices[vertexPointer];
            var edgeId        = uint.MaxValue;

            if (edgePointer == NO_EDGE)
            { // no edge yet, just add the end.
                _vertices[vertexPointer] = _nextEdgePointer;
                edgeId = _nextEdgePointer;

                // make sure we can add another edge.
                _edges.EnsureMinimumSize(_nextEdgePointer + 2);
                _edges[_nextEdgePointer]     = vertex2;
                _edges[_nextEdgePointer + 1] = DirectedDynamicGraph.AddLastEdgeAndLastFieldFlag(data);
                _nextEdgePointer            += 2;
            }
            else
            { // there are already edges present for this vertex.
                var startPointer = edgePointer;
                edgePointer += (uint)(_fixedEdgeDataSize - 1);
                while (true)
                {
                    var e = _edges[edgePointer];
                    if (e != NO_EDGE && IsLastFieldInLastEdge(e))
                    {
                        break;
                    }
                    edgePointer++;
                }

                // check size and allocate new space or move if needed.
                var size          = edgePointer - startPointer + 1;
                var totalSpace    = NextPowerOfTwoOrPowerOfTwo(size);
                var requiredSpace = size + 2;
                if (requiredSpace > totalSpace)
                { // allocate enough space.
                    var newTotalSpace = NextPowerOfTwoOrPowerOfTwo(requiredSpace);
                    if (startPointer + totalSpace == _nextEdgePointer)
                    { // at the end, just make sure the edges array is big enough.
                        _edges.EnsureMinimumSize(newTotalSpace + startPointer + 1);
                        _nextEdgePointer += (newTotalSpace - totalSpace);
                    }
                    else
                    { // move everything to the end, there isn't enough free space here.
                        // make sure the edges array is big enough.
                        _edges.EnsureMinimumSize(newTotalSpace + _nextEdgePointer + 1);

                        // move existing data to the end and update pointer.
                        _vertices[vertexPointer] = _nextEdgePointer;
                        for (uint i = 0; i < size; i++)
                        {
                            _edges[_nextEdgePointer + i] = _edges[startPointer + i];
                        }
                        edgePointer       = _nextEdgePointer + size - 1;
                        _nextEdgePointer += newTotalSpace;
                    }
                }

                // mark the current field as the non-last field.
                _edges[edgePointer] = RemoveLastEdgeFlag(_edges[edgePointer]);

                // add new data.
                edgeId = edgePointer + 1;
                _edges[edgePointer + 1] = vertex2;
                _edges[edgePointer + 2] = DirectedDynamicGraph.AddLastEdgeAndLastFieldFlag(data);
            }
            _edgeCount++;

            return(edgeId);
        }