|
316 | 316 | } |
317 | 317 | throw(IncompatibleBases()) |
318 | 318 | end |
| 319 | + |
| 320 | +""" |
| 321 | + Base class for the Choi representation of superoperators. |
| 322 | +""" |
| 323 | + |
| 324 | +mutable struct ChoiState{B1,B2,T} <: AbstractSuperOperator{B1,B2} |
| 325 | + basis_l::B1 |
| 326 | + basis_r::B2 |
| 327 | + data::T |
| 328 | + function ChoiState{BL,BR,T}(basis_l::BL, basis_r::BR, data::T) where {BL,BR,T} |
| 329 | + if (length(basis_l) != 2 || length(basis_r) != 2 || |
| 330 | + length(basis_l[1])*length(basis_l[2]) != size(data, 1) || |
| 331 | + length(basis_r[1])*length(basis_r[2]) != size(data, 2)) |
| 332 | + throw(DimensionMismatch("Tried to assign data of size $(size(data)) to Hilbert spaces of sizes $(length.(basis_l)), $(length.(basis_r))")) |
| 333 | + end |
| 334 | + new(basis_l, basis_r, data) |
| 335 | + end |
| 336 | +end |
| 337 | +ChoiState{BL,BR}(b1::BL,b2::BR,data::T) where {BL,BR,T} = ChoiState{BL,BR,T}(b1,b2,data) |
| 338 | +ChoiState(b1::BL,b2::BR,data::T) where {BL,BR,T} = ChoiState{BL,BR,T}(b1,b2,data) |
| 339 | +ChoiState(b,data) = SuperOperator(b,b,data) |
| 340 | + |
| 341 | +# reshape swaps within systems due to colum major ordering |
| 342 | +# https://docs.qojulia.org/quantumobjects/operators/#tensor_order |
| 343 | +function _super_choi((l1, l2), (r1, r2), data::Matrix) |
| 344 | + data = reshape(data, map(length, (l2, l1, r2, r1))) |
| 345 | + (l1, l2), (r1, r2) = (r2, l2), (r1, l1) |
| 346 | + data = permutedims(data, (1, 3, 2, 4)) |
| 347 | + data = reshape(data, map(length, (l1⊗l2, r1⊗r2))) |
| 348 | + return (l1, l2), (r1, r2), data |
| 349 | +end |
| 350 | + |
| 351 | +function _super_choi((r2, l2), (r1, l1), data::SparseMatrixCSC) |
| 352 | + data = _permutedims(data, map(length, (l2, r2, l1, r1)), (1, 3, 2, 4)) |
| 353 | + data = reshape(data, map(length, (l1⊗l2, r1⊗r2))) |
| 354 | + # sparse(data) is necessary since reshape of a sparse array returns a |
| 355 | + # ReshapedSparseArray which is not a subtype of AbstractArray and so |
| 356 | + # _permutedims fails to acces the ".m" field |
| 357 | + # https://github.com/qojulia/QuantumOpticsBase.jl/pull/83 |
| 358 | + # https://github.com/JuliaSparse/SparseArrays.jl/issues/24 |
| 359 | + # permutedims in SparseArrays.jl only implements perm (2,1) and so |
| 360 | + # _permutedims should be upstreamed |
| 361 | + # https://github.com/JuliaLang/julia/issues/26534 |
| 362 | + return (l1, l2), (r1, r2), sparse(data) |
| 363 | +end |
| 364 | + |
| 365 | +ChoiState(op::SuperOperator) = ChoiState(_super_choi(op.basis_l, op.basis_r, op.data)...) |
| 366 | +SuperOperator(op::ChoiState) = SuperOperator(_super_choi(op.basis_l, op.basis_r, op.data)...) |
0 commit comments