# Computing expectation value of product of observables in PennyLane

In PennyLane, the following circuit returns the expectation value of the PauliZ observable on qubit (wire) 1:

def my_quantum_function(x, y):
qml.RZ(x, wires=0)
qml.CNOT(wires=[0, 1])
qml.RY(y, wires=1)
return qml.expval(qml.PauliZ(1))


What if I instead wanted to return the expectation value of an operator $$H = Z_1Z_2$$ that acts on the first and the second qubit? How might I do that?

It is my understanding that qubits 1 and 2 are "correlated" because of the CNOT, so $$\left\langle Z_1 Z_2 \right\rangle \neq \left\langle Z_1 \right\rangle \left\langle Z_2 \right\rangle$$. Does this mean I have to define a custom operator? Or does [qml.expval(qml.PauliZ(i)) for i in range(2)] achieve what I want? Thanks for any help.

Note: The above example function was taken from the PennyLane measurements documentation.

PennyLane supports measurements of tensor products of observable via the @ operator, like so:

@qml.qnode(dev)
def my_quantum_function(x, y):
qml.RZ(x, wires=0)
qml.CNOT(wires=[0, 1])
qml.RY(y, wires=1)
return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))


This should return the same result as the solution by KAJ226 above, but will be slightly more efficient as it is avoiding creating a potentially large dense matrix.

There are some examples on tensor observables in the PennyLane documentation.

• Nice @Josh! I like this better. :) Jan 30, 2021 at 9:47

I think the following should work:

n_qubits = 2
Z = [ [1,0], [0,-1]]
ZZ = np.kron(Z,Z)

@qml.qnode(dev)
def circuit(params):
qml.RY(params[0], wires=0)
qml.CNOT(wires=[0, 1])
qml.RY(params[1], wires=1)
return qml.expval(qml.Hermitian(ZZ, wires=[0, 1]))