19#include "absl/log/check.h"
31 const ColIndex num_cols = matrix_.num_cols();
32 DCHECK_EQ(num_cols, new_lower_bounds.
size());
33 DCHECK_EQ(num_cols, new_upper_bounds.
size());
36 if (lower_bounds_ == new_lower_bounds && upper_bounds_ == new_upper_bounds) {
40 lower_bounds_ = new_lower_bounds;
41 upper_bounds_ = new_upper_bounds;
43 for (ColIndex col(0); col < num_cols; ++col) {
44 variable_type_[col] = ComputeVariableType(col);
50 const ColIndex num_cols = matrix_.num_cols();
51 DCHECK_EQ(num_cols, lower_bounds_.size());
52 DCHECK_EQ(num_cols, upper_bounds_.size());
54 for (ColIndex col(0); col < num_cols; ++col) {
55 variable_type_[col] = ComputeVariableType(col);
60 const DenseRow& variable_lower_bounds,
61 const DenseRow& variable_upper_bounds,
64 const ColIndex num_cols = matrix_.num_cols();
65 const ColIndex num_variables = variable_upper_bounds.
size();
66 const RowIndex num_rows = constraint_lower_bounds.
size();
68 bool is_unchanged = (num_cols == lower_bounds_.size());
70 lower_bounds_.resize(num_cols, 0.0);
71 upper_bounds_.resize(num_cols, 0.0);
75 for (ColIndex col(0); col < num_variables; ++col) {
76 if (lower_bounds_[col] != variable_lower_bounds[col] ||
77 upper_bounds_[col] != variable_upper_bounds[col]) {
78 lower_bounds_[col] = variable_lower_bounds[col];
79 upper_bounds_[col] = variable_upper_bounds[col];
81 variable_type_[col] = ComputeVariableType(col);
86 for (RowIndex row(0); row < num_rows; ++row) {
88 if (lower_bounds_[col] != -constraint_upper_bounds[row] ||
89 upper_bounds_[col] != -constraint_lower_bounds[row]) {
90 lower_bounds_[col] = -constraint_upper_bounds[row];
91 upper_bounds_[col] = -constraint_lower_bounds[row];
93 variable_type_[col] = ComputeVariableType(col);
100void VariablesInfo::ResetStatusInfo() {
101 const ColIndex num_cols = matrix_.
num_cols();
102 DCHECK_EQ(num_cols, lower_bounds_.
size());
103 DCHECK_EQ(num_cols, upper_bounds_.
size());
117 boxed_variables_are_relevant_ =
true;
118 num_entries_in_relevant_columns_ = 0;
123 ColIndex num_new_cols,
127 const ColIndex num_cols = lower_bounds_.size();
128 DCHECK_LE(num_new_cols, first_slack_col);
129 const ColIndex first_new_col(first_slack_col - num_new_cols);
134 for (ColIndex col(0); col < num_cols; ++col) {
137 if (col < first_new_col && col < state_size) {
139 }
else if (col >= first_slack_col && col - num_new_cols < state_size) {
140 status = state.
statuses[col - num_new_cols];
154 is_basic_.Set(col,
true);
157 if (lower_bounds_[col] == upper_bounds_[col]) {
161 ? DefaultVariableStatus(col)
166 if (lower_bounds_[col] == upper_bounds_[col]) {
170 ? DefaultVariableStatus(col)
182 const ColIndex num_cols = lower_bounds_.size();
183 is_basic_.ClearAndResize(num_cols);
184 for (
const ColIndex col : basis) {
187 int num_no_longer_in_basis = 0;
188 for (ColIndex col(0); col < num_cols; ++col) {
190 ++num_no_longer_in_basis;
198 return num_no_longer_in_basis;
204 const ColIndex num_cols = lower_bounds_.size();
205 for (ColIndex col(0); col < num_cols; ++col) {
209 col < starting_values.
size() ? starting_values[col] : 0.0;
210 const Fractional diff_ub = upper_bounds_[col] - value;
211 const Fractional diff_lb = value - lower_bounds_[col];
212 if (diff_lb <= diff_ub) {
213 if (diff_lb <= distance) {
218 if (diff_ub <= distance) {
229 const ColIndex num_cols = lower_bounds_.size();
230 for (ColIndex col(0); col < num_cols; ++col) {
235VariableStatus VariablesInfo::DefaultVariableStatus(ColIndex col)
const {
237 DCHECK_LT(col, lower_bounds_.
size());
238 if (lower_bounds_[col] == upper_bounds_[col]) {
248 return std::abs(lower_bounds_[col]) <= std::abs(upper_bounds_[col])
254 if (value == boxed_variables_are_relevant_)
return;
255 boxed_variables_are_relevant_ = value;
257 for (
const ColIndex col : non_basic_boxed_variables_) {
261 for (
const ColIndex col : non_basic_boxed_variables_) {
262 SetRelevance(col,
false);
268 if (in_dual_phase_one_) {
271 if (lower_bounds_[col] != 0.0) lower_bounds_[col] = -
kInfinity;
272 if (upper_bounds_[col] != 0.0) upper_bounds_[col] = +
kInfinity;
273 variable_type_[col] = ComputeVariableType(col);
276 is_basic_.Set(col,
true);
277 not_basic_.Set(col,
false);
278 can_increase_.Set(col,
false);
279 can_decrease_.Set(col,
false);
280 non_basic_boxed_variables_.Set(col,
false);
281 SetRelevance(col,
false);
287 variable_status_[col] = status;
288 is_basic_.Set(col,
false);
289 not_basic_.Set(col,
true);
297 non_basic_boxed_variables_.Set(col, boxed);
299 (boxed_variables_are_relevant_ || !boxed);
300 SetRelevance(col, relevance);
304 return variable_type_;
308 return variable_status_;
312 return can_increase_;
316 return can_decrease_;
330 return non_basic_boxed_variables_;
334 return num_entries_in_relevant_columns_;
337VariableType VariablesInfo::ComputeVariableType(ColIndex col)
const {
338 DCHECK_LE(lower_bounds_[col], upper_bounds_[col]);
344 }
else if (upper_bounds_[col] ==
kInfinity) {
346 }
else if (lower_bounds_[col] == upper_bounds_[col]) {
353void VariablesInfo::SetRelevance(ColIndex col,
bool relevance) {
354 if (relevance_.IsSet(col) == relevance)
return;
357 num_entries_in_relevant_columns_ += matrix_.ColumnNumEntries(col);
359 relevance_.Clear(col);
360 num_entries_in_relevant_columns_ -= matrix_.ColumnNumEntries(col);
366void VariablesInfo::UpdateStatusForNewType(ColIndex col) {
367 switch (variable_status_[col]) {
372 if (lower_bounds_[col] == upper_bounds_[col]) {
374 }
else if (lower_bounds_[col] == -
kInfinity) {
384 if (lower_bounds_[col] == upper_bounds_[col]) {
386 }
else if (upper_bounds_[col] ==
kInfinity) {
404 DCHECK(!in_dual_phase_one_);
405 in_dual_phase_one_ =
true;
406 saved_lower_bounds_ = lower_bounds_;
407 saved_upper_bounds_ = upper_bounds_;
413 const ColIndex num_cols = matrix_.num_cols();
414 for (ColIndex col(0); col < num_cols; ++col) {
415 switch (variable_type_[col]) {
418 lower_bounds_[col] = 0.0;
419 upper_bounds_[col] = 0.0;
423 lower_bounds_[col] = 0.0;
424 upper_bounds_[col] = 1.0;
428 lower_bounds_[col] = -1.0;
429 upper_bounds_[col] = 0.0;
433 lower_bounds_[col] = -1000.0;
434 upper_bounds_[col] = 1000.0;
442 if (reduced_costs[col] > dual_feasibility_tolerance) {
444 }
else if (reduced_costs[col] < -dual_feasibility_tolerance) {
449 UpdateStatusForNewType(col);
455 DCHECK(in_dual_phase_one_);
456 in_dual_phase_one_ =
false;
457 std::swap(saved_lower_bounds_, lower_bounds_);
458 std::swap(saved_upper_bounds_, upper_bounds_);
463 std::swap(empty1, saved_lower_bounds_);
464 std::swap(empty1, saved_upper_bounds_);
467 const ColIndex num_cols = matrix_.num_cols();
468 for (ColIndex col(0); col < num_cols; ++col) {
469 variable_type_[col] = ComputeVariableType(col);
478 if (reduced_costs[col] > dual_feasibility_tolerance) {
480 }
else if (reduced_costs[col] < -dual_feasibility_tolerance) {
485 UpdateStatusForNewType(col);
void ClearAndResize(IndexType size)
Changes the number of bits the Bitset64 can hold and set all of them to 0.
ColIndex num_cols() const
StrictITISpan< ColIndex, const Fractional > ConstView
void resize(IntType size)
void TransformToDualPhaseIProblem(Fractional dual_feasibility_tolerance, DenseRow::ConstView reduced_costs)
const DenseBitRow & GetCanDecreaseBitRow() const
const DenseBitRow & GetCanIncreaseBitRow() const
const VariableStatusRow & GetStatusRow() const
const VariableTypeRow & GetTypeRow() const
EntryIndex GetNumEntriesInRelevantColumns() const
void MakeBoxedVariableRelevant(bool value)
const DenseBitRow & GetNotBasicBitRow() const
const DenseBitRow & GetIsRelevantBitRow() const
int ChangeUnusedBasicVariablesToFree(const RowToColMapping &basis)
void UpdateToBasicStatus(ColIndex col)
const DenseBitRow & GetNonBasicBoxedVariables() const
void UpdateToNonBasicStatus(ColIndex col, VariableStatus status)
void EndDualPhaseI(Fractional dual_feasibility_tolerance, DenseRow::ConstView reduced_costs)
bool LoadBoundsAndReturnTrueIfUnchanged(const DenseRow &new_lower_bounds, const DenseRow &new_upper_bounds)
void InitializeFromBasisState(ColIndex first_slack, ColIndex num_new_cols, const BasisState &state)
void InitializeToDefaultStatus()
void InitializeFromMutatedState()
const DenseBitRow & GetIsBasicBitRow() const
int SnapFreeVariablesToBound(Fractional distance, const DenseRow &starting_values)
VariablesInfo(const CompactSparseMatrix &matrix)
Takes references to the linear program data we need.
constexpr double kInfinity
Infinity for type Fractional.
StrictITIVector< RowIndex, ColIndex > RowToColMapping
Bitset64< ColIndex > DenseBitRow
Row of bits.
ColIndex RowToColIndex(RowIndex row)
Get the ColIndex corresponding to the column # row.
bool IsFinite(Fractional value)
VariableType
Different types of variables.
@ UPPER_AND_LOWER_BOUNDED
StrictITIVector< ColIndex, VariableType > VariableTypeRow
Row of variable types.
StrictITIVector< ColIndex, VariableStatus > VariableStatusRow
Row of variable statuses.
StrictITIVector< RowIndex, Fractional > DenseColumn
Column-vector types. Column-vector types are indexed by a row index.
StrictITIVector< ColIndex, Fractional > DenseRow
Row-vector types. Row-vector types are indexed by a column index.
In SWIG mode, we don't want anything besides these top-level includes.
static constexpr double kInfinity
VariableStatusRow statuses