Xmipp  v3.23.11-Nereus
Functions
Solver.h File Reference
#include "IntPoly.h"
#include "Vector.h"
Include dependency graph for Solver.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

Vector L2NormMinimizer (Polynomial q, double delta, int *infoOut=NULL, int maxIter=1000, double *lambda1=NULL)
 
Vector L2NormMinimizer (Polynomial q, Vector pointXk, double delta, int *infoOut=NULL, int maxIter=1000, double *lambda1=NULL)
 
Vector L2NormMinimizer (Polynomial q, Vector pointXk, double delta, int *infoOut, int maxIter, double *lambda1, Vector minusG, Matrix H)
 
Vector LAGMAXModified (Polynomial q, double rho, double &VMAX)
 
Vector LAGMAXModified (Polynomial q, Vector pointXk, double rho, double &VMAX)
 
Vector LAGMAXModified (Vector G, Matrix H, double rho, double &VMAX)
 
void CONDOR (double rhoStart, double rhoEnd, int niter, ObjectiveFunction *of, int nnode=0)
 

Function Documentation

◆ CONDOR()

void CONDOR ( double  rhoStart,
double  rhoEnd,
int  niter,
ObjectiveFunction of,
int  nnode = 0 
)

Definition at line 75 of file CNLSolver.cpp.

77 {
78  rhoStart=mmax(rhoStart,rhoEnd);
79  int dim=of->dim(), info, k, t, nerror;
80  double rho=rhoStart, delta=rhoStart, rhoNew,
81  lambda1, normD=rhoEnd+1.0, modelStep, reduction, r, valueOF, valueFk, bound, noise;
82  Vector d, tmp;
83  bool improvement, forceTRStep=true, evalNeeded;
84 
86 
87  // pre-create the MultInd indexes to prevent multi-thread problems:
88  cacheMultInd.get(dim,1); cacheMultInd.get(dim,2);
89 
90  parallelInit(nnode, dim, of);
91 
92  of->initData();
93 // points=getFirstPoints(&ValuesF, &nPtsTotal, rhoStart,of);
94 
95  InterPolynomial poly(2, rho, Vector::emptyVector, of->data, of);
96  if (poly.NewtonBasis==NULL)
97  {
98  printf("cannot construct lagrange basis.\n");
99  exit(255);
100  }
101 
102 
103 
104  //Base=poly.vBase;
105  k=poly.kbest;
106  valueFk=poly.valuesF[k];
107 
108  //fprintf(stderr,"init part 1 finished.\n");
109 
110 /* InterPolynomial poly(dim,2,of);
111  for (;;)
112  {
113  // find index k of the best (lowest) value of the function
114  k=findK(ValuesF, nPtsTotal, of, points);
115  Base=points[k].clone();
116  // Base=of->xStart.clone();
117  valueFk=ValuesF[k];
118  // translation:
119  t=nPtsTotal; while (t--) points[t]-=Base;
120 
121  // exchange index 0 and index k (to be sure best point is inside poly):
122  tmp=points[k];
123  points[k]=points[0];
124  points[0]=tmp;
125  ValuesF[k]=ValuesF[0];
126  ValuesF[0]=valueFk;
127  k=0;
128 
129  poly=InterPolynomial(2, nPtsTotal, points, ValuesF);
130  if (poly.NewtonBasis!=NULL) break;
131 
132  // the construction of the first polynomial has failed
133  // delete[] points;
134  free(ValuesF);
135 
136  int kbest=findBest(of->data, of); // return 0 if startpoint is given
137  Vector BaseStart=of->data.getLine(kbest,dim);
138  double vBaseStart=((double**)of->data)[kbest][dim];
139  points=GenerateData(rho, BaseStart, vBaseStart, of, &ValuesF);
140  nPtsTotal=n;
141  }
142 */
143  // update M:
144  fullUpdateOfM(rho,poly.vBase,of->data,poly);
145 
146  //fprintf(stderr,"init part 2 finished.\n");
147  //fprintf(stderr,"init finished.\n");
148 
149  // first of init all variables:
150  parallelImprove(&poly, &k, rho, &valueFk, poly.vBase);
151 
152  // really start in parallel:
154 
155  while (true)
156  {
157 // fprintf(stderr,"rho=%e; fo=%e; NF=%i\n", rho,valueFk,QP_NF);
158  while (true)
159  {
160  // trust region step
161  while (true)
162  {
163 // poly.print();
164  parallelImprove(&poly, &k, rho, &valueFk, poly.vBase);
165 
166  niter--;
167  if ((niter==0)
168  ||(of->isConstrained&&checkForTermination(poly.NewtonPoints[k], poly.vBase, rhoEnd)))
169  {
170  poly.vBase+=poly.NewtonPoints[k];
171  //fprintf(stderr,"rho=%e; fo=%e; NF=%i\n", rho,valueFk,of->getNFE());
172  of->valueBest=valueFk;
173  of->xBest=poly.vBase;
174  // to do : compute H and Lambda
175 
176  Vector vG(dim);
177  Matrix mH(dim,dim);
178  poly.gradientHessian(poly.NewtonPoints[k],vG,mH);
179  of->finalize(vG,mH,FullLambda.clone());
180  return;
181  }
182 
183  // to debug:
184  //fprintf(stderr,"Best Value Objective=%e (nfe=%i)\n", valueFk, of->getNFE());
185 
186  d=ConstrainedL2NormMinimizer(poly,k,delta,&info,1000,&lambda1,poly.vBase,of);
187 
188 // if (d.euclidianNorm()>delta)
189 // {
190 // printf("Warning d to long: (%e > %e)\n", d.euclidianNorm(), delta);
191 // }
192 
193  normD=mmin(d.euclidianNorm(), delta);
194  d+=poly.NewtonPoints[k];
195 
196 // next line is equivalent to reduction=valueFk-poly(d);
197 // BUT is more precise (no rounding error)
198  reduction=-poly.shiftedEval(d,valueFk);
199 
200  //if (normD<0.5*rho) { evalNeeded=true; break; }
201  if ((normD<0.5*rho)&&(!forceTRStep)) { evalNeeded=true; break; }
202 
203  // IF THE MODEL REDUCTION IS SMALL, THEN WE DO NOT SAMPLE FUNCTION
204  // AT THE NEW POINT. WE THEN WILL TRY TO IMPROVE THE MODEL.
205 
206  noise=0.5*mmax(of->noiseAbsolute*(1+of->noiseRelative), condorAbs(valueFk)*of->noiseRelative);
207  if ((reduction<noise)&&(!forceTRStep)) { evalNeeded=true; break; }
208  forceTRStep=false; evalNeeded=false;
209 
210  if (quickHack) (*quickHack)(poly,k);
211  tmp=poly.vBase+d; nerror=0; valueOF=of->eval(tmp, &nerror);
212  of->saveValue(tmp,valueOF,nerror);
213  if (nerror)
214  {
215  // evaluation failed
216  delta*=0.5;
217  if (normD>=2*rho) continue;
218  break;
219  }
220  if (!of->isFeasible(tmp, &r))
221  {
222  printf("violation: %e\n",r);
223  }
224 
225  // update of delta:
226  r=(valueFk-valueOF)/reduction;
227  if (r<=0.1) delta=0.5*normD;
228  else if (r<0.7) delta=mmax(0.5*delta, normD);
229  else delta=mmax(rho+ normD, mmax(1.25*normD, delta));
230  // powell's heuristics:
231  if (delta<1.5*rho) delta=rho;
232 
233  if (valueOF<valueFk)
234  {
235  t=poly.findAGoodPointToReplace(-1, rho, d,&modelStep);
236  k=t; valueFk=valueOF;
237  improvement=true;
238 // fprintf(stderr,"Value Objective=%e\n", valueOF);
239  } else
240  {
241  t=poly.findAGoodPointToReplace(k, rho, d,&modelStep);
242  improvement=false;
243 // fprintf(stderr,".");
244  };
245 
246  if (t<0) { poly.updateM(d, valueOF); break; }
247 
248  // If we are along constraints, it's more important to update
249  // the polynomial with points which increase its quality.
250  // Thus, we will skip this update to use only points coming
251  // from checkIfValidityIsInBound
252 
253  if ((!of->isConstrained)||(improvement)||(reduction>0.0)||(normD<rho)) poly.replace(t, d, valueOF);
254 
255  if (improvement) continue;
256 // if (modelStep>4*rho*rho) continue;
257  if (modelStep>2*rho) continue;
258  if (normD>=2*rho) continue;
259  break;
260  }
261  // model improvement step
262  forceTRStep=true;
263 
264 // fprintf(stderr,"improvement step\n");
265  bound=0.0;
266  if (normD<0.5*rho)
267  {
268  bound=0.5*sqr(rho)*lambda1;
269  if (poly.nUpdateOfM<10) bound=0.0;
270  }
271 
272  parallelImprove(&poly, &k, rho, &valueFk, poly.vBase);
273 
274  // !! change d (if needed):
275  t=poly.checkIfValidityIsInBound(d, k, bound, rho );
276  if (t>=0)
277  {
278  if (quickHack) (*quickHack)(poly,k);
279  tmp=poly.vBase+d; nerror=0; valueOF=of->eval(tmp, &nerror);
280  if (nerror)
281  {
282  Vector GXk(dim);
283  Matrix H(dim,dim);
284  poly.NewtonBasis[t].gradientHessian(poly.NewtonPoints[k],GXk,H);
285  double rhot=rho,vmax;
286 
287  while (nerror)
288  {
289  rhot*=.5;
290  d=LAGMAXModified(GXk,H,rhot,vmax);
291  d+=poly.NewtonPoints[k];
292  tmp=poly.vBase+d; nerror=0; valueOF=of->eval(tmp, &nerror);
293  of->saveValue(tmp,valueOF,nerror);
294  }
295  }
296  poly.replace(t, d, valueOF);
297  if ((valueOF<valueFk)&&
298  (of->isFeasible(tmp))) { k=t; valueFk=valueOF; };
299  continue;
300  }
301 
302  // the model is perfect for this value of rho:
303  // OR
304  // we have crossed a non_linear constraint which prevent us to advance
305  if ((normD<=rho)||(reduction<0.0)) break;
306  }
307 
308 
309 
310  // change rho because no improvement can now be made:
311  if (rho<=rhoEnd) break;
312 
313  //fprintf(stderr,"rho=%e; fo=%e; NF=%i\n", rho,valueFk,of->getNFE());
314 
315  if (rho<16*rhoEnd) rhoNew=rhoEnd;
316  else if (rho<250*rhoEnd) rhoNew=sqrt(rho*rhoEnd);
317  else rhoNew=0.1*rho;
318  delta=mmax(0.5*rho,rhoNew);
319  rho=rhoNew;
320 
321 
322  // update of the polynomial: translation of x[k].
323  // replace BASE by BASE+x[k]
324  poly.translate(poly.NewtonPoints[k]);
325  }
326  parallelFinish();
327 
328  Vector vG(dim);
329  Matrix mH(dim,dim);
330 
331 
332 
333  if (evalNeeded)
334  {
335  tmp=poly.vBase+d; nerror=0; valueOF=of->eval(tmp,&nerror);
336  of->saveValue(tmp,valueOF,nerror);
337  if ((nerror)||(valueOF<valueFk))
338  {
339  poly.vBase+=poly.NewtonPoints[k];
340  poly.gradientHessian(poly.NewtonPoints[k],vG,mH);
341  }
342  else
343  {
344  valueFk=valueOF; poly.vBase=tmp;
345  poly.gradientHessian(d,vG,mH);
346  }
347  } else
348  {
349  poly.vBase+=poly.NewtonPoints[k];
350  poly.gradientHessian(poly.NewtonPoints[k],vG,mH);
351  }
352 
353 
354 // delete[] points; :not necessary: done in destructor of poly which is called automatically:
355  //fprintf(stderr,"rho=%e; fo=%e; NF=%i\n", rho,valueFk,of->getNFE());
356 
357  of->valueBest=valueFk;
358  of->xBest=poly.vBase;
359  of->finalize(vG,mH,FullLambda.clone());
360 
361 }
virtual void saveValue(Vector tmp, double valueOF, int nerror)
virtual void finalize(Vector vG, Matrix mH, Vector vLambda)
MultIndCache cacheMultInd
Definition: MultInd.cpp:42
int * mmax
void parallelFinish()
Definition: parallel.cpp:41
void fullUpdateOfM(double rho, Vector Base, Matrix data, InterPolynomial poly)
Definition: CNLSolver.cpp:60
double rho
void sqrt(Image< double > &op)
Definition: Vector.h:37
void parallelImprove(InterPolynomial *p, int *_k, double _rho, double *_valueFk, Vector _Base)
Definition: parallel.cpp:36
double euclidianNorm()
Definition: Vector.cpp:222
double mmin(const double t1, const double t2)
Definition: tools.h:69
MultInd * get(unsigned _dim, unsigned _deg)
Definition: MultInd.cpp:242
Vector clone()
Definition: Vector.cpp:207
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
doublereal * d
virtual double eval(Vector v, int *nerror)=0
void initConstrainedStep(ObjectiveFunction *of)
Definition: CTRSSolver.cpp:57
double sqr(const double &t)
Definition: tools.h:99
char isFeasible(Vector vx, double *d=NULL)
Vector LAGMAXModified(Vector G, Matrix H, double rho, double &VMAX)
Definition: MSSolver.cpp:40
char checkForTermination(Vector d, Vector Base, double rhoEnd)
Definition: CTRSSolver.cpp:56
double condorAbs(const double t1)
Definition: tools.h:47
void(* quickHack)(InterPolynomial, int)
Definition: CNLSolver.cpp:48
void startParallelThread()
Definition: parallel.cpp:39
Definition: Matrix.h:38
void parallelInit(int _nnode, int _dim, ObjectiveFunction *_of)
Definition: parallel.cpp:40
static Vector emptyVector
Definition: Vector.h:119
Vector ConstrainedL2NormMinimizer(InterPolynomial poly, int k, double delta, int *info, int iterMax, double *lambda1, Vector vOBase, ObjectiveFunction *of)
Definition: CTRSSolver.cpp:59
Vector FullLambda
Definition: CTRSSolver.cpp:38
double * delta

◆ L2NormMinimizer() [1/3]

Vector L2NormMinimizer ( Polynomial  q,
double  delta,
int *  infoOut = NULL,
int  maxIter = 1000,
double *  lambda1 = NULL 
)

Definition at line 307 of file UTRSSolver.cpp.

309 {
310  return L2NormMinimizer(q, Vector::emptyVector, delta, infoOut, maxIter, lambda1);
311 }
Vector L2NormMinimizer(Polynomial q, Vector pointXk, double delta, int *infoOut, int maxIter, double *lambda1, Vector minusG, Matrix H)
Definition: UTRSSolver.cpp:147
static Vector emptyVector
Definition: Vector.h:119
double * delta

◆ L2NormMinimizer() [2/3]

Vector L2NormMinimizer ( Polynomial  q,
Vector  pointXk,
double  delta,
int *  infoOut = NULL,
int  maxIter = 1000,
double *  lambda1 = NULL 
)

Definition at line 297 of file UTRSSolver.cpp.

299 {
300  int n=q.dim();
301  Matrix H(n,n);
302  Vector vG(n);
303  q.gradientHessian(pointXk,vG,H);
304  return L2NormMinimizer(q,pointXk,delta,infoOut,maxIter,lambda1,vG,H);
305 }
Vector L2NormMinimizer(Polynomial q, Vector pointXk, double delta, int *infoOut, int maxIter, double *lambda1, Vector minusG, Matrix H)
Definition: UTRSSolver.cpp:147
Definition: Vector.h:37
unsigned dim()
Definition: Poly.h:62
void gradientHessian(Vector P, Vector G, Matrix H)
Definition: Poly.cpp:515
Definition: Matrix.h:38
int * n
double * delta

◆ L2NormMinimizer() [3/3]

Vector L2NormMinimizer ( Polynomial  q,
Vector  pointXk,
double  delta,
int *  infoOut,
int  maxIter,
double *  lambda1,
Vector  minusG,
Matrix  H 
)

Definition at line 147 of file UTRSSolver.cpp.

149 {
150 // lambda1>0.0 if interior convergence
151 
152  const double theta=0.01;
153 // const double kappaEasy=0.1, kappaHard=0.2;
154  const double kappaEasy=0.01, kappaHard=0.02;
155 
156  double normG,lambda,lambdaCorrection, lambdaPlus, lambdaL, lambdaU,
157  uHu, alpha, normS;
158  int info=0, n=minusG.sz();
159  Matrix HLambda(n,n);
160  MatrixTriangle L(n);
161  Vector s(n), omega(n), u(n), sFinal;
162  bool gIsNull, choleskyFactorAlreadyComputed=false;
163 
164 // printf("\nG= "); minusG.print();
165 // printf("\nH=\n"); H.print();
166 
167  gIsNull=minusG.isNull();
168  normG=minusG.euclidianNorm();
169  lambda=normG/delta;
170  minusG.multiply(-1.0);
171 
172  lambdaL=initLambdaL(normG,delta,H);
173  lambdaU=initLambdaU(normG,delta,H);
174 
175  // Special case: parl = paru.
176  lambdaU= mmax(lambdaU,(1+kappaEasy)*lambdaL);
177 
178  lambda=mmax(lambda, lambdaL);
179  lambda=mmin(lambda, lambdaU);
180 
181  while (maxIter--)
182  {
183  if (!choleskyFactorAlreadyComputed)
184  {
185  if (!H.cholesky(L, lambda, &lambdaCorrection))
186  {
187  // lambdaL=mmax(mmax(lambdaL,lambda),lambdaCorrection);
188  lambdaL=mmax(lambdaL,lambda+lambdaCorrection);
189  lambda=mmax(sqrt(lambdaL*lambdaU), lambdaL+theta*(lambdaU-lambdaL));
190  continue;
191  }
192  } else choleskyFactorAlreadyComputed=false;
193 
194 
195  // cholesky factorization successful : solve Hlambda * s = -G
196  s.copyFrom(minusG);
197  L.solveInPlace(s);
198  L.solveTransposInPlace(s);
199  normS=s.euclidianNorm();
200 
201  // check for termination
202 #ifndef POWEL_TERMINATION
203  if (condorAbs(normS-delta)<kappaEasy*delta)
204  {
205  s.multiply(delta/normS);
206  info=1;
207  break;
208  }
209 #else
210 // powell check !!!
211  HLambda.copyFrom(H);
212  HLambda.addUnityInPlace(lambda);
213  double sHs=s.scalarProduct(HLambda.multiply(s));
214  if (sqr(delta/normS-1)<kappaEasy*(1+lambda*delta*delta/sHs))
215  {
216  s.multiply(delta/normS);
217  info=1;
218  break;
219  }
220 #endif
221 
222  if (normS<delta)
223  {
224  // check for termination
225  // interior convergence; maybe break;
226  if (lambda==0) { info=1; break; }
227  lambdaU=mmin(lambdaU,lambda);
228  } else lambdaL=mmax(lambdaL,lambda);
229 
230 // if (lambdaU-lambdaL<kappaEasy*(2-kappaEasy)*lambdaL) { info=3; break; };
231 
232  omega.copyFrom(s);
233  L.solveInPlace(omega);
234  lambdaPlus=lambda+(normS-delta)/delta*sqr(normS)/sqr(omega.euclidianNorm());
235  lambdaPlus=mmax(lambdaPlus, lambdaL);
236  lambdaPlus=mmin(lambdaPlus, lambdaU);
237 
238  if (normS<delta)
239  {
240  L.LINPACK(u);
241 #ifndef POWEL_TERMINATION
242  HLambda.copyFrom(H);
243  HLambda.addUnityInPlace(lambda);
244 #endif
245  uHu=u.scalarProduct(HLambda.multiply(u));
246  lambdaL=mmax(lambdaL,lambda-uHu);
247 
248  alpha=findAlpha(s,u,delta,q,pointXk,sFinal,minusG,H);
249  // check for termination
250 #ifndef POWEL_TERMINATION
251  if (sqr(alpha)*uHu<
252  kappaHard*(s.scalarProduct(HLambda.multiply(s)) ))// +lambda*sqr(delta)))
253 #else
254  if (sqr(alpha)*uHu+sHs<
255  kappaHard*(sHs+lambda*sqr(delta)))
256 #endif
257  {
258  s=sFinal; info=2; break;
259  }
260  }
261  if ((normS>delta)&&(!gIsNull)) { lambda=lambdaPlus; continue; };
262 
263  if (H.cholesky(L, lambdaPlus, &lambdaCorrection))
264  {
265  lambda=lambdaPlus;
266  choleskyFactorAlreadyComputed=true;
267  continue;
268  }
269 
270  lambdaL=mmax(lambdaL,lambdaPlus);
271  // check lambdaL for interior convergence
272 // if (lambdaL==0) return s;
273  lambda=mmax(sqrt(lambdaL*lambdaU), lambdaL+theta*(lambdaU-lambdaL));
274  }
275 
276  if (infoOut) *infoOut=info;
277  if (lambda1)
278  {
279  if (lambda==0.0)
280  {
281  // calculate the value of the lowest eigenvalue of H
282  // to check
283  lambdaL=0; lambdaU=initLambdaU2(H);
284  while (lambdaL<0.99*lambdaU)
285  {
286  lambda=0.5*(lambdaL+lambdaU);
287  if (H.cholesky(L,-lambda)) lambdaL=lambda;
288 // if (H.cholesky(L,-lambda,&lambdaCorrection)) lambdaL=lambda+lambdaCorrection;
289  else lambdaU=lambda;
290  }
291  *lambda1=lambdaL;
292  } else *lambda1=0.0;
293  }
294  return s;
295 }
double initLambdaL(double normG, double delta, Matrix H)
Definition: UTRSSolver.cpp:90
int * mmax
double initLambdaU2(Matrix H)
Definition: UTRSSolver.cpp:130
void sqrt(Image< double > &op)
Definition: Vector.h:37
double euclidianNorm()
Definition: Vector.cpp:222
double mmin(const double t1, const double t2)
Definition: tools.h:69
double initLambdaU(double normG, double delta, Matrix H)
Definition: UTRSSolver.cpp:112
double theta
unsigned sz()
Definition: Vector.h:79
double sqr(const double &t)
Definition: tools.h:99
bool cholesky(MatrixTriangle matL, double lambda=0, double *lambdaCorrection=NULL)
Definition: Matrix.cpp:763
double * lambda
double condorAbs(const double t1)
Definition: tools.h:47
Definition: Matrix.h:38
void multiply(double a)
Definition: Vector.cpp:281
bool isNull()
Definition: Vector.cpp:358
doublereal * u
double findAlpha(Vector s, Vector u, double delta, Polynomial &q, Vector pointXk, Vector &output, Vector minusG, Matrix H)
Definition: UTRSSolver.cpp:35
int * n
double * delta

◆ LAGMAXModified() [1/3]

Vector LAGMAXModified ( Polynomial  q,
double  rho,
double &  VMAX 
)

Definition at line 217 of file MSSolver.cpp.

218 {
219  return LAGMAXModified(q,Vector::emptyVector,rho,VMAX);
220 }
double rho
static Vector emptyVector
Definition: Vector.h:119
Vector LAGMAXModified(Vector G, Matrix H, double rho, double &VMAX)
Definition: MSSolver.cpp:40

◆ LAGMAXModified() [2/3]

Vector LAGMAXModified ( Polynomial  q,
Vector  pointXk,
double  rho,
double &  VMAX 
)

Definition at line 208 of file MSSolver.cpp.

209 {
210  int n=q.dim();
211  Matrix H(n,n);
212  Vector G(n), D(n);
213  q.gradientHessian(pointXk,G,H);
214  return LAGMAXModified(G,H,rho,VMAX);
215 }
double rho
Definition: Vector.h:37
unsigned dim()
Definition: Poly.h:62
void gradientHessian(Vector P, Vector G, Matrix H)
Definition: Poly.cpp:515
Definition: Matrix.h:38
Vector LAGMAXModified(Vector G, Matrix H, double rho, double &VMAX)
Definition: MSSolver.cpp:40
int * n

◆ LAGMAXModified() [3/3]

Vector LAGMAXModified ( Vector  G,
Matrix  H,
double  rho,
double &  VMAX 
)

Definition at line 40 of file MSSolver.cpp.

41 {
42  //not tested in depth but running already quite good
43 
44 // SUBROUTINE LAGMAX (N,G,H,RHO,D,V,VMAX)
45 // IMPLICIT REAL*8 (A-H,O-Z)
46 // DIMENSION G(*),H(N,*),D(*),V(*)
47 //
48 // N is the number of variables of a quadratic objective function, Q say.
49 // G is the gradient of Q at the origin.
50 // H is the symmetric Hessian matrix of Q. Only the upper triangular and
51 // diagonal parts need be set.
52 // RHO is the trust region radius, and has to be positive.
53 // D will be set to the calculated vector of variables.
54 // The array V will be used for working space.
55 // VMAX will be set to |Q(0)-Q(D)|.
56 //
57 // Calculating the D that maximizes |Q(0)-Q(D)| subject to ||D|| .EQ. RHO
58 // requires of order N**3 operations, but sometimes it is adequate if
59 // |Q(0)-Q(D)| is within about 0.9 of its greatest possible value. This
60 // subroutine provides such a solution in only of order N**2 operations,
61 // where the claim of accuracy has been tested by numerical experiments.
62 /*
63  int n=G.sz();
64  Vector D(n), V(n);
65  lagmax_(&n, (double *)G, *((double**)H), &rho,
66  (double*)D, (double*)V, &VMAX);
67  return D;
68 */
69  int i,n=G.sz();
70  Vector D(n);
71 
72  Vector V=H.getMaxColumn();
73  D=H.multiply(V);
74  double vv=V.square(),
75  dd=D.square(),
76  vd=V.scalarProduct(D),
77  dhd=D.scalarProduct(H.multiply(D)),
78  *d=D, *v=V, *g=G;
79 
80 //
81 // Set D to a vector in the subspace spanned by V and HV that maximizes
82 // |(D,HD)|/(D,D), except that we set D=HV if V and HV are nearly parallel.
83 //
84  if (sqr(vd)<0.9999*vv*dd)
85  {
86  double a=dhd*vd-dd*dd,
87  b=.5*(dhd*vv-dd*vd),
88  c=dd*vv-vd*vd,
89  tmp1=-b/a;
90  if (b*b>a*c)
91  {
92  double tmp2=sqrt(b*b-a*c)/a, dd1, dd2, dhd1, dhd2;
93  Vector D1=D.clone();
94  D1.multiply(tmp1+tmp2);
95  D1+=V;
96  dd1=D1.square();
97  dhd1=D1.scalarProduct(H.multiply(D1));
98 
99  Vector D2=D.clone();
100  D2.multiply(tmp1-tmp2);
101  D2+=V;
102  dd2=D2.square();
103  dhd2=D2.scalarProduct(H.multiply(D2));
104 
105  if (condorAbs(dhd1/dd1)>condorAbs(dhd2/dd2)) { D=D1; dd=dd1; dhd=dhd1; }
106  else { D=D2; dd=dd2; dhd=dhd2; }
107  d=(double*)D;
108  }
109  };
110 
111 
112 //
113 // We now turn our attention to the subspace spanned by G and D. A multiple
114 // of the current D is returned if that choice seems to be adequate.
115 //
116  double gg=G.square(),
117  normG=sqrt(gg),
118  gd=G.scalarProduct(D),
119  temp=gd/gg,
120  scale=sign(rho/sqrt(dd), gd*dhd);
121 
122  i=n; while (i--) v[i]=d[i]-temp*g[i];
123  vv=V.square();
124 
125  if ((normG*dd)<(0.5-2*rho*condorAbs(dhd))||(vv/dd<1e-4))
126  {
127  D.multiply(scale);
128  VMAX=condorAbs(scale*(gd+0.5*scale*dhd));
129  return D;
130  }
131 
132 //
133 // G and V are now orthogonal in the subspace spanned by G and D. Hence
134 // we generate an orthonormal basis of this subspace such that (D,HV) is
135 // negligible or zero, where D and V will be the basis vectors.
136 //
137  H.multiply(D,G); // D=HG;
138  double ghg=G.scalarProduct(D),
139  vhg=V.scalarProduct(D),
140  vhv=V.scalarProduct(H.multiply(V));
141  double theta, cosTheta, sinTheta;
142 
143  if (condorAbs(vhg)<0.01*mmax(condorAbs(vhv),condorAbs(ghg)))
144  {
145  cosTheta=1.0;
146  sinTheta=0.0;
147  } else
148  {
149  theta=0.5*atan(0.5*vhg/(vhv-ghg));
150  cosTheta=cos(theta);
151  sinTheta=sin(theta);
152  }
153  i=n;
154  while(i--)
155  {
156  d[i]= cosTheta*g[i]+ sinTheta*v[i];
157  v[i]=-sinTheta*g[i]+ cosTheta*v[i];
158  };
159 
160 //
161 // The final D is a multiple of the current D, V, D+V or D-V. We make the
162 // choice from these possibilities that is optimal.
163 //
164 
165  double norm=rho/D.euclidianNorm();
166  D.multiply(norm);
167  dhd=(ghg*sqr(cosTheta)+vhv*sqr(sinTheta))*sqr(norm);
168 
169  norm=rho/V.euclidianNorm();
170  V.multiply(norm);
171  vhv=(ghg*sqr(sinTheta)+vhv*sqr(cosTheta)*sqr(norm));
172 
173  double halfRootTwo=sqrt(0.5), // =sqrt(2)/2=cos(PI/4)
174  t1=normG*cosTheta*rho, // t1=condorAbs(D.scalarProduct(G));
175  t2=normG*sinTheta*rho, // t2=condorAbs(V.scalarProduct(G));
176  at1=condorAbs(t1),
177  at2=condorAbs(t2),
178  t3=0.25*(dhd+vhv),
179  q1=condorAbs(at1+0.5*dhd),
180  q2=condorAbs(at2+0.5*vhv),
181  q3=condorAbs(halfRootTwo*(at1+at2)+t3),
182  q4=condorAbs(halfRootTwo*(at1-at2)+t3);
183  if ((q4>q3)&&(q4>q2)&&(q4>q1))
184  {
185  double st1=sign(t1*t3), st2=sign(t2*t3);
186  i=n; while (i--) d[i]=halfRootTwo*(st1*d[i]-st2*v[i]);
187  VMAX=q4;
188  return D;
189  }
190  if ((q3>q2)&&(q3>q1))
191  {
192  double st1=sign(t1*t3), st2=sign(t2*t3);
193  i=n; while (i--) d[i]=halfRootTwo*(st1*d[i]+st2*v[i]);
194  VMAX=q3;
195  return D;
196  }
197  if (q2>q1)
198  {
199  if (t2*vhv<0) V.multiply(-1);
200  VMAX=q2;
201  return V;
202  }
203  if (t1*dhd<0) D.multiply(-1);
204  VMAX=q1;
205  return D;
206 }
double dhd
int * mmax
double sign
doublereal * c
doublereal * g
double rho
void sqrt(Image< double > &op)
Matrix multiply(Matrix B)
Definition: Matrix.cpp:633
Definition: Vector.h:37
double euclidianNorm()
Definition: Vector.cpp:222
T norm(const std::vector< T > &v)
Definition: vector_ops.h:399
#define q1
Vector clone()
Definition: Vector.cpp:207
#define i
doublereal * d
double theta
double vv
unsigned sz()
Definition: Vector.h:79
double sqr(const double &t)
Definition: tools.h:99
doublereal * b
Vector getMaxColumn()
Definition: Matrix.cpp:1073
double condorAbs(const double t1)
Definition: tools.h:47
double square()
Definition: Vector.cpp:236
void multiply(double a)
Definition: Vector.cpp:281
#define q2
double scalarProduct(Vector v)
Definition: Vector.cpp:332
int * n
#define q3
doublereal * a