#include <cmath>
#include "HCheckConfig.h"
#include "Highs.h"
#include "catch.hpp"
const bool dev_run = false;
const double inf = kHighsInf;
TEST_CASE("test-analytic-centre", "[highs_ipm]") {
std::string model = "afiro.mps";
std::string filename = std::string(HIGHS_DIR) + "/check/instances/" + model;
Highs highs;
highs.setOptionValue("output_flag", dev_run);
highs.readModel(filename);
HighsLp lp = highs.getLp();
lp.col_cost_.assign(lp.num_col_, 0);
highs.passModel(lp);
highs.setOptionValue("run_centring", true);
highs.setOptionValue("ipm_optimality_tolerance", 1e-2);
HighsStatus run_status = highs.run();
REQUIRE(run_status == HighsStatus::kOk);
highs.resetGlobalScheduler(true);
}
TEST_CASE("test-analytic-centre-infeasible", "[highs_ipm]") {
Highs highs;
highs.setOptionValue("output_flag", dev_run);
HighsLp lp;
lp.num_col_ = 2;
lp.num_row_ = 1;
lp.col_cost_.assign(lp.num_col_, 0);
lp.col_lower_.assign(lp.num_col_, 0);
lp.col_upper_.assign(lp.num_col_, inf);
lp.row_lower_ = {-inf};
lp.row_upper_ = {-1};
lp.a_matrix_.start_ = {0, 1, 2};
lp.a_matrix_.index_ = {0, 0};
lp.a_matrix_.value_ = {1, 1};
highs.passModel(lp);
highs.setOptionValue("presolve", kHighsOffString);
highs.setOptionValue("run_centring", true);
highs.setOptionValue("ipm_optimality_tolerance", 1e-2);
HighsStatus run_status = highs.run();
REQUIRE(run_status == HighsStatus::kOk);
REQUIRE(highs.getModelStatus() == HighsModelStatus::kInfeasible);
highs.resetGlobalScheduler(true);
}
TEST_CASE("test-analytic-centre-box", "[highs_ipm]") {
Highs highs;
highs.setOptionValue("output_flag", dev_run);
const HighsInt dim = 4;
HighsLp lp;
lp.num_col_ = dim;
lp.col_cost_.assign(dim, 0);
lp.col_lower_.assign(dim, -1);
lp.col_upper_.assign(dim, 1);
highs.passModel(lp);
std::vector<HighsInt> index = {0, 1};
std::vector<double> value = {1, 1};
const double root2 = std::sqrt(2.0);
highs.addRow(-root2, root2, 2, index.data(), value.data());
value[1] = -1;
highs.addRow(-root2, root2, 2, index.data(), value.data());
highs.setOptionValue("run_centring", true);
highs.setOptionValue("presolve", kHighsOffString);
highs.setOptionValue("ipm_optimality_tolerance", 1e-2);
HighsStatus run_status = highs.run();
const HighsSolution& solution = highs.getSolution();
double solution_norm = 0;
for (HighsInt ix = 0; ix < dim; ix++) {
if (dev_run)
printf("Analytic centre solution %d is %g\n", int(ix),
solution.col_value[ix]);
solution_norm += std::fabs(solution.col_value[ix]);
}
REQUIRE(solution_norm < 1e-6);
if (dev_run) printf("Analytic centre solution norm is %g\n", solution_norm);
highs.resetGlobalScheduler(true);
}
TEST_CASE("test-1966", "[highs_ipm]") {
Highs highs;
highs.setOptionValue("output_flag", dev_run);
const HighsInfo& info = highs.getInfo();
HighsLp lp;
lp.sense_ = ObjSense::kMaximize;
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {2, -1};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {kHighsInf, kHighsInf};
lp.row_lower_ = {-kHighsInf, 2};
lp.row_upper_ = {1, kHighsInf};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {1, -1, 1, -1};
lp.a_matrix_.format_ = MatrixFormat::kRowwise;
highs.passModel(lp);
highs.setOptionValue("presolve", kHighsOffString);
HighsModelStatus require_model_status = HighsModelStatus::kNotset;
int to_k = 2;
#ifdef HIPO
to_k = 3;
#endif
for (int k = 0; k < to_k; k++) {
if (k == 0) {
highs.setOptionValue("solver", kPdlpString);
if (dev_run) printf("Solving with PDLP\n");
require_model_status = HighsModelStatus::kUnboundedOrInfeasible;
} else if (k == 1) {
highs.setOptionValue("solver", kIpxString);
if (dev_run) printf("Solving with IPX\n");
require_model_status = HighsModelStatus::kInfeasible;
} else {
highs.setOptionValue("solver", kHipoString);
if (dev_run) printf("Solving with HiPO\n");
require_model_status = HighsModelStatus::kInfeasible;
}
highs.run();
REQUIRE(info.primal_solution_status != kSolutionStatusFeasible);
REQUIRE(info.dual_solution_status != kSolutionStatusFeasible);
REQUIRE(highs.getModelStatus() == require_model_status);
if (dev_run) {
printf("Primal solution status = %d\n", int(info.primal_solution_status));
printf("Dual solution status = %d\n", int(info.dual_solution_status));
printf("Num primal infeasibilities = %d\n",
int(info.num_primal_infeasibilities));
printf("Max primal infeasibility = %g\n",
info.max_primal_infeasibility);
printf("Sum primal infeasibilities = %g\n",
info.sum_primal_infeasibilities);
printf("Num dual infeasibilities = %d\n",
int(info.num_dual_infeasibilities));
printf("Max dual infeasibility = %g\n",
info.max_dual_infeasibility);
printf("Sum dual infeasibilities = %g\n",
info.sum_dual_infeasibilities);
printf("Num primal residual errors = %d\n",
int(info.num_primal_residual_errors));
printf("Max primal residual error = %g\n",
info.max_primal_residual_error);
printf("Num dual residual errors = %d\n",
int(info.num_dual_residual_errors));
printf("Max dual residual error = %g\n",
info.max_dual_residual_error);
printf("Primal-dual objective error = %g\n",
info.primal_dual_objective_error);
}
highs.clearSolver();
}
highs.resetGlobalScheduler(true);
}
TEST_CASE("test-2087", "[highs_ipm]") {
Highs h;
h.setOptionValue("output_flag", dev_run);
std::string model = "shell.mps";
std::string filename = std::string(HIGHS_DIR) + "/check/instances/" + model;
h.readModel(filename);
h.setOptionValue("solver", kIpmString);
h.run();
const HighsInt first_ipm_iteration_count = h.getInfo().ipm_iteration_count;
h.run();
REQUIRE(first_ipm_iteration_count == h.getInfo().ipm_iteration_count);
h.resetGlobalScheduler(true);
}
TEST_CASE("test-2527", "[highs_ipm]") {
std::string filename =
std::string(HIGHS_DIR) + "/check/instances/primal1.mps";
Highs h;
h.setOptionValue("output_flag", dev_run);
REQUIRE(h.readModel(filename) == HighsStatus::kOk);
HighsLp lp = h.getLp();
lp.col_cost_.assign(lp.num_col_, 0);
REQUIRE(h.passModel(lp) == HighsStatus::kOk);
h.setOptionValue("solver", kIpmString);
h.setOptionValue("presolve", kHighsOffString);
REQUIRE(h.run() == HighsStatus::kOk);
h.resetGlobalScheduler(true);
}