variable metric update of a dense symmetric positive definite matrix using the factorization b=ldtrans(l).
bfgs variable metric method.
Note
This routine was formerly called pudbg1.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer | :: | n |
actual number of variables. |
|||
| real(kind=wp) | :: | h(*) |
h(m) factorization b=ldtrans(l) of a positive definite approximation of the hessian matrix. |
|||
| real(kind=wp) | :: | g(*) |
g(nf) gradient of the objective function. |
|||
| real(kind=wp) | :: | s(*) |
s(nf) auxiliary vector. |
|||
| real(kind=wp) | :: | xo(*) |
xo(nf) vectors of variables difference. |
|||
| real(kind=wp) | :: | go(*) |
go(nf) gradients difference. |
|||
| real(kind=wp) | :: | r |
value of the stepsize parameter. |
|||
| real(kind=wp) | :: | po |
old value of the directional derivative. |
|||
| integer | :: | nit |
actual number of iterations. |
|||
| integer | :: | kit |
number of the iteration after last restart. |
|||
| integer | :: | iterh |
termination indicator.
|
|||
| integer | :: | met | ||||
| integer | :: | met1 |
selection of self scaling.
|
|||
| integer | :: | mec |
correction if the negative curvature occurs.
|
subroutine bfgs_variable_metric_update(n, h, g, s, xo, go, r, po, nit, & kit, iterh, met, met1, mec) real(wp) :: po !! old value of the directional derivative. real(wp) :: r !! value of the stepsize parameter. integer :: iterh !! termination indicator. !! !! * iterh<0-bad decomposition. !! * iterh=0-successful update. !! * iterh>0-nonpositive parameters. integer :: kit !! number of the iteration after last restart. integer :: met !! integer :: met1 !! selection of self scaling. !! !! * met1=1-self scaling suppressed. !! * met1=2 initial self scaling. integer :: mec !! correction if the negative curvature occurs. !! !! * mec=1-correction suppressed. !! * mec=2-powell's correction. integer :: n !! actual number of variables. integer :: nit !! actual number of iterations. real(wp) :: g(*) !! g(nf) gradient of the objective function. real(wp) :: go(*) !! go(nf) gradients difference. real(wp) :: h(*) !! h(m) factorization b=l*d*trans(l) of a positive !! definite approximation of the hessian matrix. real(wp) :: s(*) !! s(nf) auxiliary vector. real(wp) :: xo(*) !! xo(nf) vectors of variables difference. real(wp) :: a, b, c, gam, par, den, dis logical :: l1, l3 l1 = met1 >= 3 .or. met1 == 2 .and. nit == kit l3 = .not. l1 ! determination of the parameters b, c b = mxvdot(n, xo, go) a = 0.0_wp if (l1) then call mxvcop(n, go, s) call mxdpgb(n, h, s, 1) a = mxdpgp(n, h, s, s) if (a <= 0.0_wp) then iterh = 1 return end if end if call mxvdif(n, go, g, s) call mxvscl(n, r, s, s) c = -r*po if (c <= 0.0_wp) then iterh = 3 return end if if (mec > 1) then if (b <= 1.0e-4_wp*c) then ! powell's correction dis = (1.0_wp - 0.1_wp)*c/(c - b) call mxvdif(n, go, s, go) call mxvdir(n, dis, go, s, go) b = c + dis*(b - c) if (l1) a = c + 2.0_wp*(1.0_wp - dis)*(b - c) + dis*dis*(a - c) end if elseif (b <= 1.0e-4_wp*c) then iterh = 2 return end if if (l1) then ! determination of the parameter gam (self scaling) if (met == 1) then par = c/b elseif (a <= 0.0_wp) then par = c/b else par = sqrt(c/a) end if gam = par if (met1 > 1) then if (nit /= kit) l3 = gam < 0.5_wp .or. gam > 4.0_wp end if end if if (l3) then gam = 1.0_wp par = gam end if if (met == 1) then ! bfgs update call mxdpgu(n, h, par/b, go, xo) call mxdpgu(n, h, -1.0_wp/c, s, xo) else ! hoshino update den = par*b + c dis = 0.5_wp*b call mxvdir(n, par, go, s, s) call mxdpgu(n, h, par/dis, go, xo) call mxdpgu(n, h, -1.0_wp/den, s, xo) end if iterh = 0 if (gam == 1.0_wp) return call mxdpgs(n, h, 1.0_wp/gam) end subroutine bfgs_variable_metric_update