qml.measure¶
- measure(wires, reset=False, postselect=None)[source]¶
Perform a mid-circuit measurement in the computational basis on the supplied qubit.
Computational basis measurements are performed using the 0, 1 convention rather than the ±1 convention. Measurement outcomes can be used to conditionally apply operations, and measurement statistics can be gathered and returned by a quantum function.
If a device doesn’t support mid-circuit measurements natively, then the QNode will apply the
defer_measurements()
transform.Example:
dev = qml.device("default.qubit", wires=3) @qml.qnode(dev) def func(x, y): qml.RY(x, wires=0) qml.CNOT(wires=[0, 1]) m_0 = qml.measure(1) qml.cond(m_0, qml.RY)(y, wires=0) return qml.probs(wires=[0])
Executing this QNode:
>>> pars = np.array([0.643, 0.246], requires_grad=True) >>> func(*pars) tensor([0.90165331, 0.09834669], requires_grad=True)
Wires can be reused after measurement. Moreover, measured wires can be reset to the \(|0 \rangle\) state by setting
reset=True
.dev = qml.device("default.qubit", wires=3) @qml.qnode(dev) def func(): qml.X(1) m_0 = qml.measure(1, reset=True) return qml.probs(wires=[1])
Executing this QNode:
>>> func() tensor([1., 0.], requires_grad=True)
Mid-circuit measurements can be manipulated using the following arithmetic operators:
+
,-
,*
,/
,~
(not),&
(and),|
(or),==
,<=
,>=
,<
,>
with other mid-circuit measurements or scalars.Note
Python
not
,and
,or
, do not work since these do not have dunder methods. Instead use~
,&
,|
.Mid-circuit measurement results can be processed with the usual measurement functions such as
expval()
. For QNodes with finite shots,sample()
applied to a mid-circuit measurement result will return a binary sequence of samples. See here for more details.Note
Computational basis measurements are performed using the 0, 1 convention rather than the ±1 convention. So, for example,
expval(qml.measure(0))
andexpval(qml.Z(0))
will give different answers.dev = qml.device("default.qubit") @qml.qnode(dev) def circuit(x, y): qml.RX(x, wires=0) qml.RY(y, wires=1) m0 = qml.measure(1) return ( qml.sample(m0), qml.expval(m0), qml.var(m0), qml.probs(op=m0), qml.counts(op=m0), )
>>> circuit(1.0, 2.0, shots=1000) (array([0, 1, 1, ..., 1, 1, 1])), 0.702, 0.20919600000000002, array([0.298, 0.702]), {0: 298, 1: 702})
- Parameters
wires (Wires) – The wire to measure.
reset (Optional[bool]) – Whether to reset the wire to the \(|0 \rangle\) state after measurement.
postselect (Optional[int]) – Which basis state to postselect after a mid-circuit measurement. None by default. If postselection is requested, only the post-measurement state that is used for postselection will be considered in the remaining circuit.
- Returns
measurement process instance
- Return type
- Raises
QuantumFunctionError – if multiple wires were specified
Postselection
Postselection discards outcomes that do not meet the criteria provided by the
postselect
argument. For example, specifyingpostselect=1
on wire 0 would be equivalent to projecting the state vector onto the \(|1\rangle\) state on wire 0:dev = qml.device("default.qubit") @qml.qnode(dev) def func(x): qml.RX(x, wires=0) m0 = qml.measure(0, postselect=1) qml.cond(m0, qml.X)(wires=1) return qml.sample(wires=1)
By postselecting on
1
, we only consider the1
measurement outcome on wire 0. So, the probability of measuring1
on wire 1 after postselection should also be 1. Executing this QNode with 10 shots:>>> func(np.pi / 2, shots=10) array([1, 1, 1, 1, 1, 1, 1])
Note that only 7 samples are returned. This is because samples that do not meet the postselection criteria are thrown away.
If postselection is requested on a state with zero probability of being measured, the result may contain
NaN
orInf
values:dev = qml.device("default.qubit") @qml.qnode(dev) def func(x): qml.RX(x, wires=0) m0 = qml.measure(0, postselect=1) qml.cond(m0, qml.X)(wires=1) return qml.probs(wires=1)
>>> func(0.0) tensor([nan, nan], requires_grad=True)
In the case of
qml.sample
, an empty array will be returned:dev = qml.device("default.qubit") @qml.qnode(dev) def func(x): qml.RX(x, wires=0) m0 = qml.measure(0, postselect=1) qml.cond(m0, qml.X)(wires=1) return qml.sample(wires=[0, 1])
>>> func(0.0, shots=[10, 10]) (array([], shape=(0, 2), dtype=int64), array([], shape=(0, 2), dtype=int64))
Note
Currently, postselection support is only available on
default.qubit
. Using postselection on other devices will raise an error.Warning
All measurements are supported when using postselection. However, postselection on a zero probability state can cause some measurements to break:
With finite shots, one must be careful when measuring
qml.probs
orqml.counts
, as these measurements will raise errors if there are no valid samples after postselection. This will occur with postselection states that have zero or close to zero probability.With analytic execution,
qml.mutual_info
will raise errors when using any interfaces exceptjax
, andqml.vn_entropy
will raise an error with thetensorflow
interface when the postselection state has zero probability.When using JIT,
QNode
’s may have unexpected behaviour when postselection on a zero probability state is performed. Due to floating point precision, the zero probability may not be detected, thus letting execution continue as normal withoutNaN
orInf
values or empty samples, leading to unexpected or incorrect results.