8#include "akreon/linalg/constants.hpp"
39template <affine::AffineMapLike Map>
42 using Mat = affine::affine_mat_t<Map>;
43 using T = linalg::matrix_scalar_t<Mat>;
44 static constexpr std::size_t
M = linalg::mat_rows_v<Mat>;
45 static constexpr std::size_t
N = linalg::mat_cols_v<Mat>;
60 "Rotated2SOC requires RSOC coords with at least 3 entries "
63 const auto I = linalg::make_identity<
T,
M - 2>();
65 linalg::Matrix<T, M, M> A{};
67 A = linalg::set_block<0,
M - 2, 0,
M - 2>(A, I);
68 A(
M - 2,
M - 2) = linalg::inv_sqrt2_v<T>;
69 A(
M - 2,
M - 1) = -linalg::inv_sqrt2_v<T>;
70 A(
M - 1,
M - 2) = linalg::inv_sqrt2_v<T>;
71 A(
M - 1,
M - 1) = linalg::inv_sqrt2_v<T>;
73 affine::AffineMap<
decltype(A)> r2soc(A);
74 return r2soc.compose(map);
89template <linalg::VectorContainer Vec>
92 using T = linalg::vector_element_t<Vec>;
93 static constexpr std::size_t
N = linalg::vector_dim_v<Vec>;
105 constexpr auto operator()(
const Vec& x,
const Vec& y)
const {
106 const auto primal = std::get<0>(linalg::splice<N - 1>(x));
107 const auto t1 = x(
N - 1);
108 const auto dual = std::get<0>(linalg::splice<N - 1>(y));
109 const auto t2 = y(
N - 1);
111 const auto a = t2 * primal + t1 * dual;
112 const auto b = linalg::inner_product(primal, dual) + t1 * t2;
115 for (std::size_t i = 0; i <
N - 1; ++i) res(i) = a(i);
126template <linalg::VectorContainer Slack>
128 :
public Cone<Slack, SecondOrderCone<Slack>, ConeType::SYMMETRIC> {
165 for (std::size_t i = 0; i <
M - 1; ++i) res += x(i) * x(i);
166 res = linalg::constexpr_sqrt_safe(res);
167 return res < x(
M - 1);
219 const linalg::Vector<T, M>& p)
const {
220 constexpr T eta{0.99};
228 const auto var = std::get<0>(linalg::splice<M - 1>(x));
229 const auto t = x(
M - 1);
230 const auto dvar = std::get<0>(linalg::splice<M - 1>(p));
231 const auto dt = p(
M - 1);
233 const auto a = dt * dt - linalg::inner_product(dvar, dvar);
234 const auto b =
T(2) * (t * dt - linalg::inner_product(var, dvar));
235 const auto c = t * t - linalg::inner_product(var, var);
237 if (linalg::constexpr_abs(a) <=
eps) {
238 if (b <
T(0)) alpha = std::min(alpha, -c / b);
240 const T disc = b * b -
T(4) * a * c;
242 const T s = linalg::constexpr_sqrt_safe(disc);
243 const T inv2a =
T(1) / (
T(2) * a);
244 const T r1 = (-b - s) * inv2a;
245 const T r2 = (-b + s) * inv2a;
250 if (r1 >
T(0)) hit = std::min(hit, r1);
251 if (r2 >
T(0)) hit = std::min(hit, r2);
253 alpha = std::min(alpha, hit);
258 if (dt <
T(0)) alpha_t = std::min(alpha_t, -t / dt);
261 alpha = std::max(
T(0), std::min(
T(1), alpha));
263 return eta * std::min(alpha, alpha_t);
275 const linalg::Vector<T, M>& p)
const {
312 constexpr auto H_impl(
const Slack& x,
const Slack& y)
const {
313 const auto [
w, event] =
w_impl(x, y);
314 if (linalg::is_fatal_event(event))
317 const auto [w_inv, inv_event] =
inv_impl(
w);
318 if (linalg::is_fatal_event(inv_event))
322 const auto out_event = (
event != linalg::NumericalEvent::NONE ||
323 inv_event != linalg::NumericalEvent::NONE)
324 ? linalg::NumericalEvent::NUMERICAL_SAFEGUARD
325 : linalg::NumericalEvent::NONE;
340 const auto [x_inv, event] =
inv_impl(x);
341 return std::tuple(
T(-1) * x_inv, event);
394 constexpr auto w_impl(
const Slack& x,
const Slack& y)
const {
395 const auto x_sqrt =
sqrt(x);
396 linalg::QuadraticRep<HessianMat, SOCCirc<Slack>> P(x_sqrt);
398 const auto b = P.apply(y);
400 if (linalg::is_fatal_event(event))
return std::tuple(Slack{}, event);
402 return std::tuple(P.apply(inner), event);
415 constexpr auto circ_impl(
const Slack& x,
const Slack& y)
const {
442 const auto lambdas_x =
eigs(x);
443 const auto lambdas_y =
eigs(y);
445 const auto det_x = std::get<0>(lambdas_x) * std::get<1>(lambdas_x);
446 const auto det_y = std::get<0>(lambdas_y) * std::get<1>(lambdas_y);
450 return std::tuple(
nu_impl() * linalg::constexpr_ln_safe(tr_xy /
nu_impl()) -
451 linalg::constexpr_ln_safe(det_x) -
452 linalg::constexpr_ln_safe(det_y),
453 linalg::NumericalEvent::NONE);
467 const auto v = std::get<0>(linalg::splice<M - 1>(x));
468 const auto t = x(
M - 1);
470 for (std::size_t i = 0; i <
M - 1; ++i) adj_v(i) =
T(-1) * v(i);
473 const auto det = t * t - linalg::inner_product(v, v);
474 if (std::isnan(det) || linalg::constexpr_abs(det) <=
eps)
475 return std::tuple((
T(1) /
eps) * adj_v,
476 linalg::NumericalEvent::NUMERICAL_SAFEGUARD);
478 const auto res = (
T(1) / det) * adj_v;
479 return std::tuple(res, linalg::NumericalEvent::NONE);
484 return std::tuple(
sqrt(x), linalg::NumericalEvent::NONE);
499 constexpr auto sqrt(
const Slack& x)
const {
500 const auto v = std::get<0>(linalg::splice<M - 1>(x));
501 const auto v_norm = linalg::L2<decltype(v)>()(v);
503 const auto lambdas =
eigs(x);
504 const auto lam1 = std::get<0>(lambdas);
505 const auto lam2 = std::get<1>(lambdas);
507 const auto alpha =
T(0.5) * (linalg::constexpr_sqrt_safe(lam1) +
508 linalg::constexpr_sqrt_safe(lam2));
509 const auto beta =
T(0.5) * (linalg::constexpr_sqrt_safe(lam1) -
510 linalg::constexpr_sqrt_safe(lam2));
513 for (std::size_t i = 0; i <
M - 1; ++i) v_zero(i) = v(i);
515 auto x_sqrt = alpha *
e_impl();
516 if (v_norm >
eps) x_sqrt = x_sqrt + beta * (
T(1) / v_norm) * v_zero;
531 constexpr auto eigs(
const Slack& x)
const {
532 const auto v = std::get<0>(linalg::splice<M - 1>(x));
533 const auto t = x(
M - 1);
535 const auto v_norm = linalg::L2<decltype(v)>()(v);
536 const auto lam1 = t + v_norm;
537 const auto lam2 = t - v_norm;
539 return std::tuple(lam1, lam2);
static constexpr std::size_t M
helpers to get M slack size
linalg::Matrix< T, M, M > HessianMat
hessian type
linalg::vector_element_t< Slack > T
alias for mat type
constexpr auto w(const Slack &x, const Slack &y) const
w (self-scaling point)
constexpr auto e() const
e (jordan identity)
static constexpr T eps
eps constant
linalg::matrix_scalar_t< Mat > T
static constexpr std::size_t M
constexpr auto operator()(const Map &map)
transform native RSOC coord map to SOC map
static constexpr std::size_t N
affine::affine_mat_t< Map > Mat
extract alias & types
Circ - Jordan Map/Product for SOC.
constexpr auto operator()(const Vec &x, const Vec &y) const
circ (jordan map/product)
static constexpr std::size_t N
linalg::vector_element_t< Vec > T
types and size extraction
constexpr T trace_impl(const Slack &x, const Slack &y) const
trace
constexpr auto sqrt_impl(const Slack &x) const
Event-returning Jordan square root for the common cone implementation.
constexpr Slack y0_impl() const
default dual point
constexpr T alpha_max_impl(const Slack &x, const linalg::Vector< T, M > &p) const
fraction to boundary dK
constexpr T nu_impl() const
barrier param
constexpr auto gamma_F_impl(const Slack &x, const Slack &y) const
gamma_F
constexpr T alpha_max_dual_impl(const Slack &y, const linalg::Vector< T, M > &p) const
fracto to dK^*
constexpr auto circ_impl(const Slack &x, const Slack &y) const
circ
constexpr bool in_dual_cone_impl(const Slack &y) const
in interior of K^*
constexpr auto grad_impl(const Slack &x) const
grad
constexpr auto sqrt(const Slack &x) const
sqrt
constexpr auto H_impl(const Slack &x, const Slack &y) const
hessian
constexpr Slack x0_impl() const
default interior point
constexpr auto w_impl(const Slack &x, const Slack &y) const
w (self-scaled point)
constexpr auto e_impl() const
e (jordan identity)
constexpr auto eigs(const Slack &x) const
eigs
constexpr bool in_cone_impl(const Slack &x) const
in interior of K
constexpr auto inv_impl(const Slack &x) const
inv