Line data Source code
1 : module mod_bobyqa
2 : use const_def, only: dp
3 :
4 : contains
5 :
6 3 : subroutine do_BOBYQA (N,NPT,X,XL,XU,RHOBEG,RHOEND,IPRINT,MAXFUN,W,CALFUN,max_valid_value)
7 : implicit REAL(dp) (A-H,O-Z)
8 : integer :: N, NPT, IPRINT, MAXFUN
9 : dimension X(:),XL(:),XU(:),W(*)
10 : interface
11 : #include "num_bobyqa_proc.dek"
12 : end interface
13 : real(dp), intent(in) :: max_valid_value
14 :
15 : ! This subroutine seeks the least value of a function of many variables,
16 : ! by applying a trust region method that forms quadratic models by
17 : ! interpolation. There is usually some freedom in the interpolation
18 : ! conditions, which is taken up by minimizing the Frobenius norm of
19 : ! the change to the second derivative of the model, beginning with the
20 : ! zero matrix. The values of the variables are constrained by upper and
21 : ! lower bounds. The arguments of the subroutine are as follows.
22 : !
23 : ! N must be set to the number of variables and must be at least two.
24 : ! NPT is the number of interpolation conditions. Its value must be in
25 : ! the interval [N+2,(N+1)(N+2)/2]. Choices that exceed 2*N+1 are not
26 : ! recommended.
27 : ! Initial values of the variables must be set in X(1),X(2),...,X(N). They
28 : ! will be changed to the values that give the least calculated F.
29 : ! For I=1,2,...,N, XL(I) and XU(I) must provide the lower and upper
30 : ! bounds, respectively, on X(I). The construction of quadratic models
31 : ! requires XL(I) to be strictly less than XU(I) for each I. Further,
32 : ! the contribution to a model from changes to the I-th variable is
33 : ! damaged severely by rounding errors if XU(I)-XL(I) is too small.
34 : ! RHOBEG and RHOEND must be set to the initial and final values of a trust
35 : ! region radius, so both must be positive with RHOEND no greater than
36 : ! RHOBEG. Typically, RHOBEG should be about one tenth of the greatest
37 : ! expected change to a variable, while RHOEND should indicate the
38 : ! accuracy that is required in the final values of the variables. An
39 : ! error return occurs if any of the differences XU(I)-XL(I), I=1,...,N,
40 : ! is less than 2*RHOBEG.
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 : ! (NPT+5)*(NPT+N)+3*N*(N+5)/2.
50 : !
51 : ! subroutine CALFUN (N,X,F) has to be provided by the user. It must set
52 : ! F to the value of the objective function for the current values of the
53 : ! variables X(1),X(2),...,X(N), which are generated automatically in a
54 : ! way that satisfies the bounds given in XL and XU.
55 : !
56 : ! Return if the value of NPT is unacceptable.
57 : !
58 3 : NP=N+1
59 3 : if (NPT < N+2 .or. NPT > ((N+2)*NP)/2) then
60 0 : PRINT 10
61 : 10 FORMAT (/4X,'Return from BOBYQA because NPT is not in the required interval')
62 0 : GOTO 40
63 : end if
64 : !
65 : ! Partition the working space array, so that different parts of it can
66 : ! be treated separately during the calculation of BOBYQB. The partition
67 : ! requires the first (NPT+2)*(NPT+N)+3*N*(N+5)/2 elements of W plus the
68 : ! space that is taken by the last array in the argument list of BOBYQB.
69 : !
70 3 : NDIM=NPT+N
71 3 : IXB=1
72 3 : IXP=IXB+N
73 3 : IFV=IXP+N*NPT
74 3 : IXO=IFV+NPT
75 3 : IGO=IXO+N
76 3 : IHQ=IGO+N
77 3 : IPQ=IHQ+(N*NP)/2
78 3 : IBMAT=IPQ+NPT
79 3 : IZMAT=IBMAT+NDIM*N
80 3 : ISL=IZMAT+NPT*(NPT-NP)
81 3 : ISU=ISL+N
82 3 : IXN=ISU+N
83 3 : IXA=IXN+N
84 3 : ID=IXA+N
85 3 : IVL=ID+N
86 3 : IW=IVL+NDIM
87 : !
88 : ! Return if there is insufficient space between the bounds. Modify the
89 : ! initial X if necessary in order to avoid conflicts between the bounds
90 : ! and the construction of the first quadratic model. The lower and upper
91 : ! bounds on moves from the updated X are set now, in the ISL and ISU
92 : ! partitions of W, in order to provide useful and exact information about
93 : ! components of X that become within distance RHOBEG from their bounds.
94 : !
95 6 : ZERO=0.0D0
96 15 : do J=1,N
97 3 : TEMP=XU(J)-XL(J)
98 12 : if (TEMP < RHOBEG+RHOBEG) then
99 0 : PRINT 20
100 : 20 FORMAT (/4X,'Return from BOBYQA because one of the differences XU(I)-XL(I)'/6X,' is less than 2*RHOBEG.')
101 0 : GOTO 40
102 : end if
103 12 : JSL=ISL+J-1
104 12 : JSU=JSL+N
105 12 : W(JSL)=XL(J)-X(J)
106 12 : W(JSU)=XU(J)-X(J)
107 15 : if (W(JSL) >= -RHOBEG) then
108 0 : if (W(JSL) >= ZERO) then
109 0 : X(J)=XL(J)
110 0 : W(JSL)=ZERO
111 0 : W(JSU)=TEMP
112 : else
113 0 : X(J)=XL(J)+RHOBEG
114 0 : W(JSL)=-RHOBEG
115 0 : W(JSU)=DMAX1(XU(J)-X(J),RHOBEG)
116 : end if
117 12 : else if (W(JSU) <= RHOBEG) then
118 0 : if (W(JSU) <= ZERO) then
119 0 : X(J)=XU(J)
120 0 : W(JSL)=-TEMP
121 0 : W(JSU)=ZERO
122 : else
123 0 : X(J)=XU(J)-RHOBEG
124 0 : W(JSL)=DMIN1(XL(J)-X(J),-RHOBEG)
125 0 : W(JSU)=RHOBEG
126 : end if
127 : end if
128 : end do
129 : !
130 : ! Make the call of BOBYQB.
131 : !
132 : CALL BOBYQB (N,NPT,X,XL,XU,RHOBEG,RHOEND,IPRINT,MAXFUN,W(IXB),
133 : & W(IXP),W(IFV),W(IXO),W(IGO),W(IHQ),W(IPQ),W(IBMAT),W(IZMAT),
134 : & NDIM,W(ISL),W(ISU),W(IXN),W(IXA),W(ID),W(IVL),W(IW),CALFUN,
135 3 : & max_valid_value)
136 3 : 40 RETURN
137 : end subroutine do_BOBYQA
138 :
139 :
140 3 : subroutine BOBYQB (N,NPT,X,XL,XU,RHOBEG,RHOEND,IPRINT,
141 3 : & MAXFUN,XBASE,XPT,FVAL,XOPT,GOPT,HQ,PQ,BMAT,ZMAT,NDIM,
142 : & SL,SU,XNEW,XALT,D,VLAG,W,CALFUN,max_valid_value)
143 : implicit real(dp) (A-H,O-Z)
144 : integer :: N, NPT, IPRINT, MAXFUN, NDIM
145 : dimension X(:),XL(:),XU(:),XBASE(*),XPT(NPT,*),FVAL(*),
146 : & XOPT(*),GOPT(*),HQ(*),PQ(*),BMAT(NDIM,*),ZMAT(NPT,*),
147 : & SL(*),SU(*),XNEW(*),XALT(*),D(*),VLAG(*),W(*)
148 : interface
149 : #include "num_bobyqa_proc.dek"
150 : end interface
151 : real(dp), intent(in) :: max_valid_value
152 :
153 : logical :: do_replace
154 : !
155 : ! The arguments N, NPT, X, XL, XU, RHOBEG, RHOEND, IPRINT and MAXFUN
156 : ! are identical to the corresponding arguments in subroutine BOBYQA.
157 : ! XBASE holds a shift of origin that should reduce the contributions
158 : ! from rounding errors to values of the model and Lagrange functions.
159 : ! XPT is a two-dimensional array that holds the coordinates of the
160 : ! interpolation points relative to XBASE.
161 : ! FVAL holds the values of F at the interpolation points.
162 : ! XOPT is set to the displacement from XBASE of the trust region centre.
163 : ! GOPT holds the gradient of the quadratic model at XBASE+XOPT.
164 : ! HQ holds the explicit second derivatives of the quadratic model.
165 : ! PQ contains the parameters of the implicit second derivatives of the
166 : ! quadratic model.
167 : ! BMAT holds the last N columns of H.
168 : ! ZMAT holds the factorization of the leading NPT by NPT submatrix of H,
169 : ! this factorization being ZMAT times ZMAT^T, which provides both the
170 : ! correct rank and positive semi-definiteness.
171 : ! NDIM is the first dimension of BMAT and has the value NPT+N.
172 : ! SL and SU hold the differences XL-XBASE and XU-XBASE, respectively.
173 : ! All the components of every XOPT are going to satisfy the bounds
174 : ! SL(I) .LEQ. XOPT(I) .LEQ. SU(I), with appropriate equalities when
175 : ! XOPT is on a constraint boundary.
176 : ! XNEW is chosen by subroutine TRSBOX or ALTMOV. Usually XBASE+XNEW is the
177 : ! vector of variables for the next call of CALFUN. XNEW also satisfies
178 : ! the SL and SU constraints in the way that has just been mentioned.
179 : ! XALT is an alternative to XNEW, chosen by ALTMOV, that may replace XNEW
180 : ! in order to increase the denominator in the updating of UPDATE.
181 : ! D is reserved for a trial step from XOPT, which is usually XNEW-XOPT.
182 : ! VLAG contains the values of the Lagrange functions at a new point X.
183 : ! They are part of a product that requires VLAG to be of length NDIM.
184 : ! W is a one-dimensional array that is used for working space. Its length
185 : ! must be at least 3*NDIM = 3*(NPT+N).
186 : !
187 : ! Set some constants.
188 : !
189 3 : HALF=0.5D0
190 3 : ONE=1.0D0
191 3 : TEN=10.0D0
192 3 : TENTH=0.1D0
193 3 : TWO=2.0D0
194 3 : ZERO=0.0D0
195 3 : NP=N+1
196 3 : NPTM=NPT-NP
197 3 : NH=(N*NP)/2
198 : !
199 : ! The call of PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ,
200 : ! BMAT and ZMAT for the first iteration, with the corresponding values of
201 : ! of NF and KOPT, which are the number of calls of CALFUN so far and the
202 : ! index of the interpolation point at the trust region centre. Then the
203 : ! initial XOPT is set too. The branch to label 720 occurs if MAXFUN is
204 : ! less than NPT. GOPT will be updated if KOPT is different from KBASE.
205 : !
206 : CALL PRELIM (N,NPT,X,XL,XU,RHOBEG,IPRINT,MAXFUN,XBASE,XPT,
207 3 : & FVAL,GOPT,HQ,PQ,BMAT,ZMAT,NDIM,SL,SU,NF,KOPT,CALFUN)
208 6 : XOPTSQ=ZERO
209 15 : do I=1,N
210 12 : XOPT(I)=XPT(KOPT,I)
211 15 : XOPTSQ=XOPTSQ+XOPT(I)**2
212 : end do
213 6 : FSAVE=FVAL(1)
214 3 : if (NF < NPT) then
215 0 : if (IPRINT > 0) PRINT 390
216 : GOTO 720
217 : end if
218 3 : KBASE=1
219 : !
220 : ! Complete the settings that are required for the iterative procedure.
221 : !
222 6 : RHO=RHOBEG
223 6 : DELTA=RHO
224 3 : NRESC=NF
225 3 : NTRITS=0
226 6 : DIFFA=ZERO
227 6 : DIFFB=ZERO
228 3 : ITEST=0
229 3 : NFSAV=NF
230 : !
231 : ! Update GOPT if necessary before the first iteration and after each
232 : ! call of RESCUE that makes a call of CALFUN.
233 : !
234 3 : 20 if (KOPT /= KBASE) then
235 3 : IH=0
236 15 : do J=1,N
237 49 : do I=1,J
238 34 : IH=IH+1
239 34 : if (I < J) GOPT(J)=GOPT(J)+HQ(IH)*XOPT(I)
240 46 : GOPT(I)=GOPT(I)+HQ(IH)*XOPT(J)
241 : end do
242 : end do
243 3 : if (NF > NPT) then
244 0 : do K=1,NPT
245 3 : TEMP=ZERO
246 0 : do J=1,N
247 0 : TEMP=TEMP+XPT(K,J)*XOPT(J)
248 : end do
249 0 : TEMP=PQ(K)*TEMP
250 0 : do I=1,N
251 0 : GOPT(I)=GOPT(I)+TEMP*XPT(K,I)
252 : end do
253 : end do
254 : end if
255 : end if
256 : !
257 : ! Generate the next point in the trust region that provides a small value
258 : ! of the quadratic model subject to the constraints on the variables.
259 : ! The integer NTRITS is set to the number "trust region" iterations that
260 : ! have occurred since the last "alternative" iteration. If the length
261 : ! of XNEW-XOPT is less than HALF*RHO, however, then there is a branch to
262 : ! label 650 or 680 with NTRITS=-1, instead of calculating F at XNEW.
263 : !
264 : 60 CALL TRSBOX (N,NPT,XPT,XOPT,GOPT,HQ,PQ,SL,SU,DELTA,XNEW,D,
265 227 : & W,W(NP),W(NP+N),W(NP+2*N),W(NP+3*N),DSQ,CRVMIN)
266 230 : DNORM=DMIN1(DELTA,DSQRT(DSQ))
267 227 : if (DNORM < HALF*RHO) then
268 46 : NTRITS=-1
269 49 : DISTSQ=(TEN*RHO)**2
270 46 : if (NF <= NFSAV+2) GOTO 650
271 : !
272 : ! The following choice between labels 650 and 680 depends on whether or
273 : ! not our work with the current RHO seems to be complete. Either RHO is
274 : ! decreased or termination occurs if the errors in the quadratic model at
275 : ! the last three interpolation points compare favourably with predictions
276 : ! of likely improvements to the model within distance HALF*RHO of XOPT.
277 : !
278 11 : ERRBIG=DMAX1(DIFFA,DIFFB,DIFFC)
279 11 : FRHOSQ=0.125D0*RHO*RHO
280 8 : if (CRVMIN > ZERO .and. ERRBIG > FRHOSQ*CRVMIN) GOTO 650
281 3 : BDTOL=ERRBIG/RHO
282 0 : do J=1,N
283 3 : BDTEST=BDTOL
284 0 : if (XNEW(J) == SL(J)) BDTEST=W(J)
285 0 : if (XNEW(J) == SU(J)) BDTEST=-W(J)
286 0 : if (BDTEST < BDTOL) then
287 3 : CURV=HQ((J+J*J)/2)
288 0 : do K=1,NPT
289 0 : CURV=CURV+PQ(K)*XPT(K,J)**2
290 : end do
291 0 : BDTEST=BDTEST+HALF*CURV*RHO
292 0 : if (BDTEST < BDTOL) GOTO 650
293 : end if
294 : end do
295 : GOTO 680
296 : end if
297 181 : NTRITS=NTRITS+1
298 : !
299 : ! Severe cancellation is likely to occur if XOPT is too far from XBASE.
300 : ! If the following test holds, then XBASE is shifted so that XOPT becomes
301 : ! zero. The appropriate changes are made to BMAT and to the second
302 : ! derivatives of the current model, beginning with the changes to BMAT
303 : ! that do not depend on ZMAT. VLAG is used temporarily for working space.
304 : !
305 260 : 90 if (DSQ <= 1.0D-3*XOPTSQ) then
306 15 : FRACSQ=0.25D0*XOPTSQ
307 15 : SUMPQ=ZERO
308 136 : do K=1,NPT
309 124 : SUMPQ=SUMPQ+PQ(K)
310 127 : SUM=-HALF*XOPTSQ
311 756 : do I=1,N
312 756 : SUM=SUM+XPT(K,I)*XOPT(I)
313 : end do
314 124 : W(NPT+K)=SUM
315 124 : TEMP=FRACSQ-HALF*SUM
316 768 : do I=1,N
317 632 : W(I)=BMAT(K,I)
318 632 : VLAG(I)=SUM*XPT(K,I)+TEMP*XOPT(I)
319 632 : IP=NPT+I
320 2784 : do J=1,I
321 2660 : BMAT(IP,J)=BMAT(IP,J)+W(I)*VLAG(J)+VLAG(I)*W(J)
322 : end do
323 : end do
324 : end do
325 : !
326 : ! Then the revisions of BMAT that depend on ZMAT are calculated.
327 : !
328 68 : do JJ=1,NPTM
329 3 : SUMZ=ZERO
330 3 : SUMW=ZERO
331 688 : do K=1,NPT
332 632 : SUMZ=SUMZ+ZMAT(K,JJ)
333 632 : VLAG(K)=W(NPT+K)*ZMAT(K,JJ)
334 688 : SUMW=SUMW+VLAG(K)
335 : end do
336 344 : do J=1,N
337 288 : SUM=(FRACSQ*SUMZ-HALF*SUMW)*XOPT(J)
338 3712 : do K=1,NPT
339 3712 : SUM=SUM+VLAG(K)*XPT(K,J)
340 : end do
341 288 : W(J)=SUM
342 3768 : do K=1,NPT
343 3712 : BMAT(K,J)=BMAT(K,J)+SUM*ZMAT(K,JJ)
344 : end do
345 : end do
346 356 : do I=1,N
347 288 : IP=I+NPT
348 288 : TEMP=W(I)
349 1272 : do J=1,I
350 1216 : BMAT(IP,J)=BMAT(IP,J)+TEMP*W(J)
351 : end do
352 : end do
353 : end do
354 : !
355 : ! The following instructions complete the shift, including the changes
356 : ! to the second derivative parameters of the quadratic model.
357 : !
358 12 : IH=0
359 68 : do J=1,N
360 56 : W(J)=-HALF*SUMPQ*XOPT(J)
361 688 : do K=1,NPT
362 632 : W(J)=W(J)+PQ(K)*XPT(K,J)
363 688 : XPT(K,J)=XPT(K,J)-XOPT(J)
364 : end do
365 240 : do I=1,J
366 172 : IH=IH+1
367 172 : HQ(IH)=HQ(IH)+W(I)*XOPT(J)+XOPT(I)*W(J)
368 228 : BMAT(NPT+I,J)=BMAT(NPT+J,I)
369 : end do
370 : end do
371 68 : do I=1,N
372 56 : XBASE(I)=XBASE(I)+XOPT(I)
373 56 : XNEW(I)=XNEW(I)-XOPT(I)
374 56 : SL(I)=SL(I)-XOPT(I)
375 56 : SU(I)=SU(I)-XOPT(I)
376 68 : XOPT(I)=ZERO
377 : end do
378 : XOPTSQ=ZERO
379 : end if
380 260 : if (NTRITS == 0) GOTO 210
381 0 : GOTO 230
382 : !
383 : ! XBASE is also moved to XOPT by a call of RESCUE. This calculation is
384 : ! more expensive than the previous shift, because new matrices BMAT and
385 : ! ZMAT are generated from scratch, which may include the replacement of
386 : ! interpolation points whose positions seem to be causing near linear
387 : ! dependence in the interpolation conditions. Therefore RESCUE is called
388 : ! only if rounding errors have reduced by at least a factor of two the
389 : ! denominator of the formula for updating the H matrix. It provides a
390 : ! useful safeguard, but is not invoked in most applications of BOBYQA.
391 : !
392 0 : 190 NFSAV=NF
393 0 : KBASE=KOPT
394 : CALL RESCUE (N,NPT,XL,XU,IPRINT,MAXFUN,XBASE,XPT,FVAL,
395 : & XOPT,GOPT,HQ,PQ,BMAT,ZMAT,NDIM,SL,SU,NF,DELTA,KOPT,
396 0 : & VLAG,W,W(N+NP),W(NDIM+NP),CALFUN)
397 : !
398 : ! XOPT is updated now in case the branch below to label 720 is taken.
399 : ! Any updating of GOPT occurs after the branch below to label 20, which
400 : ! leads to a trust region iteration as does the branch to label 60.
401 : !
402 0 : XOPTSQ=ZERO
403 0 : if (KOPT /= KBASE) then
404 0 : do I=1,N
405 0 : XOPT(I)=XPT(KOPT,I)
406 0 : XOPTSQ=XOPTSQ+XOPT(I)**2
407 : end do
408 : end if
409 0 : if (NF < 0) then
410 0 : NF=MAXFUN
411 0 : if (IPRINT > 0) PRINT 390
412 : GOTO 720
413 : end if
414 0 : NRESC=NF
415 0 : if (NFSAV < NF) then
416 : NFSAV=NF
417 : GOTO 20
418 : end if
419 0 : if (NTRITS > 0) GOTO 60
420 : !
421 : ! Pick two alternative vectors of variables, relative to XBASE, that
422 : ! are suitable as new positions of the KNEW-th interpolation point.
423 : ! Firstly, XNEW is set to the point on a line through XOPT and another
424 : ! interpolation point that minimizes the predicted value of the next
425 : ! denominator, subject to ||XNEW - XOPT|| .LEQ. ADELT and to the SL
426 : ! and SU bounds. Secondly, XALT is set to the best feasible point on
427 : ! a constrained version of the Cauchy step of the KNEW-th Lagrange
428 : ! function, the corresponding value of the square of this function
429 : ! being returned in CAUCHY. The choice between these alternatives is
430 : ! going to be made when the denominator is calculated.
431 : !
432 : 210 CALL ALTMOV (N,NPT,XPT,XOPT,BMAT,ZMAT,NDIM,SL,SU,KOPT,
433 79 : & KNEW,ADELT,XNEW,XALT,ALPHA,CAUCHY,W,W(NP),W(NDIM+1))
434 463 : do I=1,N
435 463 : D(I)=XNEW(I)-XOPT(I)
436 : end do
437 : !
438 : ! Calculate VLAG and BETA for the current choice of D. The scalar
439 : ! product of D with XPT(K,.) is going to be held in W(NPT+K) for
440 : ! use when VQUAD is calculated.
441 : !
442 3596 : 230 do K=1,NPT
443 3301 : SUMA=ZERO
444 3301 : SUMB=ZERO
445 3298 : SUM=ZERO
446 20958 : do J=1,N
447 17660 : SUMA=SUMA+XPT(K,J)*D(J)
448 17660 : SUMB=SUMB+XPT(K,J)*XOPT(J)
449 20958 : SUM=SUM+BMAT(K,J)*D(J)
450 : end do
451 3298 : W(K)=SUMA*(HALF*SUMA+SUMB)
452 3298 : VLAG(K)=SUM
453 3596 : W(NPT+K)=SUMA
454 : end do
455 301 : BETA=ZERO
456 1798 : do JJ=1,NPTM
457 : SUM=ZERO
458 19160 : do K=1,NPT
459 19160 : SUM=SUM+ZMAT(K,JJ)*W(K)
460 : end do
461 1500 : BETA=BETA-SUM*SUM
462 19458 : do K=1,NPT
463 19160 : VLAG(K)=VLAG(K)+SUM*ZMAT(K,JJ)
464 : end do
465 : end do
466 298 : DSQ=ZERO
467 301 : BSUM=ZERO
468 301 : DX=ZERO
469 1798 : do J=1,N
470 1500 : DSQ=DSQ+D(J)**2
471 1500 : SUM=ZERO
472 19160 : do K=1,NPT
473 19160 : SUM=SUM+W(K)*BMAT(K,J)
474 : end do
475 1500 : BSUM=BSUM+SUM*D(J)
476 1500 : JP=NPT+J
477 9580 : do I=1,N
478 9580 : SUM=SUM+BMAT(JP,I)*D(I)
479 : end do
480 1500 : VLAG(JP)=SUM
481 1500 : BSUM=BSUM+SUM*D(J)
482 1798 : DX=DX+D(J)*XOPT(J)
483 : end do
484 298 : BETA=DX*DX+DSQ*(XOPTSQ+DX+DX+HALF*DSQ)+BETA-BSUM
485 298 : VLAG(KOPT)=VLAG(KOPT)+ONE
486 : !
487 : ! If NTRITS is zero, the denominator may be increased by replacing
488 : ! the step D of ALTMOV by a Cauchy step. Then RESCUE may be called if
489 : ! rounding errors have damaged the chosen denominator.
490 : !
491 298 : if (NTRITS == 0) then
492 120 : DENOM=VLAG(KNEW)**2+ALPHA*BETA
493 117 : if (DENOM < CAUCHY .and. CAUCHY > ZERO) then
494 236 : do I=1,N
495 198 : XNEW(I)=XALT(I)
496 236 : D(I)=XNEW(I)-XOPT(I)
497 : end do
498 38 : CAUCHY=ZERO
499 38 : GOTO 230
500 : end if
501 79 : if (DENOM <= HALF*VLAG(KNEW)**2) then
502 0 : if (NF > NRESC) GOTO 190
503 0 : if (IPRINT > 0) PRINT 320
504 : 320 FORMAT (/5X,'Return from BOBYQA because of much cancellation in a denominator.')
505 : GOTO 720
506 : end if
507 : !
508 : ! Alternatively, if NTRITS is positive, then set KNEW to the index of
509 : ! the next interpolation point to be deleted to make room for a trust
510 : ! region step. Again RESCUE may be called if rounding errors have damaged
511 : ! the chosen denominator, which is the reason for attempting to select
512 : ! KNEW before calculating the next value of the objective function.
513 : !
514 : else
515 184 : DELSQ=DELTA*DELTA
516 184 : SCADEN=ZERO
517 184 : BIGLSQ=ZERO
518 181 : KNEW=0
519 2198 : do K=1,NPT
520 2017 : if (K == KOPT) CYCLE
521 3 : HDIAG=ZERO
522 11780 : do JJ=1,NPTM
523 11780 : HDIAG=HDIAG+ZMAT(K,JJ)**2
524 : end do
525 1839 : DEN=BETA*HDIAG+VLAG(K)**2
526 1836 : DISTSQ=ZERO
527 11780 : do J=1,N
528 11780 : DISTSQ=DISTSQ+(XPT(K,J)-XOPT(J))**2
529 : end do
530 1836 : TEMP=DMAX1(ONE,(DISTSQ/DELSQ)**2)
531 1836 : if (TEMP*DEN > SCADEN) then
532 497 : SCADEN=TEMP*DEN
533 497 : KNEW=K
534 497 : DENOM=DEN
535 : end if
536 2198 : BIGLSQ=DMAX1(BIGLSQ,TEMP*VLAG(K)**2)
537 : end do
538 181 : if (SCADEN <= HALF*BIGLSQ) then
539 0 : if (NF > NRESC) GOTO 190
540 0 : if (IPRINT > 0) PRINT 320
541 : GOTO 720
542 : end if
543 : end if
544 : !
545 : ! Put the variables for the next calculation of the objective function
546 : ! in XNEW, with any adjustments for the bounds.
547 : !
548 : !
549 : ! Calculate the value of the objective function at XBASE+XNEW, unless
550 : ! the limit on the number of calculations of F has been reached.
551 : !
552 1577 : 360 do I=1,N
553 1314 : X(I)=DMIN1(DMAX1(XL(I),XBASE(I)+XNEW(I)),XU(I))
554 1314 : if (XNEW(I) == SL(I)) X(I)=XL(I)
555 1577 : if (XNEW(I) == SU(I)) X(I)=XU(I)
556 : end do
557 263 : if (NF >= MAXFUN) then
558 0 : if (IPRINT > 0) PRINT 390
559 : 390 FORMAT (/4X,'Return from BOBYQA because CALFUN has been called MAXFUN times.')
560 : GOTO 720
561 : end if
562 263 : NF=NF+1
563 263 : CALL CALFUN (N,X,F)
564 263 : if (IPRINT == 3) then
565 0 : PRINT 400, NF,F,(X(I),I=1,N)
566 : 400 FORMAT (/4X,'Function number',I6,' F =',1PD18.10,
567 : & ' The corresponding X is:'/(2X,5D15.6))
568 : end if
569 263 : if (NTRITS == -1) then
570 3 : FSAVE=F
571 3 : GOTO 720
572 : end if
573 : !
574 : ! Use the quadratic model to predict the change in F due to the step D,
575 : ! and set DIFF to the error of this prediction.
576 : !
577 263 : FOPT=FVAL(KOPT)
578 263 : VQUAD=ZERO
579 260 : IH=0
580 1562 : do J=1,N
581 1302 : VQUAD=VQUAD+D(J)*GOPT(J)
582 5711 : do I=1,J
583 4149 : IH=IH+1
584 4149 : TEMP=D(I)*D(J)
585 4149 : if (I == J) TEMP=HALF*TEMP
586 5451 : VQUAD=VQUAD+HQ(IH)*TEMP
587 : end do
588 : end do
589 3124 : do K=1,NPT
590 3124 : VQUAD=VQUAD+HALF*PQ(K)*W(NPT+K)**2
591 : end do
592 263 : DIFF=F-FOPT-VQUAD
593 260 : DIFFC=DIFFB
594 260 : DIFFB=DIFFA
595 260 : DIFFA=DABS(DIFF)
596 260 : if (DNORM > RHO) NFSAV=NF
597 : !
598 : ! Pick the next value of DELTA after a trust region step.
599 : !
600 260 : if (NTRITS > 0) then
601 181 : if (VQUAD >= ZERO) then
602 0 : if (IPRINT > 0) PRINT 430
603 : 430 FORMAT (/4X,'Return from BOBYQA because a trust',
604 : & ' region step has failed to reduce Q.')
605 : GOTO 720
606 : end if
607 184 : RATIO=(F-FOPT)/VQUAD
608 181 : if (RATIO <= TENTH) then
609 54 : DELTA=DMIN1(HALF*DELTA,DNORM)
610 127 : else if (RATIO. LE. 0.7D0) then
611 31 : DELTA=DMAX1(HALF*DELTA,DNORM)
612 : else
613 96 : DELTA=DMAX1(HALF*DELTA,DNORM+DNORM)
614 : end if
615 181 : if (DELTA <= 1.5D0*RHO) DELTA=RHO
616 : !
617 : ! Recalculate KNEW and DENOM if the new F is less than FOPT.
618 : !
619 181 : if (F < FOPT) then
620 133 : KSAV=KNEW
621 136 : DENSAV=DENOM
622 133 : DELSQ=DELTA*DELTA
623 133 : SCADEN=ZERO
624 133 : BIGLSQ=ZERO
625 133 : KNEW=0
626 1598 : do K=1,NPT
627 : HDIAG=ZERO
628 9275 : do JJ=1,NPTM
629 9275 : HDIAG=HDIAG+ZMAT(K,JJ)**2
630 : end do
631 1465 : DEN=BETA*HDIAG+VLAG(K)**2
632 1465 : DISTSQ=ZERO
633 9275 : do J=1,N
634 9275 : DISTSQ=DISTSQ+(XPT(K,J)-XNEW(J))**2
635 : end do
636 1465 : TEMP=DMAX1(ONE,(DISTSQ/DELSQ)**2)
637 1465 : if (TEMP*DEN > SCADEN) then
638 363 : SCADEN=TEMP*DEN
639 363 : KNEW=K
640 363 : DENOM=DEN
641 : end if
642 1598 : BIGLSQ=DMAX1(BIGLSQ,TEMP*VLAG(K)**2)
643 : end do
644 133 : if (SCADEN <= HALF*BIGLSQ) then
645 0 : KNEW=KSAV
646 0 : DENOM=DENSAV
647 : end if
648 : end if
649 : end if
650 : !
651 : ! Update BMAT and ZMAT, so that the KNEW-th interpolation point can be
652 : ! moved. Also update the second derivative terms of the model.
653 : !
654 260 : CALL UPDATE (N,NPT,BMAT,ZMAT,NDIM,VLAG,BETA,DENOM,KNEW,W)
655 260 : IH=0
656 263 : PQOLD=PQ(KNEW)
657 260 : PQ(KNEW)=ZERO
658 1562 : do I=1,N
659 1302 : TEMP=PQOLD*XPT(KNEW,I)
660 5711 : do J=1,I
661 4149 : IH=IH+1
662 5451 : HQ(IH)=HQ(IH)+TEMP*XPT(KNEW,J)
663 : end do
664 : end do
665 1562 : do JJ=1,NPTM
666 1302 : TEMP=DIFF*ZMAT(KNEW,JJ)
667 16856 : do K=1,NPT
668 16596 : PQ(K)=PQ(K)+TEMP*ZMAT(K,JJ)
669 : end do
670 : end do
671 : !
672 : ! Include the new interpolation point, and make the changes to GOPT at
673 : ! the old XOPT that are caused by the updating of the quadratic model.
674 : !
675 260 : FVAL(KNEW)=F
676 1562 : do I=1,N
677 1302 : XPT(KNEW,I)=XNEW(I)
678 1562 : W(I)=BMAT(KNEW,I)
679 : end do
680 3124 : do K=1,NPT
681 : SUMA=ZERO
682 18158 : do JJ=1,NPTM
683 18158 : SUMA=SUMA+ZMAT(KNEW,JJ)*ZMAT(K,JJ)
684 : end do
685 : SUMB=ZERO
686 18158 : do J=1,N
687 18158 : SUMB=SUMB+XPT(K,J)*XOPT(J)
688 : end do
689 2864 : TEMP=SUMA*SUMB
690 18418 : do I=1,N
691 18158 : W(I)=W(I)+TEMP*XPT(K,I)
692 : end do
693 : end do
694 1562 : do I=1,N
695 1562 : GOPT(I)=GOPT(I)+DIFF*W(I)
696 : end do
697 : !
698 : ! Update XOPT, GOPT and KOPT if the new calculated F is less than FOPT.
699 : !
700 260 : if (F < FOPT) then
701 151 : KOPT=KNEW
702 151 : XOPTSQ=ZERO
703 151 : IH=0
704 919 : do J=1,N
705 768 : XOPT(J)=XNEW(J)
706 768 : XOPTSQ=XOPTSQ+XOPT(J)**2
707 3383 : do I=1,J
708 2464 : IH=IH+1
709 2464 : if (I < J) GOPT(J)=GOPT(J)+HQ(IH)*D(I)
710 3232 : GOPT(I)=GOPT(I)+HQ(IH)*D(J)
711 : end do
712 : end do
713 1838 : do K=1,NPT
714 : TEMP=ZERO
715 10775 : do J=1,N
716 10775 : TEMP=TEMP+XPT(K,J)*D(J)
717 : end do
718 1687 : TEMP=PQ(K)*TEMP
719 10926 : do I=1,N
720 10775 : GOPT(I)=GOPT(I)+TEMP*XPT(K,I)
721 : end do
722 : end do
723 : end if
724 : !
725 : ! Calculate the parameters of the least Frobenius norm interpolant to
726 : ! the current data, the gradient of this interpolant at XOPT being put
727 : ! into VLAG(NPT+I), I=1,2,...,N.
728 : !
729 260 : if (NTRITS > 0) then
730 2198 : do K=1,NPT
731 2017 : VLAG(K)=FVAL(K)-FVAL(KOPT)
732 2198 : W(K)=ZERO
733 : end do
734 1099 : do J=1,NPTM
735 : SUM=ZERO
736 11961 : do K=1,NPT
737 11780 : SUM=SUM+ZMAT(K,J)*VLAG(K)
738 : end do
739 : end do
740 2198 : do K=1,NPT
741 2198 : W(K)=W(K)+SUM*ZMAT(K,J)
742 : end do
743 2198 : do K=1,NPT
744 : SUM=ZERO
745 12879 : do J=1,N
746 12879 : SUM=SUM+XPT(K,J)*XOPT(J)
747 : end do
748 2017 : W(K+NPT)=W(K)
749 2198 : W(K)=SUM*W(K)
750 : end do
751 3 : GQSQ=ZERO
752 3 : GISQ=ZERO
753 1099 : do I=1,N
754 : SUM=ZERO
755 11780 : do K=1,NPT
756 11780 : SUM=SUM+BMAT(K,I)*VLAG(K)+XPT(K,I)*W(K)
757 : end do
758 918 : if (XOPT(I) == SL(I)) then
759 0 : GQSQ=GQSQ+DMIN1(ZERO,GOPT(I))**2
760 0 : GISQ=GISQ+DMIN1(ZERO,SUM)**2
761 918 : else if (XOPT(I) == SU(I)) then
762 0 : GQSQ=GQSQ+DMAX1(ZERO,GOPT(I))**2
763 0 : GISQ=GISQ+DMAX1(ZERO,SUM)**2
764 : else
765 918 : GQSQ=GQSQ+GOPT(I)**2
766 918 : GISQ=GISQ+SUM*SUM
767 : end if
768 1099 : VLAG(NPT+I)=SUM
769 : end do
770 : !
771 : ! Test whether to replace the new quadratic model by the least Frobenius
772 : ! norm interpolant, making the replacement if the test is satisfied.
773 : !
774 181 : ITEST=ITEST+1
775 181 : if (GQSQ < TEN*GISQ) ITEST=0
776 181 : do_replace = (ITEST >= 3)
777 0 : if (.not. do_replace) then ! check for "invalid" value
778 2198 : do k=1,npt
779 2198 : if (fval(k) > max_valid_value) then
780 : do_replace = .true.
781 : !write(*,*) 'bobyqa value > max valid', fval(k), max_valid_value
782 : exit
783 : end if
784 : end do
785 : end if
786 181 : if (do_replace) then
787 : !stop 'bobyqa: do_replace'
788 0 : do I=1,MAX0(NPT,NH)
789 0 : if (I <= N) GOPT(I)=VLAG(NPT+I)
790 0 : if (I <= NPT) PQ(I)=W(NPT+I)
791 0 : if (I <= NH) HQ(I)=ZERO
792 0 : ITEST=0
793 : end do
794 : end if
795 : end if
796 : !
797 : ! If a trust region step has provided a sufficient decrease in F, then
798 : ! branch for another trust region calculation. The case NTRITS=0 occurs
799 : ! when the new interpolation point was reached by an alternative step.
800 : !
801 260 : if (NTRITS == 0) GOTO 60
802 181 : if (F <= FOPT+TENTH*VQUAD) GOTO 60
803 : !
804 : ! Alternatively, find out if the interpolation points are close enough
805 : ! to the best point so far.
806 : !
807 100 : DISTSQ=DMAX1((TWO*DELTA)**2,(TEN*RHO)**2)
808 100 : 650 KNEW=0
809 1128 : do K=1,NPT
810 1028 : SUM=ZERO
811 6260 : do J=1,N
812 6260 : SUM=SUM+(XPT(K,J)-XOPT(J))**2
813 : end do
814 1128 : if (SUM > DISTSQ) then
815 162 : KNEW=K
816 162 : DISTSQ=SUM
817 : end if
818 : end do
819 : !
820 : ! If KNEW is positive, then ALTMOV finds alternative new positions for
821 : ! the KNEW-th interpolation point within distance ADELT of XOPT. It is
822 : ! reached via label 90. Otherwise, there is a branch to label 60 for
823 : ! another trust region iteration, unless the calculations with the
824 : ! current RHO are complete.
825 : !
826 100 : if (KNEW > 0) then
827 3 : DIST=DSQRT(DISTSQ)
828 79 : if (NTRITS == -1) then
829 32 : DELTA=DMIN1(TENTH*DELTA,HALF*DIST)
830 32 : if (DELTA <= 1.5D0*RHO) DELTA=RHO
831 : end if
832 79 : NTRITS=0
833 79 : ADELT=DMAX1(DMIN1(TENTH*DIST,DELTA),RHO)
834 79 : DSQ=ADELT*ADELT
835 79 : GOTO 90
836 : end if
837 21 : if (NTRITS == -1) GOTO 680
838 7 : if (RATIO > ZERO) GOTO 60
839 6 : if (DMAX1(DELTA,DNORM) > RHO) GOTO 60
840 : !
841 : ! The calculations with the current value of RHO are complete. Pick the
842 : ! next values of RHO and DELTA.
843 : !
844 18 : 680 if (RHO > RHOEND) then
845 15 : DELTA=HALF*RHO
846 15 : RATIO=RHO/RHOEND
847 15 : if (RATIO <= 16.0D0) then
848 3 : RHO=RHOEND
849 12 : else if (RATIO <= 250.0D0) then
850 3 : RHO=DSQRT(RATIO)*RHOEND
851 : else
852 9 : RHO=TENTH*RHO
853 : end if
854 15 : DELTA=DMAX1(DELTA,RHO)
855 15 : if (IPRINT >= 2) then
856 0 : if (IPRINT >= 3) PRINT 690
857 : 690 FORMAT (5X)
858 0 : PRINT 700, RHO,NF
859 : 700 FORMAT (/4X,'New RHO =',1PD11.4,5X,'Number of',
860 : & ' function values =',I6)
861 0 : PRINT 710, FVAL(KOPT),(XBASE(I)+XOPT(I),I=1,N)
862 : 710 FORMAT (4X,'Least value of F =',1PD23.15,9X,
863 : & 'The corresponding X is:'/(2X,5D15.6))
864 : end if
865 15 : NTRITS=0
866 15 : NFSAV=NF
867 15 : GOTO 60
868 : end if
869 : !
870 : ! Return from the calculation, after another Newton-Raphson step, if
871 : ! it is too short to have been tried before.
872 : !
873 3 : if (NTRITS == -1) GOTO 360
874 3 : 720 if (FVAL(KOPT) <= FSAVE) then
875 0 : do I=1,N
876 0 : X(I)=DMIN1(DMAX1(XL(I),XBASE(I)+XOPT(I)),XU(I))
877 0 : if (XOPT(I) == SL(I)) X(I)=XL(I)
878 0 : if (XOPT(I) == SU(I)) X(I)=XU(I)
879 : end do
880 0 : F=FVAL(KOPT)
881 : end if
882 3 : if (IPRINT >= 1) then
883 0 : PRINT 740, NF
884 : 740 FORMAT (/4X,'At the return from BOBYQA',5X,'Number of function values =',I6)
885 0 : PRINT 710, F,(X(I),I=1,N)
886 : end if
887 3 : RETURN
888 : end subroutine BOBYQB
889 :
890 :
891 79 : subroutine ALTMOV (N,NPT,XPT,XOPT,BMAT,ZMAT,NDIM,SL,SU,KOPT,
892 : & KNEW,ADELT,XNEW,XALT,ALPHA,CAUCHY,GLAG,HCOL,W)
893 : implicit real(dp) (A-H,O-Z)
894 : integer :: N, NPT, NDIM, KOPT, KNEW
895 : dimension XPT(NPT,*),XOPT(*),BMAT(NDIM,*),ZMAT(NPT,*),SL(*),
896 : & SU(*),XNEW(*),XALT(*),GLAG(*),HCOL(*),W(*)
897 : !
898 : ! The arguments N, NPT, XPT, XOPT, BMAT, ZMAT, NDIM, SL and SU all have
899 : ! the same meanings as the corresponding arguments of BOBYQB.
900 : ! KOPT is the index of the optimal interpolation point.
901 : ! KNEW is the index of the interpolation point that is going to be moved.
902 : ! ADELT is the current trust region bound.
903 : ! XNEW will be set to a suitable new position for the interpolation point
904 : ! XPT(KNEW,.). Specifically, it satisfies the SL, SU and trust region
905 : ! bounds and it should provide a large denominator in the next call of
906 : ! UPDATE. The step XNEW-XOPT from XOPT is restricted to moves along the
907 : ! straight lines through XOPT and another interpolation point.
908 : ! XALT also provides a large value of the modulus of the KNEW-th Lagrange
909 : ! function subject to the constraints that have been mentioned, its main
910 : ! difference from XNEW being that XALT-XOPT is a constrained version of
911 : ! the Cauchy step within the trust region. An exception is that XALT is
912 : ! not calculated if all components of GLAG (see below) are zero.
913 : ! ALPHA will be set to the KNEW-th diagonal element of the H matrix.
914 : ! CAUCHY will be set to the square of the KNEW-th Lagrange function at
915 : ! the step XALT-XOPT from XOPT for the vector XALT that is returned,
916 : ! except that CAUCHY is set to zero if XALT is not calculated.
917 : ! GLAG is a working space vector of length N for the gradient of the
918 : ! KNEW-th Lagrange function at XOPT.
919 : ! HCOL is a working space vector of length NPT for the second derivative
920 : ! coefficients of the KNEW-th Lagrange function.
921 : ! W is a working space vector of length 2N that is going to hold the
922 : ! constrained Cauchy step from XOPT of the Lagrange function, followed
923 : ! by the downhill version of XALT when the uphill step is calculated.
924 : !
925 : ! Set the first NPT components of W to the leading elements of the
926 : ! KNEW-th column of the H matrix.
927 : !
928 79 : HALF=0.5D0
929 79 : ONE=1.0D0
930 79 : ZERO=0.0D0
931 79 : CONST=ONE+DSQRT(2.0D0)
932 926 : do K=1,NPT
933 926 : HCOL(K)=ZERO
934 : end do
935 463 : do J=1,NPT-N-1
936 463 : TEMP=ZMAT(KNEW,J)
937 4895 : do K=1,NPT
938 4816 : HCOL(K)=HCOL(K)+TEMP*ZMAT(K,J)
939 : end do
940 : end do
941 79 : ALPHA=HCOL(KNEW)
942 158 : HA=HALF*ALPHA
943 : !
944 : ! Calculate the gradient of the KNEW-th Lagrange function at XOPT.
945 : !
946 463 : do I=1,N
947 463 : GLAG(I)=BMAT(KNEW,I)
948 : end do
949 926 : do K=1,NPT
950 : TEMP=ZERO
951 5279 : do J=1,N
952 5279 : TEMP=TEMP+XPT(K,J)*XOPT(J)
953 : end do
954 847 : TEMP=HCOL(K)*TEMP
955 5358 : do I=1,N
956 5279 : GLAG(I)=GLAG(I)+TEMP*XPT(K,I)
957 : end do
958 : end do
959 : !
960 : ! Search for a large denominator along the straight lines through XOPT
961 : ! and another interpolation point. SLBD and SUBD will be lower and upper
962 : ! bounds on the step along each of these lines in turn. PREDSQ will be
963 : ! set to the square of the predicted denominator for each line. PRESAV
964 : ! will be set to the largest admissible value of PREDSQ that occurs.
965 : !
966 79 : PRESAV=ZERO
967 926 : do K=1,NPT
968 847 : if (K == KOPT) CYCLE
969 79 : DDERIV=ZERO
970 79 : DISTSQ=ZERO
971 4816 : do I=1,N
972 4048 : TEMP=XPT(K,I)-XOPT(I)
973 4048 : DDERIV=DDERIV+GLAG(I)*TEMP
974 4816 : DISTSQ=DISTSQ+TEMP*TEMP
975 : end do
976 847 : SUBD=ADELT/DSQRT(DISTSQ)
977 847 : SLBD=-SUBD
978 768 : ILBD=0
979 768 : IUBD=0
980 847 : SUMIN=DMIN1(ONE,SUBD)
981 : !
982 : ! Revise SLBD and SUBD if necessary because of the bounds in SL and SU.
983 : !
984 4816 : do I=1,N
985 4048 : TEMP=XPT(K,I)-XOPT(I)
986 4816 : if (TEMP > ZERO) then
987 1949 : if (SLBD*TEMP < SL(I)-XOPT(I)) then
988 0 : SLBD=(SL(I)-XOPT(I))/TEMP
989 0 : ILBD=-I
990 : end if
991 1949 : if (SUBD*TEMP > SU(I)-XOPT(I)) then
992 0 : SUBD=DMAX1(SUMIN,(SU(I)-XOPT(I))/TEMP)
993 0 : IUBD=I
994 : end if
995 2099 : else if (TEMP < ZERO) then
996 2099 : if (SLBD*TEMP > SU(I)-XOPT(I)) then
997 0 : SLBD=(SU(I)-XOPT(I))/TEMP
998 0 : ILBD=I
999 : end if
1000 2099 : if (SUBD*TEMP < SL(I)-XOPT(I)) then
1001 0 : SUBD=DMAX1(SUMIN,(SL(I)-XOPT(I))/TEMP)
1002 0 : IUBD=-I
1003 : end if
1004 : end if
1005 : end do
1006 : !
1007 : ! Seek a large modulus of the KNEW-th Lagrange function when the index
1008 : ! of the other interpolation point on the line through XOPT is KNEW.
1009 : !
1010 768 : if (K == KNEW) then
1011 158 : DIFF=DDERIV-ONE
1012 158 : STEP=SLBD
1013 158 : VLAG=SLBD*(DDERIV-SLBD*DIFF)
1014 79 : ISBD=ILBD
1015 79 : TEMP=SUBD*(DDERIV-SUBD*DIFF)
1016 79 : if (DABS(TEMP) > DABS(VLAG)) then
1017 37 : STEP=SUBD
1018 37 : VLAG=TEMP
1019 37 : ISBD=IUBD
1020 : end if
1021 158 : TEMPD=HALF*DDERIV
1022 158 : TEMPA=TEMPD-DIFF*SLBD
1023 158 : TEMPB=TEMPD-DIFF*SUBD
1024 79 : if (TEMPA*TEMPB < ZERO) then
1025 40 : TEMP=TEMPD*TEMPD/DIFF
1026 40 : if (DABS(TEMP) > DABS(VLAG)) then
1027 0 : STEP=TEMPD/DIFF
1028 0 : VLAG=TEMP
1029 0 : ISBD=0
1030 : end if
1031 : end if
1032 : !
1033 : ! Search along each of the other lines through XOPT and another point.
1034 : !
1035 : else
1036 689 : STEP=SLBD
1037 689 : VLAG=SLBD*(ONE-SLBD)
1038 689 : ISBD=ILBD
1039 689 : TEMP=SUBD*(ONE-SUBD)
1040 689 : if (DABS(TEMP) > DABS(VLAG)) then
1041 0 : STEP=SUBD
1042 0 : VLAG=TEMP
1043 0 : ISBD=IUBD
1044 : end if
1045 689 : if (SUBD > HALF) then
1046 126 : if (DABS(VLAG) < 0.25D0) then
1047 689 : STEP=HALF
1048 689 : VLAG=0.25D0
1049 689 : ISBD=0
1050 : end if
1051 : end if
1052 689 : VLAG=VLAG*DDERIV
1053 : end if
1054 : !
1055 : ! Calculate PREDSQ for the current line search and maintain PRESAV.
1056 : !
1057 768 : TEMP=STEP*(ONE-STEP)*DISTSQ
1058 847 : PREDSQ=VLAG*VLAG*(VLAG*VLAG+HA*TEMP*TEMP)
1059 847 : if (PREDSQ > PRESAV) then
1060 221 : PRESAV=PREDSQ
1061 221 : KSAV=K
1062 300 : STPSAV=STEP
1063 221 : IBDSAV=ISBD
1064 : end if
1065 : end do
1066 : !
1067 : ! Construct XNEW in a way that satisfies the bound constraints exactly.
1068 : !
1069 463 : do I=1,N
1070 384 : TEMP=XOPT(I)+STPSAV*(XPT(KSAV,I)-XOPT(I))
1071 463 : XNEW(I)=DMAX1(SL(I),DMIN1(SU(I),TEMP))
1072 : end do
1073 79 : if (IBDSAV < 0) XNEW(-IBDSAV)=SL(-IBDSAV)
1074 79 : if (IBDSAV > 0) XNEW(IBDSAV)=SU(IBDSAV)
1075 : !
1076 : ! Prepare for the iterative method that assembles the constrained Cauchy
1077 : ! step in W. The sum of squares of the fixed components of W is formed in
1078 : ! WFIXSQ, and the free components of W are set to BIGSTP.
1079 : !
1080 158 : BIGSTP=ADELT+ADELT
1081 79 : IFLAG=0
1082 237 : 100 WFIXSQ=ZERO
1083 237 : GGFREE=ZERO
1084 926 : do I=1,N
1085 768 : W(I)=ZERO
1086 768 : TEMPA=DMIN1(XOPT(I)-SL(I),GLAG(I))
1087 768 : TEMPB=DMAX1(XOPT(I)-SU(I),GLAG(I))
1088 926 : if (TEMPA > ZERO .or. TEMPB < ZERO) then
1089 768 : W(I)=BIGSTP
1090 768 : GGFREE=GGFREE+GLAG(I)**2
1091 : end if
1092 : end do
1093 158 : if (GGFREE == ZERO) then
1094 0 : CAUCHY=ZERO
1095 0 : GOTO 200
1096 : end if
1097 : !
1098 : ! Investigate whether more components of W can be fixed.
1099 : !
1100 158 : 120 TEMP=ADELT*ADELT-WFIXSQ
1101 158 : if (TEMP > ZERO) then
1102 237 : WSQSAV=WFIXSQ
1103 158 : STEP=DSQRT(TEMP/GGFREE)
1104 158 : GGFREE=ZERO
1105 926 : do I=1,N
1106 926 : if (W(I) == BIGSTP) then
1107 768 : TEMP=XOPT(I)-STEP*GLAG(I)
1108 768 : if (TEMP <= SL(I)) then
1109 0 : W(I)=SL(I)-XOPT(I)
1110 0 : WFIXSQ=WFIXSQ+W(I)**2
1111 768 : else if (TEMP >= SU(I)) then
1112 0 : W(I)=SU(I)-XOPT(I)
1113 0 : WFIXSQ=WFIXSQ+W(I)**2
1114 : else
1115 768 : GGFREE=GGFREE+GLAG(I)**2
1116 : end if
1117 : end if
1118 : end do
1119 158 : if (WFIXSQ > WSQSAV .and. GGFREE > ZERO) GOTO 120
1120 : end if
1121 : !
1122 : ! Set the remaining free components of W and all components of XALT,
1123 : ! except that W may be scaled later.
1124 : !
1125 237 : GW=ZERO
1126 926 : do I=1,N
1127 768 : if (W(I) == BIGSTP) then
1128 768 : W(I)=-STEP*GLAG(I)
1129 768 : XALT(I)=DMAX1(SL(I),DMIN1(SU(I),XOPT(I)+W(I)))
1130 0 : else if (W(I) == ZERO) then
1131 0 : XALT(I)=XOPT(I)
1132 0 : else if (GLAG(I) > ZERO) then
1133 0 : XALT(I)=SL(I)
1134 : else
1135 0 : XALT(I)=SU(I)
1136 : end if
1137 926 : GW=GW+GLAG(I)*W(I)
1138 : end do
1139 : !
1140 : ! Set CURV to the curvature of the KNEW-th Lagrange function along W.
1141 : ! Scale W by a factor less than one if that can reduce the modulus of
1142 : ! the Lagrange function at XOPT+W. Set CAUCHY to the final value of
1143 : ! the square of this function.
1144 : !
1145 79 : CURV=ZERO
1146 1852 : do K=1,NPT
1147 : TEMP=ZERO
1148 10558 : do J=1,N
1149 10558 : TEMP=TEMP+XPT(K,J)*W(J)
1150 : end do
1151 1852 : CURV=CURV+HCOL(K)*TEMP*TEMP
1152 : end do
1153 158 : if (IFLAG == 1) CURV=-CURV
1154 158 : if (CURV > -GW .and. CURV < -CONST*GW) then
1155 85 : SCALE=-GW/CURV
1156 30 : do I=1,N
1157 24 : TEMP=XOPT(I)+SCALE*W(I)
1158 30 : XALT(I)=DMAX1(SL(I),DMIN1(SU(I),TEMP))
1159 : end do
1160 6 : CAUCHY=(HALF*GW*SCALE)**2
1161 : else
1162 152 : CAUCHY=(GW+HALF*CURV)**2
1163 : end if
1164 : !
1165 : ! If IFLAG is zero, then XALT is calculated as before after reversing
1166 : ! the sign of GLAG. Thus two XALT vectors become available. The one that
1167 : ! is chosen is the one that gives the larger value of CAUCHY.
1168 : !
1169 158 : if (IFLAG == 0) then
1170 463 : do I=1,N
1171 384 : GLAG(I)=-GLAG(I)
1172 463 : W(N+I)=XALT(I)
1173 : end do
1174 79 : CSAVE=CAUCHY
1175 79 : IFLAG=1
1176 79 : GOTO 100
1177 : end if
1178 79 : if (CSAVE > CAUCHY) then
1179 132 : do I=1,N
1180 132 : XALT(I)=W(N+I)
1181 : end do
1182 20 : CAUCHY=CSAVE
1183 : end if
1184 79 : 200 RETURN
1185 : end subroutine ALTMOV
1186 :
1187 :
1188 6 : subroutine PRELIM (N,NPT,X,XL,XU,RHOBEG,IPRINT,MAXFUN,XBASE,
1189 3 : & XPT,FVAL,GOPT,HQ,PQ,BMAT,ZMAT,NDIM,SL,SU,NF,KOPT,CALFUN)
1190 : implicit real(dp) (A-H,O-Z)
1191 : dimension X(:),XL(:),XU(:),XBASE(*),XPT(NPT,*),FVAL(*),GOPT(*),
1192 : & HQ(*),PQ(*),BMAT(NDIM,*),ZMAT(NPT,*),SL(*),SU(*)
1193 : interface
1194 : #include "num_bobyqa_proc.dek"
1195 : end interface
1196 : !
1197 : ! The arguments N, NPT, X, XL, XU, RHOBEG, IPRINT and MAXFUN are the
1198 : ! same as the corresponding arguments in subroutine BOBYQA.
1199 : ! The arguments XBASE, XPT, FVAL, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU
1200 : ! are the same as the corresponding arguments in BOBYQB, the elements
1201 : ! of SL and SU being set in BOBYQA.
1202 : ! GOPT is usually the gradient of the quadratic model at XOPT+XBASE, but
1203 : ! it is set by PRELIM to the gradient of the quadratic model at XBASE.
1204 : ! If XOPT is nonzero, BOBYQB will change it to its usual value later.
1205 : ! NF is maintained as the number of calls of CALFUN so far.
1206 : ! KOPT will be such that the least calculated value of F so far is at
1207 : ! the point XPT(KOPT,.)+XBASE in the space of the variables.
1208 : !
1209 : ! subroutine PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ,
1210 : ! BMAT and ZMAT for the first iteration, and it maintains the values of
1211 : ! NF and KOPT. The vector X is also changed by PRELIM.
1212 : !
1213 : ! Set some constants.
1214 : !
1215 3 : HALF=0.5D0
1216 3 : ONE=1.0D0
1217 3 : TWO=2.0D0
1218 3 : ZERO=0.0D0
1219 3 : RHOSQ=RHOBEG*RHOBEG
1220 3 : RECIP=ONE/RHOSQ
1221 3 : NP=N+1
1222 : !
1223 : ! Set XBASE to the initial vector of variables, and set the initial
1224 : ! elements of XPT, BMAT, HQ, PQ and ZMAT to zero.
1225 : !
1226 15 : do J=1,N
1227 12 : XBASE(J)=X(J)
1228 136 : do K=1,NPT
1229 136 : XPT(K,J)=ZERO
1230 : end do
1231 195 : do I=1,NDIM
1232 192 : BMAT(I,J)=ZERO
1233 : end do
1234 : end do
1235 37 : do IH=1,(N*NP)/2
1236 37 : HQ(IH)=ZERO
1237 : end do
1238 30 : do K=1,NPT
1239 27 : PQ(K)=ZERO
1240 154 : do J=1,NPT-NP
1241 151 : ZMAT(K,J)=ZERO
1242 : end do
1243 : end do
1244 : !
1245 : ! Begin the initialization procedure. NF becomes one more than the number
1246 : ! of function values so far. The coordinates of the displacement of the
1247 : ! next initial interpolation point from XBASE are set in XPT(NF+1,.).
1248 : !
1249 3 : NF=0
1250 27 : 50 NFM=NF
1251 27 : NFX=NF-N
1252 27 : NF=NF+1
1253 27 : if (NFM <= 2*N) then
1254 27 : if (NFM >= 1 .and. NFM <= N) then
1255 15 : STEPA=RHOBEG
1256 12 : if (SU(NFM) == ZERO) STEPA=-STEPA
1257 12 : XPT(NF,NFM)=STEPA
1258 15 : else if (NFM > N) then
1259 12 : STEPA=XPT(NF-N,NFX)
1260 15 : STEPB=-RHOBEG
1261 12 : if (SL(NFX) == ZERO) STEPB=DMIN1(TWO*RHOBEG,SU(NFX))
1262 12 : if (SU(NFX) == ZERO) STEPB=DMAX1(-TWO*RHOBEG,SL(NFX))
1263 12 : XPT(NF,NFX)=STEPB
1264 : end if
1265 : else
1266 0 : ITEMP=(NFM-NP)/N
1267 0 : JPT=NFM-ITEMP*N-N
1268 0 : IPT=JPT+ITEMP
1269 0 : if (IPT > N) then
1270 0 : ITEMP=JPT
1271 0 : JPT=IPT-N
1272 0 : IPT=ITEMP
1273 : end if
1274 0 : XPT(NF,IPT)=XPT(IPT+1,IPT)
1275 0 : XPT(NF,JPT)=XPT(JPT+1,JPT)
1276 : end if
1277 : !
1278 : ! Calculate the next value of F. The least function value so far and
1279 : ! its index are required.
1280 : !
1281 151 : do J=1,N
1282 124 : X(J)=DMIN1(DMAX1(XL(J),XBASE(J)+XPT(NF,J)),XU(J))
1283 124 : if (XPT(NF,J) == SL(J)) X(J)=XL(J)
1284 151 : if (XPT(NF,J) == SU(J)) X(J)=XU(J)
1285 : end do
1286 27 : CALL CALFUN (N,X,F)
1287 27 : if (IPRINT == 3) then
1288 0 : PRINT 70, NF,F,(X(I),I=1,N)
1289 : 70 FORMAT (/4X,'Function number',I6,' F =',1PD18.10,' The corresponding X is:'/(2X,5D15.6))
1290 : end if
1291 27 : FVAL(NF)=F
1292 27 : if (NF == 1) then
1293 6 : FBEG=F
1294 3 : KOPT=1
1295 24 : else if (F < FVAL(KOPT)) then
1296 8 : KOPT=NF
1297 : end if
1298 : !
1299 : ! Set the nonzero initial elements of BMAT and the quadratic model in the
1300 : ! cases when NF is at most 2*N+1. If NF exceeds N+1, then the positions
1301 : ! of the NF-th and (NF-N)-th interpolation points may be switched, in
1302 : ! order that the function value at the first of them contributes to the
1303 : ! off-diagonal second derivative terms of the initial quadratic model.
1304 : !
1305 27 : if (NF <= 2*N+1) then
1306 27 : if (NF >= 2 .and. NF <= N+1) then
1307 12 : GOPT(NFM)=(F-FBEG)/STEPA
1308 12 : if (NPT < NF+N) then
1309 0 : BMAT(1,NFM)=-ONE/STEPA
1310 0 : BMAT(NF,NFM)=ONE/STEPA
1311 0 : BMAT(NPT+NFM,NFM)=-HALF*RHOSQ
1312 : end if
1313 15 : else if (NF >= N+2) then
1314 12 : IH=(NFX*(NFX+1))/2
1315 15 : TEMP=(F-FBEG)/STEPB
1316 3 : DIFF=STEPB-STEPA
1317 12 : HQ(IH)=TWO*(TEMP-GOPT(NFX))/DIFF
1318 12 : GOPT(NFX)=(GOPT(NFX)*STEPB-TEMP*STEPA)/DIFF
1319 12 : if (STEPA*STEPB < ZERO) then
1320 12 : if (F < FVAL(NF-N)) then
1321 6 : FVAL(NF)=FVAL(NF-N)
1322 6 : FVAL(NF-N)=F
1323 6 : if (KOPT == NF) KOPT=NF-N
1324 6 : XPT(NF-N,NFX)=STEPB
1325 6 : XPT(NF,NFX)=STEPA
1326 : end if
1327 : end if
1328 12 : BMAT(1,NFX)=-(STEPA+STEPB)/(STEPA*STEPB)
1329 12 : BMAT(NF,NFX)=-HALF/XPT(NF-N,NFX)
1330 12 : BMAT(NF-N,NFX)=-BMAT(1,NFX)-BMAT(NF,NFX)
1331 12 : ZMAT(1,NFX)=DSQRT(TWO)/(STEPA*STEPB)
1332 12 : ZMAT(NF,NFX)=DSQRT(HALF)/RHOSQ
1333 12 : ZMAT(NF-N,NFX)=-ZMAT(1,NFX)-ZMAT(NF,NFX)
1334 : end if
1335 : !
1336 : ! Set the off-diagonal second derivatives of the Lagrange functions and
1337 : ! the initial quadratic model.
1338 : !
1339 : else
1340 0 : IH=(IPT*(IPT-1))/2+JPT
1341 0 : ZMAT(1,NFX)=RECIP
1342 0 : ZMAT(NF,NFX)=RECIP
1343 0 : ZMAT(IPT+1,NFX)=-RECIP
1344 0 : ZMAT(JPT+1,NFX)=-RECIP
1345 0 : TEMP=XPT(NF,IPT)*XPT(NF,JPT)
1346 0 : HQ(IH)=(FBEG-FVAL(IPT+1)-FVAL(JPT+1)+F)/TEMP
1347 : end if
1348 27 : if (NF < NPT .and. NF < MAXFUN) GOTO 50
1349 3 : RETURN
1350 : end subroutine PRELIM
1351 :
1352 :
1353 0 : subroutine RESCUE (N,NPT,XL,XU,IPRINT,MAXFUN,XBASE,XPT,
1354 0 : & FVAL,XOPT,GOPT,HQ,PQ,BMAT,ZMAT,NDIM,SL,SU,NF,DELTA,
1355 : & KOPT,VLAG,PTSAUX,PTSID,W,CALFUN)
1356 : implicit real(dp) (A-H,O-Z)
1357 : dimension XL(:),XU(:),XBASE(*),XPT(NPT,*),FVAL(*),XOPT(*),
1358 : & GOPT(*),HQ(*),PQ(*),BMAT(NDIM,*),ZMAT(NPT,*),SL(*),SU(*),
1359 : & VLAG(*),PTSAUX(2,*),PTSID(*),W(*)
1360 : interface
1361 : #include "num_bobyqa_proc.dek"
1362 : end interface
1363 : !
1364 : ! The arguments N, NPT, XL, XU, IPRINT, MAXFUN, XBASE, XPT, FVAL, XOPT,
1365 : ! GOPT, HQ, PQ, BMAT, ZMAT, NDIM, SL and SU have the same meanings as
1366 : ! the corresponding arguments of BOBYQB on the entry to RESCUE.
1367 : ! NF is maintained as the number of calls of CALFUN so far, except that
1368 : ! NF is set to -1 if the value of MAXFUN prevents further progress.
1369 : ! KOPT is maintained so that FVAL(KOPT) is the least calculated function
1370 : ! value. Its correct value must be given on entry. It is updated if a
1371 : ! new least function value is found, but the corresponding changes to
1372 : ! XOPT and GOPT have to be made later by the calling program.
1373 : ! DELTA is the current trust region radius.
1374 : ! VLAG is a working space vector that will be used for the values of the
1375 : ! provisional Lagrange functions at each of the interpolation points.
1376 : ! They are part of a product that requires VLAG to be of length NDIM.
1377 : ! PTSAUX is also a working space array. For J=1,2,...,N, PTSAUX(1,J) and
1378 : ! PTSAUX(2,J) specify the two positions of provisional interpolation
1379 : ! points when a nonzero step is taken along e_J (the J-th coordinate
1380 : ! direction) through XBASE+XOPT, as specified below. Usually these
1381 : ! steps have length DELTA, but other lengths are chosen if necessary
1382 : ! in order to satisfy the given bounds on the variables.
1383 : ! PTSID is also a working space array. It has NPT components that denote
1384 : ! provisional new positions of the original interpolation points, in
1385 : ! case changes are needed to restore the linear independence of the
1386 : ! interpolation conditions. The K-th point is a candidate for change
1387 : ! if and only if PTSID(K) is nonzero. In this case let p and q be the
1388 : ! integer parts of PTSID(K) and (PTSID(K)-p) multiplied by N+1. If p
1389 : ! and q are both positive, the step from XBASE+XOPT to the new K-th
1390 : ! interpolation point is PTSAUX(1,p)*e_p + PTSAUX(1,q)*e_q. Otherwise
1391 : ! the step is PTSAUX(1,p)*e_p or PTSAUX(2,q)*e_q in the cases q=0 or
1392 : ! p=0, respectively.
1393 : ! The first NDIM+NPT elements of the array W are used for working space.
1394 : ! The final elements of BMAT and ZMAT are set in a well-conditioned way
1395 : ! to the values that are appropriate for the new interpolation points.
1396 : ! The elements of GOPT, HQ and PQ are also revised to the values that are
1397 : ! appropriate to the final quadratic model.
1398 : !
1399 : ! Set some constants.
1400 : !
1401 0 : HALF=0.5D0
1402 0 : ONE=1.0D0
1403 0 : ZERO=0.0D0
1404 0 : NP=N+1
1405 0 : SFRAC=HALF/DBLE(NP)
1406 0 : NPTM=NPT-NP
1407 : !
1408 : ! Shift the interpolation points so that XOPT becomes the origin, and set
1409 : ! the elements of ZMAT to zero. The value of SUMPQ is required in the
1410 : ! updating of HQ below. The squares of the distances from XOPT to the
1411 : ! other interpolation points are set at the end of W. Increments of WINC
1412 : ! may be added later to these squares to balance the consideration of
1413 : ! the choice of point that is going to become current.
1414 : !
1415 0 : SUMPQ=ZERO
1416 0 : WINC=ZERO
1417 0 : do K=1,NPT
1418 0 : DISTSQ=ZERO
1419 0 : do J=1,N
1420 0 : XPT(K,J)=XPT(K,J)-XOPT(J)
1421 0 : DISTSQ=DISTSQ+XPT(K,J)**2
1422 : end do
1423 0 : SUMPQ=SUMPQ+PQ(K)
1424 0 : W(NDIM+K)=DISTSQ
1425 0 : WINC=DMAX1(WINC,DISTSQ)
1426 0 : do J=1,NPTM
1427 0 : ZMAT(K,J)=ZERO
1428 : end do
1429 : end do
1430 : !
1431 : ! Update HQ so that HQ and PQ define the second derivatives of the model
1432 : ! after XBASE has been shifted to the trust region centre.
1433 : !
1434 : IH=0
1435 0 : do J=1,N
1436 0 : W(J)=HALF*SUMPQ*XOPT(J)
1437 0 : do K=1,NPT
1438 0 : W(J)=W(J)+PQ(K)*XPT(K,J)
1439 : end do
1440 0 : do I=1,J
1441 0 : IH=IH+1
1442 0 : HQ(IH)=HQ(IH)+W(I)*XOPT(J)+W(J)*XOPT(I)
1443 : end do
1444 : end do
1445 : !
1446 : ! Shift XBASE, SL, SU and XOPT. Set the elements of BMAT to zero, and
1447 : ! also set the elements of PTSAUX.
1448 : !
1449 0 : do J=1,N
1450 0 : XBASE(J)=XBASE(J)+XOPT(J)
1451 0 : SL(J)=SL(J)-XOPT(J)
1452 0 : SU(J)=SU(J)-XOPT(J)
1453 0 : XOPT(J)=ZERO
1454 0 : PTSAUX(1,J)=DMIN1(DELTA,SU(J))
1455 0 : PTSAUX(2,J)=DMAX1(-DELTA,SL(J))
1456 0 : if (PTSAUX(1,J)+PTSAUX(2,J) < ZERO) then
1457 0 : TEMP=PTSAUX(1,J)
1458 0 : PTSAUX(1,J)=PTSAUX(2,J)
1459 0 : PTSAUX(2,J)=TEMP
1460 : end if
1461 0 : if (DABS(PTSAUX(2,J)) < HALF*DABS(PTSAUX(1,J))) then
1462 0 : PTSAUX(2,J)=HALF*PTSAUX(1,J)
1463 : end if
1464 0 : do I=1,NDIM
1465 0 : BMAT(I,J)=ZERO
1466 : end do
1467 : end do
1468 0 : FBASE=FVAL(KOPT)
1469 : !
1470 : ! Set the identifiers of the artificial interpolation points that are
1471 : ! along a coordinate direction from XOPT, and set the corresponding
1472 : ! nonzero elements of BMAT and ZMAT.
1473 : !
1474 0 : PTSID(1)=SFRAC
1475 0 : do J=1,N
1476 0 : JP=J+1
1477 0 : JPN=JP+N
1478 0 : PTSID(JP)=DBLE(J)+SFRAC
1479 0 : if (JPN <= NPT) then
1480 0 : PTSID(JPN)=DBLE(J)/DBLE(NP)+SFRAC
1481 0 : TEMP=ONE/(PTSAUX(1,J)-PTSAUX(2,J))
1482 0 : BMAT(JP,J)=-TEMP+ONE/PTSAUX(1,J)
1483 0 : BMAT(JPN,J)=TEMP+ONE/PTSAUX(2,J)
1484 0 : BMAT(1,J)=-BMAT(JP,J)-BMAT(JPN,J)
1485 0 : ZMAT(1,J)=DSQRT(2.0D0)/DABS(PTSAUX(1,J)*PTSAUX(2,J))
1486 0 : ZMAT(JP,J)=ZMAT(1,J)*PTSAUX(2,J)*TEMP
1487 0 : ZMAT(JPN,J)=-ZMAT(1,J)*PTSAUX(1,J)*TEMP
1488 : else
1489 0 : BMAT(1,J)=-ONE/PTSAUX(1,J)
1490 0 : BMAT(JP,J)=ONE/PTSAUX(1,J)
1491 0 : BMAT(J+NPT,J)=-HALF*PTSAUX(1,J)**2
1492 : end if
1493 : end do
1494 : !
1495 : ! Set any remaining identifiers with their nonzero elements of ZMAT.
1496 : !
1497 0 : if (NPT >= N+NP) then
1498 0 : do K=2*NP,NPT
1499 0 : IW=(DBLE(K-NP)-HALF)/DBLE(N)
1500 0 : IP=K-NP-IW*N
1501 0 : IQ=IP+IW
1502 0 : if (IQ > N) IQ=IQ-N
1503 0 : PTSID(K)=DBLE(IP)+DBLE(IQ)/DBLE(NP)+SFRAC
1504 0 : TEMP=ONE/(PTSAUX(1,IP)*PTSAUX(1,IQ))
1505 0 : ZMAT(1,K-NP)=TEMP
1506 0 : ZMAT(IP+1,K-NP)=-TEMP
1507 0 : ZMAT(IQ+1,K-NP)=-TEMP
1508 0 : ZMAT(K,K-NP)=TEMP
1509 : end do
1510 : end if
1511 0 : NREM=NPT
1512 0 : KOLD=1
1513 0 : KNEW=KOPT
1514 : !
1515 : ! Reorder the provisional points in the way that exchanges PTSID(KOLD)
1516 : ! with PTSID(KNEW).
1517 : !
1518 0 : 80 do J=1,N
1519 0 : TEMP=BMAT(KOLD,J)
1520 0 : BMAT(KOLD,J)=BMAT(KNEW,J)
1521 0 : BMAT(KNEW,J)=TEMP
1522 : end do
1523 0 : do J=1,NPTM
1524 0 : TEMP=ZMAT(KOLD,J)
1525 0 : ZMAT(KOLD,J)=ZMAT(KNEW,J)
1526 0 : ZMAT(KNEW,J)=TEMP
1527 : end do
1528 0 : PTSID(KOLD)=PTSID(KNEW)
1529 0 : PTSID(KNEW)=ZERO
1530 0 : W(NDIM+KNEW)=ZERO
1531 0 : NREM=NREM-1
1532 0 : if (KNEW /= KOPT) then
1533 0 : TEMP=VLAG(KOLD)
1534 0 : VLAG(KOLD)=VLAG(KNEW)
1535 0 : VLAG(KNEW)=TEMP
1536 : !
1537 : ! Update the BMAT and ZMAT matrices so that the status of the KNEW-th
1538 : ! interpolation point can be changed from provisional to original. The
1539 : ! branch to label 350 occurs if all the original points are reinstated.
1540 : ! The nonnegative values of W(NDIM+K) are required in the search below.
1541 : !
1542 0 : CALL UPDATE (N,NPT,BMAT,ZMAT,NDIM,VLAG,BETA,DENOM,KNEW,W)
1543 0 : if (NREM == 0) GOTO 350
1544 0 : do K=1,NPT
1545 0 : W(NDIM+K)=DABS(W(NDIM+K))
1546 : end do
1547 : end if
1548 : !
1549 : ! Pick the index KNEW of an original interpolation point that has not
1550 : ! yet replaced one of the provisional interpolation points, giving
1551 : ! attention to the closeness to XOPT and to previous tries with KNEW.
1552 : !
1553 0 : 120 DSQMIN=ZERO
1554 0 : do K=1,NPT
1555 0 : if (W(NDIM+K) > ZERO) then
1556 0 : if (DSQMIN == ZERO .or. W(NDIM+K) < DSQMIN) then
1557 0 : KNEW=K
1558 0 : DSQMIN=W(NDIM+K)
1559 : end if
1560 : end if
1561 : end do
1562 0 : if (DSQMIN == ZERO) GOTO 260
1563 : !
1564 : ! Form the W-vector of the chosen original interpolation point.
1565 : !
1566 0 : do J=1,N
1567 0 : W(NPT+J)=XPT(KNEW,J)
1568 : end do
1569 0 : do K=1,NPT
1570 0 : SUM=ZERO
1571 0 : if (K == KOPT) then
1572 : ! do nothing
1573 0 : else if (PTSID(K) == ZERO) then
1574 0 : do J=1,N
1575 0 : SUM=SUM+W(NPT+J)*XPT(K,J)
1576 : end do
1577 : else
1578 0 : IP=PTSID(K)
1579 0 : if (IP > 0) SUM=W(NPT+IP)*PTSAUX(1,IP)
1580 0 : IQ=DBLE(NP)*PTSID(K)-DBLE(IP*NP)
1581 0 : if (IQ > 0) then
1582 0 : IW=1
1583 0 : if (IP == 0) IW=2
1584 0 : SUM=SUM+W(NPT+IQ)*PTSAUX(IW,IQ)
1585 : end if
1586 : end if
1587 0 : W(K)=HALF*SUM*SUM
1588 : end do
1589 : !
1590 : ! Calculate VLAG and BETA for the required updating of the H matrix if
1591 : ! XPT(KNEW,.) is reinstated in the set of interpolation points.
1592 : !
1593 0 : do K=1,NPT
1594 : SUM=ZERO
1595 0 : do J=1,N
1596 0 : SUM=SUM+BMAT(K,J)*W(NPT+J)
1597 : end do
1598 0 : VLAG(K)=SUM
1599 : end do
1600 0 : BETA=ZERO
1601 0 : do J=1,NPTM
1602 : SUM=ZERO
1603 0 : do K=1,NPT
1604 0 : SUM=SUM+ZMAT(K,J)*W(K)
1605 : end do
1606 0 : BETA=BETA-SUM*SUM
1607 0 : do K=1,NPT
1608 0 : VLAG(K)=VLAG(K)+SUM*ZMAT(K,J)
1609 : end do
1610 : end do
1611 0 : BSUM=ZERO
1612 : DISTSQ=ZERO
1613 0 : do J=1,N
1614 : SUM=ZERO
1615 0 : do K=1,NPT
1616 0 : SUM=SUM+BMAT(K,J)*W(K)
1617 : end do
1618 0 : JP=J+NPT
1619 0 : BSUM=BSUM+SUM*W(JP)
1620 0 : do IP=NPT+1,NDIM
1621 0 : SUM=SUM+BMAT(IP,J)*W(IP)
1622 : end do
1623 0 : BSUM=BSUM+SUM*W(JP)
1624 0 : VLAG(JP)=SUM
1625 0 : DISTSQ=DISTSQ+XPT(KNEW,J)**2
1626 : end do
1627 0 : BETA=HALF*DISTSQ*DISTSQ+BETA-BSUM
1628 0 : VLAG(KOPT)=VLAG(KOPT)+ONE
1629 : !
1630 : ! KOLD is set to the index of the provisional interpolation point that is
1631 : ! going to be deleted to make way for the KNEW-th original interpolation
1632 : ! point. The choice of KOLD is governed by the avoidance of a small value
1633 : ! of the denominator in the updating calculation of UPDATE.
1634 : !
1635 0 : DENOM=ZERO
1636 0 : VLMXSQ=ZERO
1637 0 : do K=1,NPT
1638 0 : if (PTSID(K) /= ZERO) then
1639 0 : HDIAG=ZERO
1640 0 : do J=1,NPTM
1641 0 : HDIAG=HDIAG+ZMAT(K,J)**2
1642 : end do
1643 0 : DEN=BETA*HDIAG+VLAG(K)**2
1644 0 : if (DEN > DENOM) then
1645 0 : KOLD=K
1646 0 : DENOM=DEN
1647 : end if
1648 : end if
1649 0 : VLMXSQ=DMAX1(VLMXSQ,VLAG(K)**2)
1650 : end do
1651 0 : if (DENOM <= 1.0D-2*VLMXSQ) then
1652 0 : W(NDIM+KNEW)=-W(NDIM+KNEW)-WINC
1653 0 : GOTO 120
1654 : end if
1655 0 : GOTO 80
1656 : !
1657 : ! When label 260 is reached, all the final positions of the interpolation
1658 : ! points have been chosen although any changes have not been included yet
1659 : ! in XPT. Also the final BMAT and ZMAT matrices are complete, but, apart
1660 : ! from the shift of XBASE, the updating of the quadratic model remains to
1661 : ! be done. The following cycle through the new interpolation points begins
1662 : ! by putting the new point in XPT(KPT,.) and by setting PQ(KPT) to zero,
1663 : ! except that a RETURN occurs if MAXFUN prohibits another value of F.
1664 : !
1665 0 : 260 do KPT=1,NPT
1666 0 : if (PTSID(KPT) == ZERO) CYCLE
1667 0 : if (NF >= MAXFUN) then
1668 0 : NF=-1
1669 0 : GOTO 350
1670 : end if
1671 0 : IH=0
1672 0 : do J=1,N
1673 0 : W(J)=XPT(KPT,J)
1674 0 : XPT(KPT,J)=ZERO
1675 0 : TEMP=PQ(KPT)*W(J)
1676 0 : do I=1,J
1677 0 : IH=IH+1
1678 0 : HQ(IH)=HQ(IH)+TEMP*W(I)
1679 : end do
1680 : end do
1681 0 : PQ(KPT)=ZERO
1682 0 : IP=PTSID(KPT)
1683 0 : IQ=DBLE(NP)*PTSID(KPT)-DBLE(IP*NP)
1684 0 : if (IP > 0) then
1685 0 : XP=PTSAUX(1,IP)
1686 0 : XPT(KPT,IP)=XP
1687 : end if
1688 0 : if (IQ > 0) then
1689 0 : XQ=PTSAUX(1,IQ)
1690 0 : if (IP == 0) XQ=PTSAUX(2,IQ)
1691 0 : XPT(KPT,IQ)=XQ
1692 : end if
1693 : !
1694 : ! Set VQUAD to the value of the current model at the new point.
1695 : !
1696 0 : VQUAD=FBASE
1697 0 : if (IP > 0) then
1698 0 : IHP=(IP+IP*IP)/2
1699 0 : VQUAD=VQUAD+XP*(GOPT(IP)+HALF*XP*HQ(IHP))
1700 : end if
1701 0 : if (IQ > 0) then
1702 0 : IHQ=(IQ+IQ*IQ)/2
1703 0 : VQUAD=VQUAD+XQ*(GOPT(IQ)+HALF*XQ*HQ(IHQ))
1704 0 : if (IP > 0) then
1705 0 : IW=MAX0(IHP,IHQ)-IABS(IP-IQ)
1706 0 : VQUAD=VQUAD+XP*XQ*HQ(IW)
1707 : end if
1708 : end if
1709 0 : do K=1,NPT
1710 0 : TEMP=ZERO
1711 0 : if (IP > 0) TEMP=TEMP+XP*XPT(K,IP)
1712 0 : if (IQ > 0) TEMP=TEMP+XQ*XPT(K,IQ)
1713 0 : VQUAD=VQUAD+HALF*PQ(K)*TEMP*TEMP
1714 : end do
1715 : !
1716 : ! Calculate F at the new interpolation point, and set DIFF to the factor
1717 : ! that is going to multiply the KPT-th Lagrange function when the model
1718 : ! is updated to provide interpolation to the new function value.
1719 : !
1720 0 : do I=1,N
1721 0 : W(I)=DMIN1(DMAX1(XL(I),XBASE(I)+XPT(KPT,I)),XU(I))
1722 0 : if (XPT(KPT,I) == SL(I)) W(I)=XL(I)
1723 0 : if (XPT(KPT,I) == SU(I)) W(I)=XU(I)
1724 : end do
1725 0 : NF=NF+1
1726 0 : CALL CALFUN (N,W,F)
1727 0 : if (IPRINT == 3) then
1728 0 : PRINT 300, NF,F,(W(I),I=1,N)
1729 : 300 FORMAT (/4X,'Function number',I6,' F =',1PD18.10,' The corresponding X is:'/(2X,5D15.6))
1730 : end if
1731 0 : FVAL(KPT)=F
1732 0 : if (F < FVAL(KOPT)) KOPT=KPT
1733 0 : DIFF=F-VQUAD
1734 : !
1735 : ! Update the quadratic model. The RETURN from the subroutine occurs when
1736 : ! all the new interpolation points are included in the model.
1737 : !
1738 0 : do I=1,N
1739 0 : GOPT(I)=GOPT(I)+DIFF*BMAT(KPT,I)
1740 : end do
1741 0 : do K=1,NPT
1742 : SUM=ZERO
1743 0 : do J=1,NPTM
1744 0 : SUM=SUM+ZMAT(K,J)*ZMAT(KPT,J)
1745 : end do
1746 0 : TEMP=DIFF*SUM
1747 0 : if (PTSID(K) == ZERO) then
1748 0 : PQ(K)=PQ(K)+TEMP
1749 : else
1750 0 : IP=PTSID(K)
1751 0 : IQ=DBLE(NP)*PTSID(K)-DBLE(IP*NP)
1752 0 : IHQ=(IQ*IQ+IQ)/2
1753 0 : if (IP == 0) then
1754 0 : HQ(IHQ)=HQ(IHQ)+TEMP*PTSAUX(2,IQ)**2
1755 : else
1756 0 : IHP=(IP*IP+IP)/2
1757 0 : HQ(IHP)=HQ(IHP)+TEMP*PTSAUX(1,IP)**2
1758 0 : if (IQ > 0) then
1759 0 : HQ(IHQ)=HQ(IHQ)+TEMP*PTSAUX(1,IQ)**2
1760 0 : IW=MAX0(IHP,IHQ)-IABS(IQ-IP)
1761 0 : HQ(IW)=HQ(IW)+TEMP*PTSAUX(1,IP)*PTSAUX(1,IQ)
1762 : end if
1763 : end if
1764 : end if
1765 : end do
1766 0 : PTSID(KPT)=ZERO
1767 : end do
1768 0 : 350 RETURN
1769 : end subroutine RESCUE
1770 :
1771 :
1772 227 : subroutine TRSBOX (N,NPT,XPT,XOPT,GOPT,HQ,PQ,SL,SU,DELTA,
1773 : & XNEW,D,GNEW,XBDI,S,HS,HRED,DSQ,CRVMIN)
1774 : implicit real(dp) (A-H,O-Z)
1775 : dimension XPT(NPT,*),XOPT(*),GOPT(*),HQ(*),PQ(*),SL(*),SU(*),
1776 : & XNEW(*),D(*),GNEW(*),XBDI(*),S(*),HS(*),HRED(*)
1777 : !
1778 : ! The arguments N, NPT, XPT, XOPT, GOPT, HQ, PQ, SL and SU have the same
1779 : ! meanings as the corresponding arguments of BOBYQB.
1780 : ! DELTA is the trust region radius for the present calculation, which
1781 : ! seeks a small value of the quadratic model within distance DELTA of
1782 : ! XOPT subject to the bounds on the variables.
1783 : ! XNEW will be set to a new vector of variables that is approximately
1784 : ! the one that minimizes the quadratic model within the trust region
1785 : ! subject to the SL and SU constraints on the variables. It satisfies
1786 : ! as equations the bounds that become active during the calculation.
1787 : ! D is the calculated trial step from XOPT, generated iteratively from an
1788 : ! initial value of zero. Thus XNEW is XOPT+D after the final iteration.
1789 : ! GNEW holds the gradient of the quadratic model at XOPT+D. It is updated
1790 : ! when D is updated.
1791 : ! XBDI is a working space vector. For I=1,2,...,N, the element XBDI(I) is
1792 : ! set to -1.0, 0.0, or 1.0, the value being nonzero if and only if the
1793 : ! I-th variable has become fixed at a bound, the bound being SL(I) or
1794 : ! SU(I) in the case XBDI(I)=-1.0 or XBDI(I)=1.0, respectively. This
1795 : ! information is accumulated during the construction of XNEW.
1796 : ! The arrays S, HS and HRED are also used for working space. They hold the
1797 : ! current search direction, and the changes in the gradient of Q along S
1798 : ! and the reduced D, respectively, where the reduced D is the same as D,
1799 : ! except that the components of the fixed variables are zero.
1800 : ! DSQ will be set to the square of the length of XNEW-XOPT.
1801 : ! CRVMIN is set to zero if D reaches the trust region boundary. Otherwise
1802 : ! it is set to the least curvature of H that occurs in the conjugate
1803 : ! gradient searches that are not restricted by any constraints. The
1804 : ! value CRVMIN=-1.0D0 is set, however, if all of these searches are
1805 : ! constrained.
1806 : !
1807 : ! A version of the truncated conjugate gradient is applied. If a line
1808 : ! search is restricted by a constraint, then the procedure is restarted,
1809 : ! the values of the variables that are at their bounds being fixed. If
1810 : ! the trust region boundary is reached, then further changes may be made
1811 : ! to D, each one being in the two dimensional space that is spanned
1812 : ! by the current D and the gradient of Q at XOPT+D, staying on the trust
1813 : ! region boundary. Termination occurs when the reduction in Q seems to
1814 : ! be close to the greatest reduction that can be achieved.
1815 : !
1816 : ! Set some constants.
1817 : !
1818 227 : HALF=0.5D0
1819 227 : ONE=1.0D0
1820 227 : ONEMIN=-1.0D0
1821 227 : ZERO=0.0D0
1822 : !
1823 : ! The sign of GOPT(I) gives the sign of the change to the I-th variable
1824 : ! that will reduce Q from its value at XOPT. Thus XBDI(I) shows whether
1825 : ! or not to fix the I-th variable at one of its bounds initially, with
1826 : ! NACT being set to the number of fixed variables. D and GNEW are also
1827 : ! set for the first iteration. DELSQ is the upper bound on the sum of
1828 : ! squares of the free variables. QRED is the reduction in Q so far.
1829 : !
1830 227 : ITERC=0
1831 227 : NACT=0
1832 227 : SQSTP=ZERO
1833 1327 : do I=1,N
1834 1100 : XBDI(I)=ZERO
1835 1100 : if (XOPT(I) <= SL(I)) then
1836 0 : if (GOPT(I) >= ZERO) XBDI(I)=ONEMIN
1837 1100 : else if (XOPT(I) >= SU(I)) then
1838 0 : if (GOPT(I) <= ZERO) XBDI(I)=ONE
1839 : end if
1840 1100 : if (XBDI(I) /= ZERO) NACT=NACT+1
1841 1100 : D(I)=ZERO
1842 1327 : GNEW(I)=GOPT(I)
1843 : end do
1844 454 : DELSQ=DELTA*DELTA
1845 454 : QRED=ZERO
1846 227 : CRVMIN=ONEMIN
1847 : !
1848 : ! Set the next search direction of the conjugate gradient method. It is
1849 : ! the steepest descent direction initially and when the iterations are
1850 : ! restarted because a variable has just been fixed by a bound, and of
1851 : ! course the components of the fixed variables are zero. ITERMAX is an
1852 : ! upper bound on the indices of the conjugate gradient iterations.
1853 : !
1854 227 : 20 BETA=ZERO
1855 913 : 30 STEPSQ=ZERO
1856 4180 : do I=1,N
1857 3494 : if (XBDI(I) /= ZERO) then
1858 0 : S(I)=ZERO
1859 3494 : else if (BETA == ZERO) then
1860 1100 : S(I)=-GNEW(I)
1861 : else
1862 2394 : S(I)=BETA*S(I)-GNEW(I)
1863 : end if
1864 4180 : STEPSQ=STEPSQ+S(I)**2
1865 : end do
1866 686 : if (STEPSQ == ZERO) GOTO 190
1867 686 : if (BETA == ZERO) then
1868 454 : GREDSQ=STEPSQ
1869 227 : ITERMAX=ITERC+N-NACT
1870 : end if
1871 686 : if (GREDSQ*DELSQ <= 1.0D-4*QRED*QRED) GOTO 190
1872 : !
1873 : ! Multiply the search direction by the second derivative matrix of Q and
1874 : ! calculate some scalars for the choice of steplength. Then set BLEN to
1875 : ! the length of the the step to the trust region boundary and STPLEN to
1876 : ! the steplength, ignoring the simple bounds.
1877 : !
1878 686 : GOTO 210
1879 227 : 50 RESID=DELSQ
1880 227 : DS=ZERO
1881 227 : SHS=ZERO
1882 4180 : do I=1,N
1883 4180 : if (XBDI(I) == ZERO) then
1884 3494 : RESID=RESID-D(I)**2
1885 3494 : DS=DS+S(I)*D(I)
1886 3494 : SHS=SHS+S(I)*HS(I)
1887 : end if
1888 : end do
1889 686 : if (RESID <= ZERO) GOTO 90
1890 913 : TEMP=DSQRT(STEPSQ*RESID+DS*DS)
1891 686 : if (DS < ZERO) then
1892 0 : BLEN=(TEMP-DS)/STEPSQ
1893 : else
1894 686 : BLEN=RESID/(TEMP+DS)
1895 : end if
1896 913 : STPLEN=BLEN
1897 686 : if (SHS > ZERO) then
1898 680 : STPLEN=DMIN1(BLEN,GREDSQ/SHS)
1899 : end if
1900 :
1901 : !
1902 : ! Reduce STPLEN if necessary in order to preserve the simple bounds,
1903 : ! letting IACT be the index of the new constrained variable.
1904 : !
1905 : IACT=0
1906 4180 : do I=1,N
1907 4180 : if (S(I) /= ZERO) then
1908 3721 : XSUM=XOPT(I)+D(I)
1909 3494 : if (S(I) > ZERO) then
1910 1713 : TEMP=(SU(I)-XSUM)/S(I)
1911 : else
1912 1781 : TEMP=(SL(I)-XSUM)/S(I)
1913 : end if
1914 3494 : if (TEMP < STPLEN) then
1915 3494 : STPLEN=TEMP
1916 3494 : IACT=I
1917 : end if
1918 : end if
1919 : end do
1920 : !
1921 : ! Update CRVMIN, GNEW and D. Set SDEC to the decrease that occurs in Q.
1922 : !
1923 913 : SDEC=ZERO
1924 686 : if (STPLEN > ZERO) then
1925 686 : ITERC=ITERC+1
1926 686 : TEMP=SHS/STEPSQ
1927 686 : if (IACT == 0 .and. TEMP > ZERO) then
1928 680 : CRVMIN=DMIN1(CRVMIN,TEMP)
1929 680 : if (CRVMIN == ONEMIN) CRVMIN=TEMP
1930 : end if
1931 4407 : GGSAV=GREDSQ
1932 : GREDSQ=ZERO
1933 4180 : do I=1,N
1934 3494 : GNEW(I)=GNEW(I)+STPLEN*HS(I)
1935 3494 : if (XBDI(I) == ZERO) GREDSQ=GREDSQ+GNEW(I)**2
1936 4180 : D(I)=D(I)+STPLEN*S(I)
1937 : end do
1938 686 : SDEC=DMAX1(STPLEN*(GGSAV-HALF*STPLEN*SHS),ZERO)
1939 686 : QRED=QRED+SDEC
1940 : end if
1941 : !
1942 : ! Restart the conjugate gradient method if it has hit a new bound.
1943 : !
1944 686 : if (IACT > 0) then
1945 0 : NACT=NACT+1
1946 0 : XBDI(IACT)=ONE
1947 0 : if (S(IACT) < ZERO) XBDI(IACT)=ONEMIN
1948 0 : DELSQ=DELSQ-D(IACT)**2
1949 0 : if (DELSQ <= ZERO) GOTO 90
1950 : GOTO 20
1951 : end if
1952 : !
1953 : ! If STPLEN is less than BLEN, then either apply another conjugate
1954 : ! gradient iteration or RETURN.
1955 : !
1956 686 : if (STPLEN < BLEN) then
1957 573 : if (ITERC == ITERMAX) GOTO 190
1958 485 : if (SDEC <= 0.01D0*QRED) GOTO 190
1959 459 : BETA=GREDSQ/GGSAV
1960 459 : GOTO 30
1961 : end if
1962 113 : 90 CRVMIN=ZERO
1963 : !
1964 : ! Prepare for the alternative iteration by calculating some scalars
1965 : ! and by multiplying the reduced D by the second derivative matrix of
1966 : ! Q, where S holds the reduced D in the call of GGMULT.
1967 : !
1968 113 : 100 if (NACT >= N-1) GOTO 190
1969 227 : DREDSQ=ZERO
1970 227 : DREDG=ZERO
1971 : GREDSQ=ZERO
1972 701 : do I=1,N
1973 701 : if (XBDI(I) == ZERO) then
1974 588 : DREDSQ=DREDSQ+D(I)**2
1975 588 : DREDG=DREDG+D(I)*GNEW(I)
1976 588 : GREDSQ=GREDSQ+GNEW(I)**2
1977 588 : S(I)=D(I)
1978 : else
1979 0 : S(I)=ZERO
1980 : end if
1981 : end do
1982 : ITCSAV=ITERC
1983 137 : GOTO 210
1984 : !
1985 : ! Let the search direction S be a linear combination of the reduced D
1986 : ! and the reduced G that is orthogonal to the reduced D.
1987 : !
1988 250 : 120 ITERC=ITERC+1
1989 250 : TEMP=GREDSQ*DREDSQ-DREDG*DREDG
1990 250 : if (TEMP <= 1.0D-4*QRED*QRED) GOTO 190
1991 241 : TEMP=DSQRT(TEMP)
1992 1549 : do I=1,N
1993 1549 : if (XBDI(I) == ZERO) then
1994 1308 : S(I)=(DREDG*D(I)-DREDSQ*GNEW(I))/TEMP
1995 : else
1996 0 : S(I)=ZERO
1997 : end if
1998 : end do
1999 468 : SREDG=-TEMP
2000 : !
2001 : ! By considering the simple bounds on the variables, calculate an upper
2002 : ! bound on the tangent of half the angle of the alternative iteration,
2003 : ! namely ANGBD, except that, if already a free variable has reached a
2004 : ! bound, there is a branch back to label 100 after fixing that variable.
2005 : !
2006 468 : ANGBD=ONE
2007 241 : IACT=0
2008 1549 : do I=1,N
2009 1549 : if (XBDI(I) == ZERO) then
2010 1535 : TEMPA=XOPT(I)+D(I)-SL(I)
2011 1535 : TEMPB=SU(I)-XOPT(I)-D(I)
2012 1308 : if (TEMPA <= ZERO) then
2013 0 : NACT=NACT+1
2014 0 : XBDI(I)=ONEMIN
2015 0 : GOTO 100
2016 1308 : else if (TEMPB <= ZERO) then
2017 0 : NACT=NACT+1
2018 0 : XBDI(I)=ONE
2019 0 : GOTO 100
2020 : end if
2021 1535 : RATIO=ONE
2022 1535 : SSQ=D(I)**2+S(I)**2
2023 1308 : TEMP=SSQ-(XOPT(I)-SL(I))**2
2024 1308 : if (TEMP > ZERO) then
2025 0 : TEMP=DSQRT(TEMP)-S(I)
2026 0 : if (ANGBD*TEMP > TEMPA) then
2027 0 : ANGBD=TEMPA/TEMP
2028 0 : IACT=I
2029 0 : XSAV=ONEMIN
2030 : end if
2031 : end if
2032 1308 : TEMP=SSQ-(SU(I)-XOPT(I))**2
2033 1308 : if (TEMP > ZERO) then
2034 0 : TEMP=DSQRT(TEMP)+S(I)
2035 0 : if (ANGBD*TEMP > TEMPB) then
2036 0 : ANGBD=TEMPB/TEMP
2037 0 : IACT=I
2038 0 : XSAV=ONE
2039 : end if
2040 : end if
2041 : end if
2042 : end do
2043 : !
2044 : ! Calculate HHD and some curvatures for the alternative iteration.
2045 : !
2046 241 : GOTO 210
2047 : 150 SHS=ZERO
2048 227 : DHS=ZERO
2049 227 : DHD=ZERO
2050 1549 : do I=1,N
2051 1549 : if (XBDI(I) == ZERO) then
2052 1308 : SHS=SHS+S(I)*HS(I)
2053 1308 : DHS=DHS+D(I)*HS(I)
2054 1308 : DHD=DHD+D(I)*HRED(I)
2055 : end if
2056 : end do
2057 : !
2058 : ! Seek the greatest reduction in Q for a range of equally spaced values
2059 : ! of ANGT in [0,ANGBD], where ANGT is the tangent of half the angle of
2060 : ! the alternative iteration.
2061 : !
2062 468 : REDMAX=ZERO
2063 241 : ISAV=0
2064 468 : REDSAV=ZERO
2065 241 : IU=17.0D0*ANGBD+3.1D0
2066 5061 : do I=1,IU
2067 5047 : ANGT=ANGBD*DBLE(I)/DBLE(IU)
2068 5047 : STH=(ANGT+ANGT)/(ONE+ANGT*ANGT)
2069 4820 : TEMP=SHS+ANGT*(ANGT*DHD-DHS-DHS)
2070 5047 : REDNEW=STH*(ANGT*DREDG-SREDG-HALF*STH*TEMP)
2071 4820 : if (REDNEW > REDMAX) then
2072 : REDMAX=REDNEW
2073 : ISAV=I
2074 227 : RDPREV=REDSAV
2075 4512 : else if (I == ISAV+1) then
2076 241 : RDNEXT=REDNEW
2077 : end if
2078 5061 : REDSAV=REDNEW
2079 : end do
2080 : !
2081 : ! Return if the reduction is zero. Otherwise, set the sine and cosine
2082 : ! of the angle of the alternative iteration, and calculate SDEC.
2083 : !
2084 241 : if (ISAV == 0) GOTO 190
2085 175 : if (ISAV < IU) then
2086 175 : TEMP=(RDNEXT-RDPREV)/(REDMAX+REDMAX-RDPREV-RDNEXT)
2087 175 : ANGT=ANGBD*(DBLE(ISAV)+HALF*TEMP)/DBLE(IU)
2088 : end if
2089 227 : CTH=(ONE-ANGT*ANGT)/(ONE+ANGT*ANGT)
2090 175 : STH=(ANGT+ANGT)/(ONE+ANGT*ANGT)
2091 175 : TEMP=SHS+ANGT*(ANGT*DHD-DHS-DHS)
2092 175 : SDEC=STH*(ANGT*DREDG-SREDG-HALF*STH*TEMP)
2093 175 : if (SDEC <= ZERO) GOTO 190
2094 : !
2095 : ! Update GNEW, D and HRED. If the angle of the alternative iteration
2096 : ! is restricted by a bound on a free variable, that variable is fixed
2097 : ! at the bound.
2098 : !
2099 : DREDG=ZERO
2100 : GREDSQ=ZERO
2101 1119 : do I=1,N
2102 944 : GNEW(I)=GNEW(I)+(CTH-ONE)*HRED(I)+STH*HS(I)
2103 944 : if (XBDI(I) == ZERO) then
2104 944 : D(I)=CTH*D(I)+STH*S(I)
2105 944 : DREDG=DREDG+D(I)*GNEW(I)
2106 944 : GREDSQ=GREDSQ+GNEW(I)**2
2107 : end if
2108 1119 : HRED(I)=CTH*HRED(I)+STH*HS(I)
2109 : end do
2110 175 : QRED=QRED+SDEC
2111 175 : if (IACT > 0 .and. ISAV == IU) then
2112 0 : NACT=NACT+1
2113 0 : XBDI(IACT)=XSAV
2114 0 : GOTO 100
2115 : end if
2116 : !
2117 : ! If SDEC is sufficiently small, then RETURN after setting XNEW to
2118 : ! XOPT+D, giving careful attention to the bounds.
2119 : !
2120 175 : if (SDEC > 0.01D0*QRED) GOTO 120
2121 227 : 190 DSQ=ZERO
2122 1327 : do I=1,N
2123 1100 : XNEW(I)=DMAX1(DMIN1(XOPT(I)+D(I),SU(I)),SL(I))
2124 1100 : if (XBDI(I) == ONEMIN) XNEW(I)=SL(I)
2125 1100 : if (XBDI(I) == ONE) XNEW(I)=SU(I)
2126 1100 : D(I)=XNEW(I)-XOPT(I)
2127 1327 : DSQ=DSQ+D(I)**2
2128 : end do
2129 227 : RETURN
2130 :
2131 : ! The following instructions multiply the current S-vector by the second
2132 : ! derivative matrix of the quadratic model, putting the product in HS.
2133 : ! They are reached from three different parts of the software above and
2134 : ! they can be regarded as an external subroutine.
2135 : !
2136 1040 : 210 IH=0
2137 6430 : do J=1,N
2138 5390 : HS(J)=ZERO
2139 23871 : do I=1,J
2140 17441 : IH=IH+1
2141 17441 : if (I < J) HS(J)=HS(J)+HQ(IH)*S(I)
2142 22831 : HS(I)=HS(I)+HQ(IH)*S(J)
2143 : end do
2144 : end do
2145 12860 : do K=1,NPT
2146 12860 : if (PQ(K) /= ZERO) then
2147 : TEMP=ZERO
2148 75756 : do J=1,N
2149 75756 : TEMP=TEMP+XPT(K,J)*S(J)
2150 : end do
2151 11744 : TEMP=TEMP*PQ(K)
2152 75756 : do I=1,N
2153 75756 : HS(I)=HS(I)+TEMP*XPT(K,I)
2154 : end do
2155 : end if
2156 : end do
2157 1040 : if (CRVMIN /= ZERO) GOTO 50
2158 354 : if (ITERC > ITCSAV) GOTO 150
2159 701 : do I=1,N
2160 701 : HRED(I)=HS(I)
2161 : end do
2162 : GOTO 120
2163 : end subroutine TRSBOX
2164 :
2165 :
2166 260 : subroutine UPDATE (N,NPT,BMAT,ZMAT,NDIM,VLAG,BETA,DENOM,KNEW,W)
2167 : implicit real(dp) (A-H,O-Z)
2168 : dimension BMAT(NDIM,*),ZMAT(NPT,*),VLAG(*),W(*)
2169 : !
2170 : ! The arrays BMAT and ZMAT are updated, as required by the new position
2171 : ! of the interpolation point that has the index KNEW. The vector VLAG has
2172 : ! N+NPT components, set on entry to the first NPT and last N components
2173 : ! of the product Hw in equation (4.11) of the Powell (2006) paper on
2174 : ! NEWUOA. Further, BETA is set on entry to the value of the parameter
2175 : ! with that name, and DENOM is set to the denominator of the updating
2176 : ! formula. Elements of ZMAT may be treated as zero if their moduli are
2177 : ! at most ZTEST. The first NDIM elements of W are used for working space.
2178 : !
2179 : ! Set some constants.
2180 : !
2181 260 : ONE=1.0D0
2182 260 : ZERO=0.0D0
2183 260 : NPTM=NPT-N-1
2184 260 : ZTEST=ZERO
2185 3124 : do K=1,NPT
2186 18418 : do J=1,NPTM
2187 18158 : ZTEST=DMAX1(ZTEST,DABS(ZMAT(K,J)))
2188 : end do
2189 : end do
2190 260 : ZTEST=1.0D-20*ZTEST
2191 : !
2192 : ! Apply the rotations that put zeros in the KNEW-th row of ZMAT.
2193 : !
2194 260 : JL=1
2195 1302 : do J=2,NPTM
2196 1042 : if (DABS(ZMAT(KNEW,J)) > ZTEST) then
2197 1218 : TEMP=DSQRT(ZMAT(KNEW,1)**2+ZMAT(KNEW,J)**2)
2198 1218 : TEMPA=ZMAT(KNEW,1)/TEMP
2199 1218 : TEMPB=ZMAT(KNEW,J)/TEMP
2200 12400 : do I=1,NPT
2201 11442 : TEMP=TEMPA*ZMAT(I,1)+TEMPB*ZMAT(I,J)
2202 11442 : ZMAT(I,J)=TEMPA*ZMAT(I,J)-TEMPB*ZMAT(I,1)
2203 12400 : ZMAT(I,1)=TEMP
2204 : end do
2205 : end if
2206 1302 : ZMAT(KNEW,J)=ZERO
2207 : end do
2208 :
2209 : ! Put the first NPT components of the KNEW-th column of HLAG into W,
2210 : ! and calculate the parameters of the updating formula.
2211 :
2212 3124 : do I=1,NPT
2213 3124 : W(I)=ZMAT(KNEW,1)*ZMAT(I,1)
2214 : end do
2215 520 : ALPHA=W(KNEW)
2216 260 : TAU=VLAG(KNEW)
2217 260 : VLAG(KNEW)=VLAG(KNEW)-ONE
2218 :
2219 : ! Complete the updating of ZMAT.
2220 :
2221 260 : TEMP=DSQRT(DENOM)
2222 260 : TEMPB=ZMAT(KNEW,1)/TEMP
2223 260 : TEMPA=TAU/TEMP
2224 3124 : do I=1,NPT
2225 3124 : ZMAT(I,1)=TEMPA*ZMAT(I,1)-TEMPB*VLAG(I)
2226 : end do
2227 :
2228 : ! Finally, update the matrix BMAT.
2229 :
2230 1562 : do J=1,N
2231 1302 : JP=NPT+J
2232 1302 : W(JP)=BMAT(KNEW,J)
2233 1302 : TEMPA=(ALPHA*VLAG(JP)-TAU*W(JP))/DENOM
2234 1302 : TEMPB=(-BETA*W(JP)-TAU*VLAG(JP))/DENOM
2235 21005 : do I=1,JP
2236 19443 : BMAT(I,J)=BMAT(I,J)+TEMPA*VLAG(I)+TEMPB*W(I)
2237 20745 : if (I > NPT) BMAT(JP,I-NPT)=BMAT(I,J)
2238 : end do
2239 : end do
2240 260 : RETURN
2241 : end subroutine UPDATE
2242 :
2243 : end module mod_bobyqa
|