9

我需要betarand(a,b)生成具有 beta 分布的随机数的函数的 c 或 c++ 源代码。我知道我可以使用boost库,但我要将它移植到 CUDA 架构,所以我需要代码。有人可以帮助我吗?
同时我有betapdf(Beta概率密度函数)。但我不知道如何使用它来创建随机数:)。

4

4 回答 4

20

C++11 随机数库不提供 beta 发行版。但是,可以根据库提供的两个 gamma 分布对beta 分布进行建模。我已经为你实施了beta_distribution一个std::gamma_distribution。据我所知,它完全符合随机数分布的要求。

#include <iostream>
#include <sstream>
#include <string>
#include <random>

namespace sftrabbit {

  template <typename RealType = double>
  class beta_distribution
  {
    public:
      typedef RealType result_type;

      class param_type
      {
        public:
          typedef beta_distribution distribution_type;

          explicit param_type(RealType a = 2.0, RealType b = 2.0)
            : a_param(a), b_param(b) { }

          RealType a() const { return a_param; }
          RealType b() const { return b_param; }

          bool operator==(const param_type& other) const
          {
            return (a_param == other.a_param &&
                    b_param == other.b_param);
          }

          bool operator!=(const param_type& other) const
          {
            return !(*this == other);
          }

        private:
          RealType a_param, b_param;
      };

      explicit beta_distribution(RealType a = 2.0, RealType b = 2.0)
        : a_gamma(a), b_gamma(b) { }
      explicit beta_distribution(const param_type& param)
        : a_gamma(param.a()), b_gamma(param.b()) { }

      void reset() { }

      param_type param() const
      {
        return param_type(a(), b());
      }

      void param(const param_type& param)
      {
        a_gamma = gamma_dist_type(param.a());
        b_gamma = gamma_dist_type(param.b());
      }

      template <typename URNG>
      result_type operator()(URNG& engine)
      {
        return generate(engine, a_gamma, b_gamma);
      }

      template <typename URNG>
      result_type operator()(URNG& engine, const param_type& param)
      {
        gamma_dist_type a_param_gamma(param.a()),
                        b_param_gamma(param.b());
        return generate(engine, a_param_gamma, b_param_gamma); 
      }

      result_type min() const { return 0.0; }
      result_type max() const { return 1.0; }

      result_type a() const { return a_gamma.alpha(); }
      result_type b() const { return b_gamma.alpha(); }

      bool operator==(const beta_distribution<result_type>& other) const
      {
        return (param() == other.param() &&
                a_gamma == other.a_gamma &&
                b_gamma == other.b_gamma);
      }

      bool operator!=(const beta_distribution<result_type>& other) const
      {
        return !(*this == other);
      }

    private:
      typedef std::gamma_distribution<result_type> gamma_dist_type;

      gamma_dist_type a_gamma, b_gamma;

      template <typename URNG>
      result_type generate(URNG& engine,
        gamma_dist_type& x_gamma,
        gamma_dist_type& y_gamma)
      {
        result_type x = x_gamma(engine);
        return x / (x + y_gamma(engine));
      }
  };

  template <typename CharT, typename RealType>
  std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os,
    const beta_distribution<RealType>& beta)
  {
    os << "~Beta(" << beta.a() << "," << beta.b() << ")";
    return os;
  }

  template <typename CharT, typename RealType>
  std::basic_istream<CharT>& operator>>(std::basic_istream<CharT>& is,
    beta_distribution<RealType>& beta)
  {
    std::string str;
    RealType a, b;
    if (std::getline(is, str, '(') && str == "~Beta" &&
        is >> a && is.get() == ',' && is >> b && is.get() == ')') {
      beta = beta_distribution<RealType>(a, b);
    } else {
      is.setstate(std::ios::failbit);
    }
    return is;
  }

}

像这样使用它:

std::random_device rd;
std::mt19937 gen(rd());
sftrabbit::beta_distribution<> beta(2, 2);
for (int i = 0; i < 10000; i++) {
  std::cout << beta(gen) << std::endl;
}
于 2013-03-01T20:48:02.537 回答
2

也许您可以使用gsl用于生成带有 beta 分布的随机数的代码。他们使用一种有点奇怪的方式来生成它们,因为你必须将一个随机数生成器传递给函数,但你肯定可以得到你需要的东西。

这是文档网页

于 2013-03-01T19:28:09.547 回答
1

Boost“逆不完全Beta”是另一种模拟Beta的快速(且简单)方法。

#include <random>
#include <boost/math/special_functions/beta.hpp>
template<typename URNG>
double beta_sample(URNG& engine, double a, double b)
{
  static std::uniform_real_distribution<double> unif(0,1);
  double p = unif(engine);
  return boost::math::ibeta_inv(a, b, p); 
  // Use Boost policies if it's not fast enough
}
于 2016-08-19T16:11:20.237 回答
0

查看随机数生成器实现NumPyNumPy 分发源

它们是用 C 语言实现的,工作速度非常快。

于 2013-03-01T19:26:30.297 回答