-
Notifications
You must be signed in to change notification settings - Fork 4
Replace itineraries map with a vector #217
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
Changes from 6 commits
dd339cf
bf26216
8b07c33
195d43e
e11341c
1f48afb
fc74eda
37c2607
5303494
8438d19
5b0283e
2790418
e167da2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,11 @@ | |
|
|
||
| using TimePoint = long long unsigned int; | ||
|
|
||
| template <typename T> | ||
| std::unique_ptr<T> clone(const std::unique_ptr<T>& ptr) { | ||
| return std::make_unique<T>(*ptr); | ||
| } | ||
|
|
||
| /// @brief The Measurement struct represents the mean of a quantity and its standard deviation | ||
| /// @tparam T The type of the quantity | ||
| /// @param mean The mean | ||
|
|
@@ -67,7 +72,7 @@ | |
| requires(is_numeric_v<Delay>) | ||
| class Dynamics { | ||
| protected: | ||
| std::unordered_map<Id, std::unique_ptr<Itinerary>> m_itineraries; | ||
| std::vector<std::unique_ptr<Itinerary>> m_itineraries; | ||
| std::map<Id, std::unique_ptr<Agent<Delay>>> m_agents; | ||
| TimePoint m_time, m_previousSpireTime; | ||
| Graph m_graph; | ||
|
|
@@ -154,9 +159,8 @@ | |
| } | ||
| if (path.size() == 0) { | ||
| throw std::runtime_error( | ||
| buildLog(std::format("Path with id {} and destination {} is empty. Please " | ||
| buildLog(std::format("Path destination {} is empty. Please " | ||
| "check the adjacency matrix.", | ||
| pItinerary->id(), | ||
| pItinerary->destination()))); | ||
| } | ||
| pItinerary->setPath(path); | ||
|
|
@@ -190,7 +194,7 @@ | |
| /// @param destinationNodes The destination nodes | ||
| /// @param updatePaths If true, the paths are updated | ||
| /// @throws std::invalid_argument Ifone or more destination nodes do not exist | ||
| void setDestinationNodes(const std::span<Id>& destinationNodes, | ||
| void setDestinationNodes(std::span<Id> destinationNodes, | ||
| bool updatePaths = true); | ||
| /// @brief Set the speed of an agent | ||
| /// @details This is a pure-virtual function, it must be implemented in the derived classes | ||
|
|
@@ -232,9 +236,11 @@ | |
| /// @brief Get the graph | ||
| /// @return const Graph&, The graph | ||
| const Graph& graph() const { return m_graph; }; | ||
|
|
||
| const Itinerary* itinerary(Id destination) const; | ||
| /// @brief Get the itineraries | ||
| /// @return const std::unordered_map<Id, Itinerary>&, The itineraries | ||
| const std::unordered_map<Id, std::unique_ptr<Itinerary>>& itineraries() const { | ||
| const std::vector<std::unique_ptr<Itinerary>>& itineraries() const { | ||
| return m_itineraries; | ||
| } | ||
| /// @brief Get the agents | ||
|
|
@@ -414,7 +420,7 @@ | |
| requires(is_numeric_v<Delay>) | ||
| Id Dynamics<Delay>::m_nextStreetId(Id agentId, Id nodeId, std::optional<Id> streetId) { | ||
| auto possibleMoves = m_graph.adjMatrix().getRow(nodeId, true); | ||
| if (this->m_itineraries.size() > 0 && | ||
| if (!this->m_itineraries.empty() && | ||
| this->m_uniformDist(this->m_generator) > this->m_errorProbability) { | ||
| const auto& it = this->m_itineraries[this->m_agents[agentId]->itineraryId()]; | ||
| if (it->destination() != nodeId) { | ||
|
|
@@ -662,9 +668,10 @@ | |
| template <typename Delay> | ||
| requires(is_numeric_v<Delay>) | ||
| void Dynamics<Delay>::setItineraries(std::span<Itinerary> itineraries) { | ||
| std::ranges::for_each(itineraries, [this](const auto& itinerary) { | ||
| this->m_itineraries.insert(std::make_unique<Itinerary>(itinerary)); | ||
| }); | ||
| std::transform(itineraries.cbegin(), | ||
| itineraries.cend(), | ||
| m_itineraries.begin(), | ||
| [this](const auto& pItinerary) { return clone(pItinerary); }); | ||
Check noticeCode scanning / Cppcheck (reported by Codacy) MISRA 15.5 rule Note
MISRA 15.5 rule
|
||
| } | ||
|
|
||
| template <typename Delay> | ||
|
|
@@ -700,27 +707,42 @@ | |
|
|
||
| template <typename Delay> | ||
| requires(is_numeric_v<Delay>) | ||
| void Dynamics<Delay>::setDestinationNodes(const std::span<Id>& destinationNodes, | ||
| void Dynamics<Delay>::setDestinationNodes(std::span<Id> destinationNodes, | ||
Check noticeCode scanning / Cppcheck (reported by Codacy) MISRA 12.3 rule Note
MISRA 12.3 rule
|
||
| bool updatePaths) { | ||
| for (const auto& nodeId : destinationNodes) { | ||
| if (!m_graph.nodeSet().contains(nodeId)) { | ||
| throw std::invalid_argument( | ||
| buildLog(std::format("Node with id {} not found", nodeId))); | ||
| } | ||
| this->addItinerary(Itinerary{nodeId, nodeId}); | ||
| } | ||
| m_itineraries.resize(destinationNodes.size()); | ||
| std::transform(destinationNodes.cbegin(), | ||
| destinationNodes.cend(), | ||
| m_itineraries.begin(), | ||
| [this](auto nodeId) { | ||
| if (!this->m_graph.nodeSet().contains(nodeId)) { | ||
| throw std::invalid_argument( | ||
| buildLog(std::format("Node with id {} not found", nodeId))); | ||
| } | ||
| this->addItinerary(Itinerary{nodeId}); | ||
| }); | ||
| if (updatePaths) { | ||
| this->updatePaths(); | ||
| } | ||
| } | ||
|
|
||
| template <typename Delay> | ||
| requires(is_numeric_v<Delay>) | ||
| const Itinerary* Dynamics<Delay>::itinerary(Id destination) const { | ||
| auto foundIt = std::find_if(m_itineraries.begin(), | ||
| m_itineraries.end(), | ||
| [destination](const auto& pItinerary) { | ||
| pItinerary->destination() == destination; | ||
| }); | ||
| return (foundIt == m_itineraries.end()) ? nullptr : (*foundIt).get(); | ||
Check noticeCode scanning / Cppcheck (reported by Codacy) MISRA 15.5 rule Note
MISRA 15.5 rule
|
||
| } | ||
|
|
||
| template <typename Delay> | ||
| requires(is_numeric_v<Delay>) | ||
| void Dynamics<Delay>::updatePaths() { | ||
| std::vector<std::thread> threads; | ||
| threads.reserve(m_itineraries.size()); | ||
| std::exception_ptr pThreadException; | ||
| for (const auto& [itineraryId, itinerary] : m_itineraries) { | ||
| for (const auto& itinerary : m_itineraries) { | ||
| threads.emplace_back(std::thread([this, &itinerary, &pThreadException] { | ||
| try { | ||
| this->m_updatePath(itinerary); | ||
|
|
@@ -755,7 +777,7 @@ | |
| } | ||
| // Move transport capacity agents from each node | ||
| for (const auto& [nodeId, pNode] : m_graph.nodeSet()) { | ||
| for (auto i = 0; i < pNode->transportCapacity(); ++i) { | ||
| for (auto i = 0u; i < pNode->transportCapacity(); ++i) { | ||
| if (!this->m_evolveNode(pNode)) { | ||
| break; | ||
| } | ||
|
|
@@ -936,47 +958,49 @@ | |
| } | ||
| template <typename Delay> | ||
| requires(is_numeric_v<Delay>) | ||
| void Dynamics<Delay>::addAgent(Id srcNodeId, Id itineraryId) { | ||
| void Dynamics<Delay>::addAgent(Id srcNodeId, Id dstNodeId) { | ||
| if (this->m_agents.size() + 1 > this->m_graph.maxCapacity()) { | ||
| throw std::overflow_error(buildLog( | ||
| std::format("Graph its already holding the max possible number of agents ({})", | ||
| this->m_graph.maxCapacity()))); | ||
| } | ||
| if (!(srcNodeId < this->m_graph.nodeSet().size())) { | ||
| throw std::invalid_argument( | ||
| buildLog(std::format("Node with id {} not found", srcNodeId))); | ||
| } | ||
| if (!(this->m_itineraries.contains(itineraryId))) { | ||
| throw std::invalid_argument( | ||
| buildLog(std::format("Itinerary with id {} not found", itineraryId))); | ||
| } | ||
| assert((void("Nodes indexes out of range."), | ||
| srcNodeId < this->m_graph.nodeSet().size() && | ||
Check noticeCode scanning / Cppcheck (reported by Codacy) MISRA 12.1 rule Note
MISRA 12.1 rule
|
||
| dstNodeId < this->m_graph.nodeSet().size())); | ||
| assert((void("No itineray associated with the destination node."), | ||
| std::find_if(m_itineraries.begin(), | ||
| m_itineraries.end(), | ||
| [dstNodeId](const std::unique_ptr<Itinerary>& itinerary) { | ||
| return itinerary->destination() == dstNodeId; | ||
Check noticeCode scanning / Cppcheck (reported by Codacy) MISRA 15.5 rule Note
MISRA 15.5 rule
|
||
| }) != m_itineraries.end())); | ||
| Size agentId{0}; | ||
| if (!this->m_agents.empty()) { | ||
| agentId = this->m_agents.rbegin()->first + 1; | ||
| } | ||
| this->addAgent(Agent<Delay>{agentId, itineraryId, srcNodeId}); | ||
| this->addAgent(Agent<Delay>{agentId, dstNodeId, srcNodeId}); | ||
| } | ||
| template <typename Delay> | ||
| requires(is_numeric_v<Delay>) | ||
| void Dynamics<Delay>::addAgents(Id itineraryId, | ||
| void Dynamics<Delay>::addAgents(Id dstNodeId, | ||
| Size nAgents, | ||
| std::optional<Id> srcNodeId) { | ||
| if (this->m_agents.size() + nAgents > this->m_graph.maxCapacity()) { | ||
| throw std::overflow_error(buildLog( | ||
| std::format("Graph its already holding the max possible number of agents ({})", | ||
| this->m_graph.maxCapacity()))); | ||
| } | ||
| auto itineraryIt{m_itineraries.find(itineraryId)}; | ||
| if (itineraryIt == m_itineraries.end()) { | ||
| throw std::invalid_argument( | ||
| buildLog(std::format("Itinerary with id {} not found", itineraryId))); | ||
| } | ||
| assert((void("No itineray associated with the destination node."), | ||
| std::find_if(m_itineraries.begin(), | ||
| m_itineraries.end(), | ||
| [dstNodeId](const std::unique_ptr<Itinerary>& itinerary) { | ||
| return itinerary->destination() == dstNodeId; | ||
Check noticeCode scanning / Cppcheck (reported by Codacy) MISRA 15.5 rule Note
MISRA 15.5 rule
|
||
| }) != m_itineraries.end())); | ||
| Size agentId{0}; | ||
| if (!this->m_agents.empty()) { | ||
| agentId = this->m_agents.rbegin()->first + 1; | ||
| } | ||
| for (Size i{0}; i < nAgents; ++i, ++agentId) { | ||
| this->addAgent(Agent<Delay>{agentId, itineraryId}); | ||
| this->addAgent(Agent<Delay>{agentId, dstNodeId}); | ||
| if (srcNodeId.has_value()) { | ||
| this->m_agents[agentId]->setSourceNodeId(srcNodeId.value()); | ||
| } | ||
|
|
@@ -1031,9 +1055,7 @@ | |
| 0, static_cast<Size>(this->m_graph.streetSet().size() - 1)}; | ||
| for (Size i{0}; i < nAgents; ++i) { | ||
| if (randomItinerary) { | ||
| auto itineraryIt{this->m_itineraries.begin()}; | ||
| std::advance(itineraryIt, itineraryDist(this->m_generator)); | ||
| itineraryId = itineraryIt->first; | ||
| itineraryId = m_itineraries[itineraryDist(m_generator)]->destination(); | ||
| } | ||
| Id agentId{0}; | ||
| if (!this->m_agents.empty()) { | ||
|
|
@@ -1110,16 +1132,13 @@ | |
| } | ||
| } | ||
| } | ||
| // find the itinerary with the given destination as destination | ||
| auto itineraryIt{std::find_if( | ||
| m_itineraries.begin(), m_itineraries.end(), [dstId](const auto& itinerary) { | ||
| return itinerary.second->destination() == dstId; | ||
| })}; | ||
| if (itineraryIt == m_itineraries.end()) { | ||
| throw std::invalid_argument( | ||
| buildLog(std::format("Itinerary with destination {} not found.", dstId))); | ||
| } | ||
| this->addAgent(srcId, itineraryIt->first); | ||
| assert((void("No itineray associated with the destination node."), | ||
| std::find_if(m_itineraries.begin(), | ||
| m_itineraries.end(), | ||
| [dstId](const std::unique_ptr<Itinerary>& itinerary) { | ||
| return itinerary->destination() == dstId; | ||
Check noticeCode scanning / Cppcheck (reported by Codacy) MISRA 15.5 rule Note
MISRA 15.5 rule
|
||
| }) != m_itineraries.end())); | ||
| this->addAgent(srcId, dstId); | ||
| --nAgents; | ||
| } | ||
| } | ||
|
|
@@ -1142,13 +1161,13 @@ | |
| template <typename Delay> | ||
| requires(is_numeric_v<Delay>) | ||
| void Dynamics<Delay>::addItinerary(const Itinerary& itinerary) { | ||
| m_itineraries.emplace(itinerary.id(), std::make_unique<Itinerary>(itinerary)); | ||
| m_itineraries.push_back(std::make_unique<Itinerary>(itinerary)); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. emplace_back?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. push_back should be better in this case |
||
| } | ||
|
|
||
| template <typename Delay> | ||
| requires(is_numeric_v<Delay>) | ||
| void Dynamics<Delay>::addItinerary(std::unique_ptr<Itinerary> itinerary) { | ||
| m_itineraries.emplace(itinerary->id(), std::move(itinerary)); | ||
| m_itineraries.push_back(std::move(itinerary)); | ||
| } | ||
|
|
||
| template <typename Delay> | ||
|
|
@@ -1163,7 +1182,7 @@ | |
| requires(is_numeric_v<Delay>) | ||
| void Dynamics<Delay>::addItineraries(std::span<Itinerary> itineraries) { | ||
| std::ranges::for_each(itineraries, [this](const auto& itinerary) -> void { | ||
| this->m_itineraries.insert(std::make_unique<Itinerary>(itinerary)); | ||
| this->m_itineraries.push_back(std::make_unique<Itinerary>(itinerary)); | ||
| }); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to have a one-line function?