autogenu-jupyter
An automatic code generator and the continuation/GMRES (C/GMRES) based numerical solvers for nonlinear MPC
Loading...
Searching...
No Matches
single_shooting_cgmres_solver.hpp
Go to the documentation of this file.
1#ifndef CGMRES__SINGLE_SHOOTING_CGMRES_SOLVER_HPP_
2#define CGMRES__SINGLE_SHOOTING_CGMRES_SOLVER_HPP_
3
4#include <array>
5#include <stdexcept>
6#include <iostream>
7
8#include "cgmres/types.hpp"
10#include "cgmres/timer.hpp"
11
15
16namespace cgmres {
17
25template <class OCP, int N, int kmax>
27public:
31 static constexpr int nx = OCP::nx;
32
36 static constexpr int nu = OCP::nu;
37
41 static constexpr int nc = OCP::nc;
42
46 static constexpr int nuc = nu + nc;
47
51 static constexpr int nub = OCP::nub;
52
56 static constexpr int dim = nuc * N + 2 * N * nub;
57
61
68 SingleShootingCGMRESSolver(const OCP& ocp, const Horizon& horizon,
69 const SolverSettings& settings)
70 : continuation_gmres_(SingleShootingNLP_(ocp, horizon), settings.finite_difference_epsilon, settings.zeta),
71 gmres_(),
72 settings_(settings),
73 solution_(Vector<dim>::Zero()),
74 solution_update_(Vector<dim>::Zero()) {
75 std::fill(uopt_.begin(), uopt_.end(), Vector<nu>::Zero());
76 std::fill(ucopt_.begin(), ucopt_.end(), Vector<nuc>::Zero());
77 if constexpr (nub > 0) {
78 std::fill(dummyopt_.begin(), dummyopt_.end(), Vector<nub>::Zero());
79 std::fill(muopt_.begin(), muopt_.end(), Vector<nub>::Zero());
80 }
81
82 if (settings.finite_difference_epsilon <= 0.0) {
83 throw std::invalid_argument("[SingleShootingCGMRESSolver]: 'settings.finite_difference_epsilon' must be positive!");
84 }
85 if (settings.sampling_time <= 0.0) {
86 throw std::invalid_argument("[SingleShootingCGMRESSolver]: 'settings.sampling_time' must be positive!");
87 }
88 if (settings.zeta <= 0.0) {
89 throw std::invalid_argument("[SingleShootingCGMRESSolver]: 'settings.zeta' must be positive!");
90 }
91 }
92
97
102
107 template <typename VectorType>
109 if (u.size() != nu) {
110 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_u] u.size() must be " + std::to_string(nu));
111 }
112 for (size_t i=0; i<N; ++i) {
113 uopt_[i] = u;
114 }
115 for (size_t i=0; i<N; ++i) {
116 ucopt_[i].template head<nu>() = u;
117 }
118 setInnerSolution();
119 }
120
126 template <typename VectorType>
128 if (uc.size() != nuc) {
129 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_uc] uc.size() must be " + std::to_string(nuc));
130 }
131 for (size_t i=0; i<N; ++i) {
132 uopt_[i] = uc.template head<nu>();
133 }
134 for (size_t i=0; i<N; ++i) {
135 ucopt_[i] = uc;
136 }
137 setInnerSolution();
138 }
139
144 template <typename VectorType>
146 if (dummy.size() != nub) {
147 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_dummy] dummy.size() must be " + std::to_string(nub));
148 }
149 for (size_t i=0; i<N; ++i) {
150 dummyopt_[i] = dummy;
151 }
152 setInnerSolution();
153 }
154
159 template <typename VectorType>
161 if (mu.size() != nub) {
162 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_mu] mu.size() must be " + std::to_string(nub));
163 }
164 for (size_t i=0; i<N; ++i) {
165 muopt_[i] = mu;
166 }
167 setInnerSolution();
168 }
169
174 template <typename T>
175 void set_u_array(const T& u_array) {
176 if (u_array.size() != N) {
177 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_u_array]: 'u_array.size()' must be "+std::to_string(N));
178 }
179 for (size_t i=0; i<N; ++i) {
180 if (u_array[i].size() != nu) {
181 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_u_array] u_array[i].size() must be " + std::to_string(nu));
182 }
183 uopt_[i] = u_array[i];
184 ucopt_[i].template head<nu>() = u_array[i];
185 }
186 setInnerSolution();
187 }
188
194 template <typename T>
195 void set_uc_array(const T& uc_array) {
196 if (uc_array.size() != N) {
197 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_uc_array]: 'uc_array.size()' must be "+std::to_string(N));
198 }
199 for (size_t i=0; i<N; ++i) {
200 if (uc_array[i].size() != nuc) {
201 throw std::invalid_argument("[SingleShootingCGMRESSolver::uc_array] uc_array[i].size() must be " + std::to_string(nuc));
202 }
203 uopt_[i] = uc_array[i].template head<nu>();
204 ucopt_[i] = uc_array[i];
205 }
206 setInnerSolution();
207 }
208
214 template <typename T>
215 void set_dummy_array(const T& dummy_array) {
216 if (dummy_array.size() != N) {
217 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_dummy_array]: 'dummy_array.size()' must be "+std::to_string(N));
218 }
219 for (size_t i=0; i<N; ++i) {
220 if (dummy_array[i].size() != nub) {
221 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_dummy_array] dummy_array[i].size() must be " + std::to_string(nub));
222 }
223 dummyopt_[i] = dummy_array[i];
224 }
225 setInnerSolution();
226 }
227
233 template <typename T>
234 void set_mu_array(const T& mu_array) {
235 if (mu_array.size() != N) {
236 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_mu_array]: 'mu_array.size()' must be "+std::to_string(N));
237 }
238 for (size_t i=0; i<N; ++i) {
239 if (mu_array[i].size() != nub) {
240 throw std::invalid_argument("[SingleShootingCGMRESSolver::set_mu_array] mu_array[i].size() must be " + std::to_string(nub));
241 }
242 muopt_[i] = mu_array[i];
243 }
244 setInnerSolution();
245 }
246
251 continuation_gmres_.retrive_dummy(solution_, settings_.min_dummy);
252 continuation_gmres_.retrive_mu(solution_);
253 retriveSolution();
254 }
255
260 const std::array<Vector<nu>, N>& uopt() const { return uopt_; }
261
266 const std::array<Vector<nuc>, N>& ucopt() const { return ucopt_; }
267
272 const std::array<Vector<nx>, N+1>& xopt() const { return continuation_gmres_.x(); }
273
278 const std::array<Vector<nx>, N+1>& lmdopt() const { return continuation_gmres_.lmd(); }
279
284 const std::array<Vector<nub>, N>& dummyopt() const { return dummyopt_; }
285
290 const std::array<Vector<nub>, N>& muopt() const { return muopt_; }
291
296 Scalar optError() const { return continuation_gmres_.optError(); }
297
304 template <typename VectorType>
306 if (x.size() != nx) {
307 throw std::invalid_argument("[SingleShootingCGMRESSolver::optError] x.size() must be " + std::to_string(nx));
308 }
309 continuation_gmres_.synchronize_ocp();
310 continuation_gmres_.eval_fonc(t, x, solution_);
311 return optError();
312 }
313
319 template <typename VectorType>
320 void update(const Scalar t, const MatrixBase<VectorType>& x) {
321 if (x.size() != nx) {
322 throw std::invalid_argument("[SingleShootingCGMRESSolver::update] x.size() must be " + std::to_string(nx));
323 }
324 if (settings_.verbose_level >= 1) {
325 std::cout << "\n======================= update solution with C/GMRES =======================" << std::endl;
326 }
327
328 if (settings_.profile_solver) timer_.tick();
329 continuation_gmres_.synchronize_ocp();
330 const auto gmres_iter
331 = gmres_.template solve<const Scalar, const VectorType&, const Vector<dim>&>(
332 continuation_gmres_, t, x.derived(), solution_, solution_update_);
333 const auto opt_error = continuation_gmres_.optError();
334 solution_.noalias() += settings_.sampling_time * solution_update_;
335 retriveSolution();
336 if (settings_.profile_solver) timer_.tock();
337
338 // verbose
339 if (settings_.verbose_level >= 1) {
340 std::cout << "opt error: " << opt_error << std::endl;
341 }
342 if (settings_.verbose_level >= 2) {
343 std::cout << "number of GMRES iter: " << gmres_iter << " (kmax: " << kmax << ")" << std::endl;
344 }
345 }
346
352 return timer_.getProfile();
353 }
354
355 void disp(std::ostream& os) const {
356 os << "Single shooting CGMRES solver: " << std::endl;
357 os << " N: " << N << std::endl;
358 os << " kmax: " << kmax << std::endl;
359 os << continuation_gmres_.get_nlp().ocp() << std::endl;
360 os << continuation_gmres_.get_nlp().horizon() << std::endl;
361 os << settings_ << std::endl;
362 os << timer_.getProfile() << std::endl;
363 }
364
365 friend std::ostream& operator<<(std::ostream& os, const SingleShootingCGMRESSolver& solver) {
366 solver.disp(os);
367 return os;
368 }
369
370 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
371
372private:
373 ContinuationGMRES_ continuation_gmres_;
374 MatrixFreeGMRES_ gmres_;
375 SolverSettings settings_;
376 Timer timer_;
377
378 std::array<Vector<nu>, N> uopt_;
379 std::array<Vector<nuc>, N> ucopt_;
380 std::array<Vector<nub>, N> dummyopt_;
381 std::array<Vector<nub>, N> muopt_;
382
383 Vector<dim> solution_, solution_update_;
384
385 void setInnerSolution() {
386 for (size_t i=0; i<N; ++i) {
387 const int inucb2 = i * (nuc + 2 * nub);
388 solution_.template segment<nuc>(inucb2) = ucopt_[i];
389 if constexpr (nub > 0) {
390 solution_.template segment<nub>(inucb2+nuc) = dummyopt_[i];
391 solution_.template segment<nub>(inucb2+nuc+nub) = muopt_[i];
392 }
393 }
394 }
395
396 void retriveSolution() {
397 for (size_t i=0; i<N; ++i) {
398 const int inucb2 = i * (nuc + 2 * nub);
399 uopt_[i] = solution_.template segment<nu>(inucb2);
400 ucopt_[i] = solution_.template segment<nuc>(inucb2);
401 if constexpr (nub > 0) {
402 dummyopt_[i] = solution_.template segment<nub>(inucb2+nuc);
403 muopt_[i] = solution_.template segment<nub>(inucb2+nuc+nub);
404 }
405 }
406 }
407
408};
409
410} // namespace cgmres
411
412#endif // CGMRES__SINGLE_SHOOTING_CGMRES_SOLVER_HPP_
Horizon of MPC.
Definition: horizon.hpp:18
Single-shooting C/GMRES solver for nonlinear MPC.
Definition: single_shooting_cgmres_solver.hpp:26
const std::array< Vector< nub >, N > & dummyopt() const
Getter of the optimal solution.
Definition: single_shooting_cgmres_solver.hpp:284
const std::array< Vector< nu >, N > & uopt() const
Getter of the optimal solution.
Definition: single_shooting_cgmres_solver.hpp:260
static constexpr int nc
Dimension of the equality constraints.
Definition: single_shooting_cgmres_solver.hpp:41
static constexpr int nub
Dimension of the bound constraints on the control input.
Definition: single_shooting_cgmres_solver.hpp:51
static constexpr int dim
Dimension of the linear problem solved by the GMRES solver.
Definition: single_shooting_cgmres_solver.hpp:56
static constexpr int nx
Dimension of the state.
Definition: single_shooting_cgmres_solver.hpp:31
void set_u(const MatrixBase< VectorType > &u)
Sets the control input vector.
Definition: single_shooting_cgmres_solver.hpp:108
const std::array< Vector< nuc >, N > & ucopt() const
Getter of the optimal solution.
Definition: single_shooting_cgmres_solver.hpp:266
void set_u_array(const T &u_array)
Sets the array of control input vector.
Definition: single_shooting_cgmres_solver.hpp:175
const std::array< Vector< nx >, N+1 > & lmdopt() const
Getter of the optimal solution.
Definition: single_shooting_cgmres_solver.hpp:278
void set_dummy_array(const T &dummy_array)
Sets the array of the dummy input vector with respect to the control input bounds constraint.
Definition: single_shooting_cgmres_solver.hpp:215
void set_mu(const MatrixBase< VectorType > &mu)
Sets the Lagrange multiplier with respect to the control input bounds constraint.
Definition: single_shooting_cgmres_solver.hpp:160
detail::MatrixFreeGMRES< ContinuationGMRES_, kmax > MatrixFreeGMRES_
Definition: single_shooting_cgmres_solver.hpp:60
void init_dummy_mu()
Initializes the dummy input vectors and Lagrange multipliers with respect to the control input bounds...
Definition: single_shooting_cgmres_solver.hpp:250
Scalar optError() const
Gets the l2-norm of the current optimality errors.
Definition: single_shooting_cgmres_solver.hpp:296
void set_dummy(const MatrixBase< VectorType > &dummy)
Sets the dummy input vector with respect to the control input bounds constraint.
Definition: single_shooting_cgmres_solver.hpp:145
void update(const Scalar t, const MatrixBase< VectorType > &x)
Updates the solution by performing C/GMRES method.
Definition: single_shooting_cgmres_solver.hpp:320
~SingleShootingCGMRESSolver()=default
Default destructor.
TimingProfile getProfile() const
Get timing result as TimingProfile.
Definition: single_shooting_cgmres_solver.hpp:351
void set_mu_array(const T &mu_array)
Sets the array of the Lagrange multiplier with respect to the control input bounds constraint.
Definition: single_shooting_cgmres_solver.hpp:234
const std::array< Vector< nub >, N > & muopt() const
Getter of the optimal solution.
Definition: single_shooting_cgmres_solver.hpp:290
friend std::ostream & operator<<(std::ostream &os, const SingleShootingCGMRESSolver &solver)
Definition: single_shooting_cgmres_solver.hpp:365
void set_uc(const MatrixBase< VectorType > &uc)
Sets the control input vector and Lagrange multiplier with respect to the equality constraints.
Definition: single_shooting_cgmres_solver.hpp:127
void disp(std::ostream &os) const
Definition: single_shooting_cgmres_solver.hpp:355
const std::array< Vector< nx >, N+1 > & xopt() const
Getter of the optimal solution.
Definition: single_shooting_cgmres_solver.hpp:272
static constexpr int nuc
Dimension of the concatenation of the control input and equality constraints.
Definition: single_shooting_cgmres_solver.hpp:46
SingleShootingCGMRESSolver()=default
Default constructor.
Scalar optError(const Scalar t, const MatrixBase< VectorType > &x)
Computes and gets the l2-norm of the current optimality errors.
Definition: single_shooting_cgmres_solver.hpp:305
SingleShootingCGMRESSolver(const OCP &ocp, const Horizon &horizon, const SolverSettings &settings)
Constructs the single-shooting C/GMRES solver.
Definition: single_shooting_cgmres_solver.hpp:68
void set_uc_array(const T &uc_array)
Sets the array of control input vector and Lagrange multiplier with respect to the equality constrain...
Definition: single_shooting_cgmres_solver.hpp:195
static constexpr int nu
Dimension of the control input.
Definition: single_shooting_cgmres_solver.hpp:36
detail::ContinuationGMRES< SingleShootingNLP_ > ContinuationGMRES_
Definition: single_shooting_cgmres_solver.hpp:59
A timer for benchmarks.
Definition: timer.hpp:50
void tick()
Start timer (tick).
Definition: timer.hpp:71
TimingProfile getProfile() const
Get timing result as TimingProfile.
Definition: timer.hpp:90
void tock()
Stop the timer (tock).
Definition: timer.hpp:78
void retrive_mu(Vector< dim > &solution)
Definition: continuation_gmres.hpp:95
decltype(auto) x() const
Definition: continuation_gmres.hpp:100
void eval_fonc(const Scalar t, const MatrixBase< VectorType > &x, const Vector< dim > &solution)
Definition: continuation_gmres.hpp:50
void synchronize_ocp()
Definition: continuation_gmres.hpp:106
Scalar optError() const
Definition: continuation_gmres.hpp:45
const NLP & get_nlp() const
Definition: continuation_gmres.hpp:104
void retrive_dummy(Vector< dim > &solution, const Scalar min_dummy)
Definition: continuation_gmres.hpp:90
decltype(auto) lmd() const
Definition: continuation_gmres.hpp:102
Definition: single_shooting_nlp.hpp:16
const OCP & ocp() const
Definition: single_shooting_nlp.hpp:121
const Horizon & horizon() const
Definition: single_shooting_nlp.hpp:123
Definition: continuation_gmres.hpp:11
Eigen::Matrix< Scalar, size, 1 > Vector
Alias of Eigen::Vector.
Definition: types.hpp:23
double Scalar
Alias of double.
Definition: types.hpp:11
Eigen::MatrixBase< MatrixType > MatrixBase
Alias of Eigen::MatrixBase.
Definition: types.hpp:29
Settings of solvers.
Definition: solver_settings.hpp:14
Scalar min_dummy
The minimum value of the dummy inputs. Mainly used in MultipleShootingCGMRESSolver....
Definition: solver_settings.hpp:58
Scalar finite_difference_epsilon
Epsilon of the finite difference approximation. Must be positive. Default value is 1....
Definition: solver_settings.hpp:33
Scalar sampling_time
The sampling time of MPC and used in SingleShootingCGMRESSolver and MultipleShootingCGMRESSolver....
Definition: solver_settings.hpp:40
Scalar zeta
The stabilization parameter of the continuation method. Typical value is the reciprocal of SolverSett...
Definition: solver_settings.hpp:49
size_t verbose_level
Verbose level. 0: no printings. 1-2: print some things. Default is 0.
Definition: solver_settings.hpp:63
bool profile_solver
If true, a solver profile is taken.
Definition: solver_settings.hpp:68
A profile of the timing benchmark.
Definition: timer.hpp:16