A
download copularnd.m
Language: Matlab
LOC: 63
Project Info
copula - Bayesian Copula Selection(copula)
Server: Google
Type: svn
Google\c\copula\trunk\
   alphaboundaries.m
   analytic.mws
   bcs.m
   check_alpha.m
   check_tau.m
   conditionalcdf.m
   constrain_tau.m
   copulacdf.m
   copulaparam.m
   copulapdf.m
   copularnd.m
   copulastat.m
   dilog.m
   isnear.m
   kendall.m
   lambdaarch.m
   posterior.m
   quadg.m
   tauboundaries.m
   taujacobian.m

function u = copularnd(family, varargin)
%
%    U = COPULARND(FAMILY, ALPHA [, N])
%
%    Generate random quantiles u,v from the given copula family.
% 
%   INPUT
%	    FAMILY: One of {'ind', 'gaussian', 't', 'clayton', 'frank', 'gumbel', 
%		        'fgm', 'amh', 'arch12', 'arch14', 'gb', 'joe'}.
% 	    ALPHA:  Copula parameters (None for independent copula, [rho, nu]
% 	            for the t copula.)
% 	    N:      Number of random variates, defaults to 1.
%
%   OUTPUT
%	    U = [U1, U2]
%
%   EXAMPLES
%	    copularnd('gumbel', 4.5, 10)
%       copularnd('ind', 100)
%       copularnd('t', [.8, 3], 5)
% 

if strcmp(lower(family), 'ind')
    n = varargin{1};
    u = rand(n,2);
else
    % Checking
    alpha = varargin{1};
    pass = check_alpha(family, alpha);
    if any(~pass)
        error('Bad parameter.')
    end
    if numel(alpha) ~= 1 & ~strcmp(lower(family), 't')
        error('ALPHA must be a scalar.');
    end
    
    if nargin >= 3
        n = varargin{2};
    else
        n = 1;
    end
    
    switch lower(family)    
        case 'gaussian'
            u = normcdf(mvnrnd([0 0],[1 alpha; alpha 1],n));
        case 't'
            rho = alpha(1);
            nu = alpha(2);
            u = tcdf(mvtrnd([1 rho; rho 1],nu,n),nu);
        otherwise
            % Archimedean copulas
            %
            % Random pairs from these copulae can be generated sequentially: first
            % generate u1 as a uniform r.v.  Then generate u2 from the conditional
            % distribution F(u2 | u1; alpha) by generating uniform random values, then
            % inverting the conditional CDF.
            u1 = rand(n,1);
            p = rand(n,1);
            switch lower(family)
                case 'clayton'
                    % The inverse conditional CDF has a closed form for this
                    % copula.
                    if alpha > sqrt(eps)
                        u2 = u1.*(p.^(-alpha./(1+alpha)) - 1 + u1.^alpha).^(-1./alpha);
                    else
                        u2 = p;
                    end
                    u = [u1 u2];
                    
                case 'frank'
                    % The inverse conditional CDF has a closed form for this
                    % copula.
                    if abs(alpha) > log(realmax)
                        u2 = (alpha < 0) + sign(alpha).*u1; % u1 or 1-u1
                    elseif abs(alpha) > sqrt(eps)
                        u2 = -log((exp(-alpha.*u1).*(1-p)./p + exp(-alpha))./(1 + exp(-alpha.*u1).*(1-p)./p))./alpha;
                    else
                        u2 = p;
                    end
                    u = [u1 u2];
                    
                case {'gumbel' 'fgm' 'amh' 'arch12' 'arch14' 'gb' 'joe'}
                    % The inverse conditional CDF does not have a closed form for this
                    % copula.  The inversion must be done numerically.
                    u2 = condCDFinv(@conditionalcdf,u1,p,alpha,family);
                    u = [u1 u2]; 
            end           
    end
end


function u2 = condCDFinv(condCDF,u1,p,par, family)
%
%    CONDCDFINV Inverse conditional distribution function
%    
%    U2 = CONDCDFINV(CONDCDF,U1,P,ALPHA) returns U2 such that
%
%      CONDCDF(U1,U2,ALPHA) = P,
%
%  where CONDCDF is a function handle to a function that computes the
%  conditional cumulative distribution function of U2 given U1, for an
%  archimedean copula with parameter ALPHA.
%
% CONDCDFINV uses a simple binary chop search.  Newton's method or the
% secant method would probably be faster.

lower = zeros(size(p));
upper = ones(size(p));
width = 1;
tol = 1e-12;
while width > tol
    u2 = .5 .* (lower + upper);
    lo = feval(condCDF, family, u1,u2,par) < p;
    lower(lo) = u2(lo);
    upper(~lo) = u2(~lo);
    width = .5 .* width;
end

About Koders | Resources | Downloads | Support | Black Duck | Terms of Service | DMCA | Privacy Policy | Contact Us