mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[yul-phaser] Selections+PairSelections: Add RandomSubset and PairsFromRandomSubset
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <tools/yulPhaser/PairSelections.h>
|
||||
|
||||
#include <tools/yulPhaser/Selections.h>
|
||||
#include <tools/yulPhaser/SimulationRNG.h>
|
||||
|
||||
#include <cmath>
|
||||
@@ -47,6 +48,43 @@ vector<tuple<size_t, size_t>> RandomPairSelection::materialise(size_t _poolSize)
|
||||
return selection;
|
||||
}
|
||||
|
||||
vector<tuple<size_t, size_t>> PairsFromRandomSubset::materialise(size_t _poolSize) const
|
||||
{
|
||||
vector<size_t> selectedIndices = RandomSubset(m_selectionChance).materialise(_poolSize);
|
||||
|
||||
if (selectedIndices.size() % 2 != 0)
|
||||
{
|
||||
if (selectedIndices.size() < _poolSize && SimulationRNG::bernoulliTrial(0.5))
|
||||
{
|
||||
do
|
||||
{
|
||||
size_t extraIndex = SimulationRNG::uniformInt(0, selectedIndices.size() - 1);
|
||||
if (find(selectedIndices.begin(), selectedIndices.end(), extraIndex) == selectedIndices.end())
|
||||
selectedIndices.push_back(extraIndex);
|
||||
} while (selectedIndices.size() % 2 != 0);
|
||||
}
|
||||
else
|
||||
selectedIndices.erase(selectedIndices.begin() + SimulationRNG::uniformInt(0, selectedIndices.size() - 1));
|
||||
}
|
||||
assert(selectedIndices.size() % 2 == 0);
|
||||
|
||||
vector<tuple<size_t, size_t>> selectedPairs;
|
||||
for (size_t i = selectedIndices.size() / 2; i > 0; --i)
|
||||
{
|
||||
size_t position1 = SimulationRNG::uniformInt(0, selectedIndices.size() - 1);
|
||||
size_t value1 = selectedIndices[position1];
|
||||
selectedIndices.erase(selectedIndices.begin() + position1);
|
||||
size_t position2 = SimulationRNG::uniformInt(0, selectedIndices.size() - 1);
|
||||
size_t value2 = selectedIndices[position2];
|
||||
selectedIndices.erase(selectedIndices.begin() + position2);
|
||||
|
||||
selectedPairs.push_back({value1, value2});
|
||||
}
|
||||
assert(selectedIndices.size() == 0);
|
||||
|
||||
return selectedPairs;
|
||||
}
|
||||
|
||||
vector<tuple<size_t, size_t>> PairMosaicSelection::materialise(size_t _poolSize) const
|
||||
{
|
||||
if (_poolSize < 2)
|
||||
|
||||
@@ -69,6 +69,28 @@ private:
|
||||
double m_selectionSize;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A selection that goes over all elements in a container, for each one independently decides
|
||||
* whether to select it or not and then randomly combines those elements into pairs. If the number
|
||||
* of elements is odd, randomly decides whether to take one more or exclude one.
|
||||
*
|
||||
* Each element has the same chance of being selected and can be selected at most once.
|
||||
* The number of selected elements is random and can be different with each call to
|
||||
* @a materialise().
|
||||
*/
|
||||
class PairsFromRandomSubset: public PairSelection
|
||||
{
|
||||
public:
|
||||
explicit PairsFromRandomSubset(double _selectionChance):
|
||||
m_selectionChance(_selectionChance) {}
|
||||
|
||||
std::vector<std::tuple<size_t, size_t>> materialise(size_t _poolSize) const override;
|
||||
|
||||
private:
|
||||
double m_selectionChance;
|
||||
};
|
||||
|
||||
/**
|
||||
* A selection that selects pairs of elements at specific, fixed positions indicated by a repeating
|
||||
* "pattern". If the positions in the pattern exceed the size of the container, they are capped at
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <tools/yulPhaser/SimulationRNG.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity::phaser;
|
||||
@@ -58,3 +59,12 @@ vector<size_t> RandomSelection::materialise(size_t _poolSize) const
|
||||
return selection;
|
||||
}
|
||||
|
||||
vector<size_t> RandomSubset::materialise(size_t _poolSize) const
|
||||
{
|
||||
vector<size_t> selection;
|
||||
for (size_t index = 0; index < _poolSize; ++index)
|
||||
if (SimulationRNG::bernoulliTrial(m_selectionChance))
|
||||
selection.push_back(index);
|
||||
|
||||
return selection;
|
||||
}
|
||||
|
||||
@@ -118,4 +118,26 @@ private:
|
||||
double m_selectionSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* A selection that goes over all elements in a container, for each one independently deciding
|
||||
* whether to select it or not. Each element has the same chance of being selected and can be
|
||||
* selected at most once. The order of selected elements is the same as the order of elements in
|
||||
* the container. The number of selected elements is random and can be different with each call
|
||||
* to @a materialise().
|
||||
*/
|
||||
class RandomSubset: public Selection
|
||||
{
|
||||
public:
|
||||
explicit RandomSubset(double _selectionChance):
|
||||
m_selectionChance(_selectionChance)
|
||||
{
|
||||
assert(0.0 <= _selectionChance && _selectionChance <= 1.0);
|
||||
}
|
||||
|
||||
std::vector<size_t> materialise(size_t _poolSize) const override;
|
||||
|
||||
private:
|
||||
double m_selectionChance;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user