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