28#ifndef ORTOOLS_LP_DATA_SPARSE_H_
29#define ORTOOLS_LP_DATA_SPARSE_H_
36#include "absl/log/check.h"
37#include "absl/types/span.h"
76#if (!defined(_MSC_VER) || _MSC_VER >= 1800)
78 std::initializer_list<std::initializer_list<Fractional>> init_list);
132 template <
typename Matrix>
141 template <
typename Matrix>
187 RowIndex
num_rows()
const {
return num_rows_; }
188 ColIndex
num_cols()
const {
return ColIndex(columns_.size()); }
209 std::string
Dump()
const;
238 for (ColIndex col(0); col <
num_cols; ++col) {
239 columns_[col] = &matrix.
column(col);
250 for (ColIndex col(0); col < matrix_a.
num_cols(); ++col) {
251 columns_[col] = &matrix_a.
column(col);
253 for (ColIndex col(0); col < matrix_b.
num_cols(); ++col) {
263 for (RowIndex row(0); row < basis.size(); ++row) {
266 num_rows_ = matrix.num_rows();
270 bool IsEmpty()
const {
return columns_.empty(); }
271 RowIndex
num_rows()
const {
return num_rows_; }
272 ColIndex
num_cols()
const {
return columns_.size(); }
305 : coefficients_(matrix->coefficients_.data()),
306 rows_(matrix->rows_.data()),
307 starts_(matrix->starts_.data()) {}
316 return ::util::IntegerRange<EntryIndex>(
starts_[col.value()],
317 starts_[col.value() + 1]);
319 Fractional EntryCoefficient(EntryIndex i)
const {
322 RowIndex EntryRow(EntryIndex i)
const {
return rows_[i.value()]; }
325 return starts_[col.value() + 1] - starts_[col.value()];
335 const RowIndex*
const rows_;
336 const EntryIndex*
const starts_;
340 ConstView view()
const {
return ConstView(
this); }
387 absl::Span<const RowIndex> non_zeros);
394 std::vector<RowIndex>* non_zeros);
402 EntryIndex num_entries()
const {
403 DCHECK_EQ(coefficients_.size(), rows_.size());
406 RowIndex num_rows()
const {
return num_rows_; }
407 ColIndex num_cols()
const {
return num_cols_; }
418 DCHECK_LT(col, num_cols_);
422 const EntryIndex start =
starts_[col];
429 bool ColumnIsEmpty(ColIndex col)
const {
430 return starts_[col + 1] == starts_[col];
436 return view().ColumnScalarProduct(col, vector.
const_view());
442 void ColumnAddMultipleToDenseColumn(ColIndex col,
Fractional multiplier,
444 if (multiplier == 0.0)
return;
445 const auto entry_rows =
rows_.view();
447 for (
const EntryIndex i :
Column(col)) {
448 dense_column[entry_rows[i]] += multiplier * entry_coeffs[i];
451 void ColumnAddMultipleToDenseColumn(ColIndex col,
Fractional multiplier,
454 dense_column->view());
460 void ColumnAddMultipleToSparseScatteredColumn(ColIndex col,
464 if (multiplier == 0.0)
return;
465 const auto entry_rows =
rows_.view();
467 for (
const EntryIndex i :
Column(col)) {
468 column->Add(entry_rows[i], multiplier * entry_coeffs[i]);
474 void ColumnCopyToDenseColumn(ColIndex col,
DenseColumn* dense_column)
const {
482 void ColumnCopyToClearedDenseColumn(ColIndex col,
486 const auto entry_rows =
rows_.view();
488 for (
const EntryIndex i :
Column(col)) {
489 (*dense_column)[entry_rows[i]] = entry_coeffs[i];
494 void ColumnCopyToClearedDenseColumnWithNonZeros(
500 const auto entry_rows =
rows_.view();
502 for (
const EntryIndex i :
Column(col)) {
503 const RowIndex row = entry_rows[i];
504 (*dense_column)[row] = entry_coeffs[i];
505 non_zeros->push_back(row);
514 return ::util::IntegerRange<EntryIndex>(starts_[col], starts_[col + 1]);
533 int i = starts_[col.value()].value();
534 const int end = starts_[col.value() + 1].value();
535 const int shifted_end =
end - 3;
540 for (; i < shifted_end; i += 4) {
541 result1 += coefficients_[i] * vector[
RowToColIndex(rows_[i])];
542 result2 += coefficients_[i + 1] * vector[
RowToColIndex(rows_[i + 1])];
543 result3 += coefficients_[i + 2] * vector[
RowToColIndex(rows_[i + 2])];
544 result4 += coefficients_[i + 3] * vector[
RowToColIndex(rows_[i + 3])];
546 Fractional result = result1 + result2 + result3 + result4;
563class CompactSparseMatrixView {
567 : compact_matrix_(*compact_matrix),
568 columns_(basis->data(), basis->size().value()) {}
570 const std::vector<ColIndex>* columns)
571 : compact_matrix_(*compact_matrix), columns_(*columns) {}
574 bool IsEmpty()
const {
return compact_matrix_.IsEmpty(); }
575 RowIndex
num_rows()
const {
return compact_matrix_.num_rows(); }
576 ColIndex
num_cols()
const {
return ColIndex(columns_.size()); }
578 return compact_matrix_.column(columns_[col.value()]);
588 const absl::Span<const ColIndex> columns_;
611 bool IsEmpty()
const {
return diagonal_coefficients_.empty(); }
643 RowIndex diagonal_row,
645 void AddDiagonalOnlyColumn(
Fractional diagonal_value);
652 RowIndex diagonal_row,
656 void ApplyRowPermutationToNonDiagonalEntries(
const RowPermutation& row_perm);
659 void CopyColumnToSparseColumn(ColIndex col,
SparseColumn* output)
const;
667 ColIndex GetFirstNonIdentityColumn()
const {
668 return first_non_identity_column_;
672 Fractional GetDiagonalCoefficient(ColIndex col)
const {
673 return diagonal_coefficients_[col];
677 bool ColumnIsDiagonalOnly(ColIndex col)
const {
700 void LowerSolveStartingAt(ColIndex start,
DenseColumn* rhs)
const;
736 void HyperSparseSolveWithReversedNonZeros(
740 void TransposeHyperSparseSolveWithReversedNonZeros(
748 void ComputeRowsToConsiderWithDfs(
RowIndexVector* non_zero_rows)
const;
754 void ComputeRowsToConsiderInSortedOrder(
RowIndexVector* non_zero_rows)
const;
793 void PermutedLowerSparseSolve(
const ColumnView& rhs,
798 int64_t NumFpOperationsInLastPermutedLowerSparseSolve()
const {
799 return num_fp_operations_;
837 template <
bool diagonal_of_ones>
838 void LowerSolveStartingAtInternal(ColIndex start,
840 template <
bool diagonal_of_ones>
842 template <
bool diagonal_of_ones>
844 template <
bool diagonal_of_ones>
846 template <
bool diagonal_of_ones>
849 template <
bool diagonal_of_ones>
850 void HyperSparseSolveWithReversedNonZerosInternal(
852 template <
bool diagonal_of_ones>
855 template <
bool diagonal_of_ones>
856 void TransposeHyperSparseSolveWithReversedNonZerosInternal(
869 ColIndex first_non_identity_column_;
873 bool all_diagonal_coefficients_are_one_;
878 mutable std::vector<RowIndex> nodes_to_explore_;
881 int64_t num_fp_operations_;
882 mutable std::vector<RowIndex> lower_column_rows_;
883 mutable std::vector<RowIndex> upper_column_rows_;
884 mutable DenseColumn initially_all_zero_scratchpad_;
const SparseColumn & column(ColIndex col) const
RowIndex num_rows() const
ColIndex num_cols() const
StrictITISpan< RowIndex, Fractional > View
StrictITISpan< ColIndex, const Fractional > ConstView
CompactSparseMatrixView(const CompactSparseMatrix *compact_matrix, const RowToColMapping *basis)
EntryIndex ColumnNumEntries(ColIndex col) const
ConstView(const CompactSparseMatrix *matrix)
Fractional ColumnScalarProduct(ColIndex col, DenseRow::ConstView vector) const
void Reset(RowIndex num_rows)
void PopulateFromMatrixView(const MatrixView &input)
CompactSparseMatrix & operator=(const CompactSparseMatrix &)=delete
CompactSparseMatrix()=default
ColIndex AddDenseColumnPrefix(DenseColumn::ConstView dense_column, RowIndex start)
StrictITIVector< EntryIndex, Fractional > coefficients_
void ColumnAddMultipleToDenseColumn(ColIndex col, Fractional multiplier, DenseColumn *dense_column) const
ColIndex AddDenseColumn(const DenseColumn &dense_column)
void PopulateFromSparseMatrixAndAddSlacks(const SparseMatrix &input)
StrictITIVector< ColIndex, EntryIndex > starts_
EntryIndex num_entries() const
ColIndex AddAndClearColumnWithNonZeros(DenseColumn *column, std::vector< RowIndex > *non_zeros)
RowIndex num_rows() const
ColIndex AddDenseColumnWithNonZeros(const DenseColumn &dense_column, absl::Span< const RowIndex > non_zeros)
ColIndex num_cols() const
void AddEntryToCurrentColumn(RowIndex row, Fractional coeff)
bool ColumnIsEmpty(ColIndex col) const
EntryIndex ColumnNumEntries(ColIndex col) const
StrictITIVector< EntryIndex, RowIndex > rows_
void Swap(CompactSparseMatrix *other)
void ColumnCopyToClearedDenseColumn(ColIndex col, DenseColumn *dense_column) const
Fractional ColumnScalarProduct(ColIndex col, const DenseRow &vector) const
void PopulateFromTranspose(const CompactSparseMatrix &input)
::util::IntegerRange< EntryIndex > Column(ColIndex col) const
ColumnView column(ColIndex col) const
void CloseCurrentColumn()
RowIndex num_rows() const
void PopulateFromMatrixPair(const SparseMatrix &matrix_a, const SparseMatrix &matrix_b)
Fractional ComputeInfinityNorm() const
ColIndex num_cols() const
void PopulateFromMatrix(const SparseMatrix &matrix)
EntryIndex num_entries() const
Fractional ComputeOneNorm() const
void PopulateFromBasis(const MatrixView &matrix, const RowToColMapping &basis)
const SparseColumn & column(ColIndex col) const
void ComputeMinAndMaxMagnitudes(Fractional *min_magnitude, Fractional *max_magnitude) const
void PopulateFromProduct(const SparseMatrix &a, const SparseMatrix &b)
void PopulateFromPermutedMatrix(const Matrix &a, const RowPermutation &row_perm, const ColumnPermutation &inverse_col_perm)
const SparseColumn & column(ColIndex col) const
SparseMatrix & operator=(const SparseMatrix &)=delete
void PopulateFromTranspose(const Matrix &input)
bool CheckNoDuplicates() const
void PopulateFromLinearCombination(Fractional alpha, const SparseMatrix &a, Fractional beta, const SparseMatrix &b)
SparseColumn * mutable_column(ColIndex col)
void AppendUnitVector(RowIndex row, Fractional value)
void Swap(SparseMatrix *matrix)
void ApplyRowPermutation(const RowPermutation &row_perm)
void DeleteRows(RowIndex num_rows, const RowPermutation &permutation)
void PopulateFromIdentity(ColIndex num_cols)
RowIndex num_rows() const
Fractional ComputeInfinityNorm() const
void PopulateFromZero(RowIndex num_rows, ColIndex num_cols)
bool AppendRowsFromSparseMatrix(const SparseMatrix &matrix)
void DeleteColumns(const DenseBooleanRow &columns_to_delete)
Fractional ComputeOneNorm() const
void PopulateFromSparseMatrix(const SparseMatrix &matrix)
bool Equals(const SparseMatrix &a, Fractional tolerance) const
ColIndex num_cols() const
ColIndex AppendEmptyColumn()
void SetNumRows(RowIndex num_rows)
EntryIndex num_entries() const
Fractional LookUpValue(RowIndex row, ColIndex col) const
void AssignToZero(IntType size)
ConstView const_view() const
void resize(IntType size)
Fractional ComputeInverseInfinityNorm() const
bool IsUpperTriangular() const
Fractional ComputeInverseInfinityNormUpperBound() const
void PermutedComputeRowsToConsider(const ColumnView &rhs, const RowPermutation &row_perm, RowIndexVector *lower_column_rows, RowIndexVector *upper_column_rows)
bool IsLowerTriangular() const
StrictITIVector< RowIndex, ColIndex > RowToColMapping
std::vector< RowIndex > RowIndexVector
StrictITIVector< RowIndex, bool > DenseBooleanColumn
Permutation< ColIndex > ColumnPermutation
Permutation< RowIndex > RowPermutation
ColIndex RowToColIndex(RowIndex row)
StrictITIVector< RowIndex, RowIndex > RowMapping
StrictITIVector< RowIndex, Fractional > DenseColumn
StrictITIVector< ColIndex, Fractional > DenseRow
StrictITIVector< ColIndex, bool > DenseBooleanRow
ClosedInterval::Iterator end(ClosedInterval interval)
static int input(yyscan_t yyscanner)
#define RETURN_IF_NULL(x)