/// <summary> /// FindPathForward, finds the fastes route between a and b /// </summary> /// <param name="a">stop number of the departuring station</param> /// <param name="b">stop number of the arrival station</param> /// <param name="utcStart">Departuretime in UTC format.</param> /// <returns>List of TimeTableId, describing the route for the path</returns> private List <PathItem> FindPathForward(int a, int b, long utcStart) { // the path we find as shortest var cameFrom = new Dictionary <int, TraceBackNode>(); // gScore is the actual linuxtime to arrive at a stop: <stopId, arrival time> var gScore = new Dictionary <int, long>(); gScore[a] = utcStart; // a min heap var heap = new FastPriorityQueue <QueueNode>(5000); heap.Enqueue(new QueueNode { StopId = a, Time = utcStart, TripId = -1 }, DistanceTime(a, b)); while (heap.Count != 0) { var currentNode = heap.Dequeue(); // is arrival station found? if (currentNode.StopId == b) { var path = ReconstructPath(cameFrom, currentNode.StopId); path.Reverse(); return(path); } // get the neighbours to the currentNode var neighbours = ts.Edges .Where(e => e.FromStop == currentNode.StopId) .Select(e => new { e.EdgeId, e.ToStop, e.DistanceWalk }); foreach (var n in neighbours) { Iterations += 1; long arrivalTime; // time when arriving to n.ToStop int timeTableId = -1; int tripId = -1; if (n.DistanceWalk > 0) { if ((TimeToWalkSeconds(n.DistanceWalk) > cachedGlobal.MaxWalkingtime) | (currentNode.TripId == -1)) { continue; // to long to walk, or 2 sections in a row is walking! } arrivalTime = gScore[currentNode.StopId] + TimeToWalkSeconds(n.DistanceWalk); } else { long gScoreTemp = gScore[currentNode.StopId]; // TryGetValueOrMax (currentNode.StopId)?? TimeTable timeTableEntry; timeTableEntry = GetNextDeparture(n.EdgeId, gScoreTemp); if (timeTableEntry == null) // no path found { continue; } // now chek if previous node is not walking, and change of transport and changetime is available // othwise add changeTime, and search again. if ((currentNode.TripId != -1) & (currentNode.TripId != timeTableEntry.TripId) & (timeTableEntry.DepartureTime < gScoreTemp + cachedGlobal.TimeToChangeTransport)) { gScoreTemp += cachedGlobal.TimeToChangeTransport; timeTableEntry = GetNextDeparture(n.EdgeId, gScoreTemp); if (timeTableEntry == null) // no path found { continue; } } arrivalTime = timeTableEntry.ArrivalTime; timeTableId = timeTableEntry.TimeTableId; tripId = timeTableEntry.TripId; } if (arrivalTime < gScore.TryGetValueOrMax(n.ToStop)) // quicker way found { cameFrom[n.ToStop] = new TraceBackNode { ToStop = currentNode.StopId, EdgeId = n.EdgeId, TimeTableId = timeTableId }; gScore[n.ToStop] = arrivalTime; QueueNode qn = new QueueNode { StopId = n.ToStop, Time = arrivalTime, TripId = tripId }; if (!heap.Contains(qn)) { int heuristik = DistanceTime(n.ToStop, b); // estimated traveltime from this node to the end heap.Enqueue(qn, heuristik + arrivalTime); } } } } return(null); // Local: Get the next timetable entry in respect to departuetime given TimeTable GetNextDeparture(int edgeId, long departureTime) { return(ts.TimeTables .Where(t => t.EdgeId == edgeId && (t.DepartureTime >= departureTime)) .OrderBy(t => t.DepartureTime) .FirstOrDefault()); } }
/// <summary> /// FindPathReverse, finds the fastes route between a and b /// </summary> /// <param name="a">stop number of the departuring station</param> /// <param name="b">stop number of the arrival station</param> /// <param name="finalArrivalTime">ArrivalTime in UTC format.</param> /// <returns>List of TimeTableId, describing the route for the path</returns> private List <PathItem> FindPathReverse(int a, int b, long finalArrivalTime) { // the path we find as shortest var cameFrom = new Dictionary <int, TraceBackNode>(); // gScore is the actual UTCtime to get to a stop var gScore = new Dictionary <int, long>(); gScore[b] = finalArrivalTime; // a min heap, now 'turned' into a max heap var heap = new FastPriorityQueue <QueueNode>(5000); heap.Enqueue(new QueueNode { StopId = b, Time = finalArrivalTime, TripId = -1 }, -DistanceTime(a, b)); while (heap.Count != 0) { var currentNode = heap.Dequeue(); // is arrival station found? if (currentNode.StopId == a) { return(ReconstructPath(cameFrom, currentNode.StopId)); } // get the neighbours to the currentNode var neighbours = ts.Edges .Where(e => e.ToStop == currentNode.StopId) .Select(e => new { e.EdgeId, e.FromStop, e.DistanceWalk }); foreach (var n in neighbours) { Iterations += 1; long departureTime; // utctime when departing from n.ToStop int timeTableId = -1; int tripId = -1; if (n.DistanceWalk > 0) { if ((TimeToWalkSeconds(n.DistanceWalk) > cachedGlobal.MaxWalkingtime) & (currentNode.TripId == -1)) { continue; // to long to walk, or 2 sections in a row is walking! } departureTime = gScore[currentNode.StopId] - TimeToWalkSeconds(n.DistanceWalk); } else { long gScoreTemp = gScore[currentNode.StopId]; TimeTable timeTableEntry; timeTableEntry = GetNextArrival(n.EdgeId, gScoreTemp); if (timeTableEntry == null) { continue; } // now chek if previous node is not walking, and change of transport and changetime is available // othwise add changeTime, and search again. if ((currentNode.TripId != -1) & (currentNode.TripId != timeTableEntry.TripId) & (timeTableEntry.ArrivalTime < gScoreTemp - cachedGlobal.TimeToChangeTransport)) { gScoreTemp -= cachedGlobal.TimeToChangeTransport; timeTableEntry = GetNextArrival(n.EdgeId, gScoreTemp); if (timeTableEntry == null) // no path found { continue; } } departureTime = timeTableEntry.DepartureTime; timeTableId = timeTableEntry.TimeTableId; tripId = timeTableEntry.TripId; } if (departureTime > gScore.TryGetValueOrMin(n.FromStop)) // quicker way found, with a smaller value { cameFrom[n.FromStop] = new TraceBackNode { ToStop = currentNode.StopId, EdgeId = n.EdgeId, TimeTableId = timeTableId }; gScore[n.FromStop] = departureTime; QueueNode qn = new QueueNode { StopId = n.FromStop, Time = departureTime, TripId = tripId }; if (!heap.Contains(qn)) { int heuristik = DistanceTime(n.FromStop, a); // estimated traveltime from this node to the start heap.Enqueue(qn, heuristik - departureTime); } } } } // no path found! return(null); // Local: Get the next timeTable entry in respect to arrival time given TimeTable GetNextArrival(int edgeId, long arrivalTime) { return(ts.TimeTables .Where(t => t.EdgeId == edgeId && (t.ArrivalTime <= arrivalTime)) .OrderByDescending(t => t.ArrivalTime) .FirstOrDefault()); } }