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