Google OR-Tools v9.12
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
primal_edge_norms.h
Go to the documentation of this file.
1// Copyright 2010-2025 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
14#ifndef OR_TOOLS_GLOP_PRIMAL_EDGE_NORMS_H_
15#define OR_TOOLS_GLOP_PRIMAL_EDGE_NORMS_H_
16
17#include <cstdint>
18#include <string>
19#include <vector>
20
22#include "ortools/glop/parameters.pb.h"
29#include "ortools/util/stats.h"
31
32namespace operations_research {
33namespace glop {
34
35// This class maintains the primal edge squared norms (and other variants) to be
36// used in the primal pricing step. Instead of computing the needed values from
37// scractch at each iteration, it is more efficient to update them incrementally
38// for each basis pivot applied to the simplex basis matrix B.
39//
40// Terminology:
41// - To each non-basic column 'a' of a matrix A, we can associate an "edge" in
42// the kernel of A equal to 1.0 on the index of 'a' and '-B^{-1}.a' on the
43// basic variables.
44// - 'B^{-1}.a' is called the "right inverse" of 'a'.
45// - The entering edge is the edge we are following during a simplex step,
46// and we call "direction" the reverse of this edge restricted to the
47// basic variables, i.e. the right inverse of the entering column.
48//
49// Papers:
50// - D. Goldfarb, J.K. Reid, "A practicable steepest-edge simplex algorithm"
51// Mathematical Programming 12 (1977) 361-371, North-Holland.
52// http://www.springerlink.com/content/g8335137n3j16934/
53// - J.J. Forrest, D. Goldfarb, "Steepest-edge simplex algorithms for linear
54// programming", Mathematical Programming 57 (1992) 341-374, North-Holland.
55// http://www.springerlink.com/content/q645w3t2q229m248/
56// - Ping-Qi Pan "A fast simplex algorithm for linear programming".
57// http://www.optimization-online.org/DB_FILE/2007/10/1805.pdf
58// - Ping-Qi Pan, "Efficient nested pricing in the simplex algorithm",
59// http://www.optimization-online.org/DB_FILE/2007/10/1810.pdf
61 public:
62 // Takes references to the linear program data we need. Note that we assume
63 // that the matrix will never change in our back, but the other references are
64 // supposed to reflect the correct state.
65 PrimalEdgeNorms(const CompactSparseMatrix& compact_matrix,
66 const VariablesInfo& variables_info,
67 const BasisFactorization& basis_factorization);
68
69 // This type is neither copyable nor movable.
72
73 // Clears, i.e. resets the object to its initial value. This will trigger
74 // a recomputation for the next Get*() method call.
75 void Clear();
76
77 // If this is true, then the caller must re-factorize the basis before the
78 // next call to GetEdgeSquaredNorms(). This is because the latter will
79 // recompute the norms from scratch and therefore needs a hightened precision
80 // and speed.
81 bool NeedsBasisRefactorization() const;
82
83 // Depending on the SetPricingRule(), this returns one of the "norms" vector
84 // below. Note that all norms are squared.
86
87 // Returns the primal edge squared norms. This is only valid if the caller
88 // properly called UpdateBeforeBasisPivot() before each basis pivot, or if
89 // this is the first call to this function after a Clear(). Note that only the
90 // relevant columns are filled.
92
93 // Returns an approximation of the edges norms "devex".
94 // This is only valid if the caller properly called UpdateBeforeBasisPivot()
95 // before each basis pivot, or if this is the first call to this function
96 // after a Clear().
98
99 // Returns the L2 norms of all the columns of A.
100 // Note that this is currently not cleared by Clear().
102
103 // Compares the current entering edge norm with its precise version (using the
104 // direction that wasn't avaible before) and triggers a full recomputation if
105 // the precision is not good enough (see recompute_edges_norm_threshold in
106 // GlopParameters). As a side effect, this replace the entering_col edge
107 // norm with its precise version.
108 //
109 // Returns false if the old norm is less that 0.25 the new one. We might want
110 // to change the leaving variable if this happens.
111 bool TestEnteringEdgeNormPrecision(ColIndex entering_col,
112 const ScatteredColumn& direction);
113
114 // Updates any internal data BEFORE the given simplex pivot is applied to B.
115 // Note that no updates are needed in case of a bound flip.
116 // The arguments are in order:
117 // - The index of the entering non-basic column of A.
118 // - The index in B of the leaving basic variable.
119 // - The 'direction', i.e. the right inverse of the entering column.
120 // - The update row (see UpdateRow), which will only be computed if needed.
121 void UpdateBeforeBasisPivot(ColIndex entering_col, ColIndex leaving_col,
122 RowIndex leaving_row,
123 const ScatteredColumn& direction,
124 UpdateRow* update_row);
125
126 // Sets the algorithm parameters.
127 void SetParameters(const GlopParameters& parameters) {
128 parameters_ = parameters;
129 }
130
131 // This changes what GetSquaredNorms() returns.
132 void SetPricingRule(GlopParameters::PricingRule rule) {
133 pricing_rule_ = rule;
134 }
135
136 // Registers a boolean that will be set to true each time the norms are or
137 // will be recomputed. This allows anyone that depends on this to know that it
138 // cannot just assume an incremental changes and needs to updates its data.
139 // Important: UpdateBeforeBasisPivot() will not trigger this.
140 void AddRecomputationWatcher(bool* watcher) { watchers_.push_back(watcher); }
141
142 // Returns a string with statistics about this class.
143 std::string StatString() const { return stats_.StatString(); }
144
145 // Deterministic time used by the scalar product computation of this class.
146 double DeterministicTime() const {
147 return DeterministicTimeForFpOperations(num_operations_);
148 }
149
150 void SetTimeLimit(TimeLimit* time_limit) { time_limit_ = time_limit; }
151
152 private:
153 // Statistics about this class.
154 struct Stats : public StatsGroup {
155 Stats()
156 : StatsGroup("PrimalEdgeNorms"),
157 direction_left_inverse_density("direction_left_inverse_density",
158 this),
159 direction_left_inverse_accuracy("direction_left_inverse_accuracy",
160 this),
161 edges_norm_accuracy("edges_norm_accuracy", this),
162 lower_bounded_norms("lower_bounded_norms", this) {}
163 RatioDistribution direction_left_inverse_density;
164 DoubleDistribution direction_left_inverse_accuracy;
165 DoubleDistribution edges_norm_accuracy;
166 IntegerDistribution lower_bounded_norms;
167 };
168
169 // Recompute the matrix column L2 norms from scratch.
170 void ComputeMatrixColumnNorms();
171
172 // Recompute the edge squared L2 norms from scratch.
173 void ComputeEdgeSquaredNorms();
174
175 // Compute the left inverse of the direction.
176 // The first argument is there for checking precision.
177 void ComputeDirectionLeftInverse(ColIndex entering_col,
178 const ScatteredColumn& direction);
179
180 // Updates edges_squared_norm_ according to the given pivot.
181 void UpdateEdgeSquaredNorms(ColIndex entering_col, ColIndex leaving_col,
182 RowIndex leaving_row,
183 const DenseColumn& direction,
184 const UpdateRow& update_row);
185
186 // Resets all devex weights to 1.0 .
187 void ResetDevexWeights();
188
189 // Updates devex_weights_ according to the given pivot.
190 void UpdateDevexWeights(ColIndex entering_col, ColIndex leaving_col,
191 RowIndex leaving_row, const DenseColumn& direction,
192 const UpdateRow& update_row);
193
194 // Problem data that should be updated from outside.
195 const CompactSparseMatrix& compact_matrix_;
196 const VariablesInfo& variables_info_;
197 const BasisFactorization& basis_factorization_;
198 TimeLimit* time_limit_ = nullptr;
199
200 // Internal data.
201 GlopParameters parameters_;
202 GlopParameters::PricingRule pricing_rule_ = GlopParameters::DANTZIG;
203 Stats stats_;
204
205 // Booleans to control what happens on the next ChooseEnteringColumn() call.
206 bool must_refactorize_basis_;
207 bool recompute_edge_squared_norms_;
208 bool reset_devex_weights_;
209
210 // Norm^2 of the edges of the relevant columns of A.
211 DenseRow edge_squared_norms_;
212
213 // Norm of all the columns of A.
214 DenseRow matrix_column_norms_;
215
216 // Approximation of edges norms "devex".
217 // Denoted by vector 'w' in Pin Qi Pan (1810.pdf section 1.1.4)
218 // At any time, devex_weights_ >= 1.0.
219 DenseRow devex_weights_;
220
221 // Tracks number of updates of the devex weights since we have to reset
222 // them to 1.0 every now and then.
223 int num_devex_updates_since_reset_;
224
225 // Left inverse by B of the 'direction'. This is the transpose of 'v' in the
226 // steepest edge paper. Its scalar product with a column 'a' of A gives the
227 // value of the scalar product of the 'direction' with the right inverse of
228 // 'a'.
229 ScatteredRow direction_left_inverse_;
230
231 // Used by DeterministicTime().
232 int64_t num_operations_;
233
234 // Boolean(s) to set to false when the norms are changed outside of the
235 // UpdateBeforeBasisPivot() function.
236 std::vector<bool*> watchers_;
237};
238
239} // namespace glop
240} // namespace operations_research
241
242#endif // OR_TOOLS_GLOP_PRIMAL_EDGE_NORMS_H_
Statistic on the distribution of a sequence of doubles.
Definition stats.h:276
Statistic on the distribution of a sequence of integers.
Definition stats.h:288
Statistic on the distribution of a sequence of ratios, displayed as %.
Definition stats.h:265
Base class to print a nice summary of a group of statistics.
Definition stats.h:128
PrimalEdgeNorms & operator=(const PrimalEdgeNorms &)=delete
std::string StatString() const
Returns a string with statistics about this class.
void UpdateBeforeBasisPivot(ColIndex entering_col, ColIndex leaving_col, RowIndex leaving_row, const ScatteredColumn &direction, UpdateRow *update_row)
double DeterministicTime() const
Deterministic time used by the scalar product computation of this class.
void SetPricingRule(GlopParameters::PricingRule rule)
This changes what GetSquaredNorms() returns.
bool TestEnteringEdgeNormPrecision(ColIndex entering_col, const ScatteredColumn &direction)
PrimalEdgeNorms(const CompactSparseMatrix &compact_matrix, const VariablesInfo &variables_info, const BasisFactorization &basis_factorization)
void SetParameters(const GlopParameters &parameters)
Sets the algorithm parameters.
PrimalEdgeNorms(const PrimalEdgeNorms &)=delete
This type is neither copyable nor movable.
StrictITISpan< ColIndex, const Fractional > ConstView
Definition lp_types.h:291
time_limit
Definition solve.cc:22
StrictITIVector< RowIndex, Fractional > DenseColumn
Column-vector types. Column-vector types are indexed by a row index.
Definition lp_types.h:380
StrictITIVector< ColIndex, Fractional > DenseRow
Row-vector types. Row-vector types are indexed by a column index.
Definition lp_types.h:351
static double DeterministicTimeForFpOperations(int64_t n)
Definition lp_types.h:433
In SWIG mode, we don't want anything besides these top-level includes.