LocalFoldPass

class LocalFoldPass(scale_factor, selection='random', exclude=None, rng=None)[source]

Bases: TransformationPass

Per-gate folding with fractional scale-factor support.

Each unitary gate G is replaced by G · (G† · G)^k. For a target scale factor s on a circuit with d unitary gates:

k         = (s - 1) // 2             # base folds applied to every gate
remainder = s - (1 + 2k)
n         = round(remainder · d / 2) # gates receiving one extra fold

n gates are then selected for the extra fold according to selection, yielding a post-transform gate count of d · (1 + 2k) + 2n and an effective scale factor of 1 + 2k + 2n/d. Non-unitary instructions (measure, reset, barrier) are skipped. Mirrors Mitiq’s fold_gates_from_left / _from_right / _at_random selection strategies.

Excluded gates (see exclude) are removed from the candidate pool before the k / n arithmetic. A gate is excluded if its op name matches any entry in exclude or its arity matches one of the shorthands ("single", "double", "triple").

The requested scale_factor therefore applies to the foldable subset only: excluded gates appear once in the output and the circuit-wide noise scale is effectively lower than requested. This matches Mitiq’s fold_all exclude semantics.

The achievable scales form a grid of granularity 2/d — for small d the effective scale may differ from the request. Use effective_scale() to query the realised value. Example, for a 4-gate circuit:

requested s | k | n | size | effective s
----------------------------------------
1.5         | 0 | 1 |  6   | 1.5
2.0         | 0 | 2 |  8   | 2.0
3.0         | 1 | 0 | 12   | 3.0
3.5         | 1 | 1 | 14   | 3.5

Complements GlobalFoldPass for fine-grained noise scaling on deep circuits where global folding is too coarse. Unlike GlobalFoldPass, this pass introduces randomness at fractional scales (which n gates receive the extra fold) — pass a fixed rng or use selection="from_left" / "from_right" for deterministic output.

Parameters:
  • scale_factor (float) – Real number ≥ 1. 1.0 is a pass-through.

  • selection (Literal['random', 'from_left', 'from_right']) – Which n gates receive the extra fold: "random" (default) — uniformly sampled without replacement; "from_left" — the first n gates in topological order; "from_right" — the last n gates in topological order.

  • exclude (set[str] | None) – Optional set of op names ("h", "cx", …) and/or arity shorthands ("single", "double", "triple") to skip during folding. Unknown names match nothing (harmless).

  • rng (Random | None) – Optional random.Random for reproducible selection when selection="random". Ignored otherwise. When None, uses a fresh random.Random.

Raises:

ValueError – If scale_factor < 1 or selection is unknown.

Methods Summary

effective_scale(dag)

Scale factor actually realised on dag (may differ from the requested value when the foldable pool is too small for the fractional part to round cleanly).

run(dag)

Fold dag in place and return the mutated DAG.

Methods Documentation

effective_scale(dag)[source]

Scale factor actually realised on dag (may differ from the requested value when the foldable pool is too small for the fractional part to round cleanly).

Return type:

float

run(dag)[source]

Fold dag in place and return the mutated DAG.

The input is consumed — callers that need the original should deepcopy before invoking the pass. Matches the standard Qiskit TransformationPass contract.

Return type:

DAGCircuit

Returns:

The same dag object, mutated to contain the folded circuit.