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>
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 
64  ~OptiNode();
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  return DM::nan(x.sparsity());
126  }
128 
130  Opti copy() const;
131 
133  Dict stats() const;
134 
136  std::string return_status() const;
138  bool return_success(bool accept_limit) const;
139 
141  Function casadi_solver() const;
142 
146  Function scale_helper(const Function& h) const;
147 
149  std::vector<MX> initial() const;
150 
152  std::vector<MX> value_variables() const;
153  std::vector<MX> value_parameters() const;
154 
155  void callback_class(OptiCallback* callback);
156  void callback_class();
157  bool has_callback_class() const;
158 
160  bool is_parametric(const MX& expr) const;
161 
164  std::vector<MX> symvar() const;
165  std::vector<MX> symvar(const MX& expr) const;
166  std::vector<MX> symvar(const MX& expr, VariableType type) const;
168 
170  MetaCon canon_expr(const MX& expr, const DM& linear_scale=1) const;
171 
173  MetaVar get_meta(const MX& m) const;
174 
176  MetaCon get_meta_con(const MX& m) const;
177 
179  void set_meta(const MX& m, const MetaVar& meta);
180 
182  void set_meta_con(const MX& m, const MetaCon& meta);
183 
185  void update_user_dict(const MX& m, const Dict& meta);
186  Dict user_dict(const MX& m) const;
187 
189  MX dual(const MX& m) const;
190 
191  void assert_active_symbol(const MX& m) const;
192 
193  std::vector<MX> symvar(VariableType type) const;
194  std::vector<MX> active_symvar(VariableType type) const;
195  std::vector<DM> active_values(VariableType type) const;
196  std::vector<DM> active_values(VariableType type,
197  const std::map< VariableType, std::vector<DM> >& store) const;
198 
199  MX x_lookup(casadi_int i) const;
200  MX g_lookup(casadi_int i) const;
201 
202  std::string x_describe(casadi_int i, const Dict& opts=Dict()) const;
203  std::string g_describe(casadi_int i, const Dict& opts=Dict()) const;
204  std::string describe(const MX& x, casadi_int indent=0, const Dict& opts=Dict()) const;
205 
206  void solve_prepare();
207  Function solver_construct(bool callback=true);
208  DMDict solve_actual(const DMDict& args);
209 
210  DMDict arg() const { return arg_; }
211  void res(const DMDict& res);
212  DMDict res() const { return res_; }
213  std::vector<MX> constraints() const { return g_; }
214  MX objective() const { return f_; }
215 
217  OptiAdvanced s = copy();
218  if (s.problem_dirty()) s.bake();
219  return s;
220  }
221 
222  std::string class_name() const override { return "OptiNode"; }
223 
225  casadi_int nx() const {
226  if (problem_dirty()) return baked_copy().nx();
227  return nlp_.at("x").size1();
228  }
229 
231  casadi_int np() const {
232  if (problem_dirty()) return baked_copy().np();
233  return nlp_.at("p").size1();
234  }
235 
237  casadi_int ng() const {
238  if (problem_dirty()) return baked_copy().ng();
239  return nlp_.at("g").size1();
240  }
241 
243  MX x() const {
244  if (problem_dirty()) return baked_copy().x();
245  return nlp_.at("x");
246  }
247 
249  MX p() const {
250  if (problem_dirty()) return baked_copy().p();
251  return nlp_.at("p");
252  }
253 
255  MX g() const {
256  if (problem_dirty()) return baked_copy().g();
257  return nlp_unscaled_.at("g");
258  }
259 
261  MX f() const {
262  if (problem_dirty()) return baked_copy().f();
263  return nlp_unscaled_.at("f");
264  }
265 
266  MX lbg() const {
267  if (problem_dirty()) return baked_copy().lbg();
268  return bounds_unscaled_lbg_;
269  }
270 
271  MX ubg() const {
272  if (problem_dirty()) return baked_copy().ubg();
273  return bounds_unscaled_ubg_;
274  }
275 
277  MX lam_g() const {
278  if (problem_dirty()) return baked_copy().lam_g();
279  return lam_;
280  }
281 
282  DM x_linear_scale() const {
283  if (problem_dirty()) return baked_copy().x_linear_scale();
284  return DM(linear_scale_);
285  }
287  if (problem_dirty()) return baked_copy().x_linear_scale_offset();
288  return DM(linear_scale_offset_);
289  }
290  DM g_linear_scale() const {
291  if (problem_dirty()) return baked_copy().g_linear_scale();
292  return DM(g_linear_scale_);
293  }
294  double f_linear_scale() const {
295  if (problem_dirty()) return baked_copy().f_linear_scale();
296  return f_linear_scale_;
297  }
298  void assert_empty() const;
299 
300  void show_infeasibilities(double tol=0, const Dict& opts=Dict()) const;
301 
305  Function to_function(const std::string& name,
306  const std::vector<MX>& args, const std::vector<MX>& res,
307  const std::vector<std::string>& name_in,
308  const std::vector<std::string>& name_out,
309  const Dict& opts);
310 
312  void disp(std::ostream& stream, bool more=false) const override;
313 
315  void bake();
316 
317  casadi_int instance_number() const;
318 
319  static OptiNode* create(const std::string& problem_type);
320 
322  void mark_problem_dirty(bool flag=true) { problem_dirty_=flag; mark_solver_dirty(); }
323  bool problem_dirty() const { return problem_dirty_; }
324 
326  void mark_solver_dirty(bool flag=true) { solver_dirty_=flag; mark_solved(false); }
327  bool solver_dirty() const { return solver_dirty_; }
328 
329  bool solved_;
330  void mark_solved(bool flag=true) { solved_ = flag;}
331  bool solved() const { return solved_; }
332 
333  void assert_solved() const;
334  void assert_baked() const;
335 
336  casadi_int g_index_reduce_g(casadi_int i) const;
337  casadi_int g_index_reduce_x(casadi_int i) const;
338  casadi_int g_index_unreduce_g(casadi_int i) const;
339 
340 private:
341 
342  static std::map<VariableType, std::string> VariableType2String_;
343  std::string variable_type_to_string(VariableType vt) const;
344 
345  bool parse_opti_name(const std::string& name, VariableType& vt) const;
346  void register_dual(MetaCon& meta);
347 
349  void set_value_internal(const MX& x, const DM& v,
350  std::map< VariableType, std::vector<DM> >& store);
351 
360  static std::vector<MX> ineq_unchain(const MX& a, bool& SWIG_OUTPUT(flipped));
361 
363  const MetaVar& meta(const MX& m) const;
365  MetaVar& meta(const MX& m);
366 
368  const MetaCon& meta_con(const MX& m) const;
370  MetaCon& meta_con(const MX& m);
371 
373  std::vector<MX> sort(const std::vector<MX>& v) const;
374 
376  void assert_has(const MX& m) const;
377 
378  bool has(const MX& m) const;
379 
381  void assert_has_con(const MX& m) const;
382 
383  bool has_con(const MX& m) const;
384 
385  // Data members
386 
388  std::map<MXNode*, MetaVar> meta_;
390  std::map<MXNode*, MetaCon> meta_con_;
391 
393  std::vector<MX> symbols_;
394 
395  // Which x entries are discrete?
396  std::vector<bool> discrete_;
397 
399  casadi_int count_;
400 
401  casadi_int count_var_;
402  casadi_int count_par_;
403  casadi_int count_dual_;
404 
406  std::map< VariableType, std::vector<DM> > store_initial_, store_latest_;
407 
409  std::map< VariableType, std::vector<DM> > store_linear_scale_, store_linear_scale_offset_;
410 
412  std::vector<bool> symbol_active_;
413 
415  Function solver_;
416 
417  mutable Dict stats_;
418  mutable std::vector<casadi_int> g_index_reduce_g_;
419  mutable std::vector<casadi_int> g_index_reduce_x_;
420  mutable std::vector<casadi_int> g_index_unreduce_g_;
421  mutable std::vector<casadi_int> target_x_;
422  mutable std::vector<bool> is_simple_;
423  mutable bool reduced_;
424 
426  DMDict res_;
427  DMDict arg_;
428  MXDict nlp_;
429  MXDict nlp_unscaled_;
430  MX lam_;
431  std::vector<double> linear_scale_;
432  std::vector<double> linear_scale_offset_;
433  std::vector<double> g_linear_scale_;
434  std::vector<double> h_linear_scale_;
435 
436  std::vector<casadi_int> index_all_to_g_;
437 
439  Function bounds_;
440  MX bounds_lbg_, bounds_unscaled_lbg_;
441  MX bounds_ubg_, bounds_unscaled_ubg_;
442  std::vector<bool> equality_;
443 
445  std::vector<MX> g_;
446 
447  class ValueHelper {
448  public:
449  Function helper;
450  std::vector<MX> x;
451  std::vector<MX> p;
452  std::vector<MX> lam;
453  };
454 
455  typedef RevWeakCache<MX, std::shared_ptr<ValueHelper> > ValueCache;
456 
457  mutable std::shared_ptr<ValueCache> helpers_;
458 
460  MX f_;
461 
462  double f_linear_scale_;
463 
465  std::string problem_type_;
466 
467  null_ptr_on_copy<OptiCallback> user_callback_;
468  Function callback_;
469 
470  bool old_callback() const;
471 
472  std::string solver_name_;
473  Dict solver_options_;
474 
475  void assert_only_opti_symbols(const MX& e) const;
476  void assert_only_opti_nondual(const MX& e) const;
477 
478 
479  static casadi_int instance_count_;
480  casadi_int instance_number_;
481 
482 
483  std::string name_prefix() const;
484 
485  static std::string format_stacktrace(const Dict& stacktrace, casadi_int indent);
486 
487 };
488 
489 
490 } // namespace casadi
491 
492 #endif // CASADI_OPTISTACK_INTERNAL_HPP
Function object.
Definition: function.hpp:60
MX - Matrix expression.
Definition: mx.hpp:92
const Sparsity & sparsity() const
Const access the sparsity - reference to data member.
static Matrix< double > nan(const Sparsity &sp)
create a matrix with all nan
bool problem_dirty() const
Definition: optistack.cpp:793
void bake()
Fix the structure of the optimization problem.
Definition: optistack.cpp:778
A simplified interface for NLP modeling/solving.
std::vector< MX > constraints() const
MX g() const
Get all (scalarised) constraint expressions as a column vector.
OptiAdvanced baked_copy() const
MX x() const
Get all (scalarised) decision variables as a symbolic column vector.
casadi_int nx() const
Number of (scalarised) decision variables.
casadi_int np() const
Number of (scalarised) parameters.
casadi_int ng() const
Number of (scalarised) constraints.
std::string class_name() const override
Readable name of the internal class.
DM value(const SX &x, const std::vector< MX > &values=std::vector< MX >(), bool scaled=false) const
bool problem_dirty() const
DM x_linear_scale_offset() const
void mark_problem_dirty(bool flag=true)
void mark_solver_dirty(bool flag=true)
MX p() const
Get all (scalarised) parameters as a symbolic column vector.
double f_linear_scale() const
MX lam_g() const
Get dual variables as a symbolic column vector.
MX f() const
Get objective expression.
void mark_solved(bool flag=true)
DM value(const DM &x, const std::vector< MX > &values=std::vector< MX >(), bool scaled=false) const
A simplified interface for NLP modeling/solving.
Definition: optistack.hpp:662
A simplified interface for NLP modeling/solving.
Definition: optistack.hpp:90
General sparsity class.
Definition: sparsity.hpp:106
Pointer that gets set to null when copied.
null_ptr_on_copy(const null_ptr_on_copy &rhs)
The casadi namespace.
Definition: archiver.cpp:28
std::map< std::string, MX > MXDict
Definition: mx.hpp:1009
void sort(const std::vector< T > &values, std::vector< T > &sorted_values, std::vector< casadi_int > &indices, bool invert_indices=false)
Sort the data in a vector.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void copy(const T1 *x, casadi_int n, T2 *y)
Matrix< double > DM
Definition: dm_fwd.hpp:33
std::map< std::string, DM > DMDict
Definition: dm_fwd.hpp:36