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

            if (_buckets.TryGetValue(vertex, out bucket))
            {
                foreach (var pair in bucket)
                {
                    var existing       = _solutions[pair.Key][i];
                    var total          = _weightHandler.Add(weight, pair.Value.Weight);
                    var existingWeight = _weightHandler.Infinite;
                    if (existing.Path != null)
                    {
                        existingWeight = existing.Path.Weight;
                    }
                    else if (existing.Path1 != null &&
                             existing.Path2 != null)
                    {
                        existingWeight = _weightHandler.Add(existing.Path1.Weight,
                                                            existing.Path2.Weight);
                    }
                    if (_weightHandler.IsSmallerThan(total, existingWeight))
                    { // append the backward to the forward path.
                        _solutions[pair.Key][i] = new Solution()
                        {
                            Path1 = pair.Value,
                            Path2 = dykstra.GetPath(pointer)
                        };
                    }
                }
            }
            return(false);
        }
Пример #2
0
        /// <summary>
        /// Called when a vertex was reached during a forward search.
        /// </summary>
        /// <returns></returns>
        private bool ReachedForward(EdgePath <T> forwardVisit)
        {
            // check backward search for the same vertex.
            EdgePath <T> backwardVisit;

            if (_targetSearch.TryGetVisit(-forwardVisit.Edge, out backwardVisit))
            { // there is a status for this edge in the target search.
                var localWeight = _weightHandler.Zero;
                if (forwardVisit.From != null)
                {
                    localWeight = _weightHandler.Subtract(forwardVisit.Weight, forwardVisit.From.Weight);
                }
                var totalWeight = _weightHandler.Subtract(_weightHandler.Add(forwardVisit.Weight, backwardVisit.Weight), localWeight);
                if (_weightHandler.IsSmallerThan(totalWeight, _best.Item3))
                { // this is a better match.
                    if (forwardVisit.Vertex == backwardVisit.From.Vertex &&
                        (forwardVisit.From.From != null || backwardVisit.From.From != null))
                    { // paths match and are bigger than one edge.
                        _best             = new Tuple <EdgePath <T>, EdgePath <T>, T>(forwardVisit, backwardVisit, totalWeight);
                        this.HasSucceeded = true;
                    }
                }
            }
            return(false);
        }
Пример #3
0
        /// <summary>
        /// Builds the potential shortcuts.
        /// </summary>
        public static void BuildShortcuts <T>(this VertexInfo <T> vertexinfo, WeightHandler <T> weightHandler)
            where T : struct
        {
            var vertex    = vertexinfo.Vertex;
            var shortcuts = vertexinfo.Shortcuts;

            // loop over all edge-pairs once.
            var shortcut = new Shortcut <T>()
            {
                Backward = weightHandler.Infinite,
                Forward  = weightHandler.Infinite
            };
            var shortcutEdge = new OriginalEdge();

            for (var j = 1; j < vertexinfo.Count; j++)
            {
                var edge1       = vertexinfo[j];
                var edge1Weight = weightHandler.GetEdgeWeight(edge1);
                shortcutEdge.Vertex1 = edge1.Neighbour;

                // figure out what witness paths to calculate.
                for (var k = 0; k < j; k++)
                {
                    var edge2       = vertexinfo[k];
                    var edge2Weight = weightHandler.GetEdgeWeight(edge2);
                    shortcutEdge.Vertex2 = edge2.Neighbour;

                    if (!(edge1Weight.Direction.B && edge2Weight.Direction.F) &&
                        !(edge1Weight.Direction.F && edge2Weight.Direction.B))
                    { // impossible route, do nothing.
                        continue;
                    }

                    shortcut.Backward = weightHandler.Infinite;
                    shortcut.Forward  = weightHandler.Infinite;

                    if (edge1Weight.Direction.B && edge2Weight.Direction.F)
                    {
                        shortcut.Forward = weightHandler.Add(edge1Weight.Weight, edge2Weight.Weight);
                    }
                    if (edge1Weight.Direction.F && edge2Weight.Direction.B)
                    {
                        shortcut.Backward = weightHandler.Add(edge1Weight.Weight, edge2Weight.Weight);
                    }

                    shortcuts.AddOrUpdate(shortcutEdge, shortcut, weightHandler);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Called when a backward vertex was found.
        /// </summary>
        /// <returns></returns>
        protected virtual bool BackwardVertexFound(int i, uint vertex, LinkedEdgePath <T> backwardVisit)
        {
            Dictionary <int, LinkedEdgePath <T> > bucket;

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

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

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

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

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

                    _weights[pair.Key][i] = best;
                }
            }
            return(false);
        }
Пример #5
0
        /// <summary>
        /// Called when a vertex was reached during a forward search.
        /// </summary>
        /// <returns></returns>
        private bool ReachedVertexForward(uint vertex, T weight)
        {
            // check backward search for the same vertex.
            EdgePath <T> backwardVisit;

            if (_targetSearch.TryGetVisit(vertex, out backwardVisit))
            { // there is a status for this vertex in the source search.
                weight = _weightHandler.Add(weight, backwardVisit.Weight);
                if (_weightHandler.IsSmallerThan(weight, _bestWeight))
                { // this vertex is a better match.
                    _bestWeight       = weight;
                    _bestVertex       = vertex;
                    this.HasSucceeded = true;
                }
            }
            return(false);
        }
Пример #6
0
        /// <summary>
        /// Expands the last edge in the given edge path.
        /// </summary>
        private static EdgePath <T> ExpandLast <T>(this EdgePath <T> edgePath, DirectedDynamicGraph.EdgeEnumerator enumerator, WeightHandler <T> weightHandler)
            where T : struct
        {
            bool?direction;

            if (edgePath.Edge != Constants.NO_EDGE &&
                edgePath.From != null &&
                edgePath.From.Vertex != Constants.NO_VERTEX)
            {
                enumerator.MoveToEdge(edgePath.Edge);
                var contractedId = enumerator.GetContracted();
                if (contractedId.HasValue)
                { // there is a contracted vertex here!
                    // get source/target sequences.
                    var sequence1 = enumerator.GetSequence1();
                    sequence1.Reverse();
                    var sequence2 = enumerator.GetSequence2();

                    // move to the first edge (contracted -> from vertex) and keep details.
                    enumerator.MoveToEdge(contractedId.Value, edgePath.From.Vertex, sequence1);
                    var edge1   = enumerator.IdDirected();
                    var weight1 = weightHandler.GetEdgeWeight(enumerator.Current, out direction);

                    // move to the second edge (contracted -> to vertex) and keep details.
                    enumerator.MoveToEdge(contractedId.Value, edgePath.Vertex, sequence2);
                    var weight2 = weightHandler.GetEdgeWeight(enumerator.Current, out direction);
                    var edge2   = enumerator.IdDirected();

                    if (edgePath.Edge > 0)
                    {
                        var contractedPath = new EdgePath <T>(contractedId.Value, weightHandler.Add(edgePath.From.Weight, weight1), -edge1, edgePath.From);
                        contractedPath = contractedPath.ExpandLast(enumerator, weightHandler);
                        return((new EdgePath <T>(edgePath.Vertex, edgePath.Weight, edge2, contractedPath)).ExpandLast(enumerator, weightHandler));
                    }
                    else
                    {
                        var contractedPath = new EdgePath <T>(contractedId.Value, weightHandler.Add(edgePath.From.Weight, weight1), edge1, edgePath.From);
                        contractedPath = contractedPath.ExpandLast(enumerator, weightHandler);
                        return((new EdgePath <T>(edgePath.Vertex, edgePath.Weight, -edge2, contractedPath)).ExpandLast(enumerator, weightHandler));
                    }
                }
            }
            return(edgePath);
        }
Пример #7
0
        /// <summary>
        /// Builds an edge path from a path consisiting of only vertices.
        /// </summary>
        public static EdgePath <T> BuildEdgePath <T>(this RouterDb routerDb, WeightHandler <T> weightHandler, RouterPoint source, RouterPoint target, List <uint> vertexPath)
            where T : struct
        {
            if (vertexPath == null || vertexPath.Count == 0)
            {
                return(null);
            }

            var path = new EdgePath <T>(vertexPath[0]);
            var i    = 1;

            if (path.Vertex == Constants.NO_VERTEX)
            { // add first router point segment from source.
                path = source.EdgePathTo(routerDb, weightHandler, vertexPath[1]);
                i    = 2;
            }

            var edgeEnumerator = routerDb.Network.GeometricGraph.Graph.GetEdgeEnumerator();

            for (; i < vertexPath.Count; i++)
            {
                var vertex = vertexPath[i];
                if (vertex == Constants.NO_VERTEX)
                {
                    if (i != vertexPath.Count - 1)
                    {
                        throw new Exception("Invalid data found in vertex path: a non-vertex id was found at an invalid location.");
                    }
                    var toTarget = target.EdgePathTo(routerDb, weightHandler, path.Vertex, true);
                    path = new EdgePath <T>(toTarget.Vertex, weightHandler.Add(toTarget.Weight, path.Weight), toTarget.Edge, path);
                    break;
                }
                T   weight;
                var best = edgeEnumerator.FindBestEdge(weightHandler, path.Vertex, vertexPath[i], out weight);
                if (best == Constants.NO_EDGE)
                {
                    throw new Exception(string.Format("Cannot build vertex path, edge {0} -> {1} not found.", path.Vertex, vertexPath[i]));
                }

                path = new EdgePath <T>(vertexPath[i], weightHandler.Add(weight, path.Weight), best, path);
            }
            return(path);
        }
Пример #8
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            if (_heap.Count == 0)
            {
                return(false);
            }
            _current = _heap.Pop();
            if (_current != null)
            {
                while (_visits.ContainsKey(_current.Vertex))
                {
                    _current = _heap.Pop();
                    if (_current == null)
                    {
                        return(false);
                    }
                }
            }
            else
            {
                return(false);
            }
            _visits.Add(_current.Vertex, _current);

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

            _edgeEnumerator.MoveTo(_current.Vertex);
            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;
                    if (!_visits.ContainsKey(neighbourNeighbour))
                    { // if not yet settled.
                        var routeToNeighbour = new EdgePath <T>(
                            neighbourNeighbour, _weightHandler.Add(_current.Weight, neighbourWeight), _current);
                        if (_weightHandler.IsLargerThan(routeToNeighbour.Weight, _max))
                        {
                            continue;
                        }
                        _heap.Push(routeToNeighbour, _weightHandler.GetMetric(routeToNeighbour.Weight));
                    }
                }
            }
            return(true);
        }
Пример #9
0
        /// <summary>
        /// Expands the last edge in the given edge path.
        /// </summary>
        private static EdgePath <T> ExpandLast <T>(this EdgePath <T> edgePath, DirectedDynamicGraph.EdgeEnumerator enumerator, WeightHandler <T> weightHandler, bool direction)
            where T : struct
        {
            if (edgePath.Edge != Constants.NO_EDGE &&
                edgePath.From != null &&
                edgePath.From.Vertex != Constants.NO_VERTEX)
            {
                enumerator.MoveToEdge(edgePath.Edge);
                var contractedId = enumerator.GetContracted();
                if (contractedId.HasValue)
                { // there is a contracted vertex here!
                    // get source/target sequences.
                    var sequence1 = enumerator.GetSequence1();
                    sequence1.Reverse();
                    var sequence2 = enumerator.GetSequence2();

                    if (enumerator.Neighbour != edgePath.Vertex)
                    {
                        sequence1.Reverse();
                        sequence2.Reverse();

                        var t = sequence2;
                        sequence2 = sequence1;
                        sequence1 = t;
                    }

                    // move to the first edge (contracted -> from vertex) and keep details.
                    bool?localDirection;
                    if (!enumerator.MoveToEdge(contractedId.Value, edgePath.From.Vertex, sequence1, weightHandler, !direction))
                    {
                        throw new Exception(string.Format("Edge between {0} -> {1} with sequence {2} could not be found.",
                                                          contractedId.Value, edgePath.From.Vertex, sequence1.ToStringSafe()));
                    }
                    var edge1   = enumerator.IdDirected();
                    var weight1 = weightHandler.GetEdgeWeight(enumerator.Current, out localDirection);

                    // move to the second edge (contracted -> to vertex) and keep details.
                    if (!enumerator.MoveToEdge(contractedId.Value, edgePath.Vertex, sequence2, weightHandler, direction))
                    {
                        throw new Exception(string.Format("Edge between {0} -> {1} with sequence {2} could not be found.",
                                                          contractedId.Value, edgePath.Vertex, sequence2.ToStringSafe()));
                    }
                    var weight2 = weightHandler.GetEdgeWeight(enumerator.Current, out localDirection);
                    var edge2   = enumerator.IdDirected();

                    var contractedPath = new EdgePath <T>(contractedId.Value, weightHandler.Add(edgePath.From.Weight, weight1), edge1, edgePath.From);
                    contractedPath = contractedPath.ExpandLast(enumerator, weightHandler, direction);
                    return((new EdgePath <T>(edgePath.Vertex, edgePath.Weight, edge2, contractedPath)).ExpandLast(enumerator, weightHandler, direction));
                }
            }
            return(edgePath);
        }
Пример #10
0
        /// <summary>
        /// Called when a backward vertex was found.
        /// </summary>
        /// <returns></returns>
        private bool BackwardVertexFound(int i, EdgePath <T> path)
        {
            Dictionary <int, EdgePath <T> > bucket;

            if (_buckets.TryGetValue(path.Vertex, out bucket))
            {
                foreach (var pair in bucket)
                {
                    var existing = _paths[pair.Key][i];
                    var better   = true;
                    if (existing.Path != null)
                    {
                        var existingWeight = existing.Path.Weight;
                        var total          = _weightHandler.Add(path.Weight, pair.Value.Weight);
                        better = _weightHandler.IsSmallerThan(total, existingWeight);
                    }
                    else if (existing.Path1 != null &&
                             existing.Path2 != null)
                    {
                        var existingWeight = _weightHandler.Add(existing.Path1.Weight,
                                                                existing.Path2.Weight);
                        var total = _weightHandler.Add(path.Weight, pair.Value.Weight);
                        better = _weightHandler.IsSmallerThan(total, existingWeight);
                    }
                    if (better)
                    { // append the backward to the forward path.
                        _paths[pair.Key][i] = new Solution()
                        {
                            Path1 = pair.Value,
                            Path2 = path
                        };
                    }
                }
            }
            return(false);
        }
Пример #11
0
        /// <summary>
        /// Appends the given path in reverse to the edge path.
        /// </summary>
        public static EdgePath <T> Append <T>(this EdgePath <T> path, EdgePath <T> reversePath, WeightHandler <T> weightHandler)
            where T : struct
        {
            if (path.Vertex != reversePath.Vertex)
            {
                throw new System.Exception("Cannot append path that ends with a different vertex.");
            }

            while (reversePath.From != null)
            {
                var localWeight = weightHandler.Subtract(reversePath.Weight, reversePath.From.Weight);
                path        = new EdgePath <T>(reversePath.From.Vertex, weightHandler.Add(path.Weight, localWeight), -reversePath.Edge, path);
                reversePath = reversePath.From;
            }
            return(path);
        }
Пример #12
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            if (_pointerHeap.Count == 0)
            {
                return(false);
            }

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

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

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

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

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

                if ((!_backward && nWeight.Direction.F) ||
                    (_backward && nWeight.Direction.B))
                { // the edge is forward, and is to higher or was not contracted at all.
                    var nVertex     = _edgeEnumerator.Neighbour;
                    var totalWeight = _weightHandler.Add(nWeight.Weight, cWeight);
                    if (!_weightHandler.IsSmallerThan(totalWeight, _max))
                    {
                        continue;
                    }
                    var nPointer = _weightHandler.AddPathTree(_pathTree, nVertex, totalWeight, cPointer);
                    _pointerHeap.Push(nPointer, _weightHandler.GetMetric(totalWeight));
                }
            }
            return(true);
        }
Пример #13
0
        /// <summary>
        /// Called when a vertex was reached during a backward search.
        /// </summary>
        /// <returns></returns>
        private bool ReachedBackward(uint vertex1, T weight1, float length, EdgePath <T> edge)
        {
            // check forward search for the same vertex.
            EdgePath <T> forwardVisit;

            if (_sourceSearch.TryGetVisit(-edge.Edge, out forwardVisit))
            { // there is a status for this vertex in the source search.
                var localWeight = _weightHandler.Subtract(edge.Weight, weight1);
                var totalWeight = _weightHandler.Subtract(_weightHandler.Add(edge.Weight, forwardVisit.Weight), localWeight);
                if (_weightHandler.IsSmallerThan(totalWeight, _best.Item3))
                { // this vertex is a better match.
                    _best             = new Tuple <EdgePath <T>, EdgePath <T>, T>(forwardVisit, edge, totalWeight);
                    this.HasSucceeded = true;
                }
            }
            return(false);
        }
Пример #14
0
        /// <summary>
        /// Called when a backward vertex was found.
        /// </summary>
        /// <returns></returns>
        private bool BackwardVertexFound(int i, uint vertex, T weight)
        {
            Dictionary <int, T> bucket;

            if (_buckets.TryGetValue(vertex, out bucket))
            {
                foreach (var pair in bucket)
                {
                    var existing    = _weights[pair.Key][i];
                    var totalWeight = _weightHandler.Add(weight, pair.Value);
                    if (_weightHandler.IsSmallerThan(totalWeight, existing))
                    {
                        _weights[pair.Key][i] = totalWeight;
                    }
                }
            }
            return(false);
        }
Пример #15
0
        private void DoDualBased()
        {
            var uniqueSet = new HashSet <DirectedEdgeId>();
            var sources   = new List <DirectedEdgeId>(_correctedResolvedPoints.Count * 2);

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

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

            algorithm.Run();

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

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

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

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

                    int targetIdx;
                    map.TryGetValue(_correctedResolvedPoints[t].EdgeId, out targetIdx);
                    if (targetForward != null)
                    {
                        if (sourceForward != null)
                        {
                            var w = _weightHandler.Add(_weightHandler.Add(sourceForward.Value, targetForward.Value),
                                                       algorithm.Weights[sourceIdx * 2 + 1][targetIdx * 2 + 1]);
                            if (_weightHandler.IsSmallerThan(w, _weights[s * 2 + 1][t * 2 + 1]))
                            {
                                _weights[s * 2 + 1][t * 2 + 1] = w;
                            }
                        }
                        if (sourceBackward != null)
                        {
                            var w = _weightHandler.Add(_weightHandler.Add(sourceBackward.Value, targetForward.Value),
                                                       algorithm.Weights[sourceIdx * 2 + 0][targetIdx * 2 + 1]);
                            if (_weightHandler.IsSmallerThan(w, _weights[s * 2 + 0][t * 2 + 1]))
                            {
                                _weights[s * 2 + 0][t * 2 + 1] = w;
                            }
                        }
                    }
                    if (targetBackward != null)
                    {
                        if (sourceForward != null)
                        {
                            var w = _weightHandler.Add(_weightHandler.Add(sourceForward.Value, targetBackward.Value),
                                                       algorithm.Weights[sourceIdx * 2 + 1][targetIdx * 2 + 0]);
                            if (_weightHandler.IsSmallerThan(w, _weights[s * 2 + 1][t * 2 + 0]))
                            {
                                _weights[s * 2 + 1][t * 2 + 0] = w;
                            }
                        }
                        if (sourceBackward != null)
                        {
                            var w = _weightHandler.Add(_weightHandler.Add(sourceBackward.Value, targetBackward.Value),
                                                       algorithm.Weights[sourceIdx * 2 + 0][targetIdx * 2 + 0]);
                            if (_weightHandler.IsSmallerThan(w, _weights[s * 2 + 0][t * 2 + 0]))
                            {
                                _weights[s * 2 + 0][t * 2 + 0] = w;
                            }
                        }
                    }
                }
            }
        }
Пример #16
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            // while the visit list is not empty.
            var cPointer = uint.MaxValue;

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

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

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

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

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

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

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

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

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

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

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

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

                // update the visit list.
                _pointerHeap.Push(_weightHandler.AddPathTree(_pathTree, nDirectedEdgeId.Raw, totalWeight, cPointer), _weightHandler.GetMetric(totalWeight));
            }
            return(true);
        }
Пример #17
0
        /// <summary>
        /// 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];
                var edge1Sequence2 = edges[j].GetSequence2();
                if (edge1Sequence2.Length == 0)
                {
                    edge1Sequence2 = new uint[] { vertex };
                }

                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++)
                {
                    var edge2Sequence2 = edges[k].GetSequence2();
                    if (edge2Sequence2.Length == 0)
                    {
                        edge2Sequence2 = new uint[] { vertex };
                    }

                    if (forwardWitnesses[k].HasVertex(vertex))
                    { // get forward sequences.
                        s1forward[k] = forwardWitnesses[k].GetSequence1(enumerator, 1);
                        s2forward[k] = forwardWitnesses[k].GetSequence2(enumerator, 1);

                        if (!s1forward[k].IsSequenceIdentical(edge1Sequence2) ||
                            !s2forward[k].IsSequenceIdentical(edge2Sequence2))
                        { // start and end sequences of shortest paths need to match.
                            s1forward[k] = null;
                            s2forward[k] = null;
                        }
                    }
                    if (backwardWitnesses[k].HasVertex(vertex))
                    { // get backward sequences.
                        s1backward[k] = backwardWitnesses[k].GetSequence1(enumerator, 1);
                        s2backward[k] = backwardWitnesses[k].GetSequence2(enumerator, 1);

                        if (!s1backward[k].IsSequenceIdentical(edge1Sequence2) ||
                            !s2backward[k].IsSequenceIdentical(edge2Sequence2))
                        { // start and end sequences of shortest paths need to match.
                            s1backward[k] = null;
                            s2backward[k] = null;
                        }
                    }
                }

                // 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, s1backward[k], s2backward[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, s2backward[k], s1backward[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);
        }
Пример #18
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            // while the visit list is not empty.
            _current = null;
            if (_heap.Count > 0)
            { // choose the next vertex.
                _current = _heap.Pop();
                while (_current != null && _visits.ContainsKey(_current.Vertex))
                {     // keep dequeuing.
                    if (_heap.Count == 0)
                    { // nothing more to pop.
                        break;
                    }

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

                    _current = _heap.Pop();
                }
            }

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

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

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

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

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

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

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

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

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

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

                    if (_weightHandler.IsSmallerThan(totalWeight, _sourceMax))
                    { // update the visit list.
                        _heap.Push(new EdgePath <T>(neighbour, totalWeight, edge.IdDirected(), _current),
                                   _weightHandler.GetMetric(totalWeight));
                    }
                    else
                    { // the maxium was reached.
                        this.MaxReached = true;
                    }
                }
            }
            return(true);
        }
Пример #19
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            if (_heap.Count == 0)
            {
                return(false);
            }
            _current = _heap.Pop();
            while (_current != null)
            { // keep trying.
                LinkedEdgePath <T> edgePath = null;
                if (!_visits.TryGetValue(_current.Vertex, out edgePath))
                { // this vertex has not been visited before.
                    _visits.Add(_current.Vertex, new LinkedEdgePath <T>()
                    {
                        Path = _current
                    });
                    break;
                }
                else
                {     // vertex has been visited before, check if edge has.
                    if (!edgePath.HasPath(_current))
                    { // current edge has not been used to get to this vertex.
                        _visits[_current.Vertex] = new LinkedEdgePath <T>()
                        {
                            Path = _current,
                            Next = edgePath
                        };
                        break;
                    }
                }
                _current = _heap.Pop();
            }

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

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

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

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

            currentSequence = currentSequence.Append(_current.Vertex);

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

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

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

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

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

            return(true);
        }
Пример #20
0
        /// <summary>
        /// Executes the actual run.
        /// </summary>
        protected override void DoRun()
        {
            // keep settled vertices.
            _forwardVisits  = new Dictionary <uint, EdgePath <T> >();
            _backwardVisits = new Dictionary <uint, EdgePath <T> >();

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

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

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

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

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

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

                // do a forward search.
                if (forwardQueue.Count > 0)
                { // first check for better path.
                    // get the current queued with the smallest weight that hasn't been visited yet.
                    var current = forwardQueue.Pop();
                    while (current != null && _forwardVisits.ContainsKey(current.Vertex))
                    { // keep trying.
                        current = forwardQueue.Pop();
                    }

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

                        this.SearchForward(forwardQueue, current);
                    }
                }

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

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

                        this.SearchBackward(backwardQueue, current);
                    }
                }

                // calculate stopping conditions.
                if (forwardQueue.Count > 0)
                {
                    queueForwardWeight = forwardQueue.PeekWeight();
                }
                if (backwardQueue.Count > 0)
                {
                    queueBackwardWeight = backwardQueue.PeekWeight();
                }
            }
        }
Пример #21
0
        /// <summary>
        /// Contracts the given vertex.
        /// </summary>
        private void Contract(uint vertex)
        {
            // get and keep edges.
            var edges = new List <MetaEdge>(_graph.GetEdgeEnumerator(vertex));

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

            // check for a restriction, if vertex is restricted don't add shortcuts.
            if (_restrictions != null &&
                _restrictions.Update(vertex))
            {
                if (_restrictions.Restricts(vertex))
                {
                    return;
                }
            }

            // 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 bool[j];
                var backwardWitnesses = new bool[j];
                var targets           = new List <uint>(j);
                var targetWeights     = new List <T>(j);
                var targetMetrics     = new List <float>(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.
                    forwardWitnesses[k]  = !(edge1CanMoveBackward && edge2CanMoveForward);
                    backwardWitnesses[k] = !(edge1CanMoveForward && edge2CanMoveBackward);

                    targets.Add(edge2.Neighbour);
                    var totalWeight = _weightHandler.Add(edge1Weight, edge2Weight);
                    targetWeights.Add(totalWeight);
                    targetMetrics.Add(_weightHandler.GetMetric(totalWeight));
                }

                // calculate all witness paths.
                _witnessCalculator.Calculate(_graph.Graph, edge1.Neighbour, targets, targetMetrics, ref forwardWitnesses,
                                             ref backwardWitnesses, vertex);

                // 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 (!forwardWitnesses[k] && !backwardWitnesses[k])
                    { // add bidirectional edge.
                        _weightHandler.AddOrUpdateEdge(_graph, edge1.Neighbour, edge2.Neighbour,
                                                       vertex, null, targetWeights[k]);
                        //_graph.AddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                        //    targetWeights[k], null, vertex);
                        _weightHandler.AddOrUpdateEdge(_graph, edge2.Neighbour, edge1.Neighbour,
                                                       vertex, null, targetWeights[k]);
                        //_graph.AddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                        //    targetWeights[k], null, vertex);
                    }
                    else if (!forwardWitnesses[k])
                    { // add forward edge.
                        _weightHandler.AddOrUpdateEdge(_graph, edge1.Neighbour, edge2.Neighbour,
                                                       vertex, true, targetWeights[k]);
                        //_graph.AddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                        //    targetWeights[k], true, vertex);
                        _weightHandler.AddOrUpdateEdge(_graph, edge2.Neighbour, edge1.Neighbour,
                                                       vertex, false, targetWeights[k]);
                        //_graph.AddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                        //    targetWeights[k], false, vertex);
                    }
                    else if (!backwardWitnesses[k])
                    { // add forward edge.
                        _weightHandler.AddOrUpdateEdge(_graph, edge1.Neighbour, edge2.Neighbour,
                                                       vertex, false, targetWeights[k]);
                        //_graph.AddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                        //    targetWeights[k], false, vertex);
                        _weightHandler.AddOrUpdateEdge(_graph, edge2.Neighbour, edge1.Neighbour,
                                                       vertex, true, targetWeights[k]);
                        //_graph.AddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                        //    targetWeights[k], true, vertex);
                    }
                }
            }

            _contractedFlags[vertex] = true;
            _priorityCalculator.NotifyContracted(vertex);
        }
Пример #22
0
        /// <summary>
        /// Executes the actual run.
        /// </summary>
        protected override void DoRun(CancellationToken cancellationToken)
        {
            // keep settled vertices.
            _pathTree = new PathTree();

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

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

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

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

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

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

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

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

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

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

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

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

                // calculate stopping conditions.
                if (forwardQueue.Count > 0)
                {
                    queueForwardWeight = forwardQueue.PeekWeight();
                }
                if (backwardQueue.Count > 0)
                {
                    queueBackwardWeight = backwardQueue.PeekWeight();
                }
            }
        }
        /// <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));
        }