26 #include "conic_impl.hpp"
27 #include "nlpsol_impl.hpp"
28 #include "filesystem_impl.hpp"
56 casadi_assert_dev(!f.
is_null());
63 for (
size_t i=0; i<ret.size(); ++i) ret[i]=
conic_in(i);
69 for (
size_t i=0; i<ret.size(); ++i) ret[i]=
conic_out(i);
100 return std::string();
113 const std::map<std::string, M>& qp,
const Dict& opts) {
123 bool postpone_expand =
false;
125 bool error_on_fail =
get_from_dict(opts,
"error_on_fail",
true);
127 if (expand && !postpone_expand && M::type_name()==
"MX") {
129 std::vector<SX> arg = f.
sx_in();
130 std::vector<SX> res = f(arg);
132 for (casadi_int i=0;i<f.
n_in();++i) qp_mod[f.
name_in(i)] = arg[i];
133 for (casadi_int i=0;i<f.
n_out();++i) qp_mod[f.
name_out(i)] = res[i];
134 return qpsol_nlp(name, solver, qp_mod, opt);
138 for (
auto&& i : qp) {
141 }
else if (i.first==
"p") {
143 }
else if (i.first==
"f") {
145 }
else if (i.first==
"g") {
147 }
else if (i.first==
"h") {
150 casadi_error(
"No such field: " + i.first);
154 if (f.is_empty()) f = 0;
155 if (g.is_empty()) g = M(0, 1);
158 casadi_assert(g.is_dense() && g.is_vector(),
159 "Expected a dense vector 'g', but got " + g.dim() +
".");
161 casadi_assert(f.is_dense() && f.is_scalar(),
162 "Expected a dense scalar 'f', but got " + f.dim() +
".");
164 casadi_assert(x.is_dense() && x.is_vector(),
165 "Expected a dense vector 'x', but got " + x.dim() +
".");
167 casadi_assert(h.is_square(),
168 "Expected a symmetric matrix 'h', but got " + h.dim() +
".");
170 if (g.is_empty(
true)) g = M(0, 1);
173 M gf = M::gradient(f, x);
176 M c = substitute(gf, x, M::zeros(x.sparsity()));
179 M H = M::jacobian(gf, x, {{
"symmetric",
true}});
182 Function r(
"constant_qp", {x, p}, {substitute(f, x, M::zeros(x.sparsity()))});
185 M b = substitute(g, x, M::zeros(x.sparsity()));
188 M A = M::jacobian(g, x);
191 M
P = substitute(h, x, M::zeros(x.sparsity()));
194 M
Q = M::jacobian(h, x);
197 Function prob(name +
"_qp", {x, p}, {H, c, A, b,
Q,
P},
198 {
"x",
"p"}, {
"H",
"c",
"A",
"b",
"Q",
"P"});
199 if (expand && postpone_expand) prob = prob.
expand();
202 casadi_assert(!prob.has_free(),
"Cannot create '" + prob.name() +
"' "
203 "since " +
str(prob.get_free()) +
" are free.");
207 {{
"h", H.sparsity()}, {
"a", A.sparsity()},
208 {
"p",
P.sparsity()}, {
"q",
Q.sparsity()}}, opt);
250 ret_out[
NLPSOL_G] = reshape(mtimes(v.at(2), w[
CONIC_X]), g.size()) + v.at(3);
257 fun_opts[
"error_on_fail"] = error_on_fail;
264 return qpsol_nlp(name, solver, qp, opts);
269 return qpsol_nlp(name, solver, qp, opts);
273 Conic::Conic(
const std::string& name,
const std::map<std::string, Sparsity> &st)
280 for (
auto i=st.begin(); i!=st.end(); ++i) {
283 }
else if (i->first==
"h") {
285 }
else if (i->first==
"q") {
287 }
else if (i->first==
"p") {
290 casadi_error(
"Unrecognized field in QP structure: " +
str(i->first));
296 "Cannot determine dimension");
306 "Got incompatible dimensions.\n"
307 "min x'Hx + G'x s.t. LBA <= Ax <= UBA :\n"
309 "We need: H.size2()==A.size2()");
313 "Got incompatible dimensions. min x'Hx + G'x\n"
315 "We need H square & symmetric");
326 "Got incompatible dimensions.\n"
328 "We need the product Qx to exist.");
329 np_ =
static_cast<casadi_int
>(sqrt(
static_cast<double>(
Q_.
size1())));
331 "Got incompatible dimensions.\n"
333 "We need Q.size1() to have an integer square root.");
338 "Got incompatible dimensions.");
345 "Got incompatible dimensions.\n"
347 "We need P square & symmetric.");
350 "Got incompatible dimensions.\n"
399 "Indicates which of the variables are discrete, i.e. integer-valued"}},
402 "Indicate an upfront hint which of the constraints are equalities. "
403 "Some solvers may be able to exploit this knowledge. "
404 "When true, the corresponding lower and upper bounds are assumed equal. "
405 "When false, the corresponding bounds may be equal or different."}},
408 "Print a numeric description of the problem"}}
419 for (
auto&& op : opts) {
420 if (op.first==
"discrete") {
422 }
else if (op.first==
"equality") {
424 }
else if (op.first==
"print_problem") {
431 casadi_assert(
discrete_.size()==
nx_,
"\"discrete\" option has wrong length");
434 "Discrete variables require a solver with integer support");
439 casadi_assert(
equality_.size()==
na_,
"\"equality\" option has wrong length. "
440 "Expected " +
str(
na_) +
" elements, but got " +
445 "Selected solver does not support psd constraints.");
459 casadi_int*& iw,
double*& w)
const {
489 const double* lba,
const double* uba)
const {
490 for (casadi_int i=0; i<
nx_; ++i) {
491 double lb = lbx ? lbx[i] : 0., ub = ubx ? ubx[i] : 0.;
492 casadi_assert(lb <= ub && lb!=
inf && ub!=-
inf,
493 "Ill-posed problem detected: "
494 "LBX[" +
str(i) +
"] <= UBX[" +
str(i) +
"] was violated. "
495 "Got LBX[" +
str(i) +
"]=" +
str(lb) +
" and UBX[" +
str(i) +
"] = " +
str(ub) +
".");
497 for (casadi_int i=0; i<
na_; ++i) {
498 double lb = lba ? lba[i] : 0., ub = uba ? uba[i] : 0.;
499 casadi_assert(lb <= ub && lb!=
inf && ub!=-
inf,
500 "Ill-posed problem detected: "
501 "LBA[" +
str(i) +
"] <= UBA[" +
str(i) +
"] was violated. "
502 "Got LBA[" +
str(i) +
"] = " +
str(lb) +
" and UBA[" +
str(i) +
"] = " +
str(ub) +
".");
507 casadi_error(
"generateNativeCode not defined for class " +
class_name());
512 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
513 std::mutex Conic::mutex_solvers_;
522 return -std::numeric_limits<double>::infinity();
525 return std::numeric_limits<double>::infinity();
532 eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
552 setup(mem, arg, res, iw, w);
554 int ret =
solve(arg, res, iw, w, mem);
559 casadi_error(
"conic process failed. "
560 "Set 'error_on_fail' option to false to ignore this error.");
587 std::vector<casadi_int> p;
588 casadi_int nb = aggregate.
scc(p, mem.
r);
590 std::string pattern_message =
"Pattern not recognised";
592 casadi_assert(p==
range(p.size()), pattern_message);
594 const casadi_int* row = aggregate.
row();
595 const casadi_int* colind = aggregate.
colind();
598 for (casadi_int i=0;i<nb;++i) {
599 casadi_int block_size = mem.
r[i+1]-mem.
r[i];
601 casadi_int nz = colind[mem.
r[i+1]]-colind[mem.
r[i+1]-1];
603 casadi_assert(nz==block_size, pattern_message);
604 for (casadi_int k=0;k<block_size-1;++k) {
605 casadi_assert(colind[mem.
r[i]+k+1]-colind[mem.
r[i]+k], pattern_message);
606 casadi_assert(*(row++)==k+mem.
r[i], pattern_message);
607 casadi_assert(*(row++)==mem.
r[i]+block_size-1, pattern_message);
610 for (casadi_int k=0;k<block_size;++k)
611 casadi_assert(*(row++)==k+mem.
r[i], pattern_message);
650 std::vector<casadi_int> target_start(nb), target_stop(nb);
651 for (casadi_int i=0;i<nb;++i) {
652 target_start[i] = (mem.
r[i+1]-1)*aggregate.
size1()+mem.
r[i];
653 target_stop[i] = target_start[i]+mem.
r[i+1]-mem.
r[i];
657 std::vector<casadi_int> q_nz;
659 std::vector<casadi_int> q_row, q_col;
662 for (casadi_int j=0; j<
Q_.
size2(); ++j) {
663 casadi_int block_index = 0;
666 casadi_int i =
Q_.
row(k);
669 while (i>target_stop[block_index] && block_index<nb-1) block_index++;
671 if (i>=target_start[block_index] && i<target_stop[block_index]) {
674 q_row.push_back(mem.
r[block_index]+i-target_start[block_index]);
686 casadi_int max_nnz = 0;
687 for (casadi_int i=0;i<mem.
map_Q.
size2();++i) {
695 mem.
map_P.resize(mem.
r[nb], -1);
696 for (casadi_int i=0;i<nb;++i) {
698 casadi_int r =
P_.
row(k);
704 for (casadi_int i=0;i<nb;++i)
717 stats[
"iter_count"] = m->d_qp.iter_count;
722 s.
pack(
"Conic::SDPToSOCPMem::r", m.
r);
723 s.
pack(
"Conic::SDPToSOCPMem::AT", m.
AT);
725 s.
pack(
"Conic::SDPToSOCPMem::map_Q", m.
map_Q);
726 s.
pack(
"Conic::SDPToSOCPMem::map_P", m.
map_P);
730 s.
unpack(
"Conic::SDPToSOCPMem::r", m.
r);
731 s.
unpack(
"Conic::SDPToSOCPMem::AT", m.
AT);
764 int version = s.
version(
"Conic", 1, 3);
783 void Conic::set_qp_prob() {
786 casadi_qp_setup(&
p_qp_);
791 g.
local(
"d_qp",
"struct casadi_qp_data");
792 g.
local(
"p_qp",
"struct casadi_qp_prob");
794 g <<
"d_qp.prob = &p_qp;\n";
795 g <<
"p_qp.sp_a = " << g.
sparsity(
A_) <<
";\n";
796 g <<
"p_qp.sp_h = " << g.
sparsity(
H_) <<
";\n";
797 g <<
"casadi_qp_setup(&p_qp);\n";
798 g <<
"casadi_qp_init(&d_qp, &iw, &w);\n";
801 g <<
"d_qp.h = arg[" <<
CONIC_H <<
"];\n";
802 g <<
"d_qp.g = arg[" <<
CONIC_G <<
"];\n";
803 g <<
"d_qp.a = arg[" <<
CONIC_A <<
"];\n";
804 g <<
"d_qp.lbx = arg[" <<
CONIC_LBX <<
"];\n";
805 g <<
"d_qp.ubx = arg[" <<
CONIC_UBX <<
"];\n";
806 g <<
"d_qp.lba = arg[" <<
CONIC_LBA <<
"];\n";
807 g <<
"d_qp.uba = arg[" <<
CONIC_UBA <<
"];\n";
808 g <<
"d_qp.x0 = arg[" <<
CONIC_X0 <<
"];\n";
813 g <<
"d_qp.x = res[" <<
CONIC_X <<
"];\n";
Helper class for C code generation.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
std::string sparsity(const Sparsity &sp, bool canonical=true)
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
static const Options options_
Options.
casadi_int nx_
Number of decision variables.
bool is_a(const std::string &type, bool recursive) const override
Check if the function is of a particular type.
double get_default_in(casadi_int ind) const override
Get default input value.
virtual int solve(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const =0
Solve the QP.
int init_mem(void *mem) const override
Initalize memory block.
casadi_int np_
The shape of psd constraint matrix.
Sparsity get_sparsity_in(casadi_int i) override
Sparsities of function inputs and outputs.
casadi_int na_
The number of constraints (counting both equality and inequality) == A.size1()
static std::map< std::string, Plugin > solvers_
Collection of solvers.
virtual void generateNativeCode(std::ostream &file) const
virtual void check_inputs(const double *lbx, const double *ubx, const double *lba, const double *uba) const
Check if the numerical values of the supplied bounds make sense.
Sparsity H_
Problem structure.
void init(const Dict &opts) override
Initialize.
void deserialize(DeserializingStream &s, SDPToSOCPMem &m)
std::vector< bool > discrete_
Options.
std::vector< bool > equality_
Conic(const std::string &name, const std::map< std::string, Sparsity > &st)
Sparsity get_sparsity_out(casadi_int i) override
Sparsities of function inputs and outputs.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
virtual bool psd_support() const
Can psd constraints be treated.
Dict get_stats(void *mem) const override
Get all statistics.
static const std::string infix_
Infix.
casadi_qp_prob< double > p_qp_
void serialize_type(SerializingStream &s) const override
Serialize type information.
void qp_codegen_body(CodeGenerator &g) const
Generate code for the function body.
void sdp_to_socp_init(SDPToSOCPMem &mem) const
SDP to SOCP conversion initialization.
virtual bool integer_support() const
Can discrete variables be treated.
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const final
Solve the QP.
void serialize(SerializingStream &s, const SDPToSOCPMem &m) const
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
static void open(std::ofstream &, const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
Internal class for Function.
Dict get_stats(void *mem) const override
Get all statistics.
void init(const Dict &opts) override
Initialize.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
virtual bool is_a(const std::string &type, bool recursive) const
Check if the function is of a particular type.
bool inputs_check_
Errors are thrown if numerical values of inputs look bad.
static const Options options_
Options.
void serialize_type(SerializingStream &s) const override
Serialize type information.
void setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
static std::string string_from_UnifiedReturnStatus(UnifiedReturnStatus status)
FunctionInternal * get() const
Function expand() const
Expand a function to SX.
const std::vector< std::string > & name_in() const
Get input scheme.
static Function create(FunctionInternal *node)
Create from node.
const SX sx_in(casadi_int iind) const
Get symbolic primitives equivalent to the input expressions.
casadi_int n_out() const
Get the number of function outputs.
casadi_int n_in() const
Get the number of function inputs.
const std::vector< std::string > & name_out() const
Get output scheme.
casadi_int size2() const
Get the second dimension (i.e. number of columns)
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
const casadi_int * colind() const
Get the sparsity pattern. See the Sparsity class for details.
bool is_null() const
Is a null pointer?
static MX nan(const Sparsity &sp)
create a matrix with all nan
Matrix< Scalar > T() const
Transpose the matrix.
static Matrix< casadi_int > triplet(const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, const Matrix< casadi_int > &d)
Construct a sparse matrix from triplet form.
void print_dense(std::ostream &stream, bool truncate=true) const
Print dense matrix-stype.
static Matrix< casadi_int > eye(casadi_int n)
create an n-by-n identity matrix
static bool has_plugin(const std::string &pname, bool verbose=false)
Check if a plugin is available or can be loaded.
static Conic * instantiate(const std::string &fname, const std::string &pname, Problem problem)
void serialize_type(SerializingStream &s) const
Serialize type information.
static const Options & plugin_options(const std::string &pname)
Get the plugin options.
static Plugin & getPlugin(const std::string &pname)
Load and get the creator function.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static Plugin load_plugin(const std::string &pname, bool register_plugin=true, bool needs_lock=true)
Load a plugin dynamically.
Base class for FunctionInternal and LinsolInternal.
bool error_on_fail_
Throw an exception on failure?
virtual int init_mem(void *mem) const
Initalize memory block.
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
virtual std::string class_name() const =0
Readable name of the internal class.
casadi_int size1() const
Get the number of rows.
casadi_int scc(std::vector< casadi_int > &index, std::vector< casadi_int > &offset) const
Find the strongly connected components of the bigraph defined by the sparsity pattern.
std::string dim(bool with_nz=false) const
Get the dimension as a string.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Sparsity transpose(std::vector< casadi_int > &mapping, bool invert_mapping=false) const
Transpose the matrix and get the reordering of the non-zero entries.
casadi_int size2() const
Get the number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
static Sparsity scalar(bool dense_scalar=true)
Create a scalar sparsity pattern *.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
bool is_symmetric() const
Is symmetric?
Function qpsol(const std::string &name, const std::string &solver, const SXDict &qp, const Dict &opts)
std::string conic_option_info(const std::string &name, const std::string &op)
Get documentation for a particular option.
Function conic(const std::string &name, const std::string &solver, const SpDict &qp, const Dict &opts)
std::string conic_option_type(const std::string &name, const std::string &op)
Get type info for a particular option.
bool has_conic(const std::string &name)
Check if a particular plugin is available.
std::string doc_conic(const std::string &name)
Get the documentation string for a plugin.
std::vector< std::string > conic_options(const std::string &name)
Get all options for a plugin.
std::vector< std::string > conic_out()
Get QP solver output scheme of QP solvers.
casadi_int conic_n_in()
Get the number of QP solver inputs.
casadi_int conic_n_out()
Get the number of QP solver outputs.
void load_conic(const std::string &name)
Explicitly load a plugin dynamically.
std::vector< std::string > conic_in()
Get input scheme of QP solvers.
void conic_debug(const Function &f, const std::string &filename)
std::vector< std::string > nlpsol_in()
Get input scheme of NLP solvers.
std::vector< std::string > nlpsol_out()
Get NLP solver output scheme of NLP solvers.
double nlpsol_default_in(casadi_int ind)
Default input for an NLP solver.
@ NLPSOL_P
Value of fixed parameters (np x 1)
@ NLPSOL_UBX
Decision variables upper bound (nx x 1), default +inf.
@ NLPSOL_X0
Decision variables, initial guess (nx x 1)
@ NLPSOL_LAM_G0
Lagrange multipliers for bounds on G, initial guess (ng x 1)
@ NLPSOL_UBG
Constraints upper bound (ng x 1), default +inf.
@ NLPSOL_LAM_X0
Lagrange multipliers for bounds on X, initial guess (nx x 1)
@ NLPSOL_LBG
Constraints lower bound (ng x 1), default -inf.
@ NLPSOL_LBX
Decision variables lower bound (nx x 1), default -inf.
std::map< std::string, MX > MXDict
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
@ NLPSOL_G
Constraints function at the optimal solution (ng x 1)
@ NLPSOL_X
Decision variables at the optimal solution (nx x 1)
@ NLPSOL_LAM_P
Lagrange multipliers for bounds on P at the solution (np x 1)
@ NLPSOL_F
Cost function value at the optimal solution (1 x 1)
@ NLPSOL_LAM_G
Lagrange multipliers for bounds on G at the solution (ng x 1)
@ NLPSOL_LAM_X
Lagrange multipliers for bounds on X at the solution (nx x 1)
T get_from_dict(const std::map< std::string, T > &d, const std::string &key, const T &default_value)
@ NL_NUM_IN
Number of NLP inputs.
ConicInput
Input arguments of a QP problem.
@ 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_Q
The matrix Q: sparse symmetric, (np^2 x n)
@ CONIC_LBA
dense, (nc x 1)
@ CONIC_UBX
dense, (n x 1)
@ CONIC_LBX
dense, (n x 1)
@ CONIC_P
The matrix P: sparse symmetric, (np x np)
std::map< std::string, SX > SXDict
void extract_from_dict_inplace(Dict &d, const std::string &key, T &value)
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
std::map< std::string, Sparsity > SpDict
Function qpsol_nlp(const std::string &name, const std::string &solver, const std::map< std::string, M > &qp, const Dict &opts)
std::string filename(const std::string &path)
ConicOutput
Output arguments of an QP Solver.
@ 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.
casadi_qp_data< double > d_qp
SDP to SOCP conversion memory.
std::vector< casadi_int > r
std::vector< casadi_int > A_mapping
std::vector< casadi_int > map_P
Options metadata for a class.
std::string type(const std::string &name) const
std::vector< std::string > all() const
std::string info(const std::string &name) const
UnifiedReturnStatus unified_return_status