Skip to content

Commit 1c85c41

Browse files
Refactor dimension handling by introducing hilbert_dimensions_to_size and liouville_dimensions_to_size functions
1 parent bc75150 commit 1c85c41

18 files changed

+101
-41
lines changed

docs/src/getting_started/type_stability.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ The `dims` field contains the dimensions of the subsystems (in this case, three
183183

184184
```@example type-stability
185185
function reshape_operator_data(dims)
186-
op = Qobj(randn(prod(dims), prod(dims)), type=Operator(), dims=dims)
186+
op = Qobj(randn(hilbert_dimensions_to_size(dims)...), type=Operator(), dims=dims)
187187
op_dims = op.dims
188188
op_data = op.data
189189
return reshape(op_data, vcat(op_dims, op_dims)...)

docs/src/resources/api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ convert_unit
326326
row_major_reshape
327327
meshgrid
328328
enr_state_dictionaries
329+
hilbert_dimensions_to_size
330+
liouville_dimensions_to_size
329331
```
330332

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

ext/QuantumToolboxMakieExt.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ function _plot_fock_distribution(
226226
kwargs...,
227227
) where {SType<:Union{Bra,Ket,Operator}}
228228
ρ = ket2dm(ρ)
229-
D = prod.dims)
229+
D = hilbert_dimensions_to_size.dims)[1]
230230
isapprox(tr(ρ), 1, atol = 1e-4) || (@warn "The input ρ should be normalized.")
231231

232232
xvec = 0:(D-1)

src/correlations.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ function correlation_2op_2t(
113113
reverse::Bool = false,
114114
kwargs...,
115115
) where {HOpType<:Union{Operator,SuperOperator},StateOpType<:Union{Ket,Operator}}
116-
C = eye(prod(H.dimensions), dims = H.dimensions)
116+
C = eye(hilbert_dimensions_to_size(H.dimensions)[1], dims = H.dimensions)
117117
if reverse
118118
corr = correlation_3op_2t(H, ψ0, tlist, τlist, c_ops, A, B, C; kwargs...)
119119
else

src/qobj/arithmetic_and_attributes.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,15 +672,15 @@ Get the coherence value ``\alpha`` by measuring the expectation value of the des
672672
It returns both ``\alpha`` and the corresponding state with the coherence removed: ``\ket{\delta_\alpha} = \exp ( \alpha^* \hat{a} - \alpha \hat{a}^\dagger ) \ket{\psi}`` for a pure state, and ``\hat{\rho_\alpha} = \exp ( \alpha^* \hat{a} - \alpha \hat{a}^\dagger ) \hat{\rho} \exp ( -\bar{\alpha} \hat{a} + \alpha \hat{a}^\dagger )`` for a density matrix. These states correspond to the quantum fluctuations around the coherent state ``\ket{\alpha}`` or ``|\alpha\rangle\langle\alpha|``.
673673
"""
674674
function get_coherence::QuantumObject{Ket})
675-
a = destroy(prod.dimensions))
675+
a = destroy(hilbert_dimensions_to_size.dimensions)[1])
676676
α = expect(a, ψ)
677677
D = exp* a' - conj(α) * a)
678678

679679
return α, D' * ψ
680680
end
681681

682682
function get_coherence::QuantumObject{Operator})
683-
a = destroy(prod.dimensions))
683+
a = destroy(hilbert_dimensions_to_size.dimensions)[1])
684684
α = expect(a, ρ)
685685
D = exp* a' - conj(α) * a)
686686

src/qobj/dimensions.jl

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ This file defines the ProductDimensions structures, which can describe composite
33
=#
44

55
export AbstractDimensions, ProductDimensions, GeneralProductDimensions
6+
export hilbert_dimensions_to_size, liouville_dimensions_to_size
67

78
abstract type AbstractDimensions{M,N} end
89

@@ -80,11 +81,52 @@ dimensions_to_dims(::Nothing) = nothing # for EigsolveResult.dimensions = nothin
8081

8182
Base.length(::AbstractDimensions{N}) where {N} = N
8283

83-
# need to specify return type `Int` for `_get_space_size`
84-
# otherwise the type of `prod(::ProductDimensions)` will be unstable
85-
_get_space_size(s::AbstractSpace)::Int = s.size
86-
Base.prod(dims::ProductDimensions) = prod(dims.to)
87-
Base.prod(spaces::NTuple{N,AbstractSpace}) where {N} = prod(_get_space_size, spaces)
84+
"""
85+
hilbert_dimensions_to_size(dimensions)
86+
87+
Returns the matrix dimensions `(m, n)` of an [`Operator`](@ref) with the given `dimensions`.
88+
89+
For [`ProductDimensions`](@ref), returns `(m, m)` where `m` is the product of all subsystem Hilbert space dimensions.
90+
For [`GeneralProductDimensions`](@ref), returns `(m, n)` where `m` is the product of the `to` dimensions
91+
and `n` is the product of the `from` dimensions.
92+
93+
If `dimensions` is an `Integer` or a vector/tuple of `Integer`s, it is automatically treated as [`ProductDimensions`](@ref).
94+
"""
95+
function hilbert_dimensions_to_size(dimensions::ProductDimensions)
96+
m = prod(hilbert_dimensions_to_size, dimensions.to)
97+
return (m, m)
98+
end
99+
function hilbert_dimensions_to_size(dimensions::GeneralProductDimensions)
100+
m = prod(hilbert_dimensions_to_size, dimensions.to)
101+
n = prod(hilbert_dimensions_to_size, dimensions.from)
102+
return (m, n)
103+
end
104+
hilbert_dimensions_to_size(dimensions::Union{<:Integer,AbstractVector{<:Integer},NTuple{N,Integer}}) where {N} =
105+
hilbert_dimensions_to_size(ProductDimensions(dimensions))
106+
107+
"""
108+
liouville_dimensions_to_size(dimensions)
109+
110+
Returns the matrix dimensions `(m, n)` of a [`SuperOperator`](@ref) with the given `dimensions`.
111+
112+
For [`ProductDimensions`](@ref), returns `(m, m)` where `m` is the product of all subsystem Liouville space dimensions
113+
(each Hilbert dimension `d` contributes `d²` to the product).
114+
For [`GeneralProductDimensions`](@ref), returns `(m, n)` where `m` is the product of the `to` dimensions
115+
and `n` is the product of the `from` dimensions.
116+
117+
If `dimensions` is an `Integer` or a vector/tuple of `Integer`s, it is automatically treated as [`ProductDimensions`](@ref).
118+
"""
119+
function liouville_dimensions_to_size(dimensions::ProductDimensions)
120+
m = prod(liouville_dimensions_to_size, dimensions.to)
121+
return (m, m)
122+
end
123+
function liouville_dimensions_to_size(dimensions::GeneralProductDimensions)
124+
m = prod(liouville_dimensions_to_size, dimensions.to)
125+
n = prod(liouville_dimensions_to_size, dimensions.from)
126+
return (m, n)
127+
end
128+
liouville_dimensions_to_size(dimensions::Union{<:Integer,AbstractVector{<:Integer},NTuple{N,Integer}}) where {N} =
129+
liouville_dimensions_to_size(ProductDimensions(dimensions))
88130

89131
Base.transpose(dimensions::ProductDimensions) = dimensions
90132
Base.transpose(dimensions::GeneralProductDimensions) = GeneralProductDimensions(dimensions.from, dimensions.to) # switch `to` and `from`

src/qobj/eigsolve.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ end
424424
c_ops::Union{Nothing,AbstractVector,Tuple} = nothing;
425425
alg::AbstractODEAlgorithm = DP5(),
426426
params::NamedTuple = NamedTuple(),
427-
ρ0::AbstractMatrix = rand_dm(prod(H.dimensions)).data,
427+
ρ0::AbstractMatrix = rand_dm(hilbert_dimensions_to_size(H.dimensions)[1]).data,
428428
eigvals::Int = 1,
429429
krylovdim::Int = min(10, size(H, 1)),
430430
maxiter::Int = 200,
@@ -467,7 +467,7 @@ function eigsolve_al(
467467
c_ops::Union{Nothing,AbstractVector,Tuple} = nothing;
468468
alg::AbstractODEAlgorithm = DP5(),
469469
params::NamedTuple = NamedTuple(),
470-
ρ0::AbstractMatrix = rand_dm(prod(H.dimensions)).data,
470+
ρ0::AbstractMatrix = rand_dm(hilbert_dimensions_to_size(H.dimensions)[1]).data,
471471
eigvals::Int = 1,
472472
krylovdim::Int = min(10, size(H, 1)),
473473
maxiter::Int = 200,

src/qobj/energy_restricted.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ Base.:(==)(s_enr1::EnrSpace, s_enr2::EnrSpace) = (s_enr1.size == s_enr2.size) &&
7676

7777
dimensions_to_dims(s_enr::EnrSpace) = s_enr.dims
7878

79+
hilbert_dimensions_to_size(s_enr::EnrSpace) = s_enr.size
80+
liouville_dimensions_to_size(s_enr::EnrSpace) = s_enr.size^2
81+
7982
@doc raw"""
8083
enr_state_dictionaries(dims, n_excitations)
8184

src/qobj/operators.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ rand_unitary(
3838
distribution::Union{Symbol,Val} = Val(:haar),
3939
) = rand_unitary(dimensions, makeVal(distribution))
4040
function rand_unitary(dimensions::Union{ProductDimensions,AbstractVector{Int},Tuple}, ::Val{:haar})
41-
N = prod(dimensions)
41+
N = hilbert_dimensions_to_size(dimensions)[1]
4242

4343
# generate N x N matrix Z of complex standard normal random variates
4444
Z = randn(ComplexF64, N, N)
@@ -53,7 +53,7 @@ function rand_unitary(dimensions::Union{ProductDimensions,AbstractVector{Int},Tu
5353
return QuantumObject(to_dense(Q * Diagonal(Λ)); type = Operator(), dims = dimensions)
5454
end
5555
function rand_unitary(dimensions::Union{ProductDimensions,AbstractVector{Int},Tuple}, ::Val{:exp})
56-
N = prod(dimensions)
56+
N = hilbert_dimensions_to_size(dimensions)[1]
5757

5858
# generate N x N matrix Z of complex standard normal random variates
5959
Z = randn(ComplexF64, N, N)
@@ -554,7 +554,7 @@ where ``\omega = \exp(\frac{2 \pi i}{N})``.
554554
"""
555555
qft(dimensions::Int) = QuantumObject(_qft_op(dimensions), Operator(), dimensions)
556556
qft(dimensions::Union{ProductDimensions,AbstractVector{Int},Tuple}) =
557-
QuantumObject(_qft_op(prod(dimensions)), Operator(), dimensions)
557+
QuantumObject(_qft_op(hilbert_dimensions_to_size(dimensions)[1]), Operator(), dimensions)
558558
function _qft_op(N::Int)
559559
ω = exp(2.0im * π / N)
560560
arr = 0:(N-1)

src/qobj/quantum_object_base.jl

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,23 +142,23 @@ _check_QuantumObject(
142142

143143
function _check_QuantumObject(type::Ket, dimensions::ProductDimensions, m::Int, n::Int)
144144
(n != 1) && throw(DomainError((m, n), "The size of the array is not compatible with Ket"))
145-
(prod(dimensions) != m) && throw(
145+
(hilbert_dimensions_to_size(dimensions)[1] != m) && throw(
146146
DimensionMismatch("Ket with dims = $(_get_dims_string(dimensions)) does not fit the array size = $((m, n))."),
147147
)
148148
return nothing
149149
end
150150

151151
function _check_QuantumObject(type::Bra, dimensions::ProductDimensions, m::Int, n::Int)
152152
(m != 1) && throw(DomainError((m, n), "The size of the array is not compatible with Bra"))
153-
(prod(dimensions) != n) && throw(
153+
(hilbert_dimensions_to_size(dimensions)[1] != n) && throw(
154154
DimensionMismatch("Bra with dims = $(_get_dims_string(dimensions)) does not fit the array size = $((m, n))."),
155155
)
156156
return nothing
157157
end
158158

159159
function _check_QuantumObject(type::Operator, dimensions::ProductDimensions, m::Int, n::Int)
160-
L = prod(dimensions)
161-
(L == m == n) || throw(
160+
obj_size = hilbert_dimensions_to_size(dimensions)[1]
161+
(obj_size == m == n) || throw(
162162
DimensionMismatch(
163163
"Operator with dims = $(_get_dims_string(dimensions)) does not fit the array size = $((m, n)).",
164164
),
@@ -168,7 +168,8 @@ end
168168

169169
function _check_QuantumObject(type::Operator, dimensions::GeneralProductDimensions, m::Int, n::Int)
170170
((m == 1) || (n == 1)) && throw(DomainError((m, n), "The size of the array is not compatible with Operator"))
171-
((prod(dimensions.to) != m) || (prod(dimensions.from) != n)) && throw(
171+
obj_size = hilbert_dimensions_to_size(dimensions)
172+
((obj_size[1] != m) || (obj_size[2] != n)) && throw(
172173
DimensionMismatch(
173174
"Operator with dims = $(_get_dims_string(dimensions)) does not fit the array size = $((m, n)).",
174175
),
@@ -178,7 +179,7 @@ end
178179

179180
function _check_QuantumObject(type::SuperOperator, dimensions::ProductDimensions, m::Int, n::Int)
180181
(m != n) && throw(DomainError((m, n), "The size of the array is not compatible with SuperOperator"))
181-
(prod(dimensions) != sqrt(m)) && throw(
182+
(liouville_dimensions_to_size(dimensions)[1] != m) && throw(
182183
DimensionMismatch(
183184
"SuperOperator with dims = $(_get_dims_string(dimensions)) does not fit the array size = $((m, n)).",
184185
),
@@ -188,7 +189,7 @@ end
188189

189190
function _check_QuantumObject(type::OperatorKet, dimensions::ProductDimensions, m::Int, n::Int)
190191
(n != 1) && throw(DomainError((m, n), "The size of the array is not compatible with OperatorKet"))
191-
(prod(dimensions) != sqrt(m)) && throw(
192+
(liouville_dimensions_to_size(dimensions)[1] != m) && throw(
192193
DimensionMismatch(
193194
"OperatorKet with dims = $(_get_dims_string(dimensions)) does not fit the array size = $((m, n)).",
194195
),
@@ -198,7 +199,7 @@ end
198199

199200
function _check_QuantumObject(type::OperatorBra, dimensions::ProductDimensions, m::Int, n::Int)
200201
(m != 1) && throw(DomainError((m, n), "The size of the array is not compatible with OperatorBra"))
201-
(prod(dimensions) != sqrt(n)) && throw(
202+
(liouville_dimensions_to_size(dimensions)[1] != n) && throw(
202203
DimensionMismatch(
203204
"OperatorBra with dims = $(_get_dims_string(dimensions)) does not fit the array size = $((m, n)).",
204205
),

0 commit comments

Comments
 (0)