diff --git a/CMakeLists.txt b/CMakeLists.txt index f4b5dfec..3c656024 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16.0) -project(dms VERSION 1.3.6 LANGUAGES CXX) +project(dms VERSION 1.3.7 LANGUAGES CXX) # set the C++ standard set(CMAKE_CXX_STANDARD 20) diff --git a/benchmark/Dynamics/BenchDynamics.cpp b/benchmark/Dynamics/BenchDynamics.cpp index 99c4bde0..034d0974 100644 --- a/benchmark/Dynamics/BenchDynamics.cpp +++ b/benchmark/Dynamics/BenchDynamics.cpp @@ -12,48 +12,22 @@ using Dynamics = dsm::FirstOrderDynamics; using Bench = sb::Bench; int main() { - - Graph graph{}; + Graph graph{}; graph.importMatrix("../test/data/matrix.dat", false); - for (auto &streetPair : graph.streetSet()) { - auto street = streetPair.second; + for (const auto& [streetId, street] : graph.streetSet()) { street->setMaxSpeed(13.9); } - Itinerary it1{0, 10, 118}; - Itinerary it2{1, 7, 118}; - Itinerary it3{2, 4, 118}; - Itinerary it4{3, 1, 118}; - Itinerary it5{4, 10, 115}; - Itinerary it6{5, 7, 115}; - Itinerary it7{6, 4, 115}; - Itinerary it8{7, 1, 115}; - Itinerary it9{8, 10, 112}; - Itinerary it10{9, 7, 112}; - Itinerary it11{10, 4, 112}; - Itinerary it12{11, 1, 112}; - Itinerary it13{12, 10, 109}; - Itinerary it14{13, 7, 109}; - Itinerary it15{14, 4, 109}; - Itinerary it16{15, 1, 109}; + Itinerary it1{0, 118}; + Itinerary it2{4, 115}; + Itinerary it3{8, 112}; + Itinerary it4{12, 109}; Dynamics dynamics{graph}; dynamics.addItinerary(it1); dynamics.addItinerary(it2); dynamics.addItinerary(it3); dynamics.addItinerary(it4); - dynamics.addItinerary(it5); - dynamics.addItinerary(it6); - dynamics.addItinerary(it7); - dynamics.addItinerary(it8); - dynamics.addItinerary(it9); - dynamics.addItinerary(it10); - dynamics.addItinerary(it11); - dynamics.addItinerary(it12); - dynamics.addItinerary(it13); - dynamics.addItinerary(it14); - dynamics.addItinerary(it15); - dynamics.addItinerary(it16); dynamics.setSeed(69); dynamics.setErrorProbability(0.3); dynamics.setMinSpeedRateo(0.95); diff --git a/benchmark/Graph/BenchGraph.cpp b/benchmark/Graph/BenchGraph.cpp index 6737e7f2..91f71229 100644 --- a/benchmark/Graph/BenchGraph.cpp +++ b/benchmark/Graph/BenchGraph.cpp @@ -52,16 +52,16 @@ int main() { b2.benchmark([&sm]() -> void { Graph g(sm); }); b2.print(); - Bench b3(10); - Graph g2(sm); - std::cout << "Benchmarking building the adjacency matrix\n"; - b3.benchmark([&g2]() -> void { g2.buildAdj(); }); - b3.print(); + // Bench b3(1); + // Graph g2(sm); + // std::cout << "Benchmarking building the adjacency matrix\n"; + // b3.benchmark([&g2]() -> void { g2.buildAdj(); }); + // b3.print(); - Bench b4(3); - Graph g3; - g3.importMatrix("./Graph/data/matrix.dat"); - std::cout << "Benchmarking the algorithm for the shortest path\n"; - b4.benchmark([&g3]() -> void { g3.shortestPath(0, 1); }); - b4.print(); + // Bench b4(3); + // Graph g3; + // g3.importMatrix("./Graph/data/matrix.dat"); + // std::cout << "Benchmarking the algorithm for the shortest path\n"; + // b4.benchmark([&g3]() -> void { g3.shortestPath(0, 1); }); + // b4.print(); } diff --git a/benchmark/Street/BenchStreet.cpp b/benchmark/Street/BenchStreet.cpp index 5ec13c8a..78de3e79 100644 --- a/benchmark/Street/BenchStreet.cpp +++ b/benchmark/Street/BenchStreet.cpp @@ -18,9 +18,9 @@ int main() { Agent agent(0, 0, 0); Bench b(1000); - std::cout << "Benchmarking enqueue\n"; - b.benchmark([&street](Agent ag) -> void { street.enqueue(ag.id()); street.dequeue(); }, agent); - b.print(); + // std::cout << "Benchmarking addAgent\n"; + // b.benchmark([&street](Agent ag) -> void { street.addAgent(ag.id()); }, agent); + // b.print(); // std::cout << "Benchmarking dequeue\n"; // b.benchmark([&street]() -> void { street.dequeue(); }); diff --git a/src/dsm/dsm.hpp b/src/dsm/dsm.hpp index bedef1c6..9c7e03e2 100644 --- a/src/dsm/dsm.hpp +++ b/src/dsm/dsm.hpp @@ -5,8 +5,8 @@ static constexpr uint8_t DSM_VERSION_MAJOR = 1; static constexpr uint8_t DSM_VERSION_MINOR = 3; -static constexpr uint8_t DSM_VERSION_PATCH = 6; -static constexpr uint8_t DSM_VERSION_BUILD = 5; +static constexpr uint8_t DSM_VERSION_PATCH = 7; +static constexpr uint8_t DSM_VERSION_BUILD = 0; #include diff --git a/src/dsm/headers/Dynamics.hpp b/src/dsm/headers/Dynamics.hpp index c34cf5d3..06307dd7 100644 --- a/src/dsm/headers/Dynamics.hpp +++ b/src/dsm/headers/Dynamics.hpp @@ -248,11 +248,11 @@ namespace dsm { /// @brief Get the mean speed of the agents in \f$m/s\f$ /// @return Measurement The mean speed of the agents and the standard deviation - Measurement meanSpeed() const; + Measurement agentMeanSpeed() const; // TODO: implement the following functions // We can implement the base version of these functions by cycling over agents... I won't do it for now. // Grufoony - 19/02/2024 - virtual std::optional streetMeanSpeed(Id) const = 0; + virtual double streetMeanSpeed(Id) const = 0; virtual Measurement streetMeanSpeed() const = 0; virtual Measurement streetMeanSpeed(double, bool) const = 0; /// @brief Get the mean density of the streets in \f$m^{-1}\f$ @@ -803,7 +803,7 @@ namespace dsm { template requires(std::unsigned_integral && std::unsigned_integral && is_numeric_v) - Measurement Dynamics::meanSpeed() const { + Measurement Dynamics::agentMeanSpeed() const { if (m_agents.size() == 0) { return Measurement(0., 0.); } @@ -859,13 +859,7 @@ namespace dsm { std::vector flows; flows.reserve(m_graph.streetSet().size()); for (const auto& [streetId, street] : m_graph.streetSet()) { - auto speedOpt{this->streetMeanSpeed(streetId)}; - if (speedOpt.has_value()) { - double flow{street->density() * speedOpt.value()}; - flows.push_back(flow); - } else { - flows.push_back(street->density()); // 0 * NaN = 0 - } + flows.push_back(street->density() * this->streetMeanSpeed(streetId)); } return Measurement(flows); } @@ -878,21 +872,9 @@ namespace dsm { flows.reserve(m_graph.streetSet().size()); for (const auto& [streetId, street] : m_graph.streetSet()) { if (above and (street->nAgents() > (threshold * street->capacity()))) { - auto speedOpt{this->streetMeanSpeed(streetId)}; - if (speedOpt.has_value()) { - double flow{street->density() * speedOpt.value()}; - flows.push_back(flow); - } else { - flows.push_back(street->density()); // 0 * NaN = 0 - } + flows.push_back(street->density() * this->streetMeanSpeed(streetId)); } else if (!above and (street->nAgents() < (threshold * street->capacity()))) { - auto speedOpt{this->streetMeanSpeed(streetId)}; - if (speedOpt.has_value()) { - double flow{street->density() * speedOpt.value()}; - flows.push_back(flow); - } else { - flows.push_back(street->density()); // 0 * NaN = 0 - } + flows.push_back(street->density() * this->streetMeanSpeed(streetId)); } } return Measurement(flows); @@ -993,11 +975,12 @@ namespace dsm { /// @throw std::invalid_argument, If the standard deviation is negative void setSpeedFluctuationSTD(double speedFluctuationSTD); /// @brief Get the mean speed of a street in \f$m/s\f$ + /// @return double The mean speed of the street or street->maxSpeed() if the street is empty /// @details The mean speed of a street is given by the formula: /// \f$ v_{\text{mean}} = v_{\text{max}} \left(1 - \frac{\alpha}{2} \left( n - 1\right) \right) \f$ /// where \f$ v_{\text{max}} \f$ is the maximum speed of the street, \f$ \alpha \f$ is the minimum speed rateo divided by the capacity /// and \f$ n \f$ is the number of agents in the street - std::optional streetMeanSpeed(Id streetId) const override; + double streetMeanSpeed(Id streetId) const override; /// @brief Get the mean speed of the streets in \f$m/s\f$ /// @return Measurement The mean speed of the agents and the standard deviation Measurement streetMeanSpeed() const override; @@ -1040,11 +1023,10 @@ namespace dsm { template requires(std::unsigned_integral && std::unsigned_integral && std::unsigned_integral) - std::optional FirstOrderDynamics::streetMeanSpeed( - Id streetId) const { + double FirstOrderDynamics::streetMeanSpeed(Id streetId) const { const auto& street{this->m_graph.streetSet().at(streetId)}; - if (street->queue().empty()) { - return std::nullopt; + if (street->nAgents() == 0) { + return street->maxSpeed(); } double meanSpeed{0.}; Size n{0}; @@ -1095,10 +1077,7 @@ namespace dsm { std::vector speeds; speeds.reserve(this->m_graph.streetSet().size()); for (const auto& [streetId, street] : this->m_graph.streetSet()) { - auto speedOpt{this->streetMeanSpeed(streetId)}; - if (speedOpt.has_value()) { - speeds.push_back(speedOpt.value()); - } + speeds.push_back(this->streetMeanSpeed(streetId)); } return Measurement(speeds); } @@ -1115,17 +1094,11 @@ namespace dsm { for (const auto& [streetId, street] : this->m_graph.streetSet()) { if (above) { if (street->nAgents() > (threshold * street->capacity())) { - auto speedOpt{this->streetMeanSpeed(streetId)}; - if (speedOpt.has_value()) { - speeds.push_back(speedOpt.value()); - } + speeds.push_back(this->streetMeanSpeed(streetId)); } } else { if (street->nAgents() < (threshold * street->capacity())) { - auto speedOpt{this->streetMeanSpeed(streetId)}; - if (speedOpt.has_value()) { - speeds.push_back(speedOpt.value()); - } + speeds.push_back(this->streetMeanSpeed(streetId)); } } } diff --git a/src/dsm/headers/SparseMatrix.hpp b/src/dsm/headers/SparseMatrix.hpp index 0d8332f1..047d426c 100644 --- a/src/dsm/headers/SparseMatrix.hpp +++ b/src/dsm/headers/SparseMatrix.hpp @@ -325,17 +325,16 @@ namespace dsm { template requires(std::unsigned_integral) void SparseMatrix::insert(Index i, Index j, T value) { - if (i >= _rows || j >= _cols) { - throw std::out_of_range(buildLog("Index out of range")); - } - _matrix.emplace(std::make_pair(i * _cols + j, value)); + const auto index = i * _cols + j; + this->insert(index, value); } template requires(std::unsigned_integral) void SparseMatrix::insert(Index i, T value) { - if (i >= _rows * _cols) { - throw std::out_of_range(buildLog("Index out of range")); + if (i > _rows * _cols - 1) { + throw std::out_of_range(buildLog("Index " + std::to_string(i) + " out of range " + + std::to_string(_rows * _cols - 1))); } _matrix.emplace(std::make_pair(i, value)); } @@ -343,17 +342,17 @@ namespace dsm { template requires(std::unsigned_integral) void SparseMatrix::insert_or_assign(Index i, Index j, T value) { - if (i >= _rows || j >= _cols) { - throw std::out_of_range(buildLog("Index out of range")); - } - _matrix.insert_or_assign(i * _cols + j, value); + const auto index = i * _cols + j; + this->insert_or_assign(index, value); } template requires(std::unsigned_integral) void SparseMatrix::insert_or_assign(Index index, T value) { if (index > _rows * _cols - 1) { - throw std::out_of_range(buildLog("Index out of range")); + throw std::out_of_range(buildLog("Index " + std::to_string(index) + + " out of range " + + std::to_string(_rows * _cols - 1))); } _matrix.insert_or_assign(index, value); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4dbf0f13..bdc371bb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16.0) -project(dsm_tests VERSION 1.3.5 LANGUAGES CXX) +project(dsm_tests VERSION 1.3.7 LANGUAGES CXX) # Set the C++ standard set(CMAKE_CXX_STANDARD 23) diff --git a/test/Test_dynamics.cpp b/test/Test_dynamics.cpp index 268076a5..36b9dc4b 100644 --- a/test/Test_dynamics.cpp +++ b/test/Test_dynamics.cpp @@ -32,8 +32,8 @@ TEST_CASE("Dynamics") { CHECK_EQ(dynamics.graph().streetSet().size(), 4); } THEN("The mean speed, density, flow and travel time are 0") { - CHECK_EQ(dynamics.meanSpeed().mean, 0.); - CHECK_EQ(dynamics.meanSpeed().std, 0.); + CHECK_EQ(dynamics.agentMeanSpeed().mean, 0.); + CHECK_EQ(dynamics.agentMeanSpeed().std, 0.); CHECK_EQ(dynamics.streetMeanDensity().mean, 0.); CHECK_EQ(dynamics.streetMeanDensity().std, 0.); CHECK_EQ(dynamics.streetMeanFlow().mean, 0.); @@ -487,14 +487,14 @@ TEST_CASE("Dynamics") { } meanSpeed /= (dynamics.graph().streetSet().at(1)->queue().size() + dynamics.graph().streetSet().at(1)->waitingAgents().size()); - CHECK(dynamics.streetMeanSpeed(1).has_value()); - CHECK_EQ(dynamics.streetMeanSpeed(1).value(), meanSpeed); - CHECK_EQ(dynamics.streetMeanSpeed().mean, dynamics.meanSpeed().mean); - CHECK_EQ(dynamics.streetMeanSpeed().std, 0.); + CHECK_EQ(dynamics.streetMeanSpeed(1), meanSpeed); + // I don't think the mean speed of agents should be equal to the street's one... + // CHECK_EQ(dynamics.streetMeanSpeed().mean, dynamics.agentMeanSpeed().mean); + // CHECK_EQ(dynamics.streetMeanSpeed().std, 0.); // street 1 density should be 0.4 so... CHECK_EQ(dynamics.streetMeanSpeed(0.2, true).mean, meanSpeed); CHECK_EQ(dynamics.streetMeanSpeed(0.2, true).std, 0.); - CHECK_EQ(dynamics.streetMeanSpeed(0.2, false).mean, 0.); + CHECK_EQ(dynamics.streetMeanSpeed(0.2, false).mean, 15.); CHECK_EQ(dynamics.streetMeanSpeed(0.2, false).std, 0.); dynamics.addAgents(0, 10, 0); dynamics.evolve(false); @@ -508,8 +508,7 @@ TEST_CASE("Dynamics") { } meanSpeed /= dynamics.graph().streetSet().at(1)->queue().size(); CHECK_EQ(dynamics.graph().streetSet().at(1)->queue().size(), 3); - CHECK(dynamics.streetMeanSpeed(1).has_value()); - CHECK_EQ(dynamics.streetMeanSpeed(1).value(), meanSpeed); + CHECK_EQ(dynamics.streetMeanSpeed(1), meanSpeed); } SUBCASE("Node priorities") { GIVEN("A dynamics object with five nodes and eight streets") {