Skip to content

Commit 0408d10

Browse files
committed
use local conflict pool and worker sols in heur
1 parent c59322a commit 0408d10

File tree

4 files changed

+73
-51
lines changed

4 files changed

+73
-51
lines changed

highs/mip/HighsMipSolver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ void HighsMipSolver::run() {
137137
// Initialize master worker.
138138
// Now the worker lives in mipdata.
139139
// The master worker is used in evaluateRootNode.
140+
if (mipdata_->domain.infeasible()) {
141+
cleanupSolve();
142+
return;
143+
}
140144
mipdata_->workers.emplace_back(*this, &mipdata_->lp, mipdata_->domain,
141145
&mipdata_->cutpool, &mipdata_->conflictPool);
142146

highs/mip/HighsMipWorker.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,39 @@ std::pair<bool, double> HighsMipWorker::transformNewIntegerFeasibleSolution(
148148
mipsolver_.model_->offset_);
149149

150150
return std::make_pair(feasible, transformed_solobj);
151+
}
152+
153+
bool HighsMipWorker::trySolution(const std::vector<double>& solution,
154+
const int solution_source) {
155+
if (static_cast<int>(solution.size()) != mipsolver_.model_->num_col_)
156+
return false;
157+
158+
HighsCDouble obj = 0;
159+
160+
for (HighsInt i = 0; i != mipsolver_.model_->num_col_; ++i) {
161+
if (solution[i] < mipsolver_.model_->col_lower_[i] - mipdata_.feastol)
162+
return false;
163+
if (solution[i] > mipsolver_.model_->col_upper_[i] + mipdata_.feastol)
164+
return false;
165+
if (mipsolver_.variableType(i) == HighsVarType::kInteger &&
166+
fractionality(solution[i]) > mipdata_.feastol)
167+
return false;
168+
169+
obj += mipsolver_.colCost(i) * solution[i];
170+
}
171+
172+
for (HighsInt i = 0; i != mipsolver_.model_->num_row_; ++i) {
173+
double rowactivity = 0.0;
174+
175+
HighsInt start = mipdata_.ARstart_[i];
176+
HighsInt end = mipdata_.ARstart_[i + 1];
177+
178+
for (HighsInt j = start; j != end; ++j)
179+
rowactivity += solution[mipdata_.ARindex_[j]] * mipdata_.ARvalue_[j];
180+
181+
if (rowactivity > mipsolver_.rowUpper(i) + mipdata_.feastol) return false;
182+
if (rowactivity < mipsolver_.rowLower(i) - mipdata_.feastol) return false;
183+
}
184+
185+
return addIncumbent(solution, static_cast<double>(obj), solution_source);
151186
}

highs/mip/HighsMipWorker.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,8 @@ class HighsMipWorker {
4545
HighsRandom randgen;
4646

4747
// HighsMipWorker(const HighsMipSolver& mipsolver__);
48-
HighsMipWorker(const HighsMipSolver& mipsolver__,
49-
HighsLpRelaxation* lprelax_,
50-
HighsDomain& domain,
51-
HighsCutPool* cutpool,
48+
HighsMipWorker(const HighsMipSolver& mipsolver__, HighsLpRelaxation* lprelax_,
49+
HighsDomain& domain, HighsCutPool* cutpool,
5250
HighsConflictPool* conflictpool);
5351

5452
~HighsMipWorker() {
@@ -67,11 +65,15 @@ class HighsMipWorker {
6765
// const int solution_source,
6866
// const bool print_display_line = true);
6967

70-
bool addIncumbent(const std::vector<double>& sol, double solobj, int solution_source);
68+
bool addIncumbent(const std::vector<double>& sol, double solobj,
69+
int solution_source);
7170

7271
std::pair<bool, double> transformNewIntegerFeasibleSolution(
7372
const std::vector<double>& sol);
7473

74+
bool trySolution(const std::vector<double>& solution,
75+
const int solution_source);
76+
7577
// todo:
7678
// timer_
7779
// sync too

highs/mip/HighsPrimalHeuristics.cpp

Lines changed: 27 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,7 @@ bool HighsPrimalHeuristics::solveSubMip(
176176
HighsInt oldNumImprovingSols = mipsolver.mipdata_->numImprovingSols;
177177
if (submipsolver.modelstatus_ != HighsModelStatus::kInfeasible &&
178178
!submipsolver.solution_.empty()) {
179-
mipsolver.mipdata_->trySolution(submipsolver.solution_,
180-
kSolutionSourceSubMip);
179+
worker.trySolution(submipsolver.solution_, kSolutionSourceSubMip);
181180
}
182181

183182
if (mipsolver.mipdata_->numImprovingSols != oldNumImprovingSols) {
@@ -283,8 +282,7 @@ void HighsPrimalHeuristics::rootReducedCost(HighsMipWorker& worker) {
283282
while (true) {
284283
localdom.propagate();
285284
if (localdom.infeasible()) {
286-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
287-
worker.globaldom_);
285+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
288286

289287
double prev_lower_bound = mipsolver.mipdata_->lower_bound;
290288

@@ -420,8 +418,7 @@ void HighsPrimalHeuristics::RENS(HighsMipWorker& worker,
420418
heur.branchUpwards(i, downval, downval - 0.5);
421419
localdom.propagate();
422420
if (localdom.infeasible()) {
423-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
424-
worker.globaldom_);
421+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
425422
break;
426423
}
427424
}
@@ -430,8 +427,7 @@ void HighsPrimalHeuristics::RENS(HighsMipWorker& worker,
430427
heur.branchDownwards(i, upval, upval + 0.5);
431428
localdom.propagate();
432429
if (localdom.infeasible()) {
433-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
434-
worker.globaldom_);
430+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
435431
break;
436432
}
437433
}
@@ -492,8 +488,7 @@ void HighsPrimalHeuristics::RENS(HighsMipWorker& worker,
492488
heur.branchUpwards(fracint.first, fixval, fracint.second);
493489
localdom.propagate();
494490
if (localdom.infeasible()) {
495-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
496-
worker.globaldom_);
491+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
497492
break;
498493
}
499494

@@ -505,8 +500,7 @@ void HighsPrimalHeuristics::RENS(HighsMipWorker& worker,
505500
heur.branchDownwards(fracint.first, fixval, fracint.second);
506501
localdom.propagate();
507502
if (localdom.infeasible()) {
508-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
509-
worker.globaldom_);
503+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
510504
break;
511505
}
512506

@@ -724,7 +718,7 @@ void HighsPrimalHeuristics::RINS(HighsMipWorker& worker,
724718
heur.branchUpwards(i, fixval, fixval - 0.5);
725719
localdom.propagate();
726720
if (localdom.infeasible()) {
727-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
721+
localdom.conflictAnalysis(*worker.conflictpool_,
728722
worker.globaldom_);
729723
break;
730724
}
@@ -736,7 +730,7 @@ void HighsPrimalHeuristics::RINS(HighsMipWorker& worker,
736730
heur.branchDownwards(i, fixval, fixval + 0.5);
737731
localdom.propagate();
738732
if (localdom.infeasible()) {
739-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
733+
localdom.conflictAnalysis(*worker.conflictpool_,
740734
worker.globaldom_);
741735
break;
742736
}
@@ -793,8 +787,7 @@ void HighsPrimalHeuristics::RINS(HighsMipWorker& worker,
793787
++numBranched;
794788
heur.branchUpwards(fracint->first, fixval, fracint->second);
795789
if (localdom.infeasible()) {
796-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
797-
worker.globaldom_);
790+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
798791
break;
799792
}
800793

@@ -805,8 +798,7 @@ void HighsPrimalHeuristics::RINS(HighsMipWorker& worker,
805798
++numBranched;
806799
heur.branchDownwards(fracint->first, fixval, fracint->second);
807800
if (localdom.infeasible()) {
808-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
809-
worker.globaldom_);
801+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
810802
break;
811803
}
812804

@@ -906,14 +898,12 @@ bool HighsPrimalHeuristics::tryRoundedPoint(HighsMipWorker& worker,
906898

907899
localdom.fixCol(col, intval, HighsDomain::Reason::branching());
908900
if (localdom.infeasible()) {
909-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
910-
worker.globaldom_);
901+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
911902
return false;
912903
}
913904
localdom.propagate();
914905
if (localdom.infeasible()) {
915-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
916-
worker.globaldom_);
906+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
917907
return false;
918908
}
919909
}
@@ -953,17 +943,16 @@ bool HighsPrimalHeuristics::tryRoundedPoint(HighsMipWorker& worker,
953943
if (!integerFeasible) {
954944
// there may be fractional integer variables -> try ziRound heuristic
955945
ziRound(worker, lpsol);
956-
return mipsolver.mipdata_->trySolution(lpsol, solution_source);
946+
return worker.trySolution(lpsol, solution_source);
957947
} else {
958948
// all integer variables are fixed -> add incumbent
959-
mipsolver.mipdata_->addIncumbent(lpsol, lprelax.getObjective(),
960-
solution_source);
949+
worker.addIncumbent(lpsol, lprelax.getObjective(), solution_source);
961950
return true;
962951
}
963952
}
964953
}
965954

966-
return mipsolver.mipdata_->trySolution(localdom.col_lower_, solution_source);
955+
return worker.trySolution(localdom.col_lower_, solution_source);
967956
}
968957

969958
bool HighsPrimalHeuristics::linesearchRounding(
@@ -1042,14 +1031,12 @@ void HighsPrimalHeuristics::randomizedRounding(
10421031

10431032
localdom.fixCol(i, intval, HighsDomain::Reason::branching());
10441033
if (localdom.infeasible()) {
1045-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
1046-
worker.globaldom_);
1034+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
10471035
return;
10481036
}
10491037
localdom.propagate();
10501038
if (localdom.infeasible()) {
1051-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
1052-
worker.globaldom_);
1039+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
10531040
return;
10541041
}
10551042
}
@@ -1087,12 +1074,11 @@ void HighsPrimalHeuristics::randomizedRounding(
10871074
}
10881075

10891076
} else if (lprelax.unscaledPrimalFeasible(st))
1090-
mipsolver.mipdata_->addIncumbent(
1091-
lprelax.getLpSolver().getSolution().col_value, lprelax.getObjective(),
1092-
kSolutionSourceRandomizedRounding);
1077+
worker.addIncumbent(lprelax.getLpSolver().getSolution().col_value,
1078+
lprelax.getObjective(),
1079+
kSolutionSourceRandomizedRounding);
10931080
} else {
1094-
mipsolver.mipdata_->trySolution(localdom.col_lower_,
1095-
kSolutionSourceRandomizedRounding);
1081+
worker.trySolution(localdom.col_lower_, kSolutionSourceRandomizedRounding);
10961082
}
10971083
}
10981084

@@ -1345,8 +1331,7 @@ void HighsPrimalHeuristics::shifting(HighsMipWorker& worker,
13451331
if (current_fractional_integers.size() > 0)
13461332
ziRound(worker, current_relax_solution);
13471333
else
1348-
mipsolver.mipdata_->trySolution(current_relax_solution,
1349-
kSolutionSourceShifting);
1334+
worker.trySolution(current_relax_solution, kSolutionSourceShifting);
13501335
}
13511336
}
13521337

@@ -1460,8 +1445,7 @@ void HighsPrimalHeuristics::ziRound(HighsMipWorker& worker,
14601445
improvement_in_feasibility = previous_zi_total - zi_total;
14611446
}
14621447
// re-check for feasibility and add incumbent
1463-
mipsolver.mipdata_->trySolution(current_relax_solution,
1464-
kSolutionSourceZiRound);
1448+
worker.trySolution(current_relax_solution, kSolutionSourceZiRound);
14651449
}
14661450

14671451
void HighsPrimalHeuristics::feasibilityPump(HighsMipWorker& worker) {
@@ -1504,14 +1488,12 @@ void HighsPrimalHeuristics::feasibilityPump(HighsMipWorker& worker) {
15041488
if (!localdom.infeasible()) {
15051489
localdom.fixCol(i, intval, HighsDomain::Reason::branching());
15061490
if (localdom.infeasible()) {
1507-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
1508-
worker.globaldom_);
1491+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
15091492
continue;
15101493
}
15111494
localdom.propagate();
15121495
if (localdom.infeasible()) {
1513-
localdom.conflictAnalysis(mipsolver.mipdata_->conflictPool,
1514-
worker.globaldom_);
1496+
localdom.conflictAnalysis(*worker.conflictpool_, worker.globaldom_);
15151497
continue;
15161498
}
15171499
}
@@ -1569,9 +1551,8 @@ void HighsPrimalHeuristics::feasibilityPump(HighsMipWorker& worker) {
15691551

15701552
if (lprelax.getFractionalIntegers().empty() &&
15711553
lprelax.unscaledPrimalFeasible(status))
1572-
mipsolver.mipdata_->addIncumbent(
1573-
lprelax.getLpSolver().getSolution().col_value, lprelax.getObjective(),
1574-
kSolutionSourceFeasibilityPump);
1554+
worker.addIncumbent(lprelax.getLpSolver().getSolution().col_value,
1555+
lprelax.getObjective(), kSolutionSourceFeasibilityPump);
15751556
}
15761557

15771558
void HighsPrimalHeuristics::centralRounding(HighsMipWorker& worker) {

0 commit comments

Comments
 (0)