Ejemplo n.º 1
0
		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);

		}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);

}
Ejemplo n.º 4
0
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);
}