qml.shadow_expval¶
- shadow_expval(H, k=1, seed=None)[source]¶
Compute expectation values using classical shadows in a differentiable manner.
The canonical way of computing expectation values is to simply average the expectation values for each local snapshot, \(\langle O \rangle = \sum_t \text{tr}(\rho^{(t)}O) / T\). This corresponds to the case
k=1
. In the original work, 2002.08953, it has been proposed to split theT
measurements intok
equal parts to compute the median of means. For the case of Pauli measurements and Pauli observables, there is no advantage expected from settingk>1
.- Parameters
H (Union[Iterable[Operator], Operator]) – Observable or iterable of observables to compute the expectation value over.
k (int) – Number of equal parts to split the shadow’s measurements to compute the median of means.
k=1
(default) corresponds to simply taking the mean over all measurements.seed (Union[None, int]) – Seed used to randomly sample Pauli measurements during the classical shadows protocol. If None, a random seed will be generated. If a tape with a
shadow_expval
measurement is copied, the seed will also be copied. Different seeds are still generated for different constructed tapes.
- Returns
Measurement process instance
- Return type
Note
This measurement uses the measurement
classical_shadow()
and the classClassicalShadow
for post-processing internally to compute expectation values. In order to compute correct gradients using PennyLane’s automatic differentiation, you need to use this measurement.Example
H = qml.Hamiltonian([1., 1.], [qml.Z(0) @ qml.Z(1), qml.X(0) @ qml.X(1)]) dev = qml.device("default.qubit", wires=range(2), shots=10000) @qml.qnode(dev) def circuit(x, obs): qml.Hadamard(0) qml.CNOT((0,1)) qml.RX(x, wires=0) return qml.shadow_expval(obs) x = np.array(0.5, requires_grad=True)
We can compute the expectation value of H as well as its gradient in the usual way.
>>> circuit(x, H) array(1.8774) >>> qml.grad(circuit)(x, H) -0.44999999999999984
In
shadow_expval
, we can pass a list of observables. Note that each qnode execution internally performs one quantum measurement, so be sure to include all observables that you want to estimate from a single measurement in the same execution.>>> Hs = [H, qml.X(0), qml.Y(0), qml.Z(0)] >>> circuit(x, Hs) array([ 1.881 , -0.0312, -0.0027, -0.0087]) >>> qml.jacobian(circuit)(x, Hs) array([-0.4518, 0.0174, -0.0216, -0.0063])