'gaussian'에 해당되는 글 1건

  1. 2011.06.11 Multivariate Gaussian Code using GSL 1

Multivariate Gaussian Code using GSL

카테고리 없음 2011. 6. 11. 16:29
Source 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

: