From 8ad3aa68a09120a912276673692bc96baef4039f Mon Sep 17 00:00:00 2001 From: Piotr Gawron Date: Fri, 29 Mar 2019 11:43:10 +0100 Subject: [PATCH 1/5] Pg/dimfix (#56) * Fix for #55: idim and odim where mixed up. * Additional fixes for dim issue and related issues --- src/channels.jl | 57 ++++++++++++++++++++++++------------------------- src/utils.jl | 6 +++--- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/channels.jl b/src/channels.jl index a58c9d4..e92d6ec 100644 --- a/src/channels.jl +++ b/src/channels.jl @@ -21,13 +21,13 @@ struct KrausOperators{T<:AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T throw(ArgumentError("Kraus operators list contains matrices of different dimension")) end end - idim, odim = sizes[1] + odim, idim = sizes[1] new{T1}(map(T1, v), idim, odim) end end function KrausOperators{T1}(v::Vector{T2}, idim::Int, odim::Int) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - all((idim, odim) == size(k) for k in v) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) + all((odim, idim) == size(k) for k in v) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) KrausOperators{T1}(v) end @@ -55,13 +55,13 @@ struct SuperOperator{T<:AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T} if r!=sr^2 || c!=sc^2 throw(ArgumentError("Superoperator matrix has bad dimensions")) end - idim, odim = sr, sc + odim, idim = sr, sc new{T1}(T1(m), idim, odim) end end function SuperOperator{T1}(m::T2, idim::Int, odim::Int) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - (idim^2, odim^2) == size(m) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) + (odim^2, idim^2) == size(m) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) SuperOperator{T1}(m) end @@ -127,14 +127,14 @@ struct UnitaryChannel{T<:AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T idim::Int odim::Int function UnitaryChannel{T1}(m::T2) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - idim, odim = size(m) + odim, idim = size(m) idim == odim ? () : throw(ArgumentError("UnitaryChannel matrix has to be square")) new{T1}(T1(m), idim, odim) end end function UnitaryChannel{T1}(m::T2, idim::Int, odim::Int) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - (idim, odim) == size(m) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) + (odim, idim) == size(m) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) UnitaryChannel{T1}(T1(m)) end @@ -165,10 +165,10 @@ struct POVMMeasurement{T<:AbstractMatrix{<:Number}} <: AbstractQuantumOperation{ sizes = [size(p) for p in v] for s in sizes[2:end] if s!=sizes[1] - throw(ArgumentError("Kraus operators list contains matrices of different dimension")) + throw(ArgumentError("POVM operators list contains matrices of different dimension")) end end - idim = size(v[1],1) + idim = size(v[1], 1) # TODO or size(v[1], 2) ? odim = length(v) new{T1}(map(T1, v), idim, odim) @@ -190,13 +190,13 @@ struct PostSelectionMeasurement{T<:AbstractMatrix{<:Number}} <: AbstractQuantumO idim::Int odim::Int function PostSelectionMeasurement{T1}(m::T2) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - idim, odim = size(m) + odim, idim = size(m) new{T1}(T1(m), idim, odim) end end function PostSelectionMeasurement{T1}(m::T2, idim::Int, odim::Int) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - idim, odim == size(m) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) + odim, idim == size(m) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) PostSelectionMeasurement{T1}(m) end @@ -245,16 +245,16 @@ end ################################################################################ # size() function ################################################################################ -for qop in (:KrausOperators, :POVMMeasurement) - @eval size(Φ::$qop) = (Φ.idim, Φ.odim) -end - -for qop in (:SuperOperator, :DynamicalMatrix, :Stinespring, - :UnitaryChannel, :PostSelectionMeasurement) - @eval size(Φ::$qop) = size(Φ.matrix) -end - -size(Φ::IdentityChannel) = (Φ.idim, Φ.odim) +# for qop in (:KrausOperators, :POVMMeasurement) +# @eval size(Φ::$qop) = (Φ.idim, Φ.odim) +# end +# +# for qop in (:SuperOperator, :DynamicalMatrix, :Stinespring, +# :UnitaryChannel, :PostSelectionMeasurement) +# @eval size(Φ::$qop) = size(Φ.matrix) +# end +# +# size(Φ::IdentityChannel) = (Φ.idim, Φ.odim) ################################################################################ # making channels callable @@ -334,7 +334,7 @@ $(SIGNATURES) Transforms super-operator matrix into dynamical matrix. """ function Base.convert(::Type{DynamicalMatrix{T1}}, Φ::SuperOperator{T2}) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - m = reshuffle(Φ.matrix, [Φ.idim Φ.idim; Φ.odim Φ.odim]) + m = reshuffle(Φ.matrix, [Φ.odim Φ.odim; Φ.idim Φ.idim]) DynamicalMatrix{T1}(T1(m), Φ.idim, Φ.odim) end @@ -368,9 +368,9 @@ function Base.convert(::Type{KrausOperators{T1}}, Φ::DynamicalMatrix{T2}) where v = T1[] for i in 1:length(F.values) if F.values[i] >= 0.0 - push!(v, sqrt(F.values[i]) * unres(F.vectors[:,i], Φ.odim)) + push!(v, sqrt(F.values[i]) * unres(F.vectors[:,i], Φ.idim)) else - push!(v, zero(unres(F.vectors[:,i], Φ.odim))) + push!(v, zero(unres(F.vectors[:,i], Φ.idim))) end end KrausOperators{T1}(v, Φ.idim, Φ.odim) @@ -395,7 +395,7 @@ $(SIGNATURES) Transforms dynamical matrix into super-operator matrix. """ function Base.convert(::Type{SuperOperator{T1}}, Φ::DynamicalMatrix{T2}) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - m = reshuffle(Φ.matrix, [Φ.idim Φ.odim; Φ.idim Φ.odim]) + m = reshuffle(Φ.matrix, [Φ.odim Φ.idim; Φ.odim Φ.idim]) SuperOperator{T1}(T1(m), Φ.idim, Φ.odim) end @@ -454,7 +454,7 @@ $(SIGNATURES) Application of dynamical matrix into state `ρ`. """ function applychannel(Φ::DynamicalMatrix{<:AbstractMatrix{<:Number}}, ρ::AbstractMatrix{T}) where T<:Number - ptrace(Φ.matrix * (Diagonal{T}(I, Φ.idim[1])⊗transpose(ρ)), [Φ.idim, Φ.odim], [2]) + ptrace(Φ.matrix * (Diagonal{T}(I, Φ.odim)⊗transpose(ρ)), [Φ.odim, Φ.idim], [2]) end """ @@ -491,9 +491,8 @@ $(SIGNATURES) Application of Stinespring representation of quantum channel into state `ρ`. """ function applychannel(Φ::Stinespring{<:AbstractMatrix{<:Number}}, ρ::AbstractMatrix{<:Number}) - # TODO: Check this function carefully s = Φ.matrix * ρ * Φ.matrix' - ptrace(s, [Φ.idim, Φ.idim*Φ.odim], [2]) + ptrace(s, [Φ.odim, Φ.odim*Φ.idim], [2]) end function applychannel(Φ::IdentityChannel{<:AbstractMatrix{<:Number}}, ρ::AbstractMatrix{<:Number}) @@ -564,7 +563,7 @@ function Base.kron(Φ1::UnitaryChannel{M1}, Φ2::UnitaryChannel{M2}) where {M1<: end function Base.kron(::Type{T}, Φ1::IdentityChannel, Φ2::UnitaryChannel) where {T<:AbstractQuantumOperation{M}} where {M<:AbstractMatrix{<:Number}} - matrix = convert(M, Matrix(I, Φ1.idim, Φ1.odim) ⊗ Φ2.matrix) + matrix = convert(M, Matrix(I, Φ1.odim, Φ1.idim) ⊗ Φ2.matrix) uc = UnitaryChannel(matrix, Φ1.idim * Φ2.idim, Φ1.odim * Φ2.odim) convert(T, uc) end @@ -575,7 +574,7 @@ function Base.kron(Φ1::IdentityChannel{M1}, Φ2::UnitaryChannel{M2}) where {M1< end function Base.kron(::Type{T}, Φ1::UnitaryChannel, Φ2::IdentityChannel) where {T<:AbstractQuantumOperation{M}} where {M<:AbstractMatrix{<:Number}} - matrix = convert(M, Φ1.matrix ⊗ Matrix(I, Φ2.idim, Φ2.odim)) + matrix = convert(M, Φ1.matrix ⊗ Matrix(I, Φ2.odim, Φ2.idim)) uc = UnitaryChannel(matrix, Φ1.idim * Φ2.idim, Φ1.odim * Φ2.odim) convert(T, uc) end diff --git a/src/utils.jl b/src/utils.jl index fdfd9ef..d6884b4 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -100,9 +100,9 @@ function ispositive(ρ::AbstractMatrix{<:Number}; atol=1e-13) if rows!=cols return false end - if !ishermitian(ρ) - return false - end + # if !ishermitian(ρ) # TODO: ishermitian function has no tolerance + # return false + # end h = Hermitian(ρ) fact = eigen(h) all(fact.values .> -atol) From b061932752b67cd9177efbab47b82eea34ff3ed8 Mon Sep 17 00:00:00 2001 From: Piotr Gawron Date: Fri, 29 Mar 2019 11:45:47 +0100 Subject: [PATCH 2/5] Update Project.toml Version bumb --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 16ca037..c2ec590 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "QuantumInformation" uuid = "3c0b384b-479c-5684-b2ef-9d7a46dd931e" authors = ["Dariusz Kurzyk ", "Łukasz Pawela ", "Piotr Gawron ", "Marcin Przewięźlikowski "] -version = "0.4.4" +version = "0.4.5" [compat] julia = "0.7, 1.0, 1.1" From 7ad60b7a296675436b79ab72f9146e02275d70c6 Mon Sep 17 00:00:00 2001 From: Piotr Gawron Date: Thu, 1 Aug 2019 12:47:10 +0200 Subject: [PATCH 3/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e10d612..026c060 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![DOI](https://zenodo.org/badge/23916883.svg)](https://zenodo.org/badge/latestdoi/23916883) # QuantumInformation -A Julia package for numerical computation in quantum information theory. +A Julia package for numerical computation in quantum information theory. [Published in PLoS ONE](https://doi.org/10.1371/journal.pone.0209358). Numerical investigations are prevalent in quantum information theory. Numerical experiments can be used to find counter examples for theorems, to test hypotheses or to gain insight about quantum objects and operations. From 4a5581da88c9ff370696d7a5bac5382ce19378bb Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Sat, 3 Aug 2019 16:21:29 +0800 Subject: [PATCH 4/5] fix type conversion, avoid using T1(...) --- src/channels.jl | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/channels.jl b/src/channels.jl index e92d6ec..d0e0c81 100644 --- a/src/channels.jl +++ b/src/channels.jl @@ -56,7 +56,7 @@ struct SuperOperator{T<:AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T} throw(ArgumentError("Superoperator matrix has bad dimensions")) end odim, idim = sr, sc - new{T1}(T1(m), idim, odim) + new{T1}(convert(T1, m), idim, odim) end end @@ -98,7 +98,7 @@ struct DynamicalMatrix{T<:AbstractMatrix{<:Number}} <: AbstractQuantumOperation{ if r!=c || r!=idim*odim throw(ArgumentError("DynamicalMatrix matrix has bad dimensions")) end - new(T1(m), idim, odim) + new(convert(T1, m), idim, odim) end end @@ -129,13 +129,13 @@ struct UnitaryChannel{T<:AbstractMatrix{<:Number}} <: AbstractQuantumOperation{T function UnitaryChannel{T1}(m::T2) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} odim, idim = size(m) idim == odim ? () : throw(ArgumentError("UnitaryChannel matrix has to be square")) - new{T1}(T1(m), idim, odim) + new{T1}(convert(T1,m), idim, odim) end end function UnitaryChannel{T1}(m::T2, idim::Int, odim::Int) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} (odim, idim) == size(m) ? () : throw(ArgumentError("Matrix size and operator dimensions mismatch")) - UnitaryChannel{T1}(T1(m)) + UnitaryChannel{T1}(convert(T1,m)) end """ @@ -191,7 +191,7 @@ struct PostSelectionMeasurement{T<:AbstractMatrix{<:Number}} <: AbstractQuantumO odim::Int function PostSelectionMeasurement{T1}(m::T2) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} odim, idim = size(m) - new{T1}(T1(m), idim, odim) + new{T1}(convert(T1,m), idim, odim) end end @@ -286,7 +286,7 @@ Transforms list of Kraus operators into super-operator matrix. """ function Base.convert(::Type{SuperOperator{T1}}, Φ::KrausOperators{T2}) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} m = sum(k⊗(conj.(k)) for k in Φ.matrices) - SuperOperator{T1}(T1(m), Φ.idim, Φ.odim) + SuperOperator{T1}(convert(T1,m), Φ.idim, Φ.odim) end """ @@ -300,7 +300,7 @@ function Base.convert(::Type{Stinespring{T1}}, Φ::KrausOperators{T2}) where {T1 ko = orthogonalize(Φ) # TODO: improvement: transform to stacking m = sum(k ⊗ ket(i, ko.idim*ko.odim) for (i, k) in enumerate(ko.matrices)) - Stinespring{T1}(T1(m), ko.idim, ko.odim) + Stinespring{T1}(convert(T1,m), ko.idim, ko.odim) end """ @@ -312,7 +312,7 @@ Transforms list of Kraus operators into dynamical matrix. """ function Base.convert(::Type{DynamicalMatrix{T1}}, Φ::KrausOperators{T2}) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} m = sum(res(k) * res(k)' for k in Φ.matrices) - DynamicalMatrix{T1}(T1(m), Φ.idim, Φ.odim) + DynamicalMatrix{T1}(convert(T1,m), Φ.idim, Φ.odim) end """ @@ -335,7 +335,7 @@ Transforms super-operator matrix into dynamical matrix. """ function Base.convert(::Type{DynamicalMatrix{T1}}, Φ::SuperOperator{T2}) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} m = reshuffle(Φ.matrix, [Φ.odim Φ.odim; Φ.idim Φ.idim]) - DynamicalMatrix{T1}(T1(m), Φ.idim, Φ.odim) + DynamicalMatrix{T1}(convert(T1,m), Φ.idim, Φ.odim) end """ @@ -396,11 +396,11 @@ Transforms dynamical matrix into super-operator matrix. """ function Base.convert(::Type{SuperOperator{T1}}, Φ::DynamicalMatrix{T2}) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} m = reshuffle(Φ.matrix, [Φ.odim Φ.idim; Φ.odim Φ.idim]) - SuperOperator{T1}(T1(m), Φ.idim, Φ.odim) + SuperOperator{T1}(convert(T1,m), Φ.idim, Φ.odim) end function Base.convert(::Type{KrausOperators{T1}}, Φ::UnitaryChannel{T2}) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} - KrausOperators{T1}(T1[T1(Φ.matrix)], Φ.idim, Φ.odim) + KrausOperators{T1}(T1[convert(T1,Φ.matrix)], Φ.idim, Φ.odim) end function Base.convert(::Type{KrausOperators{T1}}, Φ::IdentityChannel{T2}) where {T1<:AbstractMatrix{N1}, T2<:AbstractMatrix{N2}} where {N1<:Number, N2<:Number} @@ -417,14 +417,14 @@ function Base.convert(::Type{KrausOperators{T1}}, Φ::POVMMeasurement{T2}) where for (i, p) in enumerate(Φ.matrices) sqrtp = sqrt(p) k = ket(i, Φ.odim)*sum(bra(j, Φ.idim)*sqrtp for j in 1:Φ.idim) - push!(v, T1(k)) + push!(v, convert(T1,k)) end KrausOperators{T1}(v, Φ.idim, Φ.odim) end function Base.convert(::Type{KrausOperators{T1}}, Φ::PostSelectionMeasurement{T2}) where {T1<:AbstractMatrix{<:Number}, T2<:AbstractMatrix{<:Number}} m = Φ.matrix - v = T1[T1(m)] + v = T1[convert(T1,m)] KrausOperators{T1}(v, Φ.idim, Φ.odim) end From e2bc72a2d967aeb99abba21bbabfe8707340dd22 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Sat, 3 Aug 2019 16:31:59 +0800 Subject: [PATCH 5/5] add fallback test --- test/channels.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/channels.jl b/test/channels.jl index 55434e7..4cd75e2 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -133,6 +133,9 @@ end @testset "UnitaryChannel" begin @test_throws ArgumentError UnitaryChannel(ones(4, 5)) @test_throws ArgumentError UnitaryChannel(ones(4, 4), 4, 5) + + c = UnitaryChannel(Diagonal(ComplexF64[1 -1.0im])) + @test c isa UnitaryChannel{<:Diagonal} end @testset "POVMMeasurement" begin