Skip to content

Commit a2ade17

Browse files
authored
Excitation number restricted (ENR) state space implementation (#500)
1 parent 0066cdb commit a2ade17

File tree

11 files changed

+427
-33
lines changed

11 files changed

+427
-33
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased](https://github.com/qutip/QuantumToolbox.jl/tree/main)
99

10+
- Implement `EnrSpace` and corresponding functionality. ([#500])
1011
- Check for orthogonality breakdown in `Lanczos` solver for `spectrum`. ([#501])
1112

1213
## [v0.32.1]
@@ -255,4 +256,5 @@ Release date: 2024-11-13
255256
[#487]: https://github.com/qutip/QuantumToolbox.jl/issues/487
256257
[#489]: https://github.com/qutip/QuantumToolbox.jl/issues/489
257258
[#494]: https://github.com/qutip/QuantumToolbox.jl/issues/494
259+
[#500]: https://github.com/qutip/QuantumToolbox.jl/issues/500
258260
[#501]: https://github.com/qutip/QuantumToolbox.jl/issues/501

docs/src/resources/api.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ end
1818

1919
```@docs
2020
Space
21+
EnrSpace
2122
Dimensions
2223
GeneralDimensions
2324
AbstractQuantumObject
@@ -122,6 +123,8 @@ coherent_dm
122123
thermal_dm
123124
maximally_mixed_dm
124125
rand_dm
126+
enr_fock
127+
enr_thermal_dm
125128
spin_state
126129
spin_coherent
127130
bell_state
@@ -152,6 +155,8 @@ QuantumToolbox.momentum
152155
phase
153156
fdestroy
154157
fcreate
158+
enr_destroy
159+
enr_identity
155160
tunneling
156161
qft
157162
eye
@@ -312,6 +317,7 @@ PhysicalConstants
312317
convert_unit
313318
row_major_reshape
314319
meshgrid
320+
enr_state_dictionaries
315321
```
316322

317323
## [Visualization](@id doc-API:Visualization)

docs/src/users_guide/QuantumObject/QuantumObject.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,16 @@ Manually specifying the data for each quantum object is inefficient. Even more s
6666

6767
### States
6868
- [`zero_ket`](@ref): zero ket vector
69-
- [`fock`](@ref) or [`basis`](@ref): fock state ket vector
70-
- [`fock_dm`](@ref): density matrix of a fock state
69+
- [`fock`](@ref) or [`basis`](@ref): Fock state ket vector
70+
- [`fock_dm`](@ref): density matrix of a Fock state
7171
- [`coherent`](@ref): coherent state ket vector
7272
- [`rand_ket`](@ref): random ket vector
7373
- [`coherent_dm`](@ref): density matrix of a coherent state
7474
- [`thermal_dm`](@ref): density matrix of a thermal state
7575
- [`maximally_mixed_dm`](@ref): density matrix of a maximally mixed state
7676
- [`rand_dm`](@ref): random density matrix
77+
- [`enr_fock`](@ref): Fock state in the excitation number restricted (ENR) space
78+
- [`enr_thermal_dm`](@ref): thermal state in the excitation number restricted (ENR) space
7779
- [`spin_state`](@ref): spin state
7880
- [`spin_coherent`](@ref): coherent spin state
7981
- [`bell_state`](@ref): Bell state
@@ -108,6 +110,8 @@ Manually specifying the data for each quantum object is inefficient. Even more s
108110
- [`spin_J_set`](@ref): a set of Spin-`j` operators ``(S_x, S_y, S_z)``
109111
- [`fdestroy`](@ref): fermion destruction operator
110112
- [`fcreate`](@ref): fermion creation operator
113+
- [`enr_destroy`](@ref): destruction operator in the excitation number restricted (ENR) space
114+
- [`enr_identity`](@ref): identity operator in the excitation number restricted (ENR) space
111115
- [`commutator`](@ref): commutator or anti-commutator
112116
- [`tunneling`](@ref): tunneling operator
113117
- [`qft`](@ref): discrete quantum Fourier transform matrix

src/QuantumToolbox.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ include("linear_maps.jl")
8484

8585
# Quantum Object
8686
include("qobj/space.jl")
87+
include("qobj/energy_restricted.jl")
8788
include("qobj/dimensions.jl")
8889
include("qobj/quantum_object_base.jl")
8990
include("qobj/quantum_object.jl")

src/negativity.jl

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,20 @@ Return the partial transpose of a density matrix ``\rho``, where `mask` is an ar
7171
- `ρ_pt::QuantumObject`: The density matrix with the selected subsystems transposed.
7272
"""
7373
function partial_transpose::QuantumObject{Operator}, mask::Vector{Bool})
74-
if length(mask) != length.dimensions)
74+
any(s -> s isa EnrSpace, ρ.dimensions.to) && throw(ArgumentError("partial_transpose does not support EnrSpace"))
75+
76+
(length(mask) != length.dimensions)) &&
7577
throw(ArgumentError("The length of \`mask\` should be equal to the length of \`ρ.dims\`."))
76-
end
77-
return _partial_transpose(ρ, mask)
78-
end
7978

80-
# for dense matrices
81-
function _partial_transpose::QuantumObject{Operator}, mask::Vector{Bool})
8279
isa.dimensions, GeneralDimensions) &&
8380
(get_dimensions_to(ρ) != get_dimensions_from(ρ)) &&
8481
throw(ArgumentError("Invalid partial transpose for dims = $(_get_dims_string.dimensions))"))
8582

83+
return _partial_transpose(ρ, mask)
84+
end
85+
86+
# for dense matrices
87+
function _partial_transpose::QuantumObject{Operator}, mask::Vector{Bool})
8688
mask2 = [1 + Int(i) for i in mask]
8789
# mask2 has elements with values equal to 1 or 2
8890
# 1 - the subsystem don't need to be transposed
@@ -107,10 +109,6 @@ function _partial_transpose(
107109
ρ::QuantumObject{Operator,DimsType,<:AbstractSparseArray},
108110
mask::Vector{Bool},
109111
) where {DimsType<:AbstractDimensions}
110-
isa.dimensions, GeneralDimensions) &&
111-
(get_dimensions_to(ρ) != get_dimensions_from(ρ)) &&
112-
throw(ArgumentError("Invalid partial transpose for dims = $(_get_dims_string.dimensions))"))
113-
114112
M, N = size(ρ)
115113
dimsTuple = Tuple(dimensions_to_dims(get_dimensions_to(ρ)))
116114
colptr = ρ.data.colptr

src/qobj/arithmetic_and_attributes.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ Quantum Object: type=Operator() dims=[2] size=(2, 2) ishermitian=true
505505
```
506506
"""
507507
function ptrace(QO::QuantumObject{Ket}, sel::Union{AbstractVector{Int},Tuple})
508+
any(s -> s isa EnrSpace, QO.dimensions.to) && throw(ArgumentError("ptrace does not support EnrSpace"))
509+
508510
_non_static_array_warning("sel", sel)
509511

510512
if length(sel) == 0 # return full trace for empty sel
@@ -527,6 +529,8 @@ end
527529
ptrace(QO::QuantumObject{Bra}, sel::Union{AbstractVector{Int},Tuple}) = ptrace(QO', sel)
528530

529531
function ptrace(QO::QuantumObject{Operator}, sel::Union{AbstractVector{Int},Tuple})
532+
any(s -> s isa EnrSpace, QO.dimensions.to) && throw(ArgumentError("ptrace does not support EnrSpace"))
533+
530534
# TODO: support for special cases when some of the subsystems have same `to` and `from` space
531535
isa(QO.dimensions, GeneralDimensions) &&
532536
(get_dimensions_to(QO) != get_dimensions_from(QO)) &&
@@ -714,6 +718,8 @@ function SparseArrays.permute(
714718
A::QuantumObject{ObjType},
715719
order::Union{AbstractVector{Int},Tuple},
716720
) where {ObjType<:Union{Ket,Bra,Operator}}
721+
any(s -> s isa EnrSpace, A.dimensions.to) && throw(ArgumentError("permute does not support EnrSpace"))
722+
717723
(length(order) != length(A.dimensions)) &&
718724
throw(ArgumentError("The order list must have the same length as the number of subsystems (A.dims)"))
719725

src/qobj/dimensions.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct Dimensions{N,T<:Tuple} <: AbstractDimensions{N,N}
1717
to::T
1818

1919
# make sure the elements in the tuple are all AbstractSpace
20-
Dimensions(to::NTuple{N,T}) where {N,T<:AbstractSpace} = new{N,typeof(to)}(to)
20+
Dimensions(to::NTuple{N,AbstractSpace}) where {N} = new{N,typeof(to)}(to)
2121
end
2222
function Dimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Integer,N}
2323
_non_static_array_warning("dims", dims)
@@ -43,12 +43,11 @@ Dimensions(dims::Any) = throw(
4343
A structure that describes the left-hand side (`to`) and right-hand side (`from`) Hilbert [`Space`](@ref) of an [`Operator`](@ref).
4444
"""
4545
struct GeneralDimensions{M,N,T1<:Tuple,T2<:Tuple} <: AbstractDimensions{M,N}
46-
# note that the number `N` should be the same for both `to` and `from`
4746
to::T1 # space acting on the left
4847
from::T2 # space acting on the right
4948

5049
# make sure the elements in the tuple are all AbstractSpace
51-
GeneralDimensions(to::NTuple{M,T1}, from::NTuple{N,T2}) where {M,N,T1<:AbstractSpace,T2<:AbstractSpace} =
50+
GeneralDimensions(to::NTuple{M,AbstractSpace}, from::NTuple{N,AbstractSpace}) where {M,N} =
5251
new{M,N,typeof(to),typeof(from)}(to, from)
5352
end
5453
function GeneralDimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Union{AbstractVector,NTuple},N}
@@ -98,3 +97,8 @@ function _get_dims_string(dimensions::GeneralDimensions)
9897
return "[$(string(dims[1])), $(string(dims[2]))]"
9998
end
10099
_get_dims_string(::Nothing) = "nothing" # for EigsolveResult.dimensions = nothing
100+
101+
Base.:(==)(dim1::Dimensions, dim2::Dimensions) = dim1.to == dim2.to
102+
Base.:(==)(dim1::GeneralDimensions, dim2::GeneralDimensions) = (dim1.to == dim2.to) && (dim1.from == dim2.from)
103+
Base.:(==)(dim1::Dimensions, dim2::GeneralDimensions) = false
104+
Base.:(==)(dim1::GeneralDimensions, dim2::Dimensions) = false

0 commit comments

Comments
 (0)