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 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); }
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); }
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; }
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; } }