Example #1
0
        /// <summary>
        /// Adds or updates the weight for the given edge.
        /// </summary>
        public void AddOrUpdate(OriginalEdge edge, Shortcut <T> shortcut, WeightHandler <T> weightHandler)
        {
            Shortcut <T> existing;

            if (!_data.TryGetValue(edge, out existing))
            {
                _data[edge] = shortcut;
                return;
            }

            // update existing.
            var existingForward = weightHandler.GetMetric(existing.Forward);
            var newForward      = weightHandler.GetMetric(shortcut.Forward);

            if (existingForward == 0 ||
                existingForward > newForward)
            {
                existing.Forward = shortcut.Forward;
            }
            var existingBackward = weightHandler.GetMetric(existing.Backward);
            var newBackward      = weightHandler.GetMetric(shortcut.Backward);

            if (existingBackward == 0 ||
                existingBackward > newBackward)
            {
                existing.Backward = shortcut.Backward;
            }
            _data[edge] = existing;
        }
Example #2
0
        /// <summary>
        /// Initializes and resets.
        /// </summary>
        public void Initialize()
        {
            // algorithm always succeeds, it may be dealing with an empty network and there are no targets.
            this.HasSucceeded = true;

            // intialize dykstra data structures.
            _visits = new Dictionary <uint, EdgePath <T> >();
            _heap   = new BinaryHeap <EdgePath <T> >(1000);

            // queue all sources.
            foreach (var source in _sources)
            {
                if (_getRestriction != null)
                {
                    var restriction = _getRestriction(source.Vertex);
                    if (restriction != Constants.NO_VERTEX)
                    {
                        continue;
                    }
                }

                _heap.Push(source, _weightHandler.GetMetric(source.Weight));
            }

            // gets the edge enumerator.
            _edgeEnumerator = _graph.GetEdgeEnumerator();
        }
Example #3
0
        /// <summary>
        /// Contracts the given vertex.
        /// </summary>
        private void Contract()
        {
            var vertex     = _vertexInfo.Vertex;
            var enumerator = _graph.GetEdgeEnumerator();

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

            while (i < _vertexInfo.Count)
            {
                var edge = _vertexInfo[i];

                _graph.RemoveEdge(edge.Neighbour, vertex);
                i++;
            }

            // add shortcuts.
            foreach (var s in _vertexInfo.Shortcuts)
            {
                var shortcut       = s.Value;
                var edge           = s.Key;
                var forwardMetric  = _weightHandler.GetMetric(shortcut.Forward);
                var backwardMetric = _weightHandler.GetMetric(shortcut.Backward);

                if (forwardMetric > 0 && forwardMetric < float.MaxValue &&
                    backwardMetric > 0 && backwardMetric < float.MaxValue &&
                    System.Math.Abs(backwardMetric - forwardMetric) < HierarchyBuilder <float> .E)
                { // forward and backward and identical weights.
                    _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2,
                                                   vertex, null, shortcut.Forward);
                    _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1,
                                                   vertex, null, shortcut.Backward);
                }
                else
                {
                    if (forwardMetric > 0 && forwardMetric < float.MaxValue)
                    {
                        _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2,
                                                       vertex, true, shortcut.Forward);
                        _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1,
                                                       vertex, false, shortcut.Forward);
                    }
                    if (backwardMetric > 0 && backwardMetric < float.MaxValue)
                    {
                        _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2,
                                                       vertex, false, shortcut.Backward);
                        _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1,
                                                       vertex, true, shortcut.Backward);
                    }
                }
            }

            _contractedFlags[vertex] = true;
            this.NotifyContracted(vertex);
        }
Example #4
0
        /// <summary>
        /// Initializes and resets.
        /// </summary>
        public void Initialize()
        {
            // algorithm always succeeds, it may be dealing with an empty network and there are no targets.
            this.HasSucceeded = true;

            // intialize dykstra data structures.
            _visits = new Dictionary <uint, LinkedEdgePath <T> >();
            _heap   = new BinaryHeap <EdgePath <T> >();

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

            // gets the edge enumerator.
            _edgeEnumerator = _graph.GetEdgeEnumerator();
        }
Example #5
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);
        }
Example #6
0
        /// <summary>
        /// Calculates all routes between all sources and all targets.
        /// </summary>
        /// <returns></returns>
        public sealed override Result <T[][]> TryCalculateWeight <T>(IProfileInstance profileInstance, WeightHandler <T> weightHandler, RouterPoint[] sources, RouterPoint[] targets,
                                                                     ISet <int> invalidSources, ISet <int> invalidTargets, RoutingSettings <T> settings)
        {
            try
            {
                if (!_db.Supports(profileInstance.Profile))
                {
                    return(new Result <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;
                T[][]        weights = null;

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

                    if (!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 node-based routing.
                        var algorithm = new Itinero.Algorithms.Contracted.ManyToManyWeightsBidirectionalDykstra <T>(_db, profileInstance.Profile, weightHandler,
                                                                                                                    sources, targets, maxSearch);
                        algorithm.Run();
                        if (!algorithm.HasSucceeded)
                        {
                            return(new Result <T[][]>(algorithm.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }
                        weights = algorithm.Weights;
                    }
                    else
                    { // use edge-based routing.
                        var algorithm = new Itinero.Algorithms.Contracted.EdgeBased.ManyToManyWeightsBidirectionalDykstra <T>(_db, profileInstance.Profile, weightHandler,
                                                                                                                              sources, targets, maxSearch);
                        algorithm.Run();
                        if (!algorithm.HasSucceeded)
                        {
                            return(new Result <T[][]>(algorithm.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }
                        weights = algorithm.Weights;
                    }
                }
                else
                { // use regular graph.
                    if (_db.HasComplexRestrictions(profileInstance.Profile))
                    {
                        var algorithm = new Itinero.Algorithms.Default.EdgeBased.ManyToMany <T>(this, weightHandler, _db.GetGetRestrictions(profileInstance.Profile, true), sources, targets, maxSearch);
                        algorithm.Run();
                        if (!algorithm.HasSucceeded)
                        {
                            return(new Result <T[][]>(algorithm.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }
                        weights = algorithm.Weights;
                    }
                    else
                    {
                        var algorithm = new Itinero.Algorithms.Default.ManyToMany <T>(_db, weightHandler, sources, targets, maxSearch);
                        algorithm.Run();
                        if (!algorithm.HasSucceeded)
                        {
                            return(new Result <T[][]>(algorithm.ErrorMessage, (message) =>
                            {
                                return new RouteNotFoundException(message);
                            }));
                        }
                        weights = algorithm.Weights;
                    }
                }

                // check for invalids.
                var invalidTargetCounts = new int[targets.Length];
                for (var s = 0; s < weights.Length; s++)
                {
                    var invalids = 0;
                    for (var t = 0; t < weights[s].Length; t++)
                    {
                        if (t != s)
                        {
                            if (weightHandler.GetMetric(weights[s][t]) == float.MaxValue)
                            {
                                invalids++;
                                invalidTargetCounts[t]++;
                                if (invalidTargetCounts[t] > (sources.Length - 1) / 2)
                                {
                                    invalidTargets.Add(t);
                                }
                            }
                        }
                    }

                    if (invalids > (targets.Length - 1) / 2)
                    {
                        invalidSources.Add(s);
                    }
                }
                return(new Result <T[][]>(weights));
            }
            catch (Exception ex)
            {
                return(new Result <T[][]>(ex.Message, (m) => ex));
            }
        }
Example #7
0
        public static bool RemoveShortcuts <T>(this VertexInfo <T> vertexInfo, DirectedGraph witnessGraph, WeightHandler <T> weightHandler)
            where T : struct
        {
            var witnessGraphEnumerator = witnessGraph.GetEdgeEnumerator();

            List <Tuple <OriginalEdge, Shortcut <T> > > toUpdate = null;

            foreach (var pair in vertexInfo.Shortcuts)
            {
                var edge = pair.Key;

                if (edge.Vertex1 >= witnessGraph.VertexCount ||
                    edge.Vertex2 >= witnessGraph.VertexCount)
                {
                    continue;
                }

                var shortcut = pair.Value;

                var shortcutForward  = weightHandler.GetMetric(shortcut.Forward);
                var shortcutBackward = weightHandler.GetMetric(shortcut.Backward);

                var witnessedForward  = float.MaxValue;
                var witnessedBackward = float.MaxValue;
                if (edge.Vertex1 < edge.Vertex2)
                {
                    witnessGraphEnumerator.MoveTo(edge.Vertex1);
                    while (witnessGraphEnumerator.MoveNext())
                    {
                        if (witnessGraphEnumerator.Neighbour == edge.Vertex2)
                        {
                            witnessedForward  = DirectedGraphExtensions.FromData(witnessGraphEnumerator.Data0);
                            witnessedBackward = DirectedGraphExtensions.FromData(witnessGraphEnumerator.Data1);
                            break;
                        }
                    }
                }
                else
                {
                    witnessGraphEnumerator.MoveTo(edge.Vertex2);
                    while (witnessGraphEnumerator.MoveNext())
                    {
                        if (witnessGraphEnumerator.Neighbour == edge.Vertex1)
                        {
                            witnessedBackward = DirectedGraphExtensions.FromData(witnessGraphEnumerator.Data0);
                            witnessedForward  = DirectedGraphExtensions.FromData(witnessGraphEnumerator.Data1);
                            break;
                        }
                    }
                }

                // check forward.
                var hasUpdates = false;
                if (shortcutForward > 0 && shortcutForward < float.MaxValue &&
                    shortcutForward - FastHierarchyBuilder <float> .E > witnessedForward)
                {
                    shortcut.Forward = weightHandler.Infinite;
                    hasUpdates       = true;
                }
                if (shortcutBackward > 0 && shortcutBackward < float.MaxValue &&
                    shortcutBackward - FastHierarchyBuilder <float> .E > witnessedBackward)
                {
                    shortcut.Backward = weightHandler.Infinite;
                    hasUpdates        = true;
                }

                if (hasUpdates)
                {
                    if (toUpdate == null)
                    {
                        toUpdate = new List <Tuple <OriginalEdge, Shortcut <T> > >();
                    }
                    toUpdate.Add(new Tuple <OriginalEdge, Shortcut <T> >(edge, shortcut));
                }
            }

            if (toUpdate != null)
            {
                foreach (var update in toUpdate)
                {
                    vertexInfo.Shortcuts[update.Item1] = update.Item2;
                }
                return(true);
            }
            return(false);
        }
Example #8
0
        /// <summary>
        /// Calculates the priority of this vertex.
        /// </summary>
        public static float Priority <T>(this VertexInfo <T> vertexInfo, DirectedMetaGraph graph, WeightHandler <T> weightHandler, float differenceFactor, float contractedFactor,
                                         float depthFactor, float weightDiffFactor = 1)
            where T : struct
        {
            var vertex = vertexInfo.Vertex;

            var removed = vertexInfo.Count;
            var added   = 0;

            //var removedWeight = 0f;
            //var addedWeight = 0f;

            foreach (var shortcut in vertexInfo.Shortcuts)
            {
                var shortcutForward  = weightHandler.GetMetric(shortcut.Value.Forward);
                var shortcutBackward = weightHandler.GetMetric(shortcut.Value.Backward);

                int localAdded, localRemoved;
                if (shortcutForward > 0 && shortcutForward < float.MaxValue &&
                    shortcutBackward > 0 && shortcutBackward < float.MaxValue &&
                    System.Math.Abs(shortcutForward - shortcutBackward) < HierarchyBuilder.E)
                { // add two bidirectional edges.
                    graph.TryAddOrUpdateEdge(shortcut.Key.Vertex1, shortcut.Key.Vertex2, shortcutForward, null, vertex,
                                             out localAdded, out localRemoved);
                    added   += localAdded;
                    removed += localRemoved;
                    graph.TryAddOrUpdateEdge(shortcut.Key.Vertex2, shortcut.Key.Vertex1, shortcutForward, null, vertex,
                                             out localAdded, out localRemoved);
                    added   += localAdded;
                    removed += localRemoved;

                    //added += 2;
                    //addedWeight += shortcutForward;
                    //addedWeight += shortcutBackward;
                }
                else
                {
                    if (shortcutForward > 0 && shortcutForward < float.MaxValue)
                    {
                        graph.TryAddOrUpdateEdge(shortcut.Key.Vertex1, shortcut.Key.Vertex2, shortcutForward, true, vertex,
                                                 out localAdded, out localRemoved);
                        added   += localAdded;
                        removed += localRemoved;
                        graph.TryAddOrUpdateEdge(shortcut.Key.Vertex2, shortcut.Key.Vertex1, shortcutForward, false, vertex,
                                                 out localAdded, out localRemoved);
                        added   += localAdded;
                        removed += localRemoved;

                        //added += 2;
                        //addedWeight += shortcutForward;
                        //addedWeight += shortcutForward;
                    }
                    if (shortcutBackward > 0 && shortcutBackward < float.MaxValue)
                    {
                        graph.TryAddOrUpdateEdge(shortcut.Key.Vertex1, shortcut.Key.Vertex2, shortcutBackward, false, vertex,
                                                 out localAdded, out localRemoved);
                        added   += localAdded;
                        removed += localRemoved;
                        graph.TryAddOrUpdateEdge(shortcut.Key.Vertex2, shortcut.Key.Vertex1, shortcutBackward, true, vertex,
                                                 out localAdded, out localRemoved);
                        added   += localAdded;
                        removed += localRemoved;

                        //added += 2;
                        //addedWeight += shortcutBackward;
                        //addedWeight += shortcutBackward;
                    }
                }
            }

            //for (var e = 0; e < vertexInfo.Count; e++)
            //{
            //    var w = weightHandler.GetEdgeWeight(vertexInfo[e]);
            //    var wMetric = weightHandler.GetMetric(w.Weight);

            //    if (w.Direction.F)
            //    {
            //        removedWeight += wMetric;
            //    }
            //    if (w.Direction.B)
            //    {
            //        removedWeight += wMetric;
            //    }
            //}

            var weigthDiff = 1f;

            //if (removedWeight != 0)
            //{
            //    weigthDiff = removedWeight;
            //}

            return((differenceFactor * (added - removed) + (depthFactor * vertexInfo.Depth) +
                    (contractedFactor * vertexInfo.ContractedNeighbours)) * (weigthDiff * weightDiffFactor));
        }
Example #9
0
        /// <summary>
        /// Contracts the given vertex.
        /// </summary>
        protected virtual void Contract()
        {
            var vertex = _vertexInfo.Vertex;

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

            while (i < _vertexInfo.Count)
            {
                var edge = _vertexInfo[i];

                _graph.RemoveEdge(edge.Neighbour, vertex);
                i++;

                // TOOD: what to do when stuff is only removed, is nothing ok?
                //_witnessQueue.Add(edge.Neighbour);
            }

            // add shortcuts.
            foreach (var s in _vertexInfo.Shortcuts)
            {
                var shortcut = s.Value;
                var edge     = s.Key;

                if (edge.Vertex1 == edge.Vertex2)
                { // TODO: figure out how this is possible, it shouldn't!
                    continue;
                }

                var forwardMetric  = _weightHandler.GetMetric(shortcut.Forward);
                var backwardMetric = _weightHandler.GetMetric(shortcut.Backward);

                if (forwardMetric > 0 && forwardMetric < float.MaxValue &&
                    backwardMetric > 0 && backwardMetric < float.MaxValue &&
                    System.Math.Abs(backwardMetric - forwardMetric) < FastHierarchyBuilder <float> .E)
                { // forward and backward and identical weights.
                    _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2,
                                                   vertex, null, shortcut.Forward);
                    _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1,
                                                   vertex, null, shortcut.Backward);
                    _witnessQueue.Add(edge.Vertex1);
                    _witnessQueue.Add(edge.Vertex2);
                }
                else
                {
                    if (forwardMetric > 0 && forwardMetric < float.MaxValue)
                    {
                        _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2,
                                                       vertex, true, shortcut.Forward);
                        _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1,
                                                       vertex, false, shortcut.Forward);
                        _witnessQueue.Add(edge.Vertex1);
                        _witnessQueue.Add(edge.Vertex2);
                    }
                    if (backwardMetric > 0 && backwardMetric < float.MaxValue)
                    {
                        _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2,
                                                       vertex, false, shortcut.Backward);
                        _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1,
                                                       vertex, true, shortcut.Backward);
                        _witnessQueue.Add(edge.Vertex1);
                        _witnessQueue.Add(edge.Vertex2);
                    }
                }
            }

            _contractedFlags[vertex] = true;
            this.NotifyContracted(vertex);
        }
Example #10
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);
        }
Example #11
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();
                }
            }
        }
Example #12
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();
                }
            }
        }
Example #13
0
        /// <summary>
        /// Calculates witness paths.
        /// </summary>
        public virtual void Calculate(DirectedGraph graph, WeightHandler <T> weightHandler, uint vertex,
                                      uint source, Dictionary <uint, Shortcut <T> > targets, int maxSettles, int hopLimit)
        {
            pathTree.Clear();
            pointerHeap.Clear();

            var forwardSettled  = new HashSet <uint>();
            var backwardSettled = new HashSet <uint>();

            var forwardTargets  = new HashSet <uint>();
            var backwardTargets = new HashSet <uint>();

            var maxWeight = 0f;

            foreach (var targetPair in targets)
            {
                var target   = targetPair.Key;
                var shortcut = targetPair.Value;
                var e        = new OriginalEdge(source, target);

                var shortcutForward = weightHandler.GetMetric(shortcut.Forward);
                if (shortcutForward > 0 && shortcutForward < float.MaxValue)
                {
                    forwardTargets.Add(e.Vertex2);
                    if (shortcutForward > maxWeight)
                    {
                        maxWeight = shortcutForward;
                    }
                }
                var shortcutBackward = weightHandler.GetMetric(shortcut.Backward);
                if (shortcutBackward > 0 && shortcutBackward < float.MaxValue)
                {
                    backwardTargets.Add(e.Vertex2);
                    if (shortcutBackward > maxWeight)
                    {
                        maxWeight = shortcutBackward;
                    }
                }
            }

            // queue the source.
            pathTree.Clear();
            pointerHeap.Clear();
            var p = pathTree.AddSettledVertex(source, new WeightAndDir <float>()
            {
                Direction = new Dir(true, true),
                Weight    = 0
            }, 0);

            pointerHeap.Push(p, 0);

            // dequeue vertices until stopping conditions are reached.
            var cVertex = Constants.NO_VERTEX;
            WeightAndDir <float> cWeight;
            var cHops      = uint.MaxValue;
            var enumerator = graph.GetEdgeEnumerator();

            while (pointerHeap.Count > 0)
            {
                var cPointer = pointerHeap.Pop();
                pathTree.GetSettledVertex(cPointer, out cVertex, out cWeight, out cHops);

                if (cVertex == vertex)
                {
                    continue;
                }

                if (cWeight.Weight >= maxWeight)
                {
                    break;
                }

                if (forwardSettled.Contains(cVertex) ||
                    forwardTargets.Count == 0 ||
                    forwardSettled.Count > maxSettles)
                {
                    cWeight.Direction = new Dir(false, cWeight.Direction.B);
                }
                if (backwardSettled.Contains(cVertex) ||
                    backwardTargets.Count == 0 ||
                    backwardSettled.Count > maxSettles)
                {
                    cWeight.Direction = new Dir(cWeight.Direction.F, false);
                }

                if (cWeight.Direction.F)
                {
                    forwardSettled.Add(cVertex);
                    if (forwardTargets.Contains(cVertex))
                    { // target reached, evaluate it as a shortcut.
                        Shortcut <T> shortcut;
                        if (targets.TryGetValue(cVertex, out shortcut))
                        {
                            var shortcutForward = weightHandler.GetMetric(shortcut.Forward);
                            if (shortcutForward > cWeight.Weight)
                            { // a witness path was found, don't add a shortcut.
                                shortcut.Forward = weightHandler.Zero;
                                targets[cVertex] = shortcut;
                            }
                        }
                        forwardTargets.Remove(cVertex);
                        if (forwardTargets.Count == 0)
                        {
                            if (backwardTargets.Count == 0)
                            {
                                break;
                            }
                            cWeight.Direction = new Dir(false, cWeight.Direction.B);
                            if (!cWeight.Direction.F && !cWeight.Direction.B)
                            {
                                continue;
                            }
                        }
                    }
                }
                if (cWeight.Direction.B)
                {
                    backwardSettled.Add(cVertex);
                    if (backwardTargets.Contains(cVertex))
                    { // target reached, evaluate it as a shortcut.
                        Shortcut <T> shortcut;
                        if (targets.TryGetValue(cVertex, out shortcut))
                        {
                            var shortcutBackward = weightHandler.GetMetric(shortcut.Backward);
                            if (shortcutBackward > cWeight.Weight)
                            { // a witness path was found, don't add a shortcut.
                                shortcut.Backward = weightHandler.Zero;
                                targets[cVertex]  = shortcut;
                            }
                        }
                        backwardTargets.Remove(cVertex);
                        if (backwardTargets.Count == 0)
                        {
                            if (forwardTargets.Count == 0)
                            {
                                break;
                            }
                            cWeight.Direction = new Dir(cWeight.Direction.F, false);
                            if (!cWeight.Direction.F && !cWeight.Direction.B)
                            {
                                continue;
                            }
                        }
                    }
                }

                if (cHops + 1 >= hopLimit)
                {
                    continue;
                }

                if (forwardSettled.Count > maxSettles &&
                    backwardSettled.Count > maxSettles)
                {
                    continue;
                }

                enumerator.MoveTo(cVertex);
                while (enumerator.MoveNext())
                {
                    var nVertex = enumerator.Neighbour;
                    var nWeight = ContractedEdgeDataSerializer.Deserialize(enumerator.Data0);

                    nWeight = new WeightAndDir <float>()
                    {
                        Direction = Dir.Combine(cWeight.Direction, nWeight.Direction),
                        Weight    = cWeight.Weight + nWeight.Weight
                    };

                    if (nWeight.Direction.F &&
                        forwardSettled.Contains(nVertex))
                    {
                        nWeight.Direction = new Dir(false, nWeight.Direction.B);
                    }
                    if (nWeight.Direction.B &&
                        backwardSettled.Contains(nVertex))
                    {
                        nWeight.Direction = new Dir(nWeight.Direction.F, false);
                    }
                    if (!nWeight.Direction.F && !nWeight.Direction.B)
                    {
                        continue;
                    }

                    var nPoiner = pathTree.AddSettledVertex(nVertex, nWeight, cHops + 1);
                    pointerHeap.Push(nPoiner, nWeight.Weight);
                }
            }
        }
Example #14
0
        /// <summary>
        /// Remove all witnessed edges.
        /// </summary>
        private void RemoveWitnessedEdges()
        {
            _logger.Log(TraceEventType.Information, "Removing witnessed edges...");

            var edges   = new List <MetaEdge>();
            var weights = new List <T>();
            var metrics = new List <float>();
            var targets = new List <uint>();

            for (uint vertex = 0; vertex < _graph.VertexCount; vertex++)
            {
                edges.Clear();
                weights.Clear();
                metrics.Clear();
                targets.Clear();

                edges.AddRange(_graph.GetEdgeEnumerator(vertex));

                var forwardWitnesses  = new bool[edges.Count];
                var backwardWitnesses = new bool[edges.Count];
                for (var i = 0; i < edges.Count; i++)
                {
                    var edge = edges[i];

                    bool?edgeDirection;
                    var  edgeWeight = _weightHandler.GetEdgeWeight(edge, out edgeDirection);

                    var edgeCanMoveForward  = edgeDirection == null || edgeDirection.Value;
                    var edgeCanMoveBackward = edgeDirection == null || !edgeDirection.Value;

                    forwardWitnesses[i]  = !edgeCanMoveForward;
                    backwardWitnesses[i] = !edgeCanMoveBackward;
                    weights.Add(edgeWeight);
                    metrics.Add(_weightHandler.GetMetric(edgeWeight));
                    targets.Add(edge.Neighbour);
                }

                // calculate all witness paths.
                _witnessCalculator.Calculate(_graph.Graph, vertex, targets, metrics,
                                             ref forwardWitnesses, ref backwardWitnesses, uint.MaxValue);

                // check witness paths.
                for (var i = 0; i < edges.Count; i++)
                {
                    if (forwardWitnesses[i] && backwardWitnesses[i])
                    { // in both directions the edge does not represent the shortest path.
                        _graph.RemoveEdge(vertex, targets[i]);
                    }
                    else if (forwardWitnesses[i])
                    { // only in forward direction is this edge useless.
                        _graph.RemoveEdge(vertex, targets[i]);
                        _weightHandler.AddEdge(_graph, vertex, targets[i], Constants.NO_VERTEX, false, weights[i]);
                        //_graph.AddEdge(vertex, targets[i], weights[i], false, Constants.NO_VERTEX);
                    }
                    else if (backwardWitnesses[i])
                    { // only in backward direction is this edge useless.
                        _graph.RemoveEdge(vertex, targets[i]);
                        _weightHandler.AddEdge(_graph, vertex, targets[i], Constants.NO_VERTEX, true, weights[i]);
                    }
                }
            }
        }
        /// <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 #16
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].ToEdgePathsDirected(_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];
                if (paths.Length == 2)
                {
                    _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].ToEdgePathsDirected(_router.Db, _weightHandler, false);
                if (paths.Length == 0)
                {
                    this.ErrorMessage = string.Format("Target at {0} could not be resolved properly.", i);
                    return;
                }

                // make sure paths are the opposive of the sources.
                if (paths[0].Edge == _sourcePaths[i * 2 + 0].Edge)
                { // switchs.
                    _targetPaths[i * 2 + 1] = paths[0];
                    if (paths.Length == 2)
                    {
                        _targetPaths[i * 2 + 0] = paths[1];
                    }
                }
                else
                { // keep.
                    _targetPaths[i * 2 + 0] = paths[0];
                    if (paths.Length == 2)
                    {
                        _targetPaths[i * 2 + 1] = paths[1];
                    }
                }
            }

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

            // do forward searches into buckets.
            for (var i = 0; i < _sourcePaths.Length; i++)
            {
                var path = _sourcePaths[i];
                if (path != null)
                {
                    var forward = new Itinero.Algorithms.Contracted.EdgeBased.Dykstra <T>(_graph, _weightHandler, new EdgePath <T>[] { path }, (v) => null, false, _max);
                    forward.WasFound += (foundPath) =>
                    {
                        LinkedEdgePath <T> visits;
                        forward.TryGetVisits(foundPath.Vertex, out visits);
                        return(this.ForwardVertexFound(i, foundPath.Vertex, visits));
                    };
                    forward.Run();
                }
            }

            // do backward searches into buckets.
            for (var i = 0; i < _targetPaths.Length; i++)
            {
                var path = _targetPaths[i];
                if (path != null)
                {
                    var backward = new Itinero.Algorithms.Contracted.EdgeBased.Dykstra <T>(_graph, _weightHandler, new EdgePath <T>[] { path }, (v) => null, true, _max);
                    backward.WasFound += (foundPath) =>
                    {
                        LinkedEdgePath <T> visits;
                        backward.TryGetVisits(foundPath.Vertex, out visits);
                        return(this.BackwardVertexFound(i, foundPath.Vertex, visits));
                    };
                    backward.Run();
                }
            }

            // 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 #17
0
        /// <summary>
        /// Remove all witnessed edges.
        /// </summary>
        private void RemoveWitnessedEdges()
        {
            _logger.Log(TraceEventType.Information, "Removing witnessed edges...");

            var witnessEdgeEnumerator = _witnessGraph.GetEdgeEnumerator();
            var edgeEnumerator        = _graph.GetEdgeEnumerator();
            var edges = new List <MetaEdge>();

            for (uint vertex = 0; vertex < _graph.VertexCount; vertex++)
            {
                // collect all relevant edges.
                edges.Clear();
                if (witnessEdgeEnumerator.MoveTo(vertex) &&
                    edgeEnumerator.MoveTo(vertex))
                {
                    while (edgeEnumerator.MoveNext())
                    {
                        if (vertex < edgeEnumerator.Neighbour)
                        { // only check in on directions, all edges are added twice initially.
                            edges.Add(edgeEnumerator.Current);
                        }
                    }
                }

                // check witness paths.
                for (var i = 0; i < edges.Count; i++)
                {
                    var edge = edges[0];
                    while (witnessEdgeEnumerator.MoveNext())
                    {
                        if (witnessEdgeEnumerator.Neighbour == edge.Neighbour)
                        { // this edge is witnessed, figure out how.
                            var forwardWitnessWeight  = DirectedGraphExtensions.FromData(witnessEdgeEnumerator.Data0);
                            var backwardWitnessWeight = DirectedGraphExtensions.FromData(witnessEdgeEnumerator.Data1);

                            var weightAndDir = _weightHandler.GetEdgeWeight(edge);
                            var weight       = _weightHandler.GetMetric(weightAndDir.Weight);
                            var witnessed    = false;
                            if (weightAndDir.Direction.F &&
                                weight > forwardWitnessWeight)
                            { // witnessed in forward direction.
                                weightAndDir.Direction = new Dir(false, weightAndDir.Direction.B);
                                witnessed = true;
                            }
                            if (weightAndDir.Direction.B &&
                                weight > backwardWitnessWeight)
                            { // witnessed in backward direction.
                                weightAndDir.Direction = new Dir(weightAndDir.Direction.F, false);
                                witnessed = true;
                            }
                            if (witnessed)
                            { // edge was witnessed, do something.
                                // remove the edge (in both directions)
                                _graph.RemoveEdge(vertex, edge.Neighbour);
                                _graph.RemoveEdge(edge.Neighbour, vertex);
                                if (weightAndDir.Direction.B || weightAndDir.Direction.F)
                                { // add it again if there is something relevant still left.
                                    _weightHandler.AddEdge(_graph, vertex, edge.Neighbour, Constants.NO_VERTEX,
                                                           weightAndDir.Direction.AsNullableBool(), weightAndDir.Weight);
                                    weightAndDir.Direction.Reverse();
                                    _weightHandler.AddEdge(_graph, edge.Neighbour, vertex, Constants.NO_VERTEX,
                                                           weightAndDir.Direction.AsNullableBool(), weightAndDir.Weight);
                                }
                            }
                        }
                    }
                }
            }
        }
Example #18
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);
        }
Example #19
0
        /// <summary>
        /// Executes the algorithm.
        /// </summary>
        protected sealed override void DoRun(CancellationToken cancellationToken)
        {
            // run mass resolver if needed.
            if (!_massResolver.HasRun)
            {
                _massResolver.Run(cancellationToken);
            }

            // 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(cancellationToken);
            }
            else
            {
                this.DoDualBased(cancellationToken);
            }

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