qarp.cutting¶
QPD circuit cutting. Public depth: flat — the cut finders, the
quasi-probability decomposition engine, shot post-processing and the per-gate
decompositions. Submodules are private; CuttingPrimitive lives in
qarp.algorithms.
- class qarp.cutting.AutoCutFinder(commands: list, n_qubits: int, max_size_subcircuits: list, penalization_term: float, verbose: bool = True)[source]¶
Bases:
ABC- abstractmethod cut(manual_setting: list | None = None)[source]¶
Find cut locations and partition the circuit into subcircuits.
- Parameters:
manual_setting – Optional list of qubit-index lists, one per subcircuit.
- Returns:
CutterResult
- property cut_qc¶
2q _CutMarker command list (for decomposition iterator).
- property subcircuit_qubits¶
Global qubit indices for each subcircuit.
- property subcircuits¶
List of (commands, n_qubits) tuples for each subcircuit.
- class qarp.cutting.CutterResult(cutter_obj: AutoCutFinder)[source]¶
Bases:
objectResult of a circuit cutting operation.
- class qarp.cutting.EAPartitioning(commands: list, n_qubits: int, max_size_subcircuits: list, verbose: bool = True)[source]¶
Bases:
AutoCutFinder- cut(manual_setting: list | None = None) CutterResult[source]¶
Partition the circuit, returning a CutterResult.
- Parameters:
manual_setting – If given, a list of qubit-index lists (one per subcircuit) that specifies the partition manually.
- class qarp.cutting.PostProcessing(cutter_result: CutterResult, observable: QubitOperator, verbose: bool = True)[source]¶
Bases:
ABC- property coefficients¶
- property experiments¶
- property jobs¶
- class qarp.cutting.QPDDecomposition(cutter_result: CutterResult, observable: QubitOperator, verbose: bool = True, n_shots: int = 1024, experiment_fraction: float | None = None, rng_seed: int | None = None, shot_seed: int | None = None, force_max_number_cuts: bool = False, grouping: GroupingStrategy | None = None)[source]¶
Bases:
PostProcessing- build_experiment_blocks_streaming() Tuple[list, list][source]¶
Stream experiments, build QWC-grouped sub-blocks for the engine.
Does NOT populate self.experiments or self.jobs.
- compute(parallelize: bool = False, symbol_map: dict | None = None, **kwargs) float[source]¶
Execute experiments with QarpSimulator and return the expectation value.
Streams experiments one at a time (Plan 1). Peak memory is O(n_cuts × n_gates + n_subcircuits × local_n_qubits).
- decompose() None[source]¶
Prepare observable metadata. No experiments are materialised.
self.coefficients is populated lazily on the first compute() call.
- reconstruct_statevector(parallelize: bool = False) dict[source]¶
Reconstruct the statevector via shot simulation.
Plan 2: replaces itertools.product with incremental subcircuit folding. Peak memory is O(2^n_full_qubits) instead of O(outcomes^n_subcircuits). Streams experiments (Plan 1) — self.jobs is never required.
- class qarp.cutting.Reconstructer(commands: list, n_qubits: int)[source]¶
Bases:
object- reconstruct_delete_gates(to_delete: list) tuple[list, int][source]¶
Remove all 2q gates between qubit pairs listed in to_delete.
- Parameters:
to_delete – List of [q0, q1] pairs; gates on these pairs are removed.
- Returns:
pruned command list and number of removed gates.
- Return type:
(new_commands, n_cuts)
- static reconstruct_filter_qubits(commands: list, n_qubits: int, qubits: list) tuple[list, int][source]¶
Filter a command list to only include commands acting on qubits in the subset.
Qubit indices are remapped to be 0-based local indices within the subset. QPD Measure commands are kept and their cbit indices are re-assigned sequentially (0, 1, …) in the order they are encountered.
- Parameters:
commands – Command list (may contain _CutMarker objects — they are skipped).
n_qubits – Total qubit count (used for validation).
qubits – Subset of qubit indices to include.
- Returns:
(filtered_commands, local_n_qubits)
- reconstruct_swap_gates_by_customs(to_delete: list) tuple[list, list, int, dict][source]¶
Replace 2q gates at cut positions with _CutMarker sentinels.
Returns two variants of the cut circuit: a 1q-representation (each cut gate replaced by two single-qubit _CutMarkers at [q0] and [q1]) used for qubit filtering, and a 2q-representation (one marker spanning [q0, q1]) used for the decomposition iterator.
- Parameters:
to_delete – List of [q0, q1] pairs to cut.
- Returns:
cut_cmds_1q: command list where each cut 2q gate is replaced by two single-qubit_CutMarkerobjects (one per qubit).cut_cmds_2q: command list where each cut 2q gate is replaced by one two-qubit_CutMarkerobject (used in_iterate_experiment).n_cuts: number of cuts performed.cut_names: dict{name: (gate_type_str, params)}for each cut.
- Return type:
A
(cut_cmds_1q, cut_cmds_2q, n_cuts, cut_names)tuple
- qarp.cutting.check_cut_budget(n_cuts: int, *, force: bool = False) None[source]¶
Reject cut counts past
config.max_number_of_cuts.Every cut multiplies the experiment count by 6 (6^n_cuts total) — the guard lives here, in
qarp.cutting, so both the engine-integrated and the standalone execution paths consult it.
- qarp.cutting.decompose_cx(prefix: list, n_qubits: int, idx: list, idx_to_be_used_bit: ndarray) tuple[list, ndarray][source]¶
QPD decomposition of a CX gate into 6 single-qubit experiments.
- Parameters:
prefix – Command list accumulated before this cut.
n_qubits – Qubit count of the circuit.
idx – [ctrl_qubit, tgt_qubit].
idx_to_be_used_bit – Array of 6 ints; idx_to_be_used_bit[i] is the next available QPD cbit index for experiment i.
- Returns:
(experiments, coefficients) where experiments is a list of 6 command lists.
- qarp.cutting.decompose_rzz(prefix: list, n_qubits: int, idx: list, idx_to_be_used_bit: ndarray, parameter) tuple[list, ndarray][source]¶
QPD decomposition of an RZZ gate.
- Parameters:
prefix – Command list accumulated before this cut.
n_qubits – Qubit count.
idx – [q0, q1].
idx_to_be_used_bit – Next available QPD cbit per experiment.
parameter – RZZ rotation angle in radians (qarpx convention). May be a float or sympy.Symbol for parametric circuits.
- Returns:
(experiments, coefficients)