tinyopt
700
Tinyopt, a lightweight, header only optimization library
Toggle main menu visibility
Loading...
Searching...
No Matches
helpers.h
1
// Copyright 2026 Julien Michot.
2
// SPDX-License-Identifier: Apache-2.0
3
4
#pragma once
5
6
#include <tinyopt/math.h>
7
#include <tinyopt/traits.h>
8
9
/***
10
* @brief Macro helper to define a loss, see activations.h for examples.
11
* Not sure it was a good idea but look at activations.h, it's sooo slim!
12
*/
13
#define DefineLoss(name, code, jac_code) \
14
template <typename T, typename ExportJ> \
15
auto name(const T &x, const ExportJ &Jx_or_bool); \
16
/* Loss that only returns the final loss */
\
17
template <typename T> \
18
auto name(const T &x) { \
19
if constexpr (traits::is_pair_v<T>) { \
20
return name(x.first, x.second); \
21
} else { \
22
constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>; \
23
if constexpr (IsMatrix) {
/* matrix */
\
24
using Scalar = typename T::Scalar; \
25
return x.unaryExpr([](Scalar v) { return name<Scalar>(v); }).eval(); \
26
} else {
/* scalar */
\
27
using Scalar = std::decay_t<T>; \
28
return Scalar((code)); \
29
} \
30
} \
31
} \
32
/* Loss that returns both the loss and the Jacobian */
\
33
template <typename T, typename ExportJ> \
34
auto name(const T &x, const ExportJ &Jx_or_bool) { \
35
constexpr bool HasJac = traits::is_matrix_or_scalar_v<std::decay_t<ExportJ>>; \
36
constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>; \
37
const auto l = name(x); \
38
if constexpr (IsMatrix) {
/* matrix */
\
39
using Scalar = typename T::Scalar; \
40
const auto J = ((jac_code)); \
41
if constexpr (HasJac) { \
42
return std::make_pair(l, (J * Jx_or_bool).matrix().eval()); \
43
} else { \
44
constexpr int DimsJ = traits::params_trait<T>::Dims; \
45
return std::make_pair(l, Matrix<Scalar, DimsJ, DimsJ>(J)); \
46
} \
47
} else {
/* scalar */
\
48
if constexpr (HasJac) { \
49
return std::make_pair(l, (0
/*TODO*/
* Jx_or_bool).matrix().eval()); \
50
} else { \
51
return std::make_pair(l, 0
/*TODO*/
); \
52
} \
53
} \
54
}
55
56
/***
57
* @brief Macro helper to define a loss with a parameter `a`, see activations.h for examples
58
*/
59
#define DefineLoss2(name, code, jac_code) \
60
template <typename T, typename ExportJ, typename ParamType = float> \
61
auto name(const T &x, ParamType a, const ExportJ &Jx_or_bool); \
62
/* Loss that only returns the final loss */
\
63
template <typename T, typename ParamType = float> \
64
auto name(const T &x, ParamType a) { \
65
if constexpr (traits::is_pair_v<T>) { \
66
return name(x.first, x.second, a); \
67
} else { \
68
constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>; \
69
if constexpr (IsMatrix) {
/* matrix */
\
70
using Scalar = typename T::Scalar; \
71
return x.unaryExpr([a](Scalar v) -> Scalar { return name<Scalar>(v, a); }).eval(); \
72
} else {
/* scalar */
\
73
using Scalar = std::decay_t<T>; \
74
return Scalar((code)); \
75
} \
76
} \
77
} \
78
/* Loss that returns both the loss and the Jacobian */
\
79
template <typename T, typename ExportJ, typename ParamType> \
80
auto name(const T &x, ParamType a, const ExportJ &Jx_or_bool) { \
81
constexpr bool HasJac = traits::is_matrix_or_scalar_v<std::decay_t<ExportJ>>; \
82
constexpr bool IsMatrix = traits::is_matrix_or_array_v<T> || traits::is_sparse_matrix_v<T>; \
83
const auto l = name(x, a); \
84
if constexpr (IsMatrix) {
/* matrix */
\
85
using Scalar = typename T::Scalar; \
86
const auto J = ((jac_code)); \
87
if constexpr (HasJac) { \
88
return std::make_pair(l, (J * Jx_or_bool).matrix().eval()); \
89
} else { \
90
constexpr int DimsJ = traits::params_trait<T>::Dims; \
91
return std::make_pair(l, Matrix<Scalar, DimsJ, DimsJ>(J)); \
92
} \
93
} else {
/* scalar */
\
94
if constexpr (HasJac) { \
95
return std::make_pair(l, ((0
/*TODO*/
) * Jx_or_bool).matrix().eval()); \
96
} else { \
97
return std::make_pair(l, 0
/*TODO*/
); \
98
} \
99
} \
100
}
include
tinyopt
losses
helpers.h
Generated by
1.18.0