Antares Xpansion
Investment simulations for Antares studies
Loading...
Searching...
No Matches
BendersBase.h
1#pragma once
2
3#include <antares-xpansion/benders/plugins/BendersPlugin.h>
4#include <execution>
5#include <filesystem>
6#include <mutex>
7#include <tbb/tbb.h>
8
9#include "BendersMathLogger.h"
10#include "BendersStructsDatas.h"
11#include "CriterionComputation.h"
12#include "ICommunicationStrategy.h"
13#include "SubproblemCut.h"
14#include "SubproblemWorker.h"
15#include "Worker.h"
16#include "WorkerMaster.h"
17#include "antares-xpansion/helpers/Timer.h"
18#include "antares-xpansion/xpansion_interfaces/ILogger.h"
19#include "common.h"
20
26template<class lambda>
27auto selectPolicy(lambda f, bool shouldParallelize)
28{
29 if (shouldParallelize)
30 {
31 return f(std::execution::par_unseq);
32 }
33 else
34 {
35 return f(std::execution::seq);
36 }
37}
38
40{
41public:
42 virtual ~BendersBase() = default;
44 Logger logger,
45 std::shared_ptr<Output::OutputWriter> writer,
46 std::shared_ptr<MathLoggerDriver> mathLoggerDriver,
47 std::shared_ptr<ICommunicationStrategy> communication_strategy = nullptr);
48 virtual void launch() = 0;
49 void set_solver_log_file(const std::filesystem::path& log_file);
50 void SetPlugin(std::shared_ptr<BendersPlugin> benders_plugin);
51 double execution_time() const;
52 virtual std::string BendersName() const = 0;
53 // TODO rename to be consistent with data that it hold
54 // ref of value?
55 WorkerMasterDataVect AllCuts() const;
56 // BendersCuts CutsBestIteration() const;
57 // void Clean();
58 LogData GetBestIterationData() const;
59 void set_input_map(const CouplingMap& coupling_map);
60 int MasterRowIndex(const std::string& row_name) const;
61 void MasterChangeRhs(int id_row, double val) const;
62 void MasterGetRhs(double& rhs, int id_row) const;
63
64 const VariableMap& MasterVariables() const
65 {
66 return master_variable_map_;
67 }
68
69 std::vector<double> MasterObjectiveFunctionCoeffs() const;
70 void MasterRowsCoeffs(std::vector<int>& mstart,
71 std::vector<int>& mclind,
72 std::vector<double>& dmatval,
73 int size,
74 std::vector<int>& nels,
75 int first,
76 int last) const;
77 int MasterGetNElems() const;
78 void MasterAddRows(const std::vector<char>& qrtype_p,
79 const std::vector<double>& rhs_p,
80 const std::vector<double>& range_p,
81 const std::vector<int>& mstart_p,
82 const std::vector<int>& mclind_p,
83 const std::vector<double>& dmatval_p,
84 const std::vector<std::string>& row_names = {}) const;
85 void MasterGetRowType(std::vector<char>& qrtype, int first, int last) const;
86 void ResetMasterFromLastIteration();
87 std::filesystem::path LastMasterPath() const;
88 bool MasterIsEmpty() const;
89
90 void DoFreeProblems(bool free_problems)
91 {
92 free_problems_ = free_problems;
93 }
94
95 int MasterGetnrows() const;
96 int MasterGetncols() const;
97 WorkerMasterData BestIterationWorkerMaster() const;
98 void SetMasterObjectiveFunctionCoeffsToZeros() const;
99 void SetMasterObjectiveFunction(const double* coeffs, int first, int last) const;
100 virtual void InitializeProblems() = 0;
101
102 void SetMaxIteration(int max_iteration)
103 {
104 _options.MAX_ITERATIONS = max_iteration;
105 }
106
107 BendersBaseOptions Options() const
108 {
109 return _options;
110 }
111
112 virtual void free() = 0;
113
114 int GetBendersRunNumber() const
115 {
116 return _data.criteria_current_iteration_data.benders_num_run;
117 }
118
119 void IncrementBendersRunNumber()
120 {
121 ++_data.criteria_current_iteration_data.benders_num_run;
122 }
123
124 CurrentIterationData GetCurrentIterationData() const;
125
126 CriteriaCurrentIterationData GetOuterLoopData() const;
127
128 std::vector<double> GetOuterLoopCriterionAtBestBenders() const;
129 virtual void init_data();
130 void init_data(double external_loop_lambda,
131 double external_loop_lambda_min,
132 double external_loop_lambda_max);
133 Output::SolutionData GetOuterLoopSolution() const;
134 void SaveOuterLoopSolutionInOutputFile() const;
135 void SaveCurrentOuterLoopIterationInOutputFile() const;
136 void SetBilevelBestub(double bilevel_best_ub);
137 void UpdateOuterLoopSolution();
138
139 bool isExceptionRaised() const;
140 void UpdateOverallCosts();
141 Logger _logger;
142 std::shared_ptr<Output::OutputWriter> _writer;
143 std::shared_ptr<MathLoggerDriver> mathLoggerDriver_;
144 std::once_flag variable_indice_once_flag;
145 void setCriterionComputationInputs(
146 const Benders::Criterion::CriterionInputData& criterion_input_data);
147
148 [[nodiscard]] std::shared_ptr<ICommunicationStrategy> GetCommunicationStrategy() const
149 {
150 return communication_strategy_;
151 }
152
153protected:
154 bool exception_raised_ = false;
156 WorkerMasterDataVect workerMasterDataVect_;
157 WorkerMasterPtr _master;
158 std::shared_ptr<BendersPlugin> benders_plugin_;
159 // BendersCuts best_iteration_cuts_;
160 // BendersCuts current_iteration_cuts_;
161 VariableMap master_variable_map_;
162 CouplingMap coupling_map_;
163 VariableMap _problem_to_id;
164
166 bool init_data_ = true;
167 bool init_problems_ = true;
168 bool free_problems_ = true;
169 BendersBaseOptions _options;
170
171 std::vector<std::vector<double>> criteria_vector_for_each_iteration_;
172 bool is_bilevel_check_all_ = false;
173
174 virtual void Run() = 0;
175 void update_best_ub();
176 bool ShouldBendersStop();
177 bool is_initial_relaxation_requested() const;
178 bool SwitchToIntegerMaster(bool is_relaxed) const;
179 virtual void HandleInitialMasterRelaxation();
180 virtual void UpdateTrace();
181 virtual void ComputeXCut();
182 void roundXCut();
183 void ComputeInvestCost();
184 virtual void compute_ub();
185 virtual void get_master_value();
186 void GetSubproblemCut(SubProblemDataMap& subproblem_data_map);
187 void GetSubproblemCutFast(SubProblemDataMap& subproblem_data_map);
188 std::pair<std::vector<int>, std::vector<int>> GetProblemBasis(
189 const std::shared_ptr<SubproblemWorker>& worker) const;
190 std::shared_ptr<SubproblemWorker> BuildProblem(const std::pair<std::string, VariableMap>& kvp,
191 const std::string& name);
192 std::shared_ptr<SubproblemWorker> makeSubproblemWorker(
193 const std::pair<std::string, VariableMap>& kvp) const;
194 void SetBasisForSubproblem(const std::string& name,
195 const std::vector<int>& rstatus,
196 const std::vector<int>& cstatus);
197 void GetSubproblemCutCache(SubProblemDataMap& subproblem_data_map);
198 virtual void post_run_actions() const;
199 void BuildCutFull(const SubProblemDataMap& subproblem_data_map);
200 virtual void DeactivateIntegrityConstraints() const;
201 virtual void ActivateIntegrityConstraints() const;
202 virtual void SetDataPreRelaxation();
203 virtual void ResetDataPostRelaxation();
204 [[nodiscard]] std::filesystem::path GetSubproblemPath(const std::string& subproblem_name) const;
205 [[nodiscard]] double SubproblemWeight(int subproblem_count, const std::string& name) const;
206 [[nodiscard]] std::filesystem::path get_master_path() const;
207 [[nodiscard]] std::filesystem::path get_structure_path() const;
208 [[nodiscard]] LogData bendersDataToLogData(const CurrentIterationData& data) const;
209
210 template<typename T, typename... Args>
211 void reset_master(Args&&... args)
212 {
213 _master = std::make_shared<T>(std::forward<Args>(args)...);
214 master_is_empty_ = false;
215 }
216
217 void free_master();
218 void free_subproblems();
219 void AddSubproblem(const std::pair<std::string, VariableMap>& kvp);
220 [[nodiscard]] virtual WorkerMasterPtr get_master() const;
221 void MatchProblemToId();
222 void AddSubproblemName(const std::string& name);
223 [[nodiscard]] std::string get_master_name() const;
224 [[nodiscard]] std::string get_solver_name() const;
225 [[nodiscard]] int get_log_level() const;
226 [[nodiscard]] bool is_trace() const;
227 [[nodiscard]] Point get_x_cut() const;
228 void set_x_cut(const Point& x0);
229 [[nodiscard]] Point get_x_out() const;
230 void set_x_out(const Point& x0);
231 [[nodiscard]] double GetSubproblemCost() const;
232 void SetSubproblemCost(const double& subproblem_cost);
233 bool IsResumeMode() const;
234
235 std::filesystem::path LastIterationFile() const
236 {
237 return std::filesystem::path(_options.LAST_ITERATION_JSON_FILE);
238 }
239
240 void UpdateMaxNumberIterationResumeMode(int nb_iteration_done);
241 void SaveCurrentIterationInOutputFile() const;
242 void SaveSolutionInOutputFile() const;
243 void PrintCurrentIterationCsv();
244 void OpenCsvFile();
245 void CloseCsvFile();
246 void ChecksResumeMode();
247 virtual void SaveCurrentBendersData();
248 void ClearCurrentIterationCutTrace();
249 virtual void EndWritingInOutputFile() const;
250
251 [[nodiscard]] int GetNumIterationsBeforeRestart() const
252 {
253 return iterations_before_resume;
254 }
255
256 double GetBendersTime() const;
257 virtual void write_basis() const;
258
259 // SubproblemsMapPtr GetSubProblemsMapPtr() { return subproblem_map; }
260 SubproblemsMapPtr GetSubProblemMap() const
261 {
262 return subproblem_map;
263 }
264
265 StrVector GetSubProblemNames() const
266 {
267 return subproblems;
268 }
269
270 double AbsoluteGap() const
271 {
272 return _options.ABSOLUTE_GAP;
273 }
274
275 double RelativeGap() const
276 {
277 return _options.RELATIVE_GAP;
278 }
279
280 double RelaxedGap() const
281 {
282 return _options.RELAXED_GAP;
283 }
284
285 DblVector GetAlpha_i() const
286 {
287 return _data.single_subpb_costs_under_approx;
288 }
289
290 void SetAlpha_i(const DblVector& single_subpb_costs_under_approx)
291 {
292 _data.single_subpb_costs_under_approx = single_subpb_costs_under_approx;
293 }
294
295 int ProblemToId(const std::string& problem_name) const
296 {
297 return _problem_to_id.at(problem_name);
298 }
299
300 virtual void UpdateStoppingCriterion();
301 virtual bool ShouldRelaxationStop() const;
302
303 int GetNumOfSubProblemsSolvedBeforeResume()
304 {
305 return cumulative_number_of_subproblem_resolved_before_resume;
306 }
307
308 void BoundSimplexIterations(int subproblem_iteration);
309 void ResetSimplexIterationsBounds();
310
311 SubproblemsMapPtr subproblem_map;
312 SolverLogManager solver_log_manager_;
313
314 virtual void SolveSubproblem(PlainData::SubProblemData& subproblem_data,
315 const std::string& name,
316 const std::shared_ptr<SubproblemWorker>& worker);
317 void SetSubproblemVariablesIndices(const SubproblemWorker& subproblem);
318
319 Benders::Criterion::CriterionComputation criterion_computation_;
329 // Search for variables in sub problems that satisfy patterns
330 // var_indices is a vector(for each patterns p) of vector (var indices related
331 // to p)
333
334 void build_all_aggregated_cuts(const std::vector<SubProblemNamesInCut>& subproblem_names,
335 const std::vector<SubProblemDataMap>& gathered_subproblem_map);
336
337 int SetAggregation(int max_aggregation) const;
338
339 std::map<int, double> GetSubCutTolerance() const;
340
341private:
342 void print_master_and_cut(std::ostream& file,
343 int ite,
344 WorkerMasterData& trace,
345 const Point& xopt);
346 void print_master_csv(std::ostream& stream,
347 const WorkerMasterData& trace,
348 const Point& xopt) const;
349 void check_status(const SubProblemDataMap& subproblem_data_map) const;
350 [[nodiscard]] LogData build_log_data_from_data() const;
351 [[nodiscard]] Output::SolutionData solution() const;
352 [[nodiscard]] Output::SolutionData BendersSolution() const;
353 [[nodiscard]] std::string status_from_criterion() const;
354 void compute_cut_aggregate(const SubProblemDataMap& subproblem_data_map);
355 void compute_cut(const SubProblemDataMap& subproblem_data_map);
356 [[nodiscard]] std::map<std::string, int> get_master_variable_map(
357 const std::map<std::string, std::map<std::string, int>>& input_map) const;
358 [[nodiscard]] virtual bool shouldParallelize() const;
359
360 Output::Iteration iteration(const WorkerMasterData& masterDataPtr_l) const;
361 LogData FinalLogData() const;
362 void FillWorkerMasterData(WorkerMasterData& data) const;
363 bool master_is_empty_ = true;
364 int _totalNbProblems = 0;
365 StrVector subproblems;
366 std::ofstream _csv_file;
367 std::filesystem::path _csv_file_path;
368 LogData best_iteration_data;
369 int iterations_before_resume = 0;
370 int cumulative_number_of_subproblem_resolved_before_resume = 0;
371 Timer benders_timer;
372 Output::SolutionData outer_loop_solution_data_;
373 std::unordered_map<std::string, std::pair<std::vector<int>, std::vector<int>>> basiss_;
374 std::shared_ptr<ICommunicationStrategy> communication_strategy_;
375};
376
377using pBendersBase = std::shared_ptr<BendersBase>;
Definition BendersBase.h:40
std::filesystem::path GetSubproblemPath(const std::string &subproblem_name) const
Get path to subproblem mps file from options.
Definition BendersBase.cpp:1023
virtual void get_master_value()
Solve and get optimal variables of the Master Problem.
Definition BendersBase.cpp:375
void BoundSimplexIterations(int subproblem_iteration)
Definition BendersBase.cpp:1231
virtual void UpdateStoppingCriterion()
Update stopping criterion.
Definition BendersBase.cpp:238
void GetSubproblemCut(SubProblemDataMap &subproblem_data_map)
Solve and store optimal variables of all Subproblem Problems.
Definition BendersBase.cpp:479
std::shared_ptr< SubproblemWorker > BuildProblem(const std::pair< std::string, VariableMap > &kvp, const std::string &name)
Definition BendersBase.cpp:556
void SetSubproblemsVariablesIndices()
Definition BendersBase.cpp:682
virtual void init_data()
Initialize set of data used in the loop.
Definition BendersBase.cpp:44
std::filesystem::path get_master_path() const
Get path to master problem mps file from options.
Definition BendersBase.cpp:1055
void set_input_map(const CouplingMap &coupling_map)
set the input
Definition BendersBase.cpp:1102
virtual bool ShouldRelaxationStop() const
Check if initial relaxation should stop.
Definition BendersBase.cpp:226
double SubproblemWeight(int subproblem_count, const std::string &name) const
Return subproblem weight value.
Definition BendersBase.cpp:1035
virtual void UpdateTrace()
Update trace of the Benders for the current iteration.
Definition BendersBase.cpp:289
void update_best_ub()
Update best upper bound and best optimal variables.
Definition BendersBase.cpp:205
void roundXCut()
Definition BendersBase.cpp:1508
void BuildCutFull(const SubProblemDataMap &subproblem_data_map)
Add cuts in master problem.
Definition BendersBase.cpp:813
Definition CriterionComputation.h:10
this class contains all data read from user input file
Definition CriterionInputDataReader.h:83
Definition SolverAbstract.h:20
Class daughter of Worker Class, build and manage a subproblem.
Definition SubproblemWorker.h:16
Definition Timer.h:10
Class use to store trace information during the algorithm run.
Definition BendersStructsDatas.h:78
Definition launch.py:1
Definition common.h:207
Definition BendersStructsDatas.h:104
Definition BendersStructsDatas.h:9
Definition BendersStructsDatas.h:27
Definition ILogger.h:52
Definition OutputWriter.h:40
struct saves some entries to be later written to the json file
Definition OutputWriter.h:64
Definition SubproblemCut.h:12