27 : is_identity_factorization_(true),
31 inverse_row_perm_() {}
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;
42 inverse_row_perm_.
clear();
43 inverse_col_perm_.
clear();
55 markowitz_.
ComputeLU(matrix, &row_perm_, &col_perm_, &lower_, &upper_));
58 ComputeTransposeUpper();
59 ComputeTransposeLower();
61 is_identity_factorization_ =
false;
64 stats_.basis_num_entries.Add(matrix.
num_entries().value());
66 DCHECK(CheckFactorization(matrix,
Fractional(1e-6)));
72 const std::vector<ColIndex>& candidates) {
87 CHECK_EQ(col_perm_.
size(), candidates.size());
88 for (
int i = 0; i < col_perm_.
size(); ++i) {
103 if (is_identity_factorization_)
return;
113 if (is_identity_factorization_)
return;
130 if (non_zeros.empty()) {
134 for (
const RowIndex
row : non_zeros) {
136 (*column)[
row] = 0.0;
147 non_zero_rows_.clear();
149 DCHECK(
IsAllZero(dense_zero_scratchpad_));
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);
158 if (non_zero_rows_.empty()) {
164 if (non_zero_rows_.empty()) {
170 return ComputeSquaredNormAndResetToZero(non_zero_rows_,
171 &dense_zero_scratchpad_);
175 if (is_identity_factorization_)
return 1.0;
177 const RowIndex permuted_row =
180 non_zero_rows_.clear();
182 DCHECK(
IsAllZero(dense_zero_scratchpad_));
183 dense_zero_scratchpad_[permuted_row] = 1.0;
184 non_zero_rows_.push_back(permuted_row);
187 if (non_zero_rows_.empty()) {
189 &dense_zero_scratchpad_);
191 transpose_upper_.
HyperSparseSolve(&dense_zero_scratchpad_, &non_zero_rows_);
194 if (non_zero_rows_.empty()) {
195 transpose_lower_.
UpperSolve(&dense_zero_scratchpad_);
198 &dense_zero_scratchpad_, &non_zero_rows_);
200 return ComputeSquaredNormAndResetToZero(non_zero_rows_,
201 &dense_zero_scratchpad_);
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;
220 if (!is_identity_factorization_) {
221 DCHECK(AreEqualWithPermutation(
a, x->
values, row_perm_));
231 template <
typename Column>
232 void LuFactorization::RightSolveLInternal(
const Column&
b,
241 for (
const auto e :
b) {
242 const RowIndex permuted_row = row_perm_[e.row()];
243 (*x)[permuted_row] = e.coefficient();
253 first_column_to_consider =
std::min(first_column_to_consider,
col);
270 if (is_identity_factorization_) {
272 (*x)[e.row()] = e.coefficient();
278 RightSolveLInternal(
b, x);
282 if (is_identity_factorization_)
return;
306 if (is_identity_factorization_) {
311 if (
b.non_zeros.empty()) {
316 RightSolveLInternal(
b, x);
321 CHECK(col_perm_.
empty());
322 if (is_identity_factorization_)
return;
337 CHECK(col_perm_.
empty());
338 if (is_identity_factorization_)
return;
356 if (is_identity_factorization_) {
372 if (result_before_permutation ==
nullptr) {
384 for (
const RowIndex
row : *nz) {
385 DCHECK_NE((*x)[
row], 0.0);
397 for (RowIndex
row(0);
row < inverse_row_perm_.
size(); ++
row) {
400 const RowIndex permuted_row = inverse_row_perm_[
row];
401 (*x)[permuted_row] =
value;
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) {
409 const RowIndex permuted_row = inverse_row_perm_[
row];
410 (*x)[permuted_row] =
value;
411 nz->push_back(permuted_row);
427 if (is_identity_factorization_) {
432 const ColIndex permuted_col = col_perm_.
empty() ?
col : col_perm_[
col];
433 (*y)[permuted_col] = 1.0;
456 if (is_identity_factorization_) {
457 column_of_upper_.
Clear();
459 return column_of_upper_;
463 return column_of_upper_;
468 const int initial_num_entries = matrix.
num_entries().value();
469 const int lu_num_entries =
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);
477 return is_identity_factorization_
483 if (is_identity_factorization_)
return 1.0;
494 if (is_identity_factorization_)
return 1.0;
495 const RowIndex num_rows = lower_.
num_rows();
496 const ColIndex num_cols = lower_.
num_cols();
498 for (ColIndex
col(0);
col < num_cols; ++
col) {
505 for (RowIndex
row(0);
row < num_rows; ++
row) {
506 column_norm += std::abs(right_hand_side[
row]);
515 if (is_identity_factorization_)
return 1.0;
516 const RowIndex num_rows = lower_.
num_rows();
517 const ColIndex num_cols = lower_.
num_cols();
519 for (ColIndex
col(0);
col < num_cols; ++
col) {
525 for (RowIndex
row(0);
row < num_rows; ++
row) {
526 row_sum[
row] += std::abs(right_hand_side[
row]);
531 for (RowIndex
row(0);
row < num_rows; ++
row) {
539 if (is_identity_factorization_)
return 1.0;
545 if (is_identity_factorization_)
return 1.0;
557 double density = 0.0;
559 if (row_perm[e.row()] !=
kNonPivotal && e.coefficient() != 0.0) {
563 const RowIndex num_rows = row_perm.
size();
564 return density / num_rows.value();
568 void LuFactorization::ComputeTransposeUpper() {
573 void LuFactorization::ComputeTransposeLower()
const {
578 bool LuFactorization::CheckFactorization(
const CompactSparseMatrixView& matrix,
580 if (is_identity_factorization_)
return true;
584 paq.PopulateFromPermutedMatrix(matrix, row_perm_, inverse_col_perm_);
585 if (!row_perm_.
Check()) {
588 if (!inverse_col_perm_.
Check()) {
592 SparseMatrix should_be_zero;
593 should_be_zero.PopulateFromLinearCombination(
Fractional(1.0), paq,
596 for (ColIndex
col(0);
col < should_be_zero.num_cols(); ++
col) {
598 const Fractional magnitude = std::abs(e.coefficient());
599 if (magnitude > tolerance) {
600 VLOG(2) << magnitude <<
" != 0, at column " <<
col;
void push_back(const value_type &x)
void swap(StrongVector &x)
ColIndex num_cols() const
RowIndex num_rows() const
Fractional ComputeInfinityNorm() const
ColIndex num_cols() const
Fractional ComputeOneNorm() const
RowIndex num_rows() const
EntryIndex num_entries() const
Fractional ComputeInverseOneNorm() const
void LeftSolveUWithNonZeros(ScatteredRow *y) const
const SparseColumn & GetColumnOfU(ColIndex col) const
Fractional ComputeInverseInfinityNorm() 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
double DeterministicTimeOfLastFactorization() const
void LeftSolve(DenseRow *y) const
bool LeftSolveLWithNonZeros(ScatteredRow *y, ScatteredColumn *result_before_permutation) const
void RightSolve(DenseColumn *x) 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 ComputeDeterminant() const
Fractional ComputeInfinityNormConditionNumber(const CompactSparseMatrixView &matrix) const
void ComputeLowerTimesUpper(SparseMatrix *product) const
ABSL_MUST_USE_RESULT Status ComputeFactorization(const CompactSparseMatrixView &compact_matrix)
EntryIndex NumberOfEntries() const
Fractional ComputeInverseInfinityNormUpperBound() const
Fractional ComputeOneNormConditionNumber(const CompactSparseMatrixView &matrix) const
double DeterministicTimeOfLastFactorization() const
ABSL_MUST_USE_RESULT Status ComputeLU(const CompactSparseMatrixView &basis_matrix, RowPermutation *row_perm, ColumnPermutation *col_perm, TriangularMatrix *lower, TriangularMatrix *upper)
ABSL_MUST_USE_RESULT Status ComputeRowAndColumnPermutation(const CompactSparseMatrixView &basis_matrix, RowPermutation *row_perm, ColumnPermutation *col_perm)
int ComputeSignature() const
void PopulateFromInverse(const Permutation &inverse)
typename Iterator::Entry Entry
void SetCoefficient(Index index, Fractional value)
void resize(IntType size)
void TransposeHyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
void UpperSolve(DenseColumn *rhs) const
void HyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
ColIndex GetFirstNonIdentityColumn() const
ColIndex num_cols() const
Fractional GetDiagonalCoefficient(ColIndex col) const
void LowerSolve(DenseColumn *rhs) const
void TransposeHyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
void LowerSolveStartingAt(ColIndex start, DenseColumn *rhs) const
void PopulateFromTranspose(const TriangularMatrix &input)
void CopyColumnToSparseColumn(ColIndex col, SparseColumn *output) const
RowIndex num_rows() const
void ComputeRowsToConsiderInSortedOrder(RowIndexVector *non_zero_rows, Fractional sparsity_ratio, Fractional num_ops_ratio) const
void TransposeLowerSolve(DenseColumn *rhs) const
void TransposeUpperSolve(DenseColumn *rhs) const
Fractional ComputeInverseInfinityNormUpperBound() const
void Reset(RowIndex num_rows, ColIndex col_capacity)
bool ColumnIsDiagonalOnly(ColIndex col) const
void HyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
EntryIndex num_entries() const
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)
constexpr RowIndex kInvalidRow(-1)
void ClearAndResizeVectorWithNonZeros(IndexType size, ScatteredRowOrCol *v)
RowIndex ColToRowIndex(ColIndex col)
const RowIndex kNonPivotal(-1)
std::vector< RowIndex > RowIndexVector
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)
#define SCOPED_TIME_STAT(stats)
#define GLOP_RETURN_IF_ERROR(function_call)
#define GLOP_RETURN_AND_LOG_ERROR(error_code, message)
bool non_zeros_are_sorted
std::vector< Index > non_zeros
StrictITIVector< Index, Fractional > values
#define VLOG(verboselevel)