Skip to content

Commit

Permalink
Merge pull request #56 from ytdHuang/dev/superoperator
Browse files Browse the repository at this point in the history
Basic functionalities for Operator-Ket and Operator-Bra
  • Loading branch information
ytdHuang authored Apr 5, 2024
2 parents cc66f38 + 6fc0054 commit 0060fff
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 5 deletions.
48 changes: 44 additions & 4 deletions src/quantum_object.jl
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,12 @@ function QuantumObject(A::AbstractArray{T, N}; type::Type{ObjType}=Nothing, dims
if dims === nothing
if (type <: KetQuantumObject) || (type <: OperatorQuantumObject)
dims = [Size[1]]
elseif type <: SuperOperatorQuantumObject
elseif (type <: SuperOperatorQuantumObject) || (type <: OperatorKetQuantumObject)
dims = [isqrt(Size[1])]
elseif type <: BraQuantumObject
dims = [Size[2]]
elseif type <: OperatorBraQuantumObject
dims = [isqrt(Size[2])]
end
end

Expand Down Expand Up @@ -136,6 +138,16 @@ function _check_QuantumObject(type::Type{SuperOperatorQuantumObject}, prod_dims:
prod_dims != sqrt(m) ? throw(DimensionMismatch("The dims parameter does not fit the dimension of the Array.")) : nothing
end

function _check_QuantumObject(type::Type{OperatorKetQuantumObject}, prod_dims::Int, m::Int, n::Int)
(n != 1) ? throw(DomainError((m, n), "The dimension of the array is not compatible with Operator-Ket type")) : nothing
prod_dims != sqrt(m) ? throw(DimensionMismatch("The dims parameter does not fit the dimension of the Array.")) : nothing
end

function _check_QuantumObject(type::Type{OperatorBraQuantumObject}, prod_dims::Int, m::Int, n::Int)
(m != 1) ? throw(DomainError((m, n), "The dimension of the array is not compatible with Operator-Bra type")) : nothing
prod_dims != sqrt(n) ? throw(DimensionMismatch("The dims parameter does not fit the dimension of the Array.")) : nothing
end

function QuantumObject(A::QuantumObject{<:AbstractArray}; type::Type{ObjType}=A.type, dims=A.dims) where
{ObjType<:QuantumObjectType}

Expand Down Expand Up @@ -337,16 +349,40 @@ function LinearAlgebra.:(*)(A::QuantumObject{<:AbstractArray{T1},BraQuantumObjec
A.dims != B.dims && throw(ErrorException("The two operators are not of the same Hilbert dimension."))
A.data * B.data
end
function LinearAlgebra.:(*)(A::QuantumObject{<:AbstractArray{T1},SuperOperatorQuantumObject},
B::QuantumObject{<:AbstractArray{T2},OperatorQuantumObject}) where {T1,T2}
A.dims != B.dims && throw(ErrorException("The two operators are not of the same Hilbert dimension."))
QuantumObject(vec2mat(A.data * mat2vec(B.data)), OperatorQuantumObject, A.dims)
end
function LinearAlgebra.:(*)(A::QuantumObject{<:AbstractArray{T1},OperatorBraQuantumObject},
B::QuantumObject{<:AbstractArray{T2},OperatorKetQuantumObject}) where {T1,T2}
A.dims != B.dims && throw(ErrorException("The two operators are not of the same Hilbert dimension."))
A.data * B.data
end
function LinearAlgebra.:(*)(A::QuantumObject{<:AbstractArray{T1},SuperOperatorQuantumObject},
B::QuantumObject{<:AbstractArray{T2},OperatorKetQuantumObject}) where {T1,T2}
A.dims != B.dims && throw(ErrorException("The two operators are not of the same Hilbert dimension."))
QuantumObject(A.data * B.data, OperatorKetQuantumObject, A.dims)
end
function LinearAlgebra.:(*)(A::QuantumObject{<:AbstractArray{T1},OperatorBraQuantumObject},
B::QuantumObject{<:AbstractArray{T2},SuperOperatorQuantumObject}) where {T1,T2}
A.dims != B.dims && throw(ErrorException("The two operators are not of the same Hilbert dimension."))
QuantumObject(A.data * B.data, OperatorBraQuantumObject, A.dims)
end

LinearAlgebra.:(^)(A::QuantumObject{<:AbstractArray{T},OpType}, n::T1) where {T,T1<:Number,OpType<:QuantumObjectType} =
QuantumObject(^(A.data, n), OpType, A.dims)
LinearAlgebra.:(/)(A::QuantumObject{<:AbstractArray{T},OpType}, n::T1) where {T,T1<:Number,OpType<:QuantumObjectType} =
QuantumObject(/(A.data, n), OpType, A.dims)
LinearAlgebra.dot(A::QuantumObject{<:AbstractArray{T1},OpType},
B::QuantumObject{<:AbstractArray{T2},OpType}) where {T1<:Number,T2<:Number,OpType<:KetQuantumObject} =
LinearAlgebra.dot(A.data, B.data)
function LinearAlgebra.dot(A::QuantumObject{<:AbstractArray{T1},OpType}, B::QuantumObject{<:AbstractArray{T2},OpType}) where
{T1<:Number,T2<:Number,OpType<:Union{KetQuantumObject,OperatorKetQuantumObject}}

A.dims != B.dims && throw(ErrorException("The two operators are not of the same Hilbert dimension."))
LinearAlgebra.dot(A.data, B.data)
end

Base.conj(A::QuantumObject{<:AbstractArray{T},OpType}) where {T,OpType<:QuantumObjectType} =
QuantumObject(conj(A.data), OpType, A.dims)
LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},OpType}) where {T,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
QuantumObject(adjoint(A.data), OpType, A.dims)
LinearAlgebra.transpose(A::QuantumObject{<:AbstractArray{T},OpType}) where {T,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
Expand All @@ -355,6 +391,10 @@ LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},KetQuantumObject}) whe
QuantumObject(adjoint(A.data), BraQuantumObject, A.dims)
LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},BraQuantumObject}) where {T} =
QuantumObject(adjoint(A.data), KetQuantumObject, A.dims)
LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},OperatorKetQuantumObject}) where {T} =
QuantumObject(adjoint(A.data), OperatorBraQuantumObject, A.dims)
LinearAlgebra.adjoint(A::QuantumObject{<:AbstractArray{T},OperatorBraQuantumObject}) where {T} =
QuantumObject(adjoint(A.data), OperatorKetQuantumObject, A.dims)

LinearAlgebra.inv(A::QuantumObject{<:AbstractArray{T},OpType}) where {T,OpType<:Union{OperatorQuantumObject,SuperOperatorQuantumObject}} =
QuantumObject(sparse(inv(Matrix(A.data))), OpType, A.dims)
Expand Down
61 changes: 60 additions & 1 deletion test/quantum_objects.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@testset "Quantum Objects" begin
# unsupported size of array
for a in [rand(ComplexF64, 3, 2), rand(ComplexF64, 2, 2, 2)]
for t in [Nothing, KetQuantumObject, BraQuantumObject, OperatorQuantumObject, SuperOperatorQuantumObject]
for t in [Nothing, KetQuantumObject, BraQuantumObject, OperatorQuantumObject, SuperOperatorQuantumObject, OperatorBraQuantumObject, OperatorKetQuantumObject]
@test_throws DomainError Qobj(a, type=t)
end
end
Expand All @@ -12,9 +12,11 @@
@test_throws DomainError Qobj(a, type=BraQuantumObject)
@test_throws DomainError Qobj(a, type=OperatorQuantumObject)
@test_throws DomainError Qobj(a, type=SuperOperatorQuantumObject)
@test_throws DomainError Qobj(a, type=OperatorBraQuantumObject)
@test_throws DomainError Qobj(a', type=KetQuantumObject)
@test_throws DomainError Qobj(a', type=OperatorQuantumObject)
@test_throws DomainError Qobj(a', type=SuperOperatorQuantumObject)
@test_throws DomainError Qobj(a', type=OperatorKetQuantumObject)
@test_throws DimensionMismatch Qobj(a, dims=[2])
@test_throws DimensionMismatch Qobj(a', dims=[2])
a2 = Qobj(a')
Expand All @@ -23,10 +25,14 @@
@test isbra(a2) == true
@test isoper(a2) == false
@test issuper(a2) == false
@test isoperket(a2) == false
@test isoperbra(a2) == false
@test isket(a3) == true
@test isbra(a3) == false
@test isoper(a3) == false
@test issuper(a3) == false
@test isoperket(a3) == false
@test isoperbra(a3) == false
@test Qobj(a3) == a3
@test !(Qobj(a3) === a3)
@test isket(Qobj(Matrix([2 3])')) == true
Expand All @@ -39,10 +45,48 @@
@test isbra(a2) == false
@test isoper(a2) == true
@test issuper(a2) == false
@test isoperket(a2) == false
@test isoperbra(a2) == false
@test isket(a3) == false
@test isbra(a3) == false
@test isoper(a3) == false
@test issuper(a3) == true
@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)
a4 = rand(ComplexF64, 2, 2)
ρ = Qobj(a4)
ρ_ket = Qobj(mat2vec(a4), type=OperatorKetQuantumObject)
ρ_bra = ρ_ket'
@test ρ_bra == Qobj(mat2vec(a4)', type=OperatorBraQuantumObject)
@test isket(ρ_ket) == false
@test isbra(ρ_ket) == false
@test isoper(ρ_ket) == false
@test issuper(ρ_ket) == false
@test isoperket(ρ_ket) == true
@test isoperbra(ρ_ket) == false
@test isket(ρ_bra) == false
@test isbra(ρ_bra) == false
@test isoper(ρ_bra) == false
@test issuper(ρ_bra) == false
@test isoperket(ρ_bra) == false
@test isoperbra(ρ_bra) == true
@test ρ_bra.dims == [2]
@test ρ_ket.dims == [2]
@test H * ρ spre(H) * ρ
@test ρ * H spost(H) * ρ
@test H * ρ * H sprepost(H, H) * ρ
@test (L * ρ_ket).dims == [2]
@test L * ρ_ket -1im * (+(spre(H) * ρ_ket) - spost(H) * ρ_ket)
@test (ρ_bra * L')' == L * ρ_ket
@test sum((conj(ρ) .* ρ).data) dot(ρ_ket, ρ_ket) ρ_bra * ρ_ket
@test_throws DimensionMismatch Qobj(ρ_ket.data, type=OperatorKetQuantumObject, dims=[4])
@test_throws DimensionMismatch Qobj(ρ_bra.data, type=OperatorBraQuantumObject, dims=[4])

a = Array(a)
a4 = Qobj(a)
Expand All @@ -60,6 +104,7 @@

@test transpose(transpose(a2)) == a2
@test transpose(a2).data == transpose(a2.data)
@test adjoint(a2) transpose(conj(a2))
@test adjoint(adjoint(a2)) == a2
@test adjoint(a2).data == adjoint(a2.data)

Expand Down Expand Up @@ -152,6 +197,20 @@
ψ_size = size(ψ)
@test opstring == "Quantum Object: type=Bra dims=$ψ_dims size=$ψ_size\n$datastring"

ψ2 = Qobj(rand(ComplexF64, 4), type=OperatorKetQuantumObject)
opstring = sprint((t, s) -> show(t, "text/plain", s), ψ2)
datastring = sprint((t, s) -> show(t, "text/plain", s), ψ2.data)
ψ2_dims = ψ2.dims
ψ2_size = size(ψ2)
@test opstring == "Quantum Object: type=Operator-Ket dims=$ψ2_dims size=$ψ2_size\n$datastring"

ψ2 = ψ2'
opstring = sprint((t, s) -> show(t, "text/plain", s), ψ2)
datastring = sprint((t, s) -> show(t, "text/plain", s), ψ2.data)
ψ2_dims = ψ2.dims
ψ2_size = size(ψ2)
@test opstring == "Quantum Object: type=Operator-Bra dims=$ψ2_dims size=$ψ2_size\n$datastring"

ψ = coherent(30, 3)
α, δψ = get_coherence(ψ)
@test isapprox(abs(α), 3, atol=1e-5) && abs2(δψ[1]) > 0.999
Expand Down

0 comments on commit 0060fff

Please sign in to comment.