Supporting verbatim circuit execution
dexter2206 opened this issue · 6 comments
What is the expected enhancement?
I noticed that it is not currently possible to define a circuit in Qiskit and then run it on AWS device in verbatim mode and/or with disabled qubit rewiring. This feature seems to be very important, especially in the field of benchmarking quantum devices, when one needs to have precise control of what circuits are being executed. Is there any chance this could get implemented?
One possibility would be to introduce a verbatim
and disable_qubit_rewiring
options in AWSBraketBackend.run
method, and then act adequately by wrapping the circuit in verbatim instruction before execution or adding disable_qubit_rewiring=True
.
Hey @dexter2206 ! Thanks for the submission!
I think qubits rewiring is happening on transpilation step. So, if you do not transpile circuit and send it directly, then it should be executed as given.
Maybe I'm wrong and verbatim is happening on QASM level?
Can you spill a little more light on it @dexter2206?
Thanks for your response @IceKhan13 ! I think that unless disable_qubit_rewiring=True
is passed, the rewiring is done by Braket automatically. Similarly, the circuit being sent is compiled for a given device unless it is explicitly wrapped in a verbatim box.
Verification should be simple: I can send a circuit with incompatible gateset and/or incompatible qubit connectivity to a physical device and see if it is executed. If yes, the rewiring/compilation is happening automatically and we would need some explicit actions to prevent it. I will verify this once Lucy or Aspen M-2 are available in my region.
Consider the following piece of code, which runs CNOT(0, 1) on Lucy device in verbatim mode.
from braket.circuits import Circuit
from braket.aws import AwsDevice
subcircuit = Circuit().cnot(0, 1)
circuit = Circuit().add_verbatim_box(subcircuit)
device = AwsDevice("arn:aws:braket:eu-west-2::device/qpu/oqc/Lucy")
device.run(circuit, shots=10)
This code correctly raises an error, because Lucy device doesn't support CNOT gate natively. However, this cannot be reproduced using qiskit_braket_provider
, because there is no way of adding verbatim box. By default, circuits without verbatim boxes are compiled by Braket, and hence for instance the following code does not raise an error
from qiskit import QuantumCircuit
from qiskit_braket_provider import AWSBraketProvider
backend = AWSBraketProvider().get_backend("Lucy")
qc = QuantumCircuit(2)
qc.cnot(0, 1)
backend.run(qc, shots=10)
@dexter2206 got it! thank you!
I've looked into it and it looks like we can have couple of ways to resolve this:
- Easy-peasy way: we need to propagate some of the parameters for braket jobs. Like you suggested
disable_qubit_rewiring
is a good option. So, our code will look something like
from qiskit import QuantumCircuit
from qiskit_braket_provider import AWSBraketProvider
backend = AWSBraketProvider().get_backend("Lucy")
qc = QuantumCircuit(2)
qc.cnot(0, 1)
backend.run(qc, shots=10, disable_qubit_rewiring=True)
- Trickier: is to introduce new
VerbatimInstruction
and convert it forth and back in adapter
I like first approach. Literal code changes will be changing this lines
qiskit-braket-provider/qiskit_braket_provider/providers/braket_backend.py
Lines 247 to 249 in 440911a
into
batch_task: AwsQuantumTaskBatch = self._device.run_batch(
braket_circuits, *options
)
If you want to fix it and have a contribution, I can assign it to you 😄 if not, I will do it
@IceKhan13 Actually verbatim instructions and qubit rewiring are bit different, sorry for including only the former in the example. Anyway, the difference is:
disable_qubit_rewiring
is an argument torun_batch
(orrun
), and disables reassignment of qubits. So, for instance, if you define a circuit comprisingCNOT(0, 3)
you are sure it runs on qubits with indices 0 and 3. If not provided, the Braket compiler (or probably third partly software that Braket uses to run specific circuit) may decide to run your circuits on different qubits.- verbatim boxes are part of circuits, as illustrated in the example above.
The main point is that verbatim boxes cannot be just passed through **options
.
Fortunately, at least from my experience, one typically runs only one verbatim box, and verbatim and non-verbatim parts are not mixed. Therefore, what I suggest is a slight extensions to your first idea, i.e.:
- pass
disable_qubit_rewiring
through**options
- check if
options
containsverbatim
key with value set toTrue
. If so, wrap each circuit in a verbatim box before sending them.
This would roughly look like this:
if options.get("verbatim", False):
braket_circuits = [convert_to_verbatim(c) for c in braket_circuits]
batch_task: AwsQuantumTaskBatch = self._device.run_batch(
braket_circuits, *options
)
and _convert_to_verbatim
would look roughly like this
def convert_to_verbatim(circuit):
new_circuit = Circuit()
new_circuit.add_verbatim_box(circuit)
return new_circuit
I can contribute if you like the solution outlined above :)
@dexter2206 I love it 😄 !