@@ -256,8 +256,11 @@ void HighsMipSolver::run() {
256256
257257 // This version works during refactor with the master pseudocost.
258258 // valgrind OK.
259- HighsSearch search{master_worker, mipdata_->pseudocost };
260- search.setLpRelaxation (&mipdata_->lp );
259+ // HighsSearch search{master_worker, mipdata_->pseudocost};
260+ // search.setLpRelaxation(&mipdata_->lp);
261+ // MT: I think search should be ties to the master worker
262+ master_worker.resetSearchDomain ();
263+ HighsSearch& search = *master_worker.search_ptr_ ;
261264
262265 // This search is from the worker and will use the worker pseudocost.
263266 // does not work yet, fails at domain propagation somewhere.
@@ -312,18 +315,23 @@ void HighsMipSolver::run() {
312315 search_started = true ;
313316 const HighsInt mip_search_concurrency = options_mip_->mip_search_concurrency ;
314317 const HighsInt num_worker = mip_search_concurrency - 1 ;
318+ highs::parallel::TaskGroup tg;
315319
316- for (int i = 0 ; i < num_worker; i++) {
317- mipdata_->lps .emplace_back (*this );
318- mipdata_->workers .emplace_back (*this , mipdata_->lps .back ());
320+ for (int i = 1 ; i < mip_search_concurrency; i++) {
321+ if (mipdata_->numRestarts <= mipdata_->numRestartsRoot ) {
322+ mipdata_->lps .emplace_back (*this );
323+ mipdata_->workers .emplace_back (*this , mipdata_->lps .back ());
324+ } else {
325+ mipdata_->workers [i].resetSearchDomain ();
326+ }
319327 }
320328
321329 // Lambda for combining limit_reached across searches
322330 auto limitReached = [&]() -> bool {
323331 bool limit_reached = false ;
324332 for (HighsInt iSearch = 0 ; iSearch < mip_search_concurrency; iSearch++)
325- limit_reached =
326- limit_reached || mipdata_->workers [iSearch].search_ptr_ ->limit_reached_ ;
333+ limit_reached = limit_reached ||
334+ mipdata_->workers [iSearch].search_ptr_ ->limit_reached_ ;
327335 return limit_reached;
328336 };
329337
@@ -332,13 +340,13 @@ void HighsMipSolver::run() {
332340 bool break_search = false ;
333341 for (HighsInt iSearch = 0 ; iSearch < mip_search_concurrency; iSearch++)
334342 break_search =
335- break_search || mipdata_->workers [iSearch].search_ptr_ ->break_search_ ;
343+ break_search || mipdata_->workers [iSearch].search_ptr_ ->break_search_ ;
336344 return break_search;
337345 };
338346
339347 // Lambda checking whether loop pass is to be skipped
340348 auto performedDive = [&](const HighsSearch& search,
341- const HighsInt iSearch) -> bool {
349+ const HighsInt iSearch) -> bool {
342350 if (iSearch == 0 ) {
343351 assert (search.performed_dive_ );
344352 } else {
@@ -359,6 +367,9 @@ void HighsMipSolver::run() {
359367
360368 analysis_.mipTimerStart (kMipClockPerformAging1 );
361369 mipdata_->conflictPool .performAging ();
370+ for (int i = 0 ; i < mip_search_concurrency; i++) {
371+ mipdata_->workers [i].conflictpool_ .performAging ();
372+ }
362373 analysis_.mipTimerStop (kMipClockPerformAging1 );
363374 // set iteration limit for each lp solve during the dive to 10 times the
364375 // average nodes
@@ -369,6 +380,9 @@ void HighsMipSolver::run() {
369380 HighsInt ((3 * mipdata_->firstrootlpiters ) / 2 )});
370381
371382 mipdata_->lp .setIterationLimit (iterlimit);
383+ for (int i = 0 ; i < mip_search_concurrency; i++) {
384+ mipdata_->lps [i].setIterationLimit (iterlimit);
385+ }
372386
373387 // perform the dive and put the open nodes to the queue
374388 size_t plungestart = mipdata_->num_nodes ;
@@ -430,21 +444,80 @@ void HighsMipSolver::run() {
430444
431445 if (mipdata_->domain .infeasible ()) break ;
432446
433- if (!search.currentNodePruned ()) {
434- double this_dive_time = -analysis_.mipTimerRead (kMipClockTheDive );
435- analysis_.mipTimerStart (kMipClockTheDive );
436- const HighsSearch::NodeResult search_dive_result = search.dive ();
437- analysis_.mipTimerStop (kMipClockTheDive );
438- if (analysis_.analyse_mip_time ) {
439- this_dive_time += analysis_.mipTimerRead (kMipClockNodeSearch );
440- analysis_.dive_time .push_back (this_dive_time);
447+ // MT: My attempt at a parallel dive
448+ std::vector<double > dive_times (mip_search_concurrency,
449+ -analysis_.mipTimerRead (kMipClockTheDive ));
450+ std::vector<HighsSearch::NodeResult> dive_results (
451+ mip_search_concurrency, HighsSearch::NodeResult::kBranched );
452+ for (int i = 0 ; i < mip_search_concurrency; i++) {
453+ printf (" %d is the value used!!\n " , i);
454+ tg.spawn ([&, i]() {
455+ printf (" %d is the value used in start of the spawn!!\n " , i);
456+ if (!mipdata_->workers [i].search_ptr_ ->hasNode () ||
457+ mipdata_->workers [i].search_ptr_ ->currentNodePruned ()) {
458+ dive_times[i] = -1 ;
459+ } else {
460+ dive_results[i] = mipdata_->workers [i].search_ptr_ ->dive ();
461+ dive_times[i] += analysis_.mipTimerRead (kMipClockNodeSearch );
462+ }
463+ printf (" %d = !hasNode\n " , !mipdata_->workers [i].search_ptr_ ->hasNode ());
464+ printf (" %d is the value used in the spawn!!\n " , i);
465+ });
466+ }
467+ // auto task = [&](const int idx) {
468+ // if (!mipdata_->workers[idx].search_ptr_->hasNode() ||
469+ // mipdata_->workers[idx].search_ptr_->currentNodePruned()) {
470+ // dive_times[idx] = -1;
471+ // } else {
472+ // dive_results[idx] = mipdata_->workers[idx].search_ptr_->dive();
473+ // dive_times[idx] += analysis_.mipTimerRead(kMipClockNodeSearch);
474+ // }
475+ // };
476+ // for (int i = 0; i < mip_search_concurrency; i++) {
477+ // tg.spawn([&]() {
478+ // task(i);
479+ // });
480+ // }
481+ // tg.spawn([&]() {
482+ // if (!mipdata_->workers[0].search_ptr_->hasNode() ||
483+ // mipdata_->workers[0].search_ptr_->currentNodePruned()) {
484+ // dive_times[0] = -1;
485+ // } else {
486+ // dive_results[0] = mipdata_->workers[0].search_ptr_->dive();
487+ // dive_times[0] += analysis_.mipTimerRead(kMipClockNodeSearch);
488+ // }
489+ // });
490+ tg.sync ();
491+ bool suboptimal = false ;
492+ for (int i = 0 ; i < 1 ; i++) {
493+ if (dive_times[i] != -1 ) {
494+ analysis_.dive_time .push_back (dive_times[i]);
495+ if (dive_results[i] == HighsSearch::NodeResult::kSubOptimal ) {
496+ suboptimal = true ;
497+ } else {
498+ ++mipdata_->num_leaves ;
499+ mipdata_->workers [i].search_ptr_ ->flushStatistics ();
500+ }
441501 }
442- if (search_dive_result == HighsSearch::NodeResult::kSubOptimal ) break ;
443-
444- ++mipdata_->num_leaves ;
445-
446- search.flushStatistics ();
447502 }
503+ if (suboptimal) break ;
504+
505+ // if (!search.currentNodePruned()) {
506+ // double this_dive_time = -analysis_.mipTimerRead(kMipClockTheDive);
507+ // analysis_.mipTimerStart(kMipClockTheDive);
508+ // const HighsSearch::NodeResult search_dive_result = search.dive();
509+ // analysis_.mipTimerStop(kMipClockTheDive);
510+ // if (analysis_.analyse_mip_time) {
511+ // this_dive_time += analysis_.mipTimerRead(kMipClockNodeSearch);
512+ // analysis_.dive_time.push_back(this_dive_time);
513+ // }
514+ // if (search_dive_result == HighsSearch::NodeResult::kSubOptimal)
515+ // break;
516+ //
517+ // ++mipdata_->num_leaves;
518+ //
519+ // search.flushStatistics();
520+ // }
448521
449522 if (mipdata_->checkLimits ()) {
450523 limit_reached = true ;
0 commit comments