Measurement Circuits

alqorithms includes tools to create circuits that prepare measurements. The convention in gate-based quantum computing is that projective measurements of a quantum register happen by default in the Pauli Z basis. In other words, it is only possible to directly measure operators of the form

\[ \hat O = \hat O_1 \otimes \hat O_2 \otimes \ldots \otimes \hat O_N \]

where \( \hat O_j \in \left\{ \sigma^z_j, \mathrm{I}_j \right\} \).

In order to measure arbitrary Pauli strings, we need to append a measurement circuit at the end of our circuit to rotate the basis of the quantum register so that the standard measurement in the Pauli Z basis effectively corresponds to a measurement of the desired Pauli string.

Creating a single measurement circuit

In order to measure an arbitrary Pauli string \( \sigma_1^{\alpha_1} \otimes \sigma_2^{\alpha_2} \otimes \ldots \otimes \sigma_N^{\alpha_N} \), where \( \sigma_j^{\alpha_j} \in \left\{ \sigma^x, \sigma^y, \sigma^z, \mathrm{I} \right\}\), we need to apply single-qubit rotations to the qubits in the quantum register in order to rotate them from the Z basis to the eigenbasis of the corresponding entry in the Pauli string that we want to measure.

We can even measure multiple Pauli strings with the same measurement circuit, provided that they commute with each other. Two Pauli strings commute with each other if, for each qubit in the quantum register, both PauliProducts have either the same PauliOperator (X, Y, Z) or at least one has the identity \( \mathrm I\) operator. Such Pauli strings are compatible because they can be diagonalized simultaneously, which means that we can use a single measurement circuit to rotate the quantum register into their common eigenbasis.

In py-alqorithms, a measurement circuit can be created with the single_measurement_circuit function, as follows.

from struqture_py import PauliProduct
from py_alqorithms import single_measurement_circuit

# These PauliProducts are compatible
pp1 = PauliProduct.from_string("0X2Y3Z")
pp2 = PauliProduct.from_string("0X1Z")
pp3 = PauliProduct.from_string("2Y3Z")

meas_circuit = single_measurement_circuit([pp1, pp2, pp3], "ro", False, 4)

Creating a measurement for an observable

If we want to measure an arbitrary observable, represented in struqture as a linear combination of PauliProducts, in general, the Pauli products will not all be compatible with each other. We will then need multiple measurement circuits that we'll use to perform separate measurements for each set of compatible PauliProducts. For this, we can use the function measure_spin_operator (or measure_spin_operator_map if we have a list of operators to measure), returning a qoqo PauliZProduct, an object that collects all the information needed to perform the separated measurements and post-process the measurement results into the expectation value of the observable. It can be used as follows

from qoqo import Circuit
from qoqo import Circuit
from qoqo.operations import RotateY
from struqture_py import PauliProduct, SpinSystem
from py_alqorithms import measure_spin_operator

number_measurements = 10
number_qubits = 5
# whether to undo the basis rotation after the measurement circuit
undo_basis_rotation = False

# Prepare the base circuit after which to measure the observable
constant_circuit = Circuit()
for qubit in range(number_qubits):
    constant_circuit += RotateY(qubit, 0.5)

pauli_products = [
  # First set of compatible PauliProducts
  "0X2Y3Z",
  "0X1Z",
  "2Y3Z",
  # Second set of compatible PauliProducts
  "0Z2Z3X",
  "0Z3X",
  "1Y2Z",
]

op = SpinSystem()
for pp in pauli_products: 
    op.set(pp, 1.0)
    
measurement = measure_spin_operator(
    op,
    constant_circuit,
    "my_op",
    undo_basis_rotation,
    number_measurements
)

This measurement can then be used in a QuantumProgram as follows

from qoqo_quest import Backend

backend = Backend(number_qubits)
qp = QuantumProgram(measurement, [])
qp.run(backend, None)

Similarly we can create cheated measurements (CheatedPauliZProduct) using the function measure_spin_operator_map_cheated.