Пример #1
0
        /// <summary>
        /// Called when a forward vertex was found.
        /// </summary>
        /// <returns></returns>
        private bool ForwardVertexFound(Dykstra <T> dykstra, int i, uint pointer, uint vertex, T weight)
        {
            Dictionary <int, EdgePath <T> > bucket;

            if (!_buckets.TryGetValue(vertex, out bucket))
            {
                bucket = new Dictionary <int, EdgePath <T> >();
                _buckets.Add(vertex, bucket);
                bucket[i] = dykstra.GetPath(pointer);
            }
            else
            {
                EdgePath <T> existing;
                if (bucket.TryGetValue(i, out existing))
                {
                    if (_weightHandler.IsSmallerThan(weight, existing.Weight))
                    {
                        bucket[i] = dykstra.GetPath(pointer);
                    }
                }
                else
                {
                    bucket[i] = dykstra.GetPath(pointer);
                }
            }
            return(false);
        }
Пример #2
0
        /// <summary>
        /// Called when a forward vertex was found.
        /// </summary>
        /// <returns></returns>
        private bool ForwardVertexFound(int i, uint vertex, T weight)
        {
            Dictionary <int, T> bucket;

            if (!_buckets.TryGetValue(vertex, out bucket))
            {
                bucket = new Dictionary <int, T>();
                _buckets.Add(vertex, bucket);
                bucket[i] = weight;
            }
            else
            {
                T existing;
                if (bucket.TryGetValue(i, out existing))
                {
                    if (_weightHandler.IsSmallerThan(weight, existing))
                    {
                        bucket[i] = weight;
                    }
                }
                else
                {
                    bucket[i] = weight;
                }
            }
            return(false);
        }
Пример #3
0
        /// <summary>
        /// Called when a forward vertex was found.
        /// </summary>
        /// <returns></returns>
        private bool ForwardVertexFound(int i, EdgePath <T> path)
        {
            Dictionary <int, EdgePath <T> > bucket;

            if (!_buckets.TryGetValue(path.Vertex, out bucket))
            {
                bucket = new Dictionary <int, EdgePath <T> >();
                _buckets.Add(path.Vertex, bucket);
                bucket[i] = path;
            }
            else
            {
                EdgePath <T> existing;
                if (bucket.TryGetValue(i, out existing))
                {
                    if (_weightHandler.IsSmallerThan(path.Weight, existing.Weight))
                    {
                        bucket[i] = path;
                    }
                }
                else
                {
                    bucket[i] = path;
                }
            }
            return(false);
        }
Пример #4
0
        /// <summary>
        /// Removes witnessed shortcuts.
        /// </summary>
        /// <param name="shortcuts"></param>
        /// <param name="witnesses"></param>
        /// <returns></returns>
        public static bool RemoveWitnessed <T>(this Shortcuts <T> shortcuts, WeightHandler <T> weightHandler, Dictionary <OriginalEdge, T> witnesses)
            where T : struct
        {
            bool witnessed = false;

            foreach (var witness in witnesses)
            {
                var edge = witness.Key;
                if (shortcuts.TryGetValue(edge, out Shortcut <T> shortcut))
                {
                    if (weightHandler.IsSmallerThan(witness.Value, shortcut.Forward))
                    {
                        shortcut.Forward = witness.Value;
                        shortcuts.AddOrUpdate(edge, shortcut, weightHandler);
                        witnessed = true;
                    }
                }
                // TODO: this should be 'else', in theory this extra check isn't needed.
                edge = edge.Reverse();
                if (shortcuts.TryGetValue(edge, out shortcut))
                {
                    if (weightHandler.IsSmallerThan(witness.Value, shortcut.Backward))
                    {
                        shortcut.Backward = witness.Value;
                        shortcuts.AddOrUpdate(edge, shortcut, weightHandler);
                        witnessed = true;
                    }
                }
            }
            return(witnessed);
        }
Пример #5
0
        /// <summary>
        /// Finds the best edge between the two given vertices.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="graph"></param>
        /// <param name="weightHandler"></param>
        /// <param name="vertex1"></param>
        /// <param name="vertex2"></param>
        /// <returns></returns>
        public static long FindBestEdge <T>(this Graph.EdgeEnumerator edgeEnumerator, WeightHandler <T> weightHandler, uint vertex1, uint vertex2, out T bestWeight)
            where T : struct
        {
            edgeEnumerator.MoveTo(vertex1);
            bestWeight = weightHandler.Infinite;
            long   bestEdge = Constants.NO_EDGE;
            Factor factor;

            while (edgeEnumerator.MoveNext())
            {
                if (edgeEnumerator.To == vertex2)
                {
                    float  distance;
                    ushort edgeProfile;
                    EdgeDataSerializer.Deserialize(edgeEnumerator.Data0, out distance, out edgeProfile);
                    var weight = weightHandler.Calculate(edgeProfile, distance, out factor);

                    if (factor.Value > 0 && (factor.Direction == 0 ||
                                             ((factor.Direction == 1) && !edgeEnumerator.DataInverted) ||
                                             ((factor.Direction == 2) && edgeEnumerator.DataInverted)))
                    { // it's ok; the edge can be traversed by the given vehicle.
                        if (weightHandler.IsSmallerThan(weight, bestWeight))
                        {
                            bestWeight = weight;
                            bestEdge   = edgeEnumerator.IdDirected();
                        }
                    }
                }
            }
            if (bestEdge == Constants.NO_EDGE)
            {
                edgeEnumerator.Reset();
                while (edgeEnumerator.MoveNext())
                {
                    if (edgeEnumerator.To == vertex2)
                    {
                        float  distance;
                        ushort edgeProfile;
                        EdgeDataSerializer.Deserialize(edgeEnumerator.Data0, out distance, out edgeProfile);
                        var weight = weightHandler.Calculate(edgeProfile, distance, out factor);

                        //if (factor.Value > 0 && (factor.Direction == 0 ||
                        //    ((factor.Direction == 1) && !edgeEnumerator.DataInverted) ||
                        //    ((factor.Direction == 2) && edgeEnumerator.DataInverted)))
                        //{ // it's ok; the edge can be traversed by the given vehicle.
                        if (weightHandler.IsSmallerThan(weight, bestWeight))
                        {
                            bestWeight = weight;
                            bestEdge   = edgeEnumerator.IdDirected();
                        }
                        //}
                    }
                }
            }
            return(bestEdge);
        }
Пример #6
0
        /// <summary>
        /// Called when a backward vertex was found.
        /// </summary>
        /// <returns></returns>
        protected virtual bool BackwardVertexFound(int i, uint vertex, LinkedEdgePath <T> backwardVisit)
        {
            Dictionary <int, LinkedEdgePath <T> > bucket;

            if (_buckets.TryGetValue(vertex, out bucket))
            {
                var edgeEnumerator = _graph.GetEdgeEnumerator();

                var originalBackwardVisit = backwardVisit;
                foreach (var pair in bucket)
                {
                    var best = _weights[pair.Key][i];

                    var forwardVisit = pair.Value;
                    while (forwardVisit != null)
                    {
                        var forwardCurrent = forwardVisit.Path;
                        if (_weightHandler.IsLargerThan(forwardCurrent.Weight, best))
                        {
                            forwardVisit = forwardVisit.Next;
                            continue;
                        }
                        backwardVisit = originalBackwardVisit;
                        while (backwardVisit != null)
                        {
                            var backwardCurrent    = backwardVisit.Path;
                            var totalCurrentWeight = _weightHandler.Add(forwardCurrent.Weight, backwardCurrent.Weight);
                            if (_weightHandler.IsSmallerThan(totalCurrentWeight, best))
                            { // potentially a weight improvement.
                                var allowed = true;

                                // check u-turn.
                                var sequence2Forward = backwardCurrent.GetSequence2(edgeEnumerator);
                                var sequence2Current = forwardCurrent.GetSequence2(edgeEnumerator);
                                if (sequence2Current != null && sequence2Current.Length > 0 &&
                                    sequence2Forward != null && sequence2Forward.Length > 0)
                                {
                                    if (sequence2Current[sequence2Current.Length - 1] ==
                                        sequence2Forward[sequence2Forward.Length - 1])
                                    {
                                        allowed = false;
                                    }
                                }

                                if (allowed)
                                {
                                    best = totalCurrentWeight;
                                }
                            }
                            backwardVisit = backwardVisit.Next;
                        }
                        forwardVisit = forwardVisit.Next;
                    }

                    _weights[pair.Key][i] = best;
                }
            }
            return(false);
        }
Пример #7
0
        /// <summary>
        /// Executes the algorithm.
        /// </summary>
        protected override void DoRun()
        {
            _bestVertex            = uint.MaxValue;
            _bestWeight            = _weightHandler.Infinite;
            _maxForward            = _weightHandler.Zero;
            _maxBackward           = _weightHandler.Zero;
            _sourceSearch.WasFound = (vertex, weight) =>
            {
                _maxForward = weight;
                return(this.ReachedVertexForward(vertex, weight));
            };
            _targetSearch.WasFound = (vertex, weight) =>
            {
                _maxBackward = weight;
                return(this.ReachedVertexBackward(vertex, weight));
            };

            _sourceSearch.Initialize();
            _targetSearch.Initialize();
            var source = true;
            var target = true;

            while (source || target)
            {
                source = false;
                if (_weightHandler.IsSmallerThan(_maxForward, _bestWeight))
                { // still a need to search, not best found or max < best.
                    source = _sourceSearch.Step();
                }
                target = false;
                if (_weightHandler.IsSmallerThan(_maxBackward, _bestWeight))
                { // still a need to search, not best found or max < best.
                    target = _targetSearch.Step();
                }

                if (!source && !target)
                { // both source and target search failed or useless.
                    break;
                }
            }
        }
Пример #8
0
        /// <summary>
        /// Executes the algorithm.
        /// </summary>
        protected override void DoRun(CancellationToken cancellationToken)
        {
            _best               = new Tuple <EdgePath <T>, EdgePath <T>, T>(null, null, _weightHandler.Infinite);
            _maxForward         = _weightHandler.Zero;
            _maxBackward        = _weightHandler.Zero;
            _sourceSearch.Visit = (path) =>
            {
                _maxForward = path.Weight;
                return(this.ReachedForward(path));
            };
            _targetSearch.Visit = (path) =>
            {
                _maxBackward = path.Weight;
                return(this.ReachedBackward(path));
            };

            _sourceSearch.Initialize();
            _targetSearch.Initialize();
            var source = true;
            var target = true;

            while (source || target)
            {
                source = false;
                if (_weightHandler.IsSmallerThan(_maxForward, _best.Item3))
                { // still a need to search, not best found or max < best.
                    source = _sourceSearch.Step();
                }
                target = false;
                if (_weightHandler.IsSmallerThan(_maxBackward, _best.Item3))
                { // still a need to search, not best found or max < best.
                    target = _targetSearch.Step();
                }

                if (!source && !target)
                { // both source and target search failed or useless.
                    break;
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Gets the best path in this linked list.
        /// </summary>
        public EdgePath <T> Best(WeightHandler <T> weightHandler)
        {
            var best    = this.Path;
            var current = this.Next;

            while (current != null)
            {
                if (weightHandler.IsSmallerThan(current.Path.Weight, best.Weight))
                {
                    best = current.Path;
                }
                current = current.Next;
            }
            return(best);
        }
Пример #10
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);
        }
Пример #11
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            // while the visit list is not empty.
            _current = null;
            if (_heap.Count > 0)
            { // choose the next vertex.
                _current = _heap.Pop();
                while (_current != null && _visits.ContainsKey(_current.Vertex))
                {     // keep dequeuing.
                    if (_heap.Count == 0)
                    { // nothing more to pop.
                        break;
                    }

                    if (this.Visit != null &&
                        this.Visit(_current))
                    { // edge was found and true was returned, this search should stop.
                        return(false);
                    }

                    _current = _heap.Pop();
                }
            }

            if (_current != null &&
                !_visits.ContainsKey(_current.Vertex))
            { // we visit this one, set visit.
                _visits[_current.Vertex] = _current;
            }
            else
            { // route is not found, there are no vertices left
                // or the search went outside of the max bounds.
                return(false);
            }

            if (this.WasFound != null &&
                this.WasFound(_current.Vertex, _current.Weight))
            { // vertex was found and true was returned, this search should stop.
                return(false);
            }

            // check for restrictions.
            var restriction = Constants.NO_VERTEX;

            if (_getRestriction != null)
            {
                restriction = _getRestriction(_current.Vertex);
            }
            if (restriction != Constants.NO_VERTEX)
            { // this vertex is restricted, step is a success but just move
                // to the next one because this vertex's neighbours are not allowed.
                return(true);
            }

            if (this.Visit != null &&
                this.Visit(_current))
            { // edge was found and true was returned, this search should stop.
                return(false);
            }

            // get neighbours and queue them.
            _edgeEnumerator.MoveTo(_current.Vertex);
            while (_edgeEnumerator.MoveNext())
            {
                var edge      = _edgeEnumerator;
                var neighbour = edge.To;

                if (_current.From != null &&
                    _current.From.Vertex == neighbour)
                { // don't go back
                    continue;
                }

                if (this.Visit == null)
                {
                    if (_visits.ContainsKey(neighbour))
                    { // has already been choosen
                        continue;
                    }
                }

                // get the speed from cache or calculate.
                float  distance;
                ushort edgeProfile;
                EdgeDataSerializer.Deserialize(edge.Data0, out distance, out edgeProfile);
                var factor      = Factor.NoFactor;
                var totalWeight = _weightHandler.Add(_current.Weight, edgeProfile, distance, out factor);

                // check the tags against the interpreter.
                if (factor.Value > 0 && (factor.Direction == 0 ||
                                         (!_backward && (factor.Direction == 1) != edge.DataInverted) ||
                                         (_backward && (factor.Direction == 1) == edge.DataInverted)))
                { // it's ok; the edge can be traversed by the given vehicle.
                    // calculate neighbors weight.
                    var edgeWeight = (distance * factor.Value);

                    if (_weightHandler.IsSmallerThan(totalWeight, _sourceMax))
                    { // update the visit list.
                        _heap.Push(new EdgePath <T>(neighbour, totalWeight, edge.IdDirected(), _current),
                                   _weightHandler.GetMetric(totalWeight));
                    }
                    else
                    { // the maxium was reached.
                        this.MaxReached = true;
                    }
                }
            }
            return(true);
        }
Пример #12
0
        /// <summary>
        /// Calculates a route between the two locations.
        /// </summary>
        /// <returns></returns>
        public sealed override Result <EdgePath <T> > TryCalculateRaw <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target,
                                                                          RoutingSettings <T> settings)
        {
            try
            {
                if (!_db.Supports(profileInstance.Profile))
                {
                    return(new Result <EdgePath <T> >("Routing profile is not supported.", (message) =>
                    {
                        return new Exception(message);
                    }));
                }

                var maxSearch = weightHandler.Infinite;
                if (settings != null)
                {
                    if (!settings.TryGetMaxSearch(profileInstance.Profile.FullName, out maxSearch))
                    {
                        maxSearch = weightHandler.Infinite;
                    }
                }

                ContractedDb contracted;

                bool useContracted = false;
                if (_db.TryGetContracted(profileInstance.Profile, out contracted))
                { // contracted calculation.
                    useContracted = true;
                    if (_db.HasComplexRestrictions(profileInstance.Profile) &&
                        (!contracted.HasEdgeBasedGraph && !contracted.NodeBasedIsEdgedBased))
                    { // there is no edge-based graph for this profile but the db has complex restrictions, don't use the contracted graph.
                        Logging.Logger.Log("Router", Logging.TraceEventType.Warning,
                                           "There is a vertex-based contracted graph but also complex restrictions. Not using the contracted graph, add an edge-based contracted graph.");
                        useContracted = false;
                    }
                }

                EdgePath <T> path = null;
                if (source.EdgeId == target.EdgeId)
                { // check for a path on the same edge.
                    var edgePath = source.EdgePathTo(_db, weightHandler, target);
                    if (edgePath != null)
                    {
                        path = edgePath;
                    }
                }

                if (useContracted)
                {  // use the contracted graph.
                    List <uint> vertexPath = null;

                    if (contracted.HasEdgeBasedGraph)
                    { // use edge-based routing.
                        var bidirectionalSearch = new Itinero.Algorithms.Contracted.EdgeBased.BidirectionalDykstra <T>(contracted.EdgeBasedGraph, weightHandler,
                                                                                                                       source.ToEdgePaths(_db, weightHandler, true), target.ToEdgePaths(_db, weightHandler, false), _db.GetGetRestrictions(profileInstance.Profile, null));
                        bidirectionalSearch.Run();
                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            if (path == null)
                            {
                                return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                                {
                                    return new RouteNotFoundException(message);
                                }));
                            }
                        }
                        else
                        {
                            vertexPath = bidirectionalSearch.GetPath();
                        }
                    }
                    else if (contracted.NodeBasedIsEdgedBased)
                    {// use vertex-based graph for edge-based routing.
                        var sourceDirectedId1 = new DirectedEdgeId(source.EdgeId, true);
                        var sourceDirectedId2 = new DirectedEdgeId(source.EdgeId, false);
                        var targetDirectedId1 = new DirectedEdgeId(target.EdgeId, true);
                        var targetDirectedId2 = new DirectedEdgeId(target.EdgeId, false);

                        var bidirectionalSearch = new Itinero.Algorithms.Contracted.BidirectionalDykstra <T>(contracted.NodeBasedGraph, null, weightHandler,
                                                                                                             new EdgePath <T>[] { new EdgePath <T>(sourceDirectedId1.Raw), new EdgePath <T>(sourceDirectedId2.Raw) },
                                                                                                             new EdgePath <T>[] { new EdgePath <T>(targetDirectedId1.Raw), new EdgePath <T>(targetDirectedId2.Raw) });
                        bidirectionalSearch.Run();

                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }

                        var directedEdgePath = Algorithms.Dual.BidirectionalDykstraExtensions.GetDualPath(bidirectionalSearch);

                        // convert directed edge-path to an original vertex path.
                        var enumerator = _db.Network.GetEdgeEnumerator();
                        vertexPath = new List <uint>();
                        var edge = new List <OriginalEdge>();
                        for (var i = 0; i < directedEdgePath.Count; i++)
                        {
                            var e = new DirectedEdgeId()
                            {
                                Raw = directedEdgePath[i]
                            };

                            enumerator.MoveToEdge(e.EdgeId);
                            var original = new OriginalEdge(enumerator.From, enumerator.To);
                            if (!e.Forward)
                            {
                                original = original.Reverse();
                            }
                            edge.Add(original);
                            if (vertexPath.Count == 0)
                            {
                                vertexPath.Add(original.Vertex1);
                            }
                            vertexPath.Add(original.Vertex2);
                        }

                        vertexPath[0] = Constants.NO_VERTEX;
                        vertexPath[vertexPath.Count - 1] = Constants.NO_VERTEX;
                    }
                    else
                    {  // use node-based routing.
                        var bidirectionalSearch = new Itinero.Algorithms.Contracted.BidirectionalDykstra <T>(contracted.NodeBasedGraph, _db.GetRestrictions(profileInstance.Profile), weightHandler,
                                                                                                             source.ToEdgePaths(_db, weightHandler, true), target.ToEdgePaths(_db, weightHandler, false));
                        bidirectionalSearch.Run();
                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            if (path == null)
                            {
                                return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                                {
                                    return new RouteNotFoundException(message);
                                }));
                            }
                        }
                        else
                        {
                            vertexPath = Algorithms.Contracted.BidirectionalDykstraExtensions.GetPath(bidirectionalSearch);
                        }
                    }

                    // expand vertex path using the regular graph.
                    if (vertexPath != null)
                    {
                        var localPath = _db.BuildEdgePath(weightHandler, source, target, vertexPath);
                        if (path == null ||
                            weightHandler.IsSmallerThan(localPath.Weight, path.Weight))
                        {
                            path = localPath;
                        }
                    }
                }
                else
                { // use the regular graph.
                    EdgePath <T> localPath = null;

                    if (_db.HasComplexRestrictions(profileInstance.Profile))
                    {
                        var sourceSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler,
                                                                                        _db.GetGetRestrictions(profileInstance.Profile, true), source.ToEdgePaths(_db, weightHandler, true), maxSearch, false);
                        var targetSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler,
                                                                                        _db.GetGetRestrictions(profileInstance.Profile, false), target.ToEdgePaths(_db, weightHandler, false), maxSearch, true);

                        var bidirectionalSearch = new Algorithms.Default.EdgeBased.BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler);
                        bidirectionalSearch.Run();
                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            if (path == null)
                            {
                                return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                                {
                                    return new RouteNotFoundException(message);
                                }));
                            }
                        }
                        else
                        {
                            localPath = bidirectionalSearch.GetPath();
                        }
                    }
                    else
                    {
                        var sourceSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, _db.GetGetSimpleRestrictions(profileInstance.Profile), weightHandler,
                                                           source.ToEdgePaths(_db, weightHandler, true), maxSearch, false);
                        var targetSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, _db.GetGetSimpleRestrictions(profileInstance.Profile), weightHandler,
                                                           target.ToEdgePaths(_db, weightHandler, false), maxSearch, true);

                        var bidirectionalSearch = new BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler);
                        bidirectionalSearch.Run();
                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            if (path == null)
                            {
                                return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                                {
                                    return new RouteNotFoundException(message);
                                }));
                            }
                        }
                        else
                        {
                            localPath = bidirectionalSearch.GetPath();
                        }
                    }

                    // choose best path.
                    if (localPath != null)
                    {
                        if (path == null ||
                            weightHandler.IsSmallerThan(localPath.Weight, path.Weight))
                        {
                            path = localPath;
                        }
                    }
                }
                return(new Result <EdgePath <T> >(path));
            }
            catch (Exception ex)
            {
                return(new Result <EdgePath <T> >(ex.Message, (m) => ex));
            }
        }
Пример #13
0
        /// <summary>
        /// Executes the actual run.
        /// </summary>
        protected override void DoRun()
        {
            // keep settled vertices.
            _forwardVisits  = new Dictionary <uint, EdgePath <T> >();
            _backwardVisits = new Dictionary <uint, EdgePath <T> >();

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

            // queue sources.
            foreach (var source in _sources)
            {
                forwardQueue.Push(source, _weightHandler.GetMetric(source.Weight));
            }

            // queue targets.
            foreach (var target in _targets)
            {
                backwardQueue.Push(target, _weightHandler.GetMetric(target.Weight));
            }

            // update best with current visits.
            _best = new Tuple <uint, T>(Constants.NO_VERTEX, _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;
                }
                if (_weightHandler.GetMetric(_best.Item2) < queueForwardWeight &&
                    _weightHandler.GetMetric(_best.Item2) < 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 current = forwardQueue.Pop();
                    while (current != null && _forwardVisits.ContainsKey(current.Vertex))
                    { // keep trying.
                        current = forwardQueue.Pop();
                    }

                    if (current != null)
                    {
                        EdgePath <T> toBest;
                        if (_backwardVisits.TryGetValue(current.Vertex, out toBest))
                        { // check for a new best.
                            var total = _weightHandler.Add(current.Weight, toBest.Weight);
                            if (_weightHandler.IsSmallerThan(total, _best.Item2))
                            { // a better path was found.
                                _best             = new Tuple <uint, T>(current.Vertex, total);
                                this.HasSucceeded = true;
                            }
                        }

                        this.SearchForward(forwardQueue, current);
                    }
                }

                // do a backward search.
                if (backwardQueue.Count > 0)
                {// first check for better path.
                    // get the current vertex with the smallest weight.
                    var current = backwardQueue.Pop();
                    while (current != null && _backwardVisits.ContainsKey(current.Vertex))
                    { // keep trying.
                        current = backwardQueue.Pop();
                    }

                    if (current != null)
                    {
                        EdgePath <T> toBest;
                        if (_forwardVisits.TryGetValue(current.Vertex, out toBest))
                        { // check for a new best.
                            var total = _weightHandler.Add(current.Weight, toBest.Weight);
                            if (_weightHandler.IsSmallerThan(total, _best.Item2))
                            { // a better path was found.
                                _best             = new Tuple <uint, T>(current.Vertex, total);
                                this.HasSucceeded = true;
                            }
                        }

                        this.SearchBackward(backwardQueue, current);
                    }
                }

                // calculate stopping conditions.
                if (forwardQueue.Count > 0)
                {
                    queueForwardWeight = forwardQueue.PeekWeight();
                }
                if (backwardQueue.Count > 0)
                {
                    queueBackwardWeight = backwardQueue.PeekWeight();
                }
            }
        }
Пример #14
0
        private void DoDualBased()
        {
            var uniqueSet = new HashSet <DirectedEdgeId>();
            var sources   = new List <DirectedEdgeId>(_correctedResolvedPoints.Count * 2);

            for (var i = 0; i < _correctedResolvedPoints.Count; i++)
            {
                var f = new DirectedEdgeId(_correctedResolvedPoints[i].EdgeId, false);
                if (!uniqueSet.Contains(f))
                {
                    sources.Add(f);
                    sources.Add(new DirectedEdgeId(_correctedResolvedPoints[i].EdgeId, true));
                    uniqueSet.Add(f);
                }
            }

            var dykstraSources = Itinero.Algorithms.Contracted.Dual.DykstraSourceExtensions.ToDykstraSources <T>(sources);
            var dykstraTargets = Itinero.Algorithms.Contracted.Dual.DykstraSourceExtensions.ToDykstraSources <T>(sources);
            var algorithm      = new Itinero.Algorithms.Contracted.Dual.ManyToMany.VertexToVertexWeightAlgorithm <T>(_dualGraph, _weightHandler,
                                                                                                                     dykstraSources, dykstraTargets, _max);

            algorithm.Run();

            var map = new Dictionary <uint, int>();

            for (var i = 0; i < sources.Count; i += 2)
            {
                map[sources[i].EdgeId] = i / 2;
            }

            for (var s = 0; s < _correctedResolvedPoints.Count; s++)
            {
                T?sourceBackward = _sourcePaths[s * 2 + 0] == null ? (T?)null : _sourcePaths[s * 2 + 0].Weight;
                T?sourceForward  = _sourcePaths[s * 2 + 1] == null ? (T?)null : _sourcePaths[s * 2 + 1].Weight;

                int sourceIdx;
                if (sourceForward == null && sourceBackward == null)
                {
                    continue;
                }
                map.TryGetValue(_correctedResolvedPoints[s].EdgeId, out sourceIdx);
                for (var t = 0; t < _correctedResolvedPoints.Count; t++)
                {
                    T?targetBackward = _targetPaths[t * 2 + 0] == null ? (T?)null : _targetPaths[t * 2 + 0].Weight;
                    T?targetForward  = _targetPaths[t * 2 + 1] == null ? (T?)null : _targetPaths[t * 2 + 1].Weight;

                    int targetIdx;
                    map.TryGetValue(_correctedResolvedPoints[t].EdgeId, out targetIdx);
                    if (targetForward != null)
                    {
                        if (sourceForward != null)
                        {
                            var w = _weightHandler.Add(_weightHandler.Add(sourceForward.Value, targetForward.Value),
                                                       algorithm.Weights[sourceIdx * 2 + 1][targetIdx * 2 + 1]);
                            if (_weightHandler.IsSmallerThan(w, _weights[s * 2 + 1][t * 2 + 1]))
                            {
                                _weights[s * 2 + 1][t * 2 + 1] = w;
                            }
                        }
                        if (sourceBackward != null)
                        {
                            var w = _weightHandler.Add(_weightHandler.Add(sourceBackward.Value, targetForward.Value),
                                                       algorithm.Weights[sourceIdx * 2 + 0][targetIdx * 2 + 1]);
                            if (_weightHandler.IsSmallerThan(w, _weights[s * 2 + 0][t * 2 + 1]))
                            {
                                _weights[s * 2 + 0][t * 2 + 1] = w;
                            }
                        }
                    }
                    if (targetBackward != null)
                    {
                        if (sourceForward != null)
                        {
                            var w = _weightHandler.Add(_weightHandler.Add(sourceForward.Value, targetBackward.Value),
                                                       algorithm.Weights[sourceIdx * 2 + 1][targetIdx * 2 + 0]);
                            if (_weightHandler.IsSmallerThan(w, _weights[s * 2 + 1][t * 2 + 0]))
                            {
                                _weights[s * 2 + 1][t * 2 + 0] = w;
                            }
                        }
                        if (sourceBackward != null)
                        {
                            var w = _weightHandler.Add(_weightHandler.Add(sourceBackward.Value, targetBackward.Value),
                                                       algorithm.Weights[sourceIdx * 2 + 0][targetIdx * 2 + 0]);
                            if (_weightHandler.IsSmallerThan(w, _weights[s * 2 + 0][t * 2 + 0]))
                            {
                                _weights[s * 2 + 0][t * 2 + 0] = w;
                            }
                        }
                    }
                }
            }
        }
Пример #15
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();
                }
            }
        }
Пример #16
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);
        }
Пример #17
0
        /// <summary>
        /// Calculates a route between the two locations.
        /// </summary>
        /// <returns></returns>
        public sealed override Result <EdgePath <T> > TryCalculateRaw <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target,
                                                                          RoutingSettings <T> settings)
        {
            try
            {
                if (!_db.Supports(profileInstance.Profile))
                {
                    return(new Result <EdgePath <T> >("Routing profile is not supported.", (message) =>
                    {
                        return new Exception(message);
                    }));
                }

                var maxSearch = weightHandler.Infinite;
                if (settings != null)
                {
                    if (!settings.TryGetMaxSearch(profileInstance.Profile.FullName, out maxSearch))
                    {
                        maxSearch = weightHandler.Infinite;
                    }
                }

                EdgePath <T> path;
                ContractedDb contracted;

                bool useContracted = false;
                if (_db.TryGetContracted(profileInstance.Profile, out contracted))
                { // contracted calculation.
                    useContracted = true;
                    if (_db.HasComplexRestrictions(profileInstance.Profile) && !contracted.HasEdgeBasedGraph)
                    { // there is no edge-based graph for this profile but the db has complex restrictions, don't use the contracted graph.
                        Logging.Logger.Log("Router", Logging.TraceEventType.Warning,
                                           "There is a vertex-based contracted graph but also complex restrictions. Not using the contracted graph, add an edge-based contracted graph.");
                        useContracted = false;
                    }
                }

                if (useContracted)
                {  // use the contracted graph.
                    path = null;

                    List <uint> vertexPath = null;

                    if (!contracted.HasEdgeBasedGraph)
                    { // use node-based routing.
                        var bidirectionalSearch = new Itinero.Algorithms.Contracted.BidirectionalDykstra <T>(contracted.NodeBasedGraph, weightHandler,
                                                                                                             source.ToEdgePaths(_db, weightHandler, true), target.ToEdgePaths(_db, weightHandler, false));
                        bidirectionalSearch.Run();
                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }
                        vertexPath = bidirectionalSearch.GetPath();
                    }
                    else
                    { // use edge-based routing.
                        var bidirectionalSearch = new Itinero.Algorithms.Contracted.EdgeBased.BidirectionalDykstra <T>(contracted.EdgeBasedGraph, weightHandler,
                                                                                                                       source.ToEdgePaths(_db, weightHandler, true), target.ToEdgePaths(_db, weightHandler, false), _db.GetGetRestrictions(profileInstance.Profile, null));
                        bidirectionalSearch.Run();
                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }
                        vertexPath = bidirectionalSearch.GetPath();
                    }

                    // expand vertex path using the regular graph.
                    path = _db.BuildEdgePath(weightHandler, source, target, vertexPath);
                }
                else
                { // use the regular graph.
                    if (_db.HasComplexRestrictions(profileInstance.Profile))
                    {
                        var sourceSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler,
                                                                                        _db.GetGetRestrictions(profileInstance.Profile, true), source.ToEdgePaths(_db, weightHandler, true), maxSearch, false);
                        var targetSearch = new Algorithms.Default.EdgeBased.Dykstra <T>(_db.Network.GeometricGraph.Graph, weightHandler,
                                                                                        _db.GetGetRestrictions(profileInstance.Profile, false), target.ToEdgePaths(_db, weightHandler, false), maxSearch, true);

                        var bidirectionalSearch = new Algorithms.Default.EdgeBased.BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler);
                        bidirectionalSearch.Run();
                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }
                        path = bidirectionalSearch.GetPath();
                    }
                    else
                    {
                        var sourceSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, null, weightHandler,
                                                           source.ToEdgePaths(_db, weightHandler, true), maxSearch, false);
                        var targetSearch = new Dykstra <T>(_db.Network.GeometricGraph.Graph, null, weightHandler,
                                                           target.ToEdgePaths(_db, weightHandler, false), maxSearch, true);

                        var bidirectionalSearch = new BidirectionalDykstra <T>(sourceSearch, targetSearch, weightHandler);
                        bidirectionalSearch.Run();
                        if (!bidirectionalSearch.HasSucceeded)
                        {
                            return(new Result <EdgePath <T> >(bidirectionalSearch.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }
                        path = bidirectionalSearch.GetPath();
                    }
                }

                if (source.EdgeId == target.EdgeId)
                { // check for a shorter path on the same edge.
                    var edgePath = source.EdgePathTo(_db, weightHandler, target);
                    if (edgePath != null &&
                        weightHandler.IsSmallerThan(edgePath.Weight, path.Weight))
                    {
                        path = edgePath;
                    }
                }
                return(new Result <EdgePath <T> >(path));
            }
            catch (Exception ex)
            {
                return(new Result <EdgePath <T> >(ex.Message, (m) => ex));
            }
        }