1
- export check_ctranspose, check_hermitian, check_positive_definite, normest
1
+ export check_ctranspose, check_hermitian, check_positive_definite, normest, solve_shifted_system!, ldiv!
2
+ import LinearAlgebra. ldiv!
2
3
3
4
"""
4
5
normest(S) estimates the matrix 2-norm of S.
@@ -145,3 +146,141 @@ end
145
146
146
147
check_positive_definite (M:: AbstractMatrix ; kwargs... ) =
147
148
check_positive_definite (LinearOperator (M); kwargs... )
149
+
150
+
151
+ """
152
+ solve_shifted_system!(x, B, b, σ)
153
+
154
+ Solve linear system (B + σI) x = b, where B is a forward L-BFGS operator and σ ≥ 0.
155
+
156
+ ### Parameters
157
+
158
+ - `x::AbstractVector{T}`: preallocated vector of length n that is used to store the solution x.
159
+ - `B::LBFGSOperator`: forward L-BFGS operator that models a matrix of size n x n.
160
+ - `b::AbstractVector{T}`: right-hand side vector of length n.
161
+ - `σ::T`: nonnegative shift.
162
+
163
+ ### Returns
164
+
165
+ - `x::AbstractVector{T}`: solution vector `x` of length n.
166
+
167
+ ### Method
168
+
169
+ The method uses a two-loop recursion-like approach with modifications to handle the shift `σ`.
170
+
171
+ ### Example
172
+
173
+ ```julia
174
+ using Random
175
+
176
+ # Problem setup
177
+ n = 100 # size of the problem
178
+ mem = 10 # L-BFGS memory size
179
+ scaling = true # enable scaling
180
+
181
+ # Create an L-BFGS operator
182
+ B = LBFGSOperator(n, mem = mem, scaling = scaling)
183
+
184
+ # Add random {s, y} pairs to the L-BFGS operator
185
+ for _ = 1:10
186
+ s = rand(n)
187
+ y = rand(n)
188
+ push!(B, s, y) # Add the {s, y} pair to B
189
+ end
190
+
191
+ # Prepare vectors for the system
192
+ x = zeros(n) # Preallocated solution vector
193
+ b = rand(n) # Right-hand side vector
194
+ σ = 0.1 # Small shift value
195
+
196
+ # Solve the shifted system
197
+ result = solve_shifted_system!(x, B, b, σ)
198
+
199
+ # Check that the solution is close enough (residual test)
200
+ @assert norm(B * x + σ * x - b) / norm(b) < 1e-8
201
+ ```
202
+
203
+ ### References
204
+
205
+ Erway, J. B., Jain, V., & Marcia, R. F. Shifted L-BFGS Systems. Optimization Methods and Software, 29(5), pp. 992-1004, 2014.
206
+ """
207
+ function solve_shifted_system! (
208
+ x:: AbstractVector{T} ,
209
+ B:: LBFGSOperator{T, I, F1, F2, F3} ,
210
+ b:: AbstractVector{T} ,
211
+ σ:: T ,
212
+ ) where {T, I, F1, F2, F3}
213
+
214
+ if σ < 0
215
+ throw (ArgumentError (" σ must be nonnegative" ))
216
+ end
217
+ data = B. data
218
+ insert = data. insert
219
+
220
+ γ_inv = 1 / data. scaling_factor
221
+ x_0 = 1 / (γ_inv + σ)
222
+ @. x = x_0 * b
223
+
224
+ max_i = 2 * data. mem
225
+ sign_i = 1
226
+
227
+ for i = 1 : max_i
228
+ j = (i + 1 ) ÷ 2
229
+ k = mod (insert + j - 1 , data. mem) + 1
230
+ data. shifted_u .= ((sign_i == - 1 ) ? data. b[k] : data. a[k])
231
+
232
+ @. data. shifted_p[:, i] = x_0 * data. shifted_u
233
+
234
+ sign_t = 1
235
+ for t = 1 : (i - 1 )
236
+ c0 = dot (view (data. shifted_p, :, t), data. shifted_u)
237
+ c1= sign_t .* data. shifted_v[t]
238
+ c2 = c1 * c0
239
+ view (data. shifted_p, :, i) .+ = c2 .* view (data. shifted_p, :, t)
240
+ sign_t = - sign_t
241
+ end
242
+
243
+ data. shifted_v[i] = 1 / (1 - sign_i * dot (data. shifted_u, view (data. shifted_p, :, i)))
244
+ x .+ = sign_i * data. shifted_v[i] * (view (data. shifted_p, :, i)' * b) .* view (data. shifted_p, :, i)
245
+ sign_i = - sign_i
246
+ end
247
+ return x
248
+ end
249
+
250
+
251
+ """
252
+ ldiv!(x, B, b)
253
+
254
+ Solves the linear system Bx = b.
255
+
256
+ ### Arguments:
257
+
258
+ - `x::AbstractVector{T}`: preallocated vector of length n that is used to store the solution x.
259
+ - `B::LBFGSOperator`: forward L-BFGS operator that models a matrix of size n x n.
260
+ - `b::AbstractVector{T}`: right-hand side vector of length n.
261
+ ### Returns:
262
+
263
+ - `x::AbstractVector{T}`: The modified solution vector containing the solution to the linear system.
264
+
265
+ ### Examples:
266
+
267
+ ```julia
268
+
269
+ # Create an L-BFGS operator
270
+ B = LBFGSOperator(10)
271
+
272
+ # Generate random vectors
273
+ x = rand(10)
274
+ b = rand(10)
275
+
276
+ # Solve the linear system
277
+ ldiv!(x, B, b)
278
+
279
+ # The vector `x` now contains the solution
280
+ """
281
+
282
+ function ldiv! (x:: AbstractVector{T} , B:: LBFGSOperator{T, I, F1, F2, F3} , b:: AbstractVector{T} ) where {T, I, F1, F2, F3}
283
+ # Call solve_shifted_system! with σ = 0
284
+ solve_shifted_system! (x, B, b, T (0.0 ))
285
+ return x
286
+ end
0 commit comments