MoDeNa  1.0
Software framework facilitating sequential multi-scale modelling
powell_minimize.f90
1 MODULE powell_optimize
2 
3 ! Code converted using TO_F90 by Alan Miller
4 ! Date: 2002-11-09 Time: 16:58:08
5 
6 IMPLICIT NONE
7 !INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(15, 307)
8 
9 PRIVATE
10 PUBLIC :: uobyqa
11 
12 
13 CONTAINS
14 
15 
16 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% uobyqa.f %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
17 
18 SUBROUTINE uobyqa(n, x, rhobeg, rhoend, iprint, maxfun)
19 
20 INTEGER, INTENT(IN) :: n
21 REAL, INTENT(IN OUT) :: x(:)
22 REAL, INTENT(IN) :: rhobeg
23 REAL, INTENT(IN) :: rhoend
24 INTEGER, INTENT(IN) :: iprint
25 INTEGER, INTENT(IN) :: maxfun
26 
27 ! This subroutine seeks the least value of a function of many variables,
28 ! by a trust region method that forms quadratic models by interpolation.
29 ! The algorithm is described in "UOBYQA: unconstrained optimization by
30 ! quadratic approximation" by M.J.D. Powell, Report DAMTP 2000/NA14,
31 ! University of Cambridge. The arguments of the subroutine are as follows.
32 
33 ! N must be set to the number of variables and must be at least two.
34 ! Initial values of the variables must be set in X(1),X(2),...,X(N). They
35 ! will be changed to the values that give the least calculated F.
36 ! RHOBEG and RHOEND must be set to the initial and final values of a trust
37 ! region radius, so both must be positive with RHOEND<=RHOBEG. Typically
38 ! RHOBEG should be about one tenth of the greatest expected change to a
39 ! variable, and RHOEND should indicate the accuracy that is required in
40 ! the final values of the variables.
41 ! The value of IPRINT should be set to 0, 1, 2 or 3, which controls the
42 ! amount of printing. Specifically, there is no output if IPRINT=0 and
43 ! there is output only at the return if IPRINT=1. Otherwise, each new
44 ! value of RHO is printed, with the best vector of variables so far and
45 ! the corresponding value of the objective function. Further, each new
46 ! value of F with its variables are output if IPRINT=3.
47 ! MAXFUN must be set to an upper bound on the number of calls of CALFUN.
48 ! The array W will be used for working space. Its length must be at least
49 ! ( N**4 + 8*N**3 + 23*N**2 + 42*N + max [ 2*N**2 + 4, 18*N ] ) / 4.
50 
51 ! SUBROUTINE CALFUN (N,X,F) must be provided by the user. It must set F to
52 ! the value of the objective function for the variables X(1),X(2),...,X(N).
53 
54 INTEGER :: npt
55 
56 ! Partition the working space array, so that different parts of it can be
57 ! treated separately by the subroutine that performs the main calculation.
58 
59 npt = (n*n + 3*n + 2) / 2
60 CALL uobyqb(n, x, rhobeg, rhoend, iprint, maxfun, npt)
61 RETURN
62 END SUBROUTINE uobyqa
63 
64 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% uobyqb.f %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65 
66 SUBROUTINE uobyqb(n, x, rhobeg, rhoend, iprint, maxfun, npt)
67 
68 INTEGER, INTENT(IN) :: n
69 REAL, INTENT(IN OUT) :: x(:)
70 REAL, INTENT(IN) :: rhobeg
71 REAL, INTENT(IN) :: rhoend
72 INTEGER, INTENT(IN) :: iprint
73 INTEGER, INTENT(IN) :: maxfun
74 INTEGER, INTENT(IN) :: npt
75 
76 INTERFACE
77  SUBROUTINE calfun(n, x, f)
78  IMPLICIT NONE
79  INTEGER, PARAMETER :: dp = selected_real_kind(15, 307)
80  INTEGER, INTENT(IN) :: n
81  REAL, INTENT(IN) :: x(:)
82  REAL, INTENT(OUT) :: f
83  END SUBROUTINE calfun
84 END INTERFACE
85 
86 ! The following arrays were previously passed as arguments:
87 
88 REAL :: xbase(n), xopt(n), xnew(n), xpt(npt,n), pq(npt-1)
89 REAL :: pl(npt,npt-1), h(n,n), g(n), d(n), vlag(npt), w(npt)
90 
91 ! The arguments N, X, RHOBEG, RHOEND, IPRINT and MAXFUN are identical to
92 ! the corresponding arguments in SUBROUTINE UOBYQA.
93 
94 ! NPT is set by UOBYQA to (N*N+3*N+2)/2 for the above dimension statement.
95 ! XBASE will contain a shift of origin that reduces the contributions from
96 ! rounding errors to values of the model and Lagrange functions.
97 ! XOPT will be set to the displacement from XBASE of the vector of
98 ! variables that provides the least calculated F so far.
99 ! XNEW will be set to the displacement from XBASE of the vector of
100 ! variables for the current calculation of F.
101 ! XPT will contain the interpolation point coordinates relative to XBASE.
102 ! PQ will contain the parameters of the quadratic model.
103 ! PL will contain the parameters of the Lagrange functions.
104 ! H will provide the second derivatives that TRSTEP and LAGMAX require.
105 ! G will provide the first derivatives that TRSTEP and LAGMAX require.
106 ! D is reserved for trial steps from XOPT, except that it will contain
107 ! diagonal second derivatives during the initialization procedure.
108 ! VLAG will contain the values of the Lagrange functions at a new point X.
109 ! The array W will be used for working space.
110 
111 REAL :: half = 0.5_dp, one = 1.0_dp, tol = 0.01_dp, two = 2.0_dp
112 REAL :: zero = 0.0_dp
113 REAL :: ddknew, delta, detrat, diff, distest, dnorm, errtol, estim
114 REAL :: evalue, f, fbase, fopt, fsave, ratio, rho, rhosq, sixthm
115 REAL :: sum, sumg, sumh, temp, tempa, tworsq, vmax, vquad, wmult
116 INTEGER :: i, ih, ip, iq, iw, j, jswitch, k, knew, kopt, ksave, ktemp
117 INTEGER :: nf, nftest, nnp, nptm
118 
119 ! Set some constants.
120 
121 nnp = n + n + 1
122 nptm = npt - 1
123 nftest = max(maxfun,1)
124 
125 ! Initialization. NF is the number of function calculations so far.
126 
127 rho = rhobeg
128 rhosq = rho * rho
129 nf = 0
130 DO i = 1, n
131  xbase(i) = x(i)
132  xpt(1:npt,i) = zero
133 END DO
134 pl(1:npt,1:nptm) = zero
135 
136 ! The branch to label 120 obtains a new value of the objective function
137 ! and then there is a branch back to label 50, because the new function
138 ! value is needed to form the initial quadratic model. The least function
139 ! value so far and its index are noted below.
140 
141 50 x(1:n) = xbase(1:n) + xpt(nf+1,1:n)
142 GO TO 150
143 
144 70 IF (nf == 1) THEN
145  fopt = f
146  kopt = nf
147  fbase = f
148  j = 0
149  jswitch = -1
150  ih = n
151 ELSE
152  IF (f < fopt) THEN
153  fopt = f
154  kopt = nf
155  END IF
156 END IF
157 
158 ! Form the gradient and diagonal second derivatives of the initial
159 ! quadratic model and Lagrange functions.
160 
161 IF (nf <= nnp) THEN
162  jswitch = -jswitch
163  IF (jswitch > 0) THEN
164  IF (j >= 1) THEN
165  ih = ih + j
166  IF (w(j) < zero) THEN
167  d(j) = (fsave+f-two*fbase) / rhosq
168  pq(j) = (fsave-f) / (two*rho)
169  pl(1,ih) = -two / rhosq
170  pl(nf-1,j) = half / rho
171  pl(nf-1,ih) = one / rhosq
172  ELSE
173  pq(j) = (4.0d0*fsave-3.0d0*fbase-f) / (two*rho)
174  d(j) = (fbase+f-two*fsave) / rhosq
175  pl(1,j) = -1.5d0 / rho
176  pl(1,ih) = one / rhosq
177  pl(nf-1,j) = two / rho
178  pl(nf-1,ih) = -two / rhosq
179  END IF
180  pq(ih) = d(j)
181  pl(nf,j) = -half / rho
182  pl(nf,ih) = one / rhosq
183  END IF
184 
185 ! Pick the shift from XBASE to the next initial interpolation point
186 ! that provides diagonal second derivatives.
187 
188  IF (j < n) THEN
189  j = j + 1
190  xpt(nf+1,j) = rho
191  END IF
192  ELSE
193  fsave = f
194  IF (f < fbase) THEN
195  w(j) = rho
196  xpt(nf+1,j) = two * rho
197  ELSE
198  w(j) = -rho
199  xpt(nf+1,j) = -rho
200  END IF
201  END IF
202  IF (nf < nnp) GO TO 50
203 
204 ! Form the off-diagonal second derivatives of the initial quadratic model.
205 
206  ih = n
207  ip = 1
208  iq = 2
209 END IF
210 ih = ih + 1
211 IF (nf > nnp) THEN
212  temp = one / (w(ip)*w(iq))
213  tempa = f - fbase - w(ip) * pq(ip) - w(iq) * pq(iq)
214  pq(ih) = (tempa - half*rhosq*(d(ip)+d(iq))) * temp
215  pl(1,ih) = temp
216  iw = ip + ip
217  IF (w(ip) < zero) iw = iw + 1
218  pl(iw,ih) = -temp
219  iw = iq + iq
220  IF (w(iq) < zero) iw = iw + 1
221  pl(iw,ih) = -temp
222  pl(nf,ih) = temp
223 
224 ! Pick the shift from XBASE to the next initial interpolation point
225 ! that provides off-diagonal second derivatives.
226 
227  ip = ip + 1
228 END IF
229 IF (ip == iq) THEN
230  ih = ih + 1
231  ip = 1
232  iq = iq + 1
233 END IF
234 IF (nf < npt) THEN
235  xpt(nf+1,ip) = w(ip)
236  xpt(nf+1,iq) = w(iq)
237  GO TO 50
238 END IF
239 
240 ! Set parameters to begin the iterations for the current RHO.
241 
242 sixthm = zero
243 delta = rho
244 80 tworsq = (two*rho) ** 2
245 rhosq = rho * rho
246 
247 ! Form the gradient of the quadratic model at the trust region centre.
248 
249 90 knew = 0
250 ih = n
251 DO j = 1, n
252  xopt(j) = xpt(kopt,j)
253  g(j) = pq(j)
254  DO i = 1, j
255  ih = ih + 1
256  g(i) = g(i) + pq(ih) * xopt(j)
257  IF (i < j) g(j) = g(j) + pq(ih) * xopt(i)
258  h(i,j) = pq(ih)
259  END DO
260 END DO
261 
262 ! Generate the next trust region step and test its length. Set KNEW
263 ! to -1 if the purpose of the next F will be to improve conditioning,
264 ! and also calculate a lower bound on the Hessian term of the model Q.
265 
266 CALL trstep(n, g, h, delta, tol, d, evalue)
267 temp = zero
268 DO i = 1, n
269  temp = temp + d(i)**2
270 END DO
271 dnorm = min(delta,sqrt(temp))
272 errtol = -one
273 IF (dnorm < half*rho) THEN
274  knew = -1
275  errtol = half * evalue * rho * rho
276  IF (nf <= npt+9) errtol = zero
277  GO TO 290
278 END IF
279 
280 ! Calculate the next value of the objective function.
281 
282 130 DO i = 1, n
283  xnew(i) = xopt(i) + d(i)
284  x(i) = xbase(i) + xnew(i)
285 END DO
286 150 IF (nf >= nftest) THEN
287  IF (iprint > 0) WRITE(*, 5000)
288  GO TO 420
289 END IF
290 nf = nf + 1
291 CALL calfun(n, x, f)
292 IF (iprint == 3) THEN
293  WRITE(*, 5100) nf, f, x(1:n)
294 END IF
295 IF (nf <= npt) GO TO 70
296 IF (knew == -1) GO TO 420
297 
298 ! Use the quadratic model to predict the change in F due to the step D,
299 ! and find the values of the Lagrange functions at the new point.
300 
301 vquad = zero
302 ih = n
303 DO j = 1, n
304  w(j) = d(j)
305  vquad = vquad + w(j) * pq(j)
306  DO i = 1, j
307  ih = ih + 1
308  w(ih) = d(i) * xnew(j) + d(j) * xopt(i)
309  IF (i == j) w(ih) = half * w(ih)
310  vquad = vquad + w(ih) * pq(ih)
311  END DO
312 END DO
313 DO k = 1, npt
314  temp = zero
315  DO j = 1, nptm
316  temp = temp + w(j) * pl(k,j)
317  END DO
318  vlag(k) = temp
319 END DO
320 vlag(kopt) = vlag(kopt) + one
321 
322 ! Update SIXTHM, which is a lower bound on one sixth of the greatest
323 ! third derivative of F.
324 
325 diff = f - fopt - vquad
326 sum = zero
327 DO k = 1, npt
328  temp = zero
329  DO i = 1, n
330  temp = temp + (xpt(k,i)-xnew(i)) ** 2
331  END DO
332  temp = sqrt(temp)
333  sum = sum + abs(temp*temp*temp*vlag(k))
334 END DO
335 sixthm = max(sixthm, abs(diff)/sum)
336 
337 ! Update FOPT and XOPT if the new F is the least value of the objective
338 ! function so far. Then branch if D is not a trust region step.
339 
340 fsave = fopt
341 IF (f < fopt) THEN
342  fopt = f
343  xopt(1:n) = xnew(1:n)
344 END IF
345 ksave = knew
346 IF (knew <= 0) THEN
347 
348 ! Pick the next value of DELTA after a trust region step.
349 
350  IF (vquad >= zero) THEN
351  IF (iprint > 0) WRITE(*, 5200)
352  GO TO 420
353  END IF
354  ratio = (f-fsave) / vquad
355  IF (ratio <= 0.1d0) THEN
356  delta = half * dnorm
357  ELSE IF (ratio <= 0.7d0) THEN
358  delta = max(half*delta,dnorm)
359  ELSE
360  delta = max(delta, 1.25d0*dnorm, dnorm+rho)
361  END IF
362  IF (delta <= 1.5d0*rho) delta = rho
363 
364 ! Set KNEW to the index of the next interpolation point to be deleted.
365 
366  ktemp = 0
367  detrat = zero
368  IF (f >= fsave) THEN
369  ktemp = kopt
370  detrat = one
371  END IF
372  DO k = 1, npt
373  sum = zero
374  DO i = 1, n
375  sum = sum + (xpt(k,i)-xopt(i)) ** 2
376  END DO
377  temp = abs(vlag(k))
378  IF (sum > rhosq) temp = temp * (sum/rhosq) ** 1.5d0
379  IF (temp > detrat .AND. k /= ktemp) THEN
380  detrat = temp
381  ddknew = sum
382  knew = k
383  END IF
384  END DO
385  IF (knew == 0) GO TO 290
386 END IF
387 
388 ! Replace the interpolation point that has index KNEW by the point XNEW,
389 ! and also update the Lagrange functions and the quadratic model.
390 
391 DO i = 1, n
392  xpt(knew,i) = xnew(i)
393 END DO
394 temp = one / vlag(knew)
395 DO j = 1, nptm
396  pl(knew,j) = temp * pl(knew,j)
397  pq(j) = pq(j) + diff * pl(knew,j)
398 END DO
399 DO k = 1, npt
400  IF (k /= knew) THEN
401  temp = vlag(k)
402  DO j = 1, nptm
403  pl(k,j) = pl(k,j) - temp * pl(knew,j)
404  END DO
405  END IF
406 END DO
407 
408 ! Update KOPT if F is the least calculated value of the objective function.
409 ! Then branch for another trust region calculation. The case KSAVE > 0
410 ! indicates that a model step has just been taken.
411 
412 IF (f < fsave) THEN
413  kopt = knew
414  GO TO 90
415 END IF
416 IF (ksave > 0) GO TO 90
417 IF (dnorm > two*rho) GO TO 90
418 IF (ddknew > tworsq) GO TO 90
419 
420 ! Alternatively, find out if the interpolation points are close
421 ! enough to the best point so far.
422 
423 290 DO k = 1, npt
424  w(k) = zero
425  DO i = 1, n
426  w(k) = w(k) + (xpt(k,i)-xopt(i)) ** 2
427  END DO
428 END DO
429 320 knew = -1
430 distest = tworsq
431 DO k = 1, npt
432  IF (w(k) > distest) THEN
433  knew = k
434  distest = w(k)
435  END IF
436 END DO
437 
438 ! If a point is sufficiently far away, then set the gradient and Hessian
439 ! of its Lagrange function at the centre of the trust region, and find
440 ! half the sum of squares of components of the Hessian.
441 
442 IF (knew > 0) THEN
443  ih = n
444  sumh = zero
445  DO j = 1, n
446  g(j) = pl(knew,j)
447  DO i = 1, j
448  ih = ih + 1
449  temp = pl(knew,ih)
450  g(j) = g(j) + temp * xopt(i)
451  IF (i < j) THEN
452  g(i) = g(i) + temp * xopt(j)
453  sumh = sumh + temp * temp
454  END IF
455  h(i,j) = temp
456  END DO
457  sumh = sumh + half * temp * temp
458  END DO
459 
460 ! If ERRTOL is positive, test whether to replace the interpolation point
461 ! with index KNEW, using a bound on the maximum modulus of its Lagrange
462 ! function in the trust region.
463 
464  IF (errtol > zero) THEN
465  w(knew) = zero
466  sumg = zero
467  DO i = 1, n
468  sumg = sumg + g(i) ** 2
469  END DO
470  estim = rho * (sqrt(sumg)+rho*sqrt(half*sumh))
471  wmult = sixthm * distest ** 1.5d0
472  IF (wmult*estim <= errtol) GO TO 320
473  END IF
474 
475 ! If the KNEW-th point may be replaced, then pick a D that gives a large
476 ! value of the modulus of its Lagrange function within the trust region.
477 ! Here the vector XNEW is used as temporary working space.
478 
479  CALL lagmax(n, g, h, rho, d, xnew, vmax)
480  IF (errtol > zero) THEN
481  IF (wmult*vmax <= errtol) GO TO 320
482  END IF
483  GO TO 130
484 END IF
485 IF (dnorm > rho) GO TO 90
486 
487 ! Prepare to reduce RHO by shifting XBASE to the best point so far,
488 ! and make the corresponding changes to the gradients of the Lagrange
489 ! functions and the quadratic model.
490 
491 IF (rho > rhoend) THEN
492  ih = n
493  DO j = 1, n
494  xbase(j) = xbase(j) + xopt(j)
495  DO k = 1, npt
496  xpt(k,j) = xpt(k,j) - xopt(j)
497  END DO
498  DO i = 1, j
499  ih = ih + 1
500  pq(i) = pq(i) + pq(ih) * xopt(j)
501  IF (i < j) THEN
502  pq(j) = pq(j) + pq(ih) * xopt(i)
503  DO k = 1, npt
504  pl(k,j) = pl(k,j) + pl(k,ih) * xopt(i)
505  END DO
506  END IF
507  DO k = 1, npt
508  pl(k,i) = pl(k,i) + pl(k,ih) * xopt(j)
509  END DO
510  END DO
511  END DO
512 
513 ! Pick the next values of RHO and DELTA.
514 
515  delta = half * rho
516  ratio = rho / rhoend
517  IF (ratio <= 16.0d0) THEN
518  rho = rhoend
519  ELSE IF (ratio <= 250.0d0) THEN
520  rho = sqrt(ratio) * rhoend
521  ELSE
522  rho = 0.1d0 * rho
523  END IF
524  delta = max(delta,rho)
525  IF (iprint >= 2) THEN
526  IF (iprint >= 3) WRITE(*, 5300)
527  WRITE(*, 5400) rho, nf
528  WRITE(*, 5500) fopt, xbase(1:n)
529  END IF
530  GO TO 80
531 END IF
532 
533 ! Return from the calculation, after another Newton-Raphson step, if
534 ! it is too short to have been tried before.
535 
536 IF (errtol >= zero) GO TO 130
537 420 IF (fopt <= f) THEN
538  DO i = 1, n
539  x(i) = xbase(i) + xopt(i)
540  END DO
541  f = fopt
542 END IF
543 IF (iprint >= 1) THEN
544  WRITE(*, 5600) nf
545  WRITE(*, 5500) f, x(1:n)
546 END IF
547 RETURN
548 
549 5000 FORMAT (/t5, 'Return from UOBYQA because CALFUN has been', &
550  ' called MAXFUN times')
551 5100 FORMAT (/t5, 'Function number',i6,' F =', g18.10, &
552  ' The corresponding X is:'/ (t3, 5g15.6))
553 5200 FORMAT (/t5, 'Return from UOBYQA because a trust', &
554  ' region step has failed to reduce Q')
555 5300 FORMAT (' ')
556 5400 FORMAT (/t5, 'New RHO =', g11.4, ' Number of function values =',i6)
557 5500 FORMAT (t5, 'Least value of F =', g23.15, &
558  ' The corresponding X is:'/ (t3, 5g15.6))
559 5600 FORMAT (/t5, 'At the return from UOBYQA', &
560  ' Number of function values =', i6)
561 END SUBROUTINE uobyqb
562 
563 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% trstep.f %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
564 
565 SUBROUTINE trstep(n, g, h, delta, tol, d, evalue)
566 
567 INTEGER, INTENT(IN) :: n
568 REAL, INTENT(IN) :: g(:)
569 REAL, INTENT(IN OUT) :: h(:,:)
570 REAL, INTENT(IN) :: delta
571 REAL, INTENT(IN) :: tol
572 REAL, INTENT(OUT) :: d(:)
573 REAL, INTENT(OUT) :: evalue
574 
575 ! N is the number of variables of a quadratic objective function, Q say.
576 ! G is the gradient of Q at the origin.
577 ! H is the Hessian matrix of Q. Only the upper triangular and diagonal
578 ! parts need be set. The lower triangular part is used to store the
579 ! elements of a Householder similarity transformation.
580 ! DELTA is the trust region radius, and has to be positive.
581 ! TOL is the value of a tolerance from the open interval (0,1).
582 ! D will be set to the calculated vector of variables.
583 
584 ! EVALUE will be set to the least eigenvalue of H if and only if D is a
585 ! Newton-Raphson step. Then EVALUE will be positive, but otherwise it
586 ! will be set to zero.
587 
588 ! Let MAXRED be the maximum of Q(0)-Q(D) subject to ||D|| <= DELTA,
589 ! and let ACTRED be the value of Q(0)-Q(D) that is actually calculated.
590 ! We take the view that any D is acceptable if it has the properties
591 
592 ! ||D|| <= DELTA and ACTRED <= (1-TOL)*MAXRED.
593 
594 ! The calculation of D is done by the method of Section 2 of the paper
595 ! by MJDP in the 1997 Dundee Numerical Analysis Conference Proceedings,
596 ! after transforming H to tridiagonal form.
597 
598 ! The arrays GG, TD, TN, W, PIV and Z will be used for working space.
599 REAL :: gg(n), td(n), tn(n), w(n), piv(n), z(n)
600 
601 REAL :: delsq, dhd, dnorm, dsq, dtg, dtz, gam, gnorm, gsq, hnorm
602 REAL :: par, parl, parlest, paru, paruest, phi, phil, phiu, pivksv
603 REAL :: pivot, posdef, scale, shfmax, shfmin, shift, slope, sum
604 REAL :: tdmin, temp, tempa, tempb, wsq, wwsq, wz, zsq
605 INTEGER :: i, iterc, j, jp, k, kp, kpp, ksav, ksave, nm
606 REAL :: one = 1.0_dp, two = 2.0_dp, zero = 0.0_dp
607 
608 ! Initialization.
609 
610 delsq = delta * delta
611 evalue = zero
612 nm = n - 1
613 DO i = 1, n
614  d(i) = zero
615  td(i) = h(i,i)
616  DO j = 1, i
617  h(i,j) = h(j,i)
618  END DO
619 END DO
620 
621 ! Apply Householder transformations to obtain a tridiagonal matrix that
622 ! is similar to H, and put the elements of the Householder vectors in
623 ! the lower triangular part of H. Further, TD and TN will contain the
624 ! diagonal and other nonzero elements of the tridiagonal matrix.
625 
626 DO k = 1, nm
627  kp = k + 1
628  sum = zero
629  IF (kp < n) THEN
630  kpp = kp + 1
631  DO i = kpp, n
632  sum = sum + h(i,k) ** 2
633  END DO
634  END IF
635  IF (sum == zero) THEN
636  tn(k) = h(kp,k)
637  h(kp,k) = zero
638  ELSE
639  temp = h(kp,k)
640  tn(k) = sign(sqrt(sum+temp*temp),temp)
641  h(kp,k) = -sum / (temp+tn(k))
642  temp = sqrt(two/(sum+h(kp,k)**2))
643  DO i = kp, n
644  w(i) = temp * h(i,k)
645  h(i,k) = w(i)
646  z(i) = td(i) * w(i)
647  END DO
648  wz = zero
649  DO j = kp, nm
650  jp = j + 1
651  DO i = jp, n
652  z(i) = z(i) + h(i,j) * w(j)
653  z(j) = z(j) + h(i,j) * w(i)
654  END DO
655  wz = wz + w(j) * z(j)
656  END DO
657  wz = wz + w(n) * z(n)
658  DO j = kp, n
659  td(j) = td(j) + w(j) * (wz*w(j)-two*z(j))
660  IF (j < n) THEN
661  jp = j + 1
662  DO i = jp, n
663  h(i,j) = h(i,j) - w(i) * z(j) - w(j) * (z(i)-wz*w(i))
664  END DO
665  END IF
666  END DO
667  END IF
668 END DO
669 
670 ! Form GG by applying the similarity transformation to G.
671 
672 gsq = zero
673 DO i = 1, n
674  gg(i) = g(i)
675  gsq = gsq + g(i) ** 2
676 END DO
677 gnorm = sqrt(gsq)
678 DO k = 1, nm
679  kp = k + 1
680  sum = zero
681  DO i = kp, n
682  sum = sum + gg(i) * h(i,k)
683  END DO
684  DO i = kp, n
685  gg(i) = gg(i) - sum * h(i,k)
686  END DO
687 END DO
688 
689 ! Begin the trust region calculation with a tridiagonal matrix by
690 ! calculating the norm of H. Then treat the case when H is zero.
691 
692 hnorm = abs(td(1)) + abs(tn(1))
693 tdmin = td(1)
694 tn(n) = zero
695 DO i = 2, n
696  temp = abs(tn(i-1)) + abs(td(i)) + abs(tn(i))
697  hnorm = max(hnorm,temp)
698  tdmin = min(tdmin,td(i))
699 END DO
700 IF (hnorm == zero) THEN
701  IF (gnorm == zero) GO TO 420
702  scale = delta / gnorm
703  DO i = 1, n
704  d(i) = -scale * gg(i)
705  END DO
706  GO TO 380
707 END IF
708 
709 ! Set the initial values of PAR and its bounds.
710 
711 parl = max(zero, -tdmin, gnorm/delta-hnorm)
712 parlest = parl
713 par = parl
714 paru = zero
715 paruest = zero
716 posdef = zero
717 iterc = 0
718 
719 ! Calculate the pivots of the Cholesky factorization of (H+PAR*I).
720 
721 160 iterc = iterc + 1
722 ksav = 0
723 piv(1) = td(1) + par
724 k = 1
725 170 IF (piv(k) > zero) THEN
726  piv(k+1) = td(k+1) + par - tn(k) ** 2 / piv(k)
727 ELSE
728  IF (piv(k) < zero .OR. tn(k) /= zero) GO TO 180
729  ksav = k
730  piv(k+1) = td(k+1) + par
731 END IF
732 k = k + 1
733 IF (k < n) GO TO 170
734 IF (piv(k) >= zero) THEN
735  IF (piv(k) == zero) ksav = k
736 
737 ! Branch if all the pivots are positive, allowing for the case when
738 ! G is zero.
739 
740  IF (ksav == 0 .AND. gsq > zero) GO TO 250
741  IF (gsq == zero) THEN
742  IF (par == zero) GO TO 380
743  paru = par
744  paruest = par
745  IF (ksav == 0) GO TO 210
746  END IF
747  k = ksav
748 END IF
749 
750 ! Set D to a direction of nonpositive curvature of the given tridiagonal
751 ! matrix, and thus revise PARLEST.
752 
753 180 d(k) = one
754 IF (abs(tn(k)) <= abs(piv(k))) THEN
755  dsq = one
756  dhd = piv(k)
757 ELSE
758  temp = td(k+1) + par
759  IF (temp <= abs(piv(k))) THEN
760  d(k+1) = sign(one,-tn(k))
761  dhd = piv(k) + temp - two * abs(tn(k))
762  ELSE
763  d(k+1) = -tn(k) / temp
764  dhd = piv(k) + tn(k) * d(k+1)
765  END IF
766  dsq = one + d(k+1) ** 2
767 END IF
768 190 IF (k > 1) THEN
769  k = k - 1
770  IF (tn(k) /= zero) THEN
771  d(k) = -tn(k) * d(k+1) / piv(k)
772  dsq = dsq + d(k) ** 2
773  GO TO 190
774  END IF
775  d(1:k) = zero
776 END IF
777 parl = par
778 parlest = par - dhd / dsq
779 
780 ! Terminate with D set to a multiple of the current D if the following
781 ! test suggests that it suitable to do so.
782 
783 210 temp = paruest
784 IF (gsq == zero) temp = temp * (one-tol)
785 IF (paruest > zero .AND. parlest >= temp) THEN
786  dtg = dot_product( d(1:n), gg(1:n) )
787  scale = -sign(delta/sqrt(dsq),dtg)
788  d(1:n) = scale * d(1:n)
789  GO TO 380
790 END IF
791 
792 ! Pick the value of PAR for the next iteration.
793 
794 240 IF (paru == zero) THEN
795  par = two * parlest + gnorm / delta
796 ELSE
797  par = 0.5d0 * (parl+paru)
798  par = max(par,parlest)
799 END IF
800 IF (paruest > zero) par = min(par,paruest)
801 GO TO 160
802 
803 ! Calculate D for the current PAR in the positive definite case.
804 
805 250 w(1) = -gg(1) / piv(1)
806 DO i = 2, n
807  w(i) = (-gg(i)-tn(i-1)*w(i-1)) / piv(i)
808 END DO
809 d(n) = w(n)
810 DO i = nm, 1, -1
811  d(i) = w(i) - tn(i) * d(i+1) / piv(i)
812 END DO
813 
814 ! Branch if a Newton-Raphson step is acceptable.
815 
816 dsq = zero
817 wsq = zero
818 DO i = 1, n
819  dsq = dsq + d(i) ** 2
820  wsq = wsq + piv(i) * w(i) ** 2
821 END DO
822 IF (par /= zero .OR. dsq > delsq) THEN
823 
824 ! Make the usual test for acceptability of a full trust region step.
825 
826  dnorm = sqrt(dsq)
827  phi = one / dnorm - one / delta
828  temp = tol * (one+par*dsq/wsq) - dsq * phi * phi
829  IF (temp >= zero) THEN
830  scale = delta / dnorm
831  DO i = 1, n
832  d(i) = scale * d(i)
833  END DO
834  GO TO 380
835  END IF
836  IF (iterc >= 2 .AND. par <= parl) GO TO 380
837  IF (paru > zero .AND. par >= paru) GO TO 380
838 
839 ! Complete the iteration when PHI is negative.
840 
841  IF (phi < zero) THEN
842  parlest = par
843  IF (posdef == one) THEN
844  IF (phi <= phil) GO TO 380
845  slope = (phi-phil) / (par-parl)
846  parlest = par - phi / slope
847  END IF
848  slope = one / gnorm
849  IF (paru > zero) slope = (phiu-phi) / (paru-par)
850  temp = par - phi / slope
851  IF (paruest > zero) temp = min(temp,paruest)
852  paruest = temp
853  posdef = one
854  parl = par
855  phil = phi
856  GO TO 240
857  END IF
858 
859 ! If required, calculate Z for the alternative test for convergence.
860 
861  IF (posdef == zero) THEN
862  w(1) = one / piv(1)
863  DO i = 2, n
864  temp = -tn(i-1) * w(i-1)
865  w(i) = (sign(one,temp)+temp) / piv(i)
866  END DO
867  z(n) = w(n)
868  DO i = nm, 1, -1
869  z(i) = w(i) - tn(i) * z(i+1) / piv(i)
870  END DO
871  wwsq = zero
872  zsq = zero
873  dtz = zero
874  DO i = 1, n
875  wwsq = wwsq + piv(i) * w(i) ** 2
876  zsq = zsq + z(i) ** 2
877  dtz = dtz + d(i) * z(i)
878  END DO
879 
880 ! Apply the alternative test for convergence.
881 
882  tempa = abs(delsq-dsq)
883  tempb = sqrt(dtz*dtz+tempa*zsq)
884  gam = tempa / (sign(tempb,dtz)+dtz)
885  temp = tol * (wsq+par*delsq) - gam * gam * wwsq
886  IF (temp >= zero) THEN
887  DO i = 1, n
888  d(i) = d(i) + gam * z(i)
889  END DO
890  GO TO 380
891  END IF
892  parlest = max(parlest,par-wwsq/zsq)
893  END IF
894 
895 ! Complete the iteration when PHI is positive.
896 
897  slope = one / gnorm
898  IF (paru > zero) THEN
899  IF (phi >= phiu) GO TO 380
900  slope = (phiu-phi) / (paru-par)
901  END IF
902  parlest = max(parlest,par-phi/slope)
903  paruest = par
904  IF (posdef == one) THEN
905  slope = (phi-phil) / (par-parl)
906  paruest = par - phi / slope
907  END IF
908  paru = par
909  phiu = phi
910  GO TO 240
911 END IF
912 
913 ! Set EVALUE to the least eigenvalue of the second derivative matrix if
914 ! D is a Newton-Raphson step. SHFMAX will be an upper bound on EVALUE.
915 
916 shfmin = zero
917 pivot = td(1)
918 shfmax = pivot
919 DO k = 2, n
920  pivot = td(k) - tn(k-1) ** 2 / pivot
921  shfmax = min(shfmax,pivot)
922 END DO
923 
924 ! Find EVALUE by a bisection method, but occasionally SHFMAX may be
925 ! adjusted by the rule of false position.
926 
927 ksave = 0
928 350 shift = 0.5d0 * (shfmin+shfmax)
929 k = 1
930 temp = td(1) - shift
931 
932 360 IF (temp > zero) THEN
933  piv(k) = temp
934  IF (k < n) THEN
935  temp = td(k+1) - shift - tn(k) ** 2 / temp
936  k = k + 1
937  GO TO 360
938  END IF
939  shfmin = shift
940 ELSE
941  IF (k < ksave) GO TO 370
942  IF (k == ksave) THEN
943  IF (pivksv == zero) GO TO 370
944  IF (piv(k)-temp < temp-pivksv) THEN
945  pivksv = temp
946  shfmax = shift
947  ELSE
948  pivksv = zero
949  shfmax = (shift*piv(k) - shfmin*temp) / (piv(k)-temp)
950  END IF
951  ELSE
952  ksave = k
953  pivksv = temp
954  shfmax = shift
955  END IF
956 END IF
957 IF (shfmin <= 0.99d0*shfmax) GO TO 350
958 370 evalue = shfmin
959 
960 ! Apply the inverse Householder transformations to D.
961 
962 380 nm = n - 1
963 DO k = nm, 1, -1
964  kp = k + 1
965  sum = zero
966  DO i = kp, n
967  sum = sum + d(i) * h(i,k)
968  END DO
969  DO i = kp, n
970  d(i) = d(i) - sum * h(i,k)
971  END DO
972 END DO
973 
974 ! Return from the subroutine.
975 
976 420 RETURN
977 END SUBROUTINE trstep
978 
979 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% lagmax.f %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980 
981 SUBROUTINE lagmax(n, g, h, rho, d, v, vmax)
982 
983 INTEGER, INTENT(IN) :: n
984 REAL, INTENT(IN) :: g(:)
985 REAL, INTENT(OUT) :: h(:,:)
986 REAL, INTENT(IN) :: rho
987 REAL, INTENT(OUT) :: d(:)
988 REAL, INTENT(OUT) :: v(:)
989 REAL, INTENT(OUT) :: vmax
990 
991 ! N is the number of variables of a quadratic objective function, Q say.
992 ! G is the gradient of Q at the origin.
993 ! H is the symmetric Hessian matrix of Q. Only the upper triangular and
994 ! diagonal parts need be set.
995 ! RHO is the trust region radius, and has to be positive.
996 ! D will be set to the calculated vector of variables.
997 ! The array V will be used for working space.
998 ! VMAX will be set to |Q(0)-Q(D)|.
999 
1000 ! Calculating the D that maximizes |Q(0)-Q(D)| subject to ||D|| <= RHO
1001 ! requires of order N**3 operations, but sometimes it is adequate if
1002 ! |Q(0)-Q(D)| is within about 0.9 of its greatest possible value. This
1003 ! subroutine provides such a solution in only of order N**2 operations,
1004 ! where the claim of accuracy has been tested by numerical experiments.
1005 
1006 REAL :: half = 0.5_dp, one = 1.0_dp, zero = 0.0_dp
1007 REAL :: dd, dhd, dlin, dsq, gd, gg, ghg, gnorm, halfrt, hmax, ratio
1008 REAL :: scale, sum, sumv, temp, tempa, tempb, tempc, tempd, tempv
1009 REAL :: vhg, vhv, vhw, vlin, vmu, vnorm, vsq, vv, wcos, whw, wsin, wsq
1010 INTEGER :: i, j, k
1011 
1012 ! Preliminary calculations.
1013 
1014 halfrt = sqrt(half)
1015 
1016 ! Pick V such that ||HV|| / ||V|| is large.
1017 
1018 hmax = zero
1019 DO i = 1, n
1020  sum = zero
1021  DO j = 1, n
1022  h(j,i) = h(i,j)
1023  sum = sum + h(i,j) ** 2
1024  END DO
1025  IF (sum > hmax) THEN
1026  hmax = sum
1027  k = i
1028  END IF
1029 END DO
1030 DO j = 1, n
1031  v(j) = h(k,j)
1032 END DO
1033 
1034 ! Set D to a vector in the subspace spanned by V and HV that maximizes
1035 ! |(D,HD)|/(D,D), except that we set D=HV if V and HV are nearly parallel.
1036 ! The vector that has the name D at label 60 used to be the vector W.
1037 
1038 vsq = zero
1039 vhv = zero
1040 dsq = zero
1041 DO i = 1, n
1042  vsq = vsq + v(i) ** 2
1043  d(i) = dot_product( h(i,1:n), v(1:n) )
1044  vhv = vhv + v(i) * d(i)
1045  dsq = dsq + d(i) ** 2
1046 END DO
1047 IF (vhv*vhv <= 0.9999d0*dsq*vsq) THEN
1048  temp = vhv / vsq
1049  wsq = zero
1050  DO i = 1, n
1051  d(i) = d(i) - temp * v(i)
1052  wsq = wsq + d(i) ** 2
1053  END DO
1054  whw = zero
1055  ratio = sqrt(wsq/vsq)
1056  DO i = 1, n
1057  temp = dot_product( h(i,1:n), d(1:n) )
1058  whw = whw + temp * d(i)
1059  v(i) = ratio * v(i)
1060  END DO
1061  vhv = ratio * ratio * vhv
1062  vhw = ratio * wsq
1063  temp = half * (whw-vhv)
1064  temp = temp + sign(sqrt(temp**2+vhw**2),whw+vhv)
1065  DO i = 1, n
1066  d(i) = vhw * v(i) + temp * d(i)
1067  END DO
1068 END IF
1069 
1070 ! We now turn our attention to the subspace spanned by G and D. A multiple
1071 ! of the current D is returned if that choice seems to be adequate.
1072 
1073 gg = zero
1074 gd = zero
1075 dd = zero
1076 dhd = zero
1077 DO i = 1, n
1078  gg = gg + g(i) ** 2
1079  gd = gd + g(i) * d(i)
1080  dd = dd + d(i) ** 2
1081  sum = dot_product( h(i,1:n), d(1:n) )
1082  dhd = dhd + sum * d(i)
1083 END DO
1084 temp = gd / gg
1085 vv = zero
1086 scale = sign(rho/sqrt(dd),gd*dhd)
1087 DO i = 1, n
1088  v(i) = d(i) - temp * g(i)
1089  vv = vv + v(i) ** 2
1090  d(i) = scale * d(i)
1091 END DO
1092 gnorm = sqrt(gg)
1093 IF (gnorm*dd <= 0.5d-2*rho*abs(dhd) .OR. vv/dd <= 1.0d-4) THEN
1094  vmax = abs(scale*(gd + half*scale*dhd))
1095  GO TO 170
1096 END IF
1097 
1098 ! G and V are now orthogonal in the subspace spanned by G and D. Hence
1099 ! we generate an orthonormal basis of this subspace such that (D,HV) is
1100 ! negligible or zero, where D and V will be the basis vectors.
1101 
1102 ghg = zero
1103 vhg = zero
1104 vhv = zero
1105 DO i = 1, n
1106  sum = dot_product( h(i,1:n), g(1:n) )
1107  sumv = dot_product( h(i,1:n), v(1:n) )
1108  ghg = ghg + sum * g(i)
1109  vhg = vhg + sumv * g(i)
1110  vhv = vhv + sumv * v(i)
1111 END DO
1112 vnorm = sqrt(vv)
1113 ghg = ghg / gg
1114 vhg = vhg / (vnorm*gnorm)
1115 vhv = vhv / vv
1116 IF (abs(vhg) <= 0.01d0*max(abs(ghg),abs(vhv))) THEN
1117  vmu = ghg - vhv
1118  wcos = one
1119  wsin = zero
1120 ELSE
1121  temp = half * (ghg-vhv)
1122  vmu = temp + sign(sqrt(temp**2+vhg**2),temp)
1123  temp = sqrt(vmu**2+vhg**2)
1124  wcos = vmu / temp
1125  wsin = vhg / temp
1126 END IF
1127 tempa = wcos / gnorm
1128 tempb = wsin / vnorm
1129 tempc = wcos / vnorm
1130 tempd = wsin / gnorm
1131 DO i = 1, n
1132  d(i) = tempa * g(i) + tempb * v(i)
1133  v(i) = tempc * v(i) - tempd * g(i)
1134 END DO
1135 
1136 ! The final D is a multiple of the current D, V, D+V or D-V. We make the
1137 ! choice from these possibilities that is optimal.
1138 
1139 dlin = wcos * gnorm / rho
1140 vlin = -wsin * gnorm / rho
1141 tempa = abs(dlin) + half * abs(vmu+vhv)
1142 tempb = abs(vlin) + half * abs(ghg-vmu)
1143 tempc = halfrt * (abs(dlin)+abs(vlin)) + 0.25d0 * abs(ghg+vhv)
1144 IF (tempa >= tempb .AND. tempa >= tempc) THEN
1145  tempd = sign(rho,dlin*(vmu+vhv))
1146  tempv = zero
1147 ELSE IF (tempb >= tempc) THEN
1148  tempd = zero
1149  tempv = sign(rho,vlin*(ghg-vmu))
1150 ELSE
1151  tempd = sign(halfrt*rho,dlin*(ghg+vhv))
1152  tempv = sign(halfrt*rho,vlin*(ghg+vhv))
1153 END IF
1154 DO i = 1, n
1155  d(i) = tempd * d(i) + tempv * v(i)
1156 END DO
1157 vmax = rho * rho * max(tempa,tempb,tempc)
1158 170 RETURN
1159 END SUBROUTINE lagmax
1160 
1161 END MODULE powell_optimize