1 /*
2  *    This file is part of CasADi.
3  *
4  *    CasADi -- A symbolic framework for dynamic optimization.
5  *    Copyright (C) 2010-2014 Joel Andersson, Joris Gillis, Moritz Diehl,
6  *                            K.U. 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 
26 #ifndef CASADI_NLPSOL_IMPL_HPP
27 #define CASADI_NLPSOL_IMPL_HPP
28 
29 #include "nlpsol.hpp"
30 #include "oracle_function.hpp"
31 #include "plugin_interface.hpp"
32 
33 
34 /// \cond INTERNAL
35 namespace casadi {
36 
37   /** \brief Integrator memory */
38   struct CASADI_EXPORT NlpsolMemory : public OracleMemory {
39     // Problem data structure
40     casadi_nlpsol_data<double> d_nlp;
41     // number of iterations
42     casadi_int n_iter;
43     // Success?
44     bool success;
45     // Return status
46     FunctionInternal::UnifiedReturnStatus unified_return_status;
47   };
48 
49   /** \brief NLP solver storage class
50 
51       @copydoc Nlpsol_doc
52       \author Joel Andersson
53       \date 2010-2013
54   */
55   class CASADI_EXPORT
56   Nlpsol : public OracleFunction, public PluginInterface<Nlpsol> {
57   public:
58 
59     // Memory structure
60     casadi_nlpsol_prob<double> p_nlp_;
61 
62     /// Number of variables
63     casadi_int nx_;
64 
65     /// Number of constraints
66     casadi_int ng_;
67 
68     /// Number of parameters
69     casadi_int np_;
70 
71     /// callback function, executed at each iteration
72     Function fcallback_;
73 
74     /// Execute the callback function only after this amount of iterations
75     casadi_int callback_step_;
76 
77     /// Throw an exception on failure?
78     bool error_on_fail_;
79 
80     /// Linear solver and options
81     std::string sens_linsol_;
82     Dict sens_linsol_options_;
83 
84     ///@{
85     /** \brief Options */
86     bool eval_errors_fatal_;
87     bool warn_initial_bounds_;
88     bool iteration_callback_ignore_errors_;
89     bool calc_multipliers_;
90     bool calc_lam_x_, calc_lam_p_, calc_f_, calc_g_;
91     bool bound_consistency_;
92     double min_lam_;
93     bool no_nlp_grad_;
94     std::vector<bool> discrete_;
95     ///@}
96 
97     // Mixed integer problem?
98     bool mi_;
99 
100     /// Cache for KKT function
101     mutable WeakRef kkt_;
102 
103     /** \brief Serialize an object without type information */
104     void serialize_body(SerializingStream &s) const override;
105     /** \brief Serialize type information */
106     void serialize_type(SerializingStream &s) const override;
107 
108     /** \brief Deserialize into MX */
109     static ProtoFunction* deserialize(DeserializingStream& s);
110 
111     /** \brief String used to identify the immediate FunctionInternal subclass */
serialize_base_function() const112     std::string serialize_base_function() const override { return "Nlpsol"; }
113 
114     /// Constructor
115     Nlpsol(const std::string& name, const Function& oracle);
116 
117     /// Destructor
118     ~Nlpsol() override = 0;
119 
120     ///@{
121     /** \brief Number of function inputs and outputs */
get_n_in()122     size_t get_n_in() override { return NLPSOL_NUM_IN;}
get_n_out()123     size_t get_n_out() override { return NLPSOL_NUM_OUT;}
124     ///@}
125 
126     /// @{
127     /** \brief Sparsities of function inputs and outputs */
128     Sparsity get_sparsity_in(casadi_int i) override;
129     Sparsity get_sparsity_out(casadi_int i) override;
130     /// @}
131 
132     ///@{
133     /** \brief Names of function input and outputs */
get_name_in(casadi_int i)134     std::string get_name_in(casadi_int i) override { return nlpsol_in(i);}
get_name_out(casadi_int i)135     std::string get_name_out(casadi_int i) override { return nlpsol_out(i);}
136     /// @}
137 
138     ///@{
139     /** \brief Options */
140     static const Options options_;
get_options() const141     const Options& get_options() const override { return options_;}
142     ///@}
143 
144     /** \brief  Print description */
145     void disp_more(std::ostream& stream) const override;
146 
147     /// Initialize
148     void init(const Dict& opts) override;
149 
150     /** \brief Create memory block */
alloc_mem() const151     void* alloc_mem() const override { return new NlpsolMemory();}
152 
153     /** \brief Initalize memory block */
154     int init_mem(void* mem) const override;
155 
156     /** \brief Free memory block */
free_mem(void * mem) const157     void free_mem(void *mem) const override { delete static_cast<NlpsolMemory*>(mem);}
158 
159     /** \brief Check if the inputs correspond to a well-posed problem */
160     virtual void check_inputs(void* mem) const;
161 
162     /** \brief Get default input value */
get_default_in(casadi_int ind) const163     double get_default_in(casadi_int ind) const override { return nlpsol_default_in(ind);}
164 
165     /// Can discrete variables be treated
integer_support() const166     virtual bool integer_support() const { return false;}
167 
168     /** \brief Set the (persistent) work vectors */
169     void set_work(void* mem, const double**& arg, double**& res,
170                           casadi_int*& iw, double*& w) const override;
171 
172     // Evaluate numerically
173     int eval(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const final;
174 
175     // Solve the NLP
176     virtual int solve(void* mem) const = 0;
177 
178     /** \brief Generate code for the function body */
179     void nlpsol_codegen_body(CodeGenerator& g) const;
180 
181     /** \brief Do the derivative functions need nondifferentiated outputs? */
uses_output() const182     bool uses_output() const override {return true;}
183 
184     /// Get all statistics
185     Dict get_stats(void* mem) const override;
186 
187     ///@{
188     /** \brief Generate a function that calculates forward mode derivatives */
has_forward(casadi_int nfwd) const189     bool has_forward(casadi_int nfwd) const override { return true;}
190     Function get_forward(casadi_int nfwd, const std::string& name,
191                          const std::vector<std::string>& inames,
192                          const std::vector<std::string>& onames,
193                          const Dict& opts) const override;
194     ///@}
195 
196     ///@{
197     /** \brief Generate a function that calculates reverse mode derivatives */
has_reverse(casadi_int nadj) const198     bool has_reverse(casadi_int nadj) const override { return true;}
199     Function get_reverse(casadi_int nadj, const std::string& name,
200                          const std::vector<std::string>& inames,
201                          const std::vector<std::string>& onames,
202                          const Dict& opts) const override;
203     ///@}
204 
205     // Call the callback function
206     int callback(NlpsolMemory* m) const;
207 
208     // Get KKT function
209     Function kkt() const;
210 
211     // Make sure primal-dual solution is consistent with bounds
212     static void bound_consistency(casadi_int n, double* z, double* lam,
213                                   const double* lbz, const double* ubz);
214 
215     // Creator function for internal class
216     typedef Nlpsol* (*Creator)(const std::string& name, const Function& oracle);
217 
218     // No static functions exposed
219     struct Exposed{ };
220 
221     /// Collection of solvers
222     static std::map<std::string, Plugin> solvers_;
223 
224     /// Infix
225     static const std::string infix_;
226 
227     /// Short name
shortname()228     static std::string shortname() { return "nlpsol";}
229 
230     /** \brief Get type name */
class_name() const231     std::string class_name() const override {return "Nlpsol";}
232 
233     /** \brief Check if the function is of a particular type */
234     bool is_a(const std::string& type, bool recursive) const override;
235 
236     // Get reduced Hessian
237     virtual DM getReducedHessian();
238 
239     /// Read options from parameter xml
240     virtual void setOptionsFromFile(const std::string & file);
241 
242     /// WORKAROUND: Add an element to an std::vector stored in a GenericType:
append_to_vec(GenericType & t,Type el)243     template<typename Type> static void append_to_vec(GenericType& t, Type el) {
244       std::vector<Type> v = t;
245       v.push_back(el);
246       t = v;
247     }
248 
249     /// Convert dictionary to Problem
250     template<typename XType>
251       static Function create_oracle(const std::map<std::string, XType>& d,
252                                     const Dict& opts);
253 
254   protected:
255     /** \brief Deserializing constructor */
256     explicit Nlpsol(DeserializingStream& s);
257   private:
258     void set_nlpsol_prob();
259   };
260 
261 } // namespace casadi
262 /// \endcond
263 #endif // CASADI_NLPSOL_IMPL_HPP
264