File: TestFreezeBasis.cpp

package info (click to toggle)
scipy 1.16.3-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 236,092 kB
  • sloc: cpp: 503,720; python: 345,302; ansic: 195,677; javascript: 89,566; fortran: 56,210; cs: 3,081; f90: 1,150; sh: 857; makefile: 792; pascal: 284; csh: 135; lisp: 134; xml: 56; perl: 51
file content (162 lines) | stat: -rw-r--r-- 6,684 bytes parent folder | download | duplicates (3)
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);
}