diff options
author | Maurizio D'Addona | 2019-01-29 17:19:17 +0100 |
---|---|---|
committer | Maurizio D'Addona | 2019-01-29 17:19:17 +0100 |
commit | 6c353a60796efae6114433fca8f75bb9e5977027 (patch) | |
tree | cec01318720e423cf2ca40267205ac2552d3db43 | |
parent | c1476e6329f265e61020fe89222871be87e38719 (diff) | |
download | aur-6c353a60796efae6114433fca8f75bb9e5977027.tar.gz |
Upstream fixes source tarball
-rwxr-xr-x | .SRCINFO | 10 | ||||
-rwxr-xr-x | PKGBUILD | 14 | ||||
-rw-r--r-- | ccx_2.14_lbfgsb.f | 3949 | ||||
-rw-r--r-- | ccx_2.14_linpack.f | 218 | ||||
-rw-r--r-- | ccx_2.14_timer.f | 32 |
5 files changed, 4 insertions, 4219 deletions
@@ -1,7 +1,7 @@ pkgbase = calculix pkgdesc = CalculiX: 3D finite element solver and post-processor (executables) pkgver = 2.15 - pkgrel = 2 + pkgrel = 3 url = http://www.calculix.de/ arch = i686 arch = x86_64 @@ -22,16 +22,10 @@ pkgbase = calculix source = http://www.dhondt.de/ccx_2.15.src.tar.bz2 source = http://www.dhondt.de/ccx_2.15.test.tar.bz2 source = http://www.dhondt.de/cgx_2.15.all.tar.bz2 - source = ccx_2.14_lbfgsb.f - source = ccx_2.14_linpack.f - source = ccx_2.14_timer.f source = calculix_2.15_archlinux.patch - sha256sums = 5f112598a5f1c1d65a9d213c30fece2481f22987f39e8b36c67aa7bd2d764cbe + sha256sums = bc7dba721935af51b60c1b5aa1529a420476fc6432a7bec5254f8dfabaeb8a34 sha256sums = ee17e477aeae944c35853a663ac245c33b405c3750308c5d77e5ee9a4e609dd5 sha256sums = ce589e777249181e3c15bba6a42ec22ca305ef4e1cfba478d86ae6c775f1712b - sha256sums = b528f595f6b0969ed7e58339d1be0f09f65bd52a62b449d9d0066c367676bdb9 - sha256sums = 58c9131af4bce6649cb4fd19525311df3df52364bd1fe4908be3b770b5b076f6 - sha256sums = 8ad2be66b9dc491d20eeb9801aadfd8451439372179ca41cc95bf5acb0de6aac sha256sums = 7cd1b478aab2886b2a2eb590a165f25d6ddade1076ebbe0d3d5f8c4acc120a22 pkgname = calculix @@ -7,7 +7,7 @@ pkgname=calculix pkgver=2.15 -pkgrel=2 +pkgrel=3 pkgdesc="CalculiX: 3D finite element solver and post-processor (executables)" arch=('i686' 'x86_64') options=(!makeflags !buildflags) @@ -24,27 +24,17 @@ checkdepends=('perl') source=("http://www.dhondt.de/ccx_${pkgver}.src.tar.bz2" "http://www.dhondt.de/ccx_${pkgver}.test.tar.bz2" "http://www.dhondt.de/cgx_${pkgver}.all.tar.bz2" - "ccx_2.14_lbfgsb.f" - "ccx_2.14_linpack.f" - "ccx_2.14_timer.f" "calculix_${pkgver}_archlinux.patch") -sha256sums=('5f112598a5f1c1d65a9d213c30fece2481f22987f39e8b36c67aa7bd2d764cbe' +sha256sums=('bc7dba721935af51b60c1b5aa1529a420476fc6432a7bec5254f8dfabaeb8a34' 'ee17e477aeae944c35853a663ac245c33b405c3750308c5d77e5ee9a4e609dd5' 'ce589e777249181e3c15bba6a42ec22ca305ef4e1cfba478d86ae6c775f1712b' - 'b528f595f6b0969ed7e58339d1be0f09f65bd52a62b449d9d0066c367676bdb9' - '58c9131af4bce6649cb4fd19525311df3df52364bd1fe4908be3b770b5b076f6' - '8ad2be66b9dc491d20eeb9801aadfd8451439372179ca41cc95bf5acb0de6aac' '7cd1b478aab2886b2a2eb590a165f25d6ddade1076ebbe0d3d5f8c4acc120a22') prepare() { cd "${srcdir}" - cp -n ccx_2.14_lbfgsb.f "${srcdir}/CalculiX/ccx_${pkgver}/src/lbfgsb.f" - cp -n ccx_2.14_linpack.f "${srcdir}/CalculiX/ccx_${pkgver}/src/linpack.f" - cp -n ccx_2.14_timer.f "${srcdir}/CalculiX/ccx_${pkgver}/src/timer.f" - msg "Patching makefiles..." rm -rf CalculiX/libSNL patch -p0 -f -l -s -i calculix_${pkgver}_archlinux.patch diff --git a/ccx_2.14_lbfgsb.f b/ccx_2.14_lbfgsb.f deleted file mode 100644 index 9c9e7d931036..000000000000 --- a/ccx_2.14_lbfgsb.f +++ /dev/null @@ -1,3949 +0,0 @@ -c -c L-BFGS-B is released under the “New BSD License” (aka “Modified BSD License” -c or “3-clause license”) -c Please read attached file License.txt -c -c=========== L-BFGS-B (version 3.0. April 25, 2011 =================== -c -c This is a modified version of L-BFGS-B. Minor changes in the updated -c code appear preceded by a line comment as follows -c -c c-jlm-jn -c -c Major changes are described in the accompanying paper: -c -c Jorge Nocedal and Jose Luis Morales, Remark on "Algorithm 778: -c L-BFGS-B: Fortran Subroutines for Large-Scale Bound Constrained -c Optimization" (2011). To appear in ACM Transactions on -c Mathematical Software, -c -c The paper describes an improvement and a correction to Algorithm 778. -c It is shown that the performance of the algorithm can be improved -c significantly by making a relatively simple modication to the subspace -c minimization phase. The correction concerns an error caused by the use -c of routine dpmeps to estimate machine precision. -c -c The total work space **wa** required by the new version is -c -c 2*m*n + 11m*m + 5*n + 8*m -c -c the old version required -c -c 2*m*n + 12m*m + 4*n + 12*m -c -c -c J. Nocedal Department of Electrical Engineering and -c Computer Science. -c Northwestern University. Evanston, IL. USA -c -c -c J.L Morales Departamento de Matematicas, -c Instituto Tecnologico Autonomo de Mexico -c Mexico D.F. Mexico. -c -c March 2011 -c -c============================================================================= - subroutine setulb(n, m, x, l, u, nbd, f, g, factr, pgtol, wa, iwa, - + task, iprint, csave, lsave, isave, dsave) - - character*60 task, csave - logical lsave(4) - integer n, m, iprint, - + nbd(n), iwa(3*n), isave(44) - double precision f, factr, pgtol, x(n), l(n), u(n), g(n), -c -c-jlm-jn - + wa(2*m*n + 5*n + 11*m*m + 8*m), dsave(29) - -c ************ -c -c Subroutine setulb -c -c This subroutine partitions the working arrays wa and iwa, and -c then uses the limited memory BFGS method to solve the bound -c constrained optimization problem by calling mainlb. -c (The direct method will be used in the subspace minimization.) -c -c n is an integer variable. -c On entry n is the dimension of the problem. -c On exit n is unchanged. -c -c m is an integer variable. -c On entry m is the maximum number of variable metric corrections -c used to define the limited memory matrix. -c On exit m is unchanged. -c -c x is a double precision array of dimension n. -c On entry x is an approximation to the solution. -c On exit x is the current approximation. -c -c l is a double precision array of dimension n. -c On entry l is the lower bound on x. -c On exit l is unchanged. -c -c u is a double precision array of dimension n. -c On entry u is the upper bound on x. -c On exit u is unchanged. -c -c nbd is an integer array of dimension n. -c On entry nbd represents the type of bounds imposed on the -c variables, and must be specified as follows: -c nbd(i)=0 if x(i) is unbounded, -c 1 if x(i) has only a lower bound, -c 2 if x(i) has both lower and upper bounds, and -c 3 if x(i) has only an upper bound. -c On exit nbd is unchanged. -c -c f is a double precision variable. -c On first entry f is unspecified. -c On final exit f is the value of the function at x. -c -c g is a double precision array of dimension n. -c On first entry g is unspecified. -c On final exit g is the value of the gradient at x. -c -c factr is a double precision variable. -c On entry factr >= 0 is specified by the user. The iteration -c will stop when -c -c (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch -c -c where epsmch is the machine precision, which is automatically -c generated by the code. Typical values for factr: 1.d+12 for -c low accuracy; 1.d+7 for moderate accuracy; 1.d+1 for extremely -c high accuracy. -c On exit factr is unchanged. -c -c pgtol is a double precision variable. -c On entry pgtol >= 0 is specified by the user. The iteration -c will stop when -c -c max{|proj g_i | i = 1, ..., n} <= pgtol -c -c where pg_i is the ith component of the projected gradient. -c On exit pgtol is unchanged. -c -c wa is a double precision working array of length -c (2mmax + 5)nmax + 12mmax^2 + 12mmax. -c -c iwa is an integer working array of length 3nmax. -c -c task is a working string of characters of length 60 indicating -c the current job when entering and quitting this subroutine. -c -c iprint is an integer variable that must be set by the user. -c It controls the frequency and type of output generated: -c iprint<0 no output is generated; -c iprint=0 print only one line at the last iteration; -c 0<iprint<99 print also f and |proj g| every iprint iterations; -c iprint=99 print details of every iteration except n-vectors; -c iprint=100 print also the changes of active set and final x; -c iprint>100 print details of every iteration including x and g; -c When iprint > 0, the file iterate.dat will be created to -c summarize the iteration. -c -c csave is a working string of characters of length 60. -c -c lsave is a logical working array of dimension 4. -c On exit with 'task' = NEW_X, the following information is -c available: -c If lsave(1) = .true. then the initial X has been replaced by -c its projection in the feasible set; -c If lsave(2) = .true. then the problem is constrained; -c If lsave(3) = .true. then each variable has upper and lower -c bounds; -c -c isave is an integer working array of dimension 44. -c On exit with 'task' = NEW_X, the following information is -c available: -c isave(22) = the total number of intervals explored in the -c search of Cauchy points; -c isave(26) = the total number of skipped BFGS updates before -c the current iteration; -c isave(30) = the number of current iteration; -c isave(31) = the total number of BFGS updates prior the current -c iteration; -c isave(33) = the number of intervals explored in the search of -c Cauchy point in the current iteration; -c isave(34) = the total number of function and gradient -c evaluations; -c isave(36) = the number of function value or gradient -c evaluations in the current iteration; -c if isave(37) = 0 then the subspace argmin is within the box; -c if isave(37) = 1 then the subspace argmin is beyond the box; -c isave(38) = the number of free variables in the current -c iteration; -c isave(39) = the number of active constraints in the current -c iteration; -c n + 1 - isave(40) = the number of variables leaving the set of -c active constraints in the current iteration; -c isave(41) = the number of variables entering the set of active -c constraints in the current iteration. -c -c dsave is a double precision working array of dimension 29. -c On exit with 'task' = NEW_X, the following information is -c available: -c dsave(1) = current 'theta' in the BFGS matrix; -c dsave(2) = f(x) in the previous iteration; -c dsave(3) = factr*epsmch; -c dsave(4) = 2-norm of the line search direction vector; -c dsave(5) = the machine precision epsmch generated by the code; -c dsave(7) = the accumulated time spent on searching for -c Cauchy points; -c dsave(8) = the accumulated time spent on -c subspace minimization; -c dsave(9) = the accumulated time spent on line search; -c dsave(11) = the slope of the line search function at -c the current point of line search; -c dsave(12) = the maximum relative step length imposed in -c line search; -c dsave(13) = the infinity norm of the projected gradient; -c dsave(14) = the relative step length in the line search; -c dsave(15) = the slope of the line search function at -c the starting point of the line search; -c dsave(16) = the square of the 2-norm of the line search -c direction vector. -c -c Subprograms called: -c -c L-BFGS-B Library ... mainlb. -c -c -c References: -c -c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited -c memory algorithm for bound constrained optimization'', -c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. -c -c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a -c limited memory FORTRAN code for solving bound constrained -c optimization problems'', Tech. Report, NAM-11, EECS Department, -c Northwestern University, 1994. -c -c (Postscript files of these papers are available via anonymous -c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ -c-jlm-jn - integer lws,lr,lz,lt,ld,lxp,lwa, - + lwy,lsy,lss,lwt,lwn,lsnd - - if (task .eq. 'START') then - isave(1) = m*n - isave(2) = m**2 - isave(3) = 4*m**2 - isave(4) = 1 ! ws m*n - isave(5) = isave(4) + isave(1) ! wy m*n - isave(6) = isave(5) + isave(1) ! wsy m**2 - isave(7) = isave(6) + isave(2) ! wss m**2 - isave(8) = isave(7) + isave(2) ! wt m**2 - isave(9) = isave(8) + isave(2) ! wn 4*m**2 - isave(10) = isave(9) + isave(3) ! wsnd 4*m**2 - isave(11) = isave(10) + isave(3) ! wz n - isave(12) = isave(11) + n ! wr n - isave(13) = isave(12) + n ! wd n - isave(14) = isave(13) + n ! wt n - isave(15) = isave(14) + n ! wxp n - isave(16) = isave(15) + n ! wa 8*m - endif - lws = isave(4) - lwy = isave(5) - lsy = isave(6) - lss = isave(7) - lwt = isave(8) - lwn = isave(9) - lsnd = isave(10) - lz = isave(11) - lr = isave(12) - ld = isave(13) - lt = isave(14) - lxp = isave(15) - lwa = isave(16) - - call mainlb(n,m,x,l,u,nbd,f,g,factr,pgtol, - + wa(lws),wa(lwy),wa(lsy),wa(lss), wa(lwt), - + wa(lwn),wa(lsnd),wa(lz),wa(lr),wa(ld),wa(lt),wa(lxp), - + wa(lwa), - + iwa(1),iwa(n+1),iwa(2*n+1),task,iprint, - + csave,lsave,isave(22),dsave) - - return - - end - -c======================= The end of setulb ============================= - - subroutine mainlb(n, m, x, l, u, nbd, f, g, factr, pgtol, ws, wy, - + sy, ss, wt, wn, snd, z, r, d, t, xp, wa, - + index, iwhere, indx2, task, - + iprint, csave, lsave, isave, dsave) - implicit none - character*60 task, csave - logical lsave(4) - integer n, m, iprint, nbd(n), index(n), - + iwhere(n), indx2(n), isave(23) - double precision f, factr, pgtol, - + x(n), l(n), u(n), g(n), z(n), r(n), d(n), t(n), -c-jlm-jn - + xp(n), - + wa(8*m), - + ws(n, m), wy(n, m), sy(m, m), ss(m, m), - + wt(m, m), wn(2*m, 2*m), snd(2*m, 2*m), dsave(29) - -c ************ -c -c Subroutine mainlb -c -c This subroutine solves bound constrained optimization problems by -c using the compact formula of the limited memory BFGS updates. -c -c n is an integer variable. -c On entry n is the number of variables. -c On exit n is unchanged. -c -c m is an integer variable. -c On entry m is the maximum number of variable metric -c corrections allowed in the limited memory matrix. -c On exit m is unchanged. -c -c x is a double precision array of dimension n. -c On entry x is an approximation to the solution. -c On exit x is the current approximation. -c -c l is a double precision array of dimension n. -c On entry l is the lower bound of x. -c On exit l is unchanged. -c -c u is a double precision array of dimension n. -c On entry u is the upper bound of x. -c On exit u is unchanged. -c -c nbd is an integer array of dimension n. -c On entry nbd represents the type of bounds imposed on the -c variables, and must be specified as follows: -c nbd(i)=0 if x(i) is unbounded, -c 1 if x(i) has only a lower bound, -c 2 if x(i) has both lower and upper bounds, -c 3 if x(i) has only an upper bound. -c On exit nbd is unchanged. -c -c f is a double precision variable. -c On first entry f is unspecified. -c On final exit f is the value of the function at x. -c -c g is a double precision array of dimension n. -c On first entry g is unspecified. -c On final exit g is the value of the gradient at x. -c -c factr is a double precision variable. -c On entry factr >= 0 is specified by the user. The iteration -c will stop when -c -c (f^k - f^{k+1})/max{|f^k|,|f^{k+1}|,1} <= factr*epsmch -c -c where epsmch is the machine precision, which is automatically -c generated by the code. -c On exit factr is unchanged. -c -c pgtol is a double precision variable. -c On entry pgtol >= 0 is specified by the user. The iteration -c will stop when -c -c max{|proj g_i | i = 1, ..., n} <= pgtol -c -c where pg_i is the ith component of the projected gradient. -c On exit pgtol is unchanged. -c -c ws, wy, sy, and wt are double precision working arrays used to -c store the following information defining the limited memory -c BFGS matrix: -c ws, of dimension n x m, stores S, the matrix of s-vectors; -c wy, of dimension n x m, stores Y, the matrix of y-vectors; -c sy, of dimension m x m, stores S'Y; -c ss, of dimension m x m, stores S'S; -c yy, of dimension m x m, stores Y'Y; -c wt, of dimension m x m, stores the Cholesky factorization -c of (theta*S'S+LD^(-1)L'); see eq. -c (2.26) in [3]. -c -c wn is a double precision working array of dimension 2m x 2m -c used to store the LEL^T factorization of the indefinite matrix -c K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] -c [L_a -R_z theta*S'AA'S ] -c -c where E = [-I 0] -c [ 0 I] -c -c snd is a double precision working array of dimension 2m x 2m -c used to store the lower triangular part of -c N = [Y' ZZ'Y L_a'+R_z'] -c [L_a +R_z S'AA'S ] -c -c z(n),r(n),d(n),t(n), xp(n),wa(8*m) are double precision working arrays. -c z is used at different times to store the Cauchy point and -c the Newton point. -c xp is used to safeguard the projected Newton direction -c -c sg(m),sgo(m),yg(m),ygo(m) are double precision working arrays. -c -c index is an integer working array of dimension n. -c In subroutine freev, index is used to store the free and fixed -c variables at the Generalized Cauchy Point (GCP). -c -c iwhere is an integer working array of dimension n used to record -c the status of the vector x for GCP computation. -c iwhere(i)=0 or -3 if x(i) is free and has bounds, -c 1 if x(i) is fixed at l(i), and l(i) .ne. u(i) -c 2 if x(i) is fixed at u(i), and u(i) .ne. l(i) -c 3 if x(i) is always fixed, i.e., u(i)=x(i)=l(i) -c -1 if x(i) is always free, i.e., no bounds on it. -c -c indx2 is an integer working array of dimension n. -c Within subroutine cauchy, indx2 corresponds to the array iorder. -c In subroutine freev, a list of variables entering and leaving -c the free set is stored in indx2, and it is passed on to -c subroutine formk with this information. -c -c task is a working string of characters of length 60 indicating -c the current job when entering and leaving this subroutine. -c -c iprint is an INTEGER variable that must be set by the user. -c It controls the frequency and type of output generated: -c iprint<0 no output is generated; -c iprint=0 print only one line at the last iteration; -c 0<iprint<99 print also f and |proj g| every iprint iterations; -c iprint=99 print details of every iteration except n-vectors; -c iprint=100 print also the changes of active set and final x; -c iprint>100 print details of every iteration including x and g; -c When iprint > 0, the file iterate.dat will be created to -c summarize the iteration. -c -c csave is a working string of characters of length 60. -c -c lsave is a logical working array of dimension 4. -c -c isave is an integer working array of dimension 23. -c -c dsave is a double precision working array of dimension 29. -c -c -c Subprograms called -c -c L-BFGS-B Library ... cauchy, subsm, lnsrlb, formk, -c -c errclb, prn1lb, prn2lb, prn3lb, active, projgr, -c -c freev, cmprlb, matupd, formt. -c -c Minpack2 Library ... timer -c -c Linpack Library ... dcopy, ddot. -c -c -c References: -c -c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited -c memory algorithm for bound constrained optimization'', -c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. -c -c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN -c Subroutines for Large Scale Bound Constrained Optimization'' -c Tech. Report, NAM-11, EECS Department, Northwestern University, -c 1994. -c -c [3] R. Byrd, J. Nocedal and R. Schnabel "Representations of -c Quasi-Newton Matrices and their use in Limited Memory Methods'', -c Mathematical Programming 63 (1994), no. 4, pp. 129-156. -c -c (Postscript files of these papers are available via anonymous -c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - logical prjctd,cnstnd,boxed,updatd,wrk - character*3 word - integer i,k,nintol,itfile,iback,nskip, - + head,col,iter,itail,iupdat, - + nseg,nfgv,info,ifun, - + iword,nfree,nact,ileave,nenter - double precision theta,fold,ddot,dr,rr,tol, - + xstep,sbgnrm,ddum,dnorm,dtd,epsmch, - + cpu1,cpu2,cachyt,sbtime,lnscht,time1,time2, - + gd,gdold,stp,stpmx,time - double precision one,zero - parameter (one=1.0d0,zero=0.0d0) - - if (task .eq. 'START') then - - epsmch = epsilon(one) - - call timer(time1) - -c Initialize counters and scalars when task='START'. - -c for the limited memory BFGS matrices: - col = 0 - head = 1 - theta = one - iupdat = 0 - updatd = .false. - iback = 0 - itail = 0 - iword = 0 - nact = 0 - ileave = 0 - nenter = 0 - fold = zero - dnorm = zero - cpu1 = zero - gd = zero - stpmx = zero - sbgnrm = zero - stp = zero - gdold = zero - dtd = zero - -c for operation counts: - iter = 0 - nfgv = 0 - nseg = 0 - nintol = 0 - nskip = 0 - nfree = n - ifun = 0 -c for stopping tolerance: - tol = factr*epsmch - -c for measuring running time: - cachyt = 0 - sbtime = 0 - lnscht = 0 - -c 'word' records the status of subspace solutions. - word = '---' - -c 'info' records the termination information. - info = 0 - - itfile = 8 - if (iprint .ge. 1) then -c open a summary file 'iterate.dat' - open (8, file = 'iterate.dat', status = 'unknown') - endif - -c Check the input arguments for errors. - - call errclb(n,m,factr,l,u,nbd,task,info,k) - if (task(1:5) .eq. 'ERROR') then - call prn3lb(n,x,f,task,iprint,info,itfile, - + iter,nfgv,nintol,nskip,nact,sbgnrm, - + zero,nseg,word,iback,stp,xstep,k, - + cachyt,sbtime,lnscht) - return - endif - - call prn1lb(n,m,l,u,x,iprint,itfile,epsmch) - -c Initialize iwhere & project x onto the feasible set. - - call active(n,l,u,nbd,x,iwhere,iprint,prjctd,cnstnd,boxed) - -c The end of the initialization. - - else -c restore local variables. - - prjctd = lsave(1) - cnstnd = lsave(2) - boxed = lsave(3) - updatd = lsave(4) - - nintol = isave(1) - itfile = isave(3) - iback = isave(4) - nskip = isave(5) - head = isave(6) - col = isave(7) - itail = isave(8) - iter = isave(9) - iupdat = isave(10) - nseg = isave(12) - nfgv = isave(13) - info = isave(14) - ifun = isave(15) - iword = isave(16) - nfree = isave(17) - nact = isave(18) - ileave = isave(19) - nenter = isave(20) - - theta = dsave(1) - fold = dsave(2) - tol = dsave(3) - dnorm = dsave(4) - epsmch = dsave(5) - cpu1 = dsave(6) - cachyt = dsave(7) - sbtime = dsave(8) - lnscht = dsave(9) - time1 = dsave(10) - gd = dsave(11) - stpmx = dsave(12) - sbgnrm = dsave(13) - stp = dsave(14) - gdold = dsave(15) - dtd = dsave(16) - -c After returning from the driver go to the point where execution -c is to resume. - - if (task(1:5) .eq. 'FG_LN') goto 666 - if (task(1:5) .eq. 'NEW_X') goto 777 - if (task(1:5) .eq. 'FG_ST') goto 111 - if (task(1:4) .eq. 'STOP') then - if (task(7:9) .eq. 'CPU') then -c restore the previous iterate. - call dcopy(n,t,1,x,1) - call dcopy(n,r,1,g,1) - f = fold - endif - goto 999 - endif - endif - -c Compute f0 and g0. - - task = 'FG_START' -c return to the driver to calculate f and g; reenter at 111. - goto 1000 - 111 continue - nfgv = 1 - -c Compute the infinity norm of the (-) projected gradient. - - call projgr(n,l,u,nbd,x,g,sbgnrm) - - if (iprint .ge. 1) then - write (6,1002) iter,f,sbgnrm - write (itfile,1003) iter,nfgv,sbgnrm,f - endif - if (sbgnrm .le. pgtol) then -c terminate the algorithm. - task = 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL' - goto 999 - endif - -c ----------------- the beginning of the loop -------------------------- - - 222 continue - if (iprint .ge. 99) write (6,1001) iter + 1 - iword = -1 -c - if (.not. cnstnd .and. col .gt. 0) then -c skip the search for GCP. - call dcopy(n,x,1,z,1) - wrk = updatd - nseg = 0 - goto 333 - endif - -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c -c Compute the Generalized Cauchy Point (GCP). -c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - call timer(cpu1) - call cauchy(n,x,l,u,nbd,g,indx2,iwhere,t,d,z, - + m,wy,ws,sy,wt,theta,col,head, - + wa(1),wa(2*m+1),wa(4*m+1),wa(6*m+1),nseg, - + iprint, sbgnrm, info, epsmch) - if (info .ne. 0) then -c singular triangular system detected; refresh the lbfgs memory. - if(iprint .ge. 1) write (6, 1005) - info = 0 - col = 0 - head = 1 - theta = one - iupdat = 0 - updatd = .false. - call timer(cpu2) - cachyt = cachyt + cpu2 - cpu1 - goto 222 - endif - call timer(cpu2) - cachyt = cachyt + cpu2 - cpu1 - nintol = nintol + nseg - -c Count the entering and leaving variables for iter > 0; -c find the index set of free and active variables at the GCP. - - call freev(n,nfree,index,nenter,ileave,indx2, - + iwhere,wrk,updatd,cnstnd,iprint,iter) - nact = n - nfree - - 333 continue - -c If there are no free variables or B=theta*I, then -c skip the subspace minimization. - - if (nfree .eq. 0 .or. col .eq. 0) goto 555 - -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c -c Subspace minimization. -c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - call timer(cpu1) - -c Form the LEL^T factorization of the indefinite -c matrix K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] -c [L_a -R_z theta*S'AA'S ] -c where E = [-I 0] -c [ 0 I] - - if (wrk) call formk(n,nfree,index,nenter,ileave,indx2,iupdat, - + updatd,wn,snd,m,ws,wy,sy,theta,col,head,info) - if (info .ne. 0) then -c nonpositive definiteness in Cholesky factorization; -c refresh the lbfgs memory and restart the iteration. - if(iprint .ge. 1) write (6, 1006) - info = 0 - col = 0 - head = 1 - theta = one - iupdat = 0 - updatd = .false. - call timer(cpu2) - sbtime = sbtime + cpu2 - cpu1 - goto 222 - endif - -c compute r=-Z'B(xcp-xk)-Z'g (using wa(2m+1)=W'(xcp-x) -c from 'cauchy'). - call cmprlb(n,m,x,g,ws,wy,sy,wt,z,r,wa,index, - + theta,col,head,nfree,cnstnd,info) - if (info .ne. 0) goto 444 - -c-jlm-jn call the direct method. - - call subsm( n, m, nfree, index, l, u, nbd, z, r, xp, ws, wy, - + theta, x, g, col, head, iword, wa, wn, iprint, info) - 444 continue - if (info .ne. 0) then -c singular triangular system detected; -c refresh the lbfgs memory and restart the iteration. - if(iprint .ge. 1) write (6, 1005) - info = 0 - col = 0 - head = 1 - theta = one - iupdat = 0 - updatd = .false. - call timer(cpu2) - sbtime = sbtime + cpu2 - cpu1 - goto 222 - endif - - call timer(cpu2) - sbtime = sbtime + cpu2 - cpu1 - 555 continue - -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c -c Line search and optimality tests. -c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - -c Generate the search direction d:=z-x. - - do 40 i = 1, n - d(i) = z(i) - x(i) - 40 continue - call timer(cpu1) - 666 continue - call lnsrlb(n,l,u,nbd,x,f,fold,gd,gdold,g,d,r,t,z,stp,dnorm, - + dtd,xstep,stpmx,iter,ifun,iback,nfgv,info,task, - + boxed,cnstnd,csave,isave(22),dsave(17)) - if (info .ne. 0 .or. iback .ge. 20) then -c restore the previous iterate. - call dcopy(n,t,1,x,1) - call dcopy(n,r,1,g,1) - f = fold - if (col .eq. 0) then -c abnormal termination. - if (info .eq. 0) then - info = -9 -c restore the actual number of f and g evaluations etc. - nfgv = nfgv - 1 - ifun = ifun - 1 - iback = iback - 1 - endif - task = 'ABNORMAL_TERMINATION_IN_LNSRCH' - iter = iter + 1 - goto 999 - else -c refresh the lbfgs memory and restart the iteration. - if(iprint .ge. 1) write (6, 1008) - if (info .eq. 0) nfgv = nfgv - 1 - info = 0 - col = 0 - head = 1 - theta = one - iupdat = 0 - updatd = .false. - task = 'RESTART_FROM_LNSRCH' - call timer(cpu2) - lnscht = lnscht + cpu2 - cpu1 - goto 222 - endif - else if (task(1:5) .eq. 'FG_LN') then -c return to the driver for calculating f and g; reenter at 666. - goto 1000 - else -c calculate and print out the quantities related to the new X. - call timer(cpu2) - lnscht = lnscht + cpu2 - cpu1 - iter = iter + 1 - -c Compute the infinity norm of the projected (-)gradient. - - call projgr(n,l,u,nbd,x,g,sbgnrm) - -c Print iteration information. - - call prn2lb(n,x,f,g,iprint,itfile,iter,nfgv,nact, - + sbgnrm,nseg,word,iword,iback,stp,xstep) - goto 1000 - endif - 777 continue - -c Test for termination. - - if (sbgnrm .le. pgtol) then -c terminate the algorithm. - task = 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL' - goto 999 - endif - - ddum = max(abs(fold), abs(f), one) - if ((fold - f) .le. tol*ddum) then -c terminate the algorithm. - task = 'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH' - if (iback .ge. 10) info = -5 -c i.e., to issue a warning if iback>10 in the line search. - goto 999 - endif - -c Compute d=newx-oldx, r=newg-oldg, rr=y'y and dr=y's. - - do 42 i = 1, n - r(i) = g(i) - r(i) - 42 continue - rr = ddot(n,r,1,r,1) - if (stp .eq. one) then - dr = gd - gdold - ddum = -gdold - else - dr = (gd - gdold)*stp - call dscal(n,stp,d,1) - ddum = -gdold*stp - endif - - if (dr .le. epsmch*ddum) then -c skip the L-BFGS update. - nskip = nskip + 1 - updatd = .false. - if (iprint .ge. 1) write (6,1004) dr, ddum - goto 888 - endif - -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc -c -c Update the L-BFGS matrix. -c -cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc - - updatd = .true. - iupdat = iupdat + 1 - -c Update matrices WS and WY and form the middle matrix in B. - - call matupd(n,m,ws,wy,sy,ss,d,r,itail, - + iupdat,col,head,theta,rr,dr,stp,dtd) - -c Form the upper half of the pds T = theta*SS + L*D^(-1)*L'; -c Store T in the upper triangular of the array wt; -c Cholesky factorize T to J*J' with -c J' stored in the upper triangular of wt. - - call formt(m,wt,sy,ss,col,theta,info) - - if (info .ne. 0) then -c nonpositive definiteness in Cholesky factorization; -c refresh the lbfgs memory and restart the iteration. - if(iprint .ge. 1) write (6, 1007) - info = 0 - col = 0 - head = 1 - theta = one - iupdat = 0 - updatd = .false. - goto 222 - endif - -c Now the inverse of the middle matrix in B is - -c [ D^(1/2) O ] [ -D^(1/2) D^(-1/2)*L' ] -c [ -L*D^(-1/2) J ] [ 0 J' ] - - 888 continue - -c -------------------- the end of the loop ----------------------------- - - goto 222 - 999 continue - call timer(time2) - time = time2 - time1 - call prn3lb(n,x,f,task,iprint,info,itfile, - + iter,nfgv,nintol,nskip,nact,sbgnrm, - + time,nseg,word,iback,stp,xstep,k, - + cachyt,sbtime,lnscht) - 1000 continue - -c Save local variables. - - lsave(1) = prjctd - lsave(2) = cnstnd - lsave(3) = boxed - lsave(4) = updatd - - isave(1) = nintol - isave(3) = itfile - isave(4) = iback - isave(5) = nskip - isave(6) = head - isave(7) = col - isave(8) = itail - isave(9) = iter - isave(10) = iupdat - isave(12) = nseg - isave(13) = nfgv - isave(14) = info - isave(15) = ifun - isave(16) = iword - isave(17) = nfree - isave(18) = nact - isave(19) = ileave - isave(20) = nenter - - dsave(1) = theta - dsave(2) = fold - dsave(3) = tol - dsave(4) = dnorm - dsave(5) = epsmch - dsave(6) = cpu1 - dsave(7) = cachyt - dsave(8) = sbtime - dsave(9) = lnscht - dsave(10) = time1 - dsave(11) = gd - dsave(12) = stpmx - dsave(13) = sbgnrm - dsave(14) = stp - dsave(15) = gdold - dsave(16) = dtd - - 1001 format (//,'ITERATION ',i5) - 1002 format - + (/,'At iterate',i5,4x,'f= ',1p,d12.5,4x,'|proj g|= ',1p,d12.5) - 1003 format (2(1x,i4),5x,'-',5x,'-',3x,'-',5x,'-',5x,'-',8x,'-',3x, - + 1p,2(1x,d10.3)) - 1004 format (' ys=',1p,e10.3,' -gs=',1p,e10.3,' BFGS update SKIPPED') - 1005 format (/, - +' Singular triangular system detected;',/, - +' refresh the lbfgs memory and restart the iteration.') - 1006 format (/, - +' Nonpositive definiteness in Cholesky factorization in formk;',/, - +' refresh the lbfgs memory and restart the iteration.') - 1007 format (/, - +' Nonpositive definiteness in Cholesky factorization in formt;',/, - +' refresh the lbfgs memory and restart the iteration.') - 1008 format (/, - +' Bad direction in the line search;',/, - +' refresh the lbfgs memory and restart the iteration.') - - return - - end - -c======================= The end of mainlb ============================= - - subroutine active(n, l, u, nbd, x, iwhere, iprint, - + prjctd, cnstnd, boxed) - - logical prjctd, cnstnd, boxed - integer n, iprint, nbd(n), iwhere(n) - double precision x(n), l(n), u(n) - -c ************ -c -c Subroutine active -c -c This subroutine initializes iwhere and projects the initial x to -c the feasible set if necessary. -c -c iwhere is an integer array of dimension n. -c On entry iwhere is unspecified. -c On exit iwhere(i)=-1 if x(i) has no bounds -c 3 if l(i)=u(i) -c 0 otherwise. -c In cauchy, iwhere is given finer gradations. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer nbdd,i - double precision zero - parameter (zero=0.0d0) - -c Initialize nbdd, prjctd, cnstnd and boxed. - - nbdd = 0 - prjctd = .false. - cnstnd = .false. - boxed = .true. - -c Project the initial x to the easible set if necessary. - - do 10 i = 1, n - if (nbd(i) .gt. 0) then - if (nbd(i) .le. 2 .and. x(i) .le. l(i)) then - if (x(i) .lt. l(i)) then - prjctd = .true. - x(i) = l(i) - endif - nbdd = nbdd + 1 - else if (nbd(i) .ge. 2 .and. x(i) .ge. u(i)) then - if (x(i) .gt. u(i)) then - prjctd = .true. - x(i) = u(i) - endif - nbdd = nbdd + 1 - endif - endif - 10 continue - -c Initialize iwhere and assign values to cnstnd and boxed. - - do 20 i = 1, n - if (nbd(i) .ne. 2) boxed = .false. - if (nbd(i) .eq. 0) then -c this variable is always free - iwhere(i) = -1 - -c otherwise set x(i)=mid(x(i), u(i), l(i)). - else - cnstnd = .true. - if (nbd(i) .eq. 2 .and. u(i) - l(i) .le. zero) then -c this variable is always fixed - iwhere(i) = 3 - else - iwhere(i) = 0 - endif - endif - 20 continue - - if (iprint .ge. 0) then - if (prjctd) write (6,*) - + 'The initial X is infeasible. Restart with its projection.' - if (.not. cnstnd) - + write (6,*) 'This problem is unconstrained.' - endif - - if (iprint .gt. 0) write (6,1001) nbdd - - 1001 format (/,'At X0 ',i9,' variables are exactly at the bounds') - - return - - end - -c======================= The end of active ============================= - - subroutine bmv(m, sy, wt, col, v, p, info) - - integer m, col, info - double precision sy(m, m), wt(m, m), v(2*col), p(2*col) - -c ************ -c -c Subroutine bmv -c -c This subroutine computes the product of the 2m x 2m middle matrix -c in the compact L-BFGS formula of B and a 2m vector v; -c it returns the product in p. -c -c m is an integer variable. -c On entry m is the maximum number of variable metric corrections -c used to define the limited memory matrix. -c On exit m is unchanged. -c -c sy is a double precision array of dimension m x m. -c On entry sy specifies the matrix S'Y. -c On exit sy is unchanged. -c -c wt is a double precision array of dimension m x m. -c On entry wt specifies the upper triangular matrix J' which is -c the Cholesky factor of (thetaS'S+LD^(-1)L'). -c On exit wt is unchanged. -c -c col is an integer variable. -c On entry col specifies the number of s-vectors (or y-vectors) -c stored in the compact L-BFGS formula. -c On exit col is unchanged. -c -c v is a double precision array of dimension 2col. -c On entry v specifies vector v. -c On exit v is unchanged. -c -c p is a double precision array of dimension 2col. -c On entry p is unspecified. -c On exit p is the product Mv. -c -c info is an integer variable. -c On entry info is unspecified. -c On exit info = 0 for normal return, -c = nonzero for abnormal return when the system -c to be solved by dtrsl is singular. -c -c Subprograms called: -c -c Linpack ... dtrsl. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer i,k,i2 - double precision sum - - if (col .eq. 0) return - -c PART I: solve [ D^(1/2) O ] [ p1 ] = [ v1 ] -c [ -L*D^(-1/2) J ] [ p2 ] [ v2 ]. - -c solve Jp2=v2+LD^(-1)v1. - p(col + 1) = v(col + 1) - do 20 i = 2, col - i2 = col + i - sum = 0.0d0 - do 10 k = 1, i - 1 - sum = sum + sy(i,k)*v(k)/sy(k,k) - 10 continue - p(i2) = v(i2) + sum - 20 continue -c Solve the triangular system - call dtrsl(wt,m,col,p(col+1),11,info) - if (info .ne. 0) return - -c solve D^(1/2)p1=v1. - do 30 i = 1, col - p(i) = v(i)/sqrt(sy(i,i)) - 30 continue - -c PART II: solve [ -D^(1/2) D^(-1/2)*L' ] [ p1 ] = [ p1 ] -c [ 0 J' ] [ p2 ] [ p2 ]. - -c solve J^Tp2=p2. - call dtrsl(wt,m,col,p(col+1),01,info) - if (info .ne. 0) return - -c compute p1=-D^(-1/2)(p1-D^(-1/2)L'p2) -c =-D^(-1/2)p1+D^(-1)L'p2. - do 40 i = 1, col - p(i) = -p(i)/sqrt(sy(i,i)) - 40 continue - do 60 i = 1, col - sum = 0.d0 - do 50 k = i + 1, col - sum = sum + sy(k,i)*p(col+k)/sy(i,i) - 50 continue - p(i) = p(i) + sum - 60 continue - - return - - end - -c======================== The end of bmv =============================== - - subroutine cauchy(n, x, l, u, nbd, g, iorder, iwhere, t, d, xcp, - + m, wy, ws, sy, wt, theta, col, head, p, c, wbp, - + v, nseg, iprint, sbgnrm, info, epsmch) - implicit none - integer n, m, head, col, nseg, iprint, info, - + nbd(n), iorder(n), iwhere(n) - double precision theta, epsmch, - + x(n), l(n), u(n), g(n), t(n), d(n), xcp(n), - + wy(n, col), ws(n, col), sy(m, m), - + wt(m, m), p(2*m), c(2*m), wbp(2*m), v(2*m) - -c ************ -c -c Subroutine cauchy -c -c For given x, l, u, g (with sbgnrm > 0), and a limited memory -c BFGS matrix B defined in terms of matrices WY, WS, WT, and -c scalars head, col, and theta, this subroutine computes the -c generalized Cauchy point (GCP), defined as the first local -c minimizer of the quadratic -c -c Q(x + s) = g's + 1/2 s'Bs -c -c along the projected gradient direction P(x-tg,l,u). -c The routine returns the GCP in xcp. -c -c n is an integer variable. -c On entry n is the dimension of the problem. -c On exit n is unchanged. -c -c x is a double precision array of dimension n. -c On entry x is the starting point for the GCP computation. -c On exit x is unchanged. -c -c l is a double precision array of dimension n. -c On entry l is the lower bound of x. -c On exit l is unchanged. -c -c u is a double precision array of dimension n. -c On entry u is the upper bound of x. -c On exit u is unchanged. -c -c nbd is an integer array of dimension n. -c On entry nbd represents the type of bounds imposed on the -c variables, and must be specified as follows: -c nbd(i)=0 if x(i) is unbounded, -c 1 if x(i) has only a lower bound, -c 2 if x(i) has both lower and upper bounds, and -c 3 if x(i) has only an upper bound. -c On exit nbd is unchanged. -c -c g is a double precision array of dimension n. -c On entry g is the gradient of f(x). g must be a nonzero vector. -c On exit g is unchanged. -c -c iorder is an integer working array of dimension n. -c iorder will be used to store the breakpoints in the piecewise -c linear path and free variables encountered. On exit, -c iorder(1),...,iorder(nleft) are indices of breakpoints -c which have not been encountered; -c iorder(nleft+1),...,iorder(nbreak) are indices of -c encountered breakpoints; and -c iorder(nfree),...,iorder(n) are indices of variables which -c have no bound constraits along the search direction. -c -c iwhere is an integer array of dimension n. -c On entry iwhere indicates only the permanently fixed (iwhere=3) -c or free (iwhere= -1) components of x. -c On exit iwhere records the status of the current x variables. -c iwhere(i)=-3 if x(i) is free and has bounds, but is not moved -c 0 if x(i) is free and has bounds, and is moved -c 1 if x(i) is fixed at l(i), and l(i) .ne. u(i) -c 2 if x(i) is fixed at u(i), and u(i) .ne. l(i) -c 3 if x(i) is always fixed, i.e., u(i)=x(i)=l(i) -c -1 if x(i) is always free, i.e., it has no bounds. -c -c t is a double precision working array of dimension n. -c t will be used to store the break points. -c -c d is a double precision array of dimension n used to store -c the Cauchy direction P(x-tg)-x. -c -c xcp is a double precision array of dimension n used to return the -c GCP on exit. -c -c m is an integer variable. -c On entry m is the maximum number of variable metric corrections -c used to define the limited memory matrix. -c On exit m is unchanged. -c -c ws, wy, sy, and wt are double precision arrays. -c On entry they store information that defines the -c limited memory BFGS matrix: -c ws(n,m) stores S, a set of s-vectors; -c wy(n,m) stores Y, a set of y-vectors; -c sy(m,m) stores S'Y; -c wt(m,m) stores the -c Cholesky factorization of (theta*S'S+LD^(-1)L'). -c On exit these arrays are unchanged. -c -c theta is a double precision variable. -c On entry theta is the scaling factor specifying B_0 = theta I. -c On exit theta is unchanged. -c -c col is an integer variable. -c On entry col is the actual number of variable metric -c corrections stored so far. -c On exit col is unchanged. -c -c head is an integer variable. -c On entry head is the location of the first s-vector (or y-vector) -c in S (or Y). -c On exit col is unchanged. -c -c p is a double precision working array of dimension 2m. -c p will be used to store the vector p = W^(T)d. -c -c c is a double precision working array of dimension 2m. -c c will be used to store the vector c = W^(T)(xcp-x). -c -c wbp is a double precision working array of dimension 2m. -c wbp will be used to store the row of W corresponding -c to a breakpoint. -c -c v is a double precision working array of dimension 2m. -c -c nseg is an integer variable. -c On exit nseg records the number of quadratic segments explored -c in searching for the GCP. -c -c sg and yg are double precision arrays of dimension m. -c On entry sg and yg store S'g and Y'g correspondingly. -c On exit they are unchanged. -c -c iprint is an INTEGER variable that must be set by the user. -c It controls the frequency and type of output generated: -c iprint<0 no output is generated; -c iprint=0 print only one line at the last iteration; -c 0<iprint<99 print also f and |proj g| every iprint iterations; -c iprint=99 print details of every iteration except n-vectors; -c iprint=100 print also the changes of active set and final x; -c iprint>100 print details of every iteration including x and g; -c When iprint > 0, the file iterate.dat will be created to -c summarize the iteration. -c -c sbgnrm is a double precision variable. -c On entry sbgnrm is the norm of the projected gradient at x. -c On exit sbgnrm is unchanged. -c -c info is an integer variable. -c On entry info is 0. -c On exit info = 0 for normal return, -c = nonzero for abnormal return when the the system -c used in routine bmv is singular. -c -c Subprograms called: -c -c L-BFGS-B Library ... hpsolb, bmv. -c -c Linpack ... dscal dcopy, daxpy. -c -c -c References: -c -c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited -c memory algorithm for bound constrained optimization'', -c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. -c -c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: FORTRAN -c Subroutines for Large Scale Bound Constrained Optimization'' -c Tech. Report, NAM-11, EECS Department, Northwestern University, -c 1994. -c -c (Postscript files of these papers are available via anonymous -c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - logical xlower,xupper,bnded - integer i,j,col2,nfree,nbreak,pointr, - + ibp,nleft,ibkmin,iter - double precision f1,f2,dt,dtm,tsum,dibp,zibp,dibp2,bkmin, - + tu,tl,wmc,wmp,wmw,ddot,tj,tj0,neggi,sbgnrm, - + f2_org - double precision one,zero - parameter (one=1.0d0,zero=0.0d0) - -c Check the status of the variables, reset iwhere(i) if necessary; -c compute the Cauchy direction d and the breakpoints t; initialize -c the derivative f1 and the vector p = W'd (for theta = 1). - - if (sbgnrm .le. zero) then - if (iprint .ge. 0) write (6,*) 'Subgnorm = 0. GCP = X.' - call dcopy(n,x,1,xcp,1) - return - endif - bnded = .true. - nfree = n + 1 - nbreak = 0 - ibkmin = 0 - bkmin = zero - col2 = 2*col - f1 = zero - if (iprint .ge. 99) write (6,3010) - -c We set p to zero and build it up as we determine d. - - do 20 i = 1, col2 - p(i) = zero - 20 continue - -c In the following loop we determine for each variable its bound -c status and its breakpoint, and update p accordingly. -c Smallest breakpoint is identified. - - do 50 i = 1, n - neggi = -g(i) - if (iwhere(i) .ne. 3 .and. iwhere(i) .ne. -1) then -c if x(i) is not a constant and has bounds, -c compute the difference between x(i) and its bounds. - if (nbd(i) .le. 2) tl = x(i) - l(i) - if (nbd(i) .ge. 2) tu = u(i) - x(i) - -c If a variable is close enough to a bound -c we treat it as at bound. - xlower = nbd(i) .le. 2 .and. tl .le. zero - xupper = nbd(i) .ge. 2 .and. tu .le. zero - -c reset iwhere(i). - iwhere(i) = 0 - if (xlower) then - if (neggi .le. zero) iwhere(i) = 1 - else if (xupper) then - if (neggi .ge. zero) iwhere(i) = 2 - else - if (abs(neggi) .le. zero) iwhere(i) = -3 - endif - endif - pointr = head - if (iwhere(i) .ne. 0 .and. iwhere(i) .ne. -1) then - d(i) = zero - else - d(i) = neggi - f1 = f1 - neggi*neggi -c calculate p := p - W'e_i* (g_i). - do 40 j = 1, col - p(j) = p(j) + wy(i,pointr)* neggi - p(col + j) = p(col + j) + ws(i,pointr)*neggi - pointr = mod(pointr,m) + 1 - 40 continue - if (nbd(i) .le. 2 .and. nbd(i) .ne. 0 - + .and. neggi .lt. zero) then -c x(i) + d(i) is bounded; compute t(i). - nbreak = nbreak + 1 - iorder(nbreak) = i - t(nbreak) = tl/(-neggi) - if (nbreak .eq. 1 .or. t(nbreak) .lt. bkmin) then - bkmin = t(nbreak) - ibkmin = nbreak - endif - else if (nbd(i) .ge. 2 .and. neggi .gt. zero) then -c x(i) + d(i) is bounded; compute t(i). - nbreak = nbreak + 1 - iorder(nbreak) = i - t(nbreak) = tu/neggi - if (nbreak .eq. 1 .or. t(nbreak) .lt. bkmin) then - bkmin = t(nbreak) - ibkmin = nbreak - endif - else -c x(i) + d(i) is not bounded. - nfree = nfree - 1 - iorder(nfree) = i - if (abs(neggi) .gt. zero) bnded = .false. - endif - endif - 50 continue - -c The indices of the nonzero components of d are now stored -c in iorder(1),...,iorder(nbreak) and iorder(nfree),...,iorder(n). -c The smallest of the nbreak breakpoints is in t(ibkmin)=bkmin. - - if (theta .ne. one) then -c complete the initialization of p for theta not= one. - call dscal(col,theta,p(col+1),1) - endif - -c Initialize GCP xcp = x. - - call dcopy(n,x,1,xcp,1) - - if (nbreak .eq. 0 .and. nfree .eq. n + 1) then -c is a zero vector, return with the initial xcp as GCP. - if (iprint .gt. 100) write (6,1010) (xcp(i), i = 1, n) - return - endif - -c Initialize c = W'(xcp - x) = 0. - - do 60 j = 1, col2 - c(j) = zero - 60 continue - -c Initialize derivative f2. - - f2 = -theta*f1 - f2_org = f2 - if (col .gt. 0) then - call bmv(m,sy,wt,col,p,v,info) - if (info .ne. 0) return - f2 = f2 - ddot(col2,v,1,p,1) - endif - dtm = -f1/f2 - tsum = zero - nseg = 1 - if (iprint .ge. 99) - + write (6,*) 'There are ',nbreak,' breakpoints ' - -c If there are no breakpoints, locate the GCP and return. - - if (nbreak .eq. 0) goto 888 - - nleft = nbreak - iter = 1 - - - tj = zero - -c------------------- the beginning of the loop ------------------------- - - 777 continue - -c Find the next smallest breakpoint; -c compute dt = t(nleft) - t(nleft + 1). - - tj0 = tj - if (iter .eq. 1) then -c Since we already have the smallest breakpoint we need not do -c heapsort yet. Often only one breakpoint is used and the -c cost of heapsort is avoided. - tj = bkmin - ibp = iorder(ibkmin) - else - if (iter .eq. 2) then -c Replace the already used smallest breakpoint with the -c breakpoint numbered nbreak > nlast, before heapsort call. - if (ibkmin .ne. nbreak) then - t(ibkmin) = t(nbreak) - iorder(ibkmin) = iorder(nbreak) - endif -c Update heap structure of breakpoints -c (if iter=2, initialize heap). - endif - call hpsolb(nleft,t,iorder,iter-2) - tj = t(nleft) - ibp = iorder(nleft) - endif - - dt = tj - tj0 - - if (dt .ne. zero .and. iprint .ge. 100) then - write (6,4011) nseg,f1,f2 - write (6,5010) dt - write (6,6010) dtm - endif - -c If a minimizer is within this interval, locate the GCP and return. - - if (dtm .lt. dt) goto 888 - -c Otherwise fix one variable and -c reset the corresponding component of d to zero. - - tsum = tsum + dt - nleft = nleft - 1 - iter = iter + 1 - dibp = d(ibp) - d(ibp) = zero - if (dibp .gt. zero) then - zibp = u(ibp) - x(ibp) - xcp(ibp) = u(ibp) - iwhere(ibp) = 2 - else - zibp = l(ibp) - x(ibp) - xcp(ibp) = l(ibp) - iwhere(ibp) = 1 - endif - if (iprint .ge. 100) write (6,*) 'Variable ',ibp,' is fixed.' - if (nleft .eq. 0 .and. nbreak .eq. n) then -c all n variables are fixed, -c return with xcp as GCP. - dtm = dt - goto 999 - endif - -c Update the derivative information. - - nseg = nseg + 1 - dibp2 = dibp**2 - -c Update f1 and f2. - -c temporarily set f1 and f2 for col=0. - f1 = f1 + dt*f2 + dibp2 - theta*dibp*zibp - f2 = f2 - theta*dibp2 - - if (col .gt. 0) then -c update c = c + dt*p. - call daxpy(col2,dt,p,1,c,1) - -c choose wbp, -c the row of W corresponding to the breakpoint encountered. - pointr = head - do 70 j = 1,col - wbp(j) = wy(ibp,pointr) - wbp(col + j) = theta*ws(ibp,pointr) - pointr = mod(pointr,m) + 1 - 70 continue - -c compute (wbp)Mc, (wbp)Mp, and (wbp)M(wbp)'. - call bmv(m,sy,wt,col,wbp,v,info) - if (info .ne. 0) return - wmc = ddot(col2,c,1,v,1) - wmp = ddot(col2,p,1,v,1) - wmw = ddot(col2,wbp,1,v,1) - -c update p = p - dibp*wbp. - call daxpy(col2,-dibp,wbp,1,p,1) - -c complete updating f1 and f2 while col > 0. - f1 = f1 + dibp*wmc - f2 = f2 + 2.0d0*dibp*wmp - dibp2*wmw - endif - - f2 = max(epsmch*f2_org,f2) - if (nleft .gt. 0) then - dtm = -f1/f2 - goto 777 -c to repeat the loop for unsearched intervals. - else if(bnded) then - f1 = zero - f2 = zero - dtm = zero - else - dtm = -f1/f2 - endif - -c------------------- the end of the loop ------------------------------- - - 888 continue - if (iprint .ge. 99) then - write (6,*) - write (6,*) 'GCP found in this segment' - write (6,4010) nseg,f1,f2 - write (6,6010) dtm - endif - if (dtm .le. zero) dtm = zero - tsum = tsum + dtm - -c Move free variables (i.e., the ones w/o breakpoints) and -c the variables whose breakpoints haven't been reached. - - call daxpy(n,tsum,d,1,xcp,1) - - 999 continue - -c Update c = c + dtm*p = W'(x^c - x) -c which will be used in computing r = Z'(B(x^c - x) + g). - - if (col .gt. 0) call daxpy(col2,dtm,p,1,c,1) - if (iprint .gt. 100) write (6,1010) (xcp(i),i = 1,n) - if (iprint .ge. 99) write (6,2010) - - 1010 format ('Cauchy X = ',/,(4x,1p,6(1x,d11.4))) - 2010 format (/,'---------------- exit CAUCHY----------------------',/) - 3010 format (/,'---------------- CAUCHY entered-------------------') - 4010 format ('Piece ',i3,' --f1, f2 at start point ',1p,2(1x,d11.4)) - 4011 format (/,'Piece ',i3,' --f1, f2 at start point ', - + 1p,2(1x,d11.4)) - 5010 format ('Distance to the next break point = ',1p,d11.4) - 6010 format ('Distance to the stationary point = ',1p,d11.4) - - return - - end - -c====================== The end of cauchy ============================== - - subroutine cmprlb(n, m, x, g, ws, wy, sy, wt, z, r, wa, index, - + theta, col, head, nfree, cnstnd, info) - - logical cnstnd - integer n, m, col, head, nfree, info, index(n) - double precision theta, - + x(n), g(n), z(n), r(n), wa(4*m), - + ws(n, m), wy(n, m), sy(m, m), wt(m, m) - -c ************ -c -c Subroutine cmprlb -c -c This subroutine computes r=-Z'B(xcp-xk)-Z'g by using -c wa(2m+1)=W'(xcp-x) from subroutine cauchy. -c -c Subprograms called: -c -c L-BFGS-B Library ... bmv. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer i,j,k,pointr - double precision a1,a2 - - if (.not. cnstnd .and. col .gt. 0) then - do 26 i = 1, n - r(i) = -g(i) - 26 continue - else - do 30 i = 1, nfree - k = index(i) - r(i) = -theta*(z(k) - x(k)) - g(k) - 30 continue - call bmv(m,sy,wt,col,wa(2*m+1),wa(1),info) - if (info .ne. 0) then - info = -8 - return - endif - pointr = head - do 34 j = 1, col - a1 = wa(j) - a2 = theta*wa(col + j) - do 32 i = 1, nfree - k = index(i) - r(i) = r(i) + wy(k,pointr)*a1 + ws(k,pointr)*a2 - 32 continue - pointr = mod(pointr,m) + 1 - 34 continue - endif - - return - - end - -c======================= The end of cmprlb ============================= - - subroutine errclb(n, m, factr, l, u, nbd, task, info, k) - - character*60 task - integer n, m, info, k, nbd(n) - double precision factr, l(n), u(n) - -c ************ -c -c Subroutine errclb -c -c This subroutine checks the validity of the input data. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer i - double precision one,zero - parameter (one=1.0d0,zero=0.0d0) - -c Check the input arguments for errors. - - if (n .le. 0) task = 'ERROR: N .LE. 0' - if (m .le. 0) task = 'ERROR: M .LE. 0' - if (factr .lt. zero) task = 'ERROR: FACTR .LT. 0' - -c Check the validity of the arrays nbd(i), u(i), and l(i). - - do 10 i = 1, n - if (nbd(i) .lt. 0 .or. nbd(i) .gt. 3) then -c return - task = 'ERROR: INVALID NBD' - info = -6 - k = i - endif - if (nbd(i) .eq. 2) then - if (l(i) .gt. u(i)) then -c return - task = 'ERROR: NO FEASIBLE SOLUTION' - info = -7 - k = i - endif - endif - 10 continue - - return - - end - -c======================= The end of errclb ============================= - - subroutine formk(n, nsub, ind, nenter, ileave, indx2, iupdat, - + updatd, wn, wn1, m, ws, wy, sy, theta, col, - + head, info) - - integer n, nsub, m, col, head, nenter, ileave, iupdat, - + info, ind(n), indx2(n) - double precision theta, wn(2*m, 2*m), wn1(2*m, 2*m), - + ws(n, m), wy(n, m), sy(m, m) - logical updatd - -c ************ -c -c Subroutine formk -c -c This subroutine forms the LEL^T factorization of the indefinite -c -c matrix K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] -c [L_a -R_z theta*S'AA'S ] -c where E = [-I 0] -c [ 0 I] -c The matrix K can be shown to be equal to the matrix M^[-1]N -c occurring in section 5.1 of [1], as well as to the matrix -c Mbar^[-1] Nbar in section 5.3. -c -c n is an integer variable. -c On entry n is the dimension of the problem. -c On exit n is unchanged. -c -c nsub is an integer variable -c On entry nsub is the number of subspace variables in free set. -c On exit nsub is not changed. -c -c ind is an integer array of dimension nsub. -c On entry ind specifies the indices of subspace variables. -c On exit ind is unchanged. -c -c nenter is an integer variable. -c On entry nenter is the number of variables entering the -c free set. -c On exit nenter is unchanged. -c -c ileave is an integer variable. -c On entry indx2(ileave),...,indx2(n) are the variables leaving -c the free set. -c On exit ileave is unchanged. -c -c indx2 is an integer array of dimension n. -c On entry indx2(1),...,indx2(nenter) are the variables entering -c the free set, while indx2(ileave),...,indx2(n) are the -c variables leaving the free set. -c On exit indx2 is unchanged. -c -c iupdat is an integer variable. -c On entry iupdat is the total number of BFGS updates made so far. -c On exit iupdat is unchanged. -c -c updatd is a logical variable. -c On entry 'updatd' is true if the L-BFGS matrix is updatd. -c On exit 'updatd' is unchanged. -c -c wn is a double precision array of dimension 2m x 2m. -c On entry wn is unspecified. -c On exit the upper triangle of wn stores the LEL^T factorization -c of the 2*col x 2*col indefinite matrix -c [-D -Y'ZZ'Y/theta L_a'-R_z' ] -c [L_a -R_z theta*S'AA'S ] -c -c wn1 is a double precision array of dimension 2m x 2m. -c On entry wn1 stores the lower triangular part of -c [Y' ZZ'Y L_a'+R_z'] -c [L_a+R_z S'AA'S ] -c in the previous iteration. -c On exit wn1 stores the corresponding updated matrices. -c The purpose of wn1 is just to store these inner products -c so they can be easily updated and inserted into wn. -c -c m is an integer variable. -c On entry m is the maximum number of variable metric corrections -c used to define the limited memory matrix. -c On exit m is unchanged. -c -c ws, wy, sy, and wtyy are double precision arrays; -c theta is a double precision variable; -c col is an integer variable; -c head is an integer variable. -c On entry they store the information defining the -c limited memory BFGS matrix: -c ws(n,m) stores S, a set of s-vectors; -c wy(n,m) stores Y, a set of y-vectors; -c sy(m,m) stores S'Y; -c wtyy(m,m) stores the Cholesky factorization -c of (theta*S'S+LD^(-1)L') -c theta is the scaling factor specifying B_0 = theta I; -c col is the number of variable metric corrections stored; -c head is the location of the 1st s- (or y-) vector in S (or Y). -c On exit they are unchanged. -c -c info is an integer variable. -c On entry info is unspecified. -c On exit info = 0 for normal return; -c = -1 when the 1st Cholesky factorization failed; -c = -2 when the 2st Cholesky factorization failed. -c -c Subprograms called: -c -c Linpack ... dcopy, dpofa, dtrsl. -c -c -c References: -c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited -c memory algorithm for bound constrained optimization'', -c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. -c -c [2] C. Zhu, R.H. Byrd, P. Lu, J. Nocedal, ``L-BFGS-B: a -c limited memory FORTRAN code for solving bound constrained -c optimization problems'', Tech. Report, NAM-11, EECS Department, -c Northwestern University, 1994. -c -c (Postscript files of these papers are available via anonymous -c ftp to eecs.nwu.edu in the directory pub/lbfgs/lbfgs_bcm.) -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer m2,ipntr,jpntr,iy,is,jy,js,is1,js1,k1,i,k, - + col2,pbegin,pend,dbegin,dend,upcl - double precision ddot,temp1,temp2,temp3,temp4 - double precision one,zero - parameter (one=1.0d0,zero=0.0d0) - -c Form the lower triangular part of -c WN1 = [Y' ZZ'Y L_a'+R_z'] -c [L_a+R_z S'AA'S ] -c where L_a is the strictly lower triangular part of S'AA'Y -c R_z is the upper triangular part of S'ZZ'Y. - - if (updatd) then - if (iupdat .gt. m) then -c shift old part of WN1. - do 10 jy = 1, m - 1 - js = m + jy - call dcopy(m-jy,wn1(jy+1,jy+1),1,wn1(jy,jy),1) - call dcopy(m-jy,wn1(js+1,js+1),1,wn1(js,js),1) - call dcopy(m-1,wn1(m+2,jy+1),1,wn1(m+1,jy),1) - 10 continue - endif - -c put new rows in blocks (1,1), (2,1) and (2,2). - pbegin = 1 - pend = nsub - dbegin = nsub + 1 - dend = n - iy = col - is = m + col - ipntr = head + col - 1 - if (ipntr .gt. m) ipntr = ipntr - m - jpntr = head - do 20 jy = 1, col - js = m + jy - temp1 = zero - temp2 = zero - temp3 = zero -c compute element jy of row 'col' of Y'ZZ'Y - do 15 k = pbegin, pend - k1 = ind(k) - temp1 = temp1 + wy(k1,ipntr)*wy(k1,jpntr) - 15 continue -c compute elements jy of row 'col' of L_a and S'AA'S - do 16 k = dbegin, dend - k1 = ind(k) - temp2 = temp2 + ws(k1,ipntr)*ws(k1,jpntr) - temp3 = temp3 + ws(k1,ipntr)*wy(k1,jpntr) - 16 continue - wn1(iy,jy) = temp1 - wn1(is,js) = temp2 - wn1(is,jy) = temp3 - jpntr = mod(jpntr,m) + 1 - 20 continue - -c put new column in block (2,1). - jy = col - jpntr = head + col - 1 - if (jpntr .gt. m) jpntr = jpntr - m - ipntr = head - do 30 i = 1, col - is = m + i - temp3 = zero -c compute element i of column 'col' of R_z - do 25 k = pbegin, pend - k1 = ind(k) - temp3 = temp3 + ws(k1,ipntr)*wy(k1,jpntr) - 25 continue - ipntr = mod(ipntr,m) + 1 - wn1(is,jy) = temp3 - 30 continue - upcl = col - 1 - else - upcl = col - endif - -c modify the old parts in blocks (1,1) and (2,2) due to changes -c in the set of free variables. - ipntr = head - do 45 iy = 1, upcl - is = m + iy - jpntr = head - do 40 jy = 1, iy - js = m + jy - temp1 = zero - temp2 = zero - temp3 = zero - temp4 = zero - do 35 k = 1, nenter - k1 = indx2(k) - temp1 = temp1 + wy(k1,ipntr)*wy(k1,jpntr) - temp2 = temp2 + ws(k1,ipntr)*ws(k1,jpntr) - 35 continue - do 36 k = ileave, n - k1 = indx2(k) - temp3 = temp3 + wy(k1,ipntr)*wy(k1,jpntr) - temp4 = temp4 + ws(k1,ipntr)*ws(k1,jpntr) - 36 continue - wn1(iy,jy) = wn1(iy,jy) + temp1 - temp3 - wn1(is,js) = wn1(is,js) - temp2 + temp4 - jpntr = mod(jpntr,m) + 1 - 40 continue - ipntr = mod(ipntr,m) + 1 - 45 continue - -c modify the old parts in block (2,1). - ipntr = head - do 60 is = m + 1, m + upcl - jpntr = head - do 55 jy = 1, upcl - temp1 = zero - temp3 = zero - do 50 k = 1, nenter - k1 = indx2(k) - temp1 = temp1 + ws(k1,ipntr)*wy(k1,jpntr) - 50 continue - do 51 k = ileave, n - k1 = indx2(k) - temp3 = temp3 + ws(k1,ipntr)*wy(k1,jpntr) - 51 continue - if (is .le. jy + m) then - wn1(is,jy) = wn1(is,jy) + temp1 - temp3 - else - wn1(is,jy) = wn1(is,jy) - temp1 + temp3 - endif - jpntr = mod(jpntr,m) + 1 - 55 continue - ipntr = mod(ipntr,m) + 1 - 60 continue - -c Form the upper triangle of WN = [D+Y' ZZ'Y/theta -L_a'+R_z' ] -c [-L_a +R_z S'AA'S*theta] - - m2 = 2*m - do 70 iy = 1, col - is = col + iy - is1 = m + iy - do 65 jy = 1, iy - js = col + jy - js1 = m + jy - wn(jy,iy) = wn1(iy,jy)/theta - wn(js,is) = wn1(is1,js1)*theta - 65 continue - do 66 jy = 1, iy - 1 - wn(jy,is) = -wn1(is1,jy) - 66 continue - do 67 jy = iy, col - wn(jy,is) = wn1(is1,jy) - 67 continue - wn(iy,iy) = wn(iy,iy) + sy(iy,iy) - 70 continue - -c Form the upper triangle of WN= [ LL' L^-1(-L_a'+R_z')] -c [(-L_a +R_z)L'^-1 S'AA'S*theta ] - -c first Cholesky factor (1,1) block of wn to get LL' -c with L' stored in the upper triangle of wn. - call dpofa(wn,m2,col,info) - if (info .ne. 0) then - info = -1 - return - endif -c then form L^-1(-L_a'+R_z') in the (1,2) block. - col2 = 2*col - do 71 js = col+1 ,col2 - call dtrsl(wn,m2,col,wn(1,js),11,info) - 71 continue - -c Form S'AA'S*theta + (L^-1(-L_a'+R_z'))'L^-1(-L_a'+R_z') in the -c upper triangle of (2,2) block of wn. - - - do 72 is = col+1, col2 - do 74 js = is, col2 - wn(is,js) = wn(is,js) + ddot(col,wn(1,is),1,wn(1,js),1) - 74 continue - 72 continue - -c Cholesky factorization of (2,2) block of wn. - - call dpofa(wn(col+1,col+1),m2,col,info) - if (info .ne. 0) then - info = -2 - return - endif - - return - - end - -c======================= The end of formk ============================== - - subroutine formt(m, wt, sy, ss, col, theta, info) - - integer m, col, info - double precision theta, wt(m, m), sy(m, m), ss(m, m) - -c ************ -c -c Subroutine formt -c -c This subroutine forms the upper half of the pos. def. and symm. -c T = theta*SS + L*D^(-1)*L', stores T in the upper triangle -c of the array wt, and performs the Cholesky factorization of T -c to produce J*J', with J' stored in the upper triangle of wt. -c -c Subprograms called: -c -c Linpack ... dpofa. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer i,j,k,k1 - double precision ddum - double precision zero - parameter (zero=0.0d0) - - -c Form the upper half of T = theta*SS + L*D^(-1)*L', -c store T in the upper triangle of the array wt. - - do 52 j = 1, col - wt(1,j) = theta*ss(1,j) - 52 continue - do 55 i = 2, col - do 54 j = i, col - k1 = min(i,j) - 1 - ddum = zero - do 53 k = 1, k1 - ddum = ddum + sy(i,k)*sy(j,k)/sy(k,k) - 53 continue - wt(i,j) = ddum + theta*ss(i,j) - 54 continue - 55 continue - -c Cholesky factorize T to J*J' with -c J' stored in the upper triangle of wt. - - call dpofa(wt,m,col,info) - if (info .ne. 0) then - info = -3 - endif - - return - - end - -c======================= The end of formt ============================== - - subroutine freev(n, nfree, index, nenter, ileave, indx2, - + iwhere, wrk, updatd, cnstnd, iprint, iter) - - integer n, nfree, nenter, ileave, iprint, iter, - + index(n), indx2(n), iwhere(n) - logical wrk, updatd, cnstnd - -c ************ -c -c Subroutine freev -c -c This subroutine counts the entering and leaving variables when -c iter > 0, and finds the index set of free and active variables -c at the GCP. -c -c cnstnd is a logical variable indicating whether bounds are present -c -c index is an integer array of dimension n -c for i=1,...,nfree, index(i) are the indices of free variables -c for i=nfree+1,...,n, index(i) are the indices of bound variables -c On entry after the first iteration, index gives -c the free variables at the previous iteration. -c On exit it gives the free variables based on the determination -c in cauchy using the array iwhere. -c -c indx2 is an integer array of dimension n -c On entry indx2 is unspecified. -c On exit with iter>0, indx2 indicates which variables -c have changed status since the previous iteration. -c For i= 1,...,nenter, indx2(i) have changed from bound to free. -c For i= ileave+1,...,n, indx2(i) have changed from free to bound. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer iact,i,k - - nenter = 0 - ileave = n + 1 - if (iter .gt. 0 .and. cnstnd) then -c count the entering and leaving variables. - do 20 i = 1, nfree - k = index(i) - -c write(6,*) ' k = index(i) ', k -c write(6,*) ' index = ', i - - if (iwhere(k) .gt. 0) then - ileave = ileave - 1 - indx2(ileave) = k - if (iprint .ge. 100) write (6,*) - + 'Variable ',k,' leaves the set of free variables' - endif - 20 continue - do 22 i = 1 + nfree, n - k = index(i) - if (iwhere(k) .le. 0) then - nenter = nenter + 1 - indx2(nenter) = k - if (iprint .ge. 100) write (6,*) - + 'Variable ',k,' enters the set of free variables' - endif - 22 continue - if (iprint .ge. 99) write (6,*) - + n+1-ileave,' variables leave; ',nenter,' variables enter' - endif - wrk = (ileave .lt. n+1) .or. (nenter .gt. 0) .or. updatd - -c Find the index set of free and active variables at the GCP. - - nfree = 0 - iact = n + 1 - do 24 i = 1, n - if (iwhere(i) .le. 0) then - nfree = nfree + 1 - index(nfree) = i - else - iact = iact - 1 - index(iact) = i - endif - 24 continue - if (iprint .ge. 99) write (6,*) - + nfree,' variables are free at GCP ',iter + 1 - - return - - end - -c======================= The end of freev ============================== - - subroutine hpsolb(n, t, iorder, iheap) - integer iheap, n, iorder(n) - double precision t(n) - -c ************ -c -c Subroutine hpsolb -c -c This subroutine sorts out the least element of t, and puts the -c remaining elements of t in a heap. -c -c n is an integer variable. -c On entry n is the dimension of the arrays t and iorder. -c On exit n is unchanged. -c -c t is a double precision array of dimension n. -c On entry t stores the elements to be sorted, -c On exit t(n) stores the least elements of t, and t(1) to t(n-1) -c stores the remaining elements in the form of a heap. -c -c iorder is an integer array of dimension n. -c On entry iorder(i) is the index of t(i). -c On exit iorder(i) is still the index of t(i), but iorder may be -c permuted in accordance with t. -c -c iheap is an integer variable specifying the task. -c On entry iheap should be set as follows: -c iheap .eq. 0 if t(1) to t(n) is not in the form of a heap, -c iheap .ne. 0 if otherwise. -c On exit iheap is unchanged. -c -c -c References: -c Algorithm 232 of CACM (J. W. J. Williams): HEAPSORT. -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c ************ - - integer i,j,k,indxin,indxou - double precision ddum,out - - if (iheap .eq. 0) then - -c Rearrange the elements t(1) to t(n) to form a heap. - - do 20 k = 2, n - ddum = t(k) - indxin = iorder(k) - -c Add ddum to the heap. - i = k - 10 continue - if (i.gt.1) then - j = i/2 - if (ddum .lt. t(j)) then - t(i) = t(j) - iorder(i) = iorder(j) - i = j - goto 10 - endif - endif - t(i) = ddum - iorder(i) = indxin - 20 continue - endif - -c Assign to 'out' the value of t(1), the least member of the heap, -c and rearrange the remaining members to form a heap as -c elements 1 to n-1 of t. - - if (n .gt. 1) then - i = 1 - out = t(1) - indxou = iorder(1) - ddum = t(n) - indxin = iorder(n) - -c Restore the heap - 30 continue - j = i+i - if (j .le. n-1) then - if (t(j+1) .lt. t(j)) j = j+1 - if (t(j) .lt. ddum ) then - t(i) = t(j) - iorder(i) = iorder(j) - i = j - goto 30 - endif - endif - t(i) = ddum - iorder(i) = indxin - -c Put the least member in t(n). - - t(n) = out - iorder(n) = indxou - endif - - return - - end - -c====================== The end of hpsolb ============================== - - subroutine lnsrlb(n, l, u, nbd, x, f, fold, gd, gdold, g, d, r, t, - + z, stp, dnorm, dtd, xstep, stpmx, iter, ifun, - + iback, nfgv, info, task, boxed, cnstnd, csave, - + isave, dsave) - - character*60 task, csave - logical boxed, cnstnd - integer n, iter, ifun, iback, nfgv, info, - + nbd(n), isave(2) - double precision f, fold, gd, gdold, stp, dnorm, dtd, xstep, - + stpmx, x(n), l(n), u(n), g(n), d(n), r(n), t(n), - + z(n), dsave(13) -c ********** -c -c Subroutine lnsrlb -c -c This subroutine calls subroutine dcsrch from the Minpack2 library -c to perform the line search. Subroutine dscrch is safeguarded so -c that all trial points lie within the feasible region. -c -c Subprograms called: -c -c Minpack2 Library ... dcsrch. -c -c Linpack ... dtrsl, ddot. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ********** - - integer i - double precision ddot,a1,a2 - double precision one,zero,big - parameter (one=1.0d0,zero=0.0d0,big=1.0d+10) - double precision ftol,gtol,xtol - parameter (ftol=1.0d-3,gtol=0.9d0,xtol=0.1d0) - - if (task(1:5) .eq. 'FG_LN') goto 556 - - dtd = ddot(n,d,1,d,1) - dnorm = sqrt(dtd) - -c Determine the maximum step length. - - stpmx = big - if (cnstnd) then - if (iter .eq. 0) then - stpmx = one - else - do 43 i = 1, n - a1 = d(i) - if (nbd(i) .ne. 0) then - if (a1 .lt. zero .and. nbd(i) .le. 2) then - a2 = l(i) - x(i) - if (a2 .ge. zero) then - stpmx = zero - else if (a1*stpmx .lt. a2) then - stpmx = a2/a1 - endif - else if (a1 .gt. zero .and. nbd(i) .ge. 2) then - a2 = u(i) - x(i) - if (a2 .le. zero) then - stpmx = zero - else if (a1*stpmx .gt. a2) then - stpmx = a2/a1 - endif - endif - endif - 43 continue - endif - endif - - if (iter .eq. 0 .and. .not. boxed) then - stp = min(one/dnorm, stpmx) - else - stp = one - endif - - call dcopy(n,x,1,t,1) - call dcopy(n,g,1,r,1) - fold = f - ifun = 0 - iback = 0 - csave = 'START' - 556 continue - gd = ddot(n,g,1,d,1) - if (ifun .eq. 0) then - gdold=gd - if (gd .ge. zero) then -c the directional derivative >=0. -c Line search is impossible. - write(6,*)' ascent direction in projection gd = ', gd - info = -4 - return - endif - endif - - call dcsrch(f,gd,stp,ftol,gtol,xtol,zero,stpmx,csave,isave,dsave) - - xstep = stp*dnorm - if (csave(1:4) .ne. 'CONV' .and. csave(1:4) .ne. 'WARN') then - task = 'FG_LNSRCH' - ifun = ifun + 1 - nfgv = nfgv + 1 - iback = ifun - 1 - if (stp .eq. one) then - call dcopy(n,z,1,x,1) - else - do 41 i = 1, n - x(i) = stp*d(i) + t(i) - 41 continue - endif - else - task = 'NEW_X' - endif - - return - - end - -c======================= The end of lnsrlb ============================= - - subroutine matupd(n, m, ws, wy, sy, ss, d, r, itail, - + iupdat, col, head, theta, rr, dr, stp, dtd) - - integer n, m, itail, iupdat, col, head - double precision theta, rr, dr, stp, dtd, d(n), r(n), - + ws(n, m), wy(n, m), sy(m, m), ss(m, m) - -c ************ -c -c Subroutine matupd -c -c This subroutine updates matrices WS and WY, and forms the -c middle matrix in B. -c -c Subprograms called: -c -c Linpack ... dcopy, ddot. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer j,pointr - double precision ddot - double precision one - parameter (one=1.0d0) - -c Set pointers for matrices WS and WY. - - if (iupdat .le. m) then - col = iupdat - itail = mod(head+iupdat-2,m) + 1 - else - itail = mod(itail,m) + 1 - head = mod(head,m) + 1 - endif - -c Update matrices WS and WY. - - call dcopy(n,d,1,ws(1,itail),1) - call dcopy(n,r,1,wy(1,itail),1) - -c Set theta=yy/ys. - - theta = rr/dr - -c Form the middle matrix in B. - -c update the upper triangle of SS, -c and the lower triangle of SY: - if (iupdat .gt. m) then -c move old information - do 50 j = 1, col - 1 - call dcopy(j,ss(2,j+1),1,ss(1,j),1) - call dcopy(col-j,sy(j+1,j+1),1,sy(j,j),1) - 50 continue - endif -c add new information: the last row of SY -c and the last column of SS: - pointr = head - do 51 j = 1, col - 1 - sy(col,j) = ddot(n,d,1,wy(1,pointr),1) - ss(j,col) = ddot(n,ws(1,pointr),1,d,1) - pointr = mod(pointr,m) + 1 - 51 continue - if (stp .eq. one) then - ss(col,col) = dtd - else - ss(col,col) = stp*stp*dtd - endif - sy(col,col) = dr - - return - - end - -c======================= The end of matupd ============================= - - subroutine prn1lb(n, m, l, u, x, iprint, itfile, epsmch) - - integer n, m, iprint, itfile - double precision epsmch, x(n), l(n), u(n) - -c ************ -c -c Subroutine prn1lb -c -c This subroutine prints the input data, initial point, upper and -c lower bounds of each variable, machine precision, as well as -c the headings of the output. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer i - - if (iprint .ge. 0) then - write (6,7001) epsmch - write (6,*) 'N = ',n,' M = ',m - if (iprint .ge. 1) then - write (itfile,2001) epsmch - write (itfile,*)'N = ',n,' M = ',m - write (itfile,9001) - if (iprint .gt. 100) then - write (6,1004) 'L =',(l(i),i = 1,n) - write (6,1004) 'X0 =',(x(i),i = 1,n) - write (6,1004) 'U =',(u(i),i = 1,n) - endif - endif - endif - - 1004 format (/,a4, 1p, 6(1x,d11.4),/,(4x,1p,6(1x,d11.4))) - 2001 format ('RUNNING THE L-BFGS-B CODE',/,/, - + 'it = iteration number',/, - + 'nf = number of function evaluations',/, - + 'nseg = number of segments explored during the Cauchy search',/, - + 'nact = number of active bounds at the generalized Cauchy point' - + ,/, - + 'sub = manner in which the subspace minimization terminated:' - + ,/,' con = converged, bnd = a bound was reached',/, - + 'itls = number of iterations performed in the line search',/, - + 'stepl = step length used',/, - + 'tstep = norm of the displacement (total step)',/, - + 'projg = norm of the projected gradient',/, - + 'f = function value',/,/, - + ' * * *',/,/, - + 'Machine precision =',1p,d10.3) - 7001 format ('RUNNING THE L-BFGS-B CODE',/,/, - + ' * * *',/,/, - + 'Machine precision =',1p,d10.3) - 9001 format (/,3x,'it',3x,'nf',2x,'nseg',2x,'nact',2x,'sub',2x,'itls', - + 2x,'stepl',4x,'tstep',5x,'projg',8x,'f') - - return - - end - -c======================= The end of prn1lb ============================= - - subroutine prn2lb(n, x, f, g, iprint, itfile, iter, nfgv, nact, - + sbgnrm, nseg, word, iword, iback, stp, xstep) - - character*3 word - integer n, iprint, itfile, iter, nfgv, nact, nseg, - + iword, iback - double precision f, sbgnrm, stp, xstep, x(n), g(n) - -c ************ -c -c Subroutine prn2lb -c -c This subroutine prints out new information after a successful -c line search. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer i,imod - -c 'word' records the status of subspace solutions. - if (iword .eq. 0) then -c the subspace minimization converged. - word = 'con' - else if (iword .eq. 1) then -c the subspace minimization stopped at a bound. - word = 'bnd' - else if (iword .eq. 5) then -c the truncated Newton step has been used. - word = 'TNT' - else - word = '---' - endif - if (iprint .ge. 99) then - write (6,*) 'LINE SEARCH',iback,' times; norm of step = ',xstep - write (6,2001) iter,f,sbgnrm - if (iprint .gt. 100) then - write (6,1004) 'X =',(x(i), i = 1, n) - write (6,1004) 'G =',(g(i), i = 1, n) - endif - else if (iprint .gt. 0) then - imod = mod(iter,iprint) - if (imod .eq. 0) write (6,2001) iter,f,sbgnrm - endif - if (iprint .ge. 1) write (itfile,3001) - + iter,nfgv,nseg,nact,word,iback,stp,xstep,sbgnrm,f - - 1004 format (/,a4, 1p, 6(1x,d11.4),/,(4x,1p,6(1x,d11.4))) - 2001 format - + (/,'At iterate',i5,4x,'f= ',1p,d12.5,4x,'|proj g|= ',1p,d12.5) - 3001 format(2(1x,i4),2(1x,i5),2x,a3,1x,i4,1p,2(2x,d7.1),1p,2(1x,d10.3)) - - return - - end - -c======================= The end of prn2lb ============================= - - subroutine prn3lb(n, x, f, task, iprint, info, itfile, - + iter, nfgv, nintol, nskip, nact, sbgnrm, - + time, nseg, word, iback, stp, xstep, k, - + cachyt, sbtime, lnscht) - - character*60 task - character*3 word - integer n, iprint, info, itfile, iter, nfgv, nintol, - + nskip, nact, nseg, iback, k - double precision f, sbgnrm, time, stp, xstep, cachyt, sbtime, - + lnscht, x(n) - -c ************ -c -c Subroutine prn3lb -c -c This subroutine prints out information when either a built-in -c convergence test is satisfied or when an error message is -c generated. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer i - - if (task(1:5) .eq. 'ERROR') goto 999 - - if (iprint .ge. 0) then - write (6,3003) - write (6,3004) - write(6,3005) n,iter,nfgv,nintol,nskip,nact,sbgnrm,f - if (iprint .ge. 100) then - write (6,1004) 'X =',(x(i),i = 1,n) - endif - if (iprint .ge. 1) write (6,*) ' F =',f - endif - 999 continue - if (iprint .ge. 0) then - write (6,3009) task - if (info .ne. 0) then - if (info .eq. -1) write (6,9011) - if (info .eq. -2) write (6,9012) - if (info .eq. -3) write (6,9013) - if (info .eq. -4) write (6,9014) - if (info .eq. -5) write (6,9015) - if (info .eq. -6) write (6,*)' Input nbd(',k,') is invalid.' - if (info .eq. -7) - + write (6,*)' l(',k,') > u(',k,'). No feasible solution.' - if (info .eq. -8) write (6,9018) - if (info .eq. -9) write (6,9019) - endif - if (iprint .ge. 1) write (6,3007) cachyt,sbtime,lnscht - write (6,3008) time - if (iprint .ge. 1) then - if (info .eq. -4 .or. info .eq. -9) then - write (itfile,3002) - + iter,nfgv,nseg,nact,word,iback,stp,xstep - endif - write (itfile,3009) task - if (info .ne. 0) then - if (info .eq. -1) write (itfile,9011) - if (info .eq. -2) write (itfile,9012) - if (info .eq. -3) write (itfile,9013) - if (info .eq. -4) write (itfile,9014) - if (info .eq. -5) write (itfile,9015) - if (info .eq. -8) write (itfile,9018) - if (info .eq. -9) write (itfile,9019) - endif - write (itfile,3008) time - endif - endif - - 1004 format (/,a4, 1p, 6(1x,d11.4),/,(4x,1p,6(1x,d11.4))) - 3002 format(2(1x,i4),2(1x,i5),2x,a3,1x,i4,1p,2(2x,d7.1),6x,'-',10x,'-') - 3003 format (/, - + ' * * *',/,/, - + 'Tit = total number of iterations',/, - + 'Tnf = total number of function evaluations',/, - + 'Tnint = total number of segments explored during', - + ' Cauchy searches',/, - + 'Skip = number of BFGS updates skipped',/, - + 'Nact = number of active bounds at final generalized', - + ' Cauchy point',/, - + 'Projg = norm of the final projected gradient',/, - + 'F = final function value',/,/, - + ' * * *') - 3004 format (/,3x,'N',4x,'Tit',5x,'Tnf',2x,'Tnint',2x, - + 'Skip',2x,'Nact',5x,'Projg',8x,'F') - 3005 format (i5,2(1x,i6),(1x,i6),(2x,i4),(1x,i5),1p,2(2x,d10.3)) - 3007 format (/,' Cauchy time',1p,e10.3,' seconds.',/ - + ' Subspace minimization time',1p,e10.3,' seconds.',/ - + ' Line search time',1p,e10.3,' seconds.') - 3008 format (/,' Total User time',1p,e10.3,' seconds.',/) - 3009 format (/,a60) - 9011 format (/, - +' Matrix in 1st Cholesky factorization in formk is not Pos. Def.') - 9012 format (/, - +' Matrix in 2st Cholesky factorization in formk is not Pos. Def.') - 9013 format (/, - +' Matrix in the Cholesky factorization in formt is not Pos. Def.') - 9014 format (/, - +' Derivative >= 0, backtracking line search impossible.',/, - +' Previous x, f and g restored.',/, - +' Possible causes: 1 error in function or gradient evaluation;',/, - +' 2 rounding errors dominate computation.') - 9015 format (/, - +' Warning: more than 10 function and gradient',/, - +' evaluations in the last line search. Termination',/, - +' may possibly be caused by a bad search direction.') - 9018 format (/,' The triangular system is singular.') - 9019 format (/, - +' Line search cannot locate an adequate point after 20 function',/ - +,' and gradient evaluations. Previous x, f and g restored.',/, - +' Possible causes: 1 error in function or gradient evaluation;',/, - +' 2 rounding error dominate computation.') - - return - - end - -c======================= The end of prn3lb ============================= - - subroutine projgr(n, l, u, nbd, x, g, sbgnrm) - - integer n, nbd(n) - double precision sbgnrm, x(n), l(n), u(n), g(n) - -c ************ -c -c Subroutine projgr -c -c This subroutine computes the infinity norm of the projected -c gradient. -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer i - double precision gi - double precision one,zero - parameter (one=1.0d0,zero=0.0d0) - - sbgnrm = zero - do 15 i = 1, n - gi = g(i) - if (nbd(i) .ne. 0) then - if (gi .lt. zero) then - if (nbd(i) .ge. 2) gi = max((x(i)-u(i)),gi) - else - if (nbd(i) .le. 2) gi = min((x(i)-l(i)),gi) - endif - endif - sbgnrm = max(sbgnrm,abs(gi)) - 15 continue - - return - - end - -c======================= The end of projgr ============================= - - subroutine subsm ( n, m, nsub, ind, l, u, nbd, x, d, xp, ws, wy, - + theta, xx, gg, - + col, head, iword, wv, wn, iprint, info ) - implicit none - integer n, m, nsub, col, head, iword, iprint, info, - + ind(nsub), nbd(n) - double precision theta, - + l(n), u(n), x(n), d(n), xp(n), xx(n), gg(n), - + ws(n, m), wy(n, m), - + wv(2*m), wn(2*m, 2*m) - -c ********************************************************************** -c -c This routine contains the major changes in the updated version. -c The changes are described in the accompanying paper -c -c Jose Luis Morales, Jorge Nocedal -c "Remark On Algorithm 788: L-BFGS-B: Fortran Subroutines for Large-Scale -c Bound Constrained Optimization". Decemmber 27, 2010. -c -c J.L. Morales Departamento de Matematicas, -c Instituto Tecnologico Autonomo de Mexico -c Mexico D.F. -c -c J, Nocedal Department of Electrical Engineering and -c Computer Science. -c Northwestern University. Evanston, IL. USA -c -c January 17, 2011 -c -c ********************************************************************** -c -c -c Subroutine subsm -c -c Given xcp, l, u, r, an index set that specifies -c the active set at xcp, and an l-BFGS matrix B -c (in terms of WY, WS, SY, WT, head, col, and theta), -c this subroutine computes an approximate solution -c of the subspace problem -c -c (P) min Q(x) = r'(x-xcp) + 1/2 (x-xcp)' B (x-xcp) -c -c subject to l<=x<=u -c x_i=xcp_i for all i in A(xcp) -c -c along the subspace unconstrained Newton direction -c -c d = -(Z'BZ)^(-1) r. -c -c The formula for the Newton direction, given the L-BFGS matrix -c and the Sherman-Morrison formula, is -c -c d = (1/theta)r + (1/theta*2) Z'WK^(-1)W'Z r. -c -c where -c K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] -c [L_a -R_z theta*S'AA'S ] -c -c Note that this procedure for computing d differs -c from that described in [1]. One can show that the matrix K is -c equal to the matrix M^[-1]N in that paper. -c -c n is an integer variable. -c On entry n is the dimension of the problem. -c On exit n is unchanged. -c -c m is an integer variable. -c On entry m is the maximum number of variable metric corrections -c used to define the limited memory matrix. -c On exit m is unchanged. -c -c nsub is an integer variable. -c On entry nsub is the number of free variables. -c On exit nsub is unchanged. -c -c ind is an integer array of dimension nsub. -c On entry ind specifies the coordinate indices of free variables. -c On exit ind is unchanged. -c -c l is a double precision array of dimension n. -c On entry l is the lower bound of x. -c On exit l is unchanged. -c -c u is a double precision array of dimension n. -c On entry u is the upper bound of x. -c On exit u is unchanged. -c -c nbd is a integer array of dimension n. -c On entry nbd represents the type of bounds imposed on the -c variables, and must be specified as follows: -c nbd(i)=0 if x(i) is unbounded, -c 1 if x(i) has only a lower bound, -c 2 if x(i) has both lower and upper bounds, and -c 3 if x(i) has only an upper bound. -c On exit nbd is unchanged. -c -c x is a double precision array of dimension n. -c On entry x specifies the Cauchy point xcp. -c On exit x(i) is the minimizer of Q over the subspace of -c free variables. -c -c d is a double precision array of dimension n. -c On entry d is the reduced gradient of Q at xcp. -c On exit d is the Newton direction of Q. -c -c xp is a double precision array of dimension n. -c used to safeguard the projected Newton direction -c -c xx is a double precision array of dimension n -c On entry it holds the current iterate -c On output it is unchanged - -c gg is a double precision array of dimension n -c On entry it holds the gradient at the current iterate -c On output it is unchanged -c -c ws and wy are double precision arrays; -c theta is a double precision variable; -c col is an integer variable; -c head is an integer variable. -c On entry they store the information defining the -c limited memory BFGS matrix: -c ws(n,m) stores S, a set of s-vectors; -c wy(n,m) stores Y, a set of y-vectors; -c theta is the scaling factor specifying B_0 = theta I; -c col is the number of variable metric corrections stored; -c head is the location of the 1st s- (or y-) vector in S (or Y). -c On exit they are unchanged. -c -c iword is an integer variable. -c On entry iword is unspecified. -c On exit iword specifies the status of the subspace solution. -c iword = 0 if the solution is in the box, -c 1 if some bound is encountered. -c -c wv is a double precision working array of dimension 2m. -c -c wn is a double precision array of dimension 2m x 2m. -c On entry the upper triangle of wn stores the LEL^T factorization -c of the indefinite matrix -c -c K = [-D -Y'ZZ'Y/theta L_a'-R_z' ] -c [L_a -R_z theta*S'AA'S ] -c where E = [-I 0] -c [ 0 I] -c On exit wn is unchanged. -c -c iprint is an INTEGER variable that must be set by the user. -c It controls the frequency and type of output generated: -c iprint<0 no output is generated; -c iprint=0 print only one line at the last iteration; -c 0<iprint<99 print also f and |proj g| every iprint iterations; -c iprint=99 print details of every iteration except n-vectors; -c iprint=100 print also the changes of active set and final x; -c iprint>100 print details of every iteration including x and g; -c When iprint > 0, the file iterate.dat will be created to -c summarize the iteration. -c -c info is an integer variable. -c On entry info is unspecified. -c On exit info = 0 for normal return, -c = nonzero for abnormal return -c when the matrix K is ill-conditioned. -c -c Subprograms called: -c -c Linpack dtrsl. -c -c -c References: -c -c [1] R. H. Byrd, P. Lu, J. Nocedal and C. Zhu, ``A limited -c memory algorithm for bound constrained optimization'', -c SIAM J. Scientific Computing 16 (1995), no. 5, pp. 1190--1208. -c -c -c -c * * * -c -c NEOS, November 1994. (Latest revision June 1996.) -c Optimization Technology Center. -c Argonne National Laboratory and Northwestern University. -c Written by -c Ciyou Zhu -c in collaboration with R.H. Byrd, P. Lu-Chen and J. Nocedal. -c -c -c ************ - - integer pointr,m2,col2,ibd,jy,js,i,j,k - double precision alpha, xk, dk, temp1, temp2 - double precision one,zero - parameter (one=1.0d0,zero=0.0d0) -c - double precision dd_p - - if (nsub .le. 0) return - if (iprint .ge. 99) write (6,1001) - -c Compute wv = W'Zd. - - pointr = head - do 20 i = 1, col - temp1 = zero - temp2 = zero - do 10 j = 1, nsub - k = ind(j) - temp1 = temp1 + wy(k,pointr)*d(j) - temp2 = temp2 + ws(k,pointr)*d(j) - 10 continue - wv(i) = temp1 - wv(col + i) = theta*temp2 - pointr = mod(pointr,m) + 1 - 20 continue - -c Compute wv:=K^(-1)wv. - - m2 = 2*m - col2 = 2*col - call dtrsl(wn,m2,col2,wv,11,info) - if (info .ne. 0) return - do 25 i = 1, col - wv(i) = -wv(i) - 25 continue - call dtrsl(wn,m2,col2,wv,01,info) - if (info .ne. 0) return - -c Compute d = (1/theta)d + (1/theta**2)Z'W wv. - - pointr = head - do 40 jy = 1, col - js = col + jy - do 30 i = 1, nsub - k = ind(i) - d(i) = d(i) + wy(k,pointr)*wv(jy)/theta - + + ws(k,pointr)*wv(js) - 30 continue - pointr = mod(pointr,m) + 1 - 40 continue - - call dscal( nsub, one/theta, d, 1 ) -c -c----------------------------------------------------------------- -c Let us try the projection, d is the Newton direction - - iword = 0 - - call dcopy ( n, x, 1, xp, 1 ) -c - do 50 i=1, nsub - k = ind(i) - dk = d(i) - xk = x(k) - if ( nbd(k) .ne. 0 ) then -c - if ( nbd(k).eq.1 ) then ! lower bounds only - x(k) = max( l(k), xk + dk ) - if ( x(k).eq.l(k) ) iword = 1 - else -c - if ( nbd(k).eq.2 ) then ! upper and lower bounds - xk = max( l(k), xk + dk ) - x(k) = min( u(k), xk ) - if ( x(k).eq.l(k) .or. x(k).eq.u(k) ) iword = 1 - else -c - if ( nbd(k).eq.3 ) then ! upper bounds only - x(k) = min( u(k), xk + dk ) - if ( x(k).eq.u(k) ) iword = 1 - end if - end if - end if -c - else ! free variables - x(k) = xk + dk - end if - 50 continue -c - if ( iword.eq.0 ) then - go to 911 - end if -c -c check sign of the directional derivative -c - dd_p = zero - do 55 i=1, n - dd_p = dd_p + (x(i) - xx(i))*gg(i) - 55 continue - if ( dd_p .gt.zero ) then - call dcopy( n, xp, 1, x, 1 ) - write(6,*) ' Positive dir derivative in projection ' - write(6,*) ' Using the backtracking step ' - else - go to 911 - endif -c -c----------------------------------------------------------------- -c - alpha = one - temp1 = alpha - ibd = 0 - do 60 i = 1, nsub - k = ind(i) - dk = d(i) - if (nbd(k) .ne. 0) then - if (dk .lt. zero .and. nbd(k) .le. 2) then - temp2 = l(k) - x(k) - if (temp2 .ge. zero) then - temp1 = zero - else if (dk*alpha .lt. temp2) then - temp1 = temp2/dk - endif - else if (dk .gt. zero .and. nbd(k) .ge. 2) then - temp2 = u(k) - x(k) - if (temp2 .le. zero) then - temp1 = zero - else if (dk*alpha .gt. temp2) then - temp1 = temp2/dk - endif - endif - if (temp1 .lt. alpha) then - alpha = temp1 - ibd = i - endif - endif - 60 continue - - if (alpha .lt. one) then - dk = d(ibd) - k = ind(ibd) - if (dk .gt. zero) then - x(k) = u(k) - d(ibd) = zero - else if (dk .lt. zero) then - x(k) = l(k) - d(ibd) = zero - endif - endif - do 70 i = 1, nsub - k = ind(i) - x(k) = x(k) + alpha*d(i) - 70 continue -cccccc - 911 continue - - if (iprint .ge. 99) write (6,1004) - - 1001 format (/,'----------------SUBSM entered-----------------',/) - 1004 format (/,'----------------exit SUBSM --------------------',/) - - return - - end -c====================== The end of subsm =============================== - - subroutine dcsrch(f,g,stp,ftol,gtol,xtol,stpmin,stpmax, - + task,isave,dsave) - character*(*) task - integer isave(2) - double precision f,g,stp,ftol,gtol,xtol,stpmin,stpmax - double precision dsave(13) -c ********** -c -c Subroutine dcsrch -c -c This subroutine finds a step that satisfies a sufficient -c decrease condition and a curvature condition. -c -c Each call of the subroutine updates an interval with -c endpoints stx and sty. The interval is initially chosen -c so that it contains a minimizer of the modified function -c -c psi(stp) = f(stp) - f(0) - ftol*stp*f'(0). -c -c If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the -c interval is chosen so that it contains a minimizer of f. -c -c The algorithm is designed to find a step that satisfies -c the sufficient decrease condition -c -c f(stp) <= f(0) + ftol*stp*f'(0), -c -c and the curvature condition -c -c abs(f'(stp)) <= gtol*abs(f'(0)). -c -c If ftol is less than gtol and if, for example, the function -c is bounded below, then there is always a step which satisfies -c both conditions. -c -c If no step can be found that satisfies both conditions, then -c the algorithm stops with a warning. In this case stp only -c satisfies the sufficient decrease condition. -c -c A typical invocation of dcsrch has the following outline: -c -c task = 'START' -c 10 continue -c call dcsrch( ... ) -c if (task .eq. 'FG') then -c Evaluate the function and the gradient at stp -c goto 10 -c end if -c -c NOTE: The user must no alter work arrays between calls. -c -c The subroutine statement is -c -c subroutine dcsrch(f,g,stp,ftol,gtol,xtol,stpmin,stpmax, -c task,isave,dsave) -c where -c -c f is a double precision variable. -c On initial entry f is the value of the function at 0. -c On subsequent entries f is the value of the -c function at stp. -c On exit f is the value of the function at stp. -c -c g is a double precision variable. -c On initial entry g is the derivative of the function at 0. -c On subsequent entries g is the derivative of the -c function at stp. -c On exit g is the derivative of the function at stp. -c -c stp is a double precision variable. -c On entry stp is the current estimate of a satisfactory -c step. On initial entry, a positive initial estimate -c must be provided. -c On exit stp is the current estimate of a satisfactory step -c if task = 'FG'. If task = 'CONV' then stp satisfies -c the sufficient decrease and curvature condition. -c -c ftol is a double precision variable. -c On entry ftol specifies a nonnegative tolerance for the -c sufficient decrease condition. -c On exit ftol is unchanged. -c -c gtol is a double precision variable. -c On entry gtol specifies a nonnegative tolerance for the -c curvature condition. -c On exit gtol is unchanged. -c -c xtol is a double precision variable. -c On entry xtol specifies a nonnegative relative tolerance -c for an acceptable step. The subroutine exits with a -c warning if the relative difference between sty and stx -c is less than xtol. -c On exit xtol is unchanged. -c -c stpmin is a double precision variable. -c On entry stpmin is a nonnegative lower bound for the step. -c On exit stpmin is unchanged. -c -c stpmax is a double precision variable. -c On entry stpmax is a nonnegative upper bound for the step. -c On exit stpmax is unchanged. -c -c task is a character variable of length at least 60. -c On initial entry task must be set to 'START'. -c On exit task indicates the required action: -c -c If task(1:2) = 'FG' then evaluate the function and -c derivative at stp and call dcsrch again. -c -c If task(1:4) = 'CONV' then the search is successful. -c -c If task(1:4) = 'WARN' then the subroutine is not able -c to satisfy the convergence conditions. The exit value of -c stp contains the best point found during the search. -c -c If task(1:5) = 'ERROR' then there is an error in the -c input arguments. -c -c On exit with convergence, a warning or an error, the -c variable task contains additional information. -c -c isave is an integer work array of dimension 2. -c -c dsave is a double precision work array of dimension 13. -c -c Subprograms called -c -c MINPACK-2 ... dcstep -c -c MINPACK-1 Project. June 1983. -c Argonne National Laboratory. -c Jorge J. More' and David J. Thuente. -c -c MINPACK-2 Project. October 1993. -c Argonne National Laboratory and University of Minnesota. -c Brett M. Averick, Richard G. Carter, and Jorge J. More'. -c -c ********** - double precision zero,p5,p66 - parameter(zero=0.0d0,p5=0.5d0,p66=0.66d0) - double precision xtrapl,xtrapu - parameter(xtrapl=1.1d0,xtrapu=4.0d0) - - logical brackt - integer stage - double precision finit,ftest,fm,fx,fxm,fy,fym,ginit,gtest, - + gm,gx,gxm,gy,gym,stx,sty,stmin,stmax,width,width1 - -c Initialization block. - - if (task(1:5) .eq. 'START') then - -c Check the input arguments for errors. - - if (stp .lt. stpmin) task = 'ERROR: STP .LT. STPMIN' - if (stp .gt. stpmax) task = 'ERROR: STP .GT. STPMAX' - if (g .ge. zero) task = 'ERROR: INITIAL G .GE. ZERO' - if (ftol .lt. zero) task = 'ERROR: FTOL .LT. ZERO' - if (gtol .lt. zero) task = 'ERROR: GTOL .LT. ZERO' - if (xtol .lt. zero) task = 'ERROR: XTOL .LT. ZERO' - if (stpmin .lt. zero) task = 'ERROR: STPMIN .LT. ZERO' - if (stpmax .lt. stpmin) task = 'ERROR: STPMAX .LT. STPMIN' - -c Exit if there are errors on input. - - if (task(1:5) .eq. 'ERROR') return - -c Initialize local variables. - - brackt = .false. - stage = 1 - finit = f - ginit = g - gtest = ftol*ginit - width = stpmax - stpmin - width1 = width/p5 - -c The variables stx, fx, gx contain the values of the step, -c function, and derivative at the best step. -c The variables sty, fy, gy contain the value of the step, -c function, and derivative at sty. -c The variables stp, f, g contain the values of the step, -c function, and derivative at stp. - - stx = zero - fx = finit - gx = ginit - sty = zero - fy = finit - gy = ginit - stmin = zero - stmax = stp + xtrapu*stp - task = 'FG' - - goto 1000 - - else - -c Restore local variables. - - if (isave(1) .eq. 1) then - brackt = .true. - else - brackt = .false. - endif - stage = isave(2) - ginit = dsave(1) - gtest = dsave(2) - gx = dsave(3) - gy = dsave(4) - finit = dsave(5) - fx = dsave(6) - fy = dsave(7) - stx = dsave(8) - sty = dsave(9) - stmin = dsave(10) - stmax = dsave(11) - width = dsave(12) - width1 = dsave(13) - - endif - -c If psi(stp) <= 0 and f'(stp) >= 0 for some step, then the -c algorithm enters the second stage. - - ftest = finit + stp*gtest - if (stage .eq. 1 .and. f .le. ftest .and. g .ge. zero) - + stage = 2 - -c Test for warnings. - - if (brackt .and. (stp .le. stmin .or. stp .ge. stmax)) - + task = 'WARNING: ROUNDING ERRORS PREVENT PROGRESS' - if (brackt .and. stmax - stmin .le. xtol*stmax) - + task = 'WARNING: XTOL TEST SATISFIED' - if (stp .eq. stpmax .and. f .le. ftest .and. g .le. gtest) - + task = 'WARNING: STP = STPMAX' - if (stp .eq. stpmin .and. (f .gt. ftest .or. g .ge. gtest)) - + task = 'WARNING: STP = STPMIN' - -c Test for convergence. - - if (f .le. ftest .and. abs(g) .le. gtol*(-ginit)) - + task = 'CONVERGENCE' - -c Test for termination. - - if (task(1:4) .eq. 'WARN' .or. task(1:4) .eq. 'CONV') goto 1000 - -c A modified function is used to predict the step during the -c first stage if a lower function value has been obtained but -c the decrease is not sufficient. - - if (stage .eq. 1 .and. f .le. fx .and. f .gt. ftest) then - -c Define the modified function and derivative values. - - fm = f - stp*gtest - fxm = fx - stx*gtest - fym = fy - sty*gtest - gm = g - gtest - gxm = gx - gtest - gym = gy - gtest - -c Call dcstep to update stx, sty, and to compute the new step. - - call dcstep(stx,fxm,gxm,sty,fym,gym,stp,fm,gm, - + brackt,stmin,stmax) - -c Reset the function and derivative values for f. - - fx = fxm + stx*gtest - fy = fym + sty*gtest - gx = gxm + gtest - gy = gym + gtest - - else - -c Call dcstep to update stx, sty, and to compute the new step. - - call dcstep(stx,fx,gx,sty,fy,gy,stp,f,g, - + brackt,stmin,stmax) - - endif - -c Decide if a bisection step is needed. - - if (brackt) then - if (abs(sty-stx) .ge. p66*width1) stp = stx + p5*(sty - stx) - width1 = width - width = abs(sty-stx) - endif - -c Set the minimum and maximum steps allowed for stp. - - if (brackt) then - stmin = min(stx,sty) - stmax = max(stx,sty) - else - stmin = stp + xtrapl*(stp - stx) - stmax = stp + xtrapu*(stp - stx) - endif - -c Force the step to be within the bounds stpmax and stpmin. - - stp = max(stp,stpmin) - stp = min(stp,stpmax) - -c If further progress is not possible, let stp be the best -c point obtained during the search. - - if (brackt .and. (stp .le. stmin .or. stp .ge. stmax) - + .or. (brackt .and. stmax-stmin .le. xtol*stmax)) stp = stx - -c Obtain another function and derivative. - - task = 'FG' - - 1000 continue - -c Save local variables. - - if (brackt) then - isave(1) = 1 - else - isave(1) = 0 - endif - isave(2) = stage - dsave(1) = ginit - dsave(2) = gtest - dsave(3) = gx - dsave(4) = gy - dsave(5) = finit - dsave(6) = fx - dsave(7) = fy - dsave(8) = stx - dsave(9) = sty - dsave(10) = stmin - dsave(11) = stmax - dsave(12) = width - dsave(13) = width1 - - return - end - -c====================== The end of dcsrch ============================== - - subroutine dcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,brackt, - + stpmin,stpmax) - logical brackt - double precision stx,fx,dx,sty,fy,dy,stp,fp,dp,stpmin,stpmax -c ********** -c -c Subroutine dcstep -c -c This subroutine computes a safeguarded step for a search -c procedure and updates an interval that contains a step that -c satisfies a sufficient decrease and a curvature condition. -c -c The parameter stx contains the step with the least function -c value. If brackt is set to .true. then a minimizer has -c been bracketed in an interval with endpoints stx and sty. -c The parameter stp contains the current step. -c The subroutine assumes that if brackt is set to .true. then -c -c min(stx,sty) < stp < max(stx,sty), -c -c and that the derivative at stx is negative in the direction -c of the step. -c -c The subroutine statement is -c -c subroutine dcstep(stx,fx,dx,sty,fy,dy,stp,fp,dp,brackt, -c stpmin,stpmax) -c -c where -c -c stx is a double precision variable. -c On entry stx is the best step obtained so far and is an -c endpoint of the interval that contains the minimizer. -c On exit stx is the updated best step. -c -c fx is a double precision variable. -c On entry fx is the function at stx. -c On exit fx is the function at stx. -c -c dx is a double precision variable. -c On entry dx is the derivative of the function at -c stx. The derivative must be negative in the direction of -c the step, that is, dx and stp - stx must have opposite -c signs. -c On exit dx is the derivative of the function at stx. -c -c sty is a double precision variable. -c On entry sty is the second endpoint of the interval that -c contains the minimizer. -c On exit sty is the updated endpoint of the interval that -c contains the minimizer. -c -c fy is a double precision variable. -c On entry fy is the function at sty. -c On exit fy is the function at sty. -c -c dy is a double precision variable. -c On entry dy is the derivative of the function at sty. -c On exit dy is the derivative of the function at the exit sty. -c -c stp is a double precision variable. -c On entry stp is the current step. If brackt is set to .true. -c then on input stp must be between stx and sty. -c On exit stp is a new trial step. -c -c fp is a double precision variable. -c On entry fp is the function at stp -c On exit fp is unchanged. -c -c dp is a double precision variable. -c On entry dp is the the derivative of the function at stp. -c On exit dp is unchanged. -c -c brackt is an logical variable. -c On entry brackt specifies if a minimizer has been bracketed. -c Initially brackt must be set to .false. -c On exit brackt specifies if a minimizer has been bracketed. -c When a minimizer is bracketed brackt is set to .true. -c -c stpmin is a double precision variable. -c On entry stpmin is a lower bound for the step. -c On exit stpmin is unchanged. -c -c stpmax is a double precision variable. -c On entry stpmax is an upper bound for the step. -c On exit stpmax is unchanged. -c -c MINPACK-1 Project. June 1983 -c Argonne National Laboratory. -c Jorge J. More' and David J. Thuente. -c -c MINPACK-2 Project. October 1993. -c Argonne National Laboratory and University of Minnesota. -c Brett M. Averick and Jorge J. More'. -c -c ********** - double precision zero,p66,two,three - parameter(zero=0.0d0,p66=0.66d0,two=2.0d0,three=3.0d0) - - double precision gamma,p,q,r,s,sgnd,stpc,stpf,stpq,theta - - sgnd = dp*(dx/abs(dx)) - -c First case: A higher function value. The minimum is bracketed. -c If the cubic step is closer to stx than the quadratic step, the -c cubic step is taken, otherwise the average of the cubic and -c quadratic steps is taken. - - if (fp .gt. fx) then - theta = three*(fx - fp)/(stp - stx) + dx + dp - s = max(abs(theta),abs(dx),abs(dp)) - gamma = s*sqrt((theta/s)**2 - (dx/s)*(dp/s)) - if (stp .lt. stx) gamma = -gamma - p = (gamma - dx) + theta - q = ((gamma - dx) + gamma) + dp - r = p/q - stpc = stx + r*(stp - stx) - stpq = stx + ((dx/((fx - fp)/(stp - stx) + dx))/two)* - + (stp - stx) - if (abs(stpc-stx) .lt. abs(stpq-stx)) then - stpf = stpc - else - stpf = stpc + (stpq - stpc)/two - endif - brackt = .true. - -c Second case: A lower function value and derivatives of opposite -c sign. The minimum is bracketed. If the cubic step is farther from -c stp than the secant step, the cubic step is taken, otherwise the -c secant step is taken. - - else if (sgnd .lt. zero) then - theta = three*(fx - fp)/(stp - stx) + dx + dp - s = max(abs(theta),abs(dx),abs(dp)) - gamma = s*sqrt((theta/s)**2 - (dx/s)*(dp/s)) - if (stp .gt. stx) gamma = -gamma - p = (gamma - dp) + theta - q = ((gamma - dp) + gamma) + dx - r = p/q - stpc = stp + r*(stx - stp) - stpq = stp + (dp/(dp - dx))*(stx - stp) - if (abs(stpc-stp) .gt. abs(stpq-stp)) then - stpf = stpc - else - stpf = stpq - endif - brackt = .true. - -c Third case: A lower function value, derivatives of the same sign, -c and the magnitude of the derivative decreases. - - else if (abs(dp) .lt. abs(dx)) then - -c The cubic step is computed only if the cubic tends to infinity -c in the direction of the step or if the minimum of the cubic -c is beyond stp. Otherwise the cubic step is defined to be the -c secant step. - - theta = three*(fx - fp)/(stp - stx) + dx + dp - s = max(abs(theta),abs(dx),abs(dp)) - -c The case gamma = 0 only arises if the cubic does not tend -c to infinity in the direction of the step. - - gamma = s*sqrt(max(zero,(theta/s)**2-(dx/s)*(dp/s))) - if (stp .gt. stx) gamma = -gamma - p = (gamma - dp) + theta - q = (gamma + (dx - dp)) + gamma - r = p/q - if (r .lt. zero .and. gamma .ne. zero) then - stpc = stp + r*(stx - stp) - else if (stp .gt. stx) then - stpc = stpmax - else - stpc = stpmin - endif - stpq = stp + (dp/(dp - dx))*(stx - stp) - - if (brackt) then - -c A minimizer has been bracketed. If the cubic step is -c closer to stp than the secant step, the cubic step is -c taken, otherwise the secant step is taken. - - if (abs(stpc-stp) .lt. abs(stpq-stp)) then - stpf = stpc - else - stpf = stpq - endif - if (stp .gt. stx) then - stpf = min(stp+p66*(sty-stp),stpf) - else - stpf = max(stp+p66*(sty-stp),stpf) - endif - else - -c A minimizer has not been bracketed. If the cubic step is -c farther from stp than the secant step, the cubic step is -c taken, otherwise the secant step is taken. - - if (abs(stpc-stp) .gt. abs(stpq-stp)) then - stpf = stpc - else - stpf = stpq - endif - stpf = min(stpmax,stpf) - stpf = max(stpmin,stpf) - endif - -c Fourth case: A lower function value, derivatives of the same sign, -c and the magnitude of the derivative does not decrease. If the -c minimum is not bracketed, the step is either stpmin or stpmax, -c otherwise the cubic step is taken. - - else - if (brackt) then - theta = three*(fp - fy)/(sty - stp) + dy + dp - s = max(abs(theta),abs(dy),abs(dp)) - gamma = s*sqrt((theta/s)**2 - (dy/s)*(dp/s)) - if (stp .gt. sty) gamma = -gamma - p = (gamma - dp) + theta - q = ((gamma - dp) + gamma) + dy - r = p/q - stpc = stp + r*(sty - stp) - stpf = stpc - else if (stp .gt. stx) then - stpf = stpmax - else - stpf = stpmin - endif - endif - -c Update the interval which contains a minimizer. - - if (fp .gt. fx) then - sty = stp - fy = fp - dy = dp - else - if (sgnd .lt. zero) then - sty = stx - fy = fx - dy = dx - endif - stx = stp - fx = fp - dx = dp - endif - -c Compute the new step. - - stp = stpf - - return - end - diff --git a/ccx_2.14_linpack.f b/ccx_2.14_linpack.f deleted file mode 100644 index c737987114ad..000000000000 --- a/ccx_2.14_linpack.f +++ /dev/null @@ -1,218 +0,0 @@ -c -c L-BFGS-B is released under the “New BSD License” (aka “Modified BSD License” -c or “3-clause license”) -c Please read attached file License.txt -c - subroutine dpofa(a,lda,n,info) - integer lda,n,info - double precision a(lda,*) -c -c dpofa factors a double precision symmetric positive definite -c matrix. -c -c dpofa is usually called by dpoco, but it can be called -c directly with a saving in time if rcond is not needed. -c (time for dpoco) = (1 + 18/n)*(time for dpofa) . -c -c on entry -c -c a double precision(lda, n) -c the symmetric matrix to be factored. only the -c diagonal and upper triangle are used. -c -c lda integer -c the leading dimension of the array a . -c -c n integer -c the order of the matrix a . -c -c on return -c -c a an upper triangular matrix r so that a = trans(r)*r -c where trans(r) is the transpose. -c the strict lower triangle is unaltered. -c if info .ne. 0 , the factorization is not complete. -c -c info integer -c = 0 for normal return. -c = k signals an error condition. the leading minor -c of order k is not positive definite. -c -c linpack. this version dated 08/14/78 . -c cleve moler, university of new mexico, argonne national lab. -c -c subroutines and functions -c -c blas ddot -c fortran sqrt -c -c internal variables -c - double precision ddot,t - double precision s - integer j,jm1,k -c begin block with ...exits to 40 -c -c - do 30 j = 1, n - info = j - s = 0.0d0 - jm1 = j - 1 - if (jm1 .lt. 1) go to 20 - do 10 k = 1, jm1 - t = a(k,j) - ddot(k-1,a(1,k),1,a(1,j),1) - t = t/a(k,k) - a(k,j) = t - s = s + t*t - 10 continue - 20 continue - s = a(j,j) - s -c ......exit - if (s .le. 0.0d0) go to 40 - a(j,j) = sqrt(s) - 30 continue - info = 0 - 40 continue - return - end - -c====================== The end of dpofa =============================== - - subroutine dtrsl(t,ldt,n,b,job,info) - integer ldt,n,job,info - double precision t(ldt,*),b(*) -c -c -c dtrsl solves systems of the form -c -c t * x = b -c or -c trans(t) * x = b -c -c where t is a triangular matrix of order n. here trans(t) -c denotes the transpose of the matrix t. -c -c on entry -c -c t double precision(ldt,n) -c t contains the matrix of the system. the zero -c elements of the matrix are not referenced, and -c the corresponding elements of the array can be -c used to store other information. -c -c ldt integer -c ldt is the leading dimension of the array t. -c -c n integer -c n is the order of the system. -c -c b double precision(n). -c b contains the right hand side of the system. -c -c job integer -c job specifies what kind of system is to be solved. -c if job is -c -c 00 solve t*x=b, t lower triangular, -c 01 solve t*x=b, t upper triangular, -c 10 solve trans(t)*x=b, t lower triangular, -c 11 solve trans(t)*x=b, t upper triangular. -c -c on return -c -c b b contains the solution, if info .eq. 0. -c otherwise b is unaltered. -c -c info integer -c info contains zero if the system is nonsingular. -c otherwise info contains the index of -c the first zero diagonal element of t. -c -c linpack. this version dated 08/14/78 . -c g. w. stewart, university of maryland, argonne national lab. -c -c subroutines and functions -c -c blas daxpy,ddot -c fortran mod -c -c internal variables -c - double precision ddot,temp - integer case,j,jj -c -c begin block permitting ...exits to 150 -c -c check for zero diagonal elements. -c - do 10 info = 1, n -c ......exit - if (t(info,info) .eq. 0.0d0) go to 150 - 10 continue - info = 0 -c -c determine the task and go to it. -c - case = 1 - if (mod(job,10) .ne. 0) case = 2 - if (mod(job,100)/10 .ne. 0) case = case + 2 - go to (20,50,80,110), case -c -c solve t*x=b for t lower triangular -c - 20 continue - b(1) = b(1)/t(1,1) - if (n .lt. 2) go to 40 - do 30 j = 2, n - temp = -b(j-1) - call daxpy(n-j+1,temp,t(j,j-1),1,b(j),1) - b(j) = b(j)/t(j,j) - 30 continue - 40 continue - go to 140 -c -c solve t*x=b for t upper triangular. -c - 50 continue - b(n) = b(n)/t(n,n) - if (n .lt. 2) go to 70 - do 60 jj = 2, n - j = n - jj + 1 - temp = -b(j+1) - call daxpy(j,temp,t(1,j+1),1,b(1),1) - b(j) = b(j)/t(j,j) - 60 continue - 70 continue - go to 140 -c -c solve trans(t)*x=b for t lower triangular. -c - 80 continue - b(n) = b(n)/t(n,n) - if (n .lt. 2) go to 100 - do 90 jj = 2, n - j = n - jj + 1 - b(j) = b(j) - ddot(jj-1,t(j+1,j),1,b(j+1),1) - b(j) = b(j)/t(j,j) - 90 continue - 100 continue - go to 140 -c -c solve trans(t)*x=b for t upper triangular. -c - 110 continue - b(1) = b(1)/t(1,1) - if (n .lt. 2) go to 130 - do 120 j = 2, n - b(j) = b(j) - ddot(j-1,t(1,j),1,b(1),1) - b(j) = b(j)/t(j,j) - 120 continue - 130 continue - 140 continue - 150 continue - return - end - -c====================== The end of dtrsl =============================== - - diff --git a/ccx_2.14_timer.f b/ccx_2.14_timer.f deleted file mode 100644 index 5535ccf93719..000000000000 --- a/ccx_2.14_timer.f +++ /dev/null @@ -1,32 +0,0 @@ -c -c L-BFGS-B is released under the “New BSD License” (aka “Modified BSD License” -c or “3-clause license”) -c Please read attached file License.txt -c - subroutine timer(ttime) - double precision ttime -c - real temp -c -c This routine computes cpu time in double precision; it makes use of -c the intrinsic f90 cpu_time therefore a conversion type is -c needed. -c -c J.L Morales Departamento de Matematicas, -c Instituto Tecnologico Autonomo de Mexico -c Mexico D.F. -c -c J.L Nocedal Department of Electrical Engineering and -c Computer Science. -c Northwestern University. Evanston, IL. USA -c -c January 21, 2011 -c - temp = sngl(ttime) - call cpu_time(temp) - ttime = dble(temp) - - return - - end - |