guppyalgos.primitives.measurement

Measurement helpers for sampling, discarding, statistics, and Pauli estimates.

Functions

discard_array_zero(qs)

Discard qubit array with panic if not in 0.

discard_nested_array(nested_qregs)

Discard all qubits in a nested array of registers.

discard_stack(qs)

Discard all qubits in a stack.

discard_stack_zero(qs)

Discard all qubits in a stack with panic if not in 0.

discard_zero(q)

Discard qubit with panic if not in 0.

estimate_expectation_from_binary_samples(samples)

Estimate the mean of binary measurement samples.

estimate_pauli_observable_expectation_from_binary_samples(...)

Estimate statistics for a real (hermitian) Pauli observable from binary samples.

estimate_pauli_observable_expectation_from_bitstrings(...)

Estimate a real Pauli observable from full-register bitstrings.

iqft_and_measure(qs)

Dynamic inverse QFT followed by measurement.

make_direct_measure_pauli(...)

Build a full-register measurement program.

make_direct_measure_pauli_simple(...)

Build a direct measurement program with per-term Z-basis rotations.

make_hadamard_test_pauli(pauli_string, size)

Return a Hadamard-test program specialized to a Pauli string.

measure_stack(qs)

Measure all qubits in a stack.

qft_and_measure(qs)

Dynamic QFT followed by measurement.

Classes

BinaryShotEstimate(expectation, variance, ...)

Frozen dataclass holding empirical statistics from finite shots.

PauliObservableExpectationEstimate(...)

Statistics for a real Pauli observable.

class guppyalgos.primitives.measurement.BinaryShotEstimate(expectation, variance, standard_error, shots, positive_shots, negative_shots)

Frozen dataclass holding empirical statistics from finite shots.

A single two-outcome observable is assumed.

For N shots with n_plus false outcomes and n_minus true outcomes, the sample mean is

mu_hat = (n_plus - n_minus) / N

and the estimated variance of the sample mean is

var_hat = (1 - mu_hat**2) / N.

expectation: float
negative_shots: int
positive_shots: int
shots: int
standard_error: float
variance: float
class guppyalgos.primitives.measurement.PauliObservableExpectationEstimate(expectation, variance, standard_error, term_estimates)

Statistics for a real Pauli observable.

For \(H = \sum_j c_jP_j\), stores \(\hat E[H]\), propagated variance \(\widehat{\operatorname{Var}}(H)\), and per-term estimates.

expectation: float
print_terms(file=None)

Print a formatted table of per-term estimates.

Return type:

None

standard_error: float
term_estimates: dict[str, BinaryShotEstimate]
variance: float
guppyalgos.primitives.measurement.discard_array_zero(qs)

Discard qubit array with panic if not in 0.

guppyalgos.primitives.measurement.discard_nested_array(nested_qregs)

Discard all qubits in a nested array of registers.

Parameters:
  • nested_qregs – Nested array of qubit registers to discard.

  • n_qubits_per_register (nat) – Number of qubits in each register.

  • n_registers (nat) – Number of registers in the nested array.

guppyalgos.primitives.measurement.discard_stack(qs)

Discard all qubits in a stack.

Parameters:

qs (Stack[qubit, n_work] @ owned) – The stack of qubits to discard.

guppyalgos.primitives.measurement.discard_stack_zero(qs)

Discard all qubits in a stack with panic if not in 0.

Parameters:

qs (Stack[qubit, n_work] @ owned) – The stack of qubits to discard.

guppyalgos.primitives.measurement.discard_zero(q)

Discard qubit with panic if not in 0.

guppyalgos.primitives.measurement.estimate_expectation_from_binary_samples(samples)

Estimate the mean of binary measurement samples.

The measured outcomes are mapped to a +/- 1 random variable with False -> +1 and True -> -1.

The estimate also includes the variance of the sample mean. The returned variance is estimated from the observed samples, so the corresponding uncertainty is sqrt(variance).

Return type:

BinaryShotEstimate

guppyalgos.primitives.measurement.estimate_pauli_observable_expectation_from_binary_samples(operator, pauli_samples)

Estimate statistics for a real (hermitian) Pauli observable from binary samples.

The operator must be a zixy.qubit.pauli.RealTermSum, i.e. a sum of Pauli strings with real coefficients. Each term label in pauli_samples should match the string form of the Pauli term being sampled. Zero- coefficient terms are treated as no-ops and do not require sample data. Additional keys in pauli_samples are allowed and ignored, which lets callers reuse a broader sample collection than the estimator needs.

For H = sum_j c_j P_j, this returns the estimated mean

E_hat(H) = sum_j c_j * mu_hat_j

and the propagated variance

Var_hat(H) = sum_j c_j**2 * var_hat_j.

Return type:

PauliObservableExpectationEstimate

guppyalgos.primitives.measurement.estimate_pauli_observable_expectation_from_bitstrings(operator, pauli_bitstrings)

Estimate a real Pauli observable from full-register bitstrings.

pauli_bitstrings maps each non-identity term to either a sequence of full-register bitstrings, one per shot, or a histogram mapping bitstring tuples to non-negative counts. For \(P_j\), each shot becomes \((-1)^{\oplus_{k\in\operatorname{supp}(P_j)} b_k}\) before applying the binary estimator. Variance propagation assumes independent term samples; grouped settings require covariance terms.

Return type:

PauliObservableExpectationEstimate

guppyalgos.primitives.measurement.iqft_and_measure(qs)

Dynamic inverse QFT followed by measurement.

This implements the dynamic inverse QFT+measurement (iQFT+M) protocol described in [1].

Mid-circuit measurements and classical feed-forward replace the controlled-phase gates of the standard unitary iQFT. The protocol requires one adaptive measurement/feed-forward round per qubit, resulting in \(n\) rounds and \(Theta(n^2)\) classically conditioned single-qubit phase corrections, rather than \(\Theta(n^2)\) controlled-phase gates required by the standard unitary iQFT.

This operation is not a unitary iQFT and does not produce a reusable transformed quantum state. All qubits in qs are measured, and the measurement results are returned in little-endian order. The qs register should be discarded or reset after this operation.

References

[1] Bäumer, E. et al (2024). Quantum Fourier Transform Using Dynamic Circuits. Phys. Rev. Lett. 133, 150602.

Parameters:

qs – Qubit register to perform the iQFT on.

Returns:

Measurement results in logical little-endian order.

guppyalgos.primitives.measurement.make_direct_measure_pauli(measurement_structure_function, size)

Build a full-register measurement program.

measurement_structure_function prepares the register for Z-basis measurement. The returned program emits the bitstring on "bitstring" and consumes the register.

Return type:

GuppyFunctionDefinition[(array[qubit, TypeVar(n_q, bound= nat)], ), None]

guppyalgos.primitives.measurement.make_direct_measure_pauli_simple(pauli_string, size)

Build a direct measurement program with per-term Z-basis rotations.

Return type:

GuppyFunctionDefinition[(array[qubit, TypeVar(n_q, bound= nat)], ), None]

guppyalgos.primitives.measurement.make_hadamard_test_pauli(pauli_string, size)

Return a Hadamard-test program specialized to a Pauli string.

This Python factory returns a Guppy-compiled program that allocates the ancilla internally, applies the Hadamard-test primitive for operator kickback, and records the ancilla outcome in the ancilla result stream. Repeated shots estimate the expectation value of the observable associated with pauli_string.

Return type:

GuppyFunctionDefinition[(array[qubit, TypeVar(n_q, bound= nat)], ), None]

guppyalgos.primitives.measurement.measure_stack(qs)

Measure all qubits in a stack.

Qubits are returned in the order they are popped off the stack.

Parameters:

qs (Stack[qubit, n_work] @ owned) – The stack of qubits to measure.

guppyalgos.primitives.measurement.qft_and_measure(qs)

Dynamic QFT followed by measurement.

This implements the dynamic QFT+measurement (QFT+M) protocol described in [1].

Mid-circuit measurements and classical feed-forward replace the controlled-phase gates of the standard unitary QFT. The protocol requires one adaptive measurement/feed-forward round per qubit, resulting in \(n\) rounds and \(Theta(n^2)\) classically conditioned single-qubit phase corrections, rather than \(\Theta(n^2)\) controlled-phase gates required by the standard unitary QFT.

This operation is not a unitary QFT and does not produce a reusable transformed quantum state. All qubits in qs are measured, and the measurement results are returned in little-endian order. The qs register should be discarded or reset after this operation.

References

[1] Bäumer, E. et al (2024). Quantum Fourier Transform Using Dynamic Circuits. Phys. Rev. Lett. 133, 150602.

Parameters:

qs – Qubit register to perform the QFT on.

Returns:

Measurement results in logical little-endian order.