# Is there a "parameterized initialization" that I can apply to a QuantumRegister to re-use a circuit?

I'm working on a QuantumCircuit which measures the fidelity of one point (my "test vector") and two other points (my "data set", containing of states phi_1 and phi_2) at once. I'm using Afham; Basheer, Afrad; Goyal, Sandeep (2020) to reproduce their circuit. My circuit right now looks as follows:

                                          ░ ┌───┐                    ┌───┐ ░ ┌─┐
control_0: ─────────────────────░─┤ H ├────────────■──■──■─┤ H ├─░─┤M├───
┌──────────────────┐ ░ └───┘            │  │  │ └───┘ ░ └╥┘
state_to_classify_0: ┤0                 ├─░──────────────────X──┼──┼───────░──╫────
│                  │ ░                  │  │  │       ░  ║
state_to_classify_1: ┤1 INIT TEST STATE ├─░──────────────────┼──X──┼───────░──╫────
│                  │ ░                  │  │  │       ░  ║
state_to_classify_2: ┤2                 ├─░──────────────────┼──┼──X───────░──╫────
└──────────────────┘ ░      ┌─────────┐ │  │  │       ░  ║
train_states_0: ─────────────────────░──────┤0        ├─X──┼──┼───────░──╫────
░      │         │    │  │       ░  ║
train_states_1: ─────────────────────░──────┤1        ├────X──┼───────░──╫────
░      │  oracle │       │       ░  ║
train_states_2: ─────────────────────░──────┤2        ├───────X───────░──╫────
░ ┌───┐│         │               ░  ║ ┌─┐
comp_basis_0: ─────────────────────░─┤ H ├┤3        ├───────────────░──╫─┤M├
░ └───┘└─────────┘               ░  ║ └╥┘
meas_control_0: ═════════════════════════════════════════════════════════╩══╬═
║
meas_comp_basis_0: ════════════════════════════════════════════════════════════╩═


Where the INIT TEST STATE is used to initialise my test state on a 3-qubit register, and my oracle is defined as follows:

                     ┌────────┐     ┌────────┐
train_states_0: ─────┤0       ├─────┤0       ├
│        │     │        │
train_states_1: ─────┤1 phi_0 ├─────┤1 phi_1 ├
│        │     │        │
train_states_2: ─────┤2       ├─────┤2       ├
┌───┐└───┬────┘┌───┐└───┬────┘
comp_basis_0: ┤ X ├────■─────┤ X ├────■─────
└───┘          └───┘


So that my train_states register is in a superposition of my full data set. I want to be able to measure the fidelity between multiple points, so what I'm doing right now is just create my circuit where I call qiskit.extensions.quantum_initializer.Isometry to initialize my registers into the desired state. If I want to test another test state, I reproduce my entire circuit.

For now this works, but eventually I want to move onto larger datasets with thousands of points, I can imagine that recreating a QuantumCircuit from scratch for every data point can become a bottleneck. Hence my question: can I make INIT TEST STATE in such a way that I can define an example function like:

def apply_new_datapoint(new_init_gate, old_circuit):
old_circuit.data.replace(0, new_init_gate)


I have no idea if the above works, but this is what I'm trying to reach eventually.

There is no replace() method, but you can do the trick by means of pop() and insert().

Example:

from qiskit import QuantumCircuit, Aer, execute
from qiskit.extensions.standard import XGate

simulator = Aer.get_backend("qasm_simulator")

qc = QuantumCircuit(4,4)
qc.h([0,1,2,3])
qc.measure([0,1,2,3], [0,1,2,3])
print(qc.draw())
result = execute(qc, backend=simulator, shots=1000).result()
counts = result.get_counts(qc)
print("\nTotal counts:",counts)

qc.data.pop(0)
qc.data.insert(0,(XGate(),[qc.qregs[0][0]],[]))
print(qc.draw())
result = execute(qc, backend=simulator, shots=1000).result()
counts = result.get_counts(qc)
print("\nTotal counts:",counts)

• This is a nice and concise way to express the Python script, but how does it address the bottleneck concern in the OP? Each execute method creates a new quantum circuit from scratch in the hardware (1000 times). Jun 12 '20 at 12:22
• In my understanding, the envisioned bottleneck was in the Python (i.e., classical) part. Executing the quantum circuit should not be time-consuming. Jun 12 '20 at 12:34
• Thank you @MicheleAmoretti and @JonathanTrousdale for both the example script and the continuation on it. The provided example of code does help and does answer my question. The thing is that I still have that bottleneck in the back of my head as Jonathan said: is there some sort of way I can "burn in" the circuit that I do not change, so that the potential Quantum Computer running it can keep that fixed and only needs to change the part I want to pop() and insert()? Jun 15 '20 at 8:30
• Actually, you cannot "burn in" the circuit you don't change. The only "burnt in" circuitry is the one of the quantum computer, whose logic makes it universal. This means that the sequence of operations (quantum gates) is always performed from the scratch, driven by the submitted description of the quantum algorithm. Jun 15 '20 at 9:32
• Alright, that seems logical. The thing that now remains is just a matter of 'beauty': I'd like to have some sort of "parameterized init" where I can just fill in the parameter (in my case, 8D-vector) that I want at execute just like you can do with controlled rz(theta, qbit). You seemed to focus mainly on my replace() example, but maybe you know of something like that as well? Jun 15 '20 at 11:44

John Preskill identified the bottleneck you described as a fundamental problem in quantum deep learning (section 6.5, here). In particular,

But typical proposals for quantum machine learning applications are confounded by severe input/output bottlenecks. For applications to large classical data sets one should take into account the cost of encoding the input into QRAM, which can nullify the potential advantages.... These bottlenecks arise when we try to train a quantum network to learn about correlations in classical data.

Although he is somewhat skeptical of the value of quantum annealing in other parts of the paper, Preskill hints at the end of this section that quantum annealers might ultimately be a solution to overcoming these bottlenecks.

• Thank you for the link. However, there are some ways that Machine Learning algorithms are running with parameterized circuits where the values of e.g. a Support Vector Machine are updated classically, and then given as input into the algorithm. My goal is to reach something similar, but with an initialisation. I would say that that would be possible, since those hybrid models already exists. Or do you think that those hybrid models just "swallow" those bottlenecks and go with it? Jun 15 '20 at 8:33
• @GroenteLepel From what I understand, one could conceivably get improved performance by sacrificing universality of the logic and moving to a special purpose circuit (the quantum analog of microcontroller vs. ASIC), such that the initialization you seek is hardwired into the circuit. AFAIK the benefits that can be gained by doing this are not currently well understood. Jun 15 '20 at 15:04
• @GroenteLepel To go deeper, understanding the relationship between restricted Boltzmann machines and tensor networks is a good place to start (e.g. Section II(E)-(F) of this paper), noting that quantum circuits, like the one in your OP, are just a particular form of a tensor network. Jun 15 '20 at 15:05