@@ -127,6 +127,8 @@ namespace dsm {
127127 const TContainer& dst_weights,
128128 const size_t minNodeDistance = 0 );
129129
130+ void addAgentsRandomly (Size nAgents, const size_t minNodeDistance = 0 );
131+
130132 // / @brief Evolve the simulation
131133 // / @details Evolve the simulation by moving the agents and updating the travel times.
132134 // / In particular:
@@ -234,7 +236,10 @@ namespace dsm {
234236 }
235237 }
236238 }
237- assert (possibleMoves.size () > 0 );
239+ if (possibleMoves.empty ()) {
240+ Logger::error (
241+ std::format (" No possible moves from node {} for agent {}" , nodeId, agentId));
242+ }
238243 std::uniform_int_distribution<Size> moveDist{
239244 0 , static_cast <Size>(possibleMoves.size () - 1 )};
240245 // while loop to avoid U turns in non-roundabout junctions
@@ -315,9 +320,7 @@ namespace dsm {
315320 }
316321 }
317322 if (bArrived) {
318- if (pStreet->dequeue (queueIndex) == std::nullopt ) {
319- continue ;
320- }
323+ pStreet->dequeue (queueIndex);
321324 m_travelDTs.push_back ({pAgent->distance (), static_cast <double >(pAgent->time ())});
322325 if (reinsert_agents) {
323326 // reset Agent's values
@@ -332,8 +335,9 @@ namespace dsm {
332335 if (nextStreet->isFull ()) {
333336 continue ;
334337 }
335- if (pStreet->dequeue (queueIndex) == std::nullopt ) {
336- continue ;
338+ pStreet->dequeue (queueIndex);
339+ if (destinationNode->id () != nextStreet->source ()) {
340+ Logger::error (std::format (" Agent {} is going to the wrong street" , agentId));
337341 }
338342 assert (destinationNode->id () == nextStreet->source ());
339343 if (destinationNode->isIntersection ()) {
@@ -490,7 +494,7 @@ namespace dsm {
490494 } else if (!agent->streetId ().has_value () && !agent->nextStreetId ().has_value ()) {
491495 Id srcNodeId = agent->srcNodeId ().has_value () ? agent->srcNodeId ().value ()
492496 : nodeDist (this ->m_generator );
493- const auto & srcNode{this ->m_graph .nodeSet ()[ srcNodeId] };
497+ const auto & srcNode{this ->m_graph .node ( srcNodeId) };
494498 if (srcNode->isFull ()) {
495499 continue ;
496500 }
@@ -592,7 +596,16 @@ namespace dsm {
592596 const TContainer& src_weights,
593597 const TContainer& dst_weights,
594598 const size_t minNodeDistance) {
595- if (src_weights.size () == 1 && dst_weights.size () == 1 &&
599+ auto const & nSources{src_weights.size ()};
600+ auto const & nDestinations{dst_weights.size ()};
601+ Logger::debug (
602+ std::format (" Init addAgentsRandomly for {} agents from {} nodes to {} nodes with "
603+ " minNodeDistance {}" ,
604+ nAgents,
605+ nSources,
606+ dst_weights.size (),
607+ minNodeDistance));
608+ if (nSources == 1 && nDestinations == 1 &&
596609 src_weights.begin ()->first == dst_weights.begin ()->first ) {
597610 throw std::invalid_argument (Logger::buildExceptionMessage (
598611 std::format (" The only source node {} is also the only destination node." ,
@@ -626,9 +639,10 @@ namespace dsm {
626639 if (!this ->agents ().empty ()) {
627640 agentId = this ->agents ().rbegin ()->first + 1 ;
628641 }
642+ Logger::debug (std::format (" Adding {} agents at time {}." , nAgents, this ->time ()));
629643 while (nAgents > 0 ) {
630644 Id srcId{0 }, dstId{0 };
631- if (dst_weights. size () == 1 ) {
645+ if (nDestinations == 1 ) {
632646 dstId = dst_weights.begin ()->first ;
633647 srcId = dstId;
634648 }
@@ -644,19 +658,24 @@ namespace dsm {
644658 }
645659 }
646660 }
647- if (src_weights. size () > 1 ) {
661+ if (nSources > 1 ) {
648662 dstId = srcId;
649663 }
650664 while (dstId == srcId) {
651665 dRand = dstUniformDist (this ->m_generator );
652666 sum = 0 .;
653667 for (const auto & [id, weight] : dst_weights) {
654668 // if the node is at a minimum distance from the destination, skip it
655- auto result{this ->m_graph .shortestPath (srcId, id)};
656- if (result.has_value () && result.value ().path ().size () < minNodeDistance &&
657- dst_weights.size () > 1 ) {
669+ if (this ->itineraries ().at (id)->path ()->getRow (srcId).empty ()) {
658670 continue ;
659671 }
672+ if (nDestinations > 1 && minNodeDistance > 0 ) {
673+ // NOTE: Result must have a value in this case, so we can use value() as sort-of assertion
674+ if (this ->m_graph .shortestPath (srcId, id).value ().path ().size () <
675+ minNodeDistance) {
676+ continue ;
677+ }
678+ }
660679 dstId = id;
661680 sum += weight;
662681 if (dRand < sum) {
@@ -679,6 +698,20 @@ namespace dsm {
679698 }
680699 }
681700
701+ template <typename delay_t >
702+ requires (is_numeric_v<delay_t >)
703+ void RoadDynamics<delay_t >::addAgentsRandomly(Size nAgents,
704+ const size_t minNodeDistance) {
705+ std::unordered_map<Id, double > src_weights, dst_weights;
706+ for (auto const & id : this ->m_graph .inputNodes ()) {
707+ src_weights[id] = 1 .;
708+ }
709+ for (auto const & id : this ->m_graph .outputNodes ()) {
710+ dst_weights[id] = 1 .;
711+ }
712+ addAgentsRandomly (nAgents, src_weights, dst_weights, minNodeDistance);
713+ }
714+
682715 template <typename delay_t >
683716 requires (is_numeric_v<delay_t >)
684717 void RoadDynamics<delay_t >::evolve(bool reinsert_agents) {
@@ -743,9 +776,9 @@ namespace dsm {
743776 auto const streetId = sourceId * N + nodeId;
744777 auto const & pStreet{this ->m_graph .street (streetId)};
745778 if (streetPriorities.contains (streetId)) {
746- inputGreenSum += m_streetTails[ streetId] / pStreet->nLanes ();
779+ inputGreenSum += m_streetTails. at ( streetId) / pStreet->nLanes ();
747780 } else {
748- inputRedSum += m_streetTails[ streetId] / pStreet->nLanes ();
781+ inputRedSum += m_streetTails. at ( streetId) / pStreet->nLanes ();
749782 }
750783 }
751784 inputGreenSum /= meanGreenFraction;
@@ -783,13 +816,13 @@ namespace dsm {
783816 // - Check that the incoming streets have a density less than the mean one (eventually + tolerance): I want to avoid being into the cluster, better to be out or on the border
784817 // - If the previous check fails, do nothing
785818 double outputGreenSum{0 .}, outputRedSum{0 .};
786- for (const auto & targetId : this ->m_graph .adjMatrix ().getRow (nodeId)) {
819+ for (auto const & targetId : this ->m_graph .adjMatrix ().getRow (nodeId)) {
787820 auto const streetId = nodeId * N + targetId;
788821 auto const & pStreet{this ->m_graph .street (streetId)};
789822 if (streetPriorities.contains (streetId)) {
790- outputGreenSum += m_streetTails[ streetId] / pStreet->nLanes ();
823+ outputGreenSum += m_streetTails. at ( streetId) / pStreet->nLanes ();
791824 } else {
792- outputRedSum += m_streetTails[ streetId] / pStreet->nLanes ();
825+ outputRedSum += m_streetTails. at ( streetId) / pStreet->nLanes ();
793826 }
794827 }
795828 auto const outputDifference{(outputGreenSum - outputRedSum) / nCycles};
0 commit comments