Brush C++ API
A flexible interpretable machine learning framework
Loading...
Searching...
No Matches
functions.h
Go to the documentation of this file.
1/* Brush
2copyright 2020 William La Cava
3license: GNU/GPL v3
4
5Code below heavily inspired by heal-research/operon
6*/
7#ifndef OP_H
8#define OP_H
9#include <cmath>
10#include <iterator>
11#include <functional>
12#include <numeric>
13#include <type_traits>
14
15#include "../init.h"
16#include "nodetype.h"
17#include "../util/utils.h"
18#include "../data/data.h"
19#include "node.h"
20using namespace Brush::Util;
21
22using namespace std;
23// using namespace Brush;
24
25typedef Eigen::Array<bool,Eigen::Dynamic,1> ArrayXb;
26using Eigen::ArrayBase;
27using Eigen::Array;
28using Eigen::ArrayXi;
29using Eigen::Dynamic;
30
33using Brush::NodeType;
34
35namespace Brush
36{
37/* Operators
38- In order to work with ceres, operators should be templated to take jets.
39- by returning auto, operators preserve expression templates in Eigen. that allows them to be evaluated once after the expression is constructed.
40- might need to extend eigen to handle the median case
41https://eigen.tuxfamily.org/dox/TopicCustomizing_Plugins.html
42
43- eigen reference of operators:
44https://eigen.tuxfamily.org/dox/group__QuickRefPage.html#arrayonly
45*/
46 template<Brush::NodeType N>
47 struct Function
48 {
49 template<typename T1, typename... Tn>
50 inline auto operator()(const T1& t1, Tn... tn) { return t1; }
51 };
52 /* template<Brush::NodeType N = NodeType::Add> */
53 template<>
55 {
56 template<typename T1, typename T2>
57 inline auto operator()(const T1& t1, const T2& t2) {
58 return t1 + t2;
59 }
60 };
61
62 template<>
64 {
65 template<typename T1, typename T2>
66 inline auto operator()(const T1& t1, const T2& t2) { return t1 - t2; }
67 };
68
69 template<>
71 {
72 template<typename T1, typename T2>
73 inline auto operator()(const T1& t1, const T2& t2) { return t1 * t2 ;}
74 };
75
76 template<>
78 {
79 template<typename T1, typename T2>
80 inline auto operator()(const T1& t1, const T2& t2) { return t1 / t2 ; }
81 };
82
83
84 /* coefficient-wise minimum of two or more arguments. */
85 template<>
87 {
88 template<typename T1, typename T2, typename... Tn>
89 inline auto operator()(const T1& t1, const T2& t2, Tn... tn) { return fmin(t1, t2, tn ...); }
90
91 template<typename T>
92 inline auto operator()(const T& t) { return t.rowwise().minCoeff(); }
93
94 template<typename T>
95 inline auto operator()(const TimeSeries<T>& t) { return t.min(); }
96 };
97
98 /* coefficient-wise maximum of two or more arguments. */
99 template<>
101 {
102 template<typename T1, typename T2, typename... Tn>
103 inline auto operator()(const T1& t1, const T2& t2, Tn... tn) { return fmax(t1, t2, tn ...); }
104
105 template<typename T>
106 inline auto operator()(const T& t) { return t.rowwise().maxCoeff(); }
107
108 template<typename T>
109 inline auto operator()(const TimeSeries<T>& t) { return t.max(); }
110 };
111
112 /* mean */
113 template<>
115 {
116
117 template<typename T>
118 inline auto operator()(const T& t) { return t.rowwise().mean(); }
119
120 template<typename T>
121 inline auto operator()(const TimeSeries<T>& t) { return t.mean(); }
122
123 };
124
125 /* median
126 https://stackoverflow.com/questions/62696455/is-there-a-way-to-find-the-median-value-of-coefficients-of-an-eigen-matrix#62698308
127 template<>
128 */
129 template<>
131 {
132 template<typename Derived>
133 typename Derived::Scalar median( Eigen::DenseBase<Derived>& d ){
134 auto r { d.reshaped() };
135 std::sort( r.begin(), r.end() );
136 return r.size() % 2 == 0 ?
137 r.segment( (r.size()-2)/2, 2 ).mean() :
138 r( r.size()/2 );
139 }
140
141 template<typename Derived>
142 typename Derived::Scalar median( const Eigen::DenseBase<Derived>& d ){
143 typename Derived::PlainObject m { d.replicate(1,1) };
144 return median(m);
145 }
146
147 template<typename Derived, typename T=Derived::Scalar>
148 inline auto operator()(const Eigen::ArrayBase<Derived>& t) {
149 Eigen::Array<T,-1,1> tmp(t.rows());
150 std::transform(t.rowwise().begin(), t.rowwise().end(),
151 tmp.begin(),
152 [&](const auto& i){return this->median(i);}
153 );
154 return tmp;
155 }
156
157 template<typename T>
158 inline auto operator()(const TimeSeries<T>& t) { return t.median(); }
159 };
160
161 template<>
163 {
164 template<typename T>
165 inline auto operator()(const T& t) { return t.rowwise().prod(); }
166
167 template<typename T>
168 inline auto operator()(const TimeSeries<T>& t) { return t.prod(); }
169 };
170
171 /* sum */
172 template<>
174 {
175 template<typename T>
176 inline auto operator()(const T& t) { return t.rowwise().sum(); }
177
178 inline auto operator()(ArrayXXb t) {
179 return (t.rowwise().count().cast <float> ());
180 }
181
182 template<typename T>
183 inline auto operator()(const TimeSeries<T>& t) { return t.sum(); }
184 };
185
186 /* OffsetSum */
187 template<>
189 {
190 // just add with a constant (definition is like identity)
191 template<typename T>
192 inline auto operator()(const T& t) {
193 return t;
194 }
195
196 // n-ary version
197 // template<typename T>
198 // inline auto operator()(const T& t) { return t.rowwise().sum(); }
199
200 // inline auto operator()(ArrayXXb t) {
201 // return (t.rowwise().count().cast <float> ());
202 // }
203
204 // template<typename T>
205 // inline auto operator()(const TimeSeries<T>& t) { return t.sum(); }
206 };
207
208 template<>
210 {
211 inline auto operator()(ArrayXXb t) { return t.rowwise().count(); }
212
213 template<typename T>
214 inline auto operator()(const TimeSeries<T>& t) { return t.count(); }
215 };
216
217 /* coefficient-wise maximum of two or more arguments. */
218 template<>
220 {
221 template<typename T>
222 inline auto operator()(const T& t) {
223 ArrayXi idx(t.rows());
224 for (int i = 0; i < t.rows(); ++i)
225 t.row(i).maxCoeff(&idx(i));
226 return idx;
227 }
228 };
229
230 template<>
232 {
233 template<typename T1, typename T2>
234 inline auto operator()(const T1& t1, const T2& t2) { return t1.pow(t2); }
235 };
236
237 template<>
239 {
240 template<typename T>
241 inline auto operator()(const T& t) { return t.abs(); }
242 };
243
244 template<>
246 {
247 template<typename T>
248 inline auto operator()(const T& t) { return float(1.0) / (float(1.0) + (-t).exp()) ; }
249 };
250
251 template<>
253 {
254 template<typename T>
255 inline auto operator()(const T& t) { return t.log(); }
256 };
257
258 template<>
260 {
261 template<typename T>
262 inline auto operator()(const T& t) { return t.abs().log(); }
263 };
264
265 template<>
267 {
268 template<typename T>
269 inline auto operator()(const T& t) { return t.log1p(); }
270 };
271
272 template<>
274 {
275 template<typename T>
276 inline auto operator()(const T& t) { return t.ceil(); }
277 };
278
279 template<>
281 {
282 template<typename T>
283 inline auto operator()(const T& t) { return t.floor(); }
284 };
285
286 template<>
288 {
289 template<typename T>
290 inline auto operator()(const T& t) { return t.exp(); }
291 };
292
293 template<>
295 {
296 template<typename T>
297 inline auto operator()(const T& t) { return t.sin(); }
298 };
299
300 template<>
302 {
303 template<typename T>
304 inline auto operator()(const T& t) { return t.cos(); }
305 };
306
307 template<>
309 {
310 template<typename T>
311 inline auto operator()(const T& t) { return t.tan(); }
312 };
313
314 template<>
316 {
317 template<typename T>
318 inline auto operator()(const T& t) { return t.asin(); }
319 };
320
321 template<>
323 {
324 template<typename T>
325 inline auto operator()(const T& t) { return t.acos(); }
326 };
327
328 template<>
330 {
331 template<typename T>
332 inline auto operator()(const T& t) { return t.atan(); }
333 };
334
335 template<>
337 {
338 template<typename T>
339 inline auto operator()(const T& t) { return t.sinh(); }
340 };
341
342 template<>
344 {
345 template<typename T>
346 inline auto operator()(const T& t) { return t.cosh(); }
347 };
348
349 template<>
351 {
352 template<typename T>
353 inline auto operator()(const T& t) { return t.tanh(); }
354 };
355
356 template<>
358 {
359 template<typename T>
360 inline auto operator()(const T& t) { return t.sqrt(); }
361 };
362
363 template<>
365 {
366 template<typename T>
367 inline auto operator()(const T& t) { return t.abs().sqrt(); }
368 };
369
370 template<>
372 {
373 template<typename T>
374 inline auto operator()(const T& t) { return t.square(); }
375 };
376
377 template<>
379 {
380 template<typename T1, typename T2>
381 inline auto operator()(const T1& t1, const T2& t2) { return t1.before(t2); }
382 };
383
384 template<>
386 {
387 template<typename T1, typename T2>
388 inline auto operator()(const T1& t1, const T2& t2) { return t1.after(t2); }
389 };
390
391 template<>
393 {
394 template<typename T1, typename T2>
395 inline auto operator()(const T1& t1, const T2& t2) { return t1.during(t2); }
396 };
397
398 template<>
400 {
401 template<typename T1, typename T2>
402 inline auto operator()(const T1& t1, const T2& t2, const T2& t3) { return t2; }
403 };
404
407 template<typename T>
408 constexpr auto Stack = [](auto m, auto... ms) {
409 return ((Array<T,-1,-1>(m.rows(),1+sizeof...(ms))<<m),...,ms).finished();
410 };
411
412 template<>
414 {
415 template <typename T>
416 inline auto softmax(const ArrayBase<T> &t) const
417 {
418 auto tMinusMax = t.rowwise() - t.colwise().maxCoeff();
419 return tMinusMax.rowwise() - tMinusMax.exp().colwise().sum().log();
420 }
421
422 template <typename T>
423 inline auto operator()(const ArrayBase<T> &t)
424 {
425 return this->softmax(t);
426 }
427
428 // template<typename T, typename ...Ts>
429 // inline auto operator()(const Array<T,-1,1>& first, const Ts& ... inputs)
430 // {
431 // auto output = Stack<T>(first, inputs...);
432 // return this->softmax(output);
433 // }
434 };
435
436 /* logical and -- mul with boolean inputs */
437 template<>
439 {
440 template<typename T>
441 inline auto operator()(const ArrayBase<T>& t1, const ArrayBase<T>& t2) {
442 return t1 && t2;
443 }
444 template<typename T> requires same_as<typename T::Scalar, bJet>
445 inline auto operator()(const ArrayBase<T>& t1, const ArrayBase<T>& t2) {
446 // ArrayXb t1_bool(t1.size());
447 // for (int i = 0; i< t1.size(); ++i)
448 // t1_bool(i) = t1(i).a;
449
450 // ArrayXb t2_bool(t2.size());
451 // for (int i = 0; i< t2.size(); ++i)
452 // t2_bool(i) = t2(i).a;
453
454 // return (t1_bool || t2_bool).cast<bool>();
455 return t1 * t2;
456 }
457 };
458
459 /* logical or -- add with boolean inputs */
460 template<>
462 {
463 template<typename T>
464 inline auto operator()(const ArrayBase<T>& t1, const ArrayBase<T>& t2) {
465 return t1 || t2;
466 }
467 template<typename T> requires same_as<typename T::Scalar, bJet>
468 inline auto operator()(const ArrayBase<T>& t1, const ArrayBase<T>& t2) {
469 return t1 + t2;
470 }
471 };
472
473 /* logical not -- negate the input */
474 template<>
476 {
477 template<typename T>
478 inline auto operator()(const ArrayBase<T>& t) {
479 return !t;
480 }
481 template<typename T> requires same_as<typename T::Scalar, bJet>
482 inline auto operator()(const ArrayBase<T>& t) {
483 auto trues = ArrayXb::Constant(t.size(), true);
484 return (t - trues);
485
486 // for (size_t i = 0; i < t.size(); ++i) {
487 // t.at(i).a = !t.at(i).a;
488 // }
489
490 // return t;
491 }
492 };
493} // Brush
494
495#endif
void bind_engine(py::module &m, string name)
Eigen::Array< bool, Eigen::Dynamic, 1 > ArrayXb
Definition functions.h:25
namespace containing various utility functions
Definition error.cpp:11
vector< T > softmax(const vector< T > &w)
return the softmax transformation of a vector.
Definition utils.h:296
Scalar median(const T &v)
calculate median
Definition utils.h:202
static Rnd & r
Definition rnd.h:174
< nsga2 selection operator for getting the front
Definition data.cpp:12
NodeType
Definition nodetype.h:31
constexpr auto Stack
Stacks Eigen arrays into a 2d-array, where each array is a column.
Definition functions.h:408
Eigen::Array< bool, Eigen::Dynamic, Eigen::Dynamic > ArrayXXb
Definition types.h:41
Eigen::Array< int, Eigen::Dynamic, 1 > ArrayXi
Definition types.h:40
STL namespace.
Stores time series data and implements operators over it.
Definition timeseries.h:26
auto operator()(const T1 &t1, const T2 &t2)
Definition functions.h:57
auto operator()(const T1 &t1, const T2 &t2)
Definition functions.h:388
auto operator()(const ArrayBase< T > &t1, const ArrayBase< T > &t2)
Definition functions.h:441
auto operator()(const ArrayBase< T > &t1, const ArrayBase< T > &t2)
Definition functions.h:445
auto operator()(const T1 &t1, const T2 &t2)
Definition functions.h:381
auto operator()(const TimeSeries< T > &t)
Definition functions.h:214
auto operator()(const T1 &t1, const T2 &t2)
Definition functions.h:80
auto operator()(const T1 &t1, const T2 &t2)
Definition functions.h:395
auto operator()(const T1 &t1, const T2 &t2, Tn... tn)
Definition functions.h:103
auto operator()(const TimeSeries< T > &t)
Definition functions.h:109
auto operator()(const TimeSeries< T > &t)
Definition functions.h:121
auto operator()(const Eigen::ArrayBase< Derived > &t)
Definition functions.h:148
Derived::Scalar median(const Eigen::DenseBase< Derived > &d)
Definition functions.h:142
Derived::Scalar median(Eigen::DenseBase< Derived > &d)
Definition functions.h:133
auto operator()(const TimeSeries< T > &t)
Definition functions.h:158
auto operator()(const TimeSeries< T > &t)
Definition functions.h:95
auto operator()(const T1 &t1, const T2 &t2, Tn... tn)
Definition functions.h:89
auto operator()(const T1 &t1, const T2 &t2)
Definition functions.h:73
auto operator()(const ArrayBase< T > &t)
Definition functions.h:482
auto operator()(const ArrayBase< T > &t)
Definition functions.h:478
auto operator()(const ArrayBase< T > &t1, const ArrayBase< T > &t2)
Definition functions.h:464
auto operator()(const ArrayBase< T > &t1, const ArrayBase< T > &t2)
Definition functions.h:468
auto operator()(const T1 &t1, const T2 &t2)
Definition functions.h:234
auto operator()(const TimeSeries< T > &t)
Definition functions.h:168
auto operator()(const ArrayBase< T > &t)
Definition functions.h:423
auto softmax(const ArrayBase< T > &t) const
Definition functions.h:416
auto operator()(const T1 &t1, const T2 &t2, const T2 &t3)
Definition functions.h:402
auto operator()(const T1 &t1, const T2 &t2)
Definition functions.h:66
auto operator()(const TimeSeries< T > &t)
Definition functions.h:183
auto operator()(const T1 &t1, Tn... tn)
Definition functions.h:50