Skip to content

Commit 560e5c1

Browse files
First working case
1 parent 76ab887 commit 560e5c1

File tree

3 files changed

+102
-11
lines changed

3 files changed

+102
-11
lines changed

src/qobj/eigsolve.jl

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,44 @@ function _update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, k, m, β, sorted_vals, sort
144144
ordschur!(F, select)
145145

146146
copyto!(Hₘ, F.T)
147-
Tₘ = Hₘ
148147
copyto!(Uₘ, F.Z)
149148
mul!(f, Uₘᵥ, β)
150149

151-
return Tₘ, Uₘ
150+
return nothing
151+
end
152+
153+
# Pure Julia implementation of computing right eigenvectors from Schur form
154+
# Instead of using LAPACK.trevc!('R', 'A', select, Tₘ)
155+
function _schur_right_eigenvectors(Tₘ, k)
156+
n = size(Tₘ, 1)
157+
vecs = zeros(eltype(Tₘ), n, k)
158+
k == 0 && return vecs
159+
160+
value_tol(λ) = eps(typeof(abs(λ))) * max(one(typeof(abs(λ))), abs(λ))
161+
162+
@inbounds for col in 1:k
163+
vec = view(vecs, :, col)
164+
fill!(vec, zero(eltype(Tₘ)))
165+
vec[col] = one(eltype(Tₘ))
166+
λ = Tₘ[col, col]
167+
168+
for row in (col-1):-1:1
169+
acc = zero(eltype(Tₘ))
170+
for inner in (row + 1):col
171+
acc += Tₘ[row, inner] * vec[inner]
172+
end
173+
denom = Tₘ[row, row] - λ
174+
if abs(denom) <= value_tol(λ)
175+
vec[row] = zero(eltype(Tₘ))
176+
else
177+
vec[row] = -acc / denom
178+
end
179+
end
180+
181+
LinearAlgebra.normalize!(vec)
182+
end
183+
184+
return vecs
152185
end
153186

154187
function _eigsolve(
@@ -196,12 +229,13 @@ function _eigsolve(
196229
V₁ₖ = view(V, :, 1:k)
197230
Vₖ₊₁ = view(V, :, k + 1)
198231
Hₖ₊₁₁ₖ = view(H, k + 1, 1:k)
232+
cache0₁ₖ = view(cache0, :, 1:k)
199233
cache1₁ₖ = view(cache1, :, 1:k)
200234
cache2₁ₖ = view(cache2, 1:k)
201235

202236
M = typeof(cache0)
203237

204-
Tₘ, Uₘ = _update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, k, m, β, sorted_vals, sortby, rev)
238+
_update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, k, m, β, sorted_vals, sortby, rev)
205239

206240
numops = m
207241
iter = 0
@@ -227,20 +261,18 @@ function _eigsolve(
227261

228262
# println( A * Vₘ ≈ Vₘ * M(Hₘ) + qₘ * M(transpose(βeₘ)) ) # SHOULD BE TRUE
229263

230-
Tₘ, Uₘ = _update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, k, m, β, sorted_vals, sortby, rev)
264+
_update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, k, m, β, sorted_vals, sortby, rev)
231265

232266
numops += m - k - 1
233267
iter += 1
234268
end
235269

270+
Tₘ = Hₘ
236271
vals = diag(view(Tₘ, 1:k, 1:k))
237-
select = Vector{Int}(undef, 0)
238-
VR = LAPACK.trevc!('R', 'A', select, Tₘ)
239-
@inbounds for i in 1:size(VR, 2)
240-
normalize!(view(VR, :, i))
241-
end
242-
mul!(cache1, Vₘ, M(Uₘ * VR))
243-
vecs = cache1[:, 1:k]
272+
VR = _schur_right_eigenvectors(Tₘ, k)
273+
mul!(cache0₁ₖ, Uₘ, VR)
274+
mul!(cache1₁ₖ, Vₘ, cache0₁ₖ)
275+
vecs = copy(cache1₁ₖ)
244276
settings.auto_tidyup && tidyup!(vecs)
245277

246278
return EigsolveResult(vals, vecs, type, dimensions, iter, numops, (iter < maxiter))

test_env/Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[deps]
2+
GenericLinearAlgebra = "14197337-ba66-59df-a3e3-ca00e7dcff7a"
3+
GenericSchur = "c145ed77-6b09-5dd9-b285-bf645a82121e"
4+
QuantumToolbox = "6c2fb7c5-b903-41d2-bc5e-5a7c320b9fab"

test_env/my_test.jl

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using Revise
2+
using LinearAlgebra
3+
using SparseArrays
4+
using QuantumToolbox
5+
# using GenericLinearAlgebra
6+
using GenericSchur
7+
using BenchmarkTools
8+
9+
# include("arnoldi_new.jl")
10+
11+
# %%
12+
13+
# T = ComplexF64
14+
T = Complex{BigFloat}
15+
16+
# A = rand(T, 100, 100)
17+
A = sprand(T, 100, 100, 0.01) + Diagonal(rand(T, 100))
18+
x = rand(T, 100)
19+
20+
nev = 5
21+
krylov_dim = 15
22+
tol = 1e-8
23+
24+
# values0 = eigvals(Array(A); sortby=abs2)[end-nev+1:end] |> reverse
25+
res0 = eigen(Array{ComplexF64}(A); sortby=abs2)
26+
values0 = res0.values[end-nev+1:end]
27+
vectors0 = res0.vectors[:, end-nev+1:end]
28+
29+
res = eigsolve(A; v0=x, eigvals=nev, krylovdim=krylov_dim, eigstol=tol);
30+
res.iter
31+
32+
values0
33+
res.values
34+
35+
idxs1 = sortperm(res.values, by=abs2)
36+
idxs2 = sortperm(values0, by=abs2)
37+
38+
res.values[idxs1] - values0[idxs2]
39+
40+
# res.vectors[:, idxs1] - vectors0[:, idxs2]
41+
42+
values_2 = [v' * A * v for v in eachcol(res.vectors[:, idxs1])]
43+
44+
values_2 - values0[idxs2]
45+
46+
map(1:nev) do i
47+
v0 = vectors0[:, idxs2[i]] |> copy
48+
v = res.vectors[:, idxs1[i]] |> copy
49+
50+
abs(dot(v0, v))
51+
end
52+
53+
# %%
54+
55+
@benchmark eigsolve($A; v0=$x, eigvals=$nev, krylovdim=$krylov_dim, eigstol=$tol)

0 commit comments

Comments
 (0)