Skip to content

Commit 665302f

Browse files
committed
Cleaned up debug printing, and all unit tests on
1 parent 001b1df commit 665302f

2 files changed

Lines changed: 19 additions & 103 deletions

File tree

check/TestPresolveRules.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "Highs.h"
55
#include "catch.hpp"
66

7-
const bool dev_run = true;
7+
const bool dev_run = false;
88

99
void presolveOffOn(const std::string& message, const HighsLp& lp, Highs& h,
1010
const HighsInt require_presolved_model_num_col = 0,
@@ -15,12 +15,12 @@ TEST_CASE("test-col-stuffing", "[highs_test_presolve_rules]") {
1515
HighsLp lp;
1616

1717
Highs h;
18-
// h.setOptionValue("output_flag", dev_run);
18+
h.setOptionValue("output_flag", dev_run);
1919
h.setOptionValue("presolve_rule_test", kPresolveRuleColStuffing);
20-
const bool lp0 = false;
21-
const bool lp1 = false;
20+
const bool lp0 = true;
21+
const bool lp1 = true;
2222
const bool lp1a = true;
23-
const bool lp1b = false;
23+
const bool lp1b = true;
2424

2525
if (lp0) {
2626
lp.num_col_ = 3;

highs/presolve/HPresolve.cpp

Lines changed: 14 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -4988,8 +4988,7 @@ HPresolve::Result HPresolve::singletonColStuffing(
49884988

49894989
// count number of fixed columns
49904990
HighsInt numFixedCols = 0;
4991-
// Temporary for fix-col-stuffing
4992-
bool report_stuffing = true;
4991+
49934992
struct candidate {
49944993
HighsInt col;
49954994
double val;
@@ -5028,8 +5027,7 @@ HPresolve::Result HPresolve::singletonColStuffing(
50285027
double& maxWeight, size_t& numIntegerCandidates) {
50295028
if (model->integrality_[col] == HighsVarType::kInteger)
50305029
numIntegerCandidates++;
5031-
// Temporary for fix-col-stuffing
5032-
assert(direction * val > 0);
5030+
50335031
minWeight = std::min(minWeight, direction * val);
50345032
maxWeight = std::max(maxWeight, direction * val);
50355033
candidates.push_back(candidate{col, val, direction});
@@ -5071,54 +5069,6 @@ HPresolve::Result HPresolve::singletonColStuffing(
50715069
double sumUpperBound = model->col_upper_[j];
50725070
bool isCandidate = allowIntegerCandidates ||
50735071
model->integrality_[j] != HighsVarType::kInteger;
5074-
// Considering row as a knapsack
5075-
//
5076-
// minimize c^Tx st a^Tx <= W; l <= x <= u
5077-
//
5078-
// NB minimize
5079-
//
5080-
// If cj/aj >= 0, then dual fixing means that xj can _probably_
5081-
// be fixed
5082-
//
5083-
// If aj > 0, then xj is contributing positively to the
5084-
// knapsack, but if cj >=0 its optimal value would appear to be
5085-
// lj, and it must be if cj > 0, in which case lj = -inf implies
5086-
// dual infeasibility.
5087-
//
5088-
// However, if cj = 0 and lj = -inf, then it is not logically
5089-
// correct to fix it to its lower bound and claim dual
5090-
// infeasibility. The row is redundant since, whatever values
5091-
// are assigned to the other variables, xj can be made
5092-
// sufficiently negative so that a^Tx <= W.
5093-
//
5094-
// If lj is finite, then it is fair to fix xj = lj
5095-
//
5096-
// If aj < 0 then then xj is contributing negatively to the
5097-
// knapsack, and if cj < 0 its optimal value is uj, in which
5098-
// case uj = inf implies dual infeasibility. If cj = 0 then, as
5099-
// above, if uj is finite fix xj = uj, otherwise the row is
5100-
// redundant.
5101-
//
5102-
// If cj/aj < 0, then xj is a candidate to have its value
5103-
// assigned optimally. This is done greedily according to the
5104-
// sorted values of cj/aj, over all such candidates
5105-
//
5106-
// Perhaps the cj = 0 issue is moot, since fixing to an infinte
5107-
// bound leads to at least one of sumLowerFinite and
5108-
// sumUpperFinite being false, so set of candidates is
5109-
// abandoned.
5110-
//
5111-
// Question: The greedy algorithm is only guaranteed to assign
5112-
// values optimally if the variables are continuous. The
5113-
// criterion minWeight != maxWeight (ie not all |aj| values
5114-
// being equal) leading to abandonment of stuffing if there are
5115-
// only integer columns overcomes this. However, is it
5116-
// guaranteed that with those continuous decisions the knapsack
5117-
// is solved optimally?
5118-
//
5119-
// Question: Is there value in solving the knapsack problem by
5120-
// DP if all variables are integer, and not all |aj| values are
5121-
// equal?
51225072
if (isSingleton(j)) {
51235073
// check singleton
51245074
if (aj > 0) {
@@ -5209,12 +5159,6 @@ HPresolve::Result HPresolve::singletonColStuffing(
52095159
sortCols(candidates);
52105160

52115161
// check candidates
5212-
// Temporary for fix-col-stuffing
5213-
if (report_stuffing)
5214-
printf(
5215-
"ColStuffing: num candidates = %d; sumLower = %g; sumUpper = %g; rhs "
5216-
"= %g\n",
5217-
int(candidates.size()), double(sumLower), double(sumUpper), rhs);
52185162
for (const auto& t : candidates) {
52195163
// both bounds have to be finite
52205164
if (model->col_lower_[t.col] == -kHighsInf ||
@@ -5228,38 +5172,20 @@ HPresolve::Result HPresolve::singletonColStuffing(
52285172
// check if variable can be fixed
52295173
if (sumUpperFinite &&
52305174
delta <= direction * rhs - sumUpper + primal_feastol) {
5231-
if (report_stuffing)
5232-
printf(
5233-
"ColStuffing:0 (%2d) fix %6d to %s: cost = %11.4g; delta = "
5234-
"%11.4g | "
5235-
"Logic: delta = %11.4g <= %11.4g = direction * rhs - sumUpper + "
5236-
"primal_feastol\n",
5237-
int(t.multiplier), int(t.col),
5238-
t.multiplier < 0 ? "lower" : "upper", model->col_cost_[t.col],
5239-
double(delta), double(delta),
5240-
double(direction * rhs - sumUpper + primal_feastol));
52415175
numFixedCols++;
52425176
HPRESOLVE_CHECKED_CALL(fixCol(t.col, t.multiplier));
52435177
} else if (sumLowerFinite &&
5244-
direction * rhs <= sumLower + primal_feastol) {
5245-
// Only allow fixing if there is no degeneracy
5246-
const bool allow_fixing =
5247-
direction * rhs + delta <= sumLower + primal_feastol;
5248-
if (report_stuffing) {
5249-
printf(
5250-
"ColStuffing:1 (%2d) fix %6d to %s: cost = %11.4g; delta = "
5251-
"%11.4g | "
5252-
"Logic: direction * rhs = %11.4g <= %11.4g = sumLower + "
5253-
"primal_feastol: %s fixing\n",
5254-
int(-t.multiplier), int(t.col),
5255-
-t.multiplier < 0 ? "lower" : "upper", model->col_cost_[t.col],
5256-
double(delta), double(direction * rhs),
5257-
double(sumLower + primal_feastol), allow_fixing ? "allow" : "no");
5258-
}
5259-
if (allow_fixing) {
5260-
numFixedCols++;
5261-
HPRESOLVE_CHECKED_CALL(fixCol(t.col, -t.multiplier));
5262-
}
5178+
delta <= sumLower - direction * rhs + primal_feastol) {
5179+
// Previously
5180+
//
5181+
// direction * rhs <= sumLower + primal_feastol
5182+
//
5183+
// But this led to fixing at -t.multiplier until row activity
5184+
// was at its bound, which is primal optmal but degenerate,
5185+
// and does not yield an optimal basis if column costs are
5186+
// positive
5187+
numFixedCols++;
5188+
HPRESOLVE_CHECKED_CALL(fixCol(t.col, -t.multiplier));
52635189
}
52645190
// update row activities
52655191
if (sumLowerFinite) sumLower += delta;
@@ -5842,9 +5768,6 @@ HPresolve::Result HPresolve::fastPresolveLoop(
58425768

58435769
HPRESOLVE_CHECKED_CALL(presolveChangedCols(postsolve_stack));
58445770

5845-
// Temporary for fix-col-stuffing
5846-
HPRESOLVE_CHECKED_CALL(checkLimits(postsolve_stack));
5847-
58485771
} while (problemSizeReduction() > 0.01);
58495772

58505773
return Result::kOk;
@@ -6220,12 +6143,7 @@ HPresolve::Result HPresolve::checkLimits(HighsPostsolveStack& postsolve_stack) {
62206143

62216144
if ((numreductions & 1023u) == 0) HPRESOLVE_CHECKED_CALL(checkTimeLimit());
62226145

6223-
// Temporary for fix-col-stuffing
6224-
const bool limit_reached = numreductions >= reductionLimit;
6225-
if (limit_reached) {
6226-
printf("HPresolve::checkLimits Reduction limit reached\n");
6227-
}
6228-
return limit_reached ? Result::kStopped : Result::kOk;
6146+
return numreductions >= reductionLimit ? Result::kStopped : Result::kOk;
62296147
}
62306148

62316149
void HPresolve::storeCurrentProblemSize() {
@@ -7040,8 +6958,6 @@ HPresolve::Result HPresolve::presolveColSingletons(
70406958
HighsInt col = singletonColumns[i];
70416959
if (colDeleted[col]) continue;
70426960
HPRESOLVE_CHECKED_CALL(colPresolve(postsolve_stack, col));
7043-
// Temporary for fix-col-stuffing
7044-
HPRESOLVE_CHECKED_CALL(checkLimits(postsolve_stack));
70456961
}
70466962
singletonColumns.erase(
70476963
std::remove_if(

0 commit comments

Comments
 (0)