#include "ilt.h" /* ####################################################################### */ /* Setting Parameters */ /* default values */ /* ####################################################################### */ void SetParameter(HEAD *head){ head->newton_tol = 1e-8; head->alpha_tol = 1e-4; head->confirm = 0; head->dimension = 2; strcpy(head->outbase, ""); head->Atype = 0; head->sfactor = 1.0e-4; head->alpha0 = 0.1; head->alpha_loop_max = 5000; head->newton_loop_max = 5000; head->sigma0 = 0; head->DXnum = 0; head->DYnum = 0; head->TXnum = 50; head->TXmin = 1.0e-4; head->TXmax = 10; strcpy(head->TXspace, "log"); strcpy(head->TXtype, "T1"); head->TYnum = 50; head->TYmin = 1.0e-4; head->TYmax = 10; strcpy(head->TYspace, "log"); strcpy(head->TYtype, "T2"); head->newton_loop = 0; head->alpha_loop = 0; head->s_taget = 0.0; head->alpha_start = -4; /* log10 space */ head->alpha_end = 6; /* log10 space */ head->alpha_num = 20; } /* ####################################################################### */ /* Transpose Matrix */ /* ####################################################################### */ void Transpose(MATRIX *A, MATRIX *B){ int x; int i, j, p; div_t temp; B->m = A->n; B->n = A->m; B->a = (double*)malloc(sizeof(double)*B->m*B->n); for (x=0; xm*A->n; x++){ temp = div(x, A->m); i = temp.rem; j = temp.quot; p = i*B->m + j; B->a[p] = A->a[x]; } } /* ####################################################################### */ /* Kronecker (Tensor) product */ /* ####################################################################### */ void Kronecker(MATRIX *k1, MATRIX *k2, MATRIX *k0){ int i, j, k, l; int row, col; int p; int x, y; div_t temp; k0->m = k1->m*k2->m; k0->n = k1->n*k2->n; k0->a = (double*)malloc(sizeof(double)*k0->m*k0->n); for (x=0; xm*k1->n; x++){ temp = div(x, k1->m); i = temp.rem; j = temp.quot; for (y=0; ym*k2->n; y++){ temp = div(y, k2->m); k = temp.rem; l = temp.quot; row = i*k2->m + k; col = j*k2->n + l; p = col * k0->m + row; k0->a[p] = k1->a[x] * k2->a[y]; } } } /* ####################################################################### */ /* Lexicographic row major */ /* ####################################################################### */ void Lexicographic(MATRIX *A, MATRIX *Al){ int i, p; const int incr = 1; const int mn = A->m*A->n; div_t temp; Al->a = (double*)malloc(sizeof(double)*A->m*A->n); Al->m = A->m * A->n; Al->n = 1; dcopy_(&mn, A->a, &incr, Al->a, &incr); for (i=0; in); p = temp.rem * A->m + temp.quot; Al->a[i] = A->a[p]; } } /* ####################################################################### */ /* 行列の掛け算 C = A.a*B.a + beta*C.a */ /* alpha=beta=1 */ /* ####################################################################### */ void MultiplyMatrix(MATRIX *A, MATRIX *B, MATRIX *C, char aopt[], char bopt[]){ int m, k, n; int lda, ldb, ldc; double alpha = 1.0; double beta = 0.0; int info; if (strcmp(aopt, "N")==0){ m = A->m; k = A->n; lda = A->m; ldb = B->m; ldc = A->m; C->m = A->m; } if (strcmp(aopt, "T")==0){ m = A->n; k = A->m; lda = A->m; ldb = B->m; ldc = A->n; C->m = A->n; } if (strcmp(bopt, "N")==0){ n = B->n; ldb = B->m; C->n = B->n; } if (strcmp(bopt, "T")==0){ n = B->m; ldb = B->m; C->n = B->m; } C->a = (double*)malloc(sizeof(double)*C->m*C->n); dgemm_(aopt, bopt, &m, &n, &k, &alpha, A->a, &lda, B->a, &ldb, &beta, C->a, &ldc, &info); } /* ####################################################################### */ /* 配列の出力 */ /* ####################################################################### */ void PrintList(const double *x, const int m){ int i; printf("Vector size: %d\n", m); for (i=0; im = points; x->n = 1; x->a = (double*)malloc(sizeof(double)*points); if (strcmp(type, "log")==0){ start = log10(start); end = log10(end); dx = (end - start)/(double)(points-1); for (i=0; ia[i] = pow(10, start+i*dx); } else if (strcmp(type, "linear")==0){ start = start; end = end; dx = (end - start)/(double)(points-1); for (i=0; ia[i] = start+i*dx; } else { printf("Kernel space %s is strange.", type); Error(); } } /* ####################################################################### */ /* kernel生成 */ /* ####################################################################### */ void MakeKernel(MATRIX *t, MATRIX *x, char *type, MATRIX *k){ int i, j, c=0; if ((strcmp(type, "T1inf") == 0) || (strcmp(type, "T2inf") == 0) || (strcmp(type, "T2ginf") == 0) ){ k->a = (double*)malloc(sizeof(double)*t->m*(x->m+1)); k->m = t->m; k->n = x->m + 1; } else { k->a = (double*)malloc(sizeof(double)*t->m*x->m); k->m = t->m; k->n = x->m; } if (strcmp(type, "T1") == 0 || strcmp(type, "T1inf") == 0){ for (i=0; im; i++){ for (j=0; jm; j++){ k->a[c] = 1.0-2.0*exp(-t->a[j]/x->a[i]); c++; } } } if (strcmp(type, "T2") == 0 || strcmp(type, "T2inf") == 0 || strcmp(type, "T1p") == 0){ for (i=0; im; i++){ for (j=0; jm; j++){ k->a[c] = exp(-t->a[j]/x->a[i]); c++; } } } if (strcmp(type, "D") == 0 ){ for (i=0; im; i++){ for (j=0; jm; j++){ k->a[c] = exp(-t->a[j]*x->a[i]); c++; } } } if (strcmp(type, "T2g") == 0 || strcmp(type, "T2ginf") == 0){ for (i=0; im; i++){ for (j=0; jm; j++){ k->a[c] = exp(-0.5*(t->a[j]/x->a[i])*(t->a[j]/x->a[i])); c++; } } } /* base lineの継ぎ足し */ if (strcmp(type, "T1inf") == 0 || strcmp(type, "T2inf") == 0|| strcmp(type, "T2ginf") == 0){ for (j=0; jm; j++){ k->a[c] = 1.0; c++; } } } /* ####################################################################### */ /* SVD compress */ /* A = U * S * Vt */ /* ####################################################################### */ void SvdCompress(MATRIX *A, MATRIX *uz, MATRIX *sz, MATRIX *vz, double sfactor){ int i, j; const int incr = 1; const int m = A->m, n= A->n, mn = A->m*A->n; const int lwork=5*m*n; int info; double *U, *Vt, *Aa, *work; MATRIX S; (m < n) ? (S.m = A->m) : (S.m = A->n); S.n = 1; Aa = malloc(sizeof(double)*m*n); U = malloc(sizeof(double)*m*m); S.a = malloc(sizeof(double)*m*n); Vt = malloc(sizeof(double)*n*n); work = malloc(sizeof(double)*lwork); dcopy_(&mn, A->a, &incr, Aa, &incr); dgesvd_("A", "A", &m, &n, Aa, &m, S.a, U, &m, Vt, &n, work, &lwork, &info); if (info != 0){ printf("svd is fault!!! info=%d\n", info); exit(1); } /* 切り捨てずに採用するランク数の計算 */ for (i=0; S.a[i]>S.a[0]*sfactor; i++); sz->m = i; sz->n = i; sz->a = (double*)malloc(sizeof(double) * sz->m * sz->n); uz->m = m; uz->n = i; uz->a = (double*)malloc(sizeof(double) * uz->m * uz->n); vz->m = i; vz->n = n; vz->a = (double*)malloc(sizeof(double) * vz->m * vz->n); /* 圧縮した行列の生成 */ for (i=0; i < (sz->m*sz->n); i++) sz->a[i] = 0.0; /* 初期化 */ for (i=0; i < sz->n; i++) sz->a[i*(sz->n+1)] = S.a[i]; /* diagonalだけ */ for (i=0; i < (uz->n*uz->m); i++) uz->a[i] = U[i]; for (i=0; i < (vz->n); i++){ for (j=0; j < vz->m; j++){ vz->a[j+i*vz->m] = Vt[j+i*n]; } } free(S.a); free(Aa); free(U); free(Vt); free(work); } /* ####################################################################### */ /* NNLSで初期値を決める */ /* ####################################################################### */ void Calcf0(MATRIX *k0, MATRIX *mz, double *f0){ double rnorm; const int incr = 1; const int m=k0->m; const int n=k0->n; const int mn=k0->m*k0->n; int index[k0->n]; int mode; double *mn_mem, *m_mem, *m_mem2, *n_mem; mn_mem = malloc(sizeof(double)*k0->m*k0->n); m_mem = malloc(sizeof(double)*k0->m); m_mem2 = malloc(sizeof(double)*k0->m); n_mem = malloc(sizeof(double)*k0->n); dcopy_(&mn, k0->a, &incr, mn_mem, &incr); dcopy_(&m, mz->a, &incr, m_mem, &incr); nnls_c(mn_mem, &m, &m, &n, m_mem, f0, &rnorm, n_mem, m_mem2, index, &mode); free(mn_mem); free(m_mem); free(m_mem2); free(n_mem); } void CalcSim1D(MATRIX *k, double *f, double *baseline, MATRIX *Msim, INDATA *d, HEAD *head){ int incr = 1; double alpha = 1.0, beta = 0.0; double *deltaM; double one_ = -1.0; Msim->a = malloc(sizeof(double)*k->m); deltaM = malloc(sizeof(double)*k->m); dgemv_("N", &k->m, &k->n, &alpha, k->a, &k->m, f, &incr, &beta, Msim->a, &incr); if (strcmp(head->TXtype, "T2inf")==0){ baseline[0] = f[k->n-1]; } dcopy_(&k->m, Msim->a, &incr, deltaM, &incr); daxpy_(&k->m, &one_, d->m.a, &incr, deltaM, &incr); head->sigma = dnrm2_(&k->m, deltaM, &incr)/sqrt(k->m); free(deltaM); } void CalcSim(MATRIX *k1, MATRIX *k2, double *f, double *baseline, MATRIX *Msim, INDATA *d, HEAD *head){ int i, j, k=0, mn = k1->m*k2->n; int mm = k1->n * k2->n; MATRIX F, KF; div_t temp; double *deltaM; double one_ = -1.0; int incr = 1; F.m = k1->n; F.n = k2->n; F.a = malloc(sizeof(double)*F.m*F.n); deltaM = malloc(sizeof(double)*mm); for (i=0; iTXtype, "T1inf") == 0){ j = 0; for (i=0; ia, &incr, deltaM, &incr); daxpy_(&mm, &one_, d->m.a, &incr, deltaM, &incr); head->sigma = dnrm2_(&mm, deltaM, &incr)/sqrt(mm); free(F.a); free(deltaM); } void Copyright(){ int i; printf("\n"); for (i=0; i<70; i++) printf("-"); printf("\n"); printf("1D- and 2D-ILT program, MAY 2014\n"); printf("Author: T. Ohkubo (Chiba University)\n\n"); printf("The program can not be distributed without author's permission.\n"); printf("Use of this program is limited to non-profit or evaluation purposes."); printf("\n"); for (i=0; i<70; i++) printf("-"); printf("\n"); printf("\n"); } int main(int argc, char** argv){ INDATA d; MATRIX k0, k1, k2, s1z, s2z, u1z, u2z, v1z, v2z; MATRIX k1z, k2z, mz_tmp1, mz_tmp2, mz, msim; MATRIX x, y; /* T1とT2の離散化データ */ double *f, *baseline; HEAD head; Copyright(); SetParameter(&head); SetArgment(argc, argv, &head); MakeKspace(head.TXmin, head.TXmax, head.TXnum, &x, head.TXspace); MakeKspace(head.TYmin, head.TYmax, head.TYnum, &y, head.TYspace); if (head.dimension == 2){ SetDataSize(&head, &d); ReadData(&head, &d); Confirm(&head, &d); printf("Making kernel...\n"); MakeKernel(&d.u, &x, head.TXtype, &k1); MakeKernel(&d.v, &y, head.TYtype, &k2); printf("SVD compressing...\n"); printf(" Kernel size (K1): %d*%d\n", k1.m, k1.n); printf(" Kernel size (K2): %d*%d\n", k2.m, k2.n); SvdCompress(&k1, &u1z, &s1z, &v1z, head.sfactor); SvdCompress(&k2, &u2z, &s2z, &v2z, head.sfactor); printf("Making compress kernel...\n"); MultiplyMatrix(&s1z, &v1z, &k1z, "N", "N"); MultiplyMatrix(&s2z, &v2z, &k2z, "N", "N"); printf(" Kernel size (K1): %d*%d\n", k1z.m, k1z.n); printf(" Kernel size (K2): %d*%d\n", k2z.m, k2z.n); head.s1 = k1z.m; head.N1 = k1.m; head.s2 = k2z.m; head.N2 = k2.m; MultiplyMatrix(&u1z, &d.m, &mz_tmp1, "T", "N"); MultiplyMatrix(&mz_tmp1, &u2z, &mz_tmp2, "N", "N"); Lexicographic(&mz_tmp2, &mz); Kronecker(&k1z, &k2z, &k0); /* mz, k0以外のmallocしたメモリをrelease */ free(s1z.a); free(s2z.a); free(v1z.a); free(v2z.a); free(u1z.a); free(u2z.a); free(k1z.a); free(k2z.a); free(mz_tmp1.a); free(mz_tmp2.a); } if (head.dimension == 1){ ReadData1D(&head, &d); Confirm(&head, &d); printf("Making kernel...\n"); MakeKernel(&d.u, &x, head.TXtype, &k1); printf("Making compress kernel...\n"); SvdCompress(&k1, &u1z, &s1z, &v1z, head.sfactor); MultiplyMatrix(&s1z, &v1z, &k0, "N", "N"); head.s1 = k0.m; head.N1 = k1.m; k2.n = 1; printf(" Kernel size (K1): %d*%d\n", k0.m, k0.n); MultiplyMatrix(&u1z, &d.m, &mz, "T", "N"); } printf("Calculating initial F using NNLS... \n"); f = malloc(sizeof(double)*k0.n); baseline = malloc(sizeof(double)*k2.n); Calcf0(&k0, &mz, f); if (head.s_taget == 0) { printf("Start BRD routine...\n"); BRDAlphaLoop(&k0, &mz, &head, f, &k1, &k2, &d); } else { printf("Start S-curve routine...\n"); ScurveAlphaLoop(&k0, &mz, &head, f, &k1, &k2, &d); } printf("Output results...\n"); if (head.dimension == 2){ CalcSim(&k1, &k2, f, baseline, &msim, &d, &head); OutputDistr(&head, &x, &y, f, baseline); OutputDecay(&head, &d, &x, &y, &msim); } if (head.dimension == 1){ CalcSim1D(&k1, f, baseline, &msim, &d, &head); OutputDistr1D(&head, &x, f, baseline); OutputDecay1D(&head, &d, &x, &msim); } Copyright(); return 0; }