Multivariate Gaussian Code using GSL
카테고리 없음 2011. 6. 11. 16:29Source code by Ralph Silva
from here
/*************************************************************************************** * Multivariate Normal density function and random number generator * Multivariate Student t density function and random number generator * Wishart random number generator * Using GSL -> www.gnu.org/software/gsl * * Copyright (C) 2006 Ralph dos Santos Silva * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AUTHOR * Ralph dos Santos Silva, [EMAIL PROTECTED] * March, 2006 ***************************************************************************************/ #include <math.h> #include <gsl/gsl_sf_gamma.h> #include <gsl/gsl_rng.h> #include <gsl/gsl_randist.h> #include <gsl/gsl_vector.h> #include <gsl/gsl_matrix.h> #include <gsl/gsl_blas.h> #include <gsl/gsl_linalg.h> /*****************************************************************************************************************/ /*****************************************************************************************************************/ int rmvnorm(const gsl_rng *r, const int n, const gsl_vector *mean, const gsl_matrix *var, gsl_vector *result){ /* multivariate normal distribution random number generator */ /* * n dimension of the random vetor * mean vector of means of size n * var variance matrix of dimension n x n * result output variable with a sigle random vector normal distribution generation */ int k; gsl_matrix *work = gsl_matrix_alloc(n,n); gsl_matrix_memcpy(work,var); gsl_linalg_cholesky_decomp(work); for(k=0; k<n; k++) gsl_vector_set( result, k, gsl_ran_ugaussian(r) ); gsl_blas_dtrmv(CblasLower, CblasNoTrans, CblasNonUnit, work, result); gsl_vector_add(result,mean); gsl_matrix_free(work); return 0; } /*****************************************************************************************************************/ /*****************************************************************************************************************/ double dmvnorm(const int n, const gsl_vector *x, const gsl_vector *mean, const gsl_matrix *var){ /* multivariate normal density function */ /* * n dimension of the random vetor * mean vector of means of size n * var variance matrix of dimension n x n */ int s; double ax,ay; gsl_vector *ym, *xm; gsl_matrix *work = gsl_matrix_alloc(n,n), *winv = gsl_matrix_alloc(n,n); gsl_permutation *p = gsl_permutation_alloc(n); gsl_matrix_memcpy( work, var ); gsl_linalg_LU_decomp( work, p, &s ); gsl_linalg_LU_invert( work, p, winv ); ax = gsl_linalg_LU_det( work, s ); gsl_matrix_free( work ); gsl_permutation_free( p ); xm = gsl_vector_alloc(n); gsl_vector_memcpy( xm, x); gsl_vector_sub( xm, mean ); ym = gsl_vector_alloc(n); gsl_blas_dsymv(CblasUpper,1.0,winv,xm,0.0,ym); gsl_matrix_free( winv ); gsl_blas_ddot( xm, ym, &ay); gsl_vector_free(xm); gsl_vector_free(ym); ay = exp(-0.5*ay)/sqrt( pow((2*M_PI),n)*ax ); return ay; } /*****************************************************************************************************************/ /*****************************************************************************************************************/ int rmvt(const gsl_rng *r, const int n, const gsl_vector *location, const gsl_matrix *scale, const int dof, gsl_vector *result){ /* multivariate Student t distribution random number generator */ /* * n dimension of the random vetor * location vector of locations of size n * scale scale matrix of dimension n x n * dof degrees of freedom * result output variable with a single random vector normal distribution generation */ int k; gsl_matrix *work = gsl_matrix_alloc(n,n); double ax = 0.5*dof; ax = gsl_ran_gamma(r,ax,(1/ax)); /* gamma distribution */ gsl_matrix_memcpy(work,scale); gsl_matrix_scale(work,(1/ax)); /* scaling the matrix */ gsl_linalg_cholesky_decomp(work); for(k=0; k<n; k++) gsl_vector_set( result, k, gsl_ran_ugaussian(r) ); gsl_blas_dtrmv(CblasLower, CblasNoTrans, CblasNonUnit, work, result); gsl_vector_add(result, location); gsl_matrix_free(work); return 0; } /*****************************************************************************************************************/ /*****************************************************************************************************************/ double dmvt(const int n, const gsl_vector *x, const gsl_vector *location, const gsl_matrix *scale, const int dof){ /* multivariate Student t density function */ /* * n dimension of the random vetor * location vector of locations of size n * scale scale matrix of dimension n x n * dof degrees of freedom */ int s; double ax,ay,az=0.5*(dof + n); gsl_vector *ym, *xm; gsl_matrix *work = gsl_matrix_alloc(n,n), *winv = gsl_matrix_alloc(n,n); gsl_permutation *p = gsl_permutation_alloc(n); gsl_matrix_memcpy( work, scale ); gsl_linalg_LU_decomp( work, p, &s ); gsl_linalg_LU_invert( work, p, winv ); ax = gsl_linalg_LU_det( work, s ); gsl_matrix_free( work ); gsl_permutation_free( p ); xm = gsl_vector_alloc(n); gsl_vector_memcpy( xm, x); gsl_vector_sub( xm, location ); ym = gsl_vector_alloc(n); gsl_blas_dsymv(CblasUpper,1.0,winv,xm,0.0,ym); gsl_matrix_free( winv ); gsl_blas_ddot( xm, ym, &ay); gsl_vector_free(xm); gsl_vector_free(ym); ay = pow((1+ay/dof),-az)*gsl_sf_gamma(az)/(gsl_sf_gamma(0.5*dof)*sqrt( pow((dof*M_PI),n)*ax )); return ay; } /*****************************************************************************************************************/ /*****************************************************************************************************************/ int rwishart(const gsl_rng *r, const int n, const int dof, const gsl_matrix *scale, gsl_matrix *result){ /* Wishart distribution random number generator */ /* * n gives the dimension of the random matrix * dof degrees of freedom * scale scale matrix of dimension n x n * result output variable with a single random matrix Wishart distribution generation */ int k,l; gsl_matrix *work = gsl_matrix_calloc(n,n); for(k=0; k<n; k++){ gsl_matrix_set( work, k, k, sqrt( gsl_ran_chisq( r, (dof-k) ) ) ); for(l=0; l<k; l++){ gsl_matrix_set( work, k, l, gsl_ran_ugaussian(r) ); } } gsl_matrix_memcpy(result,scale); gsl_linalg_cholesky_decomp(result); gsl_blas_dtrmm(CblasLeft,CblasLower,CblasNoTrans,CblasNonUnit,1.0,result,work); gsl_blas_dsyrk(CblasUpper,CblasNoTrans,1.0,work,0.0,result); return 0; } /*************************************************************************************** * Multivariate Normal density function and random number generator * Multivariate Student t density function and random number generator * Wishart random number generator * Using GSL -> www.gnu.org/software/gsl * * Copyright (C) 2006 Ralph dos Santos Silva * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AUTHOR * Ralph dos Santos Silva, [EMAIL PROTECTED] * March, 2006 ***************************************************************************************/ int rmvnorm(const gsl_rng *r, const int n, const gsl_vector *mean, const gsl_matrix *var, gsl_vector *result); double dmvnorm(const int n, const gsl_vector *x, const gsl_vector *mean, const gsl_matrix *var); int rmvt(const gsl_rng *r, const int n, const gsl_vector *location, const gsl_matrix *scale, const int dof, gsl_vector *result); double dmvt(const int n, const gsl_vector *x, const gsl_vector *locationn, const gsl_matrix *scale, const int dof); int rwishart(const gsl_rng *r, const int n, const int dof, const gsl_matrix *scale, gsl_matrix *result); /*************************************************************************************** * A testing program for multivariate distributions * Using GSL -> www.gnu.org/software/gsl * Copyright (C) 2006 Ralph dos Santos Silva * * 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 2 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, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * AUTHOR * Ralph dos Santos Silva, [EMAIL PROTECTED] * March, 2006 ***************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <time.h> #include <math.h> /* GSL - GNU Scientific Library */ /* #define GSL_CHECK_RANGE_OFF */ #include <gsl/gsl_math.h> #include <gsl/gsl_rng.h> #include <gsl/gsl_cdf.h> /* ----------------------------- */ #include <gsl/gsl_vector.h> #include <gsl/gsl_matrix.h> /* ----------------------------- */ #include "rmv.h" int main(){ FILE *f; int k; unsigned long int initime; double result; gsl_vector *x = gsl_vector_calloc(3), *mean = gsl_vector_calloc(3); gsl_matrix *m = gsl_matrix_alloc(3,3), *rm = gsl_matrix_alloc(3,3); gsl_rng *r; time(&initime); r = gsl_rng_alloc(gsl_rng_mt19937); gsl_rng_set(r, initime); printf("The SEED is %li.\n\n",initime); gsl_matrix_set(m,0,0, 1.0); gsl_matrix_set(m,0,1, 0.2); gsl_matrix_set(m,0,2,-0.9); gsl_matrix_set(m,1,0, 0.2); gsl_matrix_set(m,1,1, 1.0); gsl_matrix_set(m,1,2, 0.1); gsl_matrix_set(m,2,0,-0.9); gsl_matrix_set(m,2,1, 0.1); gsl_matrix_set(m,2,2, 1.0); gsl_vector_set(x,0,0.1); gsl_vector_set(x,1,0.1); gsl_vector_set(x,2,0.1); result = dmvnorm(3,x,mean,m); fprintf(stdout,"norm = %g\n", result); gsl_vector_set(x,0,0.1); gsl_vector_set(x,1,0.1); gsl_vector_set(x,2,0.1); result = dmvt(3,x,mean,m,5); fprintf(stdout,"t = %g\n", result); f = fopen("test-n.txt","w"); for(k=0; k<10; k++){ rmvnorm(r,3,mean,m,x); fprintf(f, "%g %g %g\n",gsl_vector_get(x,0),gsl_vector_get(x,1),gsl_vector_get(x,2)); } fclose(f); f = fopen("test-t.txt","w"); for(k=0; k<10; k++){ rmvt(r,3,mean,m,5,x); fprintf(f, "%g %g %g\n",gsl_vector_get(x,0),gsl_vector_get(x,1),gsl_vector_get(x,2)); } fclose(f); f = fopen("test-w.txt","w"); for(k=0; k<1000; k++){ rwishart(r,3,5,m,rm); fprintf(f, "%g %g %g\n",gsl_matrix_get(rm,0,0),gsl_matrix_get(rm,0,1),gsl_matrix_get(rm,0,2)); fprintf(f, "%g %g %g\n",gsl_matrix_get(rm,1,0),gsl_matrix_get(rm,1,1),gsl_matrix_get(rm,1,2)); fprintf(f, "%g %g %g\n",gsl_matrix_get(rm,2,0),gsl_matrix_get(rm,2,1),gsl_matrix_get(rm,2,2)); } fclose(f); return 0; }Makefile
# Copyright (C) 2006 Ralph dos Santos Silva #LIBDIR = /home/rsilva1/local/libsun LIBDIR = /usr/lib INCLUDEDIR = /usr/include LIBGSL = -lgsl LIBCBLAS = -lcblas LIBATLAS = -latlas LIBMATH = -lm CFLAGS = -O2 -static -g -Wall -W -DHAVE_INLINE -I$(INCLUDEDIR) CC = gcc .c.o: $(CC) $(CFLAGS) -c $< all: test.o rmv.o $(CC) -o test test.o rmv.o -L$(LIBDIR) $(LIBGSL) $(LIBCBLAS) $(LIBATLAS) $(LIBMATH) clean: rm -f *.o test