OR-Tools  9.2
lu_factorization.cc
Go to the documentation of this file.
1// Copyright 2010-2021 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#include <cstddef>
17
20
21namespace operations_research {
22namespace glop {
23
25 : is_identity_factorization_(true),
26 col_perm_(),
27 inverse_col_perm_(),
28 row_perm_(),
29 inverse_row_perm_() {}
30
32 SCOPED_TIME_STAT(&stats_);
33 lower_.Reset(RowIndex(0), ColIndex(0));
34 upper_.Reset(RowIndex(0), ColIndex(0));
35 transpose_upper_.Reset(RowIndex(0), ColIndex(0));
36 transpose_lower_.Reset(RowIndex(0), ColIndex(0));
37 is_identity_factorization_ = true;
38 col_perm_.clear();
39 row_perm_.clear();
40 inverse_row_perm_.clear();
41 inverse_col_perm_.clear();
42}
43
45 const CompactSparseMatrixView& matrix) {
46 SCOPED_TIME_STAT(&stats_);
47 Clear();
48 if (matrix.num_rows().value() != matrix.num_cols().value()) {
49 GLOP_RETURN_AND_LOG_ERROR(Status::ERROR_LU, "Not a square matrix!!");
50 }
51
53 markowitz_.ComputeLU(matrix, &row_perm_, &col_perm_, &lower_, &upper_));
54 inverse_col_perm_.PopulateFromInverse(col_perm_);
55 inverse_row_perm_.PopulateFromInverse(row_perm_);
56 ComputeTransposeUpper();
57 ComputeTransposeLower();
58
59 is_identity_factorization_ = false;
61 stats_.lu_fill_in.Add(GetFillInPercentage(matrix));
62 stats_.basis_num_entries.Add(matrix.num_entries().value());
63 });
64 DCHECK(CheckFactorization(matrix, Fractional(1e-6)));
65 return Status::OK();
66}
67
69 const CompactSparseMatrix& matrix,
70 const std::vector<ColIndex>& candidates) {
71 CompactSparseMatrixView view(&matrix, &candidates);
72 (void)markowitz_.ComputeRowAndColumnPermutation(view, &row_perm_, &col_perm_);
73
74 // Starts by the missing slacks.
75 RowToColMapping basis;
76 for (RowIndex row(0); row < matrix.num_rows(); ++row) {
77 if (row_perm_[row] == kInvalidRow) {
78 // Add the slack for this row.
79 basis.push_back(matrix.num_cols() +
80 RowToColIndex(row - matrix.num_rows()));
81 }
82 }
83
84 // Then add the used candidate columns.
85 CHECK_EQ(col_perm_.size(), candidates.size());
86 for (int i = 0; i < col_perm_.size(); ++i) {
87 if (col_perm_[ColIndex(i)] != kInvalidCol) {
88 basis.push_back(candidates[i]);
89 }
90 }
91
92 return basis;
93}
94
96 return markowitz_.DeterministicTimeOfLastFactorization();
97}
98
100 SCOPED_TIME_STAT(&stats_);
101 if (is_identity_factorization_) return;
102
103 ApplyPermutation(row_perm_, *x, &dense_column_scratchpad_);
104 lower_.LowerSolve(&dense_column_scratchpad_);
105 upper_.UpperSolve(&dense_column_scratchpad_);
106 ApplyPermutation(inverse_col_perm_, dense_column_scratchpad_, x);
107}
108
110 SCOPED_TIME_STAT(&stats_);
111 if (is_identity_factorization_) return;
112
113 // We need to interpret y as a column for the permutation functions.
114 DenseColumn* const x = reinterpret_cast<DenseColumn*>(y);
115 ApplyInversePermutation(inverse_col_perm_, *x, &dense_column_scratchpad_);
116 upper_.TransposeUpperSolve(&dense_column_scratchpad_);
117 lower_.TransposeLowerSolve(&dense_column_scratchpad_);
118 ApplyInversePermutation(row_perm_, dense_column_scratchpad_, x);
119}
120
121namespace {
122// If non_zeros is empty, uses a dense algorithm to compute the squared L2
123// norm of the given column, otherwise do the same with a sparse version. In
124// both cases column is cleared.
125Fractional ComputeSquaredNormAndResetToZero(
126 const std::vector<RowIndex>& non_zeros, DenseColumn* column) {
127 Fractional sum = 0.0;
128 if (non_zeros.empty()) {
129 sum = SquaredNorm(*column);
130 column->clear();
131 } else {
132 for (const RowIndex row : non_zeros) {
133 sum += Square((*column)[row]);
134 (*column)[row] = 0.0;
135 }
136 }
137 return sum;
138}
139} // namespace
140
142 SCOPED_TIME_STAT(&stats_);
143 if (is_identity_factorization_) return SquaredNorm(a);
144
145 non_zero_rows_.clear();
146 dense_zero_scratchpad_.resize(lower_.num_rows(), 0.0);
147 DCHECK(IsAllZero(dense_zero_scratchpad_));
148
149 for (const SparseColumn::Entry e : a) {
150 const RowIndex permuted_row = row_perm_[e.row()];
151 dense_zero_scratchpad_[permuted_row] = e.coefficient();
152 non_zero_rows_.push_back(permuted_row);
153 }
154
155 lower_.ComputeRowsToConsiderInSortedOrder(&non_zero_rows_);
156 if (non_zero_rows_.empty()) {
157 lower_.LowerSolve(&dense_zero_scratchpad_);
158 } else {
159 lower_.HyperSparseSolve(&dense_zero_scratchpad_, &non_zero_rows_);
160 upper_.ComputeRowsToConsiderInSortedOrder(&non_zero_rows_);
161 }
162 if (non_zero_rows_.empty()) {
163 upper_.UpperSolve(&dense_zero_scratchpad_);
164 } else {
165 upper_.HyperSparseSolveWithReversedNonZeros(&dense_zero_scratchpad_,
166 &non_zero_rows_);
167 }
168 return ComputeSquaredNormAndResetToZero(non_zero_rows_,
169 &dense_zero_scratchpad_);
170}
171
173 if (is_identity_factorization_) return 1.0;
174 SCOPED_TIME_STAT(&stats_);
175 const RowIndex permuted_row =
176 col_perm_.empty() ? row : ColToRowIndex(col_perm_[RowToColIndex(row)]);
177
178 non_zero_rows_.clear();
179 dense_zero_scratchpad_.resize(lower_.num_rows(), 0.0);
180 DCHECK(IsAllZero(dense_zero_scratchpad_));
181 dense_zero_scratchpad_[permuted_row] = 1.0;
182 non_zero_rows_.push_back(permuted_row);
183
184 transpose_upper_.ComputeRowsToConsiderInSortedOrder(&non_zero_rows_);
185 if (non_zero_rows_.empty()) {
186 transpose_upper_.LowerSolveStartingAt(RowToColIndex(permuted_row),
187 &dense_zero_scratchpad_);
188 } else {
189 transpose_upper_.HyperSparseSolve(&dense_zero_scratchpad_, &non_zero_rows_);
190 transpose_lower_.ComputeRowsToConsiderInSortedOrder(&non_zero_rows_);
191 }
192 if (non_zero_rows_.empty()) {
193 transpose_lower_.UpperSolve(&dense_zero_scratchpad_);
194 } else {
196 &dense_zero_scratchpad_, &non_zero_rows_);
197 }
198 return ComputeSquaredNormAndResetToZero(non_zero_rows_,
199 &dense_zero_scratchpad_);
200}
201
202namespace {
203// Returns whether 'b' is equal to 'a' permuted by the given row permutation
204// 'perm'.
205bool AreEqualWithPermutation(const DenseColumn& a, const DenseColumn& b,
206 const RowPermutation& perm) {
207 const RowIndex num_rows = perm.size();
208 for (RowIndex row(0); row < num_rows; ++row) {
209 if (a[row] != b[perm[row]]) return false;
210 }
211 return true;
212}
213} // namespace
214
216 ScatteredColumn* x) const {
217 SCOPED_TIME_STAT(&stats_);
218 if (!is_identity_factorization_) {
219 DCHECK(AreEqualWithPermutation(a, x->values, row_perm_));
221 if (x->non_zeros.empty()) {
222 lower_.LowerSolve(&x->values);
223 } else {
224 lower_.HyperSparseSolve(&x->values, &x->non_zeros);
225 }
226 }
227}
228
229template <typename Column>
230void LuFactorization::RightSolveLInternal(const Column& b,
231 ScatteredColumn* x) const {
232 // This code is equivalent to
233 // b.PermutedCopyToDenseVector(row_perm_, num_rows, x);
234 // but it also computes the first column index which does not correspond to an
235 // identity column of lower_ thus exploiting a bit the hyper-sparsity
236 // of b.
237 ColIndex first_column_to_consider(RowToColIndex(x->values.size()));
238 const ColIndex limit = lower_.GetFirstNonIdentityColumn();
239 for (const auto e : b) {
240 const RowIndex permuted_row = row_perm_[e.row()];
241 (*x)[permuted_row] = e.coefficient();
242 x->non_zeros.push_back(permuted_row);
243
244 // The second condition only works because the elements on the diagonal of
245 // lower_ are all equal to 1.0.
246 const ColIndex col = RowToColIndex(permuted_row);
247 if (col < limit || lower_.ColumnIsDiagonalOnly(col)) {
249 continue;
250 }
251 first_column_to_consider = std::min(first_column_to_consider, col);
252 }
253
255 x->non_zeros_are_sorted = true;
256 if (x->non_zeros.empty()) {
257 lower_.LowerSolveStartingAt(first_column_to_consider, &x->values);
258 } else {
259 lower_.HyperSparseSolve(&x->values, &x->non_zeros);
260 }
261}
262
264 ScatteredColumn* x) const {
265 SCOPED_TIME_STAT(&stats_);
267 x->non_zeros.clear();
268 if (is_identity_factorization_) {
269 for (const ColumnView::Entry e : b) {
270 (*x)[e.row()] = e.coefficient();
271 x->non_zeros.push_back(e.row());
272 }
273 return;
274 }
275
276 RightSolveLInternal(b, x);
277}
278
280 if (is_identity_factorization_) return;
281 if (x->non_zeros.empty()) {
282 PermuteWithScratchpad(row_perm_, &dense_zero_scratchpad_, &x->values);
283 lower_.LowerSolve(&x->values);
284 return;
285 }
286
287 PermuteWithKnownNonZeros(row_perm_, &dense_zero_scratchpad_, &x->values,
288 &x->non_zeros);
290 x->non_zeros_are_sorted = true;
291 if (x->non_zeros.empty()) {
292 lower_.LowerSolve(&x->values);
293 } else {
294 lower_.HyperSparseSolve(&x->values, &x->non_zeros);
295 }
296}
297
299 ScatteredColumn* x) const {
300 SCOPED_TIME_STAT(&stats_);
302 x->non_zeros.clear();
303
304 if (is_identity_factorization_) {
305 *x = b;
306 return;
307 }
308
309 if (b.non_zeros.empty()) {
310 *x = b;
311 return RightSolveLWithNonZeros(x);
312 }
313
314 RightSolveLInternal(b, x);
315}
316
318 SCOPED_TIME_STAT(&stats_);
319 CHECK(col_perm_.empty());
320 if (is_identity_factorization_) return;
321
322 DenseColumn* const x = reinterpret_cast<DenseColumn*>(&y->values);
323 RowIndexVector* const nz = reinterpret_cast<RowIndexVector*>(&y->non_zeros);
324 transpose_upper_.ComputeRowsToConsiderInSortedOrder(nz);
325 y->non_zeros_are_sorted = true;
326 if (nz->empty()) {
327 upper_.TransposeUpperSolve(x);
328 } else {
329 upper_.TransposeHyperSparseSolve(x, nz);
330 }
331}
332
334 SCOPED_TIME_STAT(&stats_);
335 CHECK(col_perm_.empty());
336 if (is_identity_factorization_) return;
337
338 // If non-zeros is non-empty, we use an hypersparse solve. Note that if
339 // non_zeros starts to be too big, we clear it and thus switch back to a
340 // normal sparse solve.
341 upper_.ComputeRowsToConsiderInSortedOrder(&x->non_zeros, 0.1, 0.2);
342 x->non_zeros_are_sorted = true;
343 if (x->non_zeros.empty()) {
344 transpose_upper_.TransposeLowerSolve(&x->values);
345 } else {
347 &x->values, &x->non_zeros);
348 }
349}
350
352 ScatteredRow* y, ScatteredColumn* result_before_permutation) const {
353 SCOPED_TIME_STAT(&stats_);
354 if (is_identity_factorization_) {
355 // It is not advantageous to fill result_before_permutation in this case.
356 return false;
357 }
358 DenseColumn* const x = reinterpret_cast<DenseColumn*>(&y->values);
359 std::vector<RowIndex>* nz = reinterpret_cast<RowIndexVector*>(&y->non_zeros);
360
361 // Hypersparse?
362 transpose_lower_.ComputeRowsToConsiderInSortedOrder(nz);
363 y->non_zeros_are_sorted = true;
364 if (nz->empty()) {
365 lower_.TransposeLowerSolve(x);
366 } else {
368 }
369
370 if (result_before_permutation == nullptr) {
371 // Note(user): For the behavior of the two functions to be exactly the same,
372 // we need the positions listed in nz to be the "exact" non-zeros of x. This
373 // should be the case because the hyper-sparse functions makes sure of that.
374 // We also DCHECK() this below.
375 if (nz->empty()) {
376 PermuteWithScratchpad(inverse_row_perm_, &dense_zero_scratchpad_, x);
377 } else {
378 PermuteWithKnownNonZeros(inverse_row_perm_, &dense_zero_scratchpad_, x,
379 nz);
380 }
381 if (DEBUG_MODE) {
382 for (const RowIndex row : *nz) {
383 DCHECK_NE((*x)[row], 0.0);
384 }
385 }
386 return false;
387 }
388
389 // This computes the same thing as in the other branch but also keeps the
390 // original x in result_before_permutation. Because of this, it is faster to
391 // use a different algorithm.
392 ClearAndResizeVectorWithNonZeros(x->size(), result_before_permutation);
393 x->swap(result_before_permutation->values);
394 if (nz->empty()) {
395 for (RowIndex row(0); row < inverse_row_perm_.size(); ++row) {
396 const Fractional value = (*result_before_permutation)[row];
397 if (value != 0.0) {
398 const RowIndex permuted_row = inverse_row_perm_[row];
399 (*x)[permuted_row] = value;
400 }
401 }
402 } else {
403 nz->swap(result_before_permutation->non_zeros);
404 nz->reserve(result_before_permutation->non_zeros.size());
405 for (const RowIndex row : result_before_permutation->non_zeros) {
406 const Fractional value = (*result_before_permutation)[row];
407 const RowIndex permuted_row = inverse_row_perm_[row];
408 (*x)[permuted_row] = value;
409 nz->push_back(permuted_row);
410 }
411 y->non_zeros_are_sorted = false;
412 }
413 return true;
414}
415
417 LeftSolveLWithNonZeros(y, nullptr);
418}
419
421 ScatteredRow* y) const {
422 SCOPED_TIME_STAT(&stats_);
424 DCHECK(y->non_zeros.empty());
425 if (is_identity_factorization_) {
426 (*y)[col] = 1.0;
427 y->non_zeros.push_back(col);
428 return col;
429 }
430 const ColIndex permuted_col = col_perm_.empty() ? col : col_perm_[col];
431 (*y)[permuted_col] = 1.0;
432 y->non_zeros.push_back(permuted_col);
433
434 // Using the transposed matrix here is faster (even accounting the time to
435 // construct it). Note the small optimization in case the inversion is
436 // trivial.
437 if (transpose_upper_.ColumnIsDiagonalOnly(permuted_col)) {
438 (*y)[permuted_col] /= transpose_upper_.GetDiagonalCoefficient(permuted_col);
439 } else {
440 RowIndexVector* const nz = reinterpret_cast<RowIndexVector*>(&y->non_zeros);
441 DenseColumn* const x = reinterpret_cast<DenseColumn*>(&y->values);
442 transpose_upper_.ComputeRowsToConsiderInSortedOrder(nz);
443 y->non_zeros_are_sorted = true;
444 if (y->non_zeros.empty()) {
445 transpose_upper_.LowerSolveStartingAt(permuted_col, x);
446 } else {
447 transpose_upper_.HyperSparseSolve(x, nz);
448 }
449 }
450 return permuted_col;
451}
452
454 if (is_identity_factorization_) {
455 column_of_upper_.Clear();
456 column_of_upper_.SetCoefficient(ColToRowIndex(col), 1.0);
457 return column_of_upper_;
458 }
459 upper_.CopyColumnToSparseColumn(col_perm_.empty() ? col : col_perm_[col],
460 &column_of_upper_);
461 return column_of_upper_;
462}
463
465 const CompactSparseMatrixView& matrix) const {
466 const int initial_num_entries = matrix.num_entries().value();
467 const int lu_num_entries =
468 (lower_.num_entries() + upper_.num_entries()).value();
469 if (is_identity_factorization_ || initial_num_entries == 0) return 1.0;
470 return static_cast<double>(lu_num_entries) /
471 static_cast<double>(initial_num_entries);
472}
473
475 return is_identity_factorization_
476 ? EntryIndex(0)
477 : lower_.num_entries() + upper_.num_entries();
478}
479
481 if (is_identity_factorization_) return 1.0;
482 DCHECK_EQ(upper_.num_rows().value(), upper_.num_cols().value());
483 Fractional product(1.0);
484 for (ColIndex col(0); col < upper_.num_cols(); ++col) {
485 product *= upper_.GetDiagonalCoefficient(col);
486 }
487 return product * row_perm_.ComputeSignature() *
488 inverse_col_perm_.ComputeSignature();
489}
490
492 if (is_identity_factorization_) return 1.0;
493 const RowIndex num_rows = lower_.num_rows();
494 const ColIndex num_cols = lower_.num_cols();
495 Fractional norm = 0.0;
496 for (ColIndex col(0); col < num_cols; ++col) {
497 DenseColumn right_hand_side(num_rows, 0.0);
498 right_hand_side[ColToRowIndex(col)] = 1.0;
499 // Get a column of the matrix inverse.
500 RightSolve(&right_hand_side);
501 Fractional column_norm = 0.0;
502 // Compute sum_i |basis_matrix_ij|.
503 for (RowIndex row(0); row < num_rows; ++row) {
504 column_norm += std::abs(right_hand_side[row]);
505 }
506 // Compute max_j sum_i |basis_matrix_ij|
507 norm = std::max(norm, column_norm);
508 }
509 return norm;
510}
511
513 if (is_identity_factorization_) return 1.0;
514 const RowIndex num_rows = lower_.num_rows();
515 const ColIndex num_cols = lower_.num_cols();
516 DenseColumn row_sum(num_rows, 0.0);
517 for (ColIndex col(0); col < num_cols; ++col) {
518 DenseColumn right_hand_side(num_rows, 0.0);
519 right_hand_side[ColToRowIndex(col)] = 1.0;
520 // Get a column of the matrix inverse.
521 RightSolve(&right_hand_side);
522 // Compute sum_j |basis_matrix_ij|.
523 for (RowIndex row(0); row < num_rows; ++row) {
524 row_sum[row] += std::abs(right_hand_side[row]);
525 }
526 }
527 // Compute max_i sum_j |basis_matrix_ij|
528 Fractional norm = 0.0;
529 for (RowIndex row(0); row < num_rows; ++row) {
530 norm = std::max(norm, row_sum[row]);
531 }
532 return norm;
533}
534
536 const CompactSparseMatrixView& matrix) const {
537 if (is_identity_factorization_) return 1.0;
538 return matrix.ComputeOneNorm() * ComputeInverseOneNorm();
539}
540
542 const CompactSparseMatrixView& matrix) const {
543 if (is_identity_factorization_) return 1.0;
545}
546
550}
551
552namespace {
553// Returns the density of the sparse column 'b' w.r.t. the given permutation.
554double ComputeDensity(const SparseColumn& b, const RowPermutation& row_perm) {
555 double density = 0.0;
556 for (const SparseColumn::Entry e : b) {
557 if (row_perm[e.row()] != kNonPivotal && e.coefficient() != 0.0) {
558 ++density;
559 }
560 }
561 const RowIndex num_rows = row_perm.size();
562 return density / num_rows.value();
563}
564} // anonymous namespace
565
566void LuFactorization::ComputeTransposeUpper() {
567 SCOPED_TIME_STAT(&stats_);
568 transpose_upper_.PopulateFromTranspose(upper_);
569}
570
571void LuFactorization::ComputeTransposeLower() const {
572 SCOPED_TIME_STAT(&stats_);
573 transpose_lower_.PopulateFromTranspose(lower_);
574}
575
576bool LuFactorization::CheckFactorization(const CompactSparseMatrixView& matrix,
577 Fractional tolerance) const {
578 if (is_identity_factorization_) return true;
579 SparseMatrix lu;
581 SparseMatrix paq;
582 paq.PopulateFromPermutedMatrix(matrix, row_perm_, inverse_col_perm_);
583 if (!row_perm_.Check()) {
584 return false;
585 }
586 if (!inverse_col_perm_.Check()) {
587 return false;
588 }
589
590 SparseMatrix should_be_zero;
591 should_be_zero.PopulateFromLinearCombination(Fractional(1.0), paq,
592 Fractional(-1.0), lu);
593
594 for (ColIndex col(0); col < should_be_zero.num_cols(); ++col) {
595 for (const SparseColumn::Entry e : should_be_zero.column(col)) {
596 const Fractional magnitude = std::abs(e.coefficient());
597 if (magnitude > tolerance) {
598 VLOG(2) << magnitude << " != 0, at column " << col;
599 return false;
600 }
601 }
602 }
603 return true;
604}
605
606} // namespace glop
607} // namespace operations_research
int64_t max
Definition: alldiff_cst.cc:140
int64_t min
Definition: alldiff_cst.cc:139
#define CHECK(condition)
Definition: base/logging.h:495
#define DCHECK_NE(val1, val2)
Definition: base/logging.h:891
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:702
#define DCHECK(condition)
Definition: base/logging.h:889
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:890
#define VLOG(verboselevel)
Definition: base/logging.h:983
void push_back(const value_type &x)
void swap(StrongVector &x)
void LeftSolveUWithNonZeros(ScatteredRow *y) const
const SparseColumn & GetColumnOfU(ColIndex col) const
RowToColMapping ComputeInitialBasis(const CompactSparseMatrix &matrix, const std::vector< ColIndex > &candidates)
void RightSolveLForColumnView(const ColumnView &b, ScatteredColumn *x) const
void RightSolveLWithPermutedInput(const DenseColumn &a, ScatteredColumn *x) const
double GetFillInPercentage(const CompactSparseMatrixView &matrix) const
Fractional RightSolveSquaredNorm(const ColumnView &a) const
void RightSolveUWithNonZeros(ScatteredColumn *x) const
bool LeftSolveLWithNonZeros(ScatteredRow *y, ScatteredColumn *result_before_permutation) const
ColIndex LeftSolveUForUnitRow(ColIndex col, ScatteredRow *y) const
Fractional DualEdgeSquaredNorm(RowIndex row) const
void RightSolveLForScatteredColumn(const ScatteredColumn &b, ScatteredColumn *x) const
void RightSolveLWithNonZeros(ScatteredColumn *x) const
Fractional ComputeInfinityNormConditionNumber(const CompactSparseMatrixView &matrix) const
void ComputeLowerTimesUpper(SparseMatrix *product) const
ABSL_MUST_USE_RESULT Status ComputeFactorization(const CompactSparseMatrixView &compact_matrix)
Fractional ComputeOneNormConditionNumber(const CompactSparseMatrixView &matrix) const
double DeterministicTimeOfLastFactorization() const
Definition: markowitz.cc:553
ABSL_MUST_USE_RESULT Status ComputeLU(const CompactSparseMatrixView &basis_matrix, RowPermutation *row_perm, ColumnPermutation *col_perm, TriangularMatrix *lower, TriangularMatrix *upper)
Definition: markowitz.cc:149
ABSL_MUST_USE_RESULT Status ComputeRowAndColumnPermutation(const CompactSparseMatrixView &basis_matrix, RowPermutation *row_perm, ColumnPermutation *col_perm)
Definition: markowitz.cc:27
void PopulateFromInverse(const Permutation &inverse)
Definition: sparse_column.h:28
void SetCoefficient(Index index, Fractional value)
static const Status OK()
Definition: status.h:56
void TransposeHyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:957
void UpperSolve(DenseColumn *rhs) const
Definition: sparse.cc:797
void HyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:896
Fractional GetDiagonalCoefficient(ColIndex col) const
Definition: sparse.h:581
void LowerSolve(DenseColumn *rhs) const
Definition: sparse.cc:764
void TransposeHyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:987
void LowerSolveStartingAt(ColIndex start, DenseColumn *rhs) const
Definition: sparse.cc:768
void PopulateFromTranspose(const TriangularMatrix &input)
Definition: sparse.cc:518
void CopyColumnToSparseColumn(ColIndex col, SparseColumn *output) const
Definition: sparse.cc:747
void ComputeRowsToConsiderInSortedOrder(RowIndexVector *non_zero_rows, Fractional sparsity_ratio, Fractional num_ops_ratio) const
Definition: sparse.cc:1343
void TransposeLowerSolve(DenseColumn *rhs) const
Definition: sparse.cc:858
void TransposeUpperSolve(DenseColumn *rhs) const
Definition: sparse.cc:828
Fractional ComputeInverseInfinityNormUpperBound() const
Definition: sparse.cc:1386
void Reset(RowIndex num_rows, ColIndex col_capacity)
Definition: sparse.cc:551
bool ColumnIsDiagonalOnly(ColIndex col) const
Definition: sparse.h:586
void HyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:926
int64_t b
int64_t a
int64_t value
const bool DEBUG_MODE
Definition: macros.h:24
ColIndex col
Definition: markowitz.cc:183
RowIndex row
Definition: markowitz.cc:182
void PermuteWithScratchpad(const Permutation< PermutationIndexType > &permutation, StrictITIVector< IndexType, Fractional > *zero_scratchpad, StrictITIVector< IndexType, Fractional > *input_output)
Fractional Square(Fractional f)
Fractional SquaredNorm(const SparseColumn &v)
void ApplyInversePermutation(const Permutation< IndexType > &perm, const ITIVectorType &b, ITIVectorType *result)
const RowIndex kInvalidRow(-1)
bool IsAllZero(const Container &input)
void PermuteWithKnownNonZeros(const Permutation< IndexType > &permutation, StrictITIVector< IndexType, Fractional > *zero_scratchpad, StrictITIVector< IndexType, Fractional > *output, std::vector< IndexType > *non_zeros)
ColIndex RowToColIndex(RowIndex row)
Definition: lp_types.h:49
void ClearAndResizeVectorWithNonZeros(IndexType size, ScatteredRowOrCol *v)
RowIndex ColToRowIndex(ColIndex col)
Definition: lp_types.h:52
const RowIndex kNonPivotal(-1)
std::vector< RowIndex > RowIndexVector
Definition: lp_types.h:313
void ApplyPermutation(const Permutation< IndexType > &perm, const ITIVectorType &b, ITIVectorType *result)
const ColIndex kInvalidCol(-1)
Collection of objects used to extend the Constraint Solver library.
#define IF_STATS_ENABLED(instructions)
Definition: stats.h:437
#define SCOPED_TIME_STAT(stats)
Definition: stats.h:438
#define GLOP_RETURN_IF_ERROR(function_call)
Definition: status.h:72
#define GLOP_RETURN_AND_LOG_ERROR(error_code, message)
Definition: status.h:79
StrictITIVector< Index, Fractional > values