I am calculating the expectation value of an operator using the CircuitSampler
class as mentioned here. Now, I was getting exact same result for the expectation values even when I specified different number of shots. It turns out that in the method convert
of CircuitSampler
ignores the number of shots if the backend
is a statevector_simulator
. Why is that the case? Also, what is the difference if backend
is a statevector
or something else?

- 189
- 1
- 7
2 Answers
The Statevector is a vector of length $2^n$ (where you have $n$ qubits) in which the square of each element's absolute value gives you the probability of getting that bit pattern. So, for example, $[\frac{\sqrt3}4, \frac{\sqrt5}4, \frac{\sqrt6}4, \frac{\sqrt2}4]$ indicates that you have a $\frac{3}{16}$ chance of getting $|00\rangle$, a $\frac5{16}$ chance of getting $|01\rangle$, etc. This is a calculation that can only be done by a simulator keeping track of every possible state, and not by an actual quantum device with $n$ qubits.
Since a statevector simulator knows the exact odds of every possible result (save for floating point errors), it can give a precise answer.
Simulators that return shots rather than statevectors often generate a statevector internally, and then use a method similar to Statevector.sample_memory(shots)
to emulate taking quantum measurements on a statevector. The results look less clean and more like coin tossing.

- 713
- 2
- 8
This behavior is called "Aer fast expectation". It is enabled by default if operator primitives are Paulis and the used backend is Aer Qasm backend. It has the advantage of being fast. However, if you pass a noise model to the simulator, it will be ignored.
If you are using ExpectationFactory
you can disable this behavior by setting include_custom
to False
so that PauliExpectation
will be used instead of AerPauliExpectation
observables = [
X^X,
Z^I,
Z^Z,
]
circuit_sampler = CircuitSampler(quantum_instance)
exp_converter = ExpectationFactory.build(observables[0], None, include_custom = False) # <== here
list_op = ListOp([StateFn(obs, is_measurement = True).compose(StateFn(circuit)) for obs in observables])
observables_expect = exp_converter.convert(list_op)
observables_expect_sampled = circuit_sampler.convert(observables_expect)
observables_results = np.real(observables_expect_sampled.eval())
print(observables_results)

- 9,972
- 1
- 11
- 30
-
I also notice that specifying
statevector_simulator
as the backend returns much more accurate results than specifyingaer_simulator
in this case. Why is that the case? – bisarch Dec 07 '22 at 16:19 -
Does statevector_simulator with CircuitSampler simulate a quantum computer at all? Does it simply do a matrix vector multiplication to get the expectation value? – bisarch Dec 07 '22 at 20:58
statevector_simulator
withCircuitSampler
doesn't simulate a quantum computer at all? Does it simply do a matrix vector multiplication to get the expectation value? – bisarch Dec 07 '22 at 19:57