diff --git a/benchmark/Street/BenchStreet.cpp b/benchmark/Street/BenchStreet.cpp index 47f1345cd..2ea585180 100644 --- a/benchmark/Street/BenchStreet.cpp +++ b/benchmark/Street/BenchStreet.cpp @@ -6,7 +6,7 @@ #include "RoadNetwork.hpp" -using Agent = dsm::Agent; +using Agent = dsm::Agent; using Street = dsm::Street; using SparseMatrix = dsm::SparseMatrix; diff --git a/src/dsm/dsm.hpp b/src/dsm/dsm.hpp index 0c6700291..5a02d5a77 100644 --- a/src/dsm/dsm.hpp +++ b/src/dsm/dsm.hpp @@ -6,7 +6,7 @@ static constexpr uint8_t DSM_VERSION_MAJOR = 2; static constexpr uint8_t DSM_VERSION_MINOR = 5; -static constexpr uint8_t DSM_VERSION_PATCH = 5; +static constexpr uint8_t DSM_VERSION_PATCH = 6; static auto const DSM_VERSION = std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH); diff --git a/src/dsm/headers/Agent.hpp b/src/dsm/headers/Agent.hpp index 56a09ab2b..7a21744f3 100644 --- a/src/dsm/headers/Agent.hpp +++ b/src/dsm/headers/Agent.hpp @@ -11,8 +11,6 @@ #pragma once #include "Itinerary.hpp" -#include "SparseMatrix.hpp" -#include "../utility/TypeTraits/is_numeric.hpp" #include "../utility/Logger.hpp" #include "../utility/Typedef.hpp" @@ -25,70 +23,54 @@ namespace dsm { /// @brief The Agent class represents an agent in the network. - /// @tparam delay_t, The type of the agent's delay. It must be a numeric type (see utility/TypeTraits/is_numeric.hpp). - template - requires(is_numeric_v) class Agent { private: + Time m_spawnTime, m_freeTime; Id m_id; std::vector m_trip; std::optional m_streetId; std::optional m_srcNodeId; std::optional m_nextStreetId; - delay_t m_delay; - double m_speed; - double m_distance; // Travelled distance - unsigned int m_time; // Travelled time size_t m_itineraryIdx; + double m_speed; + double m_distance; // Travelled distance public: /// @brief Construct a new Agent object + /// @param spawnTime The agent's spawn time /// @param id The agent's id /// @param itineraryId Optional, The agent's destination node. If not provided, the agent is a random agent /// @param srcNodeId Optional, The id of the source node of the agent - Agent(Id id, + Agent(Time const& spawnTime, + Id id, std::optional itineraryId = std::nullopt, std::optional srcNodeId = std::nullopt); /// @brief Construct a new Agent object + /// @param spawnTime The agent's spawn time /// @param id The agent's id /// @param itineraryIds The agent's itinerary /// @param srcNodeId Optional, The id of the source node of the agent - Agent(Id id, std::vector const& trip, std::optional srcNodeId = std::nullopt); + Agent(Time const& spawnTime, + Id id, + std::vector const& trip, + std::optional srcNodeId = std::nullopt); /// @brief Set the street occupied by the agent /// @param streetId The id of the street currently occupied by the agent - void setStreetId(Id streetId); + void setStreetId(std::optional streetId = std::nullopt); /// @brief Set the id of the next street /// @param nextStreetId The id of the next street - void setNextStreetId(Id nextStreetId) { m_nextStreetId = nextStreetId; } + void setNextStreetId(Id nextStreetId); /// @brief Set the agent's speed /// @param speed, The agent's speed /// @throw std::invalid_argument, if speed is negative void setSpeed(double speed); - /// @brief Increment the agent's delay by 1 - /// @throw std::overflow_error, if delay has reached its maximum value - void incrementDelay(); - /// @brief Increment the agent's delay by a given value - /// @param delay The agent's delay - /// @throw std::overflow_error, if delay has reached its maximum value - void incrementDelay(delay_t const delay); - /// @brief Decrement the agent's delay by 1 - /// @throw std::underflow_error, if delay has reached its minimum value - void decrementDelay(); - /// @brief Increment the agent's distance by its speed * 1 second - void incrementDistance() { m_distance += m_speed; } + /// @brief Set the agent's free time + /// @param freeTime The agent's free time + void setFreeTime(Time const& freeTime); /// @brief Increment the agent's distance by a given value /// @param distance The value to increment the agent's distance byù /// @throw std::invalid_argument, if distance is negative void incrementDistance(double distance); - /// @brief Increment the agent's time by 1 - /// @throw std::overflow_error, if time has reached its maximum value - void incrementTime(); - /// @brief Increment the agent's time by a given value - /// @param time The value to increment the agent's time by - /// @throw std::overflow_error, if time has reached its maximum value - void incrementTime(unsigned int const time); - /// @brief Reset the agent's time to 0 - void resetTime() { m_time = 0; } /// @brief Update the agent's itinerary /// @details If possible, the agent's itinerary is updated by removing the first element /// from the itinerary's vector. @@ -101,164 +83,40 @@ namespace dsm { /// - distance = 0 /// - time = 0 /// - itinerary index = 0 - void reset(); + void reset(Time const& spawnTime); + /// @brief Get the agent's spawn time + /// @return The agent's spawn time + Time const& spawnTime() const; + /// @brief Get the agent's free time + /// @return The agent's free time + Time const& freeTime() const; /// @brief Get the agent's id /// @return The agent's id - Id id() const { return m_id; } + Id id() const; /// @brief Get the agent's itinerary /// @return The agent's itinerary Id itineraryId() const; /// @brief Get the agent's trip /// @return The agent's trip - std::vector const& trip() const { return m_trip; } + std::vector const& trip() const; /// @brief Get the id of the street currently occupied by the agent /// @return The id of the street currently occupied by the agent - std::optional streetId() const { return m_streetId; } + std::optional streetId() const; /// @brief Get the id of the source node of the agent /// @return The id of the source node of the agent - std::optional srcNodeId() const { return m_srcNodeId; } + std::optional srcNodeId() const; /// @brief Get the id of the next street /// @return The id of the next street - std::optional nextStreetId() const { return m_nextStreetId; } + std::optional nextStreetId() const; /// @brief Get the agent's speed /// @return The agent's speed - double speed() const { return m_speed; } - /// @brief Get the agent's delay - /// @return The agent's delay - delay_t delay() const { return m_delay; } + double speed() const; /// @brief Get the agent's travelled distance /// @return The agent's travelled distance - double distance() const { return m_distance; } - /// @brief Get the agent's travel time - /// @return The agent's travel time - unsigned int time() const { return m_time; } + double distance() const; /// @brief Return true if the agent is a random agent /// @return True if the agent is a random agent, false otherwise - bool isRandom() const { return m_trip.empty(); } + bool isRandom() const; }; - - template - requires(is_numeric_v) - Agent::Agent(Id id, std::optional itineraryId, std::optional srcNodeId) - : m_id{id}, - m_trip{itineraryId.has_value() ? std::vector{itineraryId.value()} - : std::vector{}}, - m_srcNodeId{srcNodeId}, - m_nextStreetId{std::nullopt}, - m_delay{0}, - m_speed{0.}, - m_distance{0.}, - m_time{0}, - m_itineraryIdx{0} {} - - template - requires(is_numeric_v) - Agent::Agent(Id id, std::vector const& trip, std::optional srcNodeId) - : m_id{id}, - m_trip{trip}, - m_srcNodeId{srcNodeId}, - m_nextStreetId{std::nullopt}, - m_delay{0}, - m_speed{0.}, - m_distance{0.}, - m_time{0}, - m_itineraryIdx{0} {} - - template - requires(is_numeric_v) - Id Agent::itineraryId() const { - assert(m_itineraryIdx < m_trip.size()); - return m_trip[m_itineraryIdx]; - } - - template - requires(is_numeric_v) - void Agent::setStreetId(Id streetId) { - assert(m_nextStreetId.has_value() ? streetId == m_nextStreetId.value() : true); - m_streetId = streetId; - m_nextStreetId = std::nullopt; - } - - template - requires(is_numeric_v) - void Agent::setSpeed(double speed) { - if (speed < 0) { - Logger::error(std::format("Speed ({}) of agent {} must be positive", speed, m_id)); - } - m_speed = speed; - } - template - requires(is_numeric_v) - void Agent::updateItinerary() { - if (m_itineraryIdx < m_trip.size() - 1) { - ++m_itineraryIdx; - } - } - template - requires(is_numeric_v) - void Agent::reset() { - m_streetId = std::nullopt; - m_delay = 0; - m_speed = 0.; - m_distance = 0.; - m_time = 0; - m_itineraryIdx = 0; - } - template - requires(is_numeric_v) - void Agent::incrementDelay() { - if (m_delay == std::numeric_limits::max()) { - throw std::overflow_error( - Logger::buildExceptionMessage("delay_t has reached its maximum value")); - } - ++m_delay; - } - template - requires(is_numeric_v) - void Agent::incrementDelay(delay_t const delay) { - if (m_delay + delay < m_delay) { - throw std::overflow_error( - Logger::buildExceptionMessage("delay_t has reached its maximum value")); - } - m_delay += delay; - } - template - requires(is_numeric_v) - void Agent::decrementDelay() { - if (m_delay == 0) { - throw std::underflow_error( - Logger::buildExceptionMessage("delay_t has reached its minimum value")); - } - --m_delay; - } - - template - requires(is_numeric_v) - void Agent::incrementDistance(double distance) { - if (distance < 0) { - Logger::error(std::format( - "Distance travelled ({}) by agent {} must be positive", distance, m_id)); - } - m_distance += distance; - } - - template - requires(is_numeric_v) - void Agent::incrementTime() { - if (m_time == std::numeric_limits::max()) { - throw std::overflow_error( - Logger::buildExceptionMessage("Time has reached its maximum value")); - } - ++m_time; - } - template - requires(is_numeric_v) - void Agent::incrementTime(unsigned int const time) { - if (m_time + time < m_time) { - throw std::overflow_error( - Logger::buildExceptionMessage("Time has reached its maximum value")); - } - m_time += time; - } }; // namespace dsm diff --git a/src/dsm/headers/RoadDynamics.hpp b/src/dsm/headers/RoadDynamics.hpp index ac69ef7b0..ca2efb38f 100644 --- a/src/dsm/headers/RoadDynamics.hpp +++ b/src/dsm/headers/RoadDynamics.hpp @@ -45,7 +45,7 @@ namespace dsm { template requires(is_numeric_v) class RoadDynamics : public Dynamics { - std::map>> m_agents; + std::map> m_agents; std::unordered_map> m_itineraries; protected: @@ -93,7 +93,7 @@ namespace dsm { /// @brief Evolve the agents. /// @details Puts all new agents on a street, if possible, decrements all delays /// and increments all travel times. - void m_evolveAgent(std::unique_ptr> const& pAgent); + void m_evolveAgent(std::unique_ptr const& pAgent); public: /// @brief Construct a new RoadDynamics object @@ -164,29 +164,15 @@ namespace dsm { /// @brief Add an agent to the simulation /// @param agent std::unique_ptr to the agent - void addAgent(std::unique_ptr> agent); + void addAgent(std::unique_ptr agent); template - requires(std::is_constructible_v, TArgs...>) + requires(std::is_constructible_v) void addAgent(TArgs&&... args); template - requires(std::is_constructible_v, Id, TArgs...>) + requires(std::is_constructible_v) void addAgents(Size nAgents, TArgs&&... args); - /// @brief Add a pack of agents to the simulation - /// @param agents Parameter pack of agents - template - requires(is_agent_v && ...) - void addAgents(Tn... agents); - /// @brief Add a pack of agents to the simulation - /// @param agent An agent - /// @param agents Parameter pack of agents - template - requires(is_agent_v && (is_agent_v && ...)) - void addAgents(T1 agent, Tn... agents); - /// @brief Add a set of agents to the simulation - /// @param agents Generic container of agents, represented by an std::span - void addAgents(std::span> agents); /// @brief Remove an agent from the simulation /// @param agentId the id of the agent to remove @@ -237,9 +223,7 @@ namespace dsm { } /// @brief Get the agents /// @return const std::unordered_map>&, The agents - const std::map>>& agents() const { - return m_agents; - } + const std::map>& agents() const { return m_agents; } /// @brief Get the number of agents currently in the simulation /// @return Size The number of agents Size nAgents() const { return m_agents.size(); } @@ -559,7 +543,7 @@ namespace dsm { } const auto agentId{pStreet->queue(queueIndex).front()}; auto const& pAgent{this->agents().at(agentId)}; - if (pAgent->delay() > 0) { + if (pAgent->freeTime() > this->time()) { continue; } pAgent->setSpeed(0.); @@ -592,10 +576,11 @@ namespace dsm { } if (bArrived) { pStreet->dequeue(queueIndex); - m_travelDTs.push_back({pAgent->distance(), static_cast(pAgent->time())}); + m_travelDTs.push_back({pAgent->distance(), + static_cast(this->time() - pAgent->spawnTime())}); if (reinsert_agents) { // reset Agent's values - pAgent->reset(); + pAgent->reset(this->time()); } else { m_agentsToRemove.push_back(agentId); // this->removeAgent(agentId); @@ -644,7 +629,8 @@ namespace dsm { intersection.removeAgent(agentId); this->agents().at(agentId)->setStreetId(nextStreet->id()); this->setAgentSpeed(agentId); - this->agents().at(agentId)->incrementDelay( + this->agents().at(agentId)->setFreeTime( + this->time() + std::ceil(nextStreet->length() / this->agents().at(agentId)->speed())); nextStreet->addAgent(agentId); return true; @@ -672,7 +658,8 @@ namespace dsm { roundabout.dequeue(); this->agents().at(agentId)->setStreetId(nextStreet->id()); this->setAgentSpeed(agentId); - this->agents().at(agentId)->incrementDelay( + this->agents().at(agentId)->setFreeTime( + this->time() + std::ceil(nextStreet->length() / this->agents().at(agentId)->speed())); nextStreet->addAgent(agentId); } else { @@ -684,82 +671,69 @@ namespace dsm { template requires(is_numeric_v) - void RoadDynamics::m_evolveAgent( - std::unique_ptr> const& pAgent) { + void RoadDynamics::m_evolveAgent(std::unique_ptr const& pAgent) { std::uniform_int_distribution nodeDist{ 0, static_cast(this->graph().nNodes() - 1)}; - if (pAgent->delay() > 0) { - const auto& street{this->graph().edge(pAgent->streetId().value())}; - if (pAgent->delay() > 1) { - pAgent->incrementDistance(); - } else { - double distance{std::fmod(street->length(), pAgent->speed())}; - if (distance < std::numeric_limits::epsilon()) { - pAgent->incrementDistance(); - } else { - pAgent->incrementDistance(distance); + // The "cost" of enqueuing is one time unit, so we consider it as passed + if (pAgent->freeTime() == this->time() + 1 && pAgent->streetId().has_value()) { + const auto& street{this->graph().edge(*pAgent->streetId())}; + auto const nLanes = street->nLanes(); + bool bArrived{false}; + if (!pAgent->isRandom()) { + if (this->itineraries().at(pAgent->itineraryId())->destination() == + street->target()) { + pAgent->updateItinerary(); } - } - pAgent->decrementDelay(); - if (pAgent->delay() == 0) { - auto const nLanes = street->nLanes(); - bool bArrived{false}; - if (!pAgent->isRandom()) { - if (this->itineraries().at(pAgent->itineraryId())->destination() == - street->target()) { - pAgent->updateItinerary(); - } - if (this->itineraries().at(pAgent->itineraryId())->destination() == - street->target()) { - bArrived = true; - } + if (this->itineraries().at(pAgent->itineraryId())->destination() == + street->target()) { + bArrived = true; } - if (bArrived) { - std::uniform_int_distribution laneDist{0, - static_cast(nLanes - 1)}; - street->enqueue(pAgent->id(), laneDist(this->m_generator)); + } + pAgent->incrementDistance(street->length()); + if (bArrived) { + std::uniform_int_distribution laneDist{0, + static_cast(nLanes - 1)}; + street->enqueue(pAgent->id(), laneDist(this->m_generator)); + } else { + auto const nextStreetId = + this->m_nextStreetId(pAgent->id(), street->target(), street->id()); + auto const& pNextStreet{this->graph().edge(nextStreetId)}; + pAgent->setNextStreetId(nextStreetId); + if (nLanes == 1) { + street->enqueue(pAgent->id(), 0); } else { - auto const nextStreetId = - this->m_nextStreetId(pAgent->id(), street->target(), street->id()); - auto const& pNextStreet{this->graph().edge(nextStreetId)}; - pAgent->setNextStreetId(nextStreetId); - if (nLanes == 1) { - street->enqueue(pAgent->id(), 0); - } else { - auto const deltaAngle{pNextStreet->deltaAngle(street->angle())}; - if (std::abs(deltaAngle) < std::numbers::pi) { - // Lanes are counted as 0 is the far right lane - if (std::abs(deltaAngle) < std::numbers::pi / 4) { - std::vector weights; - for (auto const& queue : street->exitQueues()) { - weights.push_back(1. / (queue.size() + 1)); - } - // If all weights are the same, make the last 0 - if (std::all_of(weights.begin(), weights.end(), [&](double w) { - return std::abs(w - weights.front()) < - std::numeric_limits::epsilon(); - })) { - weights.back() = 0.; - if (nLanes > 2) { - weights.front() = 0.; - } - } - // Normalize the weights - auto const sum = std::accumulate(weights.begin(), weights.end(), 0.); - for (auto& w : weights) { - w /= sum; + auto const deltaAngle{pNextStreet->deltaAngle(street->angle())}; + if (std::abs(deltaAngle) < std::numbers::pi) { + // Lanes are counted as 0 is the far right lane + if (std::abs(deltaAngle) < std::numbers::pi / 4) { + std::vector weights; + for (auto const& queue : street->exitQueues()) { + weights.push_back(1. / (queue.size() + 1)); + } + // If all weights are the same, make the last 0 + if (std::all_of(weights.begin(), weights.end(), [&](double w) { + return std::abs(w - weights.front()) < + std::numeric_limits::epsilon(); + })) { + weights.back() = 0.; + if (nLanes > 2) { + weights.front() = 0.; } - std::discrete_distribution laneDist{weights.begin(), - weights.end()}; - street->enqueue(pAgent->id(), laneDist(this->m_generator)); - } else if (deltaAngle < 0.) { // Right - street->enqueue(pAgent->id(), 0); // Always the first lane - } else { // Left (deltaAngle > 0.) - street->enqueue(pAgent->id(), nLanes - 1); // Always the last lane } - } else { // U turn + // Normalize the weights + auto const sum = std::accumulate(weights.begin(), weights.end(), 0.); + for (auto& w : weights) { + w /= sum; + } + std::discrete_distribution laneDist{weights.begin(), weights.end()}; + street->enqueue(pAgent->id(), laneDist(this->m_generator)); + } else if (deltaAngle < 0.) { // Right + street->enqueue(pAgent->id(), 0); // Always the first lane + } else { // Left (deltaAngle > 0.) street->enqueue(pAgent->id(), nLanes - 1); // Always the last lane } + } else { // U turn + street->enqueue(pAgent->id(), nLanes - 1); // Always the last lane } } } @@ -784,10 +758,9 @@ namespace dsm { roundabout.enqueue(pAgent->id()); } pAgent->setNextStreetId(nextStreet->id()); - } else if (pAgent->delay() == 0) { + } else if (pAgent->freeTime() == this->time()) { pAgent->setSpeed(0.); } - pAgent->incrementTime(); } template @@ -889,8 +862,7 @@ namespace dsm { auto const& pAgent{this->agents().at(agentId)}; pAgent->setStreetId(streetId); this->setAgentSpeed(agentId); - pAgent->incrementDelay( - std::ceil(street->length() / this->agents().at(agentId)->speed())); + pAgent->setFreeTime(this->time() + std::ceil(street->length() / pAgent->speed())); street->addAgent(agentId); ++agentId; } @@ -1023,7 +995,7 @@ namespace dsm { template requires(is_numeric_v) - void RoadDynamics::addAgent(std::unique_ptr> agent) { + void RoadDynamics::addAgent(std::unique_ptr agent) { if (m_agents.size() + 1 > this->graph().maxCapacity()) { throw std::overflow_error(Logger::buildExceptionMessage(std::format( "RoadNetwork is already holding the max possible number of agents ({})", @@ -1043,48 +1015,26 @@ namespace dsm { template requires(is_numeric_v) template - requires(std::is_constructible_v, TArgs...>) + requires(std::is_constructible_v) void RoadDynamics::addAgent(TArgs&&... args) { - addAgent(std::make_unique>(std::forward(args)...)); + addAgent(std::make_unique(this->time(), std::forward(args)...)); } template requires(is_numeric_v) template - requires(std::is_constructible_v, Id, TArgs...>) + requires(std::is_constructible_v) void RoadDynamics::addAgents(Size nAgents, TArgs&&... args) { Id agentId{0}; if (!m_agents.empty()) { agentId = m_agents.rbegin()->first + 1; } for (size_t i{0}; i < nAgents; ++i, ++agentId) { - addAgent(std::make_unique>(agentId, std::forward(args)...)); + addAgent( + std::make_unique(this->time(), agentId, std::forward(args)...)); } } - template - requires(is_numeric_v) - template - requires(is_agent_v && ...) - void RoadDynamics::addAgents(Tn... agents) {} - - template - requires(is_numeric_v) - template - requires(is_agent_v && (is_agent_v && ...)) - void RoadDynamics::addAgents(T1 agent, Tn... agents) { - addAgent(std::make_unique>(agent)); - addAgents(agents...); - } - - template - requires(is_numeric_v) - void RoadDynamics::addAgents(std::span> agents) { - std::ranges::for_each(agents, [this](const auto& agent) -> void { - addAgent(std::make_unique>(agent)); - }); - } - template requires(is_numeric_v) void RoadDynamics::removeAgent(Size agentId) { diff --git a/src/dsm/sources/Agent.cpp b/src/dsm/sources/Agent.cpp new file mode 100644 index 000000000..7624a224d --- /dev/null +++ b/src/dsm/sources/Agent.cpp @@ -0,0 +1,86 @@ +#include "../headers/Agent.hpp" + +namespace dsm { + Agent::Agent(Time const& spawnTime, + Id id, + std::optional itineraryId, + std::optional srcNodeId) + : m_spawnTime{spawnTime}, + m_freeTime{0}, + m_id{id}, + m_trip{itineraryId.has_value() ? std::vector{*itineraryId} + : std::vector{}}, + m_srcNodeId{srcNodeId}, + m_nextStreetId{std::nullopt}, + m_itineraryIdx{0}, + m_speed{0.}, + m_distance{0.} {} + Agent::Agent(Time const& spawnTime, + Id id, + std::vector const& trip, + std::optional srcNodeId) + : m_spawnTime{spawnTime}, + m_freeTime{spawnTime}, + m_id{id}, + m_trip{trip}, + m_srcNodeId{srcNodeId}, + m_nextStreetId{std::nullopt}, + m_itineraryIdx{0}, + m_speed{0.}, + m_distance{0.} {} + + void Agent::setStreetId(std::optional streetId) { + if (!streetId.has_value()) { + assert(m_nextStreetId.has_value()); + m_streetId = std::move(m_nextStreetId); + return; + } + assert(m_nextStreetId.has_value() ? streetId == m_nextStreetId.value() : true); + m_streetId = streetId; + m_nextStreetId = std::nullopt; + } + void Agent::setNextStreetId(Id nextStreetId) { m_nextStreetId = nextStreetId; } + void Agent::setSpeed(double speed) { + if (speed < 0.) { + Logger::error(std::format("Speed ({}) of agent {} must be positive", speed, m_id)); + } + m_speed = speed; + } + void Agent::setFreeTime(Time const& freeTime) { m_freeTime = freeTime; } + + void Agent::incrementDistance(double distance) { + if (distance < 0) { + Logger::error(std::format( + "Distance travelled ({}) by agent {} must be positive", distance, m_id)); + } + m_distance += distance; + } + void Agent::updateItinerary() { + if (m_itineraryIdx < m_trip.size() - 1) { + ++m_itineraryIdx; + } + } + void Agent::reset(Time const& spawnTime) { + m_spawnTime = spawnTime; + m_freeTime = 0; + m_streetId = std::nullopt; + m_speed = 0.; + m_distance = 0.; + m_itineraryIdx = 0; + } + + Time const& Agent::spawnTime() const { return m_spawnTime; } + Time const& Agent::freeTime() const { return m_freeTime; } + Id Agent::id() const { return m_id; } + Id Agent::itineraryId() const { + assert(m_itineraryIdx < m_trip.size()); + return m_trip[m_itineraryIdx]; + } + std::vector const& Agent::trip() const { return m_trip; } + std::optional Agent::streetId() const { return m_streetId; } + std::optional Agent::srcNodeId() const { return m_srcNodeId; } + std::optional Agent::nextStreetId() const { return m_nextStreetId; } + double Agent::speed() const { return m_speed; } + double Agent::distance() const { return m_distance; } + bool Agent::isRandom() const { return m_trip.empty(); } +} // namespace dsm diff --git a/src/dsm/sources/RoadNetwork.cpp b/src/dsm/sources/RoadNetwork.cpp index 2325c347c..784ba3516 100644 --- a/src/dsm/sources/RoadNetwork.cpp +++ b/src/dsm/sources/RoadNetwork.cpp @@ -619,8 +619,8 @@ namespace dsm { auto streetIt = std::find_if(m_edges.begin(), m_edges.end(), [source, destination](const auto& street) -> bool { - return street.second->nodePair().first == source && - street.second->nodePair().second == destination; + return street.second->source() == source && + street.second->target() == destination; }); if (streetIt == m_edges.end()) { return nullptr; @@ -629,11 +629,11 @@ namespace dsm { auto id1 = streetIt->first; auto id2 = source * n + destination; assert(id1 == id2); - if (id1 != id2) { - std::cout << "node size: " << n << std::endl; - std::cout << "Street id: " << id1 << std::endl; - std::cout << "Nodes: " << id2 << std::endl; - } + // if (id1 != id2) { + // std::cout << "node size: " << n << std::endl; + // std::cout << "Street id: " << id1 << std::endl; + // std::cout << "Nodes: " << id2 << std::endl; + // } return &(streetIt->second); } diff --git a/src/dsm/utility/TypeTraits/is_agent.hpp b/src/dsm/utility/TypeTraits/is_agent.hpp index de708561f..ca4b6ee35 100644 --- a/src/dsm/utility/TypeTraits/is_agent.hpp +++ b/src/dsm/utility/TypeTraits/is_agent.hpp @@ -1,27 +1,23 @@ -#pragma once +// #pragma once -#include -#include -#include -#include "is_numeric.hpp" +// #include +// #include +// #include +// #include "is_numeric.hpp" -namespace dsm { - template - requires(is_numeric_v) - class Agent; +// namespace dsm { +// class Agent; - // define is_node type trait - template - struct is_agent : std::false_type {}; +// // define is_node type trait +// template +// struct is_agent : std::false_type {}; - template - struct is_agent> : std::true_type {}; +// struct is_agent : std::true_type {}; - template - struct is_agent>> : std::true_type {}; +// struct is_agent> : std::true_type {}; - template - inline constexpr bool is_agent_v = is_agent::value; +// template +// inline constexpr bool is_agent_v = is_agent::value; -}; // namespace dsm +// }; // namespace dsm diff --git a/src/dsm/utility/TypeTraits/is_itinerary.hpp b/src/dsm/utility/TypeTraits/is_itinerary.hpp index d6bcb01de..3ae531787 100644 --- a/src/dsm/utility/TypeTraits/is_itinerary.hpp +++ b/src/dsm/utility/TypeTraits/is_itinerary.hpp @@ -1,24 +1,22 @@ -#pragma once +// #pragma once -#include -#include -#include +// #include +// #include +// #include -namespace dsm { - class Itinerary; +// namespace dsm { +// class Itinerary; - // define is_node type trait - template - struct is_itinerary : std::false_type {}; +// // define is_node type trait +// template +// struct is_itinerary : std::false_type {}; - template - struct is_itinerary> : std::true_type {}; +// struct is_itinerary : std::true_type {}; - template - struct is_itinerary>> : std::true_type {}; +// struct is_itinerary> : std::true_type {}; - template - inline constexpr bool is_itinerary_v = is_itinerary::value; +// template +// inline constexpr bool is_itinerary_v = is_itinerary::value; -}; // namespace dsm +// }; // namespace dsm diff --git a/test/Test_agent.cpp b/test/Test_agent.cpp index b367a8442..caa9635d2 100644 --- a/test/Test_agent.cpp +++ b/test/Test_agent.cpp @@ -6,7 +6,7 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "doctest.h" -using Agent = dsm::Agent; +using Agent = dsm::Agent; TEST_CASE("Agent") { SUBCASE("Constructors") { @@ -14,15 +14,15 @@ TEST_CASE("Agent") { uint16_t agentId{1}; uint16_t itineraryId{0}; WHEN("The Agent is constructed") { - Agent agent{agentId, itineraryId}; + Agent agent{0, agentId, itineraryId}; THEN("The agent and itinerary ids are set correctly") { CHECK_EQ(agent.id(), agentId); CHECK_EQ(agent.itineraryId(), itineraryId); CHECK_FALSE(agent.streetId().has_value()); CHECK_FALSE(agent.srcNodeId().has_value()); CHECK_EQ(agent.speed(), 0); - CHECK_EQ(agent.delay(), 0); - CHECK_EQ(agent.time(), 0); + CHECK_EQ(agent.freeTime(), 0); + CHECK_EQ(agent.spawnTime(), 0); } } } @@ -31,7 +31,7 @@ TEST_CASE("Agent") { uint16_t itineraryId{0}; uint16_t srcNodeId{0}; WHEN("The Agent is constructed") { - Agent agent{agentId, itineraryId, srcNodeId}; + Agent agent{0, agentId, itineraryId, srcNodeId}; THEN("The agent and itinerary ids are set correctly") { CHECK_EQ(agent.id(), agentId); CHECK_EQ(agent.itineraryId(), itineraryId); @@ -39,15 +39,15 @@ TEST_CASE("Agent") { CHECK(agent.srcNodeId().has_value()); CHECK_EQ(agent.srcNodeId().value(), srcNodeId); CHECK_EQ(agent.speed(), 0); - CHECK_EQ(agent.delay(), 0); - CHECK_EQ(agent.time(), 0); + CHECK_EQ(agent.freeTime(), 0); + CHECK_EQ(agent.spawnTime(), 0); } } } GIVEN("An agent it") { uint16_t agentId{1}; WHEN("The agent is constructed") { - auto randomAgent = Agent{agentId}; + auto randomAgent = Agent{0, agentId}; THEN("The agent is a random agent") { CHECK(randomAgent.isRandom()); } } } diff --git a/test/Test_dynamics.cpp b/test/Test_dynamics.cpp index 6c2092731..9c26a7a82 100644 --- a/test/Test_dynamics.cpp +++ b/test/Test_dynamics.cpp @@ -13,7 +13,7 @@ using SparseMatrix = dsm::SparseMatrix; using Road = dsm::Road; using Street = dsm::Street; using SpireStreet = dsm::SpireStreet; -using Agent = dsm::Agent; +using Agent = dsm::Agent; using Itinerary = dsm::Itinerary; using Intersection = dsm::Intersection; using TrafficLight = dsm::TrafficLight; @@ -446,23 +446,23 @@ TEST_CASE("Dynamics") { graph.addStreets(s1, s2, s3); graph.buildAdj(); Dynamics dynamics{graph, false, 69, 0.0, dsm::weight_functions::streetLength, 1.}; - dynamics.addItinerary(std::unique_ptr(new Itinerary(0, 2))); + dynamics.addItinerary(2, 2); dynamics.updatePaths(); WHEN("We add an agent randomly and evolve the dynamics") { - dynamics.addAgent(0, 0, 0); - dynamics.evolve(false); - dynamics.evolve(false); + dynamics.addAgent(0, 2, 0); + dynamics.evolve(false); // Agent goes into node 0 + dynamics.evolve(false); // Agent goes from node 0 to street 0->1 THEN("The agent evolves") { - CHECK_EQ(dynamics.agents().at(0)->time(), 2); - CHECK_EQ(dynamics.agents().at(0)->delay(), 0); + CHECK_EQ(dynamics.time() - dynamics.agents().at(0)->spawnTime(), 2); + CHECK_EQ(dynamics.agents().at(0)->freeTime(), dynamics.time()); CHECK(dynamics.agents().at(0)->streetId().has_value()); CHECK_EQ(dynamics.agents().at(0)->streetId().value(), 1); CHECK_EQ(dynamics.agents().at(0)->speed(), 13.8888888889); } - dynamics.evolve(false); + dynamics.evolve(false); // Agent enqueues on street 0->1 THEN("The agent evolves again, changing street") { - CHECK_EQ(dynamics.agents().at(0)->time(), 3); - CHECK_EQ(dynamics.agents().at(0)->delay(), 0); + CHECK_EQ(dynamics.time() - dynamics.agents().at(0)->spawnTime(), 3); + CHECK_EQ(dynamics.agents().at(0)->freeTime(), dynamics.time()); CHECK_EQ(dynamics.agents().at(0)->streetId().value(), 5); CHECK_EQ(dynamics.agents().at(0)->speed(), 13.8888888889); } @@ -484,8 +484,8 @@ TEST_CASE("Dynamics") { dynamics.evolve(false); dynamics.evolve(false); THEN("The agent evolves") { - CHECK_EQ(dynamics.agents().at(0)->time(), 2); - CHECK_EQ(dynamics.agents().at(0)->delay(), 0); + CHECK_EQ(dynamics.time() - dynamics.agents().at(0)->spawnTime(), 2); + CHECK_EQ(dynamics.agents().at(0)->freeTime(), dynamics.time()); CHECK_EQ(dynamics.agents().at(0)->streetId().value(), 1); CHECK_EQ(dynamics.agents().at(0)->speed(), 13.8888888889); CHECK_EQ(dynamics.agents().at(0)->distance(), 13.8888888889); @@ -501,15 +501,15 @@ TEST_CASE("Dynamics") { graph2.addStreets(s1, s2); graph2.buildAdj(); Dynamics dynamics{graph2, false, 69, 0., dsm::weight_functions::streetLength, 1.}; - dynamics.addItinerary(std::unique_ptr(new Itinerary(0, 1))); + dynamics.addItinerary(1, 1); dynamics.updatePaths(); - dynamics.addAgent(0, 0, 0); + dynamics.addAgent(0, 1, 0); WHEN("We evolve the dynamics with reinsertion") { dynamics.evolve(true); dynamics.evolve(true); THEN("The agent has correct values") { - CHECK_EQ(dynamics.agents().at(0)->time(), 2); - CHECK_EQ(dynamics.agents().at(0)->delay(), 0); + CHECK_EQ(dynamics.time() - dynamics.agents().at(0)->spawnTime(), 2); + CHECK_EQ(dynamics.agents().at(0)->freeTime(), dynamics.time()); CHECK_EQ(dynamics.agents().at(0)->streetId().value(), 1); CHECK_EQ(dynamics.agents().at(0)->speed(), 13.8888888889); CHECK_EQ(dynamics.agents().at(0)->distance(), 13.8888888889); @@ -517,8 +517,8 @@ TEST_CASE("Dynamics") { dynamics.evolve(true); THEN("The agent is reinserted") { CHECK_EQ(dynamics.nAgents(), 1); - CHECK_EQ(dynamics.agents().at(0)->time(), 1); - CHECK_EQ(dynamics.agents().at(0)->delay(), 0); + CHECK_EQ(dynamics.time() - dynamics.agents().at(0)->spawnTime(), 1); + CHECK(dynamics.agents().at(0)->freeTime() < dynamics.time()); CHECK_FALSE(dynamics.agents().at(0)->streetId().has_value()); CHECK_EQ(dynamics.agents().at(0)->speed(), 0.); } @@ -638,9 +638,8 @@ TEST_CASE("Dynamics") { dynamics.setDestinationNodes({0, 2, 3, 4}); WHEN("We add agents and make the system evolve") { - Agent agent1{0, 2, 0}; - Agent agent2{1, 4, 0}; - dynamics.addAgents(agent1, agent2); + dynamics.addAgent(0, 2, 0); + dynamics.addAgent(1, 4, 0); dynamics.evolve(false); // Counter 0 THEN("The agents are not yet on the streets") { CHECK_FALSE(dynamics.agents().at(0)->streetId().has_value()); @@ -702,9 +701,8 @@ TEST_CASE("Dynamics") { dynamics.setDestinationNodes({0, 2, 3, 4}); WHEN("We add agents and make the system evolve") { - Agent agent1{0, 2, 0}; - Agent agent2{1, 4, 0}; - dynamics.addAgents(agent1, agent2); + dynamics.addAgent(0, 2, 0); + dynamics.addAgent(1, 4, 0); dynamics.evolve(false); // Counter 0 dynamics.evolve(false); // Counter 1 THEN("The agents are correctly placed") { @@ -845,8 +843,8 @@ TEST_CASE("Dynamics") { dynamics.evolve(false); dynamics.evolve(false); THEN("The agent has travelled the correct distance") { - CHECK_EQ(dynamics.agents().at(0)->time(), 2); - CHECK_EQ(dynamics.agents().at(0)->delay(), 0); + CHECK_EQ(dynamics.time() - dynamics.agents().at(0)->spawnTime(), 2); + CHECK_EQ(dynamics.agents().at(0)->freeTime(), dynamics.time()); CHECK_EQ(dynamics.agents().at(0)->streetId().value(), 1); CHECK_EQ(dynamics.agents().at(0)->speed(), 13.8888888889); CHECK_EQ(dynamics.agents().at(0)->distance(), 3.); @@ -875,8 +873,8 @@ TEST_CASE("Dynamics") { dynamics.evolve(false); #ifndef __APPLE__ THEN("The agent has travelled the correct distance") { - CHECK_EQ(dynamics.agents().at(0)->time(), 6); - CHECK_EQ(dynamics.agents().at(0)->delay(), 0); + CHECK_EQ(dynamics.time() - dynamics.agents().at(0)->spawnTime(), 6); + CHECK_EQ(dynamics.agents().at(0)->freeTime(), dynamics.time()); CHECK_EQ(dynamics.agents().at(0)->streetId().value(), 5); CHECK_EQ(dynamics.agents().at(0)->speed(), 13.8888888889); CHECK_EQ(dynamics.agents().at(0)->distance(), 4.); @@ -885,8 +883,8 @@ TEST_CASE("Dynamics") { dynamics.evolve(false); dynamics.evolve(false); THEN("The agent has travelled the correct distance") { - CHECK_EQ(dynamics.agents().at(0)->time(), 8); - CHECK_EQ(dynamics.agents().at(0)->delay(), 0); + CHECK_EQ(dynamics.time() - dynamics.agents().at(0)->spawnTime(), 8); + CHECK_EQ(dynamics.agents().at(0)->freeTime(), dynamics.time()); CHECK_EQ(dynamics.agents().at(0)->streetId().value(), 5); CHECK_EQ(dynamics.agents().at(0)->speed(), 13.8888888889); CHECK_EQ(dynamics.agents().at(0)->distance(), 4.); diff --git a/test/Test_street.cpp b/test/Test_street.cpp index 1135c4733..01dee26b9 100644 --- a/test/Test_street.cpp +++ b/test/Test_street.cpp @@ -9,7 +9,7 @@ #include "doctest.h" -using Agent = dsm::Agent; +using Agent = dsm::Agent; using Intersection = dsm::Intersection; using Street = dsm::Street; using Road = dsm::Road; @@ -76,10 +76,10 @@ TEST_CASE("Street") { /*This tests the insertion of an agent in a street's queue*/ // define some agents - Agent a1{1, 1, 0}; // they are all in street 1 - Agent a2{2, 1, 0}; - Agent a3{3, 1, 0}; - Agent a4{4, 1, 0}; + Agent a1{0, 1, 1, 0}; // they are all in street 1 + Agent a2{0, 2, 1, 0}; + Agent a3{0, 3, 1, 0}; + Agent a4{0, 4, 1, 0}; Street street{1, std::make_pair(0, 1), 3.5}; // fill the queue @@ -104,10 +104,10 @@ TEST_CASE("Street") { /*This tests the exit of an agent from a street's queue*/ // define some agents - Agent a1{1, 1, 0}; // they are all in street 1 - Agent a2{2, 1, 0}; - Agent a3{3, 1, 0}; - Agent a4{4, 1, 0}; + Agent a1{0, 1, 1, 0}; // they are all in street 1 + Agent a2{0, 2, 1, 0}; + Agent a3{0, 3, 1, 0}; + Agent a4{0, 4, 1, 0}; Street street{1, std::make_pair(0, 1), 3.5}; // fill the queue