14#ifndef XTENSOR_RANDOM_HPP
15#define XTENSOR_RANDOM_HPP
23#include <xtl/xspan.hpp>
25#include "../containers/xtensor.hpp"
26#include "../core/xmath.hpp"
27#include "../core/xtensor_config.hpp"
28#include "../generators/xbuilder.hpp"
29#include "../generators/xgenerator.hpp"
30#include "../misc/xtl_concepts.hpp"
31#include "../views/xindex_view.hpp"
32#include "../views/xview.hpp"
42 using default_engine_type = std::mt19937;
43 using seed_type = default_engine_type::result_type;
45 default_engine_type& get_default_random_engine();
46 void seed(seed_type seed);
48 template <
class T,
class S,
class E = random::default_engine_type>
49 auto rand(
const S& shape, T lower = 0, T upper = 1, E& engine = random::get_default_random_engine());
51 template <
class T,
class S,
class E = random::default_engine_type>
55 T upper = (std::numeric_limits<T>::max)(),
56 E& engine = random::get_default_random_engine()
59 template <
class T,
class S,
class E = random::default_engine_type>
60 auto randn(
const S& shape, T
mean = 0, T std_dev = 1, E& engine = random::get_default_random_engine());
62 template <
class T,
class S,
class D =
double,
class E = random::default_engine_type>
64 binomial(
const S& shape, T trials = 1, D prob = 0.5, E& engine = random::get_default_random_engine());
66 template <
class T,
class S,
class D =
double,
class E = random::default_engine_type>
67 auto geometric(
const S& shape, D prob = 0.5, E& engine = random::get_default_random_engine());
69 template <
class T,
class S,
class D =
double,
class E = random::default_engine_type>
71 negative_binomial(
const S& shape, T k = 1, D prob = 0.5, E& engine = random::get_default_random_engine());
73 template <
class T,
class S,
class D =
double,
class E = random::default_engine_type>
74 auto poisson(
const S& shape, D rate = 1.0, E& engine = random::get_default_random_engine());
76 template <
class T,
class S,
class E = random::default_engine_type>
77 auto exponential(
const S& shape, T rate = 1.0, E& engine = random::get_default_random_engine());
79 template <
class T,
class S,
class E = random::default_engine_type>
81 gamma(
const S& shape, T alpha = 1.0, T beta = 1.0, E& engine = random::get_default_random_engine());
83 template <
class T,
class S,
class E = random::default_engine_type>
84 auto weibull(
const S& shape, T a = 1.0, T b = 1.0, E& engine = random::get_default_random_engine());
86 template <
class T,
class S,
class E = random::default_engine_type>
88 extreme_value(
const S& shape, T a = 0.0, T b = 1.0, E& engine = random::get_default_random_engine());
90 template <
class T,
class S,
class E = random::default_engine_type>
92 lognormal(
const S& shape, T
mean = 0, T std_dev = 1, E& engine = random::get_default_random_engine());
94 template <
class T,
class S,
class E = random::default_engine_type>
95 auto chi_squared(
const S& shape, T deg = 1.0, E& engine = random::get_default_random_engine());
97 template <
class T,
class S,
class E = random::default_engine_type>
98 auto cauchy(
const S& shape, T a = 0.0, T b = 1.0, E& engine = random::get_default_random_engine());
100 template <
class T,
class S,
class E = random::default_engine_type>
101 auto fisher_f(
const S& shape, T m = 1.0, T n = 1.0, E& engine = random::get_default_random_engine());
103 template <
class T,
class S,
class E = random::default_engine_type>
104 auto student_t(
const S& shape, T n = 1.0, E& engine = random::get_default_random_engine());
106 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
108 rand(
const I (&shape)[L], T lower = 0, T upper = 1, E& engine = random::get_default_random_engine());
110 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
114 T upper = (std::numeric_limits<T>::max)(),
115 E& engine = random::get_default_random_engine()
118 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
120 randn(
const I (&shape)[L], T
mean = 0, T std_dev = 1, E& engine = random::get_default_random_engine());
122 template <
class T,
class I, std::
size_t L,
class D =
double,
class E = random::default_engine_type>
124 binomial(
const I (&shape)[L], T trials = 1, D prob = 0.5, E& engine = random::get_default_random_engine());
126 template <
class T,
class I, std::
size_t L,
class D =
double,
class E = random::default_engine_type>
127 auto geometric(
const I (&shape)[L], D prob = 0.5, E& engine = random::get_default_random_engine());
129 template <
class T,
class I, std::
size_t L,
class D =
double,
class E = random::default_engine_type>
130 auto negative_binomial(
134 E& engine = random::get_default_random_engine()
137 template <
class T,
class I, std::
size_t L,
class D =
double,
class E = random::default_engine_type>
138 auto poisson(
const I (&shape)[L], D rate = 1.0, E& engine = random::get_default_random_engine());
140 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
141 auto exponential(
const I (&shape)[L], T rate = 1.0, E& engine = random::get_default_random_engine());
143 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
145 gamma(
const I (&shape)[L], T alpha = 1.0, T beta = 1.0, E& engine = random::get_default_random_engine());
147 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
149 weibull(
const I (&shape)[L], T a = 1.0, T b = 1.0, E& engine = random::get_default_random_engine());
151 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
153 extreme_value(
const I (&shape)[L], T a = 0.0, T b = 1.0, E& engine = random::get_default_random_engine());
155 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
160 E& engine = random::get_default_random_engine()
163 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
164 auto chi_squared(
const I (&shape)[L], T deg = 1.0, E& engine = random::get_default_random_engine());
166 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
167 auto cauchy(
const I (&shape)[L], T a = 0.0, T b = 1.0, E& engine = random::get_default_random_engine());
169 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
171 fisher_f(
const I (&shape)[L], T m = 1.0, T n = 1.0, E& engine = random::get_default_random_engine());
173 template <
class T,
class I, std::
size_t L,
class E = random::default_engine_type>
174 auto student_t(
const I (&shape)[L], T n = 1.0, E& engine = random::get_default_random_engine());
176 template <
class T,
class E = random::default_engine_type>
177 void shuffle(xexpression<T>& e, E& engine = random::get_default_random_engine());
179 template <xtl::
integral_concept T,
class E = random::default_engine_type>
180 xtensor<T, 1> permutation(T e, E& engine = random::get_default_random_engine());
182 template <xexpression_concept T,
class E = random::default_engine_type>
183 std::decay_t<T> permutation(T&& e, E& engine = random::get_default_random_engine());
185 template <
class T,
class E = random::default_engine_type>
187 const xexpression<T>& e,
190 E& engine = random::get_default_random_engine()
193 template <
class T,
class W,
class E = random::default_engine_type>
195 const xexpression<T>& e,
197 const xexpression<W>& weights,
199 E& engine = random::get_default_random_engine()
205 template <
class T,
class E,
class D>
208 using value_type = T;
210 random_impl(E& engine, D&& dist)
212 , m_dist(std::move(dist))
216 template <
class... Args>
217 inline value_type operator()(Args...)
const
219 return m_dist(m_engine);
223 inline value_type element(It, It)
const
225 return m_dist(m_engine);
229 inline void assign_to(xexpression<EX>& e)
const noexcept
232 auto& ed = e.derived_cast();
233 for (
auto&& el : ed.storage())
235 el = m_dist(m_engine);
251 inline default_engine_type& get_default_random_engine()
253 static default_engine_type mt;
261 inline void seed(seed_type seed)
263 get_default_random_engine().seed(seed);
278 template <
class T,
class S,
class E>
279 inline auto rand(
const S& shape, T lower, T upper, E& engine)
281 std::uniform_real_distribution<T> dist(lower, upper);
282 return detail::make_xgenerator(
283 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
300 template <
class T,
class S,
class E>
301 inline auto randint(
const S& shape, T lower, T upper, E& engine)
303 std::uniform_int_distribution<T> dist(lower, T(upper - 1));
304 return detail::make_xgenerator(
305 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
323 template <
class T,
class S,
class E>
324 inline auto randn(
const S& shape, T
mean, T std_dev, E& engine)
326 std::normal_distribution<T> dist(
mean, std_dev);
327 return detail::make_xgenerator(
328 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
346 template <
class T,
class S,
class D,
class E>
347 inline auto binomial(
const S& shape, T trials, D prob, E& engine)
349 std::binomial_distribution<T> dist(trials, prob);
350 return detail::make_xgenerator(
351 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
368 template <
class T,
class S,
class D,
class E>
369 inline auto geometric(
const S& shape, D prob, E& engine)
371 std::geometric_distribution<T> dist(prob);
372 return detail::make_xgenerator(
373 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
392 template <
class T,
class S,
class D,
class E>
393 inline auto negative_binomial(
const S& shape, T k, D prob, E& engine)
395 std::negative_binomial_distribution<T> dist(k, prob);
396 return detail::make_xgenerator(
397 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
413 template <
class T,
class S,
class D,
class E>
414 inline auto poisson(
const S& shape, D rate, E& engine)
416 std::poisson_distribution<T> dist(rate);
417 return detail::make_xgenerator(
418 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
434 template <
class T,
class S,
class E>
435 inline auto exponential(
const S& shape, T rate, E& engine)
437 std::exponential_distribution<T> dist(rate);
438 return detail::make_xgenerator(
439 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
456 template <
class T,
class S,
class E>
457 inline auto gamma(
const S& shape, T alpha, T beta, E& engine)
459 std::gamma_distribution<T> dist(alpha, beta);
460 return detail::make_xgenerator(
461 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
478 template <
class T,
class S,
class E>
479 inline auto weibull(
const S& shape, T a, T b, E& engine)
481 std::weibull_distribution<T> dist(a, b);
482 return detail::make_xgenerator(
483 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
500 template <
class T,
class S,
class E>
501 inline auto extreme_value(
const S& shape, T a, T b, E& engine)
503 std::extreme_value_distribution<T> dist(a, b);
504 return detail::make_xgenerator(
505 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
523 template <
class T,
class S,
class E>
524 inline auto lognormal(
const S& shape, T
mean, T std_dev, E& engine)
526 std::lognormal_distribution<T> dist(
mean, std_dev);
527 return detail::make_xgenerator(
528 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
544 template <
class T,
class S,
class E>
545 inline auto chi_squared(
const S& shape, T deg, E& engine)
547 std::chi_squared_distribution<T> dist(deg);
548 return detail::make_xgenerator(
549 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
566 template <
class T,
class S,
class E>
567 inline auto cauchy(
const S& shape, T a, T b, E& engine)
569 std::cauchy_distribution<T> dist(a, b);
570 return detail::make_xgenerator(
571 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
589 template <
class T,
class S,
class E>
590 inline auto fisher_f(
const S& shape, T m, T n, E& engine)
592 std::fisher_f_distribution<T> dist(m, n);
593 return detail::make_xgenerator(
594 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
611 template <
class T,
class S,
class E>
612 inline auto student_t(
const S& shape, T n, E& engine)
614 std::student_t_distribution<T> dist(n);
615 return detail::make_xgenerator(
616 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
621 template <
class T,
class I, std::
size_t L,
class E>
622 inline auto rand(
const I (&shape)[L], T lower, T upper, E& engine)
624 std::uniform_real_distribution<T> dist(lower, upper);
625 return detail::make_xgenerator(
626 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
631 template <
class T,
class I, std::
size_t L,
class E>
632 inline auto randint(
const I (&shape)[L], T lower, T upper, E& engine)
634 std::uniform_int_distribution<T> dist(lower, T(upper - 1));
635 return detail::make_xgenerator(
636 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
641 template <
class T,
class I, std::
size_t L,
class E>
642 inline auto randn(
const I (&shape)[L], T
mean, T std_dev, E& engine)
644 std::normal_distribution<T> dist(
mean, std_dev);
645 return detail::make_xgenerator(
646 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
651 template <
class T,
class I, std::
size_t L,
class D,
class E>
652 inline auto binomial(
const I (&shape)[L], T trials, D prob, E& engine)
654 std::binomial_distribution<T> dist(trials, prob);
655 return detail::make_xgenerator(
656 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
661 template <
class T,
class I, std::
size_t L,
class D,
class E>
662 inline auto geometric(
const I (&shape)[L], D prob, E& engine)
664 std::geometric_distribution<T> dist(prob);
665 return detail::make_xgenerator(
666 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
671 template <
class T,
class I, std::
size_t L,
class D,
class E>
672 inline auto negative_binomial(
const I (&shape)[L], T k, D prob, E& engine)
674 std::negative_binomial_distribution<T> dist(k, prob);
675 return detail::make_xgenerator(
676 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
681 template <
class T,
class I, std::
size_t L,
class D,
class E>
682 inline auto poisson(
const I (&shape)[L], D rate, E& engine)
684 std::poisson_distribution<T> dist(rate);
685 return detail::make_xgenerator(
686 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
691 template <
class T,
class I, std::
size_t L,
class E>
692 inline auto exponential(
const I (&shape)[L], T rate, E& engine)
694 std::exponential_distribution<T> dist(rate);
695 return detail::make_xgenerator(
696 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
701 template <
class T,
class I, std::
size_t L,
class E>
702 inline auto gamma(
const I (&shape)[L], T alpha, T beta, E& engine)
704 std::gamma_distribution<T> dist(alpha, beta);
705 return detail::make_xgenerator(
706 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
711 template <
class T,
class I, std::
size_t L,
class E>
712 inline auto weibull(
const I (&shape)[L], T a, T b, E& engine)
714 std::weibull_distribution<T> dist(a, b);
715 return detail::make_xgenerator(
716 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
721 template <
class T,
class I, std::
size_t L,
class E>
722 inline auto extreme_value(
const I (&shape)[L], T a, T b, E& engine)
724 std::extreme_value_distribution<T> dist(a, b);
725 return detail::make_xgenerator(
726 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
731 template <
class T,
class I, std::
size_t L,
class E>
732 inline auto lognormal(
const I (&shape)[L], T
mean, T std_dev, E& engine)
734 std::lognormal_distribution<T> dist(
mean, std_dev);
735 return detail::make_xgenerator(
736 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
741 template <
class T,
class I, std::
size_t L,
class E>
742 inline auto chi_squared(
const I (&shape)[L], T deg, E& engine)
744 std::chi_squared_distribution<T> dist(deg);
745 return detail::make_xgenerator(
746 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
751 template <
class T,
class I, std::
size_t L,
class E>
752 inline auto cauchy(
const I (&shape)[L], T a, T b, E& engine)
754 std::cauchy_distribution<T> dist(a, b);
755 return detail::make_xgenerator(
756 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
761 template <
class T,
class I, std::
size_t L,
class E>
762 inline auto fisher_f(
const I (&shape)[L], T m, T n, E& engine)
764 std::fisher_f_distribution<T> dist(m, n);
765 return detail::make_xgenerator(
766 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
771 template <
class T,
class I, std::
size_t L,
class E>
772 inline auto student_t(
const I (&shape)[L], T n, E& engine)
774 std::student_t_distribution<T> dist(n);
775 return detail::make_xgenerator(
776 detail::random_impl<T, E,
decltype(dist)>(engine, std::move(dist)),
788 template <
class T,
class E>
789 void shuffle(xexpression<T>& e, E& engine)
791 T& de = e.derived_cast();
793 if (de.dimension() == 1)
795 using size_type =
typename T::size_type;
796 auto first = de.begin();
797 auto last = de.end();
799 for (size_type i = std::size_t((last - first) - 1); i > 0; --i)
801 std::uniform_int_distribution<size_type> dist(0, i);
802 auto j = dist(engine);
804 swap(first[i], first[j]);
809 using size_type =
typename T::size_type;
812 for (size_type i = de.shape()[0] - 1; i > 0; --i)
814 std::uniform_int_distribution<size_type> dist(0, i);
815 size_type j = dist(engine);
837 template <xtl::
integral_concept T,
class E>
841 shuffle(res, engine);
846 template <xexpression_concept T,
class E>
847 std::decay_t<T> permutation(T&& e, E& engine)
849 using copy_type = std::decay_t<T>;
851 shuffle(res, engine);
868 template <
class T,
class E>
870 choice(
const xexpression<T>& e, std::size_t n,
bool replace, E& engine)
872 const auto& de = e.derived_cast();
873 XTENSOR_ASSERT((de.dimension() == 1));
874 XTENSOR_ASSERT((replace || n <= de.size()));
876 using size_type =
typename result_type::size_type;
882 auto dist = std::uniform_int_distribution<size_type>(0, de.size() - 1);
883 for (size_type i = 0; i < n; ++i)
885 result[i] = de.storage()[dist(engine)];
891 std::copy(de.storage().begin(), de.storage().begin() + n, result.begin());
893 for (
auto it = de.storage().begin() + n; it != de.storage().end(); ++it, ++i)
895 auto idx = std::uniform_int_distribution<size_type>(0, i)(engine);
898 result.storage()[idx] = *it;
932 template <
class T,
class W,
class E>
934 choice(
const xexpression<T>& e, std::size_t n,
const xexpression<W>& weights,
bool replace, E& engine)
936 const auto& de = e.derived_cast();
937 const auto& dweights = weights.derived_cast();
938 XTENSOR_ASSERT((de.dimension() == 1));
939 XTENSOR_ASSERT((replace || n <= de.size()));
940 XTENSOR_ASSERT((de.size() == dweights.size()));
941 XTENSOR_ASSERT((de.dimension() == dweights.dimension()));
942 XTENSOR_ASSERT(
xt::all(dweights >= 0));
944 std::is_floating_point<typename W::value_type>::value,
945 "Weight expression must be of floating point type"
948 using size_type =
typename result_type::size_type;
949 using weight_type =
typename W::value_type;
959 std::uniform_real_distribution<weight_type> weight_dist{0, wc[wc.size() - 1]};
960 for (
auto& x : result)
962 const auto u = weight_dist(engine);
963 const auto idx =
static_cast<size_type
>(
964 std::upper_bound(wc.cbegin(), wc.cend(), u) - wc.cbegin()
973 keys.
resize({dweights.size()});
974 std::exponential_distribution<weight_type> randexp{weight_type(1)};
979 [&randexp, &engine](
auto w)
981 return w / randexp(engine);
991 [&keys](
auto i,
auto j)
993 return keys[i] > keys[j];
998 result =
index_view(de, xtl::span<size_type>{indices.data(), n});
void resize(S &&shape, bool force=false)
Resizes the container.
auto cumsum(E &&e, std::ptrdiff_t axis)
Cumulative sum.
auto mean(E &&e, X &&axes, EVS es=EVS())
Mean of elements over given axes.
auto eval(T &&t) -> std::enable_if_t< detail::is_container< std::decay_t< T > >::value, T && >
Force evaluation of xexpression.
@ weibull
Method 6 of (Hyndman and Fan, 1996) with alpha=0 and beta=0.
standard mathematical functions for xexpressions
auto arange(T start, T stop, S step=1) noexcept
Generates numbers evenly spaced within given half-open interval [start, stop).
auto all() noexcept
Returns a slice representing a full dimension, to be used as an argument of view function.
xtensor_container< uvector< T, A >, N, L > xtensor
Alias template on xtensor_container with default parameters for data container type.
auto index_view(E &&e, I &&indices) noexcept
creates an indexview from a container of indices.
auto empty_like(const xexpression< E > &e)
Create a xcontainer (xarray, xtensor or xtensor_fixed) with uninitialized values of the same shape,...
auto view(E &&e, S &&... slices)
Constructs and returns a view on the specified xexpression.