Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

solve_shifted_system! method for LBFGS solving step in recursive way #338

Merged
merged 34 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
786bc0d
solve_shifted_system!
farhadrclass Sep 23, 2024
f95d210
Update src/utilities.jl
farhadrclass Sep 23, 2024
bac9f6f
Update src/utilities.jl
farhadrclass Sep 23, 2024
62d35f6
Update src/utilities.jl
farhadrclass Sep 23, 2024
186b6c5
Update src/utilities.jl
farhadrclass Sep 23, 2024
0d4f952
Update src/utilities.jl
farhadrclass Sep 23, 2024
4672bd3
Update src/utilities.jl
farhadrclass Sep 23, 2024
f3ea738
Update src/utilities.jl
farhadrclass Sep 23, 2024
4bf8f55
Update src/utilities.jl
farhadrclass Sep 23, 2024
025645e
Update src/utilities.jl
farhadrclass Sep 23, 2024
94fb35f
changes after review
farhadrclass Sep 23, 2024
ded60c1
Update src/lbfgs.jl
farhadrclass Sep 28, 2024
e5b054a
Update src/lbfgs.jl
farhadrclass Sep 28, 2024
6c40d0a
Update src/utilities.jl
farhadrclass Sep 28, 2024
773f2fd
Update src/utilities.jl
farhadrclass Sep 28, 2024
13162dc
Update src/utilities.jl
farhadrclass Sep 28, 2024
2cf4246
updated according to the PR review
farhadrclass Oct 2, 2024
5c1eeae
updated according to PR, renamed variable
farhadrclass Oct 2, 2024
1323a98
added ldiv!
farhadrclass Oct 3, 2024
d1da6ef
Update src/utilities.jl
farhadrclass Oct 4, 2024
ad9567f
Update src/utilities.jl
farhadrclass Oct 4, 2024
d5c1cfd
Update src/utilities.jl
farhadrclass Oct 4, 2024
759ab02
Update src/utilities.jl
farhadrclass Oct 4, 2024
3094644
Update src/utilities.jl
farhadrclass Oct 4, 2024
88479e5
Update src/utilities.jl
farhadrclass Oct 4, 2024
bc6ba12
Update src/utilities.jl
farhadrclass Oct 4, 2024
5a173ef
Update src/utilities.jl
farhadrclass Oct 4, 2024
4ad62e6
Update src/utilities.jl
farhadrclass Oct 4, 2024
17ffb34
Update src/utilities.jl
farhadrclass Oct 4, 2024
87bd7b6
Update src/utilities.jl
farhadrclass Oct 4, 2024
e039299
Update test/test_solve_shifted_system.jl
farhadrclass Oct 4, 2024
89d28d6
Update test/test_solve_shifted_system.jl
farhadrclass Oct 4, 2024
aa4c8a3
added the example
farhadrclass Oct 4, 2024
90084b9
Update utilities.jl
farhadrclass Oct 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Function | Description
`size` | Return the size of a linear operator
`symmetric` | Determine whether the operator is symmetric
`normest` | Estimate the 2-norm
`solve_shifted_system!` | Solves linear system $(B + \sigma I) x = b$, where $B$ is a forward L-BFGS operator and $\sigma \geq 0$.


## Other Operations on Operators
Expand Down
6 changes: 6 additions & 0 deletions src/lbfgs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ mutable struct LBFGSData{T, I <: Integer}
b::Vector{Vector{T}}
insert::I
Ax::Vector{T}
shifted_p::Matrix{T} # Temporary matrix used in the computation solve_shifted_system!
shifted_v::Vector{T}
shifted_u::Vector{T}
end

function LBFGSData(
Expand Down Expand Up @@ -43,6 +46,9 @@ function LBFGSData(
inverse ? Vector{T}(undef, 0) : [zeros(T, n) for _ = 1:mem],
1,
Vector{T}(undef, n),
zeros(T, n, 2*mem),
zeros(T, 2*mem),
zeros(T, n)
farhadrclass marked this conversation as resolved.
Show resolved Hide resolved
)
end

Expand Down
72 changes: 71 additions & 1 deletion src/utilities.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export check_ctranspose, check_hermitian, check_positive_definite, normest
export check_ctranspose, check_hermitian, check_positive_definite, normest, solve_shifted_system!

"""
normest(S) estimates the matrix 2-norm of S.
Expand Down Expand Up @@ -145,3 +145,73 @@ end

check_positive_definite(M::AbstractMatrix; kwargs...) =
check_positive_definite(LinearOperator(M); kwargs...)


"""
solve_shifted_system!(B,
x,
σ,
γ_inv,
inv_Cx,
p,
farhadrclass marked this conversation as resolved.
Show resolved Hide resolved
v,
u)

Solves linear system (B + σI) x = b, where B is a forward L-BFGS operator and σ ≥ 0.

farhadrclass marked this conversation as resolved.
Show resolved Hide resolved
### Parameters

farhadrclass marked this conversation as resolved.
Show resolved Hide resolved
- `B::LBFGSOperator{T,I,F1,F2,F3}`: forward L-BFGS operator.
- `x::AbstractVector{T}`: The vector representing `-b`.
- `σ::T`: Nonnegative shift.
- `inv_Cx::AbstractVector{T}`: A preallocated vector used to store the solution.

### Returns

- `inv_Cx::AbstractVector{T}`: The solution vector `x`, the solution to `(B + σI) x = b`.

farhadrclass marked this conversation as resolved.
Show resolved Hide resolved
### Method

The method uses a two-loop recursion-like approach with modifications to handle the shift `σ`.

### References
Erway, J. B., Jain, V., & Marcia, R. F. (2014). Shifted L-BFGS Systems. Optimization Methods and Software, 29(5), 992-1004.
"""
farhadrclass marked this conversation as resolved.
Show resolved Hide resolved

function solve_shifted_system!(
B::LBFGSOperator{T, I, F1, F2, F3},
x::AbstractVector{T},
σ::T,
inv_Cx::AbstractVector{T},
) where {T, I, F1, F2, F3}
farhadrclass marked this conversation as resolved.
Show resolved Hide resolved
data = B.data
insert = data.insert

γ_inv = 1 / data.scaling_factor
inv_c0 = 1 / (γ_inv + σ)
@. inv_Cx = inv_c0 * x

max_i = 2 * data.mem
sign_i = 1
for i = 1:max_i
j = (i + 1) ÷ 2
k = mod(insert + j - 1, data.mem) + 1
data.shifted_u .= ((i % 2) == 0 ? data.b[k] : data.a[k])

farhadrclass marked this conversation as resolved.
Show resolved Hide resolved
@. data.shifted_p[:, i] = inv_c0 * data.shifted_u

sign_t = 1
for t = 1:(i - 1)
c0 = dot(view(data.shifted_p, :, t), data.shifted_u)
c1= sign_t .*data.shifted_v[t]
c2 = c1 * c0
view(data.shifted_p, :, i) .+= c2 .* view(data.shifted_p, :, t)
sign_t = -sign_t
end

data.shifted_v[i] = 1 / (1 + ((i % 2) == 0 ? 1 : -1) * dot(data.shifted_u, view(data.shifted_p, :, i)))
inv_Cx .+= sign_i *data.shifted_v[i] * (view(data.shifted_p, :, i)' * x) .* view(data.shifted_p, :, i)
sign_i = -sign_i
end
return inv_Cx
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ include("test_deprecated.jl")
include("test_normest.jl")
include("test_diag.jl")
include("test_chainrules.jl")
include("test_solve_shifted_system.jl")
43 changes: 43 additions & 0 deletions test/test_solve_shifted_system.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Test
using LinearOperators
using LinearAlgebra

function setup_test_val(; M = 5, n = 100, scaling = false)
σ = 0.1
B = LBFGSOperator(n, mem = 5, scaling = scaling)

for _ = 1:10
s = rand(n)
y = rand(n)
push!(B, s, y)
end

x = randn(n)
z = B * x + σ .* x # so we know the true answer is x

return B, z, σ, zeros(n), x
end

function test_solve_shifted_system()
@testset "solve_shifted_system! Default setup test" begin
# Setup Test Case 1: Default setup from setup_test_val
B, z, σ, inv_Cz, x = setup_test_val(n = 100, M = 5)

result = solve_shifted_system!(B, z, σ, inv_Cz)

# Test 1: Check if result is a vector of the same size as z
@test length(result) == length(z)

# Test 2: Verify that inv_Cz (result) is modified in place
@test result === inv_Cz

# Test 3: Check if the function produces finite values
@test all(isfinite, result)

# Test 4: Check if inv_Cz is close to the known solution x
@test isapprox(inv_Cz, x, atol = 1e-6, rtol = 1e-6)
end

end

test_solve_shifted_system()
dpo marked this conversation as resolved.
Show resolved Hide resolved
Loading