# Initialization time for StatevectorSimulator Qiskit

I have a question about initializing a quantum circuit to a custom state using Qiskit's StatevectorSimulator(). My naive understanding is that eventually, the simulator would be doing matrix multiplications on the backend (I might be wrong here, if so please correct me). And thus it seems to me that there should be a way of setting a custom initial state with no extra time cost each time you run the circuit. Here is an example. The following code compares the run time of two circuits: qc_1 has initialization to some custom state using qc_1.initialize(state_vec, q_args), and qc_2 which doesn't has such initialization.

import time
from numpy import pi
from numpy.random import random
from qiskit import QuantumCircuit, transpile
from qiskit.providers.aer import StatevectorSimulator

qc = QuantumCircuit(16)
# This for loop is irrelevant. Just used to get some nontrivial statevector
for i in range(num_terms):
rz_pos = (i//2) % 14 + 1
for j in range(rz_pos):
qc.cx(j, j+1)
qc.rz(pi*random(1)[0], rz_pos)
for j in range(rz_pos)[::-1]:
qc.cx(j, j+1)
qc.h([*range(rz_pos)])

qc = transpile(qc)
simulator = StatevectorSimulator()
result = simulator.run(qc).result()
state_vec = result.get_statevector()

qc_1 = QuantumCircuit(16)
qc_1.initialize(state_vec, [*range(16)]) # pylint: disable=no-member

qc_2 = QuantumCircuit(16)

start = time.time()
for i in range(1000):
result = simulator.run(qc_1).result()
time_1 = time.time() - start
print(f'time took to run circuit w initialization {1000} times: {round(time_1,3)}s')

start = time.time()
for i in range(1000):
result = simulator.run(qc_2).result()
time_2 = time.time() - start
print(f'time took to run circuit w/o initialization {1000} times: {round(time_2,3)}s')


This gives the following output:

time took to run circuit w initialization 1000 times: 5.93s
time took to run circuit w/o initialization 1000 times: 0.62s


My assumption is that, using StatevectorSimulator(), there should be a way to set up qc_1 such that the initialization process takes virtually no extra time. This way would be just like saying, instead of using the '0' vector to start multiplying the gates to, use the cutom statevector. This way there should be no extra time cost, correct? Again I understand that this way of thinking only applies to StatevectorSimulator().

The QuantumCircuit.set_statevector method is exactly what you are searching for.

from qiskit.quantum_info import Statevector
qc_3 = QuantumCircuit(16)
qc_3.set_statevector(state_vec)

start = time.time()
for i in range(1000):
result = simulator.run(qc_3).result()
time_3 = time.time() - start
print(f"time took to run circuit w set_statevector {1000} times: {round(time_3,3)}s")


at the end of your code snippet illustrates how to use it.

On my benchmarks, it is faster than QuantumCircuit.initialize but still way slower than noop:

time took to run circuit w initialization 1000 times: 11.65s
time took to run circuit w/o initialization 1000 times: 1.056s
time took to run circuit w set_statevector 1000 times: 7.663s


I suspect that copying the statevector is the costly part, but I have no data to backup my claim.

• Thanks a lot! This indeed seems to be what I was looking for. I also see no other reason for this to take more time other than just copying the state every time it runs the circuit. At any rate, thanks again! Aug 9 '21 at 15:45