25 : is_identity_factorization_(true),
29 inverse_row_perm_() {}
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;
40 inverse_row_perm_.
clear();
41 inverse_col_perm_.
clear();
53 markowitz_.
ComputeLU(matrix, &row_perm_, &col_perm_, &lower_, &upper_));
56 ComputeTransposeUpper();
57 ComputeTransposeLower();
59 is_identity_factorization_ =
false;
62 stats_.basis_num_entries.Add(matrix.
num_entries().value());
70 const std::vector<ColIndex>& candidates) {
86 for (
int i = 0; i < col_perm_.
size(); ++i) {
101 if (is_identity_factorization_)
return;
111 if (is_identity_factorization_)
return;
126 const std::vector<RowIndex>& non_zeros,
DenseColumn* column) {
128 if (non_zeros.empty()) {
132 for (
const RowIndex
row : non_zeros) {
134 (*column)[
row] = 0.0;
145 non_zero_rows_.clear();
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);
156 if (non_zero_rows_.empty()) {
162 if (non_zero_rows_.empty()) {
168 return ComputeSquaredNormAndResetToZero(non_zero_rows_,
169 &dense_zero_scratchpad_);
173 if (is_identity_factorization_)
return 1.0;
175 const RowIndex permuted_row =
178 non_zero_rows_.clear();
181 dense_zero_scratchpad_[permuted_row] = 1.0;
182 non_zero_rows_.push_back(permuted_row);
185 if (non_zero_rows_.empty()) {
187 &dense_zero_scratchpad_);
189 transpose_upper_.
HyperSparseSolve(&dense_zero_scratchpad_, &non_zero_rows_);
192 if (non_zero_rows_.empty()) {
193 transpose_lower_.
UpperSolve(&dense_zero_scratchpad_);
196 &dense_zero_scratchpad_, &non_zero_rows_);
198 return ComputeSquaredNormAndResetToZero(non_zero_rows_,
199 &dense_zero_scratchpad_);
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;
218 if (!is_identity_factorization_) {
229template <
typename Column>
230void LuFactorization::RightSolveLInternal(
const Column&
b,
239 for (
const auto e :
b) {
240 const RowIndex permuted_row = row_perm_[e.row()];
241 (*x)[permuted_row] = e.coefficient();
251 first_column_to_consider =
std::min(first_column_to_consider,
col);
268 if (is_identity_factorization_) {
270 (*x)[e.row()] = e.coefficient();
276 RightSolveLInternal(
b, x);
280 if (is_identity_factorization_)
return;
304 if (is_identity_factorization_) {
309 if (
b.non_zeros.empty()) {
314 RightSolveLInternal(
b, x);
320 if (is_identity_factorization_)
return;
336 if (is_identity_factorization_)
return;
354 if (is_identity_factorization_) {
370 if (result_before_permutation ==
nullptr) {
382 for (
const RowIndex
row : *nz) {
395 for (RowIndex
row(0);
row < inverse_row_perm_.
size(); ++
row) {
398 const RowIndex permuted_row = inverse_row_perm_[
row];
399 (*x)[permuted_row] =
value;
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) {
407 const RowIndex permuted_row = inverse_row_perm_[
row];
408 (*x)[permuted_row] =
value;
409 nz->push_back(permuted_row);
425 if (is_identity_factorization_) {
430 const ColIndex permuted_col = col_perm_.
empty() ?
col : col_perm_[
col];
431 (*y)[permuted_col] = 1.0;
454 if (is_identity_factorization_) {
455 column_of_upper_.
Clear();
457 return column_of_upper_;
461 return column_of_upper_;
466 const int initial_num_entries = matrix.
num_entries().value();
467 const int lu_num_entries =
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);
475 return is_identity_factorization_
481 if (is_identity_factorization_)
return 1.0;
492 if (is_identity_factorization_)
return 1.0;
493 const RowIndex num_rows = lower_.
num_rows();
494 const ColIndex num_cols = lower_.
num_cols();
496 for (ColIndex
col(0);
col < num_cols; ++
col) {
503 for (RowIndex
row(0);
row < num_rows; ++
row) {
504 column_norm += std::abs(right_hand_side[
row]);
513 if (is_identity_factorization_)
return 1.0;
514 const RowIndex num_rows = lower_.
num_rows();
515 const ColIndex num_cols = lower_.
num_cols();
517 for (ColIndex
col(0);
col < num_cols; ++
col) {
523 for (RowIndex
row(0);
row < num_rows; ++
row) {
524 row_sum[
row] += std::abs(right_hand_side[
row]);
529 for (RowIndex
row(0);
row < num_rows; ++
row) {
537 if (is_identity_factorization_)
return 1.0;
543 if (is_identity_factorization_)
return 1.0;
555 double density = 0.0;
557 if (row_perm[e.row()] !=
kNonPivotal && e.coefficient() != 0.0) {
561 const RowIndex num_rows = row_perm.
size();
562 return density / num_rows.value();
566void LuFactorization::ComputeTransposeUpper() {
571void LuFactorization::ComputeTransposeLower()
const {
576bool LuFactorization::CheckFactorization(
const CompactSparseMatrixView& matrix,
578 if (is_identity_factorization_)
return true;
582 paq.PopulateFromPermutedMatrix(matrix, row_perm_, inverse_col_perm_);
583 if (!row_perm_.
Check()) {
586 if (!inverse_col_perm_.
Check()) {
590 SparseMatrix should_be_zero;
591 should_be_zero.PopulateFromLinearCombination(
Fractional(1.0), paq,
594 for (ColIndex
col(0);
col < should_be_zero.num_cols(); ++
col) {
596 const Fractional magnitude = std::abs(e.coefficient());
597 if (magnitude > tolerance) {
598 VLOG(2) << magnitude <<
" != 0, at column " <<
col;
#define DCHECK_NE(val1, val2)
#define CHECK_EQ(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
#define VLOG(verboselevel)
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
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)
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)
const ColIndex kInvalidCol(-1)
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