From 5496c87aa289adaf18148dc435706dc6e233d7a1 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Thu, 12 Aug 2021 15:23:02 +0200 Subject: [PATCH] minor improvement in glop presolve --- ortools/glop/BUILD | 1 + ortools/glop/lp_solver.cc | 2 +- ortools/glop/preprocessor.cc | 8 ++++++++ ortools/glop/preprocessor.h | 10 +++++----- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ortools/glop/BUILD b/ortools/glop/BUILD index 8c404ac8b0..998246752c 100644 --- a/ortools/glop/BUILD +++ b/ortools/glop/BUILD @@ -326,6 +326,7 @@ cc_library( ":revised_simplex", ":status", "//ortools/base", + "//ortools/base:iterator_adaptors", "//ortools/lp_data", "//ortools/lp_data:base", "//ortools/lp_data:lp_data_utils", diff --git a/ortools/glop/lp_solver.cc b/ortools/glop/lp_solver.cc index 2837a1ecc5..04406d28e0 100644 --- a/ortools/glop/lp_solver.cc +++ b/ortools/glop/lp_solver.cc @@ -217,7 +217,7 @@ ProblemStatus LPSolver::SolveWithTimeLimit(const LinearProgram& lp, RunRevisedSimplexIfNeeded(&solution, time_limit); } - if (postsolve_is_needed) preprocessor.RecoverSolution(&solution); + if (postsolve_is_needed) preprocessor.DestructiveRecoverSolution(&solution); const ProblemStatus status = LoadAndVerifySolution(lp, solution); // LOG some statistics that can be parsed by our benchmark script. diff --git a/ortools/glop/preprocessor.cc b/ortools/glop/preprocessor.cc index 9b7a979d1f..189b10f3c0 100644 --- a/ortools/glop/preprocessor.cc +++ b/ortools/glop/preprocessor.cc @@ -17,6 +17,7 @@ #include #include "absl/strings/str_format.h" +#include "ortools/base/iterator_adaptors.h" #include "ortools/base/strong_vector.h" #include "ortools/glop/revised_simplex.h" #include "ortools/glop/status.h" @@ -177,6 +178,13 @@ void MainLpPreprocessor::RunAndPushIfRelevant( } void MainLpPreprocessor::RecoverSolution(ProblemSolution* solution) const { + SCOPED_INSTRUCTION_COUNT(time_limit_); + for (const auto& p : gtl::reversed_view(preprocessors_)) { + p->RecoverSolution(solution); + } +} + +void MainLpPreprocessor::DestructiveRecoverSolution(ProblemSolution* solution) { SCOPED_INSTRUCTION_COUNT(time_limit_); while (!preprocessors_.empty()) { preprocessors_.back()->RecoverSolution(solution); diff --git a/ortools/glop/preprocessor.h b/ortools/glop/preprocessor.h index 385d6ebc34..6889cbeaa1 100644 --- a/ortools/glop/preprocessor.h +++ b/ortools/glop/preprocessor.h @@ -110,6 +110,10 @@ class MainLpPreprocessor : public Preprocessor { bool Run(LinearProgram* lp) final; void RecoverSolution(ProblemSolution* solution) const override; + // Like RecoverSolution but destroys data structures as it goes to reduce peak + // RAM use. After calling this the MainLpPreprocessor object may no longer be + // used. + void DestructiveRecoverSolution(ProblemSolution* solution); private: // Runs the given preprocessor and push it on preprocessors_ for the postsolve @@ -119,11 +123,7 @@ class MainLpPreprocessor : public Preprocessor { LinearProgram* lp); // Stack of preprocessors currently applied to the lp that needs postsolve. - // - // TODO(user): This is mutable so that the preprocessor can be freed as soon - // as their RecoverSolution() is called. Make RecoverSolution() non-const or - // remove this optimization? - mutable std::vector> preprocessors_; + std::vector> preprocessors_; // Initial dimension of the lp given to Run(), for displaying purpose. EntryIndex initial_num_entries_;