Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSDispatch_Greedy.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2007-2025 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
18// An algorithm that performs dispatch for the taxi device
19/****************************************************************************/
20#include <config.h>
21
22#include <limits>
23#include <microsim/MSNet.h>
24#include <microsim/MSEdge.h>
26#include "MSRoutingEngine.h"
28
29//#define DEBUG_DISPATCH
30//#define DEBUG_SERVABLE
31//#define DEBUG_TRAVELTIME
32//#define DEBUG_COND2(obj) (obj->getID() == "p0")
33#define DEBUG_COND2(obj) (true)
34
35// ===========================================================================
36// MSDispatch_Greedy methods
37// ===========================================================================
38
39void
40MSDispatch_Greedy::computeDispatch(SUMOTime now, const std::vector<MSDevice_Taxi*>& fleet) {
41 int numDispatched = 0;
42 int numPostponed = 0;
43 // find available vehicles
44 std::set<MSDevice_Taxi*, MSVehicleDevice::ComparatorNumericalVehicleIdLess> available;
45 for (auto* taxi : fleet) {
46 if (taxi->isEmpty()) {
47 available.insert(taxi);
48 }
49 }
50 // greedy assign closest vehicle in reservation order
52 std::vector<Reservation*> reservations = getReservations();
53 std::sort(reservations.begin(), reservations.end(), time_sorter());
54#ifdef DEBUG_DISPATCH
55 std::cout << SIMTIME << " computeDispatch fleet=" << fleet.size() << " available=" << available.size() << " reservations=" << toString(reservations) << "\n";
56#endif
57 for (auto it = reservations.begin(); it != reservations.end();) {
58 if (available.size() == 0) {
59 break;
60 }
61 Reservation* res = *it;
62 if (res->recheck > now) {
63 it++;
64 numPostponed++;
65 continue;
66 }
67 //Position pos = res.from->getLanes().front()->geometryPositionAtOffset(res.fromPos);
68 MSDevice_Taxi* closest = nullptr;
69 SUMOTime closestTime = SUMOTime_MAX;
70 bool tooEarly = false;
71 bool unreachable = false;
72 bool unreachableDest = false;
73 for (auto* taxi : available) {
74 if (remainingCapacity(taxi, res) < 0 || !taxi->compatibleLine(res)) {
75 continue;
76 }
77 SUMOTime travelTime = computePickupTime(now, taxi, *res, router);
78 const bool destConnected = isReachable(now, taxi, *res, router);
79#ifdef DEBUG_TRAVELTIME
80 if (DEBUG_COND2(person)) {
81 std::cout << SIMTIME << " taxi=" << taxi->getHolder().getID() << " person=" << toString(res->persons) << " traveltime=" << time2string(travelTime) << " reachable=" << reachable << "\n";
82 }
83#endif
84 if (travelTime < closestTime && destConnected) {
85 closestTime = travelTime;
86 closest = taxi;
87 SUMOTime taxiWait = res->pickupTime - (now + closestTime);
88 if (taxiWait > myMaximumWaitingTime) {
89 // no need to service this customer now
90 tooEarly = true;
91 res->recheck += MAX2(now + myRecheckTime, res->pickupTime - closestTime - myRecheckSafety);
92 break;
93 }
94 } else if (travelTime == SUMOTime_MAX) {
95 unreachable = true;
96 } else if (!destConnected) {
97 unreachableDest = true;
98 }
99 }
100 if (tooEarly || closest == nullptr) {
101 // too early or all taxis are too small
102 SUMOTime resWait = now - res->pickupTime;
103 if ((unreachable || unreachableDest) && resWait > myKeepUnreachableResTime) {
104 it = reservations.erase(it);
105 if (unreachable) {
106 WRITE_WARNINGF("Aborting reservation for customers '%' from '%' after waiting time % because no taxi can reach the pickup location, time=%.",
107 toString(res->persons), res->from->getID(), time2string(resWait), time2string(SIMSTEP));
108 } else {
109 WRITE_WARNINGF("Aborting reservation for customers '%' to '%' after waiting time % because no taxi can reach the dropoff location, time=%.",
110 toString(res->persons), res->from->getID(), time2string(resWait), time2string(SIMSTEP));
111 }
112 std::set<const MSTransportable*> persons = res->persons;
113 for (const MSTransportable* p : persons) {
114 removeReservation(const_cast<MSTransportable*>(p), res->from, res->fromPos, res->to, res->toPos, res->group);
115 }
116 } else {
117 it++;
118 numPostponed++;
119 }
120 } else {
121 numDispatched += dispatch(closest, it, router, reservations);
122 available.erase(closest);
123 }
124 }
125 // check if any taxis are able to service the remaining requests
126 myHasServableReservations = reservations.size() > 0 && (available.size() < fleet.size() || numPostponed > 0 || numDispatched > 0);
127#ifdef DEBUG_SERVABLE
128 std::cout << SIMTIME << " reservations=" << reservations.size() << " avail=" << available.size()
129 << " fleet=" << fleet.size() << " postponed=" << numPostponed << " dispatched=" << numDispatched << "\n";
130#endif
131}
132
133
134int
135MSDispatch_Greedy::dispatch(MSDevice_Taxi* taxi, std::vector<Reservation*>::iterator& resIt, SUMOAbstractRouter<MSEdge, SUMOVehicle>& /*router*/, std::vector<Reservation*>& reservations) {
136#ifdef DEBUG_DISPATCH
137 if (DEBUG_COND2(person)) {
138 std::cout << SIMTIME << " dispatch taxi=" << taxi->getHolder().getID() << " person=" << toString((*resIt)->persons) << "\n";
139 }
140#endif
141 taxi->dispatch(**resIt);
142 servedReservation(*resIt, taxi); // deleting res
143 resIt = reservations.erase(resIt);
144 return 1;
145}
146
147
148// ===========================================================================
149// MSDispatch_GreedyClosest methods
150// ===========================================================================
151
152void
153MSDispatch_GreedyClosest::computeDispatch(SUMOTime now, const std::vector<MSDevice_Taxi*>& fleet) {
154 bool havePostponed = false;
155 int numDispatched = 0;
156 // find available vehicles
157 std::set<MSDevice_Taxi*, MSVehicleDevice::ComparatorNumericalVehicleIdLess> available;
158 for (auto* taxi : fleet) {
159 if (taxi->isEmpty()) {
160 available.insert(taxi);
161 }
162 }
163#ifdef DEBUG_DISPATCH
164 std::cout << SIMTIME << " computeDispatch fleet=" << fleet.size() << " available=" << available.size() << "\n";
165#endif
166 // greedy assign closest vehicle
168 std::vector<Reservation*> activeReservations;
169 for (Reservation* res : getReservations()) {
170 if (res->recheck <= now) {
171 activeReservations.push_back(res);
172 }
173 }
174 while (available.size() > 0 && activeReservations.size() > 0) {
175 Reservation* closest = nullptr;
176 MSDevice_Taxi* closestTaxi = nullptr;
177 SUMOTime closestTime = SUMOTime_MAX;
178 for (Reservation* res : activeReservations) {
179 SUMOTime recheck = SUMOTime_MAX;
180 for (auto* taxi : available) {
181 if (remainingCapacity(taxi, res) < 0 || !taxi->compatibleLine(res)) {
182 continue;
183 }
184 SUMOTime travelTime = computePickupTime(now, taxi, *res, router);
185 SUMOTime taxiWait = res->pickupTime - (now + travelTime);
186#ifdef DEBUG_TRAVELTIME
187 if (DEBUG_COND2(person)) std::cout << SIMTIME << " taxi=" << taxi->getHolder().getID() << " person=" << toString(res->persons)
188 << " traveltime=" << time2string(travelTime)
189 << " pickupTime=" << time2string(res->pickupTime)
190 << " taxiWait=" << time2string(taxiWait) << "\n";
191#endif
192 if (travelTime < closestTime) {
193 if (taxiWait < myMaximumWaitingTime) {
194 closestTime = travelTime;
195 closest = res;
196 closestTaxi = taxi;
197#ifdef DEBUG_DISPATCH
198 if (DEBUG_COND2(person)) std::cout << SIMTIME << " bestTaxi=" << taxi->getHolder().getID() << " bestRes=" << toString(res->persons)
199 << " taxiPos=" << taxi->getHolder().getPositionOnLane() << " resFromPos=" << res->fromPos << " traveltime=" << time2string(travelTime) << " taxiWait=" << time2string(taxiWait) << "\n";
200#endif
201 } else {
202 recheck = MIN2(recheck,
203 MAX2(now + myRecheckTime, res->pickupTime - closestTime - myRecheckSafety));
204 }
205 }
206 }
207 /*
208 if (closestTaxi == nullptr) {
209 // all taxis would arrive to early. postpone recheck
210 res.recheck = recheck;
211 }
212 */
213 }
214 if (closestTaxi != nullptr) {
215 auto closeIt = std::find(activeReservations.begin(), activeReservations.end(), closest);
216 numDispatched += dispatch(closestTaxi, closeIt, router, activeReservations);
217 available.erase(closestTaxi);
218 } else {
219 // all current reservations are too early or too big
220 havePostponed = true;
221 break;
222 }
223 }
224 // check if any taxis are able to service the remaining requests
225 myHasServableReservations = getReservations().size() > 0 && (available.size() < fleet.size() || havePostponed || numDispatched > 0);
226#ifdef DEBUG_SERVABLE
227 std::cout << SIMTIME << " reservations=" << getReservations().size() << " avail=" << available.size()
228 << " fleet=" << fleet.size() << " postponed=" << havePostponed << " dispatched=" << numDispatched << "\n";
229#endif
230}
231
232
233/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define DEBUG_COND2(obj)
Definition MESegment.cpp:54
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define SIMSTEP
Definition SUMOTime.h:61
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define SIMTIME
Definition SUMOTime.h:62
@ SVC_TAXI
vehicle is a taxi
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A device which collects info on the vehicle trip (mainly on departure and arrival)
void dispatch(const Reservation &res)
service the given reservation
sorts reservations by time
Definition MSDispatch.h:116
void computeDispatch(SUMOTime now, const std::vector< MSDevice_Taxi * > &fleet)
computes dispatch and updates reservations
const SUMOTime myRecheckTime
recheck interval for early reservations
virtual void computeDispatch(SUMOTime now, const std::vector< MSDevice_Taxi * > &fleet)
computes dispatch and updates reservations
const int myRoutingMode
which router/edge weights to use
virtual int dispatch(MSDevice_Taxi *taxi, std::vector< Reservation * >::iterator &resIt, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, std::vector< Reservation * > &reservations)
trigger taxi dispatch.
const SUMOTime myRecheckSafety
const SUMOTime myMaximumWaitingTime
maximum time to arrive earlier at customer
bool isReachable(SUMOTime t, const MSDevice_Taxi *taxi, const Reservation &res, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router)
compute whether the reservation is servable
int remainingCapacity(const MSDevice_Taxi *taxi, const Reservation *res)
whether the given taxi has sufficient capacity to serve the reservation
static SUMOTime computePickupTime(SUMOTime t, const MSDevice_Taxi *taxi, const Reservation &res, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router)
compute time to pick up the given reservation
virtual std::string removeReservation(MSTransportable *person, const MSEdge *from, double fromPos, const MSEdge *to, double toPos, std::string group)
remove person from reservation. If the whole reservation is removed, return its id
bool myHasServableReservations
whether the last call to computeDispatch has left servable reservations
Definition MSDispatch.h:194
std::vector< Reservation * > getReservations()
retrieve all reservations
SUMOTime myKeepUnreachableResTime
the duration before canceling unreachable reservations
Definition MSDispatch.h:211
void servedReservation(const Reservation *res, MSDevice_Taxi *taxi)
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:186
MSVehicleRouter & getRouterTT(int rngIndex, const Prohibitions &prohibited={}) const
Definition MSNet.cpp:1580
static MSVehicleRouter & getRouterTT(const int rngIndex, SUMOVehicleClass svc, const Prohibitions &prohibited={})
return the vehicle router instance
SUMOVehicle & getHolder() const
Returns the vehicle that holds this device.
const std::string & getID() const
Returns the id.
Definition Named.h:74
SUMOTime pickupTime
Definition MSDispatch.h:79
const MSEdge * to
Definition MSDispatch.h:84
SUMOTime recheck
Definition MSDispatch.h:89
double fromPos
Definition MSDispatch.h:82
const MSEdge * from
Definition MSDispatch.h:81
std::string group
Definition MSDispatch.h:87
std::set< const MSTransportable * > persons
Definition MSDispatch.h:77
double toPos
Definition MSDispatch.h:85