akreon-convex
Typed convex modeling, conic canonicalization, and primal-dual optimization in C++26.
Loading...
Searching...
No Matches
softplus.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
10
11namespace convex {
12
14template <linalg::RnSpace Space>
15 requires(linalg::space_dim_v<Space> == 1)
17
19template <linalg::RnSpace Space>
20 requires(linalg::space_dim_v<Space> == 1)
22
24template <linalg::RnSpace Space>
25 requires(linalg::space_dim_v<Space> == 1)
27
29template <linalg::RnSpace Space>
32
34template <linalg::RnSpace Space>
38
48template <typename Meta, typename Child>
49 requires(dom_size_v<meta_dom_t<Meta>> == 1)
50struct Softplus : Atom<Meta, Softplus<Meta, Child>, Child> {
53 using ConvexBase::N;
56
59
61 static constexpr CurvatureType Tag = meta_curv_v<Meta>;
62
68 constexpr explicit Softplus(const Child& child_in)
70 }
71
78 constexpr explicit Softplus(const Child& child_in,
79 const affine::AffineMap<LiftedVarMat<T>>& map_in)
80 : ConvexBase(child_in), lift_map(map_in) {}
81
87 constexpr MonotonicityType monotonicity() const {
88 if constexpr (Tag == CurvatureType::CONVEX) return MonotonicityType::NONDEC;
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 const auto alpha = lift_map.linear_part()(0, 0);
110 const auto beta = lift_map.translation()(0);
111 if constexpr (Tag == CurvatureType::CONVEX)
112 return alpha *
113 linalg::constexpr_ln(1 + linalg::constexpr_exp(x(0))).value() +
114 beta;
115 else
116 return T(-1) * alpha *
117 linalg::constexpr_ln(1 + linalg::constexpr_exp(x(0))).value() +
118 beta;
119 }
120
126 template <T Scalar>
127 constexpr auto mul() const {
128 if constexpr (Scalar < T(0)) {
129 const auto alpha = T(-1) * Scalar;
130 affine::AffineMap<LiftedVarMat<T>> new_map(alpha * lift_map.linear_part(),
131 lift_map.translation());
132 if constexpr (Tag == CurvatureType::CONCAVE) {
133 return Softplus<SoftplusMeta<Space>, Child>(std::get<0>(this->children),
134 new_map);
135 } else {
137 std::get<0>(this->children), new_map);
138 }
139 } else {
140 affine::AffineMap<LiftedVarMat<T>> new_map(
141 Scalar * lift_map.linear_part(), lift_map.translation());
142 return Softplus<Meta, Child>(std::get<0>(this->children), new_map);
143 }
144 }
145
153 constexpr auto add(T beta) const {
154 LiftedVarBias<T> bias{beta + lift_map.translation()(0)};
155 affine::AffineMap<LiftedVarMat<T>> new_map(lift_map.linear_part(), bias);
156 return Softplus<Meta, Child>(std::get<0>(this->children), new_map);
157 }
158
196 template <AtomType Type, conic::BuilderLike Builder>
197 constexpr auto canonicalize_impl(const Builder& builder) const {
198 const auto child_builder =
199 std::get<0>(this->children)
200 .template canonicalize<AtomType::FN>(builder);
201 const auto child_coord = child_builder.coord_map;
202
203 using AffineMatT = affine::affine_mat_t<decltype(child_coord)>;
204 static constexpr std::size_t Dom = linalg::mat_cols_v<AffineMatT>;
205 static constexpr std::size_t Codom = linalg::mat_rows_v<AffineMatT>;
206 static_assert(Codom == 1,
207 "input affine map from cone block has invalid codom dim for "
208 "scalar fn domain (i.e., != 1");
209
210 linalg::Matrix<T, 7, Dom + 3> F;
211 linalg::Vector<T, 7> g;
212
213 if constexpr (Tag == CurvatureType::CONVEX) {
214 F(0, Dom) = T(-1);
215 F(3, Dom) = T(-1);
216 } else {
217 F(0, Dom) = T(1);
218 F(3, Dom) = T(1);
219 }
220
221 F(2, Dom + 1) = T(1);
222 F = linalg::set_block<3, 4, 0, Dom>(F, child_coord.linear_part());
223 F(5, 3) = T(1);
224 F(6, 2) = T(-1);
225 F(6, 3) = T(-1);
226
227 g(1) = T(1);
228 g(3) = child_coord.translation()(0);
229 g(4) = T(1);
230 g(6) = T(1);
231
232 const auto coord_map_up = affine::AffineMap<decltype(F)>(F, g);
235 const auto cones = std::make_tuple(exp_cone, exp_cone, rplus);
236 const auto emission =
238
239 return child_builder.template realize<Type>(idx, lift_map, emission);
240 }
241
243 affine::AffineMap<LiftedVarMat<T>> lift_map;
244 const int idx{-3};
245};
246
247template <typename Child>
251
252} // 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
forward decl for exp
Definition exp_cone.hpp:25
Atom-local canonical emission bundle.
forward decl for nonneg orthant cone
Definition rplus.hpp:47
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 - softplus fn
Definition softplus.hpp:50
constexpr T operator()(const PointT &x) const
eval via operator overload
Definition softplus.hpp:99
constexpr auto add(T beta) const
add
Definition softplus.hpp:153
affine::AffineMap< LiftedVarMat< T > > lift_map
member vars
Definition softplus.hpp:243
dom_space_t< meta_dom_t< Meta > > Space
alias to extract space type
Definition softplus.hpp:58
constexpr Softplus(const Child &child_in)
CTOR.
Definition softplus.hpp:68
constexpr auto mul() const
mul
Definition softplus.hpp:127
constexpr Softplus(const Child &child_in, const affine::AffineMap< LiftedVarMat< T > > &map_in)
CTOR.
Definition softplus.hpp:78
constexpr T eval(const PointT &x) const
eval impl
Definition softplus.hpp:108
constexpr auto canonicalize_impl(const Builder &builder) const
softplus canonicalization
Definition softplus.hpp:197
constexpr MonotonicityType monotonicity() const
mono
Definition softplus.hpp:87