qolumbina.utils.quantum_measurement module#
Utilities for appending Pauli-basis measurements to Qiskit circuits.
This module resolves user-facing measurement specifications into the concrete objects that Qiskit needs:
a dense Pauli-basis list with one entry per qubit; and
a qubit-to-classical-bit measurement mapping.
The public entry point is QuantumMeasurement.measure(). It supports the
legacy dense basis form, a sparse basis dictionary, automatic classical-bit
mapping, and explicit conflict detection when both basis and mapping are
provided.
- class MeaBasisType(value)[source]#
Bases:
EnumSupported measurement-basis input categories.
The enum is intentionally small because measurement currently supports only Pauli bases. The value determines how the user input is normalized into a dense basis list before gates are appended to a circuit.
- PAULI_STRING#
Dense basis list, for example
["x", "i", "z"]. The list must cover every qubit of the measured circuit.
- PAULI_MAPPING#
Sparse basis mapping, for example
{0: "x", 3: "z"}. Unspecified qubits are treated as"i"and are therefore not measured.
- class QuantumMeasurement(qc, meas_basis, meas_mapping)[source]#
Bases:
objectAppend Pauli-basis measurement operations to a circuit.
QuantumMeasurementseparates two concerns:meas_basisdecides which qubits are measured and in which Pauli basis. A basis value of"i"means identity/no measurement.meas_mappingdecides where each measured qubit is written in the classical register.
The two specifications must agree after basis resolution. In other words, the set of qubits whose basis is not
"i"must exactly matchmeas_mapping.keys(). This explicit conflict check prevents accidental full-circuit measurements when the caller intended a partial measurement.Supported Pauli basis labels are
"x","y","z", and"i". Measurement in X and Y basis is implemented by applying the standard basis rotations before Qiskit’s computational-basis measurement.Create a measurement appender for an already allocated circuit.
The constructor does not modify
qc. Callapply()to append the actual gates, or use the convenience constructorQuantumMeasurement.measure().- Parameters:
qc (qiskit.QuantumCircuit) – Circuit that already contains the required classical bits.
meas_basis (list[str] or dict[int, str]) – Dense or sparse Pauli measurement basis. A dense list must cover every qubit in
qc. A sparse dict leaves unspecified qubits unmeasured.meas_mapping (dict[int, int]) – Mapping from measured qubit index to classical-bit index. Its keys must exactly match the measured qubits.
- PAULI_BASIS_SET = {'i', 'x', 'y', 'z'}#
- PAULI_STRING_TRANS = {'i': None, 'x': '_pauli_x_measure', 'y': '_pauli_y_measure', 'z': '_pauli_z_measure'}#
- apply()[source]#
Append the resolved measurement gates to
self.qc.This method normalizes sparse basis inputs to a dense Pauli string, validates basis labels and mapping indices, checks that basis and mapping describe the same measured qubits, and then appends the appropriate basis-rotation and measurement gates.
- Raises:
TypeError – If the measurement mapping has invalid key/value types.
ValueError – If the dense basis length does not match the circuit width, if basis labels are unsupported, if qubit/classical indices are invalid, if multiple qubits map to the same classical bit, or if basis and mapping conflict.
- Return type:
None
- classmethod measure(qc, meas_basis, input_meas_mapping=None)[source]#
Resolve a measurement specification and append measurement gates.
Measurement specification is resolved as follows:
If both
meas_basisandinput_meas_mappingareNone, every qubit is measured in Pauli-Z basis with the defaultq_i -> c_imapping. This preserves the original full-measurement behavior.If
input_meas_mappingis provided butmeas_basisisNone, only the qubits appearing in the mapping keys are measured, all in Pauli-Z basis.If
meas_basisis provided butinput_meas_mappingisNone, only qubits whose basis is not"i"are measured. Classical bits are assigned contiguously in ascending qubit-index order; for example, measured qubits[0, 3, 4]map to classical bits[0, 1, 2].If both are provided, the non-
"i"qubits frommeas_basismust exactly matchinput_meas_mapping.keys(). Missing or extra mapping entries are treated as conflicts and raiseValueError.
meas_basiscan be a denselist[str]covering all circuit qubits or a sparsedict[int, str]whose unspecified qubits are treated as"i".Important
qcmust already have enough classical bits for the resolved mapping. If the caller does not know the required width in advance, callrequired_clbits()before constructingqc.Examples
Control only
input_meas_mapping. The basis is omitted, so only the mapped qubits are measured and they default to Pauli-Z basis:qc = QuantumCircuit(5, 2) QuantumMeasurement.measure( qc, meas_basis=None, input_meas_mapping={1: 0, 4: 1}, ) # Resolved basis: ["i", "z", "i", "i", "z"] # Resolved mapping: {1: 0, 4: 1} # Measurements appended: q1 -> c0, q4 -> c1.
Control only
meas_basis. The mapping is omitted, so classical bits are assigned contiguously in ascending measured-qubit order:qc = QuantumCircuit(5, 3) QuantumMeasurement.measure( qc, meas_basis=["z", "i", "i", "x", "y"], ) # Measured qubits: [0, 3, 4] # Resolved mapping: {0: 0, 3: 1, 4: 2} # q0 is measured in Z, q3 in X, and q4 in Y.
Use sparse
meas_basisand explicitinput_meas_mappingtogether. The two specifications are accepted only when their qubit sets match:qc = QuantumCircuit(6, 2) QuantumMeasurement.measure( qc, meas_basis={2: "x", 5: "z"}, input_meas_mapping={2: 1, 5: 0}, ) # Resolved basis: ["i", "i", "x", "i", "i", "z"] # Resolved mapping: {2: 1, 5: 0}
A conflicting pair raises
ValueError:QuantumMeasurement.measure( qc, meas_basis={2: "x", 5: "z"}, input_meas_mapping={2: 1, 4: 0}, )
- Parameters:
qc (qiskit.QuantumCircuit) – Circuit to mutate by appending measurement operations.
meas_basis (list[str] or dict[int, str] or None) – Dense basis list, sparse basis mapping, or
None.input_meas_mapping (dict[int, int] or None) – Optional explicit qubit-to-classical-bit mapping.
- Returns:
The same circuit object after measurement gates are appended.
- Return type:
qiskit.QuantumCircuit
- Raises:
TypeError – If basis or mapping containers have invalid key/value types.
ValueError – If the specification is inconsistent, if the circuit has insufficient classical bits, or if an index is outside the valid range.
- classmethod required_clbits(num_qubits, meas_basis, input_meas_mapping=None)[source]#
Return the classical-register width required by a measurement spec.
Callers that allocate a circuit before invoking
measure()should use this helper so that allocation, default handling, and conflict checks follow the same rules as the measurement implementation.The returned value is
max(meas_mapping.values()) + 1after the specification is resolved. This preserves sparse explicit classical-bit mappings. For example,{2: 5}requires six classical bits even though it measures only one qubit.- Parameters:
num_qubits (int) – Number of qubits in the circuit that will be measured.
meas_basis (list[str] or dict[int, str] or None) – Dense basis list, sparse basis mapping, or
None.input_meas_mapping (dict[int, int] or None) – Optional explicit qubit-to-classical-bit mapping.
- Returns:
Minimum classical register width needed by the resolved measurement mapping.
- Return type:
int
- Raises:
TypeError – If basis or mapping containers have invalid key/value types.
ValueError – If the measurement specification is invalid or internally inconsistent.
- classmethod resolve_measurement_spec(num_qubits, meas_basis, input_meas_mapping=None)[source]#
Resolve measurement inputs into a dense basis and concrete mapping.
The returned basis always has length
num_qubits. The returned mapping contains exactly the qubits whose basis is not"i".This method is the single source of truth for all default handling:
None/Nonebecomes full Pauli-Z measurement.mapping-only input becomes sparse Pauli-Z measurement on mapped qubits.
basis-only input gets contiguous classical bits in ascending qubit order.
basis-plus-mapping input is accepted only if the measured qubit sets match exactly.
- Parameters:
num_qubits (int) – Number of qubits in the measured circuit.
meas_basis (list[str] or dict[int, str] or None) – Dense basis list, sparse basis mapping, or
None.input_meas_mapping (dict[int, int] or None) – Optional explicit qubit-to-classical-bit mapping.
- Returns:
(resolved_basis, resolved_mapping)whereresolved_basisis a dense list of lengthnum_qubitsandresolved_mappingmaps each measured qubit to a classical bit.- Return type:
tuple[list[str], dict[int, int]]
- Raises:
TypeError – If basis or mapping containers have invalid key/value types.
ValueError – If
num_qubitsis invalid, if dense basis length is wrong, if indices are out of range, if basis labels are invalid, or if basis and mapping conflict.
- infer_measurement_basis_type(mea_input)[source]#
Infer the measurement-basis input category.
Supported inputs are:
list[str]: dense Pauli basis list.dict[int, str]: sparse mapping from qubit index to Pauli basis.
This function validates only the container and element types. Semantic checks such as valid basis labels, valid qubit ranges, dense-list length, and mapping compatibility are handled later by
QuantumMeasurement.- Parameters:
mea_input (list[str] or dict[int, str]) – Measurement-basis input to classify.
- Returns:
The inferred basis input category.
- Return type:
- Raises:
TypeError – If
mea_inputis notlist[str]ordict[int, str].ValueError – If
mea_inputis an empty dense list.