From e462496a7440ccc2d25367d09b8d24efe9be058c Mon Sep 17 00:00:00 2001
From: awenjb <126257927+awenjb@users.noreply.github.com>
Date: Fri, 28 Mar 2025 10:15:04 +0100
Subject: [PATCH] Add code to run multiple instances

- add code to run multiple instances and store the result in a specific directory
- add new config
- add a complete json output
---
 CMakeLists.txt                   |  1 +
 src/config.h                     |  8 ++++++
 src/mains/main.cpp               | 16 +++++++++---
 src/output/lns_output.cpp        |  5 ----
 src/output/lns_output.h          |  1 -
 src/output/run.cpp               | 36 ++++++++++++++++++++++++++
 src/output/run.h                 | 14 ++++++++++
 src/output/solution_exporter.cpp | 44 +++++++++++++++++++++++++++-----
 src/output/solution_exporter.h   | 12 ++++-----
 9 files changed, 114 insertions(+), 23 deletions(-)
 create mode 100644 src/output/run.cpp
 create mode 100644 src/output/run.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f8a9551..f653153 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,6 +49,7 @@ add_executable(pdptw src/mains/main.cpp
                 src/lns/operators/selector/small_large_selector.cpp
                 src/lns/lns.cpp
                 src/utils.cpp
+                src/output/run.cpp
                 )
 
 target_link_libraries(pdptw PRIVATE CLI11::CLI11 nlohmann_json::nlohmann_json spdlog::spdlog)
diff --git a/src/config.h b/src/config.h
index 33bb959..3b8a175 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,3 +1,5 @@
+#include <string>
+
 // Parameters
 
 // Penalty for excluding a certain pickup-delivery pair, aims to minimize the number of excluded pairs.
@@ -26,3 +28,9 @@ bool const PRINT = true;
 // Flag indicating whether the final solution is stored.
 bool const STORE_SOLUTION = true;
 
+// Flag indicating whether the solution is stored with complete information or not.
+bool const COMPLETE_STORE = true;
+
+// Directories
+
+std::string const OUTPUT_DIRECTORY = "./../../output/100_complete";
\ No newline at end of file
diff --git a/src/mains/main.cpp b/src/mains/main.cpp
index 96c5dea..377dbfa 100644
--- a/src/mains/main.cpp
+++ b/src/mains/main.cpp
@@ -28,6 +28,8 @@
 #include "output/solution_checker.h"
 #include "output/solution_exporter.h"
 #include "types.h"
+#include "output/run.h"
+#include "config.h"
 
 #include <filesystem>
 #include <fstream>
@@ -73,7 +75,10 @@ void simpleLNS(PDPTWData const &data, Solution &startingSolution)
     // run lns
     output::LnsOutput result = lns::runLns(startingSolution, smallLargeSelector, acceptor);
 
-    result.getBestSolution().print();
+    if (STORE_SOLUTION)
+    {
+        output::exportToJson(result);
+    }
 }
 
 int main(int argc, char **argv)
@@ -87,9 +92,12 @@ int main(int argc, char **argv)
     //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/Nantes_1.json";
     //std::string filepath = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/n5000/bar-n5000-1.json";
 
-    PDPTWData data = parsing::parseJson(filepath);
-    Solution startingSolution = Solution::emptySolution(data);
-    simpleLNS(data, startingSolution);
+    // PDPTWData data = parsing::parseJson(filepath);
+    // Solution startingSolution = Solution::emptySolution(data);
+    // simpleLNS(data, startingSolution);
+
+    std::string path = "/home/a24jacqb/Documents/Code/pdptw-main/data_in/pdp_100";
+    runAllInDirectory(path, simpleLNS);
 
     return 0;
 }
diff --git a/src/output/lns_output.cpp b/src/output/lns_output.cpp
index 95e75ad..50e1670 100644
--- a/src/output/lns_output.cpp
+++ b/src/output/lns_output.cpp
@@ -20,8 +20,3 @@ unsigned long output::LnsOutput::getTimeSpent() const
 output::LnsOutput::LnsOutput(Solution &&bestSolution, unsigned int numberOfIteration, unsigned long timeSpent)
     : bestSolution(std::move(bestSolution)), numberOfIteration(numberOfIteration), timeSpent(timeSpent)
 {}
-
-void output::LnsOutput::writeSolutionToFile() const
-{
-    output::exportToJson(getBestSolution());
-}
\ No newline at end of file
diff --git a/src/output/lns_output.h b/src/output/lns_output.h
index 9b7c25a..f372f66 100644
--- a/src/output/lns_output.h
+++ b/src/output/lns_output.h
@@ -15,6 +15,5 @@ namespace output
         unsigned int getNumberOfIteration() const;
         Solution const &getBestSolution() const;
         unsigned long getTimeSpent() const;
-        void writeSolutionToFile() const;
     };
 }// namespace output
\ No newline at end of file
diff --git a/src/output/run.cpp b/src/output/run.cpp
new file mode 100644
index 0000000..8cbdf4f
--- /dev/null
+++ b/src/output/run.cpp
@@ -0,0 +1,36 @@
+#include "run.h"
+#include "input/json_parser.h"
+#include "lns/lns.h"
+
+namespace fs = std::filesystem;
+
+std::vector<std::string> getFilesInDirectory(std::string const &directoryPath)
+{
+    std::vector<std::string> filePaths;
+    try
+    {
+        for (auto const &entry: fs::directory_iterator(directoryPath))
+        {
+            if (entry.is_regular_file())
+            {
+                filePaths.push_back(entry.path().string());
+            }
+        }
+    } catch (std::filesystem::filesystem_error const &e)
+    {
+        std::cerr << "Error : " << e.what() << std::endl;
+    }
+    return filePaths;
+}
+
+void runAllInDirectory(std::string const &directoryPath, std::function<void(PDPTWData &, Solution &)> function)
+{
+    std::vector<std::string> files = getFilesInDirectory(directoryPath);
+
+    for (std::string file: files)
+    {
+        PDPTWData data = parsing::parseJson(file);
+        Solution startingSolution = Solution::emptySolution(data);
+        function(data, startingSolution);
+    }
+}
diff --git a/src/output/run.h b/src/output/run.h
new file mode 100644
index 0000000..23f8e54
--- /dev/null
+++ b/src/output/run.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "input/pdptw_data.h"
+#include "lns/solution/solution.h"
+#include <functional>
+#include <iostream>
+#include <vector>
+#include <string>
+#include <filesystem>
+
+
+std::vector<std::string> getFilesInDirectory(const std::string& directoryPath);
+
+void runAllInDirectory(const std::string& directoryPath, std::function<void(PDPTWData &, Solution &)> function);
\ No newline at end of file
diff --git a/src/output/solution_exporter.cpp b/src/output/solution_exporter.cpp
index a537cdf..ba6850b 100644
--- a/src/output/solution_exporter.cpp
+++ b/src/output/solution_exporter.cpp
@@ -1,5 +1,7 @@
 #include "solution_exporter.h"
 
+#include "config.h"
+
 std::string getCurrentDate()
 {
     std::time_t t = std::time(nullptr);
@@ -30,17 +32,35 @@ nlohmann::ordered_json output::getMinimalJson(Solution const &solution)
     return jsonSolution;
 }
 
-nlohmann::ordered_json output::getCompleteJson(Solution const &solution)
+nlohmann::ordered_json output::getCompleteJson(Solution const &solution, int iteration, double time)
 {
     nlohmann::ordered_json jsonSolution;
-    // TO DO
+
+    nlohmann::ordered_json jsonRoutes = nlohmann::ordered_json::array();
+    int routeID = 0;
+    for (auto const &route: solution.getRoutes())
+    {
+        jsonRoutes.push_back(routeToJson(routeID, route));
+        ++routeID;
+    }
+
+    jsonSolution["InstanceName"] = solution.getData().getDataName();
+    jsonSolution["Authors"] = "...";
+    jsonSolution["Date"] = getCurrentDate();
+    jsonSolution["Reference"] = "...";
+    jsonSolution["Cost"] =  std::ceil(solution.getRawCost() * 100.0) / 100.0;
+    jsonSolution["Time"] = time;
+    jsonSolution["Iteration"] = iteration;
+    jsonSolution["Unfullfilled"] = solution.getPairBank().size();
+    jsonSolution["routes"] = jsonRoutes;
+
     return jsonSolution;
 }
 
-void output::exportToJson(Solution const &solution)
+void output::exportToJson(output::LnsOutput result)
 {
-    std::string directory = "./../../output";
-    std::string filename = directory + "/" + solution.getData().getDataName() + "_sol.json";
+    std::string directory = OUTPUT_DIRECTORY;
+    std::string filename = directory + "/" + result.getBestSolution().getData().getDataName() + "_sol.json";
 
     if (!std::filesystem::exists(directory))
     {
@@ -55,8 +75,18 @@ void output::exportToJson(Solution const &solution)
         return;
     }
 
-    nlohmann::ordered_json jsonData = output::getMinimalJson(solution);
-    file << jsonData.dump();
+    nlohmann::ordered_json jsonData;
+    if (COMPLETE_STORE)
+    {
+        jsonData =
+                output::getCompleteJson(result.getBestSolution(), result.getNumberOfIteration(), result.getTimeSpent());
+    }
+    else
+    {
+        jsonData = output::getMinimalJson(result.getBestSolution());
+    }
+
+    file << jsonData.dump(4);
     file.close();
     std::cout << "Solution exported" << std::endl;
 }
diff --git a/src/output/solution_exporter.h b/src/output/solution_exporter.h
index 62a6f09..51dd931 100644
--- a/src/output/solution_exporter.h
+++ b/src/output/solution_exporter.h
@@ -1,11 +1,11 @@
 #pragma once
 
 #include "lns/solution/solution.h"
+#include "output/lns_output.h"
 
-#include <nlohmann/json.hpp>
-#include <ctime> 
+#include <ctime>
 #include <fstream>
-
+#include <nlohmann/json.hpp>
 
 namespace output
 {
@@ -17,13 +17,13 @@ namespace output
     /**
      * Get a complete json representation of a solution (heavier)
      */
-    nlohmann::ordered_json getCompleteJson(Solution const &solution);
+    nlohmann::ordered_json getCompleteJson(Solution const &solution, int iteration, double time);
 
 
-    nlohmann::ordered_json routeToJson(int routeID, const Route& route);
+    nlohmann::ordered_json routeToJson(int routeID, Route const &route);
 
 
-    void exportToJson(Solution const &solution);
+    void exportToJson(output::LnsOutput result);
 
 }// namespace output
 
-- 
GitLab