17 #include <initializer_list>
22 #include "absl/strings/str_format.h"
23 #include "absl/strings/str_join.h"
35 template <
typename Matrix>
36 EntryIndex ComputeNumEntries(
const Matrix& matrix) {
38 const ColIndex num_cols(matrix.num_cols());
39 for (ColIndex
col(0);
col < num_cols; ++
col) {
48 template <
typename Matrix>
49 Fractional ComputeOneNormTemplate(
const Matrix& matrix) {
51 const ColIndex num_cols(matrix.num_cols());
52 for (ColIndex
col(0);
col < num_cols; ++
col) {
56 column_norm += fabs(e.coefficient());
67 template <
typename Matrix>
68 Fractional ComputeInfinityNormTemplate(
const Matrix& matrix) {
70 const ColIndex num_cols(matrix.num_cols());
71 for (ColIndex
col(0);
col < num_cols; ++
col) {
74 row_sum[e.row()] += fabs(e.coefficient());
80 const RowIndex num_rows(matrix.num_rows());
81 for (RowIndex
row(0);
row < num_rows; ++
row) {
94 #if (!defined(_MSC_VER) || (_MSC_VER >= 1800))
96 std::initializer_list<std::initializer_list<Fractional>> init_list) {
98 num_rows_ = RowIndex(init_list.size());
100 for (std::initializer_list<Fractional> init_row : init_list) {
117 num_rows_ = RowIndex(0);
121 return columns_.empty() || num_rows_ == 0;
125 const ColIndex
num_cols(columns_.size());
127 columns_[
col].CleanUp();
133 const ColIndex
num_cols(columns_.size());
141 const ColIndex
num_cols(columns_.size());
151 const ColIndex result = columns_.size();
157 DCHECK_LT(
row, num_rows_);
160 columns_.push_back(std::move(new_col));
165 columns_.swap(matrix->columns_);
172 columns_[
col].Clear();
185 template <
typename Matrix>
194 ++row_degree[e.row()];
205 columns_[transposed_col].SetCoefficient(transposed_row, e.coefficient());
212 Reset(ColIndex(0), matrix.num_rows_);
213 columns_ = matrix.columns_;
216 template <
typename Matrix>
223 for (
const auto e :
a.column(inverse_col_perm[
col])) {
224 columns_[
col].SetCoefficient(row_perm[e.row()], e.coefficient());
234 DCHECK_EQ(
a.num_cols(),
b.num_cols());
235 DCHECK_EQ(
a.num_rows(),
b.num_rows());
250 columns_[
col].CleanUp();
251 dense_column.
Clear();
262 for (ColIndex col_b(0); col_b <
num_cols; ++col_b) {
264 if (eb.coefficient() == 0.0) {
276 columns_[col_b].CleanUp();
282 if (columns_to_delete.
empty())
return;
283 ColIndex new_index(0);
284 const ColIndex
num_cols = columns_.size();
286 if (
col >= columns_to_delete.
size() || !columns_to_delete[
col]) {
287 columns_[
col].Swap(&(columns_[new_index]));
291 columns_.resize(new_index);
296 DCHECK_EQ(num_rows_, permutation.
size());
297 for (RowIndex
row(0);
row < num_rows_; ++
row) {
298 DCHECK_LT(permutation[
row], new_num_rows);
302 columns_[
col].ApplyPartialRowPermutation(permutation);
315 columns_[
col].AppendEntriesWithOffset(source_column, offset);
322 const ColIndex
num_cols(columns_.size());
324 columns_[
col].ApplyRowPermutation(row_perm);
329 return columns_[
col].LookUpCoefficient(
row);
348 if (fabs(e.coefficient() - dense_column.
GetCoefficient(e.row())) >
361 if (fabs(e.coefficient() - dense_column_a.
GetCoefficient(e.row())) >
367 dense_column.
Clear();
368 dense_column_a.
Clear();
379 *max_magnitude = 0.0;
382 const Fractional magnitude = fabs(e.coefficient());
383 if (magnitude != 0.0) {
384 *min_magnitude =
std::min(*min_magnitude, magnitude);
385 *max_magnitude =
std::max(*max_magnitude, magnitude);
389 if (*max_magnitude == 0.0) {
390 *min_magnitude = 0.0;
395 return ComputeNumEntries(*
this);
398 return ComputeOneNormTemplate(*
this);
401 return ComputeInfinityNormTemplate(*
this);
406 const ColIndex
num_cols(columns_.size());
408 for (RowIndex
row(0);
row < num_rows_; ++
row) {
413 result.append(
"}\n");
418 void SparseMatrix::Reset(ColIndex num_cols, RowIndex num_rows) {
426 return ComputeOneNormTemplate(*
this);
429 return ComputeInfinityNormTemplate(*
this);
433 template void SparseMatrix::PopulateFromTranspose<SparseMatrix>(
435 template void SparseMatrix::PopulateFromPermutedMatrix<SparseMatrix>(
438 template void SparseMatrix::PopulateFromPermutedMatrix<CompactSparseMatrixView>(
497 for (
const RowIndex
row :
input.rows_) {
510 const auto input_entry_rows =
input.rows_.view();
512 const auto input_entry_coefficients =
input.coefficients_.view();
517 for (
const EntryIndex i :
input.Column(
col)) {
518 const ColIndex transposed_col =
RowToColIndex(input_entry_rows[i]);
519 const EntryIndex
index = starts[transposed_col + 1]++;
520 entry_coefficients[
index] = input_entry_coefficients[i];
521 entry_rows[
index] = transposed_row;
533 diagonal_coefficients_ =
input.diagonal_coefficients_;
534 all_diagonal_coefficients_are_one_ =
input.all_diagonal_coefficients_are_one_;
544 first_non_identity_column_ = 0;
545 const ColIndex
end = diagonal_coefficients_.
size();
546 while (first_non_identity_column_ <
end &&
548 diagonal_coefficients_[first_non_identity_column_] == 1.0) {
549 ++first_non_identity_column_;
564 first_non_identity_column_ = 0;
565 all_diagonal_coefficients_are_one_ =
true;
567 pruned_ends_.
resize(col_capacity);
568 diagonal_coefficients_.
resize(col_capacity);
582 if (dense_column[
row] != 0.0) {
593 const DenseColumn& dense_column,
const std::vector<RowIndex>& non_zeros) {
595 for (
const RowIndex
row : non_zeros) {
609 for (
const RowIndex
row : *non_zeros) {
614 (*column)[
row] = 0.0;
633 diagonal_coefficients_.
swap(other->diagonal_coefficients_);
634 std::swap(first_non_identity_column_, other->first_non_identity_column_);
635 std::swap(all_diagonal_coefficients_are_one_,
636 other->all_diagonal_coefficients_are_one_);
640 return ComputeNumEntries(*
this);
643 return ComputeOneNormTemplate(*
this);
646 return ComputeInfinityNormTemplate(*
this);
652 void TriangularMatrix::CloseCurrentColumn(
Fractional diagonal_value) {
653 DCHECK_NE(diagonal_value, 0.0);
657 diagonal_coefficients_[
num_cols_] = diagonal_value;
667 diagonal_value == 1.0) {
670 all_diagonal_coefficients_are_one_ =
671 all_diagonal_coefficients_are_one_ && (diagonal_value == 1.0);
675 CloseCurrentColumn(diagonal_value);
679 RowIndex diagonal_row) {
682 if (e.row() == diagonal_row) {
683 diagonal_value = e.coefficient();
685 DCHECK_NE(0.0, e.coefficient());
690 CloseCurrentColumn(diagonal_value);
698 if (e.row() != diagonal_row) {
699 if (e.coefficient() != 0.0) {
704 DCHECK_EQ(e.coefficient(), diagonal_coefficient);
707 CloseCurrentColumn(1.0);
714 DCHECK_NE(e.row(), diagonal_row);
718 CloseCurrentColumn(diagonal_value);
732 if (diagonal_coefficients_[
col] == 0.0)
return false;
742 if (diagonal_coefficients_[
col] == 0.0)
return false;
784 if (all_diagonal_coefficients_are_one_) {
785 LowerSolveStartingAtInternal<true>(
start, rhs->
view());
787 LowerSolveStartingAtInternal<false>(
start, rhs->
view());
791 template <
bool diagonal_of_ones>
792 void TriangularMatrix::LowerSolveStartingAtInternal(
794 const ColIndex begin =
std::max(
start, first_non_identity_column_);
797 const auto diagonal_coefficients = diagonal_coefficients_.
view();
798 const ColIndex
end = diagonal_coefficients.size();
801 if (
value == 0.0)
continue;
803 diagonal_of_ones ?
value :
value / diagonal_coefficients[
col];
804 if (!diagonal_of_ones) {
808 rhs[entry_rows[i]] -= coeff * entry_coefficients[i];
815 if (all_diagonal_coefficients_are_one_) {
816 UpperSolveInternal<true>(rhs->
view());
818 UpperSolveInternal<false>(rhs->
view());
822 template <
bool diagonal_of_ones>
824 const ColIndex
end = first_non_identity_column_;
827 const auto diagonal_coefficients = diagonal_coefficients_.
view();
828 for (ColIndex
col(diagonal_coefficients.size() - 1);
col >=
end; --
col) {
830 if (
value == 0.0)
continue;
832 diagonal_of_ones ?
value :
value / diagonal_coefficients[
col];
833 if (!diagonal_of_ones) {
841 for (EntryIndex i(
starts_[
col + 1] - 1); i >= i_end; --i) {
842 rhs[entry_rows[i]] -= coeff * entry_coefficients[i];
849 if (all_diagonal_coefficients_are_one_) {
850 TransposeUpperSolveInternal<true>(rhs->
view());
852 TransposeUpperSolveInternal<false>(rhs->
view());
856 template <
bool diagonal_of_ones>
857 void TriangularMatrix::TransposeUpperSolveInternal(
863 const auto diagonal_coefficients = diagonal_coefficients_.
view();
865 EntryIndex i =
starts_[first_non_identity_column_];
866 for (ColIndex
col(first_non_identity_column_);
col <
end; ++
col) {
874 const EntryIndex i_end = starts[
col + 1];
875 const EntryIndex shifted_end = i_end - 3;
876 for (; i < shifted_end; i += 4) {
877 sum -= entry_coefficients[i] * rhs[entry_rows[i]] +
878 entry_coefficients[i + 1] * rhs[entry_rows[i + 1]] +
879 entry_coefficients[i + 2] * rhs[entry_rows[i + 2]] +
880 entry_coefficients[i + 3] * rhs[entry_rows[i + 3]];
883 sum -= entry_coefficients[i] * rhs[entry_rows[i]];
885 sum -= entry_coefficients[i + 1] * rhs[entry_rows[i + 1]];
887 sum -= entry_coefficients[i + 2] * rhs[entry_rows[i + 2]];
894 diagonal_of_ones ? sum : sum / diagonal_coefficients[
col];
900 if (all_diagonal_coefficients_are_one_) {
901 TransposeLowerSolveInternal<true>(rhs->
view());
903 TransposeLowerSolveInternal<false>(rhs->
view());
907 template <
bool diagonal_of_ones>
908 void TriangularMatrix::TransposeLowerSolveInternal(
910 const ColIndex
end = first_non_identity_column_;
919 const auto diagonal_coeffs = diagonal_coefficients_.
view();
922 EntryIndex i = starts[
col + 1] - 1;
932 const EntryIndex i_end = starts[
col];
933 const EntryIndex shifted_end = i_end + 3;
934 for (; i >= shifted_end; i -= 4) {
935 sum -= entry_coefficients[i] * rhs[entry_rows[i]] +
936 entry_coefficients[i - 1] * rhs[entry_rows[i - 1]] +
937 entry_coefficients[i - 2] * rhs[entry_rows[i - 2]] +
938 entry_coefficients[i - 3] * rhs[entry_rows[i - 3]];
941 sum -= entry_coefficients[i] * rhs[entry_rows[i]];
942 if (i >= i_end + 1) {
943 sum -= entry_coefficients[i - 1] * rhs[entry_rows[i - 1]];
944 if (i >= i_end + 2) {
945 sum -= entry_coefficients[i - 2] * rhs[entry_rows[i - 2]];
952 diagonal_of_ones ? sum : sum / diagonal_coeffs[
col];
959 if (all_diagonal_coefficients_are_one_) {
960 HyperSparseSolveInternal<true>(rhs->
view(), non_zero_rows);
962 HyperSparseSolveInternal<false>(rhs->
view(), non_zero_rows);
966 template <
bool diagonal_of_ones>
967 void TriangularMatrix::HyperSparseSolveInternal(
972 for (
const RowIndex
row : *non_zero_rows) {
973 if (rhs[
row] == 0.0)
continue;
976 diagonal_of_ones ? rhs[
row]
977 : rhs[
row] / diagonal_coefficients_[row_as_col];
979 for (
const EntryIndex i :
Column(row_as_col)) {
980 rhs[entry_rows[i]] -= coeff * entry_coefficients[i];
982 (*non_zero_rows)[new_size] =
row;
985 non_zero_rows->resize(new_size);
991 if (all_diagonal_coefficients_are_one_) {
992 HyperSparseSolveWithReversedNonZerosInternal<true>(rhs->
view(),
995 HyperSparseSolveWithReversedNonZerosInternal<false>(rhs->
view(),
1000 template <
bool diagonal_of_ones>
1001 void TriangularMatrix::HyperSparseSolveWithReversedNonZerosInternal(
1003 int new_start = non_zero_rows->size();
1006 for (
const RowIndex
row :
Reverse(*non_zero_rows)) {
1007 if (rhs[
row] == 0.0)
continue;
1010 diagonal_of_ones ? rhs[
row]
1011 : rhs[
row] / diagonal_coefficients_[row_as_col];
1013 for (
const EntryIndex i :
Column(row_as_col)) {
1014 rhs[entry_rows[i]] -= coeff * entry_coefficients[i];
1017 (*non_zero_rows)[new_start] =
row;
1019 non_zero_rows->erase(non_zero_rows->begin(),
1020 non_zero_rows->begin() + new_start);
1026 if (all_diagonal_coefficients_are_one_) {
1027 TransposeHyperSparseSolveInternal<true>(rhs->
view(), non_zero_rows);
1029 TransposeHyperSparseSolveInternal<false>(rhs->
view(), non_zero_rows);
1033 template <
bool diagonal_of_ones>
1034 void TriangularMatrix::TransposeHyperSparseSolveInternal(
1040 for (
const RowIndex
row : *non_zero_rows) {
1046 EntryIndex i =
starts_[row_as_col];
1047 const EntryIndex i_end =
starts_[row_as_col + 1];
1048 const EntryIndex shifted_end = i_end - 3;
1049 for (; i < shifted_end; i += 4) {
1050 sum -= entry_coefficients[i] * rhs[entry_rows[i]] +
1051 entry_coefficients[i + 1] * rhs[entry_rows[i + 1]] +
1052 entry_coefficients[i + 2] * rhs[entry_rows[i + 2]] +
1053 entry_coefficients[i + 3] * rhs[entry_rows[i + 3]];
1056 sum -= entry_coefficients[i] * rhs[entry_rows[i]];
1057 if (i + 1 < i_end) {
1058 sum -= entry_coefficients[i + 1] * rhs[entry_rows[i + 1]];
1059 if (i + 2 < i_end) {
1060 sum -= entry_coefficients[i + 2] * rhs[entry_rows[i + 2]];
1066 diagonal_of_ones ? sum : sum / diagonal_coefficients_[row_as_col];
1068 (*non_zero_rows)[new_size] =
row;
1072 non_zero_rows->resize(new_size);
1078 if (all_diagonal_coefficients_are_one_) {
1079 TransposeHyperSparseSolveWithReversedNonZerosInternal<true>(rhs->
view(),
1082 TransposeHyperSparseSolveWithReversedNonZerosInternal<false>(rhs->
view(),
1087 template <
bool diagonal_of_ones>
1088 void TriangularMatrix::TransposeHyperSparseSolveWithReversedNonZerosInternal(
1090 int new_start = non_zero_rows->size();
1093 for (
const RowIndex
row :
Reverse(*non_zero_rows)) {
1099 EntryIndex i =
starts_[row_as_col + 1] - 1;
1100 const EntryIndex i_end =
starts_[row_as_col];
1101 const EntryIndex shifted_end = i_end + 3;
1102 for (; i >= shifted_end; i -= 4) {
1103 sum -= entry_coefficients[i] * rhs[entry_rows[i]] +
1104 entry_coefficients[i - 1] * rhs[entry_rows[i - 1]] +
1105 entry_coefficients[i - 2] * rhs[entry_rows[i - 2]] +
1106 entry_coefficients[i - 3] * rhs[entry_rows[i - 3]];
1109 sum -= entry_coefficients[i] * rhs[entry_rows[i]];
1110 if (i >= i_end + 1) {
1111 sum -= entry_coefficients[i - 1] * rhs[entry_rows[i - 1]];
1112 if (i >= i_end + 2) {
1113 sum -= entry_coefficients[i - 2] * rhs[entry_rows[i - 2]];
1119 diagonal_of_ones ? sum : sum / diagonal_coefficients_[row_as_col];
1122 (*non_zero_rows)[new_start] =
row;
1125 non_zero_rows->erase(non_zero_rows->begin(),
1126 non_zero_rows->begin() + new_start);
1133 DCHECK(all_diagonal_coefficients_are_one_);
1139 initially_all_zero_scratchpad_[e.row()] = e.coefficient();
1144 const RowIndex end_row(partial_inverse_row_perm.
size());
1147 const RowIndex permuted_row = partial_inverse_row_perm[
row];
1148 const Fractional pivot = initially_all_zero_scratchpad_[permuted_row];
1149 if (pivot == 0.0)
continue;
1152 initially_all_zero_scratchpad_[entry_rows[i]] -=
1153 entry_coefficients[i] * pivot;
1160 if (initially_all_zero_scratchpad_[
row] != 0.0) {
1161 if (row_perm[
row] < 0) {
1162 lower->SetCoefficient(
row, initially_all_zero_scratchpad_[
row]);
1164 upper->SetCoefficient(
row, initially_all_zero_scratchpad_[
row]);
1166 initially_all_zero_scratchpad_[
row] = 0.0;
1169 DCHECK(
lower->CheckNoDuplicates());
1176 DCHECK(all_diagonal_coefficients_are_one_);
1183 &upper_column_rows_);
1187 for (
const auto e : rhs) {
1188 initially_all_zero_scratchpad_[e.row()] = e.coefficient();
1193 num_fp_operations_ = 0;
1194 lower_column->
Clear();
1201 EntryIndex(upper_column_rows_.size()));
1202 for (
const RowIndex permuted_row :
Reverse(upper_column_rows_)) {
1203 const Fractional pivot = initially_all_zero_scratchpad_[permuted_row];
1204 if (pivot == 0.0)
continue;
1207 initially_all_zero_scratchpad_[permuted_row] = 0.0;
1208 const ColIndex row_as_col =
RowToColIndex(row_perm[permuted_row]);
1209 DCHECK_GE(row_as_col, 0);
1211 DCHECK_EQ(diagonal_coefficients_[row_as_col], 1.0);
1213 for (
const auto e :
column(row_as_col)) {
1214 initially_all_zero_scratchpad_[e.row()] -= e.coefficient() * pivot;
1219 lower_column->
Reserve(EntryIndex(lower_column_rows_.size()));
1220 for (
const RowIndex permuted_row : lower_column_rows_) {
1221 const Fractional pivot = initially_all_zero_scratchpad_[permuted_row];
1222 initially_all_zero_scratchpad_[permuted_row] = 0.0;
1257 lower_column_rows->clear();
1258 upper_column_rows->clear();
1259 nodes_to_explore_.clear();
1264 stored_[e.row()] =
true;
1267 nodes_to_explore_.push_back(e.row());
1282 while (!nodes_to_explore_.empty()) {
1283 const RowIndex
row = nodes_to_explore_.back();
1289 nodes_to_explore_.pop_back();
1290 const RowIndex explored_row = nodes_to_explore_.back();
1291 nodes_to_explore_.pop_back();
1292 DCHECK(!stored_[explored_row]);
1293 stored_[explored_row] =
true;
1294 upper_column_rows->
push_back(explored_row);
1305 EntryIndex
end = pruned_ends_[
col];
1307 const RowIndex entry_row = entry_rows[i];
1308 if (!marked_[entry_row]) {
1317 marked_[entry_row] =
false;
1327 nodes_to_explore_.pop_back();
1335 stored_[
row] =
true;
1337 nodes_to_explore_.pop_back();
1344 const EntryIndex
end = pruned_ends_[
col];
1346 const RowIndex entry_row = entry_rows[i];
1347 if (!stored_[entry_row]) {
1348 nodes_to_explore_.push_back(entry_row);
1350 marked_[entry_row] =
true;
1358 for (
const RowIndex
row : *lower_column_rows) {
1359 stored_[
row] =
false;
1361 for (
const RowIndex
row : *upper_column_rows) {
1362 stored_[
row] =
false;
1368 if (non_zero_rows->empty())
return;
1378 const int sparsity_threshold =
1379 static_cast<int>(0.025 *
static_cast<double>(
num_rows_.value()));
1380 const int num_ops_threshold =
1381 static_cast<int>(0.05 *
static_cast<double>(
num_rows_.value()));
1382 int num_ops = non_zero_rows->size();
1383 if (num_ops > sparsity_threshold) {
1384 non_zero_rows->clear();
1390 nodes_to_explore_.clear();
1391 nodes_to_explore_.swap(*non_zero_rows);
1396 while (!nodes_to_explore_.empty()) {
1397 const RowIndex
row = nodes_to_explore_.back();
1402 nodes_to_explore_.pop_back();
1403 const RowIndex explored_row = -
row - 1;
1404 stored_[explored_row] =
true;
1411 nodes_to_explore_.pop_back();
1420 nodes_to_explore_.back() = -
row - 1;
1423 const RowIndex entry_row = entry_rows[i];
1424 if (!stored_[entry_row]) {
1425 nodes_to_explore_.push_back(entry_row);
1432 if (num_ops > num_ops_threshold)
break;
1436 for (
const RowIndex
row : *non_zero_rows) {
1437 stored_[
row] =
false;
1441 if (num_ops > num_ops_threshold) non_zero_rows->
clear();
1446 static const Fractional kDefaultSparsityRatio = 0.025;
1447 static const Fractional kDefaultNumOpsRatio = 0.05;
1449 kDefaultNumOpsRatio);
1455 if (non_zero_rows->empty())
return;
1458 const int sparsity_threshold =
1459 static_cast<int>(0.025 *
static_cast<double>(
num_rows_.value()));
1460 const int num_ops_threshold =
1461 static_cast<int>(0.05 *
static_cast<double>(
num_rows_.value()));
1462 int num_ops = non_zero_rows->size();
1463 if (num_ops > sparsity_threshold) {
1464 non_zero_rows->clear();
1469 for (
const RowIndex
row : *non_zero_rows) stored_[
row] =
true;
1472 for (
int i = 0; i < non_zero_rows->size(); ++i) {
1473 const RowIndex
row = (*non_zero_rows)[i];
1476 const RowIndex entry_row = entry_rows[i];
1477 if (!stored_[entry_row]) {
1478 non_zero_rows->push_back(entry_row);
1479 stored_[entry_row] =
true;
1482 if (num_ops > num_ops_threshold)
break;
1485 for (
const RowIndex
row : *non_zero_rows) stored_[
row] =
false;
1486 if (num_ops > num_ops_threshold) {
1487 non_zero_rows->
clear();
1489 std::sort(non_zero_rows->begin(), non_zero_rows->end());
1498 if (first_non_identity_column_ ==
num_cols_) {
1509 for (
int i = 0; i <
num_cols; ++i) {
1510 const ColIndex
col(is_upper ?
num_cols - 1 - i : i);
1511 DCHECK_NE(diagonal_coefficients_[
col], 0.0);
1513 std::abs(diagonal_coefficients_[
col]);
1516 for (
const EntryIndex i :
Column(
col)) {
1517 row_norm_estimate[entry_rows[i]] +=
1518 coeff * std::abs(entry_coefficients[i]);
1522 return *std::max_element(row_norm_estimate.
begin(), row_norm_estimate.
end());
1543 row_sum[
row] += std::abs(right_hand_side[
row]);
void push_back(const value_type &x)
void swap(StrongVector &x)
ColIndex AddDenseColumn(const DenseColumn &dense_column)
StrictITIVector< ColIndex, EntryIndex > starts_
ColIndex num_cols() const
ColIndex AddDenseColumnWithNonZeros(const DenseColumn &dense_column, const std::vector< RowIndex > &non_zeros)
::util::IntegerRange< EntryIndex > Column(ColIndex col) const
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
StrictITIVector< EntryIndex, Fractional > coefficients_
void PopulateFromTranspose(const CompactSparseMatrix &input)
void Reset(RowIndex num_rows)
void PopulateFromSparseMatrixAndAddSlacks(const SparseMatrix &input)
void PopulateFromMatrixView(const MatrixView &input)
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)
SparseColumn * mutable_column(ColIndex col)
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)
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
constexpr double kInfinity
ColIndex RowToColIndex(RowIndex row)
constexpr RowIndex kInvalidRow(-1)
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