Есть ли библиотека для генерации случайных чисел в соответствии с бета-дистрибутивом для JavaScript? - PullRequest
9 голосов
/ 06 марта 2012

Мне нужно генерировать случайные числа из JavaScript в пределах Бета-распределения вероятностей .Я гуглил, но не могу найти библиотек, которые поддерживают это.

Может кто-нибудь подсказать, где я могу найти библиотеку или фрагмент кода, который будет это делать?

Ответы [ 5 ]

7 голосов
/ 10 июня 2014

В библиотеке jStat есть функции для выборки из бета-версии, а также множество других дистрибутивов .

var random_num = jStat.beta.sample( alpha, beta );
7 голосов
/ 26 ноября 2012

Мой перевод.Это в значительной степени слово в слово, так что это, вероятно, не самый идиоматический javascript.

// javascript shim for Python's built-in 'sum'
function sum(nums) {
  var accumulator = 0;
  for (var i = 0, l = nums.length; i < l; i++)
    accumulator += nums[i];
  return accumulator;
}

// In case you were wondering, the nice functional version is slower.
// function sum_slow(nums) {
//   return nums.reduce(function(a, b) { return a + b; }, 0);
// }
// var tenmil = _.range(1e7); sum(tenmil); sum_slow(tenmil);

// like betavariate, but more like R's name
function rbeta(alpha, beta) {
  var alpha_gamma = rgamma(alpha, 1);
  return alpha_gamma / (alpha_gamma + rgamma(beta, 1));
}

// From Python source, so I guess it's PSF Licensed
var SG_MAGICCONST = 1 + Math.log(4.5);
var LOG4 = Math.log(4.0);

function rgamma(alpha, beta) {
  // does not check that alpha > 0 && beta > 0
  if (alpha > 1) {
    // Uses R.C.H. Cheng, "The generation of Gamma variables with non-integral
    // shape parameters", Applied Statistics, (1977), 26, No. 1, p71-74
    var ainv = Math.sqrt(2.0 * alpha - 1.0);
    var bbb = alpha - LOG4;
    var ccc = alpha + ainv;

    while (true) {
      var u1 = Math.random();
      if (!((1e-7 < u1) && (u1 < 0.9999999))) {
        continue;
      }
      var u2 = 1.0 - Math.random();
      v = Math.log(u1/(1.0-u1))/ainv;
      x = alpha*Math.exp(v);
      var z = u1*u1*u2;
      var r = bbb+ccc*v-x;
      if (r + SG_MAGICCONST - 4.5*z >= 0.0 || r >= Math.log(z)) {
        return x * beta;
      }
    }
  }
  else if (alpha == 1.0) {
    var u = Math.random();
    while (u <= 1e-7) {
      u = Math.random();
    }
    return -Math.log(u) * beta;
  }
  else { // 0 < alpha < 1
    // Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
    while (true) {
      var u3 = Math.random();
      var b = (Math.E + alpha)/Math.E;
      var p = b*u3;
      if (p <= 1.0) {
        x = Math.pow(p, (1.0/alpha));
      }
      else {
        x = -Math.log((b-p)/alpha);
      }
      var u4 = Math.random();
      if (p > 1.0) {
        if (u4 <= Math.pow(x, (alpha - 1.0))) {
          break;
        }
      }
      else if (u4 <= Math.exp(-x)) {
        break;
      }
    }
    return x * beta;
  }
}

Частично проверяется с помощью средств, которые легко вычисляются:

function testbeta(a, b, N) {
  var sample_mean = sum(_.range(N).map(function() { return rbeta(a, b); })) / N;
  var analytic_mean = a / (a + b);
  console.log(sample_mean, "~", analytic_mean);
}
testbeta(5, 1, 100000);
2 голосов
/ 06 марта 2012

Вы можете преобразовать этот код Python в JS:

SG_MAGICCONST = 1.0 + _log(4.5)
LOG4 = log(4.0)

def gamma(z, sqrt2pi=(2.0*pi)**0.5):
  # Reflection to right half of complex plane
  if z < 0.5:
      return pi / sin(pi*z) / gamma(1.0-z)
  # Lanczos approximation with g=7
  az = z + (7.0 - 0.5)
  return az ** (z-0.5) / exp(az) * sqrt2pi * fsum([
    0.9999999999995183,
    676.5203681218835 / z,
    -1259.139216722289 / (z+1.0),
    771.3234287757674 / (z+2.0),
    -176.6150291498386 / (z+3.0),
    12.50734324009056 / (z+4.0),
    -0.1385710331296526 / (z+5.0),
    0.9934937113930748e-05 / (z+6.0),
    0.1659470187408462e-06 / (z+7.0),
  ])



def gammavariate(self, alpha, beta):
  """Gamma distribution.  Not the gamma function!

  Conditions on the parameters are alpha > 0 and beta > 0.

  The probability distribution function is:

        x ** (alpha - 1) * math.exp(-x / beta)
    pdf(x) =  --------------------------------------
          math.gamma(alpha) * beta ** alpha

  """

  # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2

  # Warning: a few older sources define the gamma distribution in terms
  # of alpha > -1.0
  if alpha <= 0.0 or beta <= 0.0:
    raise ValueError, 'gammavariate: alpha and beta must be > 0.0'

  random = self.random
  if alpha > 1.0:

    # Uses R.C.H. Cheng, "The generation of Gamma
    # variables with non-integral shape parameters",
    # Applied Statistics, (1977), 26, No. 1, p71-74

    ainv = _sqrt(2.0 * alpha - 1.0)
    bbb = alpha - LOG4
    ccc = alpha + ainv

    while 1:
      u1 = random()
      if not 1e-7 < u1 < .9999999:
        continue
      u2 = 1.0 - random()
      v = _log(u1/(1.0-u1))/ainv
      x = alpha*_exp(v)
      z = u1*u1*u2
      r = bbb+ccc*v-x
      if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
        return x * beta

  elif alpha == 1.0:
    # expovariate(1)
    u = random()
    while u <= 1e-7:
      u = random()
    return -_log(u) * beta

  else:   # alpha is between 0 and 1 (exclusive)

    # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle

    while 1:
      u = random()
      b = (_e + alpha)/_e
      p = b*u
      if p <= 1.0:
        x = p ** (1.0/alpha)
      else:
        x = -_log((b-p)/alpha)
      u1 = random()
      if p > 1.0:
        if u1 <= x ** (alpha - 1.0):
          break
      elif u1 <= _exp(-x):
        break
    return x * beta



def betavariate(alpha, beta):
  if y == 0:
    return 0.0
  else:
    return y / (y + gammavariate(beta, 1.0))

Это напрямую из исходного кода Python (с небольшими изменениями), но его легко конвертировать.

0 голосов
/ 18 мая 2017

См. stdlib , который включает в себя загружаемые PRNG для многих дистрибутивов, включая бета-дистрибутив. Например, в среде разработки stdlib ,

var beta = require( '@stdlib/math/base/random/beta' );

var r = beta( 2.0, 5.0 );
// returns <number>

В противном случае см. Исходный код, выпущенный по лицензии Apache.

0 голосов
/ 29 марта 2012

http://mbostock.github.com/d3/ex/stack.html

У вас есть пример генерации слоев гистограммы с использованием гамма-распределения. Я думаю, очень близко к тому, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...