12 #ifndef HIPIPE_CORE_GROUPS_HPP
13 #define HIPIPE_CORE_GROUPS_HPP
15 #include <hipipe/core/utility/random.hpp>
17 #include <range/v3/action/insert.hpp>
18 #include <range/v3/action/shuffle.hpp>
19 #include <range/v3/algorithm/all_of.hpp>
20 #include <range/v3/algorithm/copy.hpp>
21 #include <range/v3/numeric/accumulate.hpp>
22 #include <range/v3/range/conversion.hpp>
23 #include <range/v3/view/concat.hpp>
24 #include <range/v3/view/drop.hpp>
25 #include <range/v3/view/filter.hpp>
26 #include <range/v3/view/iota.hpp>
27 #include <range/v3/view/repeat_n.hpp>
28 #include <range/v3/view/take.hpp>
34 namespace rga = ranges::actions;
35 namespace rgv = ranges::views;
53 template<
typename Prng = std::mt19937&>
54 std::vector<std::size_t>
generate_groups(std::size_t size, std::vector<double> ratio,
58 assert(ranges::all_of(ratio, [](
double d) {
return d >= 0; }));
61 double ratio_sum = ranges::accumulate(ratio, 0.);
62 assert(ratio_sum > 0);
65 ratio.erase(std::find_if(ratio.rbegin(), ratio.rend(), [](
double r) {
return r > 0; }).base(),
69 for (
double& r : ratio) r /= ratio_sum;
71 std::vector<std::size_t> groups;
74 for (std::size_t i = 0; i < ratio.size(); ++i) {
75 std::size_t count = std::lround(ratio[i] * size);
77 if (i + 1 == ratio.size()) count = size - groups.size();
78 rga::insert(groups, groups.end(), rgv::repeat_n(i, count));
81 rga::shuffle(groups, gen);
110 template<
typename Prng = std::mt19937&>
111 std::vector<std::vector<std::size_t>>
113 const std::vector<double>& volatile_ratio,
114 const std::vector<double>& fixed_ratio,
117 std::size_t volatile_size = volatile_ratio.size();
118 auto full_ratio = ranges::to_vector(rgv::concat(volatile_ratio, fixed_ratio));
120 std::vector<std::vector<std::size_t>> all_groups;
121 std::vector<std::size_t> initial_groups =
generate_groups(size, full_ratio, gen);
123 for (std::size_t i = 0; i < n; ++i) {
124 auto groups = initial_groups;
126 auto groups_volatile =
127 rgv::filter(groups, [volatile_size](std::size_t l) {
return l < volatile_size; });
129 std::size_t volatile_count = ranges::distance(groups_volatile);
131 auto groups_volatile_new =
generate_groups(volatile_count, volatile_ratio, gen);
133 ranges::copy(groups_volatile_new, groups_volatile.begin());
135 all_groups.emplace_back(std::move(groups));