Skip to content

Commit 3a9b23b

Browse files
authored
Merge pull request ERGO-Code#2917 from fwesselm/fix-2915
Speed up equation handling in `HPresolve::dualFixing`
2 parents 0e119e9 + 3064077 commit 3a9b23b

File tree

1 file changed

+41
-30
lines changed

1 file changed

+41
-30
lines changed

highs/presolve/HPresolve.cpp

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4665,6 +4665,13 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
46654665
// return if variable is already fixed
46664666
if (model->col_lower_[col] == model->col_upper_[col]) return Result::kOk;
46674667

4668+
// struct for single equation handling
4669+
struct equationNonZero {
4670+
HighsInt col;
4671+
double val;
4672+
HighsInt mark;
4673+
};
4674+
46684675
// lambda for variable substitution
46694676
auto substituteCol = [&](HighsInt col, HighsInt row, HighsInt direction,
46704677
double colBound, double otherColBound) {
@@ -4760,41 +4767,45 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
47604767
};
47614768

47624769
// lambda for fixing variables
4763-
auto fixCols = [&](const std::vector<std::pair<HighsInt, double>>& vars,
4770+
auto fixCols = [&](const std::vector<equationNonZero>& equationRowVector,
47644771
HighsInt direction) {
4765-
for (const auto& elm : vars) {
4766-
if (direction * elm.second > 0)
4767-
HPRESOLVE_CHECKED_CALL(fixColToUpper(postsolve_stack, elm.first));
4772+
for (const auto& rowNz : equationRowVector) {
4773+
if (direction * rowNz.mark >= 0) continue;
4774+
if (direction * rowNz.val > 0)
4775+
HPRESOLVE_CHECKED_CALL(fixColToUpper(postsolve_stack, rowNz.col));
47684776
else
4769-
HPRESOLVE_CHECKED_CALL(fixColToLower(postsolve_stack, elm.first));
4777+
HPRESOLVE_CHECKED_CALL(fixColToLower(postsolve_stack, rowNz.col));
47704778
}
47714779
return Result::kOk;
47724780
};
47734781

47744782
// lambda for handling single equations
47754783
auto handleSingleEquation = [&](HighsInt row) {
47764784
assert(isEquation(row));
4777-
std::vector<std::pair<HighsInt, double>> sPlus;
4778-
std::vector<std::pair<HighsInt, double>> sMinus;
4779-
sPlus.reserve(rowsize[row]);
4780-
sMinus.reserve(rowsize[row]);
4781-
std::vector<HighsInt> sMark(model->num_col_, 0);
4785+
std::vector<equationNonZero> equationRowVector;
4786+
equationRowVector.reserve(rowsize[row]);
4787+
HighsInt numSPlus = 0;
4788+
HighsInt numSMinus = 0;
47824789
for (const auto& rowNz : getRowVector(row)) {
47834790
// flip column direction if coefficient is negative
47844791
// (equivalent to negating the column's coefficients)
47854792
HighsInt colDirection = std::copysign(HighsInt{1}, rowNz.value());
4793+
HighsInt mark = 0;
47864794
if (checkColumn(rowNz.index(), colDirection, row)) {
47874795
// store in S_+
4788-
sPlus.push_back(std::make_pair(rowNz.index(), rowNz.value()));
4789-
sMark[rowNz.index()] = 1;
4796+
numSPlus++;
4797+
mark = 1;
47904798
} else if (checkColumn(rowNz.index(), -colDirection, row)) {
47914799
// store in S_-
4792-
sMinus.push_back(std::make_pair(rowNz.index(), rowNz.value()));
4793-
sMark[rowNz.index()] = -1;
4800+
numSMinus++;
4801+
mark = -1;
47944802
}
4803+
// store non-zero
4804+
equationRowVector.emplace_back(
4805+
equationNonZero{rowNz.index(), rowNz.value(), mark});
47954806
}
47964807
// return if both sets are empty
4797-
if (sPlus.empty() && sMinus.empty()) return Result::kOk;
4808+
if (numSPlus == 0 && numSMinus == 0) return Result::kOk;
47984809
// compute activities
47994810
HighsCDouble activityTPlus = 0.0;
48004811
HighsCDouble activityTMinus = 0.0;
@@ -4804,41 +4815,41 @@ HPresolve::Result HPresolve::dualFixing(HighsPostsolveStack& postsolve_stack,
48044815
bool activityTMinusFinite = true;
48054816
bool activitySCPlusFinite = true;
48064817
bool activitySCMinusFinite = true;
4807-
for (const auto& rowNz : getRowVector(row)) {
4808-
if (sMark[rowNz.index()] <= 0 ||
4809-
model->integrality_[rowNz.index()] != HighsVarType::kContinuous)
4818+
for (const auto& rowNz : equationRowVector) {
4819+
if (rowNz.mark <= 0 ||
4820+
model->integrality_[rowNz.col] != HighsVarType::kContinuous)
48104821
// T_+
4811-
computeActivity(rowNz.index(), rowNz.value(), activityTPlus,
4822+
computeActivity(rowNz.col, rowNz.val, activityTPlus,
48124823
activityTPlusFinite, HighsInt{1});
48134824
else
48144825
// S^C_+
4815-
computeActivity(rowNz.index(), rowNz.value(), activitySCPlus,
4826+
computeActivity(rowNz.col, rowNz.val, activitySCPlus,
48164827
activitySCPlusFinite, HighsInt{-1});
4817-
if (sMark[rowNz.index()] >= 0 ||
4818-
model->integrality_[rowNz.index()] != HighsVarType::kContinuous)
4828+
if (rowNz.mark >= 0 ||
4829+
model->integrality_[rowNz.col] != HighsVarType::kContinuous)
48194830
// T_-
4820-
computeActivity(rowNz.index(), rowNz.value(), activityTMinus,
4831+
computeActivity(rowNz.col, rowNz.val, activityTMinus,
48214832
activityTMinusFinite, HighsInt{-1});
48224833
else
48234834
// S^C_-
4824-
computeActivity(rowNz.index(), rowNz.value(), activitySCMinus,
4835+
computeActivity(rowNz.col, rowNz.val, activitySCMinus,
48254836
activitySCMinusFinite, HighsInt{1});
48264837
// break if activities are not finite
4827-
if ((sMinus.empty() || !activityTPlusFinite || !activitySCPlusFinite) &&
4828-
(sPlus.empty() || !activityTMinusFinite || !activitySCMinusFinite))
4838+
if ((numSMinus == 0 || !activityTPlusFinite || !activitySCPlusFinite) &&
4839+
(numSPlus == 0 || !activityTMinusFinite || !activitySCMinusFinite))
48294840
break;
48304841
}
48314842
// fix variables
4832-
if (!sMinus.empty() && activityTPlusFinite && activitySCPlusFinite &&
4843+
if (numSMinus > 0 && activityTPlusFinite && activitySCPlusFinite &&
48334844
activityTPlus + activitySCPlus <=
48344845
model->row_lower_[row] + primal_feastol)
48354846
// fix all variables in S_-
4836-
HPRESOLVE_CHECKED_CALL(fixCols(sMinus, HighsInt{1}));
4837-
else if (!sPlus.empty() && activityTMinusFinite && activitySCMinusFinite &&
4847+
HPRESOLVE_CHECKED_CALL(fixCols(equationRowVector, HighsInt{1}));
4848+
else if (numSPlus > 0 && activityTMinusFinite && activitySCMinusFinite &&
48384849
activityTMinus + activitySCMinus >=
48394850
model->row_lower_[row] - primal_feastol)
48404851
// fix all variables in S_+
4841-
HPRESOLVE_CHECKED_CALL(fixCols(sPlus, HighsInt{-1}));
4852+
HPRESOLVE_CHECKED_CALL(fixCols(equationRowVector, HighsInt{-1}));
48424853
return Result::kOk;
48434854
};
48444855

0 commit comments

Comments
 (0)