1 /* BOBYQA derivative-free optimization code by M. J. D. Powell.
2 Original Fortran code by Powell (2009). Converted via v2c,
3 cleaned up, and incorporated into NLopt by S. G. Johnson (2009).
12 #define min(a,b) ((a) <= (b) ? (a) : (b))
13 #define max(a,b) ((a) >= (b) ? (a) : (b))
14 #define iabs(x) ((x) < 0 ? -(x) : (x))
16 static void update_(int *n, int *npt, double *bmat,
17 double *zmat, int *ndim, double *vlag, double *beta,
18 double *denom, int *knew, double *w)
20 /* System generated locals */
21 int bmat_dim1, bmat_offset, zmat_dim1, zmat_offset, i__1, i__2;
22 double d__1, d__2, d__3;
25 int i__, j, k, jl, jp;
26 double one, tau, temp;
28 double zero, alpha, tempa, tempb, ztest;
31 /* The arrays BMAT and ZMAT are updated, as required by the new position */
32 /* of the interpolation point that has the index KNEW. The vector VLAG has */
33 /* N+NPT components, set on entry to the first NPT and last N components */
34 /* of the product Hw in equation (4.11) of the Powell (2006) paper on */
35 /* NEWUOA. Further, BETA is set on entry to the value of the parameter */
36 /* with that name, and DENOM is set to the denominator of the updating */
37 /* formula. Elements of ZMAT may be treated as zero if their moduli are */
38 /* at most ZTEST. The first NDIM elements of W are used for working space. */
40 /* Set some constants. */
42 /* Parameter adjustments */
44 zmat_offset = 1 + zmat_dim1;
47 bmat_offset = 1 + bmat_dim1;
58 for (k = 1; k <= i__1; ++k) {
60 for (j = 1; j <= i__2; ++j) {
63 d__2 = ztest, d__3 = (d__1 = zmat[k + j * zmat_dim1], fabs(d__1));
64 ztest = max(d__2,d__3);
69 /* Apply the rotations that put zeros in the KNEW-th row of ZMAT. */
73 for (j = 2; j <= i__2; ++j) {
74 if ((d__1 = zmat[*knew + j * zmat_dim1], fabs(d__1)) > ztest) {
75 /* Computing 2nd power */
76 d__1 = zmat[*knew + zmat_dim1];
77 /* Computing 2nd power */
78 d__2 = zmat[*knew + j * zmat_dim1];
79 temp = sqrt(d__1 * d__1 + d__2 * d__2);
80 tempa = zmat[*knew + zmat_dim1] / temp;
81 tempb = zmat[*knew + j * zmat_dim1] / temp;
83 for (i__ = 1; i__ <= i__1; ++i__) {
84 temp = tempa * zmat[i__ + zmat_dim1] + tempb * zmat[i__ + j *
86 zmat[i__ + j * zmat_dim1] = tempa * zmat[i__ + j * zmat_dim1]
87 - tempb * zmat[i__ + zmat_dim1];
89 zmat[i__ + zmat_dim1] = temp;
92 zmat[*knew + j * zmat_dim1] = zero;
96 /* Put the first NPT components of the KNEW-th column of HLAG into W, */
97 /* and calculate the parameters of the updating formula. */
100 for (i__ = 1; i__ <= i__2; ++i__) {
101 w[i__] = zmat[*knew + zmat_dim1] * zmat[i__ + zmat_dim1];
108 /* Complete the updating of ZMAT. */
111 tempb = zmat[*knew + zmat_dim1] / temp;
114 for (i__ = 1; i__ <= i__2; ++i__) {
116 zmat[i__ + zmat_dim1] = tempa * zmat[i__ + zmat_dim1] - tempb * vlag[
120 /* Finally, update the matrix BMAT. */
123 for (j = 1; j <= i__2; ++j) {
125 w[jp] = bmat[*knew + j * bmat_dim1];
126 tempa = (alpha * vlag[jp] - tau * w[jp]) / *denom;
127 tempb = (-(*beta) * w[jp] - tau * vlag[jp]) / *denom;
129 for (i__ = 1; i__ <= i__1; ++i__) {
130 bmat[i__ + j * bmat_dim1] = bmat[i__ + j * bmat_dim1] + tempa *
131 vlag[i__] + tempb * w[i__];
133 bmat[jp + (i__ - *npt) * bmat_dim1] = bmat[i__ + j *
141 static nlopt_result rescue_(int *n, int *npt, const double *xl, const double *xu,
143 nlopt_stopping *stop,
144 bobyqa_func calfun, void *calfun_data,
145 double *xbase, double *xpt, double *fval, double *xopt, double *gopt,
146 double *hq, double *pq, double *bmat, double *zmat,
147 int *ndim, double *sl, double *su, /* int *nf, */
148 double *delta, int *kopt, double *vlag, double *
149 ptsaux, double *ptsid, double *w)
151 /* System generated locals */
152 int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1,
153 zmat_offset, i__1, i__2, i__3;
154 double d__1, d__2, d__3, d__4;
156 /* Local variables */
158 int i__, j, k, ih, jp, ip, iq, np, iw;
163 double sum, diff, half, beta;
169 double zero, hdiag, fbase, sfrac, denom, vquad, sumpq;
170 double dsqmin, distsq, vlmxsq;
173 /* The arguments N, NPT, XL, XU, MAXFUN, XBASE, XPT, FVAL, XOPT, */
174 /* GOPT, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU have the same meanings as */
175 /* the corresponding arguments of BOBYQB on the entry to RESCUE. */
176 /* NF is maintained as the number of calls of CALFUN so far, except that */
177 /* NF is set to -1 if the value of MAXFUN prevents further progress. */
178 /* KOPT is maintained so that FVAL(KOPT) is the least calculated function */
179 /* value. Its correct value must be given on entry. It is updated if a */
180 /* new least function value is found, but the corresponding changes to */
181 /* XOPT and GOPT have to be made later by the calling program. */
182 /* DELTA is the current trust region radius. */
183 /* VLAG is a working space vector that will be used for the values of the */
184 /* provisional Lagrange functions at each of the interpolation points. */
185 /* They are part of a product that requires VLAG to be of length NDIM. */
186 /* PTSAUX is also a working space array. For J=1,2,...,N, PTSAUX(1,J) and */
187 /* PTSAUX(2,J) specify the two positions of provisional interpolation */
188 /* points when a nonzero step is taken along e_J (the J-th coordinate */
189 /* direction) through XBASE+XOPT, as specified below. Usually these */
190 /* steps have length DELTA, but other lengths are chosen if necessary */
191 /* in order to satisfy the given bounds on the variables. */
192 /* PTSID is also a working space array. It has NPT components that denote */
193 /* provisional new positions of the original interpolation points, in */
194 /* case changes are needed to restore the linear independence of the */
195 /* interpolation conditions. The K-th point is a candidate for change */
196 /* if and only if PTSID(K) is nonzero. In this case let p and q be the */
197 /* int parts of PTSID(K) and (PTSID(K)-p) multiplied by N+1. If p */
198 /* and q are both positive, the step from XBASE+XOPT to the new K-th */
199 /* interpolation point is PTSAUX(1,p)*e_p + PTSAUX(1,q)*e_q. Otherwise */
200 /* the step is PTSAUX(1,p)*e_p or PTSAUX(2,q)*e_q in the cases q=0 or */
201 /* p=0, respectively. */
202 /* The first NDIM+NPT elements of the array W are used for working space. */
203 /* The final elements of BMAT and ZMAT are set in a well-conditioned way */
204 /* to the values that are appropriate for the new interpolation points. */
205 /* The elements of GOPT, HQ and PQ are also revised to the values that are */
206 /* appropriate to the final quadratic model. */
208 /* Set some constants. */
210 /* Parameter adjustments */
212 zmat_offset = 1 + zmat_dim1;
215 xpt_offset = 1 + xpt_dim1;
226 bmat_offset = 1 + bmat_dim1;
240 sfrac = half / (double) np;
243 /* Shift the interpolation points so that XOPT becomes the origin, and set */
244 /* the elements of ZMAT to zero. The value of SUMPQ is required in the */
245 /* updating of HQ below. The squares of the distances from XOPT to the */
246 /* other interpolation points are set at the end of W. Increments of WINC */
247 /* may be added later to these squares to balance the consideration of */
248 /* the choice of point that is going to become current. */
253 for (k = 1; k <= i__1; ++k) {
256 for (j = 1; j <= i__2; ++j) {
257 xpt[k + j * xpt_dim1] -= xopt[j];
259 /* Computing 2nd power */
260 d__1 = xpt[k + j * xpt_dim1];
261 distsq += d__1 * d__1;
264 w[*ndim + k] = distsq;
265 winc = max(winc,distsq);
267 for (j = 1; j <= i__2; ++j) {
269 zmat[k + j * zmat_dim1] = zero;
273 /* Update HQ so that HQ and PQ define the second derivatives of the model */
274 /* after XBASE has been shifted to the trust region centre. */
278 for (j = 1; j <= i__2; ++j) {
279 w[j] = half * sumpq * xopt[j];
281 for (k = 1; k <= i__1; ++k) {
283 w[j] += pq[k] * xpt[k + j * xpt_dim1];
286 for (i__ = 1; i__ <= i__1; ++i__) {
289 hq[ih] = hq[ih] + w[i__] * xopt[j] + w[j] * xopt[i__];
293 /* Shift XBASE, SL, SU and XOPT. Set the elements of BMAT to zero, and */
294 /* also set the elements of PTSAUX. */
297 for (j = 1; j <= i__1; ++j) {
303 d__1 = *delta, d__2 = su[j];
304 ptsaux[(j << 1) + 1] = min(d__1,d__2);
306 d__1 = -(*delta), d__2 = sl[j];
307 ptsaux[(j << 1) + 2] = max(d__1,d__2);
308 if (ptsaux[(j << 1) + 1] + ptsaux[(j << 1) + 2] < zero) {
309 temp = ptsaux[(j << 1) + 1];
310 ptsaux[(j << 1) + 1] = ptsaux[(j << 1) + 2];
311 ptsaux[(j << 1) + 2] = temp;
313 if ((d__2 = ptsaux[(j << 1) + 2], fabs(d__2)) < half * (d__1 = ptsaux[(
314 j << 1) + 1], fabs(d__1))) {
315 ptsaux[(j << 1) + 2] = half * ptsaux[(j << 1) + 1];
318 for (i__ = 1; i__ <= i__2; ++i__) {
320 bmat[i__ + j * bmat_dim1] = zero;
325 /* Set the identifiers of the artificial interpolation points that are */
326 /* along a coordinate direction from XOPT, and set the corresponding */
327 /* nonzero elements of BMAT and ZMAT. */
331 for (j = 1; j <= i__2; ++j) {
334 ptsid[jp] = (double) j + sfrac;
336 ptsid[jpn] = (double) j / (double) np + sfrac;
337 temp = one / (ptsaux[(j << 1) + 1] - ptsaux[(j << 1) + 2]);
338 bmat[jp + j * bmat_dim1] = -temp + one / ptsaux[(j << 1) + 1];
339 bmat[jpn + j * bmat_dim1] = temp + one / ptsaux[(j << 1) + 2];
340 bmat[j * bmat_dim1 + 1] = -bmat[jp + j * bmat_dim1] - bmat[jpn +
342 zmat[j * zmat_dim1 + 1] = sqrt(2.) / (d__1 = ptsaux[(j << 1) + 1]
343 * ptsaux[(j << 1) + 2], fabs(d__1));
344 zmat[jp + j * zmat_dim1] = zmat[j * zmat_dim1 + 1] * ptsaux[(j <<
346 zmat[jpn + j * zmat_dim1] = -zmat[j * zmat_dim1 + 1] * ptsaux[(j
349 bmat[j * bmat_dim1 + 1] = -one / ptsaux[(j << 1) + 1];
350 bmat[jp + j * bmat_dim1] = one / ptsaux[(j << 1) + 1];
351 /* Computing 2nd power */
352 d__1 = ptsaux[(j << 1) + 1];
353 bmat[j + *npt + j * bmat_dim1] = -half * (d__1 * d__1);
358 /* Set any remaining identifiers with their nonzero elements of ZMAT. */
360 if (*npt >= *n + np) {
362 for (k = np << 1; k <= i__2; ++k) {
363 iw = (int) (((double) (k - np) - half) / (double) (*n)
365 ip = k - np - iw * *n;
370 ptsid[k] = (double) ip + (double) iq / (double) np +
372 temp = one / (ptsaux[(ip << 1) + 1] * ptsaux[(iq << 1) + 1]);
373 zmat[(k - np) * zmat_dim1 + 1] = temp;
374 zmat[ip + 1 + (k - np) * zmat_dim1] = -temp;
375 zmat[iq + 1 + (k - np) * zmat_dim1] = -temp;
377 zmat[k + (k - np) * zmat_dim1] = temp;
384 /* Reorder the provisional points in the way that exchanges PTSID(KOLD) */
385 /* with PTSID(KNEW). */
389 for (j = 1; j <= i__2; ++j) {
390 temp = bmat[kold + j * bmat_dim1];
391 bmat[kold + j * bmat_dim1] = bmat[knew + j * bmat_dim1];
393 bmat[knew + j * bmat_dim1] = temp;
396 for (j = 1; j <= i__2; ++j) {
397 temp = zmat[kold + j * zmat_dim1];
398 zmat[kold + j * zmat_dim1] = zmat[knew + j * zmat_dim1];
400 zmat[knew + j * zmat_dim1] = temp;
402 ptsid[kold] = ptsid[knew];
404 w[*ndim + knew] = zero;
408 vlag[kold] = vlag[knew];
411 /* Update the BMAT and ZMAT matrices so that the status of the KNEW-th */
412 /* interpolation point can be changed from provisional to original. The */
413 /* branch to label 350 occurs if all the original points are reinstated. */
414 /* The nonnegative values of W(NDIM+K) are required in the search below. */
416 update_(n, npt, &bmat[bmat_offset], &zmat[zmat_offset], ndim, &vlag[1]
417 , &beta, &denom, &knew, &w[1]);
422 for (k = 1; k <= i__2; ++k) {
424 w[*ndim + k] = (d__1 = w[*ndim + k], fabs(d__1));
428 /* Pick the index KNEW of an original interpolation point that has not */
429 /* yet replaced one of the provisional interpolation points, giving */
430 /* attention to the closeness to XOPT and to previous tries with KNEW. */
435 for (k = 1; k <= i__2; ++k) {
436 if (w[*ndim + k] > zero) {
437 if (dsqmin == zero || w[*ndim + k] < dsqmin) {
439 dsqmin = w[*ndim + k];
444 if (dsqmin == zero) {
448 /* Form the W-vector of the chosen original interpolation point. */
451 for (j = 1; j <= i__2; ++j) {
453 w[*npt + j] = xpt[knew + j * xpt_dim1];
456 for (k = 1; k <= i__2; ++k) {
459 } else if (ptsid[k] == zero) {
461 for (j = 1; j <= i__1; ++j) {
463 sum += w[*npt + j] * xpt[k + j * xpt_dim1];
468 sum = w[*npt + ip] * ptsaux[(ip << 1) + 1];
470 iq = (int) ((double) np * ptsid[k] - (double) (ip *
477 sum += w[*npt + iq] * ptsaux[iw + (iq << 1)];
481 w[k] = half * sum * sum;
484 /* Calculate VLAG and BETA for the required updating of the H matrix if */
485 /* XPT(KNEW,.) is reinstated in the set of interpolation points. */
488 for (k = 1; k <= i__2; ++k) {
491 for (j = 1; j <= i__1; ++j) {
493 sum += bmat[k + j * bmat_dim1] * w[*npt + j];
500 for (j = 1; j <= i__2; ++j) {
503 for (k = 1; k <= i__1; ++k) {
505 sum += zmat[k + j * zmat_dim1] * w[k];
509 for (k = 1; k <= i__1; ++k) {
511 vlag[k] += sum * zmat[k + j * zmat_dim1];
517 for (j = 1; j <= i__1; ++j) {
520 for (k = 1; k <= i__2; ++k) {
522 sum += bmat[k + j * bmat_dim1] * w[k];
527 for (ip = *npt + 1; ip <= i__2; ++ip) {
529 sum += bmat[ip + j * bmat_dim1] * w[ip];
534 /* Computing 2nd power */
535 d__1 = xpt[knew + j * xpt_dim1];
536 distsq += d__1 * d__1;
538 beta = half * distsq * distsq + beta - bsum;
541 /* KOLD is set to the index of the provisional interpolation point that is */
542 /* going to be deleted to make way for the KNEW-th original interpolation */
543 /* point. The choice of KOLD is governed by the avoidance of a small value */
544 /* of the denominator in the updating calculation of UPDATE. */
549 for (k = 1; k <= i__1; ++k) {
550 if (ptsid[k] != zero) {
553 for (j = 1; j <= i__2; ++j) {
555 /* Computing 2nd power */
556 d__1 = zmat[k + j * zmat_dim1];
557 hdiag += d__1 * d__1;
559 /* Computing 2nd power */
561 den = beta * hdiag + d__1 * d__1;
569 /* Computing 2nd power */
571 d__1 = vlmxsq, d__2 = d__3 * d__3;
572 vlmxsq = max(d__1,d__2);
574 if (denom <= vlmxsq * .01) {
575 w[*ndim + knew] = -w[*ndim + knew] - winc;
580 /* When label 260 is reached, all the final positions of the interpolation */
581 /* points have been chosen although any changes have not been included yet */
582 /* in XPT. Also the final BMAT and ZMAT matrices are complete, but, apart */
583 /* from the shift of XBASE, the updating of the quadratic model remains to */
584 /* be done. The following cycle through the new interpolation points begins */
585 /* by putting the new point in XPT(KPT,.) and by setting PQ(KPT) to zero, */
586 /* except that a RETURN occurs if MAXFUN prohibits another value of F. */
590 for (kpt = 1; kpt <= i__1; ++kpt) {
591 if (ptsid[kpt] == zero) {
595 if (nlopt_stop_forced(stop)) return NLOPT_FORCE_STOP;
596 else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
597 else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;
601 for (j = 1; j <= i__2; ++j) {
602 w[j] = xpt[kpt + j * xpt_dim1];
603 xpt[kpt + j * xpt_dim1] = zero;
604 temp = pq[kpt] * w[j];
606 for (i__ = 1; i__ <= i__3; ++i__) {
609 hq[ih] += temp * w[i__];
613 ip = (int) ptsid[kpt];
614 iq = (int) ((double) np * ptsid[kpt] - (double) (ip * np))
617 xp = ptsaux[(ip << 1) + 1];
618 xpt[kpt + ip * xpt_dim1] = xp;
621 xq = ptsaux[(iq << 1) + 1];
623 xq = ptsaux[(iq << 1) + 2];
625 xpt[kpt + iq * xpt_dim1] = xq;
628 /* Set VQUAD to the value of the current model at the new point. */
632 ihp = (ip + ip * ip) / 2;
633 vquad += xp * (gopt[ip] + half * xp * hq[ihp]);
636 ihq = (iq + iq * iq) / 2;
637 vquad += xq * (gopt[iq] + half * xq * hq[ihq]);
639 iw = max(ihp,ihq) - (i__3 = ip - iq, iabs(i__3));
640 vquad += xp * xq * hq[iw];
644 for (k = 1; k <= i__3; ++k) {
647 temp += xp * xpt[k + ip * xpt_dim1];
650 temp += xq * xpt[k + iq * xpt_dim1];
653 vquad += half * pq[k] * temp * temp;
656 /* Calculate F at the new interpolation point, and set DIFF to the factor */
657 /* that is going to multiply the KPT-th Lagrange function when the model */
658 /* is updated to provide interpolation to the new function value. */
661 for (i__ = 1; i__ <= i__3; ++i__) {
664 d__3 = xl[i__], d__4 = xbase[i__] + xpt[kpt + i__ * xpt_dim1];
665 d__1 = max(d__3,d__4), d__2 = xu[i__];
666 w[i__] = min(d__1,d__2);
667 if (xpt[kpt + i__ * xpt_dim1] == sl[i__]) {
670 if (xpt[kpt + i__ * xpt_dim1] == su[i__]) {
677 f = calfun(*n, &w[1], calfun_data);
679 if (f < fval[*kopt]) {
682 if (nlopt_stop_forced(stop)) return NLOPT_FORCE_STOP;
683 else if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
684 else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
685 else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;
689 /* Update the quadratic model. The RETURN from the subroutine occurs when */
690 /* all the new interpolation points are included in the model. */
693 for (i__ = 1; i__ <= i__3; ++i__) {
695 gopt[i__] += diff * bmat[kpt + i__ * bmat_dim1];
698 for (k = 1; k <= i__3; ++k) {
701 for (j = 1; j <= i__2; ++j) {
703 sum += zmat[k + j * zmat_dim1] * zmat[kpt + j * zmat_dim1];
706 if (ptsid[k] == zero) {
710 iq = (int) ((double) np * ptsid[k] - (double) (ip
712 ihq = (iq * iq + iq) / 2;
714 /* Computing 2nd power */
715 d__1 = ptsaux[(iq << 1) + 2];
716 hq[ihq] += temp * (d__1 * d__1);
718 ihp = (ip * ip + ip) / 2;
719 /* Computing 2nd power */
720 d__1 = ptsaux[(ip << 1) + 1];
721 hq[ihp] += temp * (d__1 * d__1);
723 /* Computing 2nd power */
724 d__1 = ptsaux[(iq << 1) + 1];
725 hq[ihq] += temp * (d__1 * d__1);
726 iw = max(ihp,ihq) - (i__2 = iq - ip, iabs(i__2));
727 hq[iw] += temp * ptsaux[(ip << 1) + 1] * ptsaux[(iq <<
739 return NLOPT_SUCCESS;
742 static void altmov_(int *n, int *npt, double *xpt,
743 double *xopt, double *bmat, double *zmat, int *ndim,
744 double *sl, double *su, int *kopt, int *knew,
745 double *adelt, double *xnew, double *xalt, double *
746 alpha, double *cauchy, double *glag, double *hcol,
749 /* System generated locals */
750 int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1,
751 zmat_offset, i__1, i__2;
752 double d__1, d__2, d__3, d__4;
754 /* Local variables */
756 double ha, gw, one, diff, half;
760 double vlag, subd, temp;
762 double step, zero, curv;
764 double scale, csave, tempa, tempb, tempd, const__, sumin, ggfree;
766 double dderiv, bigstp, predsq, presav, distsq, stpsav, wfixsq, wsqsav;
769 /* The arguments N, NPT, XPT, XOPT, BMAT, ZMAT, NDIM, SL and SU all have */
770 /* the same meanings as the corresponding arguments of BOBYQB. */
771 /* KOPT is the index of the optimal interpolation point. */
772 /* KNEW is the index of the interpolation point that is going to be moved. */
773 /* ADELT is the current trust region bound. */
774 /* XNEW will be set to a suitable new position for the interpolation point */
775 /* XPT(KNEW,.). Specifically, it satisfies the SL, SU and trust region */
776 /* bounds and it should provide a large denominator in the next call of */
777 /* UPDATE. The step XNEW-XOPT from XOPT is restricted to moves along the */
778 /* straight lines through XOPT and another interpolation point. */
779 /* XALT also provides a large value of the modulus of the KNEW-th Lagrange */
780 /* function subject to the constraints that have been mentioned, its main */
781 /* difference from XNEW being that XALT-XOPT is a constrained version of */
782 /* the Cauchy step within the trust region. An exception is that XALT is */
783 /* not calculated if all components of GLAG (see below) are zero. */
784 /* ALPHA will be set to the KNEW-th diagonal element of the H matrix. */
785 /* CAUCHY will be set to the square of the KNEW-th Lagrange function at */
786 /* the step XALT-XOPT from XOPT for the vector XALT that is returned, */
787 /* except that CAUCHY is set to zero if XALT is not calculated. */
788 /* GLAG is a working space vector of length N for the gradient of the */
789 /* KNEW-th Lagrange function at XOPT. */
790 /* HCOL is a working space vector of length NPT for the second derivative */
791 /* coefficients of the KNEW-th Lagrange function. */
792 /* W is a working space vector of length 2N that is going to hold the */
793 /* constrained Cauchy step from XOPT of the Lagrange function, followed */
794 /* by the downhill version of XALT when the uphill step is calculated. */
796 /* Set the first NPT components of W to the leading elements of the */
797 /* KNEW-th column of the H matrix. */
799 /* Parameter adjustments */
801 zmat_offset = 1 + zmat_dim1;
804 xpt_offset = 1 + xpt_dim1;
808 bmat_offset = 1 + bmat_dim1;
822 const__ = one + sqrt(2.);
824 for (k = 1; k <= i__1; ++k) {
828 i__1 = *npt - *n - 1;
829 for (j = 1; j <= i__1; ++j) {
830 temp = zmat[*knew + j * zmat_dim1];
832 for (k = 1; k <= i__2; ++k) {
834 hcol[k] += temp * zmat[k + j * zmat_dim1];
837 *alpha = hcol[*knew];
840 /* Calculate the gradient of the KNEW-th Lagrange function at XOPT. */
843 for (i__ = 1; i__ <= i__2; ++i__) {
845 glag[i__] = bmat[*knew + i__ * bmat_dim1];
848 for (k = 1; k <= i__2; ++k) {
851 for (j = 1; j <= i__1; ++j) {
853 temp += xpt[k + j * xpt_dim1] * xopt[j];
855 temp = hcol[k] * temp;
857 for (i__ = 1; i__ <= i__1; ++i__) {
859 glag[i__] += temp * xpt[k + i__ * xpt_dim1];
863 /* Search for a large denominator along the straight lines through XOPT */
864 /* and another interpolation point. SLBD and SUBD will be lower and upper */
865 /* bounds on the step along each of these lines in turn. PREDSQ will be */
866 /* set to the square of the predicted denominator for each line. PRESAV */
867 /* will be set to the largest admissible value of PREDSQ that occurs. */
871 for (k = 1; k <= i__1; ++k) {
878 for (i__ = 1; i__ <= i__2; ++i__) {
879 temp = xpt[k + i__ * xpt_dim1] - xopt[i__];
880 dderiv += glag[i__] * temp;
882 distsq += temp * temp;
884 subd = *adelt / sqrt(distsq);
888 sumin = min(one,subd);
890 /* Revise SLBD and SUBD if necessary because of the bounds in SL and SU. */
893 for (i__ = 1; i__ <= i__2; ++i__) {
894 temp = xpt[k + i__ * xpt_dim1] - xopt[i__];
896 if (slbd * temp < sl[i__] - xopt[i__]) {
897 slbd = (sl[i__] - xopt[i__]) / temp;
900 if (subd * temp > su[i__] - xopt[i__]) {
902 d__1 = sumin, d__2 = (su[i__] - xopt[i__]) / temp;
903 subd = max(d__1,d__2);
906 } else if (temp < zero) {
907 if (slbd * temp > su[i__] - xopt[i__]) {
908 slbd = (su[i__] - xopt[i__]) / temp;
911 if (subd * temp < sl[i__] - xopt[i__]) {
913 d__1 = sumin, d__2 = (sl[i__] - xopt[i__]) / temp;
914 subd = max(d__1,d__2);
921 /* Seek a large modulus of the KNEW-th Lagrange function when the index */
922 /* of the other interpolation point on the line through XOPT is KNEW. */
927 vlag = slbd * (dderiv - slbd * diff);
929 temp = subd * (dderiv - subd * diff);
930 if (fabs(temp) > fabs(vlag)) {
935 tempd = half * dderiv;
936 tempa = tempd - diff * slbd;
937 tempb = tempd - diff * subd;
938 if (tempa * tempb < zero) {
939 temp = tempd * tempd / diff;
940 if (fabs(temp) > fabs(vlag)) {
947 /* Search along each of the other lines through XOPT and another point. */
951 vlag = slbd * (one - slbd);
953 temp = subd * (one - subd);
954 if (fabs(temp) > fabs(vlag)) {
960 if (fabs(vlag) < .25) {
969 /* Calculate PREDSQ for the current line search and maintain PRESAV. */
971 temp = step * (one - step) * distsq;
972 predsq = vlag * vlag * (vlag * vlag + ha * temp * temp);
973 if (predsq > presav) {
983 /* Construct XNEW in a way that satisfies the bound constraints exactly. */
986 for (i__ = 1; i__ <= i__1; ++i__) {
987 temp = xopt[i__] + stpsav * (xpt[ksav + i__ * xpt_dim1] - xopt[i__]);
992 d__1 = sl[i__], d__2 = min(d__3,temp);
993 xnew[i__] = max(d__1,d__2);
996 xnew[-ibdsav] = sl[-ibdsav];
999 xnew[ibdsav] = su[ibdsav];
1002 /* Prepare for the iterative method that assembles the constrained Cauchy */
1003 /* step in W. The sum of squares of the fixed components of W is formed in */
1004 /* WFIXSQ, and the free components of W are set to BIGSTP. */
1006 bigstp = *adelt + *adelt;
1012 for (i__ = 1; i__ <= i__1; ++i__) {
1015 d__1 = xopt[i__] - sl[i__], d__2 = glag[i__];
1016 tempa = min(d__1,d__2);
1018 d__1 = xopt[i__] - su[i__], d__2 = glag[i__];
1019 tempb = max(d__1,d__2);
1020 if (tempa > zero || tempb < zero) {
1022 /* Computing 2nd power */
1024 ggfree += d__1 * d__1;
1028 if (ggfree == zero) {
1033 /* Investigate whether more components of W can be fixed. */
1036 temp = *adelt * *adelt - wfixsq;
1039 step = sqrt(temp / ggfree);
1042 for (i__ = 1; i__ <= i__1; ++i__) {
1043 if (w[i__] == bigstp) {
1044 temp = xopt[i__] - step * glag[i__];
1045 if (temp <= sl[i__]) {
1046 w[i__] = sl[i__] - xopt[i__];
1047 /* Computing 2nd power */
1049 wfixsq += d__1 * d__1;
1050 } else if (temp >= su[i__]) {
1051 w[i__] = su[i__] - xopt[i__];
1052 /* Computing 2nd power */
1054 wfixsq += d__1 * d__1;
1056 /* Computing 2nd power */
1058 ggfree += d__1 * d__1;
1063 if (wfixsq > wsqsav && ggfree > zero) {
1068 /* Set the remaining free components of W and all components of XALT, */
1069 /* except that W may be scaled later. */
1073 for (i__ = 1; i__ <= i__1; ++i__) {
1074 if (w[i__] == bigstp) {
1075 w[i__] = -step * glag[i__];
1078 d__3 = su[i__], d__4 = xopt[i__] + w[i__];
1079 d__1 = sl[i__], d__2 = min(d__3,d__4);
1080 xalt[i__] = max(d__1,d__2);
1081 } else if (w[i__] == zero) {
1082 xalt[i__] = xopt[i__];
1083 } else if (glag[i__] > zero) {
1084 xalt[i__] = sl[i__];
1086 xalt[i__] = su[i__];
1089 gw += glag[i__] * w[i__];
1092 /* Set CURV to the curvature of the KNEW-th Lagrange function along W. */
1093 /* Scale W by a factor less than one if that can reduce the modulus of */
1094 /* the Lagrange function at XOPT+W. Set CAUCHY to the final value of */
1095 /* the square of this function. */
1099 for (k = 1; k <= i__1; ++k) {
1102 for (j = 1; j <= i__2; ++j) {
1104 temp += xpt[k + j * xpt_dim1] * w[j];
1107 curv += hcol[k] * temp * temp;
1112 if (curv > -gw && curv < -const__ * gw) {
1115 for (i__ = 1; i__ <= i__1; ++i__) {
1116 temp = xopt[i__] + scale * w[i__];
1121 d__1 = sl[i__], d__2 = min(d__3,temp);
1122 xalt[i__] = max(d__1,d__2);
1124 /* Computing 2nd power */
1125 d__1 = half * gw * scale;
1126 *cauchy = d__1 * d__1;
1128 /* Computing 2nd power */
1129 d__1 = gw + half * curv;
1130 *cauchy = d__1 * d__1;
1133 /* If IFLAG is zero, then XALT is calculated as before after reversing */
1134 /* the sign of GLAG. Thus two XALT vectors become available. The one that */
1135 /* is chosen is the one that gives the larger value of CAUCHY. */
1139 for (i__ = 1; i__ <= i__1; ++i__) {
1140 glag[i__] = -glag[i__];
1142 w[*n + i__] = xalt[i__];
1148 if (csave > *cauchy) {
1150 for (i__ = 1; i__ <= i__1; ++i__) {
1152 xalt[i__] = w[*n + i__];
1160 static void trsbox_(int *n, int *npt, double *xpt,
1161 double *xopt, double *gopt, double *hq, double *pq,
1162 double *sl, double *su, double *delta, double *xnew,
1163 double *d__, double *gnew, double *xbdi, double *s,
1164 double *hs, double *hred, double *dsq, double *crvmin)
1166 /* System generated locals */
1167 int xpt_dim1, xpt_offset, i__1, i__2;
1168 double d__1, d__2, d__3, d__4;
1170 /* Local variables */
1174 double dhd, dhs, cth, one, shs, sth, ssq, half, beta, sdec, blen;
1178 double temp, zero, xsav, xsum, angbd, dredg, sredg;
1180 double resid, delsq, ggsav, tempa, tempb, ratio, sqstp, redmax,
1181 dredsq, redsav, onemin, gredsq, rednew;
1183 double rdprev, rdnext, stplen, stepsq;
1187 /* The arguments N, NPT, XPT, XOPT, GOPT, HQ, PQ, SL and SU have the same */
1188 /* meanings as the corresponding arguments of BOBYQB. */
1189 /* DELTA is the trust region radius for the present calculation, which */
1190 /* seeks a small value of the quadratic model within distance DELTA of */
1191 /* XOPT subject to the bounds on the variables. */
1192 /* XNEW will be set to a new vector of variables that is approximately */
1193 /* the one that minimizes the quadratic model within the trust region */
1194 /* subject to the SL and SU constraints on the variables. It satisfies */
1195 /* as equations the bounds that become active during the calculation. */
1196 /* D is the calculated trial step from XOPT, generated iteratively from an */
1197 /* initial value of zero. Thus XNEW is XOPT+D after the final iteration. */
1198 /* GNEW holds the gradient of the quadratic model at XOPT+D. It is updated */
1199 /* when D is updated. */
1200 /* XBDI is a working space vector. For I=1,2,...,N, the element XBDI(I) is */
1201 /* set to -1.0, 0.0, or 1.0, the value being nonzero if and only if the */
1202 /* I-th variable has become fixed at a bound, the bound being SL(I) or */
1203 /* SU(I) in the case XBDI(I)=-1.0 or XBDI(I)=1.0, respectively. This */
1204 /* information is accumulated during the construction of XNEW. */
1205 /* The arrays S, HS and HRED are also used for working space. They hold the */
1206 /* current search direction, and the changes in the gradient of Q along S */
1207 /* and the reduced D, respectively, where the reduced D is the same as D, */
1208 /* except that the components of the fixed variables are zero. */
1209 /* DSQ will be set to the square of the length of XNEW-XOPT. */
1210 /* CRVMIN is set to zero if D reaches the trust region boundary. Otherwise */
1211 /* it is set to the least curvature of H that occurs in the conjugate */
1212 /* gradient searches that are not restricted by any constraints. The */
1213 /* value CRVMIN=-1.0D0 is set, however, if all of these searches are */
1216 /* A version of the truncated conjugate gradient is applied. If a line */
1217 /* search is restricted by a constraint, then the procedure is restarted, */
1218 /* the values of the variables that are at their bounds being fixed. If */
1219 /* the trust region boundary is reached, then further changes may be made */
1220 /* to D, each one being in the two dimensional space that is spanned */
1221 /* by the current D and the gradient of Q at XOPT+D, staying on the trust */
1222 /* region boundary. Termination occurs when the reduction in Q seems to */
1223 /* be close to the greatest reduction that can be achieved. */
1225 /* Set some constants. */
1227 /* Parameter adjustments */
1229 xpt_offset = 1 + xpt_dim1;
1251 /* The sign of GOPT(I) gives the sign of the change to the I-th variable */
1252 /* that will reduce Q from its value at XOPT. Thus XBDI(I) shows whether */
1253 /* or not to fix the I-th variable at one of its bounds initially, with */
1254 /* NACT being set to the number of fixed variables. D and GNEW are also */
1255 /* set for the first iteration. DELSQ is the upper bound on the sum of */
1256 /* squares of the free variables. QRED is the reduction in Q so far. */
1262 for (i__ = 1; i__ <= i__1; ++i__) {
1264 if (xopt[i__] <= sl[i__]) {
1265 if (gopt[i__] >= zero) {
1268 } else if (xopt[i__] >= su[i__]) {
1269 if (gopt[i__] <= zero) {
1273 if (xbdi[i__] != zero) {
1278 gnew[i__] = gopt[i__];
1280 delsq = *delta * *delta;
1284 /* Set the next search direction of the conjugate gradient method. It is */
1285 /* the steepest descent direction initially and when the iterations are */
1286 /* restarted because a variable has just been fixed by a bound, and of */
1287 /* course the components of the fixed variables are zero. ITERMAX is an */
1288 /* upper bound on the indices of the conjugate gradient iterations. */
1295 for (i__ = 1; i__ <= i__1; ++i__) {
1296 if (xbdi[i__] != zero) {
1298 } else if (beta == zero) {
1299 s[i__] = -gnew[i__];
1301 s[i__] = beta * s[i__] - gnew[i__];
1304 /* Computing 2nd power */
1306 stepsq += d__1 * d__1;
1308 if (stepsq == zero) {
1313 itermax = iterc + *n - nact;
1315 if (gredsq * delsq <= qred * 1e-4 * qred) {
1319 /* Multiply the search direction by the second derivative matrix of Q and */
1320 /* calculate some scalars for the choice of steplength. Then set BLEN to */
1321 /* the length of the the step to the trust region boundary and STPLEN to */
1322 /* the steplength, ignoring the simple bounds. */
1330 for (i__ = 1; i__ <= i__1; ++i__) {
1331 if (xbdi[i__] == zero) {
1332 /* Computing 2nd power */
1334 resid -= d__1 * d__1;
1335 ds += s[i__] * d__[i__];
1336 shs += s[i__] * hs[i__];
1340 if (resid <= zero) {
1343 temp = sqrt(stepsq * resid + ds * ds);
1345 blen = (temp - ds) / stepsq;
1347 blen = resid / (temp + ds);
1352 d__1 = blen, d__2 = gredsq / shs;
1353 stplen = min(d__1,d__2);
1356 /* Reduce STPLEN if necessary in order to preserve the simple bounds, */
1357 /* letting IACT be the index of the new constrained variable. */
1361 for (i__ = 1; i__ <= i__1; ++i__) {
1362 if (s[i__] != zero) {
1363 xsum = xopt[i__] + d__[i__];
1364 if (s[i__] > zero) {
1365 temp = (su[i__] - xsum) / s[i__];
1367 temp = (sl[i__] - xsum) / s[i__];
1369 if (temp < stplen) {
1377 /* Update CRVMIN, GNEW and D. Set SDEC to the decrease that occurs in Q. */
1380 if (stplen > zero) {
1382 temp = shs / stepsq;
1383 if (iact == 0 && temp > zero) {
1384 *crvmin = min(*crvmin,temp);
1385 if (*crvmin == onemin) {
1392 for (i__ = 1; i__ <= i__1; ++i__) {
1393 gnew[i__] += stplen * hs[i__];
1394 if (xbdi[i__] == zero) {
1395 /* Computing 2nd power */
1397 gredsq += d__1 * d__1;
1400 d__[i__] += stplen * s[i__];
1403 d__1 = stplen * (ggsav - half * stplen * shs);
1404 sdec = max(d__1,zero);
1408 /* Restart the conjugate gradient method if it has hit a new bound. */
1413 if (s[iact] < zero) {
1414 xbdi[iact] = onemin;
1416 /* Computing 2nd power */
1418 delsq -= d__1 * d__1;
1419 if (delsq <= zero) {
1425 /* If STPLEN is less than BLEN, then either apply another conjugate */
1426 /* gradient iteration or RETURN. */
1428 if (stplen < blen) {
1429 if (iterc == itermax) {
1432 if (sdec <= qred * .01) {
1435 beta = gredsq / ggsav;
1441 /* Prepare for the alternative iteration by calculating some scalars */
1442 /* and by multiplying the reduced D by the second derivative matrix of */
1443 /* Q, where S holds the reduced D in the call of GGMULT. */
1446 if (nact >= *n - 1) {
1453 for (i__ = 1; i__ <= i__1; ++i__) {
1454 if (xbdi[i__] == zero) {
1455 /* Computing 2nd power */
1457 dredsq += d__1 * d__1;
1458 dredg += d__[i__] * gnew[i__];
1459 /* Computing 2nd power */
1461 gredsq += d__1 * d__1;
1471 /* Let the search direction S be a linear combination of the reduced D */
1472 /* and the reduced G that is orthogonal to the reduced D. */
1476 temp = gredsq * dredsq - dredg * dredg;
1477 if (temp <= qred * 1e-4 * qred) {
1482 for (i__ = 1; i__ <= i__1; ++i__) {
1483 if (xbdi[i__] == zero) {
1484 s[i__] = (dredg * d__[i__] - dredsq * gnew[i__]) / temp;
1492 /* By considering the simple bounds on the variables, calculate an upper */
1493 /* bound on the tangent of half the angle of the alternative iteration, */
1494 /* namely ANGBD, except that, if already a free variable has reached a */
1495 /* bound, there is a branch back to label 100 after fixing that variable. */
1500 for (i__ = 1; i__ <= i__1; ++i__) {
1501 if (xbdi[i__] == zero) {
1502 tempa = xopt[i__] + d__[i__] - sl[i__];
1503 tempb = su[i__] - xopt[i__] - d__[i__];
1504 if (tempa <= zero) {
1508 } else if (tempb <= zero) {
1514 /* Computing 2nd power */
1516 /* Computing 2nd power */
1518 ssq = d__1 * d__1 + d__2 * d__2;
1519 /* Computing 2nd power */
1520 d__1 = xopt[i__] - sl[i__];
1521 temp = ssq - d__1 * d__1;
1523 temp = sqrt(temp) - s[i__];
1524 if (angbd * temp > tempa) {
1525 angbd = tempa / temp;
1530 /* Computing 2nd power */
1531 d__1 = su[i__] - xopt[i__];
1532 temp = ssq - d__1 * d__1;
1534 temp = sqrt(temp) + s[i__];
1535 if (angbd * temp > tempb) {
1536 angbd = tempb / temp;
1545 /* Calculate HHD and some curvatures for the alternative iteration. */
1553 for (i__ = 1; i__ <= i__1; ++i__) {
1554 if (xbdi[i__] == zero) {
1555 shs += s[i__] * hs[i__];
1556 dhs += d__[i__] * hs[i__];
1557 dhd += d__[i__] * hred[i__];
1562 /* Seek the greatest reduction in Q for a range of equally spaced values */
1563 /* of ANGT in [0,ANGBD], where ANGT is the tangent of half the angle of */
1564 /* the alternative iteration. */
1569 iu = (int) (angbd * 17. + 3.1);
1571 for (i__ = 1; i__ <= i__1; ++i__) {
1572 angt = angbd * (double) i__ / (double) iu;
1573 sth = (angt + angt) / (one + angt * angt);
1574 temp = shs + angt * (angt * dhd - dhs - dhs);
1575 rednew = sth * (angt * dredg - sredg - half * sth * temp);
1576 if (rednew > redmax) {
1580 } else if (i__ == isav + 1) {
1587 /* Return if the reduction is zero. Otherwise, set the sine and cosine */
1588 /* of the angle of the alternative iteration, and calculate SDEC. */
1594 temp = (rdnext - rdprev) / (redmax + redmax - rdprev - rdnext);
1595 angt = angbd * ((double) isav + half * temp) / (double) iu;
1597 cth = (one - angt * angt) / (one + angt * angt);
1598 sth = (angt + angt) / (one + angt * angt);
1599 temp = shs + angt * (angt * dhd - dhs - dhs);
1600 sdec = sth * (angt * dredg - sredg - half * sth * temp);
1605 /* Update GNEW, D and HRED. If the angle of the alternative iteration */
1606 /* is restricted by a bound on a free variable, that variable is fixed */
1612 for (i__ = 1; i__ <= i__1; ++i__) {
1613 gnew[i__] = gnew[i__] + (cth - one) * hred[i__] + sth * hs[i__];
1614 if (xbdi[i__] == zero) {
1615 d__[i__] = cth * d__[i__] + sth * s[i__];
1616 dredg += d__[i__] * gnew[i__];
1617 /* Computing 2nd power */
1619 gredsq += d__1 * d__1;
1622 hred[i__] = cth * hred[i__] + sth * hs[i__];
1625 if (iact > 0 && isav == iu) {
1631 /* If SDEC is sufficiently small, then RETURN after setting XNEW to */
1632 /* XOPT+D, giving careful attention to the bounds. */
1634 if (sdec > qred * .01) {
1640 for (i__ = 1; i__ <= i__1; ++i__) {
1643 d__3 = xopt[i__] + d__[i__], d__4 = su[i__];
1644 d__1 = min(d__3,d__4), d__2 = sl[i__];
1645 xnew[i__] = max(d__1,d__2);
1646 if (xbdi[i__] == onemin) {
1647 xnew[i__] = sl[i__];
1649 if (xbdi[i__] == one) {
1650 xnew[i__] = su[i__];
1652 d__[i__] = xnew[i__] - xopt[i__];
1654 /* Computing 2nd power */
1656 *dsq += d__1 * d__1;
1659 /* The following instructions multiply the current S-vector by the second */
1660 /* derivative matrix of the quadratic model, putting the product in HS. */
1661 /* They are reached from three different parts of the software above and */
1662 /* they can be regarded as an external subroutine. */
1667 for (j = 1; j <= i__1; ++j) {
1670 for (i__ = 1; i__ <= i__2; ++i__) {
1673 hs[j] += hq[ih] * s[i__];
1676 hs[i__] += hq[ih] * s[j];
1680 for (k = 1; k <= i__2; ++k) {
1681 if (pq[k] != zero) {
1684 for (j = 1; j <= i__1; ++j) {
1686 temp += xpt[k + j * xpt_dim1] * s[j];
1690 for (i__ = 1; i__ <= i__1; ++i__) {
1692 hs[i__] += temp * xpt[k + i__ * xpt_dim1];
1697 if (*crvmin != zero) {
1700 if (iterc > itcsav) {
1704 for (i__ = 1; i__ <= i__2; ++i__) {
1706 hred[i__] = hs[i__];
1711 static nlopt_result prelim_(int *n, int *npt, double *x,
1712 const double *xl, const double *xu, double *rhobeg,
1713 nlopt_stopping *stop,
1714 bobyqa_func calfun, void *calfun_data,
1715 double *xbase, double *xpt, double *fval,
1716 double *gopt, double *hq, double *pq, double *bmat,
1717 double *zmat, int *ndim, double *sl, double *su,
1720 /* System generated locals */
1721 int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1,
1722 zmat_offset, i__1, i__2;
1723 double d__1, d__2, d__3, d__4;
1725 /* Local variables */
1727 int i__, j, k, ih, np, nfm;
1730 double two, fbeg, diff, half, temp, zero, recip, stepa, stepb;
1736 /* The arguments N, NPT, X, XL, XU, RHOBEG, and MAXFUN are the */
1737 /* same as the corresponding arguments in SUBROUTINE BOBYQA. */
1738 /* The arguments XBASE, XPT, FVAL, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU */
1739 /* are the same as the corresponding arguments in BOBYQB, the elements */
1740 /* of SL and SU being set in BOBYQA. */
1741 /* GOPT is usually the gradient of the quadratic model at XOPT+XBASE, but */
1742 /* it is set by PRELIM to the gradient of the quadratic model at XBASE. */
1743 /* If XOPT is nonzero, BOBYQB will change it to its usual value later. */
1744 /* NF is maintaned as the number of calls of CALFUN so far. */
1745 /* KOPT will be such that the least calculated value of F so far is at */
1746 /* the point XPT(KOPT,.)+XBASE in the space of the variables. */
1748 /* SUBROUTINE PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ, */
1749 /* BMAT and ZMAT for the first iteration, and it maintains the values of */
1750 /* NF and KOPT. The vector X is also changed by PRELIM. */
1752 /* Set some constants. */
1754 /* Parameter adjustments */
1756 zmat_offset = 1 + zmat_dim1;
1757 zmat -= zmat_offset;
1759 xpt_offset = 1 + xpt_dim1;
1770 bmat_offset = 1 + bmat_dim1;
1771 bmat -= bmat_offset;
1780 rhosq = *rhobeg * *rhobeg;
1781 recip = one / rhosq;
1784 /* Set XBASE to the initial vector of variables, and set the initial */
1785 /* elements of XPT, BMAT, HQ, PQ and ZMAT to zero. */
1788 for (j = 1; j <= i__1; ++j) {
1791 for (k = 1; k <= i__2; ++k) {
1793 xpt[k + j * xpt_dim1] = zero;
1796 for (i__ = 1; i__ <= i__2; ++i__) {
1798 bmat[i__ + j * bmat_dim1] = zero;
1802 for (ih = 1; ih <= i__2; ++ih) {
1807 for (k = 1; k <= i__2; ++k) {
1810 for (j = 1; j <= i__1; ++j) {
1812 zmat[k + j * zmat_dim1] = zero;
1816 /* Begin the initialization procedure. NF becomes one more than the number */
1817 /* of function values so far. The coordinates of the displacement of the */
1818 /* next initial interpolation point from XBASE are set in XPT(NF+1,.). */
1825 if (nfm <= *n << 1) {
1826 if (nfm >= 1 && nfm <= *n) {
1828 if (su[nfm] == zero) {
1831 xpt[nf + nfm * xpt_dim1] = stepa;
1832 } else if (nfm > *n) {
1833 stepa = xpt[nf - *n + nfx * xpt_dim1];
1835 if (sl[nfx] == zero) {
1837 d__1 = two * *rhobeg, d__2 = su[nfx];
1838 stepb = min(d__1,d__2);
1840 if (su[nfx] == zero) {
1842 d__1 = -two * *rhobeg, d__2 = sl[nfx];
1843 stepb = max(d__1,d__2);
1845 xpt[nf + nfx * xpt_dim1] = stepb;
1848 itemp = (nfm - np) / *n;
1849 jpt = nfm - itemp * *n - *n;
1856 xpt[nf + ipt * xpt_dim1] = xpt[ipt + 1 + ipt * xpt_dim1];
1857 xpt[nf + jpt * xpt_dim1] = xpt[jpt + 1 + jpt * xpt_dim1];
1860 /* Calculate the next value of F. The least function value so far and */
1861 /* its index are required. */
1864 for (j = 1; j <= i__1; ++j) {
1867 d__3 = xl[j], d__4 = xbase[j] + xpt[nf + j * xpt_dim1];
1868 d__1 = max(d__3,d__4), d__2 = xu[j];
1869 x[j] = min(d__1,d__2);
1870 if (xpt[nf + j * xpt_dim1] == sl[j]) {
1873 if (xpt[nf + j * xpt_dim1] == su[j]) {
1879 f = calfun(*n, &x[1], calfun_data);
1884 } else if (f < fval[*kopt]) {
1888 /* Set the nonzero initial elements of BMAT and the quadratic model in the */
1889 /* cases when NF is at most 2*N+1. If NF exceeds N+1, then the positions */
1890 /* of the NF-th and (NF-N)-th interpolation points may be switched, in */
1891 /* order that the function value at the first of them contributes to the */
1892 /* off-diagonal second derivative terms of the initial quadratic model. */
1894 if (nf <= (*n << 1) + 1) {
1895 if (nf >= 2 && nf <= *n + 1) {
1896 gopt[nfm] = (f - fbeg) / stepa;
1897 if (*npt < nf + *n) {
1898 bmat[nfm * bmat_dim1 + 1] = -one / stepa;
1899 bmat[nf + nfm * bmat_dim1] = one / stepa;
1900 bmat[*npt + nfm + nfm * bmat_dim1] = -half * rhosq;
1902 } else if (nf >= *n + 2) {
1903 ih = nfx * (nfx + 1) / 2;
1904 temp = (f - fbeg) / stepb;
1905 diff = stepb - stepa;
1906 hq[ih] = two * (temp - gopt[nfx]) / diff;
1907 gopt[nfx] = (gopt[nfx] * stepb - temp * stepa) / diff;
1908 if (stepa * stepb < zero) {
1909 if (f < fval[nf - *n]) {
1910 fval[nf] = fval[nf - *n];
1915 xpt[nf - *n + nfx * xpt_dim1] = stepb;
1916 xpt[nf + nfx * xpt_dim1] = stepa;
1919 bmat[nfx * bmat_dim1 + 1] = -(stepa + stepb) / (stepa * stepb);
1920 bmat[nf + nfx * bmat_dim1] = -half / xpt[nf - *n + nfx *
1922 bmat[nf - *n + nfx * bmat_dim1] = -bmat[nfx * bmat_dim1 + 1] -
1923 bmat[nf + nfx * bmat_dim1];
1924 zmat[nfx * zmat_dim1 + 1] = sqrt(two) / (stepa * stepb);
1925 zmat[nf + nfx * zmat_dim1] = sqrt(half) / rhosq;
1926 zmat[nf - *n + nfx * zmat_dim1] = -zmat[nfx * zmat_dim1 + 1] -
1927 zmat[nf + nfx * zmat_dim1];
1930 /* Set the off-diagonal second derivatives of the Lagrange functions and */
1931 /* the initial quadratic model. */
1934 ih = ipt * (ipt - 1) / 2 + jpt;
1935 zmat[nfx * zmat_dim1 + 1] = recip;
1936 zmat[nf + nfx * zmat_dim1] = recip;
1937 zmat[ipt + 1 + nfx * zmat_dim1] = -recip;
1938 zmat[jpt + 1 + nfx * zmat_dim1] = -recip;
1939 temp = xpt[nf + ipt * xpt_dim1] * xpt[nf + jpt * xpt_dim1];
1940 hq[ih] = (fbeg - fval[ipt + 1] - fval[jpt + 1] + f) / temp;
1942 if (nlopt_stop_forced(stop)) return NLOPT_FORCE_STOP;
1943 else if (f < stop->minf_max) return NLOPT_MINF_MAX_REACHED;
1944 else if (nlopt_stop_evals(stop)) return NLOPT_MAXEVAL_REACHED;
1945 else if (nlopt_stop_time(stop)) return NLOPT_MAXTIME_REACHED;
1949 return NLOPT_SUCCESS;
1952 static nlopt_result bobyqb_(int *n, int *npt, double *x,
1953 const double *xl, const double *xu, double *rhobeg, double *
1955 nlopt_stopping *stop,
1956 bobyqa_func calfun, void *calfun_data,
1959 double *xpt, double *fval, double *xopt, double *gopt,
1960 double *hq, double *pq, double *bmat, double *zmat,
1961 int *ndim, double *sl, double *su, double *xnew,
1962 double *xalt, double *d__, double *vlag, double *w)
1964 /* System generated locals */
1965 int xpt_dim1, xpt_offset, bmat_dim1, bmat_offset, zmat_dim1,
1966 zmat_offset, i__1, i__2, i__3;
1967 double d__1, d__2, d__3, d__4;
1969 /* Local variables */
1971 int i__, j, k, ih, jj, nh, ip, jp;
1974 double den, one, ten, dsq, rho, sum, two, diff, half, beta, gisq;
1976 double temp, suma, sumb, bsum, fopt;
1980 double gqsq, dist, sumw, sumz, diffa, diffb, diffc, hdiag;
1982 double alpha, delta, adelt, denom, fsave, bdtol, delsq;
1984 double ratio, dnorm, vquad, pqold, tenth;
1986 double sumpq, scaden;
1987 double errbig, cauchy, fracsq, biglsq, densav;
1989 double crvmin, frhosq;
1994 nlopt_result rc = NLOPT_SUCCESS, rc2;
1996 /* The arguments N, NPT, X, XL, XU, RHOBEG, RHOEND, and MAXFUN */
1997 /* are identical to the corresponding arguments in SUBROUTINE BOBYQA. */
1998 /* XBASE holds a shift of origin that should reduce the contributions */
1999 /* from rounding errors to values of the model and Lagrange functions. */
2000 /* XPT is a two-dimensional array that holds the coordinates of the */
2001 /* interpolation points relative to XBASE. */
2002 /* FVAL holds the values of F at the interpolation points. */
2003 /* XOPT is set to the displacement from XBASE of the trust region centre. */
2004 /* GOPT holds the gradient of the quadratic model at XBASE+XOPT. */
2005 /* HQ holds the explicit second derivatives of the quadratic model. */
2006 /* PQ contains the parameters of the implicit second derivatives of the */
2007 /* quadratic model. */
2008 /* BMAT holds the last N columns of H. */
2009 /* ZMAT holds the factorization of the leading NPT by NPT submatrix of H, */
2010 /* this factorization being ZMAT times ZMAT^T, which provides both the */
2011 /* correct rank and positive semi-definiteness. */
2012 /* NDIM is the first dimension of BMAT and has the value NPT+N. */
2013 /* SL and SU hold the differences XL-XBASE and XU-XBASE, respectively. */
2014 /* All the components of every XOPT are going to satisfy the bounds */
2015 /* SL(I) .LEQ. XOPT(I) .LEQ. SU(I), with appropriate equalities when */
2016 /* XOPT is on a constraint boundary. */
2017 /* XNEW is chosen by SUBROUTINE TRSBOX or ALTMOV. Usually XBASE+XNEW is the */
2018 /* vector of variables for the next call of CALFUN. XNEW also satisfies */
2019 /* the SL and SU constraints in the way that has just been mentioned. */
2020 /* XALT is an alternative to XNEW, chosen by ALTMOV, that may replace XNEW */
2021 /* in order to increase the denominator in the updating of UPDATE. */
2022 /* D is reserved for a trial step from XOPT, which is usually XNEW-XOPT. */
2023 /* VLAG contains the values of the Lagrange functions at a new point X. */
2024 /* They are part of a product that requires VLAG to be of length NDIM. */
2025 /* W is a one-dimensional array that is used for working space. Its length */
2026 /* must be at least 3*NDIM = 3*(NPT+N). */
2028 /* Set some constants. */
2030 /* Parameter adjustments */
2032 zmat_offset = 1 + zmat_dim1;
2033 zmat -= zmat_offset;
2035 xpt_offset = 1 + xpt_dim1;
2047 bmat_offset = 1 + bmat_dim1;
2048 bmat -= bmat_offset;
2068 /* The call of PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ, */
2069 /* BMAT and ZMAT for the first iteration, with the corresponding values of */
2070 /* of NF and KOPT, which are the number of calls of CALFUN so far and the */
2071 /* index of the interpolation point at the trust region centre. Then the */
2072 /* initial XOPT is set too. The branch to label 720 occurs if MAXFUN is */
2073 /* less than NPT. GOPT will be updated if KOPT is different from KBASE. */
2075 rc2 = prelim_(n, npt, &x[1], &xl[1], &xu[1], rhobeg,
2076 stop, calfun, calfun_data,
2077 &xbase[1], &xpt[xpt_offset], &fval[1], &gopt[1], &hq[1], &pq[1], &bmat[
2078 bmat_offset], &zmat[zmat_offset], ndim, &sl[1], &su[1], &kopt);
2081 for (i__ = 1; i__ <= i__1; ++i__) {
2082 xopt[i__] = xpt[kopt + i__ * xpt_dim1];
2084 /* Computing 2nd power */
2086 xoptsq += d__1 * d__1;
2089 if (rc2 != NLOPT_SUCCESS) {
2095 /* Complete the settings that are required for the iterative procedure. */
2099 nresc = stop->nevals;
2104 nfsav = stop->nevals;
2106 /* Update GOPT if necessary before the first iteration and after each */
2107 /* call of RESCUE that makes a call of CALFUN. */
2110 if (kopt != kbase) {
2113 for (j = 1; j <= i__1; ++j) {
2115 for (i__ = 1; i__ <= i__2; ++i__) {
2118 gopt[j] += hq[ih] * xopt[i__];
2121 gopt[i__] += hq[ih] * xopt[j];
2124 if (stop->nevals > *npt) {
2126 for (k = 1; k <= i__2; ++k) {
2129 for (j = 1; j <= i__1; ++j) {
2131 temp += xpt[k + j * xpt_dim1] * xopt[j];
2133 temp = pq[k] * temp;
2135 for (i__ = 1; i__ <= i__1; ++i__) {
2137 gopt[i__] += temp * xpt[k + i__ * xpt_dim1];
2143 /* Generate the next point in the trust region that provides a small value */
2144 /* of the quadratic model subject to the constraints on the variables. */
2145 /* The int NTRITS is set to the number "trust region" iterations that */
2146 /* have occurred since the last "alternative" iteration. If the length */
2147 /* of XNEW-XOPT is less than HALF*RHO, however, then there is a branch to */
2148 /* label 650 or 680 with NTRITS=-1, instead of calculating F at XNEW. */
2151 trsbox_(n, npt, &xpt[xpt_offset], &xopt[1], &gopt[1], &hq[1], &pq[1], &sl[
2152 1], &su[1], &delta, &xnew[1], &d__[1], &w[1], &w[np], &w[np + *n],
2153 &w[np + (*n << 1)], &w[np + *n * 3], &dsq, &crvmin);
2155 d__1 = delta, d__2 = sqrt(dsq);
2156 dnorm = min(d__1,d__2);
2157 if (dnorm < half * rho) {
2159 /* Computing 2nd power */
2161 distsq = d__1 * d__1;
2162 if (stop->nevals <= nfsav + 2) {
2166 /* The following choice between labels 650 and 680 depends on whether or */
2167 /* not our work with the current RHO seems to be complete. Either RHO is */
2168 /* decreased or termination occurs if the errors in the quadratic model at */
2169 /* the last three interpolation points compare favourably with predictions */
2170 /* of likely improvements to the model within distance HALF*RHO of XOPT. */
2173 d__1 = max(diffa,diffb);
2174 errbig = max(d__1,diffc);
2175 frhosq = rho * .125 * rho;
2176 if (crvmin > zero && errbig > frhosq * crvmin) {
2179 bdtol = errbig / rho;
2181 for (j = 1; j <= i__1; ++j) {
2183 if (xnew[j] == sl[j]) {
2186 if (xnew[j] == su[j]) {
2189 if (bdtest < bdtol) {
2190 curv = hq[(j + j * j) / 2];
2192 for (k = 1; k <= i__2; ++k) {
2194 /* Computing 2nd power */
2195 d__1 = xpt[k + j * xpt_dim1];
2196 curv += pq[k] * (d__1 * d__1);
2198 bdtest += half * curv * rho;
2199 if (bdtest < bdtol) {
2209 /* Severe cancellation is likely to occur if XOPT is too far from XBASE. */
2210 /* If the following test holds, then XBASE is shifted so that XOPT becomes */
2211 /* zero. The appropriate changes are made to BMAT and to the second */
2212 /* derivatives of the current model, beginning with the changes to BMAT */
2213 /* that do not depend on ZMAT. VLAG is used temporarily for working space. */
2216 if (dsq <= xoptsq * .001) {
2217 fracsq = xoptsq * .25;
2220 for (k = 1; k <= i__1; ++k) {
2222 sum = -half * xoptsq;
2224 for (i__ = 1; i__ <= i__2; ++i__) {
2226 sum += xpt[k + i__ * xpt_dim1] * xopt[i__];
2229 temp = fracsq - half * sum;
2231 for (i__ = 1; i__ <= i__2; ++i__) {
2232 w[i__] = bmat[k + i__ * bmat_dim1];
2233 vlag[i__] = sum * xpt[k + i__ * xpt_dim1] + temp * xopt[i__];
2236 for (j = 1; j <= i__3; ++j) {
2238 bmat[ip + j * bmat_dim1] = bmat[ip + j * bmat_dim1] + w[
2239 i__] * vlag[j] + vlag[i__] * w[j];
2244 /* Then the revisions of BMAT that depend on ZMAT are calculated. */
2247 for (jj = 1; jj <= i__3; ++jj) {
2251 for (k = 1; k <= i__2; ++k) {
2252 sumz += zmat[k + jj * zmat_dim1];
2253 vlag[k] = w[*npt + k] * zmat[k + jj * zmat_dim1];
2258 for (j = 1; j <= i__2; ++j) {
2259 sum = (fracsq * sumz - half * sumw) * xopt[j];
2261 for (k = 1; k <= i__1; ++k) {
2263 sum += vlag[k] * xpt[k + j * xpt_dim1];
2267 for (k = 1; k <= i__1; ++k) {
2269 bmat[k + j * bmat_dim1] += sum * zmat[k + jj * zmat_dim1];
2273 for (i__ = 1; i__ <= i__1; ++i__) {
2277 for (j = 1; j <= i__2; ++j) {
2279 bmat[ip + j * bmat_dim1] += temp * w[j];
2284 /* The following instructions complete the shift, including the changes */
2285 /* to the second derivative parameters of the quadratic model. */
2289 for (j = 1; j <= i__2; ++j) {
2290 w[j] = -half * sumpq * xopt[j];
2292 for (k = 1; k <= i__1; ++k) {
2293 w[j] += pq[k] * xpt[k + j * xpt_dim1];
2295 xpt[k + j * xpt_dim1] -= xopt[j];
2298 for (i__ = 1; i__ <= i__1; ++i__) {
2300 hq[ih] = hq[ih] + w[i__] * xopt[j] + xopt[i__] * w[j];
2302 bmat[*npt + i__ + j * bmat_dim1] = bmat[*npt + j + i__ *
2307 for (i__ = 1; i__ <= i__1; ++i__) {
2308 xbase[i__] += xopt[i__];
2309 xnew[i__] -= xopt[i__];
2310 sl[i__] -= xopt[i__];
2311 su[i__] -= xopt[i__];
2322 /* XBASE is also moved to XOPT by a call of RESCUE. This calculation is */
2323 /* more expensive than the previous shift, because new matrices BMAT and */
2324 /* ZMAT are generated from scratch, which may include the replacement of */
2325 /* interpolation points whose positions seem to be causing near linear */
2326 /* dependence in the interpolation conditions. Therefore RESCUE is called */
2327 /* only if rounding errors have reduced by at least a factor of two the */
2328 /* denominator of the formula for updating the H matrix. It provides a */
2329 /* useful safeguard, but is not invoked in most applications of BOBYQA. */
2332 nfsav = stop->nevals;
2334 rc2 = rescue_(n, npt, &xl[1], &xu[1],
2335 stop, calfun, calfun_data,
2336 &xbase[1], &xpt[xpt_offset], &fval[1], &xopt[1], &gopt[1],
2337 &hq[1], &pq[1], &bmat[bmat_offset], &zmat[zmat_offset], ndim,
2338 &sl[1], &su[1], &delta, &kopt, &vlag[1],
2339 &w[1], &w[*n + np], &w[*ndim + np]);
2341 /* XOPT is updated now in case the branch below to label 720 is taken. */
2342 /* Any updating of GOPT occurs after the branch below to label 20, which */
2343 /* leads to a trust region iteration as does the branch to label 60. */
2346 if (kopt != kbase) {
2348 for (i__ = 1; i__ <= i__1; ++i__) {
2349 xopt[i__] = xpt[kopt + i__ * xpt_dim1];
2351 /* Computing 2nd power */
2353 xoptsq += d__1 * d__1;
2356 if (rc2 != NLOPT_SUCCESS) {
2360 nresc = stop->nevals;
2361 if (nfsav < stop->nevals) {
2362 nfsav = stop->nevals;
2369 /* Pick two alternative vectors of variables, relative to XBASE, that */
2370 /* are suitable as new positions of the KNEW-th interpolation point. */
2371 /* Firstly, XNEW is set to the point on a line through XOPT and another */
2372 /* interpolation point that minimizes the predicted value of the next */
2373 /* denominator, subject to ||XNEW - XOPT|| .LEQ. ADELT and to the SL */
2374 /* and SU bounds. Secondly, XALT is set to the best feasible point on */
2375 /* a constrained version of the Cauchy step of the KNEW-th Lagrange */
2376 /* function, the corresponding value of the square of this function */
2377 /* being returned in CAUCHY. The choice between these alternatives is */
2378 /* going to be made when the denominator is calculated. */
2381 altmov_(n, npt, &xpt[xpt_offset], &xopt[1], &bmat[bmat_offset], &zmat[
2382 zmat_offset], ndim, &sl[1], &su[1], &kopt, &knew, &adelt, &xnew[1]
2383 , &xalt[1], &alpha, &cauchy, &w[1], &w[np], &w[*ndim + 1]);
2385 for (i__ = 1; i__ <= i__1; ++i__) {
2387 d__[i__] = xnew[i__] - xopt[i__];
2390 /* Calculate VLAG and BETA for the current choice of D. The scalar */
2391 /* product of D with XPT(K,.) is going to be held in W(NPT+K) for */
2392 /* use when VQUAD is calculated. */
2396 for (k = 1; k <= i__1; ++k) {
2401 for (j = 1; j <= i__2; ++j) {
2402 suma += xpt[k + j * xpt_dim1] * d__[j];
2403 sumb += xpt[k + j * xpt_dim1] * xopt[j];
2405 sum += bmat[k + j * bmat_dim1] * d__[j];
2407 w[k] = suma * (half * suma + sumb);
2414 for (jj = 1; jj <= i__1; ++jj) {
2417 for (k = 1; k <= i__2; ++k) {
2419 sum += zmat[k + jj * zmat_dim1] * w[k];
2423 for (k = 1; k <= i__2; ++k) {
2425 vlag[k] += sum * zmat[k + jj * zmat_dim1];
2432 for (j = 1; j <= i__2; ++j) {
2433 /* Computing 2nd power */
2438 for (k = 1; k <= i__1; ++k) {
2440 sum += w[k] * bmat[k + j * bmat_dim1];
2442 bsum += sum * d__[j];
2445 for (i__ = 1; i__ <= i__1; ++i__) {
2447 sum += bmat[jp + i__ * bmat_dim1] * d__[i__];
2450 bsum += sum * d__[j];
2452 dx += d__[j] * xopt[j];
2454 beta = dx * dx + dsq * (xoptsq + dx + dx + half * dsq) + beta - bsum;
2457 /* If NTRITS is zero, the denominator may be increased by replacing */
2458 /* the step D of ALTMOV by a Cauchy step. Then RESCUE may be called if */
2459 /* rounding errors have damaged the chosen denominator. */
2462 /* Computing 2nd power */
2464 denom = d__1 * d__1 + alpha * beta;
2465 if (denom < cauchy && cauchy > zero) {
2467 for (i__ = 1; i__ <= i__2; ++i__) {
2468 xnew[i__] = xalt[i__];
2470 d__[i__] = xnew[i__] - xopt[i__];
2475 /* Computing 2nd power */
2477 if (denom <= half * (d__1 * d__1)) {
2478 if (stop->nevals > nresc) {
2481 /* Return from BOBYQA because of much cancellation in a
2483 rc = NLOPT_ROUNDOFF_LIMITED;
2487 /* Alternatively, if NTRITS is positive, then set KNEW to the index of */
2488 /* the next interpolation point to be deleted to make room for a trust */
2489 /* region step. Again RESCUE may be called if rounding errors have damaged */
2490 /* the chosen denominator, which is the reason for attempting to select */
2491 /* KNEW before calculating the next value of the objective function. */
2494 delsq = delta * delta;
2499 for (k = 1; k <= i__2; ++k) {
2505 for (jj = 1; jj <= i__1; ++jj) {
2507 /* Computing 2nd power */
2508 d__1 = zmat[k + jj * zmat_dim1];
2509 hdiag += d__1 * d__1;
2511 /* Computing 2nd power */
2513 den = beta * hdiag + d__1 * d__1;
2516 for (j = 1; j <= i__1; ++j) {
2518 /* Computing 2nd power */
2519 d__1 = xpt[k + j * xpt_dim1] - xopt[j];
2520 distsq += d__1 * d__1;
2523 /* Computing 2nd power */
2524 d__3 = distsq / delsq;
2525 d__1 = one, d__2 = d__3 * d__3;
2526 temp = max(d__1,d__2);
2527 if (temp * den > scaden) {
2528 scaden = temp * den;
2533 /* Computing 2nd power */
2535 d__1 = biglsq, d__2 = temp * (d__3 * d__3);
2536 biglsq = max(d__1,d__2);
2540 if (scaden <= half * biglsq) {
2541 if (stop->nevals > nresc) {
2544 /* Return from BOBYQA because of much cancellation in a
2546 rc = NLOPT_ROUNDOFF_LIMITED;
2551 /* Put the variables for the next calculation of the objective function */
2552 /* in XNEW, with any adjustments for the bounds. */
2555 /* Calculate the value of the objective function at XBASE+XNEW, unless */
2556 /* the limit on the number of calculations of F has been reached. */
2560 for (i__ = 1; i__ <= i__2; ++i__) {
2563 d__3 = xl[i__], d__4 = xbase[i__] + xnew[i__];
2564 d__1 = max(d__3,d__4), d__2 = xu[i__];
2565 x[i__] = min(d__1,d__2);
2566 if (xnew[i__] == sl[i__]) {
2569 if (xnew[i__] == su[i__]) {
2575 if (nlopt_stop_forced(stop)) rc = NLOPT_FORCE_STOP;
2576 else if (nlopt_stop_evals(stop)) rc = NLOPT_MAXEVAL_REACHED;
2577 else if (nlopt_stop_time(stop)) rc = NLOPT_MAXTIME_REACHED;
2578 if (rc != NLOPT_SUCCESS) goto L720;
2581 f = calfun(*n, &x[1], calfun_data);
2584 rc = NLOPT_XTOL_REACHED;
2585 if (fsave < fval[kopt]) { *minf = f; return rc; }
2589 if (f < stop->minf_max) {
2591 return NLOPT_MINF_MAX_REACHED;
2594 /* Use the quadratic model to predict the change in F due to the step D, */
2595 /* and set DIFF to the error of this prediction. */
2601 for (j = 1; j <= i__2; ++j) {
2602 vquad += d__[j] * gopt[j];
2604 for (i__ = 1; i__ <= i__1; ++i__) {
2606 temp = d__[i__] * d__[j];
2611 vquad += hq[ih] * temp;
2615 for (k = 1; k <= i__1; ++k) {
2617 /* Computing 2nd power */
2619 vquad += half * pq[k] * (d__1 * d__1);
2621 diff = f - fopt - vquad;
2626 nfsav = stop->nevals;
2629 /* Pick the next value of DELTA after a trust region step. */
2632 if (vquad >= zero) {
2633 /* Return from BOBYQA because a trust region step has failed
2635 rc = NLOPT_ROUNDOFF_LIMITED; /* or FTOL_REACHED? */
2638 ratio = (f - fopt) / vquad;
2639 if (ratio <= tenth) {
2641 d__1 = half * delta;
2642 delta = min(d__1,dnorm);
2643 } else if (ratio <= .7) {
2645 d__1 = half * delta;
2646 delta = max(d__1,dnorm);
2649 d__1 = half * delta, d__2 = dnorm + dnorm;
2650 delta = max(d__1,d__2);
2652 if (delta <= rho * 1.5) {
2656 /* Recalculate KNEW and DENOM if the new F is less than FOPT. */
2661 delsq = delta * delta;
2666 for (k = 1; k <= i__1; ++k) {
2669 for (jj = 1; jj <= i__2; ++jj) {
2671 /* Computing 2nd power */
2672 d__1 = zmat[k + jj * zmat_dim1];
2673 hdiag += d__1 * d__1;
2675 /* Computing 2nd power */
2677 den = beta * hdiag + d__1 * d__1;
2680 for (j = 1; j <= i__2; ++j) {
2682 /* Computing 2nd power */
2683 d__1 = xpt[k + j * xpt_dim1] - xnew[j];
2684 distsq += d__1 * d__1;
2687 /* Computing 2nd power */
2688 d__3 = distsq / delsq;
2689 d__1 = one, d__2 = d__3 * d__3;
2690 temp = max(d__1,d__2);
2691 if (temp * den > scaden) {
2692 scaden = temp * den;
2698 /* Computing 2nd power */
2700 d__1 = biglsq, d__2 = temp * (d__3 * d__3);
2701 biglsq = max(d__1,d__2);
2703 if (scaden <= half * biglsq) {
2710 /* Update BMAT and ZMAT, so that the KNEW-th interpolation point can be */
2711 /* moved. Also update the second derivative terms of the model. */
2713 update_(n, npt, &bmat[bmat_offset], &zmat[zmat_offset], ndim, &vlag[1], &
2714 beta, &denom, &knew, &w[1]);
2719 for (i__ = 1; i__ <= i__1; ++i__) {
2720 temp = pqold * xpt[knew + i__ * xpt_dim1];
2722 for (j = 1; j <= i__2; ++j) {
2725 hq[ih] += temp * xpt[knew + j * xpt_dim1];
2729 for (jj = 1; jj <= i__2; ++jj) {
2730 temp = diff * zmat[knew + jj * zmat_dim1];
2732 for (k = 1; k <= i__1; ++k) {
2734 pq[k] += temp * zmat[k + jj * zmat_dim1];
2738 /* Include the new interpolation point, and make the changes to GOPT at */
2739 /* the old XOPT that are caused by the updating of the quadratic model. */
2743 for (i__ = 1; i__ <= i__1; ++i__) {
2744 xpt[knew + i__ * xpt_dim1] = xnew[i__];
2746 w[i__] = bmat[knew + i__ * bmat_dim1];
2749 for (k = 1; k <= i__1; ++k) {
2752 for (jj = 1; jj <= i__2; ++jj) {
2754 suma += zmat[knew + jj * zmat_dim1] * zmat[k + jj * zmat_dim1];
2756 if (nlopt_isinf(suma)) {
2757 /* SGJ: detect singularity here (happend if we run
2758 for too many iterations) ... is there another way to recover? */
2759 rc = NLOPT_ROUNDOFF_LIMITED;
2764 for (j = 1; j <= i__2; ++j) {
2766 sumb += xpt[k + j * xpt_dim1] * xopt[j];
2770 for (i__ = 1; i__ <= i__2; ++i__) {
2772 w[i__] += temp * xpt[k + i__ * xpt_dim1];
2776 for (i__ = 1; i__ <= i__2; ++i__) {
2778 gopt[i__] += diff * w[i__];
2781 /* Update XOPT, GOPT and KOPT if the new calculated F is less than FOPT. */
2788 for (j = 1; j <= i__2; ++j) {
2790 /* Computing 2nd power */
2792 xoptsq += d__1 * d__1;
2794 for (i__ = 1; i__ <= i__1; ++i__) {
2797 gopt[j] += hq[ih] * d__[i__];
2800 gopt[i__] += hq[ih] * d__[j];
2804 for (k = 1; k <= i__1; ++k) {
2807 for (j = 1; j <= i__2; ++j) {
2809 temp += xpt[k + j * xpt_dim1] * d__[j];
2811 temp = pq[k] * temp;
2813 for (i__ = 1; i__ <= i__2; ++i__) {
2815 gopt[i__] += temp * xpt[k + i__ * xpt_dim1];
2818 if (nlopt_stop_ftol(stop, f, fopt)) {
2819 rc = NLOPT_FTOL_REACHED;
2824 /* Calculate the parameters of the least Frobenius norm interpolant to */
2825 /* the current data, the gradient of this interpolant at XOPT being put */
2826 /* into VLAG(NPT+I), I=1,2,...,N. */
2830 for (k = 1; k <= i__2; ++k) {
2831 vlag[k] = fval[k] - fval[kopt];
2836 for (j = 1; j <= i__2; ++j) {
2839 for (k = 1; k <= i__1; ++k) {
2841 sum += zmat[k + j * zmat_dim1] * vlag[k];
2844 for (k = 1; k <= i__1; ++k) {
2846 w[k] += sum * zmat[k + j * zmat_dim1];
2850 for (k = 1; k <= i__1; ++k) {
2853 for (j = 1; j <= i__2; ++j) {
2855 sum += xpt[k + j * xpt_dim1] * xopt[j];
2864 for (i__ = 1; i__ <= i__1; ++i__) {
2867 for (k = 1; k <= i__2; ++k) {
2869 sum = sum + bmat[k + i__ * bmat_dim1] * vlag[k] + xpt[k + i__
2872 if (xopt[i__] == sl[i__]) {
2874 d__2 = zero, d__3 = gopt[i__];
2875 /* Computing 2nd power */
2876 d__1 = min(d__2,d__3);
2877 gqsq += d__1 * d__1;
2878 /* Computing 2nd power */
2879 d__1 = min(zero,sum);
2880 gisq += d__1 * d__1;
2881 } else if (xopt[i__] == su[i__]) {
2883 d__2 = zero, d__3 = gopt[i__];
2884 /* Computing 2nd power */
2885 d__1 = max(d__2,d__3);
2886 gqsq += d__1 * d__1;
2887 /* Computing 2nd power */
2888 d__1 = max(zero,sum);
2889 gisq += d__1 * d__1;
2891 /* Computing 2nd power */
2893 gqsq += d__1 * d__1;
2897 vlag[*npt + i__] = sum;
2900 /* Test whether to replace the new quadratic model by the least Frobenius */
2901 /* norm interpolant, making the replacement if the test is satisfied. */
2904 if (gqsq < ten * gisq) {
2908 i__1 = max(*npt,nh);
2909 for (i__ = 1; i__ <= i__1; ++i__) {
2911 gopt[i__] = vlag[*npt + i__];
2914 pq[i__] = w[*npt + i__];
2925 /* If a trust region step has provided a sufficient decrease in F, then */
2926 /* branch for another trust region calculation. The case NTRITS=0 occurs */
2927 /* when the new interpolation point was reached by an alternative step. */
2932 if (f <= fopt + tenth * vquad) {
2936 /* Alternatively, find out if the interpolation points are close enough */
2937 /* to the best point so far. */
2940 /* Computing 2nd power */
2942 /* Computing 2nd power */
2944 d__1 = d__3 * d__3, d__2 = d__4 * d__4;
2945 distsq = max(d__1,d__2);
2949 for (k = 1; k <= i__1; ++k) {
2952 for (j = 1; j <= i__2; ++j) {
2954 /* Computing 2nd power */
2955 d__1 = xpt[k + j * xpt_dim1] - xopt[j];
2965 /* If KNEW is positive, then ALTMOV finds alternative new positions for */
2966 /* the KNEW-th interpolation point within distance ADELT of XOPT. It is */
2967 /* reached via label 90. Otherwise, there is a branch to label 60 for */
2968 /* another trust region iteration, unless the calculations with the */
2969 /* current RHO are complete. */
2972 dist = sqrt(distsq);
2975 d__1 = tenth * delta, d__2 = half * dist;
2976 delta = min(d__1,d__2);
2977 if (delta <= rho * 1.5) {
2984 d__2 = tenth * dist;
2985 d__1 = min(d__2,delta);
2986 adelt = max(d__1,rho);
2987 dsq = adelt * adelt;
2996 if (max(delta,dnorm) > rho) {
3000 /* The calculations with the current value of RHO are complete. Pick the */
3001 /* next values of RHO and DELTA. */
3004 if (rho > *rhoend) {
3006 ratio = rho / *rhoend;
3009 } else if (ratio <= 250.) {
3010 rho = sqrt(ratio) * *rhoend;
3014 delta = max(delta,rho);
3016 nfsav = stop->nevals;
3020 /* Return from the calculation, after another Newton-Raphson step, if */
3021 /* it is too short to have been tried before. */
3027 /* originally: if (fval[kopt] <= fsave) -- changed by SGJ, since
3028 this seems like a slight optimization to not update x[]
3029 unnecessarily, at the expense of possibly not returning the
3030 best x[] found so far if the algorithm is stopped suddenly
3031 (e.g. runs out of time) ... it seems safer to execute this
3032 unconditionally, and the efficiency loss seems negligible. */
3035 for (i__ = 1; i__ <= i__1; ++i__) {
3038 d__3 = xl[i__], d__4 = xbase[i__] + xopt[i__];
3039 d__1 = max(d__3,d__4), d__2 = xu[i__];
3040 x[i__] = min(d__1,d__2);
3041 if (xopt[i__] == sl[i__]) {
3044 if (xopt[i__] == su[i__]) {
3055 /**************************************************************************/
3057 nlopt_result bobyqa(int n, int npt, double *x,
3058 const double *xl, const double *xu, double rhobeg,
3059 nlopt_stopping *stop, double *minf,
3060 bobyqa_func calfun, void *calfun_data)
3062 /* System generated locals */
3066 /* Local variables */
3067 int j, id, np, iw, igo, ihq, ixb, ixa, ifv, isl, jsl, ipq, ivl, ixn,
3068 ixo, ixp, isu, jsu, ndim;
3076 /* SGJ, 2009: compute rhoend from NLopt stop info */
3077 rhoend = stop->xtol_rel * (rhobeg);
3078 for (j = 0; j < n; ++j)
3079 if (rhoend < stop->xtol_abs[j])
3080 rhoend = stop->xtol_abs[j];
3083 /* This subroutine seeks the least value of a function of many variables, */
3084 /* by applying a trust region method that forms quadratic models by */
3085 /* interpolation. There is usually some freedom in the interpolation */
3086 /* conditions, which is taken up by minimizing the Frobenius norm of */
3087 /* the change to the second derivative of the model, beginning with the */
3088 /* zero matrix. The values of the variables are constrained by upper and */
3089 /* lower bounds. The arguments of the subroutine are as follows. */
3091 /* N must be set to the number of variables and must be at least two. */
3092 /* NPT is the number of interpolation conditions. Its value must be in */
3093 /* the interval [N+2,(N+1)(N+2)/2]. Choices that exceed 2*N+1 are not */
3095 /* Initial values of the variables must be set in X(1),X(2),...,X(N). They */
3096 /* will be changed to the values that give the least calculated F. */
3097 /* For I=1,2,...,N, XL(I) and XU(I) must provide the lower and upper */
3098 /* bounds, respectively, on X(I). The construction of quadratic models */
3099 /* requires XL(I) to be strictly less than XU(I) for each I. Further, */
3100 /* the contribution to a model from changes to the I-th variable is */
3101 /* damaged severely by rounding errors if XU(I)-XL(I) is too small. */
3102 /* RHOBEG and RHOEND must be set to the initial and final values of a trust */
3103 /* region radius, so both must be positive with RHOEND no greater than */
3104 /* RHOBEG. Typically, RHOBEG should be about one tenth of the greatest */
3105 /* expected change to a variable, while RHOEND should indicate the */
3106 /* accuracy that is required in the final values of the variables. An */
3107 /* error return occurs if any of the differences XU(I)-XL(I), I=1,...,N, */
3108 /* is less than 2*RHOBEG. */
3109 /* MAXFUN must be set to an upper bound on the number of calls of CALFUN. */
3110 /* The array W will be used for working space. Its length must be at least */
3111 /* (NPT+5)*(NPT+N)+3*N*(N+5)/2. */
3113 /* SUBROUTINE CALFUN (N,X,F) has to be provided by the user. It must set */
3114 /* F to the value of the objective function for the current values of the */
3115 /* variables X(1),X(2),...,X(N), which are generated automatically in a */
3116 /* way that satisfies the bounds given in XL and XU. */
3118 /* Return if the value of NPT is unacceptable. */
3120 /* Parameter adjustments */
3127 if (npt < n + 2 || npt > (n + 2) * np / 2) {
3128 /* Return from BOBYQA because NPT is not in the required interval */
3129 return NLOPT_INVALID_ARGS;
3132 /* Partition the working space array, so that different parts of it can */
3133 /* be treated separately during the calculation of BOBYQB. The partition */
3134 /* requires the first (NPT+2)*(NPT+N)+3*N*(N+5)/2 elements of W plus the */
3135 /* space that is taken by the last array in the argument list of BOBYQB. */
3140 ifv = ixp + n * npt;
3144 ipq = ihq + n * np / 2;
3146 izmat = ibmat + ndim * n;
3147 isl = izmat + npt * (npt - np);
3155 w = (double *) malloc(sizeof(double) * ((npt+5)*(npt+n)+3*n*(n+5)/2));
3156 if (!w) return NLOPT_OUT_OF_MEMORY;
3159 /* Return if there is insufficient space between the bounds. Modify the */
3160 /* initial X if necessary in order to avoid conflicts between the bounds */
3161 /* and the construction of the first quadratic model. The lower and upper */
3162 /* bounds on moves from the updated X are set now, in the ISL and ISU */
3163 /* partitions of W, in order to provide useful and exact information about */
3164 /* components of X that become within distance RHOBEG from their bounds. */
3168 for (j = 1; j <= i__1; ++j) {
3169 temp = xu[j] - xl[j];
3170 if (temp < rhobeg + rhobeg) {
3171 /* Return from BOBYQA because one of the differences
3172 XU(I)-XL(I)s is less than 2*RHOBEG. */
3174 return NLOPT_INVALID_ARGS;
3178 w[jsl] = xl[j] - x[j];
3179 w[jsu] = xu[j] - x[j];
3180 if (w[jsl] >= -(rhobeg)) {
3181 if (w[jsl] >= zero) {
3186 x[j] = xl[j] + rhobeg;
3189 d__1 = xu[j] - x[j];
3190 w[jsu] = max(d__1,rhobeg);
3192 } else if (w[jsu] <= rhobeg) {
3193 if (w[jsu] <= zero) {
3198 x[j] = xu[j] - rhobeg;
3200 d__1 = xl[j] - x[j], d__2 = -(rhobeg);
3201 w[jsl] = min(d__1,d__2);
3208 /* Make the call of BOBYQB. */
3210 ret = bobyqb_(&n, &npt, &x[1], &xl[1], &xu[1], &rhobeg, &rhoend,
3211 stop, calfun, calfun_data, minf,
3212 &w[ixb], &w[ixp], &w[ifv], &w[ixo], &w[igo], &w[ihq], &w[ipq],
3213 &w[ibmat], &w[izmat], &ndim, &w[isl], &w[isu], &w[ixn], &w[ixa],
3214 &w[id], &w[ivl], &w[iw]);