1 | ! **************************************************************
|
---|
2 | !
|
---|
3 | ! This file contains the subroutines: mincjg
|
---|
4 | !
|
---|
5 | ! Copyright 2003-2005 Frank Eisenmenger, U.H.E. Hansmann,
|
---|
6 | ! Shura Hayryan, Chin-Ku
|
---|
7 | ! Copyright 2007 Frank Eisenmenger, U.H.E. Hansmann,
|
---|
8 | ! Jan H. Meinke, Sandipan Mohanty
|
---|
9 | !
|
---|
10 | ! ********************************************************************
|
---|
11 | subroutine mincjg(n,mxn,x,f,g,acur,d,xa,ga,dt,yt,gt,maxfun,nfun)
|
---|
12 |
|
---|
13 | ! ....................................................................
|
---|
14 | !
|
---|
15 | ! Conjugate Gradient Minimizer
|
---|
16 | !
|
---|
17 | ! INPUT: X,F,G - variables, value of FUNC, gradient at START/
|
---|
18 | ! ACUR - convergence is assumed if ACUR > SUM ( G(I)**2 )
|
---|
19 | ! MAXFUN - maximum overall number of function calls
|
---|
20 | !
|
---|
21 | ! OUTPUT: X,F,G - variables, value of FUNC, gradient at MINIMUM
|
---|
22 | ! NFUN - overall number of function calls used
|
---|
23 | !
|
---|
24 | ! ARRAYS: D,XA,GA,YT,DT,GT - dimension N
|
---|
25 | !
|
---|
26 | ! CALLS: MOVE - calculate function & its gradients for current X
|
---|
27 | !
|
---|
28 | ! PARAMETERS: AMF - rough estimate of first reduction in F, used
|
---|
29 | ! to guess initial step of 1st line search
|
---|
30 | ! MXFCON - see 'ier=4'
|
---|
31 | ! MAXLIN -
|
---|
32 | !
|
---|
33 | ! DIAGNOSTICS (ier)
|
---|
34 | !
|
---|
35 | ! = 0: minimization completed successfully
|
---|
36 | ! = 1: number of steps reached MAXFUN
|
---|
37 | ! = 2: line search was abandoned
|
---|
38 | ! = 3: search direction is uphill
|
---|
39 | ! = 4: two consecutive line searches failed to reduce F
|
---|
40 | ! ....................................................................
|
---|
41 |
|
---|
42 | double precision amf, tol, eps, gsqrd, fmin, f, t, g, ga, d, xa, x
|
---|
43 | double precision gsq2, gnew, dfpr, stmin, fuit, gdit, gt, gdmi
|
---|
44 | double precision sbound, stepch, step, wo, sum, fch, acur, ddspln
|
---|
45 | double precision gspln, beta, gama, yt, dt, gamden, di
|
---|
46 |
|
---|
47 | integer mxfcon, maxlin, mxn, ier, iter, iterfm, iterrs, nfun
|
---|
48 | integer nfopt, i, n, nfbeg, iretry, maxfun
|
---|
49 |
|
---|
50 | parameter (AMF = 10.d0,
|
---|
51 | & MXFCON = 2,
|
---|
52 | & MAXLIN = 5,
|
---|
53 | & TOL = 1.d-7, ! controls 'stepch'
|
---|
54 | & EPS = .7d0)
|
---|
55 |
|
---|
56 | dimension x(mxn),g(mxn),
|
---|
57 | & d(mxn),xa(mxn),ga(mxn),dt(mxn),yt(mxn),gt(mxn)
|
---|
58 |
|
---|
59 |
|
---|
60 | ier = 0
|
---|
61 | iter = 0
|
---|
62 | iterfm = 0
|
---|
63 | iterrs = 0
|
---|
64 | nfun = 0
|
---|
65 | nfopt = nfun
|
---|
66 |
|
---|
67 | gsqrd = 0.d0
|
---|
68 | fmin = f
|
---|
69 |
|
---|
70 | do i=1,n
|
---|
71 | t = g(i)
|
---|
72 | ga(i) = t
|
---|
73 | d(i) = -t
|
---|
74 | gsqrd = gsqrd + t**2
|
---|
75 | xa(i) = x(i)
|
---|
76 | enddo
|
---|
77 |
|
---|
78 | gsq2 = .2d0 * gsqrd
|
---|
79 | gnew = -gsqrd
|
---|
80 | dfpr = AMF
|
---|
81 | stmin = AMF / gsqrd
|
---|
82 |
|
---|
83 | 1 iter = iter + 1
|
---|
84 |
|
---|
85 | fuit = f
|
---|
86 | gdit = 0.d0
|
---|
87 |
|
---|
88 | do i=1,n
|
---|
89 | t = g(i)
|
---|
90 | gt(i) = t
|
---|
91 | gdit = gdit + d(i) * t
|
---|
92 | enddo
|
---|
93 |
|
---|
94 | if ( gdit .ge. 0.d0 ) then
|
---|
95 | write(*,*) ' mincjg> search direction is uphill'
|
---|
96 | ier = 3
|
---|
97 | goto 6
|
---|
98 | endif
|
---|
99 |
|
---|
100 | gdmi = gdit
|
---|
101 | sbound = -1.d0
|
---|
102 | nfbeg = nfun
|
---|
103 | iretry = -1
|
---|
104 |
|
---|
105 | stepch = min( stmin, abs ( (dfpr/gdit) ) )
|
---|
106 | stmin = 0.d0
|
---|
107 |
|
---|
108 | 2 step = stmin + stepch
|
---|
109 | wo = 0.d0
|
---|
110 |
|
---|
111 | do i=1,n
|
---|
112 | t = stepch * d(i)
|
---|
113 | wo = max( wo, abs( t ) )
|
---|
114 | x(i) = xa(i) + t
|
---|
115 | enddo
|
---|
116 |
|
---|
117 | if ( wo .gt. TOL ) then
|
---|
118 |
|
---|
119 | nfun = nfun + 1
|
---|
120 | call move(nfun,n,f,x,g)
|
---|
121 |
|
---|
122 | gnew = 0.d0
|
---|
123 | sum = 0.d0
|
---|
124 |
|
---|
125 | do i=1,n
|
---|
126 | t = g(i)
|
---|
127 | gnew = gnew + d(i) * t
|
---|
128 | sum = sum + t**2
|
---|
129 | enddo
|
---|
130 |
|
---|
131 | fch = f - fmin
|
---|
132 |
|
---|
133 | if ( fch .le. 0.d0 ) then
|
---|
134 |
|
---|
135 | if ( fch .lt. 0.d0 .or. (gnew/gdmi) .ge. -1.d0 ) then
|
---|
136 |
|
---|
137 | fmin = f
|
---|
138 | gsqrd = sum
|
---|
139 | gsq2 = .2d0 * gsqrd
|
---|
140 | nfopt = nfun
|
---|
141 |
|
---|
142 | do i=1,n
|
---|
143 | xa(i) = x(i)
|
---|
144 | ga(i) = g(i)
|
---|
145 | enddo
|
---|
146 |
|
---|
147 | endif
|
---|
148 |
|
---|
149 | if ( sum .le. ACUR ) return ! normal end
|
---|
150 |
|
---|
151 | endif
|
---|
152 |
|
---|
153 | if ( nfun .eq. MAXFUN ) then
|
---|
154 | ier = 1
|
---|
155 | return
|
---|
156 | endif
|
---|
157 |
|
---|
158 | else ! stepch is effectively zero
|
---|
159 |
|
---|
160 | if ( nfun .gt. (nfbeg + 1) .or.
|
---|
161 | & abs(gdmi/gdit) .gt. EPS ) then
|
---|
162 |
|
---|
163 | ier=2
|
---|
164 | write(*,*) ' mincjg> too small step in search direction'
|
---|
165 | endif
|
---|
166 |
|
---|
167 | goto 6
|
---|
168 |
|
---|
169 | endif
|
---|
170 |
|
---|
171 | wo = (fch + fch) / stepch - gnew - gdmi
|
---|
172 | ddspln = (gnew - gdmi) / stepch
|
---|
173 |
|
---|
174 | if ( nfun .le. nfopt ) then
|
---|
175 |
|
---|
176 | if ( gdmi * gnew .le. 0.d0 ) sbound = stmin
|
---|
177 |
|
---|
178 | stmin = step
|
---|
179 | gdmi = gnew
|
---|
180 | stepch = -stepch
|
---|
181 |
|
---|
182 | else
|
---|
183 |
|
---|
184 | sbound = step
|
---|
185 |
|
---|
186 | endif
|
---|
187 |
|
---|
188 | if ( fch .ne. 0.d0 ) ddspln = ddspln + (wo + wo) / stepch
|
---|
189 |
|
---|
190 | if ( gdmi .eq. 0.d0 ) goto 6
|
---|
191 |
|
---|
192 | if ( nfun .le. (nfbeg + 1) ) goto 4
|
---|
193 |
|
---|
194 | if ( abs(gdmi/gdit) .le. EPS ) goto 6
|
---|
195 |
|
---|
196 | 3 if ( nfun .ge. (nfopt + MAXLIN) ) then
|
---|
197 |
|
---|
198 | ier = 2
|
---|
199 | goto 6
|
---|
200 |
|
---|
201 | endif
|
---|
202 |
|
---|
203 | 4 if ( sbound .lt. -.5d0 ) then
|
---|
204 | stepch = 9.d0 * stmin
|
---|
205 | else
|
---|
206 | stepch = .5d0 * ( sbound - stmin )
|
---|
207 | endif
|
---|
208 |
|
---|
209 | gspln = gdmi + stepch * ddspln
|
---|
210 |
|
---|
211 | if ( (gdmi * gspln) .lt. 0.d0 ) stepch = stepch * gdmi /
|
---|
212 | & (gdmi - gspln)
|
---|
213 |
|
---|
214 | goto 2
|
---|
215 |
|
---|
216 | 5 sum = 0.d0
|
---|
217 | do i=1,n
|
---|
218 | sum = sum + g(i) * gt(i)
|
---|
219 | enddo
|
---|
220 |
|
---|
221 | beta = (gsqrd - sum) / (gdmi - gdit)
|
---|
222 |
|
---|
223 | if ( abs(beta * gdmi) .gt. gsq2) then
|
---|
224 | iretry = iretry + 1
|
---|
225 | if (iretry .le. 0) goto 3
|
---|
226 | endif
|
---|
227 |
|
---|
228 | if ( f .lt. fuit ) iterfm = iter
|
---|
229 |
|
---|
230 | if ( iter .ge. (iterfm + MXFCON) ) then
|
---|
231 | ier = 4
|
---|
232 | write(*,*) ' mincjg> line search failed to reduce function'
|
---|
233 | return
|
---|
234 | endif
|
---|
235 |
|
---|
236 | dfpr = stmin * gdit
|
---|
237 |
|
---|
238 | if ( iretry .gt. 0 ) then
|
---|
239 |
|
---|
240 | do i=1,n
|
---|
241 | d(i) = -g(i)
|
---|
242 | enddo
|
---|
243 |
|
---|
244 | iterrs = 0
|
---|
245 |
|
---|
246 | else
|
---|
247 |
|
---|
248 | if (iterrs .ne. 0 .and. (iter - iterrs) .lt. (n-1) .and.
|
---|
249 | & abs(sum) .lt. gsq2 ) then
|
---|
250 |
|
---|
251 | gama = 0.d0
|
---|
252 | sum = 0.d0
|
---|
253 |
|
---|
254 | do i=1,n
|
---|
255 | t = g(i)
|
---|
256 | gama = gama + t * yt(i)
|
---|
257 | sum = sum + t * dt(i)
|
---|
258 | enddo
|
---|
259 |
|
---|
260 | gama = gama / gamden
|
---|
261 |
|
---|
262 | if ( abs( (beta * gdmi + gama * sum) ) .lt. gsq2) then
|
---|
263 |
|
---|
264 | do i=1,n
|
---|
265 | d(i) = -g(i) + beta * d(i) + gama * dt(i)
|
---|
266 | enddo
|
---|
267 |
|
---|
268 | goto 1
|
---|
269 |
|
---|
270 | endif
|
---|
271 |
|
---|
272 | endif
|
---|
273 |
|
---|
274 | gamden = gdmi - gdit
|
---|
275 |
|
---|
276 | do i=1,n
|
---|
277 | t = g(i)
|
---|
278 | di = d(i)
|
---|
279 | dt(i) = di
|
---|
280 | yt(i) = t - gt(i)
|
---|
281 | d(i) = -t + beta * di
|
---|
282 | enddo
|
---|
283 |
|
---|
284 | iterrs = iter
|
---|
285 |
|
---|
286 | endif
|
---|
287 |
|
---|
288 | goto 1
|
---|
289 |
|
---|
290 | 6 if ( nfun .ne. nfopt ) then
|
---|
291 |
|
---|
292 | f = fmin
|
---|
293 |
|
---|
294 | do i=1,n
|
---|
295 | x(i) = xa(i)
|
---|
296 | g(i) = ga(i)
|
---|
297 | enddo
|
---|
298 |
|
---|
299 | endif
|
---|
300 |
|
---|
301 | if ( ier .eq. 0 ) goto 5
|
---|
302 |
|
---|
303 | nfun = nfun + 1
|
---|
304 | call move(nfun,n,f,x,g)
|
---|
305 |
|
---|
306 | write(*,*) ' mincjg> ier = ',ier
|
---|
307 |
|
---|
308 | return
|
---|
309 | end
|
---|
310 |
|
---|