22#include "Eigen/SparseCore"
23#include "absl/log/check.h"
24#include "absl/strings/string_view.h"
37void WarnIfMatrixUnbalanced(
38 const Eigen::SparseMatrix<double, Eigen::ColMajor, int64_t>& matrix,
39 absl::string_view matrix_name, int64_t density_limit,
41 if (matrix.cols() == 0)
return;
42 int64_t worst_column = 0;
43 for (int64_t
col = 0;
col < matrix.cols(); ++
col) {
44 if (matrix.col(
col).nonZeros() > matrix.col(worst_column).nonZeros()) {
48 if (matrix.col(worst_column).nonZeros() > density_limit) {
53 logger,
"WARNING: The ", matrix_name,
" has ",
54 matrix.col(worst_column).nonZeros(),
" non-zeros in its ",
56 "th column. For best parallelization all rows and columns should "
57 "have at most order ",
59 " non-zeros. Consider rewriting the QP to split the corresponding "
60 "variable or constraint.");
63 <<
"The " << matrix_name <<
" has "
64 << matrix.col(worst_column).nonZeros() <<
" non-zeros in its "
66 <<
"th column. For best parallelization all rows and columns should "
69 <<
" non-zeros. Consider rewriting the QP to split the corresponding "
70 "variable or constraint.";
81 transposed_constraint_matrix_(qp_.constraint_matrix.transpose()),
82 thread_pool_(num_threads == 1
85 constraint_matrix_sharder_(qp_.constraint_matrix, num_shards,
87 transposed_constraint_matrix_sharder_(transposed_constraint_matrix_,
88 num_shards, thread_pool_.get()),
89 primal_sharder_(qp_.variable_lower_bounds.
size(), num_shards,
91 dual_sharder_(qp_.constraint_lower_bounds.
size(), num_shards,
93 CHECK_GE(num_threads, 1);
94 CHECK_GE(num_shards, num_threads);
95 if (num_threads > 1) {
96 thread_pool_->StartWorkers();
100 const int64_t column_density_limit = work_per_iteration / num_threads;
102 column_density_limit, logger);
103 WarnIfMatrixUnbalanced(transposed_constraint_matrix_,
104 "transposed constraint matrix", column_density_limit,
115 const Eigen::VectorXd& col_scaling_vec,
116 const Eigen::VectorXd& row_scaling_vec,
const Sharder& sharder,
117 Eigen::SparseMatrix<double, Eigen::ColMajor, int64_t>& matrix) {
118 CHECK_EQ(matrix.cols(), col_scaling_vec.size());
119 CHECK_EQ(matrix.rows(), row_scaling_vec.size());
121 auto matrix_shard = shard(matrix);
122 auto col_scaling_vec_shard = shard(col_scaling_vec);
123 for (int64_t col_num = 0; col_num < shard(matrix).outerSize(); ++col_num) {
124 for (
decltype(matrix_shard)::InnerIterator it(matrix_shard, col_num); it;
127 row_scaling_vec[it.row()] * col_scaling_vec_shard[it.col()];
133void ReplaceLargeValuesWithInfinity(
const double threshold,
134 const Sharder& sharder,
135 Eigen::VectorXd& vector) {
136 constexpr double kInfinity = std::numeric_limits<double>::infinity();
137 sharder.ParallelForEachShard([&](
const Sharder::Shard& shard) {
138 auto vector_shard = shard(vector);
139 for (int64_t i = 0;
i < vector_shard.size(); ++
i) {
140 if (vector_shard[i] <= -threshold) vector_shard[
i] = -
kInfinity;
141 if (vector_shard[i] >= threshold) vector_shard[
i] =
kInfinity;
149 const Eigen::VectorXd& col_scaling_vec,
150 const Eigen::VectorXd& row_scaling_vec) {
151 CHECK_EQ(
PrimalSize(), col_scaling_vec.size());
152 CHECK_EQ(
DualSize(), row_scaling_vec.size());
154 CHECK((shard(col_scaling_vec).array() > 0.0).all());
165 shard(col_scaling_vec).cwiseProduct(shard(col_scaling_vec)));
169 CHECK((shard(row_scaling_vec).array() > 0.0).all());
176 ScaleMatrix(col_scaling_vec, row_scaling_vec, constraint_matrix_sharder_,
178 ScaleMatrix(row_scaling_vec, col_scaling_vec,
179 transposed_constraint_matrix_sharder_,
180 transposed_constraint_matrix_);
184 const double threshold) {
185 ReplaceLargeValuesWithInfinity(threshold,
DualSharder(),
187 ReplaceLargeValuesWithInfinity(threshold,
DualSharder(),
int64_t PrimalSize() const
void SetConstraintBounds(int64_t constraint_index, std::optional< double > lower_bound, std::optional< double > upper_bound)
ShardedQuadraticProgram(QuadraticProgram qp, int num_threads, int num_shards, operations_research::SolverLogger *logger=nullptr)
const Sharder & DualSharder() const
Returns a Sharder intended for dual vectors.
void ReplaceLargeConstraintBoundsWithInfinity(double threshold)
void RescaleQuadraticProgram(const Eigen::VectorXd &col_scaling_vec, const Eigen::VectorXd &row_scaling_vec)
void ParallelForEachShard(const std::function< void(const Shard &)> &func) const
Runs func on each of the shards.
Validation utilities for solvers.proto.
constexpr double kInfinity
bool IsLinearProgram(const QuadraticProgram &qp)
Eigen::VectorXd variable_lower_bounds
Eigen::VectorXd constraint_lower_bounds
Eigen::VectorXd objective_vector
std::optional< Eigen::DiagonalMatrix< double, Eigen::Dynamic > > objective_matrix
Eigen::SparseMatrix< double, Eigen::ColMajor, int64_t > constraint_matrix
Eigen::VectorXd variable_upper_bounds
Eigen::VectorXd constraint_upper_bounds
#define SOLVER_LOG(logger,...)