* @brief Utilities for tests with special LPs
*/
#ifndef SIMPLEX_SPECIALPS_H_
#define SIMPLEX_SPECIALPS_H_
#include <vector>
#include "lp_data/HConst.h"
#include "lp_data/HighsLp.h"
const double inf = kHighsInf;
class SpecialLps {
public:
void issue272Lp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
lp.model_name_ = "issue272";
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {3, 2};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {inf, inf};
lp.row_lower_ = {-inf, -inf};
lp.row_upper_ = {23, 10};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {3, 5, 6, 2};
lp.sense_ = ObjSense::kMaximize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
optimal_objective = 8.83333333333333;
}
void issue280Lp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
lp.model_name_ = "issue280";
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {-1, 1};
lp.col_lower_ = {1, 2};
lp.col_upper_ = {1, 2};
lp.row_lower_ = {-inf, 2};
lp.row_upper_ = {1, 2};
lp.a_matrix_.start_ = {0, 1, 2};
lp.a_matrix_.index_ = {0, 1};
lp.a_matrix_.value_ = {1, 1};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
optimal_objective = 1;
}
void issue282Lp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
lp.model_name_ = "issue282";
lp.num_col_ = 2;
lp.num_row_ = 3;
lp.col_cost_ = {-3, -2};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {inf, inf};
lp.row_lower_ = {-inf, -inf, -inf};
lp.row_upper_ = {10, 8, 4};
lp.a_matrix_.start_ = {0, 3, 5};
lp.a_matrix_.index_ = {0, 1, 2, 0, 1};
lp.a_matrix_.value_ = {2, 1, 1, 1, 1};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
optimal_objective = -18;
}
void issue285Lp(HighsLp& lp, HighsModelStatus& require_model_status) {
lp.model_name_ = "issue285";
lp.num_col_ = 2;
lp.num_row_ = 3;
lp.col_cost_ = {-4, 1};
lp.col_lower_ = {2, 0};
lp.col_upper_ = {2, inf};
lp.row_lower_ = {-inf, -inf, -inf};
lp.row_upper_ = {14, 0, 3};
lp.a_matrix_.start_ = {0, 2, 5};
lp.a_matrix_.index_ = {0, 2, 0, 1, 2};
lp.a_matrix_.value_ = {7, 2, -2, 1, -2};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kInfeasible;
}
void issue295Lp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
lp.model_name_ = "issue295";
lp.num_col_ = 5;
lp.num_row_ = 2;
lp.col_cost_ = {0, 0, 0, 1, -1};
lp.col_lower_ = {-inf, -inf, -inf, -1, -1};
lp.col_upper_ = {inf, inf, inf, 1, 1};
lp.row_lower_ = {-inf, -inf};
lp.row_upper_ = {2, -2};
lp.a_matrix_.start_ = {0, 1, 2, 2, 2, 2};
lp.a_matrix_.index_ = {0, 1};
lp.a_matrix_.value_ = {1, 1};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
optimal_objective = -2;
}
void issue306Lp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
lp.model_name_ = "issue30";
lp.num_col_ = 10;
lp.num_row_ = 6;
lp.col_cost_ = {-1.64, 0.7, 1.8, -1.06, -1.16,
0.26, 2.13, 1.53, 0.66, 0.28};
lp.col_lower_ = {-0.84, -0.97, 0.34, 0.4, -0.33,
-0.74, 0.47, 0.09, -1.45, -0.73};
lp.col_upper_ = {0.37, 0.02, 2.86, 0.86, 1.18,
0.5, 1.76, 0.17, 0.32, -0.15};
lp.row_lower_ = {0.9626, -1e+200, -1e+200, -1e+200, -1e+200, -1e+200};
lp.row_upper_ = {0.9626, 0.615, 0, 0.172, -0.869, -0.022};
lp.a_matrix_.start_ = {0, 0, 1, 2, 5, 5, 6, 7, 9, 10, 12};
lp.a_matrix_.index_ = {4, 4, 0, 1, 3, 0, 4, 1, 5, 0, 1, 4};
lp.a_matrix_.value_ = {-1.22, -0.25, 0.93, 1.18, 0.43, 0.65,
-2.06, -0.2, -0.25, 0.83, -0.22, 1.37};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
optimal_objective = -1.191;
}
void issue425Lp(HighsLp& lp, HighsModelStatus& require_model_status) {
lp.model_name_ = "issue425";
lp.num_col_ = 4;
lp.num_row_ = 4;
lp.col_cost_ = {1, 1, 1, 2};
lp.col_lower_ = {0, 0, 0, 0};
lp.col_upper_ = {inf, inf, inf, inf};
lp.row_lower_ = {1, 2, 2, 4};
lp.row_upper_ = {1, 2, 2, 4};
lp.a_matrix_.start_ = {0, 3, 5, 6, 7};
lp.a_matrix_.index_ = {0, 2, 3, 1, 3, 3, 3};
lp.a_matrix_.value_ = {1, 1, 1, 2, 1, 1, 1};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kInfeasible;
}
void issue669Lp(HighsLp& lp, HighsModelStatus& require_model_status) {
lp.model_name_ = "issue669";
lp.num_col_ = 27;
lp.num_row_ = 9;
vector<double> zero_vector_col;
vector<double> zero_vector_row;
vector<HighsInt> zero_vector_start;
for (int iCol = 0; iCol < lp.num_col_; iCol++) zero_vector_col.push_back(0);
for (int iRow = 0; iRow < lp.num_row_; iRow++) zero_vector_row.push_back(0);
lp.col_cost_ = zero_vector_col;
lp.col_lower_ = zero_vector_col;
lp.col_upper_ = zero_vector_col;
lp.row_lower_ = zero_vector_row;
lp.row_upper_ = zero_vector_row;
for (int iCol = 0; iCol < lp.num_col_; iCol++)
lp.a_matrix_.start_.push_back(0);
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
}
void primalDualInfeasible1Lp(HighsLp& lp,
HighsModelStatus& require_model_status) {
lp.model_name_ = "primalDualInfeasible1";
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {2, -1};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {inf, inf};
lp.row_lower_ = {-inf, -inf};
lp.row_upper_ = {1, -2};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {1, -1, -1, 1};
lp.sense_ = ObjSense::kMaximize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kInfeasible;
}
void primalDualInfeasible2Lp(HighsLp& lp,
HighsModelStatus& require_model_status) {
lp.model_name_ = "primalDualInfeasible2";
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {1, 1};
lp.col_lower_ = {-inf, -inf};
lp.col_upper_ = {inf, inf};
lp.row_lower_ = {-inf, -inf};
lp.row_upper_ = {0, -1};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {1, -1, -1, 1};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kInfeasible;
}
void primalDualInfeasible3Lp(HighsLp& lp,
HighsModelStatus& require_model_status) {
lp.model_name_ = "primalDualInfeasible3";
lp.num_col_ = 3;
lp.num_row_ = 2;
lp.col_cost_ = {-1, 0, 0};
lp.col_lower_ = {0, 0, 0};
lp.col_upper_ = {inf, inf, inf};
lp.row_lower_ = {-inf, -inf};
lp.row_upper_ = {1, -2};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {1, 2, 1, 2};
lp.a_matrix_.value_ = {1, 1, 1, -1};
lp.a_matrix_.format_ = MatrixFormat::kRowwise;
require_model_status = HighsModelStatus::kInfeasible;
}
void scipLpi2Lp(HighsLp& lp, HighsModelStatus& require_model_status) {
lp.model_name_ = "scipLpi2";
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {3, 1};
lp.col_lower_ = {-inf, -inf};
lp.col_upper_ = {inf, inf};
lp.row_lower_ = {-inf, -inf};
lp.row_upper_ = {10, 15};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {2, 1, 1, 3};
lp.sense_ = ObjSense::kMaximize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kUnbounded;
}
void scipLpi3Lp(HighsLp& lp, HighsModelStatus& require_model_status) {
lp.model_name_ = "scipLpi3";
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {10, 15};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {inf, inf};
lp.row_lower_ = {3, 1};
lp.row_upper_ = {3, 1};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {2, 1, 1, 3};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kInfeasible;
}
void distillationLp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
lp.model_name_ = "distillation";
lp.num_col_ = 2;
lp.num_row_ = 3;
lp.col_cost_ = {8, 10};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {inf, inf};
lp.row_lower_ = {7, 12, 6};
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_ = {2, 3, 2, 2, 4, 1};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
optimal_objective = 31.2;
}
void distillationMip(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
distillationLp(lp, require_model_status, optimal_objective);
lp.integrality_ = {HighsVarType::kInteger, HighsVarType::kInteger};
optimal_objective = 32.0;
}
void blendingLp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
lp.model_name_ = "blending";
lp.num_col_ = 2;
lp.num_row_ = 2;
lp.col_cost_ = {-8, -10};
lp.col_lower_ = {0, 0};
lp.col_upper_ = {inf, inf};
lp.row_lower_ = {-inf, -inf};
lp.row_upper_ = {120, 210};
lp.a_matrix_.start_ = {0, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {0.3, 0.7, 0.5, 0.5};
lp.sense_ = ObjSense::kMinimize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
optimal_objective = -2850;
}
void blendingMaxLp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
blendingLp(lp, require_model_status, optimal_objective);
lp.model_name_ = "blendingMax";
for (HighsInt iCol = 0; iCol < lp.num_col_; iCol++)
lp.col_cost_[iCol] = -lp.col_cost_[iCol];
lp.sense_ = ObjSense::kMaximize;
optimal_objective = -optimal_objective;
}
void ThreeDLp(HighsLp& lp, HighsModelStatus& require_model_status,
double& optimal_objective) {
lp.model_name_ = "3-d LP";
lp.num_col_ = 3;
lp.num_row_ = 2;
lp.col_cost_ = {1, 2, 3};
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, 1, 2, 4};
lp.a_matrix_.index_ = {0, 1, 0, 1};
lp.a_matrix_.value_ = {1, 1, 2, 2};
lp.sense_ = ObjSense::kMaximize;
lp.offset_ = 0;
lp.a_matrix_.format_ = MatrixFormat::kColwise;
require_model_status = HighsModelStatus::kOptimal;
optimal_objective = 7;
}
void reportIssue(const HighsInt issue, const bool dev_run = false) {
if (dev_run)
printf("\n *************\n * Issue %3" HIGHSINT_FORMAT
" *\n *************\n",
issue);
}
void reportLpName(const std::string lp_name, const bool dev_run = false) {
if (dev_run) {
HighsInt lp_name_length = lp_name.length();
printf("\n **");
for (HighsInt i = 0; i < lp_name_length; i++) printf("*");
printf("**\n * %s *\n **", lp_name.c_str());
for (HighsInt i = 0; i < lp_name_length; i++) printf("*");
printf("**\n");
}
}
bool objectiveOk(const double optimal_objective,
const double require_optimal_objective,
const bool dev_run = false) {
double error = std::fabs(optimal_objective - require_optimal_objective) /
std::max(1.0, std::fabs(require_optimal_objective));
bool error_ok = error < 1e-10;
if (!error_ok && dev_run)
printf("Objective is %g but require %g (error %g)\n", optimal_objective,
require_optimal_objective, error);
return error_ok;
}
void reportSolution(Highs& highs, const bool dev_run = false) {
if (!dev_run) return;
const HighsInfo& info = highs.getInfo();
if (info.primal_solution_status == kSolutionStatusFeasible) {
const HighsSolution& solution = highs.getSolution();
printf("Solution\n");
printf("Col Value Dual\n");
for (HighsInt iCol = 0; iCol < highs.getLp().num_col_; iCol++)
printf("%3" HIGHSINT_FORMAT " %11.4g %11.4g\n", iCol,
solution.col_value[iCol], solution.col_dual[iCol]);
printf("Row Value Dual\n");
for (HighsInt iRow = 0; iRow < highs.getLp().num_row_; iRow++)
printf("%3" HIGHSINT_FORMAT " %11.4g %11.4g\n", iRow,
solution.row_value[iRow], solution.row_dual[iRow]);
} else {
printf("info.primal_solution_status = %" HIGHSINT_FORMAT "\n",
info.primal_solution_status);
}
}
};
#endif