optistack_internal.hpp
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 #ifndef CASADI_OPTISTACK_INTERNAL_HPP
26 #define CASADI_OPTISTACK_INTERNAL_HPP
27 
28 #include "optistack.hpp"
29 #include "shared_object.hpp"
30 
31 namespace casadi {
32 
33 #ifndef SWIG
35 template<class T>
36 class null_ptr_on_copy {
37 public:
38  null_ptr_on_copy() : ptr_(nullptr) {}
39  null_ptr_on_copy(const null_ptr_on_copy& rhs) : ptr_(nullptr) {}
40  void operator=(T* ptr) { ptr_ = ptr; }
41  T* operator->() { return ptr_; }
42  operator bool() const { return ptr_; }
43 private:
44  T* ptr_;
45 };
46 #endif
47 
55 class CASADI_EXPORT OptiNode :
56  public SharedObjectInternal {
57  friend class InternalOptiCallback;
58 public:
59 
61  OptiNode(const std::string& problem_type);
62 
65 
67  MX variable(casadi_int n=1, casadi_int m=1, const std::string& attribute="full");
68  MX variable(const Sparsity& sp, const std::string& attribute="full");
69  MX variable(const MX& symbol, const std::string& attribute="full");
70 
72  MX parameter(casadi_int n=1, casadi_int m=1, const std::string& attribute="full");
73 
75  MX parameter(const Sparsity& sp, const std::string& attribute="full");
76 
77  MX parameter(const MX& symbol, const std::string& attribute="full");
78 
80  void minimize(const MX& f, double linear_scale=1);
81 
83  void subject_to(const MX& g, const DM& linear_scale=1, const Dict& options=Dict());
85  void subject_to();
86 
88  void solver(const std::string& solver,
89  const Dict& plugin_options=Dict(),
90  const Dict& solver_options=Dict());
91 
94  void set_initial(const MX& x, const DM& v);
95  void set_initial(const std::vector<MX>& assignments);
97 
99 
104  void set_value(const MX& x, const DM& v);
105  void set_value(const std::vector<MX>& assignments);
107 
109  void set_domain(const MX& x, const std::string& domain);
110 
112  void set_linear_scale(const MX& x, const DM& scale, const DM& offset);
113 
115  OptiSol solve(bool accept_limit);
116 
119  DM value(const MX& x,
120  const std::vector<MX>& values=std::vector<MX>(), bool scaled=false) const;
121  DM value(const DM& x,
122  const std::vector<MX>& values=std::vector<MX>(), bool scaled=false) const { return x; }
123  DM value(const SX& x,
124  const std::vector<MX>& values=std::vector<MX>(), bool scaled=false) const {
125  casadi_assert(x.is_constant(), "Opti works with MX: cannot evaluate SX expression " + str(x));
126  return evalf(x);
127  }
129 
131  Opti copy() const;
132 
134  Dict stats() const;
135 
137  std::string return_status() const;
139  bool return_success(bool accept_limit) const;
140 
143 
147  Function scale_helper(const Function& h) const;
148 
150  std::vector<MX> initial() const;
151 
153  std::vector<MX> value_variables() const;
154  std::vector<MX> value_parameters() const;
155 
156  void callback_class(OptiCallback* callback);
158  bool has_callback_class() const;
159 
161  bool is_parametric(const MX& expr) const;
162 
165  std::vector<MX> symvar() const;
166  std::vector<MX> symvar(const MX& expr) const;
167  std::vector<MX> symvar(const MX& expr, VariableType type) const;
169 
171  MetaCon canon_expr(const MX& expr, const DM& linear_scale=1) const;
172 
174  MetaVar get_meta(const MX& m) const;
175 
177  MetaCon get_meta_con(const MX& m) const;
178 
180  void set_meta(const MX& m, const MetaVar& meta);
181 
183  void set_meta_con(const MX& m, const MetaCon& meta);
184 
186  void update_user_dict(const MX& m, const Dict& meta);
187  Dict user_dict(const MX& m) const;
188 
190  MX dual(const MX& m) const;
191 
192  void assert_active_symbol(const MX& m) const;
193 
194  std::vector<MX> symvar(VariableType type) const;
195  std::vector<MX> active_symvar(VariableType type) const;
196  std::vector<DM> active_values(VariableType type) const;
197  std::vector<DM> active_values(VariableType type,
198  const std::map< VariableType, std::vector<DM> >& store) const;
199 
200  MX x_lookup(casadi_int i) const;
201  MX g_lookup(casadi_int i) const;
202 
203  std::string x_describe(casadi_int i, const Dict& opts=Dict()) const;
204  std::string g_describe(casadi_int i, const Dict& opts=Dict()) const;
205  std::string describe(const MX& x, casadi_int indent=0, const Dict& opts=Dict()) const;
206 
208  Function solver_construct(bool callback=true);
209  DMDict solve_actual(const DMDict& args);
210 
211  DMDict arg() const { return arg_; }
212  void res(const DMDict& res);
213  DMDict res() const { return res_; }
214  std::vector<MX> constraints() const { return g_; }
215  MX objective() const { return f_; }
216 
218  OptiAdvanced s = copy();
219  if (s.problem_dirty()) s.bake();
220  return s;
221  }
222 
223  std::string class_name() const override { return "OptiNode"; }
224 
226  casadi_int nx() const {
227  if (problem_dirty()) return baked_copy().nx();
228  return nlp_.at("x").size1();
229  }
230 
232  casadi_int np() const {
233  if (problem_dirty()) return baked_copy().np();
234  return nlp_.at("p").size1();
235  }
236 
238  casadi_int ng() const {
239  if (problem_dirty()) return baked_copy().ng();
240  return nlp_.at("g").size1();
241  }
242 
244  MX x() const {
245  if (problem_dirty()) return baked_copy().x();
246  return nlp_.at("x");
247  }
248 
250  MX p() const {
251  if (problem_dirty()) return baked_copy().p();
252  return nlp_.at("p");
253  }
254 
256  MX g() const {
257  if (problem_dirty()) return baked_copy().g();
258  return nlp_unscaled_.at("g");
259  }
260 
262  MX f() const {
263  if (problem_dirty()) return baked_copy().f();
264  return nlp_unscaled_.at("f");
265  }
266 
267  MX lbg() const {
268  if (problem_dirty()) return baked_copy().lbg();
269  return bounds_unscaled_lbg_;
270  }
271 
272  MX ubg() const {
273  if (problem_dirty()) return baked_copy().ubg();
274  return bounds_unscaled_ubg_;
275  }
276 
278  MX lam_g() const {
279  if (problem_dirty()) return baked_copy().lam_g();
280  return lam_;
281  }
282 
283  DM x_linear_scale() const {
284  if (problem_dirty()) return baked_copy().x_linear_scale();
285  return DM(linear_scale_);
286  }
288  if (problem_dirty()) return baked_copy().x_linear_scale_offset();
289  return DM(linear_scale_offset_);
290  }
291  DM g_linear_scale() const {
292  if (problem_dirty()) return baked_copy().g_linear_scale();
293  return DM(g_linear_scale_);
294  }
295  double f_linear_scale() const {
296  if (problem_dirty()) return baked_copy().f_linear_scale();
297  return f_linear_scale_;
298  }
299  void assert_empty() const;
300 
301  void show_infeasibilities(double tol=0, const Dict& opts=Dict()) const;
302 
306  Function to_function(const std::string& name,
307  const std::vector<MX>& args, const std::vector<MX>& res,
308  const std::vector<std::string>& name_in,
309  const std::vector<std::string>& name_out,
310  const Dict& opts);
311 
313  void disp(std::ostream& stream, bool more=false) const override;
314 
316  void bake();
317 
318  casadi_int instance_number() const;
319 
320  static OptiNode* create(const std::string& problem_type);
321 
323  void mark_problem_dirty(bool flag=true) { problem_dirty_=flag; mark_solver_dirty(); }
324  bool problem_dirty() const { return problem_dirty_; }
325 
327  void mark_solver_dirty(bool flag=true) { solver_dirty_=flag; mark_solved(false); }
328  bool solver_dirty() const { return solver_dirty_; }
329 
330  bool solved_;
331  void mark_solved(bool flag=true) { solved_ = flag;}
332  bool solved() const { return solved_; }
333 
334  void assert_solved() const;
335  void assert_baked() const;
336 
337  casadi_int g_index_reduce_g(casadi_int i) const;
338  casadi_int g_index_reduce_x(casadi_int i) const;
339  casadi_int g_index_unreduce_g(casadi_int i) const;
340 
341 private:
342 
343  static std::map<VariableType, std::string> VariableType2String_;
344  std::string variable_type_to_string(VariableType vt) const;
345 
346  bool parse_opti_name(const std::string& name, VariableType& vt) const;
347  void register_dual(MetaCon& meta);
348 
350  void set_value_internal(const MX& x, const DM& v,
351  std::map< VariableType, std::vector<DM> >& store);
352 
361  static std::vector<MX> ineq_unchain(const MX& a, bool& SWIG_OUTPUT(flipped));
362 
364  const MetaVar& meta(const MX& m) const;
366  MetaVar& meta(const MX& m);
367 
369  const MetaCon& meta_con(const MX& m) const;
371  MetaCon& meta_con(const MX& m);
372 
374  std::vector<MX> sort(const std::vector<MX>& v) const;
375 
377  void assert_has(const MX& m) const;
378 
379  bool has(const MX& m) const;
380 
382  void assert_has_con(const MX& m) const;
383 
384  bool has_con(const MX& m) const;
385 
386  // Data members
387 
389  std::map<MXNode*, MetaVar> meta_;
391  std::map<MXNode*, MetaCon> meta_con_;
392 
394  std::vector<MX> symbols_;
395 
396  // Which x entries are discrete?
397  std::vector<bool> discrete_;
398 
400  casadi_int count_;
401 
402  casadi_int count_var_;
403  casadi_int count_par_;
404  casadi_int count_dual_;
405 
407  std::map< VariableType, std::vector<DM> > store_initial_, store_latest_;
408 
410  std::map< VariableType, std::vector<DM> > store_linear_scale_, store_linear_scale_offset_;
411 
413  std::vector<bool> symbol_active_;
414 
416  Function solver_;
417 
418  mutable Dict stats_;
419  mutable std::vector<casadi_int> g_index_reduce_g_;
420  mutable std::vector<casadi_int> g_index_reduce_x_;
421  mutable std::vector<casadi_int> g_index_unreduce_g_;
422  mutable std::vector<casadi_int> target_x_;
423  mutable std::vector<bool> is_simple_;
424  mutable bool reduced_;
425 
427  DMDict res_;
428  DMDict arg_;
429  MXDict nlp_;
430  MXDict nlp_unscaled_;
431  MX lam_;
432  std::vector<double> linear_scale_;
433  std::vector<double> linear_scale_offset_;
434  std::vector<double> g_linear_scale_;
435  std::vector<double> h_linear_scale_;
436 
437  std::vector<casadi_int> index_all_to_g_;
438 
440  Function bounds_;
441  MX bounds_lbg_, bounds_unscaled_lbg_;
442  MX bounds_ubg_, bounds_unscaled_ubg_;
443  std::vector<bool> equality_;
444 
446  std::vector<MX> g_;
447 
448  class ValueHelper {
449  public:
450  Function helper;
451  std::vector<MX> x;
452  std::vector<MX> p;
453  std::vector<MX> lam;
454  };
455 
457 
458  mutable std::shared_ptr<ValueCache> helpers_;
459 
461  MX f_;
462 
463  double f_linear_scale_;
464 
466  std::string problem_type_;
467 
468  null_ptr_on_copy<OptiCallback> user_callback_;
469  Function callback_;
470 
471  bool old_callback() const;
472 
473  std::string solver_name_;
474  Dict solver_options_;
475 
476  void assert_only_opti_symbols(const MX& e) const;
477  void assert_only_opti_nondual(const MX& e) const;
478 
479 
480  static casadi_int instance_count_;
481  casadi_int instance_number_;
482 
483 
484  std::string name_prefix() const;
485 
486  static std::string format_stacktrace(const Dict& stacktrace, casadi_int indent);
487 
488 };
489 
490 
491 } // namespace casadi
492 
493 #endif // CASADI_OPTISTACK_INTERNAL_HPP
Function object.
Definition: function.hpp:126
MX - Matrix expression.
Definition: mx.hpp:145
bool is_constant() const
Check if every entry is a numerical constant (no symbols)
Opti with debugging and low-level access.
Definition: optistack.hpp:2786
bool problem_dirty() const
True when the problem must be baked again before solving.
void bake()
Fix the structure of the optimization problem.
Base class of iteration callbacks for Opti.
Definition: optistack.hpp:2764
A simplified interface for NLP modeling/solving.
Function solver_construct(bool callback=true)
Dict user_dict(const MX &m) const
std::vector< MX > constraints() const
std::vector< MX > symvar(VariableType type) const
casadi_int g_index_reduce_x(casadi_int i) const
std::string describe(const MX &x, casadi_int indent=0, const Dict &opts=Dict()) const
MX g() const
Get all (scalarised) constraint expressions as a column vector.
MetaCon get_meta_con(const MX &m) const
Get meta-data of symbol (for internal use only)
OptiAdvanced baked_copy() const
MX dual(const MX &m) const
get the dual variable
MX x() const
Get all (scalarised) decision variables as a symbolic column vector.
void minimize(const MX &f, double linear_scale=1)
Set objective.
casadi_int nx() const
Number of (scalarised) decision variables.
MX variable(casadi_int n=1, casadi_int m=1, const std::string &attribute="full")
Create a decision variable (symbol)
std::string x_describe(casadi_int i, const Dict &opts=Dict()) const
void bake()
Fix the structure of the optimization problem.
casadi_int instance_number() const
DM value(const MX &x, const std::vector< MX > &values=std::vector< MX >(), bool scaled=false) const
void disp(std::ostream &stream, bool more=false) const override
Print representation.
std::vector< MX > active_symvar(VariableType type) const
void set_domain(const MX &x, const std::string &domain)
Set domain of variable.
static OptiNode * create(const std::string &problem_type)
OptiSol solve(bool accept_limit)
Crunch the numbers; solve the problem.
void res(const DMDict &res)
casadi_int np() const
Number of (scalarised) parameters.
bool has_callback_class() const
MX g_lookup(casadi_int i) const
casadi_int ng() const
Number of (scalarised) constraints.
MetaVar get_meta(const MX &m) const
Get meta-data of symbol (for internal use only)
void subject_to()
Clear constraints.
void assert_baked() const
MX parameter(const MX &symbol, const std::string &attribute="full")
MX variable(const Sparsity &sp, const std::string &attribute="full")
void update_user_dict(const MX &m, const Dict &meta)
add meta-data of an expression
void assert_solved() const
std::vector< MX > initial() const
get assignment expressions for initial values
void set_meta(const MX &m, const MetaVar &meta)
Set meta-data of an expression.
std::vector< DM > active_values(VariableType type) const
std::vector< DM > active_values(VariableType type, const std::map< VariableType, std::vector< DM > > &store) const
std::string class_name() const override
MX parameter(casadi_int n=1, casadi_int m=1, const std::string &attribute="full")
Create a parameter (symbol); fixed during optimization.
void set_initial(const std::vector< MX > &assignments)
bool is_parametric(const MX &expr) const
return true if expression is only dependant on Opti parameters, not variables
void assert_active_symbol(const MX &m) const
bool return_success(bool accept_limit) const
Did the solver return successfully?
DM value(const SX &x, const std::vector< MX > &values=std::vector< MX >(), bool scaled=false) const
void subject_to(const MX &g, const DM &linear_scale=1, const Dict &options=Dict())
brief Add constraints
bool problem_dirty() const
Function to_function(const std::string &name, const std::vector< MX > &args, const std::vector< MX > &res, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out, const Dict &opts)
Create a CasADi Function from the Opti solver.
std::vector< MX > symvar() const
void callback_class(OptiCallback *callback)
std::vector< MX > value_variables() const
get assignment expressions for latest values
Opti copy() const
Copy.
DM x_linear_scale_offset() const
MX x_lookup(casadi_int i) const
casadi_int g_index_reduce_g(casadi_int i) const
std::vector< MX > value_parameters() const
void mark_problem_dirty(bool flag=true)
OptiNode(const std::string &problem_type)
Create Opti Context.
std::string return_status() const
Get return status of solver.
MX parameter(const Sparsity &sp, const std::string &attribute="full")
Create a parameter (symbol); fixed during optimization.
~OptiNode()
Destructor.
std::vector< MX > symvar(const MX &expr, VariableType type) const
void assert_empty() const
void set_initial(const MX &x, const DM &v)
void mark_solver_dirty(bool flag=true)
MX p() const
Get all (scalarised) parameters as a symbolic column vector.
casadi_int g_index_unreduce_g(casadi_int i) const
void set_value(const MX &x, const DM &v)
Set value of parameter.
double f_linear_scale() const
MX lam_g() const
Get dual variables as a symbolic column vector.
void set_value(const std::vector< MX > &assignments)
Set value of parameter.
void set_linear_scale(const MX &x, const DM &scale, const DM &offset)
Set scale of a decision variable.
std::string g_describe(casadi_int i, const Dict &opts=Dict()) const
MX variable(const MX &symbol, const std::string &attribute="full")
void solver(const std::string &solver, const Dict &plugin_options=Dict(), const Dict &solver_options=Dict())
Solver.
MX f() const
Get objective expression.
void mark_solved(bool flag=true)
Function scale_helper(const Function &h) const
Scale a helper function constructed via opti.x, opti.g, ...
Function casadi_solver() const
Get the underlying CasADi solver of the Opti stack.
MetaCon canon_expr(const MX &expr, const DM &linear_scale=1) const
Interpret an expression (for internal use only)
DM value(const DM &x, const std::vector< MX > &values=std::vector< MX >(), bool scaled=false) const
std::vector< MX > symvar(const MX &expr) const
void show_infeasibilities(double tol=0, const Dict &opts=Dict()) const
DMDict solve_actual(const DMDict &args)
Dict stats() const
Get statistics.
void set_meta_con(const MX &m, const MetaCon &meta)
Set meta-data of an expression.
Snapshot of an Opti problem and its solution.
Definition: optistack.hpp:3563
A simplified interface for NLP modeling/solving.
Definition: optistack.hpp:236
General sparsity class.
Definition: sparsity.hpp:200
The casadi namespace.
Definition: archiver.hpp:32
std::map< std::string, MX > MXDict
Definition: mx.hpp:5151
VariableType
Kind of an Opti symbol (MetaVar::type)
Definition: optistack.hpp:2711
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
Matrix< double > DM
Definition: dm_fwd.hpp:33
std::map< std::string, DM > DMDict
Definition: dm_fwd.hpp:36
Metadata of a constraint, as returned by OptiAdvanced::canon_expr/get_meta_con.
Definition: optistack.hpp:2730
Metadata of a symbol, as returned by OptiAdvanced::get_meta.
Definition: optistack.hpp:2745