ANIMA  4.0
animaBobyqaOptimizer.cxx
Go to the documentation of this file.
1 /*
2  ** An ITK interface for the Newuoa optimizer, heavily based on powell's fortran version (f2c'ed)
3  ** The raw optimization is exactly the f2c version, but c++ encapsulated to match with itk optimizers (non linear optimizers, like PowellOptimizer).
4  */
5 
6 #include "animaBobyqaOptimizer.h"
7 #include <algorithm>
8 
9 namespace anima
10 {
11 
14 {
15 
16  m_MaximumIteration = 1000;
17 
18  m_NumberSamplingPoints = 0; // This value if still at 0 at optimization time, will be set at Parameters+2 at initialisation (minimum number of sampling point required for optimisation).
19 
20  m_RhoBegin = 5;
21  m_RhoEnd = 1e-3;
22 
23  m_Stop = false;
24 
25  m_Maximize = false;
26 
27  m_StopConditionDescription << this->GetNameOfClass() << ": ";
28 }
29 
30 
33 {
34 }
35 
36 
37 void
40 {
41  if( m_CostFunction.IsNull() )
42  {
43  return;
44  }
45 
46  m_StopConditionDescription.str("");
47  m_StopConditionDescription << this->GetNameOfClass() << ": ";
48 
49  this->InvokeEvent( itk::StartEvent() );
50  m_Stop = false;
51 
52  m_SpaceDimension = m_CostFunction->GetNumberOfParameters();
53 
54  if (!this->m_ScalesInitialized)
55  {
56  BobyqaOptimizer::ParametersType sc(m_SpaceDimension);
57  for (unsigned i = 0; i < m_SpaceDimension; ++i) sc[i] = 1.;
58  this->SetScales(sc);
59  }
60 
61  px = BobyqaOptimizer::ParametersType(m_SpaceDimension);
62 
63  BobyqaOptimizer::ParametersType ip(m_SpaceDimension);
64  ip = this->GetInitialPosition();
65 
66  double *p = new double[m_SpaceDimension];
67  double *xl = new double[m_SpaceDimension];
68  double *xu = new double[m_SpaceDimension];
69  for (unsigned i = 0; i < m_SpaceDimension; ++i)
70  {
71  p[i] = ip[i] * this->GetScales()[i];
72  xl[i] = m_LowerBounds[i] * this->GetScales()[i];
73  xu[i] = m_UpperBounds[i] * this->GetScales()[i];
74  }
75 
76  double av = 2 * m_SpaceDimension + 1;
77 
78  if (this->m_NumberSamplingPoints > m_SpaceDimension+2)
79  av = m_NumberSamplingPoints;
80 
81  long int npt = (int) av;
82  double *w = new double [(npt+13)*(npt+m_SpaceDimension)+3*m_SpaceDimension*(m_SpaceDimension+3)/2 + 10];
83 
84  long int maxfun = this->m_MaximumIteration;
85 
86  this->InvokeEvent( itk::StartEvent() );
87 
88  this->optimize(npt,p,xl,xu,m_RhoBegin,m_RhoEnd,maxfun,w);
89 
90  this->m_CurrentPosition = BobyqaOptimizer::ParametersType(m_SpaceDimension);
91  for (unsigned i = 0; i < m_SpaceDimension; ++i) m_CurrentPosition[i] = p[i] / this->GetScales()[i];
92 
93  delete[] w;
94  delete[] p;
95  delete[] xl;
96  delete[] xu;
97 }
98 
99 
103 const std::string
106 {
107  return m_StopConditionDescription.str();
108 }
109 
113 void
115 ::PrintSelf(std::ostream& os, itk::Indent indent) const
116 {
117  Superclass::PrintSelf(os,indent);
118 
119  os << indent << "Metric Worst Possible Value " << m_MetricWorstPossibleValue << std::endl;
120  os << indent << "Catch GetValue Exception " << m_CatchGetValueException << std::endl;
121  os << indent << "Space Dimension " << m_SpaceDimension << std::endl;
122  os << indent << "Maximum Iteration " << m_MaximumIteration << std::endl;
123  os << indent << "Current Iteration " << m_CurrentIteration << std::endl;
124  os << indent << "Maximize On/Off " << m_Maximize << std::endl;
125  os << indent << "Initial Space Rad. " << m_RhoBegin << std::endl;
126  os << indent << "Final Space Radius " << m_RhoEnd << std::endl;
127  os << indent << "Current Cost " << m_CurrentCost << std::endl;
128  os << indent << "Stop " << m_Stop << std::endl;
129 }
130 
131 int BobyqaOptimizer
132 ::optimize(long int &npt, double *x, double *xl, double *xu, double &rhobeg, double &rhoend,
133  long int &maxfun, double *w)
134 {
135  /* System generated locals */
136  long int i__1;
137  double d__1, d__2;
138 
139  /* Local variables */
140  long int j, id, np, iw, igo, ihq, ixb, ixa, ifv, isl, jsl, ipq, ivl, ixn, ixo, ixp, isu, jsu, ndim;
141  double temp, zero;
142  long int ibmat, izmat;
143 
144  /* This subroutine seeks the least value of a function of many variables, */
145  /* by applying a trust region method that forms quadratic models by */
146  /* interpolation. There is usually some freedom in the interpolation */
147  /* conditions, which is taken up by minimizing the Frobenius norm of */
148  /* the change to the second derivative of the model, beginning with the */
149  /* zero matrix. The values of the variables are constrained by upper and */
150  /* lower bounds. The arguments of the subroutine are as follows. */
151 
152  /* N must be set to the number of variables and must be at least two. */
153  /* NPT is the number of interpolation conditions. Its value must be in */
154  /* the interval [N+2,(N+1)(N+2)/2]. Choices that exceed 2*N+1 are not */
155  /* recommended. */
156  /* Initial values of the variables must be set in X(1),X(2),...,X(N). They */
157  /* will be changed to the values that give the least calculated F. */
158  /* For I=1,2,...,N, XL(I) and XU(I) must provide the lower and upper */
159  /* bounds, respectively, on X(I). The construction of quadratic models */
160  /* requires XL(I) to be strictly less than XU(I) for each I. Further, */
161  /* the contribution to a model from changes to the I-th variable is */
162  /* damaged severely by rounding errors if XU(I)-XL(I) is too small. */
163  /* RHOBEG and RHOEND must be set to the initial and final values of a trust */
164  /* region radius, so both must be positive with RHOEND no greater than */
165  /* RHOBEG. Typically, RHOBEG should be about one tenth of the greatest */
166  /* expected change to a variable, while RHOEND should indicate the */
167  /* accuracy that is required in the final values of the variables. An */
168  /* error return occurs if any of the differences XU(I)-XL(I), I=1,...,N, */
169  /* is less than 2rhobeg. */
170  /* The value of IPRINT should be set to 0, 1, 2 or 3, which controls the */
171  /* amount of printing. Specifically, there is no output if IPRINT=0 and */
172  /* there is output only at the return if IPRINT=1. Otherwise, each new */
173  /* value of RHO is printed, with the best vector of variables so far and */
174  /* the corresponding value of the objective function. Further, each new */
175  /* value of F with its variables are output if IPRINT=3. */
176  /* MAXFUN must be set to an upper bound on the number of calls of CALFUN. */
177  /* The array W will be used for working space. Its length must be at least */
178  /* (NPT+5)*(NPT+N)+3*N*(N+5)/2. */
179 
180  /* SUBROUTINE CALFUN (N,X,F) has to be provided by the user. It must set */
181  /* F to the value of the objective function for the current values of the */
182  /* variables X(1),X(2),...,X(N), which are generated automatically in a */
183  /* way that satisfies the bounds given in XL and XU. */
184 
185  /* Return if the value of NPT is unacceptable. */
186 
187  /* Parameter adjustments */
188  --w;
189  --xu;
190  --xl;
191  --x;
192 
193  /* Function Body */
194  np = m_SpaceDimension + 1;
195  if (npt < m_SpaceDimension + 2 || npt > (m_SpaceDimension + 2) * np / 2) {
196  std::cerr << "Number of Points for the Quadratic Approximation not set right" << std::endl
197  << "We'll use the minimal value here: " << this->m_SpaceDimension
198  + 2 << std::endl;
199 
200  npt = this->m_SpaceDimension
201  + 2;
202  }
203 
204  /* Partition the working space array, so that different parts of it can */
205  /* be treated separately during the calculation of BOBYQB. The partition */
206  /* requires the first (NPT+2)*(NPT+N)+3*N*(N+5)/2 elements of W plus the */
207  /* space that is taken by the last array in the argument list of BOBYQB. */
208 
209  ndim = npt + m_SpaceDimension;
210  ixb = 1;
211  ixp = ixb + m_SpaceDimension;
212  ifv = ixp + m_SpaceDimension * npt;
213  ixo = ifv + npt;
214  igo = ixo + m_SpaceDimension;
215  ihq = igo + m_SpaceDimension;
216  ipq = ihq + m_SpaceDimension * np / 2;
217  ibmat = ipq + npt;
218  izmat = ibmat + ndim * m_SpaceDimension;
219  isl = izmat + npt * (npt - np);
220  isu = isl + m_SpaceDimension;
221  ixn = isu + m_SpaceDimension;
222  ixa = ixn + m_SpaceDimension;
223  id = ixa + m_SpaceDimension;
224  ivl = id + m_SpaceDimension;
225  iw = ivl + ndim;
226 
227  /* Return if there is insufficient space between the bounds. Modify the */
228  /* initial X if necessary in order to avoid conflicts between the bounds */
229  /* and the construction of the first quadratic model. The lower and upper */
230  /* bounds on moves from the updated X are set now, in the ISL and ISU */
231  /* partitions of W, in order to provide useful and exact information about */
232  /* components of X that become within distance RHOBEG from their bounds. */
233 
234  zero = 0.;
235  i__1 = m_SpaceDimension;
236  for (j = 1; j <= i__1; ++j) {
237  temp = xu[j] - xl[j];
238  if (temp < rhobeg + rhobeg) {
239  //s_wsfe(&io___45);
240  //e_wsfe();
241  goto L40;
242  }
243  jsl = isl + j - 1;
244  jsu = jsl + m_SpaceDimension;
245  w[jsl] = xl[j] - x[j];
246  w[jsu] = xu[j] - x[j];
247  if (w[jsl] >= -(rhobeg)) {
248  if (w[jsl] >= zero) {
249  x[j] = xl[j];
250  w[jsl] = zero;
251  w[jsu] = temp;
252  } else {
253  x[j] = xl[j] + rhobeg;
254  w[jsl] = -(rhobeg);
255  /* Computing MAX */
256  d__1 = xu[j] - x[j];
257  w[jsu] = std::max(d__1,rhobeg);
258  }
259  } else if (w[jsu] <= rhobeg) {
260  if (w[jsu] <= zero) {
261  x[j] = xu[j];
262  w[jsl] = -temp;
263  w[jsu] = zero;
264  } else {
265  x[j] = xu[j] - rhobeg;
266  /* Computing MIN */
267  d__1 = xl[j] - x[j], d__2 = -(rhobeg);
268  w[jsl] = std::min(d__1,d__2);
269  w[jsu] = rhobeg;
270  }
271  }
272  /* L30: */
273  }
274 
275  /* Make the call of BOBYQB. */
276 
277  return bobyqb_(npt, &x[1], &xl[1], &xu[1], rhobeg, rhoend, maxfun, &w[ixb], &w[ixp], &w[ifv],
278  &w[ixo], &w[igo], &w[ihq], &w[ipq], &w[ibmat], &w[izmat], ndim, &w[isl], &w[isu], &w[ixn],
279  &w[ixa], &w[id], &w[ivl], &w[iw]);
280 L40:
281  return 0;
282 }
283 
284 
285 int BobyqaOptimizer
286 ::bobyqb_(long int &npt, double *x, double *xl, double *xu, double &rhobeg, double &rhoend, long int &maxfun, double *xbase, double *xpt, double *fval, double *xopt, double *gopt, double *hq, double *pq, double *bmat, double *zmat, long int &ndim, double *sl, double *su, double *xnew, double *xalt, double *d__, double *vlag, double *w)
287 {
288  /* System generated locals */
289  long int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1,
290  zmat_offset, i__1, i__2, i__3;
291  double d__1, d__2, d__3, d__4;
292 
293  /* Local variables */
294  double f;
295  long int i__, j, k, ih, nf, jj, nh, ip, jp;
296  double dx;
297  long int np;
298  double den, one, ten, dsq, rho, sum, two, diff, half, beta, gisq;
299  long int knew;
300  double temp, suma, sumb, bsum, fopt;
301  long int kopt, nptm;
302  double zero, curv;
303  long int ksav;
304  double gqsq, dist, sumw, sumz, diffa, diffb, diffc = 0, hdiag;
305  long int kbase;
306  double alpha, delta, adelt, denom, fsave, bdtol, delsq;
307  long int nresc, nfsav;
308  double ratio = 0, dnorm, vquad, pqold, tenth;
309  long int itest;
310  double sumpq, scaden;
311 
312  double errbig, cauchy, fracsq, biglsq, densav;
313  double bdtest;
314  double crvmin, frhosq;
315  double distsq;
316  long int ntrits;
317  double xoptsq;
318 
319  /* The arguments N, NPT, X, XL, XU, RHOBEG, RHOEND, IPRINT and MAXFUN */
320  /* are identical to the corresponding arguments in SUBROUTINE BOBYQA. */
321  /* XBASE holds a shift of origin that should reduce the contributions */
322  /* from rounding errors to values of the model and Lagrange functions. */
323  /* XPT is a two-dimensional array that holds the coordinates of the */
324  /* interpolation points relative to XBASE. */
325  /* FVAL holds the values of F at the interpolation points. */
326  /* XOPT is set to the displacement from XBASE of the trust region centre. */
327  /* GOPT holds the gradient of the quadratic model at XBASE+XOPT. */
328  /* HQ holds the explicit second derivatives of the quadratic model. */
329  /* PQ contains the parameters of the implicit second derivatives of the */
330  /* quadratic model. */
331  /* BMAT holds the last N columns of H. */
332  /* ZMAT holds the factorization of the leading NPT by NPT submatrix of H, */
333  /* this factorization being ZMAT times ZMAT^T, which provides both the */
334  /* correct rank and positive semi-definiteness. */
335  /* NDIM is the first dimension of BMAT and has the value NPT+N. */
336  /* SL and SU hold the differences XL-XBASE and XU-XBASE, respectively. */
337  /* All the components of every XOPT are going to satisfy the bounds */
338  /* SL(I) .LEQ. XOPT(I) .LEQ. SU(I), with appropriate equalities when */
339  /* XOPT is on a constraint boundary. */
340  /* XNEW is chosen by SUBROUTINE TRSBOX or ALTMOV. Usually XBASE+XNEW is the */
341  /* vector of variables for the next call of CALFUN. XNEW also satisfies */
342  /* the SL and SU constraints in the way that has just been mentioned. */
343  /* XALT is an alternative to XNEW, chosen by ALTMOV, that may replace XNEW */
344  /* in order to increase the denominator in the updating of UPDATE. */
345  /* D is reserved for a trial step from XOPT, which is usually XNEW-XOPT. */
346  /* VLAG contains the values of the Lagrange functions at a new point X. */
347  /* They are part of a product that requires VLAG to be of length NDIM. */
348  /* W is a one-dimensional array that is used for working space. Its length */
349  /* must be at least 3ndim = 3*(NPT+N). */
350 
351  /* Set some constants. */
352 
353  /* Parameter adjustments */
354  zmat_dim1 = npt;
355  zmat_offset = 1 + zmat_dim1;
356  zmat -= zmat_offset;
357  xpt_dim1 = npt;
358  xpt_offset = 1 + xpt_dim1;
359  xpt -= xpt_offset;
360  --x;
361  --xl;
362  --xu;
363  --xbase;
364  --fval;
365  --xopt;
366  --gopt;
367  --hq;
368  --pq;
369  bmat_dim1 = ndim;
370  bmat_offset = 1 + bmat_dim1;
371  bmat -= bmat_offset;
372  --sl;
373  --su;
374  --xnew;
375  --xalt;
376  --d__;
377  --vlag;
378  --w;
379 
380  /* Function Body */
381  half = .5;
382  one = 1.;
383  ten = 10.;
384  tenth = .1;
385  two = 2.;
386  zero = 0.;
387  np = m_SpaceDimension + 1;
388  nptm = npt - np;
389  nh = m_SpaceDimension * np / 2;
390 
391  /* The call of PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ, */
392  /* BMAT and ZMAT for the first iteration, with the corresponding values of */
393  /* of NF and KOPT, which are the number of calls of CALFUN so far and the */
394  /* index of the interpolation point at the trust region centre. Then the */
395  /* initial XOPT is set too. The branch to label 720 occurs if MAXFUN is */
396  /* less than NPT. GOPT will be updated if KOPT is different from KBASE. */
397 
398  prelim_(npt, &x[1], &xl[1], &xu[1], rhobeg, maxfun, &xbase[1],
399  &xpt[xpt_offset], &fval[1], &gopt[1], &hq[1], &pq[1], &bmat[bmat_offset],
400  &zmat[zmat_offset], ndim, &sl[1], &su[1], nf, kopt);
401 
402  xoptsq = zero;
403  i__1 = m_SpaceDimension;
404  for (i__ = 1; i__ <= i__1; ++i__) {
405  xopt[i__] = xpt[kopt + i__ * xpt_dim1];
406  /* L10: */
407  /* Computing 2nd power */
408  d__1 = xopt[i__];
409  xoptsq += d__1 * d__1;
410  }
411  fsave = fval[1];
412  if (nf < npt) {
413 // if (*iprint > 0) {
414 // s_wsfe(&io___62);
415 // e_wsfe();
416 // }
417  goto L720;
418  }
419  kbase = 1;
420 
421  /* Complete the settings that are required for the iterative procedure. */
422 
423  rho = rhobeg;
424  delta = rho;
425  nresc = nf;
426  ntrits = 0;
427  diffa = zero;
428  diffb = zero;
429  itest = 0;
430  nfsav = nf;
431 
432  /* Update GOPT if necessary before the first iteration and after each */
433  /* call of RESCUE that makes a call of CALFUN. */
434 
435 L20:
436  if (kopt != kbase) {
437  ih = 0;
438  i__1 = m_SpaceDimension;
439  for (j = 1; j <= i__1; ++j) {
440  i__2 = j;
441  for (i__ = 1; i__ <= i__2; ++i__) {
442  ++ih;
443  if (i__ < j) {
444  gopt[j] += hq[ih] * xopt[i__];
445  }
446  /* L30: */
447  gopt[i__] += hq[ih] * xopt[j];
448  }
449  }
450  if (nf > npt) {
451  i__2 = npt;
452  for (k = 1; k <= i__2; ++k) {
453  temp = zero;
454  i__1 = m_SpaceDimension;
455  for (j = 1; j <= i__1; ++j) {
456  /* L40: */
457  temp += xpt[k + j * xpt_dim1] * xopt[j];
458  }
459  temp = pq[k] * temp;
460  i__1 = m_SpaceDimension;
461  for (i__ = 1; i__ <= i__1; ++i__) {
462  /* L50: */
463  gopt[i__] += temp * xpt[k + i__ * xpt_dim1];
464  }
465  }
466  }
467  }
468 
469  /* Generate the next point in the trust region that provides a small value */
470  /* of the quadratic model subject to the constraints on the variables. */
471  /* The long int NTRITS is set to the number "trust region" iterations that */
472  /* have occurred since the last "alternative" iteration. If the length */
473  /* of XNEW-XOPT is less than HALF*RHO, however, then there is a branch to */
474  /* label 650 or 680 with NTRITS=-1, instead of calculating F at XNEW. */
475 
476 L60:
477  trsbox_(npt, &xpt[xpt_offset], &xopt[1], &gopt[1], &hq[1], &pq[1], &sl[1],
478  &su[1], &delta, &xnew[1], &d__[1], &w[1], &w[np], &w[np + m_SpaceDimension],
479  &w[np + (m_SpaceDimension << 1)], &w[np + m_SpaceDimension * 3], &dsq, &crvmin);
480  /* Computing MIN */
481  d__1 = delta, d__2 = std::sqrt(dsq);
482  dnorm = std::min(d__1,d__2);
483  if (dnorm < half * rho) {
484  ntrits = -1;
485  /* Computing 2nd power */
486  d__1 = ten * rho;
487  distsq = d__1 * d__1;
488  if (nf <= nfsav + 2) {
489  goto L650;
490  }
491 
492  /* The following choice between labels 650 and 680 depends on whether or */
493  /* not our work with the current RHO seems to be complete. Either RHO is */
494  /* decreased or termination occurs if the errors in the quadratic model at */
495  /* the last three interpolation points compare favourably with predictions */
496  /* of likely improvements to the model within distance HALF*RHO of XOPT. */
497 
498  /* Computing MAX */
499  d__1 = std::max(diffa,diffb);
500  errbig = std::max(d__1,diffc);
501  frhosq = rho * .125 * rho;
502  if (crvmin > zero && errbig > frhosq * crvmin) {
503  goto L650;
504  }
505  bdtol = errbig / rho;
506  i__1 = m_SpaceDimension;
507  for (j = 1; j <= i__1; ++j) {
508  bdtest = bdtol;
509  if (xnew[j] == sl[j]) {
510  bdtest = w[j];
511  }
512  if (xnew[j] == su[j]) {
513  bdtest = -w[j];
514  }
515  if (bdtest < bdtol) {
516  curv = hq[(j + j * j) / 2];
517  i__2 = npt;
518  for (k = 1; k <= i__2; ++k) {
519  /* L70: */
520  /* Computing 2nd power */
521  d__1 = xpt[k + j * xpt_dim1];
522  curv += pq[k] * (d__1 * d__1);
523  }
524  bdtest += half * curv * rho;
525  if (bdtest < bdtol) {
526  goto L650;
527  }
528  }
529  /* L80: */
530  }
531  goto L680;
532  }
533  ++ntrits;
534 
535  /* Severe cancellation is likely to occur if XOPT is too far from XBASE. */
536  /* If the following test holds, then XBASE is shifted so that XOPT becomes */
537  /* zero. The appropriate changes are made to BMAT and to the second */
538  /* derivatives of the current model, beginning with the changes to BMAT */
539  /* that do not depend on ZMAT. VLAG is used temporarily for working space. */
540 
541 L90:
542  if (dsq <= xoptsq * .001) {
543  fracsq = xoptsq * .25;
544  sumpq = zero;
545  i__1 = npt;
546  for (k = 1; k <= i__1; ++k) {
547  sumpq += pq[k];
548  sum = -half * xoptsq;
549  i__2 = m_SpaceDimension;
550  for (i__ = 1; i__ <= i__2; ++i__) {
551  /* L100: */
552  sum += xpt[k + i__ * xpt_dim1] * xopt[i__];
553  }
554  w[npt + k] = sum;
555  temp = fracsq - half * sum;
556  i__2 = m_SpaceDimension;
557  for (i__ = 1; i__ <= i__2; ++i__) {
558  w[i__] = bmat[k + i__ * bmat_dim1];
559  vlag[i__] = sum * xpt[k + i__ * xpt_dim1] + temp * xopt[i__];
560  ip = npt + i__;
561  i__3 = i__;
562  for (j = 1; j <= i__3; ++j) {
563  /* L110: */
564  bmat[ip + j * bmat_dim1] = bmat[ip + j * bmat_dim1] + w[
565  i__] * vlag[j] + vlag[i__] * w[j];
566  }
567  }
568  }
569 
570  /* Then the revisions of BMAT that depend on ZMAT are calculated. */
571 
572  i__3 = nptm;
573  for (jj = 1; jj <= i__3; ++jj) {
574  sumz = zero;
575  sumw = zero;
576  i__2 = npt;
577  for (k = 1; k <= i__2; ++k) {
578  sumz += zmat[k + jj * zmat_dim1];
579  vlag[k] = w[npt + k] * zmat[k + jj * zmat_dim1];
580  /* L120: */
581  sumw += vlag[k];
582  }
583  i__2 = m_SpaceDimension;
584  for (j = 1; j <= i__2; ++j) {
585  sum = (fracsq * sumz - half * sumw) * xopt[j];
586  i__1 = npt;
587  for (k = 1; k <= i__1; ++k) {
588  /* L130: */
589  sum += vlag[k] * xpt[k + j * xpt_dim1];
590  }
591  w[j] = sum;
592  i__1 = npt;
593  for (k = 1; k <= i__1; ++k) {
594  /* L140: */
595  bmat[k + j * bmat_dim1] += sum * zmat[k + jj * zmat_dim1];
596  }
597  }
598  i__1 = m_SpaceDimension;
599  for (i__ = 1; i__ <= i__1; ++i__) {
600  ip = i__ + npt;
601  temp = w[i__];
602  i__2 = i__;
603  for (j = 1; j <= i__2; ++j) {
604  /* L150: */
605  bmat[ip + j * bmat_dim1] += temp * w[j];
606  }
607  }
608  }
609 
610  /* The following instructions complete the shift, including the changes */
611  /* to the second derivative parameters of the quadratic model. */
612 
613  ih = 0;
614  i__2 = m_SpaceDimension;
615  for (j = 1; j <= i__2; ++j) {
616  w[j] = -half * sumpq * xopt[j];
617  i__1 = npt;
618  for (k = 1; k <= i__1; ++k) {
619  w[j] += pq[k] * xpt[k + j * xpt_dim1];
620  /* L160: */
621  xpt[k + j * xpt_dim1] -= xopt[j];
622  }
623  i__1 = j;
624  for (i__ = 1; i__ <= i__1; ++i__) {
625  ++ih;
626  hq[ih] = hq[ih] + w[i__] * xopt[j] + xopt[i__] * w[j];
627  /* L170: */
628  bmat[npt + i__ + j * bmat_dim1] = bmat[npt + j + i__ *
629  bmat_dim1];
630  }
631  }
632  i__1 = m_SpaceDimension;
633  for (i__ = 1; i__ <= i__1; ++i__) {
634  xbase[i__] += xopt[i__];
635  xnew[i__] -= xopt[i__];
636  sl[i__] -= xopt[i__];
637  su[i__] -= xopt[i__];
638  /* L180: */
639  xopt[i__] = zero;
640  }
641  xoptsq = zero;
642  }
643  if (ntrits == 0) {
644  goto L210;
645  }
646  goto L230;
647 
648  /* XBASE is also moved to XOPT by a call of RESCUE. This calculation is */
649  /* more expensive than the previous shift, because new matrices BMAT and */
650  /* ZMAT are generated from scratch, which may include the replacement of */
651  /* interpolation points whose positions seem to be causing near linear */
652  /* dependence in the interpolation conditions. Therefore RESCUE is called */
653  /* only if rounding errors have reduced by at least a factor of two the */
654  /* denominator of the formula for updating the H matrix. It provides a */
655  /* useful safeguard, but is not invoked in most applications of BOBYQA. */
656 
657 L190:
658  nfsav = nf;
659  kbase = kopt;
660  rescue_(npt, &xl[1], &xu[1], maxfun, &xbase[1], &xpt[xpt_offset],
661  &fval[1], &xopt[1], &gopt[1], &hq[1], &pq[1], &bmat[bmat_offset],
662  &zmat[zmat_offset], ndim, &sl[1], &su[1], nf, &delta, kopt, &vlag[1],
663  &w[1], &w[m_SpaceDimension + np], &w[ndim + np]);
664 
665  /* XOPT is updated now in case the branch below to label 720 is taken. */
666  /* Any updating of GOPT occurs after the branch below to label 20, which */
667  /* leads to a trust region iteration as does the branch to label 60. */
668 
669  xoptsq = zero;
670  if (kopt != kbase) {
671  i__1 = m_SpaceDimension;
672  for (i__ = 1; i__ <= i__1; ++i__) {
673  xopt[i__] = xpt[kopt + i__ * xpt_dim1];
674  /* L200: */
675  /* Computing 2nd power */
676  d__1 = xopt[i__];
677  xoptsq += d__1 * d__1;
678  }
679  }
680  if (nf < 0) {
681  nf = maxfun;
682 // if (*iprint > 0) {
683 // s_wsfe(&io___93);
684 // e_wsfe();
685 // }
686  goto L720;
687  }
688  nresc = nf;
689  if (nfsav < nf) {
690  nfsav = nf;
691  goto L20;
692  }
693  if (ntrits > 0) {
694  goto L60;
695  }
696 
697  /* Pick two alternative vectors of variables, relative to XBASE, that */
698  /* are suitable as new positions of the KNEW-th interpolation point. */
699  /* Firstly, XNEW is set to the point on a line through XOPT and another */
700  /* interpolation point that minimizes the predicted value of the next */
701  /* denominator, subject to ||XNEW - XOPT|| .LEQ. ADELT and to the SL */
702  /* and SU bounds. Secondly, XALT is set to the best feasible point on */
703  /* a constrained version of the Cauchy step of the KNEW-th Lagrange */
704  /* function, the corresponding value of the square of this function */
705  /* being returned in CAUCHY. The choice between these alternatives is */
706  /* going to be made when the denominator is calculated. */
707 
708 L210:
709  altmov_(npt, &xpt[xpt_offset], &xopt[1], &bmat[bmat_offset], &zmat[zmat_offset],
710  ndim, &sl[1], &su[1], kopt, knew, &adelt, &xnew[1], &xalt[1], &alpha, &cauchy,
711  &w[1], &w[np], &w[ndim + 1]);
712  i__1 = m_SpaceDimension;
713  for (i__ = 1; i__ <= i__1; ++i__) {
714  /* L220: */
715  d__[i__] = xnew[i__] - xopt[i__];
716  }
717 
718  /* Calculate VLAG and BETA for the current choice of D. The scalar */
719  /* product of D with XPT(K,.) is going to be held in W(NPT+K) for */
720  /* use when VQUAD is calculated. */
721 
722 L230:
723  i__1 = npt;
724  for (k = 1; k <= i__1; ++k) {
725  suma = zero;
726  sumb = zero;
727  sum = zero;
728  i__2 = m_SpaceDimension;
729  for (j = 1; j <= i__2; ++j) {
730  suma += xpt[k + j * xpt_dim1] * d__[j];
731  sumb += xpt[k + j * xpt_dim1] * xopt[j];
732  /* L240: */
733  sum += bmat[k + j * bmat_dim1] * d__[j];
734  }
735  w[k] = suma * (half * suma + sumb);
736  vlag[k] = sum;
737  /* L250: */
738  w[npt + k] = suma;
739  }
740  beta = zero;
741  i__1 = nptm;
742  for (jj = 1; jj <= i__1; ++jj) {
743  sum = zero;
744  i__2 = npt;
745  for (k = 1; k <= i__2; ++k) {
746  /* L260: */
747  sum += zmat[k + jj * zmat_dim1] * w[k];
748  }
749  beta -= sum * sum;
750  i__2 = npt;
751  for (k = 1; k <= i__2; ++k) {
752  /* L270: */
753  vlag[k] += sum * zmat[k + jj * zmat_dim1];
754  }
755  }
756  dsq = zero;
757  bsum = zero;
758  dx = zero;
759  i__2 = m_SpaceDimension;
760  for (j = 1; j <= i__2; ++j) {
761  /* Computing 2nd power */
762  d__1 = d__[j];
763  dsq += d__1 * d__1;
764  sum = zero;
765  i__1 = npt;
766  for (k = 1; k <= i__1; ++k) {
767  /* L280: */
768  sum += w[k] * bmat[k + j * bmat_dim1];
769  }
770  bsum += sum * d__[j];
771  jp = npt + j;
772  i__1 = m_SpaceDimension;
773  for (i__ = 1; i__ <= i__1; ++i__) {
774  /* L290: */
775  sum += bmat[jp + i__ * bmat_dim1] * d__[i__];
776  }
777  vlag[jp] = sum;
778  bsum += sum * d__[j];
779  /* L300: */
780  dx += d__[j] * xopt[j];
781  }
782  beta = dx * dx + dsq * (xoptsq + dx + dx + half * dsq) + beta - bsum;
783  vlag[kopt] += one;
784 
785  /* If NTRITS is zero, the denominator may be increased by replacing */
786  /* the step D of ALTMOV by a Cauchy step. Then RESCUE may be called if */
787  /* rounding errors have damaged the chosen denominator. */
788 
789  if (ntrits == 0) {
790  /* Computing 2nd power */
791  d__1 = vlag[knew];
792  denom = d__1 * d__1 + alpha * beta;
793  if (denom < cauchy && cauchy > zero) {
794  i__2 = m_SpaceDimension;
795  for (i__ = 1; i__ <= i__2; ++i__) {
796  xnew[i__] = xalt[i__];
797  /* L310: */
798  d__[i__] = xnew[i__] - xopt[i__];
799  }
800  cauchy = zero;
801  goto L230;
802  }
803  /* Computing 2nd power */
804  d__1 = vlag[knew];
805  if (denom <= half * (d__1 * d__1)) {
806  if (nf > nresc) {
807  goto L190;
808  }
809 // if (*iprint > 0) {
810 // s_wsfe(&io___105);
811 // e_wsfe();
812 // }
813  goto L720;
814  }
815 
816  /* Alternatively, if NTRITS is positive, then set KNEW to the index of */
817  /* the next interpolation point to be deleted to make room for a trust */
818  /* region step. Again RESCUE may be called if rounding errors have damaged */
819  /* the chosen denominator, which is the reason for attempting to select */
820  /* KNEW before calculating the next value of the objective function. */
821 
822  } else {
823  delsq = delta * delta;
824  scaden = zero;
825  biglsq = zero;
826  knew = 0;
827  i__2 = npt;
828  for (k = 1; k <= i__2; ++k) {
829  if (k == kopt) {
830  goto L350;
831  }
832  hdiag = zero;
833  i__1 = nptm;
834  for (jj = 1; jj <= i__1; ++jj) {
835  /* L330: */
836  /* Computing 2nd power */
837  d__1 = zmat[k + jj * zmat_dim1];
838  hdiag += d__1 * d__1;
839  }
840  /* Computing 2nd power */
841  d__1 = vlag[k];
842  den = beta * hdiag + d__1 * d__1;
843  distsq = zero;
844  i__1 = m_SpaceDimension;
845  for (j = 1; j <= i__1; ++j) {
846  /* L340: */
847  /* Computing 2nd power */
848  d__1 = xpt[k + j * xpt_dim1] - xopt[j];
849  distsq += d__1 * d__1;
850  }
851  /* Computing MAX */
852  /* Computing 2nd power */
853  d__3 = distsq / delsq;
854  d__1 = one, d__2 = d__3 * d__3;
855  temp = std::max(d__1,d__2);
856  if (temp * den > scaden) {
857  scaden = temp * den;
858  knew = k;
859  denom = den;
860  }
861  /* Computing MAX */
862  /* Computing 2nd power */
863  d__3 = vlag[k];
864  d__1 = biglsq, d__2 = temp * (d__3 * d__3);
865  biglsq = std::max(d__1,d__2);
866  L350:
867  ;
868  }
869  if (scaden <= half * biglsq) {
870  if (nf > nresc) {
871  goto L190;
872  }
873 // if (*iprint > 0) {
874 // s_wsfe(&io___111);
875 // e_wsfe();
876 // }
877  goto L720;
878  }
879  }
880 
881  /* Put the variables for the next calculation of the objective function */
882  /* in XNEW, with any adjustments for the bounds. */
883 
884 
885  /* Calculate the value of the objective function at XBASE+XNEW, unless */
886  /* the limit on the number of calculations of F has been reached. */
887 
888 L360:
889  i__2 = m_SpaceDimension;
890  for (i__ = 1; i__ <= i__2; ++i__) {
891  /* Computing MIN */
892  /* Computing MAX */
893  d__3 = xl[i__], d__4 = xbase[i__] + xnew[i__];
894  d__1 = std::max(d__3,d__4), d__2 = xu[i__];
895  x[i__] = std::min(d__1,d__2);
896  if (xnew[i__] == sl[i__]) {
897  x[i__] = xl[i__];
898  }
899  if (xnew[i__] == su[i__]) {
900  x[i__] = xu[i__];
901  }
902  /* L380: */
903  }
904  if (nf >= maxfun) {
905  this->m_StopConditionDescription << "Max cost function call reached " << this->m_MaximumIteration;
906  this->InvokeEvent(itk::EndEvent());
907 
908 // if (*iprint > 0) {
909 // s_wsfe(&io___112);
910 // e_wsfe();
911 // }
912  goto L720;
913  }
914  ++nf;
915 
916  if (this->m_Stop)
917  {
918  this->m_StopConditionDescription << "User ended optimisation ";
919  this->InvokeEvent(itk::EndEvent());
920 
921  goto L720;
922  }
923 
924  // Call to cost function
925  for (unsigned int i = 0; i < m_SpaceDimension; ++i) px[i] = x[i+1] / this->GetScales()[i];
926  // f = cost(&x[1]);//*fun;
927 
928  try {
929  f = this->m_CostFunction->GetValue(px);
930  }
931  catch(...)
932  {
933  if (m_CatchGetValueException)
934  f = m_MetricWorstPossibleValue;
935  else throw;
936  }
937  if (this->m_Maximize)
938  f = -f;
939 
940  this->m_CurrentCost = f;
941 
942  //calfun_(&x[1], &f);
943 // if (*iprint == 3) {
944 // s_wsfe(&io___114);
945 // do_fio(&c__1, (char *)&nf, (ftnlen)sizeof(long int));
946 // do_fio(&c__1, (char *)&f, (ftnlen)sizeof(double));
947 // i__2 = m_SpaceDimension;
948 // for (i__ = 1; i__ <= i__2; ++i__) {
949 // do_fio(&c__1, (char *)&x[i__], (ftnlen)sizeof(double));
950 // }
951 // e_wsfe();
952 // }
953  if (ntrits == -1) {
954  fsave = f;
955  goto L720;
956  }
957 
958  /* Use the quadratic model to predict the change in F due to the step D, */
959  /* and set DIFF to the error of this prediction. */
960 
961  fopt = fval[kopt];
962  vquad = zero;
963  ih = 0;
964  i__2 = m_SpaceDimension;
965  for (j = 1; j <= i__2; ++j) {
966  vquad += d__[j] * gopt[j];
967  i__1 = j;
968  for (i__ = 1; i__ <= i__1; ++i__) {
969  ++ih;
970  temp = d__[i__] * d__[j];
971  if (i__ == j) {
972  temp = half * temp;
973  }
974  /* L410: */
975  vquad += hq[ih] * temp;
976  }
977  }
978  i__1 = npt;
979  for (k = 1; k <= i__1; ++k) {
980  /* L420: */
981  /* Computing 2nd power */
982  d__1 = w[npt + k];
983  vquad += half * pq[k] * (d__1 * d__1);
984  }
985  diff = f - fopt - vquad;
986  diffc = diffb;
987  diffb = diffa;
988  diffa = std::abs(diff);
989  if (dnorm > rho) {
990  nfsav = nf;
991  }
992 
993  /* Pick the next value of DELTA after a trust region step. */
994 
995  if (ntrits > 0) {
996  if (vquad >= zero) {
997 // if (*iprint > 0) {
998 // s_wsfe(&io___118);
999 // e_wsfe();
1000 // }
1001  goto L720;
1002  }
1003  ratio = (f - fopt) / vquad;
1004  if (ratio <= tenth) {
1005  /* Computing MIN */
1006  d__1 = half * delta;
1007  delta = std::min(d__1,dnorm);
1008  } else if (ratio <= .7) {
1009  /* Computing MAX */
1010  d__1 = half * delta;
1011  delta = std::max(d__1,dnorm);
1012  } else {
1013  /* Computing MAX */
1014  d__1 = half * delta, d__2 = dnorm + dnorm;
1015  delta = std::max(d__1,d__2);
1016  }
1017  if (delta <= rho * 1.5) {
1018  delta = rho;
1019  }
1020 
1021  /* Recalculate KNEW and DENOM if the new F is less than FOPT. */
1022 
1023  if (f < fopt) {
1024  ksav = knew;
1025  densav = denom;
1026  delsq = delta * delta;
1027  scaden = zero;
1028  biglsq = zero;
1029  knew = 0;
1030  i__1 = npt;
1031  for (k = 1; k <= i__1; ++k) {
1032  hdiag = zero;
1033  i__2 = nptm;
1034  for (jj = 1; jj <= i__2; ++jj) {
1035  /* L440: */
1036  /* Computing 2nd power */
1037  d__1 = zmat[k + jj * zmat_dim1];
1038  hdiag += d__1 * d__1;
1039  }
1040  /* Computing 2nd power */
1041  d__1 = vlag[k];
1042  den = beta * hdiag + d__1 * d__1;
1043  distsq = zero;
1044  i__2 = m_SpaceDimension;
1045  for (j = 1; j <= i__2; ++j) {
1046  /* L450: */
1047  /* Computing 2nd power */
1048  d__1 = xpt[k + j * xpt_dim1] - xnew[j];
1049  distsq += d__1 * d__1;
1050  }
1051  /* Computing MAX */
1052  /* Computing 2nd power */
1053  d__3 = distsq / delsq;
1054  d__1 = one, d__2 = d__3 * d__3;
1055  temp = std::max(d__1,d__2);
1056  if (temp * den > scaden) {
1057  scaden = temp * den;
1058  knew = k;
1059  denom = den;
1060  }
1061  /* L460: */
1062  /* Computing MAX */
1063  /* Computing 2nd power */
1064  d__3 = vlag[k];
1065  d__1 = biglsq, d__2 = temp * (d__3 * d__3);
1066  biglsq = std::max(d__1,d__2);
1067  }
1068  if (scaden <= half * biglsq) {
1069  knew = ksav;
1070  denom = densav;
1071  }
1072  }
1073  }
1074 
1075  /* Update BMAT and ZMAT, so that the KNEW-th interpolation point can be */
1076  /* moved. Also update the second derivative terms of the model. */
1077 
1078  update_(npt, &bmat[bmat_offset], &zmat[zmat_offset], ndim, &vlag[1],
1079  &beta, &denom, knew, &w[1]);
1080  ih = 0;
1081  pqold = pq[knew];
1082  pq[knew] = zero;
1083  i__1 = m_SpaceDimension;
1084  for (i__ = 1; i__ <= i__1; ++i__) {
1085  temp = pqold * xpt[knew + i__ * xpt_dim1];
1086  i__2 = i__;
1087  for (j = 1; j <= i__2; ++j) {
1088  ++ih;
1089  /* L470: */
1090  hq[ih] += temp * xpt[knew + j * xpt_dim1];
1091  }
1092  }
1093  i__2 = nptm;
1094  for (jj = 1; jj <= i__2; ++jj) {
1095  temp = diff * zmat[knew + jj * zmat_dim1];
1096  i__1 = npt;
1097  for (k = 1; k <= i__1; ++k) {
1098  /* L480: */
1099  pq[k] += temp * zmat[k + jj * zmat_dim1];
1100  }
1101  }
1102 
1103  /* Include the new interpolation point, and make the changes to GOPT at */
1104  /* the old XOPT that are caused by the updating of the quadratic model. */
1105 
1106  fval[knew] = f;
1107  i__1 = m_SpaceDimension;
1108  for (i__ = 1; i__ <= i__1; ++i__) {
1109  xpt[knew + i__ * xpt_dim1] = xnew[i__];
1110  /* L490: */
1111  w[i__] = bmat[knew + i__ * bmat_dim1];
1112  }
1113  i__1 = npt;
1114  for (k = 1; k <= i__1; ++k) {
1115  suma = zero;
1116  i__2 = nptm;
1117  for (jj = 1; jj <= i__2; ++jj) {
1118  /* L500: */
1119  suma += zmat[knew + jj * zmat_dim1] * zmat[k + jj * zmat_dim1];
1120  }
1121  sumb = zero;
1122  i__2 = m_SpaceDimension;
1123  for (j = 1; j <= i__2; ++j) {
1124  /* L510: */
1125  sumb += xpt[k + j * xpt_dim1] * xopt[j];
1126  }
1127  temp = suma * sumb;
1128  i__2 = m_SpaceDimension;
1129  for (i__ = 1; i__ <= i__2; ++i__) {
1130  /* L520: */
1131  w[i__] += temp * xpt[k + i__ * xpt_dim1];
1132  }
1133  }
1134  i__2 = m_SpaceDimension;
1135  for (i__ = 1; i__ <= i__2; ++i__) {
1136  /* L530: */
1137  gopt[i__] += diff * w[i__];
1138  }
1139 
1140  /* Update XOPT, GOPT and KOPT if the new calculated F is less than FOPT. */
1141 
1142  if (f < fopt) {
1143  kopt = knew;
1144  xoptsq = zero;
1145  ih = 0;
1146  i__2 = m_SpaceDimension;
1147  for (j = 1; j <= i__2; ++j) {
1148  xopt[j] = xnew[j];
1149  /* Computing 2nd power */
1150  d__1 = xopt[j];
1151  xoptsq += d__1 * d__1;
1152  i__1 = j;
1153  for (i__ = 1; i__ <= i__1; ++i__) {
1154  ++ih;
1155  if (i__ < j) {
1156  gopt[j] += hq[ih] * d__[i__];
1157  }
1158  /* L540: */
1159  gopt[i__] += hq[ih] * d__[j];
1160  }
1161  }
1162  i__1 = npt;
1163  for (k = 1; k <= i__1; ++k) {
1164  temp = zero;
1165  i__2 = m_SpaceDimension;
1166  for (j = 1; j <= i__2; ++j) {
1167  /* L550: */
1168  temp += xpt[k + j * xpt_dim1] * d__[j];
1169  }
1170  temp = pq[k] * temp;
1171  i__2 = m_SpaceDimension;
1172  for (i__ = 1; i__ <= i__2; ++i__) {
1173  /* L560: */
1174  gopt[i__] += temp * xpt[k + i__ * xpt_dim1];
1175  }
1176  }
1177  }
1178 
1179  /* Calculate the parameters of the least Frobenius norm interpolant to */
1180  /* the current data, the gradient of this interpolant at XOPT being put */
1181  /* into VLAG(NPT+I), I=1,2,...,N. */
1182 
1183  if (ntrits > 0) {
1184  i__2 = npt;
1185  for (k = 1; k <= i__2; ++k) {
1186  vlag[k] = fval[k] - fval[kopt];
1187  /* L570: */
1188  w[k] = zero;
1189  }
1190  i__2 = nptm;
1191  for (j = 1; j <= i__2; ++j) {
1192  sum = zero;
1193  i__1 = npt;
1194  for (k = 1; k <= i__1; ++k) {
1195  /* L580: */
1196  sum += zmat[k + j * zmat_dim1] * vlag[k];
1197  }
1198  i__1 = npt;
1199  for (k = 1; k <= i__1; ++k) {
1200  /* L590: */
1201  w[k] += sum * zmat[k + j * zmat_dim1];
1202  }
1203  }
1204  i__1 = npt;
1205  for (k = 1; k <= i__1; ++k) {
1206  sum = zero;
1207  i__2 = m_SpaceDimension;
1208  for (j = 1; j <= i__2; ++j) {
1209  /* L600: */
1210  sum += xpt[k + j * xpt_dim1] * xopt[j];
1211  }
1212  w[k + npt] = w[k];
1213  /* L610: */
1214  w[k] = sum * w[k];
1215  }
1216  gqsq = zero;
1217  gisq = zero;
1218  i__1 = m_SpaceDimension;
1219  for (i__ = 1; i__ <= i__1; ++i__) {
1220  sum = zero;
1221  i__2 = npt;
1222  for (k = 1; k <= i__2; ++k) {
1223  /* L620: */
1224  sum = sum + bmat[k + i__ * bmat_dim1] * vlag[k] + xpt[k + i__ * xpt_dim1] * w[k];
1225  }
1226  if (xopt[i__] == sl[i__]) {
1227  /* Computing MIN */
1228  d__2 = zero, d__3 = gopt[i__];
1229  /* Computing 2nd power */
1230  d__1 = std::min(d__2,d__3);
1231  gqsq += d__1 * d__1;
1232  /* Computing 2nd power */
1233  d__1 = std::min(zero,sum);
1234  gisq += d__1 * d__1;
1235  } else if (xopt[i__] == su[i__]) {
1236  /* Computing MAX */
1237  d__2 = zero, d__3 = gopt[i__];
1238  /* Computing 2nd power */
1239  d__1 = std::max(d__2,d__3);
1240  gqsq += d__1 * d__1;
1241  /* Computing 2nd power */
1242  d__1 = std::max(zero,sum);
1243  gisq += d__1 * d__1;
1244  } else {
1245  /* Computing 2nd power */
1246  d__1 = gopt[i__];
1247  gqsq += d__1 * d__1;
1248  gisq += sum * sum;
1249  }
1250  /* L630: */
1251  vlag[npt + i__] = sum;
1252  }
1253 
1254  /* Test whether to replace the new quadratic model by the least Frobenius */
1255  /* norm interpolant, making the replacement if the test is satisfied. */
1256 
1257  ++itest;
1258  if (gqsq < ten * gisq) {
1259  itest = 0;
1260  }
1261  if (itest >= 3) {
1262  i__1 = std::max(npt,nh);
1263  for (i__ = 1; i__ <= i__1; ++i__) {
1264  if (i__ <= m_SpaceDimension) {
1265  gopt[i__] = vlag[npt + i__];
1266  }
1267  if (i__ <= npt) {
1268  pq[i__] = w[npt + i__];
1269  }
1270  if (i__ <= nh) {
1271  hq[i__] = zero;
1272  }
1273  itest = 0;
1274  /* L640: */
1275  }
1276  }
1277  }
1278 
1279  /* If a trust region step has provided a sufficient decrease in F, then */
1280  /* branch for another trust region calculation. The case NTRITS=0 occurs */
1281  /* when the new interpolation point was reached by an alternative step. */
1282 
1283  if (ntrits == 0) {
1284  goto L60;
1285  }
1286  if (f <= fopt + tenth * vquad) {
1287  goto L60;
1288  }
1289 
1290  /* Alternatively, find out if the interpolation points are close enough */
1291  /* to the best point so far. */
1292 
1293  /* Computing MAX */
1294  /* Computing 2nd power */
1295  d__3 = two * delta;
1296  /* Computing 2nd power */
1297  d__4 = ten * rho;
1298  d__1 = d__3 * d__3, d__2 = d__4 * d__4;
1299  distsq = std::max(d__1,d__2);
1300 L650:
1301  knew = 0;
1302  i__1 = npt;
1303  for (k = 1; k <= i__1; ++k) {
1304  sum = zero;
1305  i__2 = m_SpaceDimension;
1306  for (j = 1; j <= i__2; ++j) {
1307  /* L660: */
1308  /* Computing 2nd power */
1309  d__1 = xpt[k + j * xpt_dim1] - xopt[j];
1310  sum += d__1 * d__1;
1311  }
1312  if (sum > distsq) {
1313  knew = k;
1314  distsq = sum;
1315  }
1316  /* L670: */
1317  }
1318 
1319  /* If KNEW is positive, then ALTMOV finds alternative new positions for */
1320  /* the KNEW-th interpolation point within distance ADELT of XOPT. It is */
1321  /* reached via label 90. Otherwise, there is a branch to label 60 for */
1322  /* another trust region iteration, unless the calculations with the */
1323  /* current RHO are complete. */
1324 
1325  if (knew > 0) {
1326  dist = std::sqrt(distsq);
1327  if (ntrits == -1) {
1328  /* Computing MIN */
1329  d__1 = tenth * delta, d__2 = half * dist;
1330  delta = std::min(d__1,d__2);
1331  if (delta <= rho * 1.5) {
1332  delta = rho;
1333  }
1334  }
1335  ntrits = 0;
1336  /* Computing MAX */
1337  /* Computing MIN */
1338  d__2 = tenth * dist;
1339  d__1 = std::min(d__2,delta);
1340  adelt = std::max(d__1,rho);
1341  dsq = adelt * adelt;
1342  goto L90;
1343  }
1344  if (ntrits == -1) {
1345  goto L680;
1346  }
1347  if (ratio > zero) {
1348  goto L60;
1349  }
1350  if (std::max(delta,dnorm) > rho) {
1351  goto L60;
1352  }
1353 
1354  /* The calculations with the current value of RHO are complete. Pick the */
1355  /* next values of RHO and DELTA. */
1356 
1357 L680:
1358  if (rho > rhoend) {
1359  delta = half * rho;
1360  ratio = rho / rhoend;
1361  if (ratio <= 16.) {
1362  rho = rhoend;
1363  } else if (ratio <= 250.) {
1364  rho = std::sqrt(ratio) * rhoend;
1365  } else {
1366  rho = tenth * rho;
1367  }
1368  delta = std::max(delta,rho);
1369 // if (*iprint >= 2) {
1370 // if (*iprint >= 3) {
1371 // s_wsfe(&io___126);
1372 // e_wsfe();
1373 // }
1374 // s_wsfe(&io___127);
1375 // do_fio(&c__1, (char *)&rho, (ftnlen)sizeof(double));
1376 // do_fio(&c__1, (char *)&nf, (ftnlen)sizeof(long int));
1377 // e_wsfe();
1378 // s_wsfe(&io___128);
1379 // do_fio(&c__1, (char *)&fval[kopt], (ftnlen)sizeof(double));
1380 // i__1 = m_SpaceDimension;
1381 // for (i__ = 1; i__ <= i__1; ++i__) {
1382 // d__1 = xbase[i__] + xopt[i__];
1383 // do_fio(&c__1, (char *)&d__1, (ftnlen)sizeof(double));
1384 // }
1385 // e_wsfe();
1386 // }
1387  ntrits = 0;
1388  nfsav = nf;
1389  goto L60;
1390  }
1391 
1392  /* Return from the calculation, after another Newton-Raphson step, if */
1393  /* it is too short to have been tried before. */
1394 
1395  if (ntrits == -1) {
1396  goto L360;
1397  }
1398 L720:
1399  if (fval[kopt] <= fsave) {
1400  i__1 = m_SpaceDimension;
1401  for (i__ = 1; i__ <= i__1; ++i__) {
1402  /* Computing MIN */
1403  /* Computing MAX */
1404  d__3 = xl[i__], d__4 = xbase[i__] + xopt[i__];
1405  d__1 = std::max(d__3,d__4), d__2 = xu[i__];
1406  x[i__] = std::min(d__1,d__2);
1407  if (xopt[i__] == sl[i__]) {
1408  x[i__] = xl[i__];
1409  }
1410  if (xopt[i__] == su[i__]) {
1411  x[i__] = xu[i__];
1412  }
1413  /* L730: */
1414  }
1415  f = fval[kopt];
1416  }
1417 // if (*iprint >= 1) {
1418 // s_wsfe(&io___129);
1419 // do_fio(&c__1, (char *)&nf, (ftnlen)sizeof(long int));
1420 // e_wsfe();
1421 // s_wsfe(&io___130);
1422 // do_fio(&c__1, (char *)&f, (ftnlen)sizeof(double));
1423 // i__1 = m_SpaceDimension;
1424 // for (i__ = 1; i__ <= i__1; ++i__) {
1425 // do_fio(&c__1, (char *)&x[i__], (ftnlen)sizeof(double));
1426 // }
1427 // e_wsfe();
1428 // }
1429  return 0;
1430 }
1431 
1432 int BobyqaOptimizer::altmov_(long int &npt, double *xpt, double *xopt,
1433  double *bmat, double *zmat, long int &ndim,
1434  double *sl, double *su, long int &kopt,
1435  long int &knew, double *adelt, double *xnew,
1436  double *xalt, double *alpha, double *cauchy,
1437  double *glag, double *hcol, double *w)
1438 {
1439  /* System generated locals */
1440  long int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1,
1441  zmat_offset, i__1, i__2;
1442  double d__1, d__2, d__3, d__4;
1443 
1444  /* Local variables */
1445  long int i__, j, k;
1446  double ha, gw, one, diff, half;
1447  long int ilbd, isbd;
1448  double slbd;
1449  long int iubd;
1450  double vlag, subd, temp;
1451  long int ksav = 0;
1452  double step = 0, zero, curv;
1453  long int iflag;
1454  double scale, csave = 0, tempa, tempb, tempd, const__, sumin, ggfree;
1455  long int ibdsav = 0;
1456  double dderiv, bigstp, predsq, presav, distsq, stpsav = 0, wfixsq, wsqsav;
1457 
1458 
1459  /* The arguments N, NPT, XPT, XOPT, BMAT, ZMAT, NDIM, SL and SU all have */
1460  /* the same meanings as the corresponding arguments of BOBYQB. */
1461  /* KOPT is the index of the optimal interpolation point. */
1462  /* KNEW is the index of the interpolation point that is going to be moved. */
1463  /* ADELT is the current trust region bound. */
1464  /* XNEW will be set to a suitable new position for the interpolation point */
1465  /* XPT(KNEW,.). Specifically, it satisfies the SL, SU and trust region */
1466  /* bounds and it should provide a large denominator in the next call of */
1467  /* UPDATE. The step XNEW-XOPT from XOPT is restricted to moves along the */
1468  /* straight lines through XOPT and another interpolation point. */
1469  /* XALT also provides a large value of the modulus of the KNEW-th Lagrange */
1470  /* function subject to the constraints that have been mentioned, its main */
1471  /* difference from XNEW being that XALT-XOPT is a constrained version of */
1472  /* the Cauchy step within the trust region. An exception is that XALT is */
1473  /* not calculated if all components of GLAG (see below) are zero. */
1474  /* ALPHA will be set to the KNEW-th diagonal element of the H matrix. */
1475  /* CAUCHY will be set to the square of the KNEW-th Lagrange function at */
1476  /* the step XALT-XOPT from XOPT for the vector XALT that is returned, */
1477  /* except that CAUCHY is set to zero if XALT is not calculated. */
1478  /* GLAG is a working space vector of length N for the gradient of the */
1479  /* KNEW-th Lagrange function at XOPT. */
1480  /* HCOL is a working space vector of length NPT for the second derivative */
1481  /* coefficients of the KNEW-th Lagrange function. */
1482  /* W is a working space vector of length 2N that is going to hold the */
1483  /* constrained Cauchy step from XOPT of the Lagrange function, followed */
1484  /* by the downhill version of XALT when the uphill step is calculated. */
1485 
1486  /* Set the first NPT components of W to the leading elements of the */
1487  /* KNEW-th column of the H matrix. */
1488 
1489  /* Parameter adjustments */
1490  zmat_dim1 = npt;
1491  zmat_offset = 1 + zmat_dim1;
1492  zmat -= zmat_offset;
1493  xpt_dim1 = npt;
1494  xpt_offset = 1 + xpt_dim1;
1495  xpt -= xpt_offset;
1496  --xopt;
1497  bmat_dim1 = ndim;
1498  bmat_offset = 1 + bmat_dim1;
1499  bmat -= bmat_offset;
1500  --sl;
1501  --su;
1502  --xnew;
1503  --xalt;
1504  --glag;
1505  --hcol;
1506  --w;
1507 
1508  /* Function Body */
1509  half = .5;
1510  one = 1.;
1511  zero = 0.;
1512  const__ = one + std::sqrt(2.);
1513  i__1 = npt;
1514  for (k = 1; k <= i__1; ++k) {
1515  /* L10: */
1516  hcol[k] = zero;
1517  }
1518  i__1 = npt - m_SpaceDimension - 1;
1519  for (j = 1; j <= i__1; ++j) {
1520  temp = zmat[knew + j * zmat_dim1];
1521  i__2 = npt;
1522  for (k = 1; k <= i__2; ++k) {
1523  /* L20: */
1524  hcol[k] += temp * zmat[k + j * zmat_dim1];
1525  }
1526  }
1527  *alpha = hcol[knew];
1528  ha = half * *alpha;
1529 
1530  /* Calculate the gradient of the KNEW-th Lagrange function at XOPT. */
1531 
1532  i__2 = m_SpaceDimension;
1533  for (i__ = 1; i__ <= i__2; ++i__) {
1534  /* L30: */
1535  glag[i__] = bmat[knew + i__ * bmat_dim1];
1536  }
1537  i__2 = npt;
1538  for (k = 1; k <= i__2; ++k) {
1539  temp = zero;
1540  i__1 = m_SpaceDimension;
1541  for (j = 1; j <= i__1; ++j) {
1542  /* L40: */
1543  temp += xpt[k + j * xpt_dim1] * xopt[j];
1544  }
1545  temp = hcol[k] * temp;
1546  i__1 = m_SpaceDimension;
1547  for (i__ = 1; i__ <= i__1; ++i__) {
1548  /* L50: */
1549  glag[i__] += temp * xpt[k + i__ * xpt_dim1];
1550  }
1551  }
1552 
1553  /* Search for a large denominator along the straight lines through XOPT */
1554  /* and another interpolation point. SLBD and SUBD will be lower and upper */
1555  /* bounds on the step along each of these lines in turn. PREDSQ will be */
1556  /* set to the square of the predicted denominator for each line. PRESAV */
1557  /* will be set to the largest admissible value of PREDSQ that occurs. */
1558 
1559  presav = zero;
1560  i__1 = npt;
1561  for (k = 1; k <= i__1; ++k) {
1562  if (k == kopt) {
1563  goto L80;
1564  }
1565  dderiv = zero;
1566  distsq = zero;
1567  i__2 = m_SpaceDimension;
1568  for (i__ = 1; i__ <= i__2; ++i__) {
1569  temp = xpt[k + i__ * xpt_dim1] - xopt[i__];
1570  dderiv += glag[i__] * temp;
1571  /* L60: */
1572  distsq += temp * temp;
1573  }
1574  subd = *adelt / std::sqrt(distsq);
1575  slbd = -subd;
1576  ilbd = 0;
1577  iubd = 0;
1578  sumin = std::min(one,subd);
1579 
1580  /* Revise SLBD and SUBD if necessary because of the bounds in SL and SU. */
1581 
1582  i__2 = m_SpaceDimension;
1583  for (i__ = 1; i__ <= i__2; ++i__) {
1584  temp = xpt[k + i__ * xpt_dim1] - xopt[i__];
1585  if (temp > zero) {
1586  if (slbd * temp < sl[i__] - xopt[i__]) {
1587  slbd = (sl[i__] - xopt[i__]) / temp;
1588  ilbd = -i__;
1589  }
1590  if (subd * temp > su[i__] - xopt[i__]) {
1591  /* Computing MAX */
1592  d__1 = sumin, d__2 = (su[i__] - xopt[i__]) / temp;
1593  subd = std::max(d__1,d__2);
1594  iubd = i__;
1595  }
1596  } else if (temp < zero) {
1597  if (slbd * temp > su[i__] - xopt[i__]) {
1598  slbd = (su[i__] - xopt[i__]) / temp;
1599  ilbd = i__;
1600  }
1601  if (subd * temp < sl[i__] - xopt[i__]) {
1602  /* Computing MAX */
1603  d__1 = sumin, d__2 = (sl[i__] - xopt[i__]) / temp;
1604  subd = std::max(d__1,d__2);
1605  iubd = -i__;
1606  }
1607  }
1608  /* L70: */
1609  }
1610 
1611  /* Seek a large modulus of the KNEW-th Lagrange function when the index */
1612  /* of the other interpolation point on the line through XOPT is KNEW. */
1613 
1614  if (k == knew) {
1615  diff = dderiv - one;
1616  step = slbd;
1617  vlag = slbd * (dderiv - slbd * diff);
1618  isbd = ilbd;
1619  temp = subd * (dderiv - subd * diff);
1620  if (std::abs(temp) > std::abs(vlag)) {
1621  step = subd;
1622  vlag = temp;
1623  isbd = iubd;
1624  }
1625  tempd = half * dderiv;
1626  tempa = tempd - diff * slbd;
1627  tempb = tempd - diff * subd;
1628  if (tempa * tempb < zero) {
1629  temp = tempd * tempd / diff;
1630  if (std::abs(temp) > std::abs(vlag)) {
1631  step = tempd / diff;
1632  vlag = temp;
1633  isbd = 0;
1634  }
1635  }
1636 
1637  /* Search along each of the other lines through XOPT and another point. */
1638 
1639  } else {
1640  step = slbd;
1641  vlag = slbd * (one - slbd);
1642  isbd = ilbd;
1643  temp = subd * (one - subd);
1644  if (std::abs(temp) > std::abs(vlag)) {
1645  step = subd;
1646  vlag = temp;
1647  isbd = iubd;
1648  }
1649  if (subd > half) {
1650  if (std::abs(vlag) < .25) {
1651  step = half;
1652  vlag = .25;
1653  isbd = 0;
1654  }
1655  }
1656  vlag *= dderiv;
1657  }
1658 
1659  /* Calculate PREDSQ for the current line search and maintain PRESAV. */
1660 
1661  temp = step * (one - step) * distsq;
1662  predsq = vlag * vlag * (vlag * vlag + ha * temp * temp);
1663  if (predsq > presav) {
1664  presav = predsq;
1665  ksav = k;
1666  stpsav = step;
1667  ibdsav = isbd;
1668  }
1669  L80:
1670  ;
1671  }
1672 
1673  /* Construct XNEW in a way that satisfies the bound constraints exactly. */
1674 
1675  i__1 = m_SpaceDimension;
1676  for (i__ = 1; i__ <= i__1; ++i__) {
1677  temp = xopt[i__] + stpsav * (xpt[ksav + i__ * xpt_dim1] - xopt[i__]);
1678  /* L90: */
1679  /* Computing MAX */
1680  /* Computing MIN */
1681  d__3 = su[i__];
1682  d__1 = sl[i__], d__2 = std::min(d__3,temp);
1683  xnew[i__] = std::max(d__1,d__2);
1684  }
1685  if (ibdsav < 0) {
1686  xnew[-ibdsav] = sl[-ibdsav];
1687  }
1688  if (ibdsav > 0) {
1689  xnew[ibdsav] = su[ibdsav];
1690  }
1691 
1692  /* Prepare for the iterative method that assembles the constrained Cauchy */
1693  /* step in W. The sum of squares of the fixed components of W is formed in */
1694  /* WFIXSQ, and the free components of W are set to BIGSTP. */
1695 
1696  bigstp = *adelt + *adelt;
1697  iflag = 0;
1698 L100:
1699  wfixsq = zero;
1700  ggfree = zero;
1701  i__1 = m_SpaceDimension;
1702  for (i__ = 1; i__ <= i__1; ++i__) {
1703  w[i__] = zero;
1704  /* Computing MIN */
1705  d__1 = xopt[i__] - sl[i__], d__2 = glag[i__];
1706  tempa = std::min(d__1,d__2);
1707  /* Computing MAX */
1708  d__1 = xopt[i__] - su[i__], d__2 = glag[i__];
1709  tempb = std::max(d__1,d__2);
1710  if (tempa > zero || tempb < zero) {
1711  w[i__] = bigstp;
1712  /* Computing 2nd power */
1713  d__1 = glag[i__];
1714  ggfree += d__1 * d__1;
1715  }
1716  /* L110: */
1717  }
1718  if (ggfree == zero) {
1719  *cauchy = zero;
1720  goto L200;
1721  }
1722 
1723  /* Investigate whether more components of W can be fixed. */
1724 
1725 L120:
1726  temp = *adelt * *adelt - wfixsq;
1727  if (temp > zero) {
1728  wsqsav = wfixsq;
1729  step = std::sqrt(temp / ggfree);
1730  ggfree = zero;
1731  i__1 = m_SpaceDimension;
1732  for (i__ = 1; i__ <= i__1; ++i__) {
1733  if (w[i__] == bigstp) {
1734  temp = xopt[i__] - step * glag[i__];
1735  if (temp <= sl[i__]) {
1736  w[i__] = sl[i__] - xopt[i__];
1737  /* Computing 2nd power */
1738  d__1 = w[i__];
1739  wfixsq += d__1 * d__1;
1740  } else if (temp >= su[i__]) {
1741  w[i__] = su[i__] - xopt[i__];
1742  /* Computing 2nd power */
1743  d__1 = w[i__];
1744  wfixsq += d__1 * d__1;
1745  } else {
1746  /* Computing 2nd power */
1747  d__1 = glag[i__];
1748  ggfree += d__1 * d__1;
1749  }
1750  }
1751  /* L130: */
1752  }
1753  if (wfixsq > wsqsav && ggfree > zero) {
1754  goto L120;
1755  }
1756  }
1757 
1758  /* Set the remaining free components of W and all components of XALT, */
1759  /* except that W may be scaled later. */
1760 
1761  gw = zero;
1762  i__1 = m_SpaceDimension;
1763  for (i__ = 1; i__ <= i__1; ++i__) {
1764  if (w[i__] == bigstp) {
1765  w[i__] = -step * glag[i__];
1766  /* Computing MAX */
1767  /* Computing MIN */
1768  d__3 = su[i__], d__4 = xopt[i__] + w[i__];
1769  d__1 = sl[i__], d__2 = std::min(d__3,d__4);
1770  xalt[i__] = std::max(d__1,d__2);
1771  } else if (w[i__] == zero) {
1772  xalt[i__] = xopt[i__];
1773  } else if (glag[i__] > zero) {
1774  xalt[i__] = sl[i__];
1775  } else {
1776  xalt[i__] = su[i__];
1777  }
1778  /* L140: */
1779  gw += glag[i__] * w[i__];
1780  }
1781 
1782  /* Set CURV to the curvature of the KNEW-th Lagrange function along W. */
1783  /* Scale W by a factor less than one if that can reduce the modulus of */
1784  /* the Lagrange function at XOPT+W. Set CAUCHY to the final value of */
1785  /* the square of this function. */
1786 
1787  curv = zero;
1788  i__1 = npt;
1789  for (k = 1; k <= i__1; ++k) {
1790  temp = zero;
1791  i__2 = m_SpaceDimension;
1792  for (j = 1; j <= i__2; ++j) {
1793  /* L150: */
1794  temp += xpt[k + j * xpt_dim1] * w[j];
1795  }
1796  /* L160: */
1797  curv += hcol[k] * temp * temp;
1798  }
1799  if (iflag == 1) {
1800  curv = -curv;
1801  }
1802  if (curv > -gw && curv < -const__ * gw) {
1803  scale = -gw / curv;
1804  i__1 = m_SpaceDimension;
1805  for (i__ = 1; i__ <= i__1; ++i__) {
1806  temp = xopt[i__] + scale * w[i__];
1807  /* L170: */
1808  /* Computing MAX */
1809  /* Computing MIN */
1810  d__3 = su[i__];
1811  d__1 = sl[i__], d__2 = std::min(d__3,temp);
1812  xalt[i__] = std::max(d__1,d__2);
1813  }
1814  /* Computing 2nd power */
1815  d__1 = half * gw * scale;
1816  *cauchy = d__1 * d__1;
1817  } else {
1818  /* Computing 2nd power */
1819  d__1 = gw + half * curv;
1820  *cauchy = d__1 * d__1;
1821  }
1822 
1823  /* If IFLAG is zero, then XALT is calculated as before after reversing */
1824  /* the sign of GLAG. Thus two XALT vectors become available. The one that */
1825  /* is chosen is the one that gives the larger value of CAUCHY. */
1826 
1827  if (iflag == 0) {
1828  i__1 = m_SpaceDimension;
1829  for (i__ = 1; i__ <= i__1; ++i__) {
1830  glag[i__] = -glag[i__];
1831  /* L180: */
1832  w[m_SpaceDimension + i__] = xalt[i__];
1833  }
1834  csave = *cauchy;
1835  iflag = 1;
1836  goto L100;
1837  }
1838  if (csave > *cauchy) {
1839  i__1 = m_SpaceDimension;
1840  for (i__ = 1; i__ <= i__1; ++i__) {
1841  /* L190: */
1842  xalt[i__] = w[m_SpaceDimension + i__];
1843  }
1844  *cauchy = csave;
1845  }
1846 L200:
1847  return 0;
1848 } /* altmov_ */
1849 
1850 int BobyqaOptimizer::prelim_(long int &npt, double *x,
1851  double *xl, double *xu, double &rhobeg,
1852  long int &maxfun, double *xbase, double *xpt, double *fval,
1853  double *gopt, double *hq, double *pq, double *bmat,
1854  double *zmat, long int &ndim, double *sl, double *su,
1855  long int &nf, long int &kopt)
1856 {
1857  /* System generated locals */
1858  long int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1,
1859  zmat_offset, i__1, i__2;
1860  double d__1, d__2, d__3, d__4;
1861 
1862  /* Local variables */
1863  double f;
1864  long int i__, j, k, ih, np, nfm;
1865  double one;
1866  long int nfx, ipt = 0, jpt = 0;
1867  double two, fbeg = 0, diff, half, temp, zero, recip, stepa = 0, stepb = 0;
1868  long int itemp;
1869  double rhosq;
1870 
1871  /* The arguments N, NPT, X, XL, XU, RHOBEG, IPRINT and MAXFUN are the */
1872  /* same as the corresponding arguments in SUBROUTINE BOBYQA. */
1873  /* The arguments XBASE, XPT, FVAL, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU */
1874  /* are the same as the corresponding arguments in BOBYQB, the elements */
1875  /* of SL and SU being set in BOBYQA. */
1876  /* GOPT is usually the gradient of the quadratic model at XOPT+XBASE, but */
1877  /* it is set by PRELIM to the gradient of the quadratic model at XBASE. */
1878  /* If XOPT is nonzero, BOBYQB will change it to its usual value later. */
1879  /* NF is maintaned as the number of calls of CALFUN so far. */
1880  /* KOPT will be such that the least calculated value of F so far is at */
1881  /* the point XPT(KOPT,.)+XBASE in the space of the variables. */
1882 
1883  /* SUBROUTINE PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ, */
1884  /* BMAT and ZMAT for the first iteration, and it maintains the values of */
1885  /* NF and KOPT. The vector X is also changed by PRELIM. */
1886 
1887  /* Set some constants. */
1888 
1889  /* Parameter adjustments */
1890  zmat_dim1 = npt;
1891  zmat_offset = 1 + zmat_dim1;
1892  zmat -= zmat_offset;
1893  xpt_dim1 = npt;
1894  xpt_offset = 1 + xpt_dim1;
1895  xpt -= xpt_offset;
1896  --x;
1897  --xl;
1898  --xu;
1899  --xbase;
1900  --fval;
1901  --gopt;
1902  --hq;
1903  --pq;
1904  bmat_dim1 = ndim;
1905  bmat_offset = 1 + bmat_dim1;
1906  bmat -= bmat_offset;
1907  --sl;
1908  --su;
1909 
1910  /* Function Body */
1911  half = .5;
1912  one = 1.;
1913  two = 2.;
1914  zero = 0.;
1915  rhosq = rhobeg * rhobeg;
1916  recip = one / rhosq;
1917  np = m_SpaceDimension + 1;
1918 
1919  /* Set XBASE to the initial vector of variables, and set the initial */
1920  /* elements of XPT, BMAT, HQ, PQ and ZMAT to zero. */
1921 
1922  i__1 = m_SpaceDimension;
1923  for (j = 1; j <= i__1; ++j) {
1924  xbase[j] = x[j];
1925  i__2 = npt;
1926  for (k = 1; k <= i__2; ++k) {
1927  /* L10: */
1928  xpt[k + j * xpt_dim1] = zero;
1929  }
1930  i__2 = ndim;
1931  for (i__ = 1; i__ <= i__2; ++i__) {
1932  /* L20: */
1933  bmat[i__ + j * bmat_dim1] = zero;
1934  }
1935  }
1936  i__2 = m_SpaceDimension * np / 2;
1937  for (ih = 1; ih <= i__2; ++ih) {
1938  /* L30: */
1939  hq[ih] = zero;
1940  }
1941  i__2 = npt;
1942  for (k = 1; k <= i__2; ++k) {
1943  pq[k] = zero;
1944  i__1 = npt - np;
1945  for (j = 1; j <= i__1; ++j) {
1946  /* L40: */
1947  zmat[k + j * zmat_dim1] = zero;
1948  }
1949  }
1950 
1951  /* Begin the initialization procedure. NF becomes one more than the number */
1952  /* of function values so far. The coordinates of the displacement of the */
1953  /* next initial interpolation point from XBASE are set in XPT(NF+1,.). */
1954 
1955  nf = 0;
1956 L50:
1957  nfm = nf;
1958  nfx = nf - m_SpaceDimension;
1959  ++(nf);
1960 
1961  this->m_CurrentIteration = nf;
1962  this->InvokeEvent( itk::IterationEvent() );
1963 
1964  if (nfm <= m_SpaceDimension << 1) {
1965  if (nfm >= 1 && nfm <= m_SpaceDimension) {
1966  stepa = rhobeg;
1967  if (su[nfm] == zero) {
1968  stepa = -stepa;
1969  }
1970  xpt[nf + nfm * xpt_dim1] = stepa;
1971  } else if (nfm > m_SpaceDimension) {
1972  stepa = xpt[nf - m_SpaceDimension + nfx * xpt_dim1];
1973  stepb = -(rhobeg);
1974  if (sl[nfx] == zero) {
1975  /* Computing MIN */
1976  d__1 = two * rhobeg, d__2 = su[nfx];
1977  stepb = std::min(d__1,d__2);
1978  }
1979  if (su[nfx] == zero) {
1980  /* Computing MAX */
1981  d__1 = -two * rhobeg, d__2 = sl[nfx];
1982  stepb = std::max(d__1,d__2);
1983  }
1984  xpt[nf + nfx * xpt_dim1] = stepb;
1985  }
1986  } else {
1987  itemp = (nfm - np) / m_SpaceDimension;
1988  jpt = nfm - itemp * m_SpaceDimension - m_SpaceDimension;
1989  ipt = jpt + itemp;
1990  if (ipt > m_SpaceDimension) {
1991  itemp = jpt;
1992  jpt = ipt - m_SpaceDimension;
1993  ipt = itemp;
1994  }
1995  xpt[nf + ipt * xpt_dim1] = xpt[ipt + 1 + ipt * xpt_dim1];
1996  xpt[nf + jpt * xpt_dim1] = xpt[jpt + 1 + jpt * xpt_dim1];
1997  }
1998 
1999  /* Calculate the next value of F. The least function value so far and */
2000  /* its index are required. */
2001 
2002  i__1 = m_SpaceDimension;
2003  for (j = 1; j <= i__1; ++j) {
2004  /* Computing MIN */
2005  /* Computing MAX */
2006  d__3 = xl[j], d__4 = xbase[j] + xpt[nf + j * xpt_dim1];
2007  d__1 = std::max(d__3,d__4), d__2 = xu[j];
2008  x[j] = std::min(d__1,d__2);
2009  if (xpt[nf + j * xpt_dim1] == sl[j]) {
2010  x[j] = xl[j];
2011  }
2012  if (xpt[nf + j * xpt_dim1] == su[j]) {
2013  x[j] = xu[j];
2014  }
2015  /* L60: */
2016  }
2017 
2018  // Call to cost function
2019  for (unsigned i = 0; i < m_SpaceDimension; ++i) px[i] = x[i+1] / this->GetScales()[i];
2020  // f = cost(&x[1]);//*fun;
2021 
2022  try {
2023  f = this->m_CostFunction->GetValue(px);
2024  }
2025  catch(...)
2026  {
2029  else throw;
2030  }
2031  if (this->m_Maximize)
2032  f = -f;
2033 
2034  this->m_CurrentCost = f;
2035 
2036  //calfun_(&x[1], &f);
2037 // if (*iprint == 3) {
2038 // s_wsfe(&io___187);
2039 // do_fio(&c__1, (char *)&(*nf), (ftnlen)sizeof(long int));
2040 // do_fio(&c__1, (char *)&f, (ftnlen)sizeof(double));
2041 // i__1 = m_SpaceDimension;
2042 // for (i__ = 1; i__ <= i__1; ++i__) {
2043 // do_fio(&c__1, (char *)&x[i__], (ftnlen)sizeof(double));
2044 // }
2045 // e_wsfe();
2046 // }
2047  fval[nf] = f;
2048  if (nf == 1) {
2049  fbeg = f;
2050  kopt = 1;
2051  } else if (f < fval[kopt]) {
2052  kopt = nf;
2053  }
2054 
2055  /* Set the nonzero initial elements of BMAT and the quadratic model in the */
2056  /* cases when NF is at most 2*N+1. If NF exceeds N+1, then the positions */
2057  /* of the NF-th and (NF-N)-th interpolation points may be switched, in */
2058  /* order that the function value at the first of them contributes to the */
2059  /* off-diagonal second derivative terms of the initial quadratic model. */
2060 
2061  if (nf <= (m_SpaceDimension << 1) + 1) {
2062  if (nf >= 2 && nf <= m_SpaceDimension + 1) {
2063  gopt[nfm] = (f - fbeg) / stepa;
2064  if (npt < nf + m_SpaceDimension) {
2065  bmat[nfm * bmat_dim1 + 1] = -one / stepa;
2066  bmat[nf + nfm * bmat_dim1] = one / stepa;
2067  bmat[npt + nfm + nfm * bmat_dim1] = -half * rhosq;
2068  }
2069  } else if (nf >= m_SpaceDimension + 2) {
2070  ih = nfx * (nfx + 1) / 2;
2071  temp = (f - fbeg) / stepb;
2072  diff = stepb - stepa;
2073  hq[ih] = two * (temp - gopt[nfx]) / diff;
2074  gopt[nfx] = (gopt[nfx] * stepb - temp * stepa) / diff;
2075  if (stepa * stepb < zero) {
2076  if (f < fval[nf - m_SpaceDimension]) {
2077  fval[nf] = fval[nf - m_SpaceDimension];
2078  fval[nf - m_SpaceDimension] = f;
2079  if (kopt == nf) {
2080  kopt = nf - m_SpaceDimension;
2081  }
2082  xpt[nf - m_SpaceDimension + nfx * xpt_dim1] = stepb;
2083  xpt[nf + nfx * xpt_dim1] = stepa;
2084  }
2085  }
2086  bmat[nfx * bmat_dim1 + 1] = -(stepa + stepb) / (stepa * stepb);
2087  bmat[nf + nfx * bmat_dim1] = -half / xpt[nf - m_SpaceDimension + nfx *
2088  xpt_dim1];
2089  bmat[nf - m_SpaceDimension + nfx * bmat_dim1] = -bmat[nfx * bmat_dim1 + 1] -
2090  bmat[nf + nfx * bmat_dim1];
2091  zmat[nfx * zmat_dim1 + 1] = std::sqrt(two) / (stepa * stepb);
2092  zmat[nf + nfx * zmat_dim1] = std::sqrt(half) / rhosq;
2093  zmat[nf - m_SpaceDimension + nfx * zmat_dim1] = -zmat[nfx * zmat_dim1 + 1] -
2094  zmat[nf + nfx * zmat_dim1];
2095  }
2096 
2097  /* Set the off-diagonal second derivatives of the Lagrange functions and */
2098  /* the initial quadratic model. */
2099 
2100  } else {
2101  ih = ipt * (ipt - 1) / 2 + jpt;
2102  zmat[nfx * zmat_dim1 + 1] = recip;
2103  zmat[nf + nfx * zmat_dim1] = recip;
2104  zmat[ipt + 1 + nfx * zmat_dim1] = -recip;
2105  zmat[jpt + 1 + nfx * zmat_dim1] = -recip;
2106  temp = xpt[nf + ipt * xpt_dim1] * xpt[nf + jpt * xpt_dim1];
2107  hq[ih] = (fbeg - fval[ipt + 1] - fval[jpt + 1] + f) / temp;
2108  }
2109  if (nf < npt && nf < maxfun) {
2110  goto L50;
2111  }
2112  return 0;
2113 } /* prelim_ */
2114 
2115 int BobyqaOptimizer::rescue_(long int &npt, double *xl,
2116  double *xu, long int &maxfun, double *xbase,
2117  double *xpt, double *fval, double *xopt, double *gopt,
2118  double *hq, double *pq, double *bmat, double *zmat,
2119  long int &ndim, double *sl, double *su, long int &nf,
2120  double *delta, long int &kopt, double *vlag, double *
2121  ptsaux, double *ptsid, double *w)
2122 {
2123  /* System generated locals */
2124  long int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1,
2125  zmat_offset, i__1, i__2, i__3;
2126  double d__1, d__2, d__3, d__4;
2127 
2128  /* Local variables */
2129  double f;
2130  long int i__, j, k, ih, jp, ip, iq, np, iw;
2131  double xp = 0, xq = 0, den;
2132  long int ihp = 0;
2133  double one;
2134  long int ihq, jpn, kpt;
2135  double sum, diff, half, beta;
2136  long int kold;
2137  double winc;
2138  long int nrem, knew;
2139  double temp, bsum;
2140  long int nptm;
2141  double zero, hdiag, fbase, sfrac, denom, vquad, sumpq;
2142 
2143  double dsqmin, distsq, vlmxsq;
2144 
2145  /* The arguments N, NPT, XL, XU, IPRINT, MAXFUN, XBASE, XPT, FVAL, XOPT, */
2146  /* GOPT, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU have the same meanings as */
2147  /* the corresponding arguments of BOBYQB on the entry to RESCUE. */
2148  /* NF is maintained as the number of calls of CALFUN so far, except that */
2149  /* NF is set to -1 if the value of MAXFUN prevents further progress. */
2150  /* KOPT is maintained so that FVAL(KOPT) is the least calculated function */
2151  /* value. Its correct value must be given on entry. It is updated if a */
2152  /* new least function value is found, but the corresponding changes to */
2153  /* XOPT and GOPT have to be made later by the calling program. */
2154  /* DELTA is the current trust region radius. */
2155  /* VLAG is a working space vector that will be used for the values of the */
2156  /* provisional Lagrange functions at each of the interpolation points. */
2157  /* They are part of a product that requires VLAG to be of length NDIM. */
2158  /* PTSAUX is also a working space array. For J=1,2,...,N, PTSAUX(1,J) and */
2159  /* PTSAUX(2,J) specify the two positions of provisional interpolation */
2160  /* points when a nonzero step is taken along e_J (the J-th coordinate */
2161  /* direction) through XBASE+XOPT, as specified below. Usually these */
2162  /* steps have length DELTA, but other lengths are chosen if necessary */
2163  /* in order to satisfy the given bounds on the variables. */
2164  /* PTSID is also a working space array. It has NPT components that denote */
2165  /* provisional new positions of the original interpolation points, in */
2166  /* case changes are needed to restore the linear independence of the */
2167  /* interpolation conditions. The K-th point is a candidate for change */
2168  /* if and only if PTSID(K) is nonzero. In this case let p and q be the */
2169  /* long int parts of PTSID(K) and (PTSID(K)-p) multiplied by N+1. If p */
2170  /* and q are both positive, the step from XBASE+XOPT to the new K-th */
2171  /* interpolation point is PTSAUX(1,p)*e_p + PTSAUX(1,q)*e_q. Otherwise */
2172  /* the step is PTSAUX(1,p)*e_p or PTSAUX(2,q)*e_q in the cases q=0 or */
2173  /* p=0, respectively. */
2174  /* The first NDIM+NPT elements of the array W are used for working space. */
2175  /* The final elements of BMAT and ZMAT are set in a well-conditioned way */
2176  /* to the values that are appropriate for the new interpolation points. */
2177  /* The elements of GOPT, HQ and PQ are also revised to the values that are */
2178  /* appropriate to the final quadratic model. */
2179 
2180  /* Set some constants. */
2181 
2182  /* Parameter adjustments */
2183  zmat_dim1 = npt;
2184  zmat_offset = 1 + zmat_dim1;
2185  zmat -= zmat_offset;
2186  xpt_dim1 = npt;
2187  xpt_offset = 1 + xpt_dim1;
2188  xpt -= xpt_offset;
2189  --xl;
2190  --xu;
2191  --xbase;
2192  --fval;
2193  --xopt;
2194  --gopt;
2195  --hq;
2196  --pq;
2197  bmat_dim1 = ndim;
2198  bmat_offset = 1 + bmat_dim1;
2199  bmat -= bmat_offset;
2200  --sl;
2201  --su;
2202  --vlag;
2203  ptsaux -= 3;
2204  --ptsid;
2205  --w;
2206 
2207  /* Function Body */
2208  half = .5;
2209  one = 1.;
2210  zero = 0.;
2211  np = m_SpaceDimension + 1;
2212  sfrac = half / (double) np;
2213  nptm = npt - np;
2214 
2215  /* Shift the interpolation points so that XOPT becomes the origin, and set */
2216  /* the elements of ZMAT to zero. The value of SUMPQ is required in the */
2217  /* updating of HQ below. The squares of the distances from XOPT to the */
2218  /* other interpolation points are set at the end of W. Increments of WINC */
2219  /* may be added later to these squares to balance the consideration of */
2220  /* the choice of point that is going to become current. */
2221 
2222  sumpq = zero;
2223  winc = zero;
2224  i__1 = npt;
2225  for (k = 1; k <= i__1; ++k) {
2226  distsq = zero;
2227  i__2 = m_SpaceDimension;
2228  for (j = 1; j <= i__2; ++j) {
2229  xpt[k + j * xpt_dim1] -= xopt[j];
2230  /* L10: */
2231  /* Computing 2nd power */
2232  d__1 = xpt[k + j * xpt_dim1];
2233  distsq += d__1 * d__1;
2234  }
2235  sumpq += pq[k];
2236  w[ndim + k] = distsq;
2237  winc = std::max(winc,distsq);
2238  i__2 = nptm;
2239  for (j = 1; j <= i__2; ++j) {
2240  /* L20: */
2241  zmat[k + j * zmat_dim1] = zero;
2242  }
2243  }
2244 
2245  /* Update HQ so that HQ and PQ define the second derivatives of the model */
2246  /* after XBASE has been shifted to the trust region centre. */
2247 
2248  ih = 0;
2249  i__2 = m_SpaceDimension;
2250  for (j = 1; j <= i__2; ++j) {
2251  w[j] = half * sumpq * xopt[j];
2252  i__1 = npt;
2253  for (k = 1; k <= i__1; ++k) {
2254  /* L30: */
2255  w[j] += pq[k] * xpt[k + j * xpt_dim1];
2256  }
2257  i__1 = j;
2258  for (i__ = 1; i__ <= i__1; ++i__) {
2259  ++ih;
2260  /* L40: */
2261  hq[ih] = hq[ih] + w[i__] * xopt[j] + w[j] * xopt[i__];
2262  }
2263  }
2264 
2265  /* Shift XBASE, SL, SU and XOPT. Set the elements of BMAT to zero, and */
2266  /* also set the elements of PTSAUX. */
2267 
2268  i__1 = m_SpaceDimension;
2269  for (j = 1; j <= i__1; ++j) {
2270  xbase[j] += xopt[j];
2271  sl[j] -= xopt[j];
2272  su[j] -= xopt[j];
2273  xopt[j] = zero;
2274  /* Computing MIN */
2275  d__1 = *delta, d__2 = su[j];
2276  ptsaux[(j << 1) + 1] = std::min(d__1,d__2);
2277  /* Computing MAX */
2278  d__1 = -(*delta), d__2 = sl[j];
2279  ptsaux[(j << 1) + 2] = std::max(d__1,d__2);
2280  if (ptsaux[(j << 1) + 1] + ptsaux[(j << 1) + 2] < zero) {
2281  temp = ptsaux[(j << 1) + 1];
2282  ptsaux[(j << 1) + 1] = ptsaux[(j << 1) + 2];
2283  ptsaux[(j << 1) + 2] = temp;
2284  }
2285  if ((d__2 = ptsaux[(j << 1) + 2], std::abs(d__2)) < half * (d__1 = ptsaux[(
2286  j << 1) + 1], std::abs(d__1))) {
2287  ptsaux[(j << 1) + 2] = half * ptsaux[(j << 1) + 1];
2288  }
2289  i__2 = ndim;
2290  for (i__ = 1; i__ <= i__2; ++i__) {
2291  /* L50: */
2292  bmat[i__ + j * bmat_dim1] = zero;
2293  }
2294  }
2295  fbase = fval[kopt];
2296 
2297  /* Set the identifiers of the artificial interpolation points that are */
2298  /* along a coordinate direction from XOPT, and set the corresponding */
2299  /* nonzero elements of BMAT and ZMAT. */
2300 
2301  ptsid[1] = sfrac;
2302  i__2 = m_SpaceDimension;
2303  for (j = 1; j <= i__2; ++j) {
2304  jp = j + 1;
2305  jpn = jp + m_SpaceDimension;
2306  ptsid[jp] = (double) j + sfrac;
2307  if (jpn <= npt) {
2308  ptsid[jpn] = (double) j / (double) np + sfrac;
2309  temp = one / (ptsaux[(j << 1) + 1] - ptsaux[(j << 1) + 2]);
2310  bmat[jp + j * bmat_dim1] = -temp + one / ptsaux[(j << 1) + 1];
2311  bmat[jpn + j * bmat_dim1] = temp + one / ptsaux[(j << 1) + 2];
2312  bmat[j * bmat_dim1 + 1] = -bmat[jp + j * bmat_dim1] - bmat[jpn +
2313  j * bmat_dim1];
2314  zmat[j * zmat_dim1 + 1] = std::sqrt(2.) / (d__1 = ptsaux[(j << 1) + 1]
2315  * ptsaux[(j << 1) + 2], std::abs(d__1));
2316  zmat[jp + j * zmat_dim1] = zmat[j * zmat_dim1 + 1] * ptsaux[(j <<
2317  1) + 2] * temp;
2318  zmat[jpn + j * zmat_dim1] = -zmat[j * zmat_dim1 + 1] * ptsaux[(j
2319  << 1) + 1] * temp;
2320  } else {
2321  bmat[j * bmat_dim1 + 1] = -one / ptsaux[(j << 1) + 1];
2322  bmat[jp + j * bmat_dim1] = one / ptsaux[(j << 1) + 1];
2323  /* Computing 2nd power */
2324  d__1 = ptsaux[(j << 1) + 1];
2325  bmat[j + npt + j * bmat_dim1] = -half * (d__1 * d__1);
2326  }
2327  /* L60: */
2328  }
2329 
2330  /* Set any remaining identifiers with their nonzero elements of ZMAT. */
2331 
2332  if (npt >= m_SpaceDimension + np) {
2333  i__2 = npt;
2334  for (k = np << 1; k <= i__2; ++k) {
2335  iw = (long int) (((double) (k - np) - half) / (double) (m_SpaceDimension)
2336  );
2337  ip = k - np - iw * m_SpaceDimension;
2338  iq = ip + iw;
2339  if (iq > m_SpaceDimension) {
2340  iq -= m_SpaceDimension;
2341  }
2342  ptsid[k] = (double) ip + (double) iq / (double) np +
2343  sfrac;
2344  temp = one / (ptsaux[(ip << 1) + 1] * ptsaux[(iq << 1) + 1]);
2345  zmat[(k - np) * zmat_dim1 + 1] = temp;
2346  zmat[ip + 1 + (k - np) * zmat_dim1] = -temp;
2347  zmat[iq + 1 + (k - np) * zmat_dim1] = -temp;
2348  /* L70: */
2349  zmat[k + (k - np) * zmat_dim1] = temp;
2350  }
2351  }
2352  nrem = npt;
2353  kold = 1;
2354  knew = kopt;
2355 
2356  /* Reorder the provisional points in the way that exchanges PTSID(KOLD) */
2357  /* with PTSID(KNEW). */
2358 
2359 L80:
2360  i__2 = m_SpaceDimension;
2361  for (j = 1; j <= i__2; ++j) {
2362  temp = bmat[kold + j * bmat_dim1];
2363  bmat[kold + j * bmat_dim1] = bmat[knew + j * bmat_dim1];
2364  /* L90: */
2365  bmat[knew + j * bmat_dim1] = temp;
2366  }
2367  i__2 = nptm;
2368  for (j = 1; j <= i__2; ++j) {
2369  temp = zmat[kold + j * zmat_dim1];
2370  zmat[kold + j * zmat_dim1] = zmat[knew + j * zmat_dim1];
2371  /* L100: */
2372  zmat[knew + j * zmat_dim1] = temp;
2373  }
2374  ptsid[kold] = ptsid[knew];
2375  ptsid[knew] = zero;
2376  w[ndim + knew] = zero;
2377  --nrem;
2378  if (knew != kopt) {
2379  temp = vlag[kold];
2380  vlag[kold] = vlag[knew];
2381  vlag[knew] = temp;
2382 
2383  /* Update the BMAT and ZMAT matrices so that the status of the KNEW-th */
2384  /* interpolation point can be changed from provisional to original. The */
2385  /* branch to label 350 occurs if all the original points are reinstated. */
2386  /* The nonnegative values of W(NDIM+K) are required in the search below. */
2387 
2388  update_(npt, &bmat[bmat_offset], &zmat[zmat_offset], ndim, &vlag[1], &beta, &denom, knew, &w[1]);
2389  if (nrem == 0) {
2390  goto L350;
2391  }
2392  i__2 = npt;
2393  for (k = 1; k <= i__2; ++k) {
2394  /* L110: */
2395  w[ndim + k] = (d__1 = w[ndim + k], std::abs(d__1));
2396  }
2397  }
2398 
2399  /* Pick the index KNEW of an original interpolation point that has not */
2400  /* yet replaced one of the provisional interpolation points, giving */
2401  /* attention to the closeness to XOPT and to previous tries with KNEW. */
2402 
2403 L120:
2404  dsqmin = zero;
2405  i__2 = npt;
2406  for (k = 1; k <= i__2; ++k) {
2407  if (w[ndim + k] > zero) {
2408  if (dsqmin == zero || w[ndim + k] < dsqmin) {
2409  knew = k;
2410  dsqmin = w[ndim + k];
2411  }
2412  }
2413  /* L130: */
2414  }
2415  if (dsqmin == zero) {
2416  goto L260;
2417  }
2418 
2419  /* Form the W-vector of the chosen original interpolation point. */
2420 
2421  i__2 = m_SpaceDimension;
2422  for (j = 1; j <= i__2; ++j) {
2423  /* L140: */
2424  w[npt + j] = xpt[knew + j * xpt_dim1];
2425  }
2426  i__2 = npt;
2427  for (k = 1; k <= i__2; ++k) {
2428  sum = zero;
2429  if (k == kopt) {
2430  } else if (ptsid[k] == zero) {
2431  i__1 = m_SpaceDimension;
2432  for (j = 1; j <= i__1; ++j) {
2433  /* L150: */
2434  sum += w[npt + j] * xpt[k + j * xpt_dim1];
2435  }
2436  } else {
2437  ip = (long int) ptsid[k];
2438  if (ip > 0) {
2439  sum = w[npt + ip] * ptsaux[(ip << 1) + 1];
2440  }
2441  iq = (long int) ((double) np * ptsid[k] - (double) (ip *
2442  np));
2443  if (iq > 0) {
2444  iw = 1;
2445  if (ip == 0) {
2446  iw = 2;
2447  }
2448  sum += w[npt + iq] * ptsaux[iw + (iq << 1)];
2449  }
2450  }
2451  /* L160: */
2452  w[k] = half * sum * sum;
2453  }
2454 
2455  /* Calculate VLAG and BETA for the required updating of the H matrix if */
2456  /* XPT(KNEW,.) is reinstated in the set of interpolation points. */
2457 
2458  i__2 = npt;
2459  for (k = 1; k <= i__2; ++k) {
2460  sum = zero;
2461  i__1 = m_SpaceDimension;
2462  for (j = 1; j <= i__1; ++j) {
2463  /* L170: */
2464  sum += bmat[k + j * bmat_dim1] * w[npt + j];
2465  }
2466  /* L180: */
2467  vlag[k] = sum;
2468  }
2469  beta = zero;
2470  i__2 = nptm;
2471  for (j = 1; j <= i__2; ++j) {
2472  sum = zero;
2473  i__1 = npt;
2474  for (k = 1; k <= i__1; ++k) {
2475  /* L190: */
2476  sum += zmat[k + j * zmat_dim1] * w[k];
2477  }
2478  beta -= sum * sum;
2479  i__1 = npt;
2480  for (k = 1; k <= i__1; ++k) {
2481  /* L200: */
2482  vlag[k] += sum * zmat[k + j * zmat_dim1];
2483  }
2484  }
2485  bsum = zero;
2486  distsq = zero;
2487  i__1 = m_SpaceDimension;
2488  for (j = 1; j <= i__1; ++j) {
2489  sum = zero;
2490  i__2 = npt;
2491  for (k = 1; k <= i__2; ++k) {
2492  /* L210: */
2493  sum += bmat[k + j * bmat_dim1] * w[k];
2494  }
2495  jp = j + npt;
2496  bsum += sum * w[jp];
2497  i__2 = ndim;
2498  for (ip = npt + 1; ip <= i__2; ++ip) {
2499  /* L220: */
2500  sum += bmat[ip + j * bmat_dim1] * w[ip];
2501  }
2502  bsum += sum * w[jp];
2503  vlag[jp] = sum;
2504  /* L230: */
2505  /* Computing 2nd power */
2506  d__1 = xpt[knew + j * xpt_dim1];
2507  distsq += d__1 * d__1;
2508  }
2509  beta = half * distsq * distsq + beta - bsum;
2510  vlag[kopt] += one;
2511 
2512  /* KOLD is set to the index of the provisional interpolation point that is */
2513  /* going to be deleted to make way for the KNEW-th original interpolation */
2514  /* point. The choice of KOLD is governed by the avoidance of a small value */
2515  /* of the denominator in the updating calculation of UPDATE. */
2516 
2517  denom = zero;
2518  vlmxsq = zero;
2519  i__1 = npt;
2520  for (k = 1; k <= i__1; ++k) {
2521  if (ptsid[k] != zero) {
2522  hdiag = zero;
2523  i__2 = nptm;
2524  for (j = 1; j <= i__2; ++j) {
2525  /* L240: */
2526  /* Computing 2nd power */
2527  d__1 = zmat[k + j * zmat_dim1];
2528  hdiag += d__1 * d__1;
2529  }
2530  /* Computing 2nd power */
2531  d__1 = vlag[k];
2532  den = beta * hdiag + d__1 * d__1;
2533  if (den > denom) {
2534  kold = k;
2535  denom = den;
2536  }
2537  }
2538  /* L250: */
2539  /* Computing MAX */
2540  /* Computing 2nd power */
2541  d__3 = vlag[k];
2542  d__1 = vlmxsq, d__2 = d__3 * d__3;
2543  vlmxsq = std::max(d__1,d__2);
2544  }
2545  if (denom <= vlmxsq * .01) {
2546  w[ndim + knew] = -w[ndim + knew] - winc;
2547  goto L120;
2548  }
2549  goto L80;
2550 
2551  /* When label 260 is reached, all the final positions of the interpolation */
2552  /* points have been chosen although any changes have not been included yet */
2553  /* in XPT. Also the final BMAT and ZMAT matrices are complete, but, apart */
2554  /* from the shift of XBASE, the updating of the quadratic model remains to */
2555  /* be done. The following cycle through the new interpolation points begins */
2556  /* by putting the new point in XPT(KPT,.) and by setting PQ(KPT) to zero, */
2557  /* except that a RETURN occurs if MAXFUN prohibits another value of F. */
2558 
2559 L260:
2560  i__1 = npt;
2561  for (kpt = 1; kpt <= i__1; ++kpt) {
2562  if (ptsid[kpt] == zero) {
2563  goto L340;
2564  }
2565  if (nf >= maxfun) {
2566  this->m_StopConditionDescription << "Max cost function call reached " << this->m_MaximumIteration;
2567  this->InvokeEvent(itk::EndEvent());
2568 
2569  nf = -1;
2570  goto L350;
2571  }
2572  ih = 0;
2573  i__2 = m_SpaceDimension;
2574  for (j = 1; j <= i__2; ++j) {
2575  w[j] = xpt[kpt + j * xpt_dim1];
2576  xpt[kpt + j * xpt_dim1] = zero;
2577  temp = pq[kpt] * w[j];
2578  i__3 = j;
2579  for (i__ = 1; i__ <= i__3; ++i__) {
2580  ++ih;
2581  /* L270: */
2582  hq[ih] += temp * w[i__];
2583  }
2584  }
2585  pq[kpt] = zero;
2586  ip = (long int) ptsid[kpt];
2587  iq = (long int) ((double) np * ptsid[kpt] - (double) (ip * np))
2588  ;
2589  if (ip > 0) {
2590  xp = ptsaux[(ip << 1) + 1];
2591  xpt[kpt + ip * xpt_dim1] = xp;
2592  }
2593  if (iq > 0) {
2594  xq = ptsaux[(iq << 1) + 1];
2595  if (ip == 0) {
2596  xq = ptsaux[(iq << 1) + 2];
2597  }
2598  xpt[kpt + iq * xpt_dim1] = xq;
2599  }
2600 
2601  /* Set VQUAD to the value of the current model at the new point. */
2602 
2603  vquad = fbase;
2604  if (ip > 0) {
2605  ihp = (ip + ip * ip) / 2;
2606  vquad += xp * (gopt[ip] + half * xp * hq[ihp]);
2607  }
2608  if (iq > 0) {
2609  ihq = (iq + iq * iq) / 2;
2610  vquad += xq * (gopt[iq] + half * xq * hq[ihq]);
2611  if (ip > 0) {
2612  iw = std::max(ihp,ihq) - (i__3 = ip - iq, std::abs(i__3));
2613  vquad += xp * xq * hq[iw];
2614  }
2615  }
2616  i__3 = npt;
2617  for (k = 1; k <= i__3; ++k) {
2618  temp = zero;
2619  if (ip > 0) {
2620  temp += xp * xpt[k + ip * xpt_dim1];
2621  }
2622  if (iq > 0) {
2623  temp += xq * xpt[k + iq * xpt_dim1];
2624  }
2625  /* L280: */
2626  vquad += half * pq[k] * temp * temp;
2627  }
2628 
2629  /* Calculate F at the new interpolation point, and set DIFF to the factor */
2630  /* that is going to multiply the KPT-th Lagrange function when the model */
2631  /* is updated to provide interpolation to the new function value. */
2632 
2633  i__3 = m_SpaceDimension;
2634  for (i__ = 1; i__ <= i__3; ++i__) {
2635  /* Computing MIN */
2636  /* Computing MAX */
2637  d__3 = xl[i__], d__4 = xbase[i__] + xpt[kpt + i__ * xpt_dim1];
2638  d__1 = std::max(d__3,d__4), d__2 = xu[i__];
2639  w[i__] = std::min(d__1,d__2);
2640  if (xpt[kpt + i__ * xpt_dim1] == sl[i__]) {
2641  w[i__] = xl[i__];
2642  }
2643  if (xpt[kpt + i__ * xpt_dim1] == su[i__]) {
2644  w[i__] = xu[i__];
2645  }
2646  /* L290: */
2647  }
2648  ++(nf);
2649 
2650  this->m_CurrentIteration = nf;
2651  this->InvokeEvent( itk::IterationEvent() );
2652 
2653  // Call to cost function
2654  for (unsigned i = 0; i < m_SpaceDimension; ++i) px[i] = w[i+1] / this->GetScales()[i];
2655  // f = cost(&x[1]);//*fun;
2656 
2657  try {
2658  f = this->m_CostFunction->GetValue(px);
2659  }
2660  catch(...)
2661  {
2664  else throw;
2665  }
2666  if (this->m_Maximize)
2667  f = -f;
2668 
2669  this->m_CurrentCost = f;
2670 
2671  //calfun_(&w[1], &f);
2672 // if (*iprint == 3) {
2673 // s_wsfe(&io___229);
2674 // do_fio(&c__1, (char *)&(*nf), (ftnlen)sizeof(long int));
2675 // do_fio(&c__1, (char *)&f, (ftnlen)sizeof(double));
2676 // i__3 = m_SpaceDimension;
2677 // for (i__ = 1; i__ <= i__3; ++i__) {
2678 // do_fio(&c__1, (char *)&w[i__], (ftnlen)sizeof(double));
2679 // }
2680 // e_wsfe();
2681 // }
2682  fval[kpt] = f;
2683  if (f < fval[kopt]) {
2684  kopt = kpt;
2685  }
2686  diff = f - vquad;
2687 
2688  /* Update the quadratic model. The RETURN from the subroutine occurs when */
2689  /* all the new interpolation points are included in the model. */
2690 
2691  i__3 = m_SpaceDimension;
2692  for (i__ = 1; i__ <= i__3; ++i__) {
2693  /* L310: */
2694  gopt[i__] += diff * bmat[kpt + i__ * bmat_dim1];
2695  }
2696  i__3 = npt;
2697  for (k = 1; k <= i__3; ++k) {
2698  sum = zero;
2699  i__2 = nptm;
2700  for (j = 1; j <= i__2; ++j) {
2701  /* L320: */
2702  sum += zmat[k + j * zmat_dim1] * zmat[kpt + j * zmat_dim1];
2703  }
2704  temp = diff * sum;
2705  if (ptsid[k] == zero) {
2706  pq[k] += temp;
2707  } else {
2708  ip = (long int) ptsid[k];
2709  iq = (long int) ((double) np * ptsid[k] - (double) (ip
2710  * np));
2711  ihq = (iq * iq + iq) / 2;
2712  if (ip == 0) {
2713  /* Computing 2nd power */
2714  d__1 = ptsaux[(iq << 1) + 2];
2715  hq[ihq] += temp * (d__1 * d__1);
2716  } else {
2717  ihp = (ip * ip + ip) / 2;
2718  /* Computing 2nd power */
2719  d__1 = ptsaux[(ip << 1) + 1];
2720  hq[ihp] += temp * (d__1 * d__1);
2721  if (iq > 0) {
2722  /* Computing 2nd power */
2723  d__1 = ptsaux[(iq << 1) + 1];
2724  hq[ihq] += temp * (d__1 * d__1);
2725  iw = std::max(ihp,ihq) - (i__2 = iq - ip, std::abs(i__2));
2726  hq[iw] += temp * ptsaux[(ip << 1) + 1] * ptsaux[(iq <<
2727  1) + 1];
2728  }
2729  }
2730  }
2731  /* L330: */
2732  }
2733  ptsid[kpt] = zero;
2734  L340:
2735  ;
2736  }
2737 L350:
2738  return 0;
2739 } /* rescue_ */
2740 
2741 int BobyqaOptimizer::trsbox_(long int &npt, double *xpt,
2742  double *xopt, double *gopt, double *hq, double *pq,
2743  double *sl, double *su, double *delta, double *xnew,
2744  double *d__, double *gnew, double *xbdi, double *s,
2745  double *hs, double *hred, double *dsq, double *crvmin)
2746 {
2747  /* System generated locals */
2748  long int xpt_dim1, xpt_offset, i__1, i__2;
2749  double d__1, d__2, d__3, d__4;
2750 
2751  /* Local variables */
2752  long int i__, j, k, ih;
2753  double ds;
2754  long int iu;
2755  double dhd, dhs, cth, one, shs, sth, ssq, half, beta, sdec, blen;
2756  long int iact = 0, nact;
2757  double angt, qred;
2758  long int isav;
2759  double temp, zero, xsav = 0, xsum, angbd = 0, dredg = 0, sredg = 0;
2760  long int iterc;
2761  double resid, delsq, ggsav = 0, tempa, tempb, redmax, dredsq = 0, redsav, onemin, gredsq = 0, rednew;
2762  long int itcsav = 0;
2763  double rdprev = 0, rdnext = 0, stplen, stepsq;
2764  long int itermax = 0;
2765 
2766 
2767  /* The arguments N, NPT, XPT, XOPT, GOPT, HQ, PQ, SL and SU have the same */
2768  /* meanings as the corresponding arguments of BOBYQB. */
2769  /* DELTA is the trust region radius for the present calculation, which */
2770  /* seeks a small value of the quadratic model within distance DELTA of */
2771  /* XOPT subject to the bounds on the variables. */
2772  /* XNEW will be set to a new vector of variables that is approximately */
2773  /* the one that minimizes the quadratic model within the trust region */
2774  /* subject to the SL and SU constraints on the variables. It satisfies */
2775  /* as equations the bounds that become active during the calculation. */
2776  /* D is the calculated trial step from XOPT, generated iteratively from an */
2777  /* initial value of zero. Thus XNEW is XOPT+D after the final iteration. */
2778  /* GNEW holds the gradient of the quadratic model at XOPT+D. It is updated */
2779  /* when D is updated. */
2780  /* XBDI is a working space vector. For I=1,2,...,N, the element XBDI(I) is */
2781  /* set to -1.0, 0.0, or 1.0, the value being nonzero if and only if the */
2782  /* I-th variable has become fixed at a bound, the bound being SL(I) or */
2783  /* SU(I) in the case XBDI(I)=-1.0 or XBDI(I)=1.0, respectively. This */
2784  /* information is accumulated during the construction of XNEW. */
2785  /* The arrays S, HS and HRED are also used for working space. They hold the */
2786  /* current search direction, and the changes in the gradient of Q along S */
2787  /* and the reduced D, respectively, where the reduced D is the same as D, */
2788  /* except that the components of the fixed variables are zero. */
2789  /* DSQ will be set to the square of the length of XNEW-XOPT. */
2790  /* CRVMIN is set to zero if D reaches the trust region boundary. Otherwise */
2791  /* it is set to the least curvature of H that occurs in the conjugate */
2792  /* gradient searches that are not restricted by any constraints. The */
2793  /* value CRVMIN=-1.0D0 is set, however, if all of these searches are */
2794  /* constrained. */
2795 
2796  /* A version of the truncated conjugate gradient is applied. If a line */
2797  /* search is restricted by a constraint, then the procedure is restarted, */
2798  /* the values of the variables that are at their bounds being fixed. If */
2799  /* the trust region boundary is reached, then further changes may be made */
2800  /* to D, each one being in the two dimensional space that is spanned */
2801  /* by the current D and the gradient of Q at XOPT+D, staying on the trust */
2802  /* region boundary. Termination occurs when the reduction in Q seems to */
2803  /* be close to the greatest reduction that can be achieved. */
2804 
2805  /* Set some constants. */
2806 
2807  /* Parameter adjustments */
2808  xpt_dim1 = npt;
2809  xpt_offset = 1 + xpt_dim1;
2810  xpt -= xpt_offset;
2811  --xopt;
2812  --gopt;
2813  --hq;
2814  --pq;
2815  --sl;
2816  --su;
2817  --xnew;
2818  --d__;
2819  --gnew;
2820  --xbdi;
2821  --s;
2822  --hs;
2823  --hred;
2824 
2825  /* Function Body */
2826  half = .5;
2827  one = 1.;
2828  onemin = -1.;
2829  zero = 0.;
2830 
2831  /* The sign of GOPT(I) gives the sign of the change to the I-th variable */
2832  /* that will reduce Q from its value at XOPT. Thus XBDI(I) shows whether */
2833  /* or not to fix the I-th variable at one of its bounds initially, with */
2834  /* NACT being set to the number of fixed variables. D and GNEW are also */
2835  /* set for the first iteration. DELSQ is the upper bound on the sum of */
2836  /* squares of the free variables. QRED is the reduction in Q so far. */
2837 
2838  iterc = 0;
2839  nact = 0;
2840  i__1 = m_SpaceDimension;
2841  for (i__ = 1; i__ <= i__1; ++i__) {
2842  xbdi[i__] = zero;
2843  if (xopt[i__] <= sl[i__]) {
2844  if (gopt[i__] >= zero) {
2845  xbdi[i__] = onemin;
2846  }
2847  } else if (xopt[i__] >= su[i__]) {
2848  if (gopt[i__] <= zero) {
2849  xbdi[i__] = one;
2850  }
2851  }
2852  if (xbdi[i__] != zero) {
2853  ++nact;
2854  }
2855  d__[i__] = zero;
2856  /* L10: */
2857  gnew[i__] = gopt[i__];
2858  }
2859  delsq = *delta * *delta;
2860  qred = zero;
2861  *crvmin = onemin;
2862 
2863  /* Set the next search direction of the conjugate gradient method. It is */
2864  /* the steepest descent direction initially and when the iterations are */
2865  /* restarted because a variable has just been fixed by a bound, and of */
2866  /* course the components of the fixed variables are zero. ITERMAX is an */
2867  /* upper bound on the indices of the conjugate gradient iterations. */
2868 
2869 L20:
2870  beta = zero;
2871 L30:
2872  stepsq = zero;
2873  i__1 = m_SpaceDimension;
2874  for (i__ = 1; i__ <= i__1; ++i__) {
2875  if (xbdi[i__] != zero) {
2876  s[i__] = zero;
2877  } else if (beta == zero) {
2878  s[i__] = -gnew[i__];
2879  } else {
2880  s[i__] = beta * s[i__] - gnew[i__];
2881  }
2882  /* L40: */
2883  /* Computing 2nd power */
2884  d__1 = s[i__];
2885  stepsq += d__1 * d__1;
2886  }
2887  if (stepsq == zero) {
2888  goto L190;
2889  }
2890  if (beta == zero) {
2891  gredsq = stepsq;
2892  itermax = iterc + m_SpaceDimension - nact;
2893  }
2894  if (gredsq * delsq <= qred * 1e-4 * qred) {
2895  goto L190;
2896  }
2897 
2898  /* Multiply the search direction by the second derivative matrix of Q and */
2899  /* calculate some scalars for the choice of steplength. Then set BLEN to */
2900  /* the length of the the step to the trust region boundary and STPLEN to */
2901  /* the steplength, ignoring the simple bounds. */
2902 
2903  goto L210;
2904 L50:
2905  resid = delsq;
2906  ds = zero;
2907  shs = zero;
2908  i__1 = m_SpaceDimension;
2909  for (i__ = 1; i__ <= i__1; ++i__) {
2910  if (xbdi[i__] == zero) {
2911  /* Computing 2nd power */
2912  d__1 = d__[i__];
2913  resid -= d__1 * d__1;
2914  ds += s[i__] * d__[i__];
2915  shs += s[i__] * hs[i__];
2916  }
2917  /* L60: */
2918  }
2919  if (resid <= zero) {
2920  goto L90;
2921  }
2922  temp = std::sqrt(stepsq * resid + ds * ds);
2923  if (ds < zero) {
2924  blen = (temp - ds) / stepsq;
2925  } else {
2926  blen = resid / (temp + ds);
2927  }
2928  stplen = blen;
2929  if (shs > zero) {
2930  /* Computing MIN */
2931  d__1 = blen, d__2 = gredsq / shs;
2932  stplen = std::min(d__1,d__2);
2933  }
2934 
2935  /* Reduce STPLEN if necessary in order to preserve the simple bounds, */
2936  /* letting IACT be the index of the new constrained variable. */
2937 
2938  iact = 0;
2939  i__1 = m_SpaceDimension;
2940  for (i__ = 1; i__ <= i__1; ++i__) {
2941  if (s[i__] != zero) {
2942  xsum = xopt[i__] + d__[i__];
2943  if (s[i__] > zero) {
2944  temp = (su[i__] - xsum) / s[i__];
2945  } else {
2946  temp = (sl[i__] - xsum) / s[i__];
2947  }
2948  if (temp < stplen) {
2949  stplen = temp;
2950  iact = i__;
2951  }
2952  }
2953  /* L70: */
2954  }
2955 
2956  /* Update CRVMIN, GNEW and D. Set SDEC to the decrease that occurs in Q. */
2957 
2958  sdec = zero;
2959  if (stplen > zero) {
2960  ++iterc;
2961  temp = shs / stepsq;
2962  if (iact == 0 && temp > zero) {
2963  *crvmin = std::min(*crvmin,temp);
2964  if (*crvmin == onemin) {
2965  *crvmin = temp;
2966  }
2967  }
2968  ggsav = gredsq;
2969  gredsq = zero;
2970  i__1 = m_SpaceDimension;
2971  for (i__ = 1; i__ <= i__1; ++i__) {
2972  gnew[i__] += stplen * hs[i__];
2973  if (xbdi[i__] == zero) {
2974  /* Computing 2nd power */
2975  d__1 = gnew[i__];
2976  gredsq += d__1 * d__1;
2977  }
2978  /* L80: */
2979  d__[i__] += stplen * s[i__];
2980  }
2981  /* Computing MAX */
2982  d__1 = stplen * (ggsav - half * stplen * shs);
2983  sdec = std::max(d__1,zero);
2984  qred += sdec;
2985  }
2986 
2987  /* Restart the conjugate gradient method if it has hit a new bound. */
2988 
2989  if (iact > 0) {
2990  ++nact;
2991  xbdi[iact] = one;
2992  if (s[iact] < zero) {
2993  xbdi[iact] = onemin;
2994  }
2995  /* Computing 2nd power */
2996  d__1 = d__[iact];
2997  delsq -= d__1 * d__1;
2998  if (delsq <= zero) {
2999  goto L90;
3000  }
3001  goto L20;
3002  }
3003 
3004  /* If STPLEN is less than BLEN, then either apply another conjugate */
3005  /* gradient iteration or RETURN. */
3006 
3007  if (stplen < blen) {
3008  if (iterc == itermax) {
3009  goto L190;
3010  }
3011  if (sdec <= qred * .01) {
3012  goto L190;
3013  }
3014  beta = gredsq / ggsav;
3015  goto L30;
3016  }
3017 L90:
3018  *crvmin = zero;
3019 
3020  /* Prepare for the alternative iteration by calculating some scalars */
3021  /* and by multiplying the reduced D by the second derivative matrix of */
3022  /* Q, where S holds the reduced D in the call of GGMULT. */
3023 
3024 L100:
3025  if (nact >= m_SpaceDimension - 1) {
3026  goto L190;
3027  }
3028  dredsq = zero;
3029  dredg = zero;
3030  gredsq = zero;
3031  i__1 = m_SpaceDimension;
3032  for (i__ = 1; i__ <= i__1; ++i__) {
3033  if (xbdi[i__] == zero) {
3034  /* Computing 2nd power */
3035  d__1 = d__[i__];
3036  dredsq += d__1 * d__1;
3037  dredg += d__[i__] * gnew[i__];
3038  /* Computing 2nd power */
3039  d__1 = gnew[i__];
3040  gredsq += d__1 * d__1;
3041  s[i__] = d__[i__];
3042  } else {
3043  s[i__] = zero;
3044  }
3045  /* L110: */
3046  }
3047  itcsav = iterc;
3048  goto L210;
3049 
3050  /* Let the search direction S be a linear combination of the reduced D */
3051  /* and the reduced G that is orthogonal to the reduced D. */
3052 
3053 L120:
3054  ++iterc;
3055  temp = gredsq * dredsq - dredg * dredg;
3056  if (temp <= qred * 1e-4 * qred) {
3057  goto L190;
3058  }
3059  temp = std::sqrt(temp);
3060  i__1 = m_SpaceDimension;
3061  for (i__ = 1; i__ <= i__1; ++i__) {
3062  if (xbdi[i__] == zero) {
3063  s[i__] = (dredg * d__[i__] - dredsq * gnew[i__]) / temp;
3064  } else {
3065  s[i__] = zero;
3066  }
3067  /* L130: */
3068  }
3069  sredg = -temp;
3070 
3071  /* By considering the simple bounds on the variables, calculate an upper */
3072  /* bound on the tangent of half the angle of the alternative iteration, */
3073  /* namely ANGBD, except that, if already a free variable has reached a */
3074  /* bound, there is a branch back to label 100 after fixing that variable. */
3075 
3076  angbd = one;
3077  iact = 0;
3078  i__1 = m_SpaceDimension;
3079  for (i__ = 1; i__ <= i__1; ++i__) {
3080  if (xbdi[i__] == zero) {
3081  tempa = xopt[i__] + d__[i__] - sl[i__];
3082  tempb = su[i__] - xopt[i__] - d__[i__];
3083  if (tempa <= zero) {
3084  ++nact;
3085  xbdi[i__] = onemin;
3086  goto L100;
3087  } else if (tempb <= zero) {
3088  ++nact;
3089  xbdi[i__] = one;
3090  goto L100;
3091  }
3092  /* Computing 2nd power */
3093  d__1 = d__[i__];
3094  /* Computing 2nd power */
3095  d__2 = s[i__];
3096  ssq = d__1 * d__1 + d__2 * d__2;
3097  /* Computing 2nd power */
3098  d__1 = xopt[i__] - sl[i__];
3099  temp = ssq - d__1 * d__1;
3100  if (temp > zero) {
3101  temp = std::sqrt(temp) - s[i__];
3102  if (angbd * temp > tempa) {
3103  angbd = tempa / temp;
3104  iact = i__;
3105  xsav = onemin;
3106  }
3107  }
3108  /* Computing 2nd power */
3109  d__1 = su[i__] - xopt[i__];
3110  temp = ssq - d__1 * d__1;
3111  if (temp > zero) {
3112  temp = std::sqrt(temp) + s[i__];
3113  if (angbd * temp > tempb) {
3114  angbd = tempb / temp;
3115  iact = i__;
3116  xsav = one;
3117  }
3118  }
3119  }
3120  /* L140: */
3121  }
3122 
3123  /* Calculate HHD and some curvatures for the alternative iteration. */
3124 
3125  goto L210;
3126 L150:
3127  shs = zero;
3128  dhs = zero;
3129  dhd = zero;
3130  i__1 = m_SpaceDimension;
3131  for (i__ = 1; i__ <= i__1; ++i__) {
3132  if (xbdi[i__] == zero) {
3133  shs += s[i__] * hs[i__];
3134  dhs += d__[i__] * hs[i__];
3135  dhd += d__[i__] * hred[i__];
3136  }
3137  /* L160: */
3138  }
3139 
3140  /* Seek the greatest reduction in Q for a range of equally spaced values */
3141  /* of ANGT in [0,ANGBD], where ANGT is the tangent of half the angle of */
3142  /* the alternative iteration. */
3143 
3144  redmax = zero;
3145  isav = 0;
3146  redsav = zero;
3147  iu = (long int) (angbd * 17. + 3.1);
3148  i__1 = iu;
3149  for (i__ = 1; i__ <= i__1; ++i__) {
3150  angt = angbd * (double) i__ / (double) iu;
3151  sth = (angt + angt) / (one + angt * angt);
3152  temp = shs + angt * (angt * dhd - dhs - dhs);
3153  rednew = sth * (angt * dredg - sredg - half * sth * temp);
3154  if (rednew > redmax) {
3155  redmax = rednew;
3156  isav = i__;
3157  rdprev = redsav;
3158  } else if (i__ == isav + 1) {
3159  rdnext = rednew;
3160  }
3161  /* L170: */
3162  redsav = rednew;
3163  }
3164 
3165  /* Return if the reduction is zero. Otherwise, set the sine and cosine */
3166  /* of the angle of the alternative iteration, and calculate SDEC. */
3167 
3168  if (isav == 0) {
3169  goto L190;
3170  }
3171  if (isav < iu) {
3172  temp = (rdnext - rdprev) / (redmax + redmax - rdprev - rdnext);
3173  angt = angbd * ((double) isav + half * temp) / (double) iu;
3174  }
3175  cth = (one - angt * angt) / (one + angt * angt);
3176  sth = (angt + angt) / (one + angt * angt);
3177  temp = shs + angt * (angt * dhd - dhs - dhs);
3178  sdec = sth * (angt * dredg - sredg - half * sth * temp);
3179  if (sdec <= zero) {
3180  goto L190;
3181  }
3182 
3183  /* Update GNEW, D and HRED. If the angle of the alternative iteration */
3184  /* is restricted by a bound on a free variable, that variable is fixed */
3185  /* at the bound. */
3186 
3187  dredg = zero;
3188  gredsq = zero;
3189  i__1 = m_SpaceDimension;
3190  for (i__ = 1; i__ <= i__1; ++i__) {
3191  gnew[i__] = gnew[i__] + (cth - one) * hred[i__] + sth * hs[i__];
3192  if (xbdi[i__] == zero) {
3193  d__[i__] = cth * d__[i__] + sth * s[i__];
3194  dredg += d__[i__] * gnew[i__];
3195  /* Computing 2nd power */
3196  d__1 = gnew[i__];
3197  gredsq += d__1 * d__1;
3198  }
3199  /* L180: */
3200  hred[i__] = cth * hred[i__] + sth * hs[i__];
3201  }
3202  qred += sdec;
3203  if (iact > 0 && isav == iu) {
3204  ++nact;
3205  xbdi[iact] = xsav;
3206  goto L100;
3207  }
3208 
3209  /* If SDEC is sufficiently small, then RETURN after setting XNEW to */
3210  /* XOPT+D, giving careful attention to the bounds. */
3211 
3212  if (sdec > qred * .01) {
3213  goto L120;
3214  }
3215 L190:
3216  *dsq = zero;
3217  i__1 = m_SpaceDimension;
3218  for (i__ = 1; i__ <= i__1; ++i__) {
3219  /* Computing MAX */
3220  /* Computing MIN */
3221  d__3 = xopt[i__] + d__[i__], d__4 = su[i__];
3222  d__1 = std::min(d__3,d__4), d__2 = sl[i__];
3223  xnew[i__] = std::max(d__1,d__2);
3224  if (xbdi[i__] == onemin) {
3225  xnew[i__] = sl[i__];
3226  }
3227  if (xbdi[i__] == one) {
3228  xnew[i__] = su[i__];
3229  }
3230  d__[i__] = xnew[i__] - xopt[i__];
3231  /* L200: */
3232  /* Computing 2nd power */
3233  d__1 = d__[i__];
3234  *dsq += d__1 * d__1;
3235  }
3236  return 0;
3237  /* The following instructions multiply the current S-vector by the second */
3238  /* derivative matrix of the quadratic model, putting the product in HS. */
3239  /* They are reached from three different parts of the software above and */
3240  /* they can be regarded as an external subroutine. */
3241 
3242 L210:
3243  ih = 0;
3244  i__1 = m_SpaceDimension;
3245  for (j = 1; j <= i__1; ++j) {
3246  hs[j] = zero;
3247  i__2 = j;
3248  for (i__ = 1; i__ <= i__2; ++i__) {
3249  ++ih;
3250  if (i__ < j) {
3251  hs[j] += hq[ih] * s[i__];
3252  }
3253  /* L220: */
3254  hs[i__] += hq[ih] * s[j];
3255  }
3256  }
3257  i__2 = npt;
3258  for (k = 1; k <= i__2; ++k) {
3259  if (pq[k] != zero) {
3260  temp = zero;
3261  i__1 = m_SpaceDimension;
3262  for (j = 1; j <= i__1; ++j) {
3263  /* L230: */
3264  temp += xpt[k + j * xpt_dim1] * s[j];
3265  }
3266  temp *= pq[k];
3267  i__1 = m_SpaceDimension;
3268  for (i__ = 1; i__ <= i__1; ++i__) {
3269  /* L240: */
3270  hs[i__] += temp * xpt[k + i__ * xpt_dim1];
3271  }
3272  }
3273  /* L250: */
3274  }
3275  if (*crvmin != zero) {
3276  goto L50;
3277  }
3278  if (iterc > itcsav) {
3279  goto L150;
3280  }
3281  i__2 = m_SpaceDimension;
3282  for (i__ = 1; i__ <= i__2; ++i__) {
3283  /* L260: */
3284  hred[i__] = hs[i__];
3285  }
3286  goto L120;
3287 } /* trsbox_ */
3288 
3289 int BobyqaOptimizer::update_(long int &npt, double *bmat,
3290  double *zmat, long int &ndim, double *vlag, double *beta,
3291  double *denom, long int &knew, double *w)
3292 {
3293  /* System generated locals */
3294  long int bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2;
3295  double d__1, d__2, d__3;
3296 
3297  /* Local variables */
3298  long int i__, j, k, jp;
3299  double one, tau, temp;
3300  long int nptm;
3301  double zero, alpha, tempa, tempb, ztest;
3302 
3303 
3304  /* The arrays BMAT and ZMAT are updated, as required by the new position */
3305  /* of the interpolation point that has the index KNEW. The vector VLAG has */
3306  /* N+NPT components, set on entry to the first NPT and last N components */
3307  /* of the product Hw in equation (4.11) of the Powell (2006) paper on */
3308  /* NEWUOA. Further, BETA is set on entry to the value of the parameter */
3309  /* with that name, and DENOM is set to the denominator of the updating */
3310  /* formula. Elements of ZMAT may be treated as zero if their moduli are */
3311  /* at most ZTEST. The first NDIM elements of W are used for working space. */
3312 
3313  /* Set some constants. */
3314 
3315  /* Parameter adjustments */
3316  zmat_dim1 = npt;
3317  zmat_offset = 1 + zmat_dim1;
3318  zmat -= zmat_offset;
3319  bmat_dim1 = ndim;
3320  bmat_offset = 1 + bmat_dim1;
3321  bmat -= bmat_offset;
3322  --vlag;
3323  --w;
3324 
3325  /* Function Body */
3326  one = 1.;
3327  zero = 0.;
3328  nptm = npt - m_SpaceDimension - 1;
3329  ztest = zero;
3330  i__1 = npt;
3331  for (k = 1; k <= i__1; ++k) {
3332  i__2 = nptm;
3333  for (j = 1; j <= i__2; ++j) {
3334  /* L10: */
3335  /* Computing MAX */
3336  d__2 = ztest, d__3 = (d__1 = zmat[k + j * zmat_dim1], std::abs(d__1));
3337  ztest = std::max(d__2,d__3);
3338  }
3339  }
3340  ztest *= 1e-20;
3341 
3342  /* Apply the rotations that put zeros in the KNEW-th row of ZMAT. */
3343  i__2 = nptm;
3344  for (j = 2; j <= i__2; ++j) {
3345  if ((d__1 = zmat[knew + j * zmat_dim1], std::abs(d__1)) > ztest) {
3346  /* Computing 2nd power */
3347  d__1 = zmat[knew + zmat_dim1];
3348  /* Computing 2nd power */
3349  d__2 = zmat[knew + j * zmat_dim1];
3350  temp = std::sqrt(d__1 * d__1 + d__2 * d__2);
3351  tempa = zmat[knew + zmat_dim1] / temp;
3352  tempb = zmat[knew + j * zmat_dim1] / temp;
3353  i__1 = npt;
3354  for (i__ = 1; i__ <= i__1; ++i__) {
3355  temp = tempa * zmat[i__ + zmat_dim1] + tempb * zmat[i__ + j *
3356  zmat_dim1];
3357  zmat[i__ + j * zmat_dim1] = tempa * zmat[i__ + j * zmat_dim1]
3358  - tempb * zmat[i__ + zmat_dim1];
3359  /* L20: */
3360  zmat[i__ + zmat_dim1] = temp;
3361  }
3362  }
3363  zmat[knew + j * zmat_dim1] = zero;
3364  /* L30: */
3365  }
3366 
3367  /* Put the first NPT components of the KNEW-th column of HLAG into W, */
3368  /* and calculate the parameters of the updating formula. */
3369 
3370  i__2 = npt;
3371  for (i__ = 1; i__ <= i__2; ++i__) {
3372  w[i__] = zmat[knew + zmat_dim1] * zmat[i__ + zmat_dim1];
3373  /* L40: */
3374  }
3375  alpha = w[knew];
3376  tau = vlag[knew];
3377  vlag[knew] -= one;
3378 
3379  /* Complete the updating of ZMAT. */
3380 
3381  temp = std::sqrt(*denom);
3382  tempb = zmat[knew + zmat_dim1] / temp;
3383  tempa = tau / temp;
3384  i__2 = npt;
3385  for (i__ = 1; i__ <= i__2; ++i__) {
3386  /* L50: */
3387  zmat[i__ + zmat_dim1] = tempa * zmat[i__ + zmat_dim1] - tempb * vlag[
3388  i__];
3389  }
3390 
3391  /* Finally, update the matrix BMAT. */
3392 
3393  i__2 = m_SpaceDimension;
3394  for (j = 1; j <= i__2; ++j) {
3395  jp = npt + j;
3396  w[jp] = bmat[knew + j * bmat_dim1];
3397  tempa = (alpha * vlag[jp] - tau * w[jp]) / *denom;
3398  tempb = (-(*beta) * w[jp] - tau * vlag[jp]) / *denom;
3399  i__1 = jp;
3400  for (i__ = 1; i__ <= i__1; ++i__) {
3401  bmat[i__ + j * bmat_dim1] = bmat[i__ + j * bmat_dim1] + tempa *
3402  vlag[i__] + tempb * w[i__];
3403  if (i__ > npt) {
3404  bmat[jp + (i__ - npt) * bmat_dim1] = bmat[i__ + j *
3405  bmat_dim1];
3406  }
3407  /* L60: */
3408  }
3409  }
3410  return 0;
3411 } /* update_ */
3412 
3413 } // end of namespace anima
int update_(long int &npt, double *bmat, double *zmat, long int &ndim, double *vlag, double *beta, double *denom, long int &knew, double *w)
int bobyqb_(long int &npt, double *x, double *xl, double *xu, double &rhobeg, double &rhoend, long int &maxfun, double *xbase, double *xpt, double *fval, double *xopt, double *gopt, double *hq, double *pq, double *bmat, double *zmat, long int &ndim, double *sl, double *su, double *xnew, double *xalt, double *d__, double *vlag, double *w)
int trsbox_(long int &npt, double *xpt, double *xopt, double *gopt, double *hq, double *pq, double *sl, double *su, double *delta, double *xnew, double *d__, double *gnew, double *xbdi, double *s, double *hs, double *hred, double *dsq, double *crvmin)
int altmov_(long int &npt, double *xpt, double *xopt, double *bmat, double *zmat, long int &ndim, double *sl, double *su, long int &kopt, long int &knew, double *adelt, double *xnew, double *xalt, double *alpha, double *cauchy, double *glag, double *hcol, double *w)
const std::string GetStopConditionDescription() const ITK_OVERRIDE
itk::SingleValuedNonLinearOptimizer::ParametersType ParametersType
void StartOptimization() ITK_OVERRIDE
int prelim_(long int &npt, double *x, double *xl, double *xu, double &rhobeg, long int &maxfun, double *xbase, double *xpt, double *fval, double *gopt, double *hq, double *pq, double *bmat, double *zmat, long int &ndim, double *sl, double *su, long int &nf, long int &kopt)
BobyqaOptimizer::ParametersType px
int rescue_(long int &npt, double *xl, double *xu, long int &maxfun, double *xbase, double *xpt, double *fval, double *xopt, double *gopt, double *hq, double *pq, double *bmat, double *zmat, long int &ndim, double *sl, double *su, long int &nf, double *delta, long int &kopt, double *vlag, double *ptsaux, double *ptsid, double *w)
void PrintSelf(std::ostream &os, itk::Indent indent) const ITK_OVERRIDE
std::ostringstream m_StopConditionDescription
int optimize(long int &npt, double *x, double *xl, double *xu, double &rhobeg, double &rhoend, long int &maxfun, double *w)