Eclipse SUMO - Simulation of Urban MObility
MSDispatch_GreedyShared.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-2024 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_COND2(obj) (obj->getID() == "p0")
31 #define DEBUG_COND2(obj) (true)
32 
33 
34 // ===========================================================================
35 // MSDispatch_GreedyShared methods
36 // ===========================================================================
37 
38 int
39 MSDispatch_GreedyShared::dispatch(MSDevice_Taxi* taxi, std::vector<Reservation*>::iterator& resIt, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, std::vector<Reservation*>& reservations) {
40  const Reservation* const res = *resIt;
41 #ifdef DEBUG_DISPATCH
42  if (DEBUG_COND2(person)) {
43  std::cout << SIMTIME << " dispatch taxi=" << taxi->getHolder().getID() << " person=" << toString(res->persons) << "\n";
44  }
45 #endif
46  const bool isPerson = (*res->persons.begin())->isPerson();
47  const int capacityLeft = remainingCapacity(taxi, res);
49  // check whether the ride can be shared
50  int shareCase = 0;
51  Reservation* res2 = nullptr;
52  double absLoss = 0;
53  double relLoss = 0;
54  double absLoss2 = 0;
55  double relLoss2 = 0;
56  double directTime = -1; // only computed once for res
57  double directTime2 = -1;
58  for (auto it2 = resIt + 1; it2 != reservations.end(); it2++) {
59  res2 = *it2;
60  const bool isPerson2 = (*res2->persons.begin())->isPerson();
61 
62  if (capacityLeft < (int)res2->persons.size() || isPerson != isPerson2 || !taxi->compatibleLine(res2)) {
63  // do not try to mix person and container dispatch
64  continue;
65  }
66  // res picks up res2 on the way
67  directTime2 = -1; // reset for new candidate
68  const SUMOTime startPickup = MAX2(now, res->pickupTime);
69  const double detourTime = computeDetourTime(startPickup, res2->pickupTime, taxi,
70  res->from, res->fromPos, res2->from, res2->fromPos, res->to, res->toPos, router, directTime);
71  const double absLossPickup = detourTime - directTime;
72  const double relLossPickup = absLossPickup / directTime;
73 
74 #ifdef DEBUG_DISPATCH
75  if (DEBUG_COND2(person)) std::cout << " consider sharing ride with " << toString(res2->persons)
76  << " absLossPickup=" << absLossPickup
77  << " relLossPickup=" << relLossPickup
78  << "\n";
79 #endif
80  if (absLossPickup < myAbsoluteLossThreshold && relLossPickup < myRelativeLossThreshold) {
81  const SUMOTime startDropOff = MAX2(now, res2->pickupTime);
82  double directTimeTmp = -1; // direct time from picking up res2 to dropping of res
83  // case 1: res2 is dropped off before res (more detour for res)
84  double detourTime2 = computeDetourTime(startDropOff, startDropOff, taxi,
85  res2->from, res2->fromPos, res2->to, res2->toPos, res->to, res->toPos, router, directTimeTmp);
86  const double absLoss_c1 = absLossPickup + (detourTime2 - directTimeTmp);
87  const double relLoss_c1 = absLoss_c1 / directTime;
88 
89  // case 2: res2 is dropped off after res (detour for res2)
90  double detourTime3 = computeDetourTime(startDropOff, startDropOff, taxi,
91  res2->from, res2->fromPos, res->to, res->toPos, res2->to, res2->toPos, router, directTime2);
92  const double absLoss_c2 = detourTime3 - directTime2;
93  const double relLoss_c2 = absLoss_c2 / directTime2;
94 
95  if (absLoss_c2 <= absLoss_c1 && absLoss_c2 < myAbsoluteLossThreshold && relLoss_c2 < myRelativeLossThreshold) {
96  shareCase = 2;
97  taxi->dispatchShared({res, res2, res, res2});
98  absLoss = absLossPickup;
99  relLoss = relLossPickup;
100  absLoss2 = absLoss_c2;
101  relLoss2 = relLoss_c2;
102  } else if (absLoss_c1 < myAbsoluteLossThreshold && relLoss_c1 < myRelativeLossThreshold) {
103  shareCase = 1;
104  taxi->dispatchShared({res, res2, res2, res});
105  absLoss = absLoss_c1;
106  relLoss = relLoss_c1;
107  absLoss2 = 0;
108  relLoss2 = 0;
109  }
110  if (shareCase != 0) {
111  reservations.erase(it2); // (it before it2) stays valid
112  break;
113  } else {
114 #ifdef DEBUG_DISPATCH
115  if (DEBUG_COND2(person)) std::cout << " rejected:"
116  << " absLoss_c1=" << absLoss_c1
117  << " relLoss_c1=" << relLoss_c1
118  << " absLoss_c2=" << absLoss_c2
119  << " relLoss_c2=" << relLoss_c2
120  << "\n";
121 #endif
122  }
123  }
124  }
125  if (shareCase != 0) {
126  if (myOutput != nullptr) {
127  myOutput->openTag("dispatchShared");
128  myOutput->writeAttr("time", time2string(now));
129  myOutput->writeAttr("id", taxi->getHolder().getID());
130  myOutput->writeAttr("persons", toString(res->persons));
131  myOutput->writeAttr("sharingPersons", toString(res2->persons));
132  myOutput->writeAttr("type", shareCase);
133  myOutput->writeAttr("absLoss", absLoss);
134  myOutput->writeAttr("relLoss", relLoss);
135  myOutput->writeAttr("absLoss2", absLoss2);
136  myOutput->writeAttr("relLoss2", relLoss2);
137  myOutput->closeTag();
138  }
139 #ifdef DEBUG_DISPATCH
140  if (DEBUG_COND2(person)) std::cout << " sharing ride with " << toString(res2->persons)
141  << " type=" << shareCase
142  << " absLoss=" << absLoss << " relLoss=" << relLoss
143  << " absLoss2=" << absLoss2 << " relLoss2=" << relLoss2
144  << "\n";
145 #endif
146  servedReservation(res2); // deleting res2
147  } else {
148  taxi->dispatch(*res);
149  }
150  servedReservation(res); // deleting res
151  resIt = reservations.erase(resIt);
152  return shareCase == 0 ? 1 : 2;
153 }
154 
155 
156 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define DEBUG_COND2(obj)
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition: SUMOTime.cpp:69
#define SIMTIME
Definition: SUMOTime.h:62
T MAX2(T a, T b)
Definition: StdDefs.h:82
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)
Definition: MSDevice_Taxi.h:49
void dispatch(const Reservation &res)
service the given reservation
void dispatchShared(std::vector< const Reservation * > reservations)
service the given reservations
bool compatibleLine(const Reservation *res)
whether the given reservation is compatible with the taxi line
const double myRelativeLossThreshold
relative time threshold for declining shared ride
const double myAbsoluteLossThreshold
absolute time threshold for declining shared ride in s
virtual int dispatch(MSDevice_Taxi *taxi, std::vector< Reservation * >::iterator &resIt, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, std::vector< Reservation * > &reservations)
trigger taxi dispatch.
OutputDevice * myOutput
optional file output for dispatch information
Definition: MSDispatch.h:203
int remainingCapacity(const MSDevice_Taxi *taxi, const Reservation *res)
whether the given taxi has sufficient capacity to serve the reservation
Definition: MSDispatch.cpp:316
static double computeDetourTime(SUMOTime t, SUMOTime viaTime, const MSDevice_Taxi *taxi, const MSEdge *from, double fromPos, const MSEdge *via, double viaPos, const MSEdge *to, double toPos, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, double &timeDirect)
compute directTime and detourTime
Definition: MSDispatch.cpp:280
void servedReservation(const Reservation *res)
Definition: MSDispatch.cpp:242
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
SUMOVehicle & getHolder() const
Returns the vehicle that holds this device.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
SUMOTime pickupTime
Definition: MSDispatch.h:79
const MSEdge * to
Definition: MSDispatch.h:84
double fromPos
Definition: MSDispatch.h:82
const MSEdge * from
Definition: MSDispatch.h:81
std::set< const MSTransportable * > persons
Definition: MSDispatch.h:77
double toPos
Definition: MSDispatch.h:85