cyqlone develop
Fast, parallel and vectorized solver for linear systems with optimal control structure.
Loading...
Searching...
No Matches
ineq-constr.tpp
Go to the documentation of this file.
1#pragma once
2
3#include <cyqlone/linalg.hpp>
5
6namespace CYQLONE_NS(cyqlone::qpalm) {
7
8template <index_t VL, StorageOrder DefaultOrder>
10 const ineq_constr_vec_t &e,
11 const ineq_constr_vec_t &e_old,
13 GUANAQO_TRACE("update_penalty_y", 0);
15 const real_t min_denom = 1e-6;
16 const real_t norm_inf_e = fmax(min_denom, norm_inf(ctx, e));
17 index_t num_changed = 0;
18 const auto update_simd = [&](auto Σji, auto eji, auto eji_old) {
19 auto insufficient_progress = abs(eji) >= settings.θ * abs(eji_old);
20#if BATMAT_WITH_GSI_HPC_SIMD
21 simd update_factor =
22 select(insufficient_progress, settings.Δy * abs(eji) / norm_inf_e, simd{1});
23#else
24 simd update_factor{1};
25 where(insufficient_progress, update_factor) = settings.Δy * abs(eji) / norm_inf_e;
26#endif
27 update_factor *= settings.Δy_always;
28 auto Σ_new = Σji * update_factor;
29 Σ_new = fmax(Σji * settings.Δy_always, fmin(Σ_new, simd{settings.max_penalty_y}));
30#if BATMAT_WITH_GSI_HPC_SIMD
31 num_changed += reduce_count(Σ_new != Σji);
32#else
33 num_changed += popcount(Σ_new != Σji);
34#endif
35 return Σ_new;
36 };
37 const auto update_batch = [&](auto, auto, auto Σj, auto ej, auto ej_old) {
38 linalg::transform_elementwise(update_simd, Σj, Σj, ej, ej_old);
39 };
40 ocp.foreach_stage(ctx, update_batch, Σ, e, e_old);
41 return ctx.reduce(num_changed);
42}
43
44template <index_t VL, StorageOrder DefaultOrder>
46 ineq_constr_vec_t &e) const {
47 GUANAQO_TRACE("ineq_constr_resid", 0);
49 const auto ineq_constr_resid = [](auto, auto, auto Axj, auto b_minj, auto b_maxj, auto ej) {
50 linalg::clamp_resid(Axj, b_minj, b_maxj, ej);
51 };
52 ocp.foreach_stage(ctx, ineq_constr_resid, Ax, b_min_strided, b_max_strided, e);
53}
54
55template <index_t VL, StorageOrder DefaultOrder>
57 ineq_constr_vec_t &y) const {
58 GUANAQO_TRACE("project_multipliers_ineq", 0);
59 const auto proj_simd = [](auto yji, auto b_minji, auto b_maxji) {
60#if BATMAT_WITH_GSI_HPC_SIMD
61 yji = select(isfinite(b_minji), yji, fmax(yji, simd{0}));
62 yji = select(isfinite(b_maxji), yji, fmin(yji, simd{0}));
63#else
64 where(!isfinite(b_minji), yji) = fmax(yji, simd{0});
65 where(!isfinite(b_maxji), yji) = fmin(yji, simd{0});
66#endif
67 return yji;
68 };
69 const auto proj_batch = [&](auto, auto, auto yji, auto b_minji, auto b_maxji) {
70 linalg::transform_elementwise(proj_simd, yji, yji, b_minji, b_maxji);
71 };
72 ocp.foreach_stage(ctx, proj_batch, y, b_min_strided, b_max_strided);
73}
74
75template <index_t VL, StorageOrder DefaultOrder>
77 const ineq_constr_vec_t &Ax) const {
78 GUANAQO_TRACE("ineq_constr_viol", 0);
80 auto nrm_simd = norms.zero_simd();
81 const auto viol_simd = [&](auto Axji, auto b_minji, auto b_maxji) {
82 auto zi = fmax(b_minji, fmin(Axji, b_maxji));
83 nrm_simd = norms(nrm_simd, Axji - zi);
84 };
85 const auto viol_batch = [&](auto, auto, auto Axj, auto b_min_j, auto b_max_j) {
86 linalg::for_each_elementwise(viol_simd, Axj, b_min_j, b_max_j);
87 };
88 ocp.foreach_stage(ctx, viol_batch, Ax, b_min_strided, b_max_strided);
89 return ctx.reduce(norms(nrm_simd), norms).norm_inf();
90}
91
92template <index_t VL, StorageOrder DefaultOrder>
94 const ineq_constr_vec_t &y,
95 const ineq_constr_vec_t &ŷ,
96 const ineq_constr_vec_t &Σ,
98 GUANAQO_TRACE("ineq_constr_resid_al", 0);
100 auto nrm_simd = norms.zero_simd();
101 const auto resid_simd = [&](auto yji, auto ŷji, auto Σji) {
102 auto ei = (ŷji - yji) / Σji;
103 nrm_simd = norms(nrm_simd, ei);
104 return ei;
105 };
106 const auto resid_batch = [&](auto, auto, auto ej, auto yj, auto ŷj, auto Σj) {
107 linalg::transform_elementwise(resid_simd, ej, yj, ŷj, Σj);
108 };
109 ocp.foreach_stage(ctx, resid_batch, e, y, ŷ, Σ);
110 return ctx.reduce(norms(nrm_simd), norms).norm_inf();
111}
112
113template <index_t VL, StorageOrder DefaultOrder>
115 const ineq_constr_vec_t &Σ,
116 const ineq_constr_vec_t &y,
117 ineq_constr_vec_t &ŷ, var_vec_t &Aᵀŷ,
118 active_set_t &J) {
119 index_t count_J = 0;
120 const auto ŷ_simd = [&count_J](auto Σi, auto yi, auto Axi, auto li, auto ui) {
121 auto ζ = Axi + yi / Σi, z = fmax(li, fmin(ζ, ui));
122 auto Ji = z != ζ; // TODO: inclusive?
123#if 0
124 simd ŷi{0};
125 where(Ji, ŷi) = yi + Σi * (Axi - z);
126#else
127 auto ŷi = yi + Σi * (Axi - z);
128#endif
129#if BATMAT_WITH_GSI_HPC_SIMD
130 simd ΣJi = select(Ji, Σi, simd{0});
131 count_J += static_cast<index_t>(reduce_count(Ji));
132#else
133 simd ΣJi{};
134 where(Ji, ΣJi) = Σi;
135 count_J += static_cast<index_t>(popcount(Ji));
136#endif
137 return std::make_pair(ŷi, ΣJi);
138 };
139 const auto ŷ_batch = [&ŷ_simd]([[maybe_unused]] auto j, auto, auto ŷi, auto Ji, auto Σi,
140 auto yi, auto Axi, auto li, auto ui) {
141 GUANAQO_TRACE("calc_ŷ_Aᵀŷ", j);
142 linalg::transform2_elementwise(ŷ_simd, ŷi, Ji, //
143 Σi, yi, Axi, li, ui);
144 };
145 {
147 ocp.foreach_stage(ctx, ŷ_batch, ŷ, J, Σ, y, Ax, b_min_strided, b_max_strided);
148 }
150 mat_vec_AT(ctx, ŷ, Aᵀŷ);
151 return ctx.reduce(count_J);
152}
153
154} // namespace CYQLONE_NS(cyqlone::qpalm)
#define CYQLONE_NS(ns)
Definition config.hpp:10
void for_each_elementwise(F &&fun, VA &&A, VAs &&...As)
Apply a function to all elements of the given matrices or vectors.
Definition linalg.hpp:433
void transform_elementwise(F &&fun, VA &&A, VAs &&...As)
Apply a function to all elements of the given matrices or vectors, storing the result in the first ar...
Definition linalg.hpp:443
void clamp_resid(Vx &&x, Vlo &&lo, Vhi &&hi, Vz &&z)
Elementwise clamping residual z = x - max(lo, min(x, hi)).
Definition linalg.hpp:333
void transform2_elementwise(F &&fun, VA &&A, VB &&B, VAs &&...As)
Apply a function to all elements of the given matrices or vectors, storing the results in the first t...
Definition linalg.hpp:453
#define GUANAQO_TRACE(name, instance,...)
real_t ineq_constr_viol(Context &ctx, const ineq_constr_vec_t &Ax) const
index_t calc_ŷ_Aᵀŷ(Context &ctx, const ineq_constr_vec_t &Ax, const ineq_constr_vec_t &Σ, const ineq_constr_vec_t &y, ineq_constr_vec_t &ŷ, var_vec_t &Aᵀŷ, active_set_t &J)
real_t norm_inf(Context &ctx, const T &x) const
Infinity or max norm of x.
Definition linalg.tpp:88
auto get_timed(Timings::type Timings::*member) const
void project_multipliers_ineq(Context &ctx, ineq_constr_vec_t &y) const
index_t update_penalty_y(Context &ctx, ineq_constr_vec_t &Σ, const ineq_constr_vec_t &e, const ineq_constr_vec_t &e_old, const PenaltySettings &settings)
Increase the penalty parameters Σ for which the violation e has not decreased sufficiently compared t...
real_t ineq_constr_resid_al(Context &ctx, const ineq_constr_vec_t &y, const ineq_constr_vec_t &ŷ, const ineq_constr_vec_t &Σ, ineq_constr_vec_t &e)
void ineq_constr_resid(Context &ctx, const ineq_constr_vec_t &Ax, ineq_constr_vec_t &e) const
void mat_vec_AT(Context &ctx, const ineq_constr_vec_t &y, var_vec_t &Aᵀy)