|
316 | 316 | } |
317 | 317 | throw(IncompatibleBases()) |
318 | 318 | 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, (l1⊗l2, r1⊗r2))) |
| 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, (l1⊗l2, r1⊗r2))) |
| 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