@@ -2621,6 +2621,7 @@ bool HighsMipSolverData::interruptFromCallbackWithData(
26212621void HighsMipSolverData::queryExternalSolution (
26222622 const double mipsolver_objective_value,
26232623 const ExternalMipSolutionQueryOrigin external_solution_query_origin) {
2624+ assert (!mipsolver.submip );
26242625 HighsCallback* callback = mipsolver.callback_ ;
26252626 const bool use_callback =
26262627 callback->user_callback && callback->active [kCallbackMipUserSolution ];
@@ -2664,11 +2665,29 @@ void HighsMipSolverData::queryExternalSolution(
26642665 is_user_solution);
26652666 }
26662667 }
2668+ if (!mipsolver.options_mip_ ->mip_race_read_solutions ) return ;
2669+ MipRace& mip_race = mipsolver.mip_race_ ;
2670+ if (!mip_race.record ) return ;
2671+ double instance_solution_objective_value;
2672+ std::vector<double > instance_solution;
2673+ for (HighsInt instance = 0 ; instance < mip_race.concurrency (); instance++) {
2674+ if (instance == mip_race.my_instance ) continue ;
2675+ HighsInt read_incumbent = mip_race.newSolution (instance, instance_solution_objective_value, instance_solution);
2676+ if (read_incumbent < 0 ) continue ;
2677+ if (read_incumbent <= mip_race.last_incumbent_read [instance]) continue ;
2678+ // Have read a new incumbent
2679+ std::vector<double > reduced_instance_solution;
2680+ reduced_instance_solution =
2681+ postSolveStack.getReducedPrimalSolution (instance_solution);
2682+ addIncumbent (reduced_instance_solution, instance_solution_objective_value,
2683+ kSolutionSourceHighsSolution );
2684+
2685+ }
26672686}
26682687
26692688HighsInt HighsMipSolverData::mipRaceConcurrency () const {
2670- if (!mipsolver.mip_race_ .record ) return ;
26712689 assert (!mipsolver.submip );
2690+ if (!mipsolver.mip_race_ .record ) return ;
26722691 return mipsolver.mip_race_ .concurrency ();
26732692}
26742693
@@ -2679,22 +2698,23 @@ void HighsMipSolverData::mipRaceUpdate() {
26792698 mipsolver.solution_ );
26802699}
26812700
2682- bool HighsMipSolverData::mipRaceNewSolution (double & objective_value ,
2683- std::vector< double >& solution) {
2684- if (!mipsolver. mip_race_ . record ) return false ;
2701+ HighsInt HighsMipSolverData::mipRaceNewSolution (const HighsInt instance ,
2702+ double & objective_value,
2703+ std::vector< double >& solution) {
26852704 assert (!mipsolver.submip );
2686- return false ;
2705+ if (!mipsolver.mip_race_ .record ) return kMipRaceNoSolution ;
2706+ return mipsolver.mip_race_ .newSolution (instance, objective_value, solution);
26872707}
26882708
26892709void HighsMipSolverData::mipRaceTerminate () {
2690- if (!mipsolver.mip_race_ .record ) return ;
26912710 assert (!mipsolver.submip );
2711+ if (!mipsolver.mip_race_ .record ) return ;
26922712 mipsolver.mip_race_ .terminate ();
26932713}
26942714
26952715bool HighsMipSolverData::mipRaceTerminated () const {
2696- if (!mipsolver.mip_race_ .record ) return false ;
26972716 assert (!mipsolver.submip );
2717+ if (!mipsolver.mip_race_ .record ) return false ;
26982718 return mipsolver.mip_race_ .terminated ();
26992719}
27002720
@@ -2840,8 +2860,8 @@ void HighsMipSolverData::updatePrimalDualIntegral(const double from_lower_bound,
28402860void HighsPrimaDualIntegral::initialise () { this ->value = -kHighsInf ; }
28412861
28422862void MipRaceIncumbent::clear () {
2843- this ->start_write_incumbent = - 1 ;
2844- this ->finish_write_incumbent = - 1 ;
2863+ this ->start_write_incumbent = kMipRaceNoSolution ;
2864+ this ->finish_write_incumbent = kMipRaceNoSolution ;
28452865 this ->objective = -kHighsInf ;
28462866 this ->solution .clear ();
28472867}
@@ -2861,17 +2881,17 @@ void MipRaceIncumbent::update(const double objective_,
28612881 assert (this ->start_write_incumbent == this ->finish_write_incumbent );
28622882}
28632883
2864- bool MipRaceIncumbent::readOk (double & objective_,
2865- std::vector<double >& solution_) const {
2884+ HighsInt MipRaceIncumbent::read (double & objective_,
2885+ std::vector<double >& solution_) const {
28662886 const HighsInt start_write_incumbent = this ->start_write_incumbent ;
28672887 assert (this ->finish_write_incumbent <= start_write_incumbent);
28682888 // If a write call has not completed, return failure
2869- if (this ->finish_write_incumbent < start_write_incumbent) return false ;
2889+ if (this ->finish_write_incumbent < start_write_incumbent) return kMipRaceNoSolution ;
28702890 // finish_write_incumbent = start_write_incumbent so start reading
28712891 objective_ = this ->objective ;
28722892 solution_ = this ->solution ;
28732893 // Read is OK if no new write has started
2874- return this ->start_write_incumbent == start_write_incumbent;
2894+ return this ->start_write_incumbent == start_write_incumbent ? start_write_incumbent : kMipRaceNoSolution ;
28752895}
28762896
28772897void MipRaceRecord::clear () {
@@ -2902,22 +2922,22 @@ void MipRaceRecord::report(const HighsLogOptions log_options) const {
29022922 HighsInt mip_race_concurrency = this ->concurrency ();
29032923 highsLogUser (log_options, HighsLogType::kInfo , " \n MipRaceRecord: " );
29042924 for (HighsInt instance = 0 ; instance < mip_race_concurrency; instance++)
2905- highsLogUser (log_options, HighsLogType::kInfo , " %11d " , int (instance));
2925+ highsLogUser (log_options, HighsLogType::kInfo , " %16d " , int (instance));
29062926 highsLogUser (log_options, HighsLogType::kInfo , " \n Terminated: " );
29072927 for (HighsInt instance = 0 ; instance < mip_race_concurrency; instance++)
2908- highsLogUser (log_options, HighsLogType::kInfo , " %11s " ,
2928+ highsLogUser (log_options, HighsLogType::kInfo , " %16s " ,
29092929 this ->terminated [instance] ? " T" : " F" );
29102930 highsLogUser (log_options, HighsLogType::kInfo , " \n StartWrite: " );
29112931 for (HighsInt instance = 0 ; instance < mip_race_concurrency; instance++)
2912- highsLogUser (log_options, HighsLogType::kInfo , " %11d " ,
2932+ highsLogUser (log_options, HighsLogType::kInfo , " %16d " ,
29132933 this ->incumbent [instance].start_write_incumbent );
29142934 highsLogUser (log_options, HighsLogType::kInfo , " \n Objective: " );
29152935 for (HighsInt instance = 0 ; instance < mip_race_concurrency; instance++)
2916- highsLogUser (log_options, HighsLogType::kInfo , " %11.4g " ,
2936+ highsLogUser (log_options, HighsLogType::kInfo , " %16.8g " ,
29172937 this ->incumbent [instance].objective );
29182938 highsLogUser (log_options, HighsLogType::kInfo , " \n FinishWrite: " );
29192939 for (HighsInt instance = 0 ; instance < mip_race_concurrency; instance++)
2920- highsLogUser (log_options, HighsLogType::kInfo , " %11d " ,
2940+ highsLogUser (log_options, HighsLogType::kInfo , " %16d " ,
29212941 this ->incumbent [instance].finish_write_incumbent );
29222942 highsLogUser (log_options, HighsLogType::kInfo , " \n " );
29232943}
@@ -2936,7 +2956,7 @@ void MipRace::initialise(const HighsInt mip_race_concurrency,
29362956 this ->my_instance = my_instance_;
29372957 this ->record = record_;
29382958 this ->log_options = log_options_;
2939- this ->last_incumbent_read .assign (mip_race_concurrency, - 1 );
2959+ this ->last_incumbent_read .assign (mip_race_concurrency, kMipRaceNoSolution );
29402960}
29412961
29422962HighsInt MipRace::concurrency () const {
@@ -2951,10 +2971,10 @@ void MipRace::update(const double objective,
29512971 this ->report ();
29522972}
29532973
2954- bool MipRace::newSolution (double objective,
2974+ HighsInt MipRace::newSolution (const HighsInt instance, double objective,
29552975 std::vector<double >& solution) const {
29562976 assert (this ->record );
2957- return false ;
2977+ return this -> record -> incumbent [instance]. read (objective, solution) ;
29582978}
29592979
29602980void MipRace::terminate () {
@@ -2974,7 +2994,7 @@ void MipRace::report() const {
29742994 this ->record ->report (this ->log_options );
29752995 highsLogUser (this ->log_options , HighsLogType::kInfo , " LastIncumbentRead: " );
29762996 for (HighsInt instance = 0 ; instance < this ->concurrency (); instance++)
2977- highsLogUser (this ->log_options , HighsLogType::kInfo , " %11d " ,
2997+ highsLogUser (this ->log_options , HighsLogType::kInfo , " %16d " ,
29782998 this ->last_incumbent_read [instance]);
29792999 highsLogUser (this ->log_options , HighsLogType::kInfo , " \n\n " );
29803000}
0 commit comments