Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve type instabilities when generating QuantumObjects #178

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 83 additions & 47 deletions src/qobj/quantum_object.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,87 @@
dims::Vector{Int}
end

function QuantumObject(

Check warning on line 144 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L144

Added line #L144 was not covered by tests
A::AbstractMatrix{T};
type::ObjType = nothing,
dims = nothing,
) where {T,ObjType<:Union{Nothing,QuantumObjectType}}
if type isa Nothing
type = Operator # default type

Check warning on line 150 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L149-L150

Added lines #L149 - L150 were not covered by tests
end

if type != Operator && type != SuperOperator
albertomercurio marked this conversation as resolved.
Show resolved Hide resolved
throw(

Check warning on line 154 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L153-L154

Added lines #L153 - L154 were not covered by tests
ArgumentError(
"The argument type must be OperatorQuantumObject or SuperOperatorQuantumObject if the input array is a matrix.",
albertomercurio marked this conversation as resolved.
Show resolved Hide resolved
),
)
end

_size = size(A)

Check warning on line 161 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L161

Added line #L161 was not covered by tests

if dims isa Nothing
if type isa OperatorQuantumObject
dims = [_size[1]]
elseif type isa SuperOperatorQuantumObject
dims = [isqrt(_size[1])]

Check warning on line 167 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L163-L167

Added lines #L163 - L167 were not covered by tests
end
else
_check_dims(dims)

Check warning on line 170 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L170

Added line #L170 was not covered by tests
end

_check_QuantumObject(type, dims, _size[1], _size[2])
return QuantumObject(A, type, dims)

Check warning on line 174 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L173-L174

Added lines #L173 - L174 were not covered by tests
end

function QuantumObject(

Check warning on line 177 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L177

Added line #L177 was not covered by tests
A::AbstractVector{T};
type::ObjType = nothing,
dims = nothing,
) where {T,ObjType<:Union{Nothing,QuantumObjectType}}
if type isa Nothing
type = Ket # default type

Check warning on line 183 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L182-L183

Added lines #L182 - L183 were not covered by tests
end

if type != Ket && type != Bra && type != OperatorKet && type != OperatorBra
albertomercurio marked this conversation as resolved.
Show resolved Hide resolved
throw(

Check warning on line 187 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L186-L187

Added lines #L186 - L187 were not covered by tests
ArgumentError(
"The argument type must be KetQuantumObject, BraQuantumObject, OperatorKetQuantumObject or OperatorBraQuantumObject if the input array is a vector.",
albertomercurio marked this conversation as resolved.
Show resolved Hide resolved
),
)
end

_size = (length(A), 1)

Check warning on line 194 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L194

Added line #L194 was not covered by tests

if dims isa Nothing
if (type isa KetQuantumObject) || (type isa BraQuantumObject)
dims = [_size[1]]
elseif (type isa OperatorKetQuantumObject) || (type isa OperatorBraQuantumObject)
dims = [isqrt(_size[1])]

Check warning on line 200 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L196-L200

Added lines #L196 - L200 were not covered by tests
end
else
_check_dims(dims)

Check warning on line 203 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L203

Added line #L203 was not covered by tests
end

if (type isa BraQuantumObject) || (type isa OperatorBraQuantumObject)
data = A'
_size = (1, length(A))

Check warning on line 208 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L206-L208

Added lines #L206 - L208 were not covered by tests
else
data = A

Check warning on line 210 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L210

Added line #L210 was not covered by tests
end

_check_QuantumObject(type, dims, _size[1], _size[2])
return QuantumObject(data, type, dims)

Check warning on line 214 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L213-L214

Added lines #L213 - L214 were not covered by tests
end

function QuantumObject(

Check warning on line 217 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L217

Added line #L217 was not covered by tests
A::AbstractArray{T,N};
type::ObjType = nothing,
dims = nothing,
) where {T,N,ObjType<:Union{Nothing,QuantumObjectType}}
throw(ArgumentError("The input array must be a vector or a matrix."))

Check warning on line 222 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L222

Added line #L222 was not covered by tests
end

function Base.show(
io::IO,
QO::QuantumObject{<:AbstractArray{T},OpType},
Expand Down Expand Up @@ -175,51 +256,6 @@
return show(io, MIME("text/plain"), op_data)
end

function QuantumObject(
A::AbstractArray{T,N};
type::ObjType = nothing,
dims = nothing,
) where {T,N,ObjType<:Union{Nothing,QuantumObjectType}}

# only accept 1D- and 2D-array
if N == 1
Size = (length(A), 1)
else
Size = size(A)
(N > 2) && throw(DomainError(Size, "The dimension of the array is not compatible with Quantum Object"))
end

# decide QuantumObjectType from the size of A
if type isa Nothing
if Size[1] == Size[2]
type = Operator
elseif Size[2] == 1
type = Ket
elseif Size[1] == 1
type = Bra
else
throw(DomainError(Size, "The dimension of the array is not compatible with Quantum Object"))
end
end

# decide dims from the size of A and the given type
if dims isa Nothing
if (type isa KetQuantumObject) || (type isa OperatorQuantumObject)
dims = [Size[1]]
elseif (type isa SuperOperatorQuantumObject) || (type isa OperatorKetQuantumObject)
dims = [isqrt(Size[1])]
elseif type isa BraQuantumObject
dims = [Size[2]]
elseif type isa OperatorBraQuantumObject
dims = [isqrt(Size[2])]
end
else
_check_dims(dims)
end
_check_QuantumObject(type, dims, Size[1], Size[2])
return QuantumObject(A, type, dims)
end

_check_dims(dims::Vector{Int}) =
all(>(0), dims) || throw(DomainError(dims, "The argument dims must be a vector with positive integers."))
_check_dims(dims::Any) = throw(ArgumentError("The argument dims must be a vector with positive integers."))
Expand Down Expand Up @@ -269,8 +305,8 @@
type::ObjType = A.type,
dims = A.dims,
) where {T,N,ObjType<:QuantumObjectType}
Size = N == 1 ? (length(A), 1) : size(A)
_check_QuantumObject(type, dims, Size[1], Size[2])
_size = N == 1 ? (length(A), 1) : size(A)
_check_QuantumObject(type, dims, _size[1], _size[2])

Check warning on line 309 in src/qobj/quantum_object.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/quantum_object.jl#L308-L309

Added lines #L308 - L309 were not covered by tests
return QuantumObject(copy(A.data), type, dims)
end

Expand Down
51 changes: 34 additions & 17 deletions test/quantum_objects.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
@testset "Quantum Objects" begin
# unsupported size of array
for a in [rand(ComplexF64, 3, 2), rand(ComplexF64, 2, 2, 2)]
for t in [nothing, Ket, Bra, Operator, SuperOperator, OperatorBra, OperatorKet]
@test_throws DomainError Qobj(a, type = t)
end
a = rand(ComplexF64, 3, 2)
for t in [nothing, Operator, SuperOperator]
@test_throws DomainError Qobj(a, type = t)
end
for t in [Ket, Bra, OperatorBra, OperatorKet]
@test_throws ArgumentError Qobj(a, type = t)
end
a = rand(ComplexF64, 2, 2, 2)
for t in [nothing, Ket, Bra, Operator, SuperOperator, OperatorBra, OperatorKet]
@test_throws ArgumentError Qobj(a, type = t)
end

# unsupported dims
Expand All @@ -16,19 +22,17 @@
N = 10
a = rand(ComplexF64, 10)
# @test_logs (:warn, "The norm of the input data is not one.") QuantumObject(a)
@test_throws DomainError Qobj(a, type = Bra)
@test_throws DomainError Qobj(a, type = Operator)
@test_throws DomainError Qobj(a, type = SuperOperator)
@test_throws DomainError Qobj(a, type = OperatorBra)
@test_throws DomainError Qobj(a', type = Ket)
@test_throws ArgumentError Qobj(a, type = Operator)
@test_throws ArgumentError Qobj(a, type = SuperOperator)
@test_throws ArgumentError Qobj(a', type = Ket)
@test_throws DomainError Qobj(a', type = Operator)
@test_throws DomainError Qobj(a', type = SuperOperator)
@test_throws DomainError Qobj(a', type = OperatorKet)
@test_throws ArgumentError Qobj(a', type = OperatorKet)
@test_throws DimensionMismatch Qobj(a, dims = [2])
@test_throws DimensionMismatch Qobj(a', dims = [2])
a2 = Qobj(a')
@test_throws DomainError Qobj(a', dims = [2])
a2 = Qobj(a, type = Bra)
a3 = Qobj(a)
@test dag(a3) == a2
albertomercurio marked this conversation as resolved.
Show resolved Hide resolved
@test a3' == a2
@test isket(a2) == false
@test isbra(a2) == true
@test isoper(a2) == false
Expand All @@ -43,7 +47,6 @@
@test isoperbra(a3) == false
@test Qobj(a3) == a3
@test !(Qobj(a3) === a3)
@test isket(Qobj(Matrix([2 3])')) == true

a = sprand(ComplexF64, 100, 100, 0.1)
a2 = Qobj(a)
Expand All @@ -62,15 +65,14 @@
@test isoperket(a3) == false
@test isoperbra(a3) == false
@test_throws DimensionMismatch Qobj(a, dims = [2])
@test_throws DimensionMismatch Qobj(a, dims = [2])

# Operator-Ket, Operator-Bra tests
H = 0.3 * sigmax() + 0.7 * sigmaz()
L = liouvillian(H)
ρ = Qobj(rand(ComplexF64, 2, 2))
ρ_ket = mat2vec(ρ)
ρ_bra = ρ_ket'
@test ρ_bra == Qobj(mat2vec(ρ.data)', type = OperatorBra)
@test ρ_bra == Qobj(mat2vec(ρ.data), type = OperatorBra)
@test ρ == vec2mat(ρ_ket)
@test isket(ρ_ket) == false
@test isbra(ρ_ket) == false
Expand All @@ -94,7 +96,7 @@
@test (ρ_bra * L')' == L * ρ_ket
@test sum((conj(ρ) .* ρ).data) ≈ dot(ρ_ket, ρ_ket) ≈ ρ_bra * ρ_ket
@test_throws DimensionMismatch Qobj(ρ_ket.data, type = OperatorKet, dims = [4])
@test_throws DimensionMismatch Qobj(ρ_bra.data, type = OperatorBra, dims = [4])
@test_throws ArgumentError Qobj(ρ_bra.data, type = OperatorBra, dims = [4])

# matrix element
s0 = Qobj(basis(4, 0).data; type = OperatorKet)
Expand Down Expand Up @@ -383,4 +385,19 @@
@test_throws ArgumentError permute(bra_bdca, wrong_order2)
@test_throws ArgumentError permute(op_bdca, wrong_order1)
@test_throws ArgumentError permute(op_bdca, wrong_order2)

@testset "Type Inference" begin
for T in [Float32, Float64, ComplexF32, ComplexF64]
N = 25
a = rand(T, N)
for type in [Ket, Bra, OperatorKet, OperatorBra]
@inferred Qobj(a, type = type)
end

a = rand(T, N, N)
for type in [Operator, SuperOperator]
@inferred Qobj(a, type = type)
end
end
end
end