/// <summary> /// Gets sequence 2, the last vertices right before the end vertex with a maximum of n. /// </summary> public static uint[] GetSequence2 <T>(this EdgePath <T> path, DirectedDynamicGraph.EdgeEnumerator enumerator, int n) where T : struct { if (path.From == null) { return(Constants.EMPTY_SEQUENCE); } return(path.GetSequence2 <T>(enumerator, n, new List <uint>())); }
public void TestGetSequence2() { // build graph. var graph = new DirectedDynamicGraph(ContractedEdgeDataSerializer.DynamicFixedSize); var e1 = graph.AddEdge(0, 1, 100, null); var e2 = graph.AddEdge(1, 2, 100, null); var e3 = graph.AddEdge(2, 6, 100, null, 4, new uint[] { 3 }, new uint[] { 5 }); var e4 = graph.AddEdge(6, 16, 100, null, 11, new uint[] { 7, 8, 9, 10 }, new uint[] { 12, 13, 14, 15 }); var enumerator = graph.GetEdgeEnumerator(); // build and test getting sequences from paths. var path = new EdgePath <float>(0); var s = path.GetSequence2(enumerator); Assert.IsNotNull(s); Assert.AreEqual(0, s.Length); path = new EdgePath <float>(1, 100, new EdgePath <float>(0)); s = path.GetSequence2(enumerator); Assert.IsNotNull(s); Assert.AreEqual(1, s.Length); Assert.AreEqual(0, s[0]); path = new EdgePath <float>(2, 200, e2 + 1, new EdgePath <float>(1, 100, new EdgePath <float>(0))); s = path.GetSequence2(enumerator); Assert.IsNotNull(s); Assert.AreEqual(2, s.Length); Assert.AreEqual(0, s[0]); Assert.AreEqual(1, s[1]); path = new EdgePath <float>(6, 300, e3 + 1, new EdgePath <float>(2, 200, e2 + 1, new EdgePath <float>(1, 100, new EdgePath <float>(0)))); s = path.GetSequence2(enumerator); Assert.IsNotNull(s); Assert.AreEqual(1, s.Length); Assert.AreEqual(5, s[0]); path = new EdgePath <float>(16, 400, e4 + 1, new EdgePath <float>(6, 300, e3 + 1, new EdgePath <float>(2, 200, e2 + 1, new EdgePath <float>(1, 100, new EdgePath <float>(0))))); s = path.GetSequence2(enumerator); Assert.IsNotNull(s); Assert.AreEqual(4, s.Length); Assert.AreEqual(12, s[0]); Assert.AreEqual(13, s[1]); Assert.AreEqual(14, s[2]); Assert.AreEqual(15, s[3]); }
/// <summary> /// Gets sequence 2, the last vertices right before the end vertex. /// </summary> public static uint[] GetSequence2 <T>(this EdgePath <T> path, DirectedDynamicGraph.EdgeEnumerator enumerator) where T : struct { return(path.GetSequence2(enumerator, int.MaxValue)); }
/// <summary> /// Executes one step in the search. /// </summary> public bool Step() { if (_heap.Count == 0) { return(false); } _current = _heap.Pop(); while (_current != null) { // keep trying. LinkedEdgePath <T> edgePath = null; if (!_visits.TryGetValue(_current.Vertex, out edgePath)) { // this vertex has not been visited before. _visits.Add(_current.Vertex, new LinkedEdgePath <T>() { Path = _current }); break; } else { // vertex has been visited before, check if edge has. if (!edgePath.HasPath(_current)) { // current edge has not been used to get to this vertex. _visits[_current.Vertex] = new LinkedEdgePath <T>() { Path = _current, Next = edgePath }; break; } } _current = _heap.Pop(); } if (_current == null) { return(false); } if (this.WasFound != null) { this.WasFound(_current.Vertex, _current.Weight); } // get relevant restrictions. var restrictions = _getRestrictions(_current.Vertex); // get the edge enumerator. var currentSequence = _current.GetSequence2(_edgeEnumerator); currentSequence = currentSequence.Append(_current.Vertex); // get neighbours. _edgeEnumerator.MoveTo(_current.Vertex); // add the neighbours to the queue. while (_edgeEnumerator.MoveNext()) { bool?neighbourDirection; var neighbourWeight = _weightHandler.GetEdgeWeight(_edgeEnumerator.Current, out neighbourDirection); if (neighbourDirection == null || (neighbourDirection.Value != _backward)) { // the edge is forward, and is to higher or was not contracted at all. var neighbourNeighbour = _edgeEnumerator.Neighbour; var neighbourSequence = Constants.EMPTY_SEQUENCE; if (_edgeEnumerator.IsOriginal()) { // original edge. if (currentSequence.Length > 1 && currentSequence[currentSequence.Length - 2] == neighbourNeighbour) { // this is a u-turn. continue; } if (restrictions != null) { neighbourSequence = currentSequence.Append(neighbourNeighbour); } } else { // not an original edge, use the sequence. neighbourSequence = _edgeEnumerator.GetSequence1(); if (currentSequence.Length > 1 && currentSequence[currentSequence.Length - 2] == neighbourSequence[0]) { // this is a u-turn. continue; } if (restrictions != null) { neighbourSequence = currentSequence.Append(neighbourSequence); } } if (restrictions != null) { // check restrictions. if (!restrictions.IsSequenceAllowed(neighbourSequence)) { continue; } } // build route to neighbour and check if it has been visited already. var routeToNeighbour = new EdgePath <T>( neighbourNeighbour, _weightHandler.Add(_current.Weight, neighbourWeight), _edgeEnumerator.IdDirected(), _current); LinkedEdgePath <T> edgePath = null; if (!_visits.TryGetValue(_current.Vertex, out edgePath) || !edgePath.HasPath(routeToNeighbour)) { // this vertex has not been visited in this way before. _heap.Push(routeToNeighbour, _weightHandler.GetMetric(routeToNeighbour.Weight)); } } } return(true); }
/// <summary> /// Search backward from one vertex. /// </summary> /// <returns></returns> private void SearchBackward(DirectedDynamicGraph.EdgeEnumerator edgeEnumerator, EdgePath <T> current, IEnumerable <uint[]> restrictions) { if (current != null) { // there is a next vertex found. // get the edge enumerator. var currentSequence = current.GetSequence2(edgeEnumerator); currentSequence = currentSequence.Append(current.Vertex); // get neighbours. edgeEnumerator.MoveTo(current.Vertex); // add the neighbours to the queue. while (edgeEnumerator.MoveNext()) { bool?neighbourDirection; var neighbourWeight = _weightHandler.GetEdgeWeight(edgeEnumerator.Current, out neighbourDirection); if (neighbourDirection == null || !neighbourDirection.Value) { // the edge is forward, and is to higher or was not contracted at all. var neighbourNeighbour = edgeEnumerator.Neighbour; var neighbourSequence = Constants.EMPTY_SEQUENCE; if (edgeEnumerator.IsOriginal()) { // original edge. if (currentSequence.Length > 1 && currentSequence[currentSequence.Length - 2] == neighbourNeighbour) { // this is a u-turn. continue; } if (restrictions != null) { neighbourSequence = currentSequence.Append(neighbourNeighbour); } } else { // not an original edge, use the sequence. neighbourSequence = edgeEnumerator.GetSequence1(); if (currentSequence.Length > 1 && currentSequence[currentSequence.Length - 2] == neighbourSequence[0]) { // this is a u-turn. continue; } if (restrictions != null) { neighbourSequence = currentSequence.Append(neighbourSequence); } } if (restrictions != null) { // check restrictions. neighbourSequence.Reverse(); if (!restrictions.IsSequenceAllowed(neighbourSequence)) { continue; } } // build route to neighbour and check if it has been visited already. var routeToNeighbour = new EdgePath <T>( neighbourNeighbour, _weightHandler.Add(current.Weight, neighbourWeight), edgeEnumerator.IdDirected(), current); LinkedEdgePath edgePath = null; if (!_backwardVisits.TryGetValue(current.Vertex, out edgePath) || !edgePath.HasPath(routeToNeighbour)) { // this vertex has not been visited in this way before. _backwardQueue.Push(routeToNeighbour, _weightHandler.GetMetric(routeToNeighbour.Weight)); } } } } }