Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 examples/slow_charge_rb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ int main(int argc, char** argv) {
std::cout << "Number of exits: " << n << '\n';

dynamics.setErrorProbability(0.05);
dynamics.setMaxFlowPercentage(0.7707);
dynamics.setPassageProbability(0.7707);
// dynamics.setForcePriorities(true);
dynamics.setSpeedFluctuationSTD(0.1);

Expand Down
8 changes: 5 additions & 3 deletions examples/stalingrado.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
Street s01{1, 2281 / 8, 2281., 13.9, std::make_pair(0, 1)};
Street s12{7, 118 / 8, 118., 13.9, std::make_pair(1, 2)};
Street s23{13, 222 / 8, 222., 13.9, std::make_pair(2, 3)};
Street s34{19, 651 / 4, 651., 13.9, std::make_pair(3, 4)};
Street s34{19, 1, 651., 13.9, std::make_pair(3, 4), 2};

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
// Viale Aldo Moro
TrafficLight tl1{1, 132};
tl1.setCycle(s01.id(), dsm::Direction::ANY, {62, 0});
Expand All @@ -76,6 +76,8 @@
graph.addNode(std::make_unique<TrafficLight>(tl4));
graph.addStreets(s01, s12, s23, s34);
graph.buildAdj();
graph.adjustNodeCapacities();
graph.normalizeStreetCapacities();
auto& spire = graph.makeSpireStreet(19);

std::cout << "Intersections: " << graph.nNodes() << '\n';
Expand All @@ -84,7 +86,7 @@
// Create the dynamics
Dynamics dynamics{graph, 69, 0.95};
dynamics.setSpeedFluctuationSTD(0.2);
Itinerary itinerary{0, 4};
Itinerary itinerary{4, 4};
dynamics.addItinerary(itinerary);
dynamics.updatePaths();

Expand All @@ -108,7 +110,7 @@
if (progress % 300 == 0) {
ofs << progress << ';' << spire.outputCounts(true) << std::endl;
}
dynamics.addAgents(0, *it / 2, 0);
dynamics.addAgents(4, *it / 2, 0);
}
dynamics.evolve(false);
++progress;
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 = 2;
static constexpr uint8_t DSM_VERSION_PATCH = 5;
static constexpr uint8_t DSM_VERSION_PATCH = 6;

static auto const DSM_VERSION =
std::format("{}.{}.{}", DSM_VERSION_MAJOR, DSM_VERSION_MINOR, DSM_VERSION_PATCH);
Expand Down
14 changes: 10 additions & 4 deletions src/dsm/headers/Agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@
public:
/// @brief Construct a new Agent object
/// @param id The agent's id
/// @param itineraryId The agent's itinerary
/// @param itineraryId Optional, The agent's destination node. If not provided, the agent is a random agent
/// @param srcNodeId Optional, The id of the source node of the agent
Agent(Id id, Id itineraryId, std::optional<Id> srcNodeId = std::nullopt);
Agent(Id id,
std::optional<Id> itineraryId = std::nullopt,
std::optional<Id> srcNodeId = std::nullopt);
/// @brief Construct a new Agent object
/// @param id The agent's id
/// @param itineraryIds The agent's itinerary
Expand Down Expand Up @@ -123,13 +125,17 @@
/// @brief Get the agent's travel time
/// @return The agent's travel time
unsigned int time() const { return m_time; }
/// @brief Return true if the agent is a random agent
/// @return True if the agent is a random agent, false otherwise
bool isRandom() const { return m_trip.empty(); }
};

template <typename delay_t>
requires(is_numeric_v<delay_t>)
Agent<delay_t>::Agent(Id id, Id itineraryId, std::optional<Id> srcNodeId)
Agent<delay_t>::Agent(Id id, std::optional<Id> itineraryId, std::optional<Id> srcNodeId)

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
: m_id{id},
m_trip{itineraryId},
m_trip{itineraryId.has_value() ? std::vector<Id>{itineraryId.value()}
: std::vector<Id>{}},

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
m_srcNodeId{srcNodeId},
m_delay{0},
m_speed{0.},
Expand Down
22 changes: 21 additions & 1 deletion src/dsm/headers/Dynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@
const TContainer& src_weights,
const TContainer& dst_weights);

void addRandomAgents(Size nAgents, std::optional<Id> srcNodeId = std::nullopt);

/// @brief Remove an agent from the simulation
/// @param agentId the id of the agent to remove
void removeAgent(Size agentId);
Expand Down Expand Up @@ -239,6 +241,9 @@
/// @brief Get the agents
/// @return const std::unordered_map<Id, Agent<Id>>&, The agents
const std::map<Id, std::unique_ptr<agent_t>>& agents() const { return m_agents; }
/// @brief Get the number of agents currently in the simulation
/// @return Size The number of agents
const Size nAgents() const { return m_agents.size(); }
/// @brief Get the time
/// @return Time The time
Time time() const { return m_time; }
Expand Down Expand Up @@ -374,7 +379,7 @@
agentId = m_agents.rbegin()->first + 1;
}
this->addAgent(agent_t{agentId, itineraryId, srcNodeId});
}

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
template <typename agent_t>
void Dynamics<agent_t>::addAgents(Id itineraryId,
Size nAgents,
Expand Down Expand Up @@ -556,13 +561,28 @@
}
}

template <typename agent_t>
void Dynamics<agent_t>::addRandomAgents(Size nAgents, std::optional<Id> srcNodeId) {
if (m_agents.size() + nAgents > m_graph.maxCapacity()) {
throw std::overflow_error(buildLog(
std::format("Graph is already holding the max possible number of agents ({})",
m_graph.maxCapacity())));
}
Id agentId{0};
if (!m_agents.empty()) {
agentId = m_agents.rbegin()->first + 1;
}
for (auto i{0}; i < nAgents; ++i, ++agentId) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
this->addAgent(agent_t{agentId, srcNodeId});
}
}

template <typename agent_t>
void Dynamics<agent_t>::removeAgent(Size agentId) {
m_agents.erase(agentId);
}

template <typename agent_t>

template <typename T1, typename... Tn>
requires(std::is_convertible_v<T1, Size> && (std::is_convertible_v<Tn, Size> && ...))
void Dynamics<agent_t>::removeAgents(T1 id, Tn... ids) {
Expand Down
4 changes: 3 additions & 1 deletion src/dsm/headers/Graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ namespace dsm {
}
}

void Graph::importMatrix(const std::string& fileName, bool isAdj) {
void Graph::importMatrix(const std::string& fileName, bool isAdj, double defaultSpeed) {
// check the file extension
std::string fileExt = fileName.substr(fileName.find_last_of(".") + 1);
if (fileExt == "dsm") {
Expand Down Expand Up @@ -178,6 +178,7 @@ namespace dsm {
if (!isAdj) {
m_streets[index]->setLength(val);
}
m_streets[index]->setMaxSpeed(defaultSpeed);
}
} else {
// default case: read the file as a matrix with the first two elements being the number of rows and columns and
Expand Down Expand Up @@ -223,6 +224,7 @@ namespace dsm {
if (!isAdj) {
m_streets[index]->setLength(value);
}
m_streets[index]->setMaxSpeed(defaultSpeed);
}
++index;
}
Expand Down
5 changes: 4 additions & 1 deletion src/dsm/headers/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,12 @@
/// the number of rows and columns and the following elements being the matrix elements.
/// @param fileName The name of the file to import the adjacency matrix from.
/// @param isAdj A boolean value indicating if the file contains the adjacency matrix or the distance matrix.
/// @param defaultSpeed The default speed limit for the streets
/// @throws std::invalid_argument if the file is not found or invalid
/// The matrix format is deduced from the file extension. Currently only .dsm files are supported.
void importMatrix(const std::string& fileName, bool isAdj = true);
void importMatrix(const std::string& fileName,
bool isAdj = true,

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.8 rule Note

MISRA 17.8 rule
double defaultSpeed = 13.8888888889);

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 17.8 rule Note

MISRA 17.8 rule
/// @brief Import the graph's nodes from a file
/// @param fileName The name of the file to import the nodes from.
/// @throws std::invalid_argument if the file is not found, invalid or the format is not supported
Expand Down
82 changes: 52 additions & 30 deletions src/dsm/headers/RoadDynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
protected:
Time m_previousOptimizationTime;
double m_errorProbability;
double m_maxFlowPercentage;
double m_passageProbability;
std::vector<double> m_travelTimes;
std::unordered_map<Id, Id> m_agentNextStreetId;
bool m_forcePriorities;
Expand Down Expand Up @@ -88,11 +88,8 @@
/// @param errorProbability The error probability
/// @throw std::invalid_argument If the error probability is not between 0 and 1
void setErrorProbability(double errorProbability);
/// @brief Set the maximum flow percentage
/// @param maxFlowPercentage The maximum flow percentage
/// @details The maximum flow percentage is the percentage of the maximum flow that a street can transmit. Default is 1 (100%).
/// @throw std::invalid_argument If the maximum flow percentage is not between 0 and 1
void setMaxFlowPercentage(double maxFlowPercentage);

void setPassageProbability(double passageProbability);
/// @brief Set the force priorities flag
/// @param forcePriorities The flag
/// @details If true, if an agent cannot move to the next street, the whole node is skipped
Expand Down Expand Up @@ -151,7 +148,7 @@
: Dynamics<Agent<delay_t>>(graph, seed),
m_previousOptimizationTime{0},
m_errorProbability{0.},
m_maxFlowPercentage{1.},
m_passageProbability{1.},

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.3 rule Note

MISRA 12.3 rule
m_forcePriorities{false} {
for (const auto& [streetId, street] : this->m_graph.streetSet()) {
m_streetTails.emplace(streetId, 0);
Expand Down Expand Up @@ -183,13 +180,16 @@
Id RoadDynamics<delay_t>::m_nextStreetId(Id agentId,
Id nodeId,
std::optional<Id> streetId) {
auto const& pAgent{this->m_agents[agentId]};
auto possibleMoves = this->m_graph.adjMatrix().getRow(nodeId, true);
std::uniform_real_distribution<double> uniformDist{0., 1.};
if (this->m_itineraries.size() > 0 &&
uniformDist(this->m_generator) > m_errorProbability) {
const auto& it = this->m_itineraries[this->m_agents[agentId]->itineraryId()];
if (it->destination() != nodeId) {
possibleMoves = it->path().getRow(nodeId, true);
if (!pAgent->isRandom()) {
std::uniform_real_distribution<double> uniformDist{0., 1.};
if (this->m_itineraries.size() > 0 &&
uniformDist(this->m_generator) > m_errorProbability) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
const auto& it = this->m_itineraries[pAgent->itineraryId()];
if (it->destination() != nodeId) {
possibleMoves = it->path().getRow(nodeId, true);
}
}
}
assert(possibleMoves.size() > 0);
Expand Down Expand Up @@ -233,8 +233,7 @@
auto const nLanes = pStreet->nLanes();
std::uniform_real_distribution<double> uniformDist{0., 1.};
for (auto queueIndex = 0; queueIndex < nLanes; ++queueIndex) {
if (uniformDist(this->m_generator) > m_maxFlowPercentage ||
pStreet->queue(queueIndex).empty()) {
if (pStreet->queue(queueIndex).empty()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
continue;
}
const auto agentId{pStreet->queue(queueIndex).front()};
Expand All @@ -254,8 +253,23 @@
continue;
}
}
if (destinationNode->id() ==
this->m_itineraries[pAgent->itineraryId()]->destination()) {
auto const bCanPass = uniformDist(this->m_generator) < m_passageProbability;
bool bArrived{false};
if (!bCanPass) {
if (pAgent->isRandom()) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
m_agentNextStreetId.erase(agentId);
bArrived = true;
} else {
continue;
}
}
if (!pAgent->isRandom()) {
if (destinationNode->id() ==
this->m_itineraries[pAgent->itineraryId()]->destination()) {
bArrived = true;
}
}
if (bArrived) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
pStreet->dequeue(queueIndex);
m_travelTimes.push_back(pAgent->time());
if (reinsert_agents) {
Expand Down Expand Up @@ -345,6 +359,8 @@
template <typename delay_t>
requires(is_numeric_v<delay_t>)
void RoadDynamics<delay_t>::m_evolveAgents() {
std::uniform_int_distribution<Id> nodeDist{
0, static_cast<Id>(this->m_graph.nNodes() - 1)};
for (const auto& [agentId, agent] : this->m_agents) {
if (agent->delay() > 0) {
const auto& street{this->m_graph.streetSet()[agent->streetId().value()]};
Expand All @@ -361,12 +377,18 @@
agent->decrementDelay();
if (agent->delay() == 0) {
auto const nLanes = street->nLanes();
if (this->m_itineraries[agent->itineraryId()]->destination() ==
street->nodePair().second) {
agent->updateItinerary();
bool bArrived{false};
if (!agent->isRandom()) {
if (this->m_itineraries[agent->itineraryId()]->destination() ==
street->nodePair().second) {
agent->updateItinerary();
}
if (this->m_itineraries[agent->itineraryId()]->destination() ==
street->nodePair().second) {
bArrived = true;
}
}
if (this->m_itineraries[agent->itineraryId()]->destination() ==
street->nodePair().second) {
if (bArrived) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 14.4 rule Note

MISRA 14.4 rule
std::uniform_int_distribution<size_t> laneDist{
0, static_cast<size_t>(nLanes - 1)};
street->enqueue(agentId, laneDist(this->m_generator));
Expand Down Expand Up @@ -398,8 +420,9 @@
}
} else if (!agent->streetId().has_value() &&
!m_agentNextStreetId.contains(agentId)) {
assert(agent->srcNodeId().has_value());
const auto& srcNode{this->m_graph.nodeSet()[agent->srcNodeId().value()]};
Id srcNodeId = agent->srcNodeId().has_value() ? agent->srcNodeId().value()
: nodeDist(this->m_generator);
const auto& srcNode{this->m_graph.nodeSet()[srcNodeId]};
if (srcNode->isFull()) {
continue;
}
Expand Down Expand Up @@ -436,13 +459,12 @@

template <typename delay_t>
requires(is_numeric_v<delay_t>)
void RoadDynamics<delay_t>::setMaxFlowPercentage(double maxFlowPercentage) {
if (maxFlowPercentage < 0. || maxFlowPercentage > 1.) {
throw std::invalid_argument(
buildLog(std::format("The maximum flow percentage ({}) must be between 0 and 1",
maxFlowPercentage)));
void RoadDynamics<delay_t>::setPassageProbability(double passageProbability) {
if (passageProbability < 0. || passageProbability > 1.) {

Check notice

Code scanning / Cppcheck (reported by Codacy)

MISRA 12.1 rule Note

MISRA 12.1 rule
throw std::invalid_argument(buildLog(std::format(
"The passage probability ({}) must be between 0 and 1", passageProbability)));
}
m_maxFlowPercentage = maxFlowPercentage;
m_passageProbability = passageProbability;
}

template <typename delay_t>
Expand Down
7 changes: 7 additions & 0 deletions test/Test_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,12 @@ TEST_CASE("Agent") {
}
}
}
GIVEN("An agent it") {
uint16_t agentId{1};
WHEN("The agent is constructed") {
auto randomAgent = Agent{agentId};
THEN("The agent is a random agent") { CHECK(randomAgent.isRandom()); }
}
}
}
}
Loading
Loading