annotate solvers/SMALL_ompGabor/ompcoreGabor.c @ 140:31d2864dfdd4 ivand_dev

Audio Impainting additional constraints with cvx added
author Ivan Damnjanovic lnx <ivan.damnjanovic@eecs.qmul.ac.uk>
date Mon, 25 Jul 2011 17:27:05 +0100
parents
children
rev   line source
ivan@140 1 /**************************************************************************
ivan@140 2 *
ivan@140 3 * File name: ompcoreGabor.c
ivan@140 4 *
ivan@140 5 * Ron Rubinstein
ivan@140 6 * Computer Science Department
ivan@140 7 * Technion, Haifa 32000 Israel
ivan@140 8 * ronrubin@cs
ivan@140 9 *
ivan@140 10 * Last Updated: 25.8.2009
ivan@140 11 *
ivan@140 12 * Modified by Ivan damnjanovic July 2011
ivan@140 13 * Takes to atoms per iteration. It should be used for Gabor dictionaries
ivan@140 14 * as specified in
ivan@140 15 * "Audio Inpainting" Amir Adler, Valentin Emiya, Maria G. Jafari,
ivan@140 16 * Michael Elad, Remi Gribonval and Mark D. Plumbley
ivan@140 17 * Draft version: March 6, 2011
ivan@140 18 *
ivan@140 19 *************************************************************************/
ivan@140 20
ivan@140 21
ivan@140 22 #include "ompcoreGabor.h"
ivan@140 23 #include "omputils.h"
ivan@140 24 #include "ompprof.h"
ivan@140 25 #include "myblas.h"
ivan@140 26 #include <math.h>
ivan@140 27 #include <string.h>
ivan@140 28
ivan@140 29
ivan@140 30
ivan@140 31 /******************************************************************************
ivan@140 32 * *
ivan@140 33 * Batch-OMP Implementation *
ivan@140 34 * *
ivan@140 35 ******************************************************************************/
ivan@140 36
ivan@140 37 mxArray* ompcoreGabor(double D[], double x[], double DtX[], double XtX[], double G[], mwSize n, mwSize m, mwSize L,
ivan@140 38 int T, double eps, int gamma_mode, int profile, double msg_delta, int erroromp)
ivan@140 39 {
ivan@140 40
ivan@140 41 profdata pd;
ivan@140 42 mxArray *Gamma;
ivan@140 43 mwIndex i, j, k, signum, pos, *ind, *gammaIr, *gammaJc, gamma_count;
ivan@140 44 mwSize allocated_coefs, allocated_cols;
ivan@140 45 int DtX_specified, XtX_specified, batchomp, standardomp, *selected_atoms;
ivan@140 46 double *proj, *proj1, *proj2, *D1, *D2, *D1D2, *n12, *alpha, *beta, *error;
ivan@140 47 double *r, *Lchol, *c, *Gsub, *Dsub, sum, *gammaPr, *tempvec1, *tempvec2;
ivan@140 48 double eps2, resnorm, delta, deltaprev, secs_remain;
ivan@140 49 int mins_remain, hrs_remain;
ivan@140 50 clock_t lastprint_time, starttime;
ivan@140 51
ivan@140 52
ivan@140 53
ivan@140 54 /*** status flags ***/
ivan@140 55
ivan@140 56 DtX_specified = (DtX!=0); /* indicates whether D'*x was provided */
ivan@140 57 XtX_specified = (XtX!=0); /* indicates whether sum(x.*x) was provided */
ivan@140 58
ivan@140 59 standardomp = (G==0); /* batch-omp or standard omp are selected depending on availability of G */
ivan@140 60 batchomp = !standardomp;
ivan@140 61
ivan@140 62
ivan@140 63
ivan@140 64 /*** allocate output matrix ***/
ivan@140 65
ivan@140 66
ivan@140 67 if (gamma_mode == FULL_GAMMA) {
ivan@140 68
ivan@140 69 /* allocate full matrix of size m X L */
ivan@140 70
ivan@140 71 Gamma = mxCreateDoubleMatrix(m, L, mxREAL);
ivan@140 72 gammaPr = mxGetPr(Gamma);
ivan@140 73 gammaIr = 0;
ivan@140 74 gammaJc = 0;
ivan@140 75 }
ivan@140 76 else {
ivan@140 77
ivan@140 78 /* allocate sparse matrix with room for allocated_coefs nonzeros */
ivan@140 79
ivan@140 80 /* for error-omp, begin with L*sqrt(n)/2 allocated nonzeros, otherwise allocate L*T nonzeros */
ivan@140 81 allocated_coefs = erroromp ? (mwSize)(ceil(L*sqrt((double)n)/2.0) + 1.01) : L*T;
ivan@140 82 Gamma = mxCreateSparse(m, L, allocated_coefs, mxREAL);
ivan@140 83 gammaPr = mxGetPr(Gamma);
ivan@140 84 gammaIr = mxGetIr(Gamma);
ivan@140 85 gammaJc = mxGetJc(Gamma);
ivan@140 86 gamma_count = 0;
ivan@140 87 gammaJc[0] = 0;
ivan@140 88 }
ivan@140 89
ivan@140 90
ivan@140 91 /*** helper arrays ***/
ivan@140 92 /* Ivan Damnjanovic July 2011*/
ivan@140 93 proj = (double*)mxMalloc(m*sizeof(double));
ivan@140 94 proj1 = (double*)mxMalloc(m/2*sizeof(double));
ivan@140 95 proj2 = (double*)mxMalloc(m/2*sizeof(double));
ivan@140 96 D1 = (double*)mxMalloc(n*m/2*sizeof(double));
ivan@140 97 D2 = (double*)mxMalloc(n*m/2*sizeof(double));
ivan@140 98 memcpy(D1, D , n*m/2*sizeof(double));
ivan@140 99 memcpy(D2, D+n*m/2, n*m/2*sizeof(double));
ivan@140 100
ivan@140 101 D1D2 = (double*)mxMalloc(m/2*sizeof(double));
ivan@140 102 n12 = (double*)mxMalloc(m/2*sizeof(double));
ivan@140 103
ivan@140 104 vec_smult(1,D2, D1, n*m/2);
ivan@140 105
ivan@140 106 for (i=0; i<m/2; i++) {
ivan@140 107 D1D2[i]=0;
ivan@140 108 n12[i]=0;
ivan@140 109 for (j=0; j<n; j++) {
ivan@140 110 D1D2[i] += D1[i*n+j];
ivan@140 111 }
ivan@140 112 n12[i]=1/(1-D1D2[i]*D1D2[i]);
ivan@140 113 }
ivan@140 114
ivan@140 115 memcpy(D1, D , n*m/2*sizeof(double));
ivan@140 116
ivan@140 117 alpha = (double*)mxMalloc(m/2*sizeof(double)); /* contains D'*residual */
ivan@140 118 beta = (double*)mxMalloc(m/2*sizeof(double));
ivan@140 119 error = (double*)mxMalloc(m/2*sizeof(double));
ivan@140 120
ivan@140 121 ind = (mwIndex*)mxMalloc(m*sizeof(mwIndex)); /* indices of selected atoms */
ivan@140 122 selected_atoms = (int*)mxMalloc(m*sizeof(int)); /* binary array with 1's for selected atoms */
ivan@140 123 c = (double*)mxMalloc(n*sizeof(double)); /* orthogonal projection result */
ivan@140 124
ivan@140 125 /* current number of columns in Dsub / Gsub / Lchol */
ivan@140 126 allocated_cols = erroromp ? (mwSize)(ceil(sqrt((double)n)/2.0) + 1.01) : T;
ivan@140 127
ivan@140 128 /* Cholesky decomposition of D_I'*D_I */
ivan@140 129 Lchol = (double*)mxMalloc(n*allocated_cols*sizeof(double));
ivan@140 130
ivan@140 131 /* temporary vectors for various computations */
ivan@140 132 tempvec1 = (double*)mxMalloc(m*sizeof(double));
ivan@140 133 tempvec2 = (double*)mxMalloc(m*sizeof(double));
ivan@140 134
ivan@140 135 if (batchomp) {
ivan@140 136 /* matrix containing G(:,ind) - the columns of G corresponding to the selected atoms, in order of selection */
ivan@140 137 Gsub = (double*)mxMalloc(m*allocated_cols*sizeof(double));
ivan@140 138 }
ivan@140 139 else {
ivan@140 140 /* matrix containing D(:,ind) - the selected atoms from D, in order of selection */
ivan@140 141 Dsub = (double*)mxMalloc(n*allocated_cols*sizeof(double));
ivan@140 142
ivan@140 143 /* stores the residual */
ivan@140 144 r = (double*)mxMalloc(n*sizeof(double));
ivan@140 145 }
ivan@140 146
ivan@140 147 if (!DtX_specified) {
ivan@140 148 /* contains D'*x for the current signal */
ivan@140 149 DtX = (double*)mxMalloc(m*sizeof(double));
ivan@140 150 }
ivan@140 151
ivan@140 152
ivan@140 153
ivan@140 154 /*** initializations for error omp ***/
ivan@140 155
ivan@140 156 if (erroromp) {
ivan@140 157 eps2 = eps*eps; /* compute eps^2 */
ivan@140 158 if (T<0 || T>n) { /* unspecified max atom num - set max atoms to n */
ivan@140 159 T = n;
ivan@140 160 }
ivan@140 161 }
ivan@140 162
ivan@140 163
ivan@140 164
ivan@140 165 /*** initialize timers ***/
ivan@140 166
ivan@140 167 initprofdata(&pd); /* initialize profiling counters */
ivan@140 168 starttime = clock(); /* record starting time for eta computations */
ivan@140 169 lastprint_time = starttime; /* time of last status display */
ivan@140 170
ivan@140 171
ivan@140 172
ivan@140 173 /********************** perform omp for each signal **********************/
ivan@140 174
ivan@140 175
ivan@140 176
ivan@140 177 for (signum=0; signum<L; ++signum) {
ivan@140 178
ivan@140 179
ivan@140 180 /* initialize residual norm and deltaprev for error-omp */
ivan@140 181
ivan@140 182 if (erroromp) {
ivan@140 183 if (XtX_specified) {
ivan@140 184 resnorm = XtX[signum];
ivan@140 185 }
ivan@140 186 else {
ivan@140 187 resnorm = dotprod(x+n*signum, x+n*signum, n);
ivan@140 188 addproftime(&pd, XtX_TIME);
ivan@140 189 }
ivan@140 190 deltaprev = 0; /* delta tracks the value of gamma'*G*gamma */
ivan@140 191 }
ivan@140 192 else {
ivan@140 193 /* ignore residual norm stopping criterion */
ivan@140 194 eps2 = 0;
ivan@140 195 resnorm = 1;
ivan@140 196 }
ivan@140 197
ivan@140 198
ivan@140 199 if (resnorm>eps2 && T>0) {
ivan@140 200
ivan@140 201 /* compute DtX */
ivan@140 202
ivan@140 203 if (!DtX_specified) {
ivan@140 204 matT_vec(1, D, x+n*signum, DtX, n, m);
ivan@140 205 addproftime(&pd, DtX_TIME);
ivan@140 206 memcpy(r , x+n*signum, n*sizeof(double));
ivan@140 207 }
ivan@140 208
ivan@140 209
ivan@140 210 /* initialize projections to D1 and D2 := DtX */
ivan@140 211
ivan@140 212 memcpy(proj, DtX + m*signum*DtX_specified, m*sizeof(double));
ivan@140 213
ivan@140 214
ivan@140 215 /* mark all atoms as unselected */
ivan@140 216
ivan@140 217 for (i=0; i<m; ++i) {
ivan@140 218 selected_atoms[i] = 0;
ivan@140 219 }
ivan@140 220
ivan@140 221 }
ivan@140 222
ivan@140 223
ivan@140 224 /* main loop */
ivan@140 225
ivan@140 226 i=0;
ivan@140 227 while (resnorm>eps2 && i<T) {
ivan@140 228
ivan@140 229 /* index of next atom */
ivan@140 230 memcpy(proj1, proj, m/2*sizeof(double));
ivan@140 231 memcpy(proj2, proj + m/2, m/2*sizeof(double));
ivan@140 232 for (k=0; k<m/2; k++){
ivan@140 233 alpha[k] = (proj1[k] - D1D2[k]*proj2[k])*n12[k];
ivan@140 234 beta[k] = (proj2[k] - D1D2[k]*proj1[k])*n12[k];
ivan@140 235 }
ivan@140 236 for (k=0; k<m/2; k++){
ivan@140 237 error[k]=0;
ivan@140 238 for (j=0; j<n; j++){
ivan@140 239 error[k]+= (abs(r[j])-D1[k*n+j]*alpha[k]-D2[k*n+j]*beta[k])*(abs(r[j])-D1[k*n+j]*alpha[k]-D2[k*n+j]*beta[k]);
ivan@140 240 }
ivan@140 241 }
ivan@140 242 pos = maxabs(error, m/2);
ivan@140 243 addproftime(&pd, MAXABS_TIME);
ivan@140 244
ivan@140 245
ivan@140 246 /* stop criterion: selected same atom twice, or inner product too small */
ivan@140 247
ivan@140 248 if (selected_atoms[pos] || alpha[pos]*alpha[pos]<1e-14) {
ivan@140 249 break;
ivan@140 250 }
ivan@140 251
ivan@140 252 for (k=0;k<2;k++){
ivan@140 253 /* mark selected atom */
ivan@140 254
ivan@140 255 ind[i] = pos+k*m/2;
ivan@140 256 selected_atoms[pos+k*m/2] = 1;
ivan@140 257
ivan@140 258
ivan@140 259 /* matrix reallocation */
ivan@140 260
ivan@140 261 if (erroromp && i>=allocated_cols) {
ivan@140 262
ivan@140 263 allocated_cols = (mwSize)(ceil(allocated_cols*MAT_INC_FACTOR) + 1.01);
ivan@140 264
ivan@140 265 Lchol = (double*)mxRealloc(Lchol,n*allocated_cols*sizeof(double));
ivan@140 266
ivan@140 267 batchomp ? (Gsub = (double*)mxRealloc(Gsub,m*allocated_cols*sizeof(double))) :
ivan@140 268 (Dsub = (double*)mxRealloc(Dsub,n*allocated_cols*sizeof(double))) ;
ivan@140 269 }
ivan@140 270
ivan@140 271
ivan@140 272 /* append column to Gsub or Dsub */
ivan@140 273
ivan@140 274 if (batchomp) {
ivan@140 275 memcpy(Gsub+i*m, G+(pos+k*m/2)*m, m*sizeof(double));
ivan@140 276 }
ivan@140 277 else {
ivan@140 278 memcpy(Dsub+(i)*n, D+(pos+k*m/2)*n, n*sizeof(double));
ivan@140 279 }
ivan@140 280
ivan@140 281
ivan@140 282 /*** Cholesky update ***/
ivan@140 283
ivan@140 284 if (i==0) {
ivan@140 285 *Lchol = 1;
ivan@140 286 }
ivan@140 287 else {
ivan@140 288
ivan@140 289 /* incremental Cholesky decomposition: compute next row of Lchol */
ivan@140 290
ivan@140 291 if (standardomp) {
ivan@140 292 matT_vec(1, Dsub, D+n*(pos+k*m/2), tempvec1, n, i); /* compute tempvec1 := Dsub'*d where d is new atom */
ivan@140 293 addproftime(&pd, DtD_TIME);
ivan@140 294 }
ivan@140 295 else {
ivan@140 296 vec_assign(tempvec1, Gsub+i*m, ind, i); /* extract tempvec1 := Gsub(ind,i) */
ivan@140 297 }
ivan@140 298 backsubst('L', Lchol, tempvec1, tempvec2, n, i); /* compute tempvec2 = Lchol \ tempvec1 */
ivan@140 299 for (j=0; j<i; ++j) { /* write tempvec2 to end of Lchol */
ivan@140 300 Lchol[j*n+i] = tempvec2[j];
ivan@140 301 }
ivan@140 302
ivan@140 303 /* compute Lchol(i,i) */
ivan@140 304 sum = 0;
ivan@140 305 for (j=0; j<i; ++j) { /* compute sum of squares of last row without Lchol(i,i) */
ivan@140 306 sum += SQR(Lchol[j*n+i]);
ivan@140 307 }
ivan@140 308 if ( (1-sum) <= 1e-14 ) { /* Lchol(i,i) is zero => selected atoms are dependent */
ivan@140 309 break;
ivan@140 310 }
ivan@140 311 Lchol[i*n+i] = sqrt(1-sum);
ivan@140 312 }
ivan@140 313
ivan@140 314 addproftime(&pd, LCHOL_TIME);
ivan@140 315
ivan@140 316 i++;
ivan@140 317
ivan@140 318 }
ivan@140 319 /* perform orthogonal projection and compute sparse coefficients */
ivan@140 320
ivan@140 321 vec_assign(tempvec1, DtX + m*signum*DtX_specified, ind, i); /* extract tempvec1 = DtX(ind) */
ivan@140 322 cholsolve('L', Lchol, tempvec1, c, n, i); /* solve LL'c = tempvec1 for c */
ivan@140 323 addproftime(&pd, COMPCOEF_TIME);
ivan@140 324
ivan@140 325
ivan@140 326 /* update alpha = D'*residual */
ivan@140 327
ivan@140 328 if (standardomp) {
ivan@140 329 mat_vec(-1, Dsub, c, r, n, i); /* compute r := -Dsub*c */
ivan@140 330 vec_sum(1, x+n*signum, r, n); /* compute r := x+r */
ivan@140 331
ivan@140 332
ivan@140 333 /*memcpy(r, x+n*signum, n*sizeof(double)); /* assign r := x */
ivan@140 334 /*mat_vec1(-1, Dsub, c, 1, r, n, i); /* compute r := r-Dsub*c */
ivan@140 335
ivan@140 336 addproftime(&pd, COMPRES_TIME);
ivan@140 337 matT_vec(1, D, r, proj, n, m); /* compute proj := D'*r */
ivan@140 338 addproftime(&pd, DtR_TIME);
ivan@140 339
ivan@140 340 /* update residual norm */
ivan@140 341 if (erroromp) {
ivan@140 342 resnorm = dotprod(r, r, n);
ivan@140 343 addproftime(&pd, UPDATE_RESNORM_TIME);
ivan@140 344 }
ivan@140 345 }
ivan@140 346 else {
ivan@140 347 mat_vec(1, Gsub, c, tempvec1, m, i); /* compute tempvec1 := Gsub*c */
ivan@140 348 memcpy(proj, DtX + m*signum*DtX_specified, m*sizeof(double)); /* set proj = D'*x */
ivan@140 349 vec_sum(-1, tempvec1, proj, m); /* compute proj := proj - tempvec1 */
ivan@140 350 addproftime(&pd, UPDATE_DtR_TIME);
ivan@140 351
ivan@140 352 /* update residual norm */
ivan@140 353 if (erroromp) {
ivan@140 354 vec_assign(tempvec2, tempvec1, ind, i); /* assign tempvec2 := tempvec1(ind) */
ivan@140 355 delta = dotprod(c,tempvec2,i); /* compute c'*tempvec2 */
ivan@140 356 resnorm = resnorm - delta + deltaprev; /* residual norm update */
ivan@140 357 deltaprev = delta;
ivan@140 358 addproftime(&pd, UPDATE_RESNORM_TIME);
ivan@140 359 }
ivan@140 360 }
ivan@140 361 }
ivan@140 362
ivan@140 363
ivan@140 364 /*** generate output vector gamma ***/
ivan@140 365
ivan@140 366 if (gamma_mode == FULL_GAMMA) { /* write the coefs in c to their correct positions in gamma */
ivan@140 367 for (j=0; j<i; ++j) {
ivan@140 368 gammaPr[m*signum + ind[j]] = c[j];
ivan@140 369 }
ivan@140 370 }
ivan@140 371 else {
ivan@140 372 /* sort the coefs by index before writing them to gamma */
ivan@140 373 quicksort(ind,c,i);
ivan@140 374 addproftime(&pd, INDEXSORT_TIME);
ivan@140 375
ivan@140 376 /* gamma is full - reallocate */
ivan@140 377 if (gamma_count+i >= allocated_coefs) {
ivan@140 378
ivan@140 379 while(gamma_count+i >= allocated_coefs) {
ivan@140 380 allocated_coefs = (mwSize)(ceil(GAMMA_INC_FACTOR*allocated_coefs) + 1.01);
ivan@140 381 }
ivan@140 382
ivan@140 383 mxSetNzmax(Gamma, allocated_coefs);
ivan@140 384 mxSetPr(Gamma, mxRealloc(gammaPr, allocated_coefs*sizeof(double)));
ivan@140 385 mxSetIr(Gamma, mxRealloc(gammaIr, allocated_coefs*sizeof(mwIndex)));
ivan@140 386
ivan@140 387 gammaPr = mxGetPr(Gamma);
ivan@140 388 gammaIr = mxGetIr(Gamma);
ivan@140 389 }
ivan@140 390
ivan@140 391 /* append coefs to gamma and update the indices */
ivan@140 392 for (j=0; j<i; ++j) {
ivan@140 393 gammaPr[gamma_count] = c[j];
ivan@140 394 gammaIr[gamma_count] = ind[j];
ivan@140 395 gamma_count++;
ivan@140 396 }
ivan@140 397 gammaJc[signum+1] = gammaJc[signum] + i;
ivan@140 398 }
ivan@140 399
ivan@140 400
ivan@140 401
ivan@140 402 /*** display status messages ***/
ivan@140 403
ivan@140 404 if (msg_delta>0 && (clock()-lastprint_time)/(double)CLOCKS_PER_SEC >= msg_delta)
ivan@140 405 {
ivan@140 406 lastprint_time = clock();
ivan@140 407
ivan@140 408 /* estimated remainig time */
ivan@140 409 secs2hms( ((L-signum-1)/(double)(signum+1)) * ((lastprint_time-starttime)/(double)CLOCKS_PER_SEC) ,
ivan@140 410 &hrs_remain, &mins_remain, &secs_remain);
ivan@140 411
ivan@140 412 mexPrintf("omp: signal %d / %d, estimated remaining time: %02d:%02d:%05.2f\n",
ivan@140 413 signum+1, L, hrs_remain, mins_remain, secs_remain);
ivan@140 414 mexEvalString("drawnow;");
ivan@140 415 }
ivan@140 416
ivan@140 417 }
ivan@140 418
ivan@140 419 /* end omp */
ivan@140 420
ivan@140 421
ivan@140 422
ivan@140 423 /*** print final messages ***/
ivan@140 424
ivan@140 425 if (msg_delta>0) {
ivan@140 426 mexPrintf("omp: signal %d / %d\n", signum, L);
ivan@140 427 }
ivan@140 428
ivan@140 429 if (profile) {
ivan@140 430 printprofinfo(&pd, erroromp, batchomp, L);
ivan@140 431 }
ivan@140 432
ivan@140 433
ivan@140 434
ivan@140 435 /* free memory */
ivan@140 436
ivan@140 437 if (!DtX_specified) {
ivan@140 438 mxFree(DtX);
ivan@140 439 }
ivan@140 440 if (standardomp) {
ivan@140 441 mxFree(r);
ivan@140 442 mxFree(Dsub);
ivan@140 443 }
ivan@140 444 else {
ivan@140 445 mxFree(Gsub);
ivan@140 446 }
ivan@140 447 mxFree(tempvec2);
ivan@140 448 mxFree(tempvec1);
ivan@140 449 mxFree(Lchol);
ivan@140 450 mxFree(c);
ivan@140 451 mxFree(selected_atoms);
ivan@140 452 mxFree(ind);
ivan@140 453 mxFree(proj);
ivan@140 454 mxFree(proj1);
ivan@140 455 mxFree(proj2);
ivan@140 456 mxFree(D1);
ivan@140 457 mxFree(D2);
ivan@140 458 mxFree(D1D2);
ivan@140 459 mxFree(n12);
ivan@140 460 mxFree(alpha);
ivan@140 461 mxFree(beta);
ivan@140 462 mxFree(error);
ivan@140 463
ivan@140 464 return Gamma;
ivan@140 465 }