Skip to content

Commit 1f06f07

Browse files
committed
Create ChoiState type and conversions to/from SuperOperator
1 parent b7edca6 commit 1f06f07

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

src/QuantumOpticsBase.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ export Basis, GenericBasis, CompositeBasis, basis,
3535
current_time, time_shift, time_stretch, time_restrict, static_operator,
3636
#superoperators
3737
SuperOperator, DenseSuperOperator, DenseSuperOpType,
38-
SparseSuperOperator, SparseSuperOpType, spre, spost, sprepost, liouvillian,
39-
identitysuperoperator,
38+
SparseSuperOperator, SparseSuperOpType,
39+
ChoiState,
40+
spre, spost, sprepost, liouvillian, identitysuperoperator,
4041
#fock
4142
FockBasis, number, destroy, create,
4243
fockstate, coherentstate, coherentstate!,

src/superoperators.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,56 @@ end
316316
}
317317
throw(IncompatibleBases())
318318
end
319+
320+
# TODO should all of PauliTransferMatrix, ChiMatrix, ChoiState, and KrausOperators subclass AbstractSuperOperator?
321+
"""
322+
Base class for the Choi representation of superoperators.
323+
"""
324+
325+
mutable struct ChoiState{B1,B2,T} <: AbstractSuperOperator{B1,B2}
326+
basis_l::B1
327+
basis_r::B2
328+
data::T
329+
function ChoiState{BL,BR,T}(basis_l::BL, basis_r::BR, data::T) where {BL,BR,T}
330+
if (length(basis_l) != 2 || length(basis_r) != 2 ||
331+
length(basis_l[1])*length(basis_l[2]) != size(data, 1) ||
332+
length(basis_r[1])*length(basis_r[2]) != size(data, 2))
333+
throw(DimensionMismatch("Tried to assign data of size $(size(data)) to Hilbert spaces of sizes $(length.(basis_l)), $(length.(basis_r))"))
334+
end
335+
new(basis_l, basis_r, data)
336+
end
337+
end
338+
ChoiState{BL,BR}(b1::BL,b2::BR,data::T) where {BL,BR,T} = ChoiState{BL,BR,T}(b1,b2,data)
339+
ChoiState(b1::BL,b2::BR,data::T) where {BL,BR,T} = ChoiState{BL,BR,T}(b1,b2,data)
340+
ChoiState(b,data) = ChoiState(b,b,data)
341+
342+
# TODO: document why we have super_to_choi return non-trace one density matrices.
343+
# https://forest-benchmarking.readthedocs.io/en/latest/superoperator_representations.html
344+
# Note the similarity to permutesystems in operators_dense.jl
345+
346+
# reshape swaps within systems due to colum major ordering
347+
# https://docs.qojulia.org/quantumobjects/operators/#tensor_order
348+
function _super_choi((l1, l2), (r1, r2), data::Matrix)
349+
data = reshape(data, map(length, (l2, l1, r2, r1)))
350+
(l1, l2), (r1, r2) = (r2, l2), (r1, l1)
351+
data = permutedims(data, (1, 3, 2, 4))
352+
data = reshape(data, map(length, (l1l2, r1r2)))
353+
return (l1, l2), (r1, r2), data
354+
end
355+
356+
function _super_choi((r2, l2), (r1, l1), data::SparseMatrixCSC)
357+
data = _permutedims(data, map(length, (l2, r2, l1, r1)), (1, 3, 2, 4))
358+
data = reshape(data, map(length, (l1l2, r1r2)))
359+
# sparse(data) is necessary since reshape of a sparse array returns a
360+
# ReshapedSparseArray which is not a subtype of AbstractArray and so
361+
# _permutedims fails to acces the ".m" field
362+
# https://github.com/qojulia/QuantumOpticsBase.jl/pull/83
363+
# https://github.com/JuliaSparse/SparseArrays.jl/issues/24
364+
# permutedims in SparseArrays.jl only implements perm (2,1) and so
365+
# _permutedims should be upstreamed
366+
# https://github.com/JuliaLang/julia/issues/26534
367+
return (l1, l2), (r1, r2), sparse(data)
368+
end
369+
370+
ChoiState(op::SuperOperator) = ChoiState(_super_choi(op.basis_l, op.basis_r, op.data)...)
371+
SuperOperator(op::ChoiState) = SuperOperator(_super_choi(op.basis_l, op.basis_r, op.data)...)

0 commit comments

Comments
 (0)