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
.