uniqc.calibration.xeb.parallel_cz module

Parallel-CZ XEB calibration: chip-pre-flight 2-qubit gate fidelity.

This module implements a generic parallel cross-entropy benchmarking protocol useful as a pre-flight chip characterization step (i.e. before running any larger experiment that depends on per-pair CZ fidelity).

Protocol

For a fixed CZ pattern (a matching of disjoint qubit pairs):

cycle = U3(haar) on every region qubit, then CZ on every pair in the pattern

Repeat for depth cycles, then measure all region qubits. Sample shots bitstrings per circuit and K random circuit instances per (pattern, depth) combination.

For each pair in the matching, the full N-qubit circuit factorises as a tensor product over pairs (1q ops are local; CZs are between disjoint pairs). The 2-qubit marginal distribution on each pair is exactly the 2-qubit pure-state distribution of that pair’s sub-circuit, so we can score every pair independently using its 2-qubit F_XEB(d). Fitting F(d) = beta · alpha^d per pair yields the per-cycle CZ fidelity alpha.

Public API

class uniqc.calibration.xeb.parallel_cz.PairCircuitFit(record_id, pair, pattern_idx, depth, instance, F_XEB, F_XEB_sigma, shots)[source]

Bases: object

Per-(record, pair) F_XEB computed on the 2-qubit marginal.

Parameters:
F_XEB: float
F_XEB_sigma: float
depth: int
instance: int
pair: tuple[int, int]
pattern_idx: int
record_id: str
shots: float
class uniqc.calibration.xeb.parallel_cz.PairDecay(pair, n_points, alpha, beta, log_alpha, log_beta, sigma_log_alpha, sigma_log_beta, log_residual_std)[source]

Bases: object

Per-pair weighted log-LS fit F(d) = beta · alpha^d.

Parameters:
alpha: float
beta: float
log_alpha: float
log_beta: float
log_residual_std: float
n_points: int
pair: tuple[int, int]
sigma_log_alpha: float
sigma_log_beta: float
class uniqc.calibration.xeb.parallel_cz.ParallelCZBenchmarker(adapter, shots=5000, cache_dir=None, seed=None, query_timeout=600.0, query_interval=2.0)[source]

Bases: object

End-to-end parallel-CZ XEB runner.

Parameters:
  • adapter (QuantumAdapter) – A QuantumAdapter supporting submit/query (and optionally submit_batch/query_batch). DummyAdapter is also supported via its simulate_pmeasure fast path.

  • shots (int) – Number of shots per circuit.

  • cache_dir (str | None) – If supplied, per-pair XEBResult objects are saved here under the standard naming convention.

  • seed (int | None) – Master seed for the corpus RNG.

  • query_timeout (float) – Per-circuit / per-batch poll timeout (seconds).

  • query_interval (float) – Poll interval (seconds).

run(region_qubits, patterns, depths, instances=20)[source]

Build a corpus, execute it, fit per-pair decays.

Returns a dict with keys:
  • corpus: list[ProbeCircuit]

  • counts_by_record: dict[record_id, counts]

  • per_pair_fits: list[PairCircuitFit]

  • per_pair_decays: dict[pair, PairDecay]

  • per_pair_results: dict[pair, XEBResult]

Parameters:
Return type:

dict

class uniqc.calibration.xeb.parallel_cz.ProbeCircuit(circuit, schedule, pattern_idx, pattern, depth, instance, record_id)[source]

Bases: object

One built circuit + its replayable schedule and metadata.

Parameters:
circuit: Any
depth: int
instance: int
pattern: tuple[tuple[int, int], ...]
pattern_idx: int
record_id: str
schedule: Schedule
class uniqc.calibration.xeb.parallel_cz.Schedule(region_qubits, measured_qubits, cycles, seed)[source]

Bases: object

Per-cycle U3 angles and CZ pattern for a single XEB instance.

cycles is a tuple of (angles_per_qubit, pattern) pairs. angles_per_qubit is ordered the same as region_qubits.

Parameters:
cycles: tuple[tuple[tuple[tuple[float, float, float], ...], tuple[tuple[int, int], ...]], ...]
property depth: int
measured_qubits: tuple[int, ...]
region_qubits: tuple[int, ...]
seed: int
uniqc.calibration.xeb.parallel_cz.build_parallel_cz_xeb_circuit(region_qubits, pattern, depth, *, seed=0, instance=0)[source]

Build one parallel-CZ XEB probe circuit.

Each cycle is U3(haar) on every region qubit, then CZ on every pair in pattern. Single-qubit angles are drawn from a deterministic RNG seeded by (seed, depth, instance, pattern_id) so different patterns get statistically independent fillings.

Parameters:
Return type:

ProbeCircuit

uniqc.calibration.xeb.parallel_cz.build_parallel_cz_xeb_corpus(region_qubits, patterns, depths, instances, *, seed=2026)[source]

Build the full XEB corpus.

Returns len(patterns) * len(depths) * instances probes. Within a single (pattern, depth) slot, instances independent random U3 fillings are emitted.

Parameters:
Return type:

list[ProbeCircuit]

uniqc.calibration.xeb.parallel_cz.fit_pair_decays(fits, *, log_floor=0.0001)[source]

Per-pair weighted log-LS fit of F(d) = beta · alpha^d.

Drops circuits where F <= log_floor (cannot take log). Weights are 1/sigma_logF^2 with sigma_logF = sigma_F / F.

Parameters:
Return type:

dict[tuple[int, int], PairDecay]

uniqc.calibration.xeb.parallel_cz.pair_ideal_probs(schedule, pair)[source]

Build and simulate the 2-qubit subcircuit on pair.

Only the cycle’s 1q ops on the pair’s two qubits and the CZ on that pair (when present in the cycle’s pattern) are kept. Returns a length-4 probability vector indexed as (bb << 1) | ba where ba is pair[0]’s outcome and bb is pair[1]’s — i.e. the index has bit 0 = pair[0], bit 1 = pair[1], matching the layout produced by pair_marginal_counts().

Parameters:
Return type:

ndarray

uniqc.calibration.xeb.parallel_cz.pair_marginal_counts(counts, measured_qubits, pair)[source]

Marginalise full N-qubit counts to a 2-qubit pair.

measured_qubits defines the bit positions of the count keys: the integer index of an outcome has bit ``k`` (LSB+k) = state of the ``k``-th measured qubit. This matches Simulator’s simulate_pmeasure ordering when format(idx, f'0{n}b') is used to render the count key as a binary string.

Returns counts indexed by (bb << 1) | ba where ba (bit 0, LSB) is the measured outcome on pair[0] and bb (bit 1) is the outcome on pair[1]. This matches the layout produced by the 2-qubit reference simulation in pair_ideal_probs().

Parameters:
Return type:

dict[int, int]

uniqc.calibration.xeb.parallel_cz.per_pair_F_XEB(records, pairs, *, counts_by_record=None)[source]

Compute per-pair F_XEB for every (record, pair) combination.

Each record must carry a Schedule (under key "schedule") plus record_id, pattern_idx, depth, instance. Counts may be embedded under "counts" or supplied via counts_by_record (keyed by record_id).

Uses the normalised (un-biased at small N) linear XEB estimator

F = (<P_id>_meas - 1/D) / (Σ P_id² - 1/D)

which equals 1 for the noiseless circuit and 0 for a fully depolarised pair, regardless of depth-dependent deviations from Porter–Thomas. Returns one PairCircuitFit per (record, pair) where the pair is in the record’s measured_qubits.

Parameters:
Return type:

list[PairCircuitFit]