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?
- 199
- 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.
- 749
- 3
- 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)
- 11,986
- 1
- 13
- 34