Skip to content

Commit ad8b0b8

Browse files
Support different length for to and from on GeneralDImensions (#448)
1 parent 6bc6e38 commit ad8b0b8

File tree

5 files changed

+31
-32
lines changed

5 files changed

+31
-32
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ 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+
- Support different length for `to` and `from` on GeneralDimensions. ([#448])
11+
1012
## [v0.30.0]
1113
Release date: 2025-04-12
1214

@@ -201,3 +203,4 @@ Release date: 2024-11-13
201203
[#438]: https://github.com/qutip/QuantumToolbox.jl/issues/438
202204
[#440]: https://github.com/qutip/QuantumToolbox.jl/issues/440
203205
[#443]: https://github.com/qutip/QuantumToolbox.jl/issues/443
206+
[#448]: https://github.com/qutip/QuantumToolbox.jl/issues/448

src/entropy.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ Here, ``S`` is the [Von Neumann entropy](https://en.wikipedia.org/wiki/Von_Neuma
149149
- `kwargs` are the keyword arguments for calculating Von Neumann entropy. See also [`entropy_vn`](@ref).
150150
"""
151151
function entropy_mutual(
152-
ρAB::QuantumObject{ObjType,<:AbstractDimensions{N}},
152+
ρAB::QuantumObject{ObjType,<:AbstractDimensions{N,N}},
153153
selA::Union{Int,AbstractVector{Int},Tuple},
154154
selB::Union{Int,AbstractVector{Int},Tuple};
155155
kwargs...,
@@ -182,7 +182,7 @@ Here, ``S`` is the [Von Neumann entropy](https://en.wikipedia.org/wiki/Von_Neuma
182182
- `kwargs` are the keyword arguments for calculating Von Neumann entropy. See also [`entropy_vn`](@ref).
183183
"""
184184
entropy_conditional(
185-
ρAB::QuantumObject{ObjType,<:AbstractDimensions{N}},
185+
ρAB::QuantumObject{ObjType,<:AbstractDimensions{N,N}},
186186
selB::Union{Int,AbstractVector{Int},Tuple};
187187
kwargs...,
188188
) where {ObjType<:Union{KetQuantumObject,OperatorQuantumObject},N} =

src/qobj/dimensions.jl

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ This file defines the Dimensions structures, which can describe composite Hilber
44

55
export AbstractDimensions, Dimensions, GeneralDimensions
66

7-
abstract type AbstractDimensions{N} end
7+
abstract type AbstractDimensions{M,N} end
88

99
@doc raw"""
10-
struct Dimensions{N,T<:Tuple} <: AbstractDimensions{N}
10+
struct Dimensions{N,T<:Tuple} <: AbstractDimensions{N, N}
1111
to::T
1212
end
1313
1414
A structure that describes the Hilbert [`Space`](@ref) of each subsystems.
1515
"""
16-
struct Dimensions{N,T<:Tuple} <: AbstractDimensions{N}
16+
struct Dimensions{N,T<:Tuple} <: AbstractDimensions{N,N}
1717
to::T
1818

1919
# make sure the elements in the tuple are all AbstractSpace
@@ -24,7 +24,7 @@ function Dimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Intege
2424
L = length(dims)
2525
(L > 0) || throw(DomainError(dims, "The argument dims must be of non-zero length"))
2626

27-
return Dimensions(NTuple{L,Space}(Space.(dims)))
27+
return Dimensions(Tuple(Space.(dims)))
2828
end
2929
Dimensions(dims::Int) = Dimensions(Space(dims))
3030
Dimensions(dims::DimType) where {DimType<:AbstractSpace} = Dimensions((dims,))
@@ -42,14 +42,14 @@ Dimensions(dims::Any) = throw(
4242
4343
A structure that describes the left-hand side (`to`) and right-hand side (`from`) Hilbert [`Space`](@ref) of an [`Operator`](@ref).
4444
"""
45-
struct GeneralDimensions{N,T1<:Tuple,T2<:Tuple} <: AbstractDimensions{N}
45+
struct GeneralDimensions{M,N,T1<:Tuple,T2<:Tuple} <: AbstractDimensions{M,N}
4646
# note that the number `N` should be the same for both `to` and `from`
4747
to::T1 # space acting on the left
4848
from::T2 # space acting on the right
4949

5050
# make sure the elements in the tuple are all AbstractSpace
51-
GeneralDimensions(to::NTuple{N,T1}, from::NTuple{N,T2}) where {N,T1<:AbstractSpace,T2<:AbstractSpace} =
52-
new{N,typeof(to),typeof(from)}(to, from)
51+
GeneralDimensions(to::NTuple{M,T1}, from::NTuple{N,T2}) where {M,N,T1<:AbstractSpace,T2<:AbstractSpace} =
52+
new{M,N,typeof(to),typeof(from)}(to, from)
5353
end
5454
function GeneralDimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Union{AbstractVector,NTuple},N}
5555
(length(dims) != 2) && throw(ArgumentError("Invalid dims = $dims"))
@@ -59,14 +59,10 @@ function GeneralDimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<
5959

6060
L1 = length(dims[1])
6161
L2 = length(dims[2])
62-
((L1 > 0) && (L1 == L2)) || throw(
63-
DomainError(
64-
(L1, L2),
65-
"The length of the arguments `dims[1]` and `dims[2]` must be in the same length and have at least one element.",
66-
),
67-
)
68-
69-
return GeneralDimensions(NTuple{L1,Space}(Space.(dims[1])), NTuple{L1,Space}(Space.(dims[2])))
62+
(L1 > 0) || throw(DomainError(L1, "The length of `dims[1]` must be larger or equal to 1."))
63+
(L2 > 0) || throw(DomainError(L2, "The length of `dims[2]` must be larger or equal to 1."))
64+
65+
return GeneralDimensions(Tuple(Space.(dims[1])), Tuple(Space.(dims[2])))
7066
end
7167

7268
_gen_dimensions(dims::AbstractDimensions) = dims

src/qobj/quantum_object_base.jl

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -263,25 +263,22 @@ function Base.getproperty(A::AbstractQuantumObject, key::Symbol)
263263
end
264264

265265
# this returns `to` in GeneralDimensions representation
266-
get_dimensions_to(A::AbstractQuantumObject{KetQuantumObject,<:Dimensions{N}}) where {N} = A.dimensions.to
266+
get_dimensions_to(A::AbstractQuantumObject{KetQuantumObject,<:Dimensions}) = A.dimensions.to
267267
get_dimensions_to(A::AbstractQuantumObject{BraQuantumObject,<:Dimensions{N}}) where {N} = space_one_list(N)
268-
get_dimensions_to(A::AbstractQuantumObject{OperatorQuantumObject,<:Dimensions{N}}) where {N} = A.dimensions.to
269-
get_dimensions_to(A::AbstractQuantumObject{OperatorQuantumObject,<:GeneralDimensions{N}}) where {N} = A.dimensions.to
268+
get_dimensions_to(A::AbstractQuantumObject{OperatorQuantumObject,<:Dimensions}) = A.dimensions.to
269+
get_dimensions_to(A::AbstractQuantumObject{OperatorQuantumObject,<:GeneralDimensions}) = A.dimensions.to
270270
get_dimensions_to(
271-
A::AbstractQuantumObject{ObjType,<:Dimensions{N}},
272-
) where {ObjType<:Union{SuperOperatorQuantumObject,OperatorBraQuantumObject,OperatorKetQuantumObject},N} =
273-
A.dimensions.to
271+
A::AbstractQuantumObject{ObjType,<:Dimensions},
272+
) where {ObjType<:Union{SuperOperatorQuantumObject,OperatorBraQuantumObject,OperatorKetQuantumObject}} = A.dimensions.to
274273

275274
# this returns `from` in GeneralDimensions representation
276275
get_dimensions_from(A::AbstractQuantumObject{KetQuantumObject,<:Dimensions{N}}) where {N} = space_one_list(N)
277-
get_dimensions_from(A::AbstractQuantumObject{BraQuantumObject,<:Dimensions{N}}) where {N} = A.dimensions.to
278-
get_dimensions_from(A::AbstractQuantumObject{OperatorQuantumObject,<:Dimensions{N}}) where {N} = A.dimensions.to
279-
get_dimensions_from(A::AbstractQuantumObject{OperatorQuantumObject,<:GeneralDimensions{N}}) where {N} =
280-
A.dimensions.from
276+
get_dimensions_from(A::AbstractQuantumObject{BraQuantumObject,<:Dimensions}) = A.dimensions.to
277+
get_dimensions_from(A::AbstractQuantumObject{OperatorQuantumObject,<:Dimensions}) = A.dimensions.to
278+
get_dimensions_from(A::AbstractQuantumObject{OperatorQuantumObject,<:GeneralDimensions}) = A.dimensions.from
281279
get_dimensions_from(
282-
A::AbstractQuantumObject{ObjType,<:Dimensions{N}},
283-
) where {ObjType<:Union{SuperOperatorQuantumObject,OperatorBraQuantumObject,OperatorKetQuantumObject},N} =
284-
A.dimensions.to
280+
A::AbstractQuantumObject{ObjType,<:Dimensions},
281+
) where {ObjType<:Union{SuperOperatorQuantumObject,OperatorBraQuantumObject,OperatorKetQuantumObject}} = A.dimensions.to
285282

286283
# functions for getting Float or Complex element type
287284
_FType(A::AbstractQuantumObject) = _FType(eltype(A))

test/core-test/quantum_objects.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
a2 = Qobj(a)
8787
a3 = Qobj(a, type = SuperOperator)
8888
a4 = Qobj(sprand(ComplexF64, 100, 10, 0.1)) # GeneralDimensions
89+
a5 = QuantumObject(rand(ComplexF64, 2*3*4, 5), dims = ((2, 3, 4), (5,)))
8990
@test isket(a2) == false
9091
@test isbra(a2) == false
9192
@test isoper(a2) == true
@@ -116,6 +117,8 @@
116117
@test isconstant(a4) == true
117118
@test isunitary(a4) == false
118119
@test a4.dims == [[100], [10]]
120+
@test isoper(a5) == true
121+
@test a5.dims == [[2, 3, 4], [5]]
119122
@test_throws DimensionMismatch Qobj(a, dims = 2)
120123
@test_throws DimensionMismatch Qobj(a4.data, dims = 2)
121124
@test_throws DimensionMismatch Qobj(a4.data, dims = ((100,), (2,)))
@@ -351,7 +354,7 @@
351354
for T in [ComplexF32, ComplexF64]
352355
N = 4
353356
a = rand(T, N)
354-
@inferred QuantumObject{KetQuantumObject,Dimensions{1},typeof(a)} Qobj(a)
357+
@inferred Qobj(a)
355358
for type in [Ket, OperatorKet]
356359
@inferred Qobj(a, type = type)
357360
end
@@ -367,7 +370,7 @@
367370
end
368371

369372
UnionType2 = Union{
370-
QuantumObject{OperatorQuantumObject,GeneralDimensions{1,Tuple{Space},Tuple{Space}},Matrix{T}},
373+
QuantumObject{OperatorQuantumObject,GeneralDimensions{1,1,Tuple{Space},Tuple{Space}},Matrix{T}},
371374
QuantumObject{OperatorQuantumObject,Dimensions{1,Tuple{Space}},Matrix{T}},
372375
}
373376
a = rand(T, N, N)

0 commit comments

Comments
 (0)