C++ 生成具有自定义分布的序列

C++ 生成具有自定义分布的序列,c++,algorithm,distribution,C++,Algorithm,Distribution,我有n元素的向量向量v具有不同的概率。概率在[0,1]范围内,其总和为1 struct elem { int value; double probability; } 如何生成一个新的向量,其中每个元素都是基于该分布以概率选择的?如果我可以选择新向量的长度就更好了。如果你想从向量v中选择一个概率与成员值成比例的elem,你需要实现一个称为轮盘选择的选择方案 要实现这一点,您可以首先基于数据成员的值创建“轮盘赌轮”: std::vector<double> wheel,

我有
n
元素的向量
向量v具有不同的概率。概率在
[0,1]
范围内,其总和为
1

struct elem
{
   int value;
   double probability;
}

如何生成一个新的
向量
,其中每个
元素
都是基于该分布以概率选择的?如果我可以选择新向量的长度就更好了。

如果你想从向量
v
中选择一个概率与成员值成比例的
elem
,你需要实现一个称为轮盘选择的选择方案

要实现这一点,您可以首先基于数据成员的值创建“轮盘赌轮”:

std::vector<double> wheel, probs;

// extract the probabilities
std::transform(std::begin(v), std::end(v),
               std::back_inserter(probs),
               [](auto const & e) { return e.probability ; });

// then create the roulette wheel
std::partial_sum(std::begin(probs), std::end(probs),
                 std::back_inserter(wheel));
现在,您可以生成任意大小的新向量

// spin the wheel N times to generate next population
std::vector<elem> new_v;
std::generate_n(std::back_inserter(new_v), N, spin);
//旋转轮子N次以生成下一个填充
std::矢量新_v;
std::generate_n(std::back_inserter(new_v),n,spin);

请注意,如果您希望生成一个新的向量而不重复元素,那么您必须投入更多的精力来确保选择仍然是随机分布的。此选择还将受到您要生成的新向量大小的影响。

为了澄清,您希望添加到新向量中的每个
elem
都根据原始向量的概率进行选择?@cigien是的,新向量中也可以有多个相同元素考虑使用。维基百科页面甚至有一个C++实现的链接。别名表需要O(k)时间来初始化一个包含k个结果的分布,但是从该表生成的是O(1)。@SamuelLiew我认为应该重新讨论这个问题。要求是明确的,问题的范围足够狭窄。理解它为什么有效需要一段时间。我将在您提供的链接中阅读。@JordanMironski使用一些硬编码的值来尝试一下,然后旋转轮子几次。这应该有助于理解它的工作原理。既然使用了部分和,那么原始向量中的元素应该如何根据概率排列?@JordanMironski无所谓,部分和可以是任意顺序。重要的只是单个部分和的大小。再次,用原始向量按几个不同的顺序进行测试,你会发现它不会影响结果。顺便说一句,在你完全理解之前,请不要接受答案。这使得其他人不太可能以更容易理解的方式发布回答您的问题的答案。
// spin the wheel N times to generate next population
std::vector<elem> new_v;
std::generate_n(std::back_inserter(new_v), N, spin);