1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
#include "HCheckConfig.h"
#include "Highs.h"
#include "catch.hpp"
const double inf = kHighsInf;
const bool dev_run = false;
const double double_equal_tolerance = 1e-5;
TEST_CASE("FreezeBasis", "[highs_test_freeze_basis]") {
std::string filename;
filename = std::string(HIGHS_DIR) + "/check/instances/avgas.mps";
Highs highs;
if (!dev_run) highs.setOptionValue("output_flag", false);
highs.readModel(filename);
const HighsLp& lp = highs.getLp();
const HighsInt num_col = lp.num_col_;
const HighsInt num_row = lp.num_row_;
const HighsInt from_col = 0;
const HighsInt to_col = num_col - 1;
const HighsInfo& info = highs.getInfo();
vector<double> original_col_lower = lp.col_lower_;
vector<double> original_col_upper = lp.col_upper_;
// Get the continuous solution and iteration count from a logical basis
highs.run();
HighsInt continuous_iteration_count = info.simplex_iteration_count;
double continuous_objective = info.objective_function_value;
// Get the integer solution to provide bound tightenings
vector<HighsVarType> integrality;
integrality.assign(num_col, HighsVarType::kInteger);
highs.changeColsIntegrality(from_col, to_col, integrality.data());
highs.setOptionValue("output_flag", false);
highs.run();
if (dev_run) highs.setOptionValue("output_flag", true);
vector<double> integer_solution = highs.getSolution().col_value;
vector<double> local_col_lower;
vector<double> local_col_upper;
// Now restore the original integrality and set an explicit logical
// basis to force reinversion
integrality.assign(num_col, HighsVarType::kContinuous);
highs.changeColsIntegrality(from_col, to_col, integrality.data());
HighsBasis basis;
for (HighsInt iCol = 0; iCol < num_col; iCol++)
basis.col_status.push_back(HighsBasisStatus::kLower);
for (HighsInt iRow = 0; iRow < num_row; iRow++)
basis.row_status.push_back(HighsBasisStatus::kBasic);
highs.setBasis(basis);
HighsInt frozen_basis_id0;
// Cannot freeze a basis when there's no INVERT
REQUIRE(highs.freezeBasis(frozen_basis_id0) == HighsStatus::kError);
// Get the basic variables to force INVERT with a logical basis
vector<HighsInt> basic_variables;
basic_variables.resize(lp.num_row_);
highs.getBasicVariables(basic_variables.data());
// Can freeze a basis now!
REQUIRE(highs.freezeBasis(frozen_basis_id0) == HighsStatus::kOk);
if (dev_run) {
highs.setOptionValue("output_flag", true);
highs.setOptionValue("log_dev_level", 2);
highs.setOptionValue("highs_debug_level", 3);
}
highs.run();
// highs.setOptionValue("output_flag", false);
// Now freeze the current basis and add the integer solution as lower bounds
HighsInt frozen_basis_id1;
REQUIRE(highs.freezeBasis(frozen_basis_id1) == HighsStatus::kOk);
if (dev_run) printf("\nSolving with bounds (integer solution, upper)\n");
local_col_lower = integer_solution;
local_col_upper = original_col_upper;
highs.changeColsBounds(from_col, to_col, local_col_lower.data(),
local_col_upper.data());
if (dev_run) highs.setOptionValue("output_flag", true);
highs.run();
// highs.setOptionValue("output_flag", false);
double semi_continuous_objective = info.objective_function_value;
// Now freeze the current basis and add the integer solution as upper bounds
HighsInt frozen_basis_id2;
REQUIRE(highs.freezeBasis(frozen_basis_id2) == HighsStatus::kOk);
if (dev_run)
printf("\nSolving with bounds (integer solution, integer solution)\n");
local_col_lower = integer_solution;
local_col_upper = integer_solution;
highs.changeColsBounds(from_col, to_col, local_col_lower.data(),
local_col_upper.data());
if (dev_run) highs.setOptionValue("output_flag", true);
highs.run();
// highs.setOptionValue("output_flag", false);
// Now test unfreeze
//
// Restore the upper bounds and unfreeze frozen_basis_id2 (semi-continuous
// optimal basis)
if (dev_run)
printf(
"\nSolving with bounds (integer solution, upper) after unfreezing "
"basis %d\n",
(int)frozen_basis_id2);
if (dev_run) printf("Change column bounds to (integer solution, upper)\n");
local_col_lower = integer_solution;
local_col_upper = original_col_upper;
highs.changeColsBounds(from_col, to_col, local_col_lower.data(),
local_col_upper.data());
if (dev_run) printf("Unfreeze basis %d\n", (int)frozen_basis_id2);
REQUIRE(highs.unfreezeBasis(frozen_basis_id2) == HighsStatus::kOk);
// Solving the LP should require no iterations
if (dev_run) highs.setOptionValue("output_flag", true);
highs.run();
// highs.setOptionValue("output_flag", false);
REQUIRE(info.simplex_iteration_count == 0);
double dl_objective =
fabs(semi_continuous_objective - info.objective_function_value);
REQUIRE(dl_objective < double_equal_tolerance);
REQUIRE(info.simplex_iteration_count == 0);
//
// Restore the lower bounds and unfreeze frozen_basis_id1 (continuous optimal
// basis)
if (dev_run)
printf("\nSolving with bounds (lower, upper) after unfreezing basis %d\n",
(int)frozen_basis_id1);
if (dev_run) printf("Change column bounds to (lower, upper)\n");
local_col_lower = original_col_lower;
local_col_upper = original_col_upper;
highs.changeColsBounds(from_col, to_col, local_col_lower.data(),
local_col_upper.data());
if (dev_run) printf("Unfreeze basis %d\n", (int)frozen_basis_id1);
REQUIRE(highs.unfreezeBasis(frozen_basis_id1) == HighsStatus::kOk);
// Solving the LP should require no iterations
if (dev_run) highs.setOptionValue("output_flag", true);
highs.run();
// highs.setOptionValue("output_flag", false);
dl_objective = fabs(continuous_objective - info.objective_function_value);
REQUIRE(dl_objective < double_equal_tolerance);
REQUIRE(info.simplex_iteration_count == 0);
//
// Unfreeze frozen_basis_id0
if (dev_run)
printf("\nSolving with bounds (lower, upper) after unfreezing basis %d\n",
(int)frozen_basis_id0);
if (dev_run) printf("Unfreeze basis %d\n", (int)frozen_basis_id0);
REQUIRE(highs.unfreezeBasis(frozen_basis_id0) == HighsStatus::kOk);
// Solving the LP should require the same number of iterations as before
if (dev_run) highs.setOptionValue("output_flag", true);
highs.run();
// highs.setOptionValue("output_flag", false);
dl_objective = fabs(continuous_objective - info.objective_function_value);
REQUIRE(dl_objective < double_equal_tolerance);
REQUIRE(info.simplex_iteration_count == continuous_iteration_count);
REQUIRE(highs.frozenBasisAllDataClear() == HighsStatus::kOk);
}
|