OR-Tools  9.6
lp_data_utils.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
15 
16 namespace operations_research {
17 namespace glop {
18 
19 void ComputeSlackVariablesValues(const LinearProgram& linear_program,
20  DenseRow* values) {
21  DCHECK(values);
22  DCHECK_EQ(linear_program.num_variables(), values->size());
23 
24  // If there are no slack variable, we can give up.
25  if (linear_program.GetFirstSlackVariable() == kInvalidCol) return;
26 
27  const auto& transposed_matrix = linear_program.GetTransposeSparseMatrix();
28  for (RowIndex row(0); row < linear_program.num_constraints(); row++) {
29  const ColIndex slack_variable = linear_program.GetSlackVariable(row);
30 
31  if (slack_variable == kInvalidCol) continue;
32 
33  DCHECK_EQ(0.0, linear_program.constraint_lower_bounds()[row]);
34  DCHECK_EQ(0.0, linear_program.constraint_upper_bounds()[row]);
35 
36  const RowIndex transposed_slack = ColToRowIndex(slack_variable);
37  Fractional activation = 0.0;
38  // Row in the initial matrix (column in the transposed).
39  const SparseColumn& sparse_row =
40  transposed_matrix.column(RowToColIndex(row));
41  for (const auto& entry : sparse_row) {
42  if (transposed_slack == entry.index()) continue;
43  activation +=
44  (*values)[RowToColIndex(entry.index())] * entry.coefficient();
45  }
46  (*values)[slack_variable] = -activation;
47  }
48 }
49 
50 // This is separated from the LinearProgram class because of a cyclic dependency
51 // when scaling as an LP.
53  // Create GlopParameters proto to get default scaling algorithm.
54  GlopParameters params;
55  Scale(lp, scaler, params.scaling_method());
56 }
57 
58 // This is separated from LinearProgram class because of a cyclic dependency
59 // when scaling as an LP.
61  GlopParameters::ScalingAlgorithm scaling_method) {
62  scaler->Init(&lp->matrix_);
63  scaler->Scale(
64  scaling_method); // Compute R and C, and replace the matrix A by R.A.C
65  scaler->ScaleRowVector(false,
66  &lp->objective_coefficients_); // oc = oc.C
67  scaler->ScaleRowVector(true,
68  &lp->variable_upper_bounds_); // cl = cl.C^-1
69  scaler->ScaleRowVector(true,
70  &lp->variable_lower_bounds_); // cu = cu.C^-1
71  scaler->ScaleColumnVector(false, &lp->constraint_upper_bounds_); // rl = R.rl
72  scaler->ScaleColumnVector(false, &lp->constraint_lower_bounds_); // ru = R.ru
73  lp->transpose_matrix_is_consistent_ = false;
74 }
75 
76 void LpScalingHelper::Scale(LinearProgram* lp) { Scale(GlopParameters(), lp); }
77 
78 void LpScalingHelper::Scale(const GlopParameters& params, LinearProgram* lp) {
79  scaler_.Clear();
80  ::operations_research::glop::Scale(lp, &scaler_, params.scaling_method());
81  bound_scaling_factor_ = 1.0 / lp->ScaleBounds();
82  objective_scaling_factor_ = 1.0 / lp->ScaleObjective(params.cost_scaling());
83 }
84 
86  scaler_.Clear();
87  bound_scaling_factor_ = 1.0;
88  objective_scaling_factor_ = 1.0;
89 }
90 
92  // During scaling a col was multiplied by ColScalingFactor() and the variable
93  // bounds divided by it.
94  return scaler_.ColUnscalingFactor(col) * bound_scaling_factor_;
95 }
96 
98  Fractional value) const {
99  return value * scaler_.ColUnscalingFactor(col) * bound_scaling_factor_;
100 }
101 
103  Fractional value) const {
104  // The reduced cost move like the objective and the col scale.
105  return value / scaler_.ColUnscalingFactor(col) * objective_scaling_factor_;
106 }
107 
109  Fractional value) const {
110  // The dual value move like the objective and the inverse of the row scale.
111  return value * (scaler_.RowUnscalingFactor(row) * objective_scaling_factor_);
112 }
113 
115  Fractional value) const {
116  // The activity move with the row_scale and the bound_scaling_factor.
117  return value / scaler_.RowUnscalingFactor(row) * bound_scaling_factor_;
118 }
119 
121  Fractional value) const {
122  // Just the opposite of ScaleVariableValue().
123  return value / (scaler_.ColUnscalingFactor(col) * bound_scaling_factor_);
124 }
125 
127  Fractional value) const {
128  // The reduced cost move like the objective and the col scale.
129  return value * scaler_.ColUnscalingFactor(col) / objective_scaling_factor_;
130 }
131 
133  Fractional value) const {
134  // The dual value move like the objective and the inverse of the row scale.
135  return value / (scaler_.RowUnscalingFactor(row) * objective_scaling_factor_);
136 }
137 
139  Fractional value) const {
140  // The activity move with the row_scale and the bound_scaling_factor.
141  return value * scaler_.RowUnscalingFactor(row) / bound_scaling_factor_;
142 }
143 
145  ColIndex basis_col, ScatteredRow* left_inverse) const {
146  const Fractional global_factor = scaler_.ColUnscalingFactor(basis_col);
147 
148  // We have left_inverse * [RowScale * B * ColScale] = unit_row.
149  if (left_inverse->non_zeros.empty()) {
150  const ColIndex num_rows = left_inverse->values.size();
151  for (ColIndex col(0); col < num_rows; ++col) {
152  left_inverse->values[col] /=
153  scaler_.RowUnscalingFactor(ColToRowIndex(col)) * global_factor;
154  }
155  } else {
156  for (const ColIndex col : left_inverse->non_zeros) {
157  left_inverse->values[col] /=
158  scaler_.RowUnscalingFactor(ColToRowIndex(col)) * global_factor;
159  }
160  }
161 }
162 
164  const RowToColMapping& basis, ColIndex col,
165  ScatteredColumn* right_inverse) const {
166  const Fractional global_factor = scaler_.ColScalingFactor(col);
167 
168  // [RowScale * B * BColScale] * inverse = RowScale * column * ColScale.
169  // That is B * (BColScale * inverse) = columm * ColScale[col].
170  if (right_inverse->non_zeros.empty()) {
171  const RowIndex num_rows = right_inverse->values.size();
172  for (RowIndex row(0); row < num_rows; ++row) {
173  right_inverse->values[row] /=
174  scaler_.ColUnscalingFactor(basis[row]) * global_factor;
175  }
176  } else {
177  for (const RowIndex row : right_inverse->non_zeros) {
178  right_inverse->values[row] /=
179  scaler_.ColUnscalingFactor(basis[row]) * global_factor;
180  }
181  }
182 }
183 
184 } // namespace glop
185 } // namespace operations_research
const SparseMatrix & GetTransposeSparseMatrix() const
Definition: lp_data.cc:377
ColIndex GetSlackVariable(RowIndex row) const
Definition: lp_data.cc:756
const DenseColumn & constraint_lower_bounds() const
Definition: lp_data.h:216
Fractional ScaleObjective(GlopParameters::CostScalingAlgorithm method)
Definition: lp_data.cc:1189
const DenseColumn & constraint_upper_bounds() const
Definition: lp_data.h:219
Fractional ScaleConstraintActivity(RowIndex row, Fractional value) const
Fractional ScaleVariableValue(ColIndex col, Fractional value) const
Fractional VariableScalingFactor(ColIndex col) const
Fractional UnscaleVariableValue(ColIndex col, Fractional value) const
Fractional UnscaleReducedCost(ColIndex col, Fractional value) const
void UnscaleUnitRowLeftSolve(ColIndex basis_col, ScatteredRow *left_inverse) const
void UnscaleColumnRightSolve(const RowToColMapping &basis, ColIndex col, ScatteredColumn *right_inverse) const
Fractional UnscaleDualValue(RowIndex row, Fractional value) const
Fractional ScaleReducedCost(ColIndex col, Fractional value) const
Fractional UnscaleConstraintActivity(RowIndex row, Fractional value) const
Fractional ScaleDualValue(RowIndex row, Fractional value) const
Fractional ColScalingFactor(ColIndex col) const
void ScaleColumnVector(bool up, DenseColumn *column_vector) const
void ScaleRowVector(bool up, DenseRow *row_vector) const
void Scale(GlopParameters::ScalingAlgorithm method)
Fractional ColUnscalingFactor(ColIndex col) const
Fractional RowUnscalingFactor(RowIndex row) const
int64_t value
ColIndex col
Definition: markowitz.cc:186
RowIndex row
Definition: markowitz.cc:185
constexpr ColIndex kInvalidCol(-1)
void Scale(LinearProgram *lp, SparseMatrixScaler *scaler, GlopParameters::ScalingAlgorithm scaling_method)
ColIndex RowToColIndex(RowIndex row)
Definition: lp_types.h:53
RowIndex ColToRowIndex(ColIndex col)
Definition: lp_types.h:56
void ComputeSlackVariablesValues(const LinearProgram &linear_program, DenseRow *values)
void Scale(LinearProgram *lp, SparseMatrixScaler *scaler)
Collection of objects used to extend the Constraint Solver library.
StrictITIVector< Index, Fractional > values