LeakageFrameSimulator#

class cuquantum.stabilizer.LeakageFrameSimulator(
num_qubits: int,
num_paulis: int,
num_measurements: int = 0,
num_detectors: int = 0,
randomize_measurements: bool = True,
x_table: ndarray | ndarray | None = None,
z_table: ndarray | ndarray | None = None,
l_table: ndarray | ndarray | None = None,
measurement_table: ndarray | ndarray | None = None,
bit_packed: bool = False,
package: Literal['numpy', 'cupy'] = 'numpy',
seed: int | None = None,
stream: int | Stream | None = None,
options: Options | None = None,
)[source]#

Simulates quantum circuits with leakage-aware Pauli frame tracking.

In addition to the X/Z Pauli frame and measurement tables of FrameSimulator, this simulator tracks a leakage bit table (L) with one bit per (qubit, sample) marking whether the qubit is in the leaked subspace. HERALD_LEAKAGE_EVENT instructions copy leakage flags into the measurement table, so num_measurements must count ordinary measurement readouts plus herald leakage readouts (Circuit.num_measurements, which for a leakage circuit already includes herald readouts).

Example

>>> circ = Circuit(
...     "R 0 1\n"
...     "LEAKAGE_MARK1(0.1) 0\n"
...     "HERALD_LEAKAGE_EVENT 0\n"
...     "M 0 1\n"
... )
>>> sim = LeakageFrameSimulator.from_circuit(circ, 1024)
>>> sim.apply(circ)
>>> leakage = sim.get_leakage_bits()

Methods

__init__(
num_qubits: int,
num_paulis: int,
num_measurements: int = 0,
num_detectors: int = 0,
randomize_measurements: bool = True,
x_table: ndarray | ndarray | None = None,
z_table: ndarray | ndarray | None = None,
l_table: ndarray | ndarray | None = None,
measurement_table: ndarray | ndarray | None = None,
bit_packed: bool = False,
package: Literal['numpy', 'cupy'] = 'numpy',
seed: int | None = None,
stream: int | Stream | None = None,
options: Options | None = None,
)[source]#

Initialize a LeakageFrameSimulator.

Parameters:
  • num_qubits – Number of qubits to simulate.

  • num_paulis – Number of Pauli frame samples.

  • num_measurements – Number of measurement table rows: ordinary measurement readouts plus herald leakage readouts.

  • num_detectors – Number of detector instructions.

  • randomize_measurements – Randomize frame after measurement gates.

  • x_table – Pre-allocated X bit table.

  • z_table – Pre-allocated Z bit table. Must accompany x_table.

  • l_table – Pre-allocated leakage bit table. When omitted, an internal zero-initialized (unleaked) table is allocated.

  • measurement_table – Pre-allocated measurement table.

  • bit_packed – Whether the input tables are in bit-packed format.

  • package – Package to use for the tables, either "numpy" or "cupy".

  • seed – Seed for a generator that will produce default seed for every call of apply().

  • stream – Optional CUDA stream.

  • options – Optional Options configuration.

apply(
circuit: Circuit,
seed: int | None = None,
stream: int | Stream | None = None,
) None[source]#

Apply a circuit to the Pauli frames.

Parameters:
  • circuit – Circuit object to apply.

  • seed – Optional random seed for measurement randomization. If provided, overrides the seed set during initialization.

  • stream – Optional CUDA stream for the operation.

Raises:

ValueError – If circuit exceeds simulator’s qubit or measurement-row capacity.

classmethod from_circuit(
circuit: Circuit,
num_paulis: int,
**kwargs,
) LeakageFrameSimulator[source]#

Create a LeakageFrameSimulator sized directly from a circuit’s attributes.

Sizes the measurement table as Circuit.num_measurements (which for a leakage circuit already counts measurement gates plus herald leakage readouts), and otherwise behaves like FrameSimulator.from_circuit().

Parameters:
  • circuit – The Circuit whose attributes determine the sizes.

  • num_paulis – Number of Pauli frame samples.

  • **kwargs – Additional keyword arguments forwarded to the constructor. Passing num_qubits, num_measurements, or num_detectors explicitly is rejected to avoid disagreeing with circuit.

Returns:

A simulator sized for circuit.

Return type:

LeakageFrameSimulator

get_leakage_bits(
bit_packed: bool = True,
) ndarray | ndarray[source]#

Retrieve the leakage bit table.

Parameters:

bit_packed – If True, return as bit-packed array (default). If False, unpack bits and return as (num_qubits, num_paulis) array.

Returns:

Leakage flags array; bit (q, shot) is 1 when qubit q is in the leaked subspace for sample shot.

If bit_packed=False, and operands_package is "cupy", the returned array is a view into the simulator state. In other cases, the returned array is a copy of the simulator state.

get_measurement_bits(
bit_packed: bool = True,
) ndarray | ndarray[source]#

Retrieve the measurement table.

Parameters:

bit_packed – If True, return as bit-packed array (default). If False, unpack bits and return as (num_measurements, num_paulis) array.

Returns:

Measurement results array.

If bit_packed=False, and FrameSimulator.operands_package is "cupy", the the returned array is a view into the simulator state. In other cases, the returned array is a copy of the simulator state.

Example

>>> sim = FrameSimulator(2, 1024, num_measurements=1)
>>> measurements = sim.get_measurement_bits(bit_packed=False)
>>> measurements.shape
(1, 1024)
get_pauli_table(
bit_packed: bool = True,
) PauliTable[source]#

Retrieve the X and Z Pauli tables.

Parameters:

bit_packed – If True, return as bit-packed arrays (default). If False, unpack bits and return as (num_qubits, num_paulis) arrays.

Returns:

PauliTable object.

If bit_packed=False, and operands_package is cupy, the returned PauliTable has a view into the simulator state. That is, the contents of PauliTable can be indirectly changed by the simulator. In other cases, the returned PauliTable references a copy of the simulator state.

Example

>>> sim = FrameSimulator(2, 1024)
>>> pauli_table = sim.get_pauli_table(bit_packed=False)
>>> pauli_table.num_qubits
2
>>> pauli_table.num_paulis
1024
get_pauli_xz_bits(
bit_packed: bool = True,
) Tuple[ndarray | ndarray, ndarray | ndarray][source]#

Get the X and Z bits as raw arrays.

Parameters:

bit_packed – If True, return as bit-packed arrays (default). If False, unpack bits and return as (num_qubits, num_paulis) arrays.

Returns:

Tuple of (x_bits, z_bits) as arrays.

The package of arrays is determined by operands_package, which is set by the last call to set_input_tables or the package parameter to constructor.

If bit_packed=False, and package is cupy, the returned arrays are views into the simulator state. In other cases, the returned arrays are copies of the simulator state.

Example

>>> sim = FrameSimulator(2, 1024)
>>> x_bits, z_bits = sim.get_pauli_xz_bits(bit_packed=False)
>>> x_bits.shape
(2, 1024)
>>> z_bits.shape
(2, 1024)
set_input_tables(
x: ndarray | ndarray | None = None,
z: ndarray | ndarray | None = None,
m: ndarray | ndarray | None = None,
l: ndarray | ndarray | None = None,
bit_packed: bool = True,
stream: int | Stream | None = None,
) None[source]#

Set the X, Z, measurement, and leakage tables.

Extends FrameSimulator.set_input_tables() with the leakage table l; see that method for conversion and ownership semantics.

Attributes

device_id#

The device for inputs and outputs.

handle#

Return the underlying C handle object.

operands_package#

The package last used inputs and of returned outputs.

randomize_measurements: bool = True#