Skip to content

Commit c8162c2

Browse files
committed
Merge branch 'cite' of https://github.com/qutip/QuantumToolbox.jl into cite
2 parents 56ead1c + 3f3d8ac commit c8162c2

File tree

15 files changed

+185
-169
lines changed

15 files changed

+185
-169
lines changed

.github/workflows/Code-Quality.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ jobs:
4040
matrix:
4141
version:
4242
- 'lts'
43+
- '1'
4344
os:
4445
- 'ubuntu-latest'
4546
arch:

.github/workflows/SpellCheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ jobs:
1010
- name: Checkout Actions Repository
1111
uses: actions/checkout@v5
1212
- name: Check spelling
13-
uses: crate-ci/[email protected].2
13+
uses: crate-ci/[email protected].3

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased](https://github.com/qutip/QuantumToolbox.jl/tree/main)
99

1010
- Add `QuantumToolbox.cite()` for bibtex generator of `QuantumToolbox.jl`. ([#544])
11+
- Add `sortby` and `rev` keyword arguments to eigensolvers. ([#546])
1112

1213
## [v0.35.0]
1314
Release date: 2025-09-03
@@ -317,3 +318,4 @@ Release date: 2024-11-13
317318
[#537]: https://github.com/qutip/QuantumToolbox.jl/issues/537
318319
[#539]: https://github.com/qutip/QuantumToolbox.jl/issues/539
319320
[#544]: https://github.com/qutip/QuantumToolbox.jl/issues/544
321+
[#546]: https://github.com/qutip/QuantumToolbox.jl/issues/546

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ changelog:
1212
${JULIA} -e 'using Changelog; Changelog.generate(Changelog.CommonMark(), "CHANGELOG.md"; repo = "qutip/QuantumToolbox.jl")'
1313

1414
test:
15-
${JULIA} --project -e 'using Pkg; Pkg.resolve(); Pkg.test()'
15+
${JULIA} --project -e 'using Pkg; Pkg.update(); Pkg.test()'
1616

1717
docs:
18-
${JULIA} --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
18+
${JULIA} --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.update()'
1919
${JULIA} --project=docs docs/make.jl
2020

2121
vitepress:

ext/QuantumToolboxMakieExt.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ import Makie:
2424
scatter!,
2525
arrows3d!,
2626
text!,
27-
Point3f,
2827
mesh!,
2928
RGBf,
30-
Vec3f,
3129
Point3f,
3230
NoShading,
3331
cameracontrols,
@@ -660,7 +658,7 @@ function _plot_arcs!(b::Bloch, lscene)
660658
dot(cross(v1, vm), n) < 0 &&-= 2π)
661659
end
662660
t_range = range(0, θ, length = 100)
663-
arc_points = [Point3f((v1 * cos(t) + cross(n, v1) * sin(t))) for t in t_range]
661+
arc_points = [Point3f(v1 * cos(t) + cross(n, v1) * sin(t)) for t in t_range]
664662
lines!(lscene, arc_points; color = "blue", linestyle = :solid)
665663
end
666664
return nothing
@@ -685,13 +683,13 @@ function _plot_vectors!(b::Bloch, lscene)
685683

686684
arrows3d!(
687685
lscene,
688-
[Point3f(0, 0, 0)],
689-
[v],
686+
Point3f(0),
687+
Point3f(v),
690688
color = color,
691689
shaftradius = b.vector_width,
692690
tiplength = b.vector_tiplength,
693691
tipradius = b.vector_tipradius,
694-
rasterize = 3,
692+
# rasterize = 3, #TODO: maybe uncomment this after https://github.com/MakieOrg/Makie.jl/issues/5259 is fixed
695693
)
696694
end
697695
return nothing

src/qobj/boolean_functions.jl

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,47 @@ export isunitary
1010
1111
Checks if the [`QuantumObject`](@ref) `A` is a [`Bra`](@ref). Default case returns `false` for any other inputs.
1212
"""
13-
isbra(A::QuantumObject) = isbra(typeof(A))
14-
isbra(::Type{<:QuantumObject{Bra,N}}) where {N} = true
13+
isbra(A::QuantumObject{Bra}) = true
1514
isbra(A) = false # default case
1615

1716
@doc raw"""
1817
isket(A)
1918
2019
Checks if the [`QuantumObject`](@ref) `A` is a [`Ket`](@ref). Default case returns `false` for any other inputs.
2120
"""
22-
isket(A::QuantumObject) = isket(typeof(A))
23-
isket(::Type{<:QuantumObject{Ket,N}}) where {N} = true
21+
isket(A::QuantumObject{Ket}) = true
2422
isket(A) = false # default case
2523

2624
@doc raw"""
2725
isoper(A)
2826
2927
Checks if the [`AbstractQuantumObject`](@ref) `A` is a [`Operator`](@ref). Default case returns `false` for any other inputs.
3028
"""
31-
isoper(A::AbstractQuantumObject) = isoper(typeof(A))
32-
isoper(::Type{<:AbstractQuantumObject{Operator,N}}) where {N} = true
29+
isoper(A::AbstractQuantumObject{Operator}) = true
3330
isoper(A) = false # default case
3431

3532
@doc raw"""
3633
isoperbra(A)
3734
3835
Checks if the [`QuantumObject`](@ref) `A` is a [`OperatorBra`](@ref). Default case returns `false` for any other inputs.
3936
"""
40-
isoperbra(A::QuantumObject) = isoperbra(typeof(A))
41-
isoperbra(::Type{<:QuantumObject{OperatorBra,N}}) where {N} = true
37+
isoperbra(A::QuantumObject{OperatorBra}) = true
4238
isoperbra(A) = false # default case
4339

4440
@doc raw"""
4541
isoperket(A)
4642
4743
Checks if the [`QuantumObject`](@ref) `A` is a [`OperatorKet`](@ref). Default case returns `false` for any other inputs.
4844
"""
49-
isoperket(A::QuantumObject) = isoperket(typeof(A))
50-
isoperket(::Type{<:QuantumObject{OperatorKet,N}}) where {N} = true
45+
isoperket(A::QuantumObject{OperatorKet}) = true
5146
isoperket(A) = false # default case
5247

5348
@doc raw"""
5449
issuper(A)
5550
5651
Checks if the [`AbstractQuantumObject`](@ref) `A` is a [`SuperOperator`](@ref). Default case returns `false` for any other inputs.
5752
"""
58-
issuper(A::AbstractQuantumObject) = issuper(typeof(A))
59-
issuper(::Type{<:AbstractQuantumObject{<:SuperOperatorType,N}}) where {N} = true
53+
issuper(A::AbstractQuantumObject{<:SuperOperatorType}) = true
6054
issuper(A) = false # default case
6155

6256
@doc raw"""

src/qobj/eigsolve.jl

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ function _permuteschur!(
149149
return T, Q
150150
end
151151

152-
function _update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, m, β, sorted_vals)
152+
function _update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, m, β, sorted_vals, sortby, rev)
153153
F = hessenberg!(Hₘ)
154154
copyto!(Uₘ, Hₘ)
155155
LAPACK.orghr!(1, m, Uₘ, F.τ)
156156
Tₘ, Uₘ, values = hseqr!(Hₘ, Uₘ)
157-
sortperm!(sorted_vals, values, by = abs, rev = true)
157+
sortperm!(sorted_vals, values, by = sortby, rev = rev)
158158
_permuteschur!(Tₘ, Uₘ, sorted_vals)
159159
mul!(f, Uₘᵥ, β)
160160

@@ -170,6 +170,8 @@ function _eigsolve(
170170
m::Int = max(20, 2 * k + 1);
171171
tol::Real = 1e-8,
172172
maxiter::Int = 200,
173+
sortby::Function = abs2,
174+
rev = true,
173175
) where {T<:BlasFloat,ObjType<:Union{Nothing,Operator,SuperOperator}}
174176
n = size(A, 2)
175177
V = similar(b, n, m + 1)
@@ -209,7 +211,7 @@ function _eigsolve(
209211

210212
M = typeof(cache0)
211213

212-
Tₘ, Uₘ = _update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, m, β, sorted_vals)
214+
Tₘ, Uₘ = _update_schur_eigs!(Hₘ, Uₘ, Uₘᵥ, f, m, β, sorted_vals, sortby, rev)
213215

214216
numops = m
215217
iter = 0
@@ -235,7 +237,7 @@ function _eigsolve(
235237

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

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

240242
numops += m - k - 1
241243
iter += 1
@@ -263,6 +265,8 @@ end
263265
tol::Real = 1e-8,
264266
maxiter::Int = 200,
265267
solver::Union{Nothing, SciMLLinearSolveAlgorithm} = nothing,
268+
sortby::Function = abs2,
269+
rev::Bool = true,
266270
kwargs...)
267271
268272
Solve for the eigenvalues and eigenvectors of a matrix `A` using the Arnoldi method.
@@ -276,6 +280,8 @@ Solve for the eigenvalues and eigenvectors of a matrix `A` using the Arnoldi met
276280
- `tol::Real`: the tolerance for the Arnoldi method. Default is `1e-8`.
277281
- `maxiter::Int`: the maximum number of iterations for the Arnoldi method. Default is `200`.
278282
- `solver::Union{Nothing, SciMLLinearSolveAlgorithm}`: the linear solver algorithm. Default is `nothing`.
283+
- `sortby::Function`: the function to sort eigenvalues. Default is `abs2`.
284+
- `rev::Bool`: whether to sort in descending order. Default is `true`.
279285
- `kwargs`: Additional keyword arguments passed to the solver.
280286
281287
# Notes
@@ -293,6 +299,8 @@ function eigsolve(
293299
tol::Real = 1e-8,
294300
maxiter::Int = 200,
295301
solver::Union{Nothing,SciMLLinearSolveAlgorithm} = nothing,
302+
sortby::Function = abs2,
303+
rev::Bool = true,
296304
kwargs...,
297305
)
298306
return eigsolve(
@@ -306,6 +314,8 @@ function eigsolve(
306314
tol = tol,
307315
maxiter = maxiter,
308316
solver = solver,
317+
sortby = sortby,
318+
rev = rev,
309319
kwargs...,
310320
)
311321
end
@@ -321,14 +331,27 @@ function eigsolve(
321331
tol::Real = 1e-8,
322332
maxiter::Int = 200,
323333
solver::Union{Nothing,SciMLLinearSolveAlgorithm} = nothing,
334+
sortby::Function = abs2,
335+
rev::Bool = true,
324336
kwargs...,
325337
)
326338
T = eltype(A)
327339
isH = ishermitian(A)
328340
v0 === nothing && (v0 = normalize!(rand(T, size(A, 1))))
329341

330342
if sigma === nothing
331-
res = _eigsolve(A, v0, type, dimensions, eigvals, krylovdim, tol = tol, maxiter = maxiter)
343+
res = _eigsolve(
344+
A,
345+
v0,
346+
type,
347+
dimensions,
348+
eigvals,
349+
krylovdim,
350+
tol = tol,
351+
maxiter = maxiter,
352+
sortby = sortby,
353+
rev = rev,
354+
)
332355
vals = res.values
333356
else
334357
Aₛ = A - sigma * I
@@ -346,7 +369,18 @@ function eigsolve(
346369

347370
Amap = EigsolveInverseMap(T, size(A), linsolve)
348371

349-
res = _eigsolve(Amap, v0, type, dimensions, eigvals, krylovdim, tol = tol, maxiter = maxiter)
372+
res = _eigsolve(
373+
Amap,
374+
v0,
375+
type,
376+
dimensions,
377+
eigvals,
378+
krylovdim,
379+
tol = tol,
380+
maxiter = maxiter,
381+
sortby = sortby,
382+
rev = rev,
383+
)
350384
vals = @. (1 + sigma * res.values) / res.values
351385
end
352386

@@ -368,6 +402,8 @@ end
368402
krylovdim::Int = min(10, size(H, 1)),
369403
maxiter::Int = 200,
370404
eigstol::Real = 1e-6,
405+
sortby::Function = abs2,
406+
rev::Bool = true,
371407
kwargs...,
372408
)
373409
@@ -384,6 +420,8 @@ Solve the eigenvalue problem for a Liouvillian superoperator `L` using the Arnol
384420
- `krylovdim`: The dimension of the Krylov subspace.
385421
- `maxiter`: The maximum number of iterations for the eigsolver.
386422
- `eigstol`: The tolerance for the eigsolver.
423+
- `sortby::Function`: the function to sort eigenvalues. Default is `abs2`.
424+
- `rev::Bool`: whether to sort in descending order. Default is `true`.
387425
- `kwargs`: Additional keyword arguments passed to the differential equation solver.
388426
389427
# Notes
@@ -407,6 +445,8 @@ function eigsolve_al(
407445
krylovdim::Int = min(10, size(H, 1)),
408446
maxiter::Int = 200,
409447
eigstol::Real = 1e-6,
448+
sortby::Function = abs2,
449+
rev::Bool = true,
410450
kwargs...,
411451
) where {HOpType<:Union{Operator,SuperOperator}}
412452
L_evo = _mesolve_make_L_QobjEvo(H, c_ops)
@@ -422,8 +462,18 @@ function eigsolve_al(
422462

423463
Lmap = ArnoldiLindbladIntegratorMap(eltype(H), size(L_evo), integrator)
424464

425-
res =
426-
_eigsolve(Lmap, mat2vec(ρ0), L_evo.type, L_evo.dimensions, eigvals, krylovdim, maxiter = maxiter, tol = eigstol)
465+
res = _eigsolve(
466+
Lmap,
467+
mat2vec(ρ0),
468+
L_evo.type,
469+
L_evo.dimensions,
470+
eigvals,
471+
krylovdim,
472+
maxiter = maxiter,
473+
tol = eigstol,
474+
sortby = sortby,
475+
rev = rev,
476+
)
427477

428478
vals = similar(res.values)
429479
vecs = similar(res.vectors)

0 commit comments

Comments
 (0)