diff --git a/Algorithms/DepthFirstSearch.h b/Algorithms/DepthFirstSearch.h index a685832..492f14b 100644 --- a/Algorithms/DepthFirstSearch.h +++ b/Algorithms/DepthFirstSearch.h @@ -117,7 +117,7 @@ class DepthFirstSearch { template struct SimpleOperation { - SimpleOperation(const GRAPH& graph, const OPERATION& operation) : graph(graph), operation(operation) {} + SimpleOperation(const GRAPH& graph, const OPERATION& operation) : operation(operation), graph(graph) {} inline void operator()(const Edge edge, const Vertex) {operation(graph.get(ToVertex, edge));} OPERATION operation; const GRAPH& graph; diff --git a/Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h b/Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h index 9e1331d..1d065e7 100644 --- a/Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h +++ b/Algorithms/TripBased/Preprocessing/StopEventGraphBuilder.h @@ -111,6 +111,12 @@ class StopEventGraphBuilder { inline void reduceTransfers(const TripId trip) noexcept { timestamp++; + + if (timestamp == 0) { + labels.clear(); + labels.resize(data.numberOfStops()); + } + const StopId* stops = data.stopArrayOfTrip(trip); for (StopIndex i = StopIndex(data.numberOfStopsInTrip(trip) - 1); i > 0; i--) { const int arrivalTime = data.getStopEvent(trip, i).arrivalTime; diff --git a/DataStructures/Graph/Classes/DynamicGraph.h b/DataStructures/Graph/Classes/DynamicGraph.h index be7655f..20fa41d 100644 --- a/DataStructures/Graph/Classes/DynamicGraph.h +++ b/DataStructures/Graph/Classes/DynamicGraph.h @@ -745,6 +745,30 @@ class DynamicGraphImplementation { } // IO: + inline void serialize(IO::Serialization& serialize) const { + serialize(vertexAttributes, edgeAttributes); + } + + inline void deserialize(IO::Deserialization& deserialize) { + clear(); + deserialize(vertexAttributes, edgeAttributes); + for (const Vertex vertex : vertices()) + edgeCount += outDegree(vertex); + Assert(satisfiesInvariants(), "Binary deserialization went wrong"); + } + + inline void serialize(const std::string& fileName) const { + IO::serialize(fileName, vertexAttributes, edgeAttributes); + } + + inline void deserialize(const std::string& fileName) { + clear(); + IO::deserialize(fileName, vertexAttributes, edgeAttributes); + for (const Vertex vertex : vertices()) + edgeCount += outDegree(vertex); + Assert(satisfiesInvariants(), "Binary deserialization went wrong"); + } + inline void writeBinary(const std::string& fileName, const std::string& separator = ".") const noexcept { vertexAttributes.serialize(fileName, separator); edgeAttributes.serialize(fileName, separator); diff --git a/DataStructures/Graph/Classes/EdgeList.h b/DataStructures/Graph/Classes/EdgeList.h index 0c0251e..01dd3b6 100644 --- a/DataStructures/Graph/Classes/EdgeList.h +++ b/DataStructures/Graph/Classes/EdgeList.h @@ -481,6 +481,24 @@ class EdgeListImplementation { } // IO: + inline void serialize(IO::Serialization& serialize) const { + serialize(vertexAttributes, edgeAttributes); + } + + inline void deserialize(IO::Deserialization& deserialize) { + clear(); + deserialize(vertexAttributes, edgeAttributes); + } + + inline void serialize(const std::string& fileName) const { + IO::serialize(fileName, vertexAttributes, edgeAttributes); + } + + inline void deserialize(const std::string& fileName) { + clear(); + IO::deserialize(fileName, vertexAttributes, edgeAttributes); + } + inline void writeBinary(const std::string& fileName, const std::string& separator = ".") const noexcept { vertexAttributes.serialize(fileName, separator); edgeAttributes.serialize(fileName, separator); diff --git a/DataStructures/Graph/Classes/StaticGraph.h b/DataStructures/Graph/Classes/StaticGraph.h index 4cbfc51..f4391b1 100644 --- a/DataStructures/Graph/Classes/StaticGraph.h +++ b/DataStructures/Graph/Classes/StaticGraph.h @@ -179,10 +179,16 @@ class StaticGraphImplementation { // Manipulation: inline void clear() noexcept { + beginOut.clear(); vertexAttributes.clear(); edgeAttributes.clear(); } + inline void removeEdges() noexcept { + std::fill(beginOut.begin(), beginOut.end(), Edge(0)); + edgeAttributes.clear(); + } + inline void reserve(const size_t numVertices, const size_t numEdges) noexcept { beginOut.reserve(numVertices + 1); vertexAttributes.reserve(numVertices); @@ -511,6 +517,26 @@ class StaticGraphImplementation { } // IO: + inline void serialize(IO::Serialization& serialize) const { + serialize(beginOut, vertexAttributes, edgeAttributes); + } + + inline void deserialize(IO::Deserialization& deserialize) { + clear(); + deserialize(beginOut, vertexAttributes, edgeAttributes); + Assert(satisfiesInvariants(), "Invariants not satisfied!"); + } + + inline void serialize(const std::string& fileName) const { + IO::serialize(fileName, beginOut, vertexAttributes, edgeAttributes); + } + + inline void deserialize(const std::string& fileName) { + clear(); + IO::deserialize(fileName, beginOut, vertexAttributes, edgeAttributes); + Assert(satisfiesInvariants(), "Invariants not satisfied!"); + } + inline void writeBinary(const std::string& fileName, const std::string& separator = ".") const noexcept { IO::serialize(fileName + separator + "beginOut", beginOut); vertexAttributes.serialize(fileName, separator); diff --git a/DataStructures/Graph/Utils/IO.h b/DataStructures/Graph/Utils/IO.h index 2de68e1..ca4aca5 100644 --- a/DataStructures/Graph/Utils/IO.h +++ b/DataStructures/Graph/Utils/IO.h @@ -5,8 +5,8 @@ #include "../Classes/GraphInterface.h" #include "../Classes/DynamicGraph.h" -#include "../Classes/StaticGraph.h" #include "../Classes/EdgeList.h" +#include "../Classes/StaticGraph.h" #include "Conversion.h" @@ -17,56 +17,193 @@ namespace Graph { - template - inline void fromDimacs(const std::string& fileBaseName, GRAPH& graph) noexcept { - EdgeList edgeList; - edgeList.fromDimacs(fileBaseName); - move(std::move(edgeList), graph); - } +template +inline void fromDimacs(const std::string &fileBaseName, GRAPH &graph) noexcept { + EdgeList + edgeList; + edgeList.fromDimacs(fileBaseName); + move(std::move(edgeList), graph); +} - template - inline void toDimacs(const std::string& fileBaseName, const GRAPH& graph, const std::vector& weight) noexcept { - std::ofstream grOs(fileBaseName + ".gr"); - Assert(grOs, "Cannot create output stream for " << fileBaseName << ".gr"); - Assert(grOs.is_open(), "Cannot open output stream for " << fileBaseName << ".gr"); - grOs << "p sp " << graph.numVertices() << " " << graph.numEdges() << std::endl; - for (const auto [edge, from] : graph.edgesWithFromVertex()) { - grOs << "a " << (from + 1) << " " << (graph.get(ToVertex, edge) + 1) << " " << weight[edge] << std::endl; - } - grOs.close(); - if constexpr (GRAPH::HasVertexAttribute(Coordinates)) { - std::ofstream coOs(fileBaseName + ".co"); - Assert(coOs, "Cannot create output stream for " << fileBaseName << ".co"); - Assert(coOs.is_open(), "Cannot open output stream for " << fileBaseName << ".co"); - coOs << "p aux sp co " << graph.numVertices() << std::endl; - for (const Vertex vertex : graph.vertices()) { - coOs << "v " << (vertex + 1) << " " << graph.get(Coordinates, vertex).x << " " << graph.get(Coordinates, vertex).y << std::endl; - } - coOs.close(); - } +template +inline void toDimacs(const std::string &fileBaseName, const GRAPH &graph, + const std::vector &weight) noexcept { + std::ofstream grOs(fileBaseName + ".gr"); + Assert(grOs, "Cannot create output stream for " << fileBaseName << ".gr"); + Assert(grOs.is_open(), + "Cannot open output stream for " << fileBaseName << ".gr"); + grOs << "p sp " << graph.numVertices() << " " << graph.numEdges() + << std::endl; + for (const auto [edge, from] : graph.edgesWithFromVertex()) { + grOs << "a " << (from + 1) << " " << (graph.get(ToVertex, edge) + 1) << " " + << weight[edge] << std::endl; + } + grOs.close(); + if constexpr (GRAPH::HasVertexAttribute(Coordinates)) { + std::ofstream coOs(fileBaseName + ".co"); + Assert(coOs, "Cannot create output stream for " << fileBaseName << ".co"); + Assert(coOs.is_open(), + "Cannot open output stream for " << fileBaseName << ".co"); + coOs << "p aux sp co " << graph.numVertices() << std::endl; + for (const Vertex vertex : graph.vertices()) { + coOs << "v " << (vertex + 1) << " " << graph.get(Coordinates, vertex).x + << " " << graph.get(Coordinates, vertex).y << std::endl; } + coOs.close(); + } +} - template - inline void toDimacs(const std::string& fileBaseName, const GRAPH& graph) noexcept { - toDimacs(fileBaseName, graph, graph.get(Weight)); - } +template +inline void toDimacs(const std::string &fileBaseName, + const GRAPH &graph) noexcept { + toDimacs(fileBaseName, graph, graph.get(Weight)); +} + +template +inline void toEdgeListCSV(const std::string &fileBaseName, + const GRAPH &graph) noexcept { + std::ofstream csv(fileBaseName + ".csv"); + Assert(csv, "Cannot create output stream for " << fileBaseName << ".csv"); + Assert(csv.is_open(), + "Cannot open output stream for " << fileBaseName << ".csv"); + + csv << "FromVertex,ToVertex"; - template - inline void toGML(const std::string& fileBaseName, const GRAPH& graph) noexcept { - std::ofstream gml(fileBaseName + ".gml"); - Assert(gml, "Cannot create output stream for " << fileBaseName << ".gml"); - Assert(gml.is_open(), "Cannot open output stream for " << fileBaseName << ".gml"); - gml << "\n"; - gml << "\n"; - gml << " \n"; - for (const Vertex vertex : graph.vertices()) { - gml << " \n"; - } - for (const auto [edge, from] : graph.edgesWithFromVertex()) { - gml << " \n"; - } - gml << " \n"; - gml << "" << std::endl; - gml.close(); + if constexpr (GRAPH::HasEdgeAttribute(TravelTime)) + csv << ",TravelTime"; + if constexpr (GRAPH::HasEdgeAttribute(Distance)) + csv << ",Distance"; + if constexpr (GRAPH::HasEdgeAttribute(ViaVertex)) + csv << ",ViaVertex"; + if constexpr (GRAPH::HasEdgeAttribute(Weight)) + csv << ",Weight"; + if constexpr (GRAPH::HasEdgeAttribute(Capacity)) + csv << ",Capacity"; + if constexpr (GRAPH::HasEdgeAttribute(ReverseEdge)) + csv << ",ReverseEdge"; + + csv << "\n"; + + for (const auto [edge, from] : graph.edgesWithFromVertex()) { + csv << size_t(from) << "," << size_t(graph.get(ToVertex, edge)); + if constexpr (GRAPH::HasEdgeAttribute(TravelTime)) + csv << "," << (int)graph.get(TravelTime, edge); + if constexpr (GRAPH::HasEdgeAttribute(Distance)) + csv << "," << (int)graph.get(Distance, edge); + if constexpr (GRAPH::HasEdgeAttribute(ViaVertex)) + csv << "," << size_t(graph.get(ViaVertex, edge)); + if constexpr (GRAPH::HasEdgeAttribute(Weight)) + csv << "," << (int)graph.get(Weight, edge); + if constexpr (GRAPH::HasEdgeAttribute(Capacity)) + csv << "," << (int)graph.get(Capacity, edge); + if constexpr (GRAPH::HasEdgeAttribute(ReverseEdge)) + csv << "," << size_t(graph.get(ReverseEdge, edge)); + csv << "\n"; + } + csv.close(); +} + +template +inline void toGML(const std::string &fileBaseName, + const GRAPH &graph) noexcept { + std::ofstream gml(fileBaseName + ".graphml"); + Assert(gml, "Cannot create output stream for " << fileBaseName << ".graphml"); + Assert(gml.is_open(), + "Cannot open output stream for " << fileBaseName << ".graphml"); + gml << "\n"; + gml << "\n"; + if constexpr (GRAPH::HasVertexAttribute(Coordinates)) { + gml << " \n"; + gml << " \n"; + } + if constexpr (GRAPH::HasVertexAttribute(Size)) + gml << " \n"; + if constexpr (GRAPH::HasVertexAttribute(Weight)) + gml << " \n"; + if constexpr (GRAPH::HasVertexAttribute(ViaVertex)) + gml << " \n"; + + if constexpr (GRAPH::HasEdgeAttribute(TravelTime)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(Distance)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(Size)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(Weight)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(ReverseEdge)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(Capacity)) + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(ViaVertex)) + gml << " \n"; + gml << " \n"; + + for (const Vertex vertex : graph.vertices()) { + gml << " \n"; + + if constexpr (GRAPH::HasVertexAttribute(Coordinates)) { + gml << " " + << (float)graph.get(Coordinates, vertex).latitude << "\n"; + gml << " " + << (float)graph.get(Coordinates, vertex).longitude << "\n"; } + if constexpr (GRAPH::HasVertexAttribute(Size)) + gml << " " << (int)graph.get(Size, vertex) + << "\n"; + if constexpr (GRAPH::HasVertexAttribute(Weight)) + gml << " " + << (int)graph.get(Weight, vertex) << "\n"; + if constexpr (GRAPH::HasVertexAttribute(ViaVertex)) + gml << " " + << (int)graph.get(ViaVertex, vertex) << "\n"; + + gml << " \n"; + } + for (const auto [edge, from] : graph.edgesWithFromVertex()) { + gml << " \n"; + if constexpr (GRAPH::HasEdgeAttribute(TravelTime)) + gml << " " + << (int)graph.get(TravelTime, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(Distance)) + gml << " " + << (int)graph.get(Distance, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(Size)) + gml << " " << (int)graph.get(Size, edge) + << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(Weight)) + gml << " " + << (int)graph.get(Weight, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(ReverseEdge)) + gml << " " + << (int)graph.get(ReverseEdge, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(Capacity)) + gml << " " + << (int)graph.get(Capacity, edge) << "\n"; + if constexpr (GRAPH::HasEdgeAttribute(ViaVertex)) + gml << " " + << size_t(graph.get(ViaVertex, edge)) << "\n"; + gml << " \n"; + } + gml << " \n"; + gml << "" << std::endl; + gml.close(); } +} // namespace Graph diff --git a/Helpers/IO/ParserCSV.h b/Helpers/IO/ParserCSV.h index c3feaa9..9941e50 100644 --- a/Helpers/IO/ParserCSV.h +++ b/Helpers/IO/ParserCSV.h @@ -178,7 +178,11 @@ class LineReader { } void setFileName(const char* fileName) { - strncpy(this->fileName, fileName, Error::MAX_FILE_NAME_LENGTH); +// https://stackoverflow.com/a/50198710 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" + std::strncpy(this->fileName, fileName, Error::MAX_FILE_NAME_LENGTH); +#pragma GCC diagnostic pop this->fileName[Error::MAX_FILE_NAME_LENGTH] = '\0'; } @@ -260,7 +264,11 @@ struct WithColumnName { WithColumnName() {std::memset(columnName, 0, MAX_COLUMN_NAME_LENGTH + 1);} void setColumnName(const char* columnName) { +// https://stackoverflow.com/a/50198710 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" std::strncpy(this->columnName, columnName, MAX_COLUMN_NAME_LENGTH); +#pragma GCC diagnostic pop this->columnName[MAX_COLUMN_NAME_LENGTH] = '\0'; } @@ -272,7 +280,11 @@ struct WithColumnContent { WithColumnContent() {std::memset(columnContent, 0, MAX_COLUMN_CONTENT_LENGTH + 1);} void setColumnContent(const char*columnContent) { +// https://stackoverflow.com/a/50198710 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-truncation" std::strncpy(this->columnContent, columnContent, MAX_COLUMN_CONTENT_LENGTH); +#pragma GCC diagnostic pop this->columnContent[MAX_COLUMN_CONTENT_LENGTH] = '\0'; } diff --git a/Runnables/downloadExample.sh b/Runnables/downloadExample.sh new file mode 100644 index 0000000..713bd0f --- /dev/null +++ b/Runnables/downloadExample.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Define the target directory and URL +TARGET_DIR="../Datasets/Karlsruhe/GTFS" +ZIP_URL="https://projekte.kvv-efa.de/GTFS/google_transit.zip" +ZIP_FILE="$TARGET_DIR/google_transit.zip" + +# Create the target directory if it doesn't exist +mkdir -p $TARGET_DIR + +# Download the zip file +wget -O $ZIP_FILE $ZIP_URL + +# Extract the zip file into the target directory +unzip -o $ZIP_FILE -d $TARGET_DIR + +# Clean up the zip file +rm $ZIP_FILE + +echo "Download and extraction complete." \ No newline at end of file diff --git a/Runnables/exampleNetwork.script b/Runnables/exampleNetwork.script new file mode 100644 index 0000000..c854492 --- /dev/null +++ b/Runnables/exampleNetwork.script @@ -0,0 +1,9 @@ +parseGTFS ../Datasets/Karlsruhe/GTFS/ ../Datasets/Karlsruhe/GTFS/GTFS.binary +gtfsToIntermediate ../Datasets/Karlsruhe/GTFS/GTFS.binary 20240101 20240102 false false ../Datasets/Karlsruhe/intermediate.binary +reduceToMaximumConnectedComponent ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/intermediate.binary +reduceGraph ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/intermediate.binary +makeOneHopTransfers ../Datasets/Karlsruhe/intermediate.binary 86400 ../Datasets/Karlsruhe/intermediate.binary true +reduceToMaximumConnectedComponent ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/intermediate.binary +reduceGraph ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/intermediate.binary +intermediateToRAPTOR ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/raptor.binary +intermediateToCSA ../Datasets/Karlsruhe/intermediate.binary ../Datasets/Karlsruhe/csa.binary \ No newline at end of file