Пример #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);

		}
Пример #2
0
void restartMapping(double *g, double *z,  double * v, 
		double lambda, int nn)
{

	int i, n=nn+1;
	double temp;
	int* S=(int *) malloc(sizeof(int)*nn);
	double *x=(double *)malloc(sizeof(double)*n);
	double *s=(double *)malloc(sizeof(double)*nn);
	double *Av=(double *)malloc(sizeof(double)*nn);
	//int numS=-1;    

	/*
	   for a given input z, 
	   we compute the z0 after restarting

	   The elements in z lie in [-lambda, lambda]

	   The returned value is g
	   */


	for (i=0;i<nn; i++)
		Av[i]=v[i+1]-v[i];



	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 = 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, g, s, nn);

	/*
	   Rose(&temp, g, s, nn);
	   */

	/*
	   project g to [-lambda, lambda]
	   */

	for(i=0;i<nn;i++){		
		if (g[i]>lambda)
			g[i]=lambda;
		else
			if (g[i]<-lambda)
				g[i]=-lambda;
	}


	free (S);
	free (x);
	free (s);
	free (Av);

}
Пример #3
0
int sfa_one(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, m;
	int tFlag=0;
	//int n=nn+1;
	double temp;
	int* S=(int *) malloc(sizeof(int)*nn);
	double gapp=-1, gappp=-2;	/*gapp denotes the previous gap*/
	int numS=-100, numSp=-200, numSpp=-300;    
	/*
	   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*/

	/*
	   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
	   */


	/*
	   we first do a gradient step based on z
	   */


	/*
	   ---------------------------------------------------
	   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];

	for (iterStep=1; iterStep<=maxStep; iterStep++){


		/*
		   ---------------------------------------------------
		   restart the algorithm with x=omega(z)
		   */

		numSpp=numSp;
		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;
		}

		/*
		   ---------------------------------------------------
		   restart the algorithm with x=omega(z)

		   we have computed a new z, based on the above relationship
		   */


		/*
		   ---------------------------------------------------
		   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];


		if (iterStep % tau==0){
			gappp=gapp;
			gapp=*gap;  /*record the previous gap*/

			dualityGap2(gap, z, g, s, Av, lambda, nn);
			/*g, the gradient of z should be computed before calling this function*/


			/*
			   printf("\n iterStep=%d, numS=%d, gap=%e",iterStep, numS, *gap);
			   */


			/*
			   printf("\n  %d  & %d   &  %2.0e \\\\ \n \\hline ",iterStep, numS, *gap);
			   */


			/*
			   printf("\n %e",*gap);
			   */

			/*		

					printf("\n %d",numS);

*/

			if (*gap <=tol){
				//tFlag=1;
				break;
			}

			m=1;
			if (nn > 1000000)
				m=5;
			else
				if (nn > 100000)
					m=3;

			if ( abs( numS-numSp) <m ){

				/*
				   printf("\n numS=%d, numSp=%d",numS,numSp);
				   */

				m=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){

					numS=m;
					tFlag=2;
					break;
				}


				if ( (*gap ==gappp) && (numS==numSpp) ){

					tFlag=2;
					break;

				}

			} /*end of if*/

		}/*end of if tau*/


	} /*end of for*/



	if (tFlag!=2){
		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);

	*activeS=numS;
	return(iterStep);
}
Пример #4
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);

}
ErrNo Interpolation_Algorithm::Piecewise_Spline_Interpolation_DF(const DPOINT *dpoints,const double compvalue,const int degree,double &result)
{
	ErrNo				err;
	double				differ = 0.0 ,differ2 = 0.0;
	double				**Tridiagonal_Matrix = NULL,*step_vector = NULL,*para_vector = NULL;

	//申请矩阵空间
	if(!(Tridiagonal_Matrix = new double* [4]))
	{
		return ALLOCATE_MEMORY_FAIL;
	}
	for(int i=0;i<4;i++)
	{
		Tridiagonal_Matrix[i] = new double[degree+1];
		if(!Tridiagonal_Matrix)
		{
			return ALLOCATE_MEMORY_FAIL;
		}
	}

	//申请保存每个区间长度的大小
	if(!(step_vector = new double [degree]))
	{
		return ALLOCATE_MEMORY_FAIL;
	}

	//申请空间保存系数
	if(!(para_vector = new double [degree+1]))
	{
		return ALLOCATE_MEMORY_FAIL;
	}

	//计算每个区间的大小
	for(int i=0;i<=degree-1;i++)
	{
		step_vector[i] = dpoints[i+1].x - dpoints[i].x;
		if(fabs(step_vector[i]) < eps)
			return DIVIDE_BY_ZERO;
	}

	//三对角矩阵的数据
	for(int i=0;i<=degree;i++)
	{
		Tridiagonal_Matrix[1][i] = 2.0;
	}
	Tridiagonal_Matrix[0][degree-1] = 1.0;
	Tridiagonal_Matrix[2][0] = 1.0;

	differ = dpoints[1].x - dpoints[0].x;
	if(fabs(differ) < eps)
		return DIVIDE_BY_ZERO;
	Tridiagonal_Matrix[3][0] = 6*(dpoints[1].fx - dpoints[0].fx - dpoints[0].df) / differ; 

	differ = dpoints[degree].x - dpoints[degree-1].x;
	if(fabs(differ) < eps)
		return	DIVIDE_BY_ZERO;
	Tridiagonal_Matrix[3][degree] = 6*(dpoints[degree].df - (dpoints[degree].fx - dpoints[degree-1].fx)) / differ; 
	
	for(int i=0;i<=degree-2;i++)
	{
		Tridiagonal_Matrix[0][i] = step_vector[i] / (step_vector[i] + step_vector[i+1]);
	}
	for(int i=1;i<=degree-1;i++)
	{
		Tridiagonal_Matrix[2][i] = step_vector[i] / (step_vector[i-1] + step_vector[i]);
	}
	for(int i=1;i<=degree-1;i++)
	{
		Tridiagonal_Matrix[3][i] = 6*( (dpoints[i+1].fx - dpoints[i].fx) / step_vector[i] - (dpoints[i].fx - dpoints[i-1].fx) / step_vector[i-1] ) / (step_vector[i-1] + step_vector[i]);
	}

	if( err = Thomas(Tridiagonal_Matrix,para_vector,degree+1))
		return err;

	//由所求点求f(x)值
	if(compvalue < dpoints[0].x || compvalue > dpoints[degree].x)				//超出所求区间
		return NOT_IN_INTERVAL;
	for(int i=0;i<degree;i++)
	{
		if(compvalue == dpoints[i].x)
		{
			result = dpoints[i].fx;
			break;
		}
		else if (compvalue > dpoints[i].x && compvalue <= dpoints[i+1].x)
		{
			differ = dpoints[i+1].x - compvalue;
			differ2 = compvalue - dpoints[i].x;
			result = para_vector[i]*differ*differ*differ/(6*step_vector[i]) + para_vector[i+1]*differ2*differ2*differ2/(6*step_vector[i]) + \
				(dpoints[i].fx - para_vector[i]*step_vector[i]*step_vector[i]/6)*differ/step_vector[i] + (dpoints[i+1].fx - para_vector[i+1]*step_vector[i]*step_vector[i]/6)*differ2/step_vector[i] ;
			break;
		}
	}

	//销毁指针
	for(int i=0;i<4;i++)
		delete [] Tridiagonal_Matrix[i];
	delete [] Tridiagonal_Matrix;
	Tridiagonal_Matrix = NULL;
	delete [] step_vector;
	step_vector = NULL;
	return 0;
}
Пример #6
0
void flsa(double *x, double *z, double *infor,
		double * v, double *z0,
		double lambda1, double lambda2, int n,
		int maxStep, double tol, int tau, int flag)
{

	int i, nn=n-1, m;
	double zMax, temp;
	double *Av, *g, *s;
	int iterStep, numS;
	double gap;
	double *zz = NULL; /*to replace z0, so that z0 shall not revised after */


	Av=(double *) malloc(sizeof(double)*nn);

	/*
	   Compute Av= A*v                  (n=4, nn=3)
	   A= [ -1  1  0  0;
	   0  -1 1  0;
	   0  0  -1 1]
	   */

	for (i=0;i<nn; i++)
		Av[i]=v[i+1]-v[i];

	/*
	   Sovlve the linear system via Thomas's algorithm or Rose's algorithm
	   B * z0 = Av
	   */

	Thomas(&zMax, z, Av, nn);

	/*
	   We consider two cases:
	   1) lambda2 >= zMax, which leads to a solution with same entry values
	   2) lambda2 < zMax, which needs to first run sfa, and then perform soft thresholding
	   */

	/*
	   First case: lambda2 >= zMax
	   */
	if (lambda2 >= zMax){

		temp=0;
		m=n%5;
		if (m!=0){
			for (i=0;i<m;i++)
				temp+=v[i];
		}
		for (i=m;i<n;i+=5){
			temp += v[i] + v[i+1] + v[i+2] + v[i+3] + v[i+4];
		}
		temp/=n;
		/* temp is the mean value of v*/


		/*
		   soft thresholding by lambda1
		   */
		if (temp> lambda1)
			temp= temp-lambda1;
		else
			if (temp < -lambda1)
				temp= temp+lambda1;
			else
				temp=0;

		m=n%7;
		if (m!=0){
			for (i=0;i<m;i++)
				x[i]=temp;
		}
		for (i=m;i<n;i+=7){
			x[i]   =temp;
			x[i+1] =temp;
			x[i+2] =temp;
			x[i+3] =temp;
			x[i+4] =temp;
			x[i+5] =temp;
			x[i+6] =temp;
		}

		gap=0;

		free(Av);

		if (infor)
		{
			infor[0]= gap;
			infor[1]= 0;
			infor[2]=zMax;
			infor[3]=0;
		}

		return;
	}


	/*
	   Second case: lambda2 < zMax

	   We need to call sfa for computing x, and then do soft thresholding

	   Before calling sfa, we need to allocate memory for g and s,
	   and initialize z and z0.
	   */


	/*
	   Allocate memory for g and s
	   */

	g    =(double *) malloc(sizeof(double)*nn),
		 s    =(double *) malloc(sizeof(double)*nn);



	m=flag /10;
	/*

	   If m=0, then this shows that, z0 is a "good" starting point. (m=1-6)

	   Otherwise (m=11-16), we shall set z as either the solution to the linear system.
	   or the zero point

*/
	if (m==0){
		for (i=0;i<nn;i++){
			if (z0[i] > lambda2)
				z[i]=lambda2;
			else
				if (z0[i]<-lambda2)
					z[i]=-lambda2;
				else
					z[i]=z0[i];
		}
	}
	else{
		if (lambda2 >= 0.5 * zMax){
			for (i=0;i<nn;i++){
				if (z[i] > lambda2)
					z[i]=lambda2;
				else
					if (z[i]<-lambda2)
						z[i]=-lambda2;
			}
		}
		else{
			for (i=0;i<nn;i++)
				z[i]=0;

		}
	}

	flag=flag %10;  /*
					   flag is now in [1:6]

					   for sfa, i.e., flag in [1:4], we need initialize z0 with zero
					   */

	if (flag>=1 && flag<=4){
		zz    =(double *) malloc(sizeof(double)*nn);

		for (i=0;i<nn;i++)
			zz[i]=0;
	}

	/*
	   call sfa, sfa_one, or sfa_special to compute z, for finding the subgradient
	   and x
	   */

	if (flag==6)
		iterStep=sfa_one(x, &gap, &numS,
				z,  v,   Av,
				lambda2, nn,  maxStep,
				s, g,
				tol, tau);
	else
		if (flag==5)
			iterStep=sfa_special(x, &gap, &numS,
					z,  v,   Av,
					lambda2, nn,  maxStep,
					s, g,
					tol, tau);
		else{
			iterStep=sfa(x, &gap, &numS,
					z, zz,   v,  Av,
					lambda2, nn, maxStep,
					s,  g,
					tol,tau, flag);

			free (zz);
			/*free the variable zz*/
		}


	/*
	   soft thresholding by lambda1
	   */

	for(i=0;i<n;i++)
		if (x[i] > lambda1)
			x[i]-=lambda1;
		else
			if (x[i]<-lambda1)
				x[i]+=lambda1;
			else
				x[i]=0;


	free(Av);
	free(g);
	free(s);

	if (infor)
	{
		infor[0]=gap;
		infor[1]=iterStep;
		infor[2]=zMax;
		infor[3]=numS;
	}
}