diff --git a/benchmark/Dynamics/BenchDynamics.cpp b/benchmark/Dynamics/BenchDynamics.cpp index 432a64348..0bb870364 100644 --- a/benchmark/Dynamics/BenchDynamics.cpp +++ b/benchmark/Dynamics/BenchDynamics.cpp @@ -18,10 +18,10 @@ int main() { street->setMaxSpeed(13.9); } - Itinerary it1{0, 118}; - Itinerary it2{4, 115}; - Itinerary it3{8, 112}; - Itinerary it4{12, 109}; + Itinerary it1{118}; + Itinerary it2{115}; + Itinerary it3{112}; + Itinerary it4{109}; Dynamics dynamics{graph}; dynamics.addItinerary(it1); diff --git a/examples/stalingrado.cpp b/examples/stalingrado.cpp index 36e181158..e99c2f5a2 100644 --- a/examples/stalingrado.cpp +++ b/examples/stalingrado.cpp @@ -87,7 +87,7 @@ int main() { dynamics.setSeed(69); dynamics.setMinSpeedRateo(0.95); dynamics.setSpeedFluctuationSTD(0.2); - Itinerary itinerary{0, 4}; + Itinerary itinerary{4}; dynamics.addItinerary(itinerary); dynamics.updatePaths(); @@ -113,7 +113,7 @@ int main() { if (progress % 300 == 0) { ofs << progress << ";" << spire.outputCounts(true) << std::endl; } - dynamics.addAgents(0, *it / 2, 0); + dynamics.addAgents(itinerary.destination(), *it / 2, 0); } dynamics.evolve(false); ++progress; diff --git a/profiling/main.cpp b/profiling/main.cpp index b7c027ef6..9ac7b5c38 100644 --- a/profiling/main.cpp +++ b/profiling/main.cpp @@ -29,10 +29,10 @@ int main() { } std::cout << "Done.\n"; - Itinerary it1{0, 118}; - Itinerary it2{1, 115}; - Itinerary it3{2, 112}; - Itinerary it4{3, 109}; + Itinerary it1{118}; + Itinerary it2{115}; + Itinerary it3{112}; + Itinerary it4{109}; std::cout << "Creating dynamics...\n"; diff --git a/src/dsm/headers/Dynamics.hpp b/src/dsm/headers/Dynamics.hpp index 015631bce..fd04b151e 100644 --- a/src/dsm/headers/Dynamics.hpp +++ b/src/dsm/headers/Dynamics.hpp @@ -35,6 +35,11 @@ namespace dsm { using TimePoint = long long unsigned int; + template + std::unique_ptr clone(const std::unique_ptr& ptr) { + return std::make_unique(*ptr); + } + /// @brief The Measurement struct represents the mean of a quantity and its standard deviation /// @tparam T The type of the quantity /// @param mean The mean @@ -67,7 +72,7 @@ namespace dsm { requires(is_numeric_v) class Dynamics { protected: - std::unordered_map> m_itineraries; + std::vector> m_itineraries; std::map>> m_agents; TimePoint m_time, m_previousSpireTime; Graph m_graph; @@ -154,9 +159,8 @@ namespace dsm { } if (path.size() == 0) { throw std::runtime_error( - buildLog(std::format("Path with id {} and destination {} is empty. Please " + buildLog(std::format("Path destination {} is empty. Please " "check the adjacency matrix.", - pItinerary->id(), pItinerary->destination()))); } pItinerary->setPath(path); @@ -190,8 +194,7 @@ namespace dsm { /// @param destinationNodes The destination nodes /// @param updatePaths If true, the paths are updated /// @throws std::invalid_argument Ifone or more destination nodes do not exist - void setDestinationNodes(const std::span& destinationNodes, - bool updatePaths = true); + void setDestinationNodes(std::span destinationNodes, bool updatePaths = true); /// @brief Set the speed of an agent /// @details This is a pure-virtual function, it must be implemented in the derived classes /// @param agentId The id of the agent @@ -232,9 +235,11 @@ namespace dsm { /// @brief Get the graph /// @return const Graph&, The graph const Graph& graph() const { return m_graph; }; + + const Itinerary* itinerary(Id destination) const; /// @brief Get the itineraries /// @return const std::unordered_map&, The itineraries - const std::unordered_map>& itineraries() const { + const std::vector>& itineraries() const { return m_itineraries; } /// @brief Get the agents @@ -414,9 +419,12 @@ namespace dsm { requires(is_numeric_v) Id Dynamics::m_nextStreetId(Id agentId, Id nodeId, std::optional streetId) { auto possibleMoves = m_graph.adjMatrix().getRow(nodeId, true); - if (this->m_itineraries.size() > 0 && + if (!this->m_itineraries.empty() && this->m_uniformDist(this->m_generator) > this->m_errorProbability) { - const auto& it = this->m_itineraries[this->m_agents[agentId]->itineraryId()]; + const auto& it = + *std::ranges::find_if(m_itineraries, [this, agentId](const auto& ptr) { + return ptr->destination() == m_agents[agentId]->itineraryId(); + }); if (it->destination() != nodeId) { possibleMoves = it->path().getRow(nodeId, true); } @@ -492,7 +500,9 @@ namespace dsm { } } if (destinationNode->id() == - m_itineraries[m_agents[agentId]->itineraryId()]->destination()) { + (*std::ranges::find_if(m_itineraries, [this, agentId](const auto& ptr) { + return m_agents[agentId]->itineraryId() == ptr->destination(); + }))->destination()) { pStreet->dequeue(queueIndex); m_travelTimes.push_back(m_agents[agentId]->time()); if (reinsert_agents) { @@ -600,8 +610,10 @@ namespace dsm { agent->decrementDelay(); if (agent->delay() == 0) { auto const nLanes = street->nLanes(); - if (this->m_itineraries[agent->itineraryId()]->destination() == - street->nodePair().second) { + + if ((*std::ranges::find_if(m_itineraries, [&agent](const auto& ptr) { + return ptr->destination() == agent->itineraryId(); + }))->destination() == street->nodePair().second) { std::uniform_int_distribution laneDist{ 0, static_cast(nLanes - 1)}; street->enqueue(agentId, laneDist(m_generator)); @@ -662,9 +674,10 @@ namespace dsm { template requires(is_numeric_v) void Dynamics::setItineraries(std::span itineraries) { - std::ranges::for_each(itineraries, [this](const auto& itinerary) { - this->m_itineraries.insert(std::make_unique(itinerary)); - }); + std::transform(itineraries.begin(), + itineraries.end(), + m_itineraries.begin(), + [this](const auto& pItinerary) { return clone(pItinerary); }); } template @@ -700,27 +713,42 @@ namespace dsm { template requires(is_numeric_v) - void Dynamics::setDestinationNodes(const std::span& destinationNodes, + void Dynamics::setDestinationNodes(std::span destinationNodes, bool updatePaths) { - for (const auto& nodeId : destinationNodes) { - if (!m_graph.nodeSet().contains(nodeId)) { - throw std::invalid_argument( - buildLog(std::format("Node with id {} not found", nodeId))); - } - this->addItinerary(Itinerary{nodeId, nodeId}); - } + m_itineraries.resize(destinationNodes.size()); + std::transform(destinationNodes.begin(), + destinationNodes.end(), + m_itineraries.begin(), + [this](auto nodeId) { + if (!this->m_graph.nodeSet().contains(nodeId)) { + throw std::invalid_argument( + buildLog(std::format("Node with id {} not found", nodeId))); + } + return std::make_unique(nodeId); + }); if (updatePaths) { this->updatePaths(); } } + template + requires(is_numeric_v) + const Itinerary* Dynamics::itinerary(Id destination) const { + auto foundIt = std::find_if(m_itineraries.begin(), + m_itineraries.end(), + [destination](const auto& pItinerary) { + return pItinerary->destination() == destination; + }); + return (foundIt == m_itineraries.end()) ? nullptr : (*foundIt).get(); + } + template requires(is_numeric_v) void Dynamics::updatePaths() { std::vector threads; threads.reserve(m_itineraries.size()); std::exception_ptr pThreadException; - for (const auto& [itineraryId, itinerary] : m_itineraries) { + for (const auto& itinerary : m_itineraries) { threads.emplace_back(std::thread([this, &itinerary, &pThreadException] { try { this->m_updatePath(itinerary); @@ -755,7 +783,7 @@ namespace dsm { } // Move transport capacity agents from each node for (const auto& [nodeId, pNode] : m_graph.nodeSet()) { - for (auto i = 0; i < pNode->transportCapacity(); ++i) { + for (auto i = 0u; i < pNode->transportCapacity(); ++i) { if (!this->m_evolveNode(pNode)) { break; } @@ -936,29 +964,30 @@ namespace dsm { } template requires(is_numeric_v) - void Dynamics::addAgent(Id srcNodeId, Id itineraryId) { + void Dynamics::addAgent(Id srcNodeId, Id dstNodeId) { if (this->m_agents.size() + 1 > this->m_graph.maxCapacity()) { throw std::overflow_error(buildLog( std::format("Graph its already holding the max possible number of agents ({})", this->m_graph.maxCapacity()))); } - if (!(srcNodeId < this->m_graph.nodeSet().size())) { - throw std::invalid_argument( - buildLog(std::format("Node with id {} not found", srcNodeId))); - } - if (!(this->m_itineraries.contains(itineraryId))) { - throw std::invalid_argument( - buildLog(std::format("Itinerary with id {} not found", itineraryId))); - } + assert((void("Nodes indexes out of range."), + srcNodeId < this->m_graph.nodeSet().size() && + dstNodeId < this->m_graph.nodeSet().size())); + assert((void("No itineray associated with the destination node."), + std::find_if(m_itineraries.begin(), + m_itineraries.end(), + [dstNodeId](const std::unique_ptr& itinerary) { + return itinerary->destination() == dstNodeId; + }) != m_itineraries.end())); Size agentId{0}; if (!this->m_agents.empty()) { agentId = this->m_agents.rbegin()->first + 1; } - this->addAgent(Agent{agentId, itineraryId, srcNodeId}); + this->addAgent(Agent{agentId, dstNodeId, srcNodeId}); } template requires(is_numeric_v) - void Dynamics::addAgents(Id itineraryId, + void Dynamics::addAgents(Id dstNodeId, Size nAgents, std::optional srcNodeId) { if (this->m_agents.size() + nAgents > this->m_graph.maxCapacity()) { @@ -966,17 +995,18 @@ namespace dsm { std::format("Graph its already holding the max possible number of agents ({})", this->m_graph.maxCapacity()))); } - auto itineraryIt{m_itineraries.find(itineraryId)}; - if (itineraryIt == m_itineraries.end()) { - throw std::invalid_argument( - buildLog(std::format("Itinerary with id {} not found", itineraryId))); - } + assert((void("No itineray associated with the destination node."), + std::find_if(m_itineraries.begin(), + m_itineraries.end(), + [dstNodeId](const std::unique_ptr& itinerary) { + return itinerary->destination() == dstNodeId; + }) != m_itineraries.end())); Size agentId{0}; if (!this->m_agents.empty()) { agentId = this->m_agents.rbegin()->first + 1; } for (Size i{0}; i < nAgents; ++i, ++agentId) { - this->addAgent(Agent{agentId, itineraryId}); + this->addAgent(Agent{agentId, dstNodeId}); if (srcNodeId.has_value()) { this->m_agents[agentId]->setSourceNodeId(srcNodeId.value()); } @@ -1031,9 +1061,8 @@ namespace dsm { 0, static_cast(this->m_graph.streetSet().size() - 1)}; for (Size i{0}; i < nAgents; ++i) { if (randomItinerary) { - auto itineraryIt{this->m_itineraries.begin()}; - std::advance(itineraryIt, itineraryDist(this->m_generator)); - itineraryId = itineraryIt->first; + auto randomItinerary = itineraryDist(this->m_generator); + itineraryId = m_itineraries[randomItinerary]->destination(); } Id agentId{0}; if (!this->m_agents.empty()) { @@ -1110,16 +1139,13 @@ namespace dsm { } } } - // find the itinerary with the given destination as destination - auto itineraryIt{std::find_if( - m_itineraries.begin(), m_itineraries.end(), [dstId](const auto& itinerary) { - return itinerary.second->destination() == dstId; - })}; - if (itineraryIt == m_itineraries.end()) { - throw std::invalid_argument( - buildLog(std::format("Itinerary with destination {} not found.", dstId))); - } - this->addAgent(srcId, itineraryIt->first); + assert((void("No itineray associated with the destination node."), + std::find_if(m_itineraries.begin(), + m_itineraries.end(), + [dstId](const std::unique_ptr& itinerary) { + return itinerary->destination() == dstId; + }) != m_itineraries.end())); + this->addAgent(srcId, dstId); --nAgents; } } @@ -1142,13 +1168,13 @@ namespace dsm { template requires(is_numeric_v) void Dynamics::addItinerary(const Itinerary& itinerary) { - m_itineraries.emplace(itinerary.id(), std::make_unique(itinerary)); + m_itineraries.push_back(std::make_unique(itinerary)); } template requires(is_numeric_v) void Dynamics::addItinerary(std::unique_ptr itinerary) { - m_itineraries.emplace(itinerary->id(), std::move(itinerary)); + m_itineraries.push_back(std::move(itinerary)); } template @@ -1163,7 +1189,7 @@ namespace dsm { requires(is_numeric_v) void Dynamics::addItineraries(std::span itineraries) { std::ranges::for_each(itineraries, [this](const auto& itinerary) -> void { - this->m_itineraries.insert(std::make_unique(itinerary)); + this->m_itineraries.push_back(std::make_unique(itinerary)); }); } diff --git a/src/dsm/headers/Itinerary.cpp b/src/dsm/headers/Itinerary.cpp index 11496b04e..ed4d22e5b 100644 --- a/src/dsm/headers/Itinerary.cpp +++ b/src/dsm/headers/Itinerary.cpp @@ -2,15 +2,10 @@ #include "Itinerary.hpp" namespace dsm { - Itinerary::Itinerary(Id id, Id destination) : m_id{id}, m_destination{destination} {} + Itinerary::Itinerary(Id destination) : m_destination{destination} {} - Itinerary::Itinerary(Id id, Id destination, SparseMatrix path) - : m_id{id}, m_path{std::move(path)}, m_destination{destination} {} - - void Itinerary::setDestination(Id destination) { - m_destination = destination; - this->m_path.clear(); - } + Itinerary::Itinerary(Id destination, SparseMatrix path) + : m_path{std::move(path)}, m_destination{destination} {} void Itinerary::setPath(SparseMatrix path) { if (path.getRowDim() != path.getColDim()) { diff --git a/src/dsm/headers/Itinerary.hpp b/src/dsm/headers/Itinerary.hpp index 754218be3..72f173521 100644 --- a/src/dsm/headers/Itinerary.hpp +++ b/src/dsm/headers/Itinerary.hpp @@ -21,30 +21,23 @@ namespace dsm { /// @tparam Id The type of the itinerary's id. It must be an unsigned integral type. class Itinerary { private: - Id m_id; SparseMatrix m_path; Id m_destination; public: /// @brief Construct a new Itinerary object /// @param destination The itinerary's destination - Itinerary(Id id, Id destination); + Itinerary(Id destination); /// @brief Construct a new Itinerary object /// @param destination The itinerary's destination /// @param path An adjacency matrix made by a SparseMatrix representing the itinerary's path - Itinerary(Id id, Id destination, SparseMatrix path); + Itinerary(Id destination, SparseMatrix path); - /// @brief Set the itinerary's destination - /// @param destination The itinerary's destination - void setDestination(Id destination); /// @brief Set the itinerary's path /// @param path An adjacency matrix made by a SparseMatrix representing the itinerary's path /// @throw std::invalid_argument, if the itinerary's source or destination is not in the path's void setPath(SparseMatrix path); - /// @brief Get the itinerary's id - /// @return Id, The itinerary's id - Id id() const { return m_id; } /// @brief Get the itinerary's destination /// @return Id, The itinerary's destination Id destination() const { return m_destination; } diff --git a/test/Test_dynamics.cpp b/test/Test_dynamics.cpp index a2247e29c..a46865d5b 100644 --- a/test/Test_dynamics.cpp +++ b/test/Test_dynamics.cpp @@ -123,7 +123,7 @@ TEST_CASE("Dynamics") { auto graph = Graph{}; graph.importMatrix("./data/matrix.dsm"); Dynamics dynamics{graph}; - dynamics.addItinerary(Itinerary{2, 2}); + dynamics.addItinerary(Itinerary{2}); WHEN("We add the agent") { dynamics.addAgent(0, 2); THEN("The agent is added") { @@ -134,16 +134,6 @@ TEST_CASE("Dynamics") { CHECK_EQ(agent->itineraryId(), 2); } } - WHEN("We try to add an agent with a non-existing source node") { - THEN("An exception is thrown") { - CHECK_THROWS_AS(dynamics.addAgent(3, 2), std::invalid_argument); - } - } - WHEN("We try to add an agent with a non-existing itinerary") { - THEN("An exception is thrown") { - CHECK_THROWS_AS(dynamics.addAgent(0, 0), std::invalid_argument); - } - } } } SUBCASE("addAgentsUniformly") { @@ -151,12 +141,7 @@ TEST_CASE("Dynamics") { auto graph = Graph{}; graph.importMatrix("./data/matrix.dsm"); Dynamics dynamics(graph); - WHEN("We add agents without adding itineraries") { - THEN("An exception is thrown") { - CHECK_THROWS_AS(dynamics.addAgentsUniformly(1), std::invalid_argument); - } - } - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; WHEN("We add a random agent") { dynamics.addItinerary(itinerary); dynamics.addAgentsUniformly(1); @@ -164,10 +149,9 @@ TEST_CASE("Dynamics") { "The number of agents is 1 and the destination is the same as the " "itinerary") { CHECK_EQ(dynamics.agents().size(), 1); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(0)->itineraryId()) - ->destination(), - itinerary.destination()); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(0)->itineraryId())->destination(), + itinerary.destination()); } } } @@ -176,7 +160,7 @@ TEST_CASE("Dynamics") { graph.importMatrix("./data/matrix.dsm"); Dynamics dynamics(graph); dynamics.setSeed(69); - Itinerary Itinerary1{0, 2}, Itinerary2{1, 1}; + Itinerary Itinerary1{2}, Itinerary2{1}; dynamics.addItinerary(Itinerary1); dynamics.addItinerary(Itinerary2); WHEN("We add many agents") { @@ -186,22 +170,19 @@ TEST_CASE("Dynamics") { "same as " "the itinerary") { CHECK_EQ(dynamics.agents().size(), 3); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(0)->itineraryId()) - ->destination(), - Itinerary1.destination()); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(0)->itineraryId())->destination(), + Itinerary2.destination()); CHECK(dynamics.agents().at(0)->streetId().has_value()); CHECK_EQ(dynamics.agents().at(0)->streetId().value(), 3); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(1)->itineraryId()) - ->destination(), - Itinerary1.destination()); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(1)->itineraryId())->destination(), + Itinerary2.destination()); CHECK(dynamics.agents().at(1)->streetId().has_value()); CHECK_EQ(dynamics.agents().at(1)->streetId().value(), 8); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(2)->itineraryId()) - ->destination(), - Itinerary2.destination()); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(2)->itineraryId())->destination(), + Itinerary1.destination()); CHECK(dynamics.agents().at(2)->streetId().has_value()); CHECK_EQ(dynamics.agents().at(2)->streetId().value(), 1); } @@ -217,50 +198,39 @@ TEST_CASE("Dynamics") { WHEN("We add one agent for existing itinerary") { std::unordered_map src{{0, 1.}}; std::unordered_map dst{{2, 1.}}; - dynamics.addItinerary(Itinerary{0, 2}); + dynamics.addItinerary(Itinerary{2}); dynamics.addAgentsRandomly(1, src, dst); THEN("The agents are correctly set") { CHECK_EQ(dynamics.agents().size(), 1); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(0)->itineraryId()) - ->destination(), - 2); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(0)->itineraryId())->destination(), + 2); CHECK_EQ(dynamics.agents().at(0)->srcNodeId().value(), 0); } } WHEN("We add agents for existing itineraries") { std::unordered_map src{{1, 0.3}, {27, 0.3}, {118, 0.4}}; std::unordered_map dst{{14, 0.3}, {102, 0.3}, {107, 0.4}}; - dynamics.addItinerary(Itinerary{0, 14}); - dynamics.addItinerary(Itinerary{1, 102}); - dynamics.addItinerary(Itinerary{2, 107}); + dynamics.addItinerary(Itinerary{14}); + dynamics.addItinerary(Itinerary{102}); + dynamics.addItinerary(Itinerary{107}); dynamics.addAgentsRandomly(3, src, dst); THEN("The agents are correctly set") { CHECK_EQ(dynamics.agents().size(), 3); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(0)->itineraryId()) - ->destination(), - 107); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(0)->itineraryId())->destination(), + 107); CHECK_EQ(dynamics.agents().at(0)->srcNodeId().value(), 27); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(1)->itineraryId()) - ->destination(), - 14); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(1)->itineraryId())->destination(), + 14); CHECK_EQ(dynamics.agents().at(1)->srcNodeId().value(), 1); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(2)->itineraryId()) - ->destination(), - 14); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(2)->itineraryId())->destination(), + 14); CHECK_EQ(dynamics.agents().at(2)->srcNodeId().value(), 118); } } - WHEN("We add agents without adding itineraries") { - THEN("An exception is thrown") { - std::unordered_map src{{0, 1.}}; - std::unordered_map dst{{10, 1.}}; - CHECK_THROWS_AS(dynamics.addAgentsRandomly(1, src, dst), std::invalid_argument); - } - } } } SUBCASE("addAgents") { @@ -268,27 +238,21 @@ TEST_CASE("Dynamics") { auto graph = Graph{}; graph.importMatrix("./data/matrix.dsm"); Dynamics dynamics{graph}; - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; dynamics.addItinerary(itinerary); - WHEN("We add an agent with itinerary 1") { - THEN("An exception is thrown") { - CHECK_THROWS_AS(dynamics.addAgents(1), std::invalid_argument); - } - } - WHEN("We add and agent with itinerary 0") { - dynamics.addAgents(0); + WHEN("We add and agent with itinerary 2") { + dynamics.addAgents(2); THEN( "The number of agents is 1 and the destination is the same as the " "itinerary") { CHECK_EQ(dynamics.agents().size(), 1); - CHECK_EQ(dynamics.itineraries() - .at(dynamics.agents().at(0)->itineraryId()) - ->destination(), - itinerary.destination()); + CHECK_EQ( + dynamics.itinerary(dynamics.agents().at(0)->itineraryId())->destination(), + itinerary.destination()); } } - WHEN("We add 69 agents with itinerary 0") { - dynamics.addAgents(0, 69); + WHEN("We add 69 agents with itinerary 2") { + dynamics.addAgents(2, 69); THEN("The number of agents is 69") { CHECK_EQ(dynamics.agents().size(), 69); } } } @@ -300,8 +264,7 @@ TEST_CASE("Dynamics") { graph2.addStreets(s); graph2.buildAdj(); Dynamics dynamics{graph2}; - Itinerary itinerary{0, 1}; - dynamics.addItinerary(itinerary); + dynamics.addItinerary(Itinerary{1}); dynamics.updatePaths(); dynamics.addAgentsUniformly(1); WHEN("We add more than one agent") { @@ -324,8 +287,7 @@ TEST_CASE("Dynamics") { graph2.buildAdj(); Dynamics dynamics{graph2}; WHEN("We add a topologically impossible itinerary") { - Itinerary itinerary{0, 0}; - dynamics.addItinerary(itinerary); + dynamics.addItinerary(Itinerary{0}); THEN("When updating paths, empty itinerary throws exception") { CHECK_THROWS_AS(dynamics.updatePaths(), std::runtime_error); } @@ -339,7 +301,7 @@ TEST_CASE("Dynamics") { graph2.addStreets(s1, s2, s3); graph2.buildAdj(); Dynamics dynamics{graph2}; - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; WHEN("We add an itinerary and update the paths") { dynamics.addItinerary(itinerary); dynamics.updatePaths(); @@ -351,10 +313,10 @@ TEST_CASE("Dynamics") { CHECK(dynamics.itineraries().at(0)->path()(0, 1)); CHECK(dynamics.itineraries().at(0)->path()(1, 2)); CHECK_FALSE(dynamics.itineraries().at(0)->path()(0, 2)); - for (auto const& it : dynamics.itineraries()) { - auto const& path = it.second->path(); + for (auto const& itinerary : dynamics.itineraries()) { + auto const& path = itinerary->path(); for (uint16_t i{0}; i < path.getRowDim(); ++i) { - if (i == it.second->destination()) { + if (i == itinerary->destination()) { CHECK_FALSE(path.getRow(i).size()); } else { CHECK(path.getRow(i).size()); @@ -364,32 +326,6 @@ TEST_CASE("Dynamics") { } } } - GIVEN( - "A dynamics objects, many streets and many itinearies with same " - "destination") { - Graph graph2{}; - graph2.importMatrix("./data/matrix.dat"); - Itinerary it1{0, 118}; - Itinerary it2{1, 118}; - Itinerary it3{2, 118}; - Itinerary it4{3, 118}; - Dynamics dynamics{graph2}; - dynamics.addItinerary(it1); - dynamics.addItinerary(it2); - dynamics.addItinerary(it3); - dynamics.addItinerary(it4); - dynamics.updatePaths(); - for (auto const& it : dynamics.itineraries()) { - auto const& path = it.second->path(); - for (uint16_t i{0}; i < path.getRowDim(); ++i) { - if (i == it.second->destination()) { - CHECK_FALSE(path.getRow(i).size()); - } else { - CHECK(path.getRow(i).size()); - } - } - } - } GIVEN("A dynamics objects, many streets and an itinerary with bifurcations") { Street s1{0, 1, 5., std::make_pair(0, 1)}; Street s2{1, 1, 5., std::make_pair(1, 2)}; @@ -399,8 +335,7 @@ TEST_CASE("Dynamics") { graph.addStreets(s1, s2, s3, s4); graph.buildAdj(); Dynamics dynamics{graph}; - Itinerary itinerary{0, 2}; - dynamics.addItinerary(itinerary); + dynamics.addItinerary(Itinerary{2}); WHEN("We update the paths") { dynamics.updatePaths(); THEN("The path is updated and correctly formed") { @@ -412,10 +347,10 @@ TEST_CASE("Dynamics") { CHECK(dynamics.itineraries().at(0)->path()(1, 2)); CHECK(dynamics.itineraries().at(0)->path()(0, 3)); CHECK(dynamics.itineraries().at(0)->path()(3, 2)); - for (auto const& it : dynamics.itineraries()) { - auto const& path = it.second->path(); + for (auto const& itinerary : dynamics.itineraries()) { + auto const& path = itinerary->path(); for (uint16_t i{0}; i < path.getRowDim(); ++i) { - if (i == it.second->destination()) { + if (i == itinerary->destination()) { CHECK_FALSE(path.getRow(i).size()); } else { CHECK(path.getRow(i).size()); @@ -436,7 +371,7 @@ TEST_CASE("Dynamics") { graph.buildAdj(); Dynamics dynamics{graph}; dynamics.setSeed(69); - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; dynamics.addItinerary(itinerary); dynamics.updatePaths(); WHEN("We add an agent randomly and evolve the dynamics") { @@ -471,8 +406,7 @@ TEST_CASE("Dynamics") { graph2.buildAdj(); Dynamics dynamics{graph2}; dynamics.setSeed(69); - Itinerary itinerary{0, 1}; - dynamics.addItinerary(itinerary); + dynamics.addItinerary(Itinerary{1}); dynamics.updatePaths(); dynamics.addAgent(Agent(0, 0, 0)); WHEN("We evolve the dynamics") { @@ -499,8 +433,7 @@ TEST_CASE("Dynamics") { graph2.buildAdj(); Dynamics dynamics{graph2}; dynamics.setSeed(69); - Itinerary itinerary{0, 1}; - dynamics.addItinerary(itinerary); + dynamics.addItinerary(Itinerary{1}); dynamics.updatePaths(); dynamics.addAgent(Agent(0, 0, 0)); WHEN("We evolve the dynamics with reinsertion") { @@ -542,7 +475,7 @@ TEST_CASE("Dynamics") { graph2.buildAdj(); Dynamics dynamics{graph2}; dynamics.setSeed(69); - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; dynamics.addItinerary(itinerary); dynamics.updatePaths(); dynamics.addAgent(Agent(0, 0, 0)); @@ -718,12 +651,8 @@ TEST_CASE("Dynamics") { tl.addStreetPriority(1); tl.addStreetPriority(11); Dynamics dynamics{graph2}; - Itinerary it_0{0, 0}, it_1{1, 2}, it_2{2, 3}, it_3{3, 4}; - dynamics.addItinerary(it_0); - dynamics.addItinerary(it_1); - dynamics.addItinerary(it_2); - dynamics.addItinerary(it_3); - dynamics.updatePaths(); + std::array destinationNodes{0, 2, 3, 4}; + dynamics.setDestinationNodes(destinationNodes); dynamics.addAgents(0, 7, 2); dynamics.addAgents(1, 7, 0); dynamics.setDataUpdatePeriod(1); @@ -772,8 +701,8 @@ TEST_CASE("Dynamics") { graph2.adjustNodeCapacities(); Dynamics dynamics{graph2}; dynamics.setSeed(69); - Itinerary itinerary{0, 2}; - Itinerary itinerary2{1, 0}; + Itinerary itinerary{2}; + Itinerary itinerary2{0}; dynamics.addItinerary(itinerary); dynamics.addItinerary(itinerary2); dynamics.updatePaths(); @@ -811,7 +740,7 @@ TEST_CASE("Dynamics") { graph2.buildAdj(); Dynamics dynamics{graph2}; dynamics.setSeed(69); - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; dynamics.addItinerary(itinerary); dynamics.updatePaths(); dynamics.addAgent(Agent(0, 0, 0)); @@ -846,7 +775,7 @@ TEST_CASE("Dynamics") { Dynamics dynamics{graph2}; dynamics.setMinSpeedRateo(0.5); dynamics.setSeed(69); - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; dynamics.addItinerary(itinerary); dynamics.updatePaths(); dynamics.addAgents(0, 4, 0); @@ -914,8 +843,8 @@ TEST_CASE("Dynamics") { Dynamics dynamics{graph2}; dynamics.graph().nodeSet().at(0)->setCapacity(3); dynamics.setSeed(69); - Itinerary itinerary{0, 2}; - Itinerary itinerary2{1, 1}; + Itinerary itinerary{2}; + Itinerary itinerary2{1}; dynamics.addItinerary(itinerary); dynamics.addItinerary(itinerary2); dynamics.updatePaths(); @@ -977,7 +906,7 @@ TEST_CASE("Dynamics") { graph2.makeSpireStreet(1); Dynamics dynamics{graph2}; dynamics.setSeed(69); - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; dynamics.addItinerary(itinerary); dynamics.updatePaths(); dynamics.addAgent(Agent(0, 0, 0)); @@ -1010,7 +939,7 @@ TEST_CASE("Dynamics") { graph2.makeSpireStreet(1); Dynamics dynamics{graph2}; dynamics.setSeed(69); - Itinerary itinerary{0, 2}; + Itinerary itinerary{2}; dynamics.addItinerary(itinerary); dynamics.updatePaths(); dynamics.addAgent(Agent(0, 0, 0)); diff --git a/test/Test_itinerary.cpp b/test/Test_itinerary.cpp index 149b39bff..9bd61e7c7 100644 --- a/test/Test_itinerary.cpp +++ b/test/Test_itinerary.cpp @@ -9,24 +9,20 @@ using Itinerary = dsm::Itinerary; TEST_CASE("Itinerary") { SUBCASE("Constructors") { GIVEN("An itinerary and its destination ids") { - uint8_t itineraryId{0}; uint8_t destinationId{2}; WHEN("The Itinerary is constructed") { - Itinerary itinerary{itineraryId, destinationId}; - THEN("The source and destination are set correctly") { - CHECK_EQ(itinerary.id(), itineraryId); + Itinerary itinerary{destinationId}; + THEN("The destination is set correctly") { CHECK_EQ(itinerary.destination(), destinationId); } } } GIVEN("An itinerary id, its destination id and a transition matrix") { - uint8_t itineraryId{0}; uint8_t destinationId{2}; dsm::SparseMatrix path{1, 1}; WHEN("The Itinerary is constructed") { - Itinerary itinerary{itineraryId, destinationId, path}; - THEN("The source, destination, and path are set correctly") { - CHECK_EQ(itinerary.id(), itineraryId); + Itinerary itinerary{destinationId, path}; + THEN("The destination and path are set correctly") { CHECK_EQ(itinerary.destination(), destinationId); CHECK_EQ(itinerary.path().getRowDim(), 1); CHECK_EQ(itinerary.path().getColDim(), 1); @@ -34,22 +30,4 @@ TEST_CASE("Itinerary") { } } } - SUBCASE("Set destination") { - GIVEN("An itinerary id, its destination id and a transition matrix") { - uint8_t itineraryId{0}; - uint8_t destinationId{2}; - dsm::SparseMatrix path{1, 1}; - Itinerary itinerary{itineraryId, destinationId, path}; - WHEN("The destination is set") { - uint8_t newDestinationId{3}; - itinerary.setDestination(newDestinationId); - THEN("The destination is set correctly and the path is cleared") { - CHECK_EQ(itinerary.destination(), newDestinationId); - CHECK_EQ(itinerary.path().getRowDim(), 0); - CHECK_EQ(itinerary.path().getColDim(), 0); - CHECK_EQ(itinerary.path().size(), 0); - } - } - } - } }