Skip to content

Commit

Permalink
Merge branch 'main' into feature_dynamic_class
Browse files Browse the repository at this point in the history
  • Loading branch information
Grufoony authored Dec 14, 2023
2 parents 6f1d480 + 5e0b50a commit 49df828
Show file tree
Hide file tree
Showing 18 changed files with 476 additions and 135 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Pylint

on: [push]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pylint
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Analysing the code with pylint
run: |
pylint $(git ls-files '*.py')
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@

# valgrind generated files
*vgcore.*

# cache files
*cache
2 changes: 1 addition & 1 deletion benchmark/Street/BenchStreet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ using Bench = sb::Bench<long long int>;

int main() {
Street street(0, 1000, 10., std::make_pair(0, 1));
Agent agent(0, 0);
Agent agent(0, 0, 0);
Bench b(1000);

std::cout << "Benchmarking enqueue\n";
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
osmnx==1.8.0
1 change: 0 additions & 1 deletion src/dsm/dsm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include "headers/Node.hpp"
#include "headers/SparseMatrix.hpp"
#include "headers/Street.hpp"
#include "utility/HashFunctions.hpp"
#include "utility/TypeTraits/is_node.hpp"
#include "utility/TypeTraits/is_street.hpp"
#include "utility/TypeTraits/is_numeric.hpp"
Expand Down
63 changes: 29 additions & 34 deletions src/dsm/headers/Agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <stdexcept>
#include <string>
#include <limits>
#include <optional>

namespace dsm {
/// @brief The Agent class represents an agent in the network.
Expand All @@ -29,31 +30,30 @@ namespace dsm {
requires std::unsigned_integral<Id> && std::unsigned_integral<Size> && is_numeric_v<Delay>
class Agent {
private:
Itinerary<Id> m_itinerary;
double m_speed;
Id m_id;
Id m_itineraryId;
std::optional<Id> m_streetId;
Delay m_delay;
Id m_index;
Id m_streetId;
double m_speed;
unsigned int m_time;

public:
Agent() = delete;
/// @brief Construct a new Agent object
/// @param index The agent's id
/// @param streetId The id of the street currently occupied by the agent
Agent(Id index, Id streetId);
/// @param id The agent's id
/// @param itineraryId The agent's itinerary
Agent(Id id, Id itineraryId);
/// @brief Construct a new Agent object
/// @param index The agent's id
/// @param id The agent's id
/// @param itineraryId The agent's itinerary
/// @param streetId The id of the street currently occupied by the agent
/// @param itinerary The agent's itinerary
Agent(Id index, Id streetId, Itinerary<Id> itinerary);

Agent(Id id, Id itineraryId, Id streetId);
/// @brief Set the street occupied by the agent
/// @param streetId The id of the street currently occupied by the agent
void setStreetId(Id streetId);
/// @brief Set the agent's itinerary
/// @param itinerary, The agent's itinerary
void setItinerary(Itinerary<Id> itinerary);
/// @param itineraryId The agent's itinerary
void setItineraryId(Id itineraryId);
/// @brief Set the agent's speed
/// @param speed, The agent's speed
/// @throw std::invalid_argument, if speed is negative
Expand All @@ -80,13 +80,13 @@ namespace dsm {

/// @brief Get the agent's id
/// @return The agent's id
Id index() const;
/// @brief Get the id of the street currently occupied by the agent
/// @return The id of the street currently occupied by the agent
Id streetId() const;
Id id() const;
/// @brief Get the agent's itinerary
/// @return The agent's itinerary
const Itinerary<Id>& itinerary() const;
Id itineraryId() const;
/// @brief Get the id of the street currently occupied by the agent
/// @return The id of the street currently occupied by the agent
std::optional<Id> streetId() const;
/// @brief Get the agent's speed
/// @return The agent's speed
double speed() const;
Expand All @@ -100,18 +100,13 @@ namespace dsm {

template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> && is_numeric_v<Delay>)
Agent<Id, Size, Delay>::Agent(Id index, Id streetId)
: m_speed{0.}, m_delay{0}, m_index{index}, m_streetId{streetId}, m_time{0} {}
Agent<Id, Size, Delay>::Agent(Id id, Id itineraryId)
: m_id{id}, m_itineraryId{itineraryId}, m_delay{0}, m_speed{0.}, m_time{0} {}

template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> && is_numeric_v<Delay>)
Agent<Id, Size, Delay>::Agent(Id index, Id streetId, Itinerary<Id> itinerary)
: m_itinerary{std::move(itinerary)},
m_speed{0.},
m_delay{0},
m_index{index},
m_streetId{streetId},
m_time{0} {}
Agent<Id, Size, Delay>::Agent(Id id, Id itineraryId, Id streetId)
: m_id{id}, m_itineraryId{itineraryId}, m_streetId{streetId}, m_delay{0}, m_speed{0.}, m_time{0} {}

template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> && is_numeric_v<Delay>)
Expand All @@ -121,8 +116,8 @@ namespace dsm {

template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> && is_numeric_v<Delay>)
void Agent<Id, Size, Delay>::setItinerary(Itinerary<Id> itinerary) {
m_itinerary = std::move(itinerary);
void Agent<Id, Size, Delay>::setItineraryId(Id itineraryId) {
m_itineraryId = itineraryId;
}

template <typename Id, typename Size, typename Delay>
Expand Down Expand Up @@ -190,13 +185,13 @@ namespace dsm {

template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> && is_numeric_v<Delay>)
Id Agent<Id, Size, Delay>::index() const {
return m_index;
Id Agent<Id, Size, Delay>::id() const {
return m_id;
}

template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> && is_numeric_v<Delay>)
Id Agent<Id, Size, Delay>::streetId() const {
std::optional<Id> Agent<Id, Size, Delay>::streetId() const {
return m_streetId;
}

Expand All @@ -220,8 +215,8 @@ namespace dsm {

template <typename Id, typename Size, typename Delay>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size> && is_numeric_v<Delay>)
const Itinerary<Id>& Agent<Id, Size, Delay>::itinerary() const {
return m_itinerary;
Id Agent<Id, Size, Delay>::itineraryId() const {
return m_itineraryId;
}
}; // namespace dsm

Expand Down
164 changes: 153 additions & 11 deletions src/dsm/headers/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <utility>
#include <string>
#include <fstream>
#include <sstream>

#include "Node.hpp"
#include "SparseMatrix.hpp"
Expand All @@ -47,6 +48,7 @@ namespace dsm {
std::unordered_map<Id, shared<Node<Id, Size>>> m_nodes;
std::unordered_map<Id, shared<Street<Id, Size>>> m_streets;
shared<SparseMatrix<Id, bool>> m_adjacency;
std::unordered_map<Id, Id> m_nodeMapping;

public:
Graph();
Expand All @@ -60,11 +62,22 @@ namespace dsm {
/// @brief Build the graph's adjacency matrix
void buildAdj();

/// @brief Import the graph's adjacency matrix from a file
/// @brief Import the graph's adjacency matrix from a file.
/// If the file is not of a supported format, it will read the file as a matrix with the first two elements being
/// 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.
/// @throws std::invalid_argument if the file is not found, invalid or the format is not supported
/// @param isAdj A boolean value indicating if the file contains the adjacency matrix or the distance matrix.
/// @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 importAdj(const std::string& fileName);
void importMatrix(const std::string& fileName, bool isAdj = true);
/// @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
void importOSMNodes(const std::string& fileName);
/// @brief Import the graph's streets from a file
/// @param fileName The name of the file to import the streets from.
/// @throws std::invalid_argument if the file is not found, invalid or the format is not supported
void importOSMEdges(const std::string& fileName);

/// @brief Add a node to the graph
/// @param node, A std::shared_ptr to the node to add
Expand Down Expand Up @@ -172,22 +185,22 @@ namespace dsm {

template <typename Id, typename Size>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size>)
void Graph<Id, Size>::importAdj(const std::string& fileName) {
void Graph<Id, Size>::importMatrix(const std::string& fileName, bool isAdj) {
// check the file extension
std::string fileExt = fileName.substr(fileName.find_last_of(".") + 1);
if (fileExt == "dsm") {
std::ifstream file(fileName);
std::ifstream file{fileName};
if (!file.is_open()) {
std::string errrorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"File not found"};
throw std::invalid_argument(errrorMsg);
std::string errorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"File not found"};
throw std::invalid_argument(errorMsg);
}
Id rows, cols;
file >> rows >> cols;
if (rows != cols) {
std::string errrorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"Adjacency matrix must be square"};
throw std::invalid_argument(errrorMsg);
std::string errorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"Adjacency matrix must be square"};
throw std::invalid_argument(errorMsg);
}
m_adjacency = make_shared<SparseMatrix<Id, bool>>(rows, cols);
// each line has (should have) 3 elements
Expand All @@ -202,6 +215,135 @@ namespace dsm {
m_nodes.insert_or_assign(node2, make_shared<Node<Id, Size>>(node2));
m_streets.insert_or_assign(index,
make_shared<Street<Id, Size>>(index, std::make_pair(node1, node2)));
if (!isAdj) {
m_streets[index]->setLength(val);
}
}
} else {
// default case: read the file as a matrix with the first two elements being the number of rows and columns and
// the following elements being the matrix elements
std::ifstream file{fileName};
if (!file.is_open()) {
std::string errorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"File not found"};
throw std::invalid_argument(errorMsg);
}
Id rows, cols;
file >> rows >> cols;
if (rows != cols) {
std::string errorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"Adjacency matrix must be square"};
throw std::invalid_argument(errorMsg);
}
m_adjacency = make_shared<SparseMatrix<Id, bool>>(rows, cols);
Id index{0};
while (!file.eof()) {
double value;
file >> value;
if (value < 0) {
std::string errorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"Adjacency matrix elements must be positive"};
throw std::invalid_argument(errorMsg);
}
if (value > 0) {
m_adjacency->insert(index, true);
const Id node1{static_cast<Id>(index / rows)};
const Id node2{static_cast<Id>(index % cols)};
m_nodes.insert_or_assign(node1, make_shared<Node<Id, Size>>(node1));
m_nodes.insert_or_assign(node2, make_shared<Node<Id, Size>>(node2));
m_streets.insert_or_assign(index,
make_shared<Street<Id, Size>>(index, std::make_pair(node1, node2)));
if (!isAdj) {
m_streets[index]->setLength(value);
}
}
++index;
}
}
}

template <typename Id, typename Size>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size>)
void Graph<Id, Size>::importOSMNodes(const std::string& fileName) {
std::string fileExt = fileName.substr(fileName.find_last_of(".") + 1);
if (fileExt == "csv") {
std::ifstream file{fileName};
if (!file.is_open()) {
std::string errrorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"File not found"};
throw std::invalid_argument(errrorMsg);
}
std::string line;
std::getline(file, line); // skip first line
Id nodeIndex{0};
while (!file.eof()) {
std::getline(file, line);
if (line.empty()) {
continue;
}
std::istringstream iss{line};
std::string id, lat, lon, highway;
// osmid;x;y;highway
std::getline(iss, id, ';');
std::getline(iss, lat, ';');
std::getline(iss, lon, ';');
std::getline(iss, highway, ';');
Id nodeId{static_cast<Id>(std::stoul(id))};
m_nodes.insert_or_assign(
nodeIndex,
make_shared<Node<Id, Size>>(nodeIndex, std::make_pair(std::stod(lat), std::stod(lon))));
m_nodeMapping.emplace(std::make_pair(nodeId, nodeIndex));
++nodeIndex;
}
} else {
std::string errrorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"File extension not supported"};
throw std::invalid_argument(errrorMsg);
}
}

template <typename Id, typename Size>
requires(std::unsigned_integral<Id> && std::unsigned_integral<Size>)
void Graph<Id, Size>::importOSMEdges(const std::string& fileName) {
std::string fileExt = fileName.substr(fileName.find_last_of(".") + 1);
if (fileExt == "csv") {
std::ifstream file{fileName};
if (!file.is_open()) {
std::string errrorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
"File not found"};
throw std::invalid_argument(errrorMsg);
}
std::string line;
std::getline(file, line); // skip first line
while (!file.eof()) {
std::getline(file, line);
if (line.empty()) {
continue;
}
std::istringstream iss{line};
std::string sourceId, targetId, length, oneway, highway, maxspeed, bridge;
// u;v;length;oneway;highway;maxspeed;bridge
std::getline(iss, sourceId, ';');
std::getline(iss, targetId, ';');
std::getline(iss, length, ';');
std::getline(iss, oneway, ';');
std::getline(iss, highway, ';');
std::getline(iss, maxspeed, ';');
std::getline(iss, bridge, ';');
try {
std::stod(maxspeed);
} catch (const std::invalid_argument& e) {
maxspeed = "30";
}
Id streetId = std::stoul(sourceId) + std::stoul(targetId) * m_nodes.size();
m_streets.insert_or_assign(
streetId,
make_shared<Street<Id, Size>>(
streetId,
1,
std::stod(maxspeed),
std::stod(length),
std::make_pair(m_nodeMapping[std::stoul(sourceId)], m_nodeMapping[std::stoul(targetId)])));
}
} else {
std::string errrorMsg{"Error at line " + std::to_string(__LINE__) + " in file " + __FILE__ + ": " +
Expand Down
Loading

0 comments on commit 49df828

Please sign in to comment.