我希望能够高效地生成一个非重复整数的随机样本,其范围为闭区间
我了解到C ++有
也可以例如使用将权重降为零的
我想知道C++中什么是高效的加权随机样本以获得唯一整数,对于不同的样本大小(例如从可用范围中取1%到90%的样本)。
[0,rnd_max]
,每个数字都可以选择,并且每个数字都与一个样本权重相关(权重越大,被选择的概率就越大,如果它在样本中尚未被选择,则概率恰好为weight[i]/sum(weight[not_taken])
),我了解到C ++有
std::discrete_distribution
可以生成随机加权整数,但是如果我使用它来生成随机整数并丢弃重复的整数,当要选取的样本相对于可能范围的长度很大时,将会有许多已经被选择的失败样本,导致高度低效的过程。不清楚Floyd算法是否有一些扩展到具有样本权重的情况(https://math.stackexchange.com/questions/178690/whats-the-proof-of-correctness-for-robert-floyds-algorithm-for-selecting-a-sin)- 我个人想不出来。也可以例如使用将权重降为零的
std::discrete_distribution
,或执行部分加权洗牌,如在此答案中所示:C ++。加权std::shuffle - 但在该答案中,每次迭代都需要重新生成std::discrete_distribution
,因此运行时间变为二次(它需要每次循环通过传递给它的权重)。我想知道C++中什么是高效的加权随机样本以获得唯一整数,对于不同的样本大小(例如从可用范围中取1%到90%的样本)。
#include <vector>
#include <random>
#include <algorithm>
int main()
{
size_t rnd_max = 1e5;
size_t ntake = 1e3;
unsigned int seed = 12345;
std::mt19937 rng(seed);
std::gamma_distribution<double> rgamma(1.0, 1.0);
std::vector<double> weights(rnd_max);
for (double &w : weights) w = rgamma(rng);
std::vector<int> chosen_sample(ntake);
// sampler goes here...
return 0;
}
uniform_distribution
自己实现,总时间复杂度为O(n log^2 n)
(每个采样需要log^2 n
的时间)。这对你有兴趣吗? - user2956272