Ejemplo n.º 1
0
        /// <summary>
        /// Search forward from one vertex.
        /// </summary>
        /// <returns></returns>
        private void SearchForward(BinaryHeap <EdgePath <T> > queue, EdgePath <T> current)
        {
            if (current != null)
            { // there is a next vertex found.
                // check restrictions.
                if (_restrictions != null &&
                    _restrictions.Update(current.Vertex) &&
                    _restrictions.Restricts(current.Vertex))
                { // vertex is restricted, don't settle.
                    return;
                }

                // get the edge enumerator.
                var edgeEnumerator = _graph.GetEdgeEnumerator();

                // add to the settled vertices.
                EdgePath <T> previousLinkedRoute;
                if (_forwardVisits.TryGetValue(current.Vertex, out previousLinkedRoute))
                {
                    if (_weightHandler.IsLargerThan(previousLinkedRoute.Weight, current.Weight))
                    { // settle the vertex again if it has a better weight.
                        _forwardVisits[current.Vertex] = current;
                    }
                }
                else
                { // settled the vertex.
                    _forwardVisits.Add(current.Vertex, current);
                }

                // get neighbours.
                edgeEnumerator.MoveTo(current.Vertex);

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

                    if (neighbourDirection == null || neighbourDirection.Value)
                    { // the edge is forward, and is to higher or was not contracted at all.
                        var neighbourNeighbour = edgeEnumerator.Neighbour;
                        if (!_forwardVisits.ContainsKey(neighbourNeighbour))
                        { // if not yet settled.
                            var routeToNeighbour = new EdgePath <T>(
                                neighbourNeighbour, _weightHandler.Add(current.Weight, neighbourWeight), current);
                            queue.Push(routeToNeighbour, _weightHandler.GetMetric(routeToNeighbour.Weight));
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Executes the actual algorithm.
        /// </summary>
        protected override void DoRun()
        {
            float  distance;
            ushort edgeProfile;

            var enumerator1 = _source.GetEdgeEnumerator();
            var enumerator2 = _source.GetEdgeEnumerator();

            for (uint v = 0; v < _source.VertexCount; v++)
            {
                enumerator1.MoveTo(v);
                while (enumerator1.MoveNext())
                {
                    EdgeDataSerializer.Deserialize(enumerator1.Data0,
                                                   out distance, out edgeProfile);
                    var accessible1 = false;
                    var weight1     = _weightHandler.CalculateWeightAndDir(edgeProfile, distance, out accessible1);
                    if (enumerator1.DataInverted)
                    {
                        var dir = weight1.Direction;
                        dir.Reverse();
                        weight1.Direction = dir;
                    }
                    if (!accessible1)
                    { // not accessible.
                        continue;
                    }
                    var direction1 = weight1.Direction;
                    var edge1      = enumerator1.DirectedEdgeId();

                    // look at the neighbours of this edge.
                    enumerator2.MoveTo(enumerator1.To);
                    _restrictions.Update(enumerator1.To);
                    while (enumerator2.MoveNext())
                    {
                        var turn = new Turn(new OriginalEdge(v, enumerator1.To), Constants.NO_VERTEX);
                        EdgeDataSerializer.Deserialize(enumerator2.Data0,
                                                       out distance, out edgeProfile);
                        var accessible2 = false;
                        var weight2     = _weightHandler.CalculateWeightAndDir(edgeProfile, distance, out accessible2);
                        if (enumerator2.DataInverted)
                        {
                            var dir = weight2.Direction;
                            dir.Reverse();
                            weight2.Direction = dir;
                        }
                        if (!accessible2)
                        { // not accessible.
                            continue;
                        }

                        var direction2 = weight2.Direction;
                        turn.Vertex3 = enumerator2.To;
                        if (turn.IsUTurn)
                        { // is a u-turn, leave this out!
                            continue;
                        }

                        var direction = Dir.Combine(direction1, direction2);

                        if (direction.F &&
                            turn.IsRestrictedBy(_restrictions))
                        { // turn is restricted.
                            direction.F = false;
                        }

                        if (!direction.F)
                        { // there is no possible combination for these two edges.
                            continue;
                        }

                        // ok, we need to add this edge, it's a non-restricted turn, not a u-turn and edges are in correct direction.
                        var edge2 = enumerator2.DirectedEdgeId();

                        _weightHandler.AddOrUpdateEdge(_target, edge1.Raw, edge2.Raw, Constants.NO_VERTEX, true,
                                                       weight1.Weight);
                        //direction.Reverse();
                        _weightHandler.AddOrUpdateEdge(_target, edge2.Raw, edge1.Raw, Constants.NO_VERTEX, false,
                                                       weight1.Weight);
                    }
                }
            }
        }
Ejemplo n.º 3
0
        private IslandLabels _islandLabels; // island id's per edge id.

        /// <summary>
        /// Runs the island detection.
        /// </summary>
        protected override void DoRun(CancellationToken cancellationToken)
        {
            _islandLabels = new IslandLabels();

            // do a run over each vertex and connect islands with bidirectional edges where possible.
            uint currentVertex   = 0;
            var  edgeEnumerator1 = _network.GetEdgeEnumerator();
            var  edgeEnumerator2 = _network.GetEdgeEnumerator();
            var  bestLabels      = new Dictionary <uint, uint>();

            while (currentVertex < _network.VertexCount)
            {
                if (!edgeEnumerator1.MoveTo(currentVertex))
                {
                    currentVertex++;
                    continue;
                }

                // update restrictions.
                _restrictions?.Update(currentVertex);

                // log all connections.
                bestLabels.Clear();
                var  incomingOneWayEdge = -1L;
                uint incomingVertex     = 0;
                var  edges = 0;
                while (edgeEnumerator1.MoveNext())
                {
                    var edge1Factor = _profile(edgeEnumerator1.Data.Profile);
                    if (edge1Factor.Value == 0)
                    {
                        // no access, don't evaluate neighbours.
                        _islandLabels[edgeEnumerator1.Id] = IslandLabels.NoAccess;
                        continue;
                    }

                    edges++;
                    if (edge1Factor.Direction != 0)
                    {
                        if (incomingOneWayEdge != Constants.NO_EDGE)
                        { // there was no bidirectional or second edge detected.
                            if ((edgeEnumerator1.DataInverted && edge1Factor.Direction == 1) ||
                                (!edgeEnumerator1.DataInverted && edge1Factor.Direction == 2))
                            {
                                if (incomingOneWayEdge < 0)
                                { // keep edge.
                                    incomingOneWayEdge = edgeEnumerator1.Id;
                                    incomingVertex     = edgeEnumerator1.To;
                                }
                                else
                                { // oeps, a second incoming edge, don't keep.
                                    incomingOneWayEdge = Constants.NO_EDGE;
                                }
                            }
                        }
                        // only consider bidirectional edges in this first step.
                        continue;
                    }
                    incomingOneWayEdge = Constants.NO_EDGE; // a bidirectional edge, not a candidate for one-way label propagation.

                    // get label or provisionally set label to own id.
                    if (!bestLabels.TryGetValue(edgeEnumerator1.Id, out var edge1Label))
                    {
                        // label wasn't set yet locally, check globally.
                        edge1Label = _islandLabels[edgeEnumerator1.Id];
                        if (edge1Label == IslandLabels.NotSet)
                        {
                            // provisionally set label to own id.
                            edge1Label = edgeEnumerator1.Id;
                        }

                        bestLabels[edgeEnumerator1.Id] = edge1Label;
                    }

                    var turn = new Turn(new OriginalEdge(edgeEnumerator1.To, currentVertex), Constants.NO_VERTEX);

                    // evaluate neighbours.
                    edgeEnumerator2.MoveTo(currentVertex);
                    while (edgeEnumerator2.MoveNext())
                    {
                        if (edgeEnumerator1.Id == edgeEnumerator2.Id)
                        { // don't evaluate u-turns.
                            // TODO: what about loops?
                            continue;
                        }

                        var edge2Factor = _profile(edgeEnumerator2.Data.Profile);
                        if (edge2Factor.Value == 0)
                        {
                            // should be marked as no access in parent loop.
                            continue;
                        }

                        if (edge2Factor.Direction != 0)
                        {
                            // only consider bidirectional edges in this first step.
                            continue;
                        }

                        // check restrictions if needed.
                        if (_restrictions != null)
                        {
                            turn.Vertex3 = edgeEnumerator2.To;
                            if (turn.IsRestrictedBy(_restrictions))
                            { // turn is restricted.
                                continue;
                            }
                        }

                        // get label or provisionally set label to own id.
                        if (!bestLabels.TryGetValue(edgeEnumerator2.Id, out var edge2Label))
                        {
                            // label wasn't set locally, check globally.
                            edge2Label = _islandLabels[edgeEnumerator2.Id];
                            if (edge2Label == IslandLabels.NotSet)
                            {
                                // provisionally set label to own id.
                                edge2Label = edgeEnumerator2.Id;
                            }

                            bestLabels[edgeEnumerator2.Id] = edge2Label;
                        }

                        // bidirectional edge, choose best label.
                        if (edge1Label < edge2Label)
                        {
                            bestLabels[edgeEnumerator2.Id] = edge1Label;
                        }
                        else
                        {
                            bestLabels[edgeEnumerator1.Id] = edge2Label;
                        }
                    }
                }

                if (incomingOneWayEdge != Constants.NO_EDGE &&
                    incomingOneWayEdge >= 0 &&
                    edges == 2)
                { // link sequences of oneways together.
                    var edge1Id = (uint)incomingOneWayEdge;
                    // we can also update neighbours if there is only one incoming edge.

                    // get label or provisionally set label to own id.
                    if (!bestLabels.TryGetValue(edge1Id, out var edge1Label))
                    {
                        // label wasn't set yet locally, check globally.
                        edge1Label = _islandLabels[edge1Id];
                        if (edge1Label == IslandLabels.NotSet)
                        {
                            // provisionally set label to own id.
                            edge1Label = edge1Id;
                        }

                        bestLabels[edge1Id] = edge1Label;
                    }

                    var turn = new Turn(new OriginalEdge(incomingVertex, currentVertex), Constants.NO_VERTEX);

                    // evaluate neighbours.
                    edgeEnumerator2.MoveTo(currentVertex);
                    while (edgeEnumerator2.MoveNext())
                    {
                        if (edge1Id == edgeEnumerator2.Id)
                        {
                            // don't evaluate u-turns.
                            // TODO: what about loops?
                            continue;
                        }

                        var edge2Factor = _profile(edgeEnumerator2.Data.Profile);
                        if (edge2Factor.Value == 0)
                        {
                            // should be marked as no access in parent loop.
                            continue;
                        }

                        if ((edgeEnumerator2.DataInverted && edge2Factor.Direction == 1) ||
                            (!edgeEnumerator2.DataInverted && edge2Factor.Direction == 2))
                        { // REMARK: no need to check for bidirectionals, already done above.
                            // only consider outgoing oneway edges.
                            continue;
                        }

                        // check restrictions if needed.
                        if (_restrictions != null)
                        {
                            turn.Vertex3 = edgeEnumerator2.To;
                            if (turn.IsRestrictedBy(_restrictions))
                            { // turn is restricted.
                                continue;
                            }
                        }

                        // get label or provisionally set label to own id.
                        if (!bestLabels.TryGetValue(edgeEnumerator2.Id, out var edge2Label))
                        {
                            // label wasn't set locally, check globally.
                            edge2Label = _islandLabels[edgeEnumerator2.Id];
                            if (edge2Label == IslandLabels.NotSet)
                            {
                                // provisionally set label to own id.
                                edge2Label = edgeEnumerator2.Id;
                            }

                            bestLabels[edgeEnumerator2.Id] = edge2Label;
                        }

                        // choose best label.
                        if (edge1Label < edge2Label)
                        {
                            bestLabels[edgeEnumerator2.Id] = edge1Label;
                        }
                        else
                        {
                            bestLabels[edge1Id] = edge2Label;
                        }
                    }
                }

                // update labels based on best labels.
                var labelsToUpdate = new HashSet <uint>();
                foreach (var pair in bestLabels)
                {
                    var edgeId = pair.Key; // the edge key.
                    var label  = pair.Value;

                    var existing = _islandLabels[edgeId];
                    if (existing != IslandLabels.NotSet &&
                        existing != label &&
                        edgeId != existing)
                    { // also make sure to update the existing label.
                        _islandLabels[existing] = label;
                        labelsToUpdate.Add(existing);
                    }
                    _islandLabels[edgeId] = label;
                    labelsToUpdate.Add(edgeId);
                }
                foreach (var label in labelsToUpdate)
                {
                    _islandLabels.UpdateLowest(label);
                }

                currentVertex++;
            }

            // update all labels to lowest possible.
            for (uint e = 0; e < _islandLabels.Count; e++)
            {
                _islandLabels.UpdateLowest(e);
            }

            // NOW ALL LABELLED EDGES ARE AT THEIR BEST.
            // do the one-way labels.
            var islandLabelGraph = new IslandLabelGraph();

            currentVertex = 0;
            while (currentVertex < _network.VertexCount)
            {
                if (!edgeEnumerator1.MoveTo(currentVertex))
                {
                    currentVertex++;
                    continue;
                }

                // update restrictions.
                _restrictions?.Update(currentVertex);

                // log all connections.
                while (edgeEnumerator1.MoveNext())
                {
                    var edge1Factor = _profile(edgeEnumerator1.Data.Profile);
                    if (edge1Factor.Value == 0)
                    {
                        // no access, don't evaluate neighbours.
                        _islandLabels[edgeEnumerator1.Id] = IslandLabels.NoAccess;
                        continue;
                    }

                    if ((edgeEnumerator1.DataInverted && edge1Factor.Direction == 2) ||
                        !edgeEnumerator1.DataInverted && edge1Factor.Direction == 1)
                    {
                        // wrong direction, this edge is oneway away from current vertex.
                        continue;
                    }

                    var turn = new Turn(new OriginalEdge(edgeEnumerator1.To, currentVertex), Constants.NO_VERTEX);

                    // get label or set to own id.
                    var edge1Label = _islandLabels[edgeEnumerator1.Id];
                    if (edge1Label == IslandLabels.NotSet)
                    {
                        edge1Label = edgeEnumerator1.Id;
                        _islandLabels[edge1Label] = edge1Label;
                    }

                    // evaluate neighbours.
                    edgeEnumerator2.MoveTo(currentVertex);
                    while (edgeEnumerator2.MoveNext())
                    {
                        if (edgeEnumerator1.Id == edgeEnumerator2.Id)
                        { // don't evaluate u-turns.
                            // TODO: what about loops?
                            continue;
                        }

                        var edge2Factor = _profile(edgeEnumerator2.Data.Profile);
                        if (edge2Factor.Value == 0)
                        {
                            // should be marked as no access in parent loop.
                            continue;
                        }

                        if ((edgeEnumerator2.DataInverted && edge2Factor.Direction == 1) ||
                            !edgeEnumerator2.DataInverted && edge2Factor.Direction == 2)
                        {
                            // wrong direction, this edge is oneway away from current vertex.
                            continue;
                        }

                        // check restrictions if needed.
                        if (_restrictions != null)
                        {
                            turn.Vertex3 = edgeEnumerator2.To;
                            if (turn.IsRestrictedBy(_restrictions))
                            { // turn is restricted.
                                continue;
                            }
                        }

                        // get label or set to own id.
                        var edge2Label = _islandLabels[edgeEnumerator2.Id];
                        if (edge2Label == IslandLabels.NotSet)
                        {
                            edge2Label = edgeEnumerator2.Id;
                            _islandLabels[edge2Label] = edge2Label;
                        }

                        if (edge1Label != edge2Label)
                        {
                            islandLabelGraph.Connect(edge1Label, edge2Label);
                        }
                    }
                }

                currentVertex++;
            }
            Itinero.Logging.Logger.Log($"{nameof(EdgeBasedIslandDetector)}.{nameof(Run)}", TraceEventType.Verbose,
                                       "Built directional graph.");

            // calculate all loops with increasing max settle settings until they are unlimited and all loops are removed.
            uint maxSettles = 1;

            Itinero.Logging.Logger.Log($"{nameof(EdgeBasedIslandDetector)}.{nameof(Run)}", TraceEventType.Verbose,
                                       $"Label graph has {islandLabelGraph.LabelCount} labels.");
            while (true)
            {
                Itinero.Logging.Logger.Log($"{nameof(EdgeBasedIslandDetector)}.{nameof(Run)}", TraceEventType.Verbose,
                                           $"Running loop detection with {maxSettles}.");

                var lastRun = maxSettles > islandLabelGraph.LabelCount;

                // find loops.
                islandLabelGraph.FindLoops(maxSettles, _islandLabels, (oldLabel, newLabel) =>
                {
                    _islandLabels[oldLabel] = newLabel;
                });

                // update all labels to lowest possible.
                for (uint e = 0; e < _islandLabels.Count; e++)
                {
                    _islandLabels.UpdateLowest(e);
                }

                if (lastRun)
                {
                    break;
                }

                // reduce graph.
                var labelCount = islandLabelGraph.Reduce(_islandLabels);
                Itinero.Logging.Logger.Log($"{nameof(EdgeBasedIslandDetector)}.{nameof(Run)}", TraceEventType.Verbose,
                                           $"Label graph now has {labelCount} non-empty labels.");
                maxSettles = (uint)_network.EdgeCount;
            }

            this.HasSucceeded = true;
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Contracts the given vertex.
        /// </summary>
        private void Contract(uint vertex)
        {
            // get and keep edges.
            var edges = new List <MetaEdge>(_graph.GetEdgeEnumerator(vertex));

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

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

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

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

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

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

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

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

                    // use witness flags to represent impossible routes.
                    forwardWitnesses[k]  = !(edge1CanMoveBackward && edge2CanMoveForward);
                    backwardWitnesses[k] = !(edge1CanMoveForward && edge2CanMoveBackward);

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

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

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

                    if (edge1.Neighbour == edge2.Neighbour)
                    { // do not try to add a shortcut between identical vertices.
                        continue;
                    }

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

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