Linesearch without derivatives (used by slsqp if linesearch_mode=2
).
Returns the abscissa approximating the point where f
attains a minimum.
to find the argument linmin where the function f
takes it's minimum
on the interval ax
, bx
. It uses a combination of golden section
and successive quadratic interpolation.
This function subprogram is a slightly modified version of the
ALGOL 60 procedure localmin
given in R.P. Brent:
"Algorithms for minimization without derivatives",
Prentice-Hall (1973).
inout
s to make the routine thread-safe.Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(inout) | :: | mode |
controls reverse communication must be set to 0 initially, returns with intermediate values 1 and 2 which must not be changed by the user, ends with convergence with value 3. |
||
real(kind=wp), | intent(in) | :: | ax |
left endpoint of initial interval |
||
real(kind=wp), | intent(in) | :: | bx |
right endpoint of initial interval |
||
real(kind=wp) | :: | f |
function value at |
|||
real(kind=wp), | intent(in) | :: | tol |
desired length of interval of uncertainty of final result |
||
real(kind=wp), | intent(inout) | :: | a | |||
real(kind=wp), | intent(inout) | :: | b | |||
real(kind=wp), | intent(inout) | :: | d | |||
real(kind=wp), | intent(inout) | :: | e | |||
real(kind=wp), | intent(inout) | :: | p | |||
real(kind=wp), | intent(inout) | :: | q | |||
real(kind=wp), | intent(inout) | :: | r | |||
real(kind=wp), | intent(inout) | :: | u | |||
real(kind=wp), | intent(inout) | :: | v | |||
real(kind=wp), | intent(inout) | :: | w | |||
real(kind=wp), | intent(inout) | :: | x | |||
real(kind=wp), | intent(inout) | :: | m | |||
real(kind=wp), | intent(inout) | :: | fu | |||
real(kind=wp), | intent(inout) | :: | fv | |||
real(kind=wp), | intent(inout) | :: | fw | |||
real(kind=wp), | intent(inout) | :: | fx | |||
real(kind=wp), | intent(inout) | :: | tol1 | |||
real(kind=wp), | intent(inout) | :: | tol2 |
real(wp) function linmin(mode,ax,bx,f,tol,& a,b,d,e,p,q,r,u,v,& w,x,m,fu,fv,fw,fx,tol1,tol2) implicit none integer,intent(inout) :: mode !! controls reverse communication !! must be set to 0 initially, returns with intermediate !! values 1 and 2 which must not be changed by the user, !! ends with convergence with value 3. real(wp) :: f !! function value at `linmin` which is to be brought in by !! reverse communication controlled by `mode` real(wp),intent(in) :: tol !! desired length of interval of uncertainty of final result real(wp),intent(in) :: ax !! left endpoint of initial interval real(wp),intent(in) :: bx !! right endpoint of initial interval real(wp),intent(inout) :: a,b,d,e,p,q,r,u,v,w,x,m,fu,fv,fw,fx,tol1,tol2 real(wp),parameter :: c = (3.0_wp-sqrt(5.0_wp))/2.0_wp !! golden section ratio = `0.381966011` real(wp),parameter :: sqrteps = sqrt(eps) !! square root of machine precision select case (mode) case(1) ! main loop starts here fx = f fv = fx fw = fv case(2) fu = f ! update a, b, v, w, and x if ( fu>fx ) then if ( u<x ) a = u if ( u>=x ) b = u if ( fu<=fw .or. abs(w-x)<=zero ) then v = w fv = fw w = u fw = fu else if ( fu<=fv .or. abs(v-x)<=zero .or. abs(v-w)<=zero ) then v = u fv = fu end if else if ( u>=x ) a = x if ( u<x ) b = x v = w fv = fw w = x fw = fx x = u fx = fu end if case default ! initialization a = ax b = bx e = zero v = a + c*(b-a) w = v x = w linmin = x mode = 1 return end select m = 0.5_wp*(a+b) tol1 = sqrteps*abs(x) + tol tol2 = tol1 + tol1 ! test convergence if ( abs(x-m)<=tol2-0.5_wp*(b-a) ) then ! end of main loop linmin = x mode = 3 else r = zero q = r p = q if ( abs(e)>tol1 ) then ! fit parabola r = (x-w)*(fx-fv) q = (x-v)*(fx-fw) p = (x-v)*q - (x-w)*r q = q - r q = q + q if ( q>zero ) p = -p if ( q<zero ) q = -q r = e e = d end if ! is parabola acceptable if ( abs(p)>=0.5_wp*abs(q*r) .or. p<=q*(a-x) .or. p>=q*(b-x) ) then ! golden section step if ( x>=m ) e = a - x if ( x<m ) e = b - x d = c*e else ! parabolic interpolation step d = p/q ! f must not be evaluated too close to a or b if ( u-a<tol2 ) d = sign(tol1,m-x) if ( b-u<tol2 ) d = sign(tol1,m-x) end if ! f must not be evaluated too close to x if ( abs(d)<tol1 ) d = sign(tol1,d) u = x + d linmin = u mode = 2 end if end function linmin