Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for io flags in importOSMNodes function #256

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 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
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 = 20;
static constexpr uint8_t DSM_VERSION_PATCH = 21;

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/Agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ namespace dsm {
Id id() const { return m_id; }
/// @brief Get the agent's itinerary
/// @return The agent's itinerary
Id itineraryId() const { return m_trip[m_itineraryIdx]; }
Id itineraryId() const { return m_trip.at(m_itineraryIdx); }
/// @brief Get the agent's trip
/// @return The agent's trip
std::vector<Id> const& trip() const { return m_trip; }
Expand Down
47 changes: 39 additions & 8 deletions src/dsm/headers/Dynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
auto path = SparseMatrix<bool>{};
path.load(file);
pItinerary->setPath(std::move(path));
Logger::info(
Logger::debug(

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

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/Dynamics.hpp#L96

Added line #L96 was not covered by tests
std::format("Loaded cached path for itinerary {}", pItinerary->id()));
return;
}
Expand All @@ -108,6 +108,8 @@
}
auto result{m_graph.shortestPath(nodeId, destinationID)};
if (!result.has_value()) {
Logger::warning(
std::format("No path found from {} to {}.", nodeId, destinationID));
continue;
}
// save the minimum distance between i and the destination
Expand Down Expand Up @@ -147,24 +149,26 @@
destinationID,
1.));
}
} else if ((nextNodeId != destinationID)) {
Logger::warning(std::format(
"No path found from node {} to node {}", nextNodeId, destinationID));
} else {
Logger::warning(
std::format("No path found from {} to {}.", nextNodeId, destinationID));
}
}
}
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 171 in src/dsm/headers/Dynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/Dynamics.hpp#L171

Added line #L171 was not covered by tests
std::format("Saved path in cache for itinerary {}", pItinerary->id()));
}
}
Expand Down Expand Up @@ -249,6 +253,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 @@ -327,7 +333,7 @@
std::optional<unsigned int> seed)
: m_bCacheEnabled{useCache},
m_graph{std::move(graph)},
m_time{0},

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
m_previousSpireTime{0},
m_generator{std::random_device{}()} {
if (seed.has_value()) {
Expand All @@ -339,13 +345,25 @@
}
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 350 in src/dsm/headers/Dynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/Dynamics.hpp#L349-L350

Added lines #L349 - L350 were not covered by tests
}
// updatePaths();
}

template <typename agent_t>
void Dynamics<agent_t>::updatePaths() {
if (m_bCacheEnabled) {
if (!std::filesystem::exists(g_cacheFolder)) {
std::filesystem::create_directory(g_cacheFolder);

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

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/Dynamics.hpp#L359

Added line #L359 was not covered by tests
}
}

std::vector<std::thread> threads;
threads.reserve(m_itineraries.size());
std::exception_ptr pThreadException;
Logger::info(std::format("Init computing {} paths", m_itineraries.size()));
for (const auto& [itineraryId, itinerary] : m_itineraries) {
threads.emplace_back(std::thread([this, &itinerary, &pThreadException] {
try {
Expand All @@ -362,6 +380,8 @@
// Throw the exception launched first
if (pThreadException)
std::rethrow_exception(pThreadException);

Logger::info("End computing paths");
}

template <typename agent_t>
Expand Down Expand Up @@ -390,6 +410,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 @@ -435,6 +459,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 @@ -468,6 +493,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
80 changes: 56 additions & 24 deletions src/dsm/headers/RoadDynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,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 @@ -235,7 +237,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 241 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L241

Added line #L241 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 @@ -319,9 +324,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 @@ -331,14 +334,14 @@
}
continue;
}
auto const& nextStreet{this->m_graph.streetSet()[m_agentNextStreetId[agentId]]};
auto const& nextStreet{this->m_graph.street(m_agentNextStreetId.at(agentId))};
if (nextStreet->isFull()) {
continue;
}
if (pStreet->dequeue(queueIndex) == std::nullopt) {
continue;
pStreet->dequeue(queueIndex);
if (destinationNode->id() != nextStreet->u()) {
Logger::error(std::format("Agent {} is going to the wrong street", agentId));

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

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L343

Added line #L343 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 All @@ -360,7 +363,7 @@
return false;
}
for (auto const [angle, agentId] : intersection.agents()) {
auto const& nextStreet{this->m_graph.streetSet()[m_agentNextStreetId[agentId]]};
auto const& nextStreet{this->m_graph.street(m_agentNextStreetId.at(agentId))};
if (nextStreet->isFull()) {
if (m_forcePriorities) {
return false;
Expand All @@ -383,7 +386,7 @@
return false;
}
auto const agentId{roundabout.agents().front()};
auto const& nextStreet{this->m_graph.streetSet()[m_agentNextStreetId[agentId]]};
auto const& nextStreet{this->m_graph.street(m_agentNextStreetId.at(agentId))};
if (!(nextStreet->isFull())) {
if (this->agents().at(agentId)->streetId().has_value()) {
const auto streetId = this->agents().at(agentId)->streetId().value();
Expand Down Expand Up @@ -494,7 +497,7 @@
!m_agentNextStreetId.contains(agentId)) {
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 @@ -596,7 +599,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 @@ -630,9 +642,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 @@ -648,19 +661,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() <

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
minNodeDistance) {
continue;

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

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L678-L679

Added lines #L678 - L679 were not covered by tests
}
}
dstId = id;
sum += weight;
if (dRand < sum) {
Expand All @@ -683,6 +701,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 @@ -691,7 +723,7 @@
m_dataUpdatePeriod.has_value() && this->m_time % m_dataUpdatePeriod.value() == 0;
for (const auto& [streetId, pStreet] : this->m_graph.streetSet()) {
if (bUpdateData) {
m_streetTails[streetId] += pStreet->nExitingAgents();
m_streetTails.at(streetId) += pStreet->nExitingAgents();
}
for (auto i = 0; i < pStreet->transportCapacity(); ++i) {
this->m_evolveStreet(pStreet, reinsert_agents);
Expand Down Expand Up @@ -736,11 +768,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 @@ -780,11 +812,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 815 in src/dsm/headers/RoadDynamics.hpp

View check run for this annotation

Codecov / codecov/patch

src/dsm/headers/RoadDynamics.hpp#L815

Added line #L815 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 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
} else {
outputRedSum += m_streetTails[streetId] / pStreet->nLanes();
outputRedSum += 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
}
}
auto const outputDifference{(outputGreenSum - outputRedSum) / nCycles};
Expand Down
Loading
Loading