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