/* License: LGPL Ref: Copied from this11/misc-2011/A1/wishart/Prog $OpenXM: OpenXM/src/hgm/mh/src/rk.c,v 1.18 2016/03/02 01:09:36 takayama Exp $ */ #include #include #include #include #include "sfile.h" #include "mh.h" #include "t-gsl_errno.h" #include "t-gsl_odeiv.h" extern int MH_RANK; extern int MH_M; extern MH_RF mh_rf; char *MH_Gfname; char *MH_Dfname; extern int MH_Mg; extern double *MH_Beta; extern double *MH_Ng; extern double MH_X0g; extern int MH_RawName; double MH_Hg = 0.001; static struct SFILE *Gf =NULL; static struct SFILE *Df =NULL; int MH_P95=0; int MH_Verbose=0; int MH_strategy=STRATEGY_DEFAULT; /* 0: rk4, 1:a-rk4 (adaptive) */ double MH_abserr = 1e-10; double MH_relerr = MH_RELERR_DEFAULT ; /* D_i = MH_abserr + MH_relerr*|y_i| If observed error E > D*110/100, the stepsize will be decreased. cf. GSL, 26.3 Adaptive Step-size control. */ int mh_rf_for_gsl(double t,const double y[],double f[],void *params) { (*mh_rf)(t,(double *)y,MH_RANK,f,MH_RANK); return(GSL_SUCCESS); } static int mypower(int x,int n) { int a,i; a = 1; for (i=0; i0?(xxn)); x += h) { if (Df) show_v(x,y, MH_RANK); if (Gf) { sprintf(swork,"%lf %le\n",x,y[0]); mh_fputs(swork,Gf); } /* Output 95% point */ if (MH_P95) { if ((MH_P95==1) && (y[0] >= 0.95)) { oxprintf("x=%le, y[0]=%lf\n",x,y[0]); MH_P95=2; }else if ((MH_P95==2) && (y[0] >=0.9500000001)) { oxprintf("x=%le, y[0]=%lf\n",x,y[0]); MH_P95=0; } } (*mh_rf)(x, y, MH_RANK, temp, MH_RANK); for (i = 0; i < MH_RANK; i++) k1[i] = h * temp[i]; for (i = 0; i < MH_RANK; i++) ty[i] = y[i] + 0.5 * k1[i]; (*mh_rf)(x + 0.5 * h, ty, MH_RANK, temp, MH_RANK); for (i = 0; i < MH_RANK; i++) k2[i] = h * temp[i]; for (i = 0; i < MH_RANK; i++) ty[i] = y[i] + 0.5 * k2[i]; (*mh_rf)(x + 0.5 * h, ty, MH_RANK, temp, MH_RANK); for (i = 0; i < MH_RANK; i++) k3[i] = h * temp[i]; for (i = 0; i < MH_RANK; i++) ty[i] = y[i] + k3[i]; (*mh_rf)(x + h, ty, MH_RANK, temp, MH_RANK); for (i = 0; i < MH_RANK; i++) k4[i] = h * temp[i]; for (i = 0; i < MH_RANK; i++) y[i] = y[i] + 1.0/6.0 * k1[i] + 1.0/3.0 * k2[i] + 1.0/3.0 * k3[i] + 1.0/6.0 * k4[i]; } }else { extern int MH_Dp; double dh; double mh_dp_orig; double x1; const gsl_odeiv_step_type *T = gsl_odeiv_step_rkf45; gsl_odeiv_step *s = gsl_odeiv_step_alloc(T, MH_RANK); gsl_odeiv_control *c = gsl_odeiv_control_y_new(MH_abserr, MH_relerr); /* We should use the relative error. hgm.cwishart(m=5,n=20,beta=c(1,2,3,4,5),x=20,x0=2,approxdeg=20); 0.977 hgm.cwishart(m=8,n=20,beta=c(1,2,3,4,5,5.6,5.7,5.8),x=30,x0=1,approxdeg=20); 0.962 (non-gsl) or 0.969 (gsl, abs error 0.0, relative error 1e-10), NaN abs=0, rel=1e-5 or abs=1e-18, rel=1e-6 ./mh causes NaN when rel error is 1e-10 on old 32bit machines. */ gsl_odeiv_evolve *e = gsl_odeiv_evolve_alloc(MH_RANK); gsl_odeiv_system sys = {mh_rf_for_gsl, NULL, 0, NULL}; sys.dimension = MH_RANK; /* oxprintf("MH_RANK=%d\n",MH_RANK); */ if (x0 >= xn) {oxprintfe("Error: x0 < x must hold.\n"); mh_exit(-30);} x = x0; if (MH_Dp > 0) dh = MH_Dp*h; else dh=xn-x0; mh_dp_orig = MH_Dp; MH_Dp=1; while (x < xn) { if (Df) show_v(x,y, MH_RANK); if (Gf) { sprintf(swork,"%lf %le\n",x,y[0]); mh_fputs(swork,Gf); } /* Output 95% point */ if (MH_P95) { if ((MH_P95==1) && (y[0] >= 0.95)) { oxprintf("x=%le, y[0]=%lf\n",x,y[0]); MH_P95=2; }else if ((MH_P95==2) && (y[0] >=0.9500000001)) { oxprintf("x=%le, y[0]=%lf\n",x,y[0]); MH_P95=0; } } x1 = x+dh; while ((x < x1) && (x < xn)) { int status = gsl_odeiv_evolve_apply(e, c, s, &sys, &x, x1, &h, y); if (status != GSL_SUCCESS) { oxprintfe("gsl_odeiv_evolve_apply failed.\n"); break; } } } gsl_odeiv_evolve_free(e); gsl_odeiv_control_free(c); gsl_odeiv_step_free(s); MH_Dp=mh_dp_orig; } if (MH_Verbose) oxprintf("x=%lf, y[0]=%lg\n",x,y[0]); result.x = x; result.rank = MH_RANK; result.y = (double *)mh_malloc(sizeof(double)*MH_RANK); /* todo, how to free it */ for (i=0; i= 0.0) MH_abserr = err[0]; if (err[1] >= 0.0) MH_relerr = err[1]; }