Skip to content

Commit a5cd9fd

Browse files
committed
update definition for AbstractDimensions
1 parent ff0a997 commit a5cd9fd

File tree

8 files changed

+95
-69
lines changed

8 files changed

+95
-69
lines changed

src/QuantumToolbox.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ include("progress_bar.jl")
7979
include("linear_maps.jl")
8080

8181
# Quantum Object
82+
include("qobj/quantum_object_base.jl")
8283
include("qobj/space.jl")
8384
include("qobj/dimensions.jl")
84-
include("qobj/quantum_object_base.jl")
8585
include("qobj/quantum_object.jl")
8686
include("qobj/quantum_object_evo.jl")
8787
include("qobj/boolean_functions.jl")

src/qobj/dimensions.jl

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,62 @@
1-
export AbstractDimensions, Dimensions#, CompoundDimensions
1+
export AbstractDimensions, Dimensions, CompoundDimensions
22

33
abstract type AbstractDimensions{N} end
44

55
struct Dimensions{N} <: AbstractDimensions{N}
6-
to::SVector{N,AbstractSpace}
6+
to::SVector{N,<:AbstractSpace}
77
end
8-
Base.show(io::IO, D::Dimensions) = print(io, D.to)
9-
108
function Dimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Integer,N}
119
_non_static_array_warning("dims", dims)
1210
L = length(dims)
1311
(L > 0) || throw(DomainError(dims, "The argument dims must be of non-zero length"))
1412

15-
return Dimensions(SVector{L,AbstractSpace}(Space.(dims)))
13+
return Dimensions{L}(SVector{L,Space}(Space.(dims)))
1614
end
17-
18-
# this creates a list of Space(1), it's used to generate `from` for Ket, and `` for Bra)
19-
# oneDimensions(N::Int) = Dimensions(SVector{N,AbstractSpace}(ntuple(i -> Space(1), Val(N))))
20-
21-
_gen_dims(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Integer,N} = Dimensions(dims)
22-
_gen_dims(dims::Int) = Dimensions(SVector{1,AbstractSpace}(Space(dims)))
23-
_gen_dims(dims::AbstractDimensions) = dims
24-
_gen_dims(dims::Any) = throw(
15+
Dimensions(dims::Int) = Dimensions(SVector{1,Int}(dims))
16+
Dimensions(dims::Any) = throw(
2517
ArgumentError(
2618
"The argument dims must be a Tuple or a StaticVector of non-zero length and contain only positive integers.",
2719
),
2820
)
2921

30-
#= struct CompoundDimensions{N} <: AbstractDimensions{N}
22+
Base.show(io::IO, D::Dimensions) = print(io, D.to)
23+
24+
# this creates a list of Space(1), it's used to generate `from` for Ket, and `to` for Bra)
25+
oneDimensions(N::Int) = Dimensions(SVector{N,Space}(ntuple(i -> Space(1), Val(N))))
26+
27+
struct CompoundDimensions{N} <: AbstractDimensions{N}
3128
# note that the number `N` should be the same for both `to` and `from`
32-
to::SVector{N,AbstractSpace} # space acting on the left
33-
from::SVector{N,AbstractSpace} # space acting on the right
29+
to::SVector{N,<:AbstractSpace} # space acting on the left
30+
from::SVector{N,<:AbstractSpace} # space acting on the right
3431
end
35-
Base.show(io::IO, D::CompoundDimensions) = print(io, "[", D.to, ", ", D.from, "]")
36-
3732
function CompoundDimensions(to::Union{AbstractVector{T},NTuple{N1,T}}, from::Union{AbstractVector{T},NTuple{N2,T}}) where {T<:Integer,N1,N2}
3833
_non_static_array_warning("dims", to)
3934
_non_static_array_warning("dims", from)
4035

4136
L1 = length(to)
4237
L2 = length(from)
43-
((L1 > 0) && (L1 == L2)) || throw(DomainError((to, from), "The arguments `to` and `from` must be in the same length and have at least one element."))
38+
((L1 > 0) && (L1 == L2)) || throw(DomainError((L1, L2), "The length of the arguments `to` and `from` must be in the same length and have at least one element."))
4439

45-
return CompoundDimensions(SVector{L1,AbstractSpace}(Space.(to)), SVector{L1,AbstractSpace}(Space.(from)))
40+
return CompoundDimensions{L1}(SVector{L1,Space}(Space.(to)), SVector{L1,Space}(Space.(from)))
4641
end
4742
CompoundDimensions(to::Int, from::Int) = CompoundDimensions(SVector{1,Int}(to), SVector{1,Int}(from))
48-
CompoundDimensions(::KetQuantumObject, dims::Dimensions) = CompoundDimensions(dims, oneDimensions(length(dims)))
49-
CompoundDimensions(::BraQuantumObject, dims::Dimensions) = CompoundDimensions(oneDimensions(length(dims)), dims)
50-
CompoundDimensions(::OperatorQuantumObject, dims::Dimensions) = CompoundDimensions(dims, dims)
51-
CompoundDimensions(::OperatorQuantumObject, dims::CompoundDimensions) = dims =#
43+
CompoundDimensions(::KetQuantumObject, dims::Dimensions{N}) where {N} = CompoundDimensions{N}(dims, oneDimensions(length(dims)))
44+
CompoundDimensions(::BraQuantumObject, dims::Dimensions{N}) where {N} = CompoundDimensions{N}(oneDimensions(length(dims)), dims)
45+
CompoundDimensions(::OperatorQuantumObject, dims::Dimensions{N}) where {N} = CompoundDimensions{N}(dims, dims)
46+
CompoundDimensions(::OperatorQuantumObject, dims::CompoundDimensions) = dims
47+
48+
Base.show(io::IO, D::CompoundDimensions) = print(io, "[", D.to, ", ", D.from, "]")
49+
50+
_gen_dims(dims::AbstractDimensions) = dims
51+
_gen_dims(dims::Any) = Dimensions(dims)
5252

5353
Base.length(dims::AbstractDimensions) = length(dims.to)
5454

5555
Base.prod(dims::Dimensions) = prod(dims.to)
56-
Base.prod(spaces::SVector{1,AbstractSpace}) = spaces[1].size # for `Dimensions.to` has only a single Space
56+
Base.prod(spaces::SVector{1,<:AbstractSpace}) = spaces[1].size # for `Dimensions.to` has only a single Space
5757

5858
LinearAlgebra.transpose(dims::Dimensions) = dims
59-
# LinearAlgebra.transpose(dims::CompoundDimensions) = CompoundDimensions(dims.from, dims.to) # switch `to` and `from`
59+
LinearAlgebra.transpose(dims::CompoundDimensions) = CompoundDimensions(dims.from, dims.to) # switch `to` and `from`
6060

61-
LinearAlgebra.kron(Adims::Dimensions, Bdims::Dimensions) = Dimensions(vcat(Adims.to, Bdims.to))
62-
# LinearAlgebra.kron(Adims::CompoundDimensions, Bdims::CompoundDimensions) = CompoundDimensions(vcat(Adims.to, Bdims.to), vcat(Adims.from, Bdims.from))
61+
LinearAlgebra.kron(Adims::Dimensions{NA}, Bdims::Dimensions{NB}) where {NA,NB} = Dimensions{NA+NB}(vcat(Adims.to, Bdims.to))
62+
LinearAlgebra.kron(Adims::CompoundDimensions{NA}, Bdims::CompoundDimensions{NB}) where {NA,NB} = CompoundDimensions{NA+NB}(vcat(Adims.to, Bdims.to), vcat(Adims.from, Bdims.from))

src/qobj/functions.jl

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -178,25 +178,53 @@ julia> a.dims, O.dims
178178
([20], [20, 20])
179179
```
180180
"""
181-
function LinearAlgebra.kron(
182-
A::AbstractQuantumObject{DT1,AOpType},
183-
B::AbstractQuantumObject{DT2,BOpType},
184-
) where {DT1,DT2,AOpType<:Union{KetQuantumObject,BraQuantumObject,OperatorQuantumObject},BOpType<:Union{KetQuantumObject,BraQuantumObject,OperatorQuantumObject}}
181+
function LinearAlgebra.kron( # for same OpType. Note that `<:DimType` means same DimType but can have different length N : DimType{N}
182+
A::AbstractQuantumObject{DT1,OpType,<:DimType},
183+
B::AbstractQuantumObject{DT2,OpType,<:DimType},
184+
) where {DT1,DT2,OpType<:Union{KetQuantumObject,BraQuantumObject,OperatorQuantumObject},DimType<:AbstractDimensions}
185185
QType = promote_op_type(A, B)
186-
kron_type = (AOpType == BOpType) ? A.type : Operator
187-
188-
# deal with dims; # TODO: uncomment the following if-else block when CompoundDimensions is supported
189-
# if (A.dims isa Dimensions) && (B.dims isa Dimensions)
190-
_Adims = A.dims
191-
_Bdims = B.dims
192-
# else
193-
# # transfer to CompoundDimensions
194-
# _Adims = CompoundDimensions(A.type, A.dims)
195-
# _Bdims = CompoundDimensions(B.type, B.dims) =#
196-
# end
197-
return QType(kron(A.data, B.data), kron_type, kron(_Adims, _Bdims))
186+
return QType(kron(A.data, B.data), A.type, kron(A.dims, B.dims))
198187
end
199188
LinearAlgebra.kron(A::AbstractQuantumObject) = A
189+
for DimType in (:Dimensions, :CompoundDimensions)
190+
@eval begin
191+
192+
end
193+
end
194+
function LinearAlgebra.kron( # if A and B are both Operator but different Dimensions type
195+
A::AbstractQuantumObject{DT1,OperatorQuantumObject,<:Dimensions},
196+
B::AbstractQuantumObject{DT2,OperatorQuantumObject,<:CompoundDimensions},
197+
) where {DT1,DT2}
198+
QType = promote_op_type(A, B)
199+
return QType(kron(A.data, B.data), Operator, kron(CompoundDimensions(A.type, A.dims), B.dims))
200+
end
201+
function LinearAlgebra.kron( # if A and B are both Operator but different Dimensions type
202+
A::AbstractQuantumObject{DT1,OperatorQuantumObject,<:CompoundDimensions},
203+
B::AbstractQuantumObject{DT2,OperatorQuantumObject,<:Dimensions},
204+
) where {DT1,DT2}
205+
QType = promote_op_type(A, B)
206+
return QType(kron(A.data, B.data), Operator, kron(A.dims, CompoundDimensions(B.type, B.dims)))
207+
end
208+
for AOpType in (:KetQuantumObject, :BraQuantumObject, :OperatorQuantumObject)
209+
for BOpType in (:KetQuantumObject, :BraQuantumObject, :OperatorQuantumObject)
210+
if (AOpType != BOpType)
211+
@eval begin
212+
function LinearAlgebra.kron(
213+
A::AbstractQuantumObject{DT1,$AOpType},
214+
B::AbstractQuantumObject{DT2,$BOpType},
215+
) where {DT1,DT2}
216+
QType = promote_op_type(A, B)
217+
218+
# transfer to CompoundDimensions
219+
_Adims = CompoundDimensions(A.type, A.dims)
220+
_Bdims = CompoundDimensions(B.type, B.dims)
221+
222+
return QType(kron(A.data, B.data), Operator, kron(_Adims, _Bdims))
223+
end
224+
end
225+
end
226+
end
227+
end
200228
function LinearAlgebra.kron(A::Vector{<:AbstractQuantumObject})
201229
@warn "`tensor(A)` or `kron(A)` with `A` is a `Vector` can hurt performance. Try to use `tensor(A...)` or `kron(A...)` instead."
202230
return kron(A...)

src/qobj/quantum_object.jl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ It also implements the fundamental functions in Julia standard library:
99
export QuantumObject
1010

1111
@doc raw"""
12-
struct QuantumObject{MT<:AbstractArray,ObjType<:QuantumObjectType,N} <: AbstractQuantumObject{MT,ObjType,N}
13-
data::MT
12+
struct QuantumObject{DataType<:AbstractArray,ObjType<:QuantumObjectType,DimType<:AbstractDimensions} <: AbstractQuantumObject{DataType,ObjType,DimType}
13+
data::DataType
1414
type::ObjType
15-
dims::AbstractDimensions{N}
15+
dims::DimType
1616
end
1717
1818
Julia struct representing any quantum objects.
@@ -33,19 +33,18 @@ julia> a isa QuantumObject
3333
true
3434
```
3535
"""
36-
struct QuantumObject{MT<:AbstractArray,ObjType<:QuantumObjectType,N} <: AbstractQuantumObject{MT,ObjType,N}
37-
data::MT
36+
struct QuantumObject{DataType<:AbstractArray,ObjType<:QuantumObjectType,DimType<:AbstractDimensions} <: AbstractQuantumObject{DataType,ObjType,DimType}
37+
data::DataType
3838
type::ObjType
39-
dims::AbstractDimensions{N}
39+
dims::DimType
4040

4141
function QuantumObject(data::MT, type::ObjType, dims) where {MT<:AbstractArray,ObjType<:QuantumObjectType}
4242
_dims = _gen_dims(dims)
43-
N = length(_dims)
4443

4544
_size = _get_size(data)
4645
_check_QuantumObject(type, _dims, _size[1], _size[2])
4746

48-
return new{MT,ObjType,N}(data, type, _dims)
47+
return new{MT,ObjType,typeof(_dims)}(data, type, _dims)
4948
end
5049
end
5150

src/qobj/quantum_object_base.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export QuantumObjectType,
1414
export Bra, Ket, Operator, OperatorBra, OperatorKet, SuperOperator
1515

1616
@doc raw"""
17-
abstract type AbstractQuantumObject{DataType,ObjType,N}
17+
abstract type AbstractQuantumObject{DataType,ObjType,DimType}
1818
1919
Abstract type for all quantum objects like [`QuantumObject`](@ref) and [`QuantumObjectEvolution`](@ref).
2020
@@ -24,7 +24,7 @@ julia> sigmax() isa AbstractQuantumObject
2424
true
2525
```
2626
"""
27-
abstract type AbstractQuantumObject{DataType,ObjType,N} end
27+
abstract type AbstractQuantumObject{DataType,ObjType,DimType} end
2828

2929
abstract type QuantumObjectType end
3030

src/qobj/quantum_object_evo.jl

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ This file defines the QuantumObjectEvolution (QobjEvo) structure.
55
export QuantumObjectEvolution
66

77
@doc raw"""
8-
struct QuantumObjectEvolution{DT<:AbstractSciMLOperator,ObjType<:QuantumObjectType,N} <: AbstractQuantumObject{DT,ObjType,N}
9-
data::DT
8+
struct QuantumObjectEvolution{DataType<:AbstractSciMLOperator,ObjType<:QuantumObjectType,DimType<:AbstractDimensions} <: AbstractQuantumObject{DataType,ObjType,DimType}
9+
data::DataType
1010
type::ObjType
11-
dims::AbstractDimensions{N}
11+
dims::DimType
1212
end
1313
1414
Julia struct representing any time-dependent quantum object. The `data` field is a `AbstractSciMLOperator` object that represents the time-dependent quantum object. It can be seen as
@@ -97,13 +97,13 @@ Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=fal
9797
```
9898
"""
9999
struct QuantumObjectEvolution{
100-
DT<:AbstractSciMLOperator,
100+
DataType<:AbstractSciMLOperator,
101101
ObjType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject},
102-
N,
103-
} <: AbstractQuantumObject{DT,ObjType,N}
104-
data::DT
102+
DimType<:AbstractDimensions,
103+
} <: AbstractQuantumObject{DataType,ObjType,DimType}
104+
data::DataType
105105
type::ObjType
106-
dims::AbstractDimensions{N}
106+
dims::DimType
107107

108108
function QuantumObjectEvolution(
109109
data::DT,
@@ -114,12 +114,11 @@ struct QuantumObjectEvolution{
114114
throw(ArgumentError("The type $type is not supported for QuantumObjectEvolution."))
115115

116116
_dims = _gen_dims(dims)
117-
N = length(_dims)
118117

119118
_size = _get_size(data)
120119
_check_QuantumObject(type, _dims, _size[1], _size[2])
121120

122-
return new{DT,ObjType,N}(data, type, _dims)
121+
return new{DT,ObjType,typeof(_dims)}(data, type, _dims)
123122
end
124123
end
125124

src/qobj/space.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export AbstractSpace, Space
33
abstract type AbstractSpace end
44

55
# this show function is for printing AbstractDimensions
6-
Base.show(io::IO, svec::SVector{N,AbstractSpace}) where {N} = print(io, "[", join(svec, ", "), "]")
6+
Base.show(io::IO, svec::SVector{N,<:AbstractSpace}) where {N} = print(io, "[", join(svec, ", "), "]")
77

88
struct Space <: AbstractSpace
99
size::Int

test/core-test/quantum_objects.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,14 +310,14 @@
310310
for T in [ComplexF32, ComplexF64]
311311
N = 4
312312
a = rand(T, N)
313-
@inferred QuantumObject{typeof(a),KetQuantumObject,1} Qobj(a)
313+
@inferred QuantumObject{typeof(a),KetQuantumObject,Dimensions{1}} Qobj(a)
314314
for type in [Ket, OperatorKet]
315315
@inferred Qobj(a, type = type)
316316
end
317317

318318
UnionType = Union{
319-
QuantumObject{Matrix{T},BraQuantumObject,1},
320-
QuantumObject{Matrix{T},OperatorQuantumObject,1},
319+
QuantumObject{Matrix{T},BraQuantumObject,Dimensions{1}},
320+
QuantumObject{Matrix{T},OperatorQuantumObject,Dimensions{1}},
321321
}
322322
a = rand(T, 1, N)
323323
@inferred UnionType Qobj(a)

0 commit comments

Comments
 (0)