X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?p=CreaPhase.git;a=blobdiff_plain;f=octave_packages%2Fstatistics-1.1.3%2Fcopularnd.m;fp=octave_packages%2Fstatistics-1.1.3%2Fcopularnd.m;h=10033e0f614689080e64bd617c876dc545fee565;hp=0000000000000000000000000000000000000000;hb=f5f7a74bd8a4900f0b797da6783be80e11a68d86;hpb=1705066eceaaea976f010f669ce8e972f3734b05 diff --git a/octave_packages/statistics-1.1.3/copularnd.m b/octave_packages/statistics-1.1.3/copularnd.m new file mode 100644 index 0000000..10033e0 --- /dev/null +++ b/octave_packages/statistics-1.1.3/copularnd.m @@ -0,0 +1,281 @@ +## Copyright (C) 2012 Arno Onken +## +## This program 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. +## +## This program 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 this program. If not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{x} =} copularnd (@var{family}, @var{theta}, @var{n}) +## @deftypefnx {Function File} {} copularnd (@var{family}, @var{theta}, @var{n}, @var{d}) +## @deftypefnx {Function File} {} copularnd ('t', @var{theta}, @var{nu}, @var{n}) +## Generate random samples from a copula family. +## +## @subheading Arguments +## +## @itemize @bullet +## @item +## @var{family} is the copula family name. Currently, @var{family} can be +## @code{'Gaussian'} for the Gaussian family, @code{'t'} for the Student's t +## family, or @code{'Clayton'} for the Clayton family. +## +## @item +## @var{theta} is the parameter of the copula. For the Gaussian and Student's t +## copula, @var{theta} must be a correlation matrix. For bivariate copulas +## @var{theta} can also be a correlation coefficient. For the Clayton family, +## @var{theta} must be a vector with the same number of elements as samples to +## be generated or be scalar. +## +## @item +## @var{nu} is the degrees of freedom for the Student's t family. @var{nu} must +## be a vector with the same number of elements as samples to be generated or +## be scalar. +## +## @item +## @var{n} is the number of rows of the matrix to be generated. @var{n} must be +## a non-negative integer and corresponds to the number of samples to be +## generated. +## +## @item +## @var{d} is the number of columns of the matrix to be generated. @var{d} must +## be a positive integer and corresponds to the dimension of the copula. +## @end itemize +## +## @subheading Return values +## +## @itemize @bullet +## @item +## @var{x} is a matrix of random samples from the copula with @var{n} samples +## of distribution dimension @var{d}. +## @end itemize +## +## @subheading Examples +## +## @example +## @group +## theta = 0.5; +## x = copularnd ("Gaussian", theta); +## @end group +## +## @group +## theta = 0.5; +## nu = 2; +## x = copularnd ("t", theta, nu); +## @end group +## +## @group +## theta = 0.5; +## n = 2; +## x = copularnd ("Clayton", theta, n); +## @end group +## @end example +## +## @subheading References +## +## @enumerate +## @item +## Roger B. Nelsen. @cite{An Introduction to Copulas}. Springer, New York, +## second edition, 2006. +## @end enumerate +## @end deftypefn + +## Author: Arno Onken +## Description: Random samples from a copula family + +function x = copularnd (family, theta, nu, n) + + # Check arguments + if (nargin < 2) + print_usage (); + endif + + if (! ischar (family)) + error ("copularnd: family must be one of 'Gaussian', 't', and 'Clayton'"); + endif + + lower_family = lower (family); + + # Check family and copula parameters + switch (lower_family) + + case {"gaussian"} + # Gaussian family + if (isscalar (theta)) + # Expand a scalar to a correlation matrix + theta = [1, theta; theta, 1]; + endif + if (! ismatrix (theta) || any (diag (theta) != 1) || any (any (theta != theta')) || min (eig (theta)) <= 0) + error ("copularnd: theta must be a correlation matrix"); + endif + if (nargin > 3) + d = n; + if (! isscalar (d) || d != size (theta, 1)) + error ("copularnd: d must correspond to dimension of theta"); + endif + else + d = size (theta, 1); + endif + if (nargin < 3) + n = 1; + else + n = nu; + if (! isscalar (n) || (n < 0) || round (n) != n) + error ("copularnd: n must be a non-negative integer"); + endif + endif + + case {"t"} + # Student's t family + if (nargin < 3) + print_usage (); + endif + if (isscalar (theta)) + # Expand a scalar to a correlation matrix + theta = [1, theta; theta, 1]; + endif + if (! ismatrix (theta) || any (diag (theta) != 1) || any (any (theta != theta')) || min (eig (theta)) <= 0) + error ("copularnd: theta must be a correlation matrix"); + endif + if (! isscalar (nu) && (! isvector (nu) || length (nu) != n)) + error ("copularnd: nu must be a vector with the same number of rows as x or be scalar"); + endif + nu = nu(:); + if (nargin < 4) + n = 1; + else + if (! isscalar (n) || (n < 0) || round (n) != n) + error ("copularnd: n must be a non-negative integer"); + endif + endif + + case {"clayton"} + # Archimedian one parameter family + if (nargin < 4) + # Default is bivariate + d = 2; + else + d = n; + if (! isscalar (d) || (d < 2) || round (d) != d) + error ("copularnd: d must be an integer greater than 1"); + endif + endif + if (nargin < 3) + # Default is one sample + n = 1; + else + n = nu; + if (! isscalar (n) || (n < 0) || round (n) != n) + error ("copularnd: n must be a non-negative integer"); + endif + endif + if (! isvector (theta) || (! isscalar (theta) && size (theta, 1) != n)) + error ("copularnd: theta must be a column vector with the number of rows equal to n or be scalar"); + endif + if (n > 1 && isscalar (theta)) + theta = repmat (theta, n, 1); + endif + + otherwise + error ("copularnd: unknown copula family '%s'", family); + + endswitch + + if (n == 0) + # Input is empty + x = zeros (0, d); + else + + # Draw random samples according to family + switch (lower_family) + + case {"gaussian"} + # The Gaussian family + x = normcdf (mvnrnd (zeros (1, d), theta, n), 0, 1); + # No parameter bounds check + k = []; + + case {"t"} + # The Student's t family + x = tcdf (mvtrnd (theta, nu, n), nu); + # No parameter bounds check + k = []; + + case {"clayton"} + # The Clayton family + u = rand (n, d); + if (d == 2) + x = zeros (n, 2); + # Conditional distribution method for the bivariate case which also + # works for theta < 0 + x(:, 1) = u(:, 1); + x(:, 2) = (1 + u(:, 1) .^ (-theta) .* (u(:, 2) .^ (-theta ./ (1 + theta)) - 1)) .^ (-1 ./ theta); + else + # Apply the algorithm by Marshall and Olkin: + # Frailty distribution for Clayton copula is gamma + y = randg (1 ./ theta, n, 1); + x = (1 - log (u) ./ repmat (y, 1, d)) .^ (-1 ./ repmat (theta, 1, d)); + endif + k = find (theta == 0); + if (any (k)) + # Produkt copula at columns k + x(k, :) = u(k, :); + endif + # Continue argument check + if (d == 2) + k = find (! (theta >= -1) | ! (theta < inf)); + else + k = find (! (theta >= 0) | ! (theta < inf)); + endif + + endswitch + + # Out of bounds parameters + if (any (k)) + x(k, :) = NaN; + endif + + endif + +endfunction + +%!test +%! theta = 0.5; +%! x = copularnd ("Gaussian", theta); +%! assert (size (x), [1, 2]); +%! assert (all ((x >= 0) & (x <= 1))); + +%!test +%! theta = 0.5; +%! nu = 2; +%! x = copularnd ("t", theta, nu); +%! assert (size (x), [1, 2]); +%! assert (all ((x >= 0) & (x <= 1))); + +%!test +%! theta = 0.5; +%! x = copularnd ("Clayton", theta); +%! assert (size (x), [1, 2]); +%! assert (all ((x >= 0) & (x <= 1))); + +%!test +%! theta = 0.5; +%! n = 2; +%! x = copularnd ("Clayton", theta, n); +%! assert (size (x), [n, 2]); +%! assert (all ((x >= 0) & (x <= 1))); + +%!test +%! theta = [1; 2]; +%! n = 2; +%! d = 3; +%! x = copularnd ("Clayton", theta, n, d); +%! assert (size (x), [n, d]); +%! assert (all ((x >= 0) & (x <= 1)));