Skip to content

Commit e49f82b

Browse files
Update utils.jl
Enhance robustness of Arpack usage by catching NCV-related errors Catch the XYAUPD_Exception error in Arpack calls and dynamically increase NCV as needed to handle convergence issues. This modification addresses instability in LSR1 computations due to insufficient NCV.
1 parent a35feb9 commit e49f82b

File tree

1 file changed

+51
-19
lines changed

1 file changed

+51
-19
lines changed

src/utils.jl

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,68 @@ function opnorm_eig(B; max_attempts::Int = 3)
1515
n = size(B, 1)
1616
nev = 1
1717
ncv = max(20, 2 * nev + 1)
18-
while !(have_eig || attempt > max_attempts)
19-
attempt += 1
20-
(d, nconv, niter, nmult, resid) = eigs(B; nev = nev, ncv = ncv, which = :LM, ritzvec = false, check = 1)
21-
have_eig = nconv == 1
22-
if (have_eig)
23-
λ = abs(d[1])
24-
else
25-
ncv = min(2 * ncv, n)
26-
end
18+
19+
while !(have_eig || attempt >= max_attempts)
20+
attempt += 1
21+
try
22+
# Perform eigendecomposition
23+
d, nconv, niter, nmult, resid = eigs(B; nev = nev, ncv = ncv, which = :LM, ritzvec = false, check = 1)
24+
25+
# Check if eigenvalue has converged
26+
have_eig = nconv == 1
27+
if have_eig
28+
λ = abs(d[1]) # Take absolute value of the largest eigenvalue
29+
break # Exit loop if successful
30+
else
31+
# Increase NCV for the next attempt if convergence wasn't achieved
32+
ncv = min(2 * ncv, n)
33+
end
34+
catch e
35+
if occursin("XYAUPD_Exception", string(e))
36+
@warn "Arpack error: $e. Increasing NCV to $ncv and retrying."
37+
ncv = min(2 * ncv, n) # Increase NCV but don't exceed matrix size
38+
else
39+
rethrow(e) # Re-raise if it's a different error
40+
end
41+
end
2742
end
43+
2844
return λ, have_eig
2945
end
3046

3147
function opnorm_svd(J; max_attempts::Int = 3)
3248
have_svd = false
3349
attempt = 0
3450
σ = zero(eltype(J))
35-
n = min(size(J)...)
51+
n = min(size(J)...) # Minimum dimension of the matrix
3652
nsv = 1
3753
ncv = 10
38-
while !(have_svd || attempt > max_attempts)
39-
attempt += 1
40-
(s, nconv, niter, nmult, resid) = svds(J, nsv = nsv, ncv = ncv, ritzvec = false, check = 1)
41-
have_svd = nconv == 1
42-
if (have_svd)
43-
σ = maximum(s.S)
44-
else
45-
ncv = min(2 * ncv, n)
46-
end
54+
55+
while !(have_svd || attempt >= max_attempts)
56+
attempt += 1
57+
try
58+
# Perform singular value decomposition
59+
s, nconv, niter, nmult, resid = svds(J; nsv = nsv, ncv = ncv, ritzvec = false, check = 1)
60+
61+
# Check if singular value has converged
62+
have_svd = nconv >= 1
63+
if have_svd
64+
σ = maximum(s.S) # Take the largest singular value
65+
break # Exit loop if successful
66+
else
67+
# Increase NCV for the next attempt if convergence wasn't achieved
68+
ncv = min(2 * ncv, n)
69+
end
70+
catch e
71+
if occursin("XYAUPD_Exception", string(e))
72+
@warn "Arpack error: $e. Increasing NCV to $ncv and retrying."
73+
ncv = min(2 * ncv, n) # Increase NCV but don't exceed matrix size
74+
else
75+
rethrow(e) # Re-raise if it's a different error
76+
end
77+
end
4778
end
79+
4880
return σ, have_svd
4981
end
5082

0 commit comments

Comments
 (0)