Пример #1
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            if (_pointerHeap.Count == 0)
            {
                return(false);
            }

            var  cPointer = _pointerHeap.Pop();
            uint cVertex, cPrevious;
            T    cWeight;

            _weightHandler.GetPathTree(_pathTree, cPointer, out cVertex, out cWeight, out cPrevious);

            if (_visited.Contains(cVertex))
            {
                return(true);
            }
            _visited.Add(cVertex);

            if (this.WasFound != null)
            {
                if (this.WasFound(cPointer, cVertex, cWeight))
                { // when true is returned, the listener signals it knows what it wants to know.
                    return(false);
                }
            }

            _edgeEnumerator.MoveTo(cVertex);
            while (_edgeEnumerator.MoveNext())
            {
                var nWeight = _weightHandler.GetEdgeWeight(_edgeEnumerator);

                if ((!_backward && nWeight.Direction.F) ||
                    (_backward && nWeight.Direction.B))
                { // the edge is forward, and is to higher or was not contracted at all.
                    var nVertex     = _edgeEnumerator.Neighbour;
                    var totalWeight = _weightHandler.Add(nWeight.Weight, cWeight);
                    if (!_weightHandler.IsSmallerThan(totalWeight, _max))
                    {
                        continue;
                    }
                    var nPointer = _weightHandler.AddPathTree(_pathTree, nVertex, totalWeight, cPointer);
                    _pointerHeap.Push(nPointer, _weightHandler.GetMetric(totalWeight));
                }
            }
            return(true);
        }
Пример #2
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            // while the visit list is not empty.
            var cPointer = uint.MaxValue;

            while (cPointer == uint.MaxValue)
            { // choose the next edge.
                if (_pointerHeap.Count == 0)
                {
                    return(false);
                }
                cPointer = _pointerHeap.Pop();
            }

            // get details.
            uint cEdge, cPreviousPointer;
            T    cWeight;

            _weightHandler.GetPathTree(_pathTree, cPointer, out cEdge, out cWeight, out cPreviousPointer);
            if (_visits.Contains(cEdge))
            {
                return(true);
            }
            _visits.Add(cEdge);
            var cDirectedEdge = new DirectedEdgeId()
            {
                Raw = cEdge
            };

            // signal was found.
            if (this.WasFound != null)
            {
                this.WasFound(cPointer, cDirectedEdge, cWeight);
            }

            // move to the current edge's target vertex.
            _edgeEnumerator.MoveToEdge(cDirectedEdge.EdgeId);
            var cOriginalEdge = new OriginalEdge(_edgeEnumerator.From, _edgeEnumerator.To);

            if (!cDirectedEdge.Forward)
            {
                cOriginalEdge = cOriginalEdge.Reverse();
            }
            var cEdgeWeightAndDirection = _weightHandler.GetEdgeWeight(_edgeEnumerator);

            // calculate total weight.
            var totalWeight = _weightHandler.Add(cEdgeWeightAndDirection.Weight, cWeight);

            if (!_weightHandler.IsSmallerThan(totalWeight, _sourceMax))
            { // weight is too big.
                this.MaxReached = true;
                return(true);
            }

            // loop over all neighbours.
            _edgeEnumerator.MoveTo(cOriginalEdge.Vertex2);
            var turn = new Turn(cOriginalEdge, Constants.NO_VERTEX);

            _restrictions.Update(turn.Vertex2);
            while (_edgeEnumerator.MoveNext())
            {
                turn.Vertex3 = _edgeEnumerator.To;
                if (turn.IsUTurn ||
                    turn.IsRestrictedBy(_restrictions))
                { // turn is restricted.
                    continue;
                }

                var nDirectedEdgeId = _edgeEnumerator.DirectedEdgeId();
                if (_visits.Contains(nDirectedEdgeId.Raw))
                { // has already been choosen.
                    continue;
                }

                // get the speed from cache or calculate.
                var nWeightAndDirection = _weightHandler.GetEdgeWeight(_edgeEnumerator);
                var nWeightMetric       = _weightHandler.GetMetric(nWeightAndDirection.Weight);
                if (nWeightMetric <= 0)
                { // edge is not valid for profile.
                    continue;
                }
                if (!_backward && !nWeightAndDirection.Direction.F)
                { // cannot do forward search on edge.
                    continue;
                }
                if (_backward && !nWeightAndDirection.Direction.B)
                { // cannot do backward on edge.
                    continue;
                }

                // update the visit list.
                _pointerHeap.Push(_weightHandler.AddPathTree(_pathTree, nDirectedEdgeId.Raw, totalWeight, cPointer), _weightHandler.GetMetric(totalWeight));
            }
            return(true);
        }
Пример #3
0
        /// <summary>
        /// Executes the actual run.
        /// </summary>
        protected override void DoRun(CancellationToken cancellationToken)
        {
            // keep settled vertices.
            _pathTree = new PathTree();

            // initialize the queues.
            var forwardQueue  = new BinaryHeap <uint>();
            var backwardQueue = new BinaryHeap <uint>();

            // queue sources.
            if (_source.Vertex1 != Constants.NO_VERTEX)
            {
                forwardQueue.Push(_weightHandler.AddPathTree(_pathTree, _source.Vertex1, _source.Weight1, uint.MaxValue), 0);
            }
            if (_source.Vertex2 != Constants.NO_VERTEX)
            {
                forwardQueue.Push(_weightHandler.AddPathTree(_pathTree, _source.Vertex2, _source.Weight2, uint.MaxValue), 0);
            }

            // queue targets.
            if (_target.Vertex1 != Constants.NO_VERTEX)
            {
                backwardQueue.Push(_weightHandler.AddPathTree(_pathTree, _target.Vertex1, _target.Weight1, uint.MaxValue), 0);
            }
            if (_target.Vertex2 != Constants.NO_VERTEX)
            {
                backwardQueue.Push(_weightHandler.AddPathTree(_pathTree, _target.Vertex2, _target.Weight2, uint.MaxValue), 0);
            }

            // update best with current visits.
            _best = new Tuple <uint, uint, T>(uint.MaxValue, uint.MaxValue, _weightHandler.Infinite);

            // calculate stopping conditions.
            var queueBackwardWeight = backwardQueue.PeekWeight();
            var queueForwardWeight  = forwardQueue.PeekWeight();

            while (true)
            {     // keep looping until stopping conditions.
                if (backwardQueue.Count == 0 && forwardQueue.Count == 0)
                { // stop the search; both queues are empty.
                    break;
                }
                var bestItem2 = _weightHandler.GetMetric(_best.Item3);
                if (bestItem2 < queueForwardWeight && bestItem2 < queueBackwardWeight)
                { // stop the search: it now became impossible to find a shorter route by further searching.
                    break;
                }

                // do a forward search.
                if (forwardQueue.Count > 0)
                { // first check for better path.
                    // get the current queued with the smallest weight that hasn't been visited yet.
                    var  cPointer = forwardQueue.Pop();
                    uint cVertex, cPreviousPointer;
                    T    cWeight;
                    _weightHandler.GetPathTree(_pathTree, cPointer, out cVertex, out cWeight, out cPreviousPointer);
                    while (_forwardVisits.ContainsKey(cVertex))
                    { // keep trying.
                        if (forwardQueue.Count == 0)
                        {
                            cPointer = uint.MaxValue;
                        }
                        else
                        {
                            cPointer = forwardQueue.Pop();
                            _weightHandler.GetPathTree(_pathTree, cPointer, out cVertex, out cWeight, out cPreviousPointer);
                        }
                    }

                    if (cPointer != uint.MaxValue)
                    {
                        uint bPointer;
                        if (_backwardVisits.TryGetValue(cVertex, out bPointer))
                        { // check for a new best.
                            uint bVertex, bPreviousPointer;
                            T    bWeight;
                            _weightHandler.GetPathTree(_pathTree, bPointer, out bVertex, out bWeight, out bPreviousPointer);
                            var total = _weightHandler.Add(cWeight, bWeight);
                            if (_weightHandler.IsSmallerThan(total, _best.Item2))
                            { // a better path was found.
                                _best             = new Tuple <uint, uint, T>(cPointer, bPointer, total);
                                this.HasSucceeded = true;
                            }
                        }

                        this.SearchForward(forwardQueue, cPointer, cVertex, cWeight);
                    }
                }

                // do a backward search.
                if (backwardQueue.Count > 0)
                {// first check for better path.
                    // get the current queued with the smallest weight that hasn't been visited yet.
                    var  cPointer = backwardQueue.Pop();
                    uint cVertex, cPreviousPointer;
                    T    cWeight;
                    _weightHandler.GetPathTree(_pathTree, cPointer, out cVertex, out cWeight, out cPreviousPointer);
                    while (_backwardVisits.ContainsKey(cVertex))
                    { // keep trying.
                        if (backwardQueue.Count == 0)
                        {
                            cPointer = uint.MaxValue;
                        }
                        else
                        {
                            cPointer = backwardQueue.Pop();
                            _weightHandler.GetPathTree(_pathTree, cPointer, out cVertex, out cWeight, out cPreviousPointer);
                        }
                    }

                    if (cPointer != uint.MaxValue)
                    {
                        uint bPointer; // best pointer.
                        if (_forwardVisits.TryGetValue(cVertex, out bPointer))
                        {              // check for a new best.
                            uint bVertex, bPreviousPointer;
                            T    bWeight;
                            _weightHandler.GetPathTree(_pathTree, bPointer, out bVertex, out bWeight, out bPreviousPointer);
                            var total = _weightHandler.Add(cWeight, bWeight);
                            if (_weightHandler.IsSmallerThan(total, _best.Item2))
                            { // a better path was found.
                                _best             = new Tuple <uint, uint, T>(bPointer, cPointer, total);
                                this.HasSucceeded = true;
                            }
                        }

                        this.SearchBackward(backwardQueue, cPointer, cVertex, cWeight);
                    }
                }

                // calculate stopping conditions.
                if (forwardQueue.Count > 0)
                {
                    queueForwardWeight = forwardQueue.PeekWeight();
                }
                if (backwardQueue.Count > 0)
                {
                    queueBackwardWeight = backwardQueue.PeekWeight();
                }
            }
        }