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 
21 namespace operations_research {
22 namespace 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 
121 namespace {
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.
125 Fractional 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 {
195  transpose_lower_.HyperSparseSolveWithReversedNonZeros(
196  &dense_zero_scratchpad_, &non_zero_rows_);
197  }
198  return ComputeSquaredNormAndResetToZero(non_zero_rows_,
199  &dense_zero_scratchpad_);
200 }
201 
202 namespace {
203 // Returns whether 'b' is equal to 'a' permuted by the given row permutation
204 // 'perm'.
205 bool 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 
229 template <typename Column>
230 void 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)) {
248  DCHECK_EQ(1.0, lower_.GetDiagonalCoefficient(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_);
266  DCHECK(IsAllZero(x->values));
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_);
301  DCHECK(IsAllZero(x->values));
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_);
423  DCHECK(IsAllZero(y->values));
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 
548  return lower_.ComputeInverseInfinityNormUpperBound() *
550 }
551 
552 namespace {
553 // Returns the density of the sparse column 'b' w.r.t. the given permutation.
554 double 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 
566 void LuFactorization::ComputeTransposeUpper() {
567  SCOPED_TIME_STAT(&stats_);
568  transpose_upper_.PopulateFromTranspose(upper_);
569 }
570 
571 void LuFactorization::ComputeTransposeLower() const {
572  SCOPED_TIME_STAT(&stats_);
573  transpose_lower_.PopulateFromTranspose(lower_);
574 }
575 
576 bool 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
#define CHECK(condition)
Definition: base/logging.h:495
ColIndex RowToColIndex(RowIndex row)
Definition: lp_types.h:49
const bool DEBUG_MODE
Definition: macros.h:24
int64_t min
Definition: alldiff_cst.cc:139
Definition: sparse_column.h:28
void Reset(RowIndex num_rows, ColIndex col_capacity)
Definition: sparse.cc:551
RowToColMapping ComputeInitialBasis(const CompactSparseMatrix &matrix, const std::vector< ColIndex > &candidates)
ABSL_MUST_USE_RESULT Status ComputeFactorization(const CompactSparseMatrixView &compact_matrix)
void LeftSolveUWithNonZeros(ScatteredRow *y) const
void TransposeLowerSolve(DenseColumn *rhs) const
Definition: sparse.cc:858
void TransposeHyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:987
ABSL_MUST_USE_RESULT Status ComputeRowAndColumnPermutation(const CompactSparseMatrixView &basis_matrix, RowPermutation *row_perm, ColumnPermutation *col_perm)
Definition: markowitz.cc:27
#define VLOG(verboselevel)
Definition: base/logging.h:983
Fractional ComputeOneNormConditionNumber(const CompactSparseMatrixView &matrix) const
const ColIndex kInvalidCol(-1)
void PopulateFromTranspose(const TriangularMatrix &input)
Definition: sparse.cc:518
void UpperSolve(DenseColumn *rhs) const
Definition: sparse.cc:797
void LowerSolveStartingAt(ColIndex start, DenseColumn *rhs) const
Definition: sparse.cc:768
const SparseColumn & GetColumnOfU(ColIndex col) const
void ApplyInversePermutation(const Permutation< IndexType > &perm, const ITIVectorType &b, ITIVectorType *result)
ColIndex col
Definition: markowitz.cc:183
#define SCOPED_TIME_STAT(stats)
Definition: stats.h:438
void swap(StrongVector &x)
void ClearAndResizeVectorWithNonZeros(IndexType size, ScatteredRowOrCol *v)
static const Status OK()
Definition: status.h:56
void PermuteWithKnownNonZeros(const Permutation< IndexType > &permutation, StrictITIVector< IndexType, Fractional > *zero_scratchpad, StrictITIVector< IndexType, Fractional > *output, std::vector< IndexType > *non_zeros)
RowIndex row
Definition: markowitz.cc:182
const RowIndex kNonPivotal(-1)
void RightSolveUWithNonZeros(ScatteredColumn *x) const
#define GLOP_RETURN_IF_ERROR(function_call)
Definition: status.h:72
void LowerSolve(DenseColumn *rhs) const
Definition: sparse.cc:764
int64_t b
Fractional RightSolveSquaredNorm(const ColumnView &a) const
void ComputeRowsToConsiderInSortedOrder(RowIndexVector *non_zero_rows, Fractional sparsity_ratio, Fractional num_ops_ratio) const
Definition: sparse.cc:1343
void TransposeUpperSolve(DenseColumn *rhs) const
Definition: sparse.cc:828
int64_t max
Definition: alldiff_cst.cc:140
Fractional DualEdgeSquaredNorm(RowIndex row) const
bool LeftSolveLWithNonZeros(ScatteredRow *y, ScatteredColumn *result_before_permutation) const
ABSL_MUST_USE_RESULT Status ComputeLU(const CompactSparseMatrixView &basis_matrix, RowPermutation *row_perm, ColumnPermutation *col_perm, TriangularMatrix *lower, TriangularMatrix *upper)
Definition: markowitz.cc:149
#define DCHECK_NE(val1, val2)
Definition: base/logging.h:891
void CopyColumnToSparseColumn(ColIndex col, SparseColumn *output) const
Definition: sparse.cc:747
void SetCoefficient(Index index, Fractional value)
StrictITIVector< Index, Fractional > values
bool ColumnIsDiagonalOnly(ColIndex col) const
Definition: sparse.h:586
void RightSolveLForColumnView(const ColumnView &b, ScatteredColumn *x) const
void RightSolveLWithPermutedInput(const DenseColumn &a, ScatteredColumn *x) const
bool IsAllZero(const Container &input)
void push_back(const value_type &x)
void TransposeHyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:957
RowIndex ColToRowIndex(ColIndex col)
Definition: lp_types.h:52
void RightSolveLForScatteredColumn(const ScatteredColumn &b, ScatteredColumn *x) const
#define CHECK_EQ(val1, val2)
Definition: base/logging.h:702
void ApplyPermutation(const Permutation< IndexType > &perm, const ITIVectorType &b, ITIVectorType *result)
const RowIndex kInvalidRow(-1)
#define GLOP_RETURN_AND_LOG_ERROR(error_code, message)
Definition: status.h:79
std::vector< RowIndex > RowIndexVector
Definition: lp_types.h:313
double DeterministicTimeOfLastFactorization() const
Definition: markowitz.cc:553
Fractional GetDiagonalCoefficient(ColIndex col) const
Definition: sparse.h:581
#define DCHECK(condition)
Definition: base/logging.h:889
void PermuteWithScratchpad(const Permutation< PermutationIndexType > &permutation, StrictITIVector< IndexType, Fractional > *zero_scratchpad, StrictITIVector< IndexType, Fractional > *input_output)
double GetFillInPercentage(const CompactSparseMatrixView &matrix) const
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:890
Fractional Square(Fractional f)
void ComputeLowerTimesUpper(SparseMatrix *product) const
void RightSolveLWithNonZeros(ScatteredColumn *x) const
Collection of objects used to extend the Constraint Solver library.
Fractional SquaredNorm(const SparseColumn &v)
void HyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:896
Fractional ComputeInverseInfinityNormUpperBound() const
Definition: sparse.cc:1386
int64_t value
void PopulateFromInverse(const Permutation &inverse)
void HyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:926
Fractional ComputeInfinityNormConditionNumber(const CompactSparseMatrixView &matrix) const
ColIndex LeftSolveUForUnitRow(ColIndex col, ScatteredRow *y) const
#define IF_STATS_ENABLED(instructions)
Definition: stats.h:437
int64_t a