/// <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, MinWeight = _current.Weight }); 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, MinWeight = edgePath.MinWeight, Next = edgePath }; break; } } _current = _heap.Pop(); } if (_current == null) { return(false); } if (this.WasFound != null) { this.WasFound(_current); } // 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, 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. if (!_weightHandler.IsSmallerThanAny(routeToNeighbour.Weight, _max)) { continue; } _heap.Push(routeToNeighbour, _weightHandler.GetMetric(routeToNeighbour.Weight)); } } } return(true); }