qolumbina.utils.execution_framework module#

The top-level interface for quantum system simulation. The current version has the following limitations:

  1. Only the quantum programs executing a unitary operation \(U\) are supported. This means that the circuit under test cannot include classical bits or mid-circuit measurements.

  2. Parameterized quantum gates are not supported for state initialization, such as \(R_X(\theta)\) being excluded.

  3. The measurement basis is currently limited to Pauli bases (\(X\), \(Y\), \(Z\)) or identity (\(I\), meaning no measurement).

These constraints are planned to be relaxed in the future development.

class AnalyticIdealSimulation(tested_subroutine, init_state=None, init_qubits='all', backend='statevector', target_qubits=None)[source]#

Bases: object

Execute a quantum program on an analytic backend without quantum measurements.

Parameters:
  • tested_subroutine (Callable[[], QuantumCircuit]) – A callable that constructs and returns the QuantumCircuit under test.

  • init_state (list | None) –

    Initial state specification for all qubits. If None, all qubits are initialized to \(\ket{0}\).

    See also

    qolumbina.utils.state_initialization module for input types for state initialization.

  • init_qubits (Literal['all'] | list[int] | None) –

    Specifies which qubits to allocate and initialize according to init_state. The default value is “all”. Use None to skip explicit initialization entirely; this is only valid when init_state is also None.

    • "all":

      All qubits are initialized. This means that the number of qubits for the entire circuit is determined by init_state.

    • list[int]:

      Only the qubits with the specified indices are initialized according to init_state. In this case, the number of qubits for the entire circuit automatically matches that of the circuit under test.

    • None:

      No qubits are explicitly initialized. The system qubits keep the default \(\ket{0}\) state. This cannot be combined with init_state.

    Example

    init_qubits=[0, 2] means that only qubits with indices 0 and 2 are initialized according to init_state, while other qubits are initialized to \(\ket{0}\) by default.

  • backend (str) – Backend name for circuit execution. Supported analytic backends include "statevector", "density_matrix", and "unitary".

  • target_qubits (list[int] | None) – Optional list of qubit indices for which the analytic result is extracted. This is only applicable for the state vector backend. If None, the full state vector is returned.

Input validation and errors

The following cases are checked before or during input-state preparation.

  • Explicitly skipping initialization: init_qubits=None means no qubits are explicitly initialized. It is valid only when init_state is None; otherwise ValueError is raised, because init_state would have no target qubits to initialize.

  • Pure-state initialization: When init_qubits is "all" or list[int], validation is delegated to PureStateInitialization. It may raise TypeError when init_state is not a supported list or init_qubits is neither "all" nor list[int]. It may raise ValueError when init_state is empty, contains an undefined single-qubit gate, has a gate-list length that does not match init_qubits, has a state-vector dimension that does not match the selected qubits, or violates the generated circuit-width constraints.

Note

Regarding the test output, we can access the following attributes after execution:

self.entire_qc (QuantumCircuit)

The full QuantumCircuit executed (including initialization, tested subroutine).

self.test_output (Any)

An analytic result, which could be a state vector, density matrix, or unitary matrix.

property init_qubits: Literal['all'] | list[int] | None#
property init_state: list#
class QuantumSystemSimulation(tested_subroutine, init_state=None, init_qubits='all', input_mode='pure', meas_mapping=None, meas_basis=None, shots=1024, backend='ideal', noise_model=None, if_noisy=False, random_seed=None, mixed_state_angles=None)[source]#

Bases: object

Execute a quantum program on a shot-based simulated quantum computer.

This class builds an execution circuit around a circuit under test:

  1. prepare an input state on selected system qubits;

  2. compose the quantum circuit returned by tested_subroutine;

  3. apply Pauli-basis measurements;

  4. execute the complete circuit on the selected backend.

The circuit returned by tested_subroutine defines the system-qubit register. In pure-state mode, init_qubits may select only a subset of those system qubits for explicit input-state preparation; all other system qubits remain in \(\ket{0}\). In mixed-state mode, the selected system qubits are prepared through appended control/environment qubits, while the circuit under test still acts only on the original system qubits.

Parameters:
  • tested_subroutine (Callable[[], QuantumCircuit]) – A callable that constructs and returns the QuantumCircuit under test.

  • init_state (list[str] | list[float] | list[complex] | None) –

    Initial state specification for the selected input qubits. If None, the selected input qubits are initialized to \(\ket{0}\).

    In pure-state mode, the meaning of init_state depends on init_qubits. If init_qubits="all", init_state describes every system qubit. If init_qubits is a list, init_state describes only those listed qubits, matched by position. For example, for a 5-qubit circuit, using init_state=["x", "x"] and init_qubits=[0, 1] prepares only system qubits q0 and q1 as \(\ket{11}\); the remaining system qubits q2, q3, and q4 remain \(\ket{0}\) unless changed by the circuit under test.

    See also

    qolumbina.utils.state_initialization module for input types for state initialization.

  • init_qubits (Literal['all'] | list[int] | None) –

    Specifies which system qubits need input-state preparation. The default value is “all”. Use None to skip explicit input-state preparation; this is only valid when init_state is also None.

    • "all":

      Pure mode: all qubits are initialized according to init_state. Mixed mode: if mixed_state_angles is provided, the targets default to the low m system qubits, where m is the number of angles; otherwise all system qubits are mixed-state targets.

    • list[int]:

      Pure mode: only these qubits are initialized according to init_state. Mixed mode: these are the system target qubits for mixed-state preparation.

    • None:

      No qubits are explicitly initialized. The system qubits keep the default \(\ket{0}\) state. This cannot be combined with init_state.

    Example

    init_qubits=[0, 2] means that only qubits with indices 0 and 2 are prepared, while other system qubits remain initialized to \(\ket{0}\) by default.

  • input_mode (Literal['pure', 'mixed']) – Input-state preparation mode. "pure" preserves the original init_state / init_qubits behavior. "mixed" uses quantum-control qubits and mixed_state_angles to prepare separable mixed states on the system qubits selected by init_qubits.

  • meas_mapping (dict[int, int] | None) –

    Measurement mapping from qubit index to classical bit index, which impacts the analysis of test output. Default value is None. If both meas_mapping and meas_basis are None, every default measured system qubit is measured in Pauli-Z basis and mapped correspondingly, meaning that qubit with index \(i\) is measured to classical bit with index \(i\). If meas_mapping is provided while meas_basis is None, only the qubits in meas_mapping are measured, all in Pauli-Z basis. In mixed-state mode, appended control/environment qubits are internal to input preparation and are not included in this default output mapping.

    Example

    meas_mapping={0: 1, 2: 0} means that qubit 0 is measured to classical bit 1, while qubit 2 is measured to classical bit 0.

    See also

    qolumbina.utils.QuantumMeasurement and qolumbina.utils.QuantumMeasurement.measure() for the complete measurement-resolution rules and examples that control meas_mapping independently from meas_basis.

  • meas_basis (list[str] | dict[int, str] | None) –

    Measurement basis. Can be "x", "y", "z" or "i" (identity, meaning no measurement). A list[str] is dense and must cover all qubits in the circuit being measured. A dict[int, str] is sparse: its keys are qubit indices and unspecified qubits are treated as "i". Default value is None. If both meas_basis and meas_mapping are None, all default measured system qubits are measured in Pauli-Z basis. In pure-state mode this means every system qubit in the circuit under test. In mixed-state mode this means every original system qubit, not the appended control/environment qubits.

    Example

    meas_basis=["x", "z", "y"] means that qubit 0 is measured in Pauli-X basis, qubit 1 is measured in Pauli-Z basis, and qubit 2 is measured in Pauli-Y basis.

    To measure only a subset of qubits, either use "i" for qubits that should not be measured, or provide a sparse dict. When meas_mapping is omitted, classical bits are assigned contiguously in ascending qubit-index order. For example, for a 5-qubit circuit, meas_basis=["z", "z", "i", "i", "i"] or meas_basis={0: "z", 1: "z"} measures only q0 and q1 and maps them to c0 and c1. If both meas_basis and meas_mapping are provided, their measured qubit sets must match exactly; otherwise a ValueError is raised.

    See also

    qolumbina.utils.QuantumMeasurement and qolumbina.utils.QuantumMeasurement.measure() for the complete measurement-resolution rules and examples that control meas_basis independently from meas_mapping.

  • shots (int) – Number of shots per circuit execution. Default value is 1024.

  • backend (str) –

    Backend name for circuit execution.

    See also

    qolumbina.utils.backend_execution module for supported backends.

  • noise_model (NoiseModel | None) – Optional custom NoiseModel.

  • if_noisy (bool) – Whether to enable noise when using fake backend.

  • random_seed (int | None) – Optional random seed for simulator to ensure reproducibility.

  • mixed_state_angles (list[float] | None) –

    Optional Ry angles for separable quantum-control qubits used to prepare a mixed-state input when input_mode="mixed". Each angle prepares one extra control qubit as Ry(theta)|0> and then controls one target system qubit. If None in mixed mode, all target angles default to pi / 2, which is equivalent to Hadamard probabilities.

    In mixed-state mode, system qubits keep their original indices 0..n-1. Target qubits are selected by init_qubits and can be any distinct valid system-qubit indices. Control qubits are appended after the maximum system-qubit index, namely n..n+m-1. Control qubits are not measured into the test output; they only act as an environment/purification for the target system qubits.

    Example

    To prepare the single-qubit mixed state \(\rho = \cos^2(\theta / 2)\lvert 0\rangle\langle 0\rvert + \sin^2(\theta / 2)\lvert 1\rangle\langle 1\rvert\) on system qubit 0, use one appended control qubit prepared by Ry(theta) and entangled with the target:

    sim = QuantumSystemSimulation(
        tested_subroutine=lambda: QuantumCircuit(1),
        input_mode="mixed",
        mixed_state_angles=[theta],
        init_qubits=[0],
        shots=1024,
        backend="ideal",
    )
    

    For a two-qubit separable mixed input such as \(\rho = \rho_0 \otimes \rho_2\) on non-contiguous system qubits 0 and 2, provide one angle per target qubit:

    sim = QuantumSystemSimulation(
        tested_subroutine=lambda: QuantumCircuit(3),
        input_mode="mixed",
        mixed_state_angles=[theta_0, theta_2],
        init_qubits=[0, 2],
        shots=1024,
        backend="ideal",
    )
    

Mode-specific defaults

input_mode="pure"

Pure-state mode is the default mode. The input-related defaults are:

  • init_state=None: initialize the selected system qubits to \(\ket{0}\).

  • init_qubits="all": initialize every system qubit according to init_state.

  • init_qubits=None: skip explicit input-state preparation; all system qubits remain in their default \(\ket{0}\) state.

  • mixed_state_angles=None: no mixed-state preparation is used.

In this mode, mixed_state_angles must remain None. The resolved prepared system qubits are stored in self.input_preparation_qubits.

input_mode="mixed"

Mixed-state mode prepares selected system qubits through appended quantum-control qubits. The input-related defaults are:

  • init_state=None: required. System targets are prepared by mixed-state preparation, not by the pure-state initializer.

  • init_qubits="all" and mixed_state_angles=None: all system qubits are mixed-state targets and all angles default to pi / 2.

  • init_qubits="all" and mixed_state_angles is a list of length m: the mixed-state targets default to low-index system qubits [0, 1, ..., m - 1].

  • init_qubits is list[int] and mixed_state_angles=None: the listed qubits are mixed-state targets and all angles default to pi / 2.

  • init_qubits is list[int] and mixed_state_angles is a list: the two lists are matched position-wise, so mixed_state_angles[i] prepares init_qubits[i].

In this mode, the resolved target system qubits are stored in self.input_preparation_qubits and the appended control qubits are stored in self.mixed_state_control_qubits. Control qubits are not measured into self.test_output.

Measurement output and bit-string order

self.test_output stores the shot counts returned by Qiskit, so the keys follow Qiskit’s classical-bit string convention. The leftmost character corresponds to the highest displayed classical bit and the rightmost character corresponds to classical bit 0.

With the default measurement mapping q_i -> c_i, this means that a 5-qubit circuit whose measured state is q4 q3 q2 q1 q0 = 0 0 0 1 1 appears in self.test_output as "00011", not "11000". This convention matters when writing expected outputs for tests: the bit string is displayed in classical register order, while qubit indices are commonly discussed from low to high.

Example:

sim = QuantumSystemSimulation(
    tested_subroutine=lambda: QuantumCircuit(5),
    init_state=["x", "x"],
    init_qubits=[0, 1],
    meas_basis=None,
    shots=1024,
    backend="ideal",
)

# Empty circuit under test; q0 and q1 are one, q2..q4 are zero.
# The expected count key is "00011" under the default q_i -> c_i
# measurement mapping.
assert sim.test_output == {"00011": 1024}

If only low-index qubits are relevant, measure only those qubits to make the output width explicit:

sim = QuantumSystemSimulation(
    tested_subroutine=lambda: QuantumCircuit(5),
    init_state=["x", "x"],
    init_qubits=[0, 1],
    meas_basis=["z", "z", "i", "i", "i"],
    meas_mapping={0: 0, 1: 1},
    shots=1024,
    backend="ideal",
)

assert sim.test_output == {"11": 1024}

Input validation and errors

The following cases are checked before or during input-state preparation. They are grouped by configuration area so callers can map an exception back to the invalid input quickly.

  • Mode selection: ValueError is raised if input_mode is not "pure" or "mixed".

  • Explicitly skipping initialization: init_qubits=None means no qubits are explicitly initialized. It is valid only when init_state is None and mixed_state_angles is None. Otherwise ValueError is raised, because those inputs would have no target qubits to initialize.

  • Pure-state mode: mixed_state_angles is invalid when input_mode="pure" and raises ValueError. If pure-state preparation is used, the delegated PureStateInitialization validation may also raise: TypeError when init_state is not a supported list or init_qubits is neither "all" nor list[int]; ValueError when init_state is empty, contains an undefined single-qubit gate, has a gate-list length that does not match init_qubits, has a state-vector dimension that does not match the selected qubits, or violates the generated circuit-width constraints.

  • Mixed-state mode: init_state is invalid when input_mode="mixed" and raises ValueError. Mixed-state target resolution may also raise: ValueError when mixed_state_angles is provided but is not a non-empty list, when init_qubits is an empty list, when the angle list and explicit target-qubit list have different lengths, when target qubits are duplicated, or when any target qubit is outside the system-qubit range; TypeError when mixed_state_angles contains non-real values or init_qubits contains non-integer values.

Note

Regarding the test output, we can access the following attributes after execution:

self.entire_qc (QuantumCircuit)

The full QuantumCircuit executed (including initialization, tested subroutine, measurement).

self.transpiled_qc (QuantumCircuit)

The transpiled circuit under test, excluding state initialization and measurement. In pure-state mode, explicit state-preparation gates are excluded. In mixed-state mode, this is the system circuit only.

The following properties can be accessed for the transpiled circuit:

transpiled_cut_width, transpiled_cut_size, transpiled_cut_depth.

self.transpiled_execution_qc (QuantumCircuit)

The full transpiled QuantumCircuit executed on the backend, including initialization, tested subroutine, control qubits for mixed-state preparation, and measurement operations.

The following properties can be accessed for the full execution circuit: transpiled_execution_width, transpiled_execution_size, transpiled_execution_depth.

self.test_output (dict[str, int])

Measurement counts as a dictionary. e.g., {'00': 512, '11': 512}

property has_mixed_state_configuration: bool#
property init_qubits: Literal['all'] | list[int] | None#
property init_state: list#
property meas_basis: list[str] | dict[int, str]#
property meas_mapping: dict[int, int]#
property transpiled_cut_depth: int#

Depth of the quantum-gate DAG (a.k.a. depth) of the transpiled circuit under test.

Compared to qc.depth for qc with QuantumCircuit type, only quantum gates are counted for the depth calculation, which should exclude measurement and barrier.

property transpiled_cut_size: int#

Number of quantum gates (a.k.a. size) of the transpiled circuit under test.

Compared to qc.size for qc with QuantumCircuit type, only quantum gates are counted, meaning that measurement and barrier are excluded.

property transpiled_cut_width: int#

Number of qubits (a.k.a. width) of the transpiled circuit under test.

Compared to qc.width for qc with QuantumCircuit type, classical bits are excluded.

property transpiled_execution_depth: int#

Quantum-gate depth of the full transpiled execution circuit.

Measurement and barrier operations are excluded, but initialization, mixed-state preparation, basis-change gates, and the circuit under test are included.

property transpiled_execution_size: int#

Number of quantum gates of the full transpiled execution circuit.

Measurement and barrier operations are excluded, but initialization, mixed-state preparation, basis-change gates, and the circuit under test are included.

property transpiled_execution_width: int#

Number of qubits of the full transpiled execution circuit.

In mixed-state mode, this includes both system qubits and appended control/environment qubits.