Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;随机数生成:生成cos平方函数_C++_C++11_Random_Probability_Probability Density - Fatal编程技术网

C++ C++;随机数生成:生成cos平方函数

C++ C++;随机数生成:生成cos平方函数,c++,c++11,random,probability,probability-density,C++,C++11,Random,Probability,Probability Density,兴趣的概率分布是 double x; // range: -pi/2.0 to +pi/2.0 double y = std::pow(std::cos(x), 2.0); 该函数可以通过分析进行积分,但不能倒置。因此,无法执行将均匀分布映射到所需概率分布的常规技巧 有没有其他方法可以用来生成随机变量cos^2(θ)分布 也许可以用数值方法找到反函数,但是我不知道有什么有效的(内存和计算)方法可以做到这一点。来源:你可以根据任何概率分布随机生成样本数,给定其cdf 假设您想要cos2x分布,从

兴趣的概率分布是

double x; // range: -pi/2.0 to +pi/2.0
double y = std::pow(std::cos(x), 2.0);
该函数可以通过分析进行积分,但不能倒置。因此,无法执行将均匀分布映射到所需概率分布的常规技巧

有没有其他方法可以用来生成随机变量cos^2(θ)分布

也许可以用数值方法找到反函数,但是我不知道有什么有效的(内存和计算)方法可以做到这一点。

来源:你可以根据任何概率分布随机生成样本数,给定其cdf

假设您想要cos2x分布,从-pi/2到pi/2。因为cos2x从-pi/2到pi/2的积分是pi/2,所以需要缩小比例,使积分为1。因此,pdf P(x)=(2/pi)cos2x

下一步是从给定的pdf计算cdf,这是pdf的积分。你可以用任何数值方法来求P(x)的积分。或者你可以去Wolfram Alpha得到答案:cdf是F(x)=(2/pi)(0.5x+0.25sin2x)+0.5

接下来需要计算F-1(x)。因为F(x)是一个单调递增函数,所以可以使用二分法(二进制搜索)轻松地找到F-1(x)。Wolfram Alpha没有这个F-1(x)公式

然后生成一个从0到1的统一实数u。您的自定义发行版是F-1(u)

From:您可以根据任意概率分布随机生成样本数,给定其cdf

假设您想要cos2x分布,从-pi/2到pi/2。因为cos2x从-pi/2到pi/2的积分是pi/2,所以需要缩小比例,使积分为1。因此,pdf P(x)=(2/pi)cos2x

下一步是从给定的pdf计算cdf,这是pdf的积分。你可以用任何数值方法来求P(x)的积分。或者你可以去Wolfram Alpha得到答案:cdf是F(x)=(2/pi)(0.5x+0.25sin2x)+0.5

接下来需要计算F-1(x)。因为F(x)是一个单调递增函数,所以可以使用二分法(二进制搜索)轻松地找到F-1(x)。Wolfram Alpha没有这个F-1(x)公式

然后生成一个从0到1的统一实数u。您的自定义发行版是F-1(u)


拒绝采样是否可接受?这不能是分布-其在范围内的积分不等于1。如果按
2/pi
缩放它,它可能会被回收。为了避免麻烦,这种情况下的累积分布函数是
F(x)=(x+sin(2*x)/2+pi/2)/pi
@IgorTandetnik良好点-我没有对其进行规范化,因为规范化取决于x的范围-因为我写了这篇文章,我认为使用0到pi/2.0的范围可能更容易,而不是问题中指定的原始范围。拒绝采样是否可接受?这不能是分布-其在该范围内的积分不等于1。如果按
2/pi
缩放它,它可能会被回收。为了避免麻烦,这种情况下的累积分布函数是
F(x)=(x+sin(2*x)/2+pi/2)/pi
@IgorTandetnik良好点-我没有对其进行规范化,因为规范化取决于x的范围-因为我写了这篇文章,我认为使用0到pi/2.0的范围可能更容易,而不是问题中规定的原始范围。
#include <iostream>
#include <cmath>
#include <random>
#include <boost/random/random_device.hpp>
#include <vector>
#include <iomanip>

const double pi = 3.14159265358979323846;

const double LOW = -pi/2;
const double HIGH = pi/2;
double pdf(double x)
{
    return cos(x) * cos(x);
}

double cdf(double x) //integral of pdf
{
    return (2/pi)*(x/2 + sin(2*x)/4) + 0.5; //from Wolfram Alpha
}

double inverse_cdf(double u)
{   //bisection, not 100% accurate
    double low  = LOW;
    double high = HIGH;
    double epsilon = 1e-10; //any small number, e.g. 1e-15
    while (high - low > epsilon)
    {
        double mid = (low + high) / 2;
        if (cdf(mid) == u) return mid;
        if (cdf(mid) < u) low = mid; else high = mid;
    }
    return (low + high) / 2;
}

double custom_distribution(std::mt19937& rng)
{
    double u = std::uniform_real_distribution<double>(0,1)(rng);
    return inverse_cdf(u);
}

int main()
{
    std::mt19937 rng{boost::random::random_device{}()};

    std::vector<double> xCount(15);
    int nSamples = 10000;
    double gap = (HIGH-LOW) / xCount.size();
    while (nSamples--) xCount[(int)( (custom_distribution(rng) - LOW) / gap )]++;
    for (int i = 0; i < xCount.size(); ++i)
    {
        std::cout << std::setw(2) << i << ":" << xCount[i] << "\t";
        for (int bar = xCount[i]/15; bar--; std::cout << '*');
        std::cout << "\n";
    }
}
 0:17   *
 1:135  *********
 2:305  ********************
 3:604  ****************************************
 4:859  *********************************************************
 5:1106 *************************************************************************
 6:1256 ***********************************************************************************
 7:1353 ******************************************************************************************
 8:1271 ************************************************************************************
 9:1102 *************************************************************************
10:876  **********************************************************
11:614  ****************************************
12:334  **********************
13:143  *********
14:25   *