20#include "absl/log/check.h"
21#include "absl/types/span.h"
22#include "ortools/glop/parameters.pb.h"
49 const RowIndex transposed_slack =
ColToRowIndex(slack_variable);
54 for (
const auto& entry : sparse_row) {
55 if (transposed_slack == entry.index())
continue;
57 (*values)[
RowToColIndex(entry.index())] * entry.coefficient();
59 (*values)[slack_variable] = -activation;
67 GlopParameters params;
68 Scale(lp, scaler, params.scaling_method());
74 GlopParameters::ScalingAlgorithm scaling_method) {
75 scaler->
Init(&lp->matrix_);
79 &lp->objective_coefficients_);
81 &lp->variable_upper_bounds_);
83 &lp->variable_lower_bounds_);
86 lp->transpose_matrix_is_consistent_ =
false;
95 objective_scaling_factor_ = 1.0 / lp->
ScaleObjective(params.cost_scaling());
97 matrix_is_scaled_ =
true;
108 absl::Span<const double> row_factors,
109 absl::Span<const double> col_factors) {
110 matrix_is_scaled_ =
true;
111 const RowIndex num_rows(row_factors.size());
112 row_unscaling_factors_.resize(num_rows, 1.0);
113 for (RowIndex row(0); row < num_rows; ++row) {
114 row_unscaling_factors_[row] = 1.0 / row_factors[row.value()];
117 const ColIndex num_cols(col_factors.size());
118 col_unscaling_factors_.resize(num_cols, 1.0);
119 for (ColIndex col(0); col < num_cols; ++col) {
120 col_unscaling_factors_[col] = 1.0 / col_factors[col.value()];
125 matrix_is_scaled_ =
false;
126 bound_scaling_factor_ = 1.0;
127 objective_scaling_factor_ = 1.0;
133 return ColUnscalingFactor(col) * bound_scaling_factor_;
137 if (!matrix_is_scaled_)
return bound_scaling_factor_;
138 const ColIndex num_cols = col_unscaling_factors_.size();
139 if (col < num_cols) {
140 return col_unscaling_factors_[col] * bound_scaling_factor_;
142 return row_unscaling_factors_[
ColToRowIndex(col - num_cols)] *
143 bound_scaling_factor_;
148 return value * ColUnscalingFactor(col) * bound_scaling_factor_;
154 return value / ColUnscalingFactor(col) * objective_scaling_factor_;
160 return value * (RowUnscalingFactor(row) * objective_scaling_factor_);
166 return value / RowUnscalingFactor(row) * bound_scaling_factor_;
172 return value / (ColUnscalingFactor(col) * bound_scaling_factor_);
178 return value * ColUnscalingFactor(col) / objective_scaling_factor_;
184 return value / (RowUnscalingFactor(row) * objective_scaling_factor_);
192 return value / RowUnscalingFactor(row);
198 return value * RowUnscalingFactor(row) / bound_scaling_factor_;
203 const Fractional global_factor = ColUnscalingFactor(basis_col);
207 const ColIndex num_rows = left_inverse->
values.
size();
208 for (ColIndex col(0); col < num_rows; ++col) {
209 left_inverse->
values[col] /=
213 for (
const ColIndex col : left_inverse->
non_zeros) {
214 left_inverse->
values[col] /=
223 const Fractional global_factor = 1.0 / ColUnscalingFactor(col);
228 const RowIndex num_rows = right_inverse->
values.
size();
229 for (RowIndex row(0); row < num_rows; ++row) {
230 right_inverse->
values[row] /=
231 ColUnscalingFactor(basis[row]) * global_factor;
234 for (
const RowIndex row : right_inverse->
non_zeros) {
235 right_inverse->
values[row] /=
236 ColUnscalingFactor(basis[row]) * global_factor;
245 if (f == 0)
continue;
249 if (num_terms == 0) {
250 objective_scaling_factor_ = 1.0;
254 const Fractional average = sum /
static_cast<double>(num_terms);
255 objective_scaling_factor_ = 1.0 / average;
257 f *= objective_scaling_factor_;
263 const double infinity = std::numeric_limits<double>::infinity();
268 if (m == 0 || m == infinity)
continue;
269 min_magnitude = std::min(min_magnitude, m);
270 max_magnitude = std::max(max_magnitude, m);
274 if (m == 0 || m == infinity)
continue;
275 min_magnitude = std::min(min_magnitude, m);
276 max_magnitude = std::max(max_magnitude, m);
279 bound_scaling_factor_ = 1.0;
280 if (min_magnitude != infinity) {
281 CHECK_LE(min_magnitude, max_magnitude);
282 if (min_magnitude > 1.0) {
283 bound_scaling_factor_ = 1.0 / min_magnitude;
284 }
else if (max_magnitude < 1.0) {
285 bound_scaling_factor_ = 1.0 / max_magnitude;
289 if (bound_scaling_factor_ == 1.0)
return;
291 f *= bound_scaling_factor_;
294 f *= bound_scaling_factor_;
const DenseColumn & constraint_lower_bounds() const
const SparseMatrix & GetTransposeSparseMatrix() const
ColIndex GetSlackVariable(RowIndex row) const
Fractional ScaleObjective(GlopParameters::CostScalingAlgorithm method)
const DenseColumn & constraint_upper_bounds() const
ColIndex num_variables() const
Returns the number of variables.
ColIndex GetFirstSlackVariable() const
RowIndex num_constraints() const
Returns the number of constraints.
void UnscaleUnitRowLeftSolve(ColIndex basis_col, ScatteredRow *left_inverse) const
void AverageCostScaling(DenseRow *objective)
Extra scaling function, to scale objective/bounds.
void ConfigureFromFactors(absl::Span< const double > row_factors, absl::Span< const double > col_factors)
Fractional VariableScalingFactorWithSlack(ColIndex col) const
Fractional ScaleVariableValue(ColIndex col, Fractional value) const
Transforms value from unscaled domain to the scaled one.
Fractional UnscaleDualValue(RowIndex row, Fractional value) const
void ContainOneBoundScaling(DenseRow *upper_bounds, DenseRow *lower_bounds)
Fractional UnscaleConstraintActivity(RowIndex row, Fractional value) const
void Clear()
Clear all scaling coefficients.
Fractional UnscaleLeftSolveValue(RowIndex row, Fractional value) const
Fractional ScaleDualValue(RowIndex row, Fractional value) const
void Scale(LinearProgram *lp)
Scale the given LP.
Fractional ScaleConstraintActivity(RowIndex row, Fractional value) const
Fractional UnscaleReducedCost(ColIndex col, Fractional value) const
Fractional VariableScalingFactor(ColIndex col) const
Fractional UnscaleVariableValue(ColIndex col, Fractional value) const
Transforms corresponding value from the scaled domain to the original one.
Fractional ScaleReducedCost(ColIndex col, Fractional value) const
void UnscaleColumnRightSolve(const RowToColMapping &basis, ColIndex col, ScatteredColumn *right_inverse) const
Unscale a col vector v such that B.c = matrix_column_col.
const DenseRow & col_scales() const
These are unscaling factor, same as [Col|Row]UnscalingFactor().
void ScaleColumnVector(bool up, DenseColumn *column_vector) const
const DenseColumn & row_scales() const
void Init(SparseMatrix *matrix)
void ScaleRowVector(bool up, DenseRow *row_vector) const
void Scale(GlopParameters::ScalingAlgorithm method)
Scales the matrix.
void resize(IntType size)
constexpr ColIndex kInvalidCol(-1)
StrictITIVector< RowIndex, ColIndex > RowToColMapping
void ComputeSlackVariablesValues(const LinearProgram &linear_program, DenseRow *values)
ColIndex RowToColIndex(RowIndex row)
Get the ColIndex corresponding to the column # row.
RowIndex ColToRowIndex(ColIndex col)
Get the RowIndex corresponding to the row # col.
void Scale(LinearProgram *lp, SparseMatrixScaler *scaler)
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.
StrictITIVector< Index, Fractional > values
std::vector< Index > non_zeros