Advertisement
Guest User

Quasi Newton Method

a guest
Oct 27th, 2021
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Julia 1.59 KB | None | 0 0
  1. abstract type
  2.     DescentMethod
  3. end
  4.  
  5. mutable struct BFGS <: DescentMethod
  6.     Q
  7. end
  8.  
  9. function bracket_minimum(f, x=0; s=1e-2, k=2.0)
  10.     a, ya = x, f(x)
  11.     b, yb = a + s, f(a + s)
  12.     if yb > ya
  13.         a, b = b, a
  14.         ya, yb = yb, ya
  15.         s = -s
  16.     end
  17.     while true
  18.         c, yc = b + s, f(b + s)
  19.         if yc > yb
  20.             return a < c ? (a, c) : (c, a)
  21.         end
  22.         a, ya, b, yb = b, yb, c, yc
  23.         s *= k
  24.     end
  25. end
  26.  
  27. function minimize(f, a, b)
  28.     a = convert(Float64, a)
  29.     b = convert(Float64, b)
  30.     return Optim.optimize(f, a, b).minimizer
  31. end
  32.  
  33. function line_search(f, x, d)
  34.     objective = α -> f(x .+ α*vec(d))
  35.     a, b = bracket_minimum(objective)
  36.     α = minimize(objective, a, b)
  37.     return x + α*d
  38. end
  39.  
  40. function init!(M::BFGS, f, ∇f, x)
  41.     m = length(x)
  42.     M.Q = Matrix(1.0I, m, m)
  43.     return M
  44. end
  45.  
  46. function step!(M::BFGS, f, ∇f, x)
  47.     Q, g = M.Q, ∇f(x)
  48.     x′ = line_search(f, x, - Q*g)
  49.     g′ = ∇f(x′)
  50.     δ = x′ - x
  51.     γ = g′ - g
  52.     Q[:] = Q - (δ*γ'*Q + Q*γ*δ')/(δ'*γ) + (1 + (γ'*Q*γ)/(δ'*γ))[1]*(δ*δ')/(δ'*γ)
  53.    return x′
  54. end
  55.  
  56. function quasi_method(f, g, x0)
  57.    xʼ = x0
  58.    Q = 0.0005
  59.    n = 10000
  60.    QN = BFGS(Q)
  61.    init!(QN, f, g, xʼ)
  62.  
  63.    i = 0
  64.    prev = 0
  65.    while i <= n
  66.        i += 1
  67.        xʼ = step!(QN, f, g, xʼ)
  68.        if prev == xʼ
  69.            break
  70.        else
  71.            prev = xʼ
  72.        end
  73.    end
  74.    return xʼ,f(xʼ),i
  75. end
  76.  
  77. k(x) = x .^ 2 + 15*x
  78. l(x) = ForwardDiff.jacobian(k, x)
  79. res = quasi_method(k, l, [-5.0, -2.0])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement