-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathlbfgs.jl
More file actions
101 lines (88 loc) · 2.06 KB
/
lbfgs.jl
File metadata and controls
101 lines (88 loc) · 2.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
mutable struct LBFGSOperator{M,R,I,T}
currmem::I
curridx::I
s::T
y::T
s_M::Vector{T}
y_M::Vector{T}
ys_M::Vector{R}
alphas::Vector{R}
H::R
end
function LBFGSOperator{M}(x::T) where {M,T}
R = real(eltype(x))
s_M = [zero(x) for i = 1:M]
y_M = [zero(x) for i = 1:M]
s = zero(x)
y = zero(x)
ys_M = zeros(R, M)
alphas = zeros(R, M)
LBFGSOperator{M,R,typeof(0),T}(0, 0, s, y, s_M, y_M, ys_M, alphas, one(R))
end
LBFGSOperator(M, x) = LBFGSOperator{M}(x)
function update!(L::LBFGSOperator{M}, s, y) where {M}
L.s .= s
L.y .= y
ys = real(dot(L.s, L.y))
if ys > 0
L.curridx += 1
if L.curridx > M
L.curridx = 1
end
L.currmem += 1
if L.currmem > M
L.currmem = M
end
L.ys_M[L.curridx] = ys
copyto!(L.s_M[L.curridx], L.s)
copyto!(L.y_M[L.curridx], L.y)
yty = real(dot(L.y, L.y))
L.H = ys / yty
end
return L
end
function reset!(L::LBFGSOperator{M,R,I}) where {M,R,I}
L.currmem, L.curridx = zero(I), zero(I)
L.H = one(R)
end
function (*)(L::LBFGSOperator, v)
w = similar(v)
mul!(w, L, v)
end
# Two-loop recursion
function mul!(d, L::LBFGSOperator, v)
d .= v
idx = loop1!(d, L)
d .*= L.H
loop2!(d, idx, L)
return d
end
function loop1!(d, L::LBFGSOperator{M}) where {M}
idx = L.curridx
for i = 1:L.currmem
L.alphas[idx] = real(dot(L.s_M[idx], d)) / L.ys_M[idx]
d .-= L.alphas[idx] .* L.y_M[idx]
idx -= 1
if idx == 0
idx = M
end
end
return idx
end
function loop2!(d, idx, L::LBFGSOperator{M}) where {M}
for i = 1:L.currmem
idx += 1
if idx > M
idx = 1
end
beta = real(dot(L.y_M[idx], d)) / L.ys_M[idx]
d .+= (L.alphas[idx] - beta) .* L.s_M[idx]
end
return d
end
struct LBFGS{M} end
LBFGS(M) = LBFGS{M}()
acceleration_style(::Type{<:LBFGS}) = QuasiNewtonStyle()
function initialize(::LBFGS{M}, x) where {M}
return LBFGSOperator{M}(x)
end