Import existing OSILAP source code
This commit is contained in:
+254
@@ -0,0 +1,254 @@
|
||||
#include "ilt.h"
|
||||
|
||||
/* ####################################################################### */
|
||||
/* 最適化したfから圧縮無しのσ^2を求める */
|
||||
/* ####################################################################### */
|
||||
double CalcSigma(MATRIX *K1, MATRIX *K2, double *f, HEAD *head, INDATA *d){
|
||||
int i, incr = 1;
|
||||
int m1 = K1->m, m2 = K2->m;
|
||||
int n1 = K1->n, n2 = K2->n;
|
||||
int nn = n1*n2, mm = m1*m2;
|
||||
int info;
|
||||
double one=1.0, one_=-1.0, zero = 0.0, chi, sigma=0;
|
||||
double *KF, *F, *M;
|
||||
div_t temp;
|
||||
|
||||
if (head->dimension == 2){
|
||||
KF = malloc(sizeof(double)*m1*n2);
|
||||
F = malloc(sizeof(double)*nn);
|
||||
M = malloc(sizeof(double)*m1*m2);
|
||||
/* fから行列Fを生成 */
|
||||
for (i=0; i<nn; i++){
|
||||
temp = div(i, n2);
|
||||
F[temp.rem*n1 + temp.quot] = f[i];
|
||||
}
|
||||
|
||||
/* K1*Fの計算 */
|
||||
dgemm_("N", "N", &m1, &n2, &n1, &one, K1->a, &m1,
|
||||
F, &n1, &zero, KF, &m1, &info);
|
||||
/* (K1*F)*K2Tの計算 */
|
||||
dgemm_("N", "T", &m1, &m2, &n2, &one, KF, &m1,
|
||||
K2->a, &m2, &zero, M, &m1, &info);
|
||||
/* M = -Mexp + Mcalの計算 */
|
||||
daxpy_(&mm, &one_, d->m.a, &incr, M, &incr);
|
||||
/* ||Mcal - Msim|| */
|
||||
chi = dnrm2_(&mm, M, &incr);
|
||||
/* sigma = σ^2 = ||KF-M||^2/m */
|
||||
sigma = chi*chi/mm;
|
||||
free(KF);
|
||||
free(F);
|
||||
free(M);
|
||||
}
|
||||
if (head->dimension == 1){
|
||||
M = malloc(sizeof(double)*m1);
|
||||
dgemv_("N", &m1, &n1, &one, K1->a, &m1, f, &incr, &zero, M, &incr);
|
||||
/* M = -Mexp + Mcalの計算 */
|
||||
daxpy_(&m1, &one_, d->m.a, &incr, M, &incr);
|
||||
chi = dnrm2_(&m1, M, &incr);
|
||||
/* sigma = σ^2 = ||KF-M||^2/m */
|
||||
sigma = chi*chi/m1;
|
||||
free(M);
|
||||
}
|
||||
return sigma;
|
||||
}
|
||||
|
||||
/* ####################################################################### */
|
||||
/* Scurve法でalpha_optを求める */
|
||||
/* ####################################################################### */
|
||||
void ScurveAlphaLoop(MATRIX *K0, MATRIX *Mz, HEAD *head, double *f,
|
||||
MATRIX *k1, MATRIX *k2, INDATA *d){
|
||||
int m = K0->m;
|
||||
int n = K0->n;
|
||||
int i, j, pnt = 0, incr = 1;
|
||||
int alpha_num=head->alpha_num;
|
||||
double *kz, *mz, *cr, *aI, *H;
|
||||
double alpha, sigma;
|
||||
double zero = 0.0, one = 1.0;
|
||||
double alpha_s = head->alpha_start, alpha_e = head->alpha_end;
|
||||
double s_target=head->s_taget, alpha_log;
|
||||
double *alpha_list, *sigma_list, *grad;
|
||||
double *t = NULL;
|
||||
|
||||
kz = K0->a;
|
||||
mz = Mz->a;
|
||||
cr = malloc(sizeof(double)*m);
|
||||
aI = malloc(sizeof(double)*m*m);
|
||||
H = malloc(sizeof(double)*n*n);
|
||||
alpha_list = (double *)malloc(sizeof(double)*alpha_num);
|
||||
sigma_list = (double *)malloc(sizeof(double)*alpha_num);
|
||||
grad = malloc(sizeof(double)*(alpha_num-1));
|
||||
/* alphaのグリッド生成 */
|
||||
for (i=0; i<alpha_num; i++){
|
||||
alpha_log = alpha_s + (double)i*(alpha_e-alpha_s)/(alpha_num-1);
|
||||
alpha_list[i] = pow(10, alpha_log);
|
||||
}
|
||||
|
||||
/* alphaI (diagonal) とH (diagonal)の初期化 */
|
||||
for (i=0; i<(n*n); i++) H[i] = 0.0;
|
||||
for (i=0; i<m*m; i++) aI[i] = 0.0;
|
||||
|
||||
/* ここからalphaのloop */
|
||||
for (j=alpha_num-1; j>=0; j--){
|
||||
/* alphaI (diagonal)の初期化*/
|
||||
for (i=0; i<m; i++) aI[i*(m+1)] = alpha_list[j];
|
||||
/* BRDでcrの最適化 */
|
||||
BRDnewton_modify(kz, mz, aI, cr, H, head, &m, &n);
|
||||
/* crからfの計算 f= kz'*cr */
|
||||
dgemv_("T", &m, &n, &one, kz, &m, cr, &incr, &zero, f, &incr);
|
||||
/* fi>0 だけが解 */
|
||||
for (i=0; i<n; i++) (f[i] < 0) ? (f[i] = 0.0) : (f[i] = f[i]);
|
||||
/* 圧縮前のカーネルを使って圧縮ノイズの標準偏差を求める */
|
||||
sigma_list[j] = CalcSigma(k1, k2, f, head, d);
|
||||
head->alpha_loop++;
|
||||
}
|
||||
|
||||
for (i=0; i<alpha_num-1; i++){
|
||||
grad[i] = (log10(sigma_list[i+1]) - log10(sigma_list[i]))/
|
||||
(log10(alpha_list[i+1]) - log10(alpha_list[i]));
|
||||
if (grad[i] > s_target && pnt == 0) pnt = i;
|
||||
}
|
||||
double alpha_0, alpha_1, grad_0, grad_1;
|
||||
double sigma_0, sigma_1;
|
||||
int step;
|
||||
alpha_0 = alpha_list[pnt-1];
|
||||
sigma_0 = sigma_list[pnt-1];
|
||||
alpha_1 = alpha_list[pnt+1];
|
||||
sigma_1 = sigma_list[pnt+1];
|
||||
for (step=1;; step++){
|
||||
pnt = alpha_num+step;
|
||||
alpha = alpha_0 + 0.5*(alpha_1 - alpha_0);
|
||||
if ((t = (double *)realloc(alpha_list, pnt*sizeof(double))) != NULL){
|
||||
alpha_list = t;
|
||||
alpha_list[alpha_num+step-1] = alpha;
|
||||
}
|
||||
for (i=0; i<m; i++) aI[i*(m+1)] = alpha;
|
||||
BRDnewton_modify(kz, mz, aI, cr, H, head, &m, &n);
|
||||
dgemv_("T", &m, &n, &one, kz, &m, cr, &incr, &zero, f, &incr);
|
||||
for (i=0; i<n; i++) (f[i] < 0) ? (f[i] = 0.0) : (f[i] = f[i]);
|
||||
sigma = CalcSigma(k1, k2, f, head, d);
|
||||
if ((t = (double *)realloc(sigma_list, pnt*sizeof(double))) != NULL){
|
||||
sigma_list = t;
|
||||
sigma_list[pnt-1] = sigma;
|
||||
}
|
||||
grad_0 = (log10(sigma) - log10(sigma_0))/(log10(alpha) - log10(alpha_0));
|
||||
grad_1 = (log10(sigma_1) - log10(sigma))/(log10(alpha_1) - log10(alpha));
|
||||
if (fabs(s_target - grad_0) < fabs(s_target - grad_1) ){
|
||||
alpha_1 = alpha;
|
||||
sigma_1 = sigma;
|
||||
}
|
||||
else {
|
||||
alpha_0 = alpha;
|
||||
sigma_0 = sigma;
|
||||
}
|
||||
head->alpha = alpha;
|
||||
if ((alpha_1 - alpha_0) < head->alpha_tol) break;
|
||||
printf("delta alpha = %g\n", alpha_1 - alpha_0);
|
||||
printf("grad0 = %g\n", grad_0);
|
||||
printf("grad1 = %g\n", grad_1);
|
||||
head->alpha_loop++;
|
||||
}
|
||||
|
||||
head->alpha_list = malloc(pnt*sizeof(double));
|
||||
head->sigma_list = malloc(pnt*sizeof(double));
|
||||
head->alpha_num = pnt;
|
||||
for (i=0; i<pnt; i++){
|
||||
head->alpha_list[i] = alpha_list[i];
|
||||
head->sigma_list[i] = sigma_list[i];
|
||||
}
|
||||
|
||||
free(cr);
|
||||
free(aI);
|
||||
free(H);
|
||||
free(alpha_list);
|
||||
free(sigma_list);
|
||||
free(grad);
|
||||
}
|
||||
|
||||
void BRDAlphaLoop(MATRIX *K0, MATRIX *Mz, HEAD *head, double *f,
|
||||
MATRIX *k1, MATRIX *k2, INDATA *d){
|
||||
int m = K0->m;
|
||||
int n = K0->n;
|
||||
int i, incr = 1;
|
||||
double *kz, *mz;
|
||||
double *cr, *cr_n;
|
||||
double *aI, *H;
|
||||
double zero = 0.0, one = 1.0, one_ = -1.0;
|
||||
double alpha_opt, cr_norm, sigma, sigma_z;
|
||||
|
||||
if (head->alpha0 == 0) {
|
||||
head->alpha = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
kz = K0->a;
|
||||
mz = Mz->a;
|
||||
cr = malloc(sizeof(double)*m);
|
||||
cr_n = malloc(sizeof(double)*m);
|
||||
aI = malloc(sizeof(double)*m*m);
|
||||
H = malloc(sizeof(double)*n*n);
|
||||
|
||||
/* 初期のfからcrを求める cr=-(Kf-m)/alpha */
|
||||
dgemv_("N", &m, &n, &one, kz, &m, f, &incr, &zero, cr, &incr);
|
||||
daxpy_(&m, &one_, mz, &incr, cr, &incr);
|
||||
alpha_opt = -1.0/head->alpha0;
|
||||
dscal_(&m, &alpha_opt, cr, &incr);
|
||||
head->alpha = head->alpha0;
|
||||
|
||||
/* alphaI (diagonal) とH (diagonal)の初期化 */
|
||||
for (i=0; i<(n*n); i++) H[i] = 0.0;
|
||||
for (i=0; i<m*m; i++) aI[i] = 0.0;
|
||||
/* for (i=0; i<m; i++) cr[i] = 0.0; */
|
||||
/* ここからalphaのloop */
|
||||
for (head->alpha_loop=0;; head->alpha_loop++){
|
||||
/* alphaI (diagonal)の初期化*/
|
||||
for (i=0; i<m; i++) aI[i*(m+1)] = head->alpha;
|
||||
/* BRDでcrの最適化 */
|
||||
cr_norm = BRDnewton_modify(kz, mz, aI, cr, H, head, &m, &n);
|
||||
/* crからfの計算f f= kz'*cr, fi>0 だけが解 */
|
||||
dgemv_("T", &m, &n, &one, kz, &m, cr, &incr, &zero, f, &incr);
|
||||
for (i=0; i<n; i++) (f[i] < 0) ? (f[i] = 0.0) : (f[i] = f[i]);
|
||||
/* 圧縮前のカーネルを使って圧縮ノイズの標準偏差を求める */
|
||||
sigma = sqrt(CalcSigma(k1, k2, f, head, d));
|
||||
printf("uncompressed sigma = %g\n", sigma);
|
||||
/* 圧縮のカーネルを使ってcrを求める */
|
||||
dgemv_("N", &m, &n, &one, kz, &m, f, &incr, &zero, cr_n, &incr);
|
||||
daxpy_(&m, &one_, mz, &incr, cr_n, &incr); /* kz*f - mz */
|
||||
sigma_z = dnrm2_(&m, cr_n, &incr)/sqrt(m);
|
||||
printf("compressed sigma = %g\n", sigma_z);
|
||||
|
||||
if (head->sigma0 != 0.0) sigma = head->sigma0;
|
||||
printf("c_norm = %g\n", cr_norm);
|
||||
|
||||
switch(head->Atype){
|
||||
case 0:
|
||||
alpha_opt = sigma/sigma_z;
|
||||
break;
|
||||
case 1:
|
||||
alpha_opt = sigma_z/dnrm2_(&n, f, &incr)/(sqrt(1-sqrt(2*m)/m));
|
||||
break;
|
||||
case 2:
|
||||
alpha_opt = sigma_z/dnrm2_(&n, f, &incr);
|
||||
break;
|
||||
case 3:
|
||||
alpha_opt = sigma/dnrm2_(&n, f, &incr)/(sqrt(1-sqrt(2*m)/m));
|
||||
break;
|
||||
}
|
||||
|
||||
/* alphaの収束チェック */
|
||||
if (fabs(alpha_opt - head->alpha)/head->alpha < head->alpha_tol)
|
||||
break;
|
||||
/* alphaをmixingしてupdate */
|
||||
if (head->alpha_loop > 1)
|
||||
head->alpha = alpha_opt;
|
||||
else
|
||||
head->alpha_loop++;
|
||||
if (head->alpha_loop == head->alpha_loop_max) {
|
||||
printf("Iteration reached maximum alpha loop.\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(cr_n);
|
||||
free(cr);
|
||||
free(aI);
|
||||
free(H);
|
||||
}
|
||||
Reference in New Issue
Block a user