Skip to content

Commit

Permalink
Implement KrausOperators, conversions, is_trace_preserving, is_valid_…
Browse files Browse the repository at this point in the history
…channel
  • Loading branch information
akirakyle committed Jul 24, 2024
1 parent 1f06f07 commit c12a150
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/QuantumOpticsBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export Basis, GenericBasis, CompositeBasis, basis,
#superoperators
SuperOperator, DenseSuperOperator, DenseSuperOpType,
SparseSuperOperator, SparseSuperOpType,
ChoiState,
ChoiState, KrausOperators, is_trace_preserving, is_valid_channel,
spre, spost, sprepost, liouvillian, identitysuperoperator,
#fock
FockBasis, number, destroy, create,
Expand Down
89 changes: 80 additions & 9 deletions src/superoperators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ mutable struct SuperOperator{B1,B2,T} <: AbstractSuperOperator{B1,B2}
basis_r::B2
data::T
function SuperOperator{BL,BR,T}(basis_l::BL, basis_r::BR, data::T) where {BL,BR,T}
if length(basis_l[1])*length(basis_l[2]) != size(data, 1) ||
length(basis_r[1])*length(basis_r[2]) != size(data, 2)
if (length(basis_l) != 2 || length(basis_r) != 2 ||
length(basis_l[1])*length(basis_l[2]) != size(data, 1) ||
length(basis_r[1])*length(basis_r[2]) != size(data, 2))
throw(DimensionMismatch("Tried to assign data of size $(size(data)) to Hilbert spaces of sizes $(length.(basis_l)), $(length.(basis_r))"))
end
new(basis_l, basis_r, data)
Expand Down Expand Up @@ -318,26 +319,72 @@ end
end

# TODO should all of PauliTransferMatrix, ChiMatrix, ChoiState, and KrausOperators subclass AbstractSuperOperator?

"""
Base class for the Choi representation of superoperators.
KrausOperators(B1, B2, data)
Superoperator represented as a list of Kraus operators.
Note unlike the SuperOperator or ChoiState types where
its possible to have basis_l[1] != basis_l[2] and basis_r[1] != basis_r[2]
which allows representations of maps between general linear operators defined on H_A \to H_B,
a quantum channel can only act on valid density operators which live in H_A \to H_A.
Thus the Kraus representation is only defined for quantum channels which map
(H_A \to H_A) \to (H_B \to H_B).
"""
mutable struct KrausOperators{B1,B2,T} <: AbstractSuperOperator{B1,B2}
basis_l::B1
basis_r::B2
data::T
function KrausOperators{BL,BR,T}(basis_l::BL, basis_r::BR, data::T) where {BL,BR,T}
if (any(!samebases(basis_r, M.basis_r) for M in data) ||

Check warning on line 339 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L338-L339

Added lines #L338 - L339 were not covered by tests
any(!samebases(basis_l, M.basis_l) for M in data))
throw(DimensionMismatch("Tried to assign data with incompatible bases"))

Check warning on line 341 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L341

Added line #L341 was not covered by tests
end

new(basis_l, basis_r, data)

Check warning on line 344 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L344

Added line #L344 was not covered by tests
end
end
KrausOperators{BL,BR}(b1::BL,b2::BR,data::T) where {BL,BR,T} = KrausOperators{BL,BR,T}(b1,b2,data)
KrausOperators(b1::BL,b2::BR,data::T) where {BL,BR,T} = KrausOperators{BL,BR,T}(b1,b2,data)
KrausOperators(b,data) = KrausOperators(b,b,data)

Check warning on line 349 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L347-L349

Added lines #L347 - L349 were not covered by tests

function is_trace_preserving(kraus::KrausOperators; tol=1e-9)
m = I(length(kraus.basis_r)) - sum(dagger(M)*M for M in kraus.data).data
m[abs.(m) .< tol] .= 0
return iszero(m)

Check warning on line 354 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L351-L354

Added lines #L351 - L354 were not covered by tests
end

function is_valid_channel(kraus::KrausOperators; tol=1e-9)
m = I(length(kraus.basis_r)) - sum(dagger(M)*M for M in kraus.data).data
eigs = eigvals(Matrix(m))
eigs[@. abs(eigs) < tol || eigs > 0] .= 0
return iszero(eigs)

Check warning on line 361 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L357-L361

Added lines #L357 - L361 were not covered by tests
end

"""
ChoiState(B1, B2, data)
Superoperator represented as a choi state stored as a sparse or dense matrix.
"""
mutable struct ChoiState{B1,B2,T} <: AbstractSuperOperator{B1,B2}
basis_l::B1
basis_r::B2
data::T
function ChoiState{BL,BR,T}(basis_l::BL, basis_r::BR, data::T) where {BL,BR,T}
function ChoiState{BL,BR,T}(basis_l::BL, basis_r::BR, data::T; tol=1e-9) where {BL,BR,T}
if (length(basis_l) != 2 || length(basis_r) != 2 ||

Check warning on line 374 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L373-L374

Added lines #L373 - L374 were not covered by tests
length(basis_l[1])*length(basis_l[2]) != size(data, 1) ||
length(basis_r[1])*length(basis_r[2]) != size(data, 2))
throw(DimensionMismatch("Tried to assign data of size $(size(data)) to Hilbert spaces of sizes $(length.(basis_l)), $(length.(basis_r))"))

Check warning on line 377 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L377

Added line #L377 was not covered by tests
end
new(basis_l, basis_r, data)
if any(abs.(data - data') .> tol)
@warn "Trying to construct ChoiState from non-hermitian data"

Check warning on line 380 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L379-L380

Added lines #L379 - L380 were not covered by tests
end
new(basis_l, basis_r, Hermitian(data))

Check warning on line 382 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L382

Added line #L382 was not covered by tests
end
end
ChoiState{BL,BR}(b1::BL,b2::BR,data::T) where {BL,BR,T} = ChoiState{BL,BR,T}(b1,b2,data)
ChoiState(b1::BL,b2::BR,data::T) where {BL,BR,T} = ChoiState{BL,BR,T}(b1,b2,data)
ChoiState(b,data) = ChoiState(b,b,data)
ChoiState{BL,BR}(b1::BL,b2::BR,data::T; tol=1e-9) where {BL,BR,T} = ChoiState{BL,BR,T}(b1,b2,data;tol=tol)
ChoiState(b1::BL,b2::BR,data::T; tol=1e-9) where {BL,BR,T} = ChoiState{BL,BR,T}(b1,b2,data; tol=tol)
ChoiState(b,data; tol=tol) = ChoiState(b,b,data; tol=tol)

Check warning on line 387 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L385-L387

Added lines #L385 - L387 were not covered by tests

# TODO: document why we have super_to_choi return non-trace one density matrices.
# https://forest-benchmarking.readthedocs.io/en/latest/superoperator_representations.html
Expand Down Expand Up @@ -367,5 +414,29 @@ function _super_choi((r2, l2), (r1, l1), data::SparseMatrixCSC)
return (l1, l2), (r1, r2), sparse(data)

Check warning on line 414 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L414

Added line #L414 was not covered by tests
end

ChoiState(op::SuperOperator) = ChoiState(_super_choi(op.basis_l, op.basis_r, op.data)...)
ChoiState(op::SuperOperator; tol=1e-9) = ChoiState(_super_choi(op.basis_l, op.basis_r, op.data)...; tol=tol)
SuperOperator(kraus::KrausOperators) =

Check warning on line 418 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L417-L418

Added lines #L417 - L418 were not covered by tests
SuperOperator((kraus.basis_l, kraus.basis_l), (kraus.basis_r, kraus.basis_r),
(sum(conj(op)op for op in kraus.data)).data)

SuperOperator(op::ChoiState) = SuperOperator(_super_choi(op.basis_l, op.basis_r, op.data)...)
ChoiState(kraus::KrausOperators) = ChoiState(SuperOperator(kraus))

Check warning on line 423 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L422-L423

Added lines #L422 - L423 were not covered by tests

function KrausOperators(choi::ChoiState; tol=1e-9)
if (!samebases(choi.basis_l[1], choi.basis_l[2]) ||

Check warning on line 426 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L425-L426

Added lines #L425 - L426 were not covered by tests
!samebases(choi.basis_r[1], choi.basis_r[2]))
throw(DimensionMismatch("Tried to convert choi state of something that isn't a quantum channel mapping density operators to density operators"))

Check warning on line 428 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L428

Added line #L428 was not covered by tests
end
bl, br = choi.basis_l[1], choi.basis_r[1]

Check warning on line 430 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L430

Added line #L430 was not covered by tests
#ishermitian(choi.data) || @warn "ChoiState is not hermitian"
# TODO: figure out how to do this with sparse matrices using e.g. Arpack.jl or ArnoldiMethod.jl
vals, vecs = eigen(Hermitian(Matrix(choi.data)))
for val in vals
(abs(val) > tol && val < 0) && @warn "eigval $(val) < 0 but abs(eigval) > tol=$(tol)"
end
ops = [Operator(bl, br, sqrt(val)*reshape(vecs[:,i], length(bl), length(br)))

Check warning on line 437 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L433-L437

Added lines #L433 - L437 were not covered by tests
for (i, val) in enumerate(vals) if abs(val) > tol && val > 0]
return KrausOperators(bl, br, ops)

Check warning on line 439 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L439

Added line #L439 was not covered by tests
end

KrausOperators(op::SuperOperator; tol=1e-9) = KrausOperators(ChoiState(op; tol=tol); tol=tol)

Check warning on line 442 in src/superoperators.jl

View check run for this annotation

Codecov / codecov/patch

src/superoperators.jl#L442

Added line #L442 was not covered by tests

0 comments on commit c12a150

Please sign in to comment.