/// <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));
        }
Exemplo n.º 2
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]);
                    }
                }
            }
        }
Exemplo n.º 3
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);
        }
        /// <summary>
        /// Calculates the priority of the given vertex.
        /// </summary>
        public float Calculate(BitArray32 contractedFlags, uint vertex)
        {
            var removed = 0;
            var added   = 0;

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

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

                float edge1Weight;
                bool? edge1Direction;
                Data.Contracted.Edges.ContractedEdgeDataSerializer.Deserialize(edge1.Data[0],
                                                                               out edge1Weight, 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 <float>(j);
                for (var k = 0; k < j; k++)
                {
                    var edge2 = edges[k];

                    float edge2Weight;
                    bool? edge2Direction;
                    Data.Contracted.Edges.ContractedEdgeDataSerializer.Deserialize(edge2.Data[0],
                                                                                   out edge2Weight, out edge2Direction);
                    var edge2CanMoveForward  = edge2Direction == null || edge2Direction.Value;
                    var edge2CanMoveBackward = edge2Direction == null || !edge2Direction.Value;

                    forwardWitnesses[k]  = !(edge1CanMoveBackward && edge2CanMoveForward);
                    backwardWitnesses[k] = !(edge1CanMoveForward && edge2CanMoveBackward);
                    targets.Add(edge2.Neighbour);
                    targetWeights.Add(edge1Weight + edge2Weight);
                }

                // calculate all witness paths.
                _witnessCalculator.Calculate(_graph.Graph, edge1.Neighbour, targets, targetWeights,
                                             ref forwardWitnesses, ref backwardWitnesses, 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] && !backwardWitnesses[k])
                    { // add bidirectional edge.
                        _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                                                  targetWeights[k], null, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                        _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                                                  targetWeights[k], null, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                    }
                    else if (!forwardWitnesses[k])
                    { // add forward edge.
                        _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                                                  targetWeights[k], true, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                        _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                                                  targetWeights[k], false, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                    }
                    else if (!backwardWitnesses[k])
                    { // add forward edge.
                        _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour,
                                                  targetWeights[k], false, vertex, out addedLocal, out removedLocal);
                        added   += addedLocal;
                        removed += removedLocal;
                        _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour,
                                                  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));
        }