akreon-convex
Typed convex modeling, conic canonicalization, and primal-dual optimization in C++26.
Loading...
Searching...
No Matches
harmonic_mean.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
11
12namespace convex {
13
15template <linalg::RnSpace Space>
16 requires(linalg::space_dim_v<Space> == 2)
18
20template <linalg::RnSpace Space>
21 requires(linalg::space_dim_v<Space> == 1)
23
25template <linalg::RnSpace Space>
26 requires(linalg::space_dim_v<Space> == 1)
28
30template <linalg::RnSpace Dom, linalg::RnSpace Codom>
34
36template <linalg::RnSpace Dom, linalg::RnSpace Codom>
40
44template <typename Meta, typename Child>
45 requires(dom_size_v<meta_dom_t<Meta>> == 2)
46struct HarmonicMean : Atom<Meta, HarmonicMean<Meta, Child>, Child> {
49 using ConvexBase::N;
52
55
57 static constexpr CurvatureType Tag = meta_curv_v<Meta>;
58
64 constexpr explicit HarmonicMean(const Child& child_in)
66 }
67
74 constexpr explicit HarmonicMean(
75 const Child& child_in, const affine::AffineMap<LiftedVarMat<T>>& map_in)
76 : ConvexBase(child_in), lift_map(map_in) {}
77
83 constexpr MonotonicityType monotonicity() const {
84 if constexpr (Tag == CurvatureType::CONCAVE)
86 else return MonotonicityType::NONINC;
87 }
88
96 constexpr T operator()(const PointT& x) const { return eval(x); }
97
105 constexpr T eval(const PointT& x) const {
106 AK_ASSERT(x(0) >= T(0) && x(1) >= T(1) &&
107 "Invalid domain for harmonic mean");
108
109 const auto alpha = lift_map.linear_part()(0, 0);
110 const auto beta = lift_map.translation()(0);
111 if constexpr (Tag == CurvatureType::CONCAVE)
112 return alpha * (T(2) * x(0) * x(1)) / (x(0) + x(1)) + beta;
113 else return alpha * (T(-2) * x(0) * x(1)) / (x(0) + x(1)) + beta;
114 }
115
121 template <T Scalar>
122 constexpr auto mul() const {
123 if constexpr (Scalar < T(0)) {
124 using Dom = dom_space_t<meta_dom_t<Meta>>;
125 using Codom = dom_space_t<meta_codom_t<Meta>>;
126 const auto alpha = T(-1) * Scalar;
127 affine::AffineMap<LiftedVarMat<T>> new_map(alpha * lift_map.linear_part(),
128 lift_map.translation());
129 if constexpr (Tag == CurvatureType::CONVEX)
131 std::get<0>(this->children), new_map);
132 else
134 std::get<0>(this->children), new_map);
135 } else {
136 affine::AffineMap<LiftedVarMat<T>> new_map(
137 Scalar * lift_map.linear_part(), lift_map.translation);
138 return HarmonicMean<Meta, Child>(std::get<0>(this->children), new_map);
139 }
140 }
141
149 constexpr auto add(T beta) const {
150 LiftedVarBias<T> bias{beta + lift_map.translation()(0)};
151 affine::AffineMap<LiftedVarMat<T>> new_map(lift_map.linear_part(), bias);
152 return HarmonicMean<Meta, Child>(std::get<0>(this->children), new_map);
153 }
154
182 template <AtomType Type, conic::BuilderLike Builder>
183 constexpr auto canonicalize_impl(const Builder& builder) const {
184 const auto child_builder =
185 std::get<0>(this->children)
186 .template canonicalize<AtomType::FN>(builder);
187 const auto child_coord = child_builder.coord_map;
188
189 using AffineMatT = affine::affine_mat_t<decltype(child_coord)>;
190 static constexpr std::size_t Dom = linalg::mat_cols_v<AffineMatT>;
191 static constexpr std::size_t Codom = linalg::mat_rows_v<AffineMatT>;
192 static_assert(Codom == N,
193 "input affine map from cone block has invalid dom which is a "
194 "mismatch between domain in the convex function");
195
196 linalg::Matrix<T, N + 1, Dom + 1> F;
197 F(1, 0) = child_coord.linear_part()(0, 0);
198 F(2, 1) = child_coord.linear_part()(1, 1);
199 linalg::Vector<T, N + 1> g;
200 g(1) = child_coord.translation()(0);
201 g(2) = child_coord.translation()(1);
202
203 if constexpr (Tag == CurvatureType::CONCAVE) {
204 F(0, Dom) = linalg::inv_sqrt2_v<T>;
205 F(1, Dom) = T(-0.5);
206 F(2, Dom) = T(-0.5);
207 } else {
208 F(0, Dom) = -linalg::inv_sqrt2_v<T>;
209 F(1, Dom) = T(0.5);
210 F(2, Dom) = T(0.5);
211 }
212
213 const auto rsoc_coords = affine::AffineMap<decltype(F)>(F, g);
214 const auto coord_map_up =
217 const auto cones = std::make_tuple(rsoc);
218 const auto emission =
220
221 return child_builder.template realize<Type>(idx, lift_map, emission);
222 }
223
225 affine::AffineMap<LiftedVarMat<T>> lift_map;
226 const int idx{-1};
227};
228
229template <typename Child>
233 linalg::Matrix<dom_type_t<meta_codom_t<atom_meta_t<Child>>>, 1, 1>>,
235
236} // namespace convex
typename dom_traits< linalg::remove_cvref_t< Dom > >::Space dom_space_t
constexpr std::size_t dom_size_v
CurvatureType
Curvature annotation for atom codomain.
linalg::remove_cvref_t< T > atom_decay_t
normalize atom-facing types to a stable internal form.
MonotonicityType
Monotonicity annotation for function atoms.
linalg::Vector< T, 1 > LiftedVarBias
alias for lifted var map
linalg::RowVector< T, 1 > LiftedVarMat
alias for lifted var map
Atom-local canonical emission bundle.
RSOC -> SOC.
Definition soc.hpp:40
forward decl for soc
Definition soc.hpp:128
CRTP base for convex atoms.
Definition atom.hpp:22
dom_point_t< Domain > PointT
Point type accepted by the atom domain.
Definition atom.hpp:32
dom_type_t< Domain > T
Scalar field for the atom domain.
Definition atom.hpp:30
Atom metadata bundling domain, codomain, and curvature.
Domain wrapper with a static sign label.
forward declaration - harmonic mean fn
constexpr HarmonicMean(const Child &child_in)
CTOR.
constexpr MonotonicityType monotonicity() const
mono
constexpr T operator()(const PointT &x) const
eval via operator overload
dom_space_t< meta_dom_t< Meta > > Space
alias to extract space type
constexpr auto canonicalize_impl(const Builder &builder) const
canonicalization impl
constexpr auto mul() const
mul
constexpr T eval(const PointT &x) const
eval impl
constexpr auto add(T beta) const
add
constexpr HarmonicMean(const Child &child_in, const affine::AffineMap< LiftedVarMat< T > > &map_in)
CTOR.
affine::AffineMap< LiftedVarMat< T > > lift_map
member vars