From ec081e8f3d842219fadf86b763cede7f19dab183 Mon Sep 17 00:00:00 2001
From: Piotr Gawron
Date: Tue, 20 Aug 2019 17:17:18 +0200
Subject: [PATCH] ElemetaryBasis generator and Superopertor from function fixed
(#71)
* dimout -> odim, dimin -> idim
* ElementaryBasis iterator added SuperOperator fixed
* doc fix
* error() -> throw ArgumentError
---
src/base.jl | 14 +++++++-------
src/channels.jl | 10 +++++-----
src/matrixbases.jl | 35 +++++++++++++++++++++++++++++++++--
test/channels.jl | 4 ++--
4 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/src/base.jl b/src/base.jl
index b8390b8..18d312e 100644
--- a/src/base.jl
+++ b/src/base.jl
@@ -40,10 +40,10 @@ Return Hermitian conjugate \$\\langle val| = |val\\rangle^\\dagger\$ of the ket
"""
bra(val::Int, dim::Int) = bra(Vector{ComplexF64}, val, dim)
-function ketbra(::Type{T}, valk::Int, valb::Int, dimin::Int, dimout::Int) where T<:AbstractMatrix{<:Number}
- dimin > 0 && dimout > 0 ? () : throw(ArgumentError("Matrix dimension has to be nonnegative"))
- 1 <= valk <= dimin && 1 <= valb <= dimout ? () : throw(ArgumentError("Ket and bra labels have to be smaller than operator dimension"))
- ρ = T(undef, dimout, dimin)
+function ketbra(::Type{T}, valk::Int, valb::Int, idim::Int, odim::Int) where T<:AbstractMatrix{<:Number}
+ idim > 0 && odim > 0 ? () : throw(ArgumentError("Matrix dimension has to be nonnegative"))
+ 1 <= valk <= idim && 1 <= valb <= odim ? () : throw(ArgumentError("Ket and bra labels have to be smaller than operator dimension"))
+ ρ = T(undef, odim, idim)
fill!(ρ, zero(eltype(T)))
ρ[valk,valb] = one(eltype(T))
ρ
@@ -70,12 +70,12 @@ ketbra(valk::Int, valb::Int, dim::Int) = ketbra(Matrix{ComplexF64}, valk, valb,
"""
- `valk`: non-zero entry - label.
- `valb`: non-zero entry - label.
-- `dimin`: length of the ket vector
-- `dimout`: length of the bra vector
+- `idim`: length of the ket vector
+- `odim`: length of the bra vector
# Return outer product \$|valk\\rangle\\langle vakb|\$ of states \$|valk\\rangle\$ and \$|valb\\rangle\$.
"""
-ketbra(valk::Int, valb::Int, dimin::Int, dimout::Int) = ketbra(Matrix{ComplexF64}, valk, valb, dimin, dimout)
+ketbra(valk::Int, valb::Int, idim::Int, odim::Int) = ketbra(Matrix{ComplexF64}, valk, valb, idim, odim)
"""
$(SIGNATURES)
diff --git a/src/channels.jl b/src/channels.jl
index 54c9b56..00b3a70 100644
--- a/src/channels.jl
+++ b/src/channels.jl
@@ -73,16 +73,16 @@ end
"""
$(SIGNATURES)
- `channel`: quantum channel map.
-- `dim`: square root of the [super-operator](https://en.wikipedia.org/wiki/Superoperator) matrix dimension.
+- `idim`: square root of the [super-operator](https://en.wikipedia.org/wiki/Superoperator) matrix input dimension.
+- `odim`: square root of the [super-operator](https://en.wikipedia.org/wiki/Superoperator) matrix output dimension.
Transforms quntum channel into super-operator matrix.
"""
function SuperOperator{T}(channel::Function, idim::Int, odim::Int) where T<:AbstractMatrix{<:Number}
- error("Broken")
- odim > 0 ? () : error("Channel dimension has to be nonnegative") # TODO: fix
+ odim > 0 && idim > 0 ? () : throw(ArgumentError("Channel dimensions have to be nonnegative"))
- m = zeros(T, idim^2, odim^2)
- for (i, e) in enumerate(base_matrices(idim)) # TODO : base_matrices should be not only square
+ m = zeros(eltype(T), idim^2, odim^2)
+ for (i, e) in enumerate(ElementaryBasisIterator{Matrix{Int}}(idim, odim))
m[:, i] = res(channel(e))
end
SuperOperator(m, idim, odim)
diff --git a/src/matrixbases.jl b/src/matrixbases.jl
index bb0768e..cd0306a 100644
--- a/src/matrixbases.jl
+++ b/src/matrixbases.jl
@@ -1,11 +1,18 @@
import .Base: length, iterate
-export AbstractMatrixBasisIterator, HermitianBasisIterator, AbstractBasis,
- AbstractMatrixBasis, HermitianBasis, hermitianbasis, represent, combine
+export AbstractMatrixBasisIterator, HermitianBasisIterator, ElementaryBasisIterator, AbstractBasis,
+ AbstractMatrixBasis, HermitianBasis, ElementaryBasis, hermitianbasis,
+ represent, combine
+
abstract type AbstractMatrixBasisIterator{T<:AbstractMatrix} end
struct HermitianBasisIterator{T} <: AbstractMatrixBasisIterator{T}
dim::Int
end
+struct ElementaryBasisIterator{T} <: AbstractMatrixBasisIterator{T}
+ idim::Int
+ odim::Int
+end
+
abstract type AbstractBasis end
abstract type AbstractMatrixBasis{T} <: AbstractBasis where T<:AbstractMatrix{<:Number} end
@@ -17,6 +24,18 @@ struct HermitianBasis{T} <: AbstractMatrixBasis{T}
end
end
+struct ElementaryBasis{T} <: AbstractMatrixBasis{T}
+ iterator::ElementaryBasisIterator{T}
+
+ function ElementaryBasis{T}(idim::Integer, odim::Integer) where T<:AbstractMatrix{<:Number}
+ new(ElementaryBasisIterator{T}(idim, odim))
+ end
+end
+
+function ElementaryBasis{T}(dim::Integer) where T<:AbstractMatrix{<:Number}
+ ElementaryBasisIterator{T}(dim, dim)
+end
+
"""
$(SIGNATURES)
- `dim`: dimensions of the matrix.
@@ -46,6 +65,18 @@ end
length(itr::HermitianBasisIterator) = itr.dim^2
+function iterate(itr::ElementaryBasisIterator{T}, state=(1,1)) where T<:AbstractMatrix{<:Number}
+ idim, odim = itr.idim, itr.odim
+ (a, b) = state
+ a > idim && return nothing
+
+ x = zeros(eltype(T), odim, idim)
+ x[b, a] = one(eltype(T))
+ return x, b == odim ? (a+1, 1) : (a, b+1)
+end
+
+length(itr::ElementaryBasisIterator) = itr.idim * itr.odim
+
function represent(basis::T, m::Matrix{<:Number}) where T<:AbstractMatrixBasis
real.(tr.([m] .* basis.iterator))
end
diff --git a/test/channels.jl b/test/channels.jl
index de565c9..ec717b8 100644
--- a/test/channels.jl
+++ b/test/channels.jl
@@ -56,8 +56,8 @@ end
@testset "construction from function" begin
ρ = [0.25 0.25im; -0.25im 0.75]
t = hcat([ComplexF64[0.25, 0.25im, -0.25im, 0.75] for i=1:4]...) #stack res ρ
- @test_throws ErrorException m = SuperOperator{Matrix{ComplexF64}}(x -> ρ, 2, 2).matrix
- @test_broken norm(t-m) ≈ 0. atol=1e-15
+ m = SuperOperator{Matrix{ComplexF64}}(x -> ρ, 2, 2).matrix
+ @test norm(t-m) ≈ 0. atol=1e-15
end
@testset "convert to KrausOperators" begin