Skip to content

Commit

Permalink
Tidied and formatted
Browse files Browse the repository at this point in the history
  • Loading branch information
jajhall committed Nov 8, 2024
1 parent b14bbe1 commit b32cfd0
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 88 deletions.
8 changes: 4 additions & 4 deletions check/TestPresolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ TEST_CASE("presolve-slacks", "[highs_test_presolve]") {
lp.a_matrix_.index_ = {0, 0};
lp.a_matrix_.value_ = {1, 1};
Highs h;
// h.setOptionValue("output_flag", dev_run);
h.setOptionValue("output_flag", dev_run);
REQUIRE(h.passModel(lp) == HighsStatus::kOk);
REQUIRE(h.presolve() == HighsStatus::kOk);
REQUIRE(h.getPresolvedLp().num_col_ == 0);
Expand All @@ -632,10 +632,10 @@ TEST_CASE("presolve-slacks", "[highs_test_presolve]") {
lp.a_matrix_.start_ = {0, 2, 4, 5, 6};
lp.a_matrix_.index_ = {0, 1, 0, 1, 0, 1};
lp.a_matrix_.value_ = {1, 1, 2, 4, 1, 1};

REQUIRE(h.setOptionValue("presolve_remove_slacks", true) == HighsStatus::kOk);
REQUIRE(h.passModel(lp) == HighsStatus::kOk);
REQUIRE(h.run() == HighsStatus::kOk);
REQUIRE(h.presolve() == HighsStatus::kOk);
// REQUIRE(h.getPresolvedLp().num_col_ == 2);
// REQUIRE(h.getPresolvedLp().num_row_ == 2);
REQUIRE(h.getPresolvedLp().num_col_ == 2);
REQUIRE(h.getPresolvedLp().num_row_ == 2);
}
72 changes: 39 additions & 33 deletions src/lp_data/Highs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1251,40 +1251,46 @@ HighsStatus Highs::run() {
// Run solver.
bool have_optimal_solution = false;
// ToDo Put solution of presolved problem in a separate method

// if (!this->options_.presolve_remove_slacks) {
HighsLp& reduced_lp = presolve_.getReducedProblem();
HighsInt num_double_slack = 0;
HighsInt num_slack = 0;
HighsInt num_zero_cost_slack = 0;
HighsInt num_unit_coeff_slack = 0;
double min_slack_coeff = kHighsInf;
double max_slack_coeff = -kHighsInf;
std::vector<bool> found_slack;
found_slack.assign(reduced_lp.num_row_, false);
for (HighsInt iCol = 0; iCol < reduced_lp.num_col_; iCol++) {
HighsInt nnz = reduced_lp.a_matrix_.start_[iCol+1] - reduced_lp.a_matrix_.start_[iCol];
if (nnz != 1) continue;
HighsInt iRow = reduced_lp.a_matrix_.index_[reduced_lp.a_matrix_.start_[iCol]];
if (found_slack[iRow]) {
num_double_slack++;
continue;
}
if (reduced_lp.row_lower_[iRow] != reduced_lp.row_upper_[iRow]) continue;
num_slack++;
printf("Column %d is slack\n", int(iCol));
double coeff = std::fabs(reduced_lp.a_matrix_.value_[reduced_lp.a_matrix_.start_[iCol]]);
if (coeff == 1.0) num_unit_coeff_slack++;
min_slack_coeff = std::min(coeff,min_slack_coeff);
max_slack_coeff = std::max(coeff,max_slack_coeff);
found_slack[iRow] = true;
if (reduced_lp.col_cost_[iCol] == 0) num_zero_cost_slack++;
HighsLp& reduced_lp = presolve_.getReducedProblem();
HighsInt num_double_slack = 0;
HighsInt num_slack = 0;
HighsInt num_zero_cost_slack = 0;
HighsInt num_unit_coeff_slack = 0;
double min_slack_coeff = kHighsInf;
double max_slack_coeff = -kHighsInf;
std::vector<bool> found_slack;
found_slack.assign(reduced_lp.num_row_, false);
for (HighsInt iCol = 0; iCol < reduced_lp.num_col_; iCol++) {
HighsInt nnz = reduced_lp.a_matrix_.start_[iCol + 1] -
reduced_lp.a_matrix_.start_[iCol];
if (nnz != 1) continue;
HighsInt iRow =
reduced_lp.a_matrix_.index_[reduced_lp.a_matrix_.start_[iCol]];
if (found_slack[iRow]) {
num_double_slack++;
continue;
}
printf("grepSlack,model,col,slack,unit coeff,zero_cost,double,min coeff, max_coeff\n");
printf("grepSlack,%s,%d, %d, %d, %d, %d, %g, %g\n", this->model_.lp_.model_name_.c_str(),
int(reduced_lp.num_col_), int(num_slack), int(num_unit_coeff_slack), int(num_zero_cost_slack), int(num_double_slack),
min_slack_coeff, max_slack_coeff);
// }
if (reduced_lp.row_lower_[iRow] != reduced_lp.row_upper_[iRow]) continue;
num_slack++;
printf("Column %d is slack\n", int(iCol));
double coeff = std::fabs(
reduced_lp.a_matrix_.value_[reduced_lp.a_matrix_.start_[iCol]]);
if (coeff == 1.0) num_unit_coeff_slack++;
min_slack_coeff = std::min(coeff, min_slack_coeff);
max_slack_coeff = std::max(coeff, max_slack_coeff);
found_slack[iRow] = true;
if (reduced_lp.col_cost_[iCol] == 0) num_zero_cost_slack++;
}
printf(
"grepSlack,model,col,slack,unit coeff,zero_cost,double,min coeff, "
"max_coeff\n");
printf("grepSlack,%s,%d, %d, %d, %d, %d, %g, %g\n",
this->model_.lp_.model_name_.c_str(), int(reduced_lp.num_col_),
int(num_slack), int(num_unit_coeff_slack), int(num_zero_cost_slack),
int(num_double_slack), min_slack_coeff, max_slack_coeff);
// }

switch (model_presolve_status_) {
case HighsPresolveStatus::kNotPresolved: {
Expand All @@ -1310,7 +1316,7 @@ HighsStatus Highs::run() {
break;
}
case HighsPresolveStatus::kReduced: {
HighsLp& reduced_lp = presolve_.getReducedProblem();
HighsLp& reduced_lp = presolve_.getReducedProblem();
reduced_lp.setMatrixDimensions();
if (kAllowDeveloperAssert) {
// Validate the reduced LP
Expand Down
8 changes: 4 additions & 4 deletions src/lp_data/HighsOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ struct HighsOptionsStruct {
presolve_substitution_maxfillin(0),
presolve_rule_off(0),
presolve_rule_logging(false),
presolve_remove_slacks(false),
presolve_remove_slacks(false),
simplex_initial_condition_check(false),
no_unnecessary_rebuild_refactor(false),
simplex_initial_condition_tolerance(0.0),
Expand Down Expand Up @@ -1326,9 +1326,9 @@ class HighsOptions : public HighsOptionsStruct {
advanced, &presolve_rule_logging, false);
records.push_back(record_bool);

record_bool = new OptionRecordBool(
"presolve_remove_slacks", "Remove slacks after presolve",
advanced, &presolve_remove_slacks, true);//false);
record_bool = new OptionRecordBool("presolve_remove_slacks",
"Remove slacks after presolve", advanced,
&presolve_remove_slacks, false);
records.push_back(record_bool);

record_int = new OptionRecordInt(
Expand Down
29 changes: 17 additions & 12 deletions src/presolve/HPresolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4380,7 +4380,8 @@ HPresolve::Result HPresolve::presolve(HighsPostsolveStack& postsolve_stack) {
return Result::kOk;
}

HPresolve::Result HPresolve::removeSlacks(HighsPostsolveStack& postsolve_stack) {
HPresolve::Result HPresolve::removeSlacks(
HighsPostsolveStack& postsolve_stack) {
// singletonColumns data structure appears not to be retained
// throughout presolve
//
Expand All @@ -4399,7 +4400,10 @@ HPresolve::Result HPresolve::removeSlacks(HighsPostsolveStack& postsolve_stack)
double cost = model->col_cost_[iCol];
double rhs = model->row_lower_[iRow];
double coeff = Avalue[coliter];
printf("Col %d is continuous and is singleton in equality row %d with cost %g, bounds [%g, %g], coeff %g and RHS = %g\n", int(iCol), int(iRow), cost, lower, upper, coeff, rhs);
printf(
"Col %d is continuous and is singleton in equality row %d with cost "
"%g, bounds [%g, %g], coeff %g and RHS = %g\n",
int(iCol), int(iRow), cost, lower, upper, coeff, rhs);
if (unit_coeff_only && std::fabs(coeff) != 1.0) continue;
assert(coeff);
// Slack is s = (rhs - a^Tx)/coeff
Expand All @@ -4409,26 +4413,27 @@ HPresolve::Result HPresolve::removeSlacks(HighsPostsolveStack& postsolve_stack)
// For coeff > 0 [rhs - coeff * upper, rhs - coeff * lower]
//
// For coeff < 0 [rhs - coeff * lower, rhs - coeff * upper]
model->row_lower_[iRow] = coeff > 0 ? rhs - coeff * upper : rhs - coeff * lower;
model->row_upper_[iRow] = coeff > 0 ? rhs - coeff * lower : rhs - coeff * upper;
model->row_lower_[iRow] =
coeff > 0 ? rhs - coeff * upper : rhs - coeff * lower;
model->row_upper_[iRow] =
coeff > 0 ? rhs - coeff * lower : rhs - coeff * upper;
if (cost) {
// Cost is (cost * rhs / coeff) + (col_cost - (cost/coeff) row_values)^Tx
double multiplier = cost / coeff;
for (const HighsSliceNonzero& nonzero : getRowVector(iRow)) {
HighsInt local_iCol = nonzero.index();
double local_value = nonzero.value();
model->col_cost_[local_iCol] -= multiplier * local_value;
HighsInt local_iCol = nonzero.index();
double local_value = nonzero.value();
model->col_cost_[local_iCol] -= multiplier * local_value;
}
model->offset_ += multiplier * rhs;
}
//
postsolve_stack.slackColSubstitution(iRow, iCol, rhs, cost, lower, upper, //coeff,
getRowVector(iRow),
getColumnVector(iCol));
//
postsolve_stack.slackColSubstitution(iRow, iCol, rhs, cost,
getRowVector(iRow));

markColDeleted(iCol);

unlink(coliter);

}
return Result::kOk;
}
Expand Down
2 changes: 1 addition & 1 deletion src/presolve/HPresolve.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ class HPresolve {
Result presolve(HighsPostsolveStack& postsolve_stack);

Result removeSlacks(HighsPostsolveStack& postsolve_stack);

Result checkLimits(HighsPostsolveStack& postsolve_stack);

void storeCurrentProblemSize();
Expand Down
34 changes: 23 additions & 11 deletions src/presolve/HighsPostsolveStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1353,9 +1353,7 @@ void HighsPostsolveStack::DuplicateColumn::transformToPresolvedSpace(

void HighsPostsolveStack::SlackColSubstitution::undo(
const HighsOptions& options, const std::vector<Nonzero>& rowValues,
const std::vector<Nonzero>& colValues, HighsSolution& solution,
HighsBasis& basis) {

HighsSolution& solution, HighsBasis& basis) {
// Taken from HighsPostsolveStack::FreeColSubstitution::undo(
//
// a (removed) cut may have been used in this reduction.
Expand All @@ -1378,33 +1376,47 @@ void HighsPostsolveStack::SlackColSubstitution::undo(

assert(colCoef != 0);
// Row values aren't fully postsolved, so why do this?
if (isModelRow) solution.row_value[row] =
if (isModelRow)
solution.row_value[row] =
double(rowValue + colCoef * solution.col_value[col]);
printf("HighsPostsolveStack::SlackColSubstitution::undo rowValue = %g\n", double(rowValue));

solution.col_value[col] = double((rhs - rowValue) / colCoef);
printf(
"\nHighsPostsolveStack::SlackColSubstitution::undo rowValue = %g; "
"colValue = %g\n",
double(rowValue), solution.col_value[col]);

// if no dual values requested, return here
if (!solution.dual_valid) return;

// compute the row dual value such that reduced cost of basic column is 0
double save_row_dual = solution.row_dual[row];
if (isModelRow) {
solution.row_dual[row] = 0;
HighsCDouble dualval = colCost;
for (const auto& colVal : colValues) {
if (static_cast<size_t>(colVal.index) < solution.row_dual.size())
dualval -= colVal.value * solution.row_dual[colVal.index];
}
HighsCDouble dualval = HighsCDouble(colCost);
dualval = -colCoef * solution.row_dual[row];
solution.row_dual[row] = double(dualval / colCoef);
}

solution.col_dual[col] = 0;
printf(
"HighsPostsolveStack::SlackColSubstitution::undo OgRowDual = %g; rowDual "
"= %g; colDual = %g\n",
save_row_dual, solution.row_dual[row], solution.col_dual[col]);

// set basis status if necessary
if (!basis.valid) return;

basis.col_status[col] = HighsBasisStatus::kBasic;
HighsBasisStatus save_row_basis_status = basis.row_status[row];
if (isModelRow)
basis.row_status[row] = computeRowStatus(solution.row_dual[row], RowType::kEq);
basis.row_status[row] =
computeRowStatus(solution.row_dual[row], RowType::kEq);
printf(
"HighsPostsolveStack::SlackColSubstitution::undo OgRowStatus = %d; "
"RowStatus = %d; ColStatus = %d\n",
int(save_row_basis_status), int(basis.row_status[row]),
int(basis.col_status[col]));
}

} // namespace presolve
29 changes: 8 additions & 21 deletions src/presolve/HighsPostsolveStack.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,15 +222,11 @@ class HighsPostsolveStack {
struct SlackColSubstitution {
double rhs;
double colCost;
double colLower;
double colUpper;
// double colCoeff;
HighsInt row;
HighsInt col;

void undo(const HighsOptions& options,
const std::vector<Nonzero>& rowValues,
const std::vector<Nonzero>& colValues, HighsSolution& solution,
const std::vector<Nonzero>& rowValues, HighsSolution& solution,
HighsBasis& basis);
};

Expand Down Expand Up @@ -339,24 +335,17 @@ class HighsPostsolveStack {
reductionAdded(ReductionType::kFreeColSubstitution);
}

template <typename RowStorageFormat, typename ColStorageFormat>
template <typename RowStorageFormat>
void slackColSubstitution(HighsInt row, HighsInt col, double rhs,
double colCost, double colLower, double colUpper, //double colCoeff,
const HighsMatrixSlice<RowStorageFormat>& rowVec,
const HighsMatrixSlice<ColStorageFormat>& colVec) {
double colCost,
const HighsMatrixSlice<RowStorageFormat>& rowVec) {
rowValues.clear();
for (const HighsSliceNonzero& rowVal : rowVec)
rowValues.emplace_back(origColIndex[rowVal.index()], rowVal.value());

colValues.clear();
for (const HighsSliceNonzero& colVal : colVec)
colValues.emplace_back(origRowIndex[colVal.index()], colVal.value());

reductionValues.push(SlackColSubstitution{rhs, colCost, colLower, colUpper, //colCoeff,
origRowIndex[row],
origColIndex[col]});
reductionValues.push(SlackColSubstitution{rhs, colCost, origRowIndex[row],
origColIndex[col]});
reductionValues.push(rowValues);
reductionValues.push(colValues);
reductionAdded(ReductionType::kSlackColSubstitution);
}

Expand Down Expand Up @@ -749,10 +738,9 @@ class HighsPostsolveStack {
}
case ReductionType::kSlackColSubstitution: {
SlackColSubstitution reduction;
reductionValues.pop(colValues);
reductionValues.pop(rowValues);
reductionValues.pop(reduction);
reduction.undo(options, rowValues, colValues, solution, basis);
reduction.undo(options, rowValues, solution, basis);
break;
}
default:
Expand Down Expand Up @@ -934,10 +922,9 @@ class HighsPostsolveStack {
}
case ReductionType::kSlackColSubstitution: {
SlackColSubstitution reduction;
reductionValues.pop(colValues);
reductionValues.pop(rowValues);
reductionValues.pop(reduction);
reduction.undo(options, rowValues, colValues, solution, basis);
reduction.undo(options, rowValues, solution, basis);
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/qpsolver/dantzigpricing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class DantzigPricing : public Pricing {

public:
DantzigPricing(Runtime& rt, Basis& bas, ReducedCosts& rc)
// clang-format off
// clang-format off
: runtime(rt), basis(bas), redcosts(rc) {};
// clang-format on
HighsInt price(const QpVector& x, const QpVector& gradient) {
Expand Down
2 changes: 1 addition & 1 deletion src/qpsolver/devexpricing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class DevexPricing : public Pricing {
: runtime(rt),
basis(bas),
redcosts(rc),
// clang-format off
// clang-format off
weights(std::vector<double>(rt.instance.num_var, 1.0)) {};
// clang-format on

Expand Down

0 comments on commit b32cfd0

Please sign in to comment.