Skip to content

Instantly share code, notes, and snippets.

@cgranade
Last active September 25, 2021 02:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgranade/4a1d525c09745619716507cc3c2adee5 to your computer and use it in GitHub Desktop.
Save cgranade/4a1d525c09745619716507cc3c2adee5 to your computer and use it in GitHub Desktop.
Operator Sum support for QuTiP

Operator Sum representation support for QuTiP

Abstract

When working with quantum objects in QuTiP, the library provides the concept of a kind, allowing the use of state vectors, dual vectors, density operators, unitary operators, and superoperators all in unified fashion. Currently, however, this support does not include representations of operator-sum decompositions of channels or instruments. For example, qt.to_kraus returns a list of Qobj instances, which then has no further metadata nor any way of enforcing that each consituent Qobj instance agrees in dimensions and other metadata. Similarly, instruments can commonly be represented by a decomposition into a sum of completely positive trace non-increasing channels, but there is no current reflection of this structure in QuTiP. This design document describes a modification to QuTiP to enable first-class support for operator-sum decompositions.

Dimensions

In general, QuTiP differentiates between kinds by using decompositions of array shapes into lists of subsystems. For example, a single-qubit state vector can represented by a shape of (2, 1) and dimensions of [[2], [1]], representing that a vector is a function from a scalar (dims of [1]) to a single qubit space. Similarly:

Example Shape Dimensions
Two-qubit dual vector (1, 4) [[1], [2, 2]]
Two-qutrit unitary operator (9, 9) [[3, 3], [3, 3]]

When representing linear functions from matrices to matrices, QuTiP implicitly uses the isomorphism that 𝐿(𝐿(𝐴, 𝐡), 𝐿(𝐢, 𝐷)) β‰… 𝐿(𝐴 βŠ— 𝐡, 𝐢 βŠ— 𝐷). That is, linear functions from linear functions to linear functions can be represented by tensoring the input and output spaces of each constiuent space together. For example, a density operator is a linear operator from β„‚Β² to β„‚Β², such that a function from density operators to density operators is an element of the space 𝐿(𝐿(β„‚Β², β„‚Β²), 𝐿(β„‚Β², β„‚Β²)). In QuTiP, we write down dimensions as [output dims, input dims], where here the input and output dimensions are themselves matrix-like ([[2], [2]]), giving a final value for our dimensions of [[[2], [2]], [[2], [2]]].

Example Shape Dimensions
Single-qubit channel (linear function from 𝐿(β„‚Β², β„‚Β²) β†’ 𝐿(β„‚Β², β„‚Β²) β‰… 𝐿(β„‚Β² βŠ— β„‚Β², β„‚Β² βŠ— β„‚Β³)) (16, 16) [[[2], [2]], [[2], [2]]]
Two-qutit channel (𝐿(𝐿(β„‚Β³ βŠ— β„‚Β³, β„‚Β³ βŠ— β„‚Β³), 𝐿(β„‚Β³ βŠ— β„‚Β³, β„‚Β³ βŠ— β„‚Β³)) β‰… 𝐿(β„‚Β³ βŠ— β„‚Β³ βŠ— β„‚Β³ βŠ— β„‚Β³, β„‚Β³ βŠ— β„‚Β³ βŠ— β„‚Β³ βŠ— β„‚Β³)) (81, 81) [[[3, 3], [3, 3]], [[3, 3]]]

Effectively, each such specification of dimensions tells the user and other parts of the QuTiP library how to decompose the shape into tensor products of constiutent spaces, with integers standing for ℂⁿ with 𝑛 a nonnegative integer.

Dimensions for operator-sum decompositions

Following convention that dimensions specify decompositions of Hilbert spaces into tensor products of ℂⁿ, we propose to extend the [output dims, input dims] pattern in QuTiP to allow for explicitly denoting operator-sum decompositions as well. We will consider two possible alternatives for doing so.

Alternative 1: Extended lists

Following this proposal, the [output_dims, input_dims] pattern is extended to [n_terms, output_dims, input_dims], with lists of two entries being interpreted as [1, output, input]. For example, a three-qubit channel with Choi rank of 3 (that is, can be specified by a minimum of three operators in a Kraus decomposition) would be represented by [3, [2, 2, 2], [2, 2, 2]] as opposed to the full superoperator representation of [[[2, 2, 2], [2, 2, 2]], [[2, 2, 2], [2, 2, 2]]].

Similarly, a two-outcome measurement on a single qutrit can be represented by an instrument of dimensions [2, [[3], [3]], [[3], [3]].

Alternative 2: L Dataclass

Following this proposal, the [output_dims, input_dims] pattern is replaced by a new dataclass qutip.spaces.L:

TSpace = Union[
  # Decomposition of a Hilbert space into indices without any further grouping.
  List[int],
  # Matrix-like decomposition.
  # NB: Python type hints do not allow enforcing that lists have exactly two elements.
  List[List[int]],
  # Superoperator-like decomposition.
  List[List[List[int]]],
  # New-style linear function notation.
  "L"
]

TDimensions = Union[
  TSpace,
  "OperatorSum"
]

@dataclass(init=False)
class L:
    """
    The space of linear operators from `input` to `output`.
    """
    output: TSpace
    input: TSpace
    
    def __init__(self, output: Union[TSpace, int], input: Union[TSpace, int, None] = None):
        self.output = [output] if isinstance(output, int) else output
        self.input = input if input is not None else self.output
    
    def __mul__(self, n_terms: int) -> OperatorSum:
        return OperatorSum(n_terms, self)
        
    def __rmul__(self, n_terms: int) -> OperatorSum:
        return OperatorSum(n_terms, self)
  
def T(output: Union[TSpace, int], input: Union[TSpace, int, None]) -> L:
    """
    The space of transformations on a given vector space (that is, linear functions from
    linear functions to linear functions).
    
    For example, `T(2)` is equivalent to `L(L(2))`, which in turn is equivalent to
    `L(L(2, 2), L(2, 2))`.
    """
    return L(L(output, input))
    
@dataclass
class OperatorSum:
    """
    Dimensions representing operator-sum decompositions, where operators
    are each defined on a given space.
    """
    n_terms: int
    operator: TSpace

For example:

Example Existing dimensions New dimensions kind
Rectangular 2Γ—3 matrix [[2], [3]] L([2], [3]), L(2, 3), or L(input=3, output=2) oper
Single-qubit channel [[[2], [2]], [[2], [2]]] L(L(2)) or T(2) super
Two-qutrit channel [[[3, 3], [3, 3]], [[3, 3], [3, 3]]] L(L([3, 3])) or T([3, 3]) super
Operator-sum decomposition of three-qu5it channel with Choi rank 3 n/a 3 * L([5, 5, 5]) kraus
Instrument with five outcomes acting on a two-qu7it space n/a 5 * T([7, 7]) instr

Modifications to superoperator APIs

  • Two new kind values, kraus and instr, would be introduced to represent operator-sum decompositions of channels and instruments, respectively.
  • Existing conversion functions (e.g.: qt.to_super, qt.to_choi, and so forth) would be modified to accept both kind="super" and kind="kraus".
  • The iscp, istp, ishp, and iscptp properties would be extended to apply to kind="kraus" and kind="instr" instances as well.
  • The existing qt.kraus_to_* conversion functions would be modified to accept kind="kraus" as well as plain lists.
  • The existing qt.*_to_kraus conversion functions would be modified to return kind="kraus". (NB: How to make this non-breaking?)
  • The existing __call__ method would be extended to allow kind="kraus".
  • A new sample(input_state: Qobj) -> Tuple[int, Qobj] method would be added for kind="instr", returning the measured result and the post-measurement state.
  • A new istni property would be added for kind="super" and kind="kraus" to allow checking for the weaker trace non-increasing condition.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment