@@ -18,9 +18,9 @@ julia> d = L*grad; # compute new direction
1818```
1919"""
2020
21- mutable struct LBFGS{R, T <: BlockArray , M} <: LinearOperator
22- currmem:: Integer
23- curridx:: Integer
21+ mutable struct LBFGS{R, T <: BlockArray , M, I <: Integer } <: LinearOperator
22+ currmem:: I
23+ curridx:: I
2424 s:: T
2525 y:: T
2626 s_M:: Array{T, 1}
@@ -30,14 +30,32 @@ mutable struct LBFGS{R, T <: BlockArray, M} <: LinearOperator
3030 H:: R
3131end
3232
33- function LBFGS (x:: T , M:: Integer ) where {R, T <: BlockArray{R} }
33+ function LBFGS (x:: T , M:: I ) where {T <: BlockArray , I <: Integer }
3434 s_M = [blockzeros (x) for i = 1 : M]
3535 y_M = [blockzeros (x) for i = 1 : M]
3636 s = blockzeros (x)
3737 y = blockzeros (x)
3838 ys_M = zeros (M)
3939 alphas = zeros (M)
40- LBFGS {R, T, M} (0 , 0 , s, y, s_M, y_M, ys_M, alphas, one (R))
40+ R = real (eltype (x[1 ]))
41+ LBFGS {R, T, M, I} (0 , 0 , s, y, s_M, y_M, ys_M, alphas, one (R))
42+ end
43+
44+ function LBFGS (domainType:: D , dim:: T , M:: I ) where {D <: Type ,
45+ T <: Tuple , I <: Integer }
46+ x = blockzeros (domainType, dim)
47+ return LBFGS (x,M)
48+ end
49+
50+ function LBFGS (domainType:: D , dim:: T , M:: I ) where {N, D <: NTuple{N,Type} ,
51+ T <: NTuple{N,Tuple} , I <: Integer }
52+ x = blockzeros (domainType, dim)
53+ return LBFGS (x,M)
54+ end
55+
56+ function LBFGS (dim:: T , M:: I ) where {T <: Tuple , I <: Integer }
57+ x = blockzeros (dim)
58+ return LBFGS (x,M)
4159end
4260
4361"""
4664See the documentation for `LBFGS`.
4765"""
4866
49- function update! (L:: LBFGS{R, T, M} , x:: T , x_prev:: T , gradx:: T , gradx_prev:: T ) where {R, T, M}
67+ function update! (L:: LBFGS{R, T, M, I } , x:: T , x_prev:: T , gradx:: T , gradx_prev:: T ) where {R, T, M, I }
5068 L. s .= x .- x_prev
5169 L. y .= gradx .- gradx_prev
5270 ys = real (blockvecdot (L. s, L. y))
@@ -58,49 +76,49 @@ function update!(L::LBFGS{R, T, M}, x::T, x_prev::T, gradx::T, gradx_prev::T) wh
5876 L. ys_M[L. curridx] = ys
5977 blockcopy! (L. s_M[L. curridx], L. s)
6078 blockcopy! (L. y_M[L. curridx], L. y)
61- yty = real (vecdot (L. y, L. y))
79+ yty = real (blockvecdot (L. y, L. y))
6280 L. H = ys/ yty
6381 end
6482 return L
6583end
6684
6785# LBFGS operators are symmetric
6886
69- Ac_mul_B! (x:: T , L:: LBFGS{R, T, M} , y:: T ) where {R, T, M} = A_mul_B! (x, L, y)
87+ Ac_mul_B! (x:: T , L:: LBFGS{R, T, M, I } , y:: T ) where {R, T, M, I } = A_mul_B! (x, L, y)
7088
7189# Two-loop recursion
7290
73- function A_mul_B! (d:: T , L:: LBFGS{R, T, M} , gradx:: T ) where {R, T, M}
91+ function A_mul_B! (d:: T , L:: LBFGS{R, T, M, I } , gradx:: T ) where {R, T, M, I }
7492 d .= gradx
7593 idx = loop1! (d,L)
7694 d .= (* ). (L. H, d)
7795 d = loop2! (d,idx,L)
7896end
7997
80- function loop1! (d:: T , L:: LBFGS{R, T, M} ) where {R, T, M}
98+ function loop1! (d:: T , L:: LBFGS{R, T, M, I } ) where {R, T, M, I }
8199 idx = L. curridx
82100 for i = 1 : L. currmem
83- L. alphas[idx] = real (vecdot (L. s_M[idx], d))/ L. ys_M[idx]
101+ L. alphas[idx] = real (blockvecdot (L. s_M[idx], d))/ L. ys_M[idx]
84102 d .- = L. alphas[idx] .* L. y_M[idx]
85103 idx -= 1
86104 if idx == 0 idx = M end
87105 end
88106 return idx
89107end
90108
91- function loop2! (d:: T , idx:: Int , L:: LBFGS{R, T, M} ) where {R, T, M}
109+ function loop2! (d:: T , idx:: Int , L:: LBFGS{R, T, M, I } ) where {R, T, M, I }
92110 for i = 1 : L. currmem
93111 idx += 1
94112 if idx > M idx = 1 end
95- beta = real (vecdot (L. y_M[idx], d))/ L. ys_M[idx]
113+ beta = real (blockvecdot (L. y_M[idx], d))/ L. ys_M[idx]
96114 d .+ = (L. alphas[idx] - beta) .* L. s_M[idx]
97115 end
98116 return d
99117end
100118
101119# Properties
102- domainType (L:: LBFGS{R, T, M} ) where {R, T, M} = T
103- codomainType (L:: LBFGS{R, T, M} ) where {R, T, M} = T
120+ domainType (L:: LBFGS{R, T, M} ) where {R, T, M} = blockeltype (L . y_M[ 1 ])
121+ codomainType (L:: LBFGS{R, T, M} ) where {R, T, M} = blockeltype (L . y_M[ 1 ])
104122
105123size (A:: LBFGS ) = (blocksize (A. s), blocksize (A. s))
106124
0 commit comments