Skip to content

Stim v1.2 Python API Reference

Craig Gidney edited this page May 27, 2021 · 1 revision

stim.Circuit


A mutable stabilizer circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit()
    >>> c.append_operation("X", [0])
    >>> c.append_operation("M", [0])
    >>> c.compile_sampler().sample(shots=1)
    array([[1]], dtype=uint8)

    >>> stim.Circuit('''
    ...    H 0
    ...    CNOT 0 1
    ...    M 0 1
    ...    DETECTOR rec[-1] rec[-2]
    ... ''').compile_detector_sampler().sample(shots=1)
    array([[0]], dtype=uint8)


stim.CompiledDetectorSampler

An analyzed stabilizer circuit whose detection events can be sampled quickly.

stim.CompiledMeasurementSampler

An analyzed stabilizer circuit whose measurements can be sampled quickly.

stim.PauliString


A signed Pauli product (e.g. "+X ⊗ X ⊗ X" or "-Y ⊗ Z".

Represents a collection of Pauli operations (I, X, Y, Z) applied pairwise to a collection of qubits.

Examples:
    >>> import stim
    >>> stim.PauliString("XX") * stim.PauliString("YY")
    stim.PauliString("-ZZ")
    >>> print(stim.PauliString(5))
    +_____


stim.Tableau


A stabilizer tableau.

Represents a Clifford operation by explicitly storing how that operation conjugates a list of Pauli
group generators into composite Pauli products.

Examples:
    >>> import stim
    >>> stim.Tableau.from_named_gate("H")
    stim.Tableau.from_conjugated_generators(
        xs=[
            stim.PauliString("+Z"),
        ],
        zs=[
            stim.PauliString("+X"),
        ],
    )

    >>> t = stim.Tableau.random(5)
    >>> t_inv = t**-1
    >>> print(t * t_inv)
    +-xz-xz-xz-xz-xz-
    | ++ ++ ++ ++ ++
    | XZ __ __ __ __
    | __ XZ __ __ __
    | __ __ XZ __ __
    | __ __ __ XZ __
    | __ __ __ __ XZ

    >>> x2z3 = t.x_output(2) * t.z_output(3)
    >>> t_inv(x2z3)
    stim.PauliString("+__XZ_")

stim.TableauSimulator


A quantum stabilizer circuit simulator whose internal state is an inverse stabilizer tableau.

Supports interactive usage, where gates and measurements are applied on demand.

Examples:
    >>> import stim
    >>> s = stim.TableauSimulator()
    >>> s.h(0)
    >>> if s.measure(0):
    ...     s.h(1)
    ...     s.cnot(1, 2)
    >>> s.measure(1) == s.measure(2)
    True

    >>> s = stim.TableauSimulator()
    >>> s.h(0)
    >>> s.cnot(0, 1)
    >>> s.current_inverse_tableau()
    stim.Tableau.from_conjugated_generators(
        xs=[
            stim.PauliString("+ZX"),
            stim.PauliString("+_X"),
        ],
        zs=[
            stim.PauliString("+X_"),
            stim.PauliString("+XZ"),
        ],
    )

stim.target_inv(qubit_index: int) -> int

Returns a target flagged as inverted that can be passed into Circuit.append_operation
For example, the '!1' in 'M 0 !1 2' is qubit 1 flagged as inverted,
meaning the measurement result from qubit 1 should be inverted when reported.

stim.target_rec(lookback_index: int) -> int

Returns a record target that can be passed into Circuit.append_operation.
For example, the 'rec[-2]' in 'DETECTOR rec[-2]' is a record target.

stim.target_x(qubit_index: int) -> int

Returns a target flagged as Pauli X that can be passed into Circuit.append_operation
For example, the 'X1' in 'CORRELATED_ERROR(0.1) X1 Y2 Z3' is qubit 1 flagged as Pauli X.

stim.target_y(qubit_index: int) -> int

Returns a target flagged as Pauli Y that can be passed into Circuit.append_operation
For example, the 'Y2' in 'CORRELATED_ERROR(0.1) X1 Y2 Z3' is qubit 2 flagged as Pauli Y.

stim.target_z(qubit_index: int) -> int

Returns a target flagged as Pauli Z that can be passed into Circuit.append_operation
For example, the 'Z3' in 'CORRELATED_ERROR(0.1) X1 Y2 Z3' is qubit 3 flagged as Pauli Z.

stim.Circuit.__add__(self, second: stim.Circuit) -> stim.Circuit

Creates a circuit by appending two circuits.

Examples:
    >>> import stim
    >>> c1 = stim.Circuit('''
    ...    X 0
    ...    Y 1 2
    ... ''')
    >>> c2 = stim.Circuit('''
    ...    M 0 1 2
    ... ''')
    >>> print(c1 + c2)
    X 0
    Y 1 2
    M 0 1 2

stim.Circuit.__iadd__(self, second: stim.Circuit) -> stim.Circuit

Appends a circuit into the receiving circuit (mutating it).

Examples:
    >>> import stim
    >>> c1 = stim.Circuit('''
    ...    X 0
    ...    Y 1 2
    ... ''')
    >>> c2 = stim.Circuit('''
    ...    M 0 1 2
    ... ''')
    >>> c1 += c2
    >>> print(c1)
    X 0
    Y 1 2
    M 0 1 2

stim.Circuit.__imul__(self, repetitions: int) -> stim.Circuit

Mutates the circuit into multiple copies of itself.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    X 0
    ...    Y 1 2
    ... ''')
    >>> c *= 3
    >>> print(c)
    REPEAT 3 {
        X 0
        Y 1 2
    }

stim.Circuit.__init__(self, stim_program_text: str = '') -> None

Creates a stim.Circuit.

Args:
    stim_program_text: Defaults to empty. Describes operations to append into the circuit.

Examples:
    >>> import stim
    >>> empty = stim.Circuit()
    >>> not_empty = stim.Circuit('''
    ...    X 0
    ...    CNOT 0 1
    ...    M 1
    ... ''')

stim.Circuit.__mul__(self, repetitions: int) -> stim.Circuit

Creates a circuit by repeating a circuit multiple times.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    X 0
    ...    Y 1 2
    ... ''')
    >>> print(c * 3)
    REPEAT 3 {
        X 0
        Y 1 2
    }

stim.Circuit.__rmul__(self, repetitions: int) -> stim.Circuit

Creates a circuit by repeating a circuit multiple times.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    X 0
    ...    Y 1 2
    ... ''')
    >>> print(3 * c)
    REPEAT 3 {
        X 0
        Y 1 2
    }

stim.Circuit.append_from_stim_program_text(self, stim_program_text: str) -> None

Appends operations described by a STIM format program into the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit()
    >>> c.append_from_stim_program_text('''
    ...    H 0  # comment
    ...    CNOT 0 2
    ...
    ...    M 2
    ...    CNOT rec[-1] 1
    ... ''')
    >>> print(c)
    H 0
    CX 0 2
    M 2
    CX rec[-1] 1

Args:
    text: The STIM program text containing the circuit operations to append.

stim.Circuit.append_operation(self, name: str, targets: List[int], arg: float = 0.0) -> None

Appends an operation into the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit()
    >>> c.append_operation("X", [0])
    >>> c.append_operation("H", [0, 1])
    >>> c.append_operation("M", [0, stim.target_inv(1)])
    >>> c.append_operation("CNOT", [stim.target_rec(-1), 0])
    >>> c.append_operation("X_ERROR", [0], 0.125)
    >>> c.append_operation("CORRELATED_ERROR", [stim.target_x(0), stim.target_y(2)], 0.25)
    >>> print(c)
    X 0
    H 0 1
    M 0 !1
    CX rec[-1] 0
    X_ERROR(0.125) 0
    E(0.25) X0 Y2

Args:
    name: The name of the operation's gate (e.g. "H" or "M" or "CNOT").
    targets: The gate targets. Gates implicitly broadcast over their targets.
    arg: A modifier for the gate, e.g. the probability of an error. Defaults to 0.

stim.Circuit.clear(self) -> None

Clears the contents of the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    X 0
    ...    Y 1 2
    ... ''')
    >>> c.clear()
    >>> c
    stim.Circuit()

stim.Circuit.compile_detector_sampler(self) -> CompiledDetectorSampler

Returns a CompiledDetectorSampler, which can quickly batch sample detection events, for the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    H 0
    ...    CNOT 0 1
    ...    M 0 1
    ...    DETECTOR rec[-1] rec[-2]
    ... ''')
    >>> s = c.compile_detector_sampler()
    >>> s.sample(shots=1)
    array([[0]], dtype=uint8)

stim.Circuit.compile_sampler(self) -> CompiledMeasurementSampler

Returns a CompiledMeasurementSampler, which can quickly batch sample measurements, for the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    X 2
    ...    M 0 1 2
    ... ''')
    >>> s = c.compile_sampler()
    >>> s.sample(shots=1)
    array([[0, 0, 1]], dtype=uint8)

stim.Circuit.num_measurements


Counts the number of measurement bits produced when sampling from the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    M 0
    ...    M 0 1
    ... ''')
    >>> c.num_measurements
    3

stim.Circuit.num_qubits


Counts the number of qubits used when simulating the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    M 0
    ...    M 0 1
    ... ''')
    >>> c.num_qubits
    2
    >>> c.append_from_stim_program_text('''
    ...    X 100
    ... ''')
    >>> c.num_qubits
    101

stim.CompiledDetectorSampler.sample(self, shots: int, *, prepend_observables: bool = False, append_observables: bool = False) -> numpy.ndarray[numpy.uint8]

Returns a numpy array containing a batch of detector samples from the circuit.

The circuit must define the detectors using DETECTOR instructions. Observables defined by OBSERVABLE_INCLUDE
instructions can also be included in the results as honorary detectors.

Args:
    shots: The number of times to sample every detector in the circuit.
    prepend_observables: Defaults to false. When set, observables are included with the detectors and are
        placed at the start of the results.
    append_observables: Defaults to false. When set, observables are included with the detectors and are
        placed at the end of the results.

Returns:
    A numpy array with `dtype=uint8` and `shape=(shots, n)` where
    `n = num_detectors + num_observables*(append_observables + prepend_observables)`.
    The bit for detection event `m` in shot `s` is at `result[s, m]`.

stim.CompiledDetectorSampler.sample_bit_packed(self, shots: int, *, prepend_observables: bool = False, append_observables: bool = False) -> numpy.ndarray[numpy.uint8]

Returns a numpy array containing bit packed batch of detector samples from the circuit.

The circuit must define the detectors using DETECTOR instructions. Observables defined by OBSERVABLE_INCLUDE
instructions can also be included in the results as honorary detectors.

Args:
    shots: The number of times to sample every detector in the circuit.
    prepend_observables: Defaults to false. When set, observables are included with the detectors and are
        placed at the start of the results.
    append_observables: Defaults to false. When set, observables are included with the detectors and are
        placed at the end of the results.

Returns:
    A numpy array with `dtype=uint8` and `shape=(shots, n)` where
    `n = num_detectors + num_observables*(append_observables + prepend_observables)`.
    The bit for detection event `m` in shot `s` is at `result[s, (m // 8)] & 2**(m % 8)`.

stim.CompiledMeasurementSampler.sample(self, shots: int) -> numpy.ndarray[numpy.uint8]

Returns a numpy array containing a batch of measurement samples from the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    X 0   2 3
    ...    M 0 1 2 3
    ... ''')
    >>> s = c.compile_sampler()
    >>> s.sample(shots=1)
    array([[1, 0, 1, 1]], dtype=uint8)

Args:
    shots: The number of times to sample every measurement in the circuit.

Returns:
    A numpy array with `dtype=uint8` and `shape=(shots, num_measurements)`.
    The bit for measurement `m` in shot `s` is at `result[s, m]`.

stim.CompiledMeasurementSampler.sample_bit_packed(self, shots: int) -> numpy.ndarray[numpy.uint8]

Returns a numpy array containing a bit packed batch of measurement samples from the circuit.

Examples:
    >>> import stim
    >>> c = stim.Circuit('''
    ...    X 0 1 2 3 4 5 6 7     10
    ...    M 0 1 2 3 4 5 6 7 8 9 10
    ... ''')
    >>> s = c.compile_sampler()
    >>> s.sample_bit_packed(shots=1)
    array([[255,   4]], dtype=uint8)

Args:
    shots: The number of times to sample every measurement in the circuit.

Returns:
    A numpy array with `dtype=uint8` and `shape=(shots, (num_measurements + 7) // 8)`.
    The bit for measurement `m` in shot `s` is at `result[s, (m // 8)] & 2**(m % 8)`.

stim.PauliString.__getitem__(*args, **kwargs)

Overloaded function.

1. __getitem__(self: stim.PauliString, index: int) -> int


        Returns an individual Pauli or Pauli string slice from the pauli string.

        Individual Paulis are returned as an int using the encoding 0=I, 1=X, 2=Y, 3=Z.
        Slices are returned as a stim.PauliString (always with positive sign).

        Examples:
            >>> import stim
            >>> p = stim.PauliString("_XYZ")
            >>> p[2]
            2
            >>> p[-1]
            3
            >>> p[:2]
            stim.PauliString("+_X")
            >>> p[::-1]
            stim.PauliString("+ZYX_")

        Args:
            index: The index of the pauli to return or slice of paulis to return.

        Returns:
            0: Identity.
            1: Pauli X.
            2: Pauli Y.
            3: Pauli Z.
     

2. __getitem__(self: stim.PauliString, slice: slice) -> stim.PauliString


        Returns an individual Pauli or Pauli string slice from the pauli string.

        Individual Paulis are returned as an int using the encoding 0=I, 1=X, 2=Y, 3=Z.
        Slices are returned as a stim.PauliString (always with positive sign).

        Examples:
            >>> import stim
            >>> p = stim.PauliString("_XYZ")
            >>> p[2]
            2
            >>> p[-1]
            3
            >>> p[:2]
            stim.PauliString("+_X")
            >>> p[::-1]
            stim.PauliString("+ZYX_")

        Args:
            index: The index of the pauli to return or slice of paulis to return.

        Returns:
            0: Identity.
            1: Pauli X.
            2: Pauli Y.
            3: Pauli Z.
     

stim.PauliString.__init__(*args, **kwargs)

Overloaded function.

1. __init__(self: stim.PauliString, text: str) -> None


                Creates a stim.PauliString from a text string.

                The string can optionally start with a sign ('+' or '-').
                The rest of the string should be characters from '_IXYZ' where
                '_' and 'I' mean identity, 'X' means Pauli X, 'Y' means Pauli Y, and 'Z' means Pauli Z.

                Examples:
                    >>> import stim
                    >>> print(stim.PauliString("YZ"))
                    +YZ
                    >>> print(stim.PauliString("+IXYZ"))
                    +_XYZ
                    >>> print(stim.PauliString("-___X_"))
                    -___X_

                Args:
                    text: A text description of the Pauli string's contents, such as "+XXX" or "-_YX".
             

2. __init__(self: stim.PauliString, num_qubits: int) -> None


                Creates an identity Pauli string over the given number of qubits.

                Examples:
                    >>> import stim
                    >>> p = stim.PauliString(5)
                    >>> print(p)
                    +_____

                Args:
                    num_qubits: The number of qubits the Pauli string acts on.
             

stim.PauliString.__mul__(*args, **kwargs)

Overloaded function.

1. __mul__(self: stim.PauliString, rhs: stim.PauliString) -> stim.PauliString


        Returns the product of two commuting Pauli strings.

        The integers +1 and -1 are considered to be identity Pauli strings with the given sign.

        For anti-commuting Pauli strings, use 'stim.PauliString.extended_product' instead.

        Args:
            rhs: The right hand side Pauli string.

        Examples:
            >>> import stim
            >>> p1 = stim.PauliString("_XYZ")
            >>> p2 = stim.PauliString("_ZYX")
            >>> p3 = p1 * p2
            >>> print(p3)
            +_Y_Y
            >>> stim.PauliString("XX") * stim.PauliString("ZZ")
            stim.PauliString("-YY")

        Returns:
            The product of the two Pauli strings.

        Raises:
            ValueError: The Pauli strings don't commute, or have different lengths.
    

2. __mul__(self: stim.PauliString, rhs: int) -> stim.PauliString


        Returns the product of two commuting Pauli strings.

        The integers +1 and -1 are considered to be identity Pauli strings with the given sign.

        For anti-commuting Pauli strings, use 'stim.PauliString.extended_product' instead.

        Args:
            rhs: The right hand side Pauli string.

        Examples:
            >>> import stim
            >>> p1 = stim.PauliString("_XYZ")
            >>> p2 = stim.PauliString("_ZYX")
            >>> p3 = p1 * p2
            >>> print(p3)
            +_Y_Y
            >>> stim.PauliString("XX") * stim.PauliString("ZZ")
            stim.PauliString("-YY")

        Returns:
            The product of the two Pauli strings.

        Raises:
            ValueError: The Pauli strings don't commute, or have different lengths.
    

stim.PauliString.__rmul__(self, lhs: int) -> stim.PauliString

Returns the product of two commuting Pauli strings.

The integers +1 and -1 are considered to be identity Pauli strings with the given sign.

For anti-commuting Pauli strings, use 'stim.PauliString.extended_product' instead.

Args:
    rhs: The right hand side Pauli string.

Examples:
    >>> import stim
    >>> p1 = stim.PauliString("_XYZ")
    >>> p2 = stim.PauliString("_ZYX")
    >>> p3 = p1 * p2
    >>> print(p3)
    +_Y_Y
    >>> stim.PauliString("XX") * stim.PauliString("ZZ")
    stim.PauliString("-YY")

Returns:
    The product of the two Pauli strings.

Raises:
    ValueError: The Pauli strings don't commute, or have different lengths.

stim.PauliString.extended_product(self, other: stim.PauliString) -> Tuple[complex, stim.PauliString]

Returns the product of two Pauli strings as a phase term and a non-imaginary Pauli string.

The phase term will be equal to 1 or to 1j. The true product is equal to the phase term
times the non-imaginary Pauli string.

Args:
    other: The right hand side Pauli string.

Examples:
    >>> import stim
    >>> x = stim.PauliString("X_")
    >>> z = stim.PauliString("Z_")
    >>> x.extended_product(z)
    (1j, stim.PauliString("-Y_"))
    >>> z.extended_product(x)
    (1j, stim.PauliString("+Y_"))
    >>> x.extended_product(x)
    ((1+0j), stim.PauliString("+__"))
    >>> xx = stim.PauliString("XX")
    >>> zz = stim.PauliString("ZZ")
    >>> xx.extended_product(zz)
    ((1+0j), stim.PauliString("-YY"))

Returns:
    The product of the two Pauli strings.

Raises:
    ValueError: The Pauli strings don't commute, or have different lengths.

stim.PauliString.random(num_qubits: int) -> stim.PauliString

Samples a uniformly random Pauli string over the given number of qubits.

Args:
    num_qubits: The number of qubits the Pauli string should act on.

Examples:
    >>> import stim
    >>> p = stim.PauliString.random(5)

Returns:
    The sampled Pauli string.

stim.PauliString.sign


The sign of the Pauli string. Can be +1 or -1. Imaginary signs are not supported.

stim.Tableau.__call__(self, pauli_string: PauliString) -> PauliString

Returns the result of conjugating the given PauliString by the Tableau's Clifford operation.

Args:
    pauli_string: The pauli string to conjugate.

Returns:
    The new conjugated pauli string.

Examples:
    >>> import stim
    >>> t = stim.Tableau.from_named_gate("CNOT")
    >>> p = stim.PauliString("XX")
    >>> result = t(p)
    >>> print(result)
    +X_

References:
    "Hadamard-free circuits expose the structure of the Clifford group"
    Sergey Bravyi, Dmitri Maslov
    https://arxiv.org/abs/2003.09412

stim.Tableau.__init__(self, num_qubits: int) -> None

Creates an identity tableau over the given number of qubits.

Examples:
    >>> import stim
    >>> t = stim.Tableau(3)
    >>> print(t)
    +-xz-xz-xz-
    | ++ ++ ++
    | XZ __ __
    | __ XZ __
    | __ __ XZ

Args:
    num_qubits: The number of qubits the tableau's operation acts on.

stim.Tableau.__mul__(self, rhs: stim.Tableau) -> stim.Tableau

Returns the product of two tableaus.

If the tableau T1 represents the Clifford operation with unitary C1,
and the tableau T2 represents the Clifford operation with unitary C2,
then the tableau T1*T2 represents the Clifford operation with unitary C1*C2.

Args:
    rhs: The tableau  on the right hand side of the multiplication.

Examples:
    >>> import stim
    >>> t1 = stim.Tableau.random(4)
    >>> t2 = stim.Tableau.random(4)
    >>> t3 = t2 * t1
    >>> p = stim.PauliString.random(4)
    >>> t3(p) == t2(t1(p))
    True

stim.Tableau.__pow__(self, exponent: int) -> stim.Tableau

Raises the tableau to an integer power using inversion and repeated squaring.

Args:
    exponent: The power to raise to. Can be negative, zero, or positive.

Examples:
    >>> import stim
    >>> s = stim.Tableau.from_named_gate("S")
    >>> s**0 == stim.Tableau(1)
    True
    >>> s**1 == s
    True
    >>> s**2 == stim.Tableau.from_named_gate("Z")
    True
    >>> s**-1 == s**3 == stim.Tableau.from_named_gate("S_DAG")
    True
    >>> s**5 == s
    True
    >>> s**(400000000 + 1) == s
    True
    >>> s**(-400000000 + 1) == s
    True

stim.Tableau.append(self, gate: stim.Tableau, targets: List[int]) -> None

Appends an operation's effect into this tableau, mutating this tableau.

Time cost is O(n*m*m) where n=len(self) and m=len(gate).

Args:
    gate: The tableau of the operation being appended into this tableau.
    targets: The qubits being targeted by the gate.

Examples:
    >>> import stim
    >>> cnot = stim.Tableau.from_named_gate("CNOT")
    >>> t = stim.Tableau(2)
    >>> t.append(cnot, [0, 1])
    >>> t.append(cnot, [1, 0])
    >>> t.append(cnot, [0, 1])
    >>> t == stim.Tableau.from_named_gate("SWAP")
    True

stim.Tableau.from_conjugated_generators(*, xs: List[PauliString], zs: List[PauliString]) -> stim.Tableau

Creates a tableau from the given outputs for each generator.

Verifies that the tableau is well formed.

Args:
    xs: A List[stim.PauliString] with the results of conjugating X0, X1, etc.
    zs: A List[stim.PauliString] with the results of conjugating Z0, Z1, etc.

Returns:
    The created tableau.

Raises:
    ValueError: The given outputs are malformed. Their lengths are inconsistent,
        or they don't satisfy the required commutation relationships.

Examples:
    >>> import stim
    >>> identity3 = stim.Tableau.from_conjugated_generators(
    ...     xs=[
    ...         stim.PauliString("X__"),
    ...         stim.PauliString("_X_"),
    ...         stim.PauliString("__X"),
    ...     ],
    ...     zs=[
    ...         stim.PauliString("Z__"),
    ...         stim.PauliString("_Z_"),
    ...         stim.PauliString("__Z"),
    ...     ],
    ... )
    >>> identity3 == stim.Tableau(3)
    True

stim.Tableau.from_named_gate(name: str) -> stim.Tableau

Returns the tableau of a named Clifford gate.

Args:
    name: The name of the Clifford gate.

Returns:
    The gate's tableau.

Examples:
    >>> import stim
    >>> print(stim.Tableau.from_named_gate("H"))
    +-xz-
    | ++
    | ZX
    >>> print(stim.Tableau.from_named_gate("CNOT"))
    +-xz-xz-
    | ++ ++
    | XZ _Z
    | X_ XZ
    >>> print(stim.Tableau.from_named_gate("S"))
    +-xz-
    | ++
    | YZ

stim.Tableau.prepend(self, gate: stim.Tableau, targets: List[int]) -> None

Prepends an operation's effect into this tableau, mutating this tableau.

Time cost is O(n*m*m) where n=len(self) and m=len(gate).

Args:
    gate: The tableau of the operation being prepended into this tableau.
    targets: The qubits being targeted by the gate.

Examples:
    >>> import stim
    >>> h = stim.Tableau.from_named_gate("H")
    >>> cnot = stim.Tableau.from_named_gate("CNOT")
    >>> t = stim.Tableau.from_named_gate("H")
    >>> t.prepend(stim.Tableau.from_named_gate("X"), [0])
    >>> t == stim.Tableau.from_named_gate("SQRT_Y_DAG")
    True

stim.Tableau.random(num_qubits: int) -> stim.Tableau

Samples a uniformly random Clifford operation over the given number of qubits and returns its tableau.

Args:
    num_qubits: The number of qubits the tableau should act on.

Returns:
    The sampled tableau.

Examples:
    >>> import stim
    >>> t = stim.Tableau.random(42)

References:
    "Hadamard-free circuits expose the structure of the Clifford group"
    Sergey Bravyi, Dmitri Maslov
    https://arxiv.org/abs/2003.09412

stim.Tableau.then(self, second: stim.Tableau) -> stim.Tableau

Returns the result of composing two tableaus.

If the tableau T1 represents the Clifford operation with unitary C1,
and the tableau T2 represents the Clifford operation with unitary C2,
then the tableau T1.then(T2) represents the Clifford operation with unitary C2*C1.

Args:
    second: The result is equivalent to applying the second tableau after
        the receiving tableau.

Examples:
    >>> import stim
    >>> t1 = stim.Tableau.random(4)
    >>> t2 = stim.Tableau.random(4)
    >>> t3 = t1.then(t2)
    >>> p = stim.PauliString.random(4)
    >>> t3(p) == t2(t1(p))
    True

stim.Tableau.x_output(self, target: int) -> PauliString

Returns the result of conjugating a Pauli X by the tableau's Clifford operation.

Args:
    target: The qubit targeted by the Pauli X operation.

Examples:
    >>> import stim
    >>> cnot = stim.Tableau.from_named_gate("CNOT")
    >>> cnot.x_output(0)
    stim.PauliString("+XX")
    >>> cnot.x_output(1)
    stim.PauliString("+_X")

stim.Tableau.z_output(self, target: int) -> PauliString

Returns the result of conjugating a Pauli Z by the tableau's Clifford operation.

Args:
    target: The qubit targeted by the Pauli Z operation.

Examples:
    >>> import stim
    >>> cnot = stim.Tableau.from_named_gate("CNOT")
    >>> cnot.z_output(0)
    stim.PauliString("+Z_")
    >>> cnot.z_output(1)
    stim.PauliString("+ZZ")

stim.TableauSimulator.cnot(self, *args) -> None

Applies a controlled X gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.current_inverse_tableau(self) -> Tableau

Returns a copy of the internal state of the simulator as a stim.Tableau.

Returns:
    A stim.Tableau copy of the simulator's state.

Examples:
    >>> import stim
    >>> s = stim.TableauSimulator()
    >>> s.h(0)
    >>> s.current_inverse_tableau()
    stim.Tableau.from_conjugated_generators(
        xs=[
            stim.PauliString("+Z"),
        ],
        zs=[
            stim.PauliString("+X"),
        ],
    )
    >>> s.cnot(0, 1)
    >>> s.current_inverse_tableau()
    stim.Tableau.from_conjugated_generators(
        xs=[
            stim.PauliString("+ZX"),
            stim.PauliString("+_X"),
        ],
        zs=[
            stim.PauliString("+X_"),
            stim.PauliString("+XZ"),
        ],
    )

stim.TableauSimulator.current_measurement_record(self) -> List[bool]

Returns a copy of the record of all measurements performed by the simulator.

Examples:
    >>> import stim
    >>> s = stim.TableauSimulator()
    >>> s.current_measurement_record()
    []
    >>> s.measure(0)
    False
    >>> s.x(0)
    >>> s.measure(0)
    True
    >>> s.current_measurement_record()
    [False, True]
    >>> s.do(stim.Circuit("M 0"))
    >>> s.current_measurement_record()
    [False, True, True]

Returns:
    A list of booleans containing the result of every measurement performed by the simulator so far.

stim.TableauSimulator.cy(self, *args) -> None

Applies a controlled Y gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.cz(self, *args) -> None

Applies a controlled Z gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.do(self, circuit: stim.Circuit) -> None

Applies all the operations in the given stim.Circuit to the simulator's state.

Examples:
    >>> import stim
    >>> s = stim.TableauSimulator()
    >>> s.do(stim.Circuit('''
    ...     X 0
    ...     M 0
    ... '''))
    >>> s.current_measurement_record()
    [True]

Args:
    circuit: A stim.Circuit containing operations to apply.

stim.TableauSimulator.h(self, *args) -> None

Applies a Hadamard gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.h_xy(self, *args) -> None

Applies a variant of the Hadamard gate that swaps the X and Y axes to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.h_yz(self, *args) -> None

Applies a variant of the Hadamard gate that swaps the Y and Z axes to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.iswap(self, *args) -> None

Applies an ISWAP gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.iswap_dag(self, *args) -> None

Applies an ISWAP_DAG gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.measure(self, target: int) -> bool

Measures a single qubit.

Unlike the other methods on TableauSimulator, this one does not broadcast
over multiple targets. This is to avoid returning a list, which would
create a pitfall where typing `if sim.measure(qubit)` would be a bug.

To measure multiple qubits, use `TableauSimulator.measure_many`.

Args:
    target: The index of the qubit to measure.

Returns:
    The measurement result as a bool.

stim.TableauSimulator.measure_many(self, *args) -> List[bool]

Measures multiple qubits.

Args:
    *targets: The indices of the qubits to measure.

Returns:
    The measurement results as a list of bools.

stim.TableauSimulator.reset(self, *args) -> None

Resets qubits to zero (e.g. by swapping them for zero'd qubit from the environment).

Args:
    *targets: The indices of the qubits to reset.

stim.TableauSimulator.s(self, *args) -> None

Applies a SQRT_Z gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.s_dag(self, *args) -> None

Applies a SQRT_Z_DAG gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.sqrt_x(self, *args) -> None

Applies a SQRT_X gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.sqrt_x_dag(self, *args) -> None

Applies a SQRT_X_DAG gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.sqrt_y(self, *args) -> None

Applies a SQRT_Y gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.sqrt_y_dag(self, *args) -> None

Applies a SQRT_Y_DAG gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.swap(self, *args) -> None

Applies a swap gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.x(self, *args) -> None

Applies a Pauli X gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.xcx(self, *args) -> None

Applies an X-controlled X gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.xcy(self, *args) -> None

Applies an X-controlled Y gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.xcz(self, *args) -> None

Applies an X-controlled Z gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.y(self, *args) -> None

Applies a Pauli Y gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.

stim.TableauSimulator.ycx(self, *args) -> None

Applies a Y-controlled X gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.ycy(self, *args) -> None

Applies a Y-controlled Y gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.ycz(self, *args) -> None

Applies a Y-controlled Z gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
        Applies the gate to the first two targets, then the next two targets, and so forth.
        There must be an even number of targets.

stim.TableauSimulator.z(self, *args) -> None

Applies a Pauli Z gate to the simulator's state.

Args:
    *targets: The indices of the qubits to target with the gate.
Clone this wiki locally