Skip to content

Commit

Permalink
Merge pull request #2196 from ERGO-Code/no-gesa2
Browse files Browse the repository at this point in the history
No gesa2
  • Loading branch information
jajhall authored Feb 27, 2025
2 parents 863832a + 481d14d commit 000923c
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 21 deletions.
4 changes: 2 additions & 2 deletions check/Avgas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ void Avgas::getRow(const HighsInt row, double& lower, double& upper,
index.push_back(7);
value.push_back(-2);
} else {
if (dev_run) printf("Avgas: row %d out of range\n", HighsInt(row));
if (dev_run) printf("Avgas: row %d out of range\n", static_cast<int>(row));
}
}

Expand Down Expand Up @@ -240,6 +240,6 @@ void Avgas::getCol(const HighsInt col, double& cost, double& lower,
index.push_back(9);
value.push_back(-2);
} else {
if (dev_run) printf("Avgas: col %d out of range\n", HighsInt(col));
if (dev_run) printf("Avgas: col %d out of range\n", static_cast<int>(col));
}
}
11 changes: 11 additions & 0 deletions check/TestPresolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,3 +649,14 @@ TEST_CASE("presolve-issue-2095", "[highs_test_presolve]") {
REQUIRE(highs.presolve() == HighsStatus::kOk);
REQUIRE(highs.getModelPresolveStatus() == HighsPresolveStatus::kReduced);
}

TEST_CASE("presolve-only-at-root", "[highs_test_presolve]") {
std::string model_file = std::string(HIGHS_DIR) + "/check/instances/rgn.mps";

Highs highs;
highs.setOptionValue("output_flag", dev_run);
// Allow only presolve at root node
highs.setOptionValue("mip_root_presolve_only", true);
highs.readModel(model_file);
REQUIRE(highs.run() == HighsStatus::kOk);
}
5 changes: 3 additions & 2 deletions src/lp_data/HighsOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ bool commandLineSolverOk(const HighsLogOptions& report_log_options,
bool boolFromString(std::string value, bool& bool_value) {
std::transform(value.begin(), value.end(), value.begin(),
[](unsigned char c) { return std::tolower(c); });
if (value == "t" || value == "true" || value == "1" || value == "on") {
if (value == "t" || value == "true" || value == "1" ||
value == kHighsOnString) {
bool_value = true;
} else if (value == "f" || value == "false" || value == "0" ||
value == "off") {
value == kHighsOffString) {
bool_value = false;
} else {
return false;
Expand Down
10 changes: 9 additions & 1 deletion src/lp_data/HighsOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ struct HighsOptionsStruct {
bool mip_improving_solution_save;
bool mip_improving_solution_report_sparse;
std::string mip_improving_solution_file;
bool mip_root_presolve_only;

// Logging callback identifiers
HighsLogOptions log_options;
Expand Down Expand Up @@ -572,7 +573,8 @@ struct HighsOptionsStruct {
mip_improving_solution_save(false),
mip_improving_solution_report_sparse(false),
// clang-format off
mip_improving_solution_file("") {};
mip_improving_solution_file(""),
mip_root_presolve_only(false) {};
// clang-format on
};

Expand Down Expand Up @@ -1003,6 +1005,12 @@ class HighsOptions : public HighsOptionsStruct {
advanced, &mip_improving_solution_file, kHighsFilenameDefault);
records.push_back(record_string);

record_bool = new OptionRecordBool(
"mip_root_presolve_only",
"Whether MIP presolve is only applied at the root node", advanced,
&mip_root_presolve_only, false);
records.push_back(record_bool);

record_int = new OptionRecordInt(
"mip_max_leaves", "MIP solver max number of leaf nodes", advanced,
&mip_max_leaves, 0, kHighsIInf, kHighsIInf);
Expand Down
3 changes: 2 additions & 1 deletion src/lp_data/HighsSolve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ HighsStatus solveLp(HighsLpSolverObject& solver_object, const string message) {
utilModelStatusToString(solver_object.model_status_).c_str(),
solver_object.basis_.valid ? "" : "not ",
solver_object.solution_.value_valid ? "" : "not ",
options.run_centring ? "off" : options.run_crossover.c_str());
options.run_centring ? kHighsOffString.c_str()
: options.run_crossover.c_str());
const bool allow_simplex_cleanup =
options.run_crossover != kHighsOffString && !options.run_centring;
if (allow_simplex_cleanup) {
Expand Down
3 changes: 3 additions & 0 deletions src/mip/HighsLpRelaxation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,9 @@ HighsLpRelaxation::Status HighsLpRelaxation::run(bool resolve_on_error) {
ipm.setOptionValue("output_flag", false);
ipm.setOptionValue("solver", "ipm");
ipm.setOptionValue("ipm_iteration_limit", 200);
// check if only root presolve is allowed
if (mipsolver.options_mip_->mip_root_presolve_only)
ipm.setOptionValue("presolve", kHighsOffString);
ipm.passModel(lpsolver.getLp());
// todo @ Julian : If you remove this you can see the looping on
// istanbul-no-cutoff
Expand Down
20 changes: 13 additions & 7 deletions src/mip/HighsMipSolverData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ void HighsMipSolverData::startAnalyticCenterComputation(
Highs ipm;
ipm.setOptionValue("solver", "ipm");
ipm.setOptionValue("run_crossover", kHighsOffString);
ipm.setOptionValue("presolve", "off");
ipm.setOptionValue("presolve", kHighsOffString);
ipm.setOptionValue("output_flag", false);
// ipm.setOptionValue("output_flag", !mipsolver.submip);
ipm.setOptionValue("ipm_iteration_limit", 200);
Expand Down Expand Up @@ -846,9 +846,9 @@ void HighsMipSolverData::runSetup() {
implications.cleanupVarbounds(col);
domain.clearChangedCols();

lp.getLpSolver().setOptionValue("presolve", "off");
lp.getLpSolver().setOptionValue("presolve", kHighsOffString);
// lp.getLpSolver().setOptionValue("dual_simplex_cost_perturbation_multiplier",
// 0.0); lp.getLpSolver().setOptionValue("parallel", "on");
// 0.0); lp.getLpSolver().setOptionValue("parallel", kHighsOnString);
lp.getLpSolver().setOptionValue("simplex_initial_condition_check", false);

checkObjIntegrality();
Expand Down Expand Up @@ -1020,10 +1020,13 @@ double HighsMipSolverData::transformNewIntegerFeasibleSolution(
tmpSolver.setOptionValue("output_flag", false);
}
// tmpSolver.setOptionValue("simplex_scale_strategy", 0);
// tmpSolver.setOptionValue("presolve", "off");
// tmpSolver.setOptionValue("presolve", kHighsOffString);
tmpSolver.setOptionValue("time_limit", time_available);
tmpSolver.setOptionValue("primal_feasibility_tolerance",
mipsolver.options_mip_->mip_feasibility_tolerance);
// check if only root presolve is allowed
if (mipsolver.options_mip_->mip_root_presolve_only)
tmpSolver.setOptionValue("presolve", kHighsOffString);
tmpSolver.passModel(std::move(fixedModel));
mipsolver.analysis_.mipTimerStart(kMipClockSimplexNoBasisSolveLp);
tmpSolver.run();
Expand Down Expand Up @@ -1776,11 +1779,14 @@ void HighsMipSolverData::evaluateRootNode() {
mipsolver.solution_objective_,
kUserMipSolutionCallbackOriginEvaluateRootNode0);

// check if only root presolve is allowed
if (firstrootbasis.valid)
lp.getLpSolver().setBasis(firstrootbasis,
"HighsMipSolverData::evaluateRootNode");
else if (mipsolver.options_mip_->mip_root_presolve_only)
lp.getLpSolver().setOptionValue("presolve", kHighsOffString);
else
lp.getLpSolver().setOptionValue("presolve", "on");
lp.getLpSolver().setOptionValue("presolve", kHighsOnString);
if (mipsolver.options_mip_->highs_debug_level)
lp.getLpSolver().setOptionValue("output_flag",
mipsolver.options_mip_->output_flag);
Expand All @@ -1794,8 +1800,8 @@ void HighsMipSolverData::evaluateRootNode() {
if (numRestarts == 0) firstrootlpiters = total_lp_iterations;

lp.getLpSolver().setOptionValue("output_flag", false);
lp.getLpSolver().setOptionValue("presolve", "off");
lp.getLpSolver().setOptionValue("parallel", "off");
lp.getLpSolver().setOptionValue("presolve", kHighsOffString);
lp.getLpSolver().setOptionValue("parallel", kHighsOffString);

if (status == HighsLpRelaxation::Status::kInfeasible ||
status == HighsLpRelaxation::Status::kUnbounded)
Expand Down
27 changes: 21 additions & 6 deletions src/mip/HighsPrimalHeuristics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,11 @@ bool HighsPrimalHeuristics::solveSubMip(
mipsolver.mipdata_->feastol * std::max(curr_abs_gap, 1000.0);
}

submipoptions.presolve = "on";
// check if only root presolve is allowed
if (submipoptions.mip_root_presolve_only)
submipoptions.presolve = kHighsOffString;
else
submipoptions.presolve = kHighsOnString;
submipoptions.mip_detect_symmetry = false;
submipoptions.mip_heuristic_effort = 0.8;
// setup solver and run it
Expand Down Expand Up @@ -884,8 +888,12 @@ bool HighsPrimalHeuristics::tryRoundedPoint(const std::vector<double>& point,
localdom.col_lower_.data(),
localdom.col_upper_.data());

if (numintcols / (double)mipsolver.numCol() >= 0.2)
lprelax.getLpSolver().setOptionValue("presolve", "on");
// check if only root presolve is allowed
if (mipsolver.options_mip_->mip_root_presolve_only)
lprelax.getLpSolver().setOptionValue("presolve", kHighsOffString);
if (!mipsolver.options_mip_->mip_root_presolve_only &&
(5 * numintcols) / mipsolver.numCol() >= 1)
lprelax.getLpSolver().setOptionValue("presolve", kHighsOnString);
else
lprelax.getLpSolver().setBasis(mipsolver.mipdata_->firstrootbasis,
"HighsPrimalHeuristics::tryRoundedPoint");
Expand Down Expand Up @@ -999,20 +1007,27 @@ void HighsPrimalHeuristics::randomizedRounding(
}
}

if (int(mipsolver.mipdata_->integer_cols.size()) != mipsolver.numCol()) {
if (mipsolver.mipdata_->integer_cols.size() !=
static_cast<size_t>(mipsolver.numCol())) {
HighsLpRelaxation lprelax(mipsolver);
lprelax.loadModel();
lprelax.setIterationLimit(
std::max(int64_t{10000}, 2 * mipsolver.mipdata_->firstrootlpiters));
lprelax.getLpSolver().changeColsBounds(0, mipsolver.numCol() - 1,
localdom.col_lower_.data(),
localdom.col_upper_.data());
if ((5 * intcols.size()) / mipsolver.numCol() >= 1)
lprelax.getLpSolver().setOptionValue("presolve", "on");

// check if only root presolve is allowed
if (mipsolver.options_mip_->mip_root_presolve_only)
lprelax.getLpSolver().setOptionValue("presolve", kHighsOffString);
if (!mipsolver.options_mip_->mip_root_presolve_only &&
(5 * intcols.size()) / mipsolver.numCol() >= 1)
lprelax.getLpSolver().setOptionValue("presolve", kHighsOnString);
else
lprelax.getLpSolver().setBasis(
mipsolver.mipdata_->firstrootbasis,
"HighsPrimalHeuristics::randomizedRounding");

HighsLpRelaxation::Status st = lprelax.resolveLp();

if (st == HighsLpRelaxation::Status::kInfeasible) {
Expand Down
2 changes: 1 addition & 1 deletion src/mip/HighsSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1530,7 +1530,7 @@ HighsSearch::NodeResult HighsSearch::branch() {
std::swap(tmpLp, lp);

// reevaluate the node with LP presolve enabled
lp->getLpSolver().setOptionValue("presolve", "on");
lp->getLpSolver().setOptionValue("presolve", kHighsOnString);
result = evaluateNode();

if (result == NodeResult::kOpen) {
Expand Down
2 changes: 1 addition & 1 deletion src/qpsolver/feasibility_highs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ static void computeStartingPointHighs(

// set HiGHS to be silent
highs.setOptionValue("output_flag", false);
highs.setOptionValue("presolve", "on");
highs.setOptionValue("presolve", kHighsOnString);
// Set the residual time limit
const double use_time_limit =
std::max(settings.time_limit - timer.read(), 0.001);
Expand Down

0 comments on commit 000923c

Please sign in to comment.