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