alpaqa 1.0.0a10
Nonconvex constrained optimization
Loading...
Searching...
No Matches
CasADiControlProblem.hpp
Go to the documentation of this file.
1#pragma once
2
8#include <filesystem>
9
10namespace alpaqa {
11
12namespace casadi_loader {
13template <Config>
15} // namespace casadi_loader
16
17template <Config Conf>
19 public:
26 mutable vec work;
27
28 /// Components of the constraint function with indices below this number are
29 /// handled using a quadratic penalty method rather than using an
30 /// augmented Lagrangian method. Specifically, the Lagrange multipliers for
31 /// these components (which determine the shifts in ALM) are kept at zero.
33 /// Same as @ref penalty_alm_split, but for the terminal constraint.
35
36 CasADiControlProblem(const std::string &so_name, length_t N);
38
43
44 /// Load the numerical problem data (bounds and parameters) from a CSV file.
45 /// The file should contain 8 rows, with the following contents:
46 /// 1. @ref U lower bound [nu]
47 /// 2. @ref U upper bound [nu]
48 /// 3. @ref D lower bound [nc]
49 /// 4. @ref D upper bound [nc]
50 /// 5. @ref D_N lower bound [nc_N]
51 /// 6. @ref D_N upper bound [nc_N]
52 /// 7. @ref x_init [nx]
53 /// 8. @ref param [p]
54 ///
55 /// Line endings are encoded using a single line feed (`\n`), and the column
56 /// separator can be specified using the @p sep argument.
57 void load_numerical_data(const std::filesystem::path &filepath,
58 char sep = ',');
59
60 void get_U(Box &U) const { U = this->U; }
61 void get_D(Box &D) const { D = this->D; }
62 void get_D_N(Box &D_N) const { D_N = this->D_N; }
63 void get_x_init(rvec x_init) const { x_init = this->x_init; }
64
65 void eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const;
66 void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const;
67 void eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p,
68 rvec grad_fxu_p) const;
69 void eval_h(index_t timestep, crvec x, crvec u, rvec h) const;
70 void eval_h_N(crvec x, rvec h) const;
71 [[nodiscard]] real_t eval_l(index_t timestep, crvec h) const;
72 [[nodiscard]] real_t eval_l_N(crvec h) const;
73 void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const;
74 void eval_q_N(crvec x, crvec h, rvec q) const;
75 void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const;
76 void eval_add_Q_N(crvec x, crvec h, rmat Q) const;
77 void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask,
78 rmat R, rvec work) const;
79 void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask,
80 rmat S, rvec work) const;
81 void eval_add_R_prod_masked(index_t timestep, crvec xu, crvec h,
82 crindexvec mask_J, crindexvec mask_K, crvec v,
83 rvec out, rvec work) const;
84 void eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h,
85 crindexvec mask_K, crvec v, rvec out,
86 rvec work) const;
87 [[nodiscard]] length_t get_R_work_size() const;
88 [[nodiscard]] length_t get_S_work_size() const;
89 void eval_constr(index_t timestep, crvec x, rvec c) const;
90 void eval_grad_constr_prod(index_t timestep, crvec x, crvec p,
91 rvec grad_cx_p) const;
92 void eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M,
93 rmat out) const;
94 void eval_constr_N(crvec x, rvec c) const;
95 void eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const;
96 void eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const;
97
98 void check() const {
99 util::check_dim_msg<config_t>(U.lowerbound, nu,
100 "Length of problem.U.lowerbound does not "
101 "match problem size problem.nu");
102 util::check_dim_msg<config_t>(U.upperbound, nu,
103 "Length of problem.U.upperbound does not "
104 "match problem size problem.nu");
105 util::check_dim_msg<config_t>(D.lowerbound, nc,
106 "Length of problem.D.lowerbound does not "
107 "match problem size problem.nc");
108 util::check_dim_msg<config_t>(D.upperbound, nc,
109 "Length of problem.D.upperbound does not "
110 "match problem size problem.nc");
111 util::check_dim_msg<config_t>(D_N.lowerbound, nc_N,
112 "Length of problem.D_N.lowerbound does "
113 "not match problem size problem.nc_N");
114 util::check_dim_msg<config_t>(D_N.upperbound, nc_N,
115 "Length of problem.D_N.upperbound does "
116 "not match problem size problem.nc_N");
117 if (penalty_alm_split < 0 || penalty_alm_split > nc)
118 throw std::invalid_argument("Invalid penalty_alm_split");
119 if (penalty_alm_split_N < 0 || penalty_alm_split > nc_N)
120 throw std::invalid_argument("Invalid penalty_alm_split_N");
121 }
122
123 [[nodiscard]] length_t get_N() const { return N; }
124 [[nodiscard]] length_t get_nx() const { return nx; }
125 [[nodiscard]] length_t get_nu() const { return nu; }
126 [[nodiscard]] length_t get_nh() const { return nh; }
127 [[nodiscard]] length_t get_nh_N() const { return nh_N; }
128 [[nodiscard]] length_t get_nc() const { return nc; }
129 [[nodiscard]] length_t get_nc_N() const { return nc_N; }
130
131 /// @see @ref TypeErasedControlProblem::eval_proj_diff_g
132 void eval_proj_diff_g(crvec z, rvec e) const {
133 for (index_t t = 0; t < N; ++t)
134 e.segment(t * nc, nc) =
135 projecting_difference(z.segment(t * nc, nc), D);
136 e.segment(N * nc, nc_N) =
137 projecting_difference(z.segment(N * nc, nc_N), D_N);
138 }
139 /// @see @ref TypeErasedControlProblem::eval_proj_multipliers
141 // If there's no lower bound, the multipliers can only be positive
142 auto max_lb = [M](real_t y, real_t z_lb) {
143 real_t y_lb = z_lb == -alpaqa::inf<config_t> ? 0 : -M;
144 return std::max(y, y_lb);
145 };
146 // If there's no upper bound, the multipliers can only be negative
147 auto min_ub = [M](real_t y, real_t z_ub) {
148 real_t y_ub = z_ub == alpaqa::inf<config_t> ? 0 : M;
149 return std::min(y, y_ub);
150 };
151 for (index_t t = 0; t < N; ++t) {
152 auto num_alm = nc - penalty_alm_split;
153 auto &&yt = y.segment(t * nc, nc);
154 auto &&y_qpm = yt.topRows(penalty_alm_split);
155 auto &&y_alm = yt.bottomRows(num_alm);
156 auto &&z_alm_lb = D.lowerbound.bottomRows(num_alm);
157 auto &&z_alm_ub = D.upperbound.bottomRows(num_alm);
158 y_qpm.setZero();
159 y_alm =
160 y_alm.binaryExpr(z_alm_lb, max_lb).binaryExpr(z_alm_ub, min_ub);
161 }
162 {
163 auto &&yt = y.segment(N * nc, nc_N);
164 auto num_alm = nc_N - penalty_alm_split_N;
165 auto &&y_qpm = yt.topRows(penalty_alm_split_N);
166 auto &&y_alm = yt.bottomRows(num_alm);
167 auto &&z_alm_lb = D.lowerbound.bottomRows(num_alm);
168 auto &&z_alm_ub = D.upperbound.bottomRows(num_alm);
169 y_qpm.setZero();
170 y_alm =
171 y_alm.binaryExpr(z_alm_lb, max_lb).binaryExpr(z_alm_ub, min_ub);
172 }
173 }
174
175 private:
178};
179
182
183} // namespace alpaqa
#define CASADI_OCP_LOADER_EXPORT_EXTERN_TEMPLATE(strcls, name,...)
void eval_jac_f(index_t timestep, crvec x, crvec u, rmat J_fxu) const
CasADiControlProblem(const CasADiControlProblem &)
void eval_add_R_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_J, crindexvec mask_K, crvec v, rvec out, rvec work) const
CasADiControlProblem & operator=(const CasADiControlProblem &)
void eval_add_gn_hess_constr_N(crvec x, crvec M, rmat out) const
void eval_qr(index_t timestep, crvec xu, crvec h, rvec qr) const
index_t penalty_alm_split_N
Same as penalty_alm_split, but for the terminal constraint.
void eval_add_S_prod_masked(index_t timestep, crvec xu, crvec h, crindexvec mask_K, crvec v, rvec out, rvec work) const
void eval_constr_N(crvec x, rvec c) const
void load_numerical_data(const std::filesystem::path &filepath, char sep=',')
Load the numerical problem data (bounds and parameters) from a CSV file.
void eval_grad_constr_prod_N(crvec x, crvec p, rvec grad_cx_p) const
void eval_add_R_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat R, rvec work) const
real_t eval_l(index_t timestep, crvec h) const
void eval_grad_f_prod(index_t timestep, crvec x, crvec u, crvec p, rvec grad_fxu_p) const
index_t penalty_alm_split
Components of the constraint function with indices below this number are handled using a quadratic pe...
void eval_add_gn_hess_constr(index_t timestep, crvec x, crvec M, rmat out) const
void eval_constr(index_t timestep, crvec x, rvec c) const
void eval_h(index_t timestep, crvec x, crvec u, rvec h) const
util::copyable_unique_ptr< Functions > impl
void eval_add_S_masked(index_t timestep, crvec xu, crvec h, crindexvec mask, rmat S, rvec work) const
void get_x_init(rvec x_init) const
void eval_proj_multipliers(rvec y, real_t M) const
void eval_q_N(crvec x, crvec h, rvec q) const
void eval_add_Q_N(crvec x, crvec h, rmat Q) const
void eval_grad_constr_prod(index_t timestep, crvec x, crvec p, rvec grad_cx_p) const
void eval_add_Q(index_t timestep, crvec xu, crvec h, rmat Q) const
void eval_proj_diff_g(crvec z, rvec e) const
void eval_f(index_t timestep, crvec x, crvec u, rvec fxu) const
void eval_h_N(crvec x, rvec h) const
CasADiControlProblem(CasADiControlProblem &&) noexcept
#define USING_ALPAQA_CONFIG(Conf)
Definition: config.hpp:54
typename Conf::rmat rmat
Definition: config.hpp:72
typename Conf::real_t real_t
Definition: config.hpp:63
typename Conf::index_t index_t
Definition: config.hpp:75
typename Conf::length_t length_t
Definition: config.hpp:74
typename Conf::rvec rvec
Definition: config.hpp:67
typename Conf::crvec crvec
Definition: config.hpp:68
typename Conf::vec vec
Definition: config.hpp:64
typename Conf::crindexvec crindexvec
Definition: config.hpp:78
Double-precision double configuration.
Definition: config.hpp:127
vec upperbound
Definition: box.hpp:28
vec lowerbound
Definition: box.hpp:27