|
3 | 3 |
|
4 | 4 | #include <ranges> |
5 | 5 | #include <unordered_map> |
6 | | -#include <unordered_set> |
7 | 6 |
|
8 | 7 | #include "reconstruction.h" |
9 | 8 | #include "schedule/Schedule.h" |
| 9 | +#include "raptor/state.h" |
10 | 10 |
|
11 | 11 | namespace raptor { |
12 | 12 |
|
13 | | - using StopIndex = std::ranges::range_difference_t<decltype(std::declval<Route>().stop_sequence())>; |
14 | | - using TripIndex = std::ranges::range_difference_t<decltype(std::declval<Route>().get_trips())>; |
15 | | - using StopTimeIndex = std::ranges::range_difference_t<decltype(std::declval<Trip>().get_stop_times())>; |
16 | | - |
17 | | - /** |
18 | | - * Contains information about reaching a stop. The algorithm supports two types of reaching a stop: either on |
19 | | - * foot or using public transport. When travelling on foot the route_and_trip_index member is set to std::nullopt. |
20 | | - * |
21 | | - * The boarding_stop member is set to std::nullopt for the starting point of the journey. |
22 | | - */ |
23 | | - struct JourneyInformation { |
24 | | - Time arrival_time; |
25 | | - std::optional<std::reference_wrapper<const Stop>> boarding_stop; |
26 | | - std::optional<std::pair<std::reference_wrapper<const Route>, TripIndex>> route_and_trip_index; |
27 | | - }; |
28 | | - |
29 | | - struct JourneyInformationPTExtension { |
30 | | - const Route& route; |
31 | | - TripIndex trip_index; |
32 | | - StopIndex stop_index; |
33 | | - }; |
34 | | - |
35 | | - /** |
36 | | - * LabelManager is responsible for controlling the labels associated with each Stop. |
37 | | - * It keeps track of two sets of the current and previous sets of labels. |
38 | | - * |
39 | | - * All modifications to the labels apply to the current set. |
40 | | - */ |
41 | | - class LabelManager { |
42 | | - using LabelType = JourneyInformation; |
43 | | - using LabelContainer = std::unordered_map<std::reference_wrapper<const Stop>, LabelType>; |
44 | | - |
45 | | - LabelContainer current_round_labels; |
46 | | - LabelContainer previous_round_labels; |
47 | | - |
48 | | - static std::optional<LabelType> get_label(const Stop& stop, const LabelContainer& labels) { |
49 | | - const auto label = labels.find(stop); |
50 | | - return label == labels.end() ? std::nullopt : std::make_optional(label->second); |
51 | | - } |
52 | | - |
53 | | - public: |
54 | | - LabelManager() = default; |
55 | | - |
56 | | - /** |
57 | | - * Initialises the object and adds a label to the current set. |
58 | | - */ |
59 | | - LabelManager(const Stop& stop, |
60 | | - const Time& arrival_time, |
61 | | - const std::optional<std::reference_wrapper<const Stop>> boarding_stop, |
62 | | - const std::optional<std::pair<std::reference_wrapper<const Route>, TripIndex>> |
63 | | - route_with_trip_index) { |
64 | | - add_label(stop, arrival_time, boarding_stop, route_with_trip_index); |
65 | | - } |
66 | | - |
67 | | - /** |
68 | | - * Copies the labels of the current round to the previous round |
69 | | - */ |
70 | | - void new_round() { |
71 | | - previous_round_labels = current_round_labels; |
72 | | - } |
73 | | - |
74 | | - /** |
75 | | - * Adds or changes the value of the label for the latest set. |
76 | | - * @param stop |
77 | | - * @param arrival_time Arrival time at the stop. |
78 | | - * @param boarding_stop Stop where the line is boarded to reach the stop. |
79 | | - * @param route_with_trip_index Route used to travel between the stops along with the index of the trip used. |
80 | | - */ |
81 | | - void add_label(const Stop& stop, |
82 | | - const Time& arrival_time, |
83 | | - const std::optional<std::reference_wrapper<const Stop>>& boarding_stop, |
84 | | - const std::optional<std::pair<std::reference_wrapper<const Route>, TripIndex>> |
85 | | - & route_with_trip_index) { |
86 | | - current_round_labels.insert_or_assign( |
87 | | - stop, JourneyInformation(arrival_time, boarding_stop, route_with_trip_index)); |
88 | | - } |
89 | | - |
90 | | - std::optional<LabelType> get_latest_label(const Stop& stop) const { |
91 | | - return get_label(stop, current_round_labels); |
92 | | - } |
93 | | - |
94 | | - std::optional<LabelType> get_previous_label(const Stop& stop) const { |
95 | | - return get_label(stop, previous_round_labels); |
96 | | - } |
97 | | - |
98 | | - using IndexWithTime = std::pair<StopIndex, Time>; |
99 | | - |
100 | | - /** |
101 | | - * Get the first stop of the route that was reached in the previous round. |
102 | | - * @param stops Range containing stop objects for this route in travel order. |
103 | | - * @return Pair containing a reference to the stop and the arrival time to the stop. No value if there is no |
104 | | - * stop in the given route that can be reached with the given number of transfers. |
105 | | - */ |
106 | | - template <std::ranges::input_range R> |
107 | | - requires std::is_convertible_v<std::ranges::range_value_t<R>, Stop> |
108 | | - std::optional<IndexWithTime> find_hop_on_stop( |
109 | | - R&& stops) { |
110 | | - auto stops_with_journeys = previous_round_labels | std::views::keys; |
111 | | - auto hop_on_stop = std::ranges::find_first_of(stops, stops_with_journeys, |
112 | | - {}, {}, &LabelContainer::value_type::first); |
113 | | - if (hop_on_stop == std::ranges::end(stops)) { |
114 | | - return std::nullopt; |
115 | | - } |
116 | | - return std::make_pair(std::ranges::distance(std::ranges::begin(stops), hop_on_stop), |
117 | | - previous_round_labels.at(*hop_on_stop).arrival_time); |
118 | | - } |
119 | | - }; |
120 | | - |
121 | | - /** |
122 | | - * Manages the internal state of the algorithm. |
123 | | - */ |
124 | | - class RaptorStatus { |
125 | | - LabelManager label_manager; |
126 | | - std::unordered_map<std::reference_wrapper<const Stop>, Time> earliest_arrival_time; |
127 | | - std::unordered_set<std::reference_wrapper<const Stop>> improved_stops; |
128 | | - int n_round = 0; |
129 | | - const Stop& destination; |
130 | | - |
131 | | - bool can_improve_current_journey_to_stop(const Time& new_arrival_time, const Stop& current_stop) const { |
132 | | - auto arrival_time_to_current_stop = earliest_arrival_time.find(current_stop); |
133 | | - if (arrival_time_to_current_stop == earliest_arrival_time.end()) |
134 | | - return true; |
135 | | - auto arrival_time_to_destination = earliest_arrival_time.find(destination); |
136 | | - if (arrival_time_to_destination == earliest_arrival_time.end()) { |
137 | | - return new_arrival_time.get_sys_time() < arrival_time_to_current_stop->second.get_sys_time(); |
138 | | - } |
139 | | - return new_arrival_time.get_sys_time() < std::min(arrival_time_to_current_stop->second.get_sys_time(), |
140 | | - arrival_time_to_destination->second.get_sys_time()); |
141 | | - } |
142 | | - |
143 | | - public: |
144 | | - RaptorStatus() = delete; |
145 | | - |
146 | | - // Copying this object is probably an error. Delete to avoid doing it by mistake. |
147 | | - RaptorStatus(const RaptorStatus& other) = delete; |
148 | | - RaptorStatus& operator=(const RaptorStatus& other) = delete; |
149 | | - |
150 | | - RaptorStatus(const Stop& origin_stop, const Stop& destination, const Time& departure_time) : |
151 | | - destination(destination) { |
152 | | - // TODO: Remove the need for nullopt boarding_stop |
153 | | - label_manager.add_label(origin_stop, departure_time, std::nullopt, std::nullopt); |
154 | | - earliest_arrival_time[origin_stop] = departure_time; |
155 | | - improved_stops.insert(origin_stop); |
156 | | - } |
157 | | - |
158 | | - int new_round() { |
159 | | - n_round++; |
160 | | - label_manager.new_round(); |
161 | | - return n_round; |
162 | | - } |
163 | | - |
164 | | - bool have_stops_to_improve() const { |
165 | | - return !improved_stops.empty(); |
166 | | - } |
167 | | - |
168 | | - bool try_improve_stop(const Stop& stop, const Time& new_arrival_time, |
169 | | - const std::optional<std::reference_wrapper<const Stop>>& boarding_stop, |
170 | | - const std::optional<std::pair<std::reference_wrapper<const Route>, TripIndex>>& |
171 | | - route_with_trip_index) { |
172 | | - if (can_improve_current_journey_to_stop(new_arrival_time, stop)) { |
173 | | - label_manager.add_label(stop, new_arrival_time, boarding_stop, route_with_trip_index); |
174 | | - earliest_arrival_time[stop] = new_arrival_time; |
175 | | - improved_stops.insert(std::cref(stop)); |
176 | | - return true; |
177 | | - } |
178 | | - return false; |
179 | | - } |
180 | | - |
181 | | - bool might_catch_earlier_trip(const Stop& stop, const Time& departure_time) const { |
182 | | - const auto previous_journey = label_manager.get_previous_label(stop); |
183 | | - return previous_journey.has_value() && |
184 | | - previous_journey->arrival_time.get_sys_time() <= departure_time.get_sys_time(); |
185 | | - } |
186 | | - |
187 | | - std::unordered_set<std::reference_wrapper<const Stop>> get_and_clear_improved_stops() { |
188 | | - auto old_improved_stops = std::move(improved_stops); |
189 | | - improved_stops.clear(); |
190 | | - return old_improved_stops; |
191 | | - } |
192 | | - |
193 | | - std::unordered_set<std::reference_wrapper<const Stop>> get_improved_stops() const { |
194 | | - return improved_stops; |
195 | | - } |
196 | | - |
197 | | - Time current_arrival_time_to_stop(const Stop& stop) const { |
198 | | - return earliest_arrival_time.at(stop); |
199 | | - } |
200 | | - |
201 | | - Time previous_arrival_time_to_stop(const Stop& stop) const { |
202 | | - return label_manager.get_previous_label(stop)->arrival_time; |
203 | | - } |
204 | | - |
205 | | - // TODO: Remove this, currently used when building journeys. |
206 | | - const LabelManager& get_label_manager() const { |
207 | | - return label_manager; |
208 | | - } |
209 | | - }; |
210 | | - |
211 | 13 | class Raptor { |
212 | 14 |
|
213 | | - // struct RouteWithStopIndex { |
214 | | - // std::reference_wrapper<const Route> route; |
215 | | - // StopIndex stop_idx; |
216 | | - // }; |
217 | | - |
218 | 15 | // Make the reference wrapper const so it can be used to directly extract pairs from the unordered_map |
219 | 16 | using RouteWithStopIndex = std::pair<const std::reference_wrapper<const Route>, StopIndex>; |
220 | 17 |
|
@@ -271,9 +68,9 @@ namespace raptor { |
271 | 68 | std::vector<Movement> build_trip(const Stop& origin, |
272 | 69 | const Stop& destination, |
273 | 70 | const LabelManager& stop_labels); |
274 | | - void process_transfers(RaptorStatus& status); |
| 71 | + void process_transfers(RaptorState& status); |
275 | 72 |
|
276 | | - void process_route(const Route& route, StopIndex hop_on_stop_idx, Time hop_on_time, RaptorStatus& status); |
| 73 | + void process_route(const Route& route, StopIndex hop_on_stop_idx, Time hop_on_time, RaptorState& status); |
277 | 74 |
|
278 | 75 |
|
279 | 76 | template <std::ranges::input_range R> |
|
0 commit comments