Skip to content

Commit 001df7d

Browse files
committed
Multi-obj: refactor solve iteration loop #239
PrepareNextIter() gets lambdas to obtain solution status and solution
1 parent fd0c34b commit 001df7d

7 files changed

+71
-58
lines changed

include/mp/backend-std.h

+9-5
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,16 @@ class StdBackend :
268268

269269
/// Our solving procedure.
270270
virtual void RunSolveIterations() {
271-
while (GetMM().PrepareSolveIteration()) {
271+
auto get_stt = [this]() { // to be called before GetSolution()
272+
auto sr = GetSolveResult();
273+
SetStatus( sr );
274+
return (sol::Status)sr.first;
275+
};
276+
auto get_sol = [this]() {
277+
return GetSolution();
278+
};
279+
while (GetMM().PrepareSolveIteration(get_stt, get_sol)) {
272280
Solve();
273-
SetStatus( GetSolveResult() ); // before GetSolution()
274-
sol_last_ = GetSolution(); // @todo don't need it in the last iteration
275-
GetMM().ProcessIterationSolution(sol_last_, status_.first);
276281
}
277282
}
278283

@@ -656,7 +661,6 @@ class StdBackend :
656661
std::pair<int, std::string> status_ { sol::NOT_SET, "status not set" };
657662
int kIntermSol_ = 0; // last written intermed solution index
658663
std::pair<double, double> objIntermSol_ { -1e100, 1e100 };
659-
Solution sol_last_;
660664

661665
///////////////////////// STORING SOLVER MESSAGES //////////////////////
662666
private:

include/mp/converter-base.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,9 @@ class BasicConverter : public EnvKeeper {
3333
virtual void ConvertModel() = 0;
3434

3535
/// Need and successfully prepared the next solve iteration?
36-
virtual bool PrepareSolveIteration() = 0;
37-
38-
/// Process solve iteration solution
39-
virtual void ProcessIterationSolution(const Solution& , int status) = 0;
36+
virtual bool PrepareSolveIteration(
37+
std::function<sol::Status(void)> get_stt, std::function<Solution(void)> get_sol)
38+
= 0;
4039

4140
/// Objective weights
4241
virtual ArrayRef<double> GetObjWeightsAdapted() = 0;

include/mp/flat/converter.h

+4-9
Original file line numberDiff line numberDiff line change
@@ -231,19 +231,14 @@ class FlatConverter :
231231
/// This should be used in particular with MO emulation.
232232
/// @return true if the next solve should be executed
233233
/// and its results passed via ProcessSolveIterationSolution().
234-
bool PrepareNextSolveIteration() {
234+
bool PrepareNextSolveIteration(
235+
std::function<sol::Status(void)> get_stt, std::function<Solution(void)> get_sol) {
235236
if (MPCD( IsMOActive() ))
236-
return MPD( PrepareMOIteration() );
237+
return MPD( PrepareMOIteration(get_stt, get_sol) );
237238
return !(n_solve_iter_++);
238239
}
239240

240-
/// Process solve iteration solution.
241-
void ProcessSolveIterationSolution(const Solution& sol, int status) {
242-
if (MPCD( IsMOActive() ))
243-
MPD( ProcessMOIterationPostsolvedSolution(sol, status) );
244-
}
245-
246-
/// Objective weights
241+
/// Objective weights, adapted according to obj:multi:weight
247242
ArrayRef<double> GetObjWeightsAdapted() { return MPD( GetMOWeightsLegacy() ); }
248243

249244

include/mp/flat/converter_multiobj.h

+42-24
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,45 @@ class MOManager {
4949
/// Prepare next multiobj iteration?
5050
/// @note Call this before a MO iteration.
5151
/// @return true iff the model is ready for the next iteration.
52-
bool PrepareMOIteration() {
52+
bool PrepareMOIteration(
53+
std::function<sol::Status(void)> get_stt, std::function<Solution(void)> get_sol) {
5354
switch (status_) {
5455
case MOManagerStatus::NOT_SET:
55-
MP_RAISE("FlatConverter: MultiobjManager not started");
56+
MP_RAISE("FlatConverter: MultiobjManager not set up");
5657
case MOManagerStatus::NOT_ACTIVE:
5758
MP_RAISE("FlatConverter: MultiobjManager not running");
5859
case MOManagerStatus::RUNNING:
59-
return DoPrepareNextMultiobjSolve();
60+
return DoPrepareNextMultiobjSolve(get_stt, get_sol);
6061
case MOManagerStatus::FINISHED:
6162
return false;
6263
}
6364
return false;
6465
}
6566

67+
/// Obtain and process a postsolved solution of the current iteration.
68+
/// Can implicitly call ProcessMOIterationUnpostsolvedSolution().
69+
/// @return (whether we should continue, solve_result).
70+
std::pair<bool, sol::Status> ProcessMOIterationPostsolvedSolution(
71+
std::function<sol::Status(void)> get_stt, std::function<Solution(void)> get_sol) {
72+
auto solst = get_stt();
73+
assert(sol::Status::NOT_SET != solst);
74+
assert(IsMOActive());
75+
assert(MOManagerStatus::FINISHED != status_);
76+
if ((sol::IsProblemSolvedOrFeasible((sol::Status)solst)
77+
// || sol::IsProblemMaybeSolved(solst) // Use this?
78+
) && !sol::IsProblemUnbounded((sol::Status)solst) // Don't want unbounded
79+
) { // (but LIMIT can have this undiscovered)
80+
get_sol(); // This implicitly calls ProcessMOIterationUnpostsolvedSolution().
81+
return { true, solst };
82+
// We ignore the solution here - but having it provided
83+
// guarantees that the postsolve has been run.
84+
}
85+
status_ = MOManagerStatus::FINISHED;
86+
return { false, solst };
87+
}
88+
6689
/// Process an unpostsolved solution of the current iteration.
67-
/// Necessary to be called.
90+
/// This is called from solution postsolve initiated by solution getter.
6891
/// @note Can be called before or after the postsolved solution.
6992
void ProcessMOIterationUnpostsolvedSolution(pre::ModelValuesDbl& sol) {
7093
if (IsMOActive()) {
@@ -79,24 +102,6 @@ class MOManager {
79102
}
80103
}
81104

82-
/// Process a postsolved solution of the current iteration.
83-
/// Necessary to be called.
84-
/// @note Can be called before or after unpostsolved solution.
85-
/// Should contain at least valid solve status.
86-
void ProcessMOIterationPostsolvedSolution(const Solution& , int solst) {
87-
assert(sol::Status::NOT_SET != solst);
88-
assert(IsMOActive());
89-
assert(MOManagerStatus::FINISHED != status_);
90-
if ((sol::IsProblemSolvedOrFeasible((sol::Status)solst)
91-
// || sol::IsProblemMaybeSolved(solst) // Use this?
92-
) && !sol::IsProblemUnbounded((sol::Status)solst))
93-
{} // continue
94-
else
95-
status_ = MOManagerStatus::FINISHED;
96-
// We ignore the solution here - but having it provided
97-
// guarantees that the postsolve has been run.
98-
}
99-
100105

101106
protected:
102107
void SetupMultiobjEmulation() {
@@ -161,7 +166,8 @@ class MOManager {
161166
}
162167

163168
/// Do prepare next solve
164-
bool DoPrepareNextMultiobjSolve() {
169+
bool DoPrepareNextMultiobjSolve(
170+
std::function<sol::Status(void)> get_stt, std::function<Solution(void)> get_sol) {
165171
if (++i_current_obj_ >= obj_new_.size()) {
166172
status_ = MOManagerStatus::FINISHED;
167173
MPD( GetEnv() ).Print(
@@ -176,8 +182,20 @@ class MOManager {
176182
"MULTI-OBJECTIVE MODE: objective {} (out of {}) ...\n"
177183
"==============================================================================\n\n"
178184
, i_current_obj_+1, obj_new_.size());
179-
if (i_current_obj_)
185+
if (i_current_obj_) {
186+
auto proc_sol = ProcessMOIterationPostsolvedSolution(get_stt, get_sol);
187+
if (!proc_sol.first) {
188+
if (MPD( GetEnv() ).verbose_mode())
189+
MPD( GetEnv() ).Print(
190+
"\n"
191+
"MULTI-OBJECTIVE MODE: objective {} (out of {}):\n"
192+
" ABORTING due to the previous iteration's solve result ({}).\n"
193+
"==============================================================================\n\n"
194+
, i_current_obj_+1, obj_new_.size(), proc_sol.second);
195+
return false;
196+
}
180197
RestrictLastObjVal();
198+
}
181199
MPD( FillConstraintCounters( MPD( GetModelAPI() ), *MPD( GetModelInfoWrt() ) ) ); // @todo a hack.
182200
MPD( GetModelAPI() ).InitProblemModificationPhase( // For adding the new constraint. @todo a hack.
183201
MPD( GetModelInfo() )); // Ideally Model would notice changes and notify

include/mp/flat/problem_flattener.h

+4-6
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,10 @@ class ProblemFlattener :
127127
}
128128

129129
/// Need and successfully prepared the next solve iteration?
130-
bool PrepareSolveIteration() override
131-
{ return GetFlatCvt().PrepareNextSolveIteration(); }
132-
133-
/// Process solve iteration solution
134-
void ProcessIterationSolution(const Solution& sol, int status) override
135-
{ GetFlatCvt().ProcessSolveIterationSolution(sol, status); }
130+
bool PrepareSolveIteration(
131+
std::function<sol::Status(void)> get_stt, std::function<Solution(void)> get_sol)
132+
override
133+
{ return GetFlatCvt().PrepareNextSolveIteration(get_stt, get_sol); }
136134

137135
/// Objective weights
138136
ArrayRef<double> GetObjWeightsAdapted() override

include/mp/model-mgr-base.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ class BasicModelManager {
7171
double) = 0;
7272

7373
/// Need and successfully prepared the next solve iteration?
74-
virtual bool PrepareSolveIteration() = 0;
75-
76-
/// Process solve iteration solution
77-
virtual void ProcessIterationSolution(const Solution& , int status) = 0;
74+
/// @param get_stt: solution status getter.
75+
/// If called, then before get_sol.
76+
/// @param get_sol: solution getter (for postsolved solution.)
77+
virtual bool PrepareSolveIteration(
78+
std::function<sol::Status(void)> get_stt, std::function<Solution(void)> get_sol) = 0;
7879

7980
/// Objective weights in the 'legacy' format of the obj:multi:weight option
8081
virtual ArrayRef<double> GetObjWeightsAdapted() = 0;

include/mp/model-mgr-with-pb.h

+4-6
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,10 @@ class ModelManagerWithProblemBuilder :
287287
}
288288

289289
/// Need and successfully prepared the next solve iteration?
290-
bool PrepareSolveIteration() override
291-
{ return GetCvt().PrepareSolveIteration(); }
292-
293-
/// Process solve iteration solution
294-
void ProcessIterationSolution(const Solution& sol, int status) override
295-
{ GetCvt().ProcessIterationSolution(sol, status); }
290+
bool PrepareSolveIteration(
291+
std::function<sol::Status(void)> get_stt, std::function<Solution(void)> get_sol)
292+
override
293+
{ return GetCvt().PrepareSolveIteration(get_stt, get_sol); }
296294

297295
/// Objective weights
298296
ArrayRef<double> GetObjWeightsAdapted() override

0 commit comments

Comments
 (0)