C ****************************************************************** C ****************************************************************** subroutine gencan(n,x,l,u,m,lambda,equatn,linear,rho,constf, +epsfeas,epsopt,maxit,iter,f,g,gpsupn,cnorm,cnormu,geninfo,inform) implicit none C SCALAR ARGUMENTS logical constf integer geninfo,inform,iter,m,maxit,n double precision cnorm,cnormu,epsfeas,epsopt,f,gpsupn C ARRAY ARGUMENTS logical equatn(m),linear(m) double precision g(n),l(n),lambda(m),rho(m),u(n),x(n) C Solves the box-constrained minimization problem C C Minimize f(x) subject to l <= x <= u C C using the method described in C C E. G. Birgin and J. M. Martinez, ''Large-scale active-set box- C constrained optimization method with spectral projected C gradients'', Computational Optimization and Applications 23, pp. C 101-125, 2002. C geninfo: C C 0: Small continuous-projected-gradient norm C 1: Maximum number of gencan iterations reached C 3: Lack of progress in the objective function value C 4: Lack of progress in the continuous-projected-gradient norm C 5: Lack of progress in the current point C 6: Unbounded objective function? C 7: Too small backtracking step. Wrong gradient? #include "dim.par" #include "machconst.com" #include "algconst.par" #include "algparam.com" #include "counters.com" #include "outtyp.com" #include "rspace.com" #include "itetyp.com" #include "sydat.com" C DATA BLOCKS character * 19 ittext(0:3) data ittext(0) /'(Initial point) '/ data ittext(1) /'(SPG step) '/ data ittext(2) /'(Truncated Newton)'/ data ittext(3) /'(MS system) '/ integer BDSREACHED,SMALLSTEP,UNBOUNDED data BDSREACHED /2/ data SMALLSTEP /3/ data UNBOUNDED /2/ c integer SMALLSTEP,UNBOUNDED c data SMALLSTEP /3/ c data UNBOUNDED /2/ C LOCAL SCALARS character * 6 precond character * 2 innittype logical memfail,vustop integer cgcnt,cginfo,cgiter,cgmaxit,i,innit,itnfp,itngp,itnxp, + lsinfo,mfit,nind,nindprev,nwcnt,outit,rbdnnz,xind double precision acgeps,amax,bcgeps,cgeps,cgdel,dsupn,fdiff,fplus, + gieucn,gisupn,gpeucn,gpi,lamspg,ssupn,tsmall,ysupn,xeucn, + xsupn C LOCAL ARRAYS integer rbdind(nmax) character rbdtype(nmax) double precision d(nmax),gplus(nmax),xplus(nmax) C EXTERNAL logical sstop C ================================================================== C Initialization C ================================================================== C Set some initial values: C to record a memory failure in the direct solver memfail = .false. C for Conjugate Gradients precond = 'QNCGNA' C for the first inner-to-the-face minimization algorithm innittype = 'CG' C for testing lack of progress checking f, g and x itnfp = 0 itngp = 0 itnxp = 0 C for counting number of iterations as well as inner-to-the-face C and leaving-face iterations iter = 0 cgcnt = 0 nwcnt = 0 outit = 0 innit = 0 C just to print "Initial point" in the first ouput ittype = 0 C Print problem information if ( iprintinn .ge. 1 ) then write(* ,1000) n write(10,1000) n end if if ( iprintinn .ge. 4 .and. nprint .ne. 0 ) then write(* ,1010) nprint,(l(i),i=1,nprint) write(* ,1020) nprint,(u(i),i=1,nprint) write(* ,1030) nprint,(x(i),i=1,nprint) write(10,1010) nprint,(l(i),i=1,nprint) write(10,1020) nprint,(u(i),i=1,nprint) write(10,1030) nprint,(x(i),i=1,nprint) end if C Project initial guess. If the initial guess is infeasible, C projection puts it into the box. do i = 1,n x(i) = max( l(i), min( x(i), u(i) ) ) end do C Compute function and gradient at the initial point call sevalal(n,x,m,lambda,rho,equatn,linear,f,inform) if ( inform .lt. 0 ) return call sevalnal(n,x,m,lambda,rho,equatn,linear,g,inform) if ( inform .lt. 0 ) return C Compute x Euclidian and sup norms, continuous-project-gradient C Euclidian and sup norms, internal gradient Euclidian norm. Set C nind as the number of free variables and save in array ind their C identifiers. Also set variable sameface (same face) indicating C that the "previous iterate" does not belong to the current face. sameface = .false. nind = 0 xsupn = 0.0d0 xeucn = 0.0d0 gpsupn = 0.0d0 gpeucn = 0.0d0 gisupn = 0.0d0 gieucn = 0.0d0 do i = 1,n if ( abs( x(i) ) .ge. xsupn ) then xsupn = abs( x(i) ) xind = i end if xeucn = xeucn + x(i) ** 2 gpi = x(i) - g(i) if ( l(i) .le. gpi .and. gpi .le. u(i) ) then gpi = - g(i) else gpi = max( l(i), min( gpi, u(i) ) ) - x(i) end if gpsupn = max( gpsupn, abs( gpi ) ) gpeucn = gpeucn + gpi ** 2 if ( x(i) - l(i) .gt. macheps23 * max( 1.0d0, l(i) ) .and. + u(i) - x(i) .gt. macheps23 * max( 1.0d0, u(i) ) ) then gisupn = max( gisupn, abs( gpi ) ) gieucn = gieucn + gpi ** 2 nind = nind + 1 ind(nind) = i end if end do xeucn = sqrt( xeucn ) gpeucn = sqrt( gpeucn ) gieucn = sqrt( gieucn ) C To be used in feasibility problems, compute constraints norm call sevalfeas(n,x,m,equatn,cnorm,cnormu,inform) if ( inform .lt. 0 ) return C Initial spectral steplength C Compute a small step and set the point at which the auxiliary C gradient will be computed if ( gpsupn .ne. 0.0d0 ) then tsmall = macheps12 * max( 1.0d0, xsupn / gpsupn ) else tsmall = 0.0d0 end if do i = 1,n gpi = x(i) - g(i) if ( l(i) .le. gpi .and. gpi .le. u(i) ) then gpi = - g(i) else gpi = max( l(i), min( gpi, u(i) ) ) - x(i) end if s(i) = x(i) + tsmall * gpi end do C Compute the gradient at the auxiliary point call ievalnalu(n,s,m,lambda,rho,equatn,linear,.false.,y,inform) if ( inform .lt. 0 ) return C Compute s = x_{1/2} - x_0 and y = g_{1/2} - g_0 sts = 0.0d0 sty = 0.0d0 ssupn = 0.0d0 ysupn = 0.0d0 yeucn = 0.0d0 do i = 1,n s(i) = s(i) - x(i) y(i) = y(i) - g(i) sts = sts + s(i) ** 2 sty = sty + s(i) * y(i) ssupn = max( ssupn, abs( s(i) ) ) ysupn = max( ysupn, abs( y(i) ) ) yeucn = yeucn + y(i) ** 2 end do seucn = sqrt( sts ) yeucn = sqrt( yeucn ) C Compute a linear relation between gpsupn and cgeps, i.e., C scalars a and b such that c C a * log10( ||g_P(x_ini)|| ) + b = log10(cgeps_ini) and c C a * log10( ||g_P(x_fin)|| ) + b = log10(cgeps_fin), c C where cgeps_ini and cgeps_fin are provided. Note that if C cgeps_ini is equal to cgeps_fin then cgeps will be always C equal to cgeps_ini and cgeps_fin. acgeps = log10( cgepsf / cgepsi ) / log10( cggpnf / gpsupn ) bcgeps = log10( cgepsi ) - acgeps * log10( gpsupn ) C Print initial information if ( iprintinn .eq. 1 ) then if ( mod(iter,10) .eq. 0 ) then write(* ,1040) write(10,1040) end if write(* ,1050) iter,f,gpsupn,xsupn write(10,1050) iter,f,gpsupn,xsupn else if ( iprintinn .ge. 2 ) then write(* ,1070) iter,ittext(ittype) write(10,1070) iter,ittext(ittype) if ( iprintinn .ge. 3 ) then write(* ,1080) outit,innit,fcnt,cgcnt,nwcnt write(10,1080) outit,innit,fcnt,cgcnt,nwcnt end if write(* ,1090) f,gpsupn,gpeucn,gisupn,gieucn,xind,xsupn,xeucn, + ssupn,seucn write(10,1090) f,gpsupn,gpeucn,gisupn,gieucn,xind,xsupn,xeucn, + ssupn,seucn if ( iprintinn .ge. 4 .and. nprint .ne. 0 ) then write(* ,1100) min(nprint,nind),nind, + (ind(i),i=1,min(nprint,nind)) write(* ,1110) nprint,(x(i),i=1,nprint) write(* ,1130) nprint,(g(i),i=1,nprint) write(* ,1140) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i), + i=1,nprint) write(10,1100) min(nprint,nind),nind, + (ind(i),i=1,min(nprint,nind)) write(10,1110) nprint,(x(i),i=1,nprint) write(10,1130) nprint,(g(i),i=1,nprint) write(10,1140) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i), + i=1,nprint) end if end if C Save intermediate data for crash report open(20,file='gencan-tabline.out') write(20,1060) iter,f,gpsupn,xsupn,ssupn,nind,outit,innit,fcnt C write(20,1400) f,0.0d0,f,0.0d0,gpsupn,inform,9,n,m,0,iter,0,0,0,0, C + 0,999.0d0 close(20) C ================================================================== C Main loop C ================================================================== 100 continue C ================================================================== C Test stopping criteria C ================================================================== C Test user-provided stopping criterion if ( useustp ) then vustop = sstop(n,x,m,lambda,rho,equatn,linear,inform) if ( inform .lt. 0 ) return if ( vustop ) then geninfo = 8 if ( iprintinn .ge. 1 ) then write(*, 1280) write(10,1280) end if return end if end if C Test whether the continuous-projected-gradient sup-norm C is small enough to declare convergence if ( .not. constf ) then if ( gpsupn .le. epsopt ) then geninfo = 0 if ( iprintinn .ge. 1 ) then write(*, 1200) write(10,1200) end if return end if else if ( cnormu .le. epsfeas ) then geninfo = 0 if ( iprintinn .ge. 1 ) then write(*, 1200) write(10,1200) end if return end if end if C Test whether the number of iterations is exhausted if ( iter .ge. maxit ) then geninfo = 1 if ( iprintinn .ge. 1 ) then write(*, 1210) write(10,1210) end if return end if C ================================================================== C Test stopping criteria related to lack of progress C ================================================================== if ( iter .gt. 0 ) then C Test whether we have performed many iterations without C moving from the current point, by checking the functional value if ( abs( fdiff ) .le. macheps * max( 1.0d0, abs( f ) ) ) then itnfp = itnfp + 1 if ( itnfp .ge. maxinnitnp ) then geninfo = 3 if ( iprintinn .ge. 1 ) then write(*, 1230) write(10,1230) end if return end if else itnfp = 0 end if C Test whether we have performed many iterations without C moving from the current point, by checking their gradients if ( ysupn .le. macheps * max( 1.0d0, gpsupn ) .or. + yeucn .le. macheps * max( 1.0d0, gpeucn ) ) then itngp = itngp + 1 if ( itngp .ge. maxinnitnp ) then geninfo = 4 if ( iprintinn .ge. 1 ) then write(*, 1240) write(10,1240) end if return end if else itngp = 0 end if C Test whether we have performed many iterations without C moving from the current point, by checking the step norm if ( ssupn .le. macheps * max( 1.0d0, xsupn ) .or. + seucn .le. macheps * max( 1.0d0, xeucn ) ) then itnxp = itnxp + 1 if ( itnxp .ge. maxinnitnp ) then geninfo = 5 if ( iprintinn .ge. 1 ) then write(*, 1250) write(10,1250) end if return end if else itnxp = 0 end if end if C ================================================================== C Iteration C ================================================================== iter = iter + 1 C ================================================================== C Compute new iterate C ================================================================== C We abandon the current face if the norm of the internal gradient C (here, internal components of the continuous projected gradient) C is smaller than eta times the norm of the continuous C projected gradient. Using eta = 0.1 is a rather conservative C strategy in the sense that internal iterations are preferred over C SPG iterations. Replace eta = 0.1 by other tolerance in (0,1) if C you find it convenient. if ( gieucn .le. eta * gpeucn .or. + gisupn .le. eta * gpsupn ) then C ============================================================== C Some constraints should be abandoned. Compute the new iterate C using an SPG iteration C ============================================================== outit = outit + 1 C Compute spectral steplength if ( sty .le. 0.0d0 ) then lamspg = max( 1.0d0, xsupn / gpsupn ) else lamspg = sts / sty end if lamspg = min( lspgma, max( lspgmi, lamspg ) ) C Perform safeguarded quadratic interpolation along the C spectral continuous projected gradient call spgls(n,x,l,u,m,lambda,rho,equatn,linear,f,g,lamspg, + xplus,fplus,lsinfo,inform) if ( inform .lt. 0 ) return call sevalnal(n,xplus,m,lambda,rho,equatn,linear,gplus,inform) if ( inform .lt. 0 ) return C Set iteration type ittype = 1 else C ============================================================== C The new iterate will belong to the closure of the current face C ============================================================== innit = innit + 1 C Shrink the point, its gradient and the bounds call shrink(nind,x) call shrink(nind,g) call shrink(nind,l) call shrink(nind,u) C Save values of fixed variables for further evaluations do i = 1,n - nind xcomplement(i) = x(nind + i) end do nt = n C Compute the descent direction solving the newtonian system if ( innittype .eq. 'DS' ) then C Solve the Newtonian system C C ( H + rho A^T A ) x = b C C by solving the Martinez-Santos system C C H x + A^t y = b C A x - y/rho = 0 C C with a direct solver. call newtd(nind,x,l,u,g,m,rho,equatn,d,memfail,inform) if ( inform .lt. 0 ) return nwcnt = nwcnt + 1 if ( memfail ) then mfit = iter end if C Set iteration type ittype = 3 end if if ( innittype .eq. 'CG' .or. + ( innittype .eq. 'DS' .and. memfail) ) then C Compute "trust-region radius" if ( iter .eq. 1 ) then cgdel = max( 100.0d0, 100.0d0 * xsupn ) else cgdel = max( delmin, 10.0d0 * ssupn ) end if C Set conjugate gradient stopping criteria. cgmaxit = min( 2 * nind, 10000 ) cgeps = 10.0d0 ** ( acgeps * log10( gpsupn ) + bcgeps ) cgeps = max( cgepsf, min( cgepsi, cgeps ) ) C Call Conjugate Gradients to solve the Newtonian system call cgm(nind,x,m,lambda,rho,equatn,linear,l,u,g,cgdel, + cgeps,cgmaxit,precond,d,rbdnnz,rbdind,rbdtype,cgiter, + cginfo,inform) cgcnt = cgcnt + cgiter if ( inform .lt. 0 ) return C Set iteration type ittype = 2 end if C Compute maximum step if ( ittype .eq. 2 .and. cginfo .eq. BDSREACHED ) then amax = 1.0d0 else call compamax(nind,x,l,u,d,amax,rbdnnz,rbdind,rbdtype) end if C Set iteration type based on the lenght of the maximum step dsupn = 0.0d0 do i = 1,nind dsupn = max( dsupn, abs( d(i) ) ) end do if ( avoidds .or. ( memfail .and. iter - mfit .le. 3 ) ) then innittype = 'CG' else if ( innittype .eq. 'DS' .and. + amax .le. macheps12 * dsupn ) then innittype = 'CG' else innittype = 'DS' end if end if C Perform line search call tnls(nind,x,l,u,m,lambda,rho,equatn,linear,f,g,amax,d, + rbdnnz,rbdind,rbdtype,xplus,fplus,gplus,lsinfo,inform) if ( inform .lt. 0 ) return C Expand the point, its gradient and the bounds. Also expand C xplus and gplus. call expand(nind,x) call expand(nind,g) call expand(nind,l) call expand(nind,u) call expand(nind,xplus) call expand(nind,gplus) end if C Compute s = xplus - x and y = gplus - g fdiff = fplus - f sts = 0.0d0 sty = 0.0d0 ssupn = 0.0d0 ysupn = 0.0d0 yeucn = 0.0d0 do i = 1,n s(i) = xplus(i) - x(i) y(i) = gplus(i) - g(i) sts = sts + s(i) ** 2 sty = sty + s(i) * y(i) ssupn = max( ssupn, abs( s(i) ) ) ysupn = max( ysupn, abs( y(i) ) ) yeucn = yeucn + y(i) ** 2 end do seucn = sqrt( sts ) yeucn = sqrt( yeucn ) C Set new point f = fplus do i = 1,n x(i) = xplus(i) g(i) = gplus(i) end do C ================================================================== C Prepare for the next iteration C ================================================================== C This adjustment/projection is ''por lo que las putas pudiera'' do i = 1,n if ( x(i) - macheps23 * max( 1.0d0, abs( x(i) ) ) .le. + l(i) ) then x(i) = l(i) else if ( x(i) + macheps23 * max( 1.0d0, abs( x(i) ) ) .ge. + u(i) ) then x(i) = u(i) end if end do C Compute continuous-project-gradient Euclidian and Sup norms, C internal gradient Euclidian norm, and store in nind the number of C free variables and in array ind their identifiers. Verify whether C x and xprev belong to the same face. sameface = .true. nindprev = nind nind = 0 xsupn = 0.0d0 xeucn = 0.0d0 gpsupn = 0.0d0 gpeucn = 0.0d0 gisupn = 0.0d0 gieucn = 0.0d0 do i = 1,n if ( abs( x(i) ) .ge. xsupn ) then xsupn = abs( x(i) ) xind = i end if xeucn = xeucn + x(i) ** 2 gpi = x(i) - g(i) if ( l(i) .le. gpi .and. gpi .le. u(i) ) then gpi = - g(i) else gpi = max( l(i), min( gpi, u(i) ) ) - x(i) end if gpsupn = max( gpsupn, abs( gpi ) ) gpeucn = gpeucn + gpi ** 2 if ( x(i) - l(i) .gt. macheps23 * max( 1.0d0, l(i) ) .and. + u(i) - x(i) .gt. macheps23 * max( 1.0d0, u(i) ) ) then gisupn = max( gisupn, abs( gpi ) ) gieucn = gieucn + gpi ** 2 nind = nind + 1 if ( nind .gt. nindprev .or. ind(nind) .ne. i ) then sameface = .false. end if ind(nind) = i end if end do xeucn = sqrt( xeucn ) gpeucn = sqrt( gpeucn ) gieucn = sqrt( gieucn ) C To be used in feasibility problems, compute constraints norm call sevalfeas(n,x,m,equatn,cnorm,cnormu,inform) if ( inform .lt. 0 ) return C Print information of this iteration if ( iprintinn .eq. 1 ) then if ( mod(iter,10) .eq. 0 ) then write(* ,1040) write(10,1040) end if write(* ,1060) iter,f,gpsupn,xsupn,ssupn,nind,outit,innit,fcnt write(10,1060) iter,f,gpsupn,xsupn,ssupn,nind,outit,innit,fcnt else if ( iprintinn .ge. 2 ) then write(* ,1070) iter,ittext(ittype) write(10,1070) iter,ittext(ittype) if ( iprintinn .ge. 3 ) then write(* ,1080) outit,innit,fcnt,cgcnt,nwcnt write(10,1080) outit,innit,fcnt,cgcnt,nwcnt end if write(* ,1090) f,gpsupn,gpeucn,gisupn,gieucn,xind,xsupn,xeucn, + ssupn,seucn write(10,1090) f,gpsupn,gpeucn,gisupn,gieucn,xind,xsupn,xeucn, + ssupn,seucn if ( iprintinn .ge. 4 .and. nprint .ne. 0 ) then write(* ,1100) min(nprint,nind),nind, + (ind(i),i=1,min(nprint,nind)) write(* ,1110) nprint,(x(i),i=1,nprint) write(* ,1130) nprint,(g(i),i=1,nprint) write(* ,1140) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i), + i=1,nprint) write(10,1100) min(nprint,nind),nind, + (ind(i),i=1,min(nprint,nind)) write(10,1110) nprint,(x(i),i=1,nprint) write(10,1130) nprint,(g(i),i=1,nprint) write(10,1140) nprint,(min(u(i),max(l(i),x(i)-g(i)))-x(i), + i=1,nprint) end if end if C SAVING INTERMEDIATE DATA FOR CRASH REPORT open(20,file='gencan-tabline.out') write(20,1060) iter,f,gpsupn,xsupn,ssupn,nind,outit,innit,fcnt close(20) C ================================================================== C Test line-search related stopping criteria C ================================================================== C Test whether the functional value is unbounded if ( lsinfo .eq. UNBOUNDED ) then geninfo = 6 if ( iprintinn .ge. 1 ) then write(*, 1260) write(10,1260) end if return end if C Test whether the line search did a very small step if ( lsinfo .eq. SMALLSTEP ) then geninfo = 7 if ( iprintinn .ge. 1 ) then write(*, 1270) write(10,1270) end if return end if C ================================================================== C Iterate C ================================================================== go to 100 C ================================================================== C End of main loop C ================================================================== C NON-EXECUTABLE STATEMENTS 1000 format(/,5X,'Entry to GENCAN.', + /,5X,'Number of variables: ',I7) 1010 format(/,5X,'Lower bounds (first ',I7,' components):', + /,(5X, 6(1X,1P,D11.4))) 1020 format(/,5X,'Upper bounds (first ',I7,' components):', + /,(5X, 6(1X,1P,D11.4))) 1030 format(/,5X,'Initial point (first ',I7,' components):', + /,(5X, 6(1X,1P,D11.4))) 1040 format(/,5X,'It',16X,'f',2X,'gpsupn',3X,'xsupn',3X,'ssupn',4X, + 'nind',3X,'outit',3X,'innit',4X,'fcnt') 1050 format( I7,1X,1P,D16.8,2(1X,1P,D7.1)) 1060 format( I7,1X,1P,D16.8,3(1X,1P,D7.1),4(1X,I7)) 1070 format(/,5X,'GENCAN ITERATION ',17X,'= ',I7,1X,A19) 1080 format(/,5X,'Leaving-face iterations ',17X,'= ',I7, + /,5X,'Inner-to-the-face iterations ',17X,'= ',I7, + /,5X,'Functional evaluations ',17X,'= ',I7, + /,5X,'Conjugate gradient iterations',17X,'= ',I7, + /,5X,'Matrix factorizations ',17X,'= ',I7) 1090 format(/,5X,'Functional value = ', + 1P,D24.16, + /,5X,'Sup-norm of the continuous projected gradient = ', + 1P,D7.1,' 2-norm = ',1P,D7.1, + /,5X,'Sup-norm of the internal projection of gp = ', + 1P,D7.1,' 2-norm = ',1P,D7.1, + /,5X,'Sup-norm of x (attained at x_{', I7,'}) = ', + 1P,D7.1,' 2-norm = ',1P,D7.1, + /,5X,'Sup-norm of x - x_{prev} = ', + 1P,D7.1,' 2-norm = ',1P,D7.1) 1100 format(/,5X,'Current free variables (first ',I7,', total ', + 'number ',I7,'): ', + /,(5X, 6(1X,I7))) 1110 format(/,5X,'Current point (first ',I7, ' components): ', + /,(5X, 6(1X,1P,D11.4))) 1130 format(/,5X,'Current gradient (first ',I7,' components): ', + /,(5X, 6(1X,1P,D11.4))) 1140 format(/,5X,'Current continuous projected gradient (first ',I7, + 5X,'components): ', + /,(5X, 6(1X,1P,D11.4))) 1200 format(/,5X,'Flag of GENCAN: Solution was found.',/) 1210 format(/,5X,'Flag of GENCAN: Maximum of iterations reached.',/) 1220 format(/,5X,'Flag of GENCAN: Maximum of functional evaluations ', + 'reached.',/) 1230 format(/,5X,'Flag of GENCAN: Lack of progress in the ', + 'functional value.', + /,5X,'Probably, an exaggerated small norm of the ', + 'continuous projected gradient', + /,5X,'is being required for declaring convergence.',/) 1240 format(/,5X,'Flag of GENCAN: Lack of progress in the gradient ', + 'norm.', + /,5X,'Probably, an exaggerated small norm of the ', + 'continuous projected gradient', + /,5X,'is being required for declaring convergence.',/) 1250 format(/,5X,'Flag of GENCAN: Lack of progress in the current ', + 'point.', + /,5X,'Probably, an exaggerated small norm of the ', + 'continuous projected gradient', + /,5X,'is being required for declaring convergence.',/) 1260 format(/,5X,'Flag of GENCAN: Objective function seems to be ', + 'unbounded.',/) 1270 format(/,5X,'Flag of GENCAN: Too small step in the line search.', + /,5X,'Probably, an exaggerated small norm of the ', + 'continuous projected gradient', + /,5X,'is being required for declaring convergence.',/) 1280 format(/,5X,'Flag of GENCAN: User-provided stopping criterion ', + 'satisfied.',/) 1400 format(1X,1P,D24.16,1X,1P,D7.1,1X,1P,D24.16,1X,1P,D7.1,1X,1P,D7.1, + 1X,I3,1X,I1,1X,I6,1X,I6,1X,I2,1X,I7,1X,I7,1X,I2,1X,I7,1X, + I7,1X,I7,0P,F8.2) end C ****************************************************************** C ****************************************************************** subroutine compamax(nind,x,l,u,d,amax,rbdnnz,rbdind,rbdtype) implicit none C SCALAR ARGUMENTS integer nind,rbdnnz double precision amax C ARRAY ARGUMENTS integer rbdind(nind) character rbdtype(nind) double precision d(nind),l(nind),u(nind),x(nind) C Compute maximum step amax > 0 such that l <= x + amax d <= u. #include "dim.par" #include "machconst.com" C LOCAL SCALARS integer i double precision amaxi rbdnnz = 0 amax = bignum do i = 1,nind if ( d(i) .gt. 0.0d0 ) then amaxi = ( u(i) - x(i) ) / d(i) if ( amaxi .lt. amax ) then amax = amaxi rbdnnz = 1 rbdind(1) = i rbdtype(1) = 'U' else if ( amaxi .eq. amax ) then rbdnnz = rbdnnz + 1 rbdind(rbdnnz) = i rbdtype(rbdnnz) = 'U' end if else if ( d(i) .lt. 0.0d0 ) then amaxi = ( l(i) - x(i) ) / d(i) if ( amaxi .lt. amax ) then amax = amaxi rbdnnz = 1 rbdind(1) = i rbdtype(1) = 'L' else if ( amaxi .eq. amax ) then rbdnnz = rbdnnz + 1 rbdind(rbdnnz) = i rbdtype(rbdnnz) = 'L' end if end if end do end