diff --git a/src/instance/graph/Graph.cpp b/src/instance/graph/Graph.cpp index 65966301d0a1267b9fe52185f8e8449c044b40cc..9d6b9ec03f77fe16d735802825fa662f30fe4cb4 100644 --- a/src/instance/graph/Graph.cpp +++ b/src/instance/graph/Graph.cpp @@ -108,11 +108,16 @@ Graph::Graph(const std::string& datFilePath) { //-- Read Public transit line std::cout << currentRow.toString() << std::endl; - std::uniform_int_distribution<uint32_t> uint_dist10(1,5); - std::uniform_int_distribution<uint32_t> uint_dist60(1,10); - while(infile >> currentRow && !currentRow[0].starts_with('#')) { - this->parseLineRandomizedSchedule(currentRow, rng, uint_dist10, uint_dist60); + if(currentRow[0].starts_with("#PT Line fixed")) { + while(infile >> currentRow && !currentRow[0].starts_with('#')) { + this->parseLineFixedSchedule(infile, currentRow); + } + } else { + while(infile >> currentRow && !currentRow[0].starts_with('#')) { + this->parseLineRandomizedSchedule(currentRow, rng); + } } + //Make links once all lines are created to prevent stale refs this->linkAllPTNodes(); } @@ -249,11 +254,9 @@ void Graph::parseEdgeRow(const DATRow& row) } } -void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng, - std::uniform_int_distribution<uint32_t> travelTimeDistribution, - std::uniform_int_distribution<uint32_t> startTimeDistribution) +void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng) { - int startTime, endTime, frequency, currentNodeIdx; + int startTime, endTime, frequency, minTravelTime, maxTravelTime, currentNodeIdx; //add nodes for the line Line newLine = Line(); //Give it an ID @@ -265,7 +268,11 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng, std::from_chars(row[0].data(), row[0].data() + row[0].size(), frequency); std::from_chars(row[1].data(), row[1].data() + row[1].size(), startTime); std::from_chars(row[2].data(), row[2].data() + row[2].size(), endTime); - int currentTime = startTime + startTimeDistribution(rng); //random startTime time with 60min max offset + std::from_chars(row[3].data(), row[3].data() + row[3].size(), minTravelTime); + std::from_chars(row[4].data(), row[4].data() + row[4].size(), maxTravelTime); + std::uniform_int_distribution<uint32_t> travelTimeDistribution(minTravelTime,maxTravelTime); + + int currentTime = startTime; while(currentTime + frequency < endTime) { timeTable.push_back(currentTime + frequency); @@ -282,7 +289,7 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng, //Create subsequent timetables according to preceding timetable and travel time for(size_t i = 1; i < newLine.getNodes().size(); ++i) { - int travelTime = travelTimeDistribution(rng); //FIXME travel time is randomized for now, we should get edge length if it exists I guess + uint travelTime = travelTimeDistribution(rng); std::vector<int> precedingTimeTable = newLine.getTimetable(i - 1); std::vector<int> newTimetable; newTimetable.reserve(precedingTimeTable.size()); //Reserve to improve foreach efficiency @@ -292,9 +299,43 @@ void Graph::parseLineRandomizedSchedule(const DATRow& row, std::mt19937 rng, newLine.addTimetable(newTimetable); newTimetable.clear(); } + //Check for errors + if(newLine.check()) { + this->addLine(newLine); + DEBUG_MSG("Created new line with randomized schedule"); + } +} + +void Graph::parseLineFixedSchedule(std::ifstream& infile, DATRow& row) { + Line newLine = Line(); + + // First line consists of the list of node indexes, add them all to the new line + uint currentNodeIdx; + for(uint i = 0; i < row.size(); ++i) + { + std::from_chars(row[i].data(), row[i].data() + row[i].size(), currentNodeIdx); + newLine.addNode(currentNodeIdx); + } + + // Read schedule until hitting an empty line, used to separate individual lines to parse + std::vector<std::vector<int>> newSchedules; + while(infile >> row && !row[0].empty()) { + assertm(row.size() == newLine.size(), "Schedule size doesn't correspond to the number of nodes"); + // Add the time to the appropriate station's schedule vector + for(uint stationIdx = 0; stationIdx < row.size(); ++stationIdx) { + newSchedules[stationIdx].emplace_back(std::stoi(row[stationIdx].data())); + } + } + + //Add properly formatted timetables to the new line in station order + for(const std::vector<int>& stationSchedule : newSchedules) { + newLine.addTimetable(stationSchedule); + } + + //Check for errors if(newLine.check()) { this->addLine(newLine); - DEBUG_MSG("Created new line with nodes"); + DEBUG_MSG("Created new line with fixed schedule"); } } diff --git a/src/instance/graph/Graph.h b/src/instance/graph/Graph.h index 050ee93fb99e67b21e123dc693eb35f599713635..f1baeeafef1be3459940e8d625638f9d6337e407 100644 --- a/src/instance/graph/Graph.h +++ b/src/instance/graph/Graph.h @@ -13,10 +13,11 @@ #include "Node.h" #include "Edge.h" -#include "../../ShortestPath/Vehicle/VehicleShortestPathCalculation.h" +#include "../../utils/Globals.h" #include "../../utils/Constants.h" -#include "../../ShortestPath/Transit/TransitShortestPathContainer.h" -#include "../../ShortestPath/Transit/TransitShortestPathPrecompute.h" +#include "../../algorithm/ShortestPath/Vehicle/VehicleShortestPathCalculation.h" +#include "../../algorithm/ShortestPath/Transit/TransitShortestPathContainer.h" +#include "../../algorithm/ShortestPath/Transit/TransitShortestPathPrecompute.h" class DATRow; class Graph { @@ -34,11 +35,41 @@ private: * @return True if @this is properly referenced in the Line object at the expected index */ bool checkLineToNodeLinks(); + /** + * Parses and adds a node from the given row object to the graph.<br> + * Format : status,x_coordinate,y_coordinate + * @param row row extracted from the input file + */ void parseNodeRow(const DATRow& row); + /** + * Parses and adds an edge from the given row object to the graph.<br> + * Format : start_node_idx,end_node_idx,length + * @param row row extracted from the input file + */ void parseEdgeRow(const DATRow& row); - void parseLineRandomizedSchedule(const DATRow &row, std::mt19937 rng, - std::uniform_int_distribution<uint32_t> travelTimeDistribution, - std::uniform_int_distribution<uint32_t> startTimeDistribution); + + /** + * Parses and adds a line to the graph from a given row object and reusing the given seeded rng engine. + * Uses the format : <br> + * frequency,start_time,end_time,min_travel_time,max_travel_time,node_0, ..., node_n + * @param row row containing the necessary info to generate a random line + * @param rng seeded random number generator + */ + void parseLineRandomizedSchedule(const DATRow &row, std::mt19937 rng); + + /** + * Parses and adds a line to the graph from the given row in given the following format : <br> + * node_0_idx, ... node_n_idx <br> + * node_0_pass_0_time, ... node_n_pass_0_time <br> + * ... <br> + * node_0_pass_m_time, ... node_n_pass_m_time <br> + * <br> + * /!\ each transit line to parse ends with an empty line + * + * @param infile input file stream, necessary to iterate over multiple lines in the function + * @param row the current DATrow object we reuse from other parsing functions + */ + void parseLineFixedSchedule(std::ifstream& infile, DATRow& row); public: [[nodiscard]] const std::vector<Node> &getNodesVector() const {