【问题标题】:Weighted random map加权随机地图
【发布时间】:2011-02-17 10:00:21
【问题描述】:

假设我在 [0,1] 范围内有一个大的二维值数组,其中 0 表示“不可能”,1 表示“极有可能”。

如何根据上述概率在这个数组中随机选择一组点?

【问题讨论】:

标签: algorithm language-agnostic random probability


【解决方案1】:

查看问题的一种方法是(暂时)忽略您正在处理 2d 网格的事实。您拥有的是一组加权项目。从这样的集合中随机选择的标准方法是:

  1. 对权重求和,调用求和s
  2. 选择一个统一的随机值0 <= u < s
  3. 遍历项目,保持您检查过的项目的总权重t
  4. 只要t >= u,选择您当前正在查看的项目(您刚刚添加的重量)。

通过添加以下步骤,可以修改为无需替换即可进行多项选择:

  • 每次选择后,从s 中减去所选项目的权重(如果您的权重是浮点数并且存在稳定性问题,您可能更愿意从头开始重新计算,至少偶尔会这样)。

  • 从第 2 步开始重复,但在第 3 步中跳过之前选择的项目。

如果对权重求和是不可行或不可取的(如果您的数组特别大,可能会出现这种情况),还有其他选择。首先想到的是拒绝抽样,这是一个相当广泛的话题,所以我只推荐你参考谷歌和维基百科,因为它们的覆盖面相当不错。

编辑:忘了回到你有一个二维数组的事实。您可以通过预先计算(MIPMAP 样式)地图中区域层次结构的权重总和来显着加快速度,这样您就可以快速跳到实际选定权重的位置。

【讨论】:

  • 我的数组确实很大,所以你描述的第一个解决方案似乎不切实际。拒绝抽样看起来很有希望。感谢您的帮助。
  • @Nicholas Repiquet:我也不一定完全取消第一个。对数组求和的成本与最初创建它的成本相当,并且可以同时完成一些工作(如果数组频繁更改,则保持最新)。但是,如果您可以提出一个相对严格的上限,或者如果您没有抽取大量样本(因此许多潜在的拒绝是可以的),那么是的,拒绝是一个很好的方法。
  • 实际上,经过进一步思考,我想起了另一种值得研究的技术——水库取样。它需要对数组进行一次遍历,每个元素有一个随机变量。维基百科的文章非常简洁,但至少对于未加权的情况来说是这样。通过一些数学运算,将其推广到加权采样并不难。
  • 进行区域层次结构的简单有效的方法是使每个区域成为一个索引范围,这本身并不依赖于它是一个二维数组。但如果是这样,在层次结构的较高级别,它们将是行范围,而在较低级别,它们将是单行的元素范围。
【解决方案2】:

代码:

  count = 0
  maxPointsInSet = 100
  foreach(point in array){
      if(randomWithChacnce(point.value))) {
         addToSet(point)
         count++
      }
      if(count == maxPointsInSet)
         break;
  }

  function randomWithChacnce(int num){
    random = a randomized number between 0 to 1 // or random from 1 to 100 num*100
    if(num >= random)
     return true;
    return false
  }

如果您需要任何特定语言的版本,请询问我

【讨论】:

  • 谢谢!但是,这将选择所有设置为 1 的点,不是吗?另外,我需要一种方法来控制在集合中放置了多少点。说,“我需要在这张地图中选择 100 个随机点”。
  • 我对代码进行了一些编辑,所以它会是你所要求的,现在它可以工作 1
  • 分布均匀吗?它不是有利于数组开头的点吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-18
  • 1970-01-01
  • 1970-01-01
  • 2015-07-05
  • 2010-09-08
相关资源
最近更新 更多