https://github.com/cran/nleqslv
Raw File
Tip revision: 29fbf340091cecba11cd5ffd76935f5c7c6a6e70 authored by Berend Hasselman on 26 September 2010, 00:00:00 UTC
version 1.8
Tip revision: 29fbf34
nwtrup.f

      subroutine nwtrup(n,fcnorm,g,sc,nwtake,stepmx,xtol,dlt,
     *                  mxtake, fpred,retcd,xprev,fpnsav,fprev,xp,fp,
     *                  fpnorm,wrk)

      integer n,retcd
      double precision  fcnorm,stepmx,xtol,dlt,fpred,fpnsav,fpnorm
      double precision  xp(*),g(*)
      double precision  sc(*),xprev(*),fprev(*),fp(*),wrk(*)
      logical nwtake,mxtake

c-------------------------------------------------------------------------
c
c     Decide whether to accept xp=xc+sc as the next iterate
c     and updates the trust region dlt
c
c     Arguments
c
c     In       n       Integer         size of xc()
c     In       fcnorm  Real            .5*||f(xc)||**2
c     In       g       Real(*)         gradient at xc()
c     In       sc      Real(*)         current step
c     In       nwtake  Logical         true if sc is newton direction
c     In       stepmx  Real            maximum step size
c     In       xtol    Real            minimum step tolerance
c     Inout    dlt     Real            trust region radius
c     In       mxtake  Logical         true if max. step taken
c     In       fpred   Real            predicted value of .5*||f()||**2
c
c     Inout    retcd   Integer         return code
c                                       0 xp accepted as next iterate;
c                                         dlt trust region for next iteration.
c
c                                       1 xp unsatisfactory but
c                                         accepted as next iterate because
c                                         xp-xc .lt. smallest allowable
c                                         step length.
c
c                                       2 f(xp) too large.
c                                         continue current iteration with
c                                         new reduced dlt.
c
c                                       3 f(xp) sufficiently small, but
c                                         quadratic model predicts f(xp)
c                                         sufficiently well to continue current
c                                         iteration with new doubled dlt.
c
c                                      On first entry, retcd must be 4
c
c     Wk       xprev   Real(*)         (internal) work
c     Wk       fpnsav  Real            (internal) work
c     Wk       fprev   Real(*)         (internal) work
c     Inout    xp      Real(*)         new iterate x()
c     Inout    fp      Real(*)         new f(xp)
c     Inout    fpnorm  Real            new .5*||f(xp)||**2
c     Wk       wrk     Real(*)         (internal) work
c
c-------------------------------------------------------------------------

      double precision  ared,pred,slope,sclen,rln,dltmp
      double precision  dnrm2,ddot,nudnrm
      logical ret3ok

      double precision Rone, Rtwo, Rthree, Rfour, Rten 
      double precision Rhalf, Rpten, Rphund
      parameter(Rpten = 0.1d0)
      parameter(Rhalf=0.5d0)    
      parameter(Rone=1.0d0, Rtwo=2.0d0, Rthree=3.0d0, Rfour=4.0d0)
      parameter(Rten=10.0d0)

      double precision Rp99,Rp4, Rp75
      parameter(Rp99=Rone-Rten**(-2), Rp4=Rten**(-4), Rp75=Rthree/Rfour)

      double precision alpha
      parameter(alpha = Rp4)

      mxtake = .false.

c     ared measures the actual    reduction in the function value
c     pred measures the predicted reduction in the function value

      ared  = fpnorm - fcnorm
      pred  = fpred  - fcnorm
      slope = ddot(n,g,1,sc,1)

      if(retcd .ne. 3) then
         ret3ok = .false.
      else
         ret3ok = fpnorm .ge. fpnsav .or. ared .gt. alpha * slope
      endif

      if(retcd .eq. 3 .and. ret3ok) then

c        reset xp to xprev and terminate global step

         retcd = 0
         call dcopy(n,xprev,1,xp,1)
         call dcopy(n,fprev,1,fp,1)
         fpnorm = fpnsav
         dlt  = Rhalf*dlt

      elseif(ared .gt. alpha * slope) then

c        fpnorm too large (decrease not sufficient)

         rln = nudnrm(n,sc,xp)
         if(rln .lt. xtol) then

c           cannot find satisfactory xp sufficiently distinct from xc

            retcd = 1

         else

c           reduce trust region and continue global step

            retcd = 2
            sclen = dnrm2(n,sc,1)
            dltmp = -slope*sclen/(Rtwo*(ared-slope))

            if(dltmp .lt. Rpten*dlt) then
               dlt = Rpten*dlt
            else
               dlt = min(Rhalf*dlt, dltmp)
            endif

         endif

      elseif(retcd .ne. 2 .and. (abs(pred-ared) .le. Rpten*abs(ared))
     *      .and. (.not.nwtake) .and. (dlt.le. Rp99*stepmx)) then

c        fpnorm sufficiently small
c        to attempt a doubling of the trust region and continue global step

         call dcopy(n,xp,1,xprev,1)
         call dcopy(n,fp,1,fprev,1)
         fpnsav = fpnorm
         dlt    = min(Rtwo*dlt,stepmx)
         retcd  = 3

      else

c        fpnorm sufficiently small to accept xp as next iterate.
c        Choose new trust region.

         retcd = 0
         if(dlt .gt. Rp99*stepmx) mxtake = .true.
         if(ared .ge. Rpten*pred) then

c           Not good enough. Decrease trust region for next iteration

            dlt = Rhalf*dlt
         elseif( ared .le. Rp75*pred ) then

c           Wonderful. Increase trust region for next iteration

            dlt = min(Rtwo*dlt,stepmx)
         endif

      endif

      return
      end
back to top