akreon-convex
Typed convex modeling, conic canonicalization, and primal-dual optimization in C++26.
Loading...
Searching...
No Matches
quad_form.hpp
Go to the documentation of this file.
1/*
2 * Copyright © 2025-2026 Akreon LLC
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6#pragma once
7
12#include "akreon/convex/sum.hpp"
13#include "akreon/linalg/operator/cholesky.hpp"
14#include "weighted_sum.hpp"
15
16namespace convex {
17
23template <linalg::Field T>
26 using Space = linalg::Matrix<T, 1, 1>;
28
39 template <AtomLike Var>
40 constexpr auto operator()(T p, T q, T r, const Var& x) {
41 static_assert(
42 std::same_as<dom_space_t<meta_codom_t<atom_meta_t<Var>>>, Space>,
43 "Scalar quad form requires scalar codomain");
45 "Scalar quad form must operate on scalar affine atoms");
46
47 const T alpha = linalg::constexpr_sqrt_safe(T(0.5) * p);
48 const auto scaled_x = x.mul(alpha);
49 const auto quadratic = Square(scaled_x);
50 const auto linear = x.mul(q);
51
52 const auto sum = Sum(quadratic, linear);
53 return sum.add(r);
54 }
55
65 template <AtomLike Var>
66 constexpr auto operator()(T p, T q, const Var& x) {
67 return this->operator()(p, q, T(0), x);
68 }
69};
70
78template <linalg::RnSpace Space>
79struct QuadForm {
81 using T = linalg::space_type_t<Space>;
82 static constexpr std::size_t N = linalg::space_dim_v<Space>;
83
85 using Mat = linalg::Matrix<T, N, N>;
86
88 using Vec = linalg::Vector<T, N>;
89
91 using Singleton = linalg::Matrix<T, 1, 1>;
92
105 template <AtomLike Var>
106 constexpr auto operator()(const Mat& P, const Vec& q, T r, const Var& x) {
107 static_assert(N > 1,
108 "Use ScalarQuadForm<T> for scalar quadratic expressions");
109 static_assert(is_var_type_v<Var>, "Quad form must operate on a var type");
110 static_assert(
111 std::same_as<dom_space_t<meta_codom_t<atom_meta_t<Var>>>, Space>,
112 "Invalid quad operator mismatch on vector types");
113
114 const auto chol = linalg::Cholesky<Mat>(T(0.5) * P);
115 AK_ASSERT(chol.is_valid() && chol.is_psd() && "Chol(P) is not PSD");
116
117 const auto LT_x = x.mul(linalg::transpose(chol.G()));
118 const auto l2 =
119 Norm<NormMeta<Space, Singleton>, Var, linalg::L2<Vec>>(LT_x);
120 const auto quadratic = Square(l2);
121 const auto weighted_sum = WeightedSum<Space>()(q, x);
122
123 const auto sum = Sum(quadratic, weighted_sum);
124 return sum.add(r);
125 }
126
136 template <AtomLike Var>
137 constexpr auto operator()(const Mat& P, const Vec& q, const Var& x) {
138 return this->operator()(P, q, T(0), x);
139 }
140};
141
152template <AtomLike Var>
156 const dom_type_t<meta_codom_t<atom_meta_t<Var>>>& r, const Var& x) {
158 return ScalarQuadForm<T>()(p, q, r, x);
159}
160
170template <AtomLike Var>
173 const dom_type_t<meta_codom_t<atom_meta_t<Var>>>& q, const Var& x) {
175 return ScalarQuadForm<T>()(p, q, x);
176}
177
188template <AtomLike Var>
189constexpr auto make_quad_form(
190 const linalg::Matrix<dom_type_t<meta_codom_t<atom_meta_t<Var>>>,
193 const linalg::Vector<dom_type_t<meta_codom_t<atom_meta_t<Var>>>,
195 const dom_type_t<meta_codom_t<atom_meta_t<Var>>>& r, const Var& x) {
197 return QuadForm<Space>()(P, q, r, x);
198}
199
209template <AtomLike Var>
210constexpr auto make_quad_form(
211 const linalg::Matrix<dom_type_t<meta_codom_t<atom_meta_t<Var>>>,
214 const linalg::Vector<dom_type_t<meta_codom_t<atom_meta_t<Var>>>,
216 const Var& x) {
218 return QuadForm<Space>()(P, q, x);
219}
220
221} // namespace convex
typename dom_traits< linalg::remove_cvref_t< Dom > >::Space dom_space_t
constexpr auto make_scalar_quad_form(const dom_type_t< meta_codom_t< atom_meta_t< Var > > > &p, const dom_type_t< meta_codom_t< atom_meta_t< Var > > > &q, const dom_type_t< meta_codom_t< atom_meta_t< Var > > > &r, const Var &x)
make scalar quad form with domain deduced from the scalar affine atom
constexpr std::size_t dom_size_v
constexpr auto make_quad_form(const linalg::Matrix< dom_type_t< meta_codom_t< atom_meta_t< Var > > >, dom_size_v< meta_codom_t< atom_meta_t< Var > > >, dom_size_v< meta_codom_t< atom_meta_t< Var > > > > &P, const linalg::Vector< dom_type_t< meta_codom_t< atom_meta_t< Var > > >, dom_size_v< meta_codom_t< atom_meta_t< Var > > > > &q, const dom_type_t< meta_codom_t< atom_meta_t< Var > > > &r, const Var &x)
make quadratic form with domain deduced from the variable atom
typename dom_traits< linalg::remove_cvref_t< Dom > >::T dom_type_t
typename meta_traits< linalg::remove_cvref_t< Meta > >::Codomain meta_codom_t
typename atom_traits< atom_decay_t< Atom > >::ConvexMeta atom_meta_t
Extract metadata type from atom.
forward declaration - norm fn
Definition norm.hpp:42
linalg::Vector< T, N > Vec
vector type for q
Definition quad_form.hpp:88
linalg::space_type_t< Space > T
alias and helpers
Definition quad_form.hpp:81
static constexpr std::size_t N
Definition quad_form.hpp:82
linalg::Matrix< T, 1, 1 > Singleton
singleton
Definition quad_form.hpp:91
linalg::Matrix< T, N, N > Mat
matrix type for P
Definition quad_form.hpp:85
constexpr auto operator()(const Mat &P, const Vec &q, const Var &x)
operator overload without constant offset
constexpr auto operator()(const Mat &P, const Vec &q, T r, const Var &x)
operator overload
ScalarQuadForm.
Definition quad_form.hpp:24
constexpr auto operator()(T p, T q, const Var &x)
operator overload (r = 0)
Definition quad_form.hpp:66
constexpr auto operator()(T p, T q, T r, const Var &x)
operator overload
Definition quad_form.hpp:40
linalg::Matrix< T, 1, 1 > Space
aliases from type info
Definition quad_form.hpp:26
forward declaration - square fn
Definition square.hpp:47
forward declaration - sum op
Definition sum.hpp:116