1
+ export DiagonalQN, SpectralGradient
2
+
1
3
function mulSquareOpDiagonal! (res, d, v, α, β:: T ) where {T <: Real }
2
4
if β == zero (T)
3
5
res .= α .* d .* v
@@ -13,7 +15,8 @@ Andrei, N.
13
15
A diagonal quasi-Newton updating method for unconstrained optimization.
14
16
https://doi.org/10.1007/s11075-018-0562-7
15
17
"""
16
- mutable struct DiagonalQN{T <: Real , I <: Integer , V <: AbstractVector{T} } <: AbstractDiagonalQuasiNewtonOperator{T}
18
+ mutable struct DiagonalQN{T <: Real , I <: Integer , V <: AbstractVector{T} } < :
19
+ AbstractDiagonalQuasiNewtonOperator{T}
17
20
d:: V # Diagonal of the operator
18
21
nrow:: I
19
22
ncol:: I
@@ -30,43 +33,54 @@ mutable struct DiagonalQN{T <: Real, I <: Integer, V <: AbstractVector{T}} <: Ab
30
33
allocated5:: Bool # true for 5-args mul!, false for 3-args mul! until the vectors are allocated
31
34
end
32
35
33
- DiagonalQN (d:: AbstractVector{T} ) where {T <: Real } =
34
- DiagonalQN (
35
- d,
36
- length (d),
37
- length (d),
38
- true ,
39
- true ,
40
- (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
41
- (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
42
- (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
43
- 0 ,
44
- 0 ,
45
- 0 ,
46
- true ,
47
- true ,
48
- true )
36
+ """
37
+ DiagonalQN(d)
38
+
39
+ Construct a linear operator that represents a diagonal quasi-Newton approximation.
40
+ The approximation satisfies the weak secant equation and is not guaranteed to be
41
+ positive definite.
42
+
43
+ # Arguments
44
+
45
+ - `d::AbstractVector`: initial diagonal approximation.
46
+ """
47
+ DiagonalQN (d:: AbstractVector{T} ) where {T <: Real } = DiagonalQN (
48
+ d,
49
+ length (d),
50
+ length (d),
51
+ true ,
52
+ true ,
53
+ (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
54
+ (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
55
+ (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
56
+ 0 ,
57
+ 0 ,
58
+ 0 ,
59
+ true ,
60
+ true ,
61
+ true ,
62
+ )
49
63
50
64
# update function
51
65
# s = x_{k+1} - x_k
52
66
# y = ∇f(x_{k+1}) - ∇f(x_k)
53
67
function push! (
54
- B:: DiagonalQN{T,I, V} ,
68
+ B:: DiagonalQN{T, I, V} ,
55
69
s:: V ,
56
- y:: V
57
- ) where {T <: Real , I <: Integer , V <: AbstractVector{T} }
70
+ y:: V ,
71
+ ) where {T <: Real , I <: Integer , V <: AbstractVector{T} }
58
72
trA2 = zero (T)
59
73
for i in eachindex (s)
60
74
trA2 += s[i]^ 4
61
75
end
62
- sT_s = dot (s,s)
63
- sT_y = dot (s,y)
76
+ sT_s = dot (s, s)
77
+ sT_y = dot (s, y)
64
78
sT_B_s = sum (s[i]^ 2 * B. d[i] for i ∈ eachindex (s))
65
79
if trA2 == 0
66
80
error (" Cannot divide by zero and trA2 = 0" )
67
81
end
68
- q = (sT_y + sT_s - sT_B_s)/ trA2
69
- B. d .+ = q .* s.^ 2 .- 1
82
+ q = (sT_y + sT_s - sT_B_s) / trA2
83
+ B. d .+ = q .* s .^ 2 .- 1
70
84
return B
71
85
end
72
86
@@ -77,7 +91,7 @@ Birgin, E. G., Martínez, J. M., & Raydan, M.
77
91
Spectral Projected Gradient Methods: Review and Perspectives.
78
92
https://doi.org/10.18637/jss.v060.i03
79
93
"""
80
- mutable struct SpectralGradient{T <: Real , I <: Integer } <: AbstractDiagonalQuasiNewtonOperator{T}
94
+ mutable struct SpectralGradient{T <: Real , I <: Integer } <: AbstractDiagonalQuasiNewtonOperator{T}
81
95
d:: T # Diagonal coefficient of the operator (multiple of the identity)
82
96
nrow:: I
83
97
ncol:: I
@@ -94,34 +108,48 @@ mutable struct SpectralGradient{T <: Real, I <: Integer} <: AbstractDiagonalQuas
94
108
allocated5:: Bool # true for 5-args mul!, false for 3-args mul! until the vectors are allocated
95
109
end
96
110
97
- SpectralGradient (d:: T , n:: I ) where {T <: Real , I <: Integer } =
111
+ """
112
+ SpectralGradient(σ, n)
113
+
114
+ Construct a spectral gradient Hessian approximation.
115
+ The approximation is defined as σI.
116
+
117
+ # Arguments
118
+
119
+ - `σ::Real`: initial positive multiple of the identity;
120
+ - `n::Int`: operator size.
121
+ """
122
+ function SpectralGradient (d:: T , n:: I ) where {T <: Real , I <: Integer }
123
+ @assert d > 0
98
124
SpectralGradient (
99
125
d,
100
126
n,
101
127
n,
102
128
true ,
103
- true ,
104
- (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
105
- (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
106
- (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
129
+ true ,
130
+ (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
131
+ (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
132
+ (res, v, α, β) -> mulSquareOpDiagonal! (res, d, v, α, β),
107
133
0 ,
108
134
0 ,
109
135
0 ,
110
136
true ,
111
137
true ,
112
- true )
138
+ true ,
139
+ )
140
+ end
113
141
114
142
# update function
115
143
# s = x_{k+1} - x_k
116
144
# y = ∇f(x_{k+1}) - ∇f(x_k)
117
145
function push! (
118
- B:: SpectralGradient{T,I} ,
146
+ B:: SpectralGradient{T, I} ,
119
147
s:: V ,
120
- y:: V
121
- ) where {T <: Real , I <: Integer , V <: AbstractVector{T} }
148
+ y:: V ,
149
+ ) where {T <: Real , I <: Integer , V <: AbstractVector{T} }
122
150
if all (s .== 0 )
123
151
error (" Cannot divide by zero and s .= 0" )
124
152
end
125
- B. d = dot (s,y) / dot (s,s)
153
+ B. d = dot (s, y) / dot (s, s)
126
154
return B
127
- end
155
+ end
0 commit comments