Skip to content

Commit d171a40

Browse files
committed
Add lambda for sepa and store basis
1 parent ebec009 commit d171a40

File tree

1 file changed

+70
-45
lines changed

1 file changed

+70
-45
lines changed

highs/mip/HighsMipSolver.cpp

Lines changed: 70 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -629,8 +629,8 @@ void HighsMipSolver::run() {
629629
std::vector<bool> prune(search_indices.size(), false);
630630
for (HighsInt i = 0; i < search_indices.size(); i++) {
631631
// TODO MT: Remove this redundant if
632-
if (search_indices[i] != 0 ||
633-
!mipdata_->workers[search_indices[i]].search_ptr_->currentNodePruned())
632+
if (search_indices[i] != 0 || !mipdata_->workers[search_indices[i]]
633+
.search_ptr_->currentNodePruned())
634634
continue;
635635
infeasible.emplace_back(false);
636636
flush.emplace_back(false);
@@ -658,8 +658,7 @@ void HighsMipSolver::run() {
658658
}
659659

660660
// Remove search indices that need a new node
661-
HighsInt num_search_indices =
662-
static_cast<HighsInt>(search_indices.size());
661+
HighsInt num_search_indices = static_cast<HighsInt>(search_indices.size());
663662
for (HighsInt i = num_search_indices - 1; i >= 0; i--) {
664663
if (prune[i]) {
665664
num_search_indices--;
@@ -695,6 +694,70 @@ void HighsMipSolver::run() {
695694
return std::make_pair(false, false);
696695
};
697696

697+
auto separateAndStoreBasis =
698+
[&](std::vector<HighsInt>& search_indices) -> bool {
699+
// the node is still not fathomed, so perform separation
700+
analysis_.mipTimerStart(kMipClockNodeSearchSeparation);
701+
for (HighsInt i : search_indices) {
702+
// TODO MT: Get rid of this line
703+
if (i != 0) continue;
704+
if (mipdata_->parallelLockActive()) {
705+
tg.spawn([&, i]() {
706+
mipdata_->workers[i].sepa_ptr_->separate(mipdata_->workers[i], mipdata_->workers[i].search_ptr_->getLocalDomain());
707+
});
708+
} else {
709+
mipdata_->workers[i].sepa_ptr_->separate(
710+
mipdata_->workers[i],
711+
mipdata_->workers[i].search_ptr_->getLocalDomain());
712+
}
713+
}
714+
analysis_.mipTimerStop(kMipClockNodeSearchSeparation);
715+
if (mipdata_->parallelLockActive()) tg.taskWait();
716+
717+
for (HighsInt i : search_indices) {
718+
// TODO MT: Get rid of this line
719+
if (i != 0) continue;
720+
if (mipdata_->workers[i].globaldom_.infeasible()) {
721+
mipdata_->workers[i].search_ptr_->cutoffNode();
722+
analysis_.mipTimerStart(kMipClockOpenNodesToQueue1);
723+
mipdata_->workers[i].search_ptr_->openNodesToQueue(mipdata_->nodequeue);
724+
analysis_.mipTimerStop(kMipClockOpenNodesToQueue1);
725+
mipdata_->nodequeue.clear();
726+
mipdata_->pruned_treeweight = 1.0;
727+
728+
analysis_.mipTimerStart(kMipClockStoreBasis);
729+
double prev_lower_bound = mipdata_->lower_bound;
730+
731+
mipdata_->lower_bound = std::min(kHighsInf, mipdata_->upper_bound);
732+
733+
bool bound_change = mipdata_->lower_bound != prev_lower_bound;
734+
if (!submip && bound_change)
735+
mipdata_->updatePrimalDualIntegral(
736+
prev_lower_bound, mipdata_->lower_bound, mipdata_->upper_bound,
737+
mipdata_->upper_bound);
738+
return true;
739+
}
740+
// after separation we store the new basis and proceed with the outer loop
741+
// to perform a dive from this node
742+
if (mipdata_->workers[i].lprelaxation_->getStatus() !=
743+
HighsLpRelaxation::Status::kError &&
744+
mipdata_->workers[i].lprelaxation_->getStatus() !=
745+
HighsLpRelaxation::Status::kNotSet)
746+
mipdata_->workers[i].lprelaxation_->storeBasis();
747+
748+
basis = mipdata_->workers[i].lprelaxation_->getStoredBasis();
749+
if (!basis || !isBasisConsistent(
750+
mipdata_->workers[i].lprelaxation_->getLp(), *basis)) {
751+
HighsBasis b = mipdata_->firstrootbasis;
752+
b.row_status.resize(mipdata_->workers[i].lprelaxation_->numRows(),
753+
HighsBasisStatus::kBasic);
754+
basis = std::make_shared<const HighsBasis>(std::move(b));
755+
mipdata_->workers[i].lprelaxation_->setStoredBasis(basis);
756+
}
757+
}
758+
return false;
759+
};
760+
698761
auto diveAllSearches = [&]() -> bool {
699762
std::vector<double> dive_times(mip_search_concurrency,
700763
-analysis_.mipTimerRead(kMipClockTheDive));
@@ -1040,6 +1103,7 @@ void HighsMipSolver::run() {
10401103
// printf("popping node from nodequeue (length = %" HIGHSINT_FORMAT ")\n",
10411104
// (HighsInt)nodequeue.size());
10421105
std::vector<HighsInt> search_indices = getSearchIndicesWithNoNodes();
1106+
if (search_indices[0] != 0) break;
10431107
// if (search_indices.size() >= mip_search_concurrency) break;
10441108

10451109
installNodes(search_indices, limit_reached);
@@ -1058,47 +1122,8 @@ void HighsMipSolver::run() {
10581122
// TODO MT: Change this line
10591123
if (search_indices.empty() || search_indices[0] != 0) continue;
10601124

1061-
// the node is still not fathomed, so perform separation
1062-
analysis_.mipTimerStart(kMipClockNodeSearchSeparation);
1063-
sepa.separate(master_worker, search.getLocalDomain());
1064-
analysis_.mipTimerStop(kMipClockNodeSearchSeparation);
1065-
1066-
if (mipdata_->domain.infeasible()) {
1067-
search.cutoffNode();
1068-
analysis_.mipTimerStart(kMipClockOpenNodesToQueue1);
1069-
search.openNodesToQueue(mipdata_->nodequeue);
1070-
analysis_.mipTimerStop(kMipClockOpenNodesToQueue1);
1071-
mipdata_->nodequeue.clear();
1072-
mipdata_->pruned_treeweight = 1.0;
1073-
1074-
analysis_.mipTimerStart(kMipClockStoreBasis);
1075-
double prev_lower_bound = mipdata_->lower_bound;
1076-
1077-
mipdata_->lower_bound = std::min(kHighsInf, mipdata_->upper_bound);
1078-
1079-
bool bound_change = mipdata_->lower_bound != prev_lower_bound;
1080-
if (!submip && bound_change)
1081-
mipdata_->updatePrimalDualIntegral(
1082-
prev_lower_bound, mipdata_->lower_bound, mipdata_->upper_bound,
1083-
mipdata_->upper_bound);
1084-
break;
1085-
}
1086-
1087-
// after separation we store the new basis and proceed with the outer loop
1088-
// to perform a dive from this node
1089-
if (mipdata_->lp.getStatus() != HighsLpRelaxation::Status::kError &&
1090-
mipdata_->lp.getStatus() != HighsLpRelaxation::Status::kNotSet)
1091-
mipdata_->lp.storeBasis();
1092-
1093-
basis = mipdata_->lp.getStoredBasis();
1094-
if (!basis || !isBasisConsistent(mipdata_->lp.getLp(), *basis)) {
1095-
HighsBasis b = mipdata_->firstrootbasis;
1096-
b.row_status.resize(mipdata_->lp.numRows(), HighsBasisStatus::kBasic);
1097-
basis = std::make_shared<const HighsBasis>(std::move(b));
1098-
mipdata_->lp.setStoredBasis(basis);
1099-
}
1100-
1101-
break;
1125+
bool infeasible = separateAndStoreBasis(search_indices);
1126+
if (infeasible) break;
11021127
} // while(!mipdata_->nodequeue.empty())
11031128
analysis_.mipTimerStop(kMipClockNodeSearch);
11041129
if (analysis_.analyse_mip_time) {

0 commit comments

Comments
 (0)