21 #include "Eigen/SparseCore"
22 #include "absl/log/check.h"
23 #include "absl/memory/memory.h"
24 #include "absl/strings/string_view.h"
36 void WarnIfMatrixUnbalanced(
37 const Eigen::SparseMatrix<double, Eigen::ColMajor, int64_t>& matrix,
38 absl::string_view matrix_name, int64_t density_limit) {
39 if (matrix.cols() == 0)
return;
40 int64_t worst_column = 0;
41 for (int64_t
col = 0;
col < matrix.cols(); ++
col) {
42 if (matrix.col(
col).nonZeros() > matrix.col(worst_column).nonZeros()) {
46 if (matrix.col(worst_column).nonZeros() > density_limit) {
50 <<
"The " << matrix_name <<
" has "
51 << matrix.col(worst_column).nonZeros() <<
" non-zeros in its "
53 <<
"th column. For best parallelization all rows and columns should "
56 <<
" non-zeros. Consider rewriting the QP to split the corresponding "
57 "variable or constraint.";
64 const int num_threads,
67 transposed_constraint_matrix_(qp_.constraint_matrix.transpose()),
68 thread_pool_(num_threads == 1
70 : std::make_unique<
ThreadPool>(
"PDLP", num_threads)),
71 constraint_matrix_sharder_(qp_.constraint_matrix, num_shards,
73 transposed_constraint_matrix_sharder_(transposed_constraint_matrix_,
74 num_shards, thread_pool_.get()),
77 dual_sharder_(qp_.constraint_lower_bounds.size(), num_shards,
79 CHECK_GE(num_threads, 1);
80 CHECK_GE(num_shards, num_threads);
81 if (num_threads > 1) {
82 thread_pool_->StartWorkers();
86 const int64_t column_density_limit = work_per_iteration / num_threads;
88 column_density_limit);
89 WarnIfMatrixUnbalanced(transposed_constraint_matrix_,
90 "transposed constraint matrix",
91 column_density_limit);
101 const Eigen::VectorXd& col_scaling_vec,
102 const Eigen::VectorXd& row_scaling_vec,
const Sharder& sharder,
103 Eigen::SparseMatrix<double, Eigen::ColMajor, int64_t>& matrix) {
104 CHECK_EQ(matrix.cols(), col_scaling_vec.size());
105 CHECK_EQ(matrix.rows(), row_scaling_vec.size());
107 auto matrix_shard = shard(matrix);
108 auto col_scaling_vec_shard = shard(col_scaling_vec);
109 for (int64_t col_num = 0; col_num < shard(matrix).outerSize(); ++col_num) {
110 for (decltype(matrix_shard)::InnerIterator it(matrix_shard, col_num); it;
113 row_scaling_vec[it.row()] * col_scaling_vec_shard[it.col()];
122 const Eigen::VectorXd& col_scaling_vec,
123 const Eigen::VectorXd& row_scaling_vec) {
124 CHECK_EQ(
PrimalSize(), col_scaling_vec.size());
125 CHECK_EQ(
DualSize(), row_scaling_vec.size());
127 CHECK((shard(col_scaling_vec).array() > 0.0).all());
138 shard(col_scaling_vec).cwiseProduct(shard(col_scaling_vec)));
142 CHECK((shard(row_scaling_vec).array() > 0.0).all());
149 ScaleMatrix(col_scaling_vec, row_scaling_vec, constraint_matrix_sharder_,
151 ScaleMatrix(row_scaling_vec, col_scaling_vec,
152 transposed_constraint_matrix_sharder_,
153 transposed_constraint_matrix_);
void RescaleQuadraticProgram(const Eigen::VectorXd &col_scaling_vec, const Eigen::VectorXd &row_scaling_vec)
ShardedQuadraticProgram(QuadraticProgram qp, int num_threads, int num_shards)
int64_t PrimalSize() const
void ParallelForEachShard(const std::function< void(const Shard &)> &func) const
bool IsLinearProgram(const QuadraticProgram &qp)
Eigen::VectorXd variable_upper_bounds
Eigen::VectorXd variable_lower_bounds
Eigen::VectorXd constraint_lower_bounds
Eigen::SparseMatrix< double, Eigen::ColMajor, int64_t > constraint_matrix
std::optional< Eigen::DiagonalMatrix< double, Eigen::Dynamic > > objective_matrix
Eigen::VectorXd constraint_upper_bounds
Eigen::VectorXd objective_vector
VectorXd variable_lower_bounds