Closed kshitijc closed 5 months ago
I will like to Contributor all the code should have a method, like unit tests
@ogunsegun Can you submit a pull request on the main repo using a feature branch?
plz how am my going to do that @JordanAWS because the is in my github
@ogunsegun: take a look here to learn how to properly submit pull requests and start contributing to open-source projects.
By the way, I'm also interested in working on this. @kshitijc @JordanAWS: can you please add me as an assignee?
Quick question: is it ok to implement the from_braket_circuit(circuit: Circuit) -> QuantumCircuit
function in the qiskit_braket_provider/providers/adapter.py
module? It sounds reasonable to me because the reverse function convert_qiskit_to_braket_circuit(circuit: QuantumCircuit) -> Circuit
is there as well.
thanks @SimoneGasperini
@kshitijc I have put my code on my github but am unable put it here
@kshitijc I have put my code on my github but am unable put it here
@ogunsegun Did you read the link that Kshitij provided on how to submit pull requests?
@kshitijc @JordanAWS have submit my code on pull requests, please is that the way I should have submit it. Create Qiskit QuantumCircuit from Braket Circuit objects! #101
@kshitijc @JordanAWS I'm working on this but I encountered several problems that I'm not sure how to handle. I start recalling the criteria to fulfill in the implementation of the function from_braket_circuit
:
The implementation should be able to handle the Braket circuit containing the following appropriately:
- Supported gates
- Supported result types and observables
- Supported noise instructions
- Verbatim blocks
The first bullet about the supported gates conversion is the minimal requirement and I already have something working including parametric gates. This is straightforward because each quantum gate in Braket has a corresponding gate in Qiskit which performs exactly the same unitary operation on a single or a specific subset of qubits.
Concerning the second bullet, we are already in troubles because the way Braket and Qiskit implement standard (computational basis) measurements, or access the final state_vector/density_matrix, or measure observables expectation values, is different by design. The function convert_qiskit_to_braket_circuit
is implemented so that each QuantumCircuit.measure
Qiskit instruction is translated into a Circuit.probability
call even if the two operations don't have exactly the same underlying logic. Nevertheless, in this case one can assume that the best Braket -> Qiskit approach for standard measurements could be the reverse Circuit.probability
-> QuantumCircuit.measure
conversion. But what about accessing for instance the final quantum state_vector/density_matrix (or any other kind of object defined in the result_types
module)? In Bracket this is done by calling the appropriate method on the circuit which modifies the Circuit
instance itself:
braket_circuit.state_vector()
While in Qiskit there is a separate module to do this and the operation doesn't affect the QuantumCircuit
instance at all:
from qiskit.quantum_info import Statevector
sv = Statevector(qiskit_circuit)
Similar problem is there also for measuring observables expectation values. In Braket we act in-place directly on the circuit:
from braket.circuits.observable import Observable
obs = Observable.X()
braket_circuit.sample(obs)
While in Qiskit we use the Sampler primitive passing the observable defined by using again the quantum_info
module.
Converting noise instructions Braket -> Qiskit turns out to be even more complicated because, while the former allows you to do something like Circuit.bit_flip(target, probability)
, the latter, as far as I know, only lets you to create a NoiseModel
and attach it to the backed used for running the circuit (again, not directly to the circuit itself).
Finally, regarding the Verbatim blocks, I guess that the only way to convert them from Braket to Qiskit would be to put a barrier
between each operation performed from the beginning to the end of the block, forcing Qiskit to skip any possible transpilation. However, this could be misleading because in the conversion Qiskit -> Braket all the barriers are simply ignored.
Can you please help me or maybe give me some feedback? Isn't this the case of loosening the criteria for implementing such a function from_braket_circuit
?
Thank you for these detailed questions @SimoneGasperini! Essentially, we wish to enable users to be able to convert Braket circuits to Qiskit circuits, perform transformations/visualize, and be able to convert these back to Braket circuits. So we want to ensure that the converted Qiskit circuit is reasonable to work with/visualize, and can be translated back to the Braket circuit. For components of the Braket circuit which aren't a component of the Qiskit circuit, you could look at storing them in the metadata property of the Qiskit circuit and then ensuring that these are accounted for when converting to a Braket circuit. Additionally, we could add a notebook demonstrating how to work with these transformations here and display info messages where relevant. These would be useful in scenarios where there is no direct mapping between Braket and Qiskit circuits.
Also note that if the Circuit object has no result types specified, then by default this has the implied meaning of measure on all qubits used.
Please let us know if you need more clarifications!
Thank you very much @kshitijc for the clarifications! If I got it well what we would like to have is a function to make braket_circuit == convert_qiskit_to_braket_circuit(from_braket_circuit(braket_circuit))
evaluate to True
, right?
I already submitted the PR #102 and will keep working on it but I'm not sure to understand how can I handle Braket features which have no direct mapping to Qiskit (i.e. all the ones in my comment above). I know that Qiskit QuantumCircuit
has a metadata
dict attribute to store free-form data which could then be used for converting the circuit back to Braket. The problem is that I don't see this metadata
used in the already available function convert_qiskit_to_braket_circuit
so I believe that maybe also that function would need to be accordingly updated to really enable users to do what you mean.
braket_circuit == convert_qiskit_to_braket_circuit(from_braket_circuit(braket_circuit)) evaluate to True, right?
Yes, that's right!
maybe also that function would need to be accordingly updated to really enable users to do what you mean
Yes, that's correct
@kshitijc Is there a function to generate random Braket circuits? It could be very useful for testing purposes.
If not available, can you provide it just as a reference for testing? It should possibly include all the Braket features we would like to support in the Braket Circuit
conversion to Qiskit QuantumCircuit
: gate instructions, result types, observables, noise instructions, verbatim blocks.
@SimoneGasperini we don't have a random circuit generator currently available in Braket, but we will take your suggestion into consideration for our roadmap :)
If you're looking for same circuits to run, a good set of test cases with be the Braket examples repo:
Greetings, I created a PR for this issue. Submissions for UnitaryHack close now, but I would like to continue working on it. So far, I am able to get braket == convert_qiskit_to_braket_circuit(from_braket_circuit(braket))
as True
for certain circuits.
There will need to be done some modifications to the convert_qiskit_to_braket_circuit()
function because it gives me errors for, e.g., a measurement on a different qubit and a classical bit.
@denvitko @SimoneGasperini Thanks for your work so far on this issue! Since you both submitted a PR before the June 13 deadline, you will have until June 20th to get your code approved and merged. It looks like it will be a race to the finish line, unless the two of you would like to collaborate.
Please don't hesitate to reach out if you need support.
@SimoneGasperini Are you still interested in working on this issue?
Hi @denvitko! Yes I'm still interested. If you are too, we can collaborate.
@JordanAWS I am facing some issues with the convert_qiskit_to_braket_circuit()
function. I generate random Qiskit circuits (using Qiskit random_circuit()
function), pass them to the converter, but it gives me errors (KeyError
s at the moment).
Could you maybe point out what are the most must-have features that should work? Because I am not sure if there is enough time to fix it all 🙃.
Also @JordanAWS, do you plan to implement draw()
method for Braket Circuit
, I think that it would be nice. Just putting print(self)
in the method would be enough.
@JordanAWS I am facing some issues with the
convert_qiskit_to_braket_circuit()
function. I generate random Qiskit circuits (using Qiskitrandom_circuit()
function), pass them to the converter, but it gives me errors (KeyError
s at the moment).
This is because not all the gates/instructions defined in Qiskit are also available in Braket: for example qiskit_gate_names_to_braket_gates["iswap"]
will raise a KeyError
.
A workaround could be to generate your random Qiskit circuit and then transpile it by passing a list of basis_gates
containing only the gates supported by the Braket adapter:
from qiskit import transpile
from qiskit_braket_provider.providers.adapter import (
qiskit_to_braket_gate_names_mapping,
convert_qiskit_to_braket_circuit
)
qiskit = # random circuit
basis_gates = list(qiskit_to_braket_gate_names_mapping.keys())
qiskit = transpile(qiskit, basis_gates=basis_gates, optimization_level=0)
braket = convert_qiskit_to_braket_circuit(qiskit)
However, for this issue we are interested in the conversion from Braket to Qiskit so we don't have to worry too much about gates/instructions that Qiskit supports and Braket doesn't.
Also @JordanAWS, do you plan to implement
draw()
method for BraketCircuit
, I think that it would be nice. Just puttingprint(self)
in the method would be enough.
I think that if the only thing the method Circuit.draw()
would do was to call print(self)
, then it wouldn't make any sense to define it at all (a user could simply use print(braket_circuit)
).
I am trying to add XX+YY gate to the adapter.py
, most of it was pretty straightforward, the only line I was not sure about is this one: "xx_plus_yy": lambda theta, beta: [gates.XY(theta)],
. It seems that Qiskit has two parameters for the XX+YY gate, but Braket XY gate takes only one.
@JordanAWS In case you have access to this, I believe there is a mistake in Braket docs, the comments for XX gate and XY gate are swapped.
@JordanAWS In case you have access to this, I believe there is a mistake in Braket docs, the comments for XX gate and XY gate are swapped.
Good catch! Have reported this to the docs team
Yeah, currently we just use print(circuit)
rather than having a separate circuit.draw()
method: https://docs.aws.amazon.com/braket/latest/developerguide/braket-constructing-circuit.html
Greetings, I am sorry I haven't done more. Despite facing some issues with Python, I am happy that I tried to tackle this problem! I posted my updates in the PR.
Hello @JordanAWS is this issue resolved?
This issue is still open. Happy to collaborate with you if you'd be interested in contributing.
closed by #136
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
What is the expected behavior?
Currently, the Qiskit Braket Provider allows you to convert Qiskit
QuantumCircuit
objects to BraketCircuit
objects. It would be useful to be able to convert BraketCircuit
objects to QiskitQuantumCircuit
objects, allowing users to make use of any of the utilities available in Qiskit to visualize or transform theQuantumCircuit
before optionally translating it back to a BraketCircuit
if needed.The method:
could potentially leverage the existing
from_qasm_str
method available in the QuantumCircuit class or operate directly on the Braket Circuit objects, and could also be potentially exposed on the Quantum circuit class to have a similar usage pattern as thefrom_qasm_str
method:Acceptance criteria