2
$\begingroup$

I'm trying to understand how result.get_statevector() works.

Using BasicAer, the following code gives the result for the statevector:

[0.70710678+0.j 0. +0.j 0. +0.j 0.70710678+0.j]

which is fine.

from qiskit import QuantumCircuit, transpile, Aer, BasicAer

circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cnot(0, 1)

#simulator = Aer.get_backend('aer_simulator_statevector')
simulator = BasicAer.get_backend('statevector_simulator')

result = simulator.run(transpile(circuit, simulator)).result()

psi = result.get_statevector(circuit)

But when I try it with the corresponding statevector simulator in Aer, it gives the error:

QiskitError: 'No statevector for experiment'

I'm not sure why this is not working.

$\endgroup$

2 Answers 2

3
$\begingroup$

You should use the QuantumCircuit.save_statevector() method whenever you wish to take a "screenshot" of the system's statevector. This modification of your code would do the job:

from qiskit import QuantumCircuit, transpile, Aer

simulator = Aer.get_backend('aer_simulator_statevector')

circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cnot(0, 1)
circuit.save_statevector()

result = simulator.run(transpile(circuit, simulator)).result()
psi = result.get_statevector(circuit)

Also note that if you wish to take multuiple "screenshots" of the statevector in different places along the circuit that is possible, while the requirement is to label each shot with a unique name. For example this code:

from qiskit import QuantumCircuit, transpile, Aer

simulator = Aer.get_backend('aer_simulator')

circuit = QuantumCircuit(2)
circuit.h(0)
circuit.save_statevector('psi1')
circuit.cnot(0, 1)
circuit.save_statevector('psi2')

result = simulator.run(transpile(circuit, simulator)).result()
data = result.data()

psi1 = data['psi1']
psi2 = data['psi2']

display(psi1.draw(output = 'latex'))
display(psi2.draw(output = 'latex'))

Gives this output: $$\frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |01\rangle \\ \frac{\sqrt{2}}{2} |00\rangle+\frac{\sqrt{2}}{2} |11\rangle$$

One more option (which I personally prefer the most) is using the Statevector class in order to easily take "screenshots" of the system's statevector whenever we desire. The following code produces the same output as the last one:

from qiskit import QuantumCircuit, transpile, Aer
from qiskit.quantum_info import Statevector

simulator = Aer.get_backend('aer_simulator')

circuit = QuantumCircuit(2)
circuit.h(0)
psi1 = Statevector(circuit)
circuit.cnot(0, 1)
psi2 = Statevector(circuit)

display(psi1.draw(output = 'latex'))
display(psi2.draw(output = 'latex'))
$\endgroup$
3
$\begingroup$

This is a supplement to Ohad's nice answer.

I was confused about why the code I wrote produced different results for the two statevector simulators that I originally tried (one worked, one gave an error). I was assuming that the various statevector simulators would be essentially interchangeable, at least as far as how you interacted with them. That was an incorrect assumption.

I did a comparison of executing a simple circuit on three of qiskit's statevector simulators.

  1. Aer's StatevectorSimulator legacy backend

    [1]: from qiskit import QuantumCircuit, BasicAer, execute
         from qiskit_aer import AerSimulator, StatevectorSimulator
    
         # Create circuit
         circuit = QuantumCircuit(2)
         circuit.h(0)
         circuit.cnot(0, 1)
    
         # Simulator 
         simulator_aerlegacy = StatevectorSimulator()
         result_aerlegacy = execute(circuit, simulator_aerlegacy).result()
    
         result_aerlegacy.data()
    [1]: {'statevector': Statevector([0.70710678+0.j, 0.  +0.j, 0.  +0.j,
                       0.70710678+0.j],
                      dims=(2, 2))}
    
    [2]: result_aerlegacy.get_statevector()
    [2]: Statevector([0.70710678+0.j, 0.        +0.j, 0.        +0.j,
              0.70710678+0.j],
             dims=(2, 2))
    
    • StatevectorSimulator automatically does a SaveStatevector() at the end of the circuit, which is why you can use result.get_statevector() without adding any QuantumCircuit.save_statevector()'s to your circuit.

    • See: https://qiskit.org/documentation/apidoc/aer_library.html#saving-simulator-data

      The StatevectorSimulator (and UnitarySimulator) backend automatically append every run circuit with the a SaveStatevector() (SaveUnitary()) instruction using the default label. Hence adding any additional save instructions of that type will require specifying a custom label for those instructions.

  2. BasicAer's statevector simulator

    [3]: # Simulator 
         simulator_basicaer = BasicAer.get_backend('statevector_simulator')
         result_basicaer = execute(circuit, simulator_basicaer).result()
    
         result_basicaer.get_statevector()
    [3]: array([0.70710678+0.j, 0.   +0.j, 0.  +0.j, 0.70710678+0.j])
    
    • BasicAer also automatically adds 'statevector' (but as a numpy array, not a Statevector). This explains why it worked fine in my original post.
  3. Aer's AerSimulator()

    [4]: # Simulator
         simulator_aer = AerSimulator(method="statevector")
         result_aer = execute(circuit, simulator_aer).result()
    
         result_aer.get_statevector()
    [4]: QiskitError: 'No statevector for experiment "None"'
    
    • You have to add QuantumCircuit.save_statevector() yourself. If you don't, result_aer.data() will be an empty dictionary.

I agree with Ohad that using quantum_info.Statevector is an preferable way to do these things.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.