OR-Tools  9.0
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  return markowitz_.DeterministicTimeOfLastFactorization();
70 }
71 
73  SCOPED_TIME_STAT(&stats_);
74  if (is_identity_factorization_) return;
75 
76  ApplyPermutation(row_perm_, *x, &dense_column_scratchpad_);
77  lower_.LowerSolve(&dense_column_scratchpad_);
78  upper_.UpperSolve(&dense_column_scratchpad_);
79  ApplyPermutation(inverse_col_perm_, dense_column_scratchpad_, x);
80 }
81 
83  SCOPED_TIME_STAT(&stats_);
84  if (is_identity_factorization_) return;
85 
86  // We need to interpret y as a column for the permutation functions.
87  DenseColumn* const x = reinterpret_cast<DenseColumn*>(y);
88  ApplyInversePermutation(inverse_col_perm_, *x, &dense_column_scratchpad_);
89  upper_.TransposeUpperSolve(&dense_column_scratchpad_);
90  lower_.TransposeLowerSolve(&dense_column_scratchpad_);
91  ApplyInversePermutation(row_perm_, dense_column_scratchpad_, x);
92 }
93 
94 namespace {
95 // If non_zeros is empty, uses a dense algorithm to compute the squared L2
96 // norm of the given column, otherwise do the same with a sparse version. In
97 // both cases column is cleared.
98 Fractional ComputeSquaredNormAndResetToZero(
99  const std::vector<RowIndex>& non_zeros, DenseColumn* column) {
100  Fractional sum = 0.0;
101  if (non_zeros.empty()) {
102  sum = SquaredNorm(*column);
103  column->clear();
104  } else {
105  for (const RowIndex row : non_zeros) {
106  sum += Square((*column)[row]);
107  (*column)[row] = 0.0;
108  }
109  }
110  return sum;
111 }
112 } // namespace
113 
115  SCOPED_TIME_STAT(&stats_);
116  if (is_identity_factorization_) return SquaredNorm(a);
117 
118  non_zero_rows_.clear();
119  dense_zero_scratchpad_.resize(lower_.num_rows(), 0.0);
120  DCHECK(IsAllZero(dense_zero_scratchpad_));
121 
122  for (const SparseColumn::Entry e : a) {
123  const RowIndex permuted_row = row_perm_[e.row()];
124  dense_zero_scratchpad_[permuted_row] = e.coefficient();
125  non_zero_rows_.push_back(permuted_row);
126  }
127 
128  lower_.ComputeRowsToConsiderInSortedOrder(&non_zero_rows_);
129  if (non_zero_rows_.empty()) {
130  lower_.LowerSolve(&dense_zero_scratchpad_);
131  } else {
132  lower_.HyperSparseSolve(&dense_zero_scratchpad_, &non_zero_rows_);
133  upper_.ComputeRowsToConsiderInSortedOrder(&non_zero_rows_);
134  }
135  if (non_zero_rows_.empty()) {
136  upper_.UpperSolve(&dense_zero_scratchpad_);
137  } else {
138  upper_.HyperSparseSolveWithReversedNonZeros(&dense_zero_scratchpad_,
139  &non_zero_rows_);
140  }
141  return ComputeSquaredNormAndResetToZero(non_zero_rows_,
142  &dense_zero_scratchpad_);
143 }
144 
146  if (is_identity_factorization_) return 1.0;
147  SCOPED_TIME_STAT(&stats_);
148  const RowIndex permuted_row =
149  col_perm_.empty() ? row : ColToRowIndex(col_perm_[RowToColIndex(row)]);
150 
151  non_zero_rows_.clear();
152  dense_zero_scratchpad_.resize(lower_.num_rows(), 0.0);
153  DCHECK(IsAllZero(dense_zero_scratchpad_));
154  dense_zero_scratchpad_[permuted_row] = 1.0;
155  non_zero_rows_.push_back(permuted_row);
156 
157  transpose_upper_.ComputeRowsToConsiderInSortedOrder(&non_zero_rows_);
158  if (non_zero_rows_.empty()) {
159  transpose_upper_.LowerSolveStartingAt(RowToColIndex(permuted_row),
160  &dense_zero_scratchpad_);
161  } else {
162  transpose_upper_.HyperSparseSolve(&dense_zero_scratchpad_, &non_zero_rows_);
163  transpose_lower_.ComputeRowsToConsiderInSortedOrder(&non_zero_rows_);
164  }
165  if (non_zero_rows_.empty()) {
166  transpose_lower_.UpperSolve(&dense_zero_scratchpad_);
167  } else {
168  transpose_lower_.HyperSparseSolveWithReversedNonZeros(
169  &dense_zero_scratchpad_, &non_zero_rows_);
170  }
171  return ComputeSquaredNormAndResetToZero(non_zero_rows_,
172  &dense_zero_scratchpad_);
173 }
174 
175 namespace {
176 // Returns whether 'b' is equal to 'a' permuted by the given row permutation
177 // 'perm'.
178 bool AreEqualWithPermutation(const DenseColumn& a, const DenseColumn& b,
179  const RowPermutation& perm) {
180  const RowIndex num_rows = perm.size();
181  for (RowIndex row(0); row < num_rows; ++row) {
182  if (a[row] != b[perm[row]]) return false;
183  }
184  return true;
185 }
186 } // namespace
187 
189  ScatteredColumn* x) const {
190  SCOPED_TIME_STAT(&stats_);
191  if (!is_identity_factorization_) {
192  DCHECK(AreEqualWithPermutation(a, x->values, row_perm_));
194  if (x->non_zeros.empty()) {
195  lower_.LowerSolve(&x->values);
196  } else {
197  lower_.HyperSparseSolve(&x->values, &x->non_zeros);
198  }
199  }
200 }
201 
202 template <typename Column>
203 void LuFactorization::RightSolveLInternal(const Column& b,
204  ScatteredColumn* x) const {
205  // This code is equivalent to
206  // b.PermutedCopyToDenseVector(row_perm_, num_rows, x);
207  // but it also computes the first column index which does not correspond to an
208  // identity column of lower_ thus exploiting a bit the hyper-sparsity
209  // of b.
210  ColIndex first_column_to_consider(RowToColIndex(x->values.size()));
211  const ColIndex limit = lower_.GetFirstNonIdentityColumn();
212  for (const auto e : b) {
213  const RowIndex permuted_row = row_perm_[e.row()];
214  (*x)[permuted_row] = e.coefficient();
215  x->non_zeros.push_back(permuted_row);
216 
217  // The second condition only works because the elements on the diagonal of
218  // lower_ are all equal to 1.0.
219  const ColIndex col = RowToColIndex(permuted_row);
220  if (col < limit || lower_.ColumnIsDiagonalOnly(col)) {
221  DCHECK_EQ(1.0, lower_.GetDiagonalCoefficient(col));
222  continue;
223  }
224  first_column_to_consider = std::min(first_column_to_consider, col);
225  }
226 
228  x->non_zeros_are_sorted = true;
229  if (x->non_zeros.empty()) {
230  lower_.LowerSolveStartingAt(first_column_to_consider, &x->values);
231  } else {
232  lower_.HyperSparseSolve(&x->values, &x->non_zeros);
233  }
234 }
235 
237  ScatteredColumn* x) const {
238  SCOPED_TIME_STAT(&stats_);
239  DCHECK(IsAllZero(x->values));
240  x->non_zeros.clear();
241  if (is_identity_factorization_) {
242  for (const ColumnView::Entry e : b) {
243  (*x)[e.row()] = e.coefficient();
244  x->non_zeros.push_back(e.row());
245  }
246  return;
247  }
248 
249  RightSolveLInternal(b, x);
250 }
251 
253  if (is_identity_factorization_) return;
254  if (x->non_zeros.empty()) {
255  PermuteWithScratchpad(row_perm_, &dense_zero_scratchpad_, &x->values);
256  lower_.LowerSolve(&x->values);
257  return;
258  }
259 
260  PermuteWithKnownNonZeros(row_perm_, &dense_zero_scratchpad_, &x->values,
261  &x->non_zeros);
263  x->non_zeros_are_sorted = true;
264  if (x->non_zeros.empty()) {
265  lower_.LowerSolve(&x->values);
266  } else {
267  lower_.HyperSparseSolve(&x->values, &x->non_zeros);
268  }
269 }
270 
272  ScatteredColumn* x) const {
273  SCOPED_TIME_STAT(&stats_);
274  DCHECK(IsAllZero(x->values));
275  x->non_zeros.clear();
276 
277  if (is_identity_factorization_) {
278  *x = b;
279  return;
280  }
281 
282  if (b.non_zeros.empty()) {
283  *x = b;
284  return RightSolveLWithNonZeros(x);
285  }
286 
287  RightSolveLInternal(b, x);
288 }
289 
291  SCOPED_TIME_STAT(&stats_);
292  CHECK(col_perm_.empty());
293  if (is_identity_factorization_) return;
294 
295  DenseColumn* const x = reinterpret_cast<DenseColumn*>(&y->values);
296  RowIndexVector* const nz = reinterpret_cast<RowIndexVector*>(&y->non_zeros);
297  transpose_upper_.ComputeRowsToConsiderInSortedOrder(nz);
298  y->non_zeros_are_sorted = true;
299  if (nz->empty()) {
300  upper_.TransposeUpperSolve(x);
301  } else {
302  upper_.TransposeHyperSparseSolve(x, nz);
303  }
304 }
305 
307  SCOPED_TIME_STAT(&stats_);
308  CHECK(col_perm_.empty());
309  if (is_identity_factorization_) return;
310 
311  // If non-zeros is non-empty, we use an hypersparse solve. Note that if
312  // non_zeros starts to be too big, we clear it and thus switch back to a
313  // normal sparse solve.
314  upper_.ComputeRowsToConsiderInSortedOrder(&x->non_zeros, 0.1, 0.2);
315  x->non_zeros_are_sorted = true;
316  if (x->non_zeros.empty()) {
317  transpose_upper_.TransposeLowerSolve(&x->values);
318  } else {
320  &x->values, &x->non_zeros);
321  }
322 }
323 
325  ScatteredRow* y, ScatteredColumn* result_before_permutation) const {
326  SCOPED_TIME_STAT(&stats_);
327  if (is_identity_factorization_) {
328  // It is not advantageous to fill result_before_permutation in this case.
329  return false;
330  }
331  DenseColumn* const x = reinterpret_cast<DenseColumn*>(&y->values);
332  std::vector<RowIndex>* nz = reinterpret_cast<RowIndexVector*>(&y->non_zeros);
333 
334  // Hypersparse?
335  transpose_lower_.ComputeRowsToConsiderInSortedOrder(nz);
336  y->non_zeros_are_sorted = true;
337  if (nz->empty()) {
338  lower_.TransposeLowerSolve(x);
339  } else {
341  }
342 
343  if (result_before_permutation == nullptr) {
344  // Note(user): For the behavior of the two functions to be exactly the same,
345  // we need the positions listed in nz to be the "exact" non-zeros of x. This
346  // should be the case because the hyper-sparse functions makes sure of that.
347  // We also DCHECK() this below.
348  if (nz->empty()) {
349  PermuteWithScratchpad(inverse_row_perm_, &dense_zero_scratchpad_, x);
350  } else {
351  PermuteWithKnownNonZeros(inverse_row_perm_, &dense_zero_scratchpad_, x,
352  nz);
353  }
354  if (DEBUG_MODE) {
355  for (const RowIndex row : *nz) {
356  DCHECK_NE((*x)[row], 0.0);
357  }
358  }
359  return false;
360  }
361 
362  // This computes the same thing as in the other branch but also keeps the
363  // original x in result_before_permutation. Because of this, it is faster to
364  // use a different algorithm.
365  ClearAndResizeVectorWithNonZeros(x->size(), result_before_permutation);
366  x->swap(result_before_permutation->values);
367  if (nz->empty()) {
368  for (RowIndex row(0); row < inverse_row_perm_.size(); ++row) {
369  const Fractional value = (*result_before_permutation)[row];
370  if (value != 0.0) {
371  const RowIndex permuted_row = inverse_row_perm_[row];
372  (*x)[permuted_row] = value;
373  }
374  }
375  } else {
376  nz->swap(result_before_permutation->non_zeros);
377  nz->reserve(result_before_permutation->non_zeros.size());
378  for (const RowIndex row : result_before_permutation->non_zeros) {
379  const Fractional value = (*result_before_permutation)[row];
380  const RowIndex permuted_row = inverse_row_perm_[row];
381  (*x)[permuted_row] = value;
382  nz->push_back(permuted_row);
383  }
384  y->non_zeros_are_sorted = false;
385  }
386  return true;
387 }
388 
390  LeftSolveLWithNonZeros(y, nullptr);
391 }
392 
394  ScatteredRow* y) const {
395  SCOPED_TIME_STAT(&stats_);
396  DCHECK(IsAllZero(y->values));
397  DCHECK(y->non_zeros.empty());
398  if (is_identity_factorization_) {
399  (*y)[col] = 1.0;
400  y->non_zeros.push_back(col);
401  return col;
402  }
403  const ColIndex permuted_col = col_perm_.empty() ? col : col_perm_[col];
404  (*y)[permuted_col] = 1.0;
405  y->non_zeros.push_back(permuted_col);
406 
407  // Using the transposed matrix here is faster (even accounting the time to
408  // construct it). Note the small optimization in case the inversion is
409  // trivial.
410  if (transpose_upper_.ColumnIsDiagonalOnly(permuted_col)) {
411  (*y)[permuted_col] /= transpose_upper_.GetDiagonalCoefficient(permuted_col);
412  } else {
413  RowIndexVector* const nz = reinterpret_cast<RowIndexVector*>(&y->non_zeros);
414  DenseColumn* const x = reinterpret_cast<DenseColumn*>(&y->values);
415  transpose_upper_.ComputeRowsToConsiderInSortedOrder(nz);
416  y->non_zeros_are_sorted = true;
417  if (y->non_zeros.empty()) {
418  transpose_upper_.LowerSolveStartingAt(permuted_col, x);
419  } else {
420  transpose_upper_.HyperSparseSolve(x, nz);
421  }
422  }
423  return permuted_col;
424 }
425 
427  if (is_identity_factorization_) {
428  column_of_upper_.Clear();
429  column_of_upper_.SetCoefficient(ColToRowIndex(col), 1.0);
430  return column_of_upper_;
431  }
432  upper_.CopyColumnToSparseColumn(col_perm_.empty() ? col : col_perm_[col],
433  &column_of_upper_);
434  return column_of_upper_;
435 }
436 
438  const CompactSparseMatrixView& matrix) const {
439  const int initial_num_entries = matrix.num_entries().value();
440  const int lu_num_entries =
441  (lower_.num_entries() + upper_.num_entries()).value();
442  if (is_identity_factorization_ || initial_num_entries == 0) return 1.0;
443  return static_cast<double>(lu_num_entries) /
444  static_cast<double>(initial_num_entries);
445 }
446 
448  return is_identity_factorization_
449  ? EntryIndex(0)
450  : lower_.num_entries() + upper_.num_entries();
451 }
452 
454  if (is_identity_factorization_) return 1.0;
455  DCHECK_EQ(upper_.num_rows().value(), upper_.num_cols().value());
456  Fractional product(1.0);
457  for (ColIndex col(0); col < upper_.num_cols(); ++col) {
458  product *= upper_.GetDiagonalCoefficient(col);
459  }
460  return product * row_perm_.ComputeSignature() *
461  inverse_col_perm_.ComputeSignature();
462 }
463 
465  if (is_identity_factorization_) return 1.0;
466  const RowIndex num_rows = lower_.num_rows();
467  const ColIndex num_cols = lower_.num_cols();
468  Fractional norm = 0.0;
469  for (ColIndex col(0); col < num_cols; ++col) {
470  DenseColumn right_hand_side(num_rows, 0.0);
471  right_hand_side[ColToRowIndex(col)] = 1.0;
472  // Get a column of the matrix inverse.
473  RightSolve(&right_hand_side);
474  Fractional column_norm = 0.0;
475  // Compute sum_i |basis_matrix_ij|.
476  for (RowIndex row(0); row < num_rows; ++row) {
477  column_norm += std::abs(right_hand_side[row]);
478  }
479  // Compute max_j sum_i |basis_matrix_ij|
480  norm = std::max(norm, column_norm);
481  }
482  return norm;
483 }
484 
486  if (is_identity_factorization_) return 1.0;
487  const RowIndex num_rows = lower_.num_rows();
488  const ColIndex num_cols = lower_.num_cols();
489  DenseColumn row_sum(num_rows, 0.0);
490  for (ColIndex col(0); col < num_cols; ++col) {
491  DenseColumn right_hand_side(num_rows, 0.0);
492  right_hand_side[ColToRowIndex(col)] = 1.0;
493  // Get a column of the matrix inverse.
494  RightSolve(&right_hand_side);
495  // Compute sum_j |basis_matrix_ij|.
496  for (RowIndex row(0); row < num_rows; ++row) {
497  row_sum[row] += std::abs(right_hand_side[row]);
498  }
499  }
500  // Compute max_i sum_j |basis_matrix_ij|
501  Fractional norm = 0.0;
502  for (RowIndex row(0); row < num_rows; ++row) {
503  norm = std::max(norm, row_sum[row]);
504  }
505  return norm;
506 }
507 
509  const CompactSparseMatrixView& matrix) const {
510  if (is_identity_factorization_) return 1.0;
511  return matrix.ComputeOneNorm() * ComputeInverseOneNorm();
512 }
513 
515  const CompactSparseMatrixView& matrix) const {
516  if (is_identity_factorization_) return 1.0;
518 }
519 
521  return lower_.ComputeInverseInfinityNormUpperBound() *
523 }
524 
525 namespace {
526 // Returns the density of the sparse column 'b' w.r.t. the given permutation.
527 double ComputeDensity(const SparseColumn& b, const RowPermutation& row_perm) {
528  double density = 0.0;
529  for (const SparseColumn::Entry e : b) {
530  if (row_perm[e.row()] != kNonPivotal && e.coefficient() != 0.0) {
531  ++density;
532  }
533  }
534  const RowIndex num_rows = row_perm.size();
535  return density / num_rows.value();
536 }
537 } // anonymous namespace
538 
539 void LuFactorization::ComputeTransposeUpper() {
540  SCOPED_TIME_STAT(&stats_);
541  transpose_upper_.PopulateFromTranspose(upper_);
542 }
543 
544 void LuFactorization::ComputeTransposeLower() const {
545  SCOPED_TIME_STAT(&stats_);
546  transpose_lower_.PopulateFromTranspose(lower_);
547 }
548 
549 bool LuFactorization::CheckFactorization(const CompactSparseMatrixView& matrix,
550  Fractional tolerance) const {
551  if (is_identity_factorization_) return true;
552  SparseMatrix lu;
554  SparseMatrix paq;
555  paq.PopulateFromPermutedMatrix(matrix, row_perm_, inverse_col_perm_);
556  if (!row_perm_.Check()) {
557  return false;
558  }
559  if (!inverse_col_perm_.Check()) {
560  return false;
561  }
562 
563  SparseMatrix should_be_zero;
564  should_be_zero.PopulateFromLinearCombination(Fractional(1.0), paq,
565  Fractional(-1.0), lu);
566 
567  for (ColIndex col(0); col < should_be_zero.num_cols(); ++col) {
568  for (const SparseColumn::Entry e : should_be_zero.column(col)) {
569  const Fractional magnitude = std::abs(e.coefficient());
570  if (magnitude > tolerance) {
571  VLOG(2) << magnitude << " != 0, at column " << col;
572  return false;
573  }
574  }
575  }
576  return true;
577 }
578 
579 } // namespace glop
580 } // 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:498
#define DCHECK_NE(val1, val2)
Definition: base/logging.h:894
#define DCHECK(condition)
Definition: base/logging.h:892
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:893
#define VLOG(verboselevel)
Definition: base/logging.h:986
void swap(StrongVector &x)
void LeftSolveUWithNonZeros(ScatteredRow *y) const
const SparseColumn & GetColumnOfU(ColIndex col) const
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
void PopulateFromInverse(const Permutation &inverse)
Definition: sparse_column.h:28
void SetCoefficient(Index index, Fractional value)
static const Status OK()
Definition: status.h:54
void TransposeHyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:930
void UpperSolve(DenseColumn *rhs) const
Definition: sparse.cc:770
void HyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:869
Fractional GetDiagonalCoefficient(ColIndex col) const
Definition: sparse.h:572
void LowerSolve(DenseColumn *rhs) const
Definition: sparse.cc:737
void TransposeHyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:960
void LowerSolveStartingAt(ColIndex start, DenseColumn *rhs) const
Definition: sparse.cc:741
void PopulateFromTranspose(const TriangularMatrix &input)
Definition: sparse.cc:491
void CopyColumnToSparseColumn(ColIndex col, SparseColumn *output) const
Definition: sparse.cc:720
void ComputeRowsToConsiderInSortedOrder(RowIndexVector *non_zero_rows, Fractional sparsity_ratio, Fractional num_ops_ratio) const
Definition: sparse.cc:1316
void TransposeLowerSolve(DenseColumn *rhs) const
Definition: sparse.cc:831
void TransposeUpperSolve(DenseColumn *rhs) const
Definition: sparse.cc:801
Fractional ComputeInverseInfinityNormUpperBound() const
Definition: sparse.cc:1359
void Reset(RowIndex num_rows, ColIndex col_capacity)
Definition: sparse.cc:524
bool ColumnIsDiagonalOnly(ColIndex col) const
Definition: sparse.h:577
void HyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Definition: sparse.cc:899
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)
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:310
void ApplyPermutation(const Permutation< IndexType > &perm, const ITIVectorType &b, ITIVectorType *result)
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:70
#define GLOP_RETURN_AND_LOG_ERROR(error_code, message)
Definition: status.h:77
StrictITIVector< Index, Fractional > values