Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
527450f
Add Edge base class
Grufoony Jan 16, 2025
3a59878
Bugfix: capacity sometimes drop to 0
Grufoony Jan 16, 2025
33c5271
Resolve deprecation warning
Grufoony Jan 16, 2025
889da9b
Remove unused functions in Street
Grufoony Jan 16, 2025
db04e6c
Remove unused things
Grufoony Jan 16, 2025
a052a14
Add u, v getters
Grufoony Jan 16, 2025
16a3ab1
Less constructors
Grufoony Jan 17, 2025
37a00ca
Remove now useless function
Grufoony Jan 17, 2025
e5a4ebb
Adjust tests
Grufoony Jan 17, 2025
6fd5298
Bugfix
Grufoony Jan 17, 2025
f7f5ac7
Compiling examples
Grufoony Jan 17, 2025
79ef769
Fix some warnings
Grufoony Jan 17, 2025
48e3559
Bugfix
Grufoony Jan 17, 2025
c799aec
Sto facendo guai
Grufoony Jan 20, 2025
e694dcf
Fix tests
Grufoony Jan 20, 2025
5d68056
Move deltaAngle function
Grufoony Jan 20, 2025
f58b068
Init generic Road class
Grufoony Jan 20, 2025
a5af651
Rename waiting into moving
Grufoony Jan 21, 2025
11bebc5
Manage nullopt return for streets
Grufoony Jan 21, 2025
e5d95fc
Virtual functions and docs
Grufoony Jan 21, 2025
8235fd0
Docs
Grufoony Jan 21, 2025
3118a1f
Init class
Grufoony Jan 21, 2025
e86aa83
Make movingVehicles a vector
Grufoony Jan 21, 2025
bfbbf50
Remove dummy file
Grufoony Jan 21, 2025
b1d6ad5
Remove hypothesis
Grufoony Jan 22, 2025
6e03dc4
Update version
Grufoony Jan 22, 2025
edbe48e
Add counter class
Grufoony Jan 22, 2025
767d0e3
Add Stochastic street class
Grufoony Jan 22, 2025
e77bd2b
Add docs
Grufoony Jan 22, 2025
b743e3e
Fix examples
Grufoony Jan 22, 2025
e703ce0
Fix some warnings
Grufoony Jan 22, 2025
ef0e291
Fix
Grufoony Jan 22, 2025
85f72ea
Fix clang warnings
Grufoony Jan 22, 2025
da201fc
Constructors?
Grufoony Jan 22, 2025
750a89c
Merge branch 'main' into StochasticStreet
Grufoony Jan 22, 2025
e3126ec
Smash the bug!
Grufoony Jan 22, 2025
c081726
Optional
Grufoony Jan 23, 2025
73b3ae0
Fix lane assegnation
Grufoony Jan 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions examples/stalingrado.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ int main() {
Graph graph;

// Street(StreetId, Capacity, Length, vMax, (from, to))
Street::setMeanVehicleLength(8.);
dsm::Road::setMeanVehicleLength(8.);
Street s01{1, std::make_pair(0, 1), 2281.};
Street s12{7, std::make_pair(1, 2), 118.};
Street s23{13, std::make_pair(2, 3), 222.};
Expand All @@ -74,7 +74,8 @@ int main() {
graph.addStreets(s01, s12, s23, s34);
graph.buildAdj();
graph.adjustNodeCapacities();
auto& spire = graph.makeSpireStreet(19);
graph.makeSpireStreet(19);
auto& spire = dynamic_cast<SpireStreet&>(*graph.streetSet().at(19));

std::cout << "Intersections: " << graph.nNodes() << '\n';
std::cout << "Streets: " << graph.nEdges() << '\n';
Expand Down
2 changes: 1 addition & 1 deletion src/dsm/dsm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

static constexpr uint8_t DSM_VERSION_MAJOR = 2;
static constexpr uint8_t DSM_VERSION_MINOR = 3;
static constexpr uint8_t DSM_VERSION_PATCH = 1;
static constexpr uint8_t DSM_VERSION_PATCH = 2;

static auto const DSM_VERSION =
std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH);
Expand Down
2 changes: 1 addition & 1 deletion src/dsm/headers/Dynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ namespace dsm {
return 0.;
}
double speed{0.};
for (auto const& agentId : pStreet->waitingAgents()) {
for (auto const& agentId : pStreet->movingAgents()) {
speed += m_agents.at(agentId)->speed();
}
return speed / nAgents;
Expand Down
44 changes: 40 additions & 4 deletions src/dsm/headers/Edge.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
#include "Edge.hpp"
#include "../utility/Logger.hpp"

#include <stdexcept>
#include <cassert>
#include <cmath>
#include <format>
#include <numbers>
#include <stdexcept>

namespace dsm {
Edge::Edge(Id id, std::pair<Id, Id> nodePair, int capacity, int transportCapacity)
Edge::Edge(Id id,
std::pair<Id, Id> nodePair,
int capacity,
int transportCapacity,
double angle)
: m_id(id),
m_nodePair(nodePair),
m_capacity{capacity},
m_transportCapacity{transportCapacity} {
m_transportCapacity{transportCapacity},

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
m_angle{angle} {
if (capacity < 1) {
throw std::invalid_argument(
buildLog(std::format("Edge capacity ({}) must be greater than 0.", capacity)));
Expand All @@ -18,6 +26,10 @@
throw std::invalid_argument(buildLog(std::format(
"Edge transport capacity ({}) must be greater than 0.", transportCapacity)));
}
if (std::abs(angle) > 2 * std::numbers::pi) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
throw std::invalid_argument(buildLog(
std::format("Edge angle ({}) must be in the range [-2pi, 2pi].", angle)));
}
}

void Edge::setCapacity(int capacity) {
Expand All @@ -35,10 +47,34 @@
m_transportCapacity = capacity;
}

void Edge::setAngle(std::pair<double, double> srcNodeCoordinates,
std::pair<double, double> dstNodeCoordinates) {
// N.B.: lat, lon <==> y, x
double const dy{dstNodeCoordinates.first - srcNodeCoordinates.first};
double const dx{dstNodeCoordinates.second - srcNodeCoordinates.second};
double angle{std::atan2(dy, dx)};
if (angle < 0.) {
angle += 2 * std::numbers::pi;
}
assert(!(std::abs(angle) > 2 * std::numbers::pi));

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
m_angle = angle;
}

Id Edge::id() const { return m_id; }
Id Edge::u() const { return m_nodePair.first; }
Id Edge::v() const { return m_nodePair.second; }
std::pair<Id, Id> Edge::nodePair() const { return m_nodePair; }
std::pair<Id, Id> const& Edge::nodePair() const { return m_nodePair; }

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
int Edge::capacity() const { return m_capacity; }
int Edge::transportCapacity() const { return m_transportCapacity; }
double Edge::angle() const { return m_angle; }

double Edge::deltaAngle(double const previousEdgeAngle) const {
double deltaAngle{this->m_angle - previousEdgeAngle};
if (deltaAngle > std::numbers::pi) {
deltaAngle -= 2 * std::numbers::pi;
} else if (deltaAngle < -std::numbers::pi) {
deltaAngle += 2 * std::numbers::pi;
}

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.7 rule Note

MISRA 15.7 rule
return deltaAngle;
}
}; // namespace dsm
37 changes: 35 additions & 2 deletions src/dsm/headers/Edge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,53 @@ namespace dsm {
std::pair<Id, Id> m_nodePair;
int m_capacity;
int m_transportCapacity;
double m_angle;

public:
Edge(Id id, std::pair<Id, Id> nodePair, int capacity = 1, int transportCapacity = 1);
/// @brief Construct a new Edge object
/// @param id The edge's id
/// @param nodePair The edge's node pair (u, v) with the edge u -> v
/// @param capacity The edge's capacity, in number of agents, i.e. the maximum number of agents that can be on the
/// edge at the same time. Default is 1.
/// @param transportCapacity The edge's transport capacity, in number of agents, i.e. the maximum number of agents
/// that can be emitted by the same time. Default is 1.
/// @param angle The edge's angle, in radians, between the source and destination nodes
Edge(Id id,
std::pair<Id, Id> nodePair,
int capacity = 1,
int transportCapacity = 1,
double angle = 0.0);

void setCapacity(int capacity);
void setTransportCapacity(int capacity);
void setAngle(std::pair<double, double> srcNodeCoordinates,
std::pair<double, double> dstNodeCoordinates);

/// @brief Get the edge's id
/// @return Id The edge's id
Id id() const;
/// @brief Get the edge's source node id
/// @return Id The edge's source node id
Id u() const;
/// @brief Get the edge's destination node id
/// @return Id The edge's destination node id
Id v() const;
std::pair<Id, Id> nodePair() const;
/// @brief Get the edge's node pair
/// @return std::pair<Id, Id> The edge's node pair, where the first element is the source node id and the second
/// element is the destination node id. The pair is (u, v) with the edge u -> v.
std::pair<Id, Id> const& nodePair() const;
/// @brief Get the edge's capacity, in number of agents
/// @return int The edge's capacity, in number of agents
int capacity() const;
/// @brief Get the edge's transport capacity, in number of agents
/// @return int The edge's transport capacity, in number of agents
int transportCapacity() const;
/// @brief Get the edge's angle, in radians, between the source and destination nodes
/// @return double The edge's angle, in radians
double angle() const;

virtual bool isFull() const = 0;

double deltaAngle(double const previousEdgeAngle) const;
};
}; // namespace dsm
4 changes: 2 additions & 2 deletions src/dsm/headers/FirstOrderDynamics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ namespace dsm {
double meanSpeed{0.};
Size n{0};
if (street->nExitingAgents() == 0) {
n = static_cast<Size>(street->waitingAgents().size());
n = static_cast<Size>(street->movingAgents().size());
double alpha{m_alpha / street->capacity()};
meanSpeed = street->maxSpeed() * n * (1. - 0.5 * alpha * (n - 1.));
} else {
for (const auto& agentId : street->waitingAgents()) {
for (const auto& agentId : street->movingAgents()) {
meanSpeed += this->agents().at(agentId)->speed();
++n;
}
Expand Down
39 changes: 31 additions & 8 deletions src/dsm/headers/Graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,29 @@
const auto n{static_cast<Size>(m_nodes.size())};
std::unordered_map<Id, Id> newStreetIds;
for (const auto& [streetId, street] : oldStreetSet) {
const auto srcId{street->nodePair().first};
const auto dstId{street->nodePair().second};
const auto srcId{street->u()};
const auto dstId{street->v()};
const auto newStreetId{static_cast<Id>(srcId * n + dstId)};
if (m_streets.contains(newStreetId)) {
throw std::invalid_argument(buildLog("Street with same id already exists."));
}
if (street->isSpire()) {
if (street->isSpire() && street->isStochastic()) {
m_streets.emplace(newStreetId,
std::make_unique<StochasticSpireStreet>(
newStreetId,
*street,
dynamic_cast<StochasticSpireStreet&>(*street).flowRate()));
} else if (street->isStochastic()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
m_streets.emplace(newStreetId,
std::make_unique<StochasticStreet>(
newStreetId,
*street,
dynamic_cast<StochasticStreet&>(*street).flowRate()));
} else if (street->isSpire()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
m_streets.emplace(newStreetId,
std::make_unique<SpireStreet>(newStreetId, *street));
} else {
m_streets.emplace(newStreetId,
std::make_unique<Street>(Street{newStreetId, *street}));
m_streets.emplace(newStreetId, std::make_unique<Street>(newStreetId, *street));
}
newStreetIds.emplace(streetId, newStreetId);
}
Expand Down Expand Up @@ -444,15 +455,27 @@
pNode = std::make_unique<Station>(*pNode, managementTime);
return dynamic_cast<Station&>(*pNode);
}

SpireStreet& Graph::makeSpireStreet(Id streetId) {
StochasticStreet& Graph::makeStochasticStreet(Id streetId, double const flowRate) {
if (!m_streets.contains(streetId)) {
throw std::invalid_argument(
buildLog(std::format("Street with id {} does not exist.", streetId)));
}
auto& pStreet = m_streets[streetId];
pStreet = std::make_unique<StochasticStreet>(pStreet->id(), *pStreet, flowRate);
return dynamic_cast<StochasticStreet&>(*pStreet);
}
void Graph::makeSpireStreet(Id streetId) {
if (!m_streets.contains(streetId)) {
throw std::invalid_argument(
buildLog(std::format("Street with id {} does not exist.", streetId)));
}
auto& pStreet = m_streets[streetId];
if (pStreet->isStochastic()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
pStreet = std::make_unique<StochasticSpireStreet>(
pStreet->id(), *pStreet, dynamic_cast<StochasticStreet&>(*pStreet).flowRate());
return;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule
}
pStreet = std::make_unique<SpireStreet>(pStreet->id(), *pStreet);
return dynamic_cast<SpireStreet&>(*pStreet);
}

void Graph::addStreet(std::unique_ptr<Street> street) {
Expand Down
16 changes: 5 additions & 11 deletions src/dsm/headers/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,6 @@ namespace dsm {
std::constructible_from<node_t, Id, TArgs...>)
node_t& addNode(Id id, TArgs&&... args);

template <typename... Tn>
requires(is_node_v<std::remove_reference_t<Tn>> && ...)
void addNodes(Tn&&... nodes);

template <typename T1, typename... Tn>
requires is_node_v<std::remove_reference_t<T1>> &&
(is_node_v<std::remove_reference_t<Tn>> && ...)
Expand All @@ -182,11 +178,12 @@ namespace dsm {
/// @return A reference to the roundabout
/// @throws std::invalid_argument if the node does not exist
Roundabout& makeRoundabout(Id nodeId);

StochasticStreet& makeStochasticStreet(Id streetId, double const flowRate);
/// @brief Convert an existing street into a spire street
/// @param streetId The id of the street to convert to a spire street
/// @return A reference to the spire street
/// @throws std::invalid_argument if the street does not exist
SpireStreet& makeSpireStreet(Id streetId);
void makeSpireStreet(Id streetId);
/// @brief Convert an existing node into a station
/// @param nodeId The id of the node to convert to a station
/// @param managementTime The station's management time
Expand Down Expand Up @@ -286,9 +283,6 @@ namespace dsm {
addNode(std::make_unique<node_t>(id, std::forward<TArgs>(args)...));
return dynamic_cast<node_t&>(*m_nodes[id]);
}
template <typename... Tn>
requires(is_node_v<std::remove_reference_t<Tn>> && ...)
void Graph::addNodes(Tn&&... nodes) {}
template <typename T1, typename... Tn>
requires is_node_v<std::remove_reference_t<T1>> &&
(is_node_v<std::remove_reference_t<Tn>> && ...)
Expand All @@ -313,8 +307,8 @@ namespace dsm {
buildLog(std::format("Street with id {} already exists.", street.id())));
}
// emplace nodes
const auto srcId{street.nodePair().first};
const auto dstId{street.nodePair().second};
auto const srcId{street.u()};
auto const dstId{street.v()};
if (!m_nodes.contains(srcId)) {
m_nodes.emplace(srcId, std::make_unique<Intersection>(srcId));
}
Expand Down
69 changes: 69 additions & 0 deletions src/dsm/headers/Road.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "Road.hpp"
#include "../utility/Logger.hpp"

#include <cmath>
#include <format>
#include <stdexcept>

namespace dsm {
double Road::m_meanVehicleLength = 5.;

Road::Road(Id id, const Road& road)
: Edge(
id, road.nodePair(), road.capacity(), road.transportCapacity(), road.angle()),
m_length{road.length()},
m_maxSpeed{road.maxSpeed()},
m_nLanes{road.nLanes()},

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
m_name{road.name()} {}

Road::Road(Id id,
std::pair<Id, Id> nodePair,
double length,
double maxSpeed,
int nLanes,
std::string name,
std::optional<int> capacity,
int transportCapacity)
: Edge(id,
std::move(nodePair),
capacity.value_or(std::ceil((length * nLanes) / m_meanVehicleLength)),

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 10.4 rule Note

MISRA 10.4 rule
transportCapacity),
m_length{length},
m_maxSpeed{maxSpeed},
m_nLanes{nLanes},

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
m_name{std::move(name)} {
if (!(length > 0.)) {
throw std::invalid_argument(buildLog(
std::format("The length of a road ({}) must be greater than 0.", length)));
}
if (!(maxSpeed > 0.)) {
throw std::invalid_argument(buildLog(std::format(
"The maximum speed of a road ({}) must be greater than 0.", maxSpeed)));
}
if (nLanes < 1) {
throw std::invalid_argument(buildLog(std::format(
"The number of lanes of a road ({}) must be greater than 0.", nLanes)));
}
}
void Road::setMeanVehicleLength(double meanVehicleLength) {
if (!(meanVehicleLength > 0.)) {
throw std::invalid_argument(buildLog(std::format(
"The mean vehicle length ({}) must be greater than 0.", meanVehicleLength)));
}
m_meanVehicleLength = meanVehicleLength;
}
double Road::meanVehicleLength() { return m_meanVehicleLength; }

void Road::setMaxSpeed(double speed) {
if (speed < 0.) {
throw std::invalid_argument(buildLog(
std::format("The maximum speed of a road ({}) cannot be negative.", speed)));
}
m_maxSpeed = speed;
}

double Road::length() const { return m_length; }
double Road::maxSpeed() const { return m_maxSpeed; }
int Road::nLanes() const { return m_nLanes; }
std::string Road::name() const { return m_name; }
}; // namespace dsm
Loading
Loading