From 7ad60b7a296675436b79ab72f9146e02275d70c6 Mon Sep 17 00:00:00 2001 From: Piotr Gawron Date: Thu, 1 Aug 2019 12:47:10 +0200 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 From 9da399a57c97c82ea32623a2a2fb48e033a773dd Mon Sep 17 00:00:00 2001 From: Piotr Gawron Date: Tue, 13 Aug 2019 23:20:59 +0200 Subject: [PATCH 4/7] more local exports added --- src/base.jl | 3 ++- src/gates.jl | 1 - src/ptrace.jl | 2 ++ src/ptranspose.jl | 1 + src/reshuffle.jl | 2 ++ 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/base.jl b/src/base.jl index 5e76fc8..50b0e89 100644 --- a/src/base.jl +++ b/src/base.jl @@ -1,4 +1,5 @@ -function ket(::Type{T}, val::Int, dim::Int) where T<:Number +export ket, bra, ketbra, proj, res, unres, max_mixed, max_entangled, + werner_state, permutesystems dim > 0 ? () : throw(ArgumentError("Vector dimension has to be nonnegative")) 1 <= val <= dim ? () : throw(ArgumentError("Label have to be smaller than vector dimension")) ψ = zeros(T, dim) diff --git a/src/gates.jl b/src/gates.jl index d79a81e..6ff4331 100644 --- a/src/gates.jl +++ b/src/gates.jl @@ -1,4 +1,3 @@ - export 𝕀, sx, sy, sz, qft, hadamard, grover sx = ComplexF64[0 1; 1 0] diff --git a/src/ptrace.jl b/src/ptrace.jl index 04001f7..ef43f42 100644 --- a/src/ptrace.jl +++ b/src/ptrace.jl @@ -1,3 +1,5 @@ +export ptrace + """ $(SIGNATURES) - `ρ`: quantum state. diff --git a/src/ptranspose.jl b/src/ptranspose.jl index 3d257ca..ad64b17 100644 --- a/src/ptranspose.jl +++ b/src/ptranspose.jl @@ -1,3 +1,4 @@ +export ptranspose """ $(SIGNATURES) - `ρ`: quantum state. diff --git a/src/reshuffle.jl b/src/reshuffle.jl index 1ed3cd3..4360ec1 100644 --- a/src/reshuffle.jl +++ b/src/reshuffle.jl @@ -1,3 +1,5 @@ +export reshuffle + # """ # Performs reshuffling of indices of a matrix. # Given multiindexed matrix M_{(m,μ),(n,ν)} it returns From a1127e9e3bb874afa81e2962a8dde5aad8141d3b Mon Sep 17 00:00:00 2001 From: Piotr Gawron Date: Tue, 13 Aug 2019 23:21:22 +0200 Subject: [PATCH 5/7] change of behaviour in ket and simillar functions --- src/base.jl | 35 ++++++++++++++++++++++++++--------- test/base.jl | 12 ++++++------ 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/base.jl b/src/base.jl index 50b0e89..ba112e1 100644 --- a/src/base.jl +++ b/src/base.jl @@ -1,12 +1,19 @@ export ket, bra, ketbra, proj, res, unres, max_mixed, max_entangled, werner_state, permutesystems + +function ket(::Type{T}, val::Int, dim::Int) where T<:AbstractVector{<:Number} dim > 0 ? () : throw(ArgumentError("Vector dimension has to be nonnegative")) 1 <= val <= dim ? () : throw(ArgumentError("Label have to be smaller than vector dimension")) - ψ = zeros(T, dim) - ψ[val] = one(T) + ψ = zero(T(undef, dim)) + ψ[val] = one(eltype(T)) ψ end +function ket(::Type{T}, val::Int, dim::Int) where T<:Number + @warn "This method is deprecated and will be removed. Use calls like `ket(Matrix{ComplexF64}, 1, 2)`." + ket(Vector{T}, val, dim) +end + """ $(SIGNATURES) - `val`: non-zero entry - label. @@ -14,9 +21,14 @@ $(SIGNATURES) Return complex column vector \$|val\\rangle\$ of unit norm describing quantum state. """ -ket(val::Int, dim::Int) = ket(ComplexF64, val, dim) +ket(val::Int, dim::Int) = ket(Vector{ComplexF64}, val, dim) + +function bra(::Type{T}, val::Int, dim::Int) where T<:Number + @warn "This method is deprecated and will be removed. Use calls like `bra(Matrix{ComplexF64}, 1, 2)`." + ket(Vector{T}, val, dim)' +end -bra(::Type{T}, val::Int, dim::Int) where T<:Number = ket(T, val, dim)' +bra(::Type{T}, val::Int, dim::Int) where T<:AbstractVector{<:Number} = ket(T, val, dim)' """ $(SIGNATURES) @@ -25,16 +37,21 @@ $(SIGNATURES) Return Hermitian conjugate \$\\langle val| = |val\\rangle^\\dagger\$ of the ket with the same label. """ -bra(val::Int, dim::Int) = bra(ComplexF64, val, dim) +bra(val::Int, dim::Int) = bra(Vector{ComplexF64}, val, dim) -function ketbra(::Type{T}, valk::Int, valb::Int, dim::Int) where T<:Number +function ketbra(::Type{T}, valk::Int, valb::Int, dim::Int) where T<:AbstractMatrix{<:Number} dim > 0 ? () : throw(ArgumentError("Vector dimension has to be nonnegative")) 1 <= valk <= dim && 1 <= valb <= dim ? () : throw(ArgumentError("Ket and bra labels have to be smaller than operator dimension")) - ρ = zeros(T, dim, dim) - ρ[valk,valb] = one(T) + ρ = zero(T(undef, dim, dim)) + ρ[valk,valb] = one(eltype(T)) ρ end +function ketbra(::Type{T}, valk::Int, valb::Int, dim::Int) where T<:Number + @warn "This method is deprecated and will be removed. Use calls like `ketbra(Matrix{ComplexF64}, 1, 1, 2)`." + ketbra(Matrix{T}, valk, valb, dim) +end + """ $(SIGNATURES) - `valk`: non-zero entry - label. @@ -43,7 +60,7 @@ $(SIGNATURES) # Return outer product \$|valk\\rangle\\langle vakb|\$ of states \$|valk\\rangle\$ and \$|valb\\rangle\$. """ -ketbra(valk::Int, valb::Int, dim::Int) = ketbra(ComplexF64, valk, valb, dim) +ketbra(valk::Int, valb::Int, dim::Int) = ketbra(Matrix{ComplexF64}, valk, valb, dim) """ $(SIGNATURES) diff --git a/test/base.jl b/test/base.jl index ccf3a81..206268a 100644 --- a/test/base.jl +++ b/test/base.jl @@ -5,8 +5,8 @@ ψ = ComplexF64[1, 0, 0, 0] @test norm(ϕ - ψ) ≈ 0. - @test typeof(ket(Float64, 1, 4)) == Vector{Float64} - @test typeof(ket(ComplexF64, 1, 4)) == Vector{ComplexF64} + @test typeof(ket(Vector{Float64}, 1, 4)) == Vector{Float64} + @test typeof(ket(Vector{ComplexF64}, 1, 4)) == Vector{ComplexF64} @test_throws ArgumentError ket(4, 3) end @@ -18,8 +18,8 @@ end @test_throws ArgumentError bra(4,3) - @test typeof(bra(Float64, 1, 4)) == LinearAlgebra.Adjoint{Float64,Array{Float64,1}} - @test typeof(bra(ComplexF64, 1, 4)) == LinearAlgebra.Adjoint{Complex{Float64},Array{Complex{Float64},1}} + @test typeof(bra(Vector{Float64}, 1, 4)) == LinearAlgebra.Adjoint{Float64,Array{Float64,1}} + @test typeof(bra(Vector{ComplexF64}, 1, 4)) == LinearAlgebra.Adjoint{Complex{Float64},Array{Complex{Float64},1}} end @testset "ketbra" begin @@ -30,8 +30,8 @@ end @test_throws ArgumentError ketbra(4, 4, 3) - @test typeof(ketbra(Float64, 1, 1, 4)) == Matrix{Float64} - @test typeof(ketbra(ComplexF64, 1, 1, 4)) == Matrix{ComplexF64} + @test typeof(ketbra(Matrix{Float64}, 1, 1, 4)) == Matrix{Float64} + @test typeof(ketbra(Matrix{ComplexF64}, 1, 1, 4)) == Matrix{ComplexF64} end @testset "proj" begin From 00b50d64cdedea11fae4f040aab2b0dac66ff3ff Mon Sep 17 00:00:00 2001 From: Piotr Gawron Date: Wed, 14 Aug 2019 17:19:39 +0200 Subject: [PATCH 6/7] New bases interface, represent combine functions added --- src/matrixbases.jl | 27 ++++++++++++++++++++------- test/matrixbases.jl | 25 +++++++++++++++++++------ test/runtests.jl | 4 ++-- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/matrixbases.jl b/src/matrixbases.jl index e5676cb..fafa99c 100644 --- a/src/matrixbases.jl +++ b/src/matrixbases.jl @@ -1,11 +1,21 @@ +import .Base: length, iterate +export AbstractMatrixBasisIterator, HermitianBasisIterator, AbstractBasis, + AbstractMatrixBasis, HermitianBasis, hermitianbasis, represent, combine abstract type AbstractMatrixBasisIterator{T<:AbstractMatrix} end struct HermitianBasisIterator{T} <: AbstractMatrixBasisIterator{T} dim::Int end -import .Base: length, iterate -export hermitianbasis, matrixtocoeffs, coeffstomatrix -hermitianbasis(dim::Int) = hermitianbasis(Matrix{ComplexF64}, dim) +abstract type AbstractBasis end +abstract type AbstractMatrixBasis{T} <: AbstractBasis where T<:AbstractMatrix{<:Number} end + +struct HermitianBasis{T} <: AbstractMatrixBasis{T} + iterator::HermitianBasisIterator{T} + + function HermitianBasis{T}(dim::Integer) where T<:AbstractMatrix{<:Number} + new(HermitianBasisIterator{T}(dim)) + end +end """ $(SIGNATURES) @@ -15,6 +25,9 @@ Returns elementary hermitian matrices of dimension `dim` x `dim`. """ hermitianbasis(T::Type{<:AbstractMatrix{<:Number}}, dim::Int) = HermitianBasisIterator{T}(dim) +hermitianbasis(dim::Int) = hermitianbasis(Matrix{ComplexF64}, dim) + + function iterate(itr::HermitianBasisIterator{T}, state=(1,1)) where T<:AbstractMatrix{<:Number} dim = itr.dim (a, b) = state @@ -32,10 +45,10 @@ end length(itr::HermitianBasisIterator) = itr.dim^2 -function matrixtocoeffs(basis::T, m::Matrix{<:Number}) where T<:AbstractMatrixBasisIterator - tr.([m] .* basis) +function represent(basis::T, m::Matrix{<:Number}) where T<:AbstractMatrixBasis + tr.([m] .* basis.iterator) end -function coeffstomatrix(basis::T, v::Vector{<:Number}) where T<:AbstractMatrixBasisIterator - sum(basis .* v) +function combine(basis::T, v::Vector{<:Number}) where T<:AbstractMatrixBasis + sum(basis.iterator .* v) end \ No newline at end of file diff --git a/test/matrixbases.jl b/test/matrixbases.jl index a6b0bd5..fbb4444 100644 --- a/test/matrixbases.jl +++ b/test/matrixbases.jl @@ -1,8 +1,21 @@ -@testset "base_matrices" begin +@testset "MatrixBases" begin + +@testset "HermitianBasisIterator" begin d = 4 - m = collect(Matrix{ComplexF64}, base_matrices(4)) - for i=1:d, j=1:d - v = tr(m[i]' * m[j]) - i == j ? @test(v == 1.) : @test(v == 0.) - end + m = collect(HermitianBasisIterator{Matrix{ComplexF64}}(d)) + @test [tr(m[i]' * m[j]) for i=1:d, j=1:d] ≈ Matrix{Float64}(I, d, d) end + +@testset "represent, combine" begin + d = 4 + A = reshape(collect(1:16), 4, 4) + vA = represent(HermitianBasis{Matrix{ComplexF64}}(d), A) + Ap = combine(HermitianBasis{Matrix{ComplexF64}}(d), vA) + @test A ≈ Ap + B = A*A' + vB = represent(HermitianBasis{Matrix{ComplexF64}}(d), B) + Bp = combine(HermitianBasis{Matrix{ComplexF64}}(d), vB) + @test B ≈ Bp +end + +end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index a59ac36..8183d73 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -6,8 +6,8 @@ using SparseArrays using Test my_tests = ["utils.jl", "base.jl", "ptrace.jl", "ptranspose.jl", "reshuffle.jl", - "channels.jl", "functionals.jl", "gates.jl", "permute_systems.jl", - "randomqobjects.jl", "convex.jl"] + "channels.jl", "functionals.jl", "gates.jl", "matrixbases.jl", + "permute_systems.jl", "randomqobjects.jl", "convex.jl"] for my_test in my_tests include(my_test) From 6cf7c8a3c6bd2677eaa06e092e681df42fbcd975 Mon Sep 17 00:00:00 2001 From: Piotr Gawron Date: Wed, 14 Aug 2019 17:30:33 +0200 Subject: [PATCH 7/7] small fix in test --- test/utils.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/utils.jl b/test/utils.jl index 16d5b87..3b192cf 100644 --- a/test/utils.jl +++ b/test/utils.jl @@ -13,12 +13,13 @@ end end @testset "renormalize" begin - v = randn(10) + rng = MersenneTwister(1234); + v = randn(rng, 10) renormalize!(v) @test norm(v) ≈ 1 atol=1e-13 - A = randn(10, 10) + A = randn(rng, 10, 10) renormalize!(A) @test tr(A) ≈ 1 atol=1e-13