22#include "Eigen/SparseCore"
23#include "absl/container/flat_hash_map.h"
24#include "absl/status/status.h"
25#include "absl/status/statusor.h"
26#include "absl/strings/str_cat.h"
30#include "ortools/math_opt/model.pb.h"
31#include "ortools/math_opt/sparse_containers.pb.h"
38absl::StatusOr<SparseDoubleVectorProto> ExtractSolution(
39 const Eigen::VectorXd& values,
const std::vector<int64_t>& pdlp_index_to_id,
40 const SparseVectorFilterProto& filter,
const double scale) {
41 if (values.size() != pdlp_index_to_id.size()) {
42 return absl::InternalError(
43 absl::StrCat(
"Expected solution vector with ", pdlp_index_to_id.size(),
44 " elements, found: ", values.size()));
46 SparseVectorFilterPredicate predicate(filter);
47 SparseDoubleVectorProto result;
48 for (
int i = 0; i < pdlp_index_to_id.size(); ++i) {
49 const double value = scale * values[i];
50 const int64_t
id = pdlp_index_to_id[i];
51 if (predicate.AcceptsAndUpdate(
id,
value)) {
53 result.add_values(
value);
65 const VariablesProto& variables =
model_proto.variables();
66 const LinearConstraintsProto& linear_constraints =
69 linear_constraints.ids_size());
73 if (variables.names_size() > 0) {
75 variables.names().end()};
77 if (linear_constraints.names_size() > 0) {
79 linear_constraints.names().end()};
81 for (
int i = 0; i < variables.ids_size(); ++i) {
82 result.var_id_to_pdlp_index_[variables.ids(i)] = i;
83 result.pdlp_index_to_var_id_.push_back(variables.ids(i));
86 if (variables.integers(i)) {
87 return absl::InvalidArgumentError(
88 "PDLP cannot solve problems with integer variables");
91 for (
int i = 0; i < linear_constraints.ids_size(); ++i) {
92 result.lin_con_id_to_pdlp_index_[linear_constraints.ids(i)] = i;
93 result.pdlp_index_to_lin_con_id_.push_back(linear_constraints.ids(i));
97 const bool is_maximize =
model_proto.objective().maximize();
98 const double obj_scale = is_maximize ? -1.0 : 1.0;
100 for (
const auto [var_id,
coef] :
105 const SparseDoubleMatrixProto& quadratic_objective =
107 const int obj_nnz = quadratic_objective.row_ids().size();
112 for (
int i = 0; i < obj_nnz; ++i) {
113 const int64_t row_index =
114 result.var_id_to_pdlp_index_.at(quadratic_objective.row_ids(i));
115 const int64_t column_index =
116 result.var_id_to_pdlp_index_.at(quadratic_objective.column_ids(i));
117 const double value = obj_scale * quadratic_objective.coefficients(i);
118 if (row_index != column_index) {
119 return absl::InvalidArgumentError(
120 "PDLP cannot solve problems with non-diagonal objective matrices");
134 std::vector<Eigen::Triplet<double, int64_t>> mat_triplets;
135 const int nnz =
model_proto.linear_constraint_matrix().row_ids_size();
136 mat_triplets.reserve(nnz);
137 const SparseDoubleMatrixProto& proto_mat =
139 for (
int i = 0; i < nnz; ++i) {
140 const int64_t row_index =
141 result.lin_con_id_to_pdlp_index_.at(proto_mat.row_ids(i));
142 const int64_t column_index =
143 result.var_id_to_pdlp_index_.at(proto_mat.column_ids(i));
144 const double value = proto_mat.coefficients(i);
145 mat_triplets.emplace_back(row_index, column_index,
value);
154 for (int64_t var_index = 0; var_index < pdlp_index_to_var_id_.size();
158 inverted_bounds.
variables.push_back(pdlp_index_to_var_id_[var_index]);
161 for (int64_t lin_con_index = 0;
162 lin_con_index < pdlp_index_to_lin_con_id_.size(); ++lin_con_index) {
166 pdlp_index_to_lin_con_id_[lin_con_index]);
169 return inverted_bounds;
173 const Eigen::VectorXd& primal_values,
174 const SparseVectorFilterProto& variable_filter)
const {
175 return ExtractSolution(primal_values, pdlp_index_to_var_id_, variable_filter,
179 const Eigen::VectorXd& dual_values,
180 const SparseVectorFilterProto& linear_constraint_filter)
const {
181 return ExtractSolution(dual_values, pdlp_index_to_lin_con_id_,
182 linear_constraint_filter,
186 const Eigen::VectorXd& reduced_costs,
187 const SparseVectorFilterProto& variable_filter)
const {
188 return ExtractSolution(reduced_costs, pdlp_index_to_var_id_, variable_filter,
const pdlp::QuadraticProgram & pdlp_lp() const
absl::StatusOr< SparseDoubleVectorProto > DualVariablesToProto(const Eigen::VectorXd &dual_values, const SparseVectorFilterProto &linear_constraint_filter) const
static absl::StatusOr< PdlpBridge > FromProto(const ModelProto &model_proto)
InvertedBounds ListInvertedBounds() const
absl::StatusOr< SparseDoubleVectorProto > PrimalVariablesToProto(const Eigen::VectorXd &primal_values, const SparseVectorFilterProto &variable_filter) const
absl::StatusOr< SparseDoubleVectorProto > ReducedCostsToProto(const Eigen::VectorXd &reduced_costs, const SparseVectorFilterProto &variable_filter) const
CpModelProto const * model_proto
SparseVectorView< T > MakeView(absl::Span< const int64_t > ids, const Collection &values)
Collection of objects used to extend the Constraint Solver library.
std::vector< int64_t > variables
std::vector< int64_t > linear_constraints
Eigen::VectorXd variable_upper_bounds
Eigen::VectorXd variable_lower_bounds
double objective_scaling_factor
absl::optional< std::vector< std::string > > constraint_names
absl::optional< std::vector< std::string > > variable_names
Eigen::VectorXd constraint_lower_bounds
absl::optional< std::string > problem_name
void ResizeAndInitialize(int64_t num_variables, int64_t num_constraints)
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