【问题标题】:Opensource Implementation of the Alias Method [closed]别名方法的开源实现[关闭]
【发布时间】:2010-09-12 16:52:33
【问题描述】:

我现在正在做一个项目,为了代码重用,我去寻找一个可以对项目执行一些概率接受/拒绝的库:

即有三个人(a,b c),每个人都有一个概率P{i}得到一个物品,其中p{a}表示a的概率。这些概率是在运行时计算的,不能硬编码。

我想要做的是生成一个随机数(对于一件物品),并根据他们获得该物品的概率来计算谁获得了该物品。此处概述的别名方法 (http://books.google.com/books?pg=PA133&dq=alias+method+walker&ei=D4ORR8ncFYuWtgOslpVE&sig=TjEThBUa4odbGJmjyF4daF1AKF4&id=ERSSDBDcYOIC&output=html) 解释了如何,但我想看看是否有现成的实现,所以我不必编写它。

【问题讨论】:

    标签: java statistics random probability


    【解决方案1】:

    这样的事情可以吗?将所有 p{i} 放入数组中,函数将向获取该项目的人返回一个索引。在 O(n) 中执行。

    public int selectPerson(float[] probabilies, Random r) {
        float t = r.nextFloat();
        float p = 0.0f;
    
        for (int i = 0; i < probabilies.length; i++) {
            p += probabilies[i];
            if (t < p) {
                return i;
            }
        }
    
        // We should not end up here if probabilities are normalized properly (sum up to one)
        return probabilies.length - 1;      
    }
    

    编辑:我还没有真正测试过这个。我的意思是,您描述的功能不是很复杂(如果我理解您的意思正确的话),您不需要下载库来解决这个问题。

    【讨论】:

    【解决方案2】:

    这是一个 Ruby 实现:https://github.com/cantino/walker_method

    【讨论】:

      【解决方案3】:

      我刚刚测试了上面的方法 - 它并不完美,但我想就我的目的而言,它应该足够了。 (groovy 中的代码,粘贴到单元测试中...)

          void test() {
              for (int i = 0; i < 10; i++) {
                  once()
              }
          }
          private def once() {
              def double[] probs = [1 / 11, 2 / 11, 3 / 11, 1 / 11, 2 / 11, 2 / 11]
              def int[] whoCounts = new int[probs.length]
              def Random r = new Random()
              def int who
              int TIMES = 1000000
              for (int i = 0; i < TIMES; i++) {
                  who = selectPerson(probs, r.nextDouble())
                  whoCounts[who]++
              }
              for (int j = 0; j < probs.length; j++) {
                  System.out.printf(" %10f ", (probs[j] - (whoCounts[j] / TIMES)))
              }
              println ""
          }
          public int selectPerson(double[] probabilies, double r) {
              double t = r
              double p = 0.0f;
              for (int i = 0; i < probabilies.length; i++) {
                  p += probabilies[i];
                  if (t < p) {
                      return i;
                  }
              }
              return probabilies.length - 1;
          }
      
      outputs: the difference betweenn the probability, and the actual count/total 
      obtained over ten 1,000,000 runs:
        -0.000009    0.000027    0.000149   -0.000125    0.000371   -0.000414 
        -0.000212   -0.000346   -0.000396    0.000013    0.000808    0.000132 
         0.000326    0.000231   -0.000113    0.000040   -0.000071   -0.000414 
         0.000236    0.000390   -0.000733   -0.000368    0.000086    0.000388 
        -0.000202   -0.000473   -0.000250    0.000101   -0.000140    0.000963 
         0.000076    0.000487   -0.000106   -0.000044    0.000095   -0.000509 
         0.000295    0.000117   -0.000545   -0.000112   -0.000062    0.000306 
        -0.000584    0.000651    0.000191    0.000280   -0.000358   -0.000181 
        -0.000334   -0.000043    0.000484   -0.000156    0.000420   -0.000372
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-09
        • 2011-04-08
        • 1970-01-01
        • 2011-01-28
        相关资源
        最近更新 更多