感兴趣的概率分布是
double x; // range: -pi/2.0 to +pi/2.0
double y = std::pow(std::cos(x), 2.0);
此功能可以通过分析进行集成,但不能反转。因此,无法执行将均匀分布映射到所需概率分布的常用技巧。
是否有另一种方法可用于生成随机变量cos ^ 2(θ)分布?
有可能以数字方式找到反函数,但我不知道这样做的有效(记忆和计算)方法。
答案 0 :(得分:2)
从Inverse transform sampling:你可以从任何概率分布中随机生成样本数,给定它的cdf。
假设你想要cos 2 x分布,从-pi / 2到pi / 2。由于cos 2 x从-pi / 2到pi / 2的积分是pi / 2,你需要按比例缩小以使积分为1.因此,pdf P(x)=(2 / PI)COS 2 X
下一步是从给定的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)。
#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 *