Files
ortools-clone/ortools/lp_data/matrix_scaler.h
Corentin Le Molgat b4b226801b update include guards
2025-11-05 11:54:02 +01:00

178 lines
6.6 KiB
C++

// Copyright 2010-2025 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The SparseMatrixScaler class provides tools to scale a SparseMatrix, i.e.
// reduce the range of its coefficients and make for each column and each row
// the maximum magnitude of its coefficients equal to 1.
//
// In the case there are bounds or costs on the columns or a right-hand side
// related to each row, SparseMatrixScaler provides the tools to scale those
// appropriately.
//
// More precisely, suppose we have the Linear Program:
// min c.x
// s.t A.x = b
// with l <= x <= u
//
// The rows of A are scaled by left-multiplying it by a diagonal matrix R
// whose elements R_ii correspond to the scaling factor of row i.
// The columns of A are scaled by right-multiplying it by a diagonal matrix C
// whose elements C_jj correspond to the scaling factor of column j.
//
// We obtain a matrix A' = R.A.C.
//
// We wish to scale x, c, b, l, u so as to work on the scaled problem:
// min c'.x'
// s.t A'.x' = b'
// with l' <= x' <= u'
//
// The right-hand side b needs to be left-multiplied by R, the cost function c
// needs to be right-multiplied by C. Finally, x, and its lower- and upper-bound
// vectors l and u need to be left-multiplied by C^-1.
//
// Note also that the dual vector y is scaled as follows:
// y'.R = y, thus y' = y.R^-1.
//
// The complete transformation is thus:
// A' = R.A.C,
// b' = R.b,
// c' = c.C,
// x' = C^-1.x,
// l' = C^-1.l,
// u' = C^-1.u,
// y' = y.R^-1.
//
// The validity of the above transformation can be checked by computing:
// c'.x' = c.C.C^-1.x = c.x.
// and:
// A'.x' = R.A.C.C^-1.x = R.A.x = R.b = b'.
#ifndef ORTOOLS_LP_DATA_MATRIX_SCALER_H_
#define ORTOOLS_LP_DATA_MATRIX_SCALER_H_
#include <string>
#include <vector>
#include "ortools/base/types.h"
#include "ortools/glop/parameters.pb.h"
#include "ortools/glop/revised_simplex.h"
#include "ortools/glop/status.h"
#include "ortools/lp_data/lp_data.h"
#include "ortools/lp_data/lp_types.h"
namespace operations_research {
namespace glop {
class SparseMatrixScaler {
public:
SparseMatrixScaler();
// This type is neither copyable nor movable.
SparseMatrixScaler(const SparseMatrixScaler&) = delete;
SparseMatrixScaler& operator=(const SparseMatrixScaler&) = delete;
// Initializes the object with the SparseMatrix passed as argument.
// The row and column scaling factors are all set to 1.0 (i.e. no scaling.)
// In terms of matrices, R and C are set to identity matrices.
void Init(SparseMatrix* matrix);
// Clears the object, and puts it back into the same state as after being
// constructed.
void Clear();
// The column col of the matrix was multiplied by ColScalingFactor(col). The
// variable bounds and objective coefficient at the same columsn where DIVIDED
// by that same factor. If col is outside the matrix size, this returns 1.0.
Fractional ColScalingFactor(ColIndex col) const;
// The constraint row of the matrix was multiplied by RowScalingFactor(row),
// same for the constraint bounds (which is not the same as for the variable
// bounds for a column!). If row is outside the matrix size, this returns 1.0.
Fractional RowScalingFactor(RowIndex row) const;
// The inverse of both factor above (this is how we keep them) so this
// direction should be faster to query (no 1.0 / factor).
Fractional ColUnscalingFactor(ColIndex col) const;
Fractional RowUnscalingFactor(RowIndex row) const;
// These are unscaling factor, same as [Col|Row]UnscalingFactor().
const DenseRow& col_scales() const { return col_scales_; }
const DenseColumn& row_scales() const { return row_scales_; }
// Scales the matrix.
void Scale(GlopParameters::ScalingAlgorithm method);
// Scales a row vector up or down (depending whether parameter up is true or
// false) using the scaling factors determined by Scale().
// Scaling up means multiplying by the scaling factors, while scaling down
// means dividing by the scaling factors.
void ScaleRowVector(bool up, DenseRow* row_vector) const;
// Scales a column vector up or down (depending whether parameter up is true
// or false) using the scaling factors determined by Scale().
// Scaling up means multiplying by the scaling factors, while scaling down
// means dividing by the scaling factors.
void ScaleColumnVector(bool up, DenseColumn* column_vector) const;
private:
// Solves the scaling problem as a linear program.
Status LPScale();
// Computes the variance of the non-zero coefficients of the matrix.
// Used by Scale() do decide when to stop.
Fractional VarianceOfAbsoluteValueOfNonZeros() const;
// Scales the rows. Returns the number of rows that have been scaled.
// Helper function to Scale().
RowIndex ScaleRowsGeometrically();
// Scales the columns. Returns the number of columns that have been scaled.
// Helper function to Scale().
ColIndex ScaleColumnsGeometrically();
// Equilibrates the rows. Returns the number of rows that have been scaled.
// Helper function to Scale().
RowIndex EquilibrateRows();
// Equilibrates the Columns. Returns the number of columns that have been
// scaled. Helper function to Scale().
ColIndex EquilibrateColumns();
// Scales the row indexed by row by 1/factor.
// Used by ScaleMatrixRowsGeometrically and EquilibrateRows.
RowIndex ScaleMatrixRows(const DenseColumn& factors);
// Scales the column index by col by 1/factor.
// Used by ScaleColumnsGeometrically and EquilibrateColumns.
void ScaleMatrixColumn(ColIndex col, Fractional factor);
// Returns a string containing information on the progress of the scaling
// algorithm. This is not meant to be called in an optimized mode as it takes
// some time to compute the displayed quantities.
std::string DebugInformationString() const;
// Pointer to the matrix to be scaled.
SparseMatrix* matrix_;
// Array of scaling factors for each row. Indexed by row number.
DenseColumn row_scales_;
// Array of scaling factors for each column. Indexed by column number.
DenseRow col_scales_;
};
} // namespace glop
} // namespace operations_research
#endif // ORTOOLS_LP_DATA_MATRIX_SCALER_H_