Skip to content

Commit 7576ade

Browse files
committed
add cglsshifts and lsqrshifts
1 parent 00f1078 commit 7576ade

File tree

4 files changed

+148
-0
lines changed

4 files changed

+148
-0
lines changed

src/PreProcess/PreProcessLSKARC.jl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
function preprocess(PData::PDataLSKARC, Jx, Fx, gNorm2, calls, max_calls, α)
2+
ζ, ξ, maxtol, mintol = PData.ζ, PData.ξ, PData.maxtol, PData.mintol
3+
nshifts = PData.nshifts
4+
shifts = PData.shifts
5+
6+
m, n = size(Jx)
7+
# Tolerance used in Assumption 2.6b in the paper ( ξ > 0, 0 < ζ ≤ 1 )
8+
atol = PData.cgatol(ζ, ξ, maxtol, mintol, gNorm2)
9+
rtol = PData.cgrtol(ζ, ξ, maxtol, mintol, gNorm2)
10+
11+
nshifts = length(shifts)
12+
cb = (slv) -> begin
13+
ind = setdiff(1:length(shifts), findall(.!slv.converged))
14+
if length(ind) > 1
15+
for i in ind
16+
if (norm(slv.x[i]) / shifts[i] - α > 0)
17+
return true
18+
end
19+
end
20+
end
21+
return false
22+
end
23+
solver = PData.solver
24+
solve!(
25+
solver,
26+
Jx,
27+
Fx,
28+
shifts,
29+
itmax = min(max_calls - sum(calls), 2 * (m + n)),
30+
atol = atol,
31+
rtol = rtol,
32+
verbose = 0,
33+
callback = cb,
34+
)
35+
36+
PData.indmin = 0
37+
PData.positives .= solver.converged
38+
for i = 1:nshifts
39+
@. PData.xShift[i] = -solver.x[i]
40+
PData.norm_dirs[i] = norm(solver.x[i]) # Get it from cg_lanczos?
41+
end
42+
PData.shifts .= shifts
43+
PData.nshifts = nshifts
44+
PData.OK = sum(solver.converged) != 0 # at least one system was solved
45+
46+
return PData
47+
end

src/SolveModel/SolveModelLSKARC.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
function solve_modelLSKARC(X::PDataLSKARC, Jx, Fx, gNorm2, calls, max_calls, α::T) where {T}
2+
# target value should be close to satisfy αλ=||d||
3+
start = findfirst(X.positives)
4+
if isnothing(start)
5+
start = 1
6+
end
7+
if VERSION < v"1.7.0"
8+
positives = collect(start:length(X.positives))
9+
target = [(abs* X.shifts[i] - X.norm_dirs[i])) for i in positives]
10+
else
11+
positives = start:length(X.positives)
12+
target = ((abs* X.shifts[i] - X.norm_dirs[i])) for i in positives)
13+
end
14+
15+
# pick the closest shift to the target within positive definite H+λI
16+
indmin = argmin(target)
17+
X.indmin = start + indmin - 1
18+
p_imin = X.indmin
19+
X.d .= X.xShift[p_imin]
20+
X.λ = X.shifts[p_imin]
21+
22+
return X.d, X.λ
23+
end

src/solvers.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,6 @@ const solvers_nls_const = Dict(
4141
:ST_TROpGN => (HessGaussNewtonOp, PDataST, solve_modelST_TR, ()),
4242
:ST_TROpGNLS => (HessGaussNewtonOp, PDataNLSST, solve_modelNLSST_TR, ()),
4343
:ST_TROpLS => (HessOp, PDataNLSST, solve_modelNLSST_TR, ()),
44+
:LSARCqKOpCgls => (HessGaussNewtonOp, PDataLSKARC, solve_modelLSKARC, [:shifts => 10.0 .^ (collect(-10.0:0.5:20.0)), :solver_method => :cgls]),
45+
:LSARCqKOpLsqr => (HessGaussNewtonOp, PDataLSKARC, solve_modelLSKARC, [:shifts => 10.0 .^ (collect(-10.0:0.5:20.0)), :solver_method => :lsqr]),
4446
)

src/utils/pdata_struct.jl

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,82 @@ function PDataKARC(
115115
)
116116
end
117117

118+
"""
119+
PDataLSKARC(::Type{S}, ::Type{T}, n)
120+
Return a structure used for the preprocessing of ARCqK methods.
121+
"""
122+
mutable struct PDataLSKARC{T} <: PDataIter{T}
123+
d::Array{T,1} # (H+λI)\g ; on first call = g
124+
λ::T # "active" value of λ; on first call = 0
125+
ζ::T # Inexact Newton order parameter: stop when ||∇q|| < ξ * ||g||^(1+ζ)
126+
ξ::T # Inexact Newton order parameter: stop when ||∇q|| < ξ * ||g||^(1+ζ)
127+
maxtol::T # Largest tolerance for Inexact Newton
128+
mintol::T # Smallest tolerance for Inexact Newton
129+
cgatol::Any
130+
cgrtol::Any
131+
132+
indmin::Int # index of best shift value within "positive". On first call = 0
133+
134+
positives::Array{Bool,1} # indices of the shift values yielding (H+λI)⪰0
135+
xShift::Array{Array{T,1},1} # solutions for each shifted system
136+
shifts::Array{T,1} # values of the shifts
137+
nshifts::Int # number of shifts
138+
norm_dirs::Array{T,1} # norms of xShifts
139+
OK::Bool # preprocess success
140+
141+
solver::Union{CglsLanczosShiftSolver,LsqrShiftSolver}
142+
end
143+
144+
function PDataLSKARC(
145+
::Type{S},
146+
::Type{T},
147+
n;
148+
ζ = T(0.5),
149+
ξ = T(0.01),
150+
maxtol = T(0.01),
151+
mintol = sqrt(eps(T)),
152+
cgatol = (ζ, ξ, maxtol, mintol, gNorm2) -> max(mintol, min(maxtol, ξ * gNorm2^(1 + ζ))),
153+
cgrtol = (ζ, ξ, maxtol, mintol, gNorm2) -> max(mintol, min(maxtol, ξ * gNorm2^ζ)),
154+
shifts = 10.0 .^ collect(-20.0:1.0:20.0),
155+
solver_method = :cgls,
156+
kwargs...,
157+
) where {S,T}
158+
d = S(undef, n)
159+
λ = zero(T)
160+
indmin = 1
161+
nshifts = length(shifts)
162+
positives = Array{Bool,1}(undef, nshifts)
163+
xShift = Array{S,1}(undef, nshifts)
164+
for i = 1:nshifts
165+
xShift[i] = S(undef, n)
166+
end
167+
norm_dirs = S(undef, nshifts)
168+
OK = true
169+
solver = if solver_method == :cgls
170+
CglsLanczosShiftSolver(n, n, nshifts, S)
171+
else
172+
LsqrShiftSolver(n, n, nshifts, S)
173+
end
174+
return PDataLSKARC(
175+
d,
176+
λ,
177+
ζ,
178+
ξ,
179+
maxtol,
180+
mintol,
181+
cgatol,
182+
cgrtol,
183+
indmin,
184+
positives,
185+
xShift,
186+
T.(shifts),
187+
nshifts,
188+
norm_dirs,
189+
OK,
190+
solver,
191+
)
192+
end
193+
118194
"""
119195
PDataTRK(::Type{S}, ::Type{T}, n)
120196
Return a structure used for the preprocessing of TRK methods.

0 commit comments

Comments
 (0)