From 4269214f4795d2f8be619a0c266e57486db6cc4a Mon Sep 17 00:00:00 2001 From: jcoupey Date: Fri, 24 May 2024 09:44:42 +0200 Subject: [PATCH 01/22] Rename max_nb_jobs_removal to depth. --- src/algorithms/local_search/local_search.cpp | 6 +++--- src/algorithms/local_search/local_search.h | 4 ++-- src/problems/vrp.h | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index a5a051d7f..fcf630793 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -75,11 +75,11 @@ LocalSearch::LocalSearch(const Input& input, std::vector& sol, - unsigned max_nb_jobs_removal, + unsigned depth, const Timeout& timeout) : _input(input), _nb_vehicles(_input.vehicles.size()), - _max_nb_jobs_removal(max_nb_jobs_removal), + _depth(depth), _deadline(timeout.has_value() ? utils::now() + timeout.value() : Deadline()), _all_routes(_nb_vehicles), @@ -2005,7 +2005,7 @@ void LocalSearch _all_routes; @@ -78,7 +78,7 @@ class LocalSearch { public: LocalSearch(const Input& input, std::vector& tw_sol, - unsigned max_nb_jobs_removal, + unsigned depth, const Timeout& timeout); utils::SolutionIndicators indicators() const; diff --git a/src/problems/vrp.h b/src/problems/vrp.h index 6ff881ce8..e8ed2c952 100644 --- a/src/problems/vrp.h +++ b/src/problems/vrp.h @@ -43,7 +43,6 @@ class VRP { : (_input.has_homogeneous_locations()) ? homogeneous_parameters : heterogeneous_parameters; - unsigned max_nb_jobs_removal = exploration_level; unsigned nb_init_solutions = h_param.size(); if (nb_init_solutions == 0) { @@ -230,7 +229,7 @@ class VRP { // Local search phase. LocalSearch ls(_input, solutions[rank], - max_nb_jobs_removal, + exploration_level, search_time); ls.run(); From 44bd7e4b9152c248e09f971c8861b97e5eb03c1c Mon Sep 17 00:00:00 2001 From: jcoupey Date: Fri, 24 May 2024 10:26:30 +0200 Subject: [PATCH 02/22] Explicitely pass number of searches and depth to solving functions. --- src/main.cpp | 10 +++++---- src/problems/cvrp/cvrp.cpp | 6 ++++-- src/problems/cvrp/cvrp.h | 3 ++- src/problems/tsp/tsp.cpp | 1 + src/problems/tsp/tsp.h | 1 + src/problems/vrp.h | 31 +++++++++------------------- src/problems/vrptw/vrptw.cpp | 6 ++++-- src/problems/vrptw/vrptw.h | 3 ++- src/structures/cl_args.cpp | 14 +++++++++++++ src/structures/cl_args.h | 5 ++++- src/structures/vroom/input/input.cpp | 6 ++++-- src/structures/vroom/input/input.h | 3 ++- 12 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 14433bcd1..f3f1f8a00 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,7 @@ int main(int argc, char** argv) { std::string limit_arg; std::string output_file; std::vector heuristic_params_arg; + unsigned exploration_level; cxxopts::Options options("vroom", "VROOM Copyright (C) 2015-2024, Julien Coupey\n" @@ -79,7 +80,7 @@ int main(int argc, char** argv) { ("v,version", "output version information and exit") ("x,explore", "exploration level to use (0..5)", - cxxopts::value(cl_args.exploration_level)->default_value(std::to_string(vroom::DEFAULT_EXPLORATION_LEVEL))) + cxxopts::value(exploration_level)->default_value(std::to_string(vroom::DEFAULT_EXPLORATION_LEVEL))) ("stdin", "optional input positional arg", cxxopts::value(cl_args.input)); @@ -153,8 +154,8 @@ int main(int argc, char** argv) { for (const auto& port : port_args) { vroom::io::update_port(cl_args.servers, port); } - cl_args.exploration_level = - std::min(cl_args.exploration_level, vroom::MAX_EXPLORATION_LEVEL); + exploration_level = std::min(exploration_level, vroom::MAX_EXPLORATION_LEVEL); + vroom::io::set_exploration_level(cl_args, exploration_level); // Determine routing engine (defaults to ROUTER::OSRM). if (router_arg == "libosrm") { @@ -220,7 +221,8 @@ int main(int argc, char** argv) { vroom::Solution sol = (cl_args.check) ? problem_instance.check(cl_args.nb_threads) - : problem_instance.solve(cl_args.exploration_level, + : problem_instance.solve(cl_args.nb_searches, + cl_args.depth, cl_args.nb_threads, cl_args.timeout, cl_args.h_params); diff --git a/src/problems/cvrp/cvrp.cpp b/src/problems/cvrp/cvrp.cpp index 273bdfb74..eda7d3448 100644 --- a/src/problems/cvrp/cvrp.cpp +++ b/src/problems/cvrp/cvrp.cpp @@ -143,7 +143,8 @@ const std::vector CVRP::heterogeneous_parameters = CVRP::CVRP(const Input& input) : VRP(input) { } -Solution CVRP::solve(unsigned exploration_level, +Solution CVRP::solve(unsigned nb_searches, + unsigned depth, unsigned nb_threads, const Timeout& timeout, const std::vector& h_param) const { @@ -164,7 +165,8 @@ Solution CVRP::solve(unsigned exploration_level, return utils::format_solution(_input, {r}); } - return VRP::solve(exploration_level, + return VRP::solve(nb_searches, + depth, nb_threads, timeout, h_param, diff --git a/src/problems/cvrp/cvrp.h b/src/problems/cvrp/cvrp.h index 134aa7a4c..58eb31bac 100644 --- a/src/problems/cvrp/cvrp.h +++ b/src/problems/cvrp/cvrp.h @@ -25,7 +25,8 @@ class CVRP : public VRP { explicit CVRP(const Input& input); Solution - solve(unsigned exploration_level, + solve(unsigned nb_searches, + unsigned depth, unsigned nb_threads, const Timeout& timeout, const std::vector& h_param) const override; diff --git a/src/problems/tsp/tsp.cpp b/src/problems/tsp/tsp.cpp index 7ee869eed..a6021948d 100644 --- a/src/problems/tsp/tsp.cpp +++ b/src/problems/tsp/tsp.cpp @@ -293,6 +293,7 @@ std::vector TSP::raw_solve(unsigned nb_threads, } Solution TSP::solve(unsigned, + unsigned, unsigned nb_threads, const Timeout& timeout, const std::vector&) const { diff --git a/src/problems/tsp/tsp.h b/src/problems/tsp/tsp.h index 8f6d9f0d0..c92778405 100644 --- a/src/problems/tsp/tsp.h +++ b/src/problems/tsp/tsp.h @@ -45,6 +45,7 @@ class TSP : public VRP { const Timeout& timeout) const; Solution solve(unsigned, + unsigned, unsigned nb_threads, const Timeout& timeout, const std::vector&) const override; diff --git a/src/problems/vrp.h b/src/problems/vrp.h index e8ed2c952..a7800e4ca 100644 --- a/src/problems/vrp.h +++ b/src/problems/vrp.h @@ -31,7 +31,8 @@ class VRP { template Solution solve( - unsigned exploration_level, + unsigned nb_searches, + unsigned depth, unsigned nb_threads, const Timeout& timeout, const std::vector& h_param, @@ -43,19 +44,9 @@ class VRP { : (_input.has_homogeneous_locations()) ? homogeneous_parameters : heterogeneous_parameters; - unsigned nb_init_solutions = h_param.size(); - - if (nb_init_solutions == 0) { - // Local search parameter. - nb_init_solutions = 4 * (exploration_level + 1); - if (exploration_level >= 4) { - nb_init_solutions += 4; - } - if (exploration_level == MAX_EXPLORATION_LEVEL) { - nb_init_solutions += 4; - } - } - assert(nb_init_solutions <= parameters.size()); + assert(nb_searches != 0); + nb_searches = + std::min(nb_searches, static_cast(parameters.size())); // Build empty solutions to be filled by heuristics. std::vector empty_sol; @@ -65,7 +56,7 @@ class VRP { empty_sol.emplace_back(_input, v, _input.zero_amount().size()); } - std::vector> solutions(nb_init_solutions, empty_sol); + std::vector> solutions(nb_searches, empty_sol); // Heuristics operate on all jobs. std::vector jobs_ranks(_input.jobs.size()); @@ -78,7 +69,7 @@ class VRP { // Split the heuristic parameters among threads. std::vector> thread_ranks(nb_threads, std::vector()); - for (std::size_t i = 0; i < nb_init_solutions; ++i) { + for (std::size_t i = 0; i < nb_searches; ++i) { thread_ranks[i % nb_threads].push_back(i); } @@ -227,10 +218,7 @@ class VRP { for (auto rank : sol_ranks) { // Local search phase. - LocalSearch ls(_input, - solutions[rank], - exploration_level, - search_time); + LocalSearch ls(_input, solutions[rank], depth, search_time); ls.run(); // Store solution indicators. @@ -281,7 +269,8 @@ class VRP { virtual ~VRP(); virtual Solution - solve(unsigned exploration_level, + solve(unsigned nb_searches, + unsigned depth, unsigned nb_threads, const Timeout& timeout, const std::vector& h_param) const = 0; diff --git a/src/problems/vrptw/vrptw.cpp b/src/problems/vrptw/vrptw.cpp index b1a08dacc..174aae3dd 100644 --- a/src/problems/vrptw/vrptw.cpp +++ b/src/problems/vrptw/vrptw.cpp @@ -142,11 +142,13 @@ const std::vector VRPTW::heterogeneous_parameters = VRPTW::VRPTW(const Input& input) : VRP(input) { } -Solution VRPTW::solve(unsigned exploration_level, +Solution VRPTW::solve(unsigned nb_searches, + unsigned depth, unsigned nb_threads, const Timeout& timeout, const std::vector& h_param) const { - return VRP::solve(exploration_level, + return VRP::solve(nb_searches, + depth, nb_threads, timeout, h_param, diff --git a/src/problems/vrptw/vrptw.h b/src/problems/vrptw/vrptw.h index 7e5bf0a3b..fc6557dab 100644 --- a/src/problems/vrptw/vrptw.h +++ b/src/problems/vrptw/vrptw.h @@ -23,7 +23,8 @@ class VRPTW : public VRP { explicit VRPTW(const Input& input); Solution - solve(unsigned exploration_level, + solve(unsigned nb_searches, + unsigned depth, unsigned nb_threads, const Timeout& timeout, const std::vector& h_param) const override; diff --git a/src/structures/cl_args.cpp b/src/structures/cl_args.cpp index 584ccc2ba..944c1d5a4 100644 --- a/src/structures/cl_args.cpp +++ b/src/structures/cl_args.cpp @@ -75,4 +75,18 @@ void update_port(Servers& servers, std::string_view value) { } } +void set_exploration_level(CLArgs& cl_args, unsigned exploration_level) { + cl_args.depth = exploration_level; + + assert(exploration_level <= MAX_EXPLORATION_LEVEL); + + cl_args.nb_searches = 4 * (exploration_level + 1); + if (exploration_level >= 4) { + cl_args.nb_searches += 4; + } + if (exploration_level == MAX_EXPLORATION_LEVEL) { + cl_args.nb_searches += 4; + } +} + } // namespace vroom::io diff --git a/src/structures/cl_args.h b/src/structures/cl_args.h index cd4427710..a20ca7ae5 100644 --- a/src/structures/cl_args.h +++ b/src/structures/cl_args.h @@ -34,13 +34,16 @@ struct CLArgs { ROUTER router; // -r std::string input; // cl arg unsigned nb_threads; // -t - unsigned exploration_level; // -x + unsigned nb_searches; // derived from -x + unsigned depth; // derived from -x }; void update_host(Servers& servers, std::string_view value); void update_port(Servers& servers, std::string_view value); +void set_exploration_level(CLArgs& cl_args, unsigned exploration_level); + } // namespace vroom::io #endif diff --git a/src/structures/vroom/input/input.cpp b/src/structures/vroom/input/input.cpp index b51627321..524eb4354 100644 --- a/src/structures/vroom/input/input.cpp +++ b/src/structures/vroom/input/input.cpp @@ -1081,7 +1081,8 @@ std::unique_ptr Input::get_problem() const { return std::make_unique(*this); } -Solution Input::solve(unsigned exploration_level, +Solution Input::solve(unsigned nb_searches, + unsigned depth, unsigned nb_thread, const Timeout& timeout, const std::vector& h_param) { @@ -1127,7 +1128,8 @@ Solution Input::solve(unsigned exploration_level, // Solve. const std::vector h_init_routes(1, HEURISTIC::INIT_ROUTES); - auto sol = instance->solve(exploration_level, + auto sol = instance->solve(nb_searches, + depth, nb_thread, solve_time, _has_initial_routes ? h_init_routes : h_param); diff --git a/src/structures/vroom/input/input.h b/src/structures/vroom/input/input.h index 287dacc7d..1f1ec016a 100644 --- a/src/structures/vroom/input/input.h +++ b/src/structures/vroom/input/input.h @@ -179,7 +179,8 @@ class Input { // Returns true iff both vehicles have common job candidates. bool vehicle_ok_with_vehicle(Index v1_index, Index v2_index) const; - Solution solve(unsigned exploration_level, + Solution solve(unsigned nb_searches, + unsigned depth, unsigned nb_thread, const Timeout& timeout = Timeout(), const std::vector& h_param = From 8c09577c92c0f8981ebd1d12aa20d49e8355b5b0 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Fri, 24 May 2024 11:58:06 +0200 Subject: [PATCH 03/22] Allow overriding nb_searches and depth for debug purposes. --- src/main.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index f3f1f8a00..bad13ec18 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -86,13 +86,22 @@ int main(int argc, char** argv) { cxxopts::value(cl_args.input)); // we don't want to print debug args on --help + std::optional debug_depth; + std::optional debug_nb_searches; + options.add_options("debug_group") ("e,heuristic-param", "Heuristic parameter", cxxopts::value>(heuristic_params_arg)) ("f,apply-tsp-fix", "apply experimental TSPFix local search operator", - cxxopts::value(cl_args.apply_TSPFix)->default_value("false")); + cxxopts::value(cl_args.apply_TSPFix)->default_value("false")) + ("d,depth", + "search depth", + cxxopts::value>(debug_depth)) + ("s,nb-searches", + "number of searches to perform in parallel", + cxxopts::value>(debug_nb_searches)); // clang-format on try { @@ -156,6 +165,12 @@ int main(int argc, char** argv) { } exploration_level = std::min(exploration_level, vroom::MAX_EXPLORATION_LEVEL); vroom::io::set_exploration_level(cl_args, exploration_level); + if (debug_depth) { + cl_args.depth = debug_depth.value(); + } + if (debug_nb_searches) { + cl_args.nb_searches = debug_nb_searches.value(); + } // Determine routing engine (defaults to ROUTER::OSRM). if (router_arg == "libosrm") { From 552f7101b168a3b9186f709e70a48692492f3c9b Mon Sep 17 00:00:00 2001 From: jcoupey Date: Mon, 10 Jun 2024 12:13:30 +0200 Subject: [PATCH 04/22] Adjust libvroom example for solve signature change. --- libvroom_examples/libvroom.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libvroom_examples/libvroom.cpp b/libvroom_examples/libvroom.cpp index 0d151269a..e0c66df8f 100644 --- a/libvroom_examples/libvroom.cpp +++ b/libvroom_examples/libvroom.cpp @@ -218,11 +218,11 @@ void run_example_with_osrm() { // - jobs 3 and 4 can only be served by vehicle 2 // - jobs 5 and 6 can be served by either one of the vehicles - // Solve! + // Solve using exploration level as depth and number of searches. auto sol = - problem_instance.solve(vroom::DEFAULT_EXPLORATION_LEVEL, // Exploration - // level. - vroom::DEFAULT_THREADS_NUMBER); // Use 4 threads. + problem_instance.solve(vroom::DEFAULT_EXPLORATION_LEVEL, + vroom::DEFAULT_EXPLORATION_LEVEL, + vroom::DEFAULT_THREADS_NUMBER); // Use 4 threads. log_solution(sol, GEOMETRY); } @@ -274,11 +274,11 @@ void run_example_with_custom_matrix() { problem_instance.add_job(j); } - // Solve! + // Solve using exploration level as depth and number of searches. auto sol = - problem_instance.solve(vroom::DEFAULT_EXPLORATION_LEVEL, // Exploration - // level. - vroom::DEFAULT_THREADS_NUMBER); // Use 4 threads. + problem_instance.solve(vroom::DEFAULT_EXPLORATION_LEVEL, + vroom::DEFAULT_EXPLORATION_LEVEL, + vroom::DEFAULT_THREADS_NUMBER); // Use 4 threads. log_solution(sol, GEOMETRY); } From 09c5db828c644c5d012d25fcb94f3065ac05949c Mon Sep 17 00:00:00 2001 From: jcoupey Date: Mon, 10 Jun 2024 17:30:14 +0200 Subject: [PATCH 05/22] Move operator_names array to typedef. --- src/structures/typedefs.h | 23 +++++++++++++++++++++++ src/utils/helpers.cpp | 23 +---------------------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/structures/typedefs.h b/src/structures/typedefs.h index 1e313c968..a0f431425 100644 --- a/src/structures/typedefs.h +++ b/src/structures/typedefs.h @@ -178,6 +178,29 @@ enum OperatorName { MAX }; +#if defined(LOG_LS_OPERATORS) || defined(LOG_LS_SEARCH) +const std::array + OPERATOR_NAMES({"UnassignedExchange", + "CrossExchange", + "MixedExchange", + "TwoOpt", + "ReverseTwoOpt", + "Relocate", + "OrOpt", + "IntraExchange", + "IntraCrossExchange", + "IntraMixedExchange", + "IntraRelocate", + "IntraOrOpt", + "IntraTwoOpt", + "PDShift", + "RouteExchange", + "SwapStar", + "RouteSplit", + "PriorityReplace", + "TSPFix"}); +#endif + // Defined based on // https://sonarcloud.io/organizations/vroom-project/rules?open=cpp%3AS6045&rule_key=cpp%3AS6045 struct StringHash { diff --git a/src/utils/helpers.cpp b/src/utils/helpers.cpp index 800417394..665f8d1f1 100644 --- a/src/utils/helpers.cpp +++ b/src/utils/helpers.cpp @@ -63,27 +63,6 @@ SORT get_sort(std::string_view s) { } #ifdef LOG_LS_OPERATORS -const std::array - operator_names({"UnassignedExchange", - "CrossExchange", - "MixedExchange", - "TwoOpt", - "ReverseTwoOpt", - "Relocate", - "OrOpt", - "IntraExchange", - "IntraCrossExchange", - "IntraMixedExchange", - "IntraRelocate", - "IntraOrOpt", - "IntraTwoOpt", - "PDShift", - "RouteExchange", - "SwapStar", - "RouteSplit", - "PriorityReplace", - "TSPFix"}); - void log_LS_operators( const std::vector>& ls_stats) { @@ -108,7 +87,7 @@ void log_LS_operators( } for (auto op = 0; op < OperatorName::MAX; ++op) { - std::cout << operator_names[op] << "," << tried_sums[op] << "," + std::cout << OPERATOR_NAMES[op] << "," << tried_sums[op] << "," << applied_sums[op] << std::endl; } std::cout << "Total," << total_tried << "," << total_applied << std::endl; From 2e6245f1e90bc132c1a97da477028b9b146994ee Mon Sep 17 00:00:00 2001 From: jcoupey Date: Mon, 10 Jun 2024 17:30:55 +0200 Subject: [PATCH 06/22] First sketch for LOG_LS_SEARCH structs. --- .../local_search/log_local_search.h | 30 +++++++++++++++++++ src/makefile | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/local_search/log_local_search.h diff --git a/src/algorithms/local_search/log_local_search.h b/src/algorithms/local_search/log_local_search.h new file mode 100644 index 000000000..023f54ac1 --- /dev/null +++ b/src/algorithms/local_search/log_local_search.h @@ -0,0 +1,30 @@ +#ifndef LOG_LOCAL_SEARCH_H +#define LOG_LOCAL_SEARCH_H + +/* + +This file is part of VROOM. + +Copyright (c) 2015-2024, Julien Coupey. +All rights reserved (see LICENSE). + +*/ + +namespace vroom::ls::log { + +enum class EVENT { Start }; + +template struct Step { + TimePoint time_point; + EVENT event; + OperatorName operator_name; + vroom::utils::SolutionIndicators indicators; +}; + +template struct Dump { + HeuristicParameters heuristic_parameters; + std::vector> steps; +}; +} // namespace vroom::ls::log + +#endif diff --git a/src/makefile b/src/makefile index 695ce248e..38d825cb4 100644 --- a/src/makefile +++ b/src/makefile @@ -6,7 +6,7 @@ # Variables. CXX ?= g++ USE_ROUTING ?= true -CXXFLAGS = -MMD -MP -I. -std=c++20 -Wextra -Wpedantic -Wall -O3 -DASIO_STANDALONE -DUSE_ROUTING=$(USE_ROUTING) +CXXFLAGS = -MMD -MP -I. -std=c++20 -Wextra -Wpedantic -Wall -O3 -DASIO_STANDALONE -DUSE_ROUTING=$(USE_ROUTING) -DLOG_LS LDLIBS = -lpthread # Using all cpp files in current directory. From 101270fe0575ac84b357e38a61e1aa086e0947b3 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Mon, 10 Jun 2024 18:06:08 +0200 Subject: [PATCH 07/22] Populate vector of ls::log::Dump with heuristic parameters. --- src/problems/vrp.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/problems/vrp.h b/src/problems/vrp.h index a7800e4ca..49b28ff72 100644 --- a/src/problems/vrp.h +++ b/src/problems/vrp.h @@ -22,6 +22,10 @@ All rights reserved (see LICENSE). #include "structures/vroom/input/input.h" #include "structures/vroom/solution/solution.h" +#ifdef LOG_LS +#include "algorithms/local_search/log_local_search.h" +#endif + namespace vroom { class VRP { @@ -58,6 +62,11 @@ class VRP { std::vector> solutions(nb_searches, empty_sol); +#ifdef LOG_LS + std::vector> ls_dumps; + ls_dumps.reserve(nb_searches); +#endif + // Heuristics operate on all jobs. std::vector jobs_ranks(_input.jobs.size()); std::iota(jobs_ranks.begin(), jobs_ranks.end(), 0); @@ -71,6 +80,10 @@ class VRP { thread_ranks(nb_threads, std::vector()); for (std::size_t i = 0; i < nb_searches; ++i) { thread_ranks[i % nb_threads].push_back(i); + +#ifdef LOG_LS + ls_dumps.push_back({parameters[i], {}}); +#endif } std::exception_ptr ep = nullptr; @@ -151,6 +164,9 @@ class VRP { if (h_other_eval < h_eval) { solutions[rank] = std::move(other_sol); +#ifdef LOG_LS + ls_dumps[rank].heuristic_parameters.sort = SORT::COST; +#endif } } } @@ -193,6 +209,9 @@ class VRP { for (auto remove_rank = to_remove.rbegin(); remove_rank != to_remove.rend(); remove_rank++) { solutions.erase(solutions.begin() + *remove_rank); +#ifdef LOG_LS + ls_dumps.erase(ls_dumps.begin() + *remove_rank); +#endif } // Split local searches across threads. From d7e4430daddf9e05bc57ef326f0a4bc2914bef46 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Tue, 11 Jun 2024 14:49:46 +0200 Subject: [PATCH 08/22] Handle writing LS log struct to json. --- .../local_search/log_local_search.h | 2 + src/problems/vrp.h | 5 + src/utils/output_json.cpp | 96 +++++++++++++++++++ src/utils/output_json.h | 8 ++ 4 files changed, 111 insertions(+) diff --git a/src/algorithms/local_search/log_local_search.h b/src/algorithms/local_search/log_local_search.h index 023f54ac1..e3c2eeaa6 100644 --- a/src/algorithms/local_search/log_local_search.h +++ b/src/algorithms/local_search/log_local_search.h @@ -10,6 +10,8 @@ All rights reserved (see LICENSE). */ +#include "structures/vroom/solution_indicators.h" + namespace vroom::ls::log { enum class EVENT { Start }; diff --git a/src/problems/vrp.h b/src/problems/vrp.h index 49b28ff72..cbcdb47da 100644 --- a/src/problems/vrp.h +++ b/src/problems/vrp.h @@ -24,6 +24,7 @@ All rights reserved (see LICENSE). #ifdef LOG_LS #include "algorithms/local_search/log_local_search.h" +#include "utils/output_json.h" #endif namespace vroom { @@ -273,6 +274,10 @@ class VRP { utils::log_LS_operators(ls_stats); #endif +#ifdef LOG_LS + io::write_LS_logs_to_json(ls_dumps); +#endif + auto best_indic = std::min_element(sol_indicators.cbegin(), sol_indicators.cend()); diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index 4c03dbfd7..0dd0f8883 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -13,6 +13,7 @@ All rights reserved (see LICENSE). #include "../include/rapidjson/include/rapidjson/stringbuffer.h" #include "../include/rapidjson/include/rapidjson/writer.h" +#include "structures/typedefs.h" #include "utils/output_json.h" namespace vroom::io { @@ -410,4 +411,99 @@ void write_to_json(const Solution& sol, write_to_output(json_output, output_file); } +#ifdef LOG_LS +template +rapidjson::Value to_json(const ls::log::Dump& dump, + rapidjson::Document::AllocatorType& allocator) { + rapidjson::Value json_parameters(rapidjson::kObjectType); + + std::string heuristic; + switch (dump.heuristic_parameters.heuristic) { + using enum HEURISTIC; + case BASIC: + heuristic = "BASIC"; + break; + case DYNAMIC: + heuristic = "DYNAMIC"; + break; + case INIT_ROUTES: + heuristic = "INIT_ROUTES"; + break; + default: + assert(false); + } + json_parameters.AddMember("heuristic", rapidjson::Value(), allocator); + json_parameters["heuristic"].SetString(heuristic.c_str(), + heuristic.size(), + allocator); + + std::string init; + switch (dump.heuristic_parameters.init) { + using enum INIT; + case NONE: + init = "NONE"; + break; + case HIGHER_AMOUNT: + init = "HIGHER_AMOUNT"; + break; + case NEAREST: + init = "NEAREST"; + break; + case FURTHEST: + init = "FURTHEST"; + break; + case EARLIEST_DEADLINE: + init = "EARLIEST_DEADLINE"; + break; + default: + assert(false); + } + json_parameters.AddMember("init", rapidjson::Value(), allocator); + json_parameters["init"].SetString(init.c_str(), init.size(), allocator); + + json_parameters.AddMember("regret", + dump.heuristic_parameters.regret_coeff, + allocator); + + std::string sort; + switch (dump.heuristic_parameters.sort) { + using enum SORT; + case AVAILABILITY: + sort = "AVAILABILITY"; + break; + case COST: + sort = "COST"; + break; + default: + assert(false); + } + json_parameters.AddMember("sort", rapidjson::Value(), allocator); + json_parameters["sort"].SetString(sort.c_str(), sort.size(), allocator); + + // json_parameters.AddMember("steps", to_json(), allocator); + + return json_parameters; +} + +template +void write_LS_logs_to_json(const std::vector>& dumps) { + rapidjson::Document json_log; + json_log.SetArray(); + rapidjson::Document::AllocatorType& allocator = json_log.GetAllocator(); + + for (const auto& dump : dumps) { + json_log.PushBack(to_json(dump, allocator), allocator); + } + + write_to_output(json_log, "vroom_ls_log.json"); +} + +template void +write_LS_logs_to_json(const std::vector>& dumps); + +template void +write_LS_logs_to_json(const std::vector>& dumps); + +#endif + } // namespace vroom::io diff --git a/src/utils/output_json.h b/src/utils/output_json.h index 6daf53f02..2d19aa6ea 100644 --- a/src/utils/output_json.h +++ b/src/utils/output_json.h @@ -14,6 +14,10 @@ All rights reserved (see LICENSE). #include "structures/vroom/solution/solution.h" #include "utils/exception.h" +#ifdef LOG_LS +#include "algorithms/local_search/log_local_search.h" +#endif + namespace vroom::io { rapidjson::Document to_json(const Solution& sol, bool report_distances); @@ -45,6 +49,10 @@ void write_to_json(const Solution& sol, const std::string& output_file = "", bool report_distances = false); +#ifdef LOG_LS +template +void write_LS_logs_to_json(const std::vector>& dumps); +#endif } // namespace vroom::io #endif From 2dab4b44ce3d9334338b9280e5ee216f0c4d7eaf Mon Sep 17 00:00:00 2001 From: jcoupey Date: Tue, 11 Jun 2024 19:30:29 +0200 Subject: [PATCH 09/22] Start populating LS solving steps. --- src/algorithms/local_search/local_search.cpp | 5 +++ src/algorithms/local_search/local_search.h | 14 ++++++++ .../local_search/log_local_search.h | 2 +- src/problems/vrp.h | 3 ++ src/utils/output_json.cpp | 36 ++++++++++++++++++- 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index fcf630793..ef8b9429c 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -1982,6 +1982,11 @@ void LocalSearch applied_moves; #endif +#ifdef LOG_LS + std::vector> steps; +#endif + void try_job_additions(const std::vector& routes, double regret_coeff); void run_ls_step(); @@ -88,6 +96,12 @@ class LocalSearch { #ifdef LOG_LS_OPERATORS std::array get_stats() const; #endif + +#ifdef LOG_LS + std::vector> get_steps() { + return steps; + } +#endif }; } // namespace vroom::ls diff --git a/src/algorithms/local_search/log_local_search.h b/src/algorithms/local_search/log_local_search.h index e3c2eeaa6..15721663c 100644 --- a/src/algorithms/local_search/log_local_search.h +++ b/src/algorithms/local_search/log_local_search.h @@ -14,7 +14,7 @@ All rights reserved (see LICENSE). namespace vroom::ls::log { -enum class EVENT { Start }; +enum class EVENT { START }; template struct Step { TimePoint time_point; diff --git a/src/problems/vrp.h b/src/problems/vrp.h index cbcdb47da..a4e2a82c3 100644 --- a/src/problems/vrp.h +++ b/src/problems/vrp.h @@ -245,6 +245,9 @@ class VRP { sol_indicators[rank] = ls.indicators(); #ifdef LOG_LS_OPERATORS ls_stats[rank] = ls.get_stats(); +#endif +#ifdef LOG_LS + ls_dumps[rank].steps = ls.get_steps(); #endif } } catch (...) { diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index 0dd0f8883..03de6c627 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -412,6 +412,40 @@ void write_to_json(const Solution& sol, } #ifdef LOG_LS +template +rapidjson::Value to_json(const std::vector>& steps, + rapidjson::Document::AllocatorType& allocator) { + rapidjson::Value json_LS_steps(rapidjson::kArrayType); + + assert(steps.front().event == ls::log::EVENT::START); + const auto start_time = steps.front().time_point; + + for (const auto& step : steps) { + rapidjson::Value json_step(rapidjson::kObjectType); + + const auto delta = std::chrono::duration_cast( + step.time_point - start_time); + json_step.AddMember("time", delta.count(), allocator); + + std::string start = "start"; + json_step.AddMember("event", rapidjson::Value(), allocator); + json_step["event"].SetString(start.c_str(), start.size(), allocator); + + rapidjson::Value json_score(rapidjson::kObjectType); + json_score.AddMember("priority", step.indicators.priority_sum, allocator); + json_score.AddMember("assigned", step.indicators.assigned, allocator); + json_score.AddMember("cost", + utils::scale_to_user_cost(step.indicators.eval.cost), + allocator); + + json_step.AddMember("score", json_score, allocator); + + json_LS_steps.PushBack(json_step, allocator); + } + + return json_LS_steps; +} + template rapidjson::Value to_json(const ls::log::Dump& dump, rapidjson::Document::AllocatorType& allocator) { @@ -480,7 +514,7 @@ rapidjson::Value to_json(const ls::log::Dump& dump, json_parameters.AddMember("sort", rapidjson::Value(), allocator); json_parameters["sort"].SetString(sort.c_str(), sort.size(), allocator); - // json_parameters.AddMember("steps", to_json(), allocator); + json_parameters.AddMember("steps", to_json(dump.steps, allocator), allocator); return json_parameters; } From 76a7cf68dd61ceb473cbbc0c74db2420b32926b0 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Tue, 11 Jun 2024 19:54:14 +0200 Subject: [PATCH 10/22] Store LS move steps. --- src/algorithms/local_search/local_search.cpp | 7 +++++++ src/algorithms/local_search/log_local_search.h | 2 +- src/structures/typedefs.h | 2 +- src/utils/output_json.cpp | 15 +++++++++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index ef8b9429c..450f75a35 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -1830,6 +1830,13 @@ void LocalSearchget_name()); #endif +#ifdef LOG_LS + steps.push_back({utils::now(), + log::EVENT::OPERATOR, + best_ops[best_source][best_target]->get_name(), + utils::SolutionIndicators(_input, _sol)}); +#endif + #ifndef NDEBUG // Update route costs. const auto previous_eval = diff --git a/src/algorithms/local_search/log_local_search.h b/src/algorithms/local_search/log_local_search.h index 15721663c..622d9db23 100644 --- a/src/algorithms/local_search/log_local_search.h +++ b/src/algorithms/local_search/log_local_search.h @@ -14,7 +14,7 @@ All rights reserved (see LICENSE). namespace vroom::ls::log { -enum class EVENT { START }; +enum class EVENT { START, OPERATOR }; template struct Step { TimePoint time_point; diff --git a/src/structures/typedefs.h b/src/structures/typedefs.h index a0f431425..abce63dc3 100644 --- a/src/structures/typedefs.h +++ b/src/structures/typedefs.h @@ -178,7 +178,7 @@ enum OperatorName { MAX }; -#if defined(LOG_LS_OPERATORS) || defined(LOG_LS_SEARCH) +#if defined(LOG_LS_OPERATORS) || defined(LOG_LS) const std::array OPERATOR_NAMES({"UnassignedExchange", "CrossExchange", diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index 03de6c627..8edba030b 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -427,9 +427,20 @@ rapidjson::Value to_json(const std::vector>& steps, step.time_point - start_time); json_step.AddMember("time", delta.count(), allocator); - std::string start = "start"; + std::string event; + switch (step.event) { + using enum ls::log::EVENT; + case START: + event = "Start"; + break; + case OPERATOR: + event = OPERATOR_NAMES[step.operator_name]; + break; + default: + assert(false); + } json_step.AddMember("event", rapidjson::Value(), allocator); - json_step["event"].SetString(start.c_str(), start.size(), allocator); + json_step["event"].SetString(event.c_str(), event.size(), allocator); rapidjson::Value json_score(rapidjson::kObjectType); json_score.AddMember("priority", step.indicators.priority_sum, allocator); From 84ea86f992cfe13a98a9b5b192449301390816d3 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Wed, 26 Jun 2024 18:34:35 +0200 Subject: [PATCH 11/22] Store job additions when performed after LS move. --- src/algorithms/local_search/local_search.cpp | 23 +++++++++++++++++-- src/algorithms/local_search/local_search.h | 8 ++++++- .../local_search/log_local_search.h | 2 +- src/utils/output_json.cpp | 3 +++ 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index 450f75a35..250daca9e 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -162,7 +162,12 @@ void LocalSearch::try_job_additions(const std::vector& routes, - double regret_coeff) { + double regret_coeff +#ifdef LOG_LS + , + bool log_addition_step +#endif +) { bool job_added; std::vector> route_job_insertions; @@ -318,6 +323,15 @@ void LocalSearch(_input, _sol)}); + } +#endif } } while (job_added); @@ -1876,7 +1890,12 @@ void LocalSearchaddition_candidates(), - 0); + 0 +#ifdef LOG_LS + , + true +#endif + ); for (auto v_rank : update_candidates) { _sol_state.update_costs(_sol[v_rank].route, v_rank); diff --git a/src/algorithms/local_search/local_search.h b/src/algorithms/local_search/local_search.h index 87de7c09d..b939fbdc3 100644 --- a/src/algorithms/local_search/local_search.h +++ b/src/algorithms/local_search/local_search.h @@ -66,7 +66,13 @@ class LocalSearch { std::vector> steps; #endif - void try_job_additions(const std::vector& routes, double regret_coeff); + void try_job_additions(const std::vector& routes, + double regret_coeff +#ifdef LOG_LS + , + bool log_addition_step = false +#endif + ); void run_ls_step(); diff --git a/src/algorithms/local_search/log_local_search.h b/src/algorithms/local_search/log_local_search.h index 622d9db23..d560d5b16 100644 --- a/src/algorithms/local_search/log_local_search.h +++ b/src/algorithms/local_search/log_local_search.h @@ -14,7 +14,7 @@ All rights reserved (see LICENSE). namespace vroom::ls::log { -enum class EVENT { START, OPERATOR }; +enum class EVENT { START, OPERATOR, JOB_ADDITION }; template struct Step { TimePoint time_point; diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index 8edba030b..cbc989e9a 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -436,6 +436,9 @@ rapidjson::Value to_json(const std::vector>& steps, case OPERATOR: event = OPERATOR_NAMES[step.operator_name]; break; + case JOB_ADDITION: + event = "JobAddition"; + break; default: assert(false); } From db17f0716a1e601ff9dbedf751ed25f4ba07c0a3 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Wed, 26 Jun 2024 19:00:19 +0200 Subject: [PATCH 12/22] Log R&R as a single step. --- src/algorithms/local_search/local_search.cpp | 7 +++++++ src/algorithms/local_search/log_local_search.h | 2 +- src/utils/output_json.cpp | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index 250daca9e..9e826aa20 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -2074,6 +2074,13 @@ void LocalSearch(_input, _sol)}); +#endif } first_step = false; diff --git a/src/algorithms/local_search/log_local_search.h b/src/algorithms/local_search/log_local_search.h index d560d5b16..ba33e5f81 100644 --- a/src/algorithms/local_search/log_local_search.h +++ b/src/algorithms/local_search/log_local_search.h @@ -14,7 +14,7 @@ All rights reserved (see LICENSE). namespace vroom::ls::log { -enum class EVENT { START, OPERATOR, JOB_ADDITION }; +enum class EVENT { START, OPERATOR, JOB_ADDITION, RUIN }; template struct Step { TimePoint time_point; diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index cbc989e9a..9d39e0c1b 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -439,6 +439,9 @@ rapidjson::Value to_json(const std::vector>& steps, case JOB_ADDITION: event = "JobAddition"; break; + case RUIN: + event = "Ruin"; + break; default: assert(false); } From 721a43c782204e6394d55af2c4f1c235b16f2ad2 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Wed, 26 Jun 2024 19:10:20 +0200 Subject: [PATCH 13/22] Store solution rollback event. --- src/algorithms/local_search/local_search.cpp | 7 +++++++ src/algorithms/local_search/log_local_search.h | 2 +- src/utils/output_json.cpp | 3 +++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index 9e826aa20..a6e62c1c6 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -2031,6 +2031,13 @@ void LocalSearch struct Step { TimePoint time_point; diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index 9d39e0c1b..889f5fa50 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -442,6 +442,9 @@ rapidjson::Value to_json(const std::vector>& steps, case RUIN: event = "Ruin"; break; + case ROLLBACK: + event = "Rollback"; + break; default: assert(false); } From 967da55c079b5a25295febb6166b4a44f3d41059 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Thu, 4 Jul 2024 13:04:33 +0200 Subject: [PATCH 14/22] Also log Rollback events for identical solutions. --- src/algorithms/local_search/local_search.cpp | 6 ++++-- src/structures/vroom/solution_indicators.h | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index a6e62c1c6..7130867b8 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -2031,14 +2031,16 @@ void LocalSearch struct SolutionIndicators { rhs.eval.duration, rhs.eval.distance); } + +#ifdef LOG_LS + friend bool operator==(const SolutionIndicators& lhs, + const SolutionIndicators& rhs) { + return std::tie(rhs.priority_sum, + rhs.assigned, + lhs.eval.cost, + lhs.used_vehicles, + lhs.eval.duration, + lhs.eval.distance) == std::tie(lhs.priority_sum, + lhs.assigned, + rhs.eval.cost, + rhs.used_vehicles, + rhs.eval.duration, + rhs.eval.distance); + } +#endif }; } // namespace vroom::utils From 041a44a5e6ee053cd65189f9942a31ee4a56928a Mon Sep 17 00:00:00 2001 From: jcoupey Date: Tue, 27 Aug 2024 09:22:05 +0200 Subject: [PATCH 15/22] Use microseconds for LS steps times. --- src/utils/output_json.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index 889f5fa50..7e77c9410 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -423,7 +423,7 @@ rapidjson::Value to_json(const std::vector>& steps, for (const auto& step : steps) { rapidjson::Value json_step(rapidjson::kObjectType); - const auto delta = std::chrono::duration_cast( + const auto delta = std::chrono::duration_cast( step.time_point - start_time); json_step.AddMember("time", delta.count(), allocator); From 15281fce3d6911baa348c1a82e8ec268de914c9d Mon Sep 17 00:00:00 2001 From: jcoupey Date: Wed, 4 Sep 2024 12:34:51 +0200 Subject: [PATCH 16/22] Add logging step when reaching local minima. --- src/algorithms/local_search/local_search.cpp | 7 +++++++ src/algorithms/local_search/log_local_search.h | 9 ++++++++- src/utils/output_json.cpp | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index 7130867b8..620ae5c3c 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -2023,6 +2023,13 @@ void LocalSearch struct Step { TimePoint time_point; diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index 7e77c9410..c7c979f56 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -436,6 +436,9 @@ rapidjson::Value to_json(const std::vector>& steps, case OPERATOR: event = OPERATOR_NAMES[step.operator_name]; break; + case LOCAL_MINIMA: + event = "LocalMinima"; + break; case JOB_ADDITION: event = "JobAddition"; break; From 5c3d08ab1a7a0764772c49ac7cda56e6c71ebe79 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Wed, 4 Sep 2024 16:39:39 +0200 Subject: [PATCH 17/22] Small refactor for solution building in utils. --- src/utils/helpers.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/utils/helpers.cpp b/src/utils/helpers.cpp index 9919971b3..8ee8d85a9 100644 --- a/src/utils/helpers.cpp +++ b/src/utils/helpers.cpp @@ -230,6 +230,17 @@ void check_priority(const Priority priority, } } +std::vector get_unassigned_jobs_from_ranks( + const Input& input, + const std::unordered_set& unassigned_ranks) { + std::vector unassigned_jobs; + std::ranges::transform(unassigned_ranks, + std::back_inserter(unassigned_jobs), + [&](auto j) { return input.jobs[j]; }); + + return unassigned_jobs; +} + Solution format_solution(const Input& input, const RawSolution& raw_routes) { std::vector routes; routes.reserve(raw_routes.size()); @@ -384,15 +395,10 @@ Solution format_solution(const Input& input, const RawSolution& raw_routes) { v.description); } - // Handle unassigned jobs. - std::vector unassigned_jobs; - std::ranges::transform(unassigned_ranks, - std::back_inserter(unassigned_jobs), - [&](auto j) { return input.jobs[j]; }); - return Solution(input.zero_amount(), std::move(routes), - std::move(unassigned_jobs)); + std::move( + get_unassigned_jobs_from_ranks(input, unassigned_ranks))); } Route format_route(const Input& input, @@ -891,15 +897,10 @@ Solution format_solution(const Input& input, const TWSolution& tw_routes) { } } - // Handle unassigned jobs. - std::vector unassigned_jobs; - std::ranges::transform(unassigned_ranks, - std::back_inserter(unassigned_jobs), - [&](auto j) { return input.jobs[j]; }); - return Solution(input.zero_amount(), std::move(routes), - std::move(unassigned_jobs)); + std::move( + get_unassigned_jobs_from_ranks(input, unassigned_ranks))); } } // namespace vroom::utils From 999c9f52fe2f4a4ea5b23a576ad264f08205433f Mon Sep 17 00:00:00 2001 From: jcoupey Date: Wed, 4 Sep 2024 17:01:38 +0200 Subject: [PATCH 18/22] Differentiate RUIN and RECREATE events for logging. --- src/algorithms/local_search/local_search.cpp | 9 ++++++++- src/algorithms/local_search/log_local_search.h | 1 + src/utils/output_json.cpp | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index 620ae5c3c..95245ca41 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -2070,6 +2070,13 @@ void LocalSearch(_input, _sol)}); +#endif + // Update insertion ranks ranges. for (std::size_t v = 0; v < _sol.size(); ++v) { _sol_state.set_insertion_ranks(_sol[v], v); @@ -2093,7 +2100,7 @@ void LocalSearch(_input, _sol)}); #endif diff --git a/src/algorithms/local_search/log_local_search.h b/src/algorithms/local_search/log_local_search.h index 938a9748b..eed47c2ec 100644 --- a/src/algorithms/local_search/log_local_search.h +++ b/src/algorithms/local_search/log_local_search.h @@ -20,6 +20,7 @@ enum class EVENT { LOCAL_MINIMA, JOB_ADDITION, RUIN, + RECREATE, ROLLBACK }; diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index c7c979f56..926fb57a9 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -445,6 +445,9 @@ rapidjson::Value to_json(const std::vector>& steps, case RUIN: event = "Ruin"; break; + case RECREATE: + event = "Recreate"; + break; case ROLLBACK: event = "Rollback"; break; From 0b367fb667b3de436949ec422dd5c80eeaba2966 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Wed, 4 Sep 2024 17:07:48 +0200 Subject: [PATCH 19/22] Optionally store solution in log steps. --- src/algorithms/local_search/local_search.cpp | 25 +++++++++++++------ .../local_search/log_local_search.h | 2 ++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/algorithms/local_search/local_search.cpp b/src/algorithms/local_search/local_search.cpp index 95245ca41..951bf44c8 100644 --- a/src/algorithms/local_search/local_search.cpp +++ b/src/algorithms/local_search/local_search.cpp @@ -329,7 +329,8 @@ void LocalSearch(_input, _sol)}); + utils::SolutionIndicators(_input, _sol), + std::nullopt}); } #endif } @@ -1848,7 +1849,8 @@ void LocalSearchget_name(), - utils::SolutionIndicators(_input, _sol)}); + utils::SolutionIndicators(_input, _sol), + std::nullopt}); #endif #ifndef NDEBUG @@ -2009,8 +2011,11 @@ void LocalSearch(_input, _sol)}); + utils::SolutionIndicators(_input, _sol), + utils::format_solution(_input, _sol)}); #endif // Update insertion ranks ranges. @@ -2102,7 +2110,8 @@ void LocalSearch(_input, _sol)}); + utils::SolutionIndicators(_input, _sol), + utils::format_solution(_input, _sol)}); #endif } diff --git a/src/algorithms/local_search/log_local_search.h b/src/algorithms/local_search/log_local_search.h index eed47c2ec..308a06935 100644 --- a/src/algorithms/local_search/log_local_search.h +++ b/src/algorithms/local_search/log_local_search.h @@ -10,6 +10,7 @@ All rights reserved (see LICENSE). */ +#include "structures/vroom/solution/solution.h" #include "structures/vroom/solution_indicators.h" namespace vroom::ls::log { @@ -29,6 +30,7 @@ template struct Step { EVENT event; OperatorName operator_name; vroom::utils::SolutionIndicators indicators; + std::optional solution; }; template struct Dump { From cd9d51339371b3501c234cdac8bff633b9b508d1 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Wed, 4 Sep 2024 18:00:19 +0200 Subject: [PATCH 20/22] Add intermediate solutions in output log. --- src/utils/output_json.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/utils/output_json.cpp b/src/utils/output_json.cpp index 926fb57a9..f20793638 100644 --- a/src/utils/output_json.cpp +++ b/src/utils/output_json.cpp @@ -466,6 +466,14 @@ rapidjson::Value to_json(const std::vector>& steps, json_step.AddMember("score", json_score, allocator); + if (step.solution.has_value()) { + rapidjson::Value step_solution(rapidjson::kObjectType); + auto json_solution = to_json(step.solution.value(), false); + step_solution.CopyFrom(json_solution, allocator); + + json_step.AddMember("solution", step_solution, allocator); + } + json_LS_steps.PushBack(json_step, allocator); } From 6ab8723074e348f38a2a95213f76ff6de2b3930c Mon Sep 17 00:00:00 2001 From: jcoupey Date: Fri, 13 Sep 2024 10:18:52 +0200 Subject: [PATCH 21/22] Mention LOG_LS flag in changes. --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d7d19195..4960430df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ ### Added +#### Internals + +- LOG_LS flag to generate debug info on the internal solving process (#1124) + ### Changed #### Internals From 95ae7aaa042bf1d311c46def2b7f5946f1302381 Mon Sep 17 00:00:00 2001 From: jcoupey Date: Fri, 13 Sep 2024 10:59:32 +0200 Subject: [PATCH 22/22] Default to not defining LOG_LS flag. --- src/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/makefile b/src/makefile index 38d825cb4..695ce248e 100644 --- a/src/makefile +++ b/src/makefile @@ -6,7 +6,7 @@ # Variables. CXX ?= g++ USE_ROUTING ?= true -CXXFLAGS = -MMD -MP -I. -std=c++20 -Wextra -Wpedantic -Wall -O3 -DASIO_STANDALONE -DUSE_ROUTING=$(USE_ROUTING) -DLOG_LS +CXXFLAGS = -MMD -MP -I. -std=c++20 -Wextra -Wpedantic -Wall -O3 -DASIO_STANDALONE -DUSE_ROUTING=$(USE_ROUTING) LDLIBS = -lpthread # Using all cpp files in current directory.