#include "HCheckConfig.h" #include "Highs.h" #include "SpecialLps.h" #include "catch.hpp" const bool dev_run = false; void solve(Highs& highs, std::string presolve, std::string solver, const HighsModelStatus require_model_status, const double require_optimal_objective = 0, const double require_iteration_count = -1) { SpecialLps special_lps; if (!dev_run) highs.setOptionValue("output_flag", false); if (dev_run) REQUIRE(highs.setOptionValue("log_dev_level", kHighsLogDevLevelDetailed) == HighsStatus::kOk); if (dev_run) printf("\n*****\nSolving with presolve = %s amd solver = %s\n", presolve.c_str(), solver.c_str()); const HighsInfo& info = highs.getInfo(); REQUIRE(highs.setOptionValue("solver", solver) == HighsStatus::kOk); REQUIRE(highs.setOptionValue("presolve", presolve) == HighsStatus::kOk); REQUIRE(highs.clearSolver() == HighsStatus::kOk); REQUIRE(highs.run() == HighsStatus::kOk); if (dev_run) printf("Solved %s with presolve: status = %s\n", highs.getLp().model_name_.c_str(), highs.modelStatusToString(highs.getModelStatus()).c_str()); REQUIRE(highs.getModelStatus() == require_model_status); if (require_model_status == HighsModelStatus::kOptimal) { REQUIRE(special_lps.objectiveOk(info.objective_function_value, require_optimal_objective, dev_run)); } if (require_iteration_count >= 0) { HighsInt iteration_count; if (solver == "simplex") { iteration_count = highs.getInfo().simplex_iteration_count; } else { iteration_count = highs.getInfo().ipm_iteration_count; } REQUIRE(iteration_count == require_iteration_count); } REQUIRE(highs.resetOptions() == HighsStatus::kOk); } void distillation(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("distillation", dev_run); // This LP is not primal feasible at the origin HighsLp lp; HighsModelStatus require_model_status; double optimal_objective; special_lps.distillationLp(lp, require_model_status, optimal_objective); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve doesn't reduce the LP solve(highs, "on", "simplex", require_model_status, optimal_objective); solve(highs, "on", "ipm", require_model_status, optimal_objective); } void issue272(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(272, dev_run); // This is the FuOR MIP that presolve failed to handle as a maximization HighsLp lp; HighsModelStatus require_model_status; double optimal_objective; special_lps.issue272Lp(lp, require_model_status, optimal_objective); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve reduces to empty, so no need to test presolve+IPX solve(highs, "on", "simplex", require_model_status, optimal_objective); solve(highs, "off", "simplex", require_model_status, optimal_objective); solve(highs, "on", "ipm", require_model_status, optimal_objective); solve(highs, "off", "ipm", require_model_status, optimal_objective); } void issue280(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(280, dev_run); HighsLp lp; HighsModelStatus require_model_status; double optimal_objective; special_lps.issue280Lp(lp, require_model_status, optimal_objective); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve reduces to empty, so no need to test presolve+IPX solve(highs, "on", "simplex", require_model_status, optimal_objective); solve(highs, "off", "simplex", require_model_status, optimal_objective); special_lps.reportSolution(highs, dev_run); solve(highs, "off", "ipm", require_model_status, optimal_objective); } void issue282(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(282, dev_run); // This is an easy problem from mckib2 on which presolve+simplex // failed to give the correct objective HighsLp lp; HighsModelStatus require_model_status; double optimal_objective; special_lps.issue282Lp(lp, require_model_status, optimal_objective); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve reduces to empty, so no real need to test presolve+IPX solve(highs, "on", "simplex", require_model_status, optimal_objective); solve(highs, "off", "simplex", require_model_status, optimal_objective); solve(highs, "on", "ipm", require_model_status, optimal_objective); solve(highs, "off", "ipm", require_model_status, optimal_objective); } void issue285(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(285, dev_run); // This is an infeasible LP for which HiGHS segfaulted after "Problem // status detected on presolve: Infeasible" HighsLp lp; HighsModelStatus require_model_status; special_lps.issue285Lp(lp, require_model_status); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve identifies infeasibility, so no need to test presolve+IPX solve(highs, "on", "simplex", require_model_status); solve(highs, "off", "simplex", require_model_status); solve(highs, "on", "ipm", require_model_status); solve(highs, "off", "ipm", require_model_status); } void issue295(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(295, dev_run); // Simplex solver (without presolve) gets a correct solution, IPX // (without presolve) reported the correct objective function value // but an inconsistent solution. Both simplex and IPX reported an // error when presolve is on. // // The bug in presolve was due to relying on size to get the number // of nonzeros. Correct interpretations of IPX inconsistent solution // was added HighsLp lp; HighsModelStatus require_model_status; double optimal_objective; special_lps.issue295Lp(lp, require_model_status, optimal_objective); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); solve(highs, "on", "simplex", require_model_status, optimal_objective); solve(highs, "off", "simplex", require_model_status, optimal_objective); solve(highs, "on", "ipm", require_model_status, optimal_objective); solve(highs, "off", "ipm", require_model_status, optimal_objective); } void issue306(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(306, dev_run); // This is test6690 from mckib2 that gave a small inconsistency in // a bound after presolve, causing an error in IPX // // Resulted in the introduction of cleanBounds after presolve HighsLp lp; HighsModelStatus require_model_status; double optimal_objective; special_lps.issue306Lp(lp, require_model_status, optimal_objective); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); solve(highs, "on", "simplex", require_model_status, optimal_objective); solve(highs, "off", "simplex", require_model_status, optimal_objective); solve(highs, "on", "ipm", require_model_status, optimal_objective); solve(highs, "off", "ipm", require_model_status, optimal_objective); } void issue316(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(316, dev_run); // This is a test problem from matbesancon where maximization failed // // Resulted in fixes being added to unconstrained LP solver bool bool_status; const HighsModelStatus require_model_status = HighsModelStatus::kOptimal; const double min_optimal_objective = -6; const double max_optimal_objective = 12; REQUIRE(highs.clearModel() == HighsStatus::kOk); bool_status = highs.addCol(2, -3, 6, 0, NULL, NULL) == HighsStatus::kOk; REQUIRE(bool_status); // Presolve reduces to empty solve(highs, "on", "simplex", require_model_status, min_optimal_objective); solve(highs, "off", "simplex", require_model_status, min_optimal_objective); bool_status = highs.changeObjectiveSense(ObjSense::kMaximize) == HighsStatus::kOk; REQUIRE(bool_status); solve(highs, "on", "simplex", require_model_status, max_optimal_objective); solve(highs, "off", "simplex", require_model_status, max_optimal_objective); } void issue425(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(425, dev_run); // This is issue425 from mckib2 for which presolve failed to identify // infeasibility HighsLp lp; HighsModelStatus require_model_status; special_lps.issue425Lp(lp, require_model_status); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); solve(highs, "on", "simplex", require_model_status, 0, -1); solve(highs, "off", "simplex", require_model_status, 0, 3); solve(highs, "off", "ipm", require_model_status, 0, 4); } void issue669(Highs& highs) { SpecialLps special_lps; special_lps.reportIssue(669, dev_run); // This is issue669 from chrhansk for which presolve gets into a // mess with zero coefficients HighsLp lp; HighsModelStatus require_model_status; special_lps.issue669Lp(lp, require_model_status); const bool issue669a = false; if (issue669a) { // Expose issue 669a. // // Forgetting that lp.a_matrix_.start_ has initial size of 1, I pushed // lp.num_col_+1 zeros onto it, giving it size lp.num_col_+2. This // triggers an assert in HPresolve.cpp:1946 // // Push the additional 0 now lp.a_matrix_.start_.push_back(0); } REQUIRE(highs.passModel(lp) == HighsStatus::kOk); if (!issue669a) { // Complete the LP as in issue 669 highs.changeColBounds(0, -0.266667, 0.266667); highs.changeColBounds(1, -0.266667, 0.266667); highs.changeColBounds(2, -0.266667, 0.266667); highs.changeColBounds(3, -0.266667, 0.266667); highs.changeColBounds(4, -0.266667, 0.266667); highs.changeColBounds(5, -0.266667, 0.266667); highs.changeColBounds(6, -0.266667, 0.266667); highs.changeColBounds(7, -0.266667, 0.266667); highs.changeColBounds(8, -0.266667, 0.266667); highs.changeColBounds(9, 0.000000, inf); highs.changeColBounds(10, 0.000000, inf); highs.changeColBounds(11, 0.000000, inf); highs.changeColBounds(12, 0.000000, inf); highs.changeColBounds(13, 0.000000, inf); highs.changeColBounds(14, 0.000000, inf); highs.changeColBounds(15, 0.000000, inf); highs.changeColBounds(16, 0.000000, inf); highs.changeColBounds(17, 0.000000, inf); highs.changeColBounds(18, 0.000000, inf); highs.changeColBounds(19, 0.000000, inf); highs.changeColBounds(20, 0.000000, inf); highs.changeColBounds(21, 0.000000, inf); highs.changeColBounds(22, 0.000000, inf); highs.changeColBounds(23, 0.000000, inf); highs.changeColBounds(24, 0.000000, inf); highs.changeColBounds(25, 0.000000, inf); highs.changeColBounds(26, 0.000000, inf); highs.changeRowBounds(0, 0.000000, 0.000000); highs.changeRowBounds(1, -948.210000, -948.210000); highs.changeRowBounds(2, 0.000000, 0.000000); highs.changeRowBounds(3, 0.000000, 0.000000); highs.changeRowBounds(4, 44.792000, 44.792000); highs.changeRowBounds(5, 0.000000, 0.000000); highs.changeRowBounds(6, 0.000000, 0.000000); highs.changeRowBounds(7, -42.684000, -42.684000); highs.changeRowBounds(8, 0.000000, 0.000000); highs.changeCoeff(0, 0, 0.000000); highs.changeCoeff(1, 0, 0.000000); highs.changeCoeff(2, 0, 0.000000); highs.changeCoeff(3, 0, -0.006089); highs.changeCoeff(6, 0, 0.000000); highs.changeCoeff(0, 1, 0.000000); highs.changeCoeff(1, 1, 0.000000); highs.changeCoeff(2, 1, 0.000000); highs.changeCoeff(4, 1, -0.006089); highs.changeCoeff(7, 1, 0.000000); highs.changeCoeff(0, 2, 0.000000); highs.changeCoeff(1, 2, 0.000000); highs.changeCoeff(2, 2, 0.000000); highs.changeCoeff(5, 2, -0.006089); highs.changeCoeff(8, 2, 0.000000); highs.changeCoeff(0, 3, -1886.000000); highs.changeCoeff(1, 3, 0.000000); highs.changeCoeff(2, 3, 0.000000); highs.changeCoeff(3, 3, 44.292000); highs.changeCoeff(6, 3, -42.362000); highs.changeCoeff(0, 4, 0.000000); highs.changeCoeff(1, 4, -1886.000000); highs.changeCoeff(2, 4, 0.000000); highs.changeCoeff(4, 4, 44.292000); highs.changeCoeff(7, 4, -42.362000); highs.changeCoeff(0, 5, 0.000000); highs.changeCoeff(1, 5, 0.000000); highs.changeCoeff(2, 5, -1886.000000); highs.changeCoeff(5, 5, 44.292000); highs.changeCoeff(8, 5, -42.362000); highs.changeCoeff(0, 6, 42.362000); highs.changeCoeff(1, 6, 0.000000); highs.changeCoeff(2, 6, 0.000000); highs.changeCoeff(3, 6, -2.001100); highs.changeCoeff(6, 6, 2.070500); highs.changeCoeff(0, 7, 0.000000); highs.changeCoeff(1, 7, 42.362000); highs.changeCoeff(2, 7, 0.000000); highs.changeCoeff(4, 7, -2.001100); highs.changeCoeff(7, 7, 2.070500); highs.changeCoeff(0, 8, 0.000000); highs.changeCoeff(1, 8, 0.000000); highs.changeCoeff(2, 8, 42.362000); highs.changeCoeff(5, 8, -2.001100); highs.changeCoeff(8, 8, 2.070500); highs.changeCoeff(0, 9, 1.000000); highs.changeCoeff(1, 10, 1.000000); highs.changeCoeff(2, 11, 1.000000); highs.changeCoeff(3, 12, 1.000000); highs.changeCoeff(4, 13, 1.000000); highs.changeCoeff(5, 14, 1.000000); highs.changeCoeff(6, 15, 1.000000); highs.changeCoeff(7, 16, 1.000000); highs.changeCoeff(8, 17, 1.000000); highs.changeCoeff(0, 18, -1.000000); highs.changeCoeff(1, 19, -1.000000); highs.changeCoeff(2, 20, -1.000000); highs.changeCoeff(3, 21, -1.000000); highs.changeCoeff(4, 22, -1.000000); highs.changeCoeff(5, 23, -1.000000); highs.changeCoeff(6, 24, -1.000000); highs.changeCoeff(7, 25, -1.000000); highs.changeCoeff(8, 26, -1.000000); highs.changeColCost(0, 0.000000); highs.changeColCost(1, 0.000000); highs.changeColCost(2, 0.000000); highs.changeColCost(3, 0.000000); highs.changeColCost(4, 0.000000); highs.changeColCost(5, 0.000000); highs.changeColCost(6, 0.000000); highs.changeColCost(7, 0.000000); highs.changeColCost(8, 0.000000); highs.changeColCost(9, 10.000000); highs.changeColCost(10, 10.000000); highs.changeColCost(11, 10.000000); highs.changeColCost(12, 10.000000); highs.changeColCost(13, 10.000000); highs.changeColCost(14, 10.000000); highs.changeColCost(15, 10.000000); highs.changeColCost(16, 10.000000); highs.changeColCost(17, 10.000000); highs.changeColCost(18, 10.000000); highs.changeColCost(19, 10.000000); highs.changeColCost(20, 10.000000); highs.changeColCost(21, 10.000000); highs.changeColCost(22, 10.000000); highs.changeColCost(23, 10.000000); highs.changeColCost(24, 10.000000); highs.changeColCost(25, 10.000000); highs.changeColCost(26, 10.000000); } const double require_optimal_objective = 4.9726034324e+03; solve(highs, "on", "simplex", require_model_status, require_optimal_objective); } void mpsGalenet(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("mpsGalenet", dev_run); const HighsModelStatus require_model_status = HighsModelStatus::kInfeasible; std::string model = "galenet"; std::string model_file; model_file = std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps"; REQUIRE(highs.readModel(model_file) == HighsStatus::kOk); solve(highs, "on", "simplex", require_model_status); solve(highs, "off", "simplex", require_model_status); solve(highs, "on", "ipm", require_model_status); solve(highs, "off", "ipm", require_model_status); } void primalDualInfeasible1(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("primalDualInfeasible1", dev_run); // This LP is both primal and dual infeasible - from Wikipedia // // IPX fails to identify primal infeasibility HighsLp lp; HighsModelStatus require_model_status; special_lps.primalDualInfeasible1Lp(lp, require_model_status); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve doesn't reduce the LP, but does identify primal infeasibility solve(highs, "on", "simplex", HighsModelStatus::kInfeasible); solve(highs, "off", "simplex", require_model_status); solve(highs, "off", "ipm", require_model_status); } void primalDualInfeasible2(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("primalDualInfeasible2", dev_run); // This LP is both primal and dual infeasible - scip-lpi4.mps from SCIP LPI // unit test (test4). IPX fails to identify primal infeasibility HighsLp lp; HighsModelStatus require_model_status; special_lps.primalDualInfeasible2Lp(lp, require_model_status); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve doesn't reduce the LP, but does identify primal infeasibility solve(highs, "on", "simplex", HighsModelStatus::kInfeasible); // ERROR without presolve because primal simplex solver not available // solve(highs, "off", "simplex", require_model_status); // solve(highs, "on", "ipm", require_model_status); } void primalDualInfeasible3(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("primalDualInfeasible3", dev_run); // This LP is both primal and dual infeasible, but looks primal // unbounded. An example of why simple primal unboundedness can't be // claimed HighsLp lp; HighsModelStatus require_model_status; special_lps.primalDualInfeasible3Lp(lp, require_model_status); REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // Presolve doesn't reduce the LP, but does identify primal infeasibility solve(highs, "on", "simplex", require_model_status); solve(highs, "off", "simplex", require_model_status); solve(highs, "off", "ipm", require_model_status); } void mpsUnbounded(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("mpsUnbounded", dev_run); // As a maximization, adlittle is unbounded, but a bug in hsol [due // to jumping to phase 2 if optimal in phase 1 after clean-up // yielded no dual infeasiblities despite the phase 1 objective // being negative] resulted in the problem being declared infeasible // // Resulted in fixes being added to hsol dual const HighsModelStatus require_model_status = HighsModelStatus::kUnbounded; // Unit test fails for IPX with adlittle solved as maximization std::string model = "adlittle"; std::string model_file; model_file = std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps"; REQUIRE(highs.readModel(model_file) == HighsStatus::kOk); REQUIRE(highs.changeObjectiveSense(ObjSense::kMaximize) == HighsStatus::kOk); solve(highs, "on", "simplex", require_model_status); solve(highs, "off", "simplex", require_model_status); // solve(highs, "on", "ipm", require_model_status); // solve(highs, "off", "ipm", require_model_status); } void mpsGas11(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("mpsGas11", dev_run); // Lots of trouble is caused by gas11 const HighsModelStatus require_model_status = HighsModelStatus::kUnbounded; std::string model = "gas11"; std::string model_file; model_file = std::string(HIGHS_DIR) + "/check/instances/" + model + ".mps"; REQUIRE(highs.readModel(model_file) == HighsStatus::kWarning); solve(highs, "on", "simplex", require_model_status); solve(highs, "off", "simplex", require_model_status); solve(highs, "on", "ipm", require_model_status); solve(highs, "off", "ipm", require_model_status); } void almostNotUnbounded(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("almostNotUnbounded", dev_run); // This problem tests how well HiGHS handles // near-unboundedness. None of the LPs is reduced by presolve // // No HighsLp lp; const HighsModelStatus require_model_status0 = HighsModelStatus::kUnbounded; const HighsModelStatus require_model_status1 = HighsModelStatus::kOptimal; const HighsModelStatus require_model_status2 = HighsModelStatus::kOptimal; const double optimal_objective1 = -1; const double optimal_objective2 = -3; // With epsilon = 1e-7 hsol declares optimality as the primal // infeasibility in phase 2 that would lead to unboundedness is // sufficiently small // // With epsilon = 1e-6 hsol goes to phase 2 before detecting // unboundedness, because the problem with perturbed costs is dual // feasible. // // With epsilon = 1e-5 hsol identifies unboundedness in phase 1 // because the problem with perturbed costs is not dual feasible. double epsilon = 1e-6; lp.num_col_ = 2; lp.num_row_ = 3; lp.col_cost_ = {-1, 1 - epsilon}; lp.col_lower_ = {0, 0}; lp.col_upper_ = {inf, inf}; lp.row_lower_ = {-1 + epsilon, -1, 3}; lp.row_upper_ = {inf, inf, inf}; lp.a_matrix_.start_ = {0, 3, 6}; lp.a_matrix_.index_ = {0, 1, 2, 0, 1, 2}; lp.a_matrix_.value_ = {1 + epsilon, -1, 1, -1, 1, 1}; lp.a_matrix_.format_ = MatrixFormat::kColwise; // LP is feasible on [1+alpha, alpha] with objective // -1-epsilon*alpha so unbounded REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // REQUIRE(highs.writeModel("epsilon_unbounded.mps") == // HighsStatus::WARNING); solve(highs, "off", "simplex", require_model_status0); solve(highs, "off", "ipm", require_model_status0); // LP is feasible on [1+alpha, alpha] with objective -1 so optimal, // but has open set of optimal solutions lp.col_cost_ = {-1, 1}; REQUIRE(highs.passModel(lp) == HighsStatus::kOk); solve(highs, "off", "simplex", require_model_status1, optimal_objective1); special_lps.reportSolution(highs, dev_run); solve(highs, "off", "ipm", require_model_status1, optimal_objective1); // LP has bounded feasible region with optimal solution // [1+2/epsilon, 2/epsilon] and objective // value -3 lp.col_cost_[1] = 1 - epsilon; lp.row_lower_[0] = -1 - epsilon; lp.a_matrix_.value_[0] = 1 - epsilon; REQUIRE(highs.passModel(lp) == HighsStatus::kOk); solve(highs, "off", "simplex", require_model_status2, optimal_objective2); special_lps.reportSolution(highs, dev_run); solve(highs, "off", "ipm", require_model_status2, optimal_objective2); } void singularStartingBasis(Highs& highs) { SpecialLps special_lps; special_lps.reportLpName("singularStartingBasis", dev_run); // This problem tests how well HiGHS handles a singular initial // basis HighsLp lp; const HighsModelStatus require_model_status = HighsModelStatus::kOptimal; const double optimal_objective = -3; lp.num_col_ = 3; lp.num_row_ = 2; lp.col_cost_ = {-3, -2, -1}; lp.col_lower_ = {0, 0, 0}; lp.col_upper_ = {inf, inf, inf}; lp.row_lower_ = {-inf, -inf}; lp.row_upper_ = {3, 2}; lp.a_matrix_.start_ = {0, 2, 4, 6}; lp.a_matrix_.index_ = {0, 1, 0, 1, 0, 1}; lp.a_matrix_.value_ = {1, 2, 2, 4, 1, 3}; lp.a_matrix_.format_ = MatrixFormat::kColwise; REQUIRE(highs.passModel(lp) == HighsStatus::kOk); if (dev_run) { REQUIRE(highs.setOptionValue("log_dev_level", kHighsLogDevLevelDetailed) == HighsStatus::kOk); } REQUIRE(highs.setOptionValue("highs_debug_level", 3) == HighsStatus::kOk); HighsBasis basis; basis.col_status.resize(lp.num_col_); basis.row_status.resize(lp.num_row_); basis.col_status[0] = HighsBasisStatus::kBasic; basis.col_status[1] = HighsBasisStatus::kBasic; basis.col_status[2] = HighsBasisStatus::kLower; basis.row_status[0] = HighsBasisStatus::kUpper; basis.row_status[1] = HighsBasisStatus::kUpper; basis.valid = true; REQUIRE(highs.setBasis(basis) == HighsStatus::kOk); REQUIRE(highs.run() == HighsStatus::kOk); const HighsInfo& info = highs.getInfo(); REQUIRE(highs.getModelStatus() == require_model_status); if (require_model_status == HighsModelStatus::kOptimal) REQUIRE(special_lps.objectiveOk(info.objective_function_value, optimal_objective, dev_run)); REQUIRE(highs.resetOptions() == HighsStatus::kOk); special_lps.reportSolution(highs, dev_run); } void unconstrained(Highs& highs) { HighsLp lp; lp.num_col_ = 2; lp.num_row_ = 0; lp.col_cost_ = {1, -1}; lp.col_lower_ = {4, 2}; lp.col_upper_ = {inf, 3}; lp.a_matrix_.start_ = {0, 0, 0}; lp.a_matrix_.format_ = MatrixFormat::kColwise; REQUIRE(highs.passModel(lp) == HighsStatus::kOk); // No need to turn off presolve, since unconstrained LPs are // automatically solved directly // // REQUIRE(highs.setOptionValue("presolve", "off") == HighsStatus::kOk); REQUIRE(highs.run() == HighsStatus::kOk); REQUIRE(highs.getModelStatus() == HighsModelStatus::kOptimal); REQUIRE(highs.getObjectiveValue() == 1); REQUIRE(highs.changeObjectiveSense(ObjSense::kMaximize) == HighsStatus::kOk); REQUIRE(highs.setBasis() == HighsStatus::kOk); REQUIRE(highs.run() == HighsStatus::kOk); REQUIRE(highs.getModelStatus() == HighsModelStatus::kUnbounded); REQUIRE(highs.changeColCost(0, -1) == HighsStatus::kOk); REQUIRE(highs.setBasis() == HighsStatus::kOk); REQUIRE(highs.run() == HighsStatus::kOk); REQUIRE(highs.getModelStatus() == HighsModelStatus::kOptimal); REQUIRE(highs.getObjectiveValue() == -6); REQUIRE(highs.changeColBounds(0, 4, 1) == HighsStatus::kOk); REQUIRE(highs.setBasis() == HighsStatus::kOk); REQUIRE(highs.run() == HighsStatus::kOk); REQUIRE(highs.getModelStatus() == HighsModelStatus::kInfeasible); } void smallValue(Highs& highs) { REQUIRE(highs.addCol(0, 0, kHighsInf, 0, nullptr, nullptr) == HighsStatus::kOk); const HighsInt index = 0; const double value = 1e-9; REQUIRE(highs.addRow(-kHighsInf, 1, 1, &index, &value) == HighsStatus::kWarning); REQUIRE(highs.run() == HighsStatus::kOk); } TEST_CASE("LP-distillation", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); distillation(highs); } TEST_CASE("LP-272", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue272(highs); } TEST_CASE("LP-280", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue280(highs); } TEST_CASE("LP-282", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue282(highs); } TEST_CASE("LP-285", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue285(highs); } TEST_CASE("LP-295", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue295(highs); } TEST_CASE("LP-306", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue306(highs); } TEST_CASE("LP-316", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue316(highs); } TEST_CASE("LP-425", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue425(highs); } TEST_CASE("LP-669", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); issue669(highs); } TEST_CASE("LP-galenet", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); mpsGalenet(highs); } TEST_CASE("LP-primal-dual-infeasible1", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); primalDualInfeasible1(highs); } TEST_CASE("LP-primal-dual-infeasible2", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); primalDualInfeasible2(highs); } TEST_CASE("LP-primal-dual-infeasible3", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); primalDualInfeasible3(highs); } TEST_CASE("LP-unbounded", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); mpsUnbounded(highs); } // for some reason hangs on IPX with presolve off: add to doctest TEST_CASE("LP-gas11", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); mpsGas11(highs); } TEST_CASE("LP-almost-not-unbounded", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); almostNotUnbounded(highs); } TEST_CASE("LP-singular-starting-basis", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); singularStartingBasis(highs); } TEST_CASE("LP-unconstrained", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); unconstrained(highs); } TEST_CASE("LP-small-value", "[highs_test_special_lps]") { Highs highs; if (!dev_run) highs.setOptionValue("output_flag", false); smallValue(highs); }