Skip to content

Commit

Permalink
Fix Dynamics::streetMeanSpeed() function (#173)
Browse files Browse the repository at this point in the history
* Fix `Dynamics::streetMeanSpeed()` function

* Rename `Dynamics::meanSpeed()` into `Dynamics::agentMeanSpeed()`

* Bugfix in SparseMatrix and disable benchmarks
  • Loading branch information
Grufoony authored Apr 26, 2024
1 parent bb2ef29 commit 827734e
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 111 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
38 changes: 6 additions & 32 deletions benchmark/Dynamics/BenchDynamics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,22 @@ using Dynamics = dsm::FirstOrderDynamics<uint32_t, uint32_t, uint32_t>;
using Bench = sb::Bench<long long int>;

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);
Expand Down
22 changes: 11 additions & 11 deletions benchmark/Graph/BenchGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,16 @@ int main() {
b2.benchmark([&sm]() -> void { Graph g(sm); });
b2.print<sb::milliseconds>();

Bench b3(10);
Graph g2(sm);
std::cout << "Benchmarking building the adjacency matrix\n";
b3.benchmark([&g2]() -> void { g2.buildAdj(); });
b3.print<sb::microseconds>();
// Bench b3(1);
// Graph g2(sm);
// std::cout << "Benchmarking building the adjacency matrix\n";
// b3.benchmark([&g2]() -> void { g2.buildAdj(); });
// b3.print<sb::microseconds>();

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<sb::microseconds>();
// 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<sb::microseconds>();
}
6 changes: 3 additions & 3 deletions benchmark/Street/BenchStreet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(); });
Expand Down
4 changes: 2 additions & 2 deletions src/dsm/dsm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <string>

Expand Down
55 changes: 14 additions & 41 deletions src/dsm/headers/Dynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,11 +248,11 @@ namespace dsm {

/// @brief Get the mean speed of the agents in \f$m/s\f$
/// @return Measurement<double> The mean speed of the agents and the standard deviation
Measurement<double> meanSpeed() const;
Measurement<double> 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<double> streetMeanSpeed(Id) const = 0;
virtual double streetMeanSpeed(Id) const = 0;
virtual Measurement<double> streetMeanSpeed() const = 0;
virtual Measurement<double> streetMeanSpeed(double, bool) const = 0;
/// @brief Get the mean density of the streets in \f$m^{-1}\f$
Expand Down Expand Up @@ -803,7 +803,7 @@ namespace dsm {
template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> &&
is_numeric_v<Delay>)
Measurement<double> Dynamics<Id, Size, Delay>::meanSpeed() const {
Measurement<double> Dynamics<Id, Size, Delay>::agentMeanSpeed() const {
if (m_agents.size() == 0) {
return Measurement(0., 0.);
}
Expand Down Expand Up @@ -859,13 +859,7 @@ namespace dsm {
std::vector<double> 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);
}
Expand All @@ -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);
Expand Down Expand Up @@ -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<double> 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<double> streetMeanSpeed() const override;
Expand Down Expand Up @@ -1040,11 +1023,10 @@ namespace dsm {
template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> &&
std::unsigned_integral<Delay>)
std::optional<double> FirstOrderDynamics<Id, Size, Delay>::streetMeanSpeed(
Id streetId) const {
double FirstOrderDynamics<Id, Size, Delay>::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};
Expand Down Expand Up @@ -1095,10 +1077,7 @@ namespace dsm {
std::vector<double> 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);
}
Expand All @@ -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));
}
}
}
Expand Down
21 changes: 10 additions & 11 deletions src/dsm/headers/SparseMatrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,35 +325,34 @@ namespace dsm {
template <typename Index, typename T>
requires(std::unsigned_integral<Index>)
void SparseMatrix<Index, T>::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 <typename Index, typename T>
requires(std::unsigned_integral<Index>)
void SparseMatrix<Index, T>::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));
}

template <typename Index, typename T>
requires(std::unsigned_integral<Index>)
void SparseMatrix<Index, T>::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 <typename Index, typename T>
requires(std::unsigned_integral<Index>)
void SparseMatrix<Index, T>::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);
}
Expand Down
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
17 changes: 8 additions & 9 deletions test/Test_dynamics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.);
Expand Down Expand Up @@ -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);
Expand All @@ -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") {
Expand Down

0 comments on commit 827734e

Please sign in to comment.