예제 #1
0
        /// <summary>
        /// Gets sequence 2, the last vertices right before the end vertex with a maximum of n.
        /// </summary>
        public static uint[] GetSequence2 <T>(this EdgePath <T> path, DirectedDynamicGraph.EdgeEnumerator enumerator, int n)
            where T : struct
        {
            if (path.From == null)
            {
                return(Constants.EMPTY_SEQUENCE);
            }

            return(path.GetSequence2 <T>(enumerator, n, new List <uint>()));
        }
예제 #2
0
        public void TestGetSequence2()
        {
            // build graph.
            var graph      = new DirectedDynamicGraph(ContractedEdgeDataSerializer.DynamicFixedSize);
            var e1         = graph.AddEdge(0, 1, 100, null);
            var e2         = graph.AddEdge(1, 2, 100, null);
            var e3         = graph.AddEdge(2, 6, 100, null, 4, new uint[] { 3 }, new uint[] { 5 });
            var e4         = graph.AddEdge(6, 16, 100, null, 11, new uint[] { 7, 8, 9, 10 }, new uint[] { 12, 13, 14, 15 });
            var enumerator = graph.GetEdgeEnumerator();

            // build and test getting sequences from paths.
            var path = new EdgePath <float>(0);
            var s    = path.GetSequence2(enumerator);

            Assert.IsNotNull(s);
            Assert.AreEqual(0, s.Length);

            path = new EdgePath <float>(1, 100, new EdgePath <float>(0));
            s    = path.GetSequence2(enumerator);
            Assert.IsNotNull(s);
            Assert.AreEqual(1, s.Length);
            Assert.AreEqual(0, s[0]);

            path = new EdgePath <float>(2, 200, e2 + 1, new EdgePath <float>(1, 100, new EdgePath <float>(0)));
            s    = path.GetSequence2(enumerator);
            Assert.IsNotNull(s);
            Assert.AreEqual(2, s.Length);
            Assert.AreEqual(0, s[0]);
            Assert.AreEqual(1, s[1]);

            path = new EdgePath <float>(6, 300, e3 + 1, new EdgePath <float>(2, 200, e2 + 1, new EdgePath <float>(1, 100, new EdgePath <float>(0))));
            s    = path.GetSequence2(enumerator);
            Assert.IsNotNull(s);
            Assert.AreEqual(1, s.Length);
            Assert.AreEqual(5, s[0]);

            path = new EdgePath <float>(16, 400, e4 + 1, new EdgePath <float>(6, 300, e3 + 1, new EdgePath <float>(2, 200, e2 + 1, new EdgePath <float>(1, 100, new EdgePath <float>(0)))));
            s    = path.GetSequence2(enumerator);
            Assert.IsNotNull(s);
            Assert.AreEqual(4, s.Length);
            Assert.AreEqual(12, s[0]);
            Assert.AreEqual(13, s[1]);
            Assert.AreEqual(14, s[2]);
            Assert.AreEqual(15, s[3]);
        }
예제 #3
0
 /// <summary>
 /// Gets sequence 2, the last vertices right before the end vertex.
 /// </summary>
 public static uint[] GetSequence2 <T>(this EdgePath <T> path, DirectedDynamicGraph.EdgeEnumerator enumerator)
     where T : struct
 {
     return(path.GetSequence2(enumerator, int.MaxValue));
 }
예제 #4
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            if (_heap.Count == 0)
            {
                return(false);
            }
            _current = _heap.Pop();
            while (_current != null)
            { // keep trying.
                LinkedEdgePath <T> edgePath = null;
                if (!_visits.TryGetValue(_current.Vertex, out edgePath))
                { // this vertex has not been visited before.
                    _visits.Add(_current.Vertex, new LinkedEdgePath <T>()
                    {
                        Path = _current
                    });
                    break;
                }
                else
                {     // vertex has been visited before, check if edge has.
                    if (!edgePath.HasPath(_current))
                    { // current edge has not been used to get to this vertex.
                        _visits[_current.Vertex] = new LinkedEdgePath <T>()
                        {
                            Path = _current,
                            Next = edgePath
                        };
                        break;
                    }
                }
                _current = _heap.Pop();
            }

            if (_current == null)
            {
                return(false);
            }

            if (this.WasFound != null)
            {
                this.WasFound(_current.Vertex, _current.Weight);
            }

            // get relevant restrictions.
            var restrictions = _getRestrictions(_current.Vertex);

            // get the edge enumerator.
            var currentSequence = _current.GetSequence2(_edgeEnumerator);

            currentSequence = currentSequence.Append(_current.Vertex);

            // get neighbours.
            _edgeEnumerator.MoveTo(_current.Vertex);

            // add the neighbours to the queue.
            while (_edgeEnumerator.MoveNext())
            {
                bool?neighbourDirection;
                var  neighbourWeight = _weightHandler.GetEdgeWeight(_edgeEnumerator.Current, out neighbourDirection);

                if (neighbourDirection == null || (neighbourDirection.Value != _backward))
                { // the edge is forward, and is to higher or was not contracted at all.
                    var neighbourNeighbour = _edgeEnumerator.Neighbour;
                    var neighbourSequence  = Constants.EMPTY_SEQUENCE;
                    if (_edgeEnumerator.IsOriginal())
                    {     // original edge.
                        if (currentSequence.Length > 1 && currentSequence[currentSequence.Length - 2] == neighbourNeighbour)
                        { // this is a u-turn.
                            continue;
                        }
                        if (restrictions != null)
                        {
                            neighbourSequence = currentSequence.Append(neighbourNeighbour);
                        }
                    }
                    else
                    { // not an original edge, use the sequence.
                        neighbourSequence = _edgeEnumerator.GetSequence1();
                        if (currentSequence.Length > 1 && currentSequence[currentSequence.Length - 2] == neighbourSequence[0])
                        { // this is a u-turn.
                            continue;
                        }
                        if (restrictions != null)
                        {
                            neighbourSequence = currentSequence.Append(neighbourSequence);
                        }
                    }

                    if (restrictions != null)
                    { // check restrictions.
                        if (!restrictions.IsSequenceAllowed(neighbourSequence))
                        {
                            continue;
                        }
                    }

                    // build route to neighbour and check if it has been visited already.
                    var routeToNeighbour = new EdgePath <T>(
                        neighbourNeighbour, _weightHandler.Add(_current.Weight, neighbourWeight), _edgeEnumerator.IdDirected(), _current);
                    LinkedEdgePath <T> edgePath = null;
                    if (!_visits.TryGetValue(_current.Vertex, out edgePath) ||
                        !edgePath.HasPath(routeToNeighbour))
                    { // this vertex has not been visited in this way before.
                        _heap.Push(routeToNeighbour, _weightHandler.GetMetric(routeToNeighbour.Weight));
                    }
                }
            }

            return(true);
        }
예제 #5
0
        /// <summary>
        /// Search backward from one vertex.
        /// </summary>
        /// <returns></returns>
        private void SearchBackward(DirectedDynamicGraph.EdgeEnumerator edgeEnumerator, EdgePath <T> current, IEnumerable <uint[]> restrictions)
        {
            if (current != null)
            { // there is a next vertex found.
                // get the edge enumerator.
                var currentSequence = current.GetSequence2(edgeEnumerator);
                currentSequence = currentSequence.Append(current.Vertex);

                // get neighbours.
                edgeEnumerator.MoveTo(current.Vertex);

                // add the neighbours to the queue.
                while (edgeEnumerator.MoveNext())
                {
                    bool?neighbourDirection;
                    var  neighbourWeight = _weightHandler.GetEdgeWeight(edgeEnumerator.Current, out neighbourDirection);

                    if (neighbourDirection == null || !neighbourDirection.Value)
                    { // the edge is forward, and is to higher or was not contracted at all.
                        var neighbourNeighbour = edgeEnumerator.Neighbour;
                        var neighbourSequence  = Constants.EMPTY_SEQUENCE;
                        if (edgeEnumerator.IsOriginal())
                        {     // original edge.
                            if (currentSequence.Length > 1 && currentSequence[currentSequence.Length - 2] == neighbourNeighbour)
                            { // this is a u-turn.
                                continue;
                            }
                            if (restrictions != null)
                            {
                                neighbourSequence = currentSequence.Append(neighbourNeighbour);
                            }
                        }
                        else
                        { // not an original edge, use the sequence.
                            neighbourSequence = edgeEnumerator.GetSequence1();
                            if (currentSequence.Length > 1 && currentSequence[currentSequence.Length - 2] == neighbourSequence[0])
                            { // this is a u-turn.
                                continue;
                            }
                            if (restrictions != null)
                            {
                                neighbourSequence = currentSequence.Append(neighbourSequence);
                            }
                        }

                        if (restrictions != null)
                        { // check restrictions.
                            neighbourSequence.Reverse();
                            if (!restrictions.IsSequenceAllowed(neighbourSequence))
                            {
                                continue;
                            }
                        }

                        // build route to neighbour and check if it has been visited already.
                        var routeToNeighbour = new EdgePath <T>(
                            neighbourNeighbour, _weightHandler.Add(current.Weight, neighbourWeight), edgeEnumerator.IdDirected(), current);
                        LinkedEdgePath edgePath = null;
                        if (!_backwardVisits.TryGetValue(current.Vertex, out edgePath) ||
                            !edgePath.HasPath(routeToNeighbour))
                        { // this vertex has not been visited in this way before.
                            _backwardQueue.Push(routeToNeighbour, _weightHandler.GetMetric(routeToNeighbour.Weight));
                        }
                    }
                }
            }
        }