Skip to content

Commit a4ac096

Browse files
committed
Fix conflict bug. Parallel dives
1 parent 62c4994 commit a4ac096

File tree

3 files changed

+16
-31
lines changed

3 files changed

+16
-31
lines changed

highs/mip/HighsConflictPool.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ void HighsConflictPool::performAging(const bool thread_safe) {
197197

198198
ageDistribution_[ages_[i]] -= 1;
199199
ages_[i] += 1;
200+
usedInDive_[i] = false;
200201

201202
if (ages_[i] > agelim) {
202203
ages_[i] = -1;
@@ -239,20 +240,22 @@ void HighsConflictPool::addConflictFromOtherPool(
239240
conflictRanges_.emplace_back(start, end);
240241
ages_.resize(conflictRanges_.size());
241242
modification_.resize(conflictRanges_.size());
243+
usedInDive_.resize(conflictRanges_.size());
242244
} else {
243245
conflictIndex = deletedConflicts_.back();
244246
deletedConflicts_.pop_back();
245247
conflictRanges_[conflictIndex].first = start;
246248
conflictRanges_[conflictIndex].second = end;
247249
}
248250

251+
usedInDive_[conflictIndex] = false;
249252
modification_[conflictIndex] += 1;
250253
ages_[conflictIndex] = 0;
251254
ageDistribution_[ages_[conflictIndex]] += 1;
252255

253256
for (HighsInt i = 0; i != conflictLen; ++i) {
254257
assert(start + i < end);
255-
conflictEntries_[i] = conflictEntries[i];
258+
conflictEntries_[start + i] = conflictEntries[i];
256259
}
257260

258261
for (HighsDomain::ConflictPoolPropagation* conflictProp : propagationDomains)
@@ -265,6 +268,7 @@ void HighsConflictPool::syncConflictPool(HighsConflictPool& syncpool) {
265268
if (ages_[i] < 0) continue;
266269
HighsInt start = conflictRanges_[i].first;
267270
HighsInt end = conflictRanges_[i].second;
271+
assert(start >= 0 && end >= 0);
268272
syncpool.addConflictFromOtherPool(&conflictEntries_[start], end - start);
269273
ageDistribution_[ages_[i]] -= 1;
270274
ages_[i] = -1;
@@ -276,4 +280,5 @@ void HighsConflictPool::syncConflictPool(HighsConflictPool& syncpool) {
276280
conflictEntries_.clear();
277281
modification_.clear();
278282
ages_.clear();
283+
usedInDive_.clear();
279284
}

highs/mip/HighsMipSolver.cpp

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,6 @@ void HighsMipSolver::run() {
504504
auto installNodes = [&](std::vector<HighsInt>& search_indices,
505505
bool& limit_reached) -> void {
506506
for (HighsInt index : search_indices) {
507-
// TODO MT: Remove this dummy if statement
508-
if (index != 0) return;
509507
if (numQueueLeaves - lastLbLeave >= 10) {
510508
mipdata_->workers[index].search_ptr_->installNode(
511509
mipdata_->nodequeue.popBestBoundNode());
@@ -542,8 +540,6 @@ void HighsMipSolver::run() {
542540
analysis_.mipTimerStart(kMipClockEvaluateNode1);
543541
setParallelLock(true);
544542
for (HighsInt i = 0; i != search_indices.size(); i++) {
545-
// TODO MT: Remove this dummy if statement
546-
if (i != 0) continue;
547543
if (mipdata_->parallelLockActive()) {
548544
tg.spawn([&, i]() {
549545
search_results[i] =
@@ -558,8 +554,6 @@ void HighsMipSolver::run() {
558554
setParallelLock(false);
559555
analysis_.mipTimerStop(kMipClockEvaluateNode1);
560556
for (HighsInt i = 0; i != search_indices.size(); i++) {
561-
// TODO MT: Remove this dummy if statement
562-
if (i != 0) continue;
563557
if (search_results[i] == HighsSearch::NodeResult::kSubOptimal) {
564558
analysis_.mipTimerStart(kMipClockCurrentNodeToQueue);
565559
mipdata_->workers[search_indices[i]].search_ptr_->currentNodeToQueue(
@@ -653,17 +647,14 @@ void HighsMipSolver::run() {
653647
// If limit_reached then return something appropriate
654648
// In multi-thread case now check limits again after everything has been
655649
// flushed
656-
std::deque<bool> infeasible;
657-
std::deque<bool> flush;
650+
std::deque<bool> infeasible(search_indices.size(), false);
651+
std::deque<bool> flush(search_indices.size(), false);
658652
std::vector<bool> prune(search_indices.size(), false);
659653
setParallelLock(true);
660654
for (HighsInt i = 0; i < search_indices.size(); i++) {
661-
// TODO MT: Remove this redundant if
662-
if (search_indices[i] != 0 || !mipdata_->workers[search_indices[i]]
663-
.search_ptr_->currentNodePruned())
655+
if (!mipdata_->workers[search_indices[i]]
656+
.search_ptr_->currentNodePruned())
664657
continue;
665-
infeasible.emplace_back(false);
666-
flush.emplace_back(false);
667658
if (mipdata_->parallelLockActive()) {
668659
tg.spawn([&, i]() {
669660
doHandlePrunedNodes(search_indices[i], mipdata_->parallelLockActive(),
@@ -719,11 +710,8 @@ void HighsMipSolver::run() {
719710

720711
// Handle case where all nodes have been pruned (and lb hasn't been updated
721712
// due to parallelism)
722-
// TODO MT: Change the if statement
723-
// if (mipdata_->hasMultipleWorkers() && num_search_indices == 0) {
724713
syncSolutions();
725-
if (mipdata_->hasMultipleWorkers() &&
726-
(num_search_indices == 0 || search_indices[0] != 0)) {
714+
if (mipdata_->hasMultipleWorkers() && num_search_indices == 0) {
727715
double prev_lower_bound = mipdata_->lower_bound;
728716
mipdata_->lower_bound = std::min(mipdata_->upper_bound,
729717
mipdata_->nodequeue.getBestLowerBound());
@@ -747,8 +735,6 @@ void HighsMipSolver::run() {
747735
analysis_.mipTimerStart(kMipClockNodeSearchSeparation);
748736
setParallelLock(true);
749737
for (HighsInt i : search_indices) {
750-
// TODO MT: Get rid of this line
751-
if (i != 0) continue;
752738
if (mipdata_->parallelLockActive()) {
753739
tg.spawn([&, i]() {
754740
mipdata_->workers[i].sepa_ptr_->separate(
@@ -764,8 +750,6 @@ void HighsMipSolver::run() {
764750
setParallelLock(false);
765751

766752
for (HighsInt i : search_indices) {
767-
// TODO MT: Get rid of this line
768-
if (i != 0) continue;
769753
if (mipdata_->workers[i].globaldom_.infeasible()) {
770754
mipdata_->workers[i].search_ptr_->cutoffNode();
771755
analysis_.mipTimerStart(kMipClockOpenNodesToQueue1);
@@ -1155,9 +1139,6 @@ void HighsMipSolver::run() {
11551139
// printf("popping node from nodequeue (length = %" HIGHSINT_FORMAT ")\n",
11561140
// (HighsInt)nodequeue.size());
11571141
std::vector<HighsInt> search_indices = getSearchIndicesWithNoNodes();
1158-
// TODO MT: Remove this line
1159-
if (search_indices[0] != 0) break;
1160-
// if (search_indices.size() >= mip_search_concurrency) break;
11611142

11621143
installNodes(search_indices, limit_reached);
11631144
if (limit_reached) break;
@@ -1172,12 +1153,12 @@ void HighsMipSolver::run() {
11721153
std::pair<bool, bool> limit_or_infeas = handlePrunedNodes(search_indices);
11731154
if (limit_or_infeas.first) limit_reached = true;
11741155
if (limit_or_infeas.first || limit_or_infeas.second) break;
1175-
// TODO MT: Change this line
1176-
if (search_indices.empty() || search_indices[0] != 0) continue;
1156+
if (search_indices.empty()) continue;
11771157

11781158
bool infeasible = separateAndStoreBasis(search_indices);
11791159
if (infeasible) break;
11801160
syncSolutions();
1161+
break;
11811162
} // while(!mipdata_->nodequeue.empty())
11821163
analysis_.mipTimerStop(kMipClockNodeSearch);
11831164
if (analysis_.analyse_mip_time) {

highs/mip/HighsSearch.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,8 @@ HighsSearch::NodeResult HighsSearch::evaluateNode() {
973973
if (!inheuristic && !localdom.infeasible()) {
974974
if (getSymmetries().numPerms > 0 && !currnode.stabilizerOrbits &&
975975
(parent == nullptr || !parent->stabilizerOrbits ||
976-
!parent->stabilizerOrbits->orbitCols.empty())) {
976+
!parent->stabilizerOrbits->orbitCols.empty()) &&
977+
!mipsolver.mipdata_->parallelLockActive()) {
977978
currnode.stabilizerOrbits =
978979
getSymmetries().computeStabilizerOrbits(localdom);
979980
}
@@ -1996,9 +1997,7 @@ const std::vector<HighsInt>& HighsSearch::getIntegralCols() const {
19961997
return mipsolver.mipdata_->integral_cols;
19971998
}
19981999

1999-
HighsDomain& HighsSearch::getDomain() const {
2000-
return mipworker.globaldom_;
2001-
}
2000+
HighsDomain& HighsSearch::getDomain() const { return mipworker.globaldom_; }
20022001

20032002
HighsConflictPool& HighsSearch::getConflictPool() const {
20042003
return mipworker.conflictpool_;

0 commit comments

Comments
 (0)