@@ -11,8 +11,9 @@ mutable struct SuperOperator{B1,B2,T} <: AbstractSuperOperator{B1,B2}
1111 basis_r:: B2
1212 data:: T
1313 function SuperOperator {BL,BR,T} (basis_l:: BL , basis_r:: BR , data:: T ) where {BL,BR,T}
14- if length (basis_l[1 ])* length (basis_l[2 ]) != size (data, 1 ) ||
15- length (basis_r[1 ])* length (basis_r[2 ]) != size (data, 2 )
14+ if (length (basis_l) != 2 || length (basis_r) != 2 ||
15+ length (basis_l[1 ])* length (basis_l[2 ]) != size (data, 1 ) ||
16+ length (basis_r[1 ])* length (basis_r[2 ]) != size (data, 2 ))
1617 throw (DimensionMismatch (" Tried to assign data of size $(size (data)) to Hilbert spaces of sizes $(length .(basis_l)) , $(length .(basis_r)) " ))
1718 end
1819 new (basis_l, basis_r, data)
316317 }
317318 throw (IncompatibleBases ())
318319end
320+
321+ """
322+ ChoiState <: AbstractSuperOperator
323+
324+ Superoperator represented as a choi state.
325+ """
326+ mutable struct ChoiState{B1,B2,T} <: AbstractSuperOperator{B1,B2}
327+ basis_l:: B1
328+ basis_r:: B2
329+ data:: T
330+ function ChoiState {BL,BR,T} (basis_l:: BL , basis_r:: BR , data:: T ) where {BL,BR,T}
331+ if (length (basis_l) != 2 || length (basis_r) != 2 ||
332+ length (basis_l[1 ])* length (basis_l[2 ]) != size (data, 1 ) ||
333+ length (basis_r[1 ])* length (basis_r[2 ]) != size (data, 2 ))
334+ throw (DimensionMismatch (" Tried to assign data of size $(size (data)) to Hilbert spaces of sizes $(length .(basis_l)) , $(length .(basis_r)) " ))
335+ end
336+ new (basis_l, basis_r, data)
337+ end
338+ end
339+ ChoiState {BL,BR} (b1:: BL , b2:: BR , data:: T ) where {BL,BR,T} = ChoiState {BL,BR,T} (b1, b2, data)
340+ ChoiState (b1:: BL , b2:: BR , data:: T ) where {BL,BR,T} = ChoiState {BL,BR,T} (b1, b2, data)
341+ ChoiState (b,data) = ChoiState (b, b, data)
342+
343+ dense (a:: ChoiState ) = ChoiState (a. basis_l, a. basis_r, Matrix (a. data))
344+ sparse (a:: ChoiState ) = ChoiStae (a. basis_l, a. basis_r, sparse (a. data))
345+ dagger (a:: ChoiState ) = ChoiState (dagger (SuperOperator (a)))
346+ * (a:: ChoiState , b:: ChoiState ) = ChoiState (SuperOperator (a)* SuperOperator (b))
347+ * (a:: ChoiState , b:: Operator ) = SuperOperator (a)* b
348+ == (a:: ChoiState , b:: ChoiState ) = SuperOperator (a) == SuperOperator (b)
349+
350+ # reshape swaps within systems due to colum major ordering
351+ # https://docs.qojulia.org/quantumobjects/operators/#tensor_order
352+ function _super_choi ((l1, l2), (r1, r2), data)
353+ data = reshape (data, map (length, (l2, l1, r2, r1)))
354+ (l1, l2), (r1, r2) = (r2, l2), (r1, l1)
355+ data = permutedims (data, (1 , 3 , 2 , 4 ))
356+ data = reshape (data, map (length, (l1⊗ l2, r1⊗ r2)))
357+ return (l1, l2), (r1, r2), data
358+ end
359+
360+ function _super_choi ((r2, l2), (r1, l1), data:: SparseMatrixCSC )
361+ data = _permutedims (data, map (length, (l2, r2, l1, r1)), (1 , 3 , 2 , 4 ))
362+ data = reshape (data, map (length, (l1⊗ l2, r1⊗ r2)))
363+ # sparse(data) is necessary since reshape of a sparse array returns a
364+ # ReshapedSparseArray which is not a subtype of AbstractArray and so
365+ # _permutedims fails to acces the ".m" field
366+ # https://github.com/qojulia/QuantumOpticsBase.jl/pull/83
367+ # https://github.com/JuliaSparse/SparseArrays.jl/issues/24
368+ # permutedims in SparseArrays.jl only implements perm (2,1) and so
369+ # _permutedims should probably be upstreamed
370+ # https://github.com/JuliaLang/julia/issues/26534
371+ return (l1, l2), (r1, r2), sparse (data)
372+ end
373+
374+ ChoiState (op:: SuperOperator ) = ChoiState (_super_choi (op. basis_l, op. basis_r, op. data)... )
375+ SuperOperator (op:: ChoiState ) = SuperOperator (_super_choi (op. basis_l, op. basis_r, op. data)... )
376+
377+ * (a:: ChoiState , b:: SuperOperator ) = SuperOperator (a)* b
378+ * (a:: SuperOperator , b:: ChoiState ) = a* SuperOperator (b)
379+
0 commit comments