akreon-convex
Typed convex modeling, conic canonicalization, and primal-dual optimization in C++26.
Loading...
Searching...
No Matches
geo_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
8#include <algorithm>
9
12
13namespace convex {
14
16template <linalg::RnSpace Space>
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>
33
35template <linalg::RnSpace Dom, linalg::RnSpace Codom>
39
48template <typename Meta, typename Child>
49struct GeoMean : Atom<Meta, GeoMean<Meta, Child>, Child> {
52 using ConvexBase::N;
55
58
61
67 constexpr explicit GeoMean(const Child& child_in)
69 }
70
77 constexpr explicit GeoMean(const Child& child_in,
78 const affine::AffineMap<LiftedVarMat<T>>& map_in)
80
86 constexpr MonotonicityType monotonicity() const {
87 if constexpr (Tag == CurvatureType::CONCAVE)
89 else return MonotonicityType::NONINC;
90 }
91
99 constexpr T operator()(const PointT& x) const { return eval(x); }
100
108 constexpr T eval(const PointT& x) const {
109 T prod(1);
110 std::for_each(x.begin(), x.end(), [&](const auto& pt) { prod *= pt; });
111 const auto alpha = lift_map.linear_part()(0, 0);
112 const auto beta = lift_map.translation()(0);
113 if constexpr (Tag == CurvatureType::CONVEX)
114 return T(-1) * alpha * linalg::constexpr_nrt_safe<T>(prod, N) + beta;
115 else return alpha * linalg::constexpr_nrt_safe<T>(prod, N) + beta;
116 }
117
123 template <T Scalar>
124 constexpr auto mul() const {
125 if constexpr (Scalar < T(0)) {
126 using Dom = dom_space_t<meta_dom_t<Meta>>;
127 using Codom = dom_space_t<meta_codom_t<Meta>>;
128 const auto alpha = T(-1) * Scalar;
129 affine::AffineMap<LiftedVarMat<T>> new_map(alpha * lift_map.linear_part(),
130 lift_map.translation());
131 if constexpr (Tag == CurvatureType::CONCAVE) {
133 std::get<0>(this->children), new_map);
134 } else {
136 std::get<0>(this->children), new_map);
137 }
138 } else {
139 affine::AffineMap<LiftedVarMat<T>> new_map(
140 Scalar * lift_map.linear_part(), lift_map.translation());
141 return GeoMean<Meta, Child>(std::get<0>(this->children), new_map);
142 }
143 }
144
152 constexpr auto add(T beta) const {
153 LiftedVarBias<T> bias{beta + lift_map.translation()(0)};
154 affine::AffineMap<LiftedVarMat<T>> new_map(lift_map.linear_part(), bias);
155 return GeoMean<Meta, Child>(std::get<0>(this->children), new_map);
156 }
157
179 template <AtomType Type, conic::BuilderLike Builder>
180 constexpr auto canonicalize_impl(const Builder& builder) const {
181 const auto child_builder =
182 std::get<0>(this->children)
183 .template canonicalize<AtomType::FN>(builder);
184 const auto child_coord = child_builder.coord_map;
185
186 using AffineMatT = affine::affine_mat_t<decltype(child_coord)>;
187 static constexpr std::size_t Dom = linalg::mat_cols_v<AffineMatT>;
188 static constexpr std::size_t Codom = linalg::mat_rows_v<AffineMatT>;
189 static_assert(Codom == N,
190 "input affine map from cone block has invalid dom which is a "
191 "mismatch between domain in the convex function");
192 linalg::Matrix<T, N + 1, Dom + 1> F;
193 F = linalg::set_block<0, N, 0, Dom>(F, child_coord.linear_part());
194 linalg::Vector<T, N + 1> g;
195 for (std::size_t i = 0; i < N; ++i) g(i) = child_coord.translation()(i);
196
197 if constexpr (Tag == CurvatureType::CONVEX) {
198 F(N, Dom) = T(-1);
199 } else {
200 F(N, Dom) = T(1);
201 }
202
203 const auto coord_map_up = affine::AffineMap<decltype(F)>(F, g);
204 const linalg::vector_traits<linalg::Vector<T, N>> vec_t;
205 const auto power_cone =
207 const auto cones = std::make_tuple(power_cone);
208 const auto emission =
210
212 }
213
215 affine::AffineMap<LiftedVarMat<T>> lift_map;
216 const int idx{-1};
217};
218
219template <typename Child>
223 linalg::Matrix<dom_type_t<meta_codom_t<atom_meta_t<Child>>>, 1, 1>>,
225
226} // 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.
forward decl for power
CRTP base for convex atoms.
Definition atom.hpp:22
ChildrenT children
Tuple of normalized child atoms.
Definition atom.hpp:240
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
static constexpr std::size_t N
Domain dimension.
Definition atom.hpp:35
Atom metadata bundling domain, codomain, and curvature.
Domain wrapper with a static sign label.
forward declaration - geo mean fn
Definition geo_mean.hpp:49
constexpr GeoMean(const Child &child_in)
CTOR.
Definition geo_mean.hpp:67
constexpr T eval(const PointT &x) const
evaluation impl
Definition geo_mean.hpp:108
constexpr MonotonicityType monotonicity() const
mono
Definition geo_mean.hpp:86
constexpr auto mul() const
mul
Definition geo_mean.hpp:124
constexpr GeoMean(const Child &child_in, const affine::AffineMap< LiftedVarMat< T > > &map_in)
CTOR.
Definition geo_mean.hpp:77
const int idx
Definition geo_mean.hpp:216
constexpr auto canonicalize_impl(const Builder &builder) const
canonicalize_impl
Definition geo_mean.hpp:180
constexpr auto add(T beta) const
add
Definition geo_mean.hpp:152
affine::AffineMap< LiftedVarMat< T > > lift_map
member vars
Definition geo_mean.hpp:215
static constexpr CurvatureType Tag
curvature tag
Definition geo_mean.hpp:60
dom_space_t< meta_dom_t< Meta > > Space
alias to extract space type
Definition geo_mean.hpp:57
constexpr T operator()(const PointT &x) const
eval via operator overload
Definition geo_mean.hpp:99