19#include "absl/log/check.h"
20#include "absl/types/span.h"
23#include "ortools/glop/parameters.pb.h"
40 transposed_matrix_(transposed_matrix),
41 variables_info_(variables_info),
43 basis_factorization_(basis_factorization),
44 unit_row_left_inverse_(),
45 non_zero_position_list_(),
46 non_zero_position_set_(),
59 return unit_row_left_inverse_;
63 RowIndex leaving_row) {
66 &unit_row_left_inverse_);
67 return unit_row_left_inverse_;
71 if (left_inverse_computed_for_ == leaving_row)
return;
72 left_inverse_computed_for_ = leaving_row;
76 &unit_row_left_inverse_);
81 unit_row_left_inverse_.
values) -
88 if (update_row_computed_for_ == leaving_row)
return;
89 update_row_computed_for_ = leaving_row;
93 if (parameters_.use_transposed_matrix()) {
95 EntryIndex num_row_wise_entries(0);
107 const Fractional drop_tolerance = parameters_.drop_tolerance();
108 unit_row_left_inverse_filtered_non_zeros_.clear();
109 const auto view = transposed_matrix_.
view();
110 if (unit_row_left_inverse_.
non_zeros.empty()) {
113 if (std::abs(unit_row_left_inverse_.
values[
col]) > drop_tolerance) {
114 unit_row_left_inverse_filtered_non_zeros_.push_back(
col);
115 num_row_wise_entries += view.ColumnNumEntries(
col);
119 for (
const auto e : unit_row_left_inverse_) {
120 if (std::abs(e.coefficient()) > drop_tolerance) {
121 unit_row_left_inverse_filtered_non_zeros_.push_back(e.column());
122 num_row_wise_entries += view.ColumnNumEntries(e.column());
131 if (unit_row_left_inverse_filtered_non_zeros_.size() == 1) {
132 ComputeUpdatesForSingleRow(
133 unit_row_left_inverse_filtered_non_zeros_.front());
134 num_operations_ += num_row_wise_entries.value();
136 static_cast<double>(num_non_zeros_) /
137 static_cast<double>(matrix_.
num_cols().value())));
142 const EntryIndex num_col_wise_entries =
148 const double row_wise =
static_cast<double>(num_row_wise_entries.value());
149 if (row_wise < 0.5 *
static_cast<double>(num_col_wise_entries.value())) {
150 if (row_wise < 1.1 *
static_cast<double>(matrix_.
num_cols().value())) {
151 ComputeUpdatesRowWiseHypersparse();
156 5 * num_row_wise_entries.value() + matrix_.
num_cols().value() / 64;
158 ComputeUpdatesRowWise();
160 num_row_wise_entries.value() + matrix_.
num_rows().value();
163 ComputeUpdatesColumnWise();
165 num_col_wise_entries.value() + matrix_.
num_cols().value();
168 ComputeUpdatesColumnWise();
174 static_cast<double>(num_non_zeros_) /
175 static_cast<double>(matrix_.
num_cols().value())));
179 const std::string& algorithm) {
180 unit_row_left_inverse_.
values = lhs;
182 if (algorithm ==
"column") {
183 ComputeUpdatesColumnWise();
184 }
else if (algorithm ==
"row") {
185 ComputeUpdatesRowWise();
186 }
else if (algorithm ==
"row_hypersparse") {
187 ComputeUpdatesRowWiseHypersparse();
189 LOG(DFATAL) <<
"Unknown algorithm in ComputeUpdateRowForBenchmark(): '"
197 return absl::MakeSpan(non_zero_position_list_.data(), num_non_zeros_);
206void UpdateRow::ComputeUpdatesRowWise() {
209 const auto output_coeffs = coefficient_.
view();
210 const auto view = transposed_matrix_.
view();
211 for (
const ColIndex
col : unit_row_left_inverse_filtered_non_zeros_) {
213 for (
const EntryIndex i : view.Column(
col)) {
215 output_coeffs[pos] += multiplier * view.EntryCoefficient(i);
219 non_zero_position_list_.resize(matrix_.
num_cols().value());
220 auto* non_zeros = non_zero_position_list_.data();
221 const Fractional drop_tolerance = parameters_.drop_tolerance();
223 if (std::abs(output_coeffs[
col]) > drop_tolerance) {
227 num_non_zeros_ = non_zeros - non_zero_position_list_.data();
232void UpdateRow::ComputeUpdatesRowWiseHypersparse() {
234 const ColIndex num_cols = matrix_.
num_cols();
236 coefficient_.
resize(num_cols, 0.0);
238 const auto output_coeffs = coefficient_.
view();
239 const auto view = transposed_matrix_.
view();
240 const auto nz_set = non_zero_position_set_.
const_view();
241 for (
const ColIndex
col : unit_row_left_inverse_filtered_non_zeros_) {
243 for (
const EntryIndex i : view.Column(
col)) {
245 const Fractional v = multiplier * view.EntryCoefficient(i);
251 output_coeffs[pos] = v;
252 non_zero_position_set_.
Set(pos);
254 output_coeffs[pos] += v;
261 non_zero_position_list_.resize(matrix_.
num_cols().value());
262 auto* non_zeros = non_zero_position_list_.data();
263 const Fractional drop_tolerance = parameters_.drop_tolerance();
264 for (
const ColIndex
col : non_zero_position_set_) {
269 if (std::abs(output_coeffs[
col]) > drop_tolerance) {
273 num_non_zeros_ = non_zeros - non_zero_position_list_.data();
276void UpdateRow::ComputeUpdatesForSingleRow(ColIndex row_as_col) {
278 non_zero_position_list_.resize(matrix_.
num_cols().value());
279 auto* non_zeros = non_zero_position_list_.data();
282 const Fractional drop_tolerance = parameters_.drop_tolerance();
283 const Fractional multiplier = unit_row_left_inverse_[row_as_col];
284 const auto output_coeffs = coefficient_.
view();
285 const auto view = transposed_matrix_.
view();
286 for (
const EntryIndex i : view.Column(row_as_col)) {
288 if (!is_relevant[pos])
continue;
290 const Fractional v = multiplier * view.EntryCoefficient(i);
291 if (std::abs(v) > drop_tolerance) {
292 output_coeffs[pos] = v;
296 num_non_zeros_ = non_zeros - non_zero_position_list_.data();
299void UpdateRow::ComputeUpdatesColumnWise() {
303 non_zero_position_list_.resize(matrix_.
num_cols().value());
304 auto* non_zeros = non_zero_position_list_.data();
306 const Fractional drop_tolerance = parameters_.drop_tolerance();
307 const auto output_coeffs = coefficient_.
view();
308 const auto view = matrix_.
view();
309 const auto unit_row_left_inverse = unit_row_left_inverse_.
values.
const_view();
313 view.ColumnScalarProduct(
col, unit_row_left_inverse);
319 if (std::abs(coeff) > drop_tolerance) {
321 output_coeffs[
col] = coeff;
324 num_non_zeros_ = non_zeros - non_zero_position_list_.data();
332 CHECK_EQ(leaving_row, left_inverse_computed_for_);
334 const ColIndex num_cols = matrix_.
num_cols();
338 (*output)[basis_[leaving_row]] = 1.0;
341 const Fractional drop_tolerance = parameters_.drop_tolerance();
342 const auto view = matrix_.
view();
343 const auto unit_row_left_inverse = unit_row_left_inverse_.
values.
const_view();
346 view.ColumnScalarProduct(
col, unit_row_left_inverse);
347 if (std::abs(coeff) > drop_tolerance) {
348 (*output)[
col] = coeff;
void Intersection(const Bitset64< IndexType > &other)
void ClearAndResize(IndexType size)
Changes the number of bits the Bitset64 can hold and set all of them to 0.
ConstView const_view() const
void Set(IndexType i)
Sets the bit at position i to 1.
void LeftSolveForUnitRow(ColIndex j, ScatteredRow *y) const
void TemporaryLeftSolveForUnitRow(ColIndex j, ScatteredRow *y) const
Same as LeftSolveForUnitRow() but does not update any internal data.
RowIndex num_rows() const
ColIndex num_cols() const
Fractional ColumnScalarProduct(ColIndex col, const DenseRow &vector) const
void AssignToZero(IntType size)
ConstView const_view() const
void resize(IntType size)
const DenseRow & GetCoefficients() const
const ScatteredRow & ComputeAndGetUnitRowLeftInverse(RowIndex leaving_row)
void SetParameters(const GlopParameters ¶meters)
Sets the algorithm parameters.
void ComputeFullUpdateRow(RowIndex leaving_row, DenseRow *output) const
const ScatteredRow & GetUnitRowLeftInverse() const
void ComputeUnitRowLeftInverse(RowIndex leaving_row)
void ComputeUpdateRow(RowIndex leaving_row)
UpdateRow(const CompactSparseMatrix &matrix, const CompactSparseMatrix &transposed_matrix, const VariablesInfo &variables_info, const RowToColMapping &basis, const BasisFactorization &basis_factorization)
Takes references to the linear program data we need.
void ComputeUpdateRowForBenchmark(const DenseRow &lhs, const std::string &algorithm)
absl::Span< const ColIndex > GetNonZeroPositions() const
EntryIndex GetNumEntriesInRelevantColumns() const
const DenseBitRow & GetNotBasicBitRow() const
const DenseBitRow & GetIsRelevantBitRow() const
double Density(const DenseRow &row)
void ComputeNonZeros(const StrictITIVector< IndexType, Fractional > &input, std::vector< IndexType > *non_zeros)
Computes the positions of the non-zeros of a dense vector.
Bitset64< ColIndex > DenseBitRow
Row of bits.
ColIndex RowToColIndex(RowIndex row)
Get the ColIndex corresponding to the column # row.
constexpr RowIndex kInvalidRow(-1)
In SWIG mode, we don't want anything besides these top-level includes.
#define IF_STATS_ENABLED(instructions)
#define SCOPED_TIME_STAT(stats)
StrictITIVector< Index, Fractional > values
std::vector< Index > non_zeros