#include #include #include #include #define XY (0) #define XYT (dim*(dim+1)) #define SIGMA_MU (2*dim*(dim+1)) #define DYGI (3*dim*(dim+1)) double hgm_ko_orthant(int dimension, double *sigma, double *mu, double rk_step_size); static int dim; static int rank; static void set_xy(double *x, double *y, const double *sigma, const double *mu); static void set_initial_g(double *g, const double *x); static void update_xy(double t, double *param); static void cal_sigmaI_muI(int I, double *param); static void cal_dygI(int I, const double *g, double *param); static double get_dxgI(const int i, const int j, const int I, const double *g, const double *param); static int function(double t, const double g[], double dg[], void *param); static void runge_kutta(double *g, const double *x, const double *y, const double rk_step_size); static double get_prob(double g, const double *sigma, const double *mu); #ifdef _DEBUG /* for debugs */ void test_dgetrf_(void); void test_dpotri_(void); static void test_function(double t, const double g[], double dg[], void *param); void test_runge_kutta(void); void test_update_xy(void); void test_cal_sigmaI_muI(void); static void subst(double *Pfaff, double t); void test1(void); void test2(void); void test3(void); #endif double hgm_ko_orthant(int dimension, double *sigma, double *mu, double rk_step_size) { dim = dimension; rank = 1 << dim; double g[rank], x[dim*dim], y[dim]; set_xy(x,y,sigma,mu); set_initial_g(g, x); runge_kutta(g, x, y, rk_step_size); return get_prob(g[rank-1], sigma, mu); } static void set_xy(double *x, double *y, const double *sigma, const double *mu) { int info; /* x <- -0.5 * (sigma)^(-1) */ /* y <- (sigma)^(-1) * mu */ cblas_dcopy(dim*dim, sigma,1, x,1); dpotrf_("U", &dim, x, &dim, &info); dpotri_("U", &dim, x, &dim, &info); cblas_dsymv(CblasColMajor, CblasUpper, dim, 1.0,x,dim, mu,1, 0.0,y,1); cblas_dscal(dim*dim, -0.5, x, 1); } static void set_initial_g(double *g, const double *x) { int i,I; for(I=0; I 1.0 */ /* g'(t) = F(t, g(t)) */ double g[2] = {1.0, 1.0}; /* initial value */ rank = 2; double dg[rank], k1[rank],k2[rank], k3[rank], k4[rank]; double t = 0.0; /* initial point */ double h = 0.0001; double h2 = 0.5*h; while (t < 1.0){ /* k1 <- F(t, g) , dg += k1 */ test_function(t, g, k1, NULL); cblas_dcopy(rank, k1,1, dg,1); /* k2 <- F(t+0.5*h,g+0.5*h*k1), dg += 2*k2 */ cblas_dscal(rank, h2, k1, 1); cblas_daxpy(rank, 1.0, g,1, k1,1); test_function(t+h2, k1, k2, NULL); cblas_daxpy(rank, 2.0, k2,1, dg,1); /* k3 <- Pfaff(t+h/2) * (phi + h/2*k2), dphi += 2*k3 */ cblas_dscal(rank, h2, k2, 1); cblas_daxpy(rank, 1.0, g,1, k2,1); test_function(t+h2, k2, k3, NULL); cblas_daxpy(rank, 2.0, k3,1, dg,1); /* k3 <- Pfaff(t+h) * (phi + h*k3), dphi += k4 */ cblas_dscal(rank, h, k3, 1); cblas_daxpy(rank, 1.0, g,1, k3,1); test_function(t+h2, k3, k4, NULL); cblas_daxpy(rank, 1.0, k4,1, dg,1); /* phi += h * dphi /6 */ cblas_daxpy(rank, h/6.0, dg,1, g,1); t += h; } printf("g(1)=[%lf %lf]\n", g[0], g[1]); } void test_update_xy(void) { dim = 2; double params[12] = {1.0,2.0,3.0,4.0, 5.0,6.0, 0,0,0,0, 0,0}; update_xy(0.5, params); int i; for ( i = 0; i < 12; i++) printf("%lf ", params[i]); printf("\n"); } void test_cal_sigmaI_muI(void) { dim = 2; double param[18] = {0,0,0,0,0,0, -0.5,0,0,-0.5,1,0, 0,0,0,0,0,0}; //double param[18] = {0,0,0,0,0,0, 2,1,1,5,1,2, 0,0,0,0,0,0}; //double param[18] = {0,0,0,0,0,0, 1,0.5,0.5,1,1,2, 0,0,0,0,0,0}; cal_sigmaI_muI(3, param); printf("%lf %lf\n%lf %lf\n%lf %lf\n\n", param[12],param[14],param[13],param[15],param[16],param[17]); cal_sigmaI_muI(2, param); printf("%lf %lf\n%lf %lf\n%lf %lf\n\n", param[12],param[14],param[13],param[15],param[16],param[17]); cal_sigmaI_muI(1, param); printf("%lf %lf\n%lf %lf\n%lf %lf\n\n", param[12],param[14],param[13],param[15],param[16],param[17]); return; } void subst(double Pfaff[], double t) { Pfaff[24] = -0.5 * t; /* 3 + 3*7 */ Pfaff[40] = -t; /* 5 + 5*7 */ Pfaff[48] = -t; /* 6 + 6*7 */ } #define TEST1rank 7 void test1() { double phi[TEST1rank] = {0, 0, 0, 0, 1, 1, 1}; double Pfaff[TEST1rank*TEST1rank] = { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1.0/2.0, 1.0/2.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; double t = 0.0; double h = 0.001; double h2 = 0.5*h; double k1[TEST1rank],k2[TEST1rank],k3[TEST1rank],k4[TEST1rank],dphi[TEST1rank]; int i; while (t < 10){ /* k1 <- Pfaff(t) * phi , dphi += k1 */ subst(Pfaff,t); cblas_dgemv(CblasRowMajor, CblasNoTrans,TEST1rank,TEST1rank, 1.0,Pfaff,TEST1rank, phi,1, 0.0,k1,1); cblas_dcopy(TEST1rank, k1,1, dphi,1); /* k2 <- Pfaff(t+h/2) * (phi + h/2*k1), dphi += 2*k2 */ subst(Pfaff,t+h2); cblas_dscal(TEST1rank, h2, k1, 1); cblas_daxpy(TEST1rank, 1.0, phi,1, k1,1); cblas_dgemv(CblasRowMajor, CblasNoTrans,TEST1rank,TEST1rank, 1.0,Pfaff,TEST1rank, k1,1, 0.0,k2,1); cblas_daxpy(TEST1rank, 2.0, k2,1, dphi,1); /* k3 <- Pfaff(t+h/2) * (phi + h/2*k2), dphi += 2*k3 */ cblas_dscal(TEST1rank, h2, k2, 1); cblas_daxpy(TEST1rank, 1.0, phi,1, k2,1); cblas_dgemv(CblasRowMajor, CblasNoTrans,TEST1rank,TEST1rank, 1.0,Pfaff,TEST1rank, k2,1, 0.0,k3,1); cblas_daxpy(TEST1rank, 2.0, k3,1, dphi,1); /* k3 <- Pfaff(t+h) * (phi + h*k3), dphi += k4 */ subst(Pfaff,t+h); cblas_dscal(TEST1rank, h, k3, 1); cblas_daxpy(TEST1rank, 1.0, phi,1, k3,1); cblas_dgemv(CblasRowMajor, CblasNoTrans,TEST1rank,TEST1rank, 1.0,Pfaff,TEST1rank, k3,1, 0.0,k4,1); cblas_daxpy(TEST1rank, 1.0, k4,1, dphi,1); /* phi += h * dphi /6 */ cblas_daxpy(TEST1rank, h/6.0, dphi,1, phi,1); t += h; } phi[0] *= 1.0 / (2*M_PI); phi[1] *= 1.0 / sqrt(2*M_PI); phi[2] *= 1.0 / sqrt(2*M_PI); phi[3] *= 1.0 / sqrt(2*M_PI); for (i = 0; i < TEST1rank; i++) printf("%lf ", phi[i]); printf("\n"); return; } void test2(void) { /* g: 1.0000000000 1.2533141373 1.2533141373 1.5707963268 probability=0.250000000 double sigma[4] = { 1.0, 0.0, 0.0, 1.0}; double mu[2] = {0.0, 0.0}; OK! g: 1.0000000000 3.4770518132 1.2533141373 4.3578381936 probability=0.420672373 double sigma[4] = { 1.0, 0.0, 0.0, 1.0}; double mu[2] = {1.0, 0.0}; OK! result = 0.707860982 g: 1.0000000000 3.4770518117 3.4770518117 12.0898893056 double sigma[4] = { 1.0, 0.0, 0.0, 1.0}; double mu[2] = {1.0, 1.0}; OK! g: 1.0000000000 2.5481580894 1.0854018818 5.6544969464 probability=0.630283928 */ double sigma[4] = { 1.0, 0.5, 0.5, 1.0}; double mu[2] = {1.0, 0.5}; dim = 2; rank = 1 << dim; printf("dim=%d, rank=%d\n", dim, rank); double x[dim*dim], y[dim]; set_xy(x,y,sigma,mu); printf("x=[%lf %lf]\n", x[0], x[2]); printf(" [%lf %lf]\n", 0.0, x[3]); printf("y=[%lf %lf]\n", y[0], y[1]); double g[rank]; set_initial_g(g, x); printf("g=[%lf %lf %lf %lf]\n", g[0], g[1], g[2], g[3]); runge_kutta(g, x, y, 1e-03); printf("g=[%lf %lf %lf %lf]\n", g[0], g[1], g[2], g[3]); double result = get_prob(g[rank-1], sigma, mu); printf("prob=%lf\n", result); return ; } void test3(void) { /* g: 1.0000000000 2.5481580894 1.0854018818 5.6544969464 probability=0.630283928 */ double sigma[4] = { 1.0, 0.5, 0.5, 1.0}; double mu[2] = {1.0, 0.5}; //set_rk_step_size(1e-6); double prob = hgm_ko_orthant(2, sigma, mu, 1e-3); printf("%lf\n", prob); } #endif