Skip to content

Commit 0764c62

Browse files
Fix all compilation errors
1 parent cb84998 commit 0764c62

File tree

6 files changed

+130
-185
lines changed

6 files changed

+130
-185
lines changed

src/qobj/arithmetic_and_attributes.jl

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ for op in (:(+), :(-), :(*))
3838
@eval begin
3939
function Base.$op(A::AbstractQuantumObject, B::AbstractQuantumObject)
4040
check_dimensions(A, B)
41+
A.type != B.type &&
42+
throw(DomainError((A.type, B.type), "The quantum objects should have the same type to do $op."))
4143
QType = promote_op_type(A, B)
4244
return QType($(op)(A.data, B.data), A.type, A.dimensions)
4345
end
@@ -50,52 +52,22 @@ for op in (:(+), :(-), :(*))
5052
end
5153
end
5254

53-
function check_mul_dimensions(from::NTuple{NA,AbstractSpace}, to::NTuple{NB,AbstractSpace}) where {NA,NB}
54-
(from != to) && throw(
55-
DimensionMismatch(
56-
"The quantum object with (right) dims = $(dimensions_to_dims(from)) can not multiply a quantum object with (left) dims = $(dimensions_to_dims(to)) on the right-hand side.",
57-
),
55+
for type in (:Operator, :SuperOperator)
56+
@eval function Base.:(*)(
57+
A::AbstractQuantumObject{$type,ProductDimensions},
58+
B::AbstractQuantumObject{$type,ProductDimensions},
5859
)
59-
return nothing
60-
end
61-
62-
for ADimType in (:Dimensions, :GeneralDimensions)
63-
for BDimType in (:Dimensions, :GeneralDimensions)
64-
if ADimType == BDimType == :Dimensions
65-
@eval begin
66-
function Base.:(*)(
67-
A::AbstractQuantumObject{Operator,<:$ADimType},
68-
B::AbstractQuantumObject{Operator,<:$BDimType},
69-
)
70-
check_dimensions(A, B)
71-
QType = promote_op_type(A, B)
72-
return QType(A.data * B.data, Operator(), A.dimensions)
73-
end
74-
end
75-
else
76-
@eval begin
77-
function Base.:(*)(
78-
A::AbstractQuantumObject{Operator,<:$ADimType},
79-
B::AbstractQuantumObject{Operator,<:$BDimType},
80-
)
81-
check_mul_dimensions(get_dimensions_from(A), get_dimensions_to(B))
82-
QType = promote_op_type(A, B)
83-
return QType(
84-
A.data * B.data,
85-
Operator(),
86-
GeneralDimensions(get_dimensions_to(A), get_dimensions_from(B)),
87-
)
88-
end
89-
end
90-
end
60+
check_mul_dimensions(get_dimensions_from(A), get_dimensions_to(B))
61+
QType = promote_op_type(A, B)
62+
return QType(A.data * B.data, $type(), ProductDimensions(get_dimensions_to(A), get_dimensions_from(B)))
9163
end
9264
end
9365

94-
function Base.:(*)(A::AbstractQuantumObject{Operator}, B::QuantumObject{Ket,<:Dimensions})
66+
function Base.:(*)(A::AbstractQuantumObject{Operator}, B::QuantumObject{Ket})
9567
check_mul_dimensions(get_dimensions_from(A), get_dimensions_to(B))
9668
return QuantumObject(A.data * B.data, Ket(), Dimensions(get_dimensions_to(A)))
9769
end
98-
function Base.:(*)(A::QuantumObject{Bra,<:Dimensions}, B::AbstractQuantumObject{Operator})
70+
function Base.:(*)(A::QuantumObject{Bra}, B::AbstractQuantumObject{Operator})
9971
check_mul_dimensions(get_dimensions_from(A), get_dimensions_to(B))
10072
return QuantumObject(A.data * B.data, Bra(), Dimensions(get_dimensions_from(B)))
10173
end
@@ -124,6 +96,15 @@ function Base.:(*)(A::QuantumObject{OperatorBra}, B::AbstractQuantumObject{Super
12496
return QuantumObject(A.data * B.data, OperatorBra(), A.dimensions)
12597
end
12698

99+
function check_mul_dimensions(from::NTuple{NA,AbstractSpace}, to::NTuple{NB,AbstractSpace}) where {NA,NB}
100+
(from != to) && throw(
101+
DimensionMismatch(
102+
"The quantum object with (right) dims = $(dimensions_to_dims(from)) can not multiply a quantum object with (left) dims = $(dimensions_to_dims(to)) on the right-hand side.",
103+
),
104+
)
105+
return nothing
106+
end
107+
127108
Base.:(^)(A::QuantumObject, n::T) where {T<:Number} = QuantumObject(^(A.data, n), A.type, A.dimensions)
128109
Base.:(/)(A::AbstractQuantumObject, n::T) where {T<:Number} = get_typename_wrapper(A)(A.data / n, A.type, A.dimensions)
129110

@@ -748,6 +729,5 @@ _dims_and_perm(::Operator, dims::SVector{N,Int}, order::AbstractVector{Int}, L::
748729
_dims_and_perm(::Operator, dims::SVector{2,SVector{N,Int}}, order::AbstractVector{Int}, L::Int) where {N} =
749730
reverse(vcat(dims[2], dims[1])), reverse((2 * L + 1) .- vcat(order, order .+ L))
750731

751-
_order_dimensions(dimensions::Dimensions, order::AbstractVector{Int}) = Dimensions(dimensions.to[order])
752-
_order_dimensions(dimensions::GeneralDimensions, order::AbstractVector{Int}) =
753-
GeneralDimensions(dimensions.to[order], dimensions.from[order])
732+
_order_dimensions(dimensions::ProductDimensions, order::AbstractVector{Int}) =
733+
ProductDimensions(dimensions.to[order], isnothing(dimensions.from) ? nothing : dimensions.from[order])

src/qobj/dimensions.jl

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,33 @@ export AbstractDimensions, Dimensions, GeneralDimensions
77
abstract type AbstractDimensions{M,N} end
88

99
@doc raw"""
10-
struct ProductDimensions{M,N,T1<:Tuple,T2<:Tuple} <: AbstractDimensions{M,N}
10+
struct ProductDimensions{M,N,T1<:Tuple,T2<:Union{<:Tuple, Nothing}} <: AbstractDimensions{M,N}
1111
to::T1
1212
from::T2
1313
end
1414
1515
A structure that describes the left-hand side (`to`) and right-hand side (`from`) dimensions of a quantum object.
1616
"""
17-
struct ProductDimensions{M,N,T1<:Tuple,T2<:Tuple} <: AbstractDimensions{M,N}
17+
struct ProductDimensions{M,N,T1<:Tuple,T2<:Union{<:Tuple,Nothing}} <: AbstractDimensions{M,N}
1818
to::T1 # space acting on the left
1919
from::T2 # space acting on the right
2020

2121
# make sure the elements in the tuple are all AbstractSpace
22-
GeneralDimensions(to::NTuple{M,AbstractSpace}, from::NTuple{N,AbstractSpace}) where {M,N} =
22+
GeneralDimensions(to::NTuple{M,AbstractSpace}, from::Union{NTuple{N,AbstractSpace},Nothing}) where {M,N} =
2323
new{M,N,typeof(to),typeof(from)}(to, from)
2424
end
2525
function ProductDimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Union{AbstractVector,NTuple},N}
2626
(length(dims) != 2) && throw(ArgumentError("Invalid dims = $dims"))
2727

28-
_non_static_array_warning("dims[1]", dims[1])
29-
_non_static_array_warning("dims[2]", dims[2])
30-
31-
L1 = length(dims[1])
32-
L2 = length(dims[2])
33-
(L1 > 0) || throw(DomainError(L1, "The length of `dims[1]` must be larger or equal to 1."))
34-
(L2 > 0) || throw(DomainError(L2, "The length of `dims[2]` must be larger or equal to 1."))
35-
36-
to = ntuple(i -> HilbertSpace(dims[1][i]), Val(L1))
37-
from = ntuple(i -> HilbertSpace(dims[2][i]), Val(L2))
28+
to = _dims_tuple_of_space(dims[1])
29+
from = isnothing(dims[2]) ? nothing : _dims_tuple_of_space(dims[2])
3830

3931
return ProductDimensions(to, from)
4032
end
4133

42-
ProductDimensions(dims::Union{Int, AbstractSpace}) = ProductDimensions((dims,), (dims,))
43-
ProductDimensions(to::NTuple{M,Int}, from::NTuple{N,Int}) where {M,N} = ProductDimensions((to, from))
44-
ProductDimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Integer,N} = ProductDimensions(dims, dims)
34+
ProductDimensions(dims::Union{Int,AbstractSpace}) = ProductDimensions((dims,), nothing)
35+
ProductDimensions(dims::Union{AbstractVector{T},NTuple{N,T}}) where {T<:Integer,N} = ProductDimensions(dims, nothing)
36+
ProductDimensions(to::NTuple{M,Int}, from::Union{NTuple{N,Int},Nothing}) where {M,N} = ProductDimensions((to, from))
4537
ProductDimensions(dims::ProductDimensions) = dims
4638

4739
# obtain dims in the type of SVector with integers
@@ -50,23 +42,36 @@ dimensions_to_dims(dimensions::ProductDimensions) =
5042
SVector{2}(dimensions_to_dims(dimensions.to), dimensions_to_dims(dimensions.from))
5143
dimensions_to_dims(::Nothing) = nothing # for EigsolveResult.dimensions = nothing
5244

53-
hilbert_dimensions_to_size(dimensions::ProductDimensions) = (prod(hilbert_dimensions_to_size, dimensions.to), prod(hilbert_dimensions_to_size, dimensions.from))
54-
liouvillian_dimensions_to_size(dimensions::ProductDimensions) =
55-
(prod(liouvillian_dimensions_to_size, dimensions.to), prod(liouvillian_dimensions_to_size, dimensions.from))
45+
hilbert_dimensions_to_size(dimensions::ProductDimensions) =
46+
(hilbert_dimensions_to_size(dimensions.to), hilbert_dimensions_to_size(dimensions.from))
47+
hilbert_dimensions_to_size(dimensions::NTuple{N,AbstractSpace}) where {N} = prod(hilbert_dimensions_to_size, dimensions)
48+
hilbert_dimensions_to_size(::Nothing) = nothing
5649

50+
liouvillian_dimensions_to_size(dimensions::ProductDimensions) =
51+
(liouvillian_dimensions_to_size(dimensions.to), liouvillian_dimensions_to_size(dimensions.from))
52+
liouvillian_dimensions_to_size(dimensions::NTuple{N,AbstractSpace}) where {N} =
53+
prod(liouvillian_dimensions_to_size, dimensions)
54+
liouvillian_dimensions_to_size(::Nothing) = nothing
5755

5856
Base.length(::AbstractDimensions{N}) where {N} = N
5957

6058
Base.transpose(dimensions::ProductDimensions) = ProductDimensions(dimensions.from, dimensions.to) # switch `to` and `from`
6159
Base.adjoint(dimensions::AbstractDimensions) = transpose(dimensions)
6260

61+
Base.:(==)(dim1::ProductDimensions, dim2::ProductDimensions) = (dim1.to == dim2.to) && (dim1.from == dim2.from)
62+
63+
function _dims_tuple_of_space(dims::NTuple{N,AbstractSpace}) where {N}
64+
_non_static_array_warning("dims", dims)
65+
66+
N > 0 || throw(DomainError(N, "The length of `dims` must be larger or equal to 1."))
67+
68+
return ntuple(dim -> HilbertSpace(dims[dim]), Val(N))
69+
end
70+
6371
# this is used to show `dims` for Qobj and QobjEvo
64-
_get_dims_string(dimensions::Dimensions) = string(dimensions_to_dims(dimensions))
6572
function _get_dims_string(dimensions::ProductDimensions)
6673
dims = dimensions_to_dims(dimensions)
67-
dims[1] == dims[2] && return string(dims[1])
74+
isnothing(dims[2]) && return string(dims[1])
6875
return "[$(string(dims[1])), $(string(dims[2]))]"
6976
end
7077
_get_dims_string(::Nothing) = "nothing" # for EigsolveResult.dimensions = nothing
71-
72-
Base.:(==)(dim1::ProductDimensions, dim2::ProductDimensions) = (dim1.to == dim2.to) && (dim1.from == dim2.from)

src/qobj/functions.jl

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -186,37 +186,22 @@ julia> a.dims, O.dims
186186
([20], [20, 20])
187187
```
188188
"""
189-
function Base.kron(
190-
A::AbstractQuantumObject{OpType,<:Dimensions},
191-
B::AbstractQuantumObject{OpType,<:Dimensions},
192-
) where {OpType<:Union{Ket,Bra,Operator}}
193-
QType = promote_op_type(A, B)
194-
_lazy_tensor_warning(A.data, B.data)
195-
return QType(kron(A.data, B.data), A.type, Dimensions((A.dimensions.to..., B.dimensions.to...)))
196-
end
197-
198-
# if A and B are both Operator but either one of them has GeneralDimensions
199-
for ADimType in (:Dimensions, :GeneralDimensions)
200-
for BDimType in (:Dimensions, :GeneralDimensions)
201-
if !(ADimType == BDimType == :Dimensions) # not for this case because it's already implemented
202-
@eval begin
203-
function Base.kron(
204-
A::AbstractQuantumObject{Operator,<:$ADimType},
205-
B::AbstractQuantumObject{Operator,<:$BDimType},
206-
)
207-
QType = promote_op_type(A, B)
208-
_lazy_tensor_warning(A.data, B.data)
209-
return QType(
210-
kron(A.data, B.data),
211-
Operator(),
212-
GeneralDimensions(
213-
(get_dimensions_to(A)..., get_dimensions_to(B)...),
214-
(get_dimensions_from(A)..., get_dimensions_from(B)...),
215-
),
216-
)
217-
end
218-
end
219-
end
189+
Base.kron(A::AbstractQuantumObject, B::AbstractQuantumObject)
190+
191+
for type in (:Operator, :SuperOperator)
192+
@eval function Base.kron(
193+
A::AbstractQuantumObject{$type,ProductDimensions},
194+
B::AbstractQuantumObject{$type,ProductDimensions},
195+
)
196+
QType = promote_op_type(A, B)
197+
_lazy_tensor_warning(A.data, B.data)
198+
199+
A_dims_from = get_dimensions_from(A)
200+
B_dims_from = get_dimensions_from(B)
201+
AB_dims_to = (get_dimensions_to(A)..., get_dimensions_to(B)...)
202+
AB_dims_from = (isnothing(A_dims_from) && isnothing(B_dims_from)) ? nothing : (A_dims_from..., B_dims_from...)
203+
204+
return QType(kron(A.data, B.data), $type(), ProductDimensions(AB_dims_to, AB_dims_from))
220205
end
221206
end
222207

src/qobj/operators.jl

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Returns a random unitary [`QuantumObject`](@ref).
1919
2020
The `dimensions` can be either the following types:
2121
- `dimensions::Int`: Number of basis states in the Hilbert space.
22-
- `dimensions::Union{Dimensions,AbstractVector{Int},Tuple}`: list of dimensions representing the each number of basis in the subsystems.
22+
- `dimensions::Union{AbstractDimensions,AbstractVector{Int},Tuple}`: list of dimensions representing the each number of basis in the subsystems.
2323
2424
The `distribution` specifies which of the method used to obtain the unitary matrix:
2525
- `:haar`: Haar random unitary matrix using the algorithm from reference 1
@@ -33,10 +33,12 @@ The `distribution` specifies which of the method used to obtain the unitary matr
3333
"""
3434
rand_unitary(dimensions::Int, distribution::Union{Symbol,Val} = Val(:haar)) =
3535
rand_unitary(SVector(dimensions), makeVal(distribution))
36-
rand_unitary(dimensions::Union{Dimensions,AbstractVector{Int},Tuple}, distribution::Union{Symbol,Val} = Val(:haar)) =
37-
rand_unitary(dimensions, makeVal(distribution))
38-
function rand_unitary(dimensions::Union{Dimensions,AbstractVector{Int},Tuple}, ::Val{:haar})
39-
N = prod(dimensions)
36+
rand_unitary(
37+
dimensions::Union{AbstractDimensions,AbstractVector{Int},Tuple},
38+
distribution::Union{Symbol,Val} = Val(:haar),
39+
) = rand_unitary(dimensions, makeVal(distribution))
40+
function rand_unitary(dimensions::Union{AbstractDimensions,AbstractVector{Int},Tuple}, ::Val{:haar})
41+
N = hilbert_dimensions_to_size(dimensions)[1]
4042

4143
# generate N x N matrix Z of complex standard normal random variates
4244
Z = randn(ComplexF64, N, N)
@@ -50,8 +52,8 @@ function rand_unitary(dimensions::Union{Dimensions,AbstractVector{Int},Tuple}, :
5052
Λ ./= abs.(Λ) # rescaling the elements
5153
return QuantumObject(to_dense(Q * Diagonal(Λ)); type = Operator(), dims = dimensions)
5254
end
53-
function rand_unitary(dimensions::Union{Dimensions,AbstractVector{Int},Tuple}, ::Val{:exp})
54-
N = prod(dimensions)
55+
function rand_unitary(dimensions::Union{AbstractDimensions,AbstractVector{Int},Tuple}, ::Val{:exp})
56+
N = hilbert_dimensions_to_size(dimensions)[1]
5557

5658
# generate N x N matrix Z of complex standard normal random variates
5759
Z = randn(ComplexF64, N, N)
@@ -61,7 +63,7 @@ function rand_unitary(dimensions::Union{Dimensions,AbstractVector{Int},Tuple}, :
6163

6264
return to_dense(exp(-1.0im * H))
6365
end
64-
rand_unitary(dimensions::Union{Dimensions,AbstractVector{Int},Tuple}, ::Val{T}) where {T} =
66+
rand_unitary(dimensions::Union{AbstractDimensions,AbstractVector{Int},Tuple}, ::Val{T}) where {T} =
6567
throw(ArgumentError("Invalid distribution: $(T)"))
6668

6769
@doc raw"""
@@ -530,7 +532,7 @@ Generates a discrete Fourier transform matrix ``\hat{F}_N`` for [Quantum Fourier
530532
531533
The `dimensions` can be either the following types:
532534
- `dimensions::Int`: Number of basis states in the Hilbert space.
533-
- `dimensions::Union{Dimensions,AbstractVector{Int},Tuple}`: list of dimensions representing the each number of basis in the subsystems.
535+
- `dimensions::Union{AbstractDimensions,AbstractVector{Int},Tuple}`: list of dimensions representing the each number of basis in the subsystems.
534536
535537
``N`` represents the total dimension, and therefore the matrix is defined as
536538
@@ -551,8 +553,8 @@ where ``\omega = \exp(\frac{2 \pi i}{N})``.
551553
It is highly recommended to use `qft(dimensions)` with `dimensions` as `Tuple` or `SVector` from [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) to keep type stability. See the [related Section](@ref doc:Type-Stability) about type stability for more details.
552554
"""
553555
qft(dimensions::Int) = QuantumObject(_qft_op(dimensions), Operator(), dimensions)
554-
qft(dimensions::Union{Dimensions,AbstractVector{Int},Tuple}) =
555-
QuantumObject(_qft_op(prod(dimensions)), Operator(), dimensions)
556+
qft(dimensions::Union{AbstractDimensions,AbstractVector{Int},Tuple}) =
557+
QuantumObject(_qft_op(hilbert_dimensions_to_size(dimensions)[1]), Operator(), dimensions)
556558
function _qft_op(N::Int)
557559
ω = exp(2.0im * π / N)
558560
arr = 0:(N-1)

0 commit comments

Comments
 (0)