30 const Fractional EtaMatrix::kSparseThreshold = 0.5;
37 DCHECK_NE(0.0, eta_col_coefficient_);
38 eta_coeff_ = direction.
values;
43 kSparseThreshold * eta_coeff_.
size().value()) {
57 if (!sparse_eta_coeff_.
IsEmpty()) {
58 LeftSolveWithSparseEta(y);
60 LeftSolveWithDenseEta(y);
66 DCHECK_EQ(eta_coeff_.
size(), d->
size());
71 if (!sparse_eta_coeff_.
IsEmpty()) {
72 RightSolveWithSparseEta(d);
74 RightSolveWithDenseEta(d);
83 bool is_eta_col_in_pos =
false;
84 const int size = pos->size();
85 for (
int i = 0; i < size; ++i) {
86 const ColIndex
col = (*pos)[i];
88 if (
col == eta_col_) {
89 is_eta_col_in_pos =
true;
92 y_value -= (*y)[
col] * eta_coeff_[
row];
95 (*y)[eta_col_] = y_value / eta_col_coefficient_;
98 if (!is_eta_col_in_pos) pos->push_back(eta_col_);
101 void EtaMatrix::LeftSolveWithDenseEta(
DenseRow* y)
const {
103 const RowIndex num_rows(eta_coeff_.
size());
104 for (RowIndex
row(0);
row < num_rows; ++
row) {
107 (*y)[eta_col_] = y_value / eta_col_coefficient_;
110 void EtaMatrix::LeftSolveWithSparseEta(
DenseRow* y)
const {
115 (*y)[eta_col_] = y_value / eta_col_coefficient_;
118 void EtaMatrix::RightSolveWithDenseEta(
DenseColumn* d)
const {
120 const Fractional coeff = (*d)[eta_row] / eta_col_coefficient_;
121 const RowIndex num_rows(eta_coeff_.
size());
122 for (RowIndex
row(0);
row < num_rows; ++
row) {
123 (*d)[
row] -= eta_coeff_[
row] * coeff;
125 (*d)[eta_row] = coeff;
128 void EtaMatrix::RightSolveWithSparseEta(
DenseColumn* d)
const {
130 const Fractional coeff = (*d)[eta_row] / eta_col_coefficient_;
132 (*d)[e.row()] -= e.coefficient() * coeff;
134 (*d)[eta_row] = coeff;
147 RowIndex leaving_variable_row,
149 const ColIndex leaving_variable_col =
RowToColIndex(leaving_variable_row);
151 new EtaMatrix(leaving_variable_col, direction);
152 eta_matrix_.push_back(eta_factorization);
157 for (
int i = eta_matrix_.size() - 1; i >= 0; --i) {
158 eta_matrix_[i]->LeftSolve(y);
164 for (
int i = eta_matrix_.size() - 1; i >= 0; --i) {
165 eta_matrix_[i]->SparseLeftSolve(y, pos);
171 const size_t num_eta_matrices = eta_matrix_.size();
172 for (
int i = 0; i < num_eta_matrices; ++i) {
173 eta_matrix_[i]->RightSolve(d);
183 compact_matrix_(*compact_matrix),
185 tau_is_computed_(false),
188 eta_factorization_(),
190 deterministic_time_(0.0) {
199 tau_computation_can_be_optimized_ =
false;
200 eta_factorization_.
Clear();
201 lu_factorization_.
Clear();
202 rank_one_factorization_.
Clear();
205 left_pool_mapping_.
clear();
206 right_pool_mapping_.
clear();
213 return ComputeFactorization();
217 const std::vector<ColIndex>& candidates) {
220 deterministic_time_ +=
234 stats_.refactorization_interval.Add(num_updates_);
236 return ComputeFactorization();
239 Status BasisFactorization::ComputeFactorization() {
242 last_factorization_deterministic_time_ =
244 deterministic_time_ += last_factorization_deterministic_time_;
257 Status BasisFactorization::MiddleProductFormUpdate(
258 ColIndex entering_col, RowIndex leaving_variable_row) {
259 const ColIndex right_index = entering_col < right_pool_mapping_.
size()
260 ? right_pool_mapping_[entering_col]
262 const ColIndex left_index =
267 LOG(INFO) <<
"One update vector is missing!!!";
275 const auto view = right_storage_.
view();
276 for (
const EntryIndex i : view.Column(right_index)) {
277 const RowIndex
row = view.EntryRow(i);
278 scratchpad_[
row] = view.EntryCoefficient(i);
279 scratchpad_non_zeros_.push_back(
row);
282 const SparseColumn& column_of_u =
285 scratchpad_[e.row()] -= e.coefficient();
286 scratchpad_non_zeros_.push_back(e.row());
293 &scratchpad_, &scratchpad_non_zeros_);
294 RankOneUpdateElementaryMatrix elementary_update_matrix(
295 &storage_, u_index, left_index, scalar_product);
296 if (elementary_update_matrix.IsSingular()) {
299 rank_one_factorization_.
Update(elementary_update_matrix);
304 RowIndex leaving_variable_row,
309 if (num_updates_ >= max_num_updates_) {
310 if (!parameters_.dynamically_adjust_refactorization_period()) {
320 if (last_factorization_deterministic_time_ <
331 if (use_middle_product_form_update_) {
333 MiddleProductFormUpdate(entering_col, leaving_variable_row));
335 eta_factorization_.
Update(entering_col, leaving_variable_row, direction);
337 tau_computation_can_be_optimized_ =
false;
344 if (use_middle_product_form_update_) {
360 if (use_middle_product_form_update_) {
376 if (use_middle_product_form_update_) {
377 if (tau_computation_can_be_optimized_) {
380 tau_computation_can_be_optimized_ =
false;
394 tau_is_computed_ =
true;
405 if (!use_middle_product_form_update_) {
418 if (j >= left_pool_mapping_.
size()) {
442 if (tau_is_computed_) {
443 tau_computation_can_be_optimized_ =
446 tau_computation_can_be_optimized_ =
false;
449 tau_is_computed_ =
false;
473 if (!use_middle_product_form_update_) {
485 if (
col >= right_pool_mapping_.
size()) {
494 right_pool_mapping_[
col] =
506 BumpDeterministicTimeForSolve(
a.num_entries().value());
513 BumpDeterministicTimeForSolve(1);
517 bool BasisFactorization::IsIdentityBasis()
const {
518 const RowIndex num_rows = compact_matrix_.
num_rows();
519 for (RowIndex
row(0);
row < num_rows; ++
row) {
520 const ColIndex
col = basis_[
row];
524 if (entry_row !=
row || coeff != 1.0)
return false;
530 if (IsIdentityBasis())
return 1.0;
536 if (IsIdentityBasis())
return 1.0;
545 if (IsIdentityBasis())
return 1.0;
546 const RowIndex num_rows = compact_matrix_.
num_rows();
549 for (ColIndex
col(0);
col < num_cols; ++
col) {
557 for (RowIndex
row(0);
row < num_rows; ++
row) {
558 column_norm += std::abs(right_hand_side[
row]);
567 if (IsIdentityBasis())
return 1.0;
568 const RowIndex num_rows = compact_matrix_.
num_rows();
571 for (ColIndex
col(0);
col < num_cols; ++
col) {
578 for (RowIndex
row(0);
row < num_rows; ++
row) {
579 row_sum[
row] += std::abs(right_hand_side[
row]);
584 for (RowIndex
row(0);
row < num_rows; ++
row) {
591 if (IsIdentityBasis())
return 1.0;
596 if (IsIdentityBasis())
return 1.0;
602 if (IsIdentityBasis())
return 1.0;
603 BumpDeterministicTimeForSolve(compact_matrix_.
num_rows().value());
609 return deterministic_time_;
612 void BasisFactorization::BumpDeterministicTimeForSolve(
int num_entries)
const {
614 if (compact_matrix_.
num_rows().value() == 0)
return;
615 const double density =
617 static_cast<double>(compact_matrix_.
num_rows().value());
618 deterministic_time_ +=
Fractional ComputeInverseOneNorm() const
BasisFactorization(const CompactSparseMatrix *compact_matrix, const RowToColMapping *basis)
Fractional ComputeInfinityNormConditionNumberUpperBound() const
ABSL_MUST_USE_RESULT Status Refactorize()
Fractional ComputeInverseInfinityNorm() const
Fractional ComputeInfinityNorm() const
const DenseColumn & RightSolveForTau(const ScatteredColumn &a) const
void LeftSolveForUnitRow(ColIndex j, ScatteredRow *y) const
Fractional RightSolveSquaredNorm(const ColumnView &a) const
Fractional ComputeOneNorm() const
Fractional ComputeOneNormConditionNumber() const
ABSL_MUST_USE_RESULT Status Initialize()
bool IsRefactorized() const
void TemporaryLeftSolveForUnitRow(ColIndex j, ScatteredRow *y) const
ABSL_MUST_USE_RESULT Status Update(ColIndex entering_col, RowIndex leaving_variable_row, const ScatteredColumn &direction)
virtual ~BasisFactorization()
Fractional DualEdgeSquaredNorm(RowIndex row) const
RowToColMapping ComputeInitialBasis(const std::vector< ColIndex > &candidates)
void LeftSolve(ScatteredRow *y) const
void RightSolveForProblemColumn(ColIndex col, ScatteredColumn *d) const
Fractional ComputeInfinityNormConditionNumber() const
void SetParameters(const GlopParameters ¶meters)
void RightSolve(ScatteredColumn *d) const
double DeterministicTime() const
ABSL_MUST_USE_RESULT Status ForceRefactorization()
RowIndex GetFirstRow() const
Fractional GetFirstCoefficient() const
EntryIndex num_entries() const
ColIndex AddDenseColumn(const DenseColumn &dense_column)
ColIndex AddDenseColumnWithNonZeros(const DenseColumn &dense_column, const std::vector< RowIndex > &non_zeros)
ColIndex AddAndClearColumnWithNonZeros(DenseColumn *column, std::vector< RowIndex > *non_zeros)
void ColumnCopyToClearedDenseColumnWithNonZeros(ColIndex col, DenseColumn *dense_column, RowIndexVector *non_zeros) const
ColIndex AddDenseColumnPrefix(const DenseColumn &dense_column, RowIndex start)
RowIndex num_rows() const
void ColumnCopyToClearedDenseColumn(ColIndex col, DenseColumn *dense_column) const
Fractional ColumnScalarProduct(ColIndex col, const DenseRow &vector) const
void Reset(RowIndex num_rows)
ColumnView column(ColIndex col) const
Fractional ComputeInfinityNorm() const
Fractional ComputeOneNorm() const
void RightSolve(DenseColumn *d) const
void LeftSolve(DenseRow *y) const
virtual ~EtaFactorization()
void SparseLeftSolve(DenseRow *y, ColIndexVector *pos) const
void Update(ColIndex entering_col, RowIndex leaving_variable_row, const ScatteredColumn &direction)
void RightSolve(DenseColumn *d) const
void LeftSolve(DenseRow *y) const
EtaMatrix(ColIndex eta_col, const ScatteredColumn &direction)
void SparseLeftSolve(DenseRow *y, ColIndexVector *pos) const
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
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
ABSL_MUST_USE_RESULT Status ComputeFactorization(const CompactSparseMatrixView &compact_matrix)
EntryIndex NumberOfEntries() const
Fractional ComputeInverseInfinityNormUpperBound() const
void RightSolveWithNonZeros(ScatteredColumn *d) const
void LeftSolveWithNonZeros(ScatteredRow *y) const
void ResetDeterministicTime()
double DeterministicTimeSinceLastReset() const
void Update(const RankOneUpdateElementaryMatrix &update_matrix)
EntryIndex num_entries() const
bool CheckNoDuplicates() const
typename Iterator::Entry Entry
void SetCoefficient(Index index, Fractional value)
void AssignToZero(IntType size)
void resize(IntType size)
void STLDeleteElements(T *container)
constexpr ColIndex kInvalidCol(-1)
std::vector< ColIndex > ColIndexVector
bool IsAllZero(const Container &input)
StrictITIVector< ColIndex, Fractional > DenseRow
ColIndex RowToColIndex(RowIndex row)
void ClearAndResizeVectorWithNonZeros(IndexType size, ScatteredRowOrCol *v)
const DenseRow & Transpose(const DenseColumn &col)
RowIndex ColToRowIndex(ColIndex col)
std::vector< RowIndex > RowIndexVector
StrictITIVector< RowIndex, Fractional > DenseColumn
static double DeterministicTimeForFpOperations(int64_t n)
Collection of objects used to extend the Constraint Solver library.
#define RETURN_IF_NULL(x)
#define SCOPED_TIME_STAT(stats)
#define GLOP_RETURN_IF_ERROR(function_call)
#define GLOP_RETURN_AND_LOG_ERROR(error_code, message)
void SortNonZerosIfNeeded()
size_t NumNonZerosEstimate() const
std::vector< Index > non_zeros
StrictITIVector< Index, Fractional > values