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_SCPGEN_HPP
27 #define CASADI_SCPGEN_HPP
28 
29 #include "casadi/core/nlpsol_impl.hpp"
30 #include <casadi/solvers/casadi_nlpsol_scpgen_export.h>
31 
32 /** \defgroup plugin_Nlpsol_scpgen
33    A structure-exploiting sequential quadratic programming
34      (to be come sequential convex programming) method for nonlinear programming.
35 */
36 
37 /** \pluginsection{Nlpsol,scpgen} */
38 
39 /// \cond INTERNAL
40 
41 namespace casadi {
42 
43   struct CASADI_NLPSOL_SCPGEN_EXPORT ScpgenMemory : public NlpsolMemory {
44     // Work vectors, nonlifted problem
45     double *dxk, *dlam, *gfk, *gL, *b_gn;
46     // Memory for lifted variables
47     struct VarMem {
48       casadi_int n;
49       double *dx, *x0, *x, *lam, *dlam;
50       double *res, *resL;
51     };
52     std::vector<VarMem> lifted_mem;
53     // Penalty parameter of merit function
54     double sigma;
55     // 1-norm of last primal step
56     double pr_step;
57     // 1-norm of last dual step
58     double du_step;
59     // Regularization
60     double reg;
61     // Message applying to a particular iteration
62     const char* iteration_note;
63     // QP
64     double *qpH, *qpA, *qpB, *qpL, *qpG, *qpH_times_du;
65     // QP solver
66     double *lbdz, *ubdz;
67     // Linesearch parameters
68     double* merit_mem;
69     casadi_int merit_ind;
70     // Timers
71     double t_eval_mat, t_eval_res, t_eval_vec, t_eval_exp, t_solve_qp, t_mainloop;
72     // Current iteration
73     casadi_int iter_count;
74   };
75 
76   /**  \brief \pluginbrief{Nlpsol,scpgen}
77 
78      @copydoc NLPSolver_doc
79      @copydoc plugin_Nlpsol_scpgen
80 
81      \author Joel Andersson, Attila Kozma and Joris Gillis
82      \date 2013
83   */
84   class CASADI_NLPSOL_SCPGEN_EXPORT Scpgen : public Nlpsol {
85   public:
86     explicit Scpgen(const std::string& name, const Function& nlp);
87     ~Scpgen() override;
88 
89     // Get name of the plugin
plugin_name() const90     const char* plugin_name() const override { return "scpgen";}
91 
92     // Name of the class
class_name() const93     std::string class_name() const override { return "Scpgen";}
94 
95     /** \brief  Create a new NLP Solver */
creator(const std::string & name,const Function & nlp)96     static Nlpsol* creator(const std::string& name, const Function& nlp) {
97       return new Scpgen(name, nlp);
98     }
99 
100     ///@{
101     /** \brief Options */
102     static const Options options_;
get_options() const103     const Options& get_options() const override { return options_;}
104     ///@}
105 
106     // Initialize the solver
107     void init(const Dict& opts) override;
108 
109     /** \brief Create memory block */
alloc_mem() const110     void* alloc_mem() const override { return new ScpgenMemory();}
111 
112     /** \brief Initalize memory block */
113     int init_mem(void* mem) const override;
114 
115     /** \brief Free memory block */
free_mem(void * mem) const116     void free_mem(void *mem) const override { delete static_cast<ScpgenMemory*>(mem);}
117 
118     /// Get all statistics
119     Dict get_stats(void* mem) const override;
120 
121     /** \brief Set the (persistent) work vectors */
122     void set_work(void* mem, const double**& arg, double**& res,
123                           casadi_int*& iw, double*& w) const override;
124 
125     // Solve the NLP
126     int solve(void* mem) const override;
127 
128     // Calculate the L1-norm of the primal infeasibility
129     double primalInfeasibility(ScpgenMemory* m) const;
130 
131     // Calculate the L1-norm of the dual infeasibility
132     double dualInfeasibility(ScpgenMemory* m) const;
133 
134     // Print iteration header
135     void printIteration(ScpgenMemory* m, std::ostream &stream) const;
136 
137     // Print iteration
138     void printIteration(ScpgenMemory* m, std::ostream &stream, casadi_int iter, double obj,
139                         double pr_inf, double du_inf,
140                         double rg, casadi_int ls_trials, bool ls_success) const;
141 
142     // Evaluate the matrices in the condensed QP
143     void eval_mat(ScpgenMemory* m) const;
144 
145     // Evaluate the vectors in the condensed QP
146     void eval_vec(ScpgenMemory* m) const;
147 
148     // Evaluate the residual function
149     void eval_res(ScpgenMemory* m) const;
150 
151     // Regularize the condensed QP
152     void regularize(ScpgenMemory* m) const;
153 
154     // Solve the QP to get the (full) step
155     void solve_qp(ScpgenMemory* m) const;
156 
157     // Perform the line-search to take the step
158     void line_search(ScpgenMemory* m, casadi_int& ls_iter, bool& ls_success) const;
159 
160     // Evaluate the step expansion
161     void eval_exp(ScpgenMemory* m) const;
162 
163     /// QP solver for the subproblems
164     Function qpsol_;
165 
166     /// use Gauss-Newton Hessian
167     bool gauss_newton_;
168 
169     /// maximum number of sqp iterations
170     casadi_int max_iter_;
171 
172     /// Memory size of L-BFGS method
173     casadi_int lbfgs_memory_;
174 
175     /// Tolerance on primal infeasibility
176     double tol_pr_;
177 
178     /// Tolerance on dual infeasibility
179     double tol_du_;
180 
181     /// Tolerance on regularization
182     double tol_reg_;
183 
184     /// stopping criterion for the stepsize
185     double tol_pr_step_;
186 
187     /// stopping criterion for the Lagrangian gradient
188     double tol_gl_;
189 
190     /// Linesearch parameters
191     ///@{
192     double c1_;
193     double beta_;
194     casadi_int max_iter_ls_;
195     casadi_int merit_memsize_;
196     double merit_start_;
197     ///@}
198 
199     /// Enable Code generation
200     bool codegen_;
201 
202     /// Access qpsol
getConic() const203     const Function getConic() const { return qpsol_;}
204 
205     /// Regularization
206     bool regularize_;
207 
208     // Number of gauss_newton equations
209     casadi_int ngn_;
210 
211     // Options
212     double reg_threshold_;
213 
214     /// Print timers
215     bool print_time_;
216 
217     /// Generate initial guess for lifted variables
218     Function vinit_fcn_;
219 
220     /// Residual function
221     Function res_fcn_;
222 
223     // Function to calculate the matrices in the reduced QP
224     Function mat_fcn_;
225     casadi_int mat_jac_, mat_hes_;
226 
227     /// Quadratic approximation
228     Function vec_fcn_;
229     casadi_int vec_gf_, vec_g_;
230 
231     /// Step expansion
232     Function exp_fcn_;
233 
234     // Residual function io indices
235     casadi_int res_x_, res_p_, res_g_lam_, res_p_lam_, res_p_d_;
236     casadi_int res_f_, res_gl_, res_g_;
237 
238     // Modifier function io indices
239     casadi_int mod_x_, mod_p_, mod_g_lam_;
240     casadi_int mod_f_, mod_gl_, mod_g_;
241     casadi_int mod_du_, mod_dlam_g_;
242 
243     struct Var {
244       casadi_int n;
245       MX v, v_def, v_lam, v_defL;
246       MX d, d_def, d_lam, d_defL;
247 
248       // Indices of function inputs and outputs
249       casadi_int res_var, res_lam, res_d, res_lam_d;
250       casadi_int mod_var, mod_lam, mod_def, mod_defL;
251       casadi_int exp_def, exp_defL;
252     };
253 
254     std::vector<Var> v_;
255 
256     // Names of the components
257     std::vector<std::string> name_x_;
258 
259     // Components to print
260     std::vector<casadi_int> print_x_;
261 
262     // QP sparsity
263     Sparsity spH_, spA_, spL_;
264 
265     // Print options
266     bool print_header_;
267 
268     /// A documentation string
269     static const std::string meta_doc;
270   };
271 
272 } // namespace casadi
273 
274 /// \endcond
275 
276 #endif // CASADI_SCPGEN_HPP
277