28 #include "casadi/core/casadi_misc.hpp"
29 #include "casadi/core/calculus.hpp"
30 #include "casadi/core/conic.hpp"
41 int CASADI_NLPSOL_QRSQP_EXPORT
44 plugin->name =
"qrsqp";
46 plugin->version = CASADI_VERSION;
68 "The QP solver to be used by the SQP method [qrqp]"}},
71 "Options to be passed to the QP solver"}},
72 {
"hessian_approximation",
74 "limited-memory|exact"}},
77 "Maximum number of SQP iterations"}},
80 "Minimum number of SQP iterations"}},
83 "Maximum number of linesearch iterations"}},
86 "Stopping criterion for primal infeasibility"}},
89 "Stopping criterion for dual infeasability"}},
92 "Armijo condition, coefficient of decrease in merit"}},
95 "Line-search parameter, restoration factor of stepsize"}},
98 "Size of memory to store history of merit function values"}},
101 "Size of L-BFGS memory."}},
104 "Automatic regularization of Lagrange Hessian."}},
107 "Print the header with problem statistics"}},
110 "Print the iterations"}},
113 "The size (inf-norm) of the step size should not become smaller than this."}},
132 std::string hessian_approximation =
"exact";
134 std::string qpsol_plugin =
"qrqp";
140 for (
auto&& op : opts) {
141 if (op.first==
"max_iter") {
143 }
else if (op.first==
"min_iter") {
145 }
else if (op.first==
"max_iter_ls") {
147 }
else if (op.first==
"c1") {
149 }
else if (op.first==
"beta") {
151 }
else if (op.first==
"merit_memory") {
153 }
else if (op.first==
"lbfgs_memory") {
155 }
else if (op.first==
"tol_pr") {
157 }
else if (op.first==
"tol_du") {
159 }
else if (op.first==
"hessian_approximation") {
160 hessian_approximation = op.second.to_string();
161 }
else if (op.first==
"min_step_size") {
163 }
else if (op.first==
"qpsol") {
164 qpsol_plugin = op.second.to_string();
165 }
else if (op.first==
"qpsol_options") {
166 qpsol_options = op.second;
167 }
else if (op.first==
"regularize") {
169 }
else if (op.first==
"print_header") {
171 }
else if (op.first==
"print_iteration") {
183 {
"f",
"grad:f:x",
"g",
"jac:g:x"});
184 Asp_ = jac_g_fcn.sparsity_out(3);
188 {
"hess:gamma:x:x"}, {{
"gamma", {
"f",
"g"}}});
196 casadi_assert(!qpsol_plugin.empty(),
"'qpsol' option has not been set");
208 print(
"-------------------------------------------\n");
209 print(
"This is casadi::Qrsqp.\n");
211 print(
"Using exact Hessian\n");
213 print(
"Using limited memory BFGS Hessian approximation\n");
215 print(
"Number of variables: %9d\n",
nx_);
216 print(
"Number of constraints: %9d\n",
ng_);
217 print(
"Number of nonzeros in constraint Jacobian: %9d\n",
Asp_.
nnz());
218 print(
"Number of nonzeros in Lagrangian Hessian: %9d\n",
Hsp_.
nnz());
251 casadi_int*& iw,
double*& w)
const {
258 m->z_cand = w; w +=
nx_+
ng_;
261 m->gLag = w; w +=
nx_;
262 m->gLag_old = w; w +=
nx_;
268 m->lbdz = w; w +=
nx_ +
ng_;
269 m->ubdz = w; w +=
nx_ +
ng_;
272 m->dz = w; w +=
nx_ +
ng_;
273 m->dlam = w; w +=
nx_ +
ng_;
289 auto d_nlp = &m->
d_nlp;
295 casadi_int ls_iter = 0;
298 bool ls_success =
true;
309 const double one = 1.;
314 m->arg[0] = d_nlp->
z;
315 m->arg[1] = d_nlp->p;
316 m->res[0] = &d_nlp->objective;
318 m->res[2] = d_nlp->z +
nx_;
339 print_iteration(m->iter_count, d_nlp->objective, pr_inf, du_inf, dx_norminf,
340 m->reg, ls_iter, ls_success);
345 print(
"WARNING(qrsqp): Aborted by callback...\n");
346 m->return_status =
"User_Requested_Stop";
352 print(
"MESSAGE(qrsqp): Convergence achieved after %d iterations\n", m->iter_count);
353 m->return_status =
"Solve_Succeeded";
359 print(
"MESSAGE(qrsqp): Maximum number of iterations reached.\n");
360 m->return_status =
"Maximum_Iterations_Exceeded";
366 print(
"MESSAGE(qrsqp): Search direction becomes too small without "
367 "convergence criteria being met.\n");
368 m->return_status =
"Search_Direction_Becomes_Too_Small";
374 m->arg[0] = d_nlp->z;
375 m->arg[1] = d_nlp->p;
377 m->arg[3] = d_nlp->lam +
nx_;
383 m->reg = std::fmin(0, -casadi_lb_eig(
Hsp_, m->Bk));
384 if (m->reg > 0) casadi_regularize(
Hsp_, m->Bk, m->reg);
386 }
else if (m->iter_count==0) {
389 casadi_bfgs_reset(
Hsp_, m->Bk);
394 casadi_bfgs(
Hsp_, m->Bk, m->dz, m->gLag, m->gLag_old, m->w);
411 solve_QP(m, m->Bk, m->gf, m->lbdz, m->ubdz, m->Jk, m->dz, m->dlam);
418 print(
"WARNING(qrsqp): Indefinite Hessian detected\n");
429 double L1dir = F_sens - m->sigma * l1_infeas;
430 double L1merit = d_nlp->objective + m->sigma * l1_infeas;
433 m->merit_mem[m->merit_ind] = L1merit;
437 double meritmax = m->merit_mem[0];
439 if (meritmax < m->merit_mem[i]) meritmax = m->merit_mem[i];
446 double L1merit_cand = 0;
466 m->arg[0] = m->z_cand;
467 m->arg[1] = d_nlp->p;
468 m->res[0] = &fk_cand;
469 m->res[1] = m->z_cand +
nx_;
478 L1merit_cand = fk_cand + m->sigma * l1_infeas;
479 if (L1merit_cand <= meritmax + t *
c1_ * L1dir) {
518 print(
"%4s %14s %9s %9s %9s %7s %2s\n",
"iter",
"objective",
"inf_pr",
519 "inf_du",
"||d||",
"lg(rg)",
"ls");
523 double pr_inf,
double du_inf,
524 double dx_norm,
double rg,
525 casadi_int ls_trials,
bool ls_success)
const {
526 print(
"%4d %14.6e %9.2e %9.2e %9.2e ", iter, obj, pr_inf, du_inf, dx_norm);
528 print(
"%7.2d ", log10(rg));
532 print(
"%2d", ls_trials);
533 if (!ls_success)
print(
"F");
538 const double* lbdz,
const double* ubdz,
539 const double* A,
double* x_opt,
double* dlam)
const {
568 stats[
"iter_count"] = m->iter_count;
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
void alloc(const Function &f, bool persistent=false, int num_threads=1)
Ensure work vectors long enough to evaluate function.
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
casadi_int n_out() const
Get the number of function outputs.
casadi_int n_in() const
Get the number of function inputs.
NLP solver storage class.
Dict get_stats(void *mem) const override
Get all statistics.
static const Options options_
Options.
void init(const Dict &opts) override
Initialize.
casadi_int ng_
Number of constraints.
int callback(NlpsolMemory *m) const
casadi_int nx_
Number of variables.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Function create_function(const Function &oracle, const std::string &fname, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const Function::AuxOut &aux=Function::AuxOut(), const Dict &opts=Dict())
int calc_function(OracleMemory *m, const std::string &fcn, const double *const *arg=nullptr, int thread_id=0) const
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
void print(const char *fmt,...) const
C-style formatted printing during evaluation.
bool verbose_
Verbose printout.
void clear_mem()
Clear all memory (called from destructor)
virtual void solve_QP(QrsqpMemory *m, const double *H, const double *g, const double *lbdz, const double *ubdz, const double *A, double *x_opt, double *dlam) const
double tol_pr_
Tolerance of primal and dual infeasibility.
double min_step_size_
Minimum step size allowed.
casadi_int max_iter_
Maximum, minimum number of SQP iterations.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Dict get_stats(void *mem) const override
Get all statistics.
static const Options options_
Options.
int solve(void *mem) const override
Qrsqp(const std::string &name, const Function &nlp)
casadi_int merit_memsize_
static const std::string meta_doc
A documentation string.
bool exact_hessian_
Exact Hessian?
void init(const Dict &opts) override
Initialize.
void print_iteration() const
Print iteration header.
bool regularize_
Regularization.
Function qpsol_
QP solver for the subproblems.
static Nlpsol * creator(const std::string &name, const Function &nlp)
Create a new NLP Solver.
casadi_int lbfgs_memory_
Memory size of L-BFGS method.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
casadi_int nnz() const
Get the number of (structural) non-zeros.
Function conic(const std::string &name, const std::string &solver, const SpDict &qp, const Dict &opts)
T1 casadi_max_viol(casadi_int n, const T1 *x, const T1 *lb, const T1 *ub)
Largest bound violation.
@ CONIC_UBA
dense, (nc x 1)
@ CONIC_A
The matrix A: sparse, (nc x n) - product with x must be dense.
@ CONIC_G
The vector g: dense, (n x 1)
@ CONIC_LBA
dense, (nc x 1)
@ CONIC_UBX
dense, (n x 1)
@ CONIC_LBX
dense, (n x 1)
T1 casadi_bilin(const T1 *A, const casadi_int *sp_A, const T1 *x, const T1 *y)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
void casadi_fill(T1 *x, casadi_int n, T1 alpha)
FILL: x <- alpha.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
T1 casadi_dot(casadi_int n, const T1 *x, const T1 *y)
Inner product.
void CASADI_NLPSOL_QRSQP_EXPORT casadi_load_nlpsol_qrsqp()
void casadi_scal(casadi_int n, T1 alpha, T1 *x)
SCAL: x <- alpha*x.
void casadi_axpy(casadi_int n, T1 alpha, const T1 *x, T1 *y)
AXPY: y <- a*x + y.
int CASADI_NLPSOL_QRSQP_EXPORT casadi_register_nlpsol_qrsqp(Nlpsol::Plugin *plugin)
T1 casadi_norm_inf(casadi_int n, const T1 *x)
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.
void casadi_mv(const T1 *x, const casadi_int *sp_x, const T1 *y, T1 *z, casadi_int tr)
Sparse matrix-vector multiplication: z <- z + x*y.
@ CONIC_X
The primal solution.
@ CONIC_LAM_A
The dual solution corresponding to linear bounds.
@ CONIC_LAM_X
The dual solution corresponding to simple bounds.
casadi_nlpsol_data< double > d_nlp
Options metadata for a class.
const char * return_status
Last return status.