@@ -278,33 +278,20 @@ void HighsMipSolver::run() {
278278 // int(mipdata_->lps.at(0).getLpSolver().getNumRow()));
279279
280280 std::shared_ptr<const HighsBasis> basis;
281-
282281 double prev_lower_bound = mipdata_->lower_bound ;
283-
284282 mipdata_->lower_bound = mipdata_->nodequeue .getBestLowerBound ();
285-
286283 bool bound_change = mipdata_->lower_bound != prev_lower_bound;
287284 if (!submip && bound_change)
288285 mipdata_->updatePrimalDualIntegral (prev_lower_bound, mipdata_->lower_bound ,
289286 mipdata_->upper_bound ,
290287 mipdata_->upper_bound );
291-
292288 mipdata_->printDisplayLine ();
293- int64_t num_nodes = mipdata_->nodequeue .numNodes ();
294- if (num_nodes > 1 ) {
295- // Should be exactly one node on the queue?
296- if (debug_logging)
297- printf (
298- " HighsMipSolver::run() popping node from nodequeue with %d > 1 "
299- " nodes\n " ,
300- HighsInt (num_nodes));
301- assert (num_nodes == 1 );
302- }
303289
304290 // Initialize worker relaxations and mipworkers
305291 const HighsInt mip_search_concurrency = options_mip_->mip_search_concurrency ;
306292 const HighsInt num_workers =
307- highs::parallel::num_threads () == 1 || mip_search_concurrency <= 1
293+ highs::parallel::num_threads () == 1 || mip_search_concurrency <= 1 ||
294+ submip
308295 ? 1
309296 : mip_search_concurrency * highs::parallel::num_threads ();
310297 highs::parallel::TaskGroup tg;
@@ -487,8 +474,14 @@ void HighsMipSolver::run() {
487474
488475 // TODO: Should we be propagating this first?
489476 destroyOldWorkers ();
490- if (num_workers > 1 ) resetGlobalDomain (true );
491- if (num_workers > 1 ) constructAdditionalWorkerData (master_worker);
477+ // TODO: Is this reset actually needed? Is copying over all
478+ // the current domain changes actually going to cause an error?
479+ if (num_workers > 1 ) {
480+ resetGlobalDomain (true );
481+ constructAdditionalWorkerData (master_worker);
482+ } else {
483+ master_worker.search_ptr_ ->resetLocalDomain ();
484+ }
492485 master_worker.upper_bound = mipdata_->upper_bound ;
493486 master_worker.upper_limit = mipdata_->upper_limit ;
494487 master_worker.optimality_limit = mipdata_->optimality_limit ;
@@ -607,8 +600,7 @@ void HighsMipSolver::run() {
607600 }
608601 };
609602
610- auto handlePrunedNodes =
611- [&](std::vector<HighsInt>& search_indices) -> std::pair<bool , bool > {
603+ auto handlePrunedNodes = [&](std::vector<HighsInt>& search_indices) -> bool {
612604 // If flush then change statistics for all searches where this was the case
613605 // If infeasible then global domain is infeasible and stop the solve
614606 // If limit_reached then return something appropriate
@@ -673,10 +665,6 @@ void HighsMipSolver::run() {
673665 prev_lower_bound, mipdata_->lower_bound , mipdata_->upper_bound ,
674666 mipdata_->upper_bound );
675667
676- if (!multiple_workers) {
677- assert (i == 0 );
678- resetGlobalDomain ();
679- }
680668 prune[i] = true ;
681669 };
682670 analysis_.mipTimerStart (kMipClockNodePrunedLoop );
@@ -714,7 +702,7 @@ void HighsMipSolver::run() {
714702 prev_lower_bound, mipdata_->lower_bound , mipdata_->upper_bound ,
715703 mipdata_->upper_bound );
716704 analysis_.mipTimerStop (kMipClockNodePrunedLoop );
717- return std::make_pair ( false , true ) ;
705+ return true ;
718706 }
719707 }
720708
@@ -731,12 +719,11 @@ void HighsMipSolver::run() {
731719 mipdata_->upper_bound );
732720 }
733721
722+ analysis_.mipTimerStop (kMipClockNodePrunedLoop );
734723 if (mipdata_->checkLimits ()) {
735- analysis_.mipTimerStop (kMipClockNodePrunedLoop );
736- return std::make_pair (true , false );
724+ return true ;
737725 }
738- analysis_.mipTimerStop (kMipClockNodePrunedLoop );
739- return std::make_pair (false , false );
726+ return false ;
740727 };
741728
742729 auto separateAndStoreBasis =
@@ -901,8 +888,9 @@ void HighsMipSolver::run() {
901888 solution_objective_, kExternalMipSolutionQueryOriginBeforeDive );
902889
903890 analysis_.mipTimerStart (kMipClockPerformAging1 );
904- for (HighsConflictPool& conflictpool : mipdata_->conflictpools ) {
905- conflictpool.performAging ();
891+ // TODO: Is there a need to age local pools? They're essentially deleted.
892+ for (HighsConflictPool& conflict_pool : mipdata_->conflictpools ) {
893+ conflict_pool.performAging ();
906894 }
907895 analysis_.mipTimerStop (kMipClockPerformAging1 );
908896 // set iteration limit for each lp solve during the dive to 10 times the
@@ -956,22 +944,22 @@ void HighsMipSolver::run() {
956944 search.backtrackPlunge (mipdata_->nodequeue );
957945 analysis_.mipTimerStop (kMipClockBacktrackPlunge );
958946 if (!backtrack_plunge) break ;
959- }
947+ assert (search. hasNode ());
960948
961- if (!mipdata_->hasMultipleWorkers ()) assert (search.hasNode ());
949+ analysis_.mipTimerStart (kMipClockPerformAging2 );
950+ for (HighsConflictPool& conflictpool : mipdata_->conflictpools ) {
951+ if (conflictpool.getNumConflicts () >
952+ options_mip_->mip_pool_soft_limit ) {
953+ conflictpool.performAging ();
954+ }
955+ }
956+ analysis_.mipTimerStop (kMipClockPerformAging2 );
962957
963- analysis_.mipTimerStart (kMipClockPerformAging2 );
964- for (HighsConflictPool& conflictpool : mipdata_->conflictpools ) {
965- if (conflictpool.getNumConflicts () >
966- options_mip_->mip_pool_soft_limit ) {
967- conflictpool.performAging ();
958+ for (HighsMipWorker& worker : mipdata_->workers ) {
959+ worker.search_ptr_ ->flushStatistics ();
968960 }
969961 }
970- analysis_.mipTimerStop (kMipClockPerformAging2 );
971962
972- for (HighsMipWorker& worker : mipdata_->workers ) {
973- worker.search_ptr_ ->flushStatistics ();
974- }
975963 mipdata_->printDisplayLine ();
976964 if (mipdata_->hasMultipleWorkers ()) break ;
977965 // printf("continue plunging due to good estimate\n");
@@ -990,6 +978,7 @@ void HighsMipSolver::run() {
990978 worker.search_ptr_ ->flushStatistics ();
991979 }
992980
981+ // TODO: Is this sync needed?
993982 syncSolutions ();
994983
995984 if (limit_reached) {
@@ -1013,8 +1002,8 @@ void HighsMipSolver::run() {
10131002 // propagate the global domain
10141003 analysis_.mipTimerStart (kMipClockDomainPropgate );
10151004 // sync global domain changes from parallel dives
1016- syncGlobalDomain ();
10171005 syncPools ();
1006+ syncGlobalDomain ();
10181007 mipdata_->domain .propagate ();
10191008 analysis_.mipTimerStop (kMipClockDomainPropgate );
10201009
@@ -1057,7 +1046,8 @@ void HighsMipSolver::run() {
10571046 if (mipdata_->hasMultipleWorkers ()) resetWorkerDomains ();
10581047 // flush all changes made to the global domain
10591048 resetGlobalDomain ();
1060- if (!mipdata_->hasMultipleWorkers ()) search.resetLocalDomain ();
1049+ // TODO: Does this line need to be here? Isn't it already reset above?
1050+ // if (!mipdata_->hasMultipleWorkers()) search.resetLocalDomain();
10611051
10621052 if (!submip && mipdata_->num_nodes >= nextCheck) {
10631053 auto nTreeRestarts = mipdata_->numRestarts - mipdata_->numRestartsRoot ;
@@ -1157,11 +1147,10 @@ void HighsMipSolver::run() {
11571147 // new global information before we perform separation rounds for the node
11581148 evaluateNodes (search_indices);
11591149
1160- // if the node was pruned we remove it from the search and install the
1161- // next node from the queue
1162- std::pair<bool , bool > limit_or_infeas = handlePrunedNodes (search_indices);
1163- if (limit_or_infeas.first ) limit_reached = true ;
1164- if (limit_or_infeas.first || limit_or_infeas.second ) break ;
1150+ // if the node was pruned we remove it from the search
1151+ // TODO MT: I'm overloading limit_reached with an infeasible status here.
1152+ limit_reached = handlePrunedNodes (search_indices);
1153+ if (limit_reached) break ;
11651154 // TODO MT: If everything was pruned then do a global sync!
11661155 if (search_indices.empty ()) {
11671156 if (mipdata_->hasMultipleWorkers ()) {
0 commit comments