1 |
|
2 |
Description of large scale optimization package, Version 3.0 |
3 |
############################################################## |
4 |
Patrick Heimbach, MIT/EAPS, 02-Mar-2000 |
5 |
Benny Cheng, NASA/JPL, 13-Apr-2010 (parallel version) |
6 |
|
7 |
reference: |
8 |
######### |
9 |
|
10 |
J.C. Gilbert & C. Lemarechal |
11 |
Some numerical experiments with variable-storage quasi-Newton algorithms |
12 |
Mathematical Programming 45 (1989), pp. 407-435 |
13 |
|
14 |
flow chart |
15 |
########## |
16 |
|
17 |
lsopt_top |
18 |
| |
19 |
|---- check arguments |
20 |
|---- CALL INSTORE |
21 |
| | |
22 |
| |---- determine whether OPWARMI available: |
23 |
| * if no: cold start: create OPWARMI |
24 |
| * if yes: warm start: read from OPWARMI |
25 |
| create or open OPWARMD |
26 |
| |
27 |
|---- check consistency between OPWARMI and model parameters |
28 |
| |
29 |
|---- >>> if COLD start: <<< |
30 |
| | first simulation with f.g. xx_0; output: first ff_0, gg_0 |
31 |
| | set first preconditioner value xdiff_0 to 1 |
32 |
| | store xx(0), gg(0), xdiff(0) to OPWARMD (first 3 entries) |
33 |
| | |
34 |
| >>> else: WARM start: <<< |
35 |
| read xx(i), gg(i) from OPWARMD (first 2 entries) |
36 |
| for first warm start after cold start, i=0 |
37 |
| |
38 |
| |
39 |
| |
40 |
|---- /// if ITMAX > 0: perform optimization (increment loop index i) |
41 |
| ( |
42 |
| )---- save current values of gg(i-1) -> gold(i-1), ff -> fold(i-1) |
43 |
| (---- CALL LSUPDXX |
44 |
| ) | |
45 |
| ( |---- >>> if jmax=0 <<< |
46 |
| ) | | first optimization after cold start: |
47 |
| ( | | preconditioner estimated via .01*ff_0 (first guess) |
48 |
| ) | | dd(i-1) = -gg(i-1)*preco |
49 |
| ( | | |
50 |
| ) | >>> if jmax > 0 <<< |
51 |
| ( | dd(i-1) = -gg(i-1) |
52 |
| ) | CALL HESSUPD |
53 |
| ( | | |
54 |
| ) | |---- dd(i-1) modified via Hessian approx. |
55 |
| ( | |
56 |
| ) |---- >>> if <dd,gg> >= 0 <<< |
57 |
| ( | ifail = 4 |
58 |
| ) | |
59 |
| ( |---- compute step size: tact(i-1) |
60 |
| ) |---- compute update: xdiff(i) = xx(i-1) + tact(i-1)*dd(i-1) |
61 |
| ( |
62 |
| )---- >>> if ifail = 4 <<< |
63 |
| ( goto 1000 |
64 |
| ) |
65 |
| (---- if (warm start) |
66 |
| (---- CALL OPTLINE / LSLINE |
67 |
| ) | |
68 |
| ( | |
69 |
| ) | |
70 |
| ( |---- /// loop over simulations |
71 |
| ) ( |
72 |
| ( if (linesearch ) |
73 |
| ( )---- CALL SIMUL |
74 |
| ) ( | |
75 |
| ( ) |---- input: xdiff(i) |
76 |
| ) ( |---- output: ff(i) |
77 |
| ) ( reads those values from file |
78 |
| ( ) |
79 |
| ( ( |---- perform quadratic line search |
80 |
| ) ) |
81 |
| ( else |
82 |
| ) )---- CALL SIMUL |
83 |
| ) ( | |
84 |
| ( ) |---- input: xdiff(i) |
85 |
| ) ( |---- output: ff(i),gg(i) |
86 |
| ) ( reads those values from file |
87 |
| ( ) |
88 |
| ) (---- 1st Wolfe test: |
89 |
| ( ) ff(i) <= tact*xpara1*<gg(i-1),dd(i-1)> |
90 |
| ) ( |
91 |
| ( )---- 2nd Wolfe test: |
92 |
| ) ( <gg(i),dd(i-1)> >= xpara2*<gg(i-1),dd(i-1)> |
93 |
| ( ) |
94 |
| ) (---- >>> if 1st and 2nd Wolfe tests ok <<< |
95 |
| ( ) | 320: update xx: xx(i) = xdiff(i) |
96 |
| ) ( | |
97 |
| ( ) >>> else |
98 |
| ) ) | ifail = 7 |
99 |
| ) ( | set stepsize equal half of previous |
100 |
| ( ) | value |
101 |
| ( ) | |
102 |
| ) ( update xdiff for new simulation |
103 |
| ( ) |
104 |
| ( |
105 |
| ) |
106 |
| (---- store new values xx(i), gg(i) to OPWARMD (first 2 entries) |
107 |
| )---- >>> if ifail = 7,8,9 <<< |
108 |
| ( goto 1000 |
109 |
| ) |
110 |
| (---- compute new pointers jmin, jmax to include latest values |
111 |
| ) gg(i)-gg(i-1), xx(i)-xx(i-1) to Hessian matrix estimate |
112 |
| (---- store gg(i)-gg(i-1), xx(i)-xx(i-1) to OPWARMD |
113 |
| ) (entries 2*jmax+2, 2*jmax+3) |
114 |
| ( |
115 |
| )---- CALL DGSCALE |
116 |
| ( | |
117 |
| ) |---- call dostore |
118 |
| ( | | |
119 |
| ) | |---- read preconditioner of previous iteration diag(i-1) |
120 |
| ( | from OPWARMD (3rd entry) |
121 |
| ) | |
122 |
| ( |---- compute new preconditioner diag(i), based upon diag(i-1), |
123 |
| ) | gg(i)-gg(i-1), xx(i)-xx(i-1) |
124 |
| ( | |
125 |
| ) |---- call dostore |
126 |
| ( | |
127 |
| ) |---- write new preconditioner diag(i) to OPWARMD (3rd entry) |
128 |
| ( |
129 |
|---- \\\ end of optimization iteration loop |
130 |
| |
131 |
| |
132 |
| |
133 |
|---- CALL OUTSTORE |
134 |
| | |
135 |
| |---- toggle linesearch flag |
136 |
| |---- store gnorm0, ff(i), current pointers jmin, jmax, iterabs, |
137 |
| |---- searchflags to OPWARMI |
138 |
| |
139 |
| xx(i+1) needs to be computed as input for offline optimization |
140 |
| | |
141 |
| |---- CALL LSUPDXX |
142 |
| | | |
143 |
| | |---- compute dd(i), tact(i) -> xdiff(i+1) = x(i) + tact(i)*dd(i) |
144 |
| | |
145 |
| |---- CALL WRITE_CONTROL |
146 |
| | | |
147 |
| | |---- write xdiff(i+1) to special file for offline optim. |
148 |
| |
149 |
|---- print final information |
150 |
| |
151 |
O |
152 |
|
153 |
|
154 |
|
155 |
Remarks: |
156 |
####### |
157 |
|
158 |
- Every call to simul refers to a read procedure which |
159 |
reads the result of an offline forward run and/or the adjoint run |
160 |
itmax = 0, for cold start |
161 |
itmax = 1, for warm start |
162 |
Also, at the end, x(i+1) needs to be computed and saved |
163 |
to be available for the offline model and adjoint run |
164 |
|
165 |
In order to achieve minimum difference between the online and offline code |
166 |
xdiff(i+1) is stored to file at the end of an (offline) iteration, |
167 |
but recomputed identically at the beginning of the next iteration. |
168 |
|
169 |
2. Number of simulations |
170 |
------------------------------------------------- |
171 |
|
172 |
- nfunc: controls the maximum number of safeguarded simulations |
173 |
|
174 |
Summary: From one iteration to the next the descent direction changes. |
175 |
The updated control used as input for these safeguarded simulations uses the same |
176 |
descent direction, but different step sizes. |
177 |
|
178 |
In detail: |
179 |
From one iteration to the next the descent direction dd changes using |
180 |
the result for the adjoint vector gg of the previous iteration. |
181 |
In lsline the updated control xdiff(i,1) = xx(i-1) + tact(i-1,1)*dd(i-1) serves as input for |
182 |
a forward and adjoint model run yielding a new gg(i,1). |
183 |
In general, the new solution passes the 1st and 2nd Wolfe tests |
184 |
so xdiff(i,1) represents the solution sought: xx(i) = xdiff(i,1). |
185 |
If one of the two tests fails, stepsize halving is invoked to determine |
186 |
a new trial step aize tact(i-1,2). |
187 |
If more than one function call is permitted, the new step size is used together |
188 |
with the "old" descent direction dd(i-1) (i.e. dd is not updated using the new gg(i)), |
189 |
to compute a new xdiff(i,2) = xx(i-1) + tact(i-1,2)*dd(i-1) that serves as input |
190 |
in a new forward and adjoint run, yielding gg(i,2). |
191 |
If now, both Wolfe tests are successfull, the updated solution is given by |
192 |
xx(i) = xdiff(i,2) = xx(i-1) + tact(i-1,2)*dd(i-1). |
193 |
|
194 |
3. Double-usage of fields dd and xdiff |
195 |
-------------------------------------- |
196 |
|
197 |
In order to save memory both the fields dd and xdiff have a double usage. |
198 |
|
199 |
- xdiff: in lsopt_top: used as x(i) - x(i-1) for Hessian update |
200 |
in lsline: intermediate result for control update x = x + tact*dd |
201 |
|
202 |
- dd : in lsopt_top, lsline: descent vector, dd = -gg & hessupd |
203 |
in dgscale: intermediate result to compute new preconditioner |
204 |
|
205 |
4. Notice for user of old code |
206 |
------------------------------ |
207 |
|
208 |
Three relevant changes needed to switch to new version: |
209 |
|
210 |
(i): OPWARMI file: two variables added: |
211 |
gnorm0 : norm of first (cold start) gradient |
212 |
iabsiter: total number of iterations with respect to cold start |
213 |
|
214 |
(ii): routine names that are referenced by main_lsopt.f |
215 |
lsoptv1 -> lsopt_top |
216 |
lsline1 -> lsline |
217 |
|
218 |
(iii): parameter list of lsopt_top |
219 |
logical loffline included |
220 |
|
221 |
parameter file data.optim |
222 |
######################## |
223 |
|
224 |
The optimization is controlled by a set of parameters |
225 |
provided through the standard input file data.optim, |
226 |
which is generated within the job script. |
227 |
|
228 |
NUPDATE : max. no. of update pairs (gg(i)-gg(i-1), xx(i)-xx(i-1)) |
229 |
to be stored in OPWARMD to estimate Hessian |
230 |
[pair of current iter. is stored in (2*jmax+2, 2*jmax+3) |
231 |
jmax must be > 0 to access these entries] |
232 |
Presently NUPDATE must be > 0 |
233 |
(i.e. iteration without reference to previous |
234 |
iterations through OPWARMD has not been tested) |
235 |
EPSX : relative precision on xx bellow which xx should not be improved |
236 |
EPSG : relative precision on gg below which optimization is considered successful |
237 |
IPRINT : controls verbose (>=1) or non-verbose output |
238 |
NUMITER : always 1 |
239 |
ITER_NUM : index of new restart file to be created (not necessarily = NUMITER!) |
240 |
NFUNC : max. no. of safeguarded simulations |
241 |
(must be > 0) |
242 |
is used if step size tact is interpolated; |
243 |
in this case, if NFUNC > 1, a new simulation is performed with |
244 |
same gradient but "improved" step size |
245 |
FC : first guess cost function value |
246 |
FMIN : not used |
247 |
|
248 |
OPWARMI, OPWARMD files |
249 |
###################### |
250 |
|
251 |
Two files retain values of previous iterations which are |
252 |
used in latest iteration to update Hessian. |
253 |
OPWARMI: contains index settings and scalar variables |
254 |
OPWARMD: contains vectors |
255 |
|
256 |
Structure of OPWARMI file: |
257 |
------------------------- |
258 |
n, fc, gnorm, m, jmin, jmax, sflag, tflag, safe_iter, stepsize |
259 |
|
260 |
n = nn : no. of control variables per processor |
261 |
fc = ff : cost value of last iteration |
262 |
m = nupdate : max. no. of updates for Hessian |
263 |
jmin, jmax : pointer indices for OPWARMD file (cf. below) |
264 |
gnorm : norm of gradient gg |
265 |
sflag : true if linesearch is applied to next iteration |
266 |
tflag : true if next iteration is a safeguarded simulation |
267 |
safe_iter : number of safeguarded simulations made so far |
268 |
stepsize : value of tact stepsize |
269 |
|
270 |
Structure of OPWARMD file: |
271 |
------------------------- |
272 |
entry |
273 |
1 : xx(i) : control vector of latest iteration |
274 |
2 : gg(i) : gradient of latest iteration |
275 |
3 : xdiff(i), diag: preconditioning vector; (1,...,1) for cold start |
276 |
--- |
277 |
2*jmax+2 : gold = g(i) - g(i-1) for last update (jmax) |
278 |
2*jmax+3 : xdiff = tact * d = xx(i) - xx(i-1) for last update (jmax) |
279 |
|
280 |
if jmax = 0: cold start; no Hessian update used to compute dd |
281 |
if jmax > nupdate, old positions are overwritten, starting |
282 |
with position pair (4,5) |
283 |
|
284 |
Example 1: jmin = 1, jmax = 3, mupd = 5 |
285 |
|
286 |
1 2 3 | 4 5 6 7 8 9 empty empty |
287 |
|___|___|___| | |___|___| |___|___| |___|___| |___|___| |___|___| |
288 |
0 | 1 2 3 |
289 |
|
290 |
Example 2: jmin = 3, jmax = 7, mupd = 5 ---> jmax = 2 |
291 |
|
292 |
1 2 3 | |
293 |
|___|___|___| | |___|___| |___|___| |___|___| |___|___| |___|___| |
294 |
| 6 7 3 4 5 |
295 |
|
296 |
|
297 |
|
298 |
Error handling |
299 |
############## |
300 |
|
301 |
ifail | description |
302 |
--------+---------------------------------------------------------- |
303 |
< 0 | should not appear (flag indic in simul.F not used) |
304 |
0 | normal mode during execution |
305 |
1 | an input argument is wrong |
306 |
2 | warm start file is corrupted |
307 |
3 | the initial gradient is too small |
308 |
4 | the search direction is not a descent one |
309 |
5 | maximal number of iterations reached |
310 |
6 | maximal number of simulations reached (handled passively) |
311 |
7 | the linesearch failed |
312 |
8 | the function could not be improved |
313 |
9 | optline parameters wrong |
314 |
10 | cold start, no optimization done |
315 |
11 | convergence achieved within precision |
316 |
|
317 |
|