cyqlone develop
Fast, parallel and vectorized solver for linear systems with optimal control structure.
Loading...
Searching...
No Matches
ocp.cpp
Go to the documentation of this file.
1#include <cyqlone/ocp.hpp>
2#include <cyqlone/reduce.hpp>
3#include <guanaqo/blas/hl-blas-interface.hpp>
4
5#include <limits>
6#include <numeric>
7
8namespace cyqlone {
9
11 using std::clamp;
12 const auto [N, nx, nu, ny, ny_N] = dim;
13 std::vector<real_t> dual_residual_sto(sol.solution.size());
14 auto dual_residual = guanaqo::MatrixView<real_t, index_t>::as_column(dual_residual_sto);
16 y = guanaqo::MatrixView<const real_t, index_t>::as_column(sol.inequality_multipliers),
17 λ = guanaqo::MatrixView<const real_t, index_t>::as_column(sol.equality_multipliers);
18
19 // Stationarity
20 dual_residual = qr();
21 for (index_t j = 0; j < N; ++j) {
22 auto xuj = x.middle_rows(j * (nx + nu), nx + nu), λj = λ.middle_rows(j * nx, nx),
23 λj_next = λ.middle_rows((j + 1) * nx, nx), yj = y.middle_rows(j * ny, ny);
24 auto rj = dual_residual.middle_rows(j * (nx + nu), nx + nu);
25 guanaqo::blas::xsymv_L(real_t{1}, H(j), xuj, real_t{1}, rj);
26 guanaqo::blas::xgemv_T(real_t{1}, AB(j), λj_next, real_t{1}, rj);
27 if (ny > 0)
28 guanaqo::blas::xgemv_T(real_t{1}, CD(j), yj, real_t{1}, rj);
29 for (index_t i = 0; i < nx; ++i)
30 rj(i, 0) -= λj(i, 0);
31 }
32 auto xN = x.bottom_rows(nx), λN = λ.bottom_rows(nx), yN = y.bottom_rows(ny_N);
33 auto rN = dual_residual.bottom_rows(nx);
34 guanaqo::blas::xsymv_L(real_t{1}, Q(N), xN, real_t{1}, rN);
35 if (ny_N > 0)
36 guanaqo::blas::xgemv_T(real_t{1}, C(N), yN, real_t{1}, rN);
37 for (index_t i = 0; i < nx; ++i)
38 rN(i, 0) -= λN(i, 0);
39 const auto norms = cyqlone::norms<real_t>{};
40 auto stat_norm = std::accumulate(dual_residual.data, dual_residual.data + dual_residual.rows,
41 norms.zero(), norms);
42
43 // Inequality constraints
44 auto ineq_res_sto = std::vector<real_t>(sol.inequality_multipliers.size());
45 auto ineq_res = guanaqo::MatrixView<real_t, index_t>::as_column(ineq_res_sto);
46 auto compl_norm = norms.zero();
47 using std::fmax;
48 using std::fmin;
49 const auto eps = std::numeric_limits<real_t>::epsilon(), big = 1 / (eps * eps);
50 for (index_t j = 0; j < N; ++j) {
51 auto xuj = x.middle_rows(j * (nx + nu), nx + nu), yj = y.middle_rows(j * ny, ny);
52 auto lbj = b_min(j), ubj = b_max(j);
53 auto cj = ineq_res.middle_rows(j * ny, ny);
54 if (ny > 0)
55 guanaqo::blas::xgemv_N(real_t{1}, CD(j), xuj, real_t{-1}, cj);
56 for (index_t i = 0; i < ny; ++i) {
57 compl_norm =
58 norms(compl_norm, yj(i, 0) > 0 ? yj(i, 0) * (cj(i, 0) - fmin(ubj(i, 0), +big))
59 : yj(i, 0) * (cj(i, 0) - fmax(lbj(i, 0), -big)));
60 cj(i, 0) -= clamp(cj(i, 0), lbj(i, 0), ubj(i, 0));
61 }
62 }
63 auto cN = ineq_res.bottom_rows(ny_N);
64 if (ny_N > 0)
65 guanaqo::blas::xgemv_N(real_t{1}, C(N), xN, real_t{-1}, cN);
66 auto lbN = b_min().bottom_rows(ny_N), ubN = b_max().bottom_rows(ny_N);
67 for (index_t i = 0; i < ny_N; ++i) {
68 compl_norm =
69 norms(compl_norm, yN(i, 0) > 0 ? yN(i, 0) * (cN(i, 0) - fmin(ubN(i, 0), +big))
70 : yN(i, 0) * (cN(i, 0) - fmax(lbN(i, 0), -big)));
71 cN(i, 0) -= clamp(cN(i, 0), lbN(i, 0), ubN(i, 0));
72 }
73 auto ineq_norm =
74 std::accumulate(ineq_res.data, ineq_res.data + ineq_res.rows, norms.zero(), norms);
75 // Complementarity: lb - Cx <= 0 and Cx - ub <= 0
76
77 // Equality constraints
78 auto eq_res_sto = std::vector<real_t>(sol.equality_multipliers.size());
80 eq_res = b();
81 for (index_t j = 0; j <= N; ++j) {
82 auto xj = x.middle_rows(j * (nx + nu), nx);
83 auto cj = eq_res.middle_rows(j * nx, nx);
84 for (index_t i = 0; i < nx; ++i)
85 cj(i, 0) -= xj(i, 0);
86 if (j > 0) {
87 auto xu_prev = x.middle_rows((j - 1) * (nx + nu), nx + nu);
88 guanaqo::blas::xgemv_N(real_t{1}, AB(j - 1), xu_prev, real_t{1}, cj);
89 }
90 }
91 auto eq_norm = std::accumulate(eq_res.data, eq_res.data + eq_res.rows, norms.zero(), norms);
92
93 return {
94 .stationarity = stat_norm.norm_inf(),
95 .inequality_residual = ineq_norm.norm_inf(),
96 .equality_residual = eq_norm.norm_inf(),
97 .complementarity = compl_norm.norm_inf(),
98 };
99}
100
101} // namespace cyqlone
void xsymv_L(T alpha, MatrixView< const T, I, UnitStride< I >, O > A, std::type_identity_t< MatrixView< const T, I > > x, T beta, MatrixView< T, I > y)
void xgemv_N(T alpha, std::type_identity_t< MatrixView< const T, I > > A, std::type_identity_t< MatrixView< const T, I > > x, T beta, MatrixView< T, I > y)
void xgemv_T(T alpha, std::type_identity_t< MatrixView< const T, I > > A, std::type_identity_t< MatrixView< const T, I > > x, T beta, MatrixView< T, I > y)
void clamp(Vx &&x, Vlo &&lo, Vhi &&hi, Vz &&z)
Elementwise clamping z = max(lo, min(x, hi)).
Definition linalg.hpp:325
Data structure for optimal control problems.
Vector reductions.
guanaqo::MatrixView< real_t, index_t > CD(index_t i)
Definition ocp.hpp:95
guanaqo::MatrixView< real_t, index_t > b_min()
Definition ocp.hpp:267
KKTError compute_kkt_error(const Solution &sol) const
Definition ocp.cpp:10
guanaqo::MatrixView< real_t, index_t > b()
Definition ocp.hpp:251
guanaqo::MatrixView< real_t, index_t > H(index_t i)
Definition ocp.hpp:64
guanaqo::MatrixView< real_t, index_t > C(index_t i)
Definition ocp.hpp:106
guanaqo::MatrixView< real_t, index_t > Q(index_t i)
Definition ocp.hpp:75
guanaqo::MatrixView< real_t, index_t > b_max()
Definition ocp.hpp:283
guanaqo::MatrixView< real_t, index_t > AB(index_t i)
Definition ocp.hpp:116
guanaqo::MatrixView< real_t, index_t > qr()
Definition ocp.hpp:225
Utilities for computing vector norms.
Definition reduce.hpp:26
static MatrixView as_column(std::span< T > v)