@@ -4045,12 +4045,15 @@ HighsStatus Highs::callSolveMip() {
40454045 worker_callback.clear ();
40464046 // Race the MIP solver!
40474047 highsLogUser (options_.log_options , HighsLogType::kInfo ,
4048- " Starting MIP race with %d instances: performance is non-deterministic!\n " , int (mip_race_concurrency));
4048+ " Starting MIP race with %d instances: performance is "
4049+ " non-deterministic!\n " ,
4050+ int (mip_race_concurrency));
40494051 // Define the HighsMipSolverInfo record for each worker
40504052 std::vector<HighsMipSolverInfo> worker_info (mip_race_concurrency);
40514053 // Set up the vector of options settings for workers
40524054 std::vector<HighsOptions> worker_options;
40534055 // std::vector<HighsMipSolver*> worker;
4056+ std::vector<double > mip_time (mip_race_concurrency);
40544057 for (HighsInt instance = 0 ; instance < mip_race_concurrency; instance++) {
40554058 HighsOptions instance_options = options_;
40564059 // No workers log to console
@@ -4059,13 +4062,12 @@ HighsStatus Highs::callSolveMip() {
40594062 // Use the instance ID as an offset to the random seed
40604063 instance_options.random_seed = options_.random_seed + instance;
40614064 std::string worker_log_file =
4062- " mip_worker" + std::to_string (instance) + " .log" ;
4065+ " mip_worker" + std::to_string (instance) + " .log" ;
40634066 highsOpenLogFile (instance_options, worker_log_file);
40644067 worker_options.push_back (instance_options);
40654068 /*
4066- HighsMipSolver worker_instance(worker_callback, worker_options[instance], lp,
4067- solution_);
4068- worker.push_back(&worker_instance);
4069+ HighsMipSolver worker_instance(worker_callback, worker_options[instance],
4070+ lp, solution_); worker.push_back(&worker_instance);
40694071 */
40704072 }
40714073 highs::parallel::for_each (
@@ -4075,49 +4077,58 @@ HighsStatus Highs::callSolveMip() {
40754077 solver.mip_race_ .initialise (mip_race_concurrency, instance,
40764078 &mip_race_record,
40774079 options_.log_options );
4080+ mip_time[instance] = -timer_.read ();
40784081 solver.run ();
4079- mip_solver_info = getMipSolverInfo (solver);
4082+ mip_time[instance] += timer_.read ();
4083+ mip_solver_info = getMipSolverInfo (solver);
40804084 } else {
4081- HighsMipSolver worker (worker_callback, worker_options[instance], lp,
4082- solution_);
4085+ HighsMipSolver worker (worker_callback, worker_options[instance],
4086+ lp, solution_);
40834087 worker.mip_race_ .initialise (mip_race_concurrency, instance,
40844088 &mip_race_record,
40854089 worker_options[instance].log_options );
4090+ mip_time[instance] = -timer_.read ();
40864091 worker.run ();
4087- worker_info[instance] = getMipSolverInfo (worker);
4092+ mip_time[instance] += timer_.read ();
4093+ worker_info[instance] = getMipSolverInfo (worker);
40884094 }
40894095 }
40904096 });
40914097 // Report on the solver and workers, and identify which has won!
40924098 HighsInt winning_instance = -1 ;
40934099 HighsModelStatus winning_model_status = HighsModelStatus::kNotset ;
40944100 highsLogUser (options_.log_options , HighsLogType::kInfo ,
4095- " MIP race results:\n " );
4101+ " MIP race results:\n " );
40964102 for (HighsInt instance = 0 ; instance < mip_race_concurrency; instance++) {
4097- const HighsMipSolverInfo& solver_info = instance == 0 ? mip_solver_info : worker_info[instance];
4103+ const HighsMipSolverInfo& solver_info =
4104+ instance == 0 ? mip_solver_info : worker_info[instance];
40984105 HighsModelStatus instance_model_status = solver_info.modelstatus ;
40994106 highsLogUser (options_.log_options , HighsLogType::kInfo ,
4100- " Solver %d has best objective %15.8g, gap %6.2f\%, and status %s\n " ,
4101- int (instance), solver_info.solution_objective , 1e2 * solver_info.gap ,
4102- modelStatusToString (instance_model_status).c_str ());
4107+ " Solver %d has best objective %15.8g, gap %6.2f\% (time "
4108+ " = %6.2f), and status %s\n " ,
4109+ int (instance), solver_info.solution_objective ,
4110+ 1e2 * solver_info.gap , mip_time[instance],
4111+ modelStatusToString (instance_model_status).c_str ());
41034112 if (instance_model_status != HighsModelStatus::kHighsInterrupt ) {
4104- // Definitive status for this instance, so check compatibility
4105- // with any current winning model status
4106- if (winning_model_status != HighsModelStatus::kNotset ) {
4107- if (winning_model_status != instance_model_status) {
4108- highsLogUser (options_.log_options , HighsLogType::kError ,
4109- " MIP race: conflict between status \" %s\" for instance %d and status \" %s\" for instance %d\n " ,
4110- modelStatusToString (winning_model_status).c_str (), int (winning_instance),
4111- modelStatusToString (instance_model_status).c_str (), int (instance));
4112- }
4113- } else {
4114- winning_model_status = instance_model_status;
4115- winning_instance = instance;
4116- }
4113+ // Definitive status for this instance, so check compatibility
4114+ // with any current winning model status
4115+ if (winning_model_status != HighsModelStatus::kNotset ) {
4116+ if (winning_model_status != instance_model_status) {
4117+ highsLogUser (options_.log_options , HighsLogType::kError ,
4118+ " MIP race: conflict between status \" %s\" for "
4119+ " instance %d and status \" %s\" for instance %d\n " ,
4120+ modelStatusToString (winning_model_status).c_str (),
4121+ int (winning_instance),
4122+ modelStatusToString (instance_model_status).c_str (),
4123+ int (instance));
4124+ }
4125+ } else {
4126+ winning_model_status = instance_model_status;
4127+ winning_instance = instance;
4128+ }
41174129 }
41184130 }
4119- if (winning_instance > 0 )
4120- mip_solver_info = worker_info[winning_instance];
4131+ if (winning_instance > 0 ) mip_solver_info = worker_info[winning_instance];
41214132 } else {
41224133 // Run a single MIP solver
41234134 solver.run ();
@@ -4135,8 +4146,10 @@ HighsStatus Highs::callSolveMip() {
41354146 HighsInt solver_solution_size = mip_solver_info.solution .size ();
41364147 const bool solver_solution_size_ok = solver_solution_size >= lp.num_col_ ;
41374148 if (!solver_solution_size)
4138- highsLogUser (options_.log_options , HighsLogType::kError ,
4139- " After MIP race, size of solution is %d < %d = lp.num_col_\n " , int (solver_solution_size), int (lp.num_col_ ));
4149+ highsLogUser (
4150+ options_.log_options , HighsLogType::kError ,
4151+ " After MIP race, size of solution is %d < %d = lp.num_col_\n " ,
4152+ int (solver_solution_size), int (lp.num_col_ ));
41404153 assert (solver_solution_size >= lp.num_col_ );
41414154 // If the original model has semi-variables, its solution is
41424155 // (still) given by the first model_.lp_.num_col_ entries of the
@@ -4186,8 +4199,8 @@ HighsStatus Highs::callSolveMip() {
41864199 return_status = checkOptimality (" MIP" );
41874200 // Overwrite max infeasibility to include integrality if there is a solution
41884201 if (mip_solver_info.solution_objective != kHighsInf ) {
4189- const double mip_max_bound_violation =
4190- std::max ( mip_solver_info.row_violation , mip_solver_info.bound_violation );
4202+ const double mip_max_bound_violation = std::max (
4203+ mip_solver_info.row_violation , mip_solver_info.bound_violation );
41914204 const double delta_max_bound_violation =
41924205 std::abs (mip_max_bound_violation - info_.max_primal_infeasibility );
41934206 // Possibly report a mis-match between the max bound violation
@@ -4887,7 +4900,6 @@ void Highs::getHighsFiles() {
48874900 this ->files_ .clear ();
48884901}
48894902
4890-
48914903HighsMipSolverInfo getMipSolverInfo (const HighsMipSolver& mip_solver) {
48924904 HighsMipSolverInfo mip_solver_info;
48934905 mip_solver_info.clear ();
0 commit comments