LCOV - code coverage report
Current view: top level - src/microsim/devices - MSDispatch_RouteExtension.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 98.5 % 65 64
Test Date: 2025-11-13 15:38:19 Functions: 100.0 % 2 2

            Line data    Source code
       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              : /****************************************************************************/
      14              : /// @file    MSDispatch_RouteExtension.cpp
      15              : /// @author  Michael Behrisch
      16              : /// @date    06.08.2020
      17              : ///
      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>
      25              : #include <microsim/transportables/MSTransportable.h>
      26              : #include "MSRoutingEngine.h"
      27              : #include "MSDispatch_RouteExtension.h"
      28              : 
      29              : //#define DEBUG_DISPATCH
      30              : //#define DEBUG_COND2(obj) (obj->getID() == "p0")
      31              : #define DEBUG_COND2(obj) (true)
      32              : 
      33              : 
      34              : // ===========================================================================
      35              : // method definitions
      36              : // ===========================================================================
      37              : void
      38          809 : MSDispatch_RouteExtension::findInsertionPoint(std::vector<const Reservation*>::iterator& resIt, EdgePosVector::iterator& edgeIt,
      39              :         const EdgePosVector::iterator& edgeEnd, ConstMSEdgeVector& route,
      40              :         const MSEdge* newEdge, const double newPos) const {
      41         3648 :     for (const MSEdge* edge : route) {
      42        10076 :         while (edgeIt != edgeEnd && edge == edgeIt->first) {
      43         6434 :             if (edge == newEdge && edgeIt->second > newPos) {
      44              :                 break;
      45              :             }
      46              :             resIt++;
      47              :             edgeIt++;
      48              :         }
      49         3648 :         if (edge == newEdge) {
      50              :             break;
      51              :         }
      52              :     }
      53          809 : }
      54              : 
      55              : 
      56              : int
      57          131 : MSDispatch_RouteExtension::dispatch(MSDevice_Taxi* taxi, std::vector<Reservation*>::iterator& resIt, SUMOAbstractRouter<MSEdge, SUMOVehicle>& router, std::vector<Reservation*>& reservations) {
      58          131 :     const Reservation* const res = *resIt;
      59              : #ifdef DEBUG_DISPATCH
      60              :     if (DEBUG_COND2(person)) {
      61              :         std::cout << SIMTIME << " dispatch taxi=" << taxi->getHolder().getID() << " person=" << toString(res->persons) << "\n";
      62              :     }
      63              : #endif
      64          131 :     const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
      65          131 :     const bool isPerson = (*res->persons.begin())->isPerson();
      66          131 :     int capacityLeft = remainingCapacity(taxi, res);
      67          131 :     std::vector<const Reservation*> sequence{ res, res };
      68          131 :     std::vector<const Reservation*> toRemove{ res };
      69          131 :     EdgePosVector posSequence({ std::make_pair(res->from, res->fromPos), std::make_pair(res->to, res->toPos) });
      70          131 :     const Reservation* first = sequence.front();
      71          131 :     const Reservation* last = sequence.back();
      72              :     ConstMSEdgeVector route;
      73          131 :     router.compute(first->from, first->fromPos, last->to, last->toPos, &taxi->getHolder(), MAX2(now, first->pickupTime), route);
      74              :     // check whether the ride can be shared
      75          663 :     for (auto it2 = resIt + 1; it2 != reservations.end();) {
      76          547 :         Reservation* const res2 = *it2;
      77          547 :         const bool isPerson2 = (*res2->persons.begin())->isPerson();
      78          547 :         if (capacityLeft < (int)res2->persons.size() || isPerson != isPerson2 || !taxi->compatibleLine(res2)) {
      79              :             it2++;
      80            0 :             continue;
      81              :         }
      82              :         // check whether res2 picks up or gets picked up on the way
      83              :         ConstMSEdgeVector route2;
      84              :         // TODO It may be more efficient to check first whether from and to are already in the route
      85          547 :         router.compute(res2->from, res2->fromPos, res2->to, res2->toPos, &taxi->getHolder(), MAX2(now, res2->pickupTime), route2);
      86          547 :         const bool pickup = std::find(route.begin(), route.end(), res2->from) != route.end();
      87          547 :         const bool dropoff = std::find(route.begin(), route.end(), res2->to) != route.end();
      88          547 :         const bool pickup2 = std::find(route2.begin(), route2.end(), first->from) != route2.end();
      89          547 :         const bool dropoff2 = std::find(route2.begin(), route2.end(), last->to) != route2.end();
      90              : #ifdef DEBUG_DISPATCH
      91              :         if (DEBUG_COND2(person)) std::cout << "  consider sharing ride with " << toString(res2->persons)
      92              :             << " from=" << res2->from->getID() << ":" << res2->fromPos << " to=" << res2->to->getID() << ":" << res2->toPos
      93              :             << " pickup=" << pickup << " startFirst=" << pickup2
      94              :             << " dropoff=" << dropoff << " endLast=" << dropoff2
      95              :             << "\n";
      96              : #endif
      97          547 :         if ((pickup || pickup2) && (dropoff || dropoff2)) {
      98          427 :             std::vector<const Reservation*>::iterator resSeqIt = sequence.begin();
      99          427 :             EdgePosVector::iterator edgeIt = posSequence.begin();
     100          427 :             if (pickup) {
     101              :                 // new reservation gets picked up
     102          392 :                 findInsertionPoint(resSeqIt, edgeIt, posSequence.end(), route, res2->from, res2->fromPos);
     103              :             }
     104          427 :             resSeqIt = sequence.insert(resSeqIt, res2) + 1;
     105          427 :             edgeIt = posSequence.insert(edgeIt, std::make_pair(res2->from, res2->fromPos)) + 1;
     106          427 :             if (dropoff) {
     107              :                 // new reservation drops off and route continues
     108          417 :                 findInsertionPoint(resSeqIt, edgeIt, posSequence.end(), route, res2->to, res2->toPos);
     109          417 :                 sequence.insert(resSeqIt, res2);
     110          417 :                 posSequence.insert(edgeIt, std::make_pair(res2->to, res2->toPos));
     111              :             } else {
     112              :                 // new reservation ends last
     113           10 :                 sequence.push_back(res2);
     114           10 :                 posSequence.push_back(std::make_pair(res2->to, res2->toPos));
     115              :             }
     116          427 :             toRemove.push_back(res2);
     117              :             it2 = reservations.erase(it2); // (resIt before it2) stays valid
     118              :             // TODO we have more capacity if some pickup is after an earlier dropoff
     119          427 :             capacityLeft -= (int)res2->persons.size();
     120          427 :             if (capacityLeft == 0) {
     121              :                 break;
     122              :             }
     123              :             route.clear();
     124          412 :             first = sequence.front();
     125          412 :             last = sequence.back();
     126              :             // TODO this is wrong for non linear networks! should be reusing the route snippets from above
     127          412 :             router.compute(first->from, first->fromPos, last->to, last->toPos, &taxi->getHolder(), MAX2(now, first->pickupTime), route);
     128          412 :         } else {
     129              :             it2++;
     130              :         }
     131          547 :     }
     132          131 :     if (sequence.size() > 2) {
     133           83 :         taxi->dispatchShared(sequence);
     134           83 :         if (myOutput != nullptr) {
     135          120 :             myOutput->writeXMLHeader("DispatchInfo_RouteExtension", "");
     136           60 :             myOutput->openTag("dispatchShared");
     137          120 :             myOutput->writeAttr("time", time2string(now));
     138           60 :             myOutput->writeAttr("id", taxi->getHolder().getID());
     139          120 :             myOutput->writeAttr("persons", toString(res->persons));
     140          120 :             myOutput->writeAttr("sharingPersons", toString(sequence));
     141           60 :             myOutput->writeAttr("type", "routeExtension");
     142          120 :             myOutput->closeTag();
     143              :         }
     144              : #ifdef DEBUG_DISPATCH
     145              :         if (DEBUG_COND2(person)) std::cout << "  sharing ride with " << toString(sequence)
     146              :                                                << "\n";
     147              : #endif
     148              :     } else {
     149           48 :         taxi->dispatch(*res);
     150              :     }
     151          689 :     for (const Reservation* r : toRemove) {
     152          558 :         servedReservation(r, taxi); // deleting r
     153              :     }
     154          131 :     resIt = reservations.erase(resIt);
     155          131 :     return (int)toRemove.size();
     156          131 : }
     157              : 
     158              : 
     159              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1