L-BFGS-B  3.0
Large-scale Bound-constrained Optimization
driver3.f

This time-controlled driver shows that it is possible to terminate a run by elapsed CPU time, and yet be able to print all desired information. This driver also illustrates the use of two stopping criteria that may be used in conjunction with a limit on execution time. The sample problem used here is the same as in driver1 and driver2 (the extended Rosenbrock function with bounds on the variables). (Fortran-77 version)

1 c> \file driver3.f
2 
3 c
4 c L-BFGS-B is released under the "New BSD License" (aka "Modified BSD License"
5 c or "3-clause license")
6 c Please read attached file License.txt
7 c
8 c DRIVER 3 in Fortran 77
9 c --------------------------------------------------------------
10 c TIME-CONTROLLED DRIVER FOR L-BFGS-B (version 3.0)
11 c --------------------------------------------------------------
12 c
13 c L-BFGS-B is a code for solving large nonlinear optimization
14 c problems with simple bounds on the variables.
15 c
16 c The code can also be used for unconstrained problems and is
17 c as efficient for these problems as the earlier limited memory
18 c code L-BFGS.
19 c
20 c This driver shows how to terminate a run after some prescribed
21 c CPU time has elapsed, and how to print the desired information
22 c before exiting.
23 c
24 c References:
25 c
26 c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited
27 c memory algorithm for bound constrained optimization'',
28 c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208.
29 c
30 c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN
31 c Subroutines for Large Scale Bound Constrained Optimization''
32 c Tech. Report, NAM-11, EECS Department, Northwestern University,
33 c 1994.
34 c
35 c
36 c (Postscript files of these papers are available via anonymous
37 c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.)
38 c
39 c * * *
40 c
41 c February 2011 (latest revision)
42 c Optimization Center at Northwestern University
43 c Instituto Tecnologico Autonomo de Mexico
44 c
45 c Jorge Nocedal and Jose Luis Morales, Remark on "Algorithm 778:
46 c L-BFGS-B: Fortran Subroutines for Large-Scale Bound Constrained
47 c Optimization" (2011). To appear in ACM Transactions on
48 c Mathematical Software,
49 c
50 c
51 c **************
52 
53  program driver
54  use json_writer, only: json_write_aggregate
55 
56 c This time-controlled driver shows that it is possible to terminate
57 c a run by elapsed CPU time, and yet be able to print all desired
58 c information. This driver also illustrates the use of two
59 c stopping criteria that may be used in conjunction with a limit
60 c on execution time. The sample problem used here is the same as in
61 c driver1 and driver2 (the extended Rosenbrock function with bounds
62 c on the variables).
63 
64  integer nmax, mmax
65  parameter(nmax=1024,mmax=17)
66 c nmax is the dimension of the largest problem to be solved.
67 c mmax is the maximum number of limited memory corrections.
68 
69 c Declare the variables needed by the code.
70 c A description of all these variables is given at the end of
71 c driver1.
72 
73  character*60 task, csave
74  logical lsave(4)
75  integer n, m, iprint,
76  + nbd(nmax), iwa(3*nmax), isave(44)
77  double precision f, factr, pgtol,
78  + x(nmax), l(nmax), u(nmax), g(nmax), dsave(29),
79  + wa(2*mmax*nmax+5*nmax+11*mmax*mmax+8*mmax)
80 
81 c Declare a few additional variables for the sample problem
82 c and for keeping track of time.
83 
84  double precision t1, t2, time1, time2, tlimit
85  integer i, j
86 
87 c Test instrumentation: dump per-iteration state to JSON when the
88 c environment variable LBFGSB_JSON_OUTPUT is set. No-op otherwise.
89 c LBFGSB_TLIMIT optionally overrides tlimit for reproducibility.
90  character*512 lbfgsb_json
91  character*64 env_tlimit
92  logical json_active
93 
94 c We specify a limite on the CPU time (in seconds).
95 
96  tlimit = 0.2
97  call get_environment_variable('LBFGSB_TLIMIT', env_tlimit)
98  if (len_trim(env_tlimit) .gt. 0) read(env_tlimit, *) tlimit
99 
100 c We suppress the default output. (The user could also elect to
101 c use the default output by choosing iprint >= 0.)
102 
103  iprint = -1
104 
105 c We suppress the code-supplied stopping tests because we will
106 c provide our own termination conditions
107 
108  factr=0.0d0
109  pgtol=0.0d0
110 
111 c We specify the dimension n of the sample problem and the number
112 c m of limited memory corrections stored. (n and m should not
113 c exceed the limits nmax and mmax respectively.)
114 
115  n=1000
116  m=10
117 
118 c We now specify nbd which defines the bounds on the variables:
119 c l specifies the lower bounds,
120 c u specifies the upper bounds.
121 
122 c First set bounds on the odd-numbered variables.
123 
124  do 10 i=1,n,2
125  nbd(i)=2
126  l(i)=1.0d0
127  u(i)=1.0d2
128  10 continue
129 
130 c Next set bounds on the even-numbered variables.
131 
132  do 12 i=2,n,2
133  nbd(i)=2
134  l(i)=-1.0d2
135  u(i)=1.0d2
136  12 continue
137 
138 c We now define the starting point.
139 
140  do 14 i=1,n
141  x(i)=3.0d0
142  14 continue
143 
144 c We now write the heading of the output.
145 
146  write (6,16)
147  16 format(/,5x, 'Solving sample problem.',
148  + /,5x, ' (f = 0.0 at the optimal solution.)',/)
149 
150 c We start the iteration by initializing task.
151 c
152  task = 'START'
153 
154 c Test instrumentation: enabled when LBFGSB_JSON_OUTPUT is set.
155  call get_environment_variable('LBFGSB_JSON_OUTPUT', lbfgsb_json)
156  json_active = (len_trim(lbfgsb_json) .gt. 0)
157 
158 c ------- the beginning of the loop ----------
159 
160 c We begin counting the CPU time.
161 
162  call timer(time1)
163 
164  111 continue
165 
166 c This is the call to the L-BFGS-B code.
167 
168  call setulb(n,m,x,l,u,nbd,f,g,factr,pgtol,wa,iwa,task,iprint,
169  + csave,lsave,isave,dsave)
170 
171  if (task(1:2) .eq. 'FG') then
172 c the minimization routine has returned to request the
173 c function f and gradient g values at the current x.
174 c Before evaluating f and g we check the CPU time spent.
175 
176  call timer(time2)
177  if (time2-time1 .gt. tlimit) then
178  task='STOP: CPU EXCEEDING THE TIME LIMIT.'
179 
180 c Note: Assigning task(1:4)='STOP' will terminate the run;
181 c setting task(7:9)='CPU' will restore the information at
182 c the latest iterate generated by the code so that it can
183 c be correctly printed by the driver.
184 
185 c In this driver we have chosen to disable the
186 c printing options of the code (we set iprint=-1);
187 c instead we are using customized output: we print the
188 c latest value of x, the corresponding function value f and
189 c the norm of the projected gradient |proj g|.
190 
191 c We print out the information contained in task.
192 
193  write (6,*) task
194 
195 c We print the latest iterate contained in wa(j+1:j+n), where
196 c
197  j = 3*n+2*m*n+11*m**2
198  write (6,*) 'Latest iterate X ='
199  write (6,'((1x,1p, 6(1x,d11.4)))') (wa(i),i = j+1,j+n)
200 
201 c We print the function value f and the norm of the projected
202 c gradient |proj g| at the last iterate; they are stored in
203 c dsave(2) and dsave(13) respectively.
204 
205  write (6,'(a,1p,d12.5,4x,a,1p,d12.5)')
206  + 'At latest iterate f =',dsave(2),'|proj g| =',dsave(13)
207 
208  else
209 
210 c The time limit has not been reached and we compute
211 c the function value f for the sample problem.
212 
213  f=.25d0*(x(1)-1.d0)**2
214  do 20 i=2,n
215  f=f+(x(i)-x(i-1)**2)**2
216  20 continue
217  f=4.d0*f
218 
219 c Compute gradient g for the sample problem.
220 
221  t1=x(2)-x(1)**2
222  g(1)=2.d0*(x(1)-1.d0)-1.6d1*x(1)*t1
223  do 22 i=2,n-1
224  t2=t1
225  t1=x(i+1)-x(i)**2
226  g(i)=8.d0*t2-1.6d1*x(i)*t1
227  22 continue
228  g(n)=8.d0*t1
229 
230  endif
231 
232 c go back to the minimization routine.
233  goto 111
234  endif
235 c
236  if (task(1:5) .eq. 'NEW_X') then
237 c the minimization routine has returned with a new iterate.
238 c The time limit has not been reached, and we test whether
239 c the following two stopping tests are satisfied:
240 
241 c 1) Terminate if the total number of f and g evaluations
242 c exceeds 900.
243 
244  if (isave(34) .ge. 900)
245  + task='STOP: TOTAL NO. of f AND g EVALUATIONS EXCEEDS LIMIT'
246 
247 c 2) Terminate if |proj g|/(1+|f|) < 1.0d-10.
248 
249  if (dsave(13) .le. 1.d-10*(1.0d0 + abs(f)))
250  + task='STOP: THE PROJECTED GRADIENT IS SUFFICIENTLY SMALL'
251 
252 c We wish to print the following information at each iteration:
253 c 1) the current iteration number, isave(30),
254 c 2) the total number of f and g evaluations, isave(34),
255 c 3) the value of the objective function f,
256 c 4) the norm of the projected gradient, dsve(13)
257 c
258 c See the comments at the end of driver1 for a description
259 c of the variables isave and dsave.
260 
261 
262  write (6,'(2(a,i5,4x),a,1p,d12.5,4x,a,1p,d12.5)') 'Iterate'
263  + ,isave(30),'nfg =',isave(34),'f =',f,'|proj g| =',dsave(13)
264 
265 c If the run is to be terminated, we print also the information
266 c contained in task as well as the final value of x.
267 
268 
269  if (task(1:4) .eq. 'STOP') then
270  write (6,*) task
271  write (6,*) 'Final X='
272  write (6,'((1x,1p, 6(1x,d11.4)))') (x(i),i = 1,n)
273  endif
274 
275 c go back to the minimization routine.
276  goto 111
277 
278  endif
279 
280 c ---------- the end of the loop -------------
281 
282 c If task is neither FG nor NEW_X we terminate execution.
283 
284  if (json_active) then
285  call json_write_aggregate(trim(lbfgsb_json), task, f,
286  + dsave(13), n, x)
287  endif
288 
289  stop
290 
291  end
292 
293 c======================= The end of driver3 ============================
294 
subroutine setulb(n, m, x, l, u, nbd, f, g, factr, pgtol, wa, iwa, task, iprint, csave, lsave, isave, dsave)
This subroutine partitions the working arrays wa and iwa, and then uses the limited memory BFGS metho...
Definition: setulb.f:190
subroutine timer(ttime)
This routine computes cpu time in double precision.
Definition: timer.f:11