int sfa(double *x, double *gap, int * activeS, double *z, double *z0, double * v, double * Av, double lambda, int nn, int maxStep, double *s, double *g, double tol, int tau, int flag){ int i, iterStep, m, tFlag=0, n=nn+1; double alphap=0, alpha=1, beta=0, temp; int* S=(int *) malloc(sizeof(int)*nn); double gapp=-1, gappp=-1; /*gapp denotes the previous gap*/ int numS=-1, numSp=-2, numSpp=-3;; /* numS denotes the number of elements in the Support Set S numSp denotes the number of elements in the previous Support Set S */ *gap=-1; /*initial a value -1*/ /* The main algorithm by Nesterov's method B is an nn x nn tridiagonal matrix. The nn eigenvalues of B are 2- 2 cos (i * PI/ n), i=1, 2, ..., nn */ for (iterStep=1; iterStep<=maxStep; iterStep++){ /*------------- Step 1 ---------------------*/ beta=(alphap -1 ) / alpha; /* compute search point s= z + beta * z0 We follow the style of CLAPACK */ m=nn % 5; if (m!=0){ for (i=0;i<m; i++) s[i]=z[i]+ beta* z0[i]; } for (i=m;i<nn;i+=5){ s[i] =z[i] + beta* z0[i]; s[i+1] =z[i+1] + beta* z0[i+1]; s[i+2] =z[i+2] + beta* z0[i+2]; s[i+3] =z[i+3] + beta* z0[i+3]; s[i+4] =z[i+4] + beta* z0[i+4]; } /* s and g are of size nn x 1 compute the gradient at s g= B * s - Av, where B is an nn x nn tridiagonal matrix. and is defined as B= [ 2 -1 0 0; -1 2 -1 0; 0 -1 2 -1; 0 0 -1 2] We assume n>=3, which leads to nn>=2 */ g[0]=s[0] + s[0] - s[1] - Av[0]; for (i=1;i<nn-1;i++){ g[i]= - s[i-1] + s[i] + s[i] - s[i+1] - Av[i]; } g[nn-1]= -s[nn-2] + s[nn-1] + s[nn-1] - Av[nn-1]; /* z0 stores the previous -z */ m=nn%7; if (m!=0){ for (i=0;i<m;i++) z0[i]=-z[i]; } for (i=m; i <nn; i+=7){ z0[i] = - z[i]; z0[i+1] = - z[i+1]; z0[i+2] = - z[i+2]; z0[i+3] = - z[i+3]; z0[i+4] = - z[i+4]; z0[i+5] = - z[i+5]; z0[i+6] = - z[i+6]; } /* do a gradient step based on s to get z */ m=nn%5; if (m!=0){ for(i=0;i<m; i++) z[i]=s[i] - g[i]/4; } for (i=m;i<nn; i+=5){ z[i] = s[i] - g[i] /4; z[i+1] = s[i+1] - g[i+1]/4; z[i+2] = s[i+2] - g[i+2]/4; z[i+3] = s[i+3] - g[i+3]/4; z[i+4] = s[i+4] - g[i+4]/4; } /* project z onto the L_{infty} ball with radius lambda z is the new approximate solution */ for (i=0;i<nn; i++){ if (z[i]>lambda) z[i]=lambda; else if (z[i]<-lambda) z[i]=-lambda; } /* compute the difference between the new solution and the previous solution (stored in z0=-z_p) the difference is written to z0 */ m=nn%5; if (m!=0){ for (i=0;i<m;i++) z0[i]+=z[i]; } for(i=m;i<nn; i+=5){ z0[i] +=z[i]; z0[i+1]+=z[i+1]; z0[i+2]+=z[i+2]; z0[i+3]+=z[i+3]; z0[i+4]+=z[i+4]; } alphap=alpha; alpha=(1+sqrt(4*alpha*alpha+1))/2; /* check the termination condition */ if (iterStep%tau==0){ /* The variables g and s can be modified The variables x, z0 and z can be revised for case 0, but not for the rest */ switch (flag){ case 1: /* terminate the program once the "duality gap" is smaller than tol compute the duality gap: x= v - A^T z Ax = Av - A A^T z = -g, where g = A A^T z - A v the duality gap= lambda * \|Ax\|-1 - <z, Ax> = lambda * \|g\|_1 + <z, g> In fact, gap=0 indicates that, if g_i >0, then z_i=-lambda if g_i <0, then z_i=lambda */ gappp=gapp; gapp=*gap; /*record the previous gap*/ numSpp=numSp; numSp=numS; /*record the previous numS*/ dualityGap(gap, z, g, s, Av, lambda, nn); /*g is computed as the gradient of z in this function*/ /* printf("\n Iteration: %d, gap=%e, numS=%d", iterStep, *gap, numS); */ /* If *gap <=tol, we terminate the iteration Otherwise, we restart the algorithm */ if (*gap <=tol){ tFlag=1; break; } /* end of *gap <=tol */ else{ /* we apply the restarting technique*/ /* we compute the solution by the second way */ numS = supportSet(x, v, z, g, S, lambda, nn); /*g, the gradient of z should be computed before calling this function*/ /*With x, we compute z via AA^T z = Av - Ax */ /* printf("\n iterStep=%d, numS=%d, gap=%e",iterStep, numS, *gap); */ m=1; if (nn > 1000000) m=10; else if (nn > 100000) m=5; if ( abs(numS-numSp) < m){ numS=generateSolution(x, z, gap, v, Av, g, s, S, lambda, nn); /*g, the gradient of z should be computed before calling this function*/ if (*gap <tol){ tFlag=2; /*tFlag =2 shows that the result is already optimal There is no need to call generateSolution for recomputing the best solution */ break; } if ( (*gap ==gappp) && (numS==numSpp) ){ tFlag=2; break; } /*we terminate the program is *gap <1 numS==numSP and gapp==*gap */ } /* compute s= Av -Ax */ for (i=0;i<nn; i++) s[i]=Av[i] - x[i+1] + x[i]; /* apply Rose Algorithm for solving z */ Thomas(&temp, z, s, nn); /* Rose(&temp, z, s, nn); */ /* printf("\n Iteration: %d, %e", iterStep, temp); */ /* project z to [-lambda2, lambda2] */ for(i=0;i<nn;i++){ if (z[i]>lambda) z[i]=lambda; else if (z[i]<-lambda) z[i]=-lambda; } m=nn%7; if (m!=0){ for (i=0;i<m;i++) z0[i]=0; } for (i=m; i<nn; i+=7){ z0[i] = z0[i+1] = z0[i+2] = z0[i+3] = z0[i+4] = z0[i+5] = z0[i+6] =0; } alphap=0; alpha=1; /* we restart the algorithm */ } break; /*break case 1*/ case 2: /* The program is terminated either the summation of the absolution change (denoted by z0) of z (from the previous zp) is less than tol * nn, or the maximal number of iteration (maxStep) is achieved Note: tol indeed measures the averaged per element change. */ temp=0; m=nn%5; if (m!=0){ for(i=0;i<m;i++) temp+=fabs(z0[i]); } for(i=m;i<nn;i+=5) temp=temp + fabs(z0[i]) + fabs(z0[i+1]) + fabs(z0[i+2]) + fabs(z0[i+3]) + fabs(z0[i+4]); *gap=temp / nn; if (*gap <=tol){ tFlag=1; } break; case 3: /* terminate the program once the "duality gap" is smaller than tol compute the duality gap: x= v - A^T z Ax = Av - A A^T z = -g, where g = A A^T z - A v the duality gap= lambda * \|Ax\|-1 - <z, Ax> = lambda * \|g\|_1 + <z, g> In fact, gap=0 indicates that, if g_i >0, then z_i=-lambda if g_i <0, then z_i=lambda */ g[0]=z[0] + z[0] - z[1] - Av[0]; for (i=1;i<nn-1;i++){ g[i]= - z[i-1] + z[i] + z[i] - z[i+1] - Av[i]; } g[nn-1]= -z[nn-2] + z[nn-1] + z[nn-1] - Av[nn-1]; for (i=0;i<nn;i++) if (g[i]>0) s[i]=lambda + z[i]; else s[i]=-lambda + z[i]; temp=0; m=nn%5; if (m!=0){ for(i=0;i<m;i++) temp+=s[i]*g[i]; } for(i=m;i<nn;i+=5) temp=temp + s[i] *g[i] + s[i+1]*g[i+1] + s[i+2]*g[i+2] + s[i+3]*g[i+3] + s[i+4]*g[i+4]; *gap=temp; /* printf("\n %e", *gap); */ if (*gap <=tol) tFlag=1; break; case 4: /* terminate the program once the "relative duality gap" is smaller than tol compute the duality gap: x= v - A^T z Ax = Av - A A^T z = -g, where g = A A^T z - A v the duality gap= lambda * \|Ax\|-1 - <z, Ax> = lambda * \|g\|_1 + <z, g> In fact, gap=0 indicates that, if g_i >0, then z_i=-lambda if g_i <0, then z_i=lambda Here, the "relative duality gap" is defined as: duality gap / - 1/2 \|A^T z\|^2 + < z, Av> We efficiently compute - 1/2 \|A^T z\|^2 + < z, Av> using the following relationship - 1/2 \|A^T z\|^2 + < z, Av> = -1/2 <z, A A^T z - Av -Av> = -1/2 <z, g - Av> */ g[0]=z[0] + z[0] - z[1] - Av[0]; for (i=1;i<nn-1;i++){ g[i]= - z[i-1] + z[i] + z[i] - z[i+1] - Av[i]; } g[nn-1]= -z[nn-2] + z[nn-1] + z[nn-1] - Av[nn-1]; for (i=0;i<nn;i++) if (g[i]>0) s[i]=lambda + z[i]; else s[i]=-lambda + z[i]; temp=0; m=nn%5; if (m!=0){ for(i=0;i<m;i++) temp+=s[i]*g[i]; } for(i=m;i<nn;i+=5) temp=temp + s[i] *g[i] + s[i+1]*g[i+1] + s[i+2]*g[i+2] + s[i+3]*g[i+3] + s[i+4]*g[i+4]; *gap=temp; /* Now, *gap contains the duality gap Next, we compute - 1/2 \|A^T z\|^2 + < z, Av> =-1/2 <z, g - Av> */ temp=0; m=nn%5; if (m!=0){ for(i=0;i<m;i++) temp+=z[i] * (g[i] - Av[i]); } for(i=m;i<nn;i+=5) temp=temp + z[i] * (g[i] - Av[i]) + z[i+1]* (g[i+1]- Av[i+1]) + z[i+2]* (g[i+2]- Av[i+2]) + z[i+3]* (g[i+3]- Av[i+3]) + z[i+4]* (g[i+4]- Av[i+4]); temp=fabs(temp) /2; if (temp <1) temp=1; *gap/=temp; /* *gap now contains the relative gap */ if (*gap <=tol){ tFlag=1; } break; default: /* The program is terminated either the summation of the absolution change (denoted by z0) of z (from the previous zp) is less than tol * nn, or the maximal number of iteration (maxStep) is achieved Note: tol indeed measures the averaged per element change. */ temp=0; m=nn%5; if (m!=0){ for(i=0;i<m;i++) temp+=fabs(z0[i]); } for(i=m;i<nn;i+=5) temp=temp + fabs(z0[i]) + fabs(z0[i+1]) + fabs(z0[i+2]) + fabs(z0[i+3]) + fabs(z0[i+4]); *gap=temp / nn; if (*gap <=tol){ tFlag=1; } break; }/*end of switch*/ if (tFlag) break; }/* end of the if for checking the termination condition */ /*-------------- Step 3 --------------------*/ } /* for the other cases, except flag=1, compute the solution x according the first way (the primal-dual way) */ if ( (flag !=1) || (tFlag==0) ){ x[0]=v[0] + z[0]; for(i=1;i<n-1;i++) x[i]= v[i] - z[i-1] + z[i]; x[n-1]=v[n-1] - z[n-2]; } if ( (flag==1) && (tFlag==1)){ /* We assume that n>=3, and thus nn>=2 We have two ways for recovering x. The first way is x = v - A^T z The second way is x =omega(z) */ /* We first compute the objective function value of the first choice in terms f(x), see our paper */ /* for numerical reason, we do a gradient descent step */ /* --------------------------------------------------- A gradient step begins */ g[0]=z[0] + z[0] - z[1] - Av[0]; for (i=1;i<nn-1;i++){ g[i]= - z[i-1] + z[i] + z[i] - z[i+1] - Av[i]; } g[nn-1]= -z[nn-2] + z[nn-1] + z[nn-1] - Av[nn-1]; /* do a gradient step based on z to get the new z */ m=nn%5; if (m!=0){ for(i=0;i<m; i++) z[i]=z[i] - g[i]/4; } for (i=m;i<nn; i+=5){ z[i] = z[i] - g[i] /4; z[i+1] = z[i+1] - g[i+1]/4; z[i+2] = z[i+2] - g[i+2]/4; z[i+3] = z[i+3] - g[i+3]/4; z[i+4] = z[i+4] - g[i+4]/4; } /* project z onto the L_{infty} ball with radius lambda z is the new approximate solution */ for (i=0;i<nn; i++){ if (z[i]>lambda) z[i]=lambda; else if (z[i]<-lambda) z[i]=-lambda; } /* --------------------------------------------------- A gradient descent step ends */ /*compute the gradient at z*/ g[0]=z[0] + z[0] - z[1] - Av[0]; for (i=1;i<nn-1;i++){ g[i]= - z[i-1] + z[i] + z[i] - z[i+1] - Av[i]; } g[nn-1]= -z[nn-2] + z[nn-1] + z[nn-1] - Av[nn-1]; numS=generateSolution(x, z, gap, v, Av, g, s, S, lambda, nn); /*g, the gradient of z should be computed before calling this function*/ } free (S); /* free the variables S */ *activeS=numS; return (iterStep); }
void overlapping_agd(double *x, double *gap, double *penalty2, double *v, int p, int g, double lambda1, double lambda2, double *w, double *G, double *Y, int maxIter, int flag, double tol){ int YSize=(int) w[3*(g-1) +1]+1; double *u=(double *)malloc(sizeof(double)*p); double *y=(double *)malloc(sizeof(double)*p); double *xnew=(double *)malloc(sizeof(double)*p); double *Ynew=(double *)malloc(sizeof(double)* YSize ); double *xS=(double *)malloc(sizeof(double)*p); double *YS=(double *)malloc(sizeof(double)* YSize ); /*double *xp=(double *)malloc(sizeof(double)*p);*/ double *Yp=(double *)malloc(sizeof(double)* YSize ); int *zeroGroupFlag=(int *)malloc(sizeof(int)*g); int *entrySignFlag=(int *)malloc(sizeof(int)*p); int pp, gg; int i, j, iterStep; double twoNorm,temp, L=1, leftValue, rightValue, gapR, penalty2R; int nextRestartStep=0; double alpha, alphap=0.5, beta, gamma; /* * call the function to identify some zero entries * * entrySignFlag[i]=0 denotes that the corresponding entry is definitely zero * * zeroGroupFlag[i]=0 denotes that the corresponding group is definitely zero * */ identifySomeZeroEntries(u, zeroGroupFlag, entrySignFlag, &pp, &gg, v, lambda1, lambda2, p, g, w, G); penalty2[1]=pp; penalty2[2]=gg; /*store pp and gg to penalty2[1] and penalty2[2]*/ /* *------------------- * Process Y *------------------- * We make sure that Y is feasible * and if x_i=0, then set Y_{ij}=0 */ for(i=0;i<g;i++){ if(zeroGroupFlag[i]){ /*this group is non-zero*/ /*compute the two norm of the group*/ twoNorm=0; for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ if (! u[ (int) G[j] ] ) Y[j]=0; twoNorm+=Y[j]*Y[j]; } twoNorm=sqrt(twoNorm); if (twoNorm > lambda2 * w[3*i+2] ){ temp=lambda2 * w[3*i+2] / twoNorm; for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++) Y[j]*=temp; } } else{ /*this group is zero*/ for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++) Y[j]=0; } } /* * set Ynew and Yp to zero * * in the following processing, we only operate, Yp, Y and Ynew in the * possibly non-zero groups by "if(zeroGroupFlag[i])" * */ for(i=0;i<YSize;i++) YS[i]=Yp[i]=Ynew[i]=0; /* * --------------- * * we first do a gradient descent step for determing the value of an approporate L * * Also, we initialize gamma * * with Y, we compute a new Ynew * */ /* * compute x=max(u-Y * e, 0); */ xFromY(x, y, u, Y, p, g, zeroGroupFlag, G, w); /* * compute (xnew, Ynew) from (x, Y) * * * gradientDescentStep(double *xnew, double *Ynew, double *LL, double *u, double *y, int *entrySignFlag, double lambda2, double *x, double *Y, int p, int g, int * zeroGroupFlag, double *G, double *w) */ gradientDescentStep(xnew, Ynew, &L, u, y,entrySignFlag,lambda2, x, Y, p, g, zeroGroupFlag, G, w); /* * we have finished one gradient descent to get * * (x, Y) and (xnew, Ynew), where (xnew, Ynew) is * * a gradient descent step based on (x, Y) * * we set (xp, Yp)=(x, Y) * * (x, Y)= (xnew, Ynew) */ /*memcpy(xp, x, sizeof(double) * p);*/ memcpy(Yp, Y, sizeof(double) * YSize); /*memcpy(x, xnew, sizeof(double) * p);*/ memcpy(Y, Ynew, sizeof(double) * YSize); gamma=L; /* * ------------------------------------ * Accelerated Gradient Descent begins here * ------------------------------------ */ for(iterStep=0;iterStep<maxIter;iterStep++){ while (1){ /* * compute alpha as the positive root of * * L * alpha^2 = (1-alpha) * gamma * */ alpha= ( - gamma + sqrt( gamma * gamma + 4 * L * gamma ) ) / 2 / L; beta= gamma * (1-alphap)/ alphap / (gamma + L * alpha); /* * compute YS= Y + beta * (Y - Yp) * */ for(i=0;i<g;i++){ if(zeroGroupFlag[i]){ /*this group is non-zero*/ for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ YS[j]=Y[j] + beta * (Y[j]-Yp[j]); } } }/*end of for(i=0;i<g;i++) */ /* * compute xS */ xFromY(xS, y, u, YS, p, g, zeroGroupFlag, G, w); /* * * Ynew = proj ( YS + xS e^T / L ) * */ for(i=0;i<g;i++){ if(zeroGroupFlag[i]){ /*this group is non-zero*/ twoNorm=0; for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ Ynew[j]= YS[j] + xS[ (int) G[j] ] / L; twoNorm+=Ynew[j]*Ynew[j]; } twoNorm=sqrt(twoNorm); if (twoNorm > lambda2 * w[3*i+2] ){ temp=lambda2 * w[3*i+2] / twoNorm; for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++) Ynew[j]*=temp; } } }/*end of for(i=0;i<g;i++) */ /* * compute xnew=max(u-Ynew * e, 0); * *void xFromY(double *x, double *y, * double *u, double *Y, * int p, int g, int *zeroGroupFlag, * double *G, double *w) */ xFromY(xnew, y, u, Ynew, p, g, zeroGroupFlag, G, w); /* test whether L is appropriate*/ leftValue=0; for(i=0;i<p;i++){ if (entrySignFlag[i]){ temp=xnew[i]-xS[i]; leftValue+= temp * ( 0.5 * temp + y[i]); } } rightValue=0; for(i=0;i<g;i++){ if(zeroGroupFlag[i]){ /*this group is non-zero*/ for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ temp=Ynew[j]-YS[j]; rightValue+=temp * temp; } } }/*end of for(i=0;i<g;i++) */ rightValue=rightValue/2; if ( leftValue <= L * rightValue){ temp= L * rightValue / leftValue; if (temp >5) L=L*0.8; break; } else{ temp=leftValue / rightValue; if (L*2 <= temp) L=temp; else L=2*L; if ( L / g - 2* g >0 ){ if (rightValue < 1e-16){ break; } else{ printf("\n AGD: leftValue=%e, rightValue=%e, ratio=%e", leftValue, rightValue, temp); printf("\n L=%e > 2 * %d * %d. There might be a bug here. Otherwise, it is due to numerical issue.", L, g, g); break; } } } } /* compute the duality gap at (xnew, Ynew) * * void dualityGap(double *gap, double *penalty2, * double *x, double *Y, int g, int *zeroGroupFlag, * double *G, double *w, double lambda2) * */ dualityGap(gap, penalty2, xnew, Ynew, g, zeroGroupFlag, G, w, lambda2); /* * if the duality gap is within pre-specified parameter tol * * we terminate the algorithm */ if (*gap <=tol){ memcpy(x, xnew, sizeof(double) * p); memcpy(Y, Ynew, sizeof(double) * YSize); break; } /* * flag =1 means restart * * flag =0 means with restart * * nextRestartStep denotes the next "step number" for * initializing the restart process. * * This is based on the fact that, the result is only beneficial when * xnew is good. In other words, * if xnew is not good, then the * restart might not be helpful. */ if ( (flag==0) || (flag==1 && iterStep < nextRestartStep )){ /*memcpy(xp, x, sizeof(double) * p);*/ memcpy(Yp, Y, sizeof(double) * YSize); /*memcpy(x, xnew, sizeof(double) * p);*/ memcpy(Y, Ynew, sizeof(double) * YSize); gamma=gamma * (1-alpha); alphap=alpha; /* printf("\n iterStep=%d, L=%2.5f, gap=%e", iterStep, L, *gap); */ } else{ /* * flag=1 * * We allow the restart of the program. * * Here, Y is constructed as a subgradient of xnew, based on the * assumption that Y might be a better choice than Ynew, provided * that xnew is good enough. * */ /* * compute the restarting point YS with xnew and Ynew * *void YFromx(double *Y, * double *xnew, double *Ynew, * double lambda2, int g, int *zeroGroupFlag, * double *G, double *w) */ YFromx(YS, xnew, Ynew, lambda2, g, zeroGroupFlag, G, w); /*compute the solution with the starting point YS * *void xFromY(double *x, double *y, * double *u, double *Y, * int p, int g, int *zeroGroupFlag, * double *G, double *w) * */ xFromY(xS, y, u, YS, p, g, zeroGroupFlag, G, w); /*compute the duality at (xS, YS) * * void dualityGap(double *gap, double *penalty2, * double *x, double *Y, int g, int *zeroGroupFlag, * double *G, double *w, double lambda2) * */ dualityGap(&gapR, &penalty2R, xS, YS, g, zeroGroupFlag, G, w, lambda2); if (*gap< gapR){ /*(xnew, Ynew) is better in terms of duality gap*/ /*In this case, we do not apply restart, as (xS,YS) is not better * * We postpone the "restart" by giving a * "nextRestartStep" */ /*memcpy(xp, x, sizeof(double) * p);*/ memcpy(Yp, Y, sizeof(double) * YSize); /*memcpy(x, xnew, sizeof(double) * p);*/ memcpy(Y, Ynew, sizeof(double) * YSize); gamma=gamma * (1-alpha); alphap=alpha; nextRestartStep=iterStep+ (int) sqrt(gapR / *gap); } else{ /*we use (xS, YS), as it is better in terms of duality gap*/ *gap=gapR; *penalty2=penalty2R; if (*gap <=tol){ memcpy(x, xS, sizeof(double) * p); memcpy(Y, YS, sizeof(double) * YSize); break; }else{ /* * we do a gradient descent based on (xS, YS) * */ /* * compute (x, Y) from (xS, YS) * * * gradientDescentStep(double *xnew, double *Ynew, * double *LL, double *u, double *y, int *entrySignFlag, double lambda2, * double *x, double *Y, int p, int g, int * zeroGroupFlag, * double *G, double *w) */ gradientDescentStep(x, Y, &L, u, y, entrySignFlag,lambda2, xS, YS, p, g, zeroGroupFlag, G, w); /*memcpy(xp, xS, sizeof(double) * p);*/ memcpy(Yp, YS, sizeof(double) * YSize); gamma=L; alphap=0.5; } } /* * printf("\n iterStep=%d, L=%2.5f, gap=%e, gapR=%e", iterStep, L, *gap, gapR); */ }/* flag =1*/ } /* main loop */ penalty2[3]=iterStep+1; /* * get the number of nonzero groups */ penalty2[4]=0; for(i=0;i<g;i++){ if (zeroGroupFlag[i]==0) penalty2[4]=penalty2[4]+1; else{ for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ if (x[ (int) G[j] ] !=0) break; } if (j>(int) w[3*i +1]) penalty2[4]=penalty2[4]+1; } } /* * assign sign to the solution x */ for(i=0;i<p;i++){ if (entrySignFlag[i]==-1){ x[i]=-x[i]; } } free (u); free (y); free (xnew); free (Ynew); free (xS); free (YS); /*free (xp);*/ free (Yp); free (zeroGroupFlag); free (entrySignFlag); }
int sfa_special(double *x, double *gap, int * activeS, double *z, double * v, double * Av, double lambda, int nn, int maxStep, double *s, double *g, double tol, int tau){ int i, iterStep; //int tFlag=0; //int n=nn+1; double temp; int* S=(int *) malloc(sizeof(int)*nn); double gapp=-1; /*gapp denotes the previous gap*/ int numS=-1, numSp=-1; /* numS denotes the number of elements in the Support Set S numSp denotes the number of elements in the previous Support Set S */ *gap=-1; /*initialize *gap a value*/ for (iterStep=1; iterStep<=maxStep; iterStep++){ g[0]=z[0] + z[0] - z[1] - Av[0]; for (i=1;i<nn-1;i++){ g[i]= - z[i-1] + z[i] + z[i] - z[i+1] - Av[i]; } g[nn-1]= -z[nn-2] + z[nn-1] + z[nn-1] - Av[nn-1]; numSp=numS; /*record the previous numS*/ numS = supportSet(x, v, z, g, S, lambda, nn); /*With x, we compute z via AA^T z = Av - Ax */ /* compute s= Av -Ax */ for (i=0;i<nn; i++) s[i]=Av[i] - x[i+1] + x[i]; /* Apply Rose Algorithm for solving z */ Thomas(&temp, z, s, nn); /* Rose(&temp, z, s, nn); */ /* project z to [-lambda, lambda] */ for(i=0;i<nn;i++){ if (z[i]>lambda) z[i]=lambda; else if (z[i]<-lambda) z[i]=-lambda; } if (iterStep%tau==0){ gapp=*gap; /*record the previous gap*/ dualityGap(gap, z, g, s, Av, lambda, nn); /* printf("\n iterStep=%d, numS=%d, gap=%e, diff=%e",iterStep, numS, *gap, *gap -gapp); */ if (*gap <=tol){ //tFlag=1; break; } if ( (*gap <1) && (numS==numSp) && (gapp == *gap) ){ //tFlag=1; break; /*we terminate the program is *gap <1 numS==numSP and gapp==*gap */ } }/*end of if tau*/ }/*end for */ free (S); * activeS=numS; return(iterStep); }
void overlapping_gd(double *x, double *gap, double *penalty2, double *v, int p, int g, double lambda1, double lambda2, double *w, double *G, double *Y, int maxIter, int flag, double tol){ int YSize=(int) w[3*(g-1) +1]+1; double *u=(double *)malloc(sizeof(double)*p); double *y=(double *)malloc(sizeof(double)*p); double *xnew=(double *)malloc(sizeof(double)*p); double *Ynew=(double *)malloc(sizeof(double)* YSize ); int *zeroGroupFlag=(int *)malloc(sizeof(int)*g); int *entrySignFlag=(int *)malloc(sizeof(int)*p); int pp, gg; int i, j, iterStep; double twoNorm,temp, L=1, leftValue, rightValue, gapR, penalty2R; int nextRestartStep=0; /* * call the function to identify some zero entries * * entrySignFlag[i]=0 denotes that the corresponding entry is definitely zero * * zeroGroupFlag[i]=0 denotes that the corresponding group is definitely zero * */ identifySomeZeroEntries(u, zeroGroupFlag, entrySignFlag, &pp, &gg, v, lambda1, lambda2, p, g, w, G); penalty2[1]=pp; penalty2[2]=gg; /*store pp and gg to penalty2[1] and penalty2[2]*/ /* *------------------- * Process Y *------------------- * We make sure that Y is feasible * and if x_i=0, then set Y_{ij}=0 */ for(i=0;i<g;i++){ if(zeroGroupFlag[i]){ /*this group is non-zero*/ /*compute the two norm of the group*/ twoNorm=0; for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ if (! u[ (int) G[j] ] ) Y[j]=0; twoNorm+=Y[j]*Y[j]; } twoNorm=sqrt(twoNorm); if (twoNorm > lambda2 * w[3*i+2] ){ temp=lambda2 * w[3*i+2] / twoNorm; for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++) Y[j]*=temp; } } else{ /*this group is zero*/ for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++) Y[j]=0; } } /* * set Ynew to zero * * in the following processing, we only operator Y and Ynew in the * possibly non-zero groups by "if(zeroGroupFlag[i])" * */ for(i=0;i<YSize;i++) Ynew[i]=0; /* * ------------------------------------ * Gradient Descent begins here * ------------------------------------ */ /* * compute x=max(u-Y * e, 0); * */ xFromY(x, y, u, Y, p, g, zeroGroupFlag, G, w); /*the main loop */ for(iterStep=0;iterStep<maxIter;iterStep++){ /* * the gradient at Y is * * omega'(Y)=-x e^T * * where x=max(u-Y * e, 0); * */ /* * line search to find Ynew with appropriate L */ while (1){ /* * compute * Ynew = proj ( Y + x e^T / L ) */ for(i=0;i<g;i++){ if(zeroGroupFlag[i]){ /*this group is non-zero*/ twoNorm=0; for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ Ynew[j]= Y[j] + x[ (int) G[j] ] / L; twoNorm+=Ynew[j]*Ynew[j]; } twoNorm=sqrt(twoNorm); if (twoNorm > lambda2 * w[3*i+2] ){ temp=lambda2 * w[3*i+2] / twoNorm; for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++) Ynew[j]*=temp; } } }/*end of for(i=0;i<g;i++) */ /* * compute xnew=max(u-Ynew * e, 0); * *void xFromY(double *x, double *y, * double *u, double *Y, * int p, int g, int *zeroGroupFlag, * double *G, double *w) */ xFromY(xnew, y, u, Ynew, p, g, zeroGroupFlag, G, w); /* test whether L is appropriate*/ leftValue=0; for(i=0;i<p;i++){ if (entrySignFlag[i]){ temp=xnew[i]-x[i]; leftValue+= temp * ( 0.5 * temp + y[i]); } } rightValue=0; for(i=0;i<g;i++){ if(zeroGroupFlag[i]){ /*this group is non-zero*/ for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ temp=Ynew[j]-Y[j]; rightValue+=temp * temp; } } }/*end of for(i=0;i<g;i++) */ rightValue=rightValue/2; if ( leftValue <= L * rightValue){ temp= L * rightValue / leftValue; if (temp >5) L=L*0.8; break; } else{ temp=leftValue / rightValue; if (L*2 <= temp) L=temp; else L=2*L; if ( L / g - 2* g ){ if (rightValue < 1e-16){ break; } else{ printf("\n GD: leftValue=%e, rightValue=%e, ratio=%e", leftValue, rightValue, temp); printf("\n L=%e > 2 * %d * %d. There might be a bug here. Otherwise, it is due to numerical issue.", L, g, g); break; } } } } /* compute the duality gap at (xnew, Ynew) * * void dualityGap(double *gap, double *penalty2, * double *x, double *Y, int g, int *zeroGroupFlag, * double *G, double *w, double lambda2) * */ dualityGap(gap, penalty2, xnew, Ynew, g, zeroGroupFlag, G, w, lambda2); /* * flag =1 means restart * * flag =0 means with restart * * nextRestartStep denotes the next "step number" for * initializing the restart process. * * This is based on the fact that, the result is only beneficial when * xnew is good. In other words, * if xnew is not good, then the * restart might not be helpful. */ if ( (flag==0) || (flag==1 && iterStep < nextRestartStep )){ /* copy Ynew to Y, and xnew to x */ memcpy(x, xnew, sizeof(double) * p); memcpy(Y, Ynew, sizeof(double) * YSize); /* printf("\n iterStep=%d, L=%2.5f, gap=%e", iterStep, L, *gap); */ } else{ /* * flag=1 * * We allow the restart of the program. * * Here, Y is constructed as a subgradient of xnew, based on the * assumption that Y might be a better choice than Ynew, provided * that xnew is good enough. * */ /* * compute the restarting point Y with xnew and Ynew * *void YFromx(double *Y, * double *xnew, double *Ynew, * double lambda2, int g, int *zeroGroupFlag, * double *G, double *w) */ YFromx(Y, xnew, Ynew, lambda2, g, zeroGroupFlag, G, w); /*compute the solution with the starting point Y * *void xFromY(double *x, double *y, * double *u, double *Y, * int p, int g, int *zeroGroupFlag, * double *G, double *w) * */ xFromY(x, y, u, Y, p, g, zeroGroupFlag, G, w); /*compute the duality at (x, Y) * * void dualityGap(double *gap, double *penalty2, * double *x, double *Y, int g, int *zeroGroupFlag, * double *G, double *w, double lambda2) * */ dualityGap(&gapR, &penalty2R, x, Y, g, zeroGroupFlag, G, w, lambda2); if (*gap< gapR){ /*(xnew, Ynew) is better in terms of duality gap*/ /* copy Ynew to Y, and xnew to x */ memcpy(x, xnew, sizeof(double) * p); memcpy(Y, Ynew, sizeof(double) * YSize); /*In this case, we do not apply restart, as (x,Y) is not better * * We postpone the "restart" by giving a * "nextRestartStep" */ /* * we test *gap here, in case *gap=0 */ if (*gap <=tol) break; else{ nextRestartStep=iterStep+ (int) sqrt(gapR / *gap); } } else{ /*we use (x, Y), as it is better in terms of duality gap*/ *gap=gapR; *penalty2=penalty2R; } /* printf("\n iterStep=%d, L=%2.5f, gap=%e, gapR=%e", iterStep, L, *gap, gapR); */ } /* * if the duality gap is within pre-specified parameter tol * * we terminate the algorithm */ if (*gap <=tol) break; } penalty2[3]=iterStep; penalty2[4]=0; for(i=0;i<g;i++){ if (zeroGroupFlag[i]==0) penalty2[4]=penalty2[4]+1; else{ for(j=(int) w[3*i] ; j<= (int) w[3*i +1]; j++){ if (x[ (int) G[j] ] !=0) break; } if (j>(int) w[3*i +1]) penalty2[4]=penalty2[4]+1; } } /* * assign sign to the solution x */ for(i=0;i<p;i++){ if (entrySignFlag[i]==-1){ x[i]=-x[i]; } } free (u); free (y); free (xnew); free (Ynew); free (zeroGroupFlag); free (entrySignFlag); }