diff --git a/src/graph.cpp b/src/graph.cpp index 11d319e..65c3942 100644 --- a/src/graph.cpp +++ b/src/graph.cpp @@ -17,7 +17,7 @@ void Graph::add_edge(int source, int target, int weight) { adjList[target].emplace_back(source, weight); } -// Trouver le chemin le plus court entre deux nœuds +// Trouver le chemin le plus court entre deux nœuds avec une optimisation bidirectionnelle std::vector Graph::shortest_path(int source, int target, int& totalTime) { constexpr int INF = std::numeric_limits::max(); @@ -29,6 +29,7 @@ std::vector Graph::shortest_path(int source, int target, int& totalTime) { size_t n = adjList.size(); std::vector distForward(n, INF), distBackward(n, INF); std::vector prevForward(n, -1), prevBackward(n, -1); + std::vector processedForward(n, false), processedBackward(n, false); distForward[source] = 0; distBackward[target] = 0; @@ -47,26 +48,30 @@ std::vector Graph::shortest_path(int source, int target, int& totalTime) { int bestCost = INF; int meetingNode = -1; - // Process nodes alternately in forward and backward directions - while (!pqForward.empty() && !pqBackward.empty()) { - // Expand forward + // Processus bidirectionnel + while (!pqForward.empty() || !pqBackward.empty()) { + // Expansion dans la direction avant if (!pqForward.empty()) { - auto [currentF, current] = pqForward.top(); + auto [currentDistF, currentNodeF] = pqForward.top(); pqForward.pop(); - if (currentF > distForward[current]) continue; + if (processedForward[currentNodeF]) continue; + processedForward[currentNodeF] = true; - for (const Edge& edge : adjList[current]) { + for (const Edge& edge : adjList[currentNodeF]) { int neighbor = edge.target; - int newDist = distForward[current] + edge.weight; + int newDist = distForward[currentNodeF] + edge.weight; if (newDist < distForward[neighbor]) { distForward[neighbor] = newDist; - prevForward[neighbor] = current; - pqForward.emplace(newDist, neighbor); + prevForward[neighbor] = currentNodeF; + + if (!processedForward[neighbor]) { + pqForward.emplace(newDist, neighbor); + } } - if (distBackward[neighbor] < INF) { + if (processedBackward[neighbor]) { int potentialCost = distForward[neighbor] + distBackward[neighbor]; if (potentialCost < bestCost) { bestCost = potentialCost; @@ -76,24 +81,28 @@ std::vector Graph::shortest_path(int source, int target, int& totalTime) { } } - // Expand backward + // Expansion dans la direction arrière if (!pqBackward.empty()) { - auto [currentB, currentBack] = pqBackward.top(); + auto [currentDistB, currentNodeB] = pqBackward.top(); pqBackward.pop(); - if (currentB > distBackward[currentBack]) continue; + if (processedBackward[currentNodeB]) continue; + processedBackward[currentNodeB] = true; - for (const Edge& edge : adjList[currentBack]) { + for (const Edge& edge : adjList[currentNodeB]) { int neighbor = edge.target; - int newDist = distBackward[currentBack] + edge.weight; + int newDist = distBackward[currentNodeB] + edge.weight; if (newDist < distBackward[neighbor]) { distBackward[neighbor] = newDist; - prevBackward[neighbor] = currentBack; - pqBackward.emplace(newDist, neighbor); + prevBackward[neighbor] = currentNodeB; + + if (!processedBackward[neighbor]) { + pqBackward.emplace(newDist, neighbor); + } } - if (distForward[neighbor] < INF) { + if (processedForward[neighbor]) { int potentialCost = distForward[neighbor] + distBackward[neighbor]; if (potentialCost < bestCost) { bestCost = potentialCost; @@ -103,7 +112,7 @@ std::vector Graph::shortest_path(int source, int target, int& totalTime) { } } - // Finish if the best cost is finalized + // Sortie anticipée si on a trouvé un chemin if (meetingNode != -1) break; } @@ -114,15 +123,24 @@ std::vector Graph::shortest_path(int source, int target, int& totalTime) { totalTime = bestCost; - // Reconstruct the path + // Reconstruction du chemin std::vector path; + path.reserve(n); // Réserver la capacité maximale possible pour éviter les réallocations + + // Construire le chemin avant et l'ajouter directement au chemin final + int forwardPathSize = 0; for (int node = meetingNode; node != -1; node = prevForward[node]) { path.push_back(node); + forwardPathSize++; } - std::reverse(path.begin(), path.end()); + + // Inverser la partie avant du chemin pour obtenir le chemin complet + std::reverse(path.begin(), path.begin() + forwardPathSize); + + // Construire le chemin arrière et l'ajouter directement au chemin final for (int node = prevBackward[meetingNode]; node != -1; node = prevBackward[node]) { path.push_back(node); } return path; -} +} \ No newline at end of file diff --git a/src/preprocessing.cpp b/src/preprocessing.cpp index 3f10b58..004a71a 100644 --- a/src/preprocessing.cpp +++ b/src/preprocessing.cpp @@ -4,11 +4,12 @@ #include #include #include +#include #define SECRET_DELIMITER "," // Alias for connections -using TPDF_CONNECTIONS = std::unordered_set; +using TPDF_CONNECTIONS = std::unordered_map>; // Data processing to populate the graph void process_chunk( @@ -36,10 +37,7 @@ void process_chunk( continue; // Ignore invalid connections or loops } - std::string connection = std::to_string(landmarkA) + SECRET_DELIMITER + std::to_string(landmarkB); - std::string reverseConnection = std::to_string(landmarkB) + SECRET_DELIMITER + std::to_string(landmarkA); - - if (seenConnections.count(connection) > 0 || seenConnections.count(reverseConnection) > 0) { + if (seenConnections[landmarkA].count(landmarkB) > 0 || seenConnections[landmarkB].count(landmarkA) > 0) { continue; // Ignore duplicate connections } @@ -47,8 +45,8 @@ void process_chunk( graph.add_edge(landmarkA, landmarkB, time); // Mark connections as seen - seenConnections.insert(connection); - seenConnections.insert(reverseConnection); + seenConnections[landmarkA].insert(landmarkB); + seenConnections[landmarkB].insert(landmarkA); // Update maxId maxId.store(std::max(maxId.load(), std::max(landmarkA, landmarkB))); @@ -69,4 +67,4 @@ bool preprocess_data(const std::string& filePath, int maxLines, Graph& graph) { inputFile.close(); return true; -} +} \ No newline at end of file diff --git a/src/shortest_path b/src/shortest_path index 0bd9236..796a7ad 100755 Binary files a/src/shortest_path and b/src/shortest_path differ