@@ -412,8 +412,8 @@ Thus the Kraus representation is only defined for quantum channels which map
412412mutable struct KrausOperators{B1,B2,T} <: AbstractSuperOperator{B1,B2}
413413 basis_l:: B1
414414 basis_r:: B2
415- data:: T
416- function KrausOperators {BL,BR,T} (basis_l:: BL , basis_r:: BR , data:: T ) where {BL,BR,T}
415+ data:: Vector{T}
416+ function KrausOperators {BL,BR,T} (basis_l:: BL , basis_r:: BR , data:: Vector{T} ) where {BL,BR,T}
417417 if (any (! samebases (basis_r, M. basis_r) for M in data) ||
418418 any (! samebases (basis_l, M. basis_l) for M in data))
419419 throw (DimensionMismatch (" Tried to assign data with incompatible bases" ))
@@ -422,8 +422,8 @@ mutable struct KrausOperators{B1,B2,T} <: AbstractSuperOperator{B1,B2}
422422 new (basis_l, basis_r, data)
423423 end
424424end
425- KrausOperators {BL,BR} (b1:: BL ,b2:: BR ,data:: T ) where {BL,BR,T} = KrausOperators {BL,BR,T} (b1,b2,data)
426- KrausOperators (b1:: BL ,b2:: BR ,data:: T ) where {BL,BR,T} = KrausOperators {BL,BR,T} (b1,b2,data)
425+ KrausOperators {BL,BR} (b1:: BL ,b2:: BR ,data:: Vector{T} ) where {BL,BR,T} = KrausOperators {BL,BR,T} (b1,b2,data)
426+ KrausOperators (b1:: BL ,b2:: BR ,data:: Vector{T} ) where {BL,BR,T} = KrausOperators {BL,BR,T} (b1,b2,data)
427427
428428tensor (a:: KrausOperators , b:: KrausOperators ) =
429429 KrausOperators (a. basis_l ⊗ b. basis_l, a. basis_r ⊗ b. basis_r,
@@ -437,20 +437,19 @@ dagger(a::KrausOperators) = KrausOperators(a.basis_r, a.basis_l, [dagger(op) for
437437isapprox (a:: KrausOperators , b:: KrausOperators ; kwargs... ) = isapprox (SuperOperator (a), SuperOperator (b); kwargs... )
438438
439439"""
440- canonicalize (kraus::KrausOperators; tol=1e-12)
440+ orthogonalize (kraus::KrausOperators; tol=1e-12)
441441
442- Canonicalize the set kraus operators by performing a qr decomposition.
443- A quantum channel with kraus operators ``{A_k}`` is in cannonical form if and only if
444-
445- ```math
446- \\ Tr A_i^\\ dagger A_j \\ sim \\ delta_{i,j}
447- ```
442+ Orthogonalize the set kraus operators by performing a qr decomposition on their vec'd operators.
443+ Note that this is different than `canonicalize` which returns a kraus decomposition such
444+ that the kraus operators are Hilbert–Schmidt orthorgonal.
448445
449446If the input dimension is d and output dimension is d' then the number of kraus
450- operators returned is guaranteed to be no greater than dd' and will furthermore
451- be equal the Kraus rank of the channel up to numerical imprecision controlled by `tol`.
447+ operators returned is guaranteed to be no greater than dd', however it may be greater
448+ than the Kraus rank.
449+
450+ `orthogonalize` should always be much faster than canonicalize as it avoids an explicit eigendecomposition.
452451"""
453- function canonicalize (kraus:: KrausOperators ; tol= 1e-12 )
452+ function orthogonalize (kraus:: KrausOperators ; tol= 1e-12 )
454453 bl, br = kraus. basis_l, kraus. basis_r
455454 dim = length (bl)* length (br)
456455
@@ -467,8 +466,31 @@ function canonicalize(kraus::KrausOperators; tol=1e-12)
467466 return KrausOperators (bl, br, ops)
468467end
469468
470- # TODO : check if canonicalize and orthogonalize are equivalent
471- orthogonalize (kraus:: KrausOperators ; tol= 1e-12 ) = KrausOperators (ChoiState (kraus); tol= tol)
469+ """
470+ canonicalize(kraus::KrausOperators; tol=1e-12)
471+
472+ Transform the quantum channel into canonical form such that the kraus operators ``{A_k}``
473+ are Hilbert–Schmidt orthorgonal:
474+
475+ ```math
476+ \\ Tr A_i^\\ dagger A_j \\ sim \\ delta_{i,j}
477+ ```
478+
479+ If the input dimension is d and output dimension is d' then the number of kraus
480+ operators returned is guaranteed to be no greater than dd' and will furthermore
481+ be equal the Kraus rank of the channel up to numerical imprecision controlled by `tol`.
482+ """
483+ canonicalize (kraus:: KrausOperators ; tol= 1e-12 ) = KrausOperators (ChoiState (kraus); tol= tol)
484+
485+ # TODO : document
486+ function make_trace_preserving (kraus; tol= 1e-12 )
487+ m = I - sum (dagger (M)* M for M in kraus. data). data
488+ if isa (_positive_eigen (m; tol= tol), Number)
489+ throw (ArgumentError (" Channel must be trace nonincreasing" ))
490+ end
491+ K = Operator (kraus. basis_l, kraus. basis_r, sqrt (Matrix (m)))
492+ return KrausOperators (kraus. basis_l, kraus. basis_r, [kraus. data; K])
493+ end
472494
473495SuperOperator (kraus:: KrausOperators ) =
474496 SuperOperator ((kraus. basis_l, kraus. basis_l), (kraus. basis_r, kraus. basis_r),
@@ -536,18 +558,18 @@ function is_completely_positive(choi::ChoiState; tol=1e-12)
536558 return true
537559end
538560
539- is_completely_positive (super:: SuperOperator ; tol= 1e-12 ) = is_completely_positive (ChoiState (super))
561+ is_completely_positive (super:: SuperOperator ; tol= 1e-12 ) =
562+ is_completely_positive (ChoiState (super); tol= tol)
540563
541564# TODO : document this
542565is_trace_preserving (kraus:: KrausOperators ; tol= 1e-12 ) =
543566 _is_identity (sum (dagger (M)* M for M in kraus. data). data, tol= tol)
544567
545- function is_trace_preserving (choi:: ChoiState ; tol= 1e-12 )
546- is_completely_positive (choi; tol= tol) || return false
547- return _is_identity (ptrace (choi_to_operator (choi), 1 ). data, tol= tol)
548- end
568+ is_trace_preserving (choi:: ChoiState ; tol= 1e-12 ) =
569+ _is_identity (ptrace (choi_to_operator (choi), 1 ). data, tol= tol)
549570
550- is_trace_preserving (super:: SuperOperator ; tol= 1e-12 ) = is_trace_preserving (ChoiState (super); tol= tol)
571+ is_trace_preserving (super:: SuperOperator ; tol= 1e-12 ) =
572+ is_trace_preserving (ChoiState (super); tol= tol)
551573
552574# TODO : document this
553575function is_trace_nonincreasing (kraus:: KrausOperators ; tol= 1e-12 )
@@ -556,12 +578,12 @@ function is_trace_nonincreasing(kraus::KrausOperators; tol=1e-12)
556578end
557579
558580function is_trace_nonincreasing (choi:: ChoiState ; tol= 1e-12 )
559- is_completely_positive (choi; tol= tol) || return false
560581 m = I - ptrace (choi_to_operator (choi), 1 ). data
561582 return ! isa (_positive_eigen (m; tol= tol), Number)
562583end
563584
564- is_trace_nonincreasing (super:: SuperOperator ; tol= 1e-12 ) = is_trace_nonincreasing (ChoiState (super); tol= tol)
585+ is_trace_nonincreasing (super:: SuperOperator ; tol= 1e-12 ) =
586+ is_trace_nonincreasing (ChoiState (super); tol= tol)
565587
566588# TODO : document this
567589is_cptp (sop; tol= 1e-12 ) = is_completely_positive (sop; tol= tol) && is_trace_preserving (sop; tol= tol)
0 commit comments