Skip to content

Commit 6f1bf9c

Browse files
FIx eigenvalues
1 parent 739852c commit 6f1bf9c

File tree

7 files changed

+110
-16
lines changed

7 files changed

+110
-16
lines changed

Project.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
1111
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
1212
IncompleteLU = "40713840-3770-5561-ab4c-a76e7d0d7895"
1313
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
14-
LinearMaps = "7a12625a-238d-50fd-b39a-03d52299707e"
1514
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
1615
OrdinaryDiffEqCore = "bbf590c4-e513-4bbe-9b18-05decba2e5d8"
1716
OrdinaryDiffEqTsit5 = "b1df2697-797e-41e3-8120-5422d3b24e4a"
@@ -39,7 +38,6 @@ FFTW = "1.5"
3938
Graphs = "1.7"
4039
IncompleteLU = "0.2"
4140
LinearAlgebra = "<0.0.1, 1"
42-
LinearMaps = "3"
4341
LinearSolve = "2"
4442
OrdinaryDiffEqCore = "1"
4543
OrdinaryDiffEqTsit5 = "1"

docs/src/api.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@ wigner
219219
negativity
220220
```
221221

222+
## [Linear Maps](@id doc-API:Linear-Maps)
223+
224+
```@docs
225+
AbstractLinearMap
226+
```
227+
222228
## [Utility functions](@id doc-API:Utility-functions)
223229

224230
```@docs

src/QuantumToolbox.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import ArrayInterface: allowed_getindex, allowed_setindex!
4040
import FFTW: fft, fftshift
4141
import Graphs: connected_components, DiGraph
4242
import IncompleteLU: ilu
43-
import LinearMaps: LinearMap
4443
import Pkg
4544
import Random
4645
import SpecialFunctions: loggamma
@@ -54,6 +53,7 @@ BLAS.set_num_threads(1)
5453
include("utilities.jl")
5554
include("versioninfo.jl")
5655
include("progress_bar.jl")
56+
include("linear_maps.jl")
5757

5858
# Quantum Object
5959
include("qobj/quantum_object.jl")

src/linear_maps.jl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
export AbstractLinearMap
2+
3+
@doc raw"""
4+
AbstractLinearMap{T, TS}
5+
6+
Represents a general linear map with element type `T` and size `TS`.
7+
8+
## Overview
9+
10+
A **linear map** is a transformation `L` that satisfies:
11+
12+
- **Additivity**:
13+
```math
14+
L(u + v) = L(u) + L(v)
15+
```
16+
- **Homogeneity**:
17+
```math
18+
L(cu) = cL(u)
19+
```
20+
21+
It is typically represented as a matrix with dimensions given by `size`, and this abtract type helps to define this map when the matrix is not explicitly available.
22+
23+
## Methods
24+
25+
- `Base.eltype(A)`: Returns the element type `T`.
26+
- `Base.size(A)`: Returns the size `A.size`.
27+
- `Base.size(A, i)`: Returns the `i`-th dimension.
28+
29+
## Example
30+
31+
As an example, we now define the linear map used in the [`eigsolve_al`](@ref) function for Arnoldi-Lindblad eigenvalue solver:
32+
33+
```julia-repl
34+
struct ArnoldiLindbladIntegratorMap{T,TS,TI} <: AbstractLinearMap{T,TS}
35+
elty::Type{T}
36+
size::TS
37+
integrator::TI
38+
end
39+
40+
function LinearAlgebra.mul!(y::AbstractVector, A::ArnoldiLindbladIntegratorMap, x::AbstractVector)
41+
reinit!(A.integrator, x)
42+
solve!(A.integrator)
43+
return copyto!(y, A.integrator.u)
44+
end
45+
```
46+
47+
where `integrator` is the ODE integrator for the time-evolution. In this way, we can diagonalize this linear map using the [`eigsolve`](@ref) function.
48+
"""
49+
abstract type AbstractLinearMap{T,TS} end
50+
51+
Base.eltype(A::AbstractLinearMap{T}) where T = T
52+
53+
Base.size(A::AbstractLinearMap) = A.size
54+
Base.size(A::AbstractLinearMap, i::Int) = A.size[i]

src/qobj/eigsolve.jl

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,27 @@ function Base.show(io::IO, res::EigsolveResult)
8484
return show(io, MIME("text/plain"), res.vectors)
8585
end
8686

87-
function _map_ldiv(linsolve, y, x)
88-
linsolve.b .= x
89-
return y .= solve!(linsolve).u
87+
struct ArnoldiLindbladIntegratorMap{T,TS,TI} <: AbstractLinearMap{T,TS}
88+
elty::Type{T}
89+
size::TS
90+
integrator::TI
91+
end
92+
93+
function LinearAlgebra.mul!(y::AbstractVector, A::ArnoldiLindbladIntegratorMap, x::AbstractVector)
94+
reinit!(A.integrator, x)
95+
solve!(A.integrator)
96+
return copyto!(y, A.integrator.u)
97+
end
98+
99+
struct EigsolveInverseMap{T,TS,TI} <: AbstractLinearMap{T,TS}
100+
elty::Type{T}
101+
size::TS
102+
linsolve::TI
103+
end
104+
105+
function LinearAlgebra.mul!(y::AbstractVector, A::EigsolveInverseMap, x::AbstractVector)
106+
A.linsolve.b .= x
107+
return copyto!(y, solve!(A.linsolve).u)
90108
end
91109

92110
function _permuteschur!(
@@ -293,7 +311,8 @@ function eigsolve(
293311

294312
prob = LinearProblem(Aₛ, v0)
295313
linsolve = init(prob, solver; kwargs2...)
296-
Amap = LinearMap{T}((y, x) -> _map_ldiv(linsolve, y, x), length(v0))
314+
315+
Amap = EigsolveInverseMap(T, size(A), linsolve)
297316

298317
res = _eigsolve(Amap, v0, type, dims, k, krylovdim, tol = tol, maxiter = maxiter)
299318
vals = @. (1 + sigma * res.values) / res.values
@@ -370,13 +389,7 @@ function eigsolve_al(
370389

371390
# prog = ProgressUnknown(desc="Applications:", showspeed = true, enabled=progress)
372391

373-
function arnoldi_lindblad_solve(ρ)
374-
reinit!(integrator, ρ)
375-
solve!(integrator)
376-
return integrator.u
377-
end
378-
379-
Lmap = LinearMap{eltype(MT1)}(arnoldi_lindblad_solve, size(L, 1), ismutating = false)
392+
Lmap = ArnoldiLindbladIntegratorMap(eltype(MT1),size(L),integrator)
380393

381394
res = _eigsolve(Lmap, mat2vec(ρ0), L.type, L.dims, k, krylovdim, maxiter = maxiter, tol = eigstol)
382395
# finish!(prog)

test/eigenvalues_and_operators.jl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
# eigen solve for general matrices
6060
vals, _, vecs = eigsolve(L.data, sigma = 0.01, k = 10, krylovdim = 50)
6161
vals2, vecs2 = eigen(sparse_to_dense(L.data))
62-
vals3, state3, vecs3 = eigsolve_al(liouvillian(H, c_ops), 1 \ (40 * κ), k = 10, krylovdim = 50)
62+
vals3, state3, vecs3 = eigsolve_al(L, 1 \ (40 * κ), k = 10, krylovdim = 50)
6363
idxs = sortperm(vals2, by = abs)
6464
vals2 = vals2[idxs][1:10]
6565
vecs2 = vecs2[:, idxs][:, 1:10]
@@ -91,4 +91,27 @@
9191
@test isapprox(abs2(vals2[1]), abs2(vals3[1]), atol = 1e-7)
9292
@test isapprox(vec2mat(vecs[1]).data * exp(-1im * angle(vecs[1][1])), vec2mat(vecs2[1]).data, atol = 1e-7)
9393
@test isapprox(vec2mat(vecs[1]).data * exp(-1im * angle(vecs[1][1])), vec2mat(state3[1]).data, atol = 1e-5)
94+
95+
@testset "Type Inference (eigen)" begin
96+
N = 5
97+
a = kron(destroy(N), qeye(N))
98+
a_d = a'
99+
b = kron(qeye(N), destroy(N))
100+
b_d = b'
101+
102+
ωc = 1
103+
ωb = 1
104+
g = 0.01
105+
κ = 0.1
106+
n_thermal = 0.01
107+
108+
H = ωc * a_d * a + ωb * b_d * b + g * (a + a_d) * (b + b_d)
109+
c_ops = [((1 + n_thermal) * κ) * a, κ * b, (n_thermal * κ) * a_d]
110+
L = liouvillian(H, c_ops)
111+
112+
@inferred eigenstates(H, sparse = false)
113+
@inferred eigenstates(H, sparse = true)
114+
@inferred eigenstates(L, sparse = true)
115+
@inferred eigsolve_al(L, 1 \ (40 * κ), k = 10)
116+
end
94117
end

test/generalized_master_equation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
c_ops = [sqrt(0.01) * a2, sqrt(0.01) * sm2]
2727
L2 = liouvillian(H_d, c_ops)
2828

29-
@test (expect(Xp' * Xp, steadystate(L1)) < 1e-10 && expect(Xp' * Xp, steadystate(L2)) > 1e-3)
29+
@test (expect(Hermitian(Xp' * Xp), steadystate(L1)) < 1e-10 && expect(Hermitian(Xp' * Xp), steadystate(L2)) > 1e-3)
3030

3131
H = 1 * a' * a + 1 * sz / 2 + 1e-5 * (a * sp + a' * sm)
3232

0 commit comments

Comments
 (0)