16bool is_bound(
const Box<config_t> &C,
index_t i) {
18 return isnan(C.lowerbound(i) + C.upperbound(i)) == 0;
29void add_bound_constr_to_constr_matrix(ladel_sparse_matrix &A,
30 const Box<config_t> &C) {
31 using mindexvec = Eigen::Map<Eigen::VectorX<qpalm::sp_index_t>>;
33 auto m =
static_cast<index_t>(A.nrow), n =
static_cast<index_t>(A.ncol);
34 auto old_nnz =
static_cast<index_t>(A.p[n]);
43 mindexvec outer_ptrs{A.p, n + 1};
46 for (
index_t col = 0; col < n; ++col) {
47 shift += is_bound(C, col) ? 1 : 0;
48 outer_ptrs(col + 1) += shift;
52 auto num_bound_constr = shift;
55 mindexvec{A.i, old_nnz}.array() += num_bound_constr;
66 for (
index_t col = n; col-- > 0;) {
68 index_t insert_nz = is_bound(C, col) ? 1 : 0;
70 index_t prev_shift = shift - insert_nz;
71 index_t next_outer = outer_ptrs(col + 1) - shift;
72 index_t curr_outer = outer_ptrs(col) - prev_shift;
74 index_t *inners_ptr = A.i + curr_outer, *inners_end = A.i + next_outer;
75 real_t *values_ptr = A.x + curr_outer, *values_end = A.x + next_outer;
78 std::shift_right(inners_ptr, inners_end + shift, shift);
79 std::shift_right(values_ptr, values_end + shift, shift);
82 inners_ptr[shift - 1] = shift - 1;
83 values_ptr[shift - 1] = 1;
89 A.nrow = m + num_bound_constr;
90 A.nzmax = old_nnz + num_bound_constr;
95void combine_bound_constr(Box<config_t> &b,
const Box<config_t> &C,
96 const Box<config_t> &D,
crvec g) {
97 const auto n = C.lowerbound.size(), m = D.lowerbound.size();
99 for (
index_t i = 0; i < n; ++i) {
100 if (is_bound(C, i)) {
101 b.lowerbound(c) = C.lowerbound(i);
102 b.upperbound(c) = C.upperbound(i);
106 assert(c ==
static_cast<length_t>(b.lowerbound.size() - m));
107 b.lowerbound.segment(c, m) = D.lowerbound - g;
108 b.upperbound.segment(c, m) = D.upperbound - g;
118 const auto n = problem.
get_n(), m = problem.
get_m();
121 if (nnz_Q < 0 || nnz_A < 0)
122 throw std::logic_error(
123 "Only sparse Hessians and Jacobians are supported");
124 auto cvt_idx = [](
index_t i) {
return static_cast<qpalm::sp_index_t
>(i); };
127 vec x = vec::Zero(n), y = vec::Zero(m), g(m);
133 qp.
sto->Q = qpalm::ladel_sparse_create(n, n, nnz_Q, UPPER);
134 qp.Q = qp.
sto->Q.get();
138 problem.
eval_hess_L(x, y, 1, inner_idx, outer_ptr, null_vec<config_t>);
140 std::ranges::transform(inner_idx, qp.Q->i, cvt_idx);
141 std::ranges::transform(outer_ptr, qp.Q->p, cvt_idx);
143 mvec H_values{qp.Q->x, nnz_Q};
144 problem.
eval_hess_L(x, y, 1, inner_idx, outer_ptr, H_values);
147 qp.
sto->A = qpalm::ladel_sparse_create(m, n, nnz_A + n, UNSYMMETRIC);
148 qp.A = qp.
sto->A.get();
152 problem.
eval_jac_g(x, inner_idx, outer_ptr, null_vec<config_t>);
154 std::ranges::transform(inner_idx, qp.A->i, cvt_idx);
155 std::ranges::transform(outer_ptr, qp.A->p, cvt_idx);
157 mvec J_values{qp.A->x, nnz_A};
158 problem.
eval_jac_g(x, inner_idx, outer_ptr, J_values);
160 add_bound_constr_to_constr_matrix(*qp.A, problem.
get_box_C());
167 qp.q = qp.
sto->q.data();
171 qp.
sto->b.lowerbound.resize(qp.A->nrow);
172 qp.
sto->b.upperbound.resize(qp.A->nrow);
173 qp.bmin = qp.
sto->b.lowerbound.data();
174 qp.bmax = qp.
sto->b.upperbound.data();
177 combine_bound_constr(qp.
sto->b, C, D, g);
179 qp.m =
static_cast<size_t>(qp.A->nrow);
180 qp.n =
static_cast<size_t>(qp.Q->nrow);
The main polymorphic minimization problem interface.
const Box & get_box_D() const
[Optional] Get the rectangular constraint set of the general constraint function, .
length_t get_n() const
[Required] Number of decision variables.
length_t get_m() const
[Required] Number of constraints.
void eval_hess_L(crvec x, crvec y, real_t scale, rindexvec inner_idx, rindexvec outer_ptr, rvec H_values) const
[Optional] Function that evaluates the Hessian of the Lagrangian as a sparse matrix,
real_t eval_f_grad_f(crvec x, rvec grad_fx) const
[Optional] Evaluate both and its gradient, .
void eval_g(crvec x, rvec gx) const
[Required] Function that evaluates the constraints,
length_t get_jac_g_num_nonzeros() const
[Optional] Function that gets the number of nonzeros of the sparse Jacobian of the constraints.
const Box & get_box_C() const
[Optional] Get the rectangular constraint set of the decision variables, .
void eval_jac_g(crvec x, rindexvec inner_idx, rindexvec outer_ptr, rvec J_values) const
[Optional] Function that evaluates the Jacobian of the constraints as a sparse matrix,
length_t get_hess_L_num_nonzeros() const
[Optional] Function that gets the number of nonzeros of the sparse Hessian of the Lagrangian.
#define USING_ALPAQA_CONFIG(Conf)
typename Conf::indexvec indexvec
QPALM_ADAPTER_EXPORT OwningQPALMData build_qpalm_problem(const TypeErasedProblem< EigenConfigd > &problem)
typename Conf::real_t real_t
typename Conf::index_t index_t
typename Conf::length_t length_t
typename Conf::crvec crvec
Double-precision double configuration.
std::unique_ptr< Storage > sto