# Qiskit - Z expectation value from counts?

For a given state $$|\psi\rangle$$, how would I work out $$\langle\psi|Z|\psi\rangle$$ ?

If I run a quantum circuit and get the counts dictionary on qiskit, I get observables in the Z basis.

For n=1 qubits, the basis states returned are $$|0\rangle$$ & $$|1\rangle$$ with the counts for each state. I would assign +1 to the counts for $$|0\rangle$$ and -1 to the counts for $$|1\rangle$$ and work out the Z expectation value.

For n=2 qubits, $$|00\rangle$$ & $$|11\rangle$$ have eigenvalues +1 and $$|01\rangle$$ &$$|10\rangle$$ have eigenvalues -1. The Z expectation value is thus [counts(00) + counts(11) - counts(01) - counts (10) ]/ shots where counts(00) is the counts returned for the $$|00\rangle$$ state.

This is extended to n = 3,4,5.. qubits.

My question is how do I calculate this automatically in qiskit?

There's actually a really great way to evaluate this with Qiskit Aqua's operator logic.

This module has the concept of statefunctions to represent $$|\Psi\rangle$$ and $$\langle\Psi |$$ and operators to represent operators such as $$Z^{\otimes n}$$. Your operator would be created using the $$Z$$ primitive:

from qiskit.aqua.operators import Z

operator = Z ^ Z  # ^ represents a tensor product
operator = Z ^ 2  # same thing, computes Z ^ Z
operator = Z.tensorpower(2)  # same thing as Z ^ 2


Now you need to create your state $$|\Psi\rangle$$, for which you have different options. Say you know the circuit to prepare your state, then you can do

from qiskit import QuantumCircuit
from qiskit.aqua.operators import StateFn

psi_circuit = QuantumCircuit(2)
psi = StateFn(psi_circuit)  # wrap it into a statefunction


Or you can also use prepared common statefunctions such as Zero = $$|0\rangle$$, One = $$|1\rangle$$, Plus = $$|+\rangle$$ or Minus = $$|-\rangle$$,

from qiskit.aqua.operators import Zero, Plus

psi = Zero ^ Plus  # creates the state |0+>


To compute the expectation value you naturally need to evaluate $$\langle \Psi | ZZ | \Psi\rangle$$, which you can do as

expectation_value = (~psi @ operator @ psi).eval()
expectation_value = (psi.adjoint().compose(operator).compose(psi)).eval()  # same as above


To explain the syntax: ~ computes the adjoint, so ~psi = $$\langle\Psi|$$. The @ sign is composition and sticks together your states and operators.

### Full example

As an example, let's compute the expectation value of $$\langle \Psi| ZZ | \Psi\rangle$$ with $$|\Psi\rangle = \frac{1}{\sqrt{2}} (|01\rangle + |10\rangle)$$. Calculating by hand, this should yield $$-1$$.

import numpy as np
from qiskit.aqua.operators import Z, Zero, One

operator = Z ^ Z
psi = 1 / np.sqrt(2) * ((One ^ Zero) + (Zero ^ One))
expectation_value = (~psi @ operator @ psi).eval()
print(expectation_value.real)  # -1.0


A function for finding the expectation value for the $$Z Z ... Z$$ operator. If, for example, one wants to measure the expectation value of the $$Z Z I$$, instead of $$Z Z Z$$ than z_index_list should be provided (z_index_list = [1, 2]). Note that I have used the Qiskit's ordering for Pauli labels.

def expectation_zzz(counts, shots, z_index_list=None):
"""
:param shots: shots of the experiment
:param counts: counts obtained from Qiskit's Result.get_counts()
:param z_index_list: a list of indexes
:return: the expectation value of ZZ...Z operator for given z_index_list
"""

if z_index_list is None:
z_counts = counts
else:
z_counts = cut_counts(counts, z_index_list)

expectation = 0
for key in z_counts:
sign = -1
if key.count('1') % 2 == 0:
sign = 1
expectation += sign * z_counts[key] / shots

return expectation


The cut_counts function that will work if z_index_list is provided:

def cut_counts(counts, bit_indexes):
"""
:param counts: counts obtained from Qiskit's Result.get_counts()
:param bit_indexes: a list of indexes
:return: new_counts for the  specified bit_indexes
"""
bit_indexes.sort(reverse=True)
new_counts = {}
for key in counts:
new_key = ''
for index in bit_indexes:
new_key += key[-1 - index]
if new_key in new_counts:
new_counts[new_key] += counts[key]
else:
new_counts[new_key] = counts[key]

return new_counts


For the arbitrary Pauli term $$P$$ before $$ZZ...Z$$ basis measurement one can apply a unitary operator $$U$$, such that:

$$\langle \psi |P| \psi \rangle = \langle \psi | U^{\dagger} ZZ...Z U | \psi \rangle$$

like was described in this answer. Note that in $$P$$ we can have identities, so, for example, if we have $$XIY$$, we will need such $$U$$, that $$U^{\dagger} ZIZ U = XIY$$.

Final notes: here I assume that we have only one ClassicalRegister. If we have more then one ClassicalRegister I guess the code should be changed. The indexes are for the measured qubits (one can do fewer measurements than the numbers of the qubits in QuantumRegister), so, in general the z_index_list (and bit_indexes) doesn't coincide with the indexes of the qubits in the QuantumRegister.

• I guess my actual question is how do I assign Z eigenvalues to the output states (ie the keys in the counts dictionary) For example Z eigenvalue of $\ket{0}$ is +1 Z eigenvalue of $\ket{1}$ is -1 Z eigenvalue of $\ket{00}$ is +1 Z eigenvalue of $\ket{11}$ is +1 Z eigenvalue of $\ket{10}$ is -1 Z eigenvalue of $\ket{01}$ is -1 – Zohim Chandani Apr 5 at 13:46
• @ZohimChandani, so your question is about the expectation value of $Z \otimes Z$ operator? Do you want to know how to write the code for it in Qiskit or do you want to understand what are the eigenvectors that have $+1$ ($-1$) eigenvalue? Can you, please, add more details about what are you looking for in your question by editing it? – Davit Khachatryan Apr 5 at 14:47
• Yes, what is the expectation value of Z for any number of qubits? I understand what eigenvectors have +1 and -1 eigenvalues but how do I assign these eigenvalues to the counts dictionary returned? I have edited the original question but let me know if it is still unclear. Thanks – Zohim Chandani Apr 5 at 15:33
• @Davit, could you please provide a modified version of your code in which only certain $Z$s (from the provided list, say z_list=[0,3,4]) would be measured? Thanks! – mavzolej May 25 at 0:54
• Perfect, thanks! TBH, I'm a little surprised that this whole procedure is not included into standard Qiskit library. – mavzolej May 25 at 15:49