MATSIM
OccupancyData.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.* *
3  *
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2023 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 package ch.sbb.matsim.routing.pt.raptor;
21 
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.Logger;
24 import org.matsim.api.core.v01.Id;
25 import org.matsim.api.core.v01.IdMap;
32 import org.matsim.vehicles.Vehicle;
33 
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.Comparator;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.ListIterator;
40 import java.util.Map;
41 
45 public class OccupancyData {
46 
47  private final static Logger LOG = LogManager.getLogger(OccupancyData.class);
48 
49  final IdMap<TransitLine, LineData> lineData = new IdMap<>(TransitLine.class);
50  final Map<Id<Vehicle>, VehicleData> vehicleData = new HashMap<>();
51  final Map<Id<Person>, PassengerData> paxData = new HashMap<>();
52  private CacheData cache = null;
53 
54  public void reset() {
55  LOG.info("[SwissRailRaptor] Resetting ExecutionData");
56  this.lineData.clear();
57  this.vehicleData.clear();
58  this.paxData.clear();
59  this.cache = null;
60  }
61 
62  public DepartureData getNextAvailableDeparture(Id<TransitLine> transitLine, Id<TransitRoute> transitRoute, Id<TransitStopFacility> stopFacility, double time) {
63  LineData line = this.lineData.get(transitLine);
64  if (line == null) {
65  return null;
66  }
67  RouteData route = line.routeData.get(transitRoute);
68  if (route == null) {
69  return null;
70  }
71  StopData stop = route.stopData.get(stopFacility);
72  if (stop == null) {
73  return null;
74  }
75  List<DepartureData> departures = stop.getSortedDepartures();
76  if (departures.isEmpty()) {
77  return null;
78  }
79 
80  for (DepartureData dep : departures) {
81  if (time <= dep.latestWaitStart) {
82  return dep;
83  }
84  }
85  return null;
86  }
87 
88  public DepartureData getDepartureData(Id<TransitLine> transitLine, Id<TransitRoute> transitRoute, Id<TransitStopFacility> stopFacility, Id<Departure> departure) {
89  LineData line = this.lineData.get(transitLine);
90  if (line == null) {
91  return null;
92  }
93  RouteData route = line.routeData.get(transitRoute);
94  if (route == null) {
95  return null;
96  }
97  StopData stop = route.stopData.get(stopFacility);
98  if (stop == null) {
99  return null;
100  }
101  for (DepartureData d : stop.depList) {
102  if (d.departureId.equals(departure)) {
103  return d;
104  }
105  }
106  return null;
107  }
108 
109  public RouteData getRouteData(Id<TransitLine> transitLine, Id<TransitRoute> transitRoute) {
110  LineData line = this.lineData.get(transitLine);
111  if (line == null) {
112  return null;
113  }
114  return line.routeData.get(transitRoute);
115  }
116 
117 // public Vehicle getVehicle(Id<TransitLine> transitLine, Id<TransitRoute> transitRoute, Id<Departure> departure) {
118 // LineData line = this.lineData.get(transitLine);
119 // if (line == null) {
120 // return null;
121 // }
122 // RouteData route = line.routeData.get(transitRoute);
123 // if (route == null) {
124 // return null;
125 // }
126 // return route.vehicles.get(departure);
127 // }
128 
130  CacheData cache = getCache(data);
131 
132  int[] latestWaitStartTimes = cache.latestWaitingTimeStartPerRouteStopPerDeparture[routeStop.index];
133  int toIndex = latestWaitStartTimes.length;
134  int offset = latestWaitStartTimes[0] - 1;
135  int pos = Arrays.binarySearch(latestWaitStartTimes, 1, toIndex, (int) time);
136  if (pos < 0) {
137  // binarySearch returns (-(insertion point) - 1) if the element was not found, which will happen most of the times.
138  // insertion_point points to the next larger element, which is the next departure in our case
139  // This can be transformed as follows:
140  // retval = -(insertion point) - 1
141  // ==> insertion point = -(retval+1) .
142  pos = -(pos + 1);
143  }
144  if (pos >= toIndex) {
145  // there is no later departure time
146  return -1;
147  }
148  return offset + pos;
149  }
150 
152  CacheData cache = this.cache;
153  if (cache == null) {
154  cache = buildCache(data);
155  }
156  return cache;
157  }
158 
159  private synchronized CacheData buildCache(SwissRailRaptorData data) {
160  CacheData cache = this.cache;
161  if (cache != null) {
162  return cache;
163  }
164  LOG.info("[SwissRailRaptor] build query-cache for ExecutionData");
165 
166  cache = new CacheData(data.routeStops.length);
167  SwissRailRaptorData.RRouteStop[] routeStops = data.routeStops;
168  for (int routeStopIdx = 0; routeStopIdx < routeStops.length; routeStopIdx++) {
169  SwissRailRaptorData.RRouteStop routeStop = routeStops[routeStopIdx];
170  SwissRailRaptorData.RRoute route = data.routes[routeStop.transitRouteIndex];
171  int departuresCount = route.countDepartures;
172  int[] departures = new int[departuresCount + 1];
173  departures[0] = route.indexFirstDeparture;
174 
175  LineData lineData = this.lineData.get(routeStop.line.getId());
176  RouteData routeData = lineData == null ? null : lineData.routeData.get(routeStop.route.getId());
177  StopData stopData = routeData == null ? null : routeData.stopData.get(routeStop.routeStop.getStopFacility().getId());
178 
179 
180  List<Departure> origDepartures = new ArrayList<>(routeStop.route.getDepartures().values());
181  origDepartures.sort(Comparator.comparingDouble(Departure::getDepartureTime));
182 
183  int lastValue = -1;
184  for (int depIdx = 0; depIdx < origDepartures.size(); depIdx++) {
185  Departure departure = origDepartures.get(depIdx);
186  DepartureData dd = stopData == null ? null : stopData.depData.get(departure.getId());
187  int latestWaitStart;
188  if (dd == null) {
189  latestWaitStart = (int) (departure.getDepartureTime() + routeStop.departureOffset);
190  } else {
191  latestWaitStart = Double.isFinite(dd.latestWaitStart) ? (int) dd.latestWaitStart : lastValue;
192  }
193  departures[depIdx + 1] = latestWaitStart;
194  lastValue = latestWaitStart;
195  }
196  cache.latestWaitingTimeStartPerRouteStopPerDeparture[routeStopIdx] = departures;
197  }
198  this.cache = cache;
199  LOG.info("[SwissRailRaptor] done (build query-cache for ExecutionData)");
200  return cache;
201  }
202 
203  private static class CacheData {
204  int[][] latestWaitingTimeStartPerRouteStopPerDeparture;
205 
206  private CacheData(int routeStopsCount) {
207  this.latestWaitingTimeStartPerRouteStopPerDeparture = new int[routeStopsCount][];
208  }
209  }
210 
211  static class LineData {
212  Map<Id<TransitRoute>, RouteData> routeData = new HashMap<>();
213  }
214 
215  static class RouteData {
216  Map<Id<TransitStopFacility>, StopData> stopData = new HashMap<>();
217  final TransitRoute route;
218 
219  public RouteData(TransitRoute route) {
220  this.route = route;
221  }
222  }
223 
224  static class StopData {
225  Map<Id<Departure>, DepartureData> depData = new HashMap<>();
226  boolean sorted = true;
227  List<DepartureData> depList = new ArrayList<>();
228 
229  DepartureData getOrCreate(Id<Departure> depId) {
230  DepartureData data = this.depData.get(depId);
231  if (data == null) {
232  data = new DepartureData(depId);
233  this.depList.add(data);
234  this.depData.put(depId, data);
235  this.sorted = false;
236  }
237  return data;
238  }
239 
240  List<DepartureData> getSortedDepartures() {
241  if (!this.sorted) {
242  this.depList.sort((o1, o2) -> Double.compare(o1.vehDepTime, o2.vehDepTime));
243  this.sorted = true;
244  }
245 
246  ListIterator<DepartureData> li = this.depList.listIterator(this.depList.size());
247  DepartureData laterDep = null;
248  while (li.hasPrevious()) {
249  DepartureData dep = li.previous();
250  if (laterDep == null) {
251  dep.latestWaitStart = dep.vehDepTime;
252  laterDep = dep;
253  } else {
254  if (laterDep.earliestWaitStart < dep.vehDepTime) {
255  // there were agents that could not board
256 
257  if (Double.isFinite(dep.latestWaitStart)) {
258  // but at least some agents could board
259  laterDep.earliestWaitStart = dep.latestWaitStart;
260  laterDep = dep;
261  }
262  } else {
263  // looks like everybody who wanted could board
264  laterDep.earliestWaitStart = dep.vehDepTime;
265  dep.latestWaitStart = dep.vehDepTime;
266  laterDep = dep;
267  }
268  }
269  }
270  return this.depList;
271  }
272  }
273 
274  public static final class DepartureData {
275  final Id<Departure> departureId;
276  double vehDepTime = Double.NEGATIVE_INFINITY;
277  double earliestWaitStart = Double.POSITIVE_INFINITY;
278  double latestWaitStart = Double.NEGATIVE_INFINITY;
279  int paxCountAtDeparture = -1;
280 
281  public DepartureData(Id<Departure> departureId) {
282  this.departureId = departureId;
283  }
284 
285  void addWaitingPerson(double startWaitTime) {
286  if (startWaitTime < this.earliestWaitStart) {
287  this.earliestWaitStart = startWaitTime;
288  }
289  if (startWaitTime > this.latestWaitStart) {
290  this.latestWaitStart = startWaitTime;
291  }
292  }
293  }
294 
295  static class VehicleData {
296  final Vehicle vehicle;
297  final Id<TransitLine> lineId;
298  final Id<TransitRoute> routeId;
299  final Id<Departure> departureId;
300  Id<TransitStopFacility> stopFacilityId = null;
301  int currentPaxCount = 0;
302 
303  public VehicleData(Vehicle vehicle, Id<TransitLine> lineId, Id<TransitRoute> routeId, Id<Departure> departureId) {
304  this.vehicle = vehicle;
305  this.lineId = lineId;
306  this.routeId = routeId;
307  this.departureId = departureId;
308  }
309  }
310 
311  static class PassengerData {
312  final Person person;
313  final Map<String, ModeUtilityParameters> modeParams;
314  String mode;
315  double waitingStartTime;
316  double vehBoardingTime;
317  Id<TransitStopFacility> boardingStopId;
318  Id<Departure> departureId;
319 
320  public PassengerData(Person person, Map<String, ModeUtilityParameters> modeParams) {
321  this.person = person;
322  this.modeParams = modeParams;
323  }
324  }
325 
326 }
CacheData getCache(SwissRailRaptorData data)
DepartureData getDepartureData(Id< TransitLine > transitLine, Id< TransitRoute > transitRoute, Id< TransitStopFacility > stopFacility, Id< Departure > departure)
synchronized CacheData buildCache(SwissRailRaptorData data)
RouteData getRouteData(Id< TransitLine > transitLine, Id< TransitRoute > transitRoute)
DepartureData getNextAvailableDeparture(Id< TransitLine > transitLine, Id< TransitRoute > transitRoute, Id< TransitStopFacility > stopFacility, double time)
int getNextAvailableDeparture(SwissRailRaptorData data, SwissRailRaptorData.RRouteStop routeStop, double time)