28#ifndef OR_TOOLS_LP_DATA_SPARSE_H_
29#define OR_TOOLS_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;
236 const ColIndex
num_cols = matrix.num_cols();
238 for (ColIndex col(0); col <
num_cols; ++col) {
239 columns_[col] = &matrix.column(col);
241 num_rows_ = matrix.num_rows();
247 const SparseMatrix& matrix_b) {
248 const ColIndex
num_cols = matrix_a.num_cols() + matrix_b.num_cols();
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) {
254 columns_[matrix_a.num_cols() + col] = &matrix_b.column(col);
256 num_rows_ = std::max(matrix_a.num_rows(), matrix_b.num_rows());
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_;
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)
Same as AddDenseColumn(), but only adds the non-zero from the given 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
Returns the matrix dimensions. See same functions in SparseMatrix.
ColIndex AddAndClearColumnWithNonZeros(DenseColumn *column, std::vector< RowIndex > *non_zeros)
RowIndex num_rows() const
bool IsEmpty() const
Returns whether or not this matrix contains any non-zero entries.
ColIndex AddDenseColumnWithNonZeros(const DenseColumn &dense_column, absl::Span< const RowIndex > non_zeros)
ColIndex num_cols() const
void AddEntryToCurrentColumn(RowIndex row, Fractional coeff)
Api to add columns one at the time.
bool ColumnIsEmpty(ColIndex col) const
EntryIndex ColumnNumEntries(ColIndex col) const
Returns the number of entries (i.e. degree) of the given column.
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)
RowIndex num_rows_
The matrix dimensions, properly updated by full and incremental builders.
::util::IntegerRange< EntryIndex > Column(ColIndex col) const
Functions to iterate on the entries of a given column.
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)
Takes all the columns of the given matrix.
bool IsEmpty() const
Same behavior as the SparseMatrix functions above.
EntryIndex num_entries() const
Fractional ComputeOneNorm() const
void PopulateFromBasis(const MatrixView &matrix, const RowToColMapping &basis)
Takes only the columns of the given matrix that belongs to the given basis.
const SparseColumn & column(ColIndex col) const
void ComputeMinAndMaxMagnitudes(Fractional *min_magnitude, Fractional *max_magnitude) const
void PopulateFromProduct(const SparseMatrix &a, const SparseMatrix &b)
Multiplies SparseMatrix a by SparseMatrix b.
std::string Dump() const
Returns a dense representation of the matrix.
void PopulateFromPermutedMatrix(const Matrix &a, const RowPermutation &row_perm, const ColumnPermutation &inverse_col_perm)
const SparseColumn & column(ColIndex col) const
Access the underlying sparse columns.
SparseMatrix & operator=(const SparseMatrix &)=delete
void PopulateFromTranspose(const Matrix &input)
Instantiate needed templates.
bool CheckNoDuplicates() const
Call CheckNoDuplicates() on all columns, useful for doing a DCHECK.
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)
bool IsCleanedUp() const
Call IsCleanedUp() on all columns, useful for doing a DCHECK.
void ApplyRowPermutation(const RowPermutation &row_perm)
Applies the row permutation.
void DeleteRows(RowIndex num_rows, const RowPermutation &permutation)
void PopulateFromIdentity(ColIndex num_cols)
RowIndex num_rows() const
Return the matrix dimension.
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()
Appends an empty column and returns its index.
void SetNumRows(RowIndex num_rows)
Change the number of row of this matrix.
EntryIndex num_entries() const
Fractional LookUpValue(RowIndex row, ColIndex col) const
StrictITISpan< RowIndex, Fractional > View
void AssignToZero(IntType size)
StrictITISpan< ColIndex, const Fractional > ConstView
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
Column of booleans.
Permutation< ColIndex > ColumnPermutation
Permutation< RowIndex > RowPermutation
ColIndex RowToColIndex(RowIndex row)
Get the ColIndex corresponding to the column # row.
StrictITIVector< RowIndex, RowIndex > RowMapping
Column of row indices. Used to represent mappings between rows.
StrictITIVector< RowIndex, Fractional > DenseColumn
Column-vector types. Column-vector types are indexed by a row index.
StrictITIVector< ColIndex, Fractional > DenseRow
Row-vector types. Row-vector types are indexed by a column index.
StrictITIVector< ColIndex, bool > DenseBooleanRow
Row of booleans.
In SWIG mode, we don't want anything besides these top-level includes.
ClosedInterval::Iterator end(ClosedInterval interval)
static int input(yyscan_t yyscanner)
#define RETURN_IF_NULL(x)