Example #1
0
        /// <summary>
        /// Gets the path to the given stop.
        /// </summary>
        public EdgePath <float> GetPath(uint stop)
        {
            EdgePath <float> best = null;
            var bestWeight        = float.MaxValue;

            _stopLinksDbEnumerator.MoveTo(stop);
            while (_stopLinksDbEnumerator.MoveNext())
            {
                var point = new RouterPoint(0, 0, _stopLinksDbEnumerator.EdgeId,
                                            _stopLinksDbEnumerator.Offset);
                if (point.EdgeId == _routerPoint.EdgeId)
                { // on the same edge.
                    EdgePath <float> path;
                    if (_backward)
                    { // from stop -> source.
                        path = point.EdgePathTo(_multimodalDb.RouterDb, new DefaultWeightHandler(_getFactor), _routerPoint);
                    }
                    else
                    { // from source -> stop.
                        path = _routerPoint.EdgePathTo(_multimodalDb.RouterDb, new DefaultWeightHandler(_getFactor), point);
                    }
                    if (path.Weight < bestWeight)
                    { // set as best because improvement.
                        best       = path;
                        bestWeight = path.Weight;
                    }
                }
                else
                { // on different edge, to the usual.
                    var paths = point.ToEdgePaths(_multimodalDb.RouterDb, new DefaultWeightHandler(_getFactor), _backward);
                    EdgePath <float> visit;
                    if (_dykstra.TryGetVisit(paths[0].Vertex, out visit))
                    {         // check if this one is better.
                        if (visit.Weight + paths[0].Weight < bestWeight)
                        {     // concatenate paths and set best.
                            if (paths[0].Weight == 0)
                            { // just use the visit.
                                best = visit;
                            }
                            else
                            { // there is a distance/weight.
                                best = new EdgePath <float>(Itinero.Constants.NO_VERTEX,
                                                            paths[0].Weight + visit.Weight, visit);
                            }
                            bestWeight = best.Weight;
                        }
                    }
                    if (paths.Length > 1 && _dykstra.TryGetVisit(paths[1].Vertex, out visit))
                    {         // check if this one is better.
                        if (visit.Weight + paths[1].Weight < bestWeight)
                        {     // concatenate paths and set best.
                            if (paths[1].Weight == 0)
                            { // just use the visit.
                                best = visit;
                            }
                            else
                            { // there is a distance/weight.
                                best = new EdgePath <float>(Itinero.Constants.NO_VERTEX,
                                                            paths[1].Weight + visit.Weight, visit);
                            }
                            bestWeight = best.Weight;
                        }
                    }
                }
            }
            return(best);
        }
Example #2
0
 /// <summary>
 /// Builds a route.
 /// </summary>
 public static Route Build(RouterDb db, Profile profile, RouterPoint source, RouterPoint target, EdgePath <float> path)
 {
     return(CompleteRouteBuilder.Build(db, profile, source, target, path, CancellationToken.None));
 }
Example #3
0
 /// <summary>
 /// Builds a route.
 /// </summary>
 public static Route Build(RouterDb db, Profile profile, RouterPoint source, RouterPoint target, EdgePath <float> path)
 {
     return(CompleteRouteBuilder.TryBuild(db, profile, source, target, path).Value);
 }
Example #4
0
        /// <summary>
        /// Returns a coverage of the given edge.
        /// </summary>
        /// <returns></returns>
        public static List <EdgeCover> CoveredEdges(this Router router, RouterPoint origin, RouterPoint target, EdgePath <float> path)
        {
            // TODO: (optional) parameter validation.
            // TODO: (optional) make sure the routerpoints match the path.

            var pathList = path.ToList();
            var edges    = new List <EdgeCover>(pathList.Count - 1);

            // loop over all pairs, or in other words over all edges.
            EdgePath <float> previous = null;

            for (var i = 0; i < pathList.Count; i++)
            {
                var current = pathList[i];
                if (previous != null)
                {
                    var startPercentage = 0f;
                    if (previous.Vertex == Constants.NO_VERTEX)
                    {
                        startPercentage = ((float)origin.Offset / ushort.MaxValue) * 100.0f;
                        if (current.Edge < 0)
                        {
                            startPercentage = 100 - startPercentage;
                        }
                    }
                    var endPercentage = 100f;
                    if (current.Vertex == Constants.NO_VERTEX)
                    {
                        endPercentage = ((float)target.Offset / ushort.MaxValue) * 100.0f;
                        if (current.Edge < 0)
                        {
                            endPercentage = 100 - endPercentage;
                        }
                    }
                    if (current.Vertex != Constants.NO_VERTEX &&
                        previous.Vertex != Constants.NO_VERTEX)
                    {
                        var edge = router.Db.Network.GetEdgeEnumerator(previous.Vertex).First(x => x.To == current.Vertex);
                    }

                    edges.Add(new EdgeCover()
                    {
                        DirectedEdgeId  = new DirectedEdgeId(current.Edge),
                        EndPercentage   = endPercentage,
                        StartPercentage = startPercentage
                    });
                }
                previous = current;
            }

            return(edges);
        }
Example #5
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.
                        return(false);
                    }

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

                    _current = _heap.Pop();
                }
            }
            else
            { // no more visits possible.
                return(false);
            }

            if (_current == null)
            { // route is not found, there are no vertices left
                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);
            }

            // we visit this one, set visit
            _visits[_current.Vertex] = _current;

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

            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;

                // is this edge closed?

                if (_closures.Contains(edge.Id))
                { // bypass
                    continue;
                }

                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);
        }
Example #6
0
 /// <summary>
 /// Builds a route based on a raw path.
 /// </summary>
 public abstract Result <Route> BuildRoute <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, EdgePath <T> path) where T : struct;
Example #7
0
        /// <summary>
        /// Calculates witness paths with just one hop.
        /// </summary>
        public void ExistsOneHop(DirectedDynamicGraph graph, uint source, List <uint> targets, List <T> weights,
                                 ref EdgePath <T>[] forwardExists, ref EdgePath <T>[] backwardExists)
        {
            var targetsToCalculate = new HashSet <uint>();
            var maxWeight          = _weightHandler.Zero;

            for (int idx = 0; idx < weights.Count; idx++)
            {
                if (forwardExists[idx] == null || backwardExists[idx] == null)
                {
                    targetsToCalculate.Add(targets[idx]);
                    if (_weightHandler.IsSmallerThan(maxWeight, weights[idx]))
                    {
                        maxWeight = weights[idx];
                    }
                }
                if (forwardExists[idx] == null)
                {
                    forwardExists[idx] = new EdgePath <T>();
                }
                if (backwardExists[idx] == null)
                {
                    backwardExists[idx] = new EdgePath <T>();
                }
            }

            if (targetsToCalculate.Count > 0)
            {
                var edgeEnumerator = graph.GetEdgeEnumerator(source);
                while (edgeEnumerator.MoveNext())
                {
                    var neighbour = edgeEnumerator.Neighbour;
                    if (targetsToCalculate.Contains(neighbour))
                    { // ok, this is a to-edge.
                        var index = targets.IndexOf(neighbour);
                        targetsToCalculate.Remove(neighbour);

                        bool?neighbourDirection;
                        var  neighbourWeight          = _weightHandler.GetEdgeWeight(edgeEnumerator.Current, out neighbourDirection);
                        var  neighbourCanMoveForward  = neighbourDirection == null || neighbourDirection.Value;
                        var  neighbourCanMoveBackward = neighbourDirection == null || !neighbourDirection.Value;

                        if (neighbourCanMoveForward &&
                            _weightHandler.IsSmallerThan(neighbourWeight, weights[index]))
                        {
                            forwardExists[index] = new EdgePath <T>(neighbour, neighbourWeight, edgeEnumerator.IdDirected(), new EdgePath <T>(source));
                        }
                        if (neighbourCanMoveBackward &&
                            _weightHandler.IsSmallerThan(neighbourWeight, weights[index]))
                        {
                            backwardExists[index] = new EdgePath <T>(neighbour, neighbourWeight, edgeEnumerator.IdDirected(), new EdgePath <T>(source));;
                        }

                        if (targetsToCalculate.Count == 0)
                        {
                            break;
                        }
                    }
                }
            }
        }
Example #8
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));
            }
        }
Example #9
0
        /// <summary>
        /// Calculates all routes between all sources and all targets.
        /// </summary>
        /// <returns></returns>
        public sealed override Result <EdgePath <T>[][]> TryCalculateRaw <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets,
                                                                             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;
                EdgePath <T>[][] paths = null;

                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;
                    }

                    if (!weightHandler.CanUse(contracted))
                    { // there is a contracted graph but it is not equipped to handle this weight-type.
                        Logging.Logger.Log("Router", Logging.TraceEventType.Warning,
                                           "There is a contracted graph but it's not built for the given weight calculations, using the default but slow implementation.");
                        useContracted = false;
                    }
                }

                if (useContracted)
                {
                    if (contracted.HasEdgeBasedGraph)
                    { // use edge-based routing.
                        var algorithm = new Itinero.Algorithms.Contracted.EdgeBased.ManyToManyBidirectionalDykstra <T>(_db, profileInstance.Profile, weightHandler,
                                                                                                                       sources, targets, maxSearch);
                        algorithm.Run();
                        if (!algorithm.HasSucceeded)
                        {
                            return(new Result <EdgePath <T>[][]>(algorithm.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }

                        // build all routes.
                        paths = new EdgePath <T> [sources.Length][];
                        for (var s = 0; s < sources.Length; s++)
                        {
                            paths[s] = new EdgePath <T> [targets.Length];
                            for (var t = 0; t < targets.Length; t++)
                            {
                                paths[s][t] = algorithm.GetPath(s, t);
                            }
                        }
                    }
                    else if (contracted.HasNodeBasedGraph &&
                             contracted.NodeBasedIsEdgedBased)
                    { // use vertex-based graph for edge-based routing.
                        var algorithm = new Itinero.Algorithms.Contracted.Dual.ManyToMany.VertexToVertexAlgorithm <T>(contracted.NodeBasedGraph, weightHandler,
                                                                                                                      Itinero.Algorithms.Contracted.Dual.RouterPointExtensions.ToDualDykstraSources(sources, _db, weightHandler, true),
                                                                                                                      Itinero.Algorithms.Contracted.Dual.RouterPointExtensions.ToDualDykstraSources(targets, _db, weightHandler, false), maxSearch);
                        algorithm.Run();

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

                        // build all routes.
                        paths = new EdgePath <T> [sources.Length][];
                        for (var s = 0; s < sources.Length; s++)
                        {
                            paths[s] = new EdgePath <T> [targets.Length];
                            for (var t = 0; t < targets.Length; t++)
                            {
                                var path = algorithm.GetPath(s, t);
                                if (path != null)
                                {
                                    path = _db.BuildDualEdgePath(weightHandler, sources[s], targets[t], path);
                                }
                                paths[s][t] = path;
                            }
                        }
                    }
                    else
                    { // use node-based routing.
                        var algorithm = new Itinero.Algorithms.Contracted.ManyToManyBidirectionalDykstra <T>(_db, profileInstance.Profile, weightHandler,
                                                                                                             sources, targets, maxSearch);
                        algorithm.Run();
                        if (!algorithm.HasSucceeded)
                        {
                            return(new Result <EdgePath <T>[][]>(algorithm.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }

                        // build all routes.
                        paths = new EdgePath <T> [sources.Length][];
                        for (var s = 0; s < sources.Length; s++)
                        {
                            paths[s] = new EdgePath <T> [targets.Length];
                            for (var t = 0; t < targets.Length; t++)
                            {
                                paths[s][t] = algorithm.GetPath(s, t);
                            }
                        }
                    }
                }

                if (paths == null)
                {
                    // use non-contracted calculation.
                    var algorithm = new Itinero.Algorithms.Default.ManyToMany <T>(_db, weightHandler, sources, targets, maxSearch);
                    algorithm.Run();
                    if (!algorithm.HasSucceeded)
                    {
                        return(new Result <EdgePath <T>[][]>(algorithm.ErrorMessage, (message) =>
                        {
                            return new RouteNotFoundException(message);
                        }));
                    }

                    // build all routes.
                    paths = new EdgePath <T> [sources.Length][];
                    for (var s = 0; s < sources.Length; s++)
                    {
                        paths[s] = new EdgePath <T> [targets.Length];
                        for (var t = 0; t < targets.Length; t++)
                        {
                            paths[s][t] = algorithm.GetPath(s, t);
                        }
                    }
                }
                return(new Result <EdgePath <T>[][]>(paths));
            }
            catch (Exception ex)
            {
                return(new Result <EdgePath <T>[][]>(ex.Message, (m) => ex));
            }
        }
        /// <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.Edge))
                {     // keep dequeuing.
                    if (_heap.Count == 0)
                    { // nothing more to pop.
                        break;
                    }
                    _current = _heap.Pop();
                }
            }

            if (_current != null)
            { // we visit this one, set visit.
                if (_current.Edge != Constants.NO_EDGE)
                {
                    _visits[_current.Edge] = _current;

                    // report on visit.
                    if (this.Visit != null)
                    {
                        if (this.Visit(_current))
                        {
                            return(true);
                        }
                    }
                }
            }
            else
            { // route is not found, there are no vertices left
                // or the search went outside of the max bounds.
                return(false);
            }

            // move to the current edge's target vertex.
            _edgeEnumerator.MoveTo(_current.Vertex);

            // get new restrictions at the current vertex.
            LinkedRestriction restrictions = null;

            if (_edgeRestrictions.TryGetValue(_current, out restrictions))
            {
                _edgeRestrictions.Remove(_current);
            }
            if (_getRestriction != null)
            {
                var targetVertexRestriction = _getRestriction(_current.Vertex);
                if (targetVertexRestriction != null)
                {
                    foreach (var restriction in targetVertexRestriction)
                    {
                        if (restriction != null &&
                            restriction.Length > 0)
                        {
                            if (restriction.Length == 1)
                            { // a simple restriction, restricted vertex, no need to check outgoing edges.
                                return(true);
                            }
                            else
                            { // a complex restriction.
                                restrictions = new LinkedRestriction()
                                {
                                    Restriction = restriction,
                                    Next        = restrictions
                                };
                            }
                        }
                    }
                }
            }
            while (_edgeEnumerator.MoveNext())
            {
                var edge           = _edgeEnumerator;
                var directedEdgeId = _edgeEnumerator.IdDirected();
                var neighbour      = edge.To;

                if (directedEdgeId == -_current.Edge)
                { // don't go back.
                    continue;
                }

                if (_visits.ContainsKey(directedEdgeId))
                { // 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 edgeWeight = _weightHandler.Calculate(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.
                    // verify restriction(s).
                    var currentRestriction            = restrictions;
                    var forbidden                     = false;
                    LinkedRestriction newRestrictions = null;
                    while (currentRestriction != null)
                    { // check if some restriction prohibits this move or if we need add a new restriction
                        // for the current edge.
                        if (currentRestriction.Restriction[1] == _edgeEnumerator.To)
                        {     // ok restrictions applies to this edge and the previous one.
                            if (currentRestriction.Restriction.Length == 2)
                            { // ok this is the last edge in this restriction, prohibit this move.
                                forbidden = true;
                                break;
                            }
                            else
                            { // append this restriction to the restrictions in for the current edge.
                                newRestrictions = new LinkedRestriction()
                                {
                                    Restriction = currentRestriction.Restriction.SubArray(1, currentRestriction.Restriction.Length - 1),
                                    Next        = newRestrictions
                                };
                            }
                        }
                        currentRestriction = currentRestriction.Next;
                    }
                    if (forbidden)
                    { // move to next neighbour.
                        continue;
                    }

                    // calculate neighbors weight.
                    var totalWeight = _weightHandler.Add(_current.Weight, edgeWeight);
                    if (_weightHandler.IsSmallerThan(totalWeight, _sourceMax))
                    { // update the visit list.
                        var path = new EdgePath <T>(neighbour, totalWeight, directedEdgeId, _current);
                        if (newRestrictions != null)
                        {
                            _edgeRestrictions[path] = newRestrictions;
                        }
                        _heap.Push(path, _weightHandler.GetMetric(totalWeight));
                    }
                    else
                    { // the maxium was reached.
                        this.MaxReached = true;
                    }
                }
            }
            return(true);
        }
 /// <summary>
 /// Returns true if the given edge was visited and sets the visit output parameters with the actual visit data.
 /// </summary>
 public bool TryGetVisit(long edge, out EdgePath <T> visit)
 {
     return(_visits.TryGetValue(edge, out visit));
 }
Example #12
0
        /// <summary>
        /// Executes the actual run of the algorithm.
        /// </summary>
        protected override void DoRun()
        {
            _best = new EdgePath <T> [_targets.Count];

            // register the targets and determine one-edge-paths.
            var sourcePaths            = _source.ToEdgePaths(_routerDb, _weightHandler, true);
            var targetIndexesPerVertex = new Dictionary <uint, LinkedTarget>();
            var targetPaths            = new IEnumerable <EdgePath <T> > [_targets.Count];

            for (var i = 0; i < _targets.Count; i++)
            {
                var targets = _targets[i].ToEdgePaths(_routerDb, _weightHandler, false);
                targetPaths[i] = targets;

                // determine one-edge-paths.
                if (_source.EdgeId == _targets[i].EdgeId)
                { // on same edge.
                    _best[i] = _source.EdgePathTo(_routerDb, _weightHandler, _targets[i]);
                }

                // register targets.
                for (var t = 0; t < targets.Length; t++)
                {
                    var target = targetIndexesPerVertex.TryGetValueOrDefault(targets[t].Vertex);
                    targetIndexesPerVertex[targets[t].Vertex] = new LinkedTarget()
                    {
                        Target = i,
                        Next   = target
                    };
                }
            }

            // determine the best max search radius.
            var max = _weightHandler.Zero;

            for (var s = 0; s < _best.Length; s++)
            {
                if (_best[s] == null)
                {
                    max = _maxSearch;
                }
                else
                {
                    if (_weightHandler.IsLargerThan(_best[s].Weight, max))
                    {
                        max = _best[s].Weight;
                    }
                }
            }

            // run the search.
            var dykstra = new Dykstra <T>(_routerDb.Network.GeometricGraph.Graph, null, _weightHandler,
                                          sourcePaths, max, _closures, false);

            dykstra.WasFound += (vertex, weight) =>
            {
                LinkedTarget target;
                if (targetIndexesPerVertex.TryGetValue(vertex, out target))
                { // there is a target for this vertex.
                    while (target != null)
                    {
                        var best = _best[target.Target];
                        foreach (var targetPath in targetPaths[target.Target])
                        {
                            EdgePath <T> path;
                            dykstra.TryGetVisit(vertex, out path);
                            if (targetPath.Vertex == vertex)
                            { // there is a path here.
                                var total = _weightHandler.Add(targetPath.Weight, weight);
                                if (best == null ||
                                    _weightHandler.IsSmallerThan(total, best.Weight))
                                {     // not a best path yet, just add this one.
                                    if (_targets[target.Target].IsVertex(_routerDb, path.Vertex))
                                    { // target is the exact vertex.
                                        best = path;
                                    }
                                    else
                                    { // target is not the exact vertex.
                                        best = new EdgePath <T>(_targets[target.Target].VertexId(_routerDb),
                                                                total, path);
                                    }
                                }
                                break;
                            }
                        }

                        // set again.
                        _best[target.Target] = best;

                        // move to next target.
                        target = target.Next;
                    }
                }
                return(false);
            };
            dykstra.Run();

            this.HasSucceeded = true;
        }
Example #13
0
        /// <summary>
        /// Builds a route.
        /// </summary>
        public static Result <Route> TryBuild(RouterDb db, Profile profile, Func <ushort, Profiles.Factor> getFactor, RouterPoint source, RouterPoint target, EdgePath <float> path)
        {
            var pathList = new List <uint>();

            path.AddToListAsVertices(pathList);
            return(FastRouteBuilder.TryBuild(db, profile, getFactor, source, target, pathList));
        }
Example #14
0
 /// <summary>
 /// Builds a route.
 /// </summary>
 public static Route Build(RouterDb db, Profile profile, Func <ushort, Profiles.Factor> getFactor, RouterPoint source, RouterPoint target, EdgePath <float> path)
 {
     return(FastRouteBuilder.TryBuild(db, profile, getFactor, source, target, path).Value);
 }
Example #15
0
        public override Result <Route> BuildRoute <T>(IProfileInstance profile, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, EdgePath <T> path)
        {
            var route = new Route();

            route.Shape = new Coordinate[]
            {
                source.Location(),
                    target.Location()
            };
            return(new Result <Route>(route));
        }
Example #16
0
        /// <summary>
        /// Builds a route.
        /// </summary>
        public override sealed Result <Route> BuildRoute <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, EdgePath <T> path)
        {
            try
            {
                if (this.CustomRouteBuilder != null)
                { // there is a custom route builder.
                    return(this.CustomRouteBuilder.TryBuild(_db, profileInstance.Profile, source, target, path));
                }

                // use the default.
                return(CompleteRouteBuilder.TryBuild(_db, profileInstance.Profile, source, target, path));
            }
            catch (Exception ex)
            {
                return(new Result <Route>(ex.Message, (m) => ex));
            }
        }
Example #17
0
        /// <summary>
        /// Calculates the priority of the given vertex.
        /// </summary>
        public float Calculate(BitArray32 contractedFlags, Func <uint, IEnumerable <uint[]> > getRestrictions, uint vertex)
        {
            var removed = 0;
            var added   = 0;

            // get and keep edges.
            var edges = new List <DynamicEdge>(_graph.GetEdgeEnumerator(vertex));

            // check if this vertex has a potential restrictions.
            var restrictions    = getRestrictions(vertex);
            var hasRestrictions = restrictions != null && restrictions.Any();

            // remove 'downward' edge to vertex.
            var i = 0;

            while (i < edges.Count)
            {
                var edgeEnumerator = _graph.GetEdgeEnumerator(edges[i].Neighbour);
                edgeEnumerator.Reset();
                while (edgeEnumerator.MoveNext())
                {
                    if (edgeEnumerator.Neighbour == vertex)
                    {
                        removed++;
                    }
                }

                if (contractedFlags[edges[i].Neighbour])
                { // neighbour was already contracted, remove 'downward' edge and exclude it.
                    edgeEnumerator.MoveTo(vertex);
                    edgeEnumerator.Reset();
                    while (edgeEnumerator.MoveNext())
                    {
                        if (edgeEnumerator.Neighbour == edges[i].Neighbour)
                        {
                            removed++;
                        }
                    }
                    edges.RemoveAt(i);
                }
                else
                { // move to next edge.
                    i++;
                }
            }

            // loop over all edge-pairs once.
            for (var j = 1; j < edges.Count; j++)
            {
                var edge1 = edges[j];

                bool?edge1Direction;
                var  edge1Weight          = _weightHandler.GetEdgeWeight(edge1, out edge1Direction);
                var  edge1CanMoveForward  = edge1Direction == null || edge1Direction.Value;
                var  edge1CanMoveBackward = edge1Direction == null || !edge1Direction.Value;

                // figure out what witness paths to calculate.
                var forwardWitnesses  = new EdgePath <T> [j];
                var backwardWitnesses = new EdgePath <T> [j];
                var targets           = new List <uint>(j);
                var targetWeights     = new List <T>(j);
                for (var k = 0; k < j; k++)
                {
                    var edge2 = edges[k];

                    bool?edge2Direction;
                    var  edge2Weight          = _weightHandler.GetEdgeWeight(edge2, out edge2Direction);
                    var  edge2CanMoveForward  = edge2Direction == null || edge2Direction.Value;
                    var  edge2CanMoveBackward = edge2Direction == null || !edge2Direction.Value;

                    if (!(edge1CanMoveBackward && edge2CanMoveForward))
                    {
                        forwardWitnesses[k] = new EdgePath <T>();
                    }
                    if (!(edge1CanMoveForward && edge2CanMoveBackward))
                    {
                        backwardWitnesses[k] = new EdgePath <T>();
                    }
                    targets.Add(edge2.Neighbour);
                    if (hasRestrictions)
                    { // weight can potentially be bigger.
                        targetWeights.Add(_weightHandler.Infinite);
                    }
                    else
                    { // weight can max be the sum of the two edges.
                        targetWeights.Add(_weightHandler.Add(edge1Weight, edge2Weight));
                    }
                }

                // calculate all witness paths.
                _witnessCalculator.Calculate(_graph, getRestrictions, edge1.Neighbour, targets, targetWeights,
                                             ref forwardWitnesses, ref backwardWitnesses, Constants.NO_VERTEX);

                // add contracted edges if needed.
                for (var k = 0; k < j; k++)
                {
                    var edge2 = edges[k];

                    var removedLocal = 0;
                    var addedLocal   = 0;
                    if (forwardWitnesses[k].HasVertex(vertex) && backwardWitnesses[k].HasVertex(vertex))
                    { // add bidirectional edge.
                        _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                                                  _weightHandler.GetMetric(targetWeights[k]), null, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                        _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                                                  _weightHandler.GetMetric(targetWeights[k]), null, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                    }
                    else if (forwardWitnesses[k].HasVertex(vertex))
                    { // add forward edge.
                        _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                                                  _weightHandler.GetMetric(targetWeights[k]), true, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                        _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                                                  _weightHandler.GetMetric(targetWeights[k]), false, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                    }
                    else if (backwardWitnesses[k].HasVertex(vertex))
                    { // add forward edge.
                        _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                                                  _weightHandler.GetMetric(targetWeights[k]), false, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                        _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                                                  _weightHandler.GetMetric(targetWeights[k]), true, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                    }
                }
            }

            var contracted = 0;

            _contractionCount.TryGetValue(vertex, out contracted);
            var depth = 0;

            _depth.TryGetValue(vertex, out depth);
            return(this.DifferenceFactor * (added - removed) + (this.DepthFactor * depth) +
                   (this.ContractedFactor * contracted));
        }
Example #18
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));
                        }
                    }
                }
            }
        }
Example #19
0
        /// <summary>
        /// Executes the algorithm.
        /// </summary>
        protected sealed override void DoRun()
        {
            // run mass resolver if needed.
            if (!_massResolver.HasRun)
            {
                _massResolver.Run();
            }

            // create error and resolved point management data structures.
            _correctedResolvedPoints = _massResolver.RouterPoints;
            _errors           = new Dictionary <int, RouterPointError>(_correctedResolvedPoints.Count);
            _correctedIndices = new List <int>(_correctedResolvedPoints.Count);

            // convert sources into directed paths.
            _sourcePaths = new EdgePath <T> [_correctedResolvedPoints.Count * 2];
            for (var i = 0; i < _correctedResolvedPoints.Count; i++)
            {
                _correctedIndices.Add(i);

                var paths = _correctedResolvedPoints[i].ToEdgePathsDirectedFixed(_router.Db, _weightHandler, true);
                if (paths.Length == 0)
                {
                    this.ErrorMessage = string.Format("Source at {0} could not be resolved properly.", i);
                    return;
                }

                _sourcePaths[i * 2 + 0] = paths[0];
                _sourcePaths[i * 2 + 1] = paths[1];
            }

            // convert targets into directed paths.
            _targetPaths = new EdgePath <T> [_correctedResolvedPoints.Count * 2];
            for (var i = 0; i < _correctedResolvedPoints.Count; i++)
            {
                var paths = _correctedResolvedPoints[i].ToEdgePathsDirectedFixed(_router.Db, _weightHandler, false);
                if (paths.Length == 0)
                {
                    this.ErrorMessage = string.Format("Target at {0} could not be resolved properly.", i);
                    return;
                }

                _targetPaths[i * 2 + 0] = paths[1];
                _targetPaths[i * 2 + 1] = paths[0];
            }

            // put in default weights and weights for one-edge-paths.
            _weights = new T[_sourcePaths.Length][];
            for (var i = 0; i < _sourcePaths.Length; i++)
            {
                var source = _sourcePaths[i];
                _weights[i] = new T[_targetPaths.Length];

                for (var j = 0; j < _targetPaths.Length; j++)
                {
                    var target = _targetPaths[j];
                    _weights[i][j] = _weightHandler.Infinite;

                    if (source == null ||
                        target == null)
                    {
                        continue;
                    }

                    if (target.Edge == -source.Edge)
                    {
                        var s           = i / 2;
                        var t           = j / 2;
                        var sourcePoint = _correctedResolvedPoints[s];
                        var targetPoint = _correctedResolvedPoints[t];

                        EdgePath <T> newPath = null;
                        if (source.Edge > 0 &&
                            sourcePoint.Offset <= targetPoint.Offset)
                        {
                            newPath = sourcePoint.EdgePathTo(_router.Db, _weightHandler, targetPoint);
                        }
                        else if (source.Edge < 0 &&
                                 sourcePoint.Offset >= targetPoint.Offset)
                        {
                            newPath = sourcePoint.EdgePathTo(_router.Db, _weightHandler, targetPoint);
                        }

                        if (newPath != null)
                        {
                            if (_weightHandler.IsLargerThan(_weights[i][j], newPath.Weight))
                            {
                                _weights[i][j] = newPath.Weight;
                            }
                        }
                    }
                }
            }

            // run the actual calculations.
            if (_graph != null)
            {
                this.DoEdgeBased();
            }
            else
            {
                this.DoDualBased();
            }

            // check for invalids.
            var originalInvalids    = new HashSet <int>();
            var invalidTargetCounts = new int[_weights.Length / 2];

            for (var s = 0; s < _weights.Length / 2; s++)
            {
                var invalids = 0;
                for (var t = 0; t < _weights[s * 2].Length / 2; t++)
                {
                    if (t != s)
                    {
                        if (_weightHandler.GetMetric(_weights[s * 2 + 0][t * 2 + 0]) == float.MaxValue &&
                            _weightHandler.GetMetric(_weights[s * 2 + 0][t * 2 + 1]) == float.MaxValue &&
                            _weightHandler.GetMetric(_weights[s * 2 + 1][t * 2 + 0]) == float.MaxValue &&
                            _weightHandler.GetMetric(_weights[s * 2 + 1][t * 2 + 1]) == float.MaxValue)
                        {
                            invalids++;
                            invalidTargetCounts[t]++;
                            if (invalidTargetCounts[t] > ((_weights.Length / 2) - 1) / 2)
                            {
                                originalInvalids.Add(t);
                            }
                        }
                    }
                }

                if (invalids > ((_weights.Length / 2) - 1) / 2)
                {
                    originalInvalids.Add(s);
                }
            }

            // take into account the non-null invalids now.
            if (originalInvalids.Count > 0)
            { // shrink lists and add errors.
                _correctedResolvedPoints = _correctedResolvedPoints.ShrinkAndCopyList(originalInvalids);
                _correctedIndices        = _correctedIndices.ShrinkAndCopyList(originalInvalids);

                // convert back to the path indexes.
                var nonNullInvalids = new HashSet <int>();
                foreach (var invalid in originalInvalids)
                {
                    nonNullInvalids.Add(invalid * 2);
                    nonNullInvalids.Add(invalid * 2 + 1);
                    _errors[invalid] = new RouterPointError()
                    {
                        Code    = RouterPointErrorCode.NotRoutable,
                        Message = "Location could not routed to or from."
                    };
                }

                _weights     = _weights.SchrinkAndCopyMatrix(nonNullInvalids);
                _sourcePaths = _sourcePaths.ShrinkAndCopyArray(nonNullInvalids);
                _targetPaths = _targetPaths.ShrinkAndCopyArray(nonNullInvalids);
            }

            this.HasSucceeded = true;
        }
Example #20
0
        /// <summary>
        /// Tries to get the path from source to target.
        /// </summary>
        public bool TryGetPath(int source, int target, out EdgePath <T> path)
        {
            this.CheckHasRunAndHasSucceeded();

            return(_sourceSearches[source].TryGetPath(target, out path));
        }
Example #21
0
        /// <summary>
        /// Calculates witness paths.
        /// </summary>
        public void Calculate(DirectedDynamicGraph graph, Func <uint, IEnumerable <uint[]> > getRestrictions, uint source, List <uint> targets, List <T> weights,
                              ref EdgePath <T>[] forwardWitness, ref EdgePath <T>[] backwardWitness, uint vertexToSkip)
        {
            if (_hopLimit == 1)
            {
                this.ExistsOneHop(graph, source, targets, weights, ref forwardWitness, ref backwardWitness);
                return;
            }

            // creates the settled list.
            var backwardSettled = new HashSet <EdgePath <T> >();
            var forwardSettled = new HashSet <EdgePath <T> >();
            var backwardTargets = new HashSet <uint>();
            var forwardTargets = new HashSet <uint>();
            T   forwardMaxWeight = _weightHandler.Zero, backwardMaxWeight = _weightHandler.Zero;

            for (int idx = 0; idx < weights.Count; idx++)
            {
                if (forwardWitness[idx] == null)
                {
                    forwardWitness[idx] = new EdgePath <T>();
                    forwardTargets.Add(targets[idx]);
                    if (_weightHandler.IsSmallerThan(forwardMaxWeight, weights[idx]))
                    {
                        forwardMaxWeight = weights[idx];
                    }
                }
                if (backwardWitness[idx] == null)
                {
                    backwardWitness[idx] = new EdgePath <T>();
                    backwardTargets.Add(targets[idx]);
                    if (_weightHandler.IsSmallerThan(backwardMaxWeight, weights[idx]))
                    {
                        backwardMaxWeight = weights[idx];
                    }
                }
            }

            if (_weightHandler.GetMetric(forwardMaxWeight) == 0 &&
                _weightHandler.GetMetric(backwardMaxWeight) == 0)
            { // no need to search!
                return;
            }

            // creates the priorty queue.
            var forwardMinWeight  = new Dictionary <EdgePath <T>, T>();
            var backwardMinWeight = new Dictionary <EdgePath <T>, T>();

            _heap.Clear();
            _heap.Push(new SettledEdge(new EdgePath <T>(source), 0, _weightHandler.GetMetric(forwardMaxWeight) > 0, _weightHandler.GetMetric(backwardMaxWeight) > 0), 0);

            // keep looping until the queue is empty or the target is found!
            var edgeEnumerator = graph.GetEdgeEnumerator();

            while (_heap.Count > 0)
            { // pop the first customer.
                var current = _heap.Pop();
                if (current.Hops + 1 < _hopLimit)
                {
                    if (current.Path.Vertex == vertexToSkip)
                    { // this is the vertex being contracted.
                        continue;
                    }
                    var forwardWasSettled  = forwardSettled.Contains(current.Path);
                    var backwardWasSettled = backwardSettled.Contains(current.Path);
                    if (forwardWasSettled && backwardWasSettled)
                    { // both are already settled.
                        continue;
                    }

                    if (current.Forward)
                    { // this is a forward settle.
                        forwardSettled.Add(current.Path);
                        forwardMinWeight.Remove(current.Path);
                        if (forwardTargets.Contains(current.Path.Vertex))
                        {
                            for (var i = 0; i < targets.Count; i++)
                            {
                                if (targets[i] == current.Path.Vertex &&
                                    _weightHandler.IsSmallerThanOrEqual(current.Path.Weight, weights[i]))
                                { // TODO: check if this is a proper stop condition.
                                    if (forwardWitness[i] == null || forwardWitness[i].Vertex == Constants.NO_VERTEX ||
                                        _weightHandler.IsSmallerThan(current.Path.Weight, forwardWitness[i].Weight))
                                    {
                                        forwardWitness[i] = current.Path;
                                        forwardTargets.Remove(current.Path.Vertex);
                                    }
                                }
                            }
                        }
                    }
                    if (current.Backward)
                    { // this is a backward settle.
                        backwardSettled.Add(current.Path);
                        backwardMinWeight.Remove(current.Path);
                        if (backwardTargets.Contains(current.Path.Vertex))
                        {
                            for (var i = 0; i < targets.Count; i++)
                            {
                                if (targets[i] == current.Path.Vertex &&
                                    _weightHandler.IsSmallerThanOrEqual(current.Path.Weight, weights[i]))
                                { // TODO: check if this is a proper stop condition.
                                    if (backwardWitness[i] == null || backwardWitness[i].Vertex == Constants.NO_VERTEX ||
                                        _weightHandler.IsSmallerThan(current.Path.Weight, backwardWitness[i].Weight))
                                    {
                                        backwardWitness[i] = current.Path;
                                        backwardTargets.Remove(current.Path.Vertex);
                                    }
                                }
                            }
                        }
                    }

                    if (forwardTargets.Count == 0 &&
                        backwardTargets.Count == 0)
                    { // there is nothing left to check.
                        break;
                    }

                    if (forwardSettled.Count >= _maxSettles &&
                        backwardSettled.Count >= _maxSettles)
                    { // do not continue searching.
                        break;
                    }

                    var doForward  = current.Forward && forwardTargets.Count > 0 && !forwardWasSettled;
                    var doBackward = current.Backward && backwardTargets.Count > 0 && !backwardWasSettled;
                    if (doForward || doBackward)
                    { // get the neighbours.
                        // check for a restriction and if need build the original sequence.
                        var restrictions = getRestrictions(current.Path.Vertex);
                        var sequence     = current.Path.GetSequence2(edgeEnumerator);
                        sequence = sequence.Append(current.Path.Vertex);

                        // move to the current vertex.
                        edgeEnumerator.MoveTo(current.Path.Vertex);
                        while (edgeEnumerator.MoveNext())
                        { // move next.
                            var neighbour = edgeEnumerator.Neighbour;

                            bool?neighbourDirection;
                            var  neighbourWeight          = _weightHandler.GetEdgeWeight(edgeEnumerator, out neighbourDirection);
                            var  neighbourCanMoveForward  = neighbourDirection == null || neighbourDirection.Value;
                            var  neighbourCanMoveBackward = neighbourDirection == null || !neighbourDirection.Value;

                            var totalNeighbourWeight = _weightHandler.Add(current.Path.Weight, neighbourWeight);
                            var neighbourPath        = new EdgePath <T>(neighbour, totalNeighbourWeight, edgeEnumerator.IdDirected(),
                                                                        current.Path);

                            var doNeighbourForward = doForward && neighbourCanMoveForward && _weightHandler.IsSmallerThanOrEqual(totalNeighbourWeight, forwardMaxWeight) &&
                                                     !forwardSettled.Contains(neighbourPath);
                            var doNeighbourBackward = doBackward && neighbourCanMoveBackward && _weightHandler.IsSmallerThanOrEqual(totalNeighbourWeight, backwardMaxWeight) &&
                                                      !backwardSettled.Contains(neighbourPath);
                            if (doNeighbourBackward || doNeighbourForward)
                            {
                                T      existingWeight;
                                uint[] sequenceAlongNeighbour = null;

                                if ((doNeighbourBackward || doNeighbourForward) && sequence.Length > 0)
                                {
                                    if (edgeEnumerator.IsOriginal())
                                    {
                                        if (sequence.Length > 1 && sequence[sequence.Length - 2] == neighbour)
                                        { // a t-turn!
                                            continue;
                                        }
                                        sequenceAlongNeighbour = sequence.Append(neighbour);
                                    }
                                    else
                                    {
                                        var sequence1Length = edgeEnumerator.GetSequence1(ref _sequence1);
                                        //var neighbourSequence = edgeEnumerator.GetSequence1();
                                        if (sequence.Length > 1 && sequence[sequence.Length - 2] == _sequence1[0])
                                        { // a t-turn!
                                            continue;
                                        }
                                        sequenceAlongNeighbour = sequence.Append(_sequence1, sequence1Length);
                                    }
                                }

                                if (doNeighbourForward)
                                {
                                    if (sequence.Length == 0 || restrictions.IsSequenceAllowed(sequenceAlongNeighbour))
                                    { // restrictions ok.
                                        if (forwardMinWeight.TryGetValue(neighbourPath, out existingWeight))
                                        {
                                            if (_weightHandler.IsSmallerThanOrEqual(existingWeight, totalNeighbourWeight))
                                            {
                                                doNeighbourForward = false;
                                            }
                                            else
                                            {
                                                forwardMinWeight[neighbourPath] = totalNeighbourWeight;
                                            }
                                        }
                                        else
                                        {
                                            forwardMinWeight[neighbourPath] = totalNeighbourWeight;
                                        }
                                    }
                                    else
                                    {
                                        doNeighbourForward = false;
                                    }
                                }
                                if (doNeighbourBackward)
                                {
                                    if (sequenceAlongNeighbour != null)
                                    {
                                        sequenceAlongNeighbour.Reverse();
                                    }
                                    if (sequence.Length == 0 || restrictions.IsSequenceAllowed(sequenceAlongNeighbour))
                                    { // restrictions ok.
                                        if (backwardMinWeight.TryGetValue(neighbourPath, out existingWeight))
                                        {
                                            if (_weightHandler.IsSmallerThanOrEqual(existingWeight, totalNeighbourWeight))
                                            {
                                                doNeighbourBackward = false;
                                            }
                                            else
                                            {
                                                backwardMinWeight[neighbourPath] = totalNeighbourWeight;
                                            }
                                        }
                                        else
                                        {
                                            backwardMinWeight[neighbourPath] = totalNeighbourWeight;
                                        }
                                    }
                                    else
                                    {
                                        doNeighbourBackward = false;
                                    }
                                }

                                if (doNeighbourBackward || doNeighbourForward)
                                { // add to heap.
                                    var newSettle = new SettledEdge(neighbourPath, current.Hops + 1, doNeighbourForward, doNeighbourBackward);
                                    _heap.Push(newSettle, _weightHandler.GetMetric(neighbourPath.Weight));
                                }
                            }
                        }
                    }
                }
            }
        }
Example #22
0
        /// <summary>
        /// Builds a route.
        /// </summary>
        public override sealed Result <Route> BuildRoute <T>(Profile profile, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, EdgePath <T> path)
        {
            if (this.CustomRouteBuilder != null)
            { // there is a custom route builder.
                return(this.CustomRouteBuilder.TryBuild(_db, profile, source, target, path));
            }

            // use the default.
            return(CompleteRouteBuilder.TryBuild(_db, profile, source, target, path));
        }
        /// <summary>
        /// Executes the actual run.
        /// </summary>
        protected override void DoRun(CancellationToken cancellationToken)
        {
            var router = new Router(_db);

            router.VerifyAllStoppable = true;

            // resolve locations as vertices.
            // WARNING: use RouterPointEmbedder first.
            var points = new RouterPoint[_locations.Length];

            for (var i = 0; i < points.Length; i++)
            {
                var resolver = new Itinero.Algorithms.Search.ResolveVertexAlgorithm(_db.Network.GeometricGraph, _locations[i].Latitude, _locations[i].Longitude,
                                                                                    500, 3000, router.GetIsAcceptable(_profile));
                resolver.Run(cancellationToken);
                if (!resolver.HasSucceeded)
                {
                    throw new System.Exception(string.Format("Could not resolve shortcut location at index {1}: {0}.", resolver.ErrorMessage, i));
                }
                points[i] = resolver.Result;
            }

            // use non-contracted calculation.
            var weightHandler = _profile.AugmentedWeightHandlerCached(_db);
            var algorithm     = new Itinero.Algorithms.Default.ManyToMany <Weight>(_db, weightHandler, points, points, new Weight()
            {
                Distance = float.MaxValue,
                Time     = _maxShortcutDuration,
                Value    = _maxShortcutDuration
            });

            algorithm.Run(cancellationToken);
            if (!algorithm.HasSucceeded)
            {
                this.ErrorMessage = "Many to many calculation failed: " + algorithm.ErrorMessage;
            }

            // build shortcuts db.
            _shortcutsDb = new ShortcutsDb(_profile.FullName);
            for (var i = 0; i < points.Length; i++)
            {
                _shortcutsDb.AddStop(points[i].VertexId(_db), _locationsMeta[i]);
            }
            var routes = new EdgePath <float> [_locations.Length][];

            _shortcutIds = new uint[_locations.Length][];
            var pathList        = new List <uint>();
            var shortcutProfile = _db.EdgeProfiles.Add(new AttributeCollection(
                                                           new Attribute(ShortcutExtensions.SHORTCUT_KEY, _name)));
            var edgeEnumerator = _db.Network.GetEdgeEnumerator();

            for (var i = 0; i < _locations.Length; i++)
            {
                _shortcutIds[i] = new uint[_locations.Length];
                for (var j = 0; j < _locations.Length; j++)
                {
                    _shortcutIds[i][j] = uint.MaxValue;
                    if (i == j)
                    {
                        continue;
                    }
                    EdgePath <Weight> path;
                    if (algorithm.TryGetPath(i, j, out path))
                    {
                        pathList.Clear();
                        path.AddToListAsVertices(pathList);

                        if (path.Weight.Time < _minShortcutSize)
                        { // don't add very short shortcuts.
                            continue;
                        }

                        if (pathList.Count < 2)
                        {
                            Itinero.Logging.Logger.Log("ShortcutBuilder", TraceEventType.Warning, "Shortcut consists of only one vertex from {0}@{1} -> {2}@{3}!",
                                                       i, _locations[i], j, _locations[j]);
                            continue;
                        }
                        if (pathList[0] == pathList[pathList.Count - 1])
                        {
                            Itinero.Logging.Logger.Log("ShortcutBuilder", TraceEventType.Warning, "Shortcut has the same start and end vertex from {0}@{1} -> {2}@{3}!",
                                                       i, _locations[i], j, _locations[j]);
                            continue;
                        }

                        // add the shortcut and keep the id.
                        var shortcutId = _shortcutsDb.Add(pathList.ToArray(), null);
                        _shortcutIds[i][j] = shortcutId;

                        // add the shortcut as an edge.
                        if (edgeEnumerator.MoveTo(pathList[0]))
                        {
                            var edgeExists = false;
                            while (edgeEnumerator.MoveNext())
                            {
                                if (edgeEnumerator.To == pathList[pathList.Count - 1])
                                {
                                    var json = edgeEnumerator.Current.ToGeoJson(router.Db);
                                    edgeExists = true;
                                    break;
                                }
                            }

                            if (edgeExists)
                            {
                                continue;
                            }
                        }
                        _db.Network.AddEdge(pathList[0], pathList[pathList.Count - 1], new Data.Network.Edges.EdgeData()
                        {
                            Distance = path.Weight.Time + _switchPentaly,
                            MetaId   = 0,
                            Profile  = (ushort)shortcutProfile
                        }, null);
                    }
                    else
                    {
                        Itinero.Logging.Logger.Log("ShortcutBuilder", TraceEventType.Warning, "Shortcut not found from {0}@{1} -> {2}@{3}!",
                                                   i, _locations[i], j, _locations[j]);
                    }
                }
            }
        }
Example #24
0
        /// <summary>
        /// Gets the weights.
        /// </summary>
        public EdgePath <T> GetPath(int source, int target)
        {
            this.CheckHasRunAndHasSucceeded();

            var solution = _solutions[source][target];

            if (solution.Path == null)
            {
                if (solution.Path1 == null || solution.Path2 == null)
                {
                    return(null);
                }
                if (solution.Path != null)
                {
                    return(solution.Path);
                }

                var fromSource = solution.Path1;
                var toTarget   = solution.Path2;
                var vertices   = new List <uint>();

                // add vertices from source.
                vertices.Add(fromSource.Vertex);
                while (fromSource.From != null)
                {
                    if (fromSource.From.Vertex != Constants.NO_VERTEX)
                    {     // this should be the end of the path.
                        if (fromSource.Edge == Constants.NO_EDGE)
                        { // only expand when there is no edge id.
                            _graph.ExpandEdge(fromSource.From.Vertex, fromSource.Vertex, vertices, false, true);
                        }
                    }
                    vertices.Add(fromSource.From.Vertex);
                    fromSource = fromSource.From;
                }
                vertices.Reverse();

                // and add vertices to target.
                while (toTarget.From != null)
                {
                    if (toTarget.From.Vertex != Constants.NO_VERTEX)
                    {     // this should be the end of the path.
                        if (toTarget.Edge == Constants.NO_EDGE)
                        { // only expand when there is no edge id.
                            _graph.ExpandEdge(toTarget.From.Vertex, toTarget.Vertex, vertices, false, false);
                        }
                    }
                    vertices.Add(toTarget.From.Vertex);
                    toTarget = toTarget.From;
                }

                var path = new EdgePath <T>(vertices[0]);
                for (var i = 1; i < vertices.Count; i++)
                {
                    path = new EdgePath <T>(vertices[i], default(T), path);
                }

                solution.Path = path;
            }
            return(solution.Path);
        }
Example #25
0
 /// <summary>
 /// Returns true if the given vertex was visited and sets the visit output parameters with the actual visit data.
 /// </summary>
 /// <returns></returns>
 public bool TryGetVisit(uint vertex, out EdgePath <T> visit)
 {
     return(_visits.TryGetValue(vertex, out visit));
 }
Example #26
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.
                        if (_weightHandler.IsLargerThan(routeToNeighbour.Weight, _max))
                        {
                            continue;
                        }
                        _heap.Push(routeToNeighbour, _weightHandler.GetMetric(routeToNeighbour.Weight));
                    }
                }
            }

            return(true);
        }
Example #27
0
 /// <summary>
 /// Builds a route.
 /// </summary>
 public static Result <Route> TryBuild <T>(RouterDb db, Profile profile, RouterPoint source, RouterPoint target, EdgePath <T> path)
 {
     return(CompleteRouteBuilder.TryBuild(db, profile, source, target, path, CancellationToken.None));
 }
        /// <summary>
        /// Returns true if the given vertex was visited and sets the visit output parameters with the actual visit data.
        /// </summary>
        /// <returns></returns>
        public bool TryGetBackwardVisit(uint vertex, out EdgePath <T> visit)
        {
            this.CheckHasRunAndHasSucceeded();

            return(_backwardVisits.TryGetValue(vertex, out visit));
        }
Example #29
0
        /// <summary>
        /// Builds a route.
        /// </summary>
        public static Result <Route> TryBuild <T>(RouterDb db, Profile profile, RouterPoint source, RouterPoint target, EdgePath <T> path)
        {
            var pathList = new List <uint>();

            path.AddToListAsVertices(pathList);
            return(CompleteRouteBuilder.TryBuild(db, profile, source, target, pathList));
        }
Example #30
0
        /// <summary>
        /// Contracts the given vertex.
        /// </summary>
        private void Contract(uint vertex)
        {
            // get and keep edges.
            var enumerator = _graph.GetEdgeEnumerator(vertex);
            var edges      = new List <DynamicEdge>(enumerator);

            // check if this vertex has a potential restrictions.
            var hasRestrictions = _restrictionFlags[vertex];

            // loop over all edge-pairs once.
            for (var j = 1; j < edges.Count; j++)
            {
                var edge1 = edges[j];

                bool?edge1Direction;
                var  edge1Weight          = _weightHandler.GetEdgeWeight(edge1, out edge1Direction);
                var  edge1CanMoveForward  = edge1Direction == null || edge1Direction.Value;
                var  edge1CanMoveBackward = edge1Direction == null || !edge1Direction.Value;

                // figure out what witness paths to calculate.
                var forwardWitnesses  = new EdgePath <T> [j];
                var backwardWitnesses = new EdgePath <T> [j];
                var targets           = new List <uint>(j);
                var targetWeights     = new List <T>(j);
                for (var k = 0; k < j; k++)
                {
                    var edge2 = edges[k];

                    bool?edge2Direction;
                    var  edge2Weight          = _weightHandler.GetEdgeWeight(edge2, out edge2Direction);
                    var  edge2CanMoveForward  = edge2Direction == null || edge2Direction.Value;
                    var  edge2CanMoveBackward = edge2Direction == null || !edge2Direction.Value;

                    // use witness flags to represent impossible routes.
                    if (!(edge1CanMoveBackward && edge2CanMoveForward))
                    {
                        forwardWitnesses[k] = new EdgePath <T>();
                    }
                    if (!(edge1CanMoveForward && edge2CanMoveBackward))
                    {
                        backwardWitnesses[k] = new EdgePath <T>();
                    }

                    targets.Add(edge2.Neighbour);
                    if (hasRestrictions)
                    {
                        targetWeights.Add(_weightHandler.Infinite);
                    }
                    else
                    {
                        targetWeights.Add(_weightHandler.Add(edge1Weight, edge2Weight));
                    }
                }

                // calculate all witness paths.
                _witnessCalculator.Calculate(_graph, _getRestrictions, edge1.Neighbour, targets, targetWeights, ref forwardWitnesses,
                                             ref backwardWitnesses, Constants.NO_VERTEX);

                // get all sequences where needed.
                var s1forward  = new uint[forwardWitnesses.Length][];
                var s2forward  = new uint[forwardWitnesses.Length][];
                var s1backward = new uint[backwardWitnesses.Length][];
                var s2backward = new uint[backwardWitnesses.Length][];
                for (var k = 0; k < j; k++)
                {
                    if (forwardWitnesses[k].HasVertex(vertex))
                    { // get forward sequences.
                        s1forward[k] = forwardWitnesses[k].GetSequence1(enumerator, 1);
                        s2forward[k] = forwardWitnesses[k].GetSequence2(enumerator, 1);
                    }
                    if (backwardWitnesses[k].HasVertex(vertex))
                    { // get backward sequences.
                        s1backward[k] = backwardWitnesses[k].GetSequence1(enumerator, 1);
                        s2backward[k] = backwardWitnesses[k].GetSequence2(enumerator, 1);
                    }
                }

                // add contracted edges if needed.
                for (var k = 0; k < j; k++)
                {
                    var edge2 = edges[k];

                    if (edge1.Neighbour == edge2.Neighbour)
                    { // do not try to add a shortcut between identical vertices.
                        continue;
                    }
                    if (s1forward[k] != null && s1backward[k] != null &&
                        System.Math.Abs(_weightHandler.GetMetric(forwardWitnesses[k].Weight) - _weightHandler.GetMetric(backwardWitnesses[k].Weight)) < E)
                    { // paths in both direction are possible and with the same weight, add just one edge in each direction.
                        s1backward[k].Reverse();
                        s2backward[k].Reverse();
                        _weightHandler.AddOrUpdateEdge(_graph, edge1.Neighbour, edge2.Neighbour, vertex, null,
                                                       forwardWitnesses[k].Weight, s1forward[k], s2forward[k]);
                        //_graph.AddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                        //    forwardWitnesses[k].Weight, null, vertex, s1forward[k], s2forward[k]);
                        _weightHandler.AddOrUpdateEdge(_graph, edge2.Neighbour, edge1.Neighbour, vertex, null,
                                                       backwardWitnesses[k].Weight, s2backward[k], s1backward[k]);
                        //_graph.AddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                        //    backwardWitnesses[k].Weight, null, vertex, s2backward[k], s1backward[k]);
                    }
                    else
                    {     // add two edge per direction.
                        if (s1forward[k] != null)
                        { // add forward edge.
                            _weightHandler.AddOrUpdateEdge(_graph, edge1.Neighbour, edge2.Neighbour, vertex, true,
                                                           forwardWitnesses[k].Weight, s1forward[k], s2forward[k]);
                            //_graph.AddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                            //    forwardWitnesses[k].Weight, true, vertex, s1forward[k], s2forward[k]);
                            s1forward[k].Reverse();
                            s2forward[k].Reverse();
                            _weightHandler.AddOrUpdateEdge(_graph, edge2.Neighbour, edge1.Neighbour, vertex, false,
                                                           forwardWitnesses[k].Weight, s2forward[k], s1forward[k]);
                            //_graph.AddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                            //    forwardWitnesses[k].Weight, false, vertex, s2forward[k], s1forward[k]);
                        }
                        if (s1backward[k] != null)
                        { // add forward edge.
                            _weightHandler.AddOrUpdateEdge(_graph, edge1.Neighbour, edge2.Neighbour, vertex, false,
                                                           backwardWitnesses[k].Weight, s2backward[k], s1backward[k]);
                            //_graph.AddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                            //    backwardWitnesses[k].Weight, false, vertex, s2backward[k], s1backward[k]);
                            s1backward[k].Reverse();
                            s2backward[k].Reverse();
                            _weightHandler.AddOrUpdateEdge(_graph, edge2.Neighbour, edge1.Neighbour, vertex, true,
                                                           backwardWitnesses[k].Weight, s1backward[k], s2backward[k]);
                            //_graph.AddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                            //    backwardWitnesses[k].Weight, true, vertex, s1backward[k], s2backward[k]);
                        }
                    }
                }
            }

            // remove 'downward' edge to vertex.
            var i = 0;

            while (i < edges.Count)
            {
                _graph.RemoveEdge(edges[i].Neighbour, vertex);

                if (_contractedFlags[edges[i].Neighbour])
                { // neighbour was already contracted, remove 'downward' edge and exclude it.
                    _graph.RemoveEdge(vertex, edges[i].Neighbour);
                    edges.RemoveAt(i);
                }
                else
                { // move to next edge.
                    i++;
                }
            }

            _contractedFlags[vertex] = true;
            _priorityCalculator.NotifyContracted(vertex);
        }