From cb9ad4b9f97b68c60dcebbb5ad2c331bd1802abe 2017-12-19 14:05:06 From: Alexandre Leroux Date: 2017-12-19 14:05:06 Subject: [PATCH] Adds weights to operations (1) Modifies the algorithm for choosing a random element to add weights --- diff --git a/plugins/amda/tests/FuzzingUtils.h b/plugins/amda/tests/FuzzingUtils.h index adfe293..6ae89ea 100644 --- a/plugins/amda/tests/FuzzingUtils.h +++ b/plugins/amda/tests/FuzzingUtils.h @@ -1,6 +1,7 @@ #ifndef SCIQLOP_FUZZINGUTILS_H #define SCIQLOP_FUZZINGUTILS_H +#include #include /** @@ -16,10 +17,17 @@ public: /// Generates a random int between [min, max] int generateInt(int min, int max); - /// Returns a random element among the elements of a container. If the container is empty, - /// returns an element built by default + /** + * Returns a random element among the elements of a container. An item may be more likely to be + * selected if it has an associated weight greater than other items + * @param container the container from which to retrieve an element + * @param weights the weight associated to each element of the container. The vector must have + * the same size of the container for the weights to be effective + * @param nbDraws the number of random draws to perform + * @return the random element retrieved, an element built by default if the container is empty + */ template - ValueType randomChoice(const T &container); + ValueType randomChoice(const T &container, const std::vector &weights = {}); private: std::mt19937 m_Mt; @@ -28,14 +36,28 @@ private: }; template -ValueType RandomGenerator::randomChoice(const T &container) +ValueType RandomGenerator::randomChoice(const T &container, const std::vector &weights) { if (container.empty()) { return ValueType{}; } - auto randomIndex = generateInt(0, container.size() - 1); - return container.at(randomIndex); + // Generates weights for each element: if the weights passed in parameter are malformed (the + // number of weights defined is inconsistent with the number of elements in the container, or + // all weights are zero), default weights are used + auto nbIndexes = container.size(); + std::vector indexWeights(nbIndexes); + if (weights.size() != nbIndexes || std::all_of(weights.cbegin(), weights.cend(), + [](const auto &val) { return val == 0.; })) { + std::fill(indexWeights.begin(), indexWeights.end(), 1.); + } + else { + std::copy(weights.begin(), weights.end(), indexWeights.begin()); + } + + // Performs a draw to determine the index to return + std::discrete_distribution<> d{indexWeights.cbegin(), indexWeights.cend()}; + return container.at(d(m_Mt)); } #endif // SCIQLOP_FUZZINGUTILS