Skip to content

Commit dc985f2

Browse files
committed
Not presolving the AC LP; cleaned up dev printing and added printf_flag to HighsTimer so that MIP timing log can be suppressed
1 parent 14dcc67 commit dc985f2

File tree

9 files changed

+48
-34
lines changed

9 files changed

+48
-34
lines changed

check/TestMipSolver.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,7 @@ TEST_CASE("mip-lp-solver", "[highs_test_mip_solver]") {
10441044
std::string model_file =
10451045
std::string(HIGHS_DIR) + "/check/instances/flugpl.mps";
10461046
Highs h;
1047-
// h.setOptionValue("output_flag", dev_run);
1047+
h.setOptionValue("output_flag", dev_run);
10481048
const bool just_hipo_test = false;
10491049
if (!just_hipo_test) {
10501050
REQUIRE(h.readModel(model_file) == HighsStatus::kOk);
@@ -1071,7 +1071,7 @@ TEST_CASE("mip-sub-solver-time", "[highs_test_mip_solver]") {
10711071
std::string model_file =
10721072
std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps";
10731073
Highs h;
1074-
// h.setOptionValue("output_flag", dev_run);
1074+
h.setOptionValue("output_flag", dev_run);
10751075
h.setOptionValue("highs_analysis_level", kHighsAnalysisLevelMipTime);
10761076
REQUIRE(h.readModel(model_file) == HighsStatus::kOk);
10771077

highs/lp_data/HighsInterface.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3062,6 +3062,8 @@ void Highs::restoreInfCost(HighsStatus& return_status) {
30623062
// Modify status and info if user bound or cost scaling, or
30633063
// primal/dual feasibility tolerances have changed
30643064
HighsStatus Highs::optionChangeAction() {
3065+
this->timer_.setPrintfFlag(options_.output_flag,
3066+
options_.log_to_console);
30653067
HighsModel& model = this->model_;
30663068
HighsLp& lp = model.lp_;
30673069
HighsInfo& info = this->info_;

highs/lp_data/HighsOptions.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,6 @@ OptionStatus setLocalOptionValue(const HighsLogOptions& report_log_options,
437437
std::vector<OptionRecord*>& option_records,
438438
const bool value) {
439439
HighsInt index;
440-
// printf("setLocalOptionValue: \"%s\" with bool %" HIGHSINT_FORMAT "\n",
441-
// name.c_str(), value);
442440
OptionStatus status =
443441
getOptionIndex(report_log_options, name, option_records, index);
444442
if (status != OptionStatus::kOk) return status;
@@ -459,8 +457,6 @@ OptionStatus setLocalOptionValue(const HighsLogOptions& report_log_options,
459457
std::vector<OptionRecord*>& option_records,
460458
const HighsInt value) {
461459
HighsInt index;
462-
// printf("setLocalOptionValue: \"%s\" with HighsInt %" HIGHSINT_FORMAT "\n",
463-
// name.c_str(), value);
464460
OptionStatus status =
465461
getOptionIndex(report_log_options, name, option_records, index);
466462
if (status != OptionStatus::kOk) return status;
@@ -488,8 +484,6 @@ OptionStatus setLocalOptionValue(const HighsLogOptions& report_log_options,
488484
std::vector<OptionRecord*>& option_records,
489485
const double value) {
490486
HighsInt index;
491-
// printf("setLocalOptionValue: \"%s\" with double %g\n", name.c_str(),
492-
// value);
493487
OptionStatus status =
494488
getOptionIndex(report_log_options, name, option_records, index);
495489
if (status != OptionStatus::kOk) return status;

highs/mip/HighsLpRelaxation.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,11 +1115,11 @@ HighsLpRelaxation::Status HighsLpRelaxation::run(bool resolve_on_error) {
11151115
bool use_simplex = !use_ipm;
11161116
if (use_ipm) {
11171117
assert(!valid_basis);
1118-
const bool ipm_logging = true;
1118+
const bool ipm_logging = false;
11191119
if (ipm_logging) {
11201120
std::string presolve;
11211121
lpsolver.getOptionValue("presolve", presolve);
1122-
printf("\nHighsLpRelaxation::run Solving the root node with IPM, using presolve = %s\n", presolve.c_str());
1122+
printf("HighsLpRelaxation::run Solving the root node with IPM, using presolve = %s\n", presolve.c_str());
11231123
bool output_flag;
11241124
lpsolver.getOptionValue("output_flag", output_flag);
11251125
assert(output_flag == false);
@@ -1129,14 +1129,17 @@ HighsLpRelaxation::Status HighsLpRelaxation::run(bool resolve_on_error) {
11291129
const bool dump_ipm_lp = false;
11301130
if (dump_ipm_lp && !mipsolver.submip) {
11311131
const std::string file_name = mipsolver.model_->model_name_ + "_root.mps";
1132-
printf("HighsMipSolverData::startAnalyticCenterComputation: Calling lpsolver.writeModel(%s)\n", file_name.c_str());
1132+
printf("HighsMipSolverData::run Calling lpsolver.writeModel(%s)\n", file_name.c_str());
11331133
lpsolver.writeModel(file_name);
11341134
fflush(stdout);
11351135
exit(1);
11361136
}
11371137
callstatus = lpsolver.run();
11381138
if (ipm_logging) lpsolver.setOptionValue("output_flag", false);
11391139
if (callstatus == HighsStatus::kError) {
1140+
highsLogDev(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1141+
"HighsLpRelaxation::run HiPO has failed : status = %s Try IPX\n",
1142+
lpsolver.modelStatusToString(lpsolver.getModelStatus()).c_str());
11401143
lpsolver.setOptionValue("solver", kSimplexString);
11411144
use_simplex = true;
11421145
}
@@ -1323,11 +1326,11 @@ HighsLpRelaxation::Status HighsLpRelaxation::run(bool resolve_on_error) {
13231326
// istanbul-no-cutoff
13241327
ipm.setOptionValue("simplex_iteration_limit",
13251328
info.simplex_iteration_count);
1326-
const bool ipm_logging = true;
1329+
const bool ipm_logging = false;
13271330
if (ipm_logging) {
13281331
std::string presolve;
13291332
ipm.getOptionValue("presolve", presolve);
1330-
printf("\nHighsLpRelaxation::run After lpsolver reached iteration limit, solving with IPM, using presolve = %s\n", presolve.c_str());
1333+
printf("HighsLpRelaxation::run After lpsolver reached iteration limit, solving with IPM, using presolve = %s\n", presolve.c_str());
13311334
bool output_flag;
13321335
ipm.getOptionValue("output_flag", output_flag);
13331336
assert(output_flag == false);
@@ -1337,11 +1340,10 @@ HighsLpRelaxation::Status HighsLpRelaxation::run(bool resolve_on_error) {
13371340
ipm.run();
13381341
if (ipm_logging) ipm.setOptionValue("output_flag", false);
13391342
if (use_hipo && !ipm.getBasis().valid) {
1340-
printf(
1341-
"In HighsLpRelaxation::run HiPO has failed to get a valid basis: "
1342-
"status = %s Try IPX\n",
1343-
ipm.modelStatusToString(ipm.getModelStatus()).c_str());
13441343
// HiPO has failed to get a solution, so try IPX
1344+
highsLogDev(mipsolver.options_mip_->log_options, HighsLogType::kInfo,
1345+
"HighsLpRelaxation::run HiPO has failed to get a valid basis: status = %s Try IPX\n",
1346+
ipm.modelStatusToString(ipm.getModelStatus()).c_str());
13451347
ipm.setOptionValue("solver", kIpxString);
13461348
ipm.run();
13471349
}

highs/mip/HighsMipAnalysis.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,14 @@ void HighsMipAnalysis::addSubSolverCallTime(const HighsSubSolverCallTime& sub_so
282282

283283
void HighsMipAnalysis::checkSubSolverCallTime(const HighsSubSolverCallTime& sub_solver_call_time) {
284284
if (!analyse_mip_time) return;
285+
const bool printf_flag = mip_clocks.timer_pointer_->printf_flag;
285286
bool error = false;
286287
auto check = [&](const HighsInt& sub_solver_clock, const HighsInt& mip_clock) {
287288
HighsInt sub_solver_num_call = sub_solver_call_time.num_call[sub_solver_clock];
288289
HighsInt mip_clock_num_call = mip_clocks.timer_pointer_->numCall(mip_clocks.clock_[mip_clock]);
289290
const bool ok = sub_solver_num_call == mip_clock_num_call;
290291
if (!ok) {
291-
printf("HighsMipAnalysis::checkSubSolverCallTime: Error for %s\n", sub_solver_call_time.name[sub_solver_clock].c_str());
292+
if (printf_flag) printf("HighsMipAnalysis::checkSubSolverCallTime: Error for %s\n", sub_solver_call_time.name[sub_solver_clock].c_str());
292293
error = true;
293294
}
294295
};
@@ -299,6 +300,6 @@ void HighsMipAnalysis::checkSubSolverCallTime(const HighsSubSolverCallTime& sub_
299300
check(kSubSolverHipoAc, kMipClockHipoSolveAnalyticCentreLp);
300301
check(kSubSolverIpxAc, kMipClockIpxSolveAnalyticCentreLp);
301302
check(kSubSolverSubMip, kMipClockSubMipSolve);
302-
printf("\nHighsMipAnalysis::checkSubSolverCallTime: %s\n", error ? "ERROR!" : "OK");
303+
if (printf_flag) printf("\nHighsMipAnalysis::checkSubSolverCallTime: %s\n", error ? "ERROR!" : "OK");
303304
assert(!error);
304305
}

highs/mip/HighsMipSolver.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ HighsMipSolver::HighsMipSolver(HighsCallback& callback,
4242
pscostinit(nullptr),
4343
clqtableinit(nullptr),
4444
implicinit(nullptr) {
45+
timer_.setPrintfFlag(options_mip_->output_flag,
46+
options_mip_->log_to_console);
4547
assert(!submip || submip_level > 0);
4648
max_submip_level = 0;
4749
if (solution.value_valid) {

highs/mip/HighsMipSolverData.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,10 +346,11 @@ void HighsMipSolverData::startAnalyticCenterComputation(
346346
Highs ipm;
347347
ipm.setOptionValue("output_flag", false);
348348
const std::vector<double>& sol = ipm.getSolution().col_value;
349-
// Don't use presolve - because the MIP has already been presolved?
350-
const bool use_presolve = true;
351-
const std::string presolve = use_presolve ? kHighsChooseString : kHighsOffString;
352-
ipm.setOptionValue("presolve", presolve);
349+
// Don't use presolve - because this can lead to postsolve putting
350+
// integer variables onto bounds. This is not just a "less good"
351+
// AC. It can have implications leading to erroneous fixing of
352+
// variables and a suboptimal solution declared as optimal.
353+
ipm.setOptionValue("presolve", kHighsOffString);
353354
// Determine the solver
354355
const std::string mip_ipm_solver = mipsolver.options_mip_->mip_ipm_solver;
355356
// Currently use HiPO by default and take action on failure
@@ -383,9 +384,6 @@ void HighsMipSolverData::startAnalyticCenterComputation(
383384
}
384385
const bool ipm_logging = false;
385386
if (ipm_logging) {
386-
std::string presolve;
387-
ipm.getOptionValue("presolve", presolve);
388-
printf("\nHighsMipSolverData::startAnalyticCenterComputation Solving for the AC with IPM, using presolve = %s\n", presolve.c_str());
389387
bool output_flag;
390388
ipm.getOptionValue("output_flag", output_flag);
391389
assert(output_flag == false);
@@ -409,6 +407,7 @@ void HighsMipSolverData::startAnalyticCenterComputation(
409407
mipsolver.analysis_.addSubSolverCallTime(sub_solver_call_time, analytic_centre);
410408
// Go through sub_solver_call_time to update any MIP clocks
411409
const bool valid_basis = false;
410+
const bool use_presolve = false;
412411
mipsolver.analysis_.mipTimerUpdate(sub_solver_call_time, valid_basis, use_presolve, analytic_centre);
413412
}
414413
if (HighsInt(sol.size()) != mipsolver.numCol()) return;

highs/mip/MipTimer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ class MipTimer {
290290
const HighsInt kMipClockIdeal = kMipClockTotal,
291291
const double tolerance_percent_report_ = -1) {
292292
HighsTimer* timer_pointer = mip_timer_clock.timer_pointer_;
293+
if (!timer_pointer->printf_flag) return false;
293294
const std::vector<HighsInt>& clock = mip_timer_clock.clock_;
294295
HighsInt mip_clock_list_size = mip_clock_list.size();
295296
std::vector<HighsInt> clockList;
@@ -312,6 +313,7 @@ class MipTimer {
312313
const HighsInt kMipClockIdeal, const bool header,
313314
const bool end_line) {
314315
HighsTimer* timer_pointer = mip_timer_clock.timer_pointer_;
316+
if (!timer_pointer->printf_flag) return;
315317
const std::vector<HighsInt>& clock = mip_timer_clock.clock_;
316318
const double ideal_sum_time =
317319
timer_pointer->clock_time[clock[kMipClockIdeal]];
@@ -511,9 +513,11 @@ class MipTimer {
511513
csvMipClockList("csvRootNode", model_name, mip_clock_list, mip_timer_clock,
512514
kMipClockEvaluateRootNode, header, end_line);
513515
};
516+
514517
void reportFjClock(std::string& model,
515518
const HighsTimerClock& mip_timer_clock) {
516519
HighsTimer* timer_pointer = mip_timer_clock.timer_pointer_;
520+
if (!timer_pointer->printf_flag) return;
517521
HighsInt iClock = mip_timer_clock.clock_[kMipClockFeasibilityJump];
518522
const double fj_time = timer_pointer->read(iClock);
519523
const double total_time = timer_pointer->read();

highs/util/HighsTimer.h

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ class HighsTimer {
4141
presolve_clock = clock_def("Presolve");
4242
solve_clock = clock_def("Solve");
4343
postsolve_clock = clock_def("Postsolve");
44+
printf_flag = true;
45+
}
46+
47+
/**
48+
* @brief Set the printf flag
49+
*/
50+
void setPrintfFlag(const bool output_flag, const bool log_to_console) {
51+
this->printf_flag = output_flag ? log_to_console : false;
4452
}
4553

4654
/**
@@ -73,6 +81,7 @@ class HighsTimer {
7381
this->presolve_clock = clock_def("Presolve");
7482
this->solve_clock = clock_def("Solve");
7583
this->postsolve_clock = clock_def("Postsolve");
84+
this->printf_flag = true;
7685
}
7786

7887
/**
@@ -92,7 +101,7 @@ class HighsTimer {
92101
void writeAllClocks() {
93102
for (HighsInt i = 0; i < num_clock; i++)
94103
if (clock_num_call[i])
95-
printf("Time %7.5f for %9d calls of clock %3d: %s\n", clock_time[i],
104+
if (printf_flag) printf("Time %7.5f for %9d calls of clock %3d: %s\n", clock_time[i],
96105
int(clock_num_call[i]), int(i), clock_names[i].c_str());
97106
}
98107

@@ -113,15 +122,15 @@ class HighsTimer {
113122
// understand this better, for now don't assert that this clock
114123
// has stopped
115124
if (!clock_stopped) {
116-
printf("Clock %d - %s - still running\n", int(i_clock),
125+
if (printf_flag) printf("Clock %d - %s - still running\n", int(i_clock),
117126
clock_names[i_clock].c_str());
118127
}
119128
assert(clock_stopped);
120129
}
121130
// Set the start to be the negation of the WallTick to check that
122131
// the clock's been started when it's next stopped
123132
if (i_clock == check_clock) {
124-
printf("HighsTimer: starting clock %d: %s\n", int(check_clock),
133+
if (printf_flag) printf("HighsTimer: starting clock %d: %s\n", int(check_clock),
125134
this->clock_names[check_clock].c_str());
126135
}
127136
clock_start[i_clock] = -getWallTime();
@@ -138,7 +147,7 @@ class HighsTimer {
138147
// -getWallTime() <= 0
139148
const bool clock_stopped = clock_start[i_clock] > 0;
140149
if (clock_stopped) {
141-
printf("Clock %d - %s - not running\n", int(i_clock),
150+
if (printf_flag) printf("Clock %d - %s - not running\n", int(i_clock),
142151
clock_names[i_clock].c_str());
143152
}
144153
assert(!clock_stopped);
@@ -149,7 +158,7 @@ class HighsTimer {
149158
// Set the start to be the WallTick to check that the clock's been
150159
// stopped when it's next started
151160
if (i_clock == check_clock) {
152-
printf("HighsTimer: stopping clock %d: %s\n", int(check_clock),
161+
if (printf_flag) printf("HighsTimer: stopping clock %d: %s\n", int(check_clock),
153162
this->clock_names[check_clock].c_str());
154163
}
155164
clock_start[i_clock] = wall_time;
@@ -164,7 +173,7 @@ class HighsTimer {
164173
assert(i_clock < num_clock);
165174
if (i_clock == check_clock) {
166175
std::string clock_name = this->clock_names[check_clock];
167-
printf("HighsTimer: reading clock %d: %s\n", int(check_clock),
176+
if (printf_flag) printf("HighsTimer: reading clock %d: %s\n", int(check_clock),
168177
clock_name.c_str());
169178
}
170179
double read_time;
@@ -187,7 +196,7 @@ class HighsTimer {
187196
assert(i_clock >= 0);
188197
assert(i_clock < num_clock);
189198
if (i_clock == check_clock) {
190-
printf("HighsTimer: querying clock %d: %s - with start record %g\n",
199+
if (printf_flag) printf("HighsTimer: querying clock %d: %s - with start record %g\n",
191200
int(check_clock), this->clock_names[check_clock].c_str(),
192201
clock_start[i_clock]);
193202
}
@@ -243,7 +252,7 @@ class HighsTimer {
243252
size_t num_clock_list_entries = clock_list.size();
244253
double current_run_highs_time = read();
245254
bool non_null_report = false;
246-
255+
if (!printf_flag) return non_null_report;
247256
// Check validity of the clock list and check no clocks are still
248257
// running, determine whether there are any times to report and
249258
// determine the total clock times
@@ -365,6 +374,7 @@ class HighsTimer {
365374
HighsInt presolve_clock;
366375
HighsInt solve_clock;
367376
HighsInt postsolve_clock;
377+
bool printf_flag;
368378
};
369379

370380
#endif /* UTIL_HIGHSTIMER_H_ */

0 commit comments

Comments
 (0)