xpress_interface.cpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include "xpress_interface.hpp"
26 #include "casadi/core/nlp_tools.hpp"
27 #include "casadi/core/casadi_misc.hpp"
28 
29 #include <xpress_runtime_str.h>
30 
31 #include <mutex>
32 
33 namespace casadi {
34 
35  // Xpress requires a single global library init via XPRSinit().
36  // We do it lazily on first plugin use; XPRSfree() is registered atexit
37  // by the OS-level library teardown when the process ends.
38  static std::once_flag s_xpress_init_flag;
39  static int s_xpress_init_rc = 0;
40  static void xpress_global_init() {
41  s_xpress_init_rc = XPRSinit(nullptr);
42  }
43 
44  extern "C"
45  int CASADI_CONIC_XPRESS_EXPORT
46  casadi_register_conic_xpress(Conic::Plugin* plugin) {
47  plugin->creator = XpressInterface::creator;
48  plugin->name = "xpress";
49  plugin->doc = XpressInterface::meta_doc.c_str();
50  plugin->version = CASADI_VERSION;
51  plugin->options = &XpressInterface::options_;
52  plugin->deserialize = &XpressInterface::deserialize;
53  return 0;
54  }
55 
56  extern "C"
57  void CASADI_CONIC_XPRESS_EXPORT casadi_load_conic_xpress() {
59  }
60 
61 
62  XpressInterface::XpressInterface(const std::string& name,
63  const std::map<std::string, Sparsity>& st)
64  : Conic(name, st) {
65  }
66 
68  = {{&Conic::options_},
69  {{"xpress",
70  {OT_DICT,
71  "Options to be passed to FICO Xpress. Each entry's key is the "
72  "Xpress control name (e.g. \"OUTPUTLOG\", \"MAXTIME\", \"MIPRELSTOP\"); "
73  "the value's type must match the control's type (int / double / string)."
74  }},
75  {"sos_groups",
77  "Definition of SOS groups by indices."}},
78  {"sos_weights",
80  "Weights corresponding to SOS entries."}},
81  {"sos_types",
82  {OT_INTVECTOR,
83  "Specify 1 or 2 for each SOS group."}},
84  {"mip_start",
85  {OT_BOOL,
86  "Pass x0 as an initial integer solution hint to Xpress via "
87  "XPRSaddmipsol before the MIP solve [Default false]."}},
88  {"log_file",
89  {OT_STRING,
90  "Write solver log to this file path via XPRSsetlogfile. "
91  "Useful for capturing output (e.g. warm-start acceptance messages) "
92  "in automated tests. Empty string (default) disables file logging."}},
93  {"compute_iis",
94  {OT_BOOL,
95  "When the problem is infeasible, compute an IIS immediately after "
96  "the solve and expose it in get_stats() as iis_rows / iis_cols. "
97  "IIS computation can be expensive; set to false to skip it "
98  "[Default false]."}},
99  }
100  };
101 
102  void XpressInterface::init(const Dict& opts) {
103  // Call the init method of the base class
104  Conic::init(opts);
105 
106  mip_start_ = false;
107  log_file_ = "";
108  compute_iis_ = false;
109 
110  std::vector< std::vector<casadi_int> > sos_groups;
111  std::vector< std::vector<double> > sos_weights;
112  std::vector<casadi_int> sos_types;
113 
114  // Read user options
115  for (auto&& op : opts) {
116  if (op.first=="xpress") {
117  opts_ = op.second;
118  } else if (op.first=="sos_groups") {
119  sos_groups = op.second.to_int_vector_vector();
120  } else if (op.first=="sos_weights") {
121  sos_weights = op.second.to_double_vector_vector();
122  } else if (op.first=="sos_types") {
123  sos_types = op.second.to_int_vector();
124  } else if (op.first=="mip_start") {
125  mip_start_ = op.second;
126  } else if (op.first=="log_file") {
127  log_file_ = op.second.to_string();
128  } else if (op.first=="compute_iis") {
129  compute_iis_ = op.second;
130  }
131  }
132 
133  // Validate + populate defaults (weights default to 1..n, types default to 1)
134  check_sos(nx_, sos_groups, sos_weights, sos_types);
135 
136  // Flatten into Xpress's CSR-like storage
137  if (!sos_groups.empty()) {
138  std::vector<casadi_int> beg, ind;
139  flatten_nested_vector(sos_groups, ind, beg);
140  flatten_nested_vector(sos_weights, sos_refval_);
141  sos_setstart_.assign(beg.begin(), beg.end());
142  sos_setind_.assign(ind.begin(), ind.end());
143  sos_settype_.resize(sos_types.size());
144  for (size_t k = 0; k < sos_types.size(); ++k) {
145  sos_settype_[k] = static_cast<char>('0' + sos_types[k]); // '1' or '2'
146  }
147  }
148 
149  // Pre-compute SOCP mapping (must run before set_xpress_prob so the
150  // socp pointer is resolved in p_)
151  has_socp_ = !Q_.is_null() && Q_.nnz() > 0;
152  if (has_socp_) build_socp_config();
153 
154  init_dependent();
155  set_xpress_prob();
156 
157  // Allocate memory
158  casadi_int sz_arg, sz_res, sz_w, sz_iw;
159  casadi_xpress_work(&p_, &sz_arg, &sz_res, &sz_iw, &sz_w);
160 
161  alloc_arg(sz_arg, true);
162  alloc_res(sz_res, true);
163  alloc_iw(sz_iw, true);
164  alloc_w(sz_w, true);
165  }
166 
168  colinda_.resize(A_.size2() + 1);
169  rowa_.resize(A_.nnz());
170  copy_vector(A_.colind(), colinda_);
171  copy_vector(A_.row(), rowa_);
172 
173  // Build upper-triangular triplets from the symmetric H_.
174  // H_ is stored CSC; iterate columns and pick (row, col) with row <= col.
175  qobj_col1_.clear();
176  qobj_col2_.clear();
177  qobj_nz_idx_.clear();
178  const casadi_int* Hc = H_.colind();
179  const casadi_int* Hr = H_.row();
180  for (casadi_int j = 0; j < H_.size2(); ++j) {
181  for (casadi_int k = Hc[j]; k < Hc[j + 1]; ++k) {
182  casadi_int i = Hr[k];
183  if (i <= j) {
184  qobj_col1_.push_back(static_cast<int>(i));
185  qobj_col2_.push_back(static_cast<int>(j));
186  qobj_nz_idx_.push_back(static_cast<int>(k));
187  }
188  }
189  }
190 
191  // Discrete variable flags: 'I' for integer, 'C' for continuous
192  if (!discrete_.empty()) {
193  coltype_.assign(nx_, 'C');
194  for (casadi_int i = 0; i < nx_; ++i) {
195  if (discrete_[i]) coltype_[i] = 'I';
196  }
197  }
198  }
199 
201  p_.qp = &p_qp_;
202  p_.colinda = get_ptr(colinda_);
203  p_.rowa = get_ptr(rowa_);
204  p_.qobj_col1 = get_ptr(qobj_col1_);
205  p_.qobj_col2 = get_ptr(qobj_col2_);
206  p_.qobj_nz_idx = get_ptr(qobj_nz_idx_);
207  p_.nquad = static_cast<int>(qobj_col1_.size());
208  p_.coltype = coltype_.empty() ? nullptr : get_ptr(coltype_);
209 
210  p_.n_sos_sets = static_cast<int>(sos_settype_.size());
211  p_.n_sos_elems = static_cast<int>(sos_setind_.size());
212  p_.sos_settype = sos_settype_.empty() ? nullptr : get_ptr(sos_settype_);
213  p_.sos_setstart = sos_setstart_.empty() ? nullptr : get_ptr(sos_setstart_);
214  p_.sos_setind = sos_setind_.empty() ? nullptr : get_ptr(sos_setind_);
215  p_.sos_refval = sos_refval_.empty() ? nullptr : get_ptr(sos_refval_);
216 
217  p_.socp = has_socp_ ? &socp_ : nullptr;
218  p_.mip_start = mip_start_ ? 1 : 0;
219 
220  casadi_xpress_setup(&p_);
221  }
222 
223  // Emit "p.<field> = <local int[]>;" for an int*-typed prob field.
224  // For empty vectors, emit a NULL assignment directly instead of going
225  // through constant_copy (which emits an unused constant ref).
226  static void codegen_int_field(CodeGenerator& g, const std::string& prob_field,
227  const std::string& local_name, const std::vector<int>& v) {
228  if (v.empty()) {
229  g << "p." << prob_field << " = 0;\n";
230  } else {
231  g.constant_copy(local_name, vector_static_cast<casadi_int>(v), "int");
232  g << "p." << prob_field << " = " << local_name << ";\n";
233  }
234  }
235 
237  g << "p.qp = &p_qp;\n";
238 
239  codegen_int_field(g, "colinda", "colinda", colinda_);
240  codegen_int_field(g, "rowa", "rowa", rowa_);
241  codegen_int_field(g, "qobj_col1", "qobj_col1", qobj_col1_);
242  codegen_int_field(g, "qobj_col2", "qobj_col2", qobj_col2_);
243  codegen_int_field(g, "qobj_nz_idx", "qobj_nz_idx", qobj_nz_idx_);
244  g << "p.nquad = " << qobj_col1_.size() << ";\n";
245 
246  if (coltype_.empty()) {
247  g << "p.coltype = 0;\n";
248  } else {
249  g << "p.coltype = " << g.constant(coltype_) << ";\n";
250  }
251 
252  if (sos_settype_.empty()) {
253  g << "p.n_sos_sets = 0;\n";
254  g << "p.n_sos_elems = 0;\n";
255  g << "p.sos_settype = 0;\n";
256  g << "p.sos_setstart = 0;\n";
257  g << "p.sos_setind = 0;\n";
258  g << "p.sos_refval = 0;\n";
259  } else {
260  codegen_int_field(g, "sos_setstart", "sos_setstart", sos_setstart_);
261  codegen_int_field(g, "sos_setind", "sos_setind", sos_setind_);
262  g << "p.sos_settype = " << g.constant(sos_settype_) << ";\n";
263  g << "p.sos_refval = " << g.constant(sos_refval_) << ";\n";
264  g << "p.n_sos_sets = " << sos_settype_.size() << ";\n";
265  g << "p.n_sos_elems = " << sos_setind_.size() << ";\n";
266  }
267 
268  if (has_socp_) {
269  g.local("socp_p", "struct casadi_socp_prob");
270  g << "socp_p.n_blocks = " << socp_.n_blocks << ";\n";
271  g << "socp_p.n_lifted = " << socp_.n_lifted << ";\n";
272  g << "socp_p.nx = " << socp_.nx << ";\n";
273  g << "socp_p.r = " << g.constant(socp_r_) << ";\n";
274  g << "socp_p.mq_colind = " << g.constant(socp_mq_colind_) << ";\n";
275  g << "socp_p.mq_row = " << g.constant(socp_mq_row_) << ";\n";
276  g << "socp_p.mq_data = " << g.constant(socp_mq_data_) << ";\n";
277  g << "socp_p.map_P = " << g.constant(socp_map_P_) << ";\n";
278  g << "casadi_socp_setup(&socp_p);\n";
279  g << "p.socp = &socp_p;\n";
280  } else {
281  g << "p.socp = 0;\n";
282  }
283 
284  g << "p.mip_start = " << (mip_start_ ? 1 : 0) << ";\n";
285  g << "casadi_xpress_setup(&p);\n";
286  }
287 
289  g << "casadi_xpress_init_mem(&" + codegen_mem(g) + ");\n";
290  g << "return 0;\n";
291  }
292 
294  g << "casadi_xpress_free_mem(&" + codegen_mem(g) + ");\n";
295  }
296 
298  qp_codegen_body(g);
303  // Always emit casadi_socp definitions: the xpress data struct
304  // references casadi_socp_data even when no Q/P is present.
306  g.add_include("xprs.h");
307  g.auxiliaries << g.sanitize_source(xpress_runtime_str, {"casadi_real"});
308 
309  g.local("d", "struct casadi_xpress_data*");
310  g.init_local("d", "&" + codegen_mem(g));
311  g.local("p", "struct casadi_xpress_prob");
312  set_xpress_prob(g);
313 
314  g << "d->prob = &p;\n";
315  g << "d->qp = &d_qp;\n";
316  g << "casadi_xpress_set_work(d, &arg, &res, &iw, &w);\n";
317 
318  if (has_socp_) {
319  g << "d->socp.q = arg[" << CONIC_Q << "];\n";
320  g << "d->socp.p = arg[" << CONIC_P << "];\n";
321  }
322 
323  g << "d->x0 = " << (mip_start_ ? ("arg[" + str(CONIC_X0) + "]") : std::string("0")) << ";\n";
324 
325  // Set crossover default (matches C++ set_work)
326  g << "XPRSsetintcontrol(d->xprob, " << XPRS_CROSSOVER << ", 1);\n";
327 
328  // Apply user options. Dispatch by the CasADi-side type tag of each
329  // value; the control id is resolved at runtime via XPRSgetcontrolinfo
330  // (which lets the generated code work without an Xpress license at
331  // codegen time).
332  for (auto&& op : opts_) {
333  g << "{\n";
334  g << " int xprs_id, xprs_type;\n";
335  g << " XPRSgetcontrolinfo(d->xprob, " << g.constant(op.first)
336  << ", &xprs_id, &xprs_type);\n";
337  if (op.second.is_double()) {
338  g << " XPRSsetdblcontrol(d->xprob, xprs_id, "
339  << g.constant(op.second.to_double()) << ");\n";
340  } else if (op.second.is_int() || op.second.is_bool()) {
341  g << " XPRSsetintcontrol(d->xprob, xprs_id, "
342  << static_cast<int>(op.second.to_int()) << ");\n";
343  } else if (op.second.is_string()) {
344  g << " XPRSsetstrcontrol(d->xprob, xprs_id, "
345  << g.constant(op.second.to_string()) << ");\n";
346  } else {
347  casadi_error("Unsupported option type for '" + op.first + "'.");
348  }
349  g << "}\n";
350  }
351 
352  g << "casadi_xpress_solve(d, arg, res, iw, w);\n";
353 
354  g << "if (!d_qp.success) {\n";
355  if (error_on_fail_) {
356  g << " return -1000;\n";
357  } else {
358  g << " return -1;\n";
359  }
360  g << "}\n";
361  g << "return 0;\n";
362  }
363 
364  void XpressInterface::build_socp_config() {
365  SDPToSOCPMem sm;
366  sdp_to_socp_init(sm);
367 
368  socp_r_ = sm.r;
369  casadi_int n_eq = sm.map_Q.size2();
370  socp_mq_colind_.assign(sm.map_Q.colind(), sm.map_Q.colind() + n_eq + 1);
371  socp_mq_row_.assign(sm.map_Q.row(), sm.map_Q.row() + sm.map_Q.nnz());
372  socp_mq_data_.assign(sm.map_Q.ptr(), sm.map_Q.ptr() + sm.map_Q.nnz());
373  socp_map_P_ = sm.map_P;
374 
375  socp_.n_blocks = static_cast<casadi_int>(sm.r.size() - 1);
376  socp_.r = get_ptr(socp_r_);
377  socp_.n_lifted = sm.r.back();
378  socp_.nx = nx_;
379  socp_.mq_colind = get_ptr(socp_mq_colind_);
380  socp_.mq_row = get_ptr(socp_mq_row_);
381  socp_.mq_data = get_ptr(socp_mq_data_);
382  socp_.map_P = get_ptr(socp_map_P_);
383  casadi_socp_setup(&socp_);
384  }
385 
386  int XpressInterface::init_mem(void* mem) const {
387  if (Conic::init_mem(mem)) return 1;
388  if (!mem) return 1;
389 
390  // Lazy global library init
391  std::call_once(s_xpress_init_flag, xpress_global_init);
392  casadi_assert(s_xpress_init_rc == 0,
393  "XPRSinit() failed (return code " + str(s_xpress_init_rc) + "). "
394  "Check that the XPRESS environment variable points to a valid license "
395  "or that a license server is reachable.");
396 
397  auto m = static_cast<XpressMemory*>(mem);
398  if (casadi_xpress_init_mem(&m->d)) return 1;
399 
400  m->add_stat("preprocessing");
401  m->add_stat("solver");
402  m->add_stat("postprocessing");
403 
404  return 0;
405  }
406 
407  void XpressInterface::free_mem(void* mem) const {
408  auto m = static_cast<XpressMemory*>(mem);
409  casadi_xpress_free_mem(&m->d);
410  delete static_cast<XpressMemory*>(mem);
411  }
412 
414  void XpressInterface::set_work(void* mem, const double**& arg, double**& res,
415  casadi_int*& iw, double*& w) const {
416 
417  auto m = static_cast<XpressMemory*>(mem);
418 
419  Conic::set_work(mem, arg, res, iw, w);
420 
421  m->d.prob = &p_;
422  m->d.qp = &m->d_qp;
423 
424  casadi_xpress_set_work(&m->d, &arg, &res, &iw, &w);
425 
426  // SOCP inputs
427  if (has_socp_) {
428  m->d.socp.q = arg[CONIC_Q];
429  m->d.socp.p = arg[CONIC_P];
430  }
431 
432  // MIP warm start: point runtime at x0 when requested
433  m->d.x0 = mip_start_ ? arg[CONIC_X0] : nullptr;
434 
435  // Optional file log (useful for tests: captures "User solution" messages)
436  if (!log_file_.empty()) {
437  XPRS_WARN(XPRSsetlogfile, m->d.xprob, log_file_.c_str());
438  }
439 
440  // Invalidate any IIS cached from a previous solve
441  m->iis_valid = false;
442 
443  // Sensible default: enable crossover after the QP barrier so the
444  // returned solution sits exactly at the optimal vertex. Without this
445  // Xpress returns an interior-point near-vertex solution that can be
446  // off by ~FEASTOL on each active constraint. User options below
447  // can still override this.
448  XPRS_WARN(XPRSsetintcontrol, m->d.xprob, XPRS_CROSSOVER, 1);
449 
450  // Push user options to Xpress. Resolve name -> (id, type) via
451  // XPRSgetcontrolinfo, then dispatch to the typed setter.
452  for (auto&& op : opts_) {
453  int id = 0;
454  int type = 0;
455  int rc = XPRSgetcontrolinfo(m->d.xprob, op.first.c_str(), &id, &type);
456  casadi_assert(rc == 0,
457  "Xpress: unknown control '" + op.first + "' (XPRSgetcontrolinfo rc=" +
458  str(rc) + ").");
459  switch (type) {
460  case XPRS_TYPE_INT:
461  rc = XPRSsetintcontrol(m->d.xprob, id, op.second.to_int());
462  break;
463  case XPRS_TYPE_INT64:
464  rc = XPRSsetintcontrol64(m->d.xprob, id,
465  static_cast<XPRSint64>(op.second.to_int()));
466  break;
467  case XPRS_TYPE_DOUBLE:
468  rc = XPRSsetdblcontrol(m->d.xprob, id, op.second.to_double());
469  break;
470  case XPRS_TYPE_STRING: {
471  std::string v = op.second.to_string();
472  rc = XPRSsetstrcontrol(m->d.xprob, id, v.c_str());
473  break;
474  }
475  default:
476  casadi_error("Xpress: unsupported control type for '" + op.first + "'.");
477  }
478  casadi_assert(rc == 0,
479  "Xpress: failed to set control '" + op.first + "' (rc=" + str(rc) + ").");
480  }
481  }
482 
484  solve(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const {
485  auto m = static_cast<XpressMemory*>(mem);
486 
487  m->fstats.at("solver").tic();
488  int rc = casadi_xpress_solve(&m->d, arg, res, iw, w);
489  m->fstats.at("solver").toc();
490 
491  // IIS: computed right after the solve while the problem is still loaded.
492  // Placed here (not in get_stats) because IIS computation can be expensive.
493  bool lp_infeas = (m->d.lp_status == XPRS_LP_INFEAS);
494  bool mip_infeas = (m->d.mip_status == XPRS_MIP_INFEAS);
495  if (compute_iis_ && (lp_infeas || mip_infeas) && m->d.xprob) {
496  int iis_status = 0;
497  // XPRS_WARN not used here: iisfirst status=0 means IIS found (not an error).
498  if (XPRSiisfirst(m->d.xprob, 2, &iis_status) == 0 && iis_status == 0) {
499  int nrows = 0, ncols = 0;
500  // First call: query sizes. Second call: retrieve data.
501  // Use XPRS_WARN so any API failure is reported but IIS is simply skipped.
502  if (XPRSgetiisdata(m->d.xprob, 1, &nrows, &ncols,
503  nullptr, nullptr, nullptr, nullptr,
504  nullptr, nullptr, nullptr, nullptr) == 0) {
505  std::vector<int> rows(nrows), cols(ncols);
506  std::vector<char> contype(nrows), bndtype(ncols);
507  if (XPRSgetiisdata(m->d.xprob, 1, &nrows, &ncols,
508  nrows > 0 ? rows.data() : nullptr,
509  ncols > 0 ? cols.data() : nullptr,
510  nrows > 0 ? contype.data() : nullptr,
511  ncols > 0 ? bndtype.data() : nullptr,
512  nullptr, nullptr, nullptr, nullptr) == 0) {
513  m->iis_rows.assign(rows.begin(), rows.end());
514  m->iis_cols.assign(cols.begin(), cols.end());
515  m->iis_row_types.assign(contype.begin(), contype.end());
516  m->iis_col_bound_types.assign(bndtype.begin(), bndtype.end());
517  m->iis_valid = true;
518  } else {
519  XPRS_LOG_ERROR(XPRSgetiisdata, m->d.xprob, "Warning");
520  }
521  } else {
522  XPRS_LOG_ERROR(XPRSgetiisdata, m->d.xprob, "Warning");
523  }
524  }
525  }
526 
527  return rc;
528  }
529 
531  clear_mem();
532  }
533 
534  Dict XpressInterface::get_stats(void* mem) const {
535  Dict stats = Conic::get_stats(mem);
536  auto m = static_cast<XpressMemory*>(mem);
537  stats["return_status"] = m->d.return_status;
538  stats["lp_status"] = m->d.lp_status;
539  stats["mip_status"] = m->d.mip_status;
540  stats["simplex_iter"] = m->d.simplex_iter;
541  stats["barrier_iter"] = m->d.barrier_iter;
542  stats["mip_nodes"] = m->d.mip_nodes;
543  stats["objective"] = m->d.obj_val;
544 
545  // IIS: read from cache populated right after the solve (see eval_body).
546  if (m->iis_valid) {
547  stats["iis_rows"] = m->iis_rows;
548  stats["iis_cols"] = m->iis_cols;
549  stats["iis_row_types"] = m->iis_row_types;
550  stats["iis_col_bound_types"] = m->iis_col_bound_types;
551  }
552 
553  return stats;
554  }
555 
557  int v = s.version("XpressInterface", 1, 2);
558  s.unpack("XpressInterface::opts", opts_);
559  mip_start_ = false;
560  log_file_ = "";
561  compute_iis_ = false;
562  if (v >= 2) {
563  s.unpack("XpressInterface::mip_start", mip_start_);
564  s.unpack("XpressInterface::log_file", log_file_);
565  s.unpack("XpressInterface::compute_iis", compute_iis_);
566  }
567  s.unpack("XpressInterface::sos_settype", sos_settype_);
568  s.unpack("XpressInterface::sos_setstart", sos_setstart_);
569  s.unpack("XpressInterface::sos_setind", sos_setind_);
570  s.unpack("XpressInterface::sos_refval", sos_refval_);
571  has_socp_ = !Q_.is_null() && Q_.nnz() > 0;
572  if (has_socp_) build_socp_config();
573  init_dependent();
574  set_xpress_prob();
575  }
576 
579 
580  s.version("XpressInterface", 2);
581  s.pack("XpressInterface::opts", opts_);
582  s.pack("XpressInterface::mip_start", mip_start_);
583  s.pack("XpressInterface::log_file", log_file_);
584  s.pack("XpressInterface::compute_iis", compute_iis_);
585  s.pack("XpressInterface::sos_settype", sos_settype_);
586  s.pack("XpressInterface::sos_setstart", sos_setstart_);
587  s.pack("XpressInterface::sos_setind", sos_setind_);
588  s.pack("XpressInterface::sos_refval", sos_refval_);
589  }
590 
591 } // end namespace casadi
Helper class for C code generation.
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
void init_local(const std::string &name, const std::string &def)
Specify the default value for a local variable.
std::string sanitize_source(const std::string &src, const std::vector< std::string > &inst, bool add_shorthand=true)
Sanitize source files for codegen.
void add_include(const std::string &new_include, bool relative_path=false, const std::string &use_ifdef=std::string())
Add an include file optionally using a relative path "..." instead of an absolute path <....
void constant_copy(const std::string &var_name, const std::vector< casadi_int > &v, const std::string &type="casadi_int")
Represent an array constant; adding it when new.
std::stringstream auxiliaries
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
Internal class.
Definition: conic_impl.hpp:44
static const Options options_
Options.
Definition: conic_impl.hpp:83
casadi_int nx_
Number of decision variables.
Definition: conic_impl.hpp:173
int init_mem(void *mem) const override
Initalize memory block.
Definition: conic.cpp:466
Sparsity H_
Problem structure.
Definition: conic_impl.hpp:170
void init(const Dict &opts) override
Initialize.
Definition: conic.cpp:415
std::vector< bool > discrete_
Options.
Definition: conic_impl.hpp:164
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: conic.cpp:753
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
Definition: conic.cpp:473
Dict get_stats(void *mem) const override
Get all statistics.
Definition: conic.cpp:726
casadi_qp_prob< double > p_qp_
Definition: conic_impl.hpp:47
void qp_codegen_body(CodeGenerator &g) const
Generate code for the function body.
Definition: conic.cpp:812
void sdp_to_socp_init(SDPToSOCPMem &mem) const
SDP to SOCP conversion initialization.
Definition: conic.cpp:595
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.
void alloc_res(size_t sz_res, bool persistent=false)
Ensure required length of res field.
void alloc_arg(size_t sz_arg, bool persistent=false)
Ensure required length of arg field.
std::string codegen_mem(CodeGenerator &g, const std::string &index="mem") const
Get thread-local memory object.
size_t sz_res() const
Get required length of res field.
size_t sz_w() const
Get required length of w field.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
size_t sz_arg() const
Get required length of arg field.
size_t sz_iw() const
Get required length of iw field.
bool is_null() const
Is a null pointer?
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
bool error_on_fail_
Throw an exception on failure?
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.
casadi_int nnz() const
Get the number of (structural) non-zeros.
Definition: sparsity.cpp:148
casadi_int size2() const
Get the number of columns.
Definition: sparsity.cpp:128
const casadi_int * row() const
Get a reference to row-vector,.
Definition: sparsity.cpp:164
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
Definition: sparsity.cpp:168
Dict get_stats(void *mem) const override
Get all statistics.
void free_mem(void *mem) const override
Free memory block.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
int init_mem(void *mem) const override
Initalize memory block.
static Conic * creator(const std::string &name, const std::map< std::string, Sparsity > &st)
Create a new QP Solver.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
void codegen_init_mem(CodeGenerator &g) const override
Codegen init for init_mem.
void codegen_body(CodeGenerator &g) const override
Generate code for the function body.
static const std::string meta_doc
A documentation string.
~XpressInterface() override
Destructor.
void codegen_free_mem(CodeGenerator &g) const override
Codegen for free_mem.
static const Options options_
Options.
void init(const Dict &opts) override
Initialize.
int solve(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Solve the QP.
XpressInterface(const std::string &name, const std::map< std::string, Sparsity > &st)
Constructor using sparsity patterns.
Dict opts_
All Xpress options.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
The casadi namespace.
Definition: archiver.cpp:28
static int s_xpress_init_rc
static std::once_flag s_xpress_init_flag
void copy_vector(const std::vector< S > &s, std::vector< D > &d)
@ CONIC_X0
dense, (n x 1)
Definition: conic.hpp:187
@ CONIC_Q
The matrix Q: sparse symmetric, (np^2 x n)
Definition: conic.hpp:193
@ CONIC_P
The matrix P: sparse symmetric, (np x np)
Definition: conic.hpp:195
void flatten_nested_vector(const std::vector< std::vector< T > > &nested, std::vector< S > &flat)
Flatten a nested std::vector tot a single flattened vector.
static void codegen_int_field(CodeGenerator &g, const std::string &prob_field, const std::string &local_name, const std::vector< int > &v)
@ OT_INTVECTOR
@ OT_DOUBLEVECTORVECTOR
@ OT_INTVECTORVECTOR
std::string str(const T &v)
String representation, any type.
void check_sos(casadi_int nx, const std::vector< std::vector< T > > &groups, std::vector< std::vector< double > > &weights, std::vector< casadi_int > &types)
Check sos structure and generate defaults.
Definition: nlp_tools.hpp:79
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
int CASADI_CONIC_XPRESS_EXPORT casadi_register_conic_xpress(Conic::Plugin *plugin)
void CASADI_CONIC_XPRESS_EXPORT casadi_load_conic_xpress()
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
static void xpress_global_init()
Options metadata for a class.
Definition: options.hpp:40
std::map< std::string, FStats > fstats
void add_stat(const std::string &s)
casadi_xpress_data< double > d
const casadi_int * r
Definition: casadi_socp.hpp:58
casadi_int n_lifted
Definition: casadi_socp.hpp:60
casadi_int n_blocks
Definition: casadi_socp.hpp:54
const casadi_int * mq_colind
Definition: casadi_socp.hpp:67
const casadi_int * map_P
Definition: casadi_socp.hpp:76
const casadi_int * mq_row
Definition: casadi_socp.hpp:68
const casadi_int * mq_data
Definition: casadi_socp.hpp:72
const double * sos_refval
const int * sos_setstart
const int * qobj_nz_idx
const char * sos_settype
const int * sos_setind
const casadi_qp_prob< T1 > * qp
const char * coltype
const casadi_socp_prob< T1 > * socp