OR-Tools  9.3
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
17#include "ortools/glop/status.h"
19
20namespace operations_research {
21namespace glop {
22
23// --------------------------------------------------------
24// EtaMatrix
25// --------------------------------------------------------
26
27const Fractional EtaMatrix::kSparseThreshold = 0.5;
28
29EtaMatrix::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
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
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
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
98void 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
107void 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
115void 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
125void 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
143void 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
154 for (int i = eta_matrix_.size() - 1; i >= 0; --i) {
155 eta_matrix_[i]->LeftSolve(y);
156 }
157}
158
161 for (int i = eta_matrix_.size() - 1; i >= 0; --i) {
162 eta_matrix_[i]->SparseLeftSolve(y, pos);
163 }
164}
165
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
222bool 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
236Status 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)
254Status 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
299Status 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_);
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_);
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_);
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(
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_);
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_);
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
513bool 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
608void 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
int64_t max
Definition: alldiff_cst.cc:140
#define CHECK(condition)
Definition: base/logging.h:495
#define DCHECK_NE(val1, val2)
Definition: base/logging.h:892
#define LOG(severity)
Definition: base/logging.h:420
#define DCHECK(condition)
Definition: base/logging.h:890
#define DCHECK_EQ(val1, val2)
Definition: base/logging.h:891
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:563
ColIndex AddDenseColumnWithNonZeros(const DenseColumn &dense_column, const std::vector< RowIndex > &non_zeros)
Definition: sparse.cc:581
ColIndex AddAndClearColumnWithNonZeros(DenseColumn *column, std::vector< RowIndex > *non_zeros)
Definition: sparse.cc:596
void ColumnCopyToClearedDenseColumnWithNonZeros(ColIndex col, DenseColumn *dense_column, RowIndexVector *non_zeros) const
Definition: sparse.h:441
ColIndex AddDenseColumnPrefix(const DenseColumn &dense_column, RowIndex start)
Definition: sparse.cc:567
Fractional EntryCoefficient(EntryIndex i) const
Definition: sparse.h:366
void ColumnCopyToClearedDenseColumn(ColIndex col, DenseColumn *dense_column) const
Definition: sparse.h:431
Fractional ColumnScalarProduct(ColIndex col, const DenseRow &vector) const
Definition: sparse.h:387
::util::IntegerRange< EntryIndex > Column(ColIndex col) const
Definition: sparse.h:363
RowIndex EntryRow(EntryIndex i) const
Definition: sparse.h:367
ColumnView column(ColIndex col) const
Definition: sparse.h:369
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:56
int64_t a
absl::Status status
Definition: g_gurobi.cc:35
const int INFO
Definition: log_severity.h:31
ColIndex col
Definition: markowitz.cc:183
RowIndex row
Definition: markowitz.cc:182
void STLDeleteElements(T *container)
Definition: stl_util.h:372
std::vector< ColIndex > ColIndexVector
Definition: lp_types.h:312
bool IsAllZero(const Container &input)
StrictITIVector< ColIndex, Fractional > DenseRow
Definition: lp_types.h:303
ColIndex RowToColIndex(RowIndex row)
Definition: lp_types.h:49
void ClearAndResizeVectorWithNonZeros(IndexType size, ScatteredRowOrCol *v)
const DenseRow & Transpose(const DenseColumn &col)
RowIndex ColToRowIndex(ColIndex col)
Definition: lp_types.h:52
std::vector< RowIndex > RowIndexVector
Definition: lp_types.h:313
StrictITIVector< RowIndex, Fractional > DenseColumn
Definition: lp_types.h:332
static double DeterministicTimeForFpOperations(int64_t n)
Definition: lp_types.h:383
const ColIndex kInvalidCol(-1)
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:438
#define GLOP_RETURN_IF_ERROR(function_call)
Definition: status.h:72
#define GLOP_RETURN_AND_LOG_ERROR(error_code, message)
Definition: status.h:79
StrictITIVector< Index, Fractional > values
const double coeff