Skip to content

Commit eb54a0d

Browse files
authored
Merge pull request #2410 from fwesselm/fix-2409
Fix 2409
2 parents 2ee7e90 + 6f5bf9a commit eb54a0d

File tree

5 files changed

+72
-38
lines changed

5 files changed

+72
-38
lines changed

check/TestPresolve.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,3 +724,14 @@ TEST_CASE("presolve-issue-2402", "[highs_test_presolve]") {
724724
REQUIRE(highs.presolve() == HighsStatus::kOk);
725725
REQUIRE(highs.getModelPresolveStatus() == HighsPresolveStatus::kInfeasible);
726726
}
727+
728+
TEST_CASE("presolve-issue-2409", "[highs_test_presolve]") {
729+
std::string model_file =
730+
std::string(HIGHS_DIR) + "/check/instances/issue-2409.mps";
731+
Highs highs;
732+
highs.setOptionValue("output_flag", dev_run);
733+
highs.readModel(model_file);
734+
REQUIRE(highs.presolve() == HighsStatus::kOk);
735+
REQUIRE(highs.getModelPresolveStatus() ==
736+
HighsPresolveStatus::kReducedToEmpty);
737+
}

check/instances/issue-2409.mps

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
NAME
2+
ROWS
3+
N Obj
4+
G r0
5+
G r1
6+
COLUMNS
7+
c0 Obj -1
8+
c0 r0 -1
9+
c0 r1 1
10+
MARK0000 'MARKER' 'INTORG'
11+
c1 Obj 1
12+
c1 r0 1
13+
c1 r1 1
14+
MARK0001 'MARKER' 'INTEND'
15+
RHS
16+
RHS_V r0 0.1
17+
RHS_V r1 0.1
18+
BOUNDS
19+
FR BOUND c0
20+
FR BOUND c1
21+
ENDATA

highs/presolve/HPresolve.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4190,14 +4190,21 @@ HPresolve::Result HPresolve::detectDominatedCol(
41904190
HPRESOLVE_CHECKED_CALL(removeRowSingletons(postsolve_stack));
41914191
return checkLimits(postsolve_stack);
41924192
} else if (analysis_.allow_rule_[kPresolveRuleForcingCol]) {
4193-
// get bound on dual (column) activity
4194-
HighsCDouble sum = 0;
4195-
if (direction > 0)
4196-
sum = impliedDualRowBounds.getSumUpperOrig(col);
4197-
else
4198-
sum = impliedDualRowBounds.getSumLowerOrig(col);
4199-
if (sum == 0.0) {
4200-
// remove column and rows
4193+
// get bound on column dual using original bounds on row duals
4194+
double boundOnColDual = direction > 0
4195+
? -impliedDualRowBounds.getSumUpperOrig(
4196+
col, -model->col_cost_[col])
4197+
: -impliedDualRowBounds.getSumLowerOrig(
4198+
col, -model->col_cost_[col]);
4199+
if (boundOnColDual == 0.0) {
4200+
// 1. column's lower bound is infinite (i.e. column dual has upper bound
4201+
// of zero) and column dual's lower bound is zero as well
4202+
// (direction = 1) or
4203+
// 2. column's upper bound is infinite (i.e. column dual has lower bound
4204+
// of zero) and column dual's upper bound is zero as well
4205+
// (direction = -1).
4206+
// thus, the column dual is zero, and we can remove the column and
4207+
// all its rows
42014208
if (logging_on) analysis_.startPresolveRuleLog(kPresolveRuleForcingCol);
42024209
postsolve_stack.forcingColumn(
42034210
col, getColumnVector(col), model->col_cost_[col], otherBound,

highs/presolve/HPresolve.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ class HPresolve {
390390
Result strengthenInequalities(HighsPostsolveStack& postsolve_stack,
391391
HighsInt& num_strenghtened);
392392

393-
HPresolve::Result detectImpliedIntegers();
393+
Result detectImpliedIntegers();
394394

395395
Result detectParallelRowsAndCols(HighsPostsolveStack& postsolve_stack);
396396

highs/util/HighsLinearSumBounds.h

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -102,41 +102,36 @@ class HighsLinearSumBounds {
102102
double getResidualSumUpperOrig(HighsInt sum, HighsInt var,
103103
double coefficient) const;
104104

105-
double getSumLowerOrig(HighsInt sum) const {
106-
return numInfSumLowerOrig[sum] == 0 ? double(sumLowerOrig[sum])
107-
: -kHighsInf;
105+
template <typename T = double>
106+
double getSumLowerOrig(HighsInt sum, T offset = T()) const {
107+
return numInfSumLowerOrig[sum] == 0
108+
? static_cast<double>(sumLowerOrig[sum] +
109+
static_cast<HighsCDouble>(offset))
110+
: -kHighsInf;
108111
}
109112

110-
double getSumUpperOrig(HighsInt sum) const {
111-
return numInfSumUpperOrig[sum] == 0 ? double(sumUpperOrig[sum]) : kHighsInf;
113+
template <typename T = double>
114+
double getSumUpperOrig(HighsInt sum, T offset = T()) const {
115+
return numInfSumUpperOrig[sum] == 0
116+
? static_cast<double>(sumUpperOrig[sum] +
117+
static_cast<HighsCDouble>(offset))
118+
: kHighsInf;
112119
}
113120

114-
double getSumLower(HighsInt sum) const {
115-
return numInfSumLower[sum] == 0 ? double(sumLower[sum]) : -kHighsInf;
121+
template <typename T = double>
122+
double getSumLower(HighsInt sum, T offset = T()) const {
123+
return numInfSumLower[sum] == 0
124+
? static_cast<double>(sumLower[sum] +
125+
static_cast<HighsCDouble>(offset))
126+
: -kHighsInf;
116127
}
117128

118-
double getSumUpper(HighsInt sum) const {
119-
return numInfSumUpper[sum] == 0 ? double(sumUpper[sum]) : kHighsInf;
120-
}
121-
122-
double getSumLower(HighsInt sum, double offset) const {
123-
return numInfSumLower[sum] == 0 ? double(sumLower[sum] + offset)
124-
: -kHighsInf;
125-
}
126-
127-
double getSumUpper(HighsInt sum, double offset) const {
128-
return numInfSumUpper[sum] == 0 ? double(sumUpper[sum] + offset)
129-
: kHighsInf;
130-
}
131-
132-
double getSumLower(HighsInt sum, HighsCDouble offset) const {
133-
return numInfSumLower[sum] == 0 ? double(sumLower[sum] + offset)
134-
: -kHighsInf;
135-
}
136-
137-
double getSumUpper(HighsInt sum, HighsCDouble offset) const {
138-
return numInfSumUpper[sum] == 0 ? double(sumUpper[sum] + offset)
139-
: kHighsInf;
129+
template <typename T = double>
130+
double getSumUpper(HighsInt sum, T offset = T()) const {
131+
return numInfSumUpper[sum] == 0
132+
? static_cast<double>(sumUpper[sum] +
133+
static_cast<HighsCDouble>(offset))
134+
: kHighsInf;
140135
}
141136

142137
HighsInt getNumInfSumLower(HighsInt sum) const { return numInfSumLower[sum]; }

0 commit comments

Comments
 (0)