@@ -147,25 +147,18 @@ namespace dsm {
147147 void setDestinationNodes (const std::span<Id>& destinationNodes,
148148 bool updatePaths = true );
149149
150- // / @brief Add an agent to the simulation
151- // / @param agent The agent
152- void addAgent (const agent_t & agent);
153150 // / @brief Add an agent to the simulation
154151 // / @param agent std::unique_ptr to the agent
155152 void addAgent (std::unique_ptr<agent_t > agent);
156- // / @brief Add an agent with given source node and itinerary
157- // / @param srcNodeId The id of the source node
158- // / @param itineraryId The id of the itinerary
159- // / @throws std::invalid_argument If the source node or the itinerary are not found
160- void addAgent (Id srcNodeId, Id itineraryId);
161- // / @brief Add a pack of agents to the simulation
162- // / @param itineraryId The index of the itinerary
163- // / @param nAgents The number of agents to add
164- // / @throw std::invalid_argument If the itinerary is not found
165- // / @details adds nAgents agents with the same itinerary of id itineraryId
166- void addAgents (Id itineraryId,
167- Size nAgents = 1 ,
168- std::optional<Id> srcNodeId = std::nullopt );
153+
154+ template <typename ... TArgs>
155+ requires (std::is_constructible_v<agent_t , TArgs...>)
156+ void addAgent (TArgs&&... args);
157+
158+ template <typename ... TArgs>
159+ requires (std::is_constructible_v<agent_t , Id, TArgs...>)
160+ void addAgents (Size nAgents, TArgs&&... args);
161+
169162 // / @brief Add a pack of agents to the simulation
170163 // / @param agents Parameter pack of agents
171164 template <typename ... Tn>
@@ -180,27 +173,12 @@ namespace dsm {
180173 // / @brief Add a set of agents to the simulation
181174 // / @param agents Generic container of agents, represented by an std::span
182175 void addAgents (std::span<agent_t > agents);
183- // / @brief Add a set of agents to the simulation
184- // / @param nAgents The number of agents to add
185- // / @param uniformly If true, the agents are added uniformly on the streets
186- // / @throw std::runtime_error If there are no itineraries
187- virtual void addAgentsUniformly (Size nAgents,
188- std::optional<Id> itineraryId = std::nullopt );
189- template <typename TContainer>
190- requires (std::is_same_v<TContainer, std::unordered_map<Id, double >> ||
191- std::is_same_v<TContainer, std::map<Id, double >>)
192- void addAgentsRandomly (Size nAgents,
193- const TContainer& src_weights,
194- const TContainer& dst_weights);
195-
196- void addRandomAgents (Size nAgents, std::optional<Id> srcNodeId = std::nullopt );
197176
198177 // / @brief Remove an agent from the simulation
199178 // / @param agentId the id of the agent to remove
200179 void removeAgent (Size agentId);
201180 template <typename T1, typename ... Tn>
202- requires (std::is_convertible_v<T1, Size> &&
203- (std::is_convertible_v<Tn, Size> && ...))
181+ requires (std::is_convertible_v<T1, Id> && (std::is_convertible_v<Tn, Size> && ...))
204182 // / @brief Remove a pack of agents from the simulation
205183 // / @param id the id of the first agent to remove
206184 // / @param ids the pack of ides of the agents to remove
@@ -333,19 +311,6 @@ namespace dsm {
333311 }
334312 }
335313
336- template <typename agent_t >
337- void Dynamics<agent_t >::addAgent(const agent_t & agent) {
338- if (m_agents.size () + 1 > m_graph.maxCapacity ()) {
339- throw std::overflow_error (buildLog (
340- std::format (" Graph is already holding the max possible number of agents ({})" ,
341- m_graph.maxCapacity ())));
342- }
343- if (m_agents.contains (agent.id ())) {
344- throw std::invalid_argument (
345- buildLog (std::format (" Agent with id {} already exists." , agent.id ())));
346- }
347- m_agents.emplace (agent.id (), std::make_unique<agent_t >(agent));
348- }
349314 template <typename agent_t >
350315 void Dynamics<agent_t >::addAgent(std::unique_ptr<agent_t > agent) {
351316 if (m_agents.size () + 1 > m_graph.maxCapacity ()) {
@@ -359,47 +324,24 @@ namespace dsm {
359324 }
360325 m_agents.emplace (agent->id (), std::move (agent));
361326 }
327+
362328 template <typename agent_t >
363- void Dynamics<agent_t >::addAgent(Id srcNodeId, Id itineraryId) {
364- if (m_agents.size () + 1 > m_graph.maxCapacity ()) {
365- throw std::overflow_error (buildLog (
366- std::format (" Graph is already holding the max possible number of agents ({})" ,
367- m_graph.maxCapacity ())));
368- }
369- if (!(srcNodeId < m_graph.nodeSet ().size ())) {
370- throw std::invalid_argument (
371- buildLog (std::format (" Node with id {} not found" , srcNodeId)));
372- }
373- if (!(m_itineraries.contains (itineraryId))) {
374- throw std::invalid_argument (
375- buildLog (std::format (" Itinerary with id {} not found" , itineraryId)));
376- }
377- Size agentId{0 };
378- if (!m_agents.empty ()) {
379- agentId = m_agents.rbegin ()->first + 1 ;
380- }
381- this ->addAgent (agent_t {agentId, itineraryId, srcNodeId});
329+ template <typename ... TArgs>
330+ requires (std::is_constructible_v<agent_t , TArgs...>)
331+ void Dynamics<agent_t >::addAgent(TArgs&&... args) {
332+ addAgent (std::make_unique<agent_t >(std::forward<TArgs>(args)...));
382333 }
334+
383335 template <typename agent_t >
384- void Dynamics<agent_t >::addAgents(Id itineraryId,
385- Size nAgents,
386- std::optional<Id> srcNodeId) {
387- if (m_agents.size () + nAgents > m_graph.maxCapacity ()) {
388- throw std::overflow_error (buildLog (
389- std::format (" Graph is already holding the max possible number of agents ({})" ,
390- m_graph.maxCapacity ())));
391- }
392- auto itineraryIt{m_itineraries.find (itineraryId)};
393- if (itineraryIt == m_itineraries.end ()) {
394- throw std::invalid_argument (
395- buildLog (std::format (" Itinerary with id {} not found" , itineraryId)));
396- }
397- Size agentId{0 };
336+ template <typename ... TArgs>
337+ requires (std::is_constructible_v<agent_t , Id, TArgs...>)
338+ void Dynamics<agent_t >::addAgents(Size nAgents, TArgs&&... args) {
339+ Id agentId{0 };
398340 if (!m_agents.empty ()) {
399341 agentId = m_agents.rbegin ()->first + 1 ;
400342 }
401- for (Size i{0 }; i < nAgents; ++i, ++agentId) {
402- this -> addAgent (agent_t { agentId, itineraryId, srcNodeId} );
343+ for (size_t i{0 }; i < nAgents; ++i, ++agentId) {
344+ addAgent (std::make_unique< agent_t >( agentId, std::forward<TArgs>(args)...) );
403345 }
404346 }
405347
@@ -412,171 +354,17 @@ namespace dsm {
412354 template <typename T1, typename ... Tn>
413355 requires (is_agent_v<T1> && (is_agent_v<Tn> && ...))
414356 void Dynamics<agent_t >::addAgents(T1 agent, Tn... agents) {
415- addAgent (agent);
357+ addAgent (std::make_unique< agent_t >( agent) );
416358 addAgents (agents...);
417359 }
418360
419361 template <typename agent_t >
420362 void Dynamics<agent_t >::addAgents(std::span<agent_t > agents) {
421- if (this ->m_agents .size () + agents.size () > this ->m_graph .maxCapacity ()) {
422- throw std::overflow_error (buildLog (
423- std::format (" Graph is already holding the max possible number of agents ({})" ,
424- this ->m_graph .maxCapacity ())));
425- }
426363 std::ranges::for_each (agents, [this ](const auto & agent) -> void {
427- this -> m_agents . push_back (std::make_unique (agent));
364+ addAgent (std::make_unique< agent_t > (agent));
428365 });
429366 }
430367
431- template <typename agent_t >
432- void Dynamics<agent_t >::addAgentsUniformly(Size nAgents,
433- std::optional<Id> itineraryId) {
434- if (m_agents.size () + nAgents > m_graph.maxCapacity ()) {
435- throw std::overflow_error (buildLog (
436- std::format (" Graph is already holding the max possible number of agents ({})" ,
437- this ->m_graph .maxCapacity ())));
438- }
439- if (m_itineraries.empty ()) {
440- // TODO: make this possible for random agents
441- throw std::invalid_argument (
442- buildLog (" It is not possible to add random agents without itineraries." ));
443- }
444- const bool randomItinerary{!itineraryId.has_value ()};
445- std::uniform_int_distribution<Size> itineraryDist{
446- 0 , static_cast <Size>(m_itineraries.size () - 1 )};
447- std::uniform_int_distribution<Size> streetDist{
448- 0 , static_cast <Size>(m_graph.streetSet ().size () - 1 )};
449- for (Size i{0 }; i < nAgents; ++i) {
450- if (randomItinerary) {
451- auto itineraryIt{m_itineraries.begin ()};
452- std::advance (itineraryIt, itineraryDist (m_generator));
453- itineraryId = itineraryIt->first ;
454- }
455- Id agentId{0 };
456- if (!m_agents.empty ()) {
457- agentId = m_agents.rbegin ()->first + 1 ;
458- }
459- Id streetId{0 };
460- do {
461- // I dunno why this works and the following doesn't
462- const auto & streetSet = m_graph.streetSet ();
463- auto streetIt = streetSet.begin ();
464- // auto streetIt = this->m_graph->streetSet().begin();
465- Size step = streetDist (m_generator);
466- std::advance (streetIt, step);
467- streetId = streetIt->first ;
468- } while (m_graph.streetSet ()[streetId]->isFull ());
469- const auto & street{m_graph.streetSet ()[streetId]};
470- agent_t agent{agentId, itineraryId.value (), street->nodePair ().first };
471- agent.setStreetId (streetId);
472- this ->addAgent (agent);
473- this ->setAgentSpeed (agentId);
474- m_agents[agentId]->incrementDelay (
475- std::ceil (street->length () / m_agents[agentId]->speed ()));
476- street->addAgent (agentId);
477- ++agentId;
478- }
479- }
480-
481- template <typename agent_t >
482- template <typename TContainer>
483- requires (std::is_same_v<TContainer, std::unordered_map<Id, double >> ||
484- std::is_same_v<TContainer, std::map<Id, double >>)
485- void Dynamics<agent_t >::addAgentsRandomly(Size nAgents,
486- const TContainer& src_weights,
487- const TContainer& dst_weights) {
488- if (src_weights.size () == 1 && dst_weights.size () == 1 &&
489- src_weights.begin ()->first == dst_weights.begin ()->first ) {
490- throw std::invalid_argument (buildLog (
491- std::format (" The only source node {} is also the only destination node." ,
492- src_weights.begin ()->first )));
493- }
494- auto const srcSum{std::accumulate (
495- src_weights.begin (),
496- src_weights.end (),
497- 0 .,
498- [](double sum, const std::pair<Id, double >& p) {
499- if (p.second < 0 .) {
500- throw std::invalid_argument (buildLog (std::format (
501- " Negative weight ({}) for source node {}." , p.second , p.first )));
502- }
503- return sum + p.second ;
504- })};
505- auto const dstSum{std::accumulate (
506- dst_weights.begin (),
507- dst_weights.end (),
508- 0 .,
509- [](double sum, const std::pair<Id, double >& p) {
510- if (p.second < 0 .) {
511- throw std::invalid_argument (buildLog (std::format (
512- " Negative weight ({}) for destination node {}." , p.second , p.first )));
513- }
514- return sum + p.second ;
515- })};
516- std::uniform_real_distribution<double > srcUniformDist{0 ., srcSum};
517- std::uniform_real_distribution<double > dstUniformDist{0 ., dstSum};
518- while (nAgents > 0 ) {
519- Id srcId{0 }, dstId{0 };
520- if (dst_weights.size () == 1 ) {
521- dstId = dst_weights.begin ()->first ;
522- srcId = dstId;
523- }
524- double dRand, sum;
525- while (srcId == dstId) {
526- dRand = srcUniformDist (m_generator);
527- sum = 0 .;
528- for (const auto & [id, weight] : src_weights) {
529- srcId = id;
530- sum += weight;
531- if (dRand < sum) {
532- break ;
533- }
534- }
535- }
536- if (src_weights.size () > 1 ) {
537- dstId = srcId;
538- }
539- while (dstId == srcId) {
540- dRand = dstUniformDist (m_generator);
541- sum = 0 .;
542- for (const auto & [id, weight] : dst_weights) {
543- dstId = id;
544- sum += weight;
545- if (dRand < sum) {
546- break ;
547- }
548- }
549- }
550- // find the itinerary with the given destination as destination
551- auto itineraryIt{std::find_if (
552- m_itineraries.begin (), m_itineraries.end (), [dstId](const auto & itinerary) {
553- return itinerary.second ->destination () == dstId;
554- })};
555- if (itineraryIt == m_itineraries.end ()) {
556- throw std::invalid_argument (
557- buildLog (std::format (" Itinerary with destination {} not found." , dstId)));
558- }
559- this ->addAgent (srcId, itineraryIt->first );
560- --nAgents;
561- }
562- }
563-
564- template <typename agent_t >
565- void Dynamics<agent_t >::addRandomAgents(Size nAgents, std::optional<Id> srcNodeId) {
566- if (m_agents.size () + nAgents > m_graph.maxCapacity ()) {
567- throw std::overflow_error (buildLog (
568- std::format (" Graph is already holding the max possible number of agents ({})" ,
569- m_graph.maxCapacity ())));
570- }
571- Id agentId{0 };
572- if (!m_agents.empty ()) {
573- agentId = m_agents.rbegin ()->first + 1 ;
574- }
575- for (auto i{0 }; i < nAgents; ++i, ++agentId) {
576- this ->addAgent (agent_t {agentId, srcNodeId});
577- }
578- }
579-
580368 template <typename agent_t >
581369 void Dynamics<agent_t >::removeAgent(Size agentId) {
582370 m_agents.erase (agentId);
0 commit comments