Skip to content

Commit 1083388

Browse files
committed
Merge branch 'enumerateSolutions6' of https://github.com/fwesselm/HiGHS into enumerateSolutions4
2 parents de48568 + d4060ec commit 1083388

File tree

1 file changed

+59
-66
lines changed

1 file changed

+59
-66
lines changed

highs/presolve/HPresolve.cpp

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4929,8 +4929,7 @@ HPresolve::Result HPresolve::enumerateSolutions(
49294929
std::vector<double> worstCaseUpperBound(model->num_col_, -kHighsInf);
49304930

49314931
// lambda for branching (just performs initial lower branch)
4932-
auto doBranch = [&](HighsDomain& domain, const std::vector<HighsInt>& vars,
4933-
std::vector<branch>& branches, HighsInt& numBranches) {
4932+
auto doBranch = [&](HighsInt& numBranches) {
49344933
// find variable for branching
49354934
HighsInt branchvar = -1;
49364935
for (HighsInt j : vars) {
@@ -4948,8 +4947,7 @@ HPresolve::Result HPresolve::enumerateSolutions(
49484947
};
49494948

49504949
// lambda for backtracking
4951-
auto doBacktrack = [&](HighsDomain& domain, std::vector<branch>& branches,
4952-
HighsInt& numBranches) {
4950+
auto doBacktrack = [&](HighsInt& numBranches) {
49534951
while (numBranches >= 0) {
49544952
// get column index
49554953
const auto& domchg =
@@ -4974,17 +4972,15 @@ HPresolve::Result HPresolve::enumerateSolutions(
49744972
};
49754973

49764974
// lambda for checking if a solution was found
4977-
auto solutionFound = [&](const HighsDomain& domain,
4978-
std::vector<HighsInt>& vars) {
4975+
auto solutionFound = [&]() {
49794976
for (HighsInt j : vars)
49804977
if (!domain.isFixed(j)) return false;
49814978
return true;
49824979
};
49834980

49844981
// lambda for checking whether the values of two binary variables are
49854982
// identical in all feasible solutions
4986-
auto identicalVars = [&](const std::vector<std::vector<HighsInt>>& solutions,
4987-
size_t index1, size_t index2) {
4983+
auto identicalVars = [&](size_t index1, size_t index2) {
49884984
for (size_t sol = 0; sol < solutions[index1].size(); sol++) {
49894985
if (solutions[index1][sol] != solutions[index2][sol]) return false;
49904986
}
@@ -4993,15 +4989,12 @@ HPresolve::Result HPresolve::enumerateSolutions(
49934989

49944990
// lambda for checking whether the values of two binary variables are
49954991
// complementary in all feasible solutions
4996-
auto complementaryVars =
4997-
[&](const std::vector<std::vector<HighsInt>>& solutions, size_t index1,
4998-
size_t index2) {
4999-
for (size_t sol = 0; sol < solutions[index1].size(); sol++) {
5000-
if (solutions[index1][sol] != 1 - solutions[index2][sol])
5001-
return false;
5002-
}
5003-
return true;
5004-
};
4992+
auto complementaryVars = [&](size_t index1, size_t index2) {
4993+
for (size_t sol = 0; sol < solutions[index1].size(); sol++) {
4994+
if (solutions[index1][sol] != 1 - solutions[index2][sol]) return false;
4995+
}
4996+
return true;
4997+
};
50054998

50064999
auto handleInfeasibility = [&](bool infeasible) {
50075000
if (infeasible) {
@@ -5011,7 +5004,49 @@ HPresolve::Result HPresolve::enumerateSolutions(
50115004
return Result::kOk;
50125005
};
50135006

5014-
// loop over candiate rows
5007+
auto handleSolution = [&](size_t& numWorstCaseBounds) {
5008+
// propagate
5009+
domain.propagate();
5010+
if (domain.infeasible()) return;
5011+
// handling of worst-case bounds
5012+
if (solutions[0].empty()) {
5013+
// initialize
5014+
for (HighsInt col : domain.getChangedCols()) {
5015+
worstCaseBounds[numWorstCaseBounds++] = col;
5016+
worstCaseLowerBound[col] =
5017+
std::min(worstCaseLowerBound[col], domain.col_lower_[col]);
5018+
worstCaseUpperBound[col] =
5019+
std::max(worstCaseUpperBound[col], domain.col_upper_[col]);
5020+
}
5021+
} else {
5022+
size_t i = 0;
5023+
while (i < numWorstCaseBounds) {
5024+
HighsInt col = worstCaseBounds[i];
5025+
if (!domain.isChangedCol(col)) {
5026+
// no bound changes for this variable -> reset worst-case
5027+
// bounds and remove variable
5028+
worstCaseLowerBound[col] = kHighsInf;
5029+
worstCaseUpperBound[col] = -kHighsInf;
5030+
worstCaseBounds[i] = worstCaseBounds[numWorstCaseBounds - 1];
5031+
worstCaseBounds[numWorstCaseBounds - 1] = 0;
5032+
numWorstCaseBounds--;
5033+
} else {
5034+
// update worst-case bounds
5035+
worstCaseLowerBound[col] =
5036+
std::min(worstCaseLowerBound[col], domain.col_lower_[col]);
5037+
worstCaseUpperBound[col] =
5038+
std::max(worstCaseUpperBound[col], domain.col_upper_[col]);
5039+
i++;
5040+
}
5041+
}
5042+
}
5043+
// store solution
5044+
for (size_t i = 0; i < vars.size(); i++)
5045+
solutions[i].push_back(domain.col_lower_[vars[i]] == 0.0 ? HighsInt{0}
5046+
: HighsInt{1});
5047+
};
5048+
5049+
// loop over candidate rows
50155050
HighsInt numRowsChecked = 0;
50165051
for (const auto& r : rows) {
50175052
// get row index
@@ -5051,55 +5086,13 @@ HPresolve::Result HPresolve::enumerateSolutions(
50515086
while (true) {
50525087
bool backtrack = domain.infeasible();
50535088
if (!backtrack) {
5054-
backtrack = solutionFound(domain, vars);
5055-
if (backtrack) {
5056-
// propagate
5057-
domain.propagate();
5058-
if (!domain.infeasible()) {
5059-
// handling of worst-case bounds
5060-
if (solutions[0].empty()) {
5061-
for (HighsInt col : domain.getChangedCols()) {
5062-
// initialize
5063-
worstCaseBounds[numWorstCaseBounds++] = col;
5064-
worstCaseLowerBound[col] =
5065-
std::min(worstCaseLowerBound[col], domain.col_lower_[col]);
5066-
worstCaseUpperBound[col] =
5067-
std::max(worstCaseUpperBound[col], domain.col_upper_[col]);
5068-
}
5069-
} else {
5070-
size_t i = 0;
5071-
while (i < numWorstCaseBounds) {
5072-
HighsInt col = worstCaseBounds[i];
5073-
if (!domain.isChangedCol(col)) {
5074-
// no bound changes for this variable -> reset worst-case
5075-
// bounds and remove variable
5076-
worstCaseLowerBound[col] = kHighsInf;
5077-
worstCaseUpperBound[col] = -kHighsInf;
5078-
worstCaseBounds[i] = worstCaseBounds[numWorstCaseBounds - 1];
5079-
worstCaseBounds[numWorstCaseBounds - 1] = 0;
5080-
numWorstCaseBounds--;
5081-
} else {
5082-
// update worst-case bounds
5083-
worstCaseLowerBound[col] = std::min(worstCaseLowerBound[col],
5084-
domain.col_lower_[col]);
5085-
worstCaseUpperBound[col] = std::max(worstCaseUpperBound[col],
5086-
domain.col_upper_[col]);
5087-
i++;
5088-
}
5089-
}
5090-
}
5091-
// store solution
5092-
for (size_t i = 0; i < vars.size(); i++)
5093-
solutions[i].push_back(domain.col_lower_[vars[i]] == 0.0
5094-
? HighsInt{0}
5095-
: HighsInt{1});
5096-
}
5097-
}
5089+
backtrack = solutionFound();
5090+
if (backtrack) handleSolution(numWorstCaseBounds);
50985091
}
50995092
// branch or backtrack
51005093
if (!backtrack)
5101-
doBranch(domain, vars, branches, numBranches);
5102-
else if (!doBacktrack(domain, branches, numBranches))
5094+
doBranch(numBranches);
5095+
else if (!doBacktrack(numBranches))
51035096
break;
51045097
}
51055098

@@ -5146,13 +5139,13 @@ HPresolve::Result HPresolve::enumerateSolutions(
51465139
if (domain.isFixed(col2)) continue;
51475140
// check if two binary variables take identical or complementary
51485141
// values in all feasible solutions
5149-
if (identicalVars(solutions, i, ii)) {
5142+
if (identicalVars(i, ii)) {
51505143
// add clique x_1 + (1 - x_2) = 1 to clique table
51515144
std::array<HighsCliqueTable::CliqueVar, 2> clique;
51525145
clique[0] = HighsCliqueTable::CliqueVar(col, 0);
51535146
clique[1] = HighsCliqueTable::CliqueVar(col2, 1);
51545147
cliquetable.addClique(*mipsolver, clique.data(), 2, true);
5155-
} else if (complementaryVars(solutions, i, ii)) {
5148+
} else if (complementaryVars(i, ii)) {
51565149
// add clique x_1 + x_2 = 1 to clique table
51575150
std::array<HighsCliqueTable::CliqueVar, 2> clique;
51585151
clique[0] = HighsCliqueTable::CliqueVar(col, 0);

0 commit comments

Comments
 (0)