##// END OF EJS Templates
Adds weights to operations (1)...
Alexandre Leroux -
r1182:cb9ad4b9f97b
parent child
Show More
@@ -1,6 +1,7
1 1 #ifndef SCIQLOP_FUZZINGUTILS_H
2 2 #define SCIQLOP_FUZZINGUTILS_H
3 3
4 #include <algorithm>
4 5 #include <random>
5 6
6 7 /**
@@ -16,10 +17,17 public:
16 17 /// Generates a random int between [min, max]
17 18 int generateInt(int min, int max);
18 19
19 /// Returns a random element among the elements of a container. If the container is empty,
20 /// returns an element built by default
20 /**
21 * Returns a random element among the elements of a container. An item may be more likely to be
22 * selected if it has an associated weight greater than other items
23 * @param container the container from which to retrieve an element
24 * @param weights the weight associated to each element of the container. The vector must have
25 * the same size of the container for the weights to be effective
26 * @param nbDraws the number of random draws to perform
27 * @return the random element retrieved, an element built by default if the container is empty
28 */
21 29 template <typename T, typename ValueType = typename T::value_type>
22 ValueType randomChoice(const T &container);
30 ValueType randomChoice(const T &container, const std::vector<double> &weights = {});
23 31
24 32 private:
25 33 std::mt19937 m_Mt;
@@ -28,14 +36,28 private:
28 36 };
29 37
30 38 template <typename T, typename ValueType>
31 ValueType RandomGenerator::randomChoice(const T &container)
39 ValueType RandomGenerator::randomChoice(const T &container, const std::vector<double> &weights)
32 40 {
33 41 if (container.empty()) {
34 42 return ValueType{};
35 43 }
36 44
37 auto randomIndex = generateInt(0, container.size() - 1);
38 return container.at(randomIndex);
45 // Generates weights for each element: if the weights passed in parameter are malformed (the
46 // number of weights defined is inconsistent with the number of elements in the container, or
47 // all weights are zero), default weights are used
48 auto nbIndexes = container.size();
49 std::vector<double> indexWeights(nbIndexes);
50 if (weights.size() != nbIndexes || std::all_of(weights.cbegin(), weights.cend(),
51 [](const auto &val) { return val == 0.; })) {
52 std::fill(indexWeights.begin(), indexWeights.end(), 1.);
53 }
54 else {
55 std::copy(weights.begin(), weights.end(), indexWeights.begin());
56 }
57
58 // Performs a draw to determine the index to return
59 std::discrete_distribution<> d{indexWeights.cbegin(), indexWeights.cend()};
60 return container.at(d(m_Mt));
39 61 }
40 62
41 63 #endif // SCIQLOP_FUZZINGUTILS
General Comments 0
You need to be logged in to leave comments. Login now