dynare/matlab/missing/stats/gamrnd.m

405 lines
12 KiB
Matlab
Raw Normal View History

function rnd = gamrnd(a,b,method)
% This function produces independent random variates from the Gamma distribution.
%
2017-05-16 15:10:20 +02:00
% INPUTS
% a [double] n*1 vector of positive parameters.
2017-05-16 15:10:20 +02:00
% b [double] n*1 vector of positive parameters.
% method [string] 'BawensLubranoRichard' or anything else (see below).
%
2017-05-16 15:10:20 +02:00
% OUTPUT
% rnd [double] n*1 vector of independent variates from the gamma(a,b) distribution.
% rnd(i) is gamma distributed with mean a(i)b(i) and variance a(i)b(i)^2.
2017-05-16 15:10:20 +02:00
%
% ALGORITHMS
% Described in Bauwens, Lubrano and Richard (1999, page 316) and Devroye (1986, chapter 9).
2017-05-18 18:36:38 +02:00
% Copyright (C) 2006-2017 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
if (nargin < 2)
error('gamrnd:: Two input arguments are needed!');
end
if nargin==2
method= 'BauwensLubranoRichard';
if any(a<1)
method = 'Devroye';
Devroye.small = 'Best'; % 'Weibull' , 'Johnk' , 'Berman' , 'GS' , 'Best'
2017-05-16 15:10:20 +02:00
% REMARK: The first algorithm (Weibull) is producing too much extreme values.
end
if ~strcmpi(method,'BauwensLubranoRichard')
2017-05-16 15:10:20 +02:00
Devroye.big = 'Best'; % 'Cheng' , 'Best'
% REMARK 1: The first algorithm (Cheng) is still producing obviously wrong simulations.
2017-05-16 15:10:20 +02:00
% REMARK 2: The second algorithm seems slightly slower than the algorithm advocated by Bauwens,
% Lubrano and Richard, but the comparison depends on the value of a (this should be
% investigated further).
end
else
error('gamrnd:: Selection of method not yet implemented')
end
[ma,na] = size(a);
[mb,nb] = size(b);
if ma~=mb || na~=nb
error('gamrnd:: Input arguments must have the same size!');
end
if na~=1
error('gamrnd:: Input arguments must be column vectors');
end
if (any(a<0)) || (any(b<0)) || (any(a==Inf)) || (any(b==Inf))
error('gamrnd:: Input arguments must be finite and positive!');
end
[tests,integer_idx,double_idx] = isint(a);
number_of_integer_a = length(integer_idx);
number_of_double_a = length(double_idx);
rnd = NaN(ma,1);
if number_of_integer_a
small_idx = find(a(integer_idx)<30);
big_idx = find(a(integer_idx)>=30);
number_of_small_a = length(small_idx);
number_of_big_a = length(big_idx);
if number_of_small_a
% Exact sampling.
for i=1:number_of_small_a
rnd(integer_idx(small_idx(i))) = sum(exprnd(ones(a(integer_idx(small_idx(i))),1)))*b(integer_idx(small_idx(i)));
end
end
if number_of_big_a
% Gaussian approximation.
rnd(integer_idx(big_idx)) = sqrt(a(integer_idx(big_idx))).* b(integer_idx(big_idx)) .* randn(number_of_big_a, 1) + a(integer_idx(big_idx)) .* b(integer_idx(big_idx));
end
end
if number_of_double_a
if strcmpi(method,'BauwensLubranoRichard')
% Algorithm given in Bauwens, Lubrano & Richard (1999) page 316.
rnd(double_idx) = knuth_algorithm(a(double_idx),b(double_idx));
2017-05-16 15:10:20 +02:00
else% Algorithm given in Devroye (1986, chapter 9)
small_idx = find(a(double_idx)<1);
big_idx = find(a(double_idx)>1);
number_of_small_a = length(small_idx);
number_of_big_a = length(big_idx);
if number_of_small_a
if strcmpi(Devroye.small,'Weibull')
% Algorithm given in Devroye (1986, page 415) [Rejection from the Weibull density]
rnd(double_idx(small_idx)) = weibull_rejection_algorithm(a(double_idx(small_idx)),b(double_idx(small_idx)));
elseif strcmpi(Devroye.small,'Johnk')
% Algorithm given in Devroye (1986, page 418) [Johnk's gamma generator]
rnd(double_idx(small_idx)) = johnk_algorithm(a(double_idx(small_idx)),b(double_idx(small_idx)));
elseif strcmpi(Devroye.small,'Berman')
% Algorithm given in Devroye (1986, page 418) [Berman's gamma generator]
rnd(double_idx(small_idx)) = berman_algorithm(a(double_idx(small_idx)),b(double_idx(small_idx)));
elseif strcmpi(Devroye.small,'GS')
% Algorithm given in Devroye (1986, page 425) [Ahrens and Dieter, 1974]
rnd(double_idx(small_idx)) = ahrens_dieter_algorithm(a(double_idx(small_idx)),b(double_idx(small_idx)));
elseif strcmpi(Devroye.small,'Best')
% Algorithm given in Devroye (1986, page 426) [Best, 1983]
rnd(double_idx(small_idx)) = best_1983_algorithm(a(double_idx(small_idx)),b(double_idx(small_idx)));
end
end
if number_of_big_a
if strcmpi(Devroye.big,'Cheng')
% Algorithm given in Devroye (1986, page 413) [Cheng's rejection algorithm GB]
rnd(double_idx(big_idx)) = cheng_algorithm(a(double_idx(big_idx)),b(double_idx(big_idx)));
elseif strcmpi(Devroye.big,'Best')
% Algorithm given in Devroye (1986, page 410) [Best's rejection algorithm XG]
rnd(double_idx(big_idx)) = best_1978_algorithm(a(double_idx(big_idx)),b(double_idx(big_idx)));
end
end
end
end
function gamma_variates = weibull_rejection_algorithm(a,b)
nn = length(a);
mm = nn;
cc = 1./a ;
dd = a.^(a./(1-a)).*(1-a);
ZE = NaN(nn,2);
X = NaN(nn,1);
INDEX = 1:mm;
index = INDEX;
while mm
ZE(index,:) = exprnd(ones(mm,2));
X(index) = ZE(index,1).^cc(index);
id = find( (ZE(:,1)+ZE(:,2) > dd + X) );
if isempty(id)
mm = 0;
else
index = INDEX(id);
mm = length(index);
end
end
gamma_variates = X.*b;
function gamma_variates = johnk_algorithm(a,b)
nn = length(a);
mm = nn;
aa = 1./a ;
bb = 1./b ;
INDEX = 1:mm;
index = INDEX;
UV = NaN(nn,2);
X = NaN(nn,1);
Y = NaN(nn,1);
while mm
UV(index,:) = rand(mm,2);
X(index) = UV(index,1).^aa(index);
Y(index) = UV(index,2).^bb(index);
id = find(X+Y>1);
if isempty(id)
mm = 0;
else
index = INDEX(id);
mm = length(index);
end
end
gamma_variates = exprnd(ones(nn,1)).*X./(X+Y);
2017-05-16 15:10:20 +02:00
function gamma_variates = berman_algorithm(a,b)
nn = length(a);
mm = nn;
aa = 1./a ;
cc = 1./(1-a) ;
INDEX = 1:mm;
index = INDEX;
UV = NaN(nn,2);
X = NaN(nn,1);
Y = NaN(nn,1);
while mm
UV(index,:) = rand(mm,2);
X(index) = UV(index,1).^aa(index);
Y(index) = UV(index,2).^cc(index);
id = find(X+Y>1);
if isempty(id)
mm = 0;
else
index = INDEX(id);
mm = length(index);
end
end
Z = gamrnd(2*ones(nn,1),ones(nn,1));
gamma_variates = Z.*X.*b ;
2017-05-16 15:10:20 +02:00
function gamma_variates = ahrens_dieter_algorithm(a,b)
nn = length(a);
mm = nn;
bb = (exp(1)+a)/exp(1);
cc = 1./a;
INDEX = 1:mm;
index = INDEX;
UW = NaN(nn,2);
V = NaN(nn,1);
X = NaN(nn,1);
while mm
UW(index,:) = rand(mm,2);
V(index) = UW(index,1).*bb(index);
state1 = find(V(index)<=1);
state2 = find(V(index)>1);%setdiff(index,index(state1));
ID = [];
if ~isempty(state1)
X(index(state1)) = V(index(state1)).^cc(index(state1));
test1 = UW(index(state1),2) <= exp(-X(index(state1))) ;
id1 = find(~test1);
ID = INDEX(index(state1(id1)));
end
if ~isempty(state2)
X(index(state2)) = -log(cc(index(state2)).*(bb(index(state2))-V(index(state2))));
test2 = UW(index(state2),2) <= X(index(state2)).^(a(index(state2))-1);
id2 = find(~test2);
if isempty(ID)
ID = INDEX(index(state2(id2)));
else
ID = [ID,INDEX(index(state2(id2)))];
end
end
mm = length(ID);
if mm
index = ID;
end
end
gamma_variates = X.*b ;
2017-05-16 15:10:20 +02:00
function gamma_variates = best_1983_algorithm(a,b)
nn = length(a);
mm = nn;
tt = .07 + .75*sqrt(1-a);
bb = 1 + exp(-tt).*a./tt;
cc = 1./a;
INDEX = 1:mm;
index = INDEX;
UW = NaN(nn,2);
V = NaN(nn,1);
X = NaN(nn,1);
Y = NaN(nn,1);
while mm
UW(index,:) = rand(mm,2);
V(index) = UW(index,1).*bb(index);
state1 = find(V(index)<=1);
state2 = find(V(index)>1);%setdiff(index,index(state1));
ID = [];
if ~isempty(state1)
X(index(state1)) = tt(index(state1)).*V(index(state1)).^cc(index(state1));
test11 = UW(index(state1),2) <= (2-X(index(state1)))./(2+X(index(state1))) ;
id11 = find(~test11);
if ~isempty(id11)
test12 = UW(index(state1(id11)),2) <= exp(-X(index(state1(id11)))) ;
id12 = find(~test12);
else
id12 = [];
end
ID = INDEX(index(state1(id11(id12))));
end
if ~isempty(state2)
X(index(state2)) = -log(cc(index(state2)).*tt(index(state2)).*(bb(index(state2))-V(index(state2)))) ;
Y(index(state2)) = X(index(state2))./tt(index(state2)) ;
test21 = UW(index(state2),2).*(a(index(state2)) + Y(index(state2)) - a(index(state2)).*Y(index(state2)) ) <= 1 ;
id21 = find(~test21);
if ~isempty(id21)
test22 = UW(index(state2(id21)),2) <= Y(index(state2(id21))).^(a(index(state2(id21)))-1) ;
id22 = find(~test22);
else
id22 = [];
end
if isempty(ID)
ID = INDEX(index(state2(id21(id22))));
else
ID = [ID,INDEX(index(state2(id21(id22))))];
end
end
mm = length(ID);
if mm
index = ID;
end
end
gamma_variates = X.*b ;
function gamma_variates = knuth_algorithm(a,b)
nn = length(a);
mm = nn;
bb = sqrt(2*a-1);
dd = 1./(a-1);
Y = NaN(nn,1);
X = NaN(nn,1);
INDEX = 1:mm;
index = INDEX;
while mm
Y(index) = tan(pi*rand(mm,1));
X(index) = Y(index).*bb(index) + a(index) - 1 ;
idy1 = find(X(index)>=0);
idn1 = setdiff(index,index(idy1));
if ~isempty(idy1)
test = log(rand(length(idy1),1)) <= ...
log(1+Y(index(idy1)).*Y(index(idy1))) + ...
(a(index(idy1))-1).*log(X(index(idy1)).*dd(index(idy1))) - ...
Y(index(idy1)).*bb(index(idy1)) ;
idy2 = find(test);
idn2 = setdiff(idy1,idy1(idy2));
else
idy2 = [];
idn2 = [];
end
index = [ INDEX(idn1) , INDEX(index(idn2)) ] ;
mm = length(index);
end
gamma_variates = X.*b;
function gamma_variates = cheng_algorithm(a,b)
nn = length(a);
mm = nn;
bb = a-log(4);
cc = a+sqrt(2*a-1);
UV = NaN(nn,2);
Y = NaN(nn,1);
X = NaN(nn,1);
Z = NaN(nn,1);
R = NaN(nn,1);
index = 1:nn;
INDEX = index;
while mm
UV(index,:) = rand(mm,2);
Y(index) = a(index).*log(UV(index,2)./(1-UV(index,2)));
X(index) = a(index).*exp(UV(index,2));
Z(index) = UV(index,1).*UV(index,2).*UV(index,2);
R(index) = bb(index) + cc(index).*Y(index)-X(index);
test1 = (R(index) >= 4.5*Z(index)-(1+log(4.5)));
jndex = index(find(test1));
Jndex = setdiff(index,jndex);
if ~isempty(Jndex)
test2 = (R(Jndex) >= log(Z(Jndex)));
lndex = Jndex(find(test2));
Lndex = setdiff(Jndex,lndex);
else
Lndex = [];
end
index = INDEX(Lndex);
mm = length(index);
end
gamma_variates = X.*b;
function gamma_variates = best_1978_algorithm(a,b)
nn = length(a);
mm = nn;
bb = a-1;
cc = 3*a-.75;
UV = NaN(nn,2);
Y = NaN(nn,1);
X = NaN(nn,1);
Z = NaN(nn,1);
W = NaN(nn,1);
index = 1:nn;
INDEX = index;
while mm
UV(index,:) = rand(mm,2);
W(index) = UV(index,1).*(1-UV(index,1));
Y(index) = sqrt(cc(index)./W(index)).*(UV(index,1)-.5);
X(index) = bb(index)+Y(index);
jndex = index(find(X(index)>=0));
Jndex = setdiff(index,jndex);
if ~isempty(jndex)
Z(jndex) = 64*W(jndex).*W(jndex).*W(jndex).*UV(jndex,2).*UV(jndex,2);
kndex = jndex(find(Z(jndex)<=1-2*Y(jndex).*Y(jndex)./X(jndex)));
Kndex = setdiff(jndex,kndex);
if ~isempty(Kndex)
lndex = Kndex(find(log(Z(Kndex))<=2*(bb(Kndex).*log(X(Kndex)./bb(Kndex))-Y(Kndex))));
Lndex = setdiff(Kndex,lndex);
else
Lndex = [];
end
new_index = INDEX(Lndex);
%mm = length(index);
end
index = union(new_index,INDEX(Jndex));
mm = length(index);
end
gamma_variates = X.*b;