Skip to content

Commit 3b379f1

Browse files
committed
Now handling the case when no basic solution required, but presolve reduces the model to empty
1 parent e1d1477 commit 3b379f1

File tree

7 files changed

+592
-13
lines changed

7 files changed

+592
-13
lines changed

check/TestPresolve.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,81 @@ TEST_CASE("presolve-issue-2446", "[highs_test_presolve]") {
734734
REQUIRE(highs.presolve() == HighsStatus::kOk);
735735
REQUIRE(highs.getModelPresolveStatus() == HighsPresolveStatus::kReduced);
736736
}
737+
738+
TEST_CASE("presolve-egout-ac", "[highs_test_presolve]") {
739+
// Tests the case where, for this model when run_crossover is off,
740+
// sparsify is used to reduce the LP to empty. However, when
741+
// starting from an empty LP, basis postsolve is always used
742+
std::string model_file =
743+
std::string(HIGHS_DIR) + "/check/instances/egout-ac.mps";
744+
Highs h;
745+
h.setOptionValue("output_flag", dev_run);
746+
REQUIRE(h.setOptionValue("presolve_rule_logging", true) == HighsStatus::kOk);
747+
if (dev_run)
748+
REQUIRE(h.setOptionValue("log_dev_level", 1) == HighsStatus::kOk);
749+
REQUIRE(h.readModel(model_file) == HighsStatus::kOk);
750+
// Firstly check that pure presolve reduces the LP to empty
751+
REQUIRE(h.presolve() == HighsStatus::kOk);
752+
// Ensure that sparsify isn't called
753+
REQUIRE(h.getPresolveLog().rule[kPresolveRuleSparsify].call == 0);
754+
755+
const HighsLp& presolved_lp = h.getPresolvedLp();
756+
REQUIRE(presolved_lp.num_col_ == 0);
757+
REQUIRE(presolved_lp.num_row_ == 0);
758+
759+
HighsSolution solution;
760+
HighsBasis basis;
761+
basis.useful = true;
762+
solution.value_valid = true;
763+
solution.dual_valid = true;
764+
// Check that postsolve with the empty solution and basis runs OK -
765+
// ie doesn't trigger assert due to sparsify having been used
766+
REQUIRE(h.postsolve(solution, basis) == HighsStatus::kOk);
767+
768+
// Check that using IPM with crossover runs OK without using
769+
// sparsify
770+
REQUIRE(h.setOptionValue("solver", kIpmString) == HighsStatus::kOk);
771+
REQUIRE(h.run() == HighsStatus::kOk);
772+
REQUIRE(h.getPresolveLog().rule[kPresolveRuleSparsify].call == 0);
773+
774+
// Check that pure presolve reduces the LP to empty without using
775+
// sparsify
776+
REQUIRE(h.presolve() == HighsStatus::kOk);
777+
REQUIRE(h.getPresolveLog().rule[kPresolveRuleSparsify].call == 0);
778+
REQUIRE(h.postsolve(solution, basis) == HighsStatus::kOk);
779+
780+
// Check that pure presolve reduces the LP to empty using sparsify
781+
// when lp_presolve_requires_basis_postsolve is false
782+
bool lp_presolve_requires_basis_postsolve = false;
783+
REQUIRE(h.setOptionValue("lp_presolve_requires_basis_postsolve",
784+
lp_presolve_requires_basis_postsolve) ==
785+
HighsStatus::kOk);
786+
REQUIRE(h.presolve() == HighsStatus::kOk);
787+
REQUIRE(h.getPresolveLog().rule[kPresolveRuleSparsify].call > 0);
788+
REQUIRE(h.postsolve(solution, basis) == HighsStatus::kOk);
789+
REQUIRE(h.getOptions().lp_presolve_requires_basis_postsolve ==
790+
lp_presolve_requires_basis_postsolve);
791+
792+
// Now, with crossover off
793+
REQUIRE(h.setOptionValue("run_crossover", kHighsOffString) ==
794+
HighsStatus::kOk);
795+
796+
// Now reset lp_presolve_requires_basis_postsolve default to true,
797+
// to test whether it's set false due to running IPM without
798+
// crossover
799+
lp_presolve_requires_basis_postsolve = true;
800+
REQUIRE(h.setOptionValue("lp_presolve_requires_basis_postsolve",
801+
lp_presolve_requires_basis_postsolve) ==
802+
HighsStatus::kOk);
803+
804+
REQUIRE(h.clearSolver() == HighsStatus::kOk);
805+
REQUIRE(h.run() == HighsStatus::kOk);
806+
REQUIRE(h.getPresolveLog().rule[kPresolveRuleSparsify].call > 0);
807+
// Ensure that lp_presolve_requires_basis_postsolve has been reset
808+
// to true, after being set false before presolve when using IPM
809+
// without crossover
810+
REQUIRE(h.getOptions().lp_presolve_requires_basis_postsolve ==
811+
lp_presolve_requires_basis_postsolve);
812+
813+
h.resetGlobalScheduler(true);
814+
}

0 commit comments

Comments
 (0)