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