|
13 | 13 | #include "Highs.h" |
14 | 14 | #include "lp_data/HighsLpUtils.h" |
15 | 15 | #include "lp_data/HighsModelUtils.h" |
| 16 | +#include "mip/HighsMipSolver.h" // For getGapString |
16 | 17 | #include "model/HighsHessianUtils.h" |
17 | 18 | #include "simplex/HSimplex.h" |
18 | 19 | #include "util/HighsMatrixUtils.h" |
@@ -4254,79 +4255,109 @@ void HighsMipSolverInfo::clear() { |
4254 | 4255 | this->dual_bound = -kHighsInf; |
4255 | 4256 | this->primal_bound = -kHighsInf; |
4256 | 4257 | this->gap = -kHighsInf; |
| 4258 | + this->max_submip_level = -1; |
4257 | 4259 | this->node_count = -kHighsSize_tInf; |
4258 | 4260 | this->total_lp_iterations = -kHighsSize_tInf; |
4259 | 4261 | this->primal_dual_integral = -kHighsInf; |
4260 | 4262 | } |
4261 | 4263 |
|
4262 | | -HighsStatus Highs::mipRaceResults(HighsMipSolverInfo& mip_solver_info, |
4263 | | - const std::vector<HighsMipSolverInfo>& worker_info, |
4264 | | - const std::vector<double>& mip_time) { |
4265 | | - |
| 4264 | +HighsStatus Highs::mipRaceResults( |
| 4265 | + HighsMipSolverInfo& mip_solver_info, |
| 4266 | + const std::vector<HighsMipSolverInfo>& worker_info, |
| 4267 | + const std::vector<double>& mip_time) { |
4266 | 4268 | const HighsInt mip_race_concurrency = this->options_.mip_race_concurrency; |
4267 | 4269 | HighsInt winning_instance = -1; |
4268 | 4270 | HighsModelStatus winning_model_status = HighsModelStatus::kNotset; |
| 4271 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4272 | + "/nMIP race results\n"); |
4269 | 4273 | for (HighsInt instance = 0; instance < mip_race_concurrency; instance++) { |
4270 | 4274 | const HighsMipSolverInfo& solver_info = |
4271 | | - instance == 0 ? mip_solver_info : worker_info[instance]; |
| 4275 | + instance == 0 ? mip_solver_info : worker_info[instance]; |
4272 | 4276 | HighsModelStatus instance_model_status = solver_info.modelstatus; |
4273 | 4277 | highsLogUser(options_.log_options, HighsLogType::kInfo, |
4274 | | - " Solver %d has best objective %15.8g, gap %6.2f\% (time " |
4275 | | - "= %6.2f), and status %s\n", |
4276 | | - int(instance), solver_info.solution_objective, |
4277 | | - 1e2 * solver_info.gap, mip_time[instance], |
4278 | | - modelStatusToString(instance_model_status).c_str()); |
| 4278 | + " Solver %d has best objective %15.8g, gap %6.2f\% (time " |
| 4279 | + "= %6.2f), and status %s\n", |
| 4280 | + int(instance), solver_info.solution_objective, |
| 4281 | + 1e2 * solver_info.gap, mip_time[instance], |
| 4282 | + modelStatusToString(instance_model_status).c_str()); |
4279 | 4283 | if (instance_model_status != HighsModelStatus::kHighsInterrupt) { |
4280 | 4284 | // Definitive status for this instance, so check compatibility |
4281 | 4285 | // with any current winning model status |
4282 | 4286 | if (winning_model_status != HighsModelStatus::kNotset) { |
4283 | | - if (winning_model_status != instance_model_status) { |
4284 | | - highsLogUser(options_.log_options, HighsLogType::kError, |
4285 | | - "MIP race: conflict between status \"%s\" for " |
4286 | | - "instance %d and status \"%s\" for instance %d\n", |
4287 | | - modelStatusToString(winning_model_status).c_str(), |
4288 | | - int(winning_instance), |
4289 | | - modelStatusToString(instance_model_status).c_str(), |
4290 | | - int(instance)); |
4291 | | - return HighsStatus::kError; |
4292 | | - } |
| 4287 | + if (winning_model_status != instance_model_status) { |
| 4288 | + highsLogUser(options_.log_options, HighsLogType::kError, |
| 4289 | + "MIP race: conflict between status \"%s\" for " |
| 4290 | + "instance %d and status \"%s\" for instance %d\n", |
| 4291 | + modelStatusToString(winning_model_status).c_str(), |
| 4292 | + int(winning_instance), |
| 4293 | + modelStatusToString(instance_model_status).c_str(), |
| 4294 | + int(instance)); |
| 4295 | + return HighsStatus::kError; |
| 4296 | + } |
4293 | 4297 | } else { |
4294 | | - winning_model_status = instance_model_status; |
4295 | | - winning_instance = instance; |
| 4298 | + winning_model_status = instance_model_status; |
| 4299 | + winning_instance = instance; |
4296 | 4300 | } |
4297 | 4301 | } |
4298 | 4302 | } |
4299 | 4303 | if (winning_instance > 0) mip_solver_info = worker_info[winning_instance]; |
4300 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, "Solving report\n"); |
4301 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " Model %s\n", |
4302 | | - this->model_.lp_.model_name_.c_str()); |
4303 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " Status %s\n", |
4304 | | - modelStatusToString(mip_solver_info.modelstatus).c_str()); |
4305 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " Primal bound %.12g\n", |
4306 | | - mip_solver_info.primal_bound); |
4307 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " Dual bound %.12g\n", |
4308 | | - mip_solver_info.dual_bound); |
4309 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " Gap %g%% (tolerance: %g%%)\n", |
4310 | | - 1e2*mip_solver_info.gap, 1e2*options_.mip_rel_gap); |
4311 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " P-D integral %.12g\n", |
4312 | | - mip_solver_info.primal_dual_integral); |
4313 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " Solution status %.12g\n", |
4314 | | - mip_solver_info.solution_objective); |
4315 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " %.12g (bound viol.)\n", |
4316 | | - mip_solver_info.bound_violation); |
4317 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " %.12g (int. viol.)\n", |
4318 | | - mip_solver_info.integrality_violation); |
4319 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " %.12g (row viol.)\n", |
4320 | | - mip_solver_info.row_violation); |
4321 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " Timing %.2f\n", |
4322 | | - mip_time[winning_instance]); |
4323 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " Nodes %llu\n", |
4324 | | - mip_solver_info.node_count); |
4325 | | - highsLogUser(options_.log_options, HighsLogType::kInfo, " LP iterations %llu\n", |
4326 | | - mip_solver_info.total_lp_iterations); |
4327 | | - /* |
4328 | | - Solution status feasible |
4329 | | - Max sub-MIP depth 1 |
4330 | | - */ |
| 4304 | + std::array<char, 128> gapString = getGapString( |
| 4305 | + mip_solver_info.gap, mip_solver_info.primal_bound, &options_); |
| 4306 | + |
| 4307 | + bool havesolution = mip_solver_info.solution_objective != kHighsInf; |
| 4308 | + bool feasible; |
| 4309 | + std::string solutionstatus = "-"; |
| 4310 | + if (havesolution) { |
| 4311 | + feasible = |
| 4312 | + mip_solver_info.bound_violation <= options_.mip_feasibility_tolerance && |
| 4313 | + mip_solver_info.integrality_violation <= |
| 4314 | + options_.mip_feasibility_tolerance && |
| 4315 | + mip_solver_info.row_violation <= options_.mip_feasibility_tolerance; |
| 4316 | + } else { |
| 4317 | + feasible = false; |
| 4318 | + } |
| 4319 | + solutionstatus = feasible ? "feasible" : "infeasible"; |
| 4320 | + |
| 4321 | + highsLogUser(options_.log_options, HighsLogType::kInfo, "Solving report\n"); |
| 4322 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4323 | + " Model %s\n", |
| 4324 | + this->model_.lp_.model_name_.c_str()); |
| 4325 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4326 | + " Status %s\n", |
| 4327 | + modelStatusToString(mip_solver_info.modelstatus).c_str()); |
| 4328 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4329 | + " Primal bound %.12g\n", mip_solver_info.primal_bound); |
| 4330 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4331 | + " Dual bound %.12g\n", mip_solver_info.dual_bound); |
| 4332 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4333 | + " Gap %s\n", gapString.data()); |
| 4334 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4335 | + " P-D integral %.12g\n", |
| 4336 | + mip_solver_info.primal_dual_integral); |
| 4337 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4338 | + " Solution status %s\n", solutionstatus.c_str()); |
| 4339 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4340 | + " %.12g\n", |
| 4341 | + mip_solver_info.solution_objective); |
| 4342 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4343 | + " %.12g (bound viol.)\n", |
| 4344 | + mip_solver_info.bound_violation); |
| 4345 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4346 | + " %.12g (int. viol.)\n", |
| 4347 | + mip_solver_info.integrality_violation); |
| 4348 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4349 | + " %.12g (row viol.)\n", |
| 4350 | + mip_solver_info.row_violation); |
| 4351 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4352 | + " Timing %.2f\n", mip_time[winning_instance]); |
| 4353 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4354 | + " Max sub-MIP depth %d\n", |
| 4355 | + int(mip_solver_info.max_submip_level)); |
| 4356 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4357 | + " Nodes %llu\n", |
| 4358 | + (long long unsigned)(mip_solver_info.node_count)); |
| 4359 | + highsLogUser(options_.log_options, HighsLogType::kInfo, |
| 4360 | + " LP iterations %llu\n", |
| 4361 | + (long long unsigned)(mip_solver_info.total_lp_iterations)); |
4331 | 4362 | return HighsStatus::kOk; |
4332 | 4363 | } |
0 commit comments