26 #include "ooqp_interface.hpp"
27 #include "casadi/core/casadi_misc.hpp"
30 #include <cQpGenSparse.h>
32 #include <GondzioSolver.h>
36 extern casadi_int gOoqpPrintLevel;
41 int CASADI_CONIC_OOQP_EXPORT
44 plugin->name =
"ooqp";
46 plugin->version = CASADI_VERSION;
58 const std::map<std::string, Sparsity>& st)
70 "Print level. OOQP listens to print_level 0, 10 and 100"}},
73 "tolerance as provided with setMuTol to OOQP"}},
76 "tolerance as provided with setArTol to OOQP"}}
90 for (
auto&& op : opts) {
91 if (op.first==
"print_level") {
93 }
else if (op.first==
"mutol") {
95 }
else if (op.first==
"artol") {
148 solve(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
153 double* g=w; w +=
nx_;
155 double* lbx=w; w +=
nx_;
157 double* ubx=w; w +=
nx_;
159 double* lba=w; w +=
na_;
161 double* uba=w; w +=
na_;
169 double* c_ = w; w +=
nx_;
170 double* bA_ = w; w +=
na_;
171 double* xlow_ = w; w +=
nx_;
172 double* xupp_ = w; w +=
nx_;
173 double* clow_ = w; w +=
na_;
174 double* cupp_ = w; w +=
na_;
175 double* x_ = w; w +=
nx_;
176 double* gamma_ = w; w +=
nx_;
177 double* phi_ = w; w +=
nx_;
178 double* y_ = w; w +=
na_;
179 double* z_ = w; w +=
na_;
180 double* lambda_ = w; w +=
na_;
181 double* pi_ = w; w +=
na_;
182 char* ixlow_ =
reinterpret_cast<char*
>(iw); iw +=
nx_;
183 char* ixupp_ =
reinterpret_cast<char*
>(iw); iw +=
nx_;
184 char* iclow_ =
reinterpret_cast<char*
>(iw); iw +=
na_;
185 char* icupp_ =
reinterpret_cast<char*
>(iw); iw +=
na_;
186 double* dQ_ = w; w +=
nQ_;
187 double* dA_ = w; w +=
nA_;
188 double* dC_ = w; w +=
nA_;
189 int* irowQ_ =
reinterpret_cast<int*
>(iw); iw +=
nQ_;
190 int* jcolQ_ =
reinterpret_cast<int*
>(iw); iw +=
nQ_;
191 int* irowA_ =
reinterpret_cast<int*
>(iw); iw +=
nA_;
192 int* jcolA_ =
reinterpret_cast<int*
>(iw); iw +=
nA_;
193 int* irowC_ =
reinterpret_cast<int*
>(iw); iw +=
nA_;
194 int* jcolC_ =
reinterpret_cast<int*
>(iw); iw +=
nA_;
195 int* x_index_ =
reinterpret_cast<int*
>(iw); iw +=
nx_;
196 int* c_index_ =
reinterpret_cast<int*
>(iw); iw +=
na_;
197 double* p_ = w; w +=
nx_;
198 double* AT = w; w +=
nA_;
204 casadi_int nx = 0, np=0;
205 for (casadi_int i=0; i<
nx_; ++i) {
206 if (lbx[i]==ubx[i]) {
211 objParam += g[i]*p_[np];
214 x_index_[i] = -1-np++;
218 if (lbx[i]==-std::numeric_limits<double>::infinity()) {
225 if (ubx[i]==std::numeric_limits<double>::infinity()) {
238 const casadi_int* H_colind =
H_.
colind();
239 const casadi_int* H_row =
H_.
row();
242 for (casadi_int cc=0; cc<
nx_; ++cc) {
245 for (casadi_int el=H_colind[cc]; el<H_colind[cc+1]; ++el) {
248 casadi_int rr=H_row[el];
252 casadi_int icc=x_index_[cc];
253 casadi_int irr=x_index_[rr];
258 objParam += icc==irr ? H[el]*
sq(p_[-1-icc])/2 : H[el]*p_[-1-irr]*p_[-1-icc];
261 c_[irr] += H[el]*p_[-1-icc];
266 c_[icc] += H[el]*p_[-1-irr];
281 const casadi_int* A_colind =
A_.
colind();
282 const casadi_int* A_row =
A_.
row();
284 const casadi_int* AT_row =
spAT_.
row();
285 casadi_int nA=0, nC=0, nnzA=0, nnzC=0;
286 for (casadi_int j=0; j<
na_; ++j) {
287 if (lba[j] == -std::numeric_limits<double>::infinity() &&
288 uba[j] == std::numeric_limits<double>::infinity()) {
291 }
else if (lba[j]==uba[j]) {
296 for (casadi_int el=AT_colind[j]; el<AT_colind[j+1]; ++el) {
297 casadi_int i=AT_row[el];
300 bA_[nA] -= AT[el]*p_[-x_index_[i]-1];
304 jcolA_[nnzA] = x_index_[i];
305 dA_[nnzA++] = AT[el];
308 c_index_[j] = -1-nA++;
311 if (lba[j]==-std::numeric_limits<double>::infinity()) {
318 if (uba[j]==std::numeric_limits<double>::infinity()) {
327 for (casadi_int el=AT_colind[j]; el<AT_colind[j+1]; ++el) {
328 casadi_int i=AT_row[el];
331 if (iclow_[nC]==1) clow_[nC] -= AT[el]*p_[-x_index_[i]-1];
332 if (icupp_[nC]==1) cupp_[nC] -= AT[el]*p_[-x_index_[i]-1];
336 jcolC_[nnzC] = x_index_[i];
337 dC_[nnzC++] = AT[el];
340 c_index_[j] = 1+nC++;
354 double objectiveValue;
360 irowQ_, nnzQ, jcolQ_, dQ_,
363 irowA_, nnzA, jcolA_, dA_,
365 irowC_, nnzC, jcolC_, dC_,
377 std::vector<int> krowQ(nx+1);
378 std::vector<int> krowA(nA+1);
379 std::vector<int> krowC(nC+1);
382 makehb(irowQ_, nnzQ,
get_ptr(krowQ), nx, &ierr);
383 if (ierr == 0) makehb(irowA_, nnzA,
get_ptr(krowA), nA, &ierr);
384 if (ierr == 0) makehb(irowC_, nnzC,
get_ptr(krowC), nC, &ierr);
389 QpGenHbGondzioSetup(c_, nx,
get_ptr(krowQ), jcolQ_, dQ_,
390 xlow_, ixlow_, xupp_, ixupp_,
391 get_ptr(krowA), nA, jcolA_, dA_, bA_,
392 get_ptr(krowC), nC, jcolC_, dC_,
393 clow_, iclow_, cupp_, icupp_, &ctx,
396 Solver* solver =
static_cast<Solver *
>(ctx.solver);
398 solver->monitorSelf();
402 QpGenFinish(&ctx, x_, gamma_, phi_,
403 y_, z_, lambda_, pi_,
404 &objectiveValue, &ierr);
411 m->return_status = ierr;
412 m->d_qp.success = ierr==SUCCESSFUL_TERMINATION;
415 casadi_warning(
"Unable to solve problem: " +
str(
errFlag(ierr)));
417 casadi_error(
"Fatal error: " +
str(
errFlag(ierr)));
421 for (casadi_int i=
nx_-1; i>=0; --i) {
422 casadi_int ii = x_index_[i];
431 for (casadi_int j=
na_-1; j>=0; --j) {
432 casadi_int jj = c_index_[j];
436 lambda_[j] = -y_[-1-jj];
438 lambda_[j] = pi_[-1+jj]-lambda_[-1+jj];
443 for (casadi_int i=
nx_-1; i>=0; --i) {
444 casadi_int ii = x_index_[i];
448 for (casadi_int el=H_colind[i]; el<H_colind[i+1]; ++el) {
449 casadi_int j=H_row[el];
450 gamma_[i] -= H[el]*x_[j];
452 for (casadi_int el=A_colind[i]; el<A_colind[i+1]; ++el) {
453 casadi_int j=A_row[el];
454 gamma_[i] -= A[el]*lambda_[j];
457 gamma_[i] = phi_[ii]-gamma_[ii];
479 case SUCCESSFUL_TERMINATION:
return "SUCCESSFUL_TERMINATION";
480 case NOT_FINISHED:
return "NOT_FINISHED";
481 case MAX_ITS_EXCEEDED:
return "MAX_ITS_EXCEEDED";
482 case INFEASIBLE:
return "INFEASIBLE";
483 case UNKNOWN:
return "UNKNOWN";
484 default:
return "N/A";
497 const std::vector<char>& ib, casadi_int n,
const char *
sign) {
498 std::stringstream ss;
500 for (casadi_int i=0; i<n; ++i) {
501 if (i!=0) ss <<
", ";
527 s.
pack(
"OoqpInterface::nQ",
nQ_);
528 s.
pack(
"OoqpInterface::nH",
nH_);
529 s.
pack(
"OoqpInterface::nA",
nA_);
static const Options options_
Options.
casadi_int nx_
Number of decision variables.
casadi_int na_
The number of constraints (counting both equality and inequality) == A.size1()
Sparsity H_
Problem structure.
void init(const Dict &opts) override
Initialize.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Dict get_stats(void *mem) const override
Get all statistics.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
casadi_int nnz_in() const
Number of input/output nonzeros.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
static const char * errFlag(int flag)
Throw error.
static Conic * creator(const std::string &name, const std::map< std::string, Sparsity > &st)
Create a new QP Solver.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
Dict get_stats(void *mem) const override
Get all statistics.
static std::string printBounds(const std::vector< double > &b, const std::vector< char > &ib, casadi_int n, const char *sign)
Print an OOQP bounds vector.
~OoqpInterface() override
Destructor.
int solve(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Solve the QP.
static const std::string meta_doc
A documentation string.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
OoqpInterface(const std::string &name, const std::map< std::string, Sparsity > &st)
Create a new Solver.
void init(const Dict &opts) override
Initialize.
static const Options options_
Options.
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
void clear_mem()
Clear all memory (called from destructor)
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
Sparsity T() const
Transpose the matrix.
casadi_int nnz_upper(bool strictly=false) const
Number of non-zeros in the upper triangular half,.
const casadi_int * row() const
Get a reference to row-vector,.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
@ 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)
double sign(double x)
Sign function, note that sign(nan) == nan.
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
int CASADI_CONIC_OOQP_EXPORT casadi_register_conic_ooqp(Conic::Plugin *plugin)
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.
void casadi_trans(const T1 *x, const casadi_int *sp_x, T1 *y, const casadi_int *sp_y, casadi_int *tmp)
TRANS: y <- trans(x) , w work vector (length >= rows x)
void CASADI_CONIC_OOQP_EXPORT casadi_load_conic_ooqp()
@ CONIC_X
The primal solution.
@ CONIC_LAM_A
The dual solution corresponding to linear bounds.
@ CONIC_COST
The optimal cost.
@ CONIC_LAM_X
The dual solution corresponding to simple bounds.
Options metadata for a class.