bitrl & cuberl Documentation
Simulation engine for reinforcement learning agents
Loading...
Searching...
No Matches
vector_math.h
Go to the documentation of this file.
1#ifndef BASIC_ARRAY_STATISTICS_H
2#define BASIC_ARRAY_STATISTICS_H
7#include "cuberl/base/cubeai_config.h"
10#include "bitrl/bitrl_consts.h"
11
12#include <cmath>
13#include <algorithm>
14#include <execution>
15#include <random>
16#include <iterator>
17#include <iostream>
18#include <stdexcept>
19
20#ifdef CUBERL_DEBUG
21#include <cassert>
22#endif
23
24
25namespace cuberl{
26namespace maths{
27
28namespace detail_{
29
30 template<typename T>
32
33 template<>
35 {
36 template<typename VecType>
37 static void randomize_(VecType& v, real_t a, real_t b, uint_t seed);
38 };
39
40
41 template<typename VecType>
42 void
44
45 std::mt19937 generator(seed);
46 std::uniform_real_distribution<real_t> distribution(a, b);
47
48 std::for_each(v.begin(),
49 v.end(),
50 [&](auto& val){
51 val = distribution(generator);
52 });
53 }
54
55 template<>
57 {
58 template<typename VecType>
59 static void randomize_(VecType& v, float_t a, float_t b, uint_t seed);
60 };
61
62 template<typename VecType>
63 void
65
66 std::mt19937 generator(seed);
67 std::uniform_real_distribution<float_t> distribution(a, b);
68
69 std::for_each(v.begin(),
70 v.end(),
71 [&](auto& val){
72 val = distribution(generator);
73 });
74 }
75}
76
77template<utils::concepts::float_or_integral_vector VectorType>
78VectorType
79element_product(const VectorType& v1, const VectorType& v2) {
80
81 auto size1_ = v1.size();
82 auto size2_ = v2.size();
83
84 if(size1_ != size2_){
85 throw std::logic_error("Sizes not equal. Cannot compute element product of vectors with no equal sizes");
86 }
87
88 VectorType v_(v1.size(), 0);
89 for(uint_t i=0; i < v1.size(); ++i){
90
91 v_[i] = v1[i] * v2[i];
92 }
93 return v_;
94}
95
96template<typename IteratorType>
97typename std::iterator_traits<IteratorType>::value_type
98sum(IteratorType begin, IteratorType end, bool parallel=true){
99
100 typedef typename std::iterator_traits<IteratorType>::value_type value_type;
101 value_type sum_ = value_type(0);
102
103 if(parallel){
104 sum_ = std::reduce(std::execution::par, begin, end, sum_);
105 }
106 else{
107 sum_ = std::accumulate(begin, end, sum_);
108 }
109
110 return sum_;
111}
112
113
114template<typename VectorType>
115typename VectorType::value_type
116sum(const VectorType& vec, bool parallel=true){
117 return sum(vec.begin(), vec.end(), parallel);
118}
119
124template<typename IteratorType>
125real_t
126mean(IteratorType begin, IteratorType end, bool parallel=true){
127
128 auto sum_ = sum(begin, end, parallel);
129 return sum_ / static_cast<real_t>(std::distance(begin, end));
130
131}
132
137template<utils::concepts::float_or_integral_vector VectorType>
138real_t
139mean(const VectorType& vector, bool parallel=true){
140 return mean(vector.begin(), vector.end(), parallel);
141}
142
146template<typename T>
147real_t
148mean(const DynVec<T>& vector, bool parallel=true){
149 return mean(vector.begin(), vector.end(), parallel);
150}
151
152
153template<typename IteratorType>
154typename std::iterator_traits<IteratorType>::value_type
155variance(IteratorType begin, IteratorType end, bool parallel=true){
156
157 typedef typename std::iterator_traits<IteratorType>::value_type value_type;
158 auto mean_val = mean(begin, end, parallel);
159 auto size = std::distance(begin, end);
160
161 std::vector<value_type> diff(size);
162 std::transform(begin, end, diff.begin(),
163 [mean_val](value_type x) { return x - mean_val; });
164
165 value_type sq_sum = std::inner_product(diff.begin(),
166 diff.end(),
167 diff.begin(), 0.0);
168 return sq_sum / static_cast<value_type>(std::distance(begin, end));
169
170}
171
176inline
177real_t
178variance(const std::vector<real_t>& vals, bool parallel=true){
179 return variance(vals.begin(), vals.end(), parallel);
180}
181
185std::vector<real_t>
186standardize(const std::vector<real_t>& vals,
188
195template<utils::concepts::float_vector Vec2>
196uint_t
197choice(const Vec2& probs, uint_t seed=42){
198
199 std::mt19937 generator(seed);
200 std::discrete_distribution<int> distribution(probs.begin(), probs.end());
201 return distribution(generator);
202}
203
204
211template<utils::concepts::integral_vector Vec1, utils::concepts::float_vector Vec2>
212uint_t
213choice(const Vec1& choices, const Vec2& probs, uint_t seed=42){
214
215 std::mt19937 generator(seed);
216 std::discrete_distribution<int> distribution(probs.begin(), probs.end());
217 return choices[distribution(generator)];
218}
219
220template<utils::concepts::float_vector Vec>
221typename Vec::value_type
222choose_value(const Vec& vals, uint_t seed=42){
223
224 std::mt19937 generator(seed);
225 auto size = std::distance(vals.begin(), vals.end());
226 std::discrete_distribution<int> distribution(0, static_cast<int>(size));
227 auto rand_idx = distribution(generator);
228 return vals[rand_idx];
229}
230
235template<utils::concepts::float_or_integral_vector Vec>
236void
237randomize_vec(Vec& v, const Vec& walk_set, uint_t seed=42){
238 std::for_each(v.begin(), v.end(),
239 [&](auto& val){
240 val += choose_value(walk_set, seed);
241 });
242
243}
244
250template<typename T>
251std::vector<T>&
252randomize(std::vector<T>& vec, T a, T b, uint_t seed=42){
254 return vec;
255}
256
257template<utils::concepts::float_or_integral_vector Vec>
258Vec& divide(Vec& v1, typename Vec::value_type val){
259
260 // both vectors must have the same size
261 for(uint_t i=0; i<v1.size(); ++i){
262 v1[i] /= val;
263 }
264 return v1;
265}
266
267template<utils::concepts::float_or_integral_vector Vec>
268Vec& add(Vec& v1, const Vec& v2){
269
270 // both vectors must have the same size
271 for(uint_t i=0; i<v1.size(); ++i){
272 v1[i] += v2[i];
273 }
274 return v1;
275}
276
277
278template<utils::concepts::float_or_integral_vector VectorType>
279VectorType
280exponentiate(const VectorType& vec){
281 VectorType vec_exp(vec.size());
282 uint_t counter = 0;
283 static auto func = [&counter](const auto& data){
284 return std::pow(data, counter++);
285 };
286 std::transform(vec.begin(), vec.end(),
287 vec_exp.begin(), func);
288 return vec_exp;
289}
290
291template<utils::concepts::float_or_integral_vector VectorType>
292VectorType
293exponentiate(const VectorType& vec, typename VectorType::value_type v){
294 VectorType vec_exp(vec.size());
295 uint_t counter = 0;
296 static auto func = [&counter, v](const auto&){
297 return std::pow(v, counter++);
298 };
299 std::transform(vec.begin(), vec.end(),
300 vec_exp.begin(), func);
301 return vec_exp;
302}
303
304
305#ifdef USE_PYTORCH
306template<utils::concepts::float_or_integral_vector VectorType>
307VectorType
308exponentiate(const torch_tensor_t tensor, typename VectorType::value_type v){
309
310#ifdef CUBERL_DEBUG
311 assert(tensor.dim() == 1 && "Invalid tensor dimension. Should be 1");
312#endif
313
314 VectorType vec_exp(tensor.size(0));
315 uint_t counter = 0;
316
317 for(uint_t i=0; i < static_cast<uint_t>(tensor.size(0)); ++i){
318
319 auto val = tensor[i].item();
320 vec_exp[i] = val.template to<typename VectorType::value_type>();
321
322 }
323
324 static auto func = [&counter, v](auto& val){
325 auto expo = std::pow(v, counter++);
326 return val*expo;
327 };
328
329 std::for_each(vec_exp.begin(), vec_exp.end(),func);
330 return vec_exp;
331}
332#endif
333
334
335
340template<typename T>
341std::vector<T>
342softmax_vec(const std::vector<T>& vec, real_t tau=1.0){
343
344 std::vector<T> result(vec.size());
345 auto exp_sum = 0.0;
346 auto vec_size = static_cast<uint_t>(vec.size());
347 // calculate the exponentials
348 for(uint_t i=0; i<vec_size; ++i){
349 result[i] = std::exp(vec[i] / tau);
350 exp_sum += result[i];
351 }
352
353 for(uint_t i=0; i<vec_size; ++i){
354 result[i] /= exp_sum;
355 }
356
357 return result;
358
359}
360
365template<typename T>
367softmax_vec(const DynVec<T>& vec, real_t tau=1.0){
368
369 DynVec<T> result(vec.size());
370 auto exp_sum = 0.0;
371 auto vec_size = static_cast<uint_t>(vec.size());
372 // calculate the exponentials
373 for(uint_t i=0; i<vec_size; ++i){
374 result[i] = std::exp(vec[i] / tau);
375 exp_sum += result[i];
376 }
377
378 result /= exp_sum;
379 return result;
380
381}
382
383
388template<typename IteratorType>
390softmax_vec(IteratorType begin, IteratorType end, real_t tau=1.0){
391 auto vec_size = std::distance(begin, end);
393 auto exp_sum = 0.0;
394
395 auto counter = 0;
396 for(; begin != end; ++begin){
397 result[counter] = std::exp(*begin / tau);
398 exp_sum += result[counter++];
399 }
400
401 result /= exp_sum;
402 return result;
403
404}
405
406
412template <typename VectorType>
413uint_t
414arg_max(const VectorType& vec) {
415 return static_cast<uint_t>(std::distance(vec.begin(), std::max_element(vec.begin(), vec.end())));
416}
417
418
424template <typename VectorType>
425uint_t
426arg_min(const VectorType& vec) {
427 return static_cast<uint_t>(std::distance(vec.begin(), std::min_element(vec.begin(), vec.end())));
428}
429
430template<typename T>
431std::vector<uint_t>
433
434 // find max value
435 auto max_val = vec.maxCoeff();
436
437 auto result = std::vector<uint_t>();
438
439 for(uint_t i=0; i<static_cast<uint_t>(vec.size()); ++i){
440 T value = vec[i];
441 if(value == max_val){
442 result.push_back(i);
443 }
444 }
445
446 return result;
447}
448
453template<typename VecTp>
454std::vector<uint_t>
455max_indices(const VecTp& vec){
456
457 // find max value
458 auto max_val = std::max_element(vec.begin(), vec.end());
459
460 auto result = std::vector<uint_t>();
461 auto counter = 0;
462
463 std::for_each(vec.begin(), vec.end(),
464 [&](auto val){
465 if(val == max_val){
466 result.push_back(counter);
467 }
468 ++counter;
469 });
470
471 return result;
472}
473
474
475template<typename T>
476std::vector<T>
477extract_subvector(const std::vector<T>& vec, uint_t end, bool up_to=true){
478
479#ifdef CUBERL_DEBUG
480 assert(end <= vec.size() && "Invalid end index");
481#endif
482
483 if(up_to){
484 return std::vector<real_t>(vec.begin(), vec.begin() + end);
485 }
486
487 return std::vector<real_t>(vec.begin() + end, vec.end());
488}
489
490
491
496template<typename SequenceTp>
497uint_t
498bin_index(const typename SequenceTp::value_type& x, const SequenceTp& sequence){
499
500 if(sequence.size() <= 1){
502 }
503
504 auto index = 1;
505 auto begin = sequence.begin();
506 auto prev_val = *begin;
507 ++begin;
508 auto end = sequence.end();
509
510 for(; begin != end; ++begin, ++index){
511
512 auto current_val = *begin;
513
514 if( (prev_val <= x) && (x < current_val)){
515 return index;
516 }
517
518 prev_val = current_val;
519 }
520
522}
523
528template<typename VectorType>
529VectorType
530zero_center(const VectorType& vec, bool parallel=true){
531
532 auto vec_mean = mean(vec.begin(), vec.end(), parallel);
533 VectorType v(vec.size());
534 std::transform(vec.begin(), vec.end(),
535 v.begin(),
536 [vec_mean](auto val){return val - vec_mean;});
537 return v;
538
539}
540
549template<typename VectorType>
550VectorType
551normalize(const VectorType& vec, typename VectorType::value_type v){
552
553 VectorType v_(vec.size(), 0);
554
555 for(uint_t i=0; i<v_.size(); ++i){
556 v_[i] = vec[i] / v;
557 }
558 return v_;
559
560}
561
562template<typename T>
563std::vector<T>
564normalize_max(const std::vector<T>& vec){
565
566 auto max_val = std::max_element(vec.begin(),
567 vec.end());
568 std::vector<T> v_(vec.size(), T(0));
569
570 for(uint_t i=0; i<v_.size(); ++i){
571 v_[i] = vec[i] / *max_val;
572 }
573 return v_;
574}
575
576template<typename T>
577std::vector<T>
578normalize_min(const std::vector<T>& vec){
579
580 auto min_val = std::min_element(vec.begin(),
581 vec.end());
582 std::vector<T> v_(vec.size(), T(0));
583
584 for(uint_t i=0; i<v_.size(); ++i){
585 v_[i] = vec[i] / *min_val;
586 }
587 return v_;
588}
589
604std::vector<real_t>
605logspace(real_t start, real_t end, uint_t num, real_t base=10.0);
606
607
608template<typename IteratorType>
609typename std::iterator_traits<IteratorType>::value_type
610dot_product(IteratorType bv1, IteratorType ev1,
611 IteratorType bv2, IteratorType ev2) {
612
613 typedef typename std::iterator_traits<IteratorType>::value_type value_type;
614
615 auto size1_ = std::distance(bv1, ev1);
616 auto size2_ = std::distance(bv2, ev2);
617
618 if(size1_ != size2_){
619 throw std::logic_error("Sizes not equal. Cannot compute dot product of vectors with no equal sizes");
620 }
621
622 value_type sum_ = value_type(0);
623
624 for(; bv1 != ev1; ++bv1, ++bv2){
625 sum_ += (*bv1) * (*bv2);
626 }
627
628 return sum_;
629}
630
631
632template<typename VectorType>
633real_t
634dot_product(const VectorType& v1, const VectorType& v2, uint_t start_idx=0){
635
636#ifdef CUBERL_DEBUG
637 assert(v1.size() == v2.size() && "Invalid vector sizes");
638 assert(start_idx < v1.size() && "Invalid start_idx");
639#endif
640
641 auto v1_begin = v1.begin();
642 std::advance(v1_begin, start_idx);
643
644 auto v2_begin = v2.begin();
645 std::advance(v2_begin, start_idx);
646 real_t dot_product = 0.0;
647
648 for(; v1_begin != v1.end(); ++v1_begin, ++v2_begin){
649 dot_product += (*v1_begin)*(*v2_begin);
650 }
651 return dot_product;
652}
653}
654}
655
656
657
658#endif // BASIC_ARRAY_STATISTICS_H
const uint_t INVALID_ID
Invalid id.
Definition bitrl_consts.h:21
const real_t TOLERANCE
Tolerance used around the library.
Definition bitrl_consts.h:31
double real_t
real_t
Definition bitrl_types.h:23
Eigen::RowVectorX< T > DynVec
Dynamically sized row vector.
Definition bitrl_types.h:74
std::size_t uint_t
uint_t
Definition bitrl_types.h:43
float float_t
float
Definition bitrl_types.h:28
uint_t arg_min(const VectorType &vec)
Returns the index of the element that has the minimum value in the array. Implementation taken from h...
Definition vector_math.h:426
VectorType element_product(const VectorType &v1, const VectorType &v2)
Definition vector_math.h:79
VectorType zero_center(const VectorType &vec, bool parallel=true)
zero_center. Subtracts the mean value of the given vector from every value of the vector
Definition vector_math.h:530
std::iterator_traits< IteratorType >::value_type dot_product(IteratorType bv1, IteratorType ev1, IteratorType bv2, IteratorType ev2)
Definition vector_math.h:610
std::vector< real_t > logspace(real_t start, real_t end, uint_t num, real_t base=10.0)
Vec & add(Vec &v1, const Vec &v2)
Definition vector_math.h:268
VectorType normalize(const VectorType &vec, typename VectorType::value_type v)
Normalize the values of the given vector with the given value. Essentially this function divides the ...
Definition vector_math.h:551
real_t mean(IteratorType begin, IteratorType end, bool parallel=true)
mean Compute the mean value of the values in the provided iterator range
Definition vector_math.h:126
std::vector< T > extract_subvector(const std::vector< T > &vec, uint_t end, bool up_to=true)
Definition vector_math.h:477
std::vector< uint_t > max_indices(const DynVec< T > &vec)
Definition vector_math.h:432
void randomize_vec(Vec &v, const Vec &walk_set, uint_t seed=42)
Given a vector of intergal or floating point values and a set of values to choose from,...
Definition vector_math.h:237
std::vector< real_t > standardize(const std::vector< real_t > &vals, real_t tol=bitrl::consts::TOLERANCE)
Standardize the given vector.
Vec::value_type choose_value(const Vec &vals, uint_t seed=42)
Definition vector_math.h:222
std::vector< T > & randomize(std::vector< T > &vec, T a, T b, uint_t seed=42)
Fill in the given vector with random values.
Definition vector_math.h:252
Vec & divide(Vec &v1, typename Vec::value_type val)
Definition vector_math.h:258
uint_t arg_max(const VectorType &vec)
Returns the index of the element that has the maximum value in the array. Implementation taken from h...
Definition vector_math.h:414
std::vector< T > normalize_min(const std::vector< T > &vec)
Definition vector_math.h:578
VectorType exponentiate(const VectorType &vec)
Definition vector_math.h:280
uint_t bin_index(const typename SequenceTp::value_type &x, const SequenceTp &sequence)
bin_index. Compute sequnce[i - 1] <= x sequnce[i] and returns the index. Sequence should be sorted
Definition vector_math.h:498
std::vector< T > softmax_vec(const std::vector< T > &vec, real_t tau=1.0)
applies softmax operation to the elements of the vector and returns a vector with the result
Definition vector_math.h:342
uint_t choice(const Vec2 &probs, uint_t seed=42)
choice. Implements similar functionality to numpy.choice function
Definition vector_math.h:197
std::iterator_traits< IteratorType >::value_type variance(IteratorType begin, IteratorType end, bool parallel=true)
Definition vector_math.h:155
std::iterator_traits< IteratorType >::value_type sum(IteratorType begin, IteratorType end, bool parallel=true)
Definition vector_math.h:98
std::vector< T > normalize_max(const std::vector< T > &vec)
Definition vector_math.h:564
Various utilities used when working with RL problems.
Definition cuberl_types.h:16