Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
36390b3
Init io node set in importOSMNodes
Grufoony Jan 30, 2025
c0d7d0e
Add general addAgentsRandomly function
Grufoony Jan 30, 2025
c92c5d6
Bugfix
Grufoony Jan 30, 2025
3ef73b2
Logging
Grufoony Jan 30, 2025
9107a59
Formatting
Grufoony Jan 30, 2025
49d79b0
Merge branch 'main' into io_nodes
Grufoony Jan 30, 2025
28da2e4
Update version
Grufoony Jan 30, 2025
ce51ac3
Bugfix + logging
Grufoony Jan 30, 2025
054471c
ChatGPPT optimization
Grufoony Jan 30, 2025
943d578
Add path caching
Grufoony Jan 31, 2025
6e6fb57
Merge branch 'pathCaching' into io_nodes
Grufoony Jan 31, 2025
1fd0ddb
Improve
Grufoony Jan 31, 2025
76f3d46
Merge branch 'pathCaching' into io_nodes
Grufoony Jan 31, 2025
8262983
To revise
Grufoony Jan 31, 2025
b0dc230
First tryal
Grufoony Jan 31, 2025
d88767b
Handle oneway
Grufoony Jan 31, 2025
ae67561
Prova
Grufoony Jan 31, 2025
12c289c
Merge branch 'main' into io_nodes
Grufoony Jan 31, 2025
c15e7bd
Update version
Grufoony Jan 31, 2025
98b3762
Merge branch 'main' into io_nodes
Grufoony Jan 31, 2025
4ff36b2
Update version
Grufoony Jan 31, 2025
fe2f5c0
Fix merge
Grufoony Jan 31, 2025
7f39bfa
Add debug logs
Grufoony Feb 3, 2025
6242461
Merge branch 'main' into io_nodes
Grufoony Feb 3, 2025
c09776c
Info to Debug
Grufoony Feb 3, 2025
f51bbf7
Enhance code security
Grufoony Feb 3, 2025
422f160
Enhance code security
Grufoony Feb 3, 2025
628b5f3
Bugfix
Grufoony Feb 3, 2025
5263389
Remove optional from street dequeue
Grufoony Feb 3, 2025
657a149
To remove asap
Grufoony Feb 3, 2025
e3c31d4
Merge branch 'main' into io_nodes
Grufoony Feb 3, 2025
731a36c
Log messages
Grufoony Feb 4, 2025
56e9d02
Bugfix
Grufoony Feb 4, 2025
69f8a99
Optimize `addAgentsRandomly` functions
Grufoony Feb 5, 2025
1201949
Merge branch 'main' into io_nodes
Grufoony Feb 5, 2025
daa2cf9
Update version
Grufoony Feb 5, 2025
81ac4f9
Fix tests
Grufoony Feb 5, 2025
87232f5
Merge branch 'main' into io_nodes
Grufoony Feb 12, 2025
912e438
Bugfix
Grufoony Feb 12, 2025
864c252
Merge branch 'main' into io_nodes
Grufoony Feb 14, 2025
53f0de3
Label coherence
Grufoony Feb 14, 2025
6a1443e
Update version
Grufoony Feb 14, 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
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 = 27;
static constexpr uint8_t DSM_VERSION_PATCH = 28;

static auto const DSM_VERSION =
std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH);
Expand Down
30 changes: 25 additions & 5 deletions src/dsm/headers/Dynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
auto path = SparseMatrix<bool>{};
path.load(file);
pItinerary->setPath(std::move(path));
Logger::info(
Logger::debug(

Check warning on line 97 in src/dsm/headers/Dynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/Dynamics.hpp#L97

Added line #L97 was not covered by tests
std::format("Loaded cached path for itinerary {}", pItinerary->id()));
return;
}
Expand Down Expand Up @@ -169,18 +169,20 @@
}
}
}
if (path.size() == 0) {

if (path.empty()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
Logger::error(
std::format("Path with id {} and destination {} is empty. Please "
"check the adjacency matrix.",
std::format("Path with id {} and destination {} is empty. Please check the "
"adjacency matrix.",
pItinerary->id(),
pItinerary->destination()));
}

pItinerary->setPath(path);
if (m_bCacheEnabled) {
pItinerary->path().cache(
std::format("{}it{}.dsmcache", g_cacheFolder, pItinerary->id()));
Logger::info(
Logger::debug(

Check warning on line 185 in src/dsm/headers/Dynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/Dynamics.hpp#L185

Added line #L185 was not covered by tests
std::format("Saved path in cache for itinerary {}", pItinerary->id()));
}
}
Expand Down Expand Up @@ -276,6 +278,8 @@
/// @param itineraries Generic container of itineraries, represented by an std::span
void addItineraries(std::span<Itinerary> itineraries);

void enableCache();

/// @brief Reset the simulation time
void resetTime();

Expand Down Expand Up @@ -372,6 +376,11 @@
}
Logger::info(std::format("Cache enabled (default folder is {})", g_cacheFolder));
}
for (const auto& nodeId : this->m_graph.outputNodes()) {
addItinerary(Itinerary{nodeId, nodeId});
m_updatePath(m_itineraries.at(nodeId));

Check warning on line 381 in src/dsm/headers/Dynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/Dynamics.hpp#L380-L381

Added lines #L380 - L381 were not covered by tests
}
// updatePaths();
}

template <typename agent_t>
Expand Down Expand Up @@ -419,6 +428,10 @@
std::format("Agent with id {} already exists.", agent->id())));
}
m_agents.emplace(agent->id(), std::move(agent));
// Logger::debug(std::format("Added agent with id {} from node {} to node {}",
// m_agents.rbegin()->first,
// m_agents.rbegin()->second->srcNodeId().value_or(-1),
// m_agents.rbegin()->second->itineraryId()));
}

template <typename agent_t>
Expand Down Expand Up @@ -464,6 +477,7 @@
template <typename agent_t>
void Dynamics<agent_t>::removeAgent(Size agentId) {
m_agents.erase(agentId);
Logger::debug(std::format("Removed agent with id {}", agentId));
}

template <typename agent_t>
Expand Down Expand Up @@ -507,6 +521,12 @@
});
}

template <typename agent_t>
void Dynamics<agent_t>::enableCache() {
m_bCacheEnabled = true;
Logger::info(std::format("Cache enabled (default folder is {})", g_cacheFolder));
}

template <typename agent_t>
void Dynamics<agent_t>::resetTime() {
m_time = 0;
Expand Down
13 changes: 11 additions & 2 deletions src/dsm/headers/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
std::unordered_map<Id, std::unique_ptr<Node>> m_nodes;
std::unordered_map<Id, std::unique_ptr<Street>> m_streets;
std::unordered_map<std::string, Id> m_nodeMapping;
std::vector<Id> m_inputNodes;
std::vector<Id> m_outputNodes;
SparseMatrix<bool> m_adjacency;
unsigned long long m_maxAgentCapacity;

Expand Down Expand Up @@ -80,6 +82,8 @@
});
m_nodeMapping = other.m_nodeMapping;
m_adjacency = other.m_adjacency;
m_inputNodes = other.m_inputNodes;
m_outputNodes = other.m_outputNodes;
}

Graph& operator=(const Graph& other) {
Expand All @@ -94,6 +98,8 @@
});
m_nodeMapping = other.m_nodeMapping;
m_adjacency = other.m_adjacency;
m_inputNodes = other.m_inputNodes;
m_outputNodes = other.m_outputNodes;

return *this;
}
Expand Down Expand Up @@ -261,6 +267,9 @@
/// @return unsigned long long The maximum agent capacity of the graph
unsigned long long maxCapacity() const { return m_maxAgentCapacity; }

std::vector<Id> const& inputNodes() const { return m_inputNodes; }
std::vector<Id> const& outputNodes() const { return m_outputNodes; }

/// @brief Get the shortest path between two nodes using dijkstra algorithm
/// @param source The source node
/// @param destination The destination node
Expand All @@ -287,7 +296,7 @@
std::constructible_from<node_t, Id, TArgs...>)
node_t& Graph::addNode(Id id, TArgs&&... args) {
addNode(std::make_unique<node_t>(id, std::forward<TArgs>(args)...));
return dynamic_cast<node_t&>(*m_nodes[id]);
return dynamic_cast<node_t&>(*m_nodes.at(id));

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule
}
template <typename T1, typename... Tn>
requires is_node_v<std::remove_reference_t<T1>> &&
Expand All @@ -302,7 +311,7 @@
std::constructible_from<edge_t, Id, TArgs...>)
edge_t& Graph::addEdge(Id id, TArgs&&... args) {
addStreet(std::make_unique<edge_t>(id, std::forward<TArgs>(args)...));
return dynamic_cast<edge_t&>(*m_streets[id]);
return dynamic_cast<edge_t&>(*m_streets.at(id));

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 15.5 rule Note

MISRA 15.5 rule
}

template <typename T1>
Expand Down
81 changes: 52 additions & 29 deletions src/dsm/headers/RoadDynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@
const TContainer& dst_weights,
const size_t minNodeDistance = 0);

void addAgentsRandomly(Size nAgents, const size_t minNodeDistance = 0);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.8 rule Note

MISRA 17.8 rule

/// @brief Evolve the simulation
/// @details Evolve the simulation by moving the agents and updating the travel times.
/// In particular:
Expand Down Expand Up @@ -234,7 +236,10 @@
}
}
}
assert(possibleMoves.size() > 0);
if (possibleMoves.empty()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
Logger::error(

Check warning on line 240 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L240

Added line #L240 was not covered by tests
std::format("No possible moves from node {} for agent {}", nodeId, agentId));
}
std::uniform_int_distribution<Size> moveDist{
0, static_cast<Size>(possibleMoves.size() - 1)};
uint8_t p{0};
Expand Down Expand Up @@ -317,9 +322,7 @@
}
}
if (bArrived) {
if (pStreet->dequeue(queueIndex) == std::nullopt) {
continue;
}
pStreet->dequeue(queueIndex);
m_travelDTs.push_back({pAgent->distance(), static_cast<double>(pAgent->time())});
if (reinsert_agents) {
// reset Agent's values
Expand All @@ -334,10 +337,10 @@
if (nextStreet->isFull()) {
continue;
}
if (pStreet->dequeue(queueIndex) == std::nullopt) {
continue;
pStreet->dequeue(queueIndex);
if (destinationNode->id() != nextStreet->source()) {
Logger::error(std::format("Agent {} is going to the wrong street", agentId));

Check warning on line 342 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L342

Added line #L342 was not covered by tests
}
assert(destinationNode->id() == nextStreet->nodePair().first);
if (destinationNode->isIntersection()) {
auto& intersection = dynamic_cast<Intersection&>(*destinationNode);
auto const delta{nextStreet->deltaAngle(pStreet->angle())};
Expand Down Expand Up @@ -492,7 +495,7 @@
} else if (!agent->streetId().has_value() && !agent->nextStreetId().has_value()) {
Id srcNodeId = agent->srcNodeId().has_value() ? agent->srcNodeId().value()
: nodeDist(this->m_generator);
const auto& srcNode{this->m_graph.nodeSet()[srcNodeId]};
const auto& srcNode{this->m_graph.node(srcNodeId)};
if (srcNode->isFull()) {
continue;
}
Expand Down Expand Up @@ -594,7 +597,16 @@
const TContainer& src_weights,
const TContainer& dst_weights,
const size_t minNodeDistance) {
if (src_weights.size() == 1 && dst_weights.size() == 1 &&
auto const& nSources{src_weights.size()};
auto const& nDestinations{dst_weights.size()};
Logger::debug(
std::format("Init addAgentsRandomly for {} agents from {} nodes to {} nodes with "
"minNodeDistance {}",
nAgents,
nSources,
dst_weights.size(),
minNodeDistance));
if (nSources == 1 && nDestinations == 1 &&

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
src_weights.begin()->first == dst_weights.begin()->first) {
throw std::invalid_argument(Logger::buildExceptionMessage(
std::format("The only source node {} is also the only destination node.",
Expand Down Expand Up @@ -628,9 +640,10 @@
if (!this->agents().empty()) {
agentId = this->agents().rbegin()->first + 1;
}
Logger::debug(std::format("Adding {} agents at time {}.", nAgents, this->time()));

Check notice

Code scanning / Cppcheck (reported by Codacy)

time is Y2038-unsafe Note

time is Y2038-unsafe
while (nAgents > 0) {
Id srcId{0}, dstId{0};
if (dst_weights.size() == 1) {
if (nDestinations == 1) {
dstId = dst_weights.begin()->first;
srcId = dstId;
}
Expand All @@ -646,19 +659,24 @@
}
}
}
if (src_weights.size() > 1) {
if (nSources > 1) {
dstId = srcId;
}
while (dstId == srcId) {
dRand = dstUniformDist(this->m_generator);
sum = 0.;
for (const auto& [id, weight] : dst_weights) {
// if the node is at a minimum distance from the destination, skip it
auto result{this->m_graph.shortestPath(srcId, id)};
if (result.has_value() && result.value().path().size() < minNodeDistance &&
dst_weights.size() > 1) {
if (this->itineraries().at(id)->path().getRow(srcId).empty()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
continue;
}
if (nDestinations > 1 && minNodeDistance > 0) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
// NOTE: Result must have a value in this case, so we can use value() as sort-of assertion
if (this->m_graph.shortestPath(srcId, id).value().path().size() <
minNodeDistance) {
continue;

Check warning on line 677 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L676-L677

Added lines #L676 - L677 were not covered by tests
}
}
dstId = id;
sum += weight;
if (dRand < sum) {
Expand All @@ -681,6 +699,20 @@
}
}

template <typename delay_t>
requires(is_numeric_v<delay_t>)
void RoadDynamics<delay_t>::addAgentsRandomly(Size nAgents,
const size_t minNodeDistance) {
std::unordered_map<Id, double> src_weights, dst_weights;

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
for (auto const& id : this->m_graph.inputNodes()) {
src_weights[id] = 1.;
}
for (auto const& id : this->m_graph.outputNodes()) {
dst_weights[id] = 1.;
}
addAgentsRandomly(nAgents, src_weights, dst_weights, minNodeDistance);
}

template <typename delay_t>
requires(is_numeric_v<delay_t>)
void RoadDynamics<delay_t>::evolve(bool reinsert_agents) {
Expand All @@ -699,15 +731,6 @@
}
}
}
// for (const auto& [streetId, pStreet] : this->m_graph.streetSet()) {
// if (bUpdateData) {
// m_streetTails[streetId] += pStreet->nExitingAgents();
// }
// Logger::info(std::format("Evolving street {}", streetId));
// for (auto i = 0; i < pStreet->transportCapacity(); ++i) {
// this->m_evolveStreet(pStreet, reinsert_agents);
// }
// }
// Move transport capacity agents from each node
for (const auto& [nodeId, pNode] : this->m_graph.nodeSet()) {
for (auto i = 0; i < pNode->transportCapacity(); ++i) {
Expand Down Expand Up @@ -747,11 +770,11 @@

double inputGreenSum{0.}, inputRedSum{0.};
for (const auto& [streetId, _] : this->m_graph.adjMatrix().getCol(nodeId, true)) {
auto const& pStreet{this->m_graph.streetSet()[streetId]};
auto const& pStreet{this->m_graph.street(streetId)};
if (streetPriorities.contains(streetId)) {
inputGreenSum += m_streetTails[streetId] / pStreet->nLanes();
inputGreenSum += m_streetTails.at(streetId) / pStreet->nLanes();
} else {
inputRedSum += m_streetTails[streetId] / pStreet->nLanes();
inputRedSum += m_streetTails.at(streetId) / pStreet->nLanes();
}
}
inputGreenSum /= meanGreenFraction;
Expand Down Expand Up @@ -791,11 +814,11 @@
// - If the previous check fails, do nothing
double outputGreenSum{0.}, outputRedSum{0.};
for (const auto& [streetId, _] : this->m_graph.adjMatrix().getRow(nodeId, true)) {
auto const& pStreet{this->m_graph.streetSet()[streetId]};
auto const& pStreet{this->m_graph.street(streetId)};

Check warning on line 817 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L817

Added line #L817 was not covered by tests
if (streetPriorities.contains(streetId)) {
outputGreenSum += m_streetTails[streetId] / pStreet->nLanes();
outputGreenSum += m_streetTails.at(streetId) / pStreet->nLanes();

Check warning on line 819 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L819

Added line #L819 was not covered by tests
} else {
outputRedSum += m_streetTails[streetId] / pStreet->nLanes();
outputRedSum += m_streetTails.at(streetId) / pStreet->nLanes();

Check warning on line 821 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L821

Added line #L821 was not covered by tests
}
}
auto const outputDifference{(outputGreenSum - outputRedSum) / nCycles};
Expand Down
2 changes: 2 additions & 0 deletions src/dsm/headers/SparseMatrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ namespace dsm {
/// @return number of non zero elements
Id size() const { return _matrix.size(); };

bool empty() const { return _matrix.empty(); }

/// @brief get the maximum number of elements in the matrix
/// @return maximum number of elements
Id max_size() const { return _rows * _cols; }
Expand Down
9 changes: 5 additions & 4 deletions src/dsm/headers/Street.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ namespace dsm {
/// @throw std::runtime_error If the street's queue is full
void enqueue(Id agentId, size_t index);
/// @brief Remove an agent from the street's queue
virtual std::optional<Id> dequeue(size_t index);
/// @return Id The id of the agent removed from the street's queue
virtual Id dequeue(size_t index);
/// @brief Check if the street is a spire
/// @return bool True if the street is a spire, false otherwise
virtual bool isSpire() const { return false; };
Expand Down Expand Up @@ -160,8 +161,8 @@ namespace dsm {
/// Notice that this flow is positive iff the input flow is greater than the output flow.
int meanFlow();
/// @brief Remove an agent from the street's queue
/// @return std::optional<Id> The id of the agent removed from the street's queue
std::optional<Id> dequeue(size_t index) final;
/// @return Id The id of the agent removed from the street's queue
Id dequeue(size_t index) final;
/// @brief Check if the street is a spire
/// @return bool True if the street is a spire, false otherwise
bool isSpire() const final { return true; };
Expand All @@ -182,7 +183,7 @@ namespace dsm {
int meanFlow();
/// @brief Remove an agent from the street's queue
/// @return std::optional<Id> The id of the agent removed from the street's queue
std::optional<Id> dequeue(size_t index) final;
Id dequeue(size_t index) final;
/// @brief Check if the street is a spire
/// @return bool True if the street is a spire, false otherwise
bool isSpire() const final { return true; };
Expand Down
2 changes: 1 addition & 1 deletion src/dsm/sources/FirstOrderDynamics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace dsm {

void FirstOrderDynamics::setAgentSpeed(Size agentId) {
const auto& agent{this->agents().at(agentId)};
const auto& street{this->m_graph.streetSet()[agent->streetId().value()]};
const auto& street{this->m_graph.street(agent->streetId().value())};
double speed{street->maxSpeed() * (1. - m_alpha * street->density(true))};
if (m_speedFluctuationSTD > 0.) {
std::normal_distribution<double> speedDist{speed, speed * m_speedFluctuationSTD};
Expand Down
Loading
Loading