【问题标题】:Choose n distinct elements from a vector with probability inverse-proportional to their index从一个向量中选择 n 个不同的元素,其概率与它们的索引成反比
【发布时间】:2021-12-08 22:54:53
【问题描述】:

给定一个向量和一定数量的元素 n,我正在寻找一种方法来从一个向量中选择 n 个不同的元素,其概率与它们的索引成反比。

例子:

std::vector v = {0, 1, 2, ... 998, 999};
n = 10;

一组潜在的选定索引可能是:

{50, 200, 350, 500, 600, 700, 800, 850, 900, 950}

注意事项:

  • 所选索引需要在调用之间保持一致。
  • 不能在同一个调用结果中选择同一个索引两次。
  • 向量开头的索引密度必须与向量结尾的索引密度成比例。 IE。结果 {990 ... 999} 对于给定示例无效。
  • 我宁愿尽可能多地使用标准库中的代码,而不是自己实现。
  • 我可能更喜欢简单且有效但效率较低的解决方案,而不是复杂且高效的解决方案。

谢谢

【问题讨论】:

  • 选择的索引需要在调用之间保持一致是什么意思?在给定的调用中,所有索引都必须是不同的吗?
  • 在给定的调用中,它们都必须是不同的。我会在帖子里说清楚。我的意思是,对于每次调用,选择的索引必须相同。
  • “概率与其索引成反比”。索引 0 的倒数是无穷大...索引 1 的倒数是 1。你能澄清一下你的权重/分布吗?在{a, b, c}之间选择2,导致{a, b}{a, c}{b, c},它们的概率是多少?
  • 谢谢。我添加了一个说明:“向量开头的索引密度必须与向量末尾的索引密度成比例。即结果 {990 ... 999} 对于给定的示例无效。”
  • “{990 ... 999} 无效”。无效或不可能?不确定你是否确切地知道你想要什么 :) 概率有几个陷阱。

标签: c++ algorithm


【解决方案1】:

This paper 描述了一种加权随机抽样方法。下面是一个 C++ 实现。

这是为您的数据基于 1 的索引分配 1 / index 的权重

namespace views = std::ranges::views;

std::random_device rd;
std::mt19937 gen(rd()); // or whichever URBG you want
std::uniform_real_distribution<double> dist(0, 1);

std::vector<std::pair<double, std::size_t>> weighted_indexes;
weighted_indexes.reserve(v.size());
for (auto i : views::iota(0u, v.size())) {
    auto k = std::pow(dist(gen), i + 1);
    weighted_indexes.emplace_back(k, i);
}
std::sort(weighted_indexes.begin(), weighted_indexes.end());

auto indexes = weighted_indexes | views::take(n) | views::values;
auto selected_values = indexes | views::transform([&v](std::size_t i){ return v[i]; });

【讨论】:

    猜你喜欢
    • 2020-01-13
    • 2013-05-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2012-01-07
    • 2012-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多