18#include "absl/strings/str_format.h"
30template <
typename Matrix>
31EntryIndex ComputeNumEntries(
const Matrix& matrix) {
33 const ColIndex num_cols(matrix.num_cols());
34 for (ColIndex
col(0);
col < num_cols; ++
col) {
43template <
typename Matrix>
44Fractional ComputeOneNormTemplate(
const Matrix& matrix) {
46 const ColIndex num_cols(matrix.num_cols());
47 for (ColIndex
col(0);
col < num_cols; ++
col) {
51 column_norm += fabs(e.coefficient());
62template <
typename Matrix>
63Fractional ComputeInfinityNormTemplate(
const Matrix& matrix) {
65 const ColIndex num_cols(matrix.num_cols());
66 for (ColIndex
col(0);
col < num_cols; ++
col) {
69 row_sum[e.row()] += fabs(e.coefficient());
75 const RowIndex num_rows(matrix.num_rows());
76 for (RowIndex
row(0);
row < num_rows; ++
row) {
89#if (!defined(_MSC_VER) || (_MSC_VER >= 1800))
91 std::initializer_list<std::initializer_list<Fractional>> init_list) {
93 num_rows_ = RowIndex(init_list.size());
95 for (std::initializer_list<Fractional> init_row : init_list) {
112 num_rows_ = RowIndex(0);
116 return columns_.empty() || num_rows_ == 0;
120 const ColIndex
num_cols(columns_.size());
122 columns_[
col].CleanUp();
128 const ColIndex
num_cols(columns_.size());
136 const ColIndex
num_cols(columns_.size());
146 const ColIndex result = columns_.size();
155 columns_.push_back(std::move(new_col));
160 columns_.swap(matrix->columns_);
167 columns_[
col].Clear();
180template <
typename Matrix>
189 ++row_degree[e.row()];
200 columns_[transposed_col].SetCoefficient(transposed_row, e.coefficient());
207 Reset(ColIndex(0), matrix.num_rows_);
208 columns_ = matrix.columns_;
211template <
typename Matrix>
218 for (
const auto e :
a.column(inverse_col_perm[
col])) {
219 columns_[
col].SetCoefficient(row_perm[e.row()], e.coefficient());
245 columns_[
col].CleanUp();
246 dense_column.
Clear();
257 for (ColIndex col_b(0); col_b <
num_cols; ++col_b) {
259 if (eb.coefficient() == 0.0) {
271 columns_[col_b].CleanUp();
277 if (columns_to_delete.
empty())
return;
278 ColIndex new_index(0);
279 const ColIndex
num_cols = columns_.size();
281 if (
col >= columns_to_delete.
size() || !columns_to_delete[
col]) {
282 columns_[
col].Swap(&(columns_[new_index]));
286 columns_.resize(new_index);
292 for (RowIndex
row(0);
row < num_rows_; ++
row) {
297 columns_[
col].ApplyPartialRowPermutation(permutation);
310 columns_[
col].AppendEntriesWithOffset(source_column, offset);
317 const ColIndex
num_cols(columns_.size());
319 columns_[
col].ApplyRowPermutation(row_perm);
324 return columns_[
col].LookUpCoefficient(
row);
343 if (fabs(e.coefficient() - dense_column.
GetCoefficient(e.row())) >
356 if (fabs(e.coefficient() - dense_column_a.
GetCoefficient(e.row())) >
362 dense_column.
Clear();
363 dense_column_a.
Clear();
374 *max_magnitude = 0.0;
377 const Fractional magnitude = fabs(e.coefficient());
378 if (magnitude != 0.0) {
379 *min_magnitude =
std::min(*min_magnitude, magnitude);
380 *max_magnitude =
std::max(*max_magnitude, magnitude);
384 if (*max_magnitude == 0.0) {
385 *min_magnitude = 0.0;
390 return ComputeNumEntries(*
this);
393 return ComputeOneNormTemplate(*
this);
396 return ComputeInfinityNormTemplate(*
this);
401 const ColIndex
num_cols(columns_.size());
403 for (RowIndex
row(0);
row < num_rows_; ++
row) {
408 result.append(
"}\n");
413void SparseMatrix::Reset(ColIndex num_cols, RowIndex num_rows) {
421 return ComputeOneNormTemplate(*
this);
424 return ComputeInfinityNormTemplate(*
this);
428template void SparseMatrix::PopulateFromTranspose<SparseMatrix>(
430template void SparseMatrix::PopulateFromPermutedMatrix<SparseMatrix>(
433template void SparseMatrix::PopulateFromPermutedMatrix<CompactSparseMatrixView>(
492 for (
const RowIndex
row :
input.rows_) {
506 for (
const EntryIndex i :
input.Column(
col)) {
522 diagonal_coefficients_ =
input.diagonal_coefficients_;
523 all_diagonal_coefficients_are_one_ =
input.all_diagonal_coefficients_are_one_;
533 first_non_identity_column_ = 0;
534 const ColIndex
end = diagonal_coefficients_.
size();
535 while (first_non_identity_column_ <
end &&
537 diagonal_coefficients_[first_non_identity_column_] == 1.0) {
538 ++first_non_identity_column_;
553 first_non_identity_column_ = 0;
554 all_diagonal_coefficients_are_one_ =
true;
556 pruned_ends_.
resize(col_capacity);
557 diagonal_coefficients_.
resize(col_capacity);
571 if (dense_column[
row] != 0.0) {
582 const DenseColumn& dense_column,
const std::vector<RowIndex>& non_zeros) {
584 for (
const RowIndex
row : non_zeros) {
597 DenseColumn* column, std::vector<RowIndex>* non_zeros) {
598 for (
const RowIndex
row : *non_zeros) {
603 (*column)[
row] = 0.0;
622 diagonal_coefficients_.
swap(other->diagonal_coefficients_);
623 std::swap(first_non_identity_column_, other->first_non_identity_column_);
624 std::swap(all_diagonal_coefficients_are_one_,
625 other->all_diagonal_coefficients_are_one_);
629 return ComputeNumEntries(*
this);
632 return ComputeOneNormTemplate(*
this);
635 return ComputeInfinityNormTemplate(*
this);
641void TriangularMatrix::CloseCurrentColumn(
Fractional diagonal_value) {
646 diagonal_coefficients_[
num_cols_] = diagonal_value;
656 diagonal_value == 1.0) {
659 all_diagonal_coefficients_are_one_ =
660 all_diagonal_coefficients_are_one_ && (diagonal_value == 1.0);
664 CloseCurrentColumn(diagonal_value);
668 RowIndex diagonal_row) {
671 if (e.row() == diagonal_row) {
672 diagonal_value = e.coefficient();
679 CloseCurrentColumn(diagonal_value);
687 if (e.row() != diagonal_row) {
688 if (e.coefficient() != 0.0) {
693 DCHECK_EQ(e.coefficient(), diagonal_coefficient);
696 CloseCurrentColumn(1.0);
707 CloseCurrentColumn(diagonal_value);
721 if (diagonal_coefficients_[
col] == 0.0)
return false;
731 if (diagonal_coefficients_[
col] == 0.0)
return false;
770 if (all_diagonal_coefficients_are_one_) {
771 LowerSolveStartingAtInternal<true>(
start, rhs);
773 LowerSolveStartingAtInternal<false>(
start, rhs);
777template <
bool diagonal_of_ones>
778void TriangularMatrix::LowerSolveStartingAtInternal(ColIndex
start,
781 const ColIndex begin =
std::max(
start, first_non_identity_column_);
782 const ColIndex
end = diagonal_coefficients_.
size();
785 if (
value == 0.0)
continue;
787 diagonal_of_ones ?
value :
value / diagonal_coefficients_[
col];
788 if (!diagonal_of_ones) {
798 if (all_diagonal_coefficients_are_one_) {
799 UpperSolveInternal<true>(rhs);
801 UpperSolveInternal<false>(rhs);
805template <
bool diagonal_of_ones>
806void TriangularMatrix::UpperSolveInternal(
DenseColumn* rhs)
const {
808 const ColIndex
end = first_non_identity_column_;
811 if (
value == 0.0)
continue;
813 diagonal_of_ones ?
value :
value / diagonal_coefficients_[
col];
814 if (!diagonal_of_ones) {
822 for (EntryIndex i(
starts_[
col + 1] - 1); i >= i_end; --i) {
829 if (all_diagonal_coefficients_are_one_) {
830 TransposeUpperSolveInternal<true>(rhs);
832 TransposeUpperSolveInternal<false>(rhs);
836template <
bool diagonal_of_ones>
837void TriangularMatrix::TransposeUpperSolveInternal(
DenseColumn* rhs)
const {
840 EntryIndex i =
starts_[first_non_identity_column_];
841 for (ColIndex
col(first_non_identity_column_);
col <
end; ++
col) {
850 for (; i < i_end; ++i) {
854 diagonal_of_ones ? sum : sum / diagonal_coefficients_[
col];
859 if (all_diagonal_coefficients_are_one_) {
860 TransposeLowerSolveInternal<true>(rhs);
862 TransposeLowerSolveInternal<false>(rhs);
866template <
bool diagonal_of_ones>
867void TriangularMatrix::TransposeLowerSolveInternal(
DenseColumn* rhs)
const {
869 const ColIndex
end = first_non_identity_column_;
888 for (; i >= i_end; --i) {
892 diagonal_of_ones ? sum : sum / diagonal_coefficients_[
col];
898 if (all_diagonal_coefficients_are_one_) {
899 HyperSparseSolveInternal<true>(rhs, non_zero_rows);
901 HyperSparseSolveInternal<false>(rhs, non_zero_rows);
905template <
bool diagonal_of_ones>
906void TriangularMatrix::HyperSparseSolveInternal(
910 for (
const RowIndex
row : *non_zero_rows) {
911 if ((*rhs)[
row] == 0.0)
continue;
914 diagonal_of_ones ? (*rhs)[
row]
915 : (*rhs)[
row] / diagonal_coefficients_[row_as_col];
917 for (
const EntryIndex i :
Column(row_as_col)) {
920 (*non_zero_rows)[new_size] =
row;
923 non_zero_rows->resize(new_size);
928 if (all_diagonal_coefficients_are_one_) {
929 HyperSparseSolveWithReversedNonZerosInternal<true>(rhs, non_zero_rows);
931 HyperSparseSolveWithReversedNonZerosInternal<false>(rhs, non_zero_rows);
935template <
bool diagonal_of_ones>
936void TriangularMatrix::HyperSparseSolveWithReversedNonZerosInternal(
939 int new_start = non_zero_rows->size();
940 for (
const RowIndex
row :
Reverse(*non_zero_rows)) {
941 if ((*rhs)[
row] == 0.0)
continue;
944 diagonal_of_ones ? (*rhs)[
row]
945 : (*rhs)[
row] / diagonal_coefficients_[row_as_col];
947 for (
const EntryIndex i :
Column(row_as_col)) {
951 (*non_zero_rows)[new_start] =
row;
953 non_zero_rows->erase(non_zero_rows->begin(),
954 non_zero_rows->begin() + new_start);
959 if (all_diagonal_coefficients_are_one_) {
960 TransposeHyperSparseSolveInternal<true>(rhs, non_zero_rows);
962 TransposeHyperSparseSolveInternal<false>(rhs, non_zero_rows);
966template <
bool diagonal_of_ones>
967void TriangularMatrix::TransposeHyperSparseSolveInternal(
971 for (
const RowIndex
row : *non_zero_rows) {
974 for (
const EntryIndex i :
Column(row_as_col)) {
978 diagonal_of_ones ? sum : sum / diagonal_coefficients_[row_as_col];
980 (*non_zero_rows)[new_size] =
row;
984 non_zero_rows->resize(new_size);
989 if (all_diagonal_coefficients_are_one_) {
990 TransposeHyperSparseSolveWithReversedNonZerosInternal<true>(rhs,
993 TransposeHyperSparseSolveWithReversedNonZerosInternal<false>(rhs,
998template <
bool diagonal_of_ones>
999void TriangularMatrix::TransposeHyperSparseSolveWithReversedNonZerosInternal(
1002 int new_start = non_zero_rows->size();
1003 for (
const RowIndex
row :
Reverse(*non_zero_rows)) {
1009 EntryIndex i =
starts_[row_as_col + 1] - 1;
1010 const EntryIndex i_end =
starts_[row_as_col];
1011 for (; i >= i_end; --i) {
1015 diagonal_of_ones ? sum : sum / diagonal_coefficients_[row_as_col];
1018 (*non_zero_rows)[new_start] =
row;
1021 non_zero_rows->erase(non_zero_rows->begin(),
1022 non_zero_rows->begin() + new_start);
1029 DCHECK(all_diagonal_coefficients_are_one_);
1035 initially_all_zero_scratchpad_[e.row()] = e.coefficient();
1038 const RowIndex end_row(partial_inverse_row_perm.
size());
1041 const RowIndex permuted_row = partial_inverse_row_perm[
row];
1042 const Fractional pivot = initially_all_zero_scratchpad_[permuted_row];
1043 if (pivot == 0.0)
continue;
1045 initially_all_zero_scratchpad_[
EntryRow(i)] -=
1053 if (initially_all_zero_scratchpad_[
row] != 0.0) {
1054 if (row_perm[
row] < 0) {
1055 lower->SetCoefficient(
row, initially_all_zero_scratchpad_[
row]);
1057 upper->SetCoefficient(
row, initially_all_zero_scratchpad_[
row]);
1059 initially_all_zero_scratchpad_[
row] = 0.0;
1069 DCHECK(all_diagonal_coefficients_are_one_);
1076 &upper_column_rows_);
1080 for (
const auto e : rhs) {
1081 initially_all_zero_scratchpad_[e.row()] = e.coefficient();
1086 num_fp_operations_ = 0;
1087 lower_column->
Clear();
1094 EntryIndex(upper_column_rows_.size()));
1095 for (
const RowIndex permuted_row :
Reverse(upper_column_rows_)) {
1096 const Fractional pivot = initially_all_zero_scratchpad_[permuted_row];
1097 if (pivot == 0.0)
continue;
1100 initially_all_zero_scratchpad_[permuted_row] = 0.0;
1101 const ColIndex row_as_col =
RowToColIndex(row_perm[permuted_row]);
1104 DCHECK_EQ(diagonal_coefficients_[row_as_col], 1.0);
1106 for (
const auto e :
column(row_as_col)) {
1107 initially_all_zero_scratchpad_[e.row()] -= e.coefficient() * pivot;
1112 lower_column->
Reserve(EntryIndex(lower_column_rows_.size()));
1113 for (
const RowIndex permuted_row : lower_column_rows_) {
1114 const Fractional pivot = initially_all_zero_scratchpad_[permuted_row];
1115 initially_all_zero_scratchpad_[permuted_row] = 0.0;
1150 lower_column_rows->clear();
1151 upper_column_rows->clear();
1152 nodes_to_explore_.clear();
1157 stored_[e.row()] =
true;
1160 nodes_to_explore_.push_back(e.row());
1174 while (!nodes_to_explore_.empty()) {
1175 const RowIndex
row = nodes_to_explore_.back();
1181 nodes_to_explore_.pop_back();
1182 const RowIndex explored_row = nodes_to_explore_.back();
1183 nodes_to_explore_.pop_back();
1184 DCHECK(!stored_[explored_row]);
1185 stored_[explored_row] =
true;
1186 upper_column_rows->
push_back(explored_row);
1197 EntryIndex
end = pruned_ends_[
col];
1199 const RowIndex entry_row =
EntryRow(i);
1200 if (!marked_[entry_row]) {
1209 marked_[entry_row] =
false;
1219 nodes_to_explore_.pop_back();
1227 stored_[
row] =
true;
1229 nodes_to_explore_.pop_back();
1236 const EntryIndex
end = pruned_ends_[
col];
1238 const RowIndex entry_row =
EntryRow(i);
1239 if (!stored_[entry_row]) {
1240 nodes_to_explore_.push_back(entry_row);
1242 marked_[entry_row] =
true;
1250 for (
const RowIndex
row : *lower_column_rows) {
1251 stored_[
row] =
false;
1253 for (
const RowIndex
row : *upper_column_rows) {
1254 stored_[
row] =
false;
1260 if (non_zero_rows->empty())
return;
1270 const int sparsity_threshold =
1271 static_cast<int>(0.025 *
static_cast<double>(
num_rows_.value()));
1272 const int num_ops_threshold =
1273 static_cast<int>(0.05 *
static_cast<double>(
num_rows_.value()));
1274 int num_ops = non_zero_rows->size();
1275 if (num_ops > sparsity_threshold) {
1276 non_zero_rows->clear();
1282 nodes_to_explore_.clear();
1283 nodes_to_explore_.swap(*non_zero_rows);
1287 while (!nodes_to_explore_.empty()) {
1288 const RowIndex
row = nodes_to_explore_.back();
1293 nodes_to_explore_.pop_back();
1294 const RowIndex explored_row = -
row - 1;
1295 stored_[explored_row] =
true;
1302 nodes_to_explore_.pop_back();
1311 nodes_to_explore_.back() = -
row - 1;
1314 const RowIndex entry_row =
EntryRow(i);
1315 if (!stored_[entry_row]) {
1316 nodes_to_explore_.push_back(entry_row);
1323 if (num_ops > num_ops_threshold)
break;
1327 for (
const RowIndex
row : *non_zero_rows) {
1328 stored_[
row] =
false;
1332 if (num_ops > num_ops_threshold) non_zero_rows->
clear();
1337 static const Fractional kDefaultSparsityRatio = 0.025;
1338 static const Fractional kDefaultNumOpsRatio = 0.05;
1340 kDefaultNumOpsRatio);
1346 if (non_zero_rows->empty())
return;
1349 const int sparsity_threshold =
1350 static_cast<int>(0.025 *
static_cast<double>(
num_rows_.value()));
1351 const int num_ops_threshold =
1352 static_cast<int>(0.05 *
static_cast<double>(
num_rows_.value()));
1353 int num_ops = non_zero_rows->size();
1354 if (num_ops > sparsity_threshold) {
1355 non_zero_rows->clear();
1360 for (
const RowIndex
row : *non_zero_rows) stored_[
row] =
true;
1361 for (
int i = 0; i < non_zero_rows->size(); ++i) {
1362 const RowIndex
row = (*non_zero_rows)[i];
1365 const RowIndex entry_row =
EntryRow(i);
1366 if (!stored_[entry_row]) {
1367 non_zero_rows->push_back(entry_row);
1368 stored_[entry_row] =
true;
1371 if (num_ops > num_ops_threshold)
break;
1374 for (
const RowIndex
row : *non_zero_rows) stored_[
row] =
false;
1375 if (num_ops > num_ops_threshold) {
1376 non_zero_rows->
clear();
1378 std::sort(non_zero_rows->begin(), non_zero_rows->end());
1387 if (first_non_identity_column_ ==
num_cols_) {
1396 for (
int i = 0; i <
num_cols; ++i) {
1397 const ColIndex
col(is_upper ?
num_cols - 1 - i : i);
1400 std::abs(diagonal_coefficients_[
col]);
1403 for (
const EntryIndex i :
Column(
col)) {
1408 return *std::max_element(row_norm_estimate.
begin(), row_norm_estimate.
end());
1429 row_sum[
row] += std::abs(right_hand_side[
row]);
#define DCHECK_LE(val1, val2)
#define DCHECK_NE(val1, val2)
#define DCHECK_GE(val1, val2)
#define DCHECK_LT(val1, val2)
#define DCHECK(condition)
#define DCHECK_EQ(val1, val2)
void push_back(const value_type &x)
void swap(StrongVector &x)
ColIndex AddDenseColumn(const DenseColumn &dense_column)
StrictITIVector< ColIndex, EntryIndex > starts_
ColIndex AddDenseColumnWithNonZeros(const DenseColumn &dense_column, const std::vector< RowIndex > &non_zeros)
ColIndex AddAndClearColumnWithNonZeros(DenseColumn *column, std::vector< RowIndex > *non_zeros)
void Swap(CompactSparseMatrix *other)
StrictITIVector< EntryIndex, RowIndex > rows_
ColIndex AddDenseColumnPrefix(const DenseColumn &dense_column, RowIndex start)
RowIndex num_rows() const
Fractional EntryCoefficient(EntryIndex i) const
StrictITIVector< EntryIndex, Fractional > coefficients_
void PopulateFromTranspose(const CompactSparseMatrix &input)
::util::IntegerRange< EntryIndex > Column(ColIndex col) const
void Reset(RowIndex num_rows)
void PopulateFromSparseMatrixAndAddSlacks(const SparseMatrix &input)
void PopulateFromMatrixView(const MatrixView &input)
RowIndex EntryRow(EntryIndex i) const
EntryIndex num_entries() const
ColumnView column(ColIndex col) const
EntryIndex ColumnNumEntries(ColIndex col) const
Fractional ComputeInfinityNorm() const
Fractional ComputeOneNorm() const
EntryIndex num_entries() const
Fractional ComputeInfinityNorm() const
Fractional ComputeOneNorm() const
EntryIndex num_entries() const
void AddToCoefficient(RowIndex row, Fractional value)
void PopulateSparseColumn(SparseColumn *sparse_column) const
Fractional GetCoefficient(RowIndex row) const
void AppendUnitVector(RowIndex row, Fractional value)
void PopulateFromLinearCombination(Fractional alpha, const SparseMatrix &a, Fractional beta, const SparseMatrix &b)
void PopulateFromPermutedMatrix(const Matrix &a, const RowPermutation &row_perm, const ColumnPermutation &inverse_col_perm)
bool CheckNoDuplicates() const
void PopulateFromTranspose(const Matrix &input)
void PopulateFromIdentity(ColIndex num_cols)
Fractional ComputeInfinityNorm() const
ColIndex num_cols() const
void SetNumRows(RowIndex num_rows)
SparseColumn * mutable_column(ColIndex col)
Fractional LookUpValue(RowIndex row, ColIndex col) const
void Swap(SparseMatrix *matrix)
Fractional ComputeOneNorm() const
void ComputeMinAndMaxMagnitudes(Fractional *min_magnitude, Fractional *max_magnitude) const
void DeleteRows(RowIndex num_rows, const RowPermutation &permutation)
ColIndex AppendEmptyColumn()
RowIndex num_rows() const
void PopulateFromProduct(const SparseMatrix &a, const SparseMatrix &b)
bool AppendRowsFromSparseMatrix(const SparseMatrix &matrix)
void DeleteColumns(const DenseBooleanRow &columns_to_delete)
void PopulateFromSparseMatrix(const SparseMatrix &matrix)
void ApplyRowPermutation(const RowPermutation &row_perm)
void PopulateFromZero(RowIndex num_rows, ColIndex num_cols)
EntryIndex num_entries() const
bool Equals(const SparseMatrix &a, Fractional tolerance) const
bool CheckNoDuplicates() const
typename Iterator::Entry Entry
void Reserve(EntryIndex new_capacity)
void SetCoefficient(Index index, Fractional value)
EntryIndex num_entries() const
void resize(IntType size)
void assign(IntType size, const T &v)
void TransposeHyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
void CopyToSparseMatrix(SparseMatrix *output) const
void AddTriangularColumnWithGivenDiagonalEntry(const SparseColumn &column, RowIndex diagonal_row, Fractional diagonal_value)
void UpperSolve(DenseColumn *rhs) const
void HyperSparseSolve(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
Fractional ComputeInverseInfinityNorm() const
void Swap(TriangularMatrix *other)
void PopulateFromTriangularSparseMatrix(const SparseMatrix &input)
ColIndex num_cols() const
bool IsLowerTriangular() 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
void AddAndNormalizeTriangularColumn(const SparseColumn &column, RowIndex diagonal_row, Fractional diagonal_coefficient)
bool IsUpperTriangular() const
RowIndex num_rows() const
void ComputeRowsToConsiderInSortedOrder(RowIndexVector *non_zero_rows, Fractional sparsity_ratio, Fractional num_ops_ratio) const
void AddTriangularColumn(const ColumnView &column, RowIndex diagonal_row)
void TransposeLowerSolve(DenseColumn *rhs) const
void PermutedLowerSparseSolve(const ColumnView &rhs, const RowPermutation &row_perm, SparseColumn *lower, SparseColumn *upper)
void PermutedComputeRowsToConsider(const ColumnView &rhs, const RowPermutation &row_perm, RowIndexVector *lower_column_rows, RowIndexVector *upper_column_rows)
void ApplyRowPermutationToNonDiagonalEntries(const RowPermutation &row_perm)
void TransposeUpperSolve(DenseColumn *rhs) const
void ComputeRowsToConsiderWithDfs(RowIndexVector *non_zero_rows) const
Fractional ComputeInverseInfinityNormUpperBound() const
void PermutedLowerSolve(const SparseColumn &rhs, const RowPermutation &row_perm, const RowMapping &partial_inverse_row_perm, SparseColumn *lower, SparseColumn *upper) const
void AddDiagonalOnlyColumn(Fractional diagonal_value)
void Reset(RowIndex num_rows, ColIndex col_capacity)
void HyperSparseSolveWithReversedNonZeros(DenseColumn *rhs, RowIndexVector *non_zero_rows) const
EntryIndex num_entries() const
const RowIndex kInvalidRow(-1)
ColIndex RowToColIndex(RowIndex row)
RowIndex ColToRowIndex(ColIndex col)
std::vector< RowIndex > RowIndexVector
StrictITIVector< RowIndex, Fractional > DenseColumn
static double ToDouble(double f)
void swap(IdMap< K, V > &a, IdMap< K, V > &b)
Collection of objects used to extend the Constraint Solver library.
BeginEndReverseIteratorWrapper< Container > Reverse(const Container &c)
static int input(yyscan_t yyscanner)
#define RETURN_IF_NULL(x)
std::optional< int64_t > end