OR-Tools  9.1
basis_representation.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 "ortools/base/stl_util.h"
17 #include "ortools/glop/status.h"
19 
20 namespace operations_research {
21 namespace glop {
22 
23 // --------------------------------------------------------
24 // EtaMatrix
25 // --------------------------------------------------------
26 
27 const Fractional EtaMatrix::kSparseThreshold = 0.5;
28 
29 EtaMatrix::EtaMatrix(ColIndex eta_col, const ScatteredColumn& direction)
30  : eta_col_(eta_col),
31  eta_col_coefficient_(direction[ColToRowIndex(eta_col)]),
32  eta_coeff_(),
33  sparse_eta_coeff_() {
34  DCHECK_NE(0.0, eta_col_coefficient_);
35  eta_coeff_ = direction.values;
36  eta_coeff_[ColToRowIndex(eta_col_)] = 0.0;
37 
38  // Only fill sparse_eta_coeff_ if it is sparse enough.
39  if (direction.non_zeros.size() <
40  kSparseThreshold * eta_coeff_.size().value()) {
41  for (const RowIndex row : direction.non_zeros) {
42  if (row == ColToRowIndex(eta_col)) continue;
43  sparse_eta_coeff_.SetCoefficient(row, eta_coeff_[row]);
44  }
45  DCHECK(sparse_eta_coeff_.CheckNoDuplicates());
46  }
47 }
48 
50 
52  RETURN_IF_NULL(y);
53  DCHECK_EQ(RowToColIndex(eta_coeff_.size()), y->size());
54  if (!sparse_eta_coeff_.IsEmpty()) {
55  LeftSolveWithSparseEta(y);
56  } else {
57  LeftSolveWithDenseEta(y);
58  }
59 }
60 
62  RETURN_IF_NULL(d);
63  DCHECK_EQ(eta_coeff_.size(), d->size());
64 
65  // Nothing to do if 'a' is zero at position eta_row.
66  // This exploits the possible sparsity of the column 'a'.
67  if ((*d)[ColToRowIndex(eta_col_)] == 0.0) return;
68  if (!sparse_eta_coeff_.IsEmpty()) {
69  RightSolveWithSparseEta(d);
70  } else {
71  RightSolveWithDenseEta(d);
72  }
73 }
74 
76  RETURN_IF_NULL(y);
77  DCHECK_EQ(RowToColIndex(eta_coeff_.size()), y->size());
78 
79  Fractional y_value = (*y)[eta_col_];
80  bool is_eta_col_in_pos = false;
81  const int size = pos->size();
82  for (int i = 0; i < size; ++i) {
83  const ColIndex col = (*pos)[i];
84  const RowIndex row = ColToRowIndex(col);
85  if (col == eta_col_) {
86  is_eta_col_in_pos = true;
87  continue;
88  }
89  y_value -= (*y)[col] * eta_coeff_[row];
90  }
91 
92  (*y)[eta_col_] = y_value / eta_col_coefficient_;
93 
94  // We add the new non-zero position if it wasn't already there.
95  if (!is_eta_col_in_pos) pos->push_back(eta_col_);
96 }
97 
98 void EtaMatrix::LeftSolveWithDenseEta(DenseRow* y) const {
99  Fractional y_value = (*y)[eta_col_];
100  const RowIndex num_rows(eta_coeff_.size());
101  for (RowIndex row(0); row < num_rows; ++row) {
102  y_value -= (*y)[RowToColIndex(row)] * eta_coeff_[row];
103  }
104  (*y)[eta_col_] = y_value / eta_col_coefficient_;
105 }
106 
107 void EtaMatrix::LeftSolveWithSparseEta(DenseRow* y) const {
108  Fractional y_value = (*y)[eta_col_];
109  for (const SparseColumn::Entry e : sparse_eta_coeff_) {
110  y_value -= (*y)[RowToColIndex(e.row())] * e.coefficient();
111  }
112  (*y)[eta_col_] = y_value / eta_col_coefficient_;
113 }
114 
115 void EtaMatrix::RightSolveWithDenseEta(DenseColumn* d) const {
116  const RowIndex eta_row = ColToRowIndex(eta_col_);
117  const Fractional coeff = (*d)[eta_row] / eta_col_coefficient_;
118  const RowIndex num_rows(eta_coeff_.size());
119  for (RowIndex row(0); row < num_rows; ++row) {
120  (*d)[row] -= eta_coeff_[row] * coeff;
121  }
122  (*d)[eta_row] = coeff;
123 }
124 
125 void EtaMatrix::RightSolveWithSparseEta(DenseColumn* d) const {
126  const RowIndex eta_row = ColToRowIndex(eta_col_);
127  const Fractional coeff = (*d)[eta_row] / eta_col_coefficient_;
128  for (const SparseColumn::Entry e : sparse_eta_coeff_) {
129  (*d)[e.row()] -= e.coefficient() * coeff;
130  }
131  (*d)[eta_row] = coeff;
132 }
133 
134 // --------------------------------------------------------
135 // EtaFactorization
136 // --------------------------------------------------------
138 
140 
142 
143 void EtaFactorization::Update(ColIndex entering_col,
144  RowIndex leaving_variable_row,
145  const ScatteredColumn& direction) {
146  const ColIndex leaving_variable_col = RowToColIndex(leaving_variable_row);
147  EtaMatrix* const eta_factorization =
148  new EtaMatrix(leaving_variable_col, direction);
149  eta_matrix_.push_back(eta_factorization);
150 }
151 
153  RETURN_IF_NULL(y);
154  for (int i = eta_matrix_.size() - 1; i >= 0; --i) {
155  eta_matrix_[i]->LeftSolve(y);
156  }
157 }
158 
160  RETURN_IF_NULL(y);
161  for (int i = eta_matrix_.size() - 1; i >= 0; --i) {
162  eta_matrix_[i]->SparseLeftSolve(y, pos);
163  }
164 }
165 
167  RETURN_IF_NULL(d);
168  const size_t num_eta_matrices = eta_matrix_.size();
169  for (int i = 0; i < num_eta_matrices; ++i) {
170  eta_matrix_[i]->RightSolve(d);
171  }
172 }
173 
174 // --------------------------------------------------------
175 // BasisFactorization
176 // --------------------------------------------------------
178  const CompactSparseMatrix* compact_matrix, const RowToColMapping* basis)
179  : stats_(),
180  compact_matrix_(*compact_matrix),
181  basis_(*basis),
182  tau_is_computed_(false),
183  max_num_updates_(0),
184  num_updates_(0),
185  eta_factorization_(),
186  lu_factorization_(),
187  deterministic_time_(0.0) {
188  SetParameters(parameters_);
189 }
190 
192 
194  SCOPED_TIME_STAT(&stats_);
195  num_updates_ = 0;
196  tau_computation_can_be_optimized_ = false;
197  eta_factorization_.Clear();
198  lu_factorization_.Clear();
199  rank_one_factorization_.Clear();
200  storage_.Reset(compact_matrix_.num_rows());
201  right_storage_.Reset(compact_matrix_.num_rows());
202  left_pool_mapping_.clear();
203  right_pool_mapping_.clear();
204 }
205 
207  SCOPED_TIME_STAT(&stats_);
208  Clear();
209  if (IsIdentityBasis()) return Status::OK();
210  return ComputeFactorization();
211 }
212 
214  const std::vector<ColIndex>& candidates) {
215  const RowToColMapping basis =
216  lu_factorization_.ComputeInitialBasis(compact_matrix_, candidates);
217  deterministic_time_ +=
218  lu_factorization_.DeterministicTimeOfLastFactorization();
219  return basis;
220 }
221 
222 bool BasisFactorization::IsRefactorized() const { return num_updates_ == 0; }
223 
225  if (IsRefactorized()) return Status::OK();
226  return ForceRefactorization();
227 }
228 
230  SCOPED_TIME_STAT(&stats_);
231  stats_.refactorization_interval.Add(num_updates_);
232  Clear();
233  return ComputeFactorization();
234 }
235 
236 Status BasisFactorization::ComputeFactorization() {
237  CompactSparseMatrixView basis_matrix(&compact_matrix_, &basis_);
238  const Status status = lu_factorization_.ComputeFactorization(basis_matrix);
239  last_factorization_deterministic_time_ =
240  lu_factorization_.DeterministicTimeOfLastFactorization();
241  deterministic_time_ += last_factorization_deterministic_time_;
242  rank_one_factorization_.ResetDeterministicTime();
243  return status;
244 }
245 
246 // This update formula can be derived by:
247 // e = unit vector on the leaving_variable_row
248 // new B = L.U + (matrix.column(entering_col) - B.e).e^T
249 // new B = L.U + L.L^{-1}.(matrix.column(entering_col) - B.e).e^T.U^{-1}.U
250 // new B = L.(Identity +
251 // (right_update_vector - U.column(leaving_column)).left_update_vector).U
252 // new B = L.RankOneUpdateElementatyMatrix(
253 // right_update_vector - U.column(leaving_column), left_update_vector)
254 Status BasisFactorization::MiddleProductFormUpdate(
255  ColIndex entering_col, RowIndex leaving_variable_row) {
256  const ColIndex right_index = entering_col < right_pool_mapping_.size()
257  ? right_pool_mapping_[entering_col]
258  : kInvalidCol;
259  const ColIndex left_index =
260  RowToColIndex(leaving_variable_row) < left_pool_mapping_.size()
261  ? left_pool_mapping_[RowToColIndex(leaving_variable_row)]
262  : kInvalidCol;
263  if (right_index == kInvalidCol || left_index == kInvalidCol) {
264  LOG(INFO) << "One update vector is missing!!!";
265  return ForceRefactorization();
266  }
267 
268  // TODO(user): create a class for these operations.
269  // Initialize scratchpad_ with the right update vector.
270  DCHECK(IsAllZero(scratchpad_));
271  scratchpad_.resize(right_storage_.num_rows(), 0.0);
272  for (const EntryIndex i : right_storage_.Column(right_index)) {
273  const RowIndex row = right_storage_.EntryRow(i);
274  scratchpad_[row] = right_storage_.EntryCoefficient(i);
275  scratchpad_non_zeros_.push_back(row);
276  }
277  // Subtract the column of U from scratchpad_.
278  const SparseColumn& column_of_u =
279  lu_factorization_.GetColumnOfU(RowToColIndex(leaving_variable_row));
280  for (const SparseColumn::Entry e : column_of_u) {
281  scratchpad_[e.row()] -= e.coefficient();
282  scratchpad_non_zeros_.push_back(e.row());
283  }
284 
285  // Creates the new rank one update matrix and update the factorization.
286  const Fractional scalar_product =
287  storage_.ColumnScalarProduct(left_index, Transpose(scratchpad_));
288  const ColIndex u_index = storage_.AddAndClearColumnWithNonZeros(
289  &scratchpad_, &scratchpad_non_zeros_);
290  RankOneUpdateElementaryMatrix elementary_update_matrix(
291  &storage_, u_index, left_index, scalar_product);
292  if (elementary_update_matrix.IsSingular()) {
293  GLOP_RETURN_AND_LOG_ERROR(Status::ERROR_LU, "Degenerate rank-one update.");
294  }
295  rank_one_factorization_.Update(elementary_update_matrix);
296  return Status::OK();
297 }
298 
299 Status BasisFactorization::Update(ColIndex entering_col,
300  RowIndex leaving_variable_row,
301  const ScatteredColumn& direction) {
302  // Note that in addition to the logic here, we also refactorize when we detect
303  // numerical imprecisions. There is various tests for that during an
304  // iteration.
305  if (num_updates_ >= max_num_updates_) {
306  if (!parameters_.dynamically_adjust_refactorization_period()) {
307  return ForceRefactorization();
308  }
309 
310  // We try to equilibrate the factorization time with the EXTRA solve time
311  // incurred since the last factorization.
312  //
313  // Note(user): The deterministic time is not really super precise for now.
314  // We tend to undercount the factorization, but this tends to favorize more
315  // refactorization which is good for numerical stability.
316  if (last_factorization_deterministic_time_ <
317  rank_one_factorization_.DeterministicTimeSinceLastReset()) {
318  return ForceRefactorization();
319  }
320  }
321 
322  // Note(user): in some rare case (to investigate!) MiddleProductFormUpdate()
323  // will trigger a full refactorization. Because of this, it is important to
324  // increment num_updates_ first as this counter is used by IsRefactorized().
325  SCOPED_TIME_STAT(&stats_);
326  ++num_updates_;
327  if (use_middle_product_form_update_) {
329  MiddleProductFormUpdate(entering_col, leaving_variable_row));
330  } else {
331  eta_factorization_.Update(entering_col, leaving_variable_row, direction);
332  }
333  tau_computation_can_be_optimized_ = false;
334  return Status::OK();
335 }
336 
338  SCOPED_TIME_STAT(&stats_);
339  RETURN_IF_NULL(y);
340  if (use_middle_product_form_update_) {
341  lu_factorization_.LeftSolveUWithNonZeros(y);
342  rank_one_factorization_.LeftSolveWithNonZeros(y);
343  lu_factorization_.LeftSolveLWithNonZeros(y);
345  } else {
346  y->non_zeros.clear();
347  eta_factorization_.LeftSolve(&y->values);
348  lu_factorization_.LeftSolve(&y->values);
349  }
350  BumpDeterministicTimeForSolve(y->NumNonZerosEstimate());
351 }
352 
354  SCOPED_TIME_STAT(&stats_);
355  RETURN_IF_NULL(d);
356  if (use_middle_product_form_update_) {
357  lu_factorization_.RightSolveLWithNonZeros(d);
358  rank_one_factorization_.RightSolveWithNonZeros(d);
359  lu_factorization_.RightSolveUWithNonZeros(d);
361  } else {
362  d->non_zeros.clear();
363  lu_factorization_.RightSolve(&d->values);
364  eta_factorization_.RightSolve(&d->values);
365  }
366  BumpDeterministicTimeForSolve(d->NumNonZerosEstimate());
367 }
368 
370  const ScatteredColumn& a) const {
371  SCOPED_TIME_STAT(&stats_);
372  if (use_middle_product_form_update_) {
373  if (tau_computation_can_be_optimized_) {
374  // Once used, the intermediate result is overwritten, so
375  // RightSolveForTau() can no longer use the optimized algorithm.
376  tau_computation_can_be_optimized_ = false;
377  lu_factorization_.RightSolveLWithPermutedInput(a.values, &tau_);
378  } else {
379  ClearAndResizeVectorWithNonZeros(compact_matrix_.num_rows(), &tau_);
380  lu_factorization_.RightSolveLForScatteredColumn(a, &tau_);
381  }
382  rank_one_factorization_.RightSolveWithNonZeros(&tau_);
383  lu_factorization_.RightSolveUWithNonZeros(&tau_);
384  } else {
385  tau_.non_zeros.clear();
386  tau_.values = a.values;
387  lu_factorization_.RightSolve(&tau_.values);
388  eta_factorization_.RightSolve(&tau_.values);
389  }
390  tau_is_computed_ = true;
391  BumpDeterministicTimeForSolve(tau_.NumNonZerosEstimate());
392  return tau_.values;
393 }
394 
396  ScatteredRow* y) const {
397  SCOPED_TIME_STAT(&stats_);
398  RETURN_IF_NULL(y);
400  y);
401  if (!use_middle_product_form_update_) {
402  (*y)[j] = 1.0;
403  y->non_zeros.push_back(j);
404  eta_factorization_.SparseLeftSolve(&y->values, &y->non_zeros);
405  lu_factorization_.LeftSolve(&y->values);
406  BumpDeterministicTimeForSolve(y->NumNonZerosEstimate());
407  return;
408  }
409 
410  // If the leaving index is the same, we can reuse the column! Note also that
411  // since we do a left solve for a unit row using an upper triangular matrix,
412  // all positions in front of the unit will be zero (modulo the column
413  // permutation).
414  if (j >= left_pool_mapping_.size()) {
415  left_pool_mapping_.resize(j + 1, kInvalidCol);
416  }
417  if (left_pool_mapping_[j] == kInvalidCol) {
418  const ColIndex start = lu_factorization_.LeftSolveUForUnitRow(j, y);
419  if (y->non_zeros.empty()) {
420  left_pool_mapping_[j] = storage_.AddDenseColumnPrefix(
421  Transpose(y->values), ColToRowIndex(start));
422  } else {
423  left_pool_mapping_[j] = storage_.AddDenseColumnWithNonZeros(
424  Transpose(y->values),
425  *reinterpret_cast<RowIndexVector*>(&y->non_zeros));
426  }
427  } else {
428  DenseColumn* const x = reinterpret_cast<DenseColumn*>(y);
429  RowIndexVector* const nz = reinterpret_cast<RowIndexVector*>(&y->non_zeros);
430  storage_.ColumnCopyToClearedDenseColumnWithNonZeros(left_pool_mapping_[j],
431  x, nz);
432  }
433 
434  rank_one_factorization_.LeftSolveWithNonZeros(y);
435 
436  // We only keep the intermediate result needed for the optimized tau_
437  // computation if it was computed after the last time this was called.
438  if (tau_is_computed_) {
439  tau_computation_can_be_optimized_ =
440  lu_factorization_.LeftSolveLWithNonZeros(y, &tau_);
441  } else {
442  tau_computation_can_be_optimized_ = false;
443  lu_factorization_.LeftSolveLWithNonZeros(y);
444  }
445  tau_is_computed_ = false;
447  BumpDeterministicTimeForSolve(y->NumNonZerosEstimate());
448 }
449 
451  ScatteredRow* y) const {
453  SCOPED_TIME_STAT(&stats_);
454  RETURN_IF_NULL(y);
456  y);
457  lu_factorization_.LeftSolveUForUnitRow(j, y);
458  lu_factorization_.LeftSolveLWithNonZeros(y);
460  BumpDeterministicTimeForSolve(y->NumNonZerosEstimate());
461 }
462 
464  ScatteredColumn* d) const {
465  SCOPED_TIME_STAT(&stats_);
466  RETURN_IF_NULL(d);
467  ClearAndResizeVectorWithNonZeros(compact_matrix_.num_rows(), d);
468 
469  if (!use_middle_product_form_update_) {
470  compact_matrix_.ColumnCopyToClearedDenseColumn(col, &d->values);
471  lu_factorization_.RightSolve(&d->values);
472  eta_factorization_.RightSolve(&d->values);
473  BumpDeterministicTimeForSolve(d->NumNonZerosEstimate());
474  return;
475  }
476 
477  // TODO(user): if right_pool_mapping_[col] != kInvalidCol, we can reuse it and
478  // just apply the last rank one update since it was computed.
479  lu_factorization_.RightSolveLForColumnView(compact_matrix_.column(col), d);
480  rank_one_factorization_.RightSolveWithNonZeros(d);
481  if (col >= right_pool_mapping_.size()) {
482  right_pool_mapping_.resize(col + 1, kInvalidCol);
483  }
484  if (d->non_zeros.empty()) {
485  right_pool_mapping_[col] = right_storage_.AddDenseColumn(d->values);
486  } else {
487  // The sort is needed if we want to have the same behavior for the sparse or
488  // hyper-sparse version.
489  std::sort(d->non_zeros.begin(), d->non_zeros.end());
490  right_pool_mapping_[col] =
491  right_storage_.AddDenseColumnWithNonZeros(d->values, d->non_zeros);
492  }
493  lu_factorization_.RightSolveUWithNonZeros(d);
495  BumpDeterministicTimeForSolve(d->NumNonZerosEstimate());
496 }
497 
499  const ColumnView& a) const {
500  SCOPED_TIME_STAT(&stats_);
502  BumpDeterministicTimeForSolve(a.num_entries().value());
503  return lu_factorization_.RightSolveSquaredNorm(a);
504 }
505 
507  SCOPED_TIME_STAT(&stats_);
509  BumpDeterministicTimeForSolve(1);
510  return lu_factorization_.DualEdgeSquaredNorm(row);
511 }
512 
513 bool BasisFactorization::IsIdentityBasis() const {
514  const RowIndex num_rows = compact_matrix_.num_rows();
515  for (RowIndex row(0); row < num_rows; ++row) {
516  const ColIndex col = basis_[row];
517  if (compact_matrix_.column(col).num_entries().value() != 1) return false;
518  const Fractional coeff = compact_matrix_.column(col).GetFirstCoefficient();
519  const RowIndex entry_row = compact_matrix_.column(col).GetFirstRow();
520  if (entry_row != row || coeff != 1.0) return false;
521  }
522  return true;
523 }
524 
526  if (IsIdentityBasis()) return 1.0;
527  CompactSparseMatrixView basis_matrix(&compact_matrix_, &basis_);
528  return basis_matrix.ComputeOneNorm();
529 }
530 
532  if (IsIdentityBasis()) return 1.0;
533  CompactSparseMatrixView basis_matrix(&compact_matrix_, &basis_);
534  return basis_matrix.ComputeInfinityNorm();
535 }
536 
537 // TODO(user): try to merge the computation of the norm of inverses
538 // with that of MatrixView. Maybe use a wrapper class for InverseMatrix.
539 
541  if (IsIdentityBasis()) return 1.0;
542  const RowIndex num_rows = compact_matrix_.num_rows();
543  const ColIndex num_cols = RowToColIndex(num_rows);
544  Fractional norm = 0.0;
545  for (ColIndex col(0); col < num_cols; ++col) {
546  ScatteredColumn right_hand_side;
547  right_hand_side.values.AssignToZero(num_rows);
548  right_hand_side[ColToRowIndex(col)] = 1.0;
549  // Get a column of the matrix inverse.
550  RightSolve(&right_hand_side);
551  Fractional column_norm = 0.0;
552  // Compute sum_i |inverse_ij|.
553  for (RowIndex row(0); row < num_rows; ++row) {
554  column_norm += std::abs(right_hand_side[row]);
555  }
556  // Compute max_j sum_i |inverse_ij|
557  norm = std::max(norm, column_norm);
558  }
559  return norm;
560 }
561 
563  if (IsIdentityBasis()) return 1.0;
564  const RowIndex num_rows = compact_matrix_.num_rows();
565  const ColIndex num_cols = RowToColIndex(num_rows);
566  DenseColumn row_sum(num_rows, 0.0);
567  for (ColIndex col(0); col < num_cols; ++col) {
568  ScatteredColumn right_hand_side;
569  right_hand_side.values.AssignToZero(num_rows);
570  right_hand_side[ColToRowIndex(col)] = 1.0;
571  // Get a column of the matrix inverse.
572  RightSolve(&right_hand_side);
573  // Compute sum_j |inverse_ij|.
574  for (RowIndex row(0); row < num_rows; ++row) {
575  row_sum[row] += std::abs(right_hand_side[row]);
576  }
577  }
578  // Compute max_i sum_j |inverse_ij|
579  Fractional norm = 0.0;
580  for (RowIndex row(0); row < num_rows; ++row) {
581  norm = std::max(norm, row_sum[row]);
582  }
583  return norm;
584 }
585 
587  if (IsIdentityBasis()) return 1.0;
589 }
590 
592  if (IsIdentityBasis()) return 1.0;
594 }
595 
597  const {
598  if (IsIdentityBasis()) return 1.0;
599  BumpDeterministicTimeForSolve(compact_matrix_.num_rows().value());
600  return ComputeInfinityNorm() *
601  lu_factorization_.ComputeInverseInfinityNormUpperBound();
602 }
603 
605  return deterministic_time_;
606 }
607 
608 void BasisFactorization::BumpDeterministicTimeForSolve(int num_entries) const {
609  // TODO(user): Spend more time finding a good approximation here.
610  if (compact_matrix_.num_rows().value() == 0) return;
611  const double density =
612  static_cast<double>(num_entries) /
613  static_cast<double>(compact_matrix_.num_rows().value());
614  deterministic_time_ +=
616  lu_factorization_.NumberOfEntries().value()) +
618  rank_one_factorization_.num_entries().value());
619 }
620 
621 } // namespace glop
622 } // namespace operations_research
BasisFactorization(const CompactSparseMatrix *compact_matrix, const RowToColMapping *basis)
const DenseRow & Transpose(const DenseColumn &col)
#define CHECK(condition)
Definition: base/logging.h:491
ColIndex RowToColIndex(RowIndex row)
Definition: lp_types.h:49
::util::IntegerRange< EntryIndex > Column(ColIndex col) const
Definition: sparse.h:363
ColIndex AddDenseColumnWithNonZeros(const DenseColumn &dense_column, const std::vector< RowIndex > &non_zeros)
Definition: sparse.cc:581
RowToColMapping ComputeInitialBasis(const CompactSparseMatrix &matrix, const std::vector< ColIndex > &candidates)
ABSL_MUST_USE_RESULT Status ComputeFactorization(const CompactSparseMatrixView &compact_matrix)
void LeftSolveUWithNonZeros(ScatteredRow *y) const
EntryIndex num_entries
RowIndex EntryRow(EntryIndex i) const
Definition: sparse.h:367
const ColIndex kInvalidCol(-1)
void LeftSolveForUnitRow(ColIndex j, ScatteredRow *y) const
const SparseColumn & GetColumnOfU(ColIndex col) const
Fractional RightSolveSquaredNorm(const ColumnView &a) const
#define LOG(severity)
Definition: base/logging.h:416
ColIndex col
Definition: markowitz.cc:183
#define SCOPED_TIME_STAT(stats)
Definition: stats.h:438
Fractional DualEdgeSquaredNorm(RowIndex row) const
void ClearAndResizeVectorWithNonZeros(IndexType size, ScatteredRowOrCol *v)
static const Status OK()
Definition: status.h:54
RowIndex row
Definition: markowitz.cc:182
void RightSolveUWithNonZeros(ScatteredColumn *x) const
void TemporaryLeftSolveForUnitRow(ColIndex j, ScatteredRow *y) const
#define GLOP_RETURN_IF_ERROR(function_call)
Definition: status.h:70
ColIndex AddDenseColumn(const DenseColumn &dense_column)
Definition: sparse.cc:563
void SparseLeftSolve(DenseRow *y, ColIndexVector *pos) const
Fractional RightSolveSquaredNorm(const ColumnView &a) const
ColumnView column(ColIndex col) const
Definition: sparse.h:369
int64_t max
Definition: alldiff_cst.cc:140
StrictITIVector< RowIndex, Fractional > DenseColumn
Definition: lp_types.h:332
Fractional DualEdgeSquaredNorm(RowIndex row) const
bool LeftSolveLWithNonZeros(ScatteredRow *y, ScatteredColumn *result_before_permutation) const
EtaMatrix(ColIndex eta_col, const ScatteredColumn &direction)
#define DCHECK_NE(val1, val2)
Definition: base/logging.h:887
ColIndex AddDenseColumnPrefix(const DenseColumn &dense_column, RowIndex start)
Definition: sparse.cc:567
void SetCoefficient(Index index, Fractional value)
StrictITIVector< Index, Fractional > values
std::vector< ColIndex > ColIndexVector
Definition: lp_types.h:312
Fractional EntryCoefficient(EntryIndex i) const
Definition: sparse.h:366
void RightSolveLForColumnView(const ColumnView &b, ScatteredColumn *x) const
void RightSolveLWithPermutedInput(const DenseColumn &a, ScatteredColumn *x) const
void STLDeleteElements(T *container)
Definition: stl_util.h:372
bool IsAllZero(const Container &input)
Fractional ColumnScalarProduct(ColIndex col, const DenseRow &vector) const
Definition: sparse.h:387
void Update(ColIndex entering_col, RowIndex leaving_variable_row, const ScatteredColumn &direction)
void SparseLeftSolve(DenseRow *y, ColIndexVector *pos) const
void ColumnCopyToClearedDenseColumn(ColIndex col, DenseColumn *dense_column) const
Definition: sparse.h:431
RowIndex ColToRowIndex(ColIndex col)
Definition: lp_types.h:52
ColIndex AddAndClearColumnWithNonZeros(DenseColumn *column, std::vector< RowIndex > *non_zeros)
Definition: sparse.cc:596
void RightSolveLForScatteredColumn(const ScatteredColumn &b, ScatteredColumn *x) const
void Update(const RankOneUpdateElementaryMatrix &update_matrix)
#define GLOP_RETURN_AND_LOG_ERROR(error_code, message)
Definition: status.h:77
std::vector< RowIndex > RowIndexVector
Definition: lp_types.h:313
#define DCHECK(condition)
Definition: base/logging.h:885
void SetParameters(const GlopParameters &parameters)
ABSL_MUST_USE_RESULT Status Update(ColIndex entering_col, RowIndex leaving_variable_row, const ScatteredColumn &direction)
RowToColMapping ComputeInitialBasis(const std::vector< ColIndex > &candidates)
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:886
void RightSolveLWithNonZeros(ScatteredColumn *x) const
#define RETURN_IF_NULL(x)
Definition: return_macros.h:20
Collection of objects used to extend the Constraint Solver library.
void ColumnCopyToClearedDenseColumnWithNonZeros(ColIndex col, DenseColumn *dense_column, RowIndexVector *non_zeros) const
Definition: sparse.h:441
void RightSolveForProblemColumn(ColIndex col, ScatteredColumn *d) const
static double DeterministicTimeForFpOperations(int64_t n)
Definition: lp_types.h:383
const DenseColumn & RightSolveForTau(const ScatteredColumn &a) const
StrictITIVector< ColIndex, Fractional > DenseRow
Definition: lp_types.h:303
ColIndex LeftSolveUForUnitRow(ColIndex col, ScatteredRow *y) const
const int INFO
Definition: log_severity.h:31
int64_t a