C++ 中的广义极值分布 (GEV)
Generalized Extreme Value Distribution in C++ (GEV)
GEV 分布 (http://en.wikipedia.org/wiki/Generalized_extreme_value_distribution) 有 3 个参数:
μ ∈ R — 位置,
σ > 0 — 尺度
ξ ∈ R — 形状
不过C++11库只支持一个extreme_value_distribution,只支持2个参数:
http://www.cplusplus.com/reference/random/extreme_value_distribution/
所以这个实现缺少形状参数 (ξ)。有没有办法在 C++ 中使用 GEV 分布生成随机数?
编辑:维基百科建议 GEV 可以从 EV、Weibull 和 Frechet 构建。所以看来可以用EV和C++中的Weibull实现来构造。
我不是概率论者,但我有理由相信您可以找到累积分布函数的反函数并将其应用于从 (0,1) 上的均匀分布中获取的值。来自提供的维基百科 link,一般情况的倒数是
F^-1(x; mu, sigma, xi) = mu + ((-ln x)^(-xi) - 1)*sigma/xi
(假设我没有失误,但很容易检查自己)。您所要做的就是将此函数应用于从统一 (0,1] 中提取的值,并且应根据需要分配结果值。当然,如果您尝试计算值,则 xi = 0 的情况将失败这样,但无论如何,这种情况是由 extreme_value_distribution 实现的。
抱歉格式问题,我熟悉 LaTeX,但完全不熟悉如何在此处发表评论时使用它。
我使用 wolfram alpha 找到了 ξ!=0 的 GEV 的 IDCF:here 和
ξ==0: here
这是一个实现:
#include <iostream>
#include <random>
#include <cmath>
double icdf(double x, double mu, double sigma, double xi)
{
if(xi == 0)
{
return (mu - sigma * log(-log(x)));
}
else
{
double a = pow(-1*log(x),-1*xi);
double b = -1*xi*mu*pow(-log(x),xi);
double c = sigma * pow(-log(x),xi) - sigma;
return (-1)*(a*(b+c) )/xi;
}
}
int main()
{
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(0,1);
for (int i=0; i<10000; ++i)
{
double number = distribution(generator);
std::cout << icdf(number, 11.328, 2.909, -0.177) << std::endl;
}
return 0;
}
我在 Matlab 中分析了数据,看起来不错。
GEV 分布 (http://en.wikipedia.org/wiki/Generalized_extreme_value_distribution) 有 3 个参数:
μ ∈ R — 位置,
σ > 0 — 尺度
ξ ∈ R — 形状
不过C++11库只支持一个extreme_value_distribution,只支持2个参数:
http://www.cplusplus.com/reference/random/extreme_value_distribution/
所以这个实现缺少形状参数 (ξ)。有没有办法在 C++ 中使用 GEV 分布生成随机数?
编辑:维基百科建议 GEV 可以从 EV、Weibull 和 Frechet 构建。所以看来可以用EV和C++中的Weibull实现来构造。
我不是概率论者,但我有理由相信您可以找到累积分布函数的反函数并将其应用于从 (0,1) 上的均匀分布中获取的值。来自提供的维基百科 link,一般情况的倒数是
F^-1(x; mu, sigma, xi) = mu + ((-ln x)^(-xi) - 1)*sigma/xi
(假设我没有失误,但很容易检查自己)。您所要做的就是将此函数应用于从统一 (0,1] 中提取的值,并且应根据需要分配结果值。当然,如果您尝试计算值,则 xi = 0 的情况将失败这样,但无论如何,这种情况是由 extreme_value_distribution 实现的。
抱歉格式问题,我熟悉 LaTeX,但完全不熟悉如何在此处发表评论时使用它。
我使用 wolfram alpha 找到了 ξ!=0 的 GEV 的 IDCF:here 和 ξ==0: here
这是一个实现:
#include <iostream>
#include <random>
#include <cmath>
double icdf(double x, double mu, double sigma, double xi)
{
if(xi == 0)
{
return (mu - sigma * log(-log(x)));
}
else
{
double a = pow(-1*log(x),-1*xi);
double b = -1*xi*mu*pow(-log(x),xi);
double c = sigma * pow(-log(x),xi) - sigma;
return (-1)*(a*(b+c) )/xi;
}
}
int main()
{
std::default_random_engine generator;
std::uniform_real_distribution<double> distribution(0,1);
for (int i=0; i<10000; ++i)
{
double number = distribution(generator);
std::cout << icdf(number, 11.328, 2.909, -0.177) << std::endl;
}
return 0;
}
我在 Matlab 中分析了数据,看起来不错。