@@ -191,7 +191,10 @@ namespace dsf::mobility {
191191 void resetTurnCounts ();
192192
193193 // / @brief Update the paths of the itineraries based on the given weight function
194- void updatePaths ();
194+ // / @param throw_on_empty If true, throws an exception if an itinerary has an empty path (default is true)
195+ // / If false, removes the itinerary with empty paths and the associated node from the origin/destination nodes
196+ // / @throws std::runtime_error if throw_on_empty is true and an itinerary has an empty path
197+ void updatePaths (bool const throw_on_empty = true );
195198 // / @brief Add agents uniformly on the road network
196199 // / @param nAgents The number of agents to add
197200 // / @param itineraryId The id of the itinerary to use (default is std::nullopt)
@@ -413,7 +416,6 @@ namespace dsf::mobility {
413416 for (auto const& [nodeId, weight] : this->m_destinationNodes) {
414417 m_itineraries.emplace(nodeId, std::make_unique<Itinerary>(nodeId, nodeId));
415418 }
416- // updatePaths();
417419 std::for_each(
418420 this->graph().edges().cbegin(),
419421 this->graph().edges().cend(),
@@ -470,12 +472,6 @@ namespace dsf::mobility {
470472
471473 auto const& path{this->graph().allPathsTo(
472474 pItinerary->destination(), m_weightFunction, m_weightTreshold)};
473- if (path.empty()) {
474- throw std::runtime_error(
475- std::format("No path found for itinerary {} with destination node {}",
476- pItinerary->id(),
477- pItinerary->destination()));
478- }
479475 pItinerary->setPath(path);
480476 auto const newSize{pItinerary->path().size()};
481477 if (oldSize > 0 && newSize != oldSize) {
@@ -1250,12 +1246,39 @@ namespace dsf::mobility {
12501246
12511247 template <typename delay_t >
12521248 requires (is_numeric_v<delay_t >)
1253- void RoadDynamics<delay_t>::updatePaths() {
1249+ void RoadDynamics<delay_t>::updatePaths(bool const throw_on_empty ) {
12541250 spdlog::debug (" Init updating paths..." );
1251+ tbb::concurrent_vector<Id> emptyItineraries;
12551252 tbb::parallel_for_each (
12561253 this ->itineraries ().cbegin (),
12571254 this ->itineraries ().cend (),
1258- [this ](auto const & pair) -> void { this ->m_updatePath (pair.second ); });
1255+ [this , throw_on_empty, &emptyItineraries](auto const & pair) -> void {
1256+ auto const & pItinerary{pair.second };
1257+ this ->m_updatePath (pItinerary);
1258+ if (pItinerary->empty ()) {
1259+ if (!throw_on_empty) {
1260+ spdlog::warn (" No path found for itinerary {} with destination node {}" ,
1261+ pItinerary->id (),
1262+ pItinerary->destination ());
1263+ emptyItineraries.push_back (pItinerary->id ());
1264+ return ;
1265+ }
1266+ throw std::runtime_error (
1267+ std::format (" No path found for itinerary {} with destination node {}" ,
1268+ pItinerary->id (),
1269+ pItinerary->destination ()));
1270+ }
1271+ });
1272+ if (!emptyItineraries.empty ()) {
1273+ spdlog::warn (" Removing {} itineraries with no valid path from the dynamics." ,
1274+ emptyItineraries.size ());
1275+ for (auto const & id : emptyItineraries) {
1276+ auto const destination = m_itineraries.at (id)->destination ();
1277+ m_destinationNodes.erase (destination);
1278+ m_originNodes.erase (destination);
1279+ m_itineraries.erase (id);
1280+ }
1281+ }
12591282 spdlog::debug (" End updating paths." );
12601283 }
12611284
0 commit comments