-
Notifications
You must be signed in to change notification settings - Fork 48
Feature: Add Hadamard Test #158
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| ======= | ||
| The Hadamard test is a quantum circuit that allows estimation of the real and imaginary parts of the expected value of a unitary operator. It is a fundamental subroutine used in many quantum algorithms, including quantum phase estimation where it helps extract eigenvalue information through controlled operations. The test works by applying a controlled-unitary operation between an auxiliary qubit and the system of interest, with the measurement statistics of the auxiliary qubit encoding information about the unitary's expectation value. | ||
| >>>>>>> Stashed changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed that these were not merged, miss by myself. Can update this in a following revision, pending comments from reviewers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, please address this also
mbeach-aws
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was really excellent! Thanks for adding this functionality.
| "# controlled_unitary = Circuit().z(0)\n", | ||
| "# ht_circuit = hadamard_test_circuit(controlled_unitary)\n", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can uncomment this and run on Garnet before we merge the PR if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be great!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "# controlled_unitary = Circuit().z(0)\n", | |
| "# ht_circuit = hadamard_test_circuit(controlled_unitary)\n", | |
| "# controlled_unitary = Circuit().z(0)\n", | |
| "# ht_circuit = hadamard_test_circuit(Qubit(0), controlled_unitary)\n", |
| ======= | ||
| The Hadamard test is a quantum circuit that allows estimation of the real and imaginary parts of the expected value of a unitary operator. It is a fundamental subroutine used in many quantum algorithms, including quantum phase estimation where it helps extract eigenvalue information through controlled operations. The test works by applying a controlled-unitary operation between an auxiliary qubit and the system of interest, with the measurement statistics of the auxiliary qubit encoding information about the unitary's expectation value. | ||
| >>>>>>> Stashed changes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, please address this also
| circ.h(0) | ||
| if component == 'imaginary': | ||
| circ.s(0).adjoint() | ||
|
|
||
| # Add control qubit to the unitary circuit | ||
| for inst in controlled_unitary.instructions: | ||
| targets = [q + 1 for q in inst.target] | ||
| controlled_inst = Instruction( | ||
| operator=inst.operator, | ||
| target=targets, | ||
| control=0 | ||
| ) | ||
| circ.add_instruction(controlled_inst) | ||
|
|
||
| circ.h(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we generalize this to work on an ancilla qubit(s) q0 instead of hard-coded 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, great call-out
| device = LocalSimulator() | ||
| task = device.run(test_circuit, shots=10000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could mock the results rather than running a true simulation during unit tests. Especially since the probabilistic nature of shots=10_000 and atol=0.1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like standard in this package is not to mock but use .isclose(). Happy to do the mocking, or I can run some further tests / loosen the bounds to ensure we are probabilistically safe "enough".
813a05d to
181aa75
Compare
mbeach-aws
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The notebook doesn't seem to use the updated hadamard_test_circuit with an ancilla qubit. It only shows a control unitary as the argument.
181aa75 to
910819d
Compare
| "source": [ | ||
| "## Run on a QPU \n", | ||
| "\n", | ||
| "To run the Hadamard test on a QPU, we replace the LocalSimulator with an AwsDevice. The cost to run this experiment is $0.3 per task and $0.00145 per shot on the IQM Garnet device, that totals $1.75 USD. Because Garnet does not support arbitrary unitary operators, we will directly apply the Pauli-Z gate in this example." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "To run the Hadamard test on a QPU, we replace the LocalSimulator with an AwsDevice. The cost to run this experiment is $0.3 per task and $0.00145 per shot on the IQM Garnet device, that totals $1.75 USD. Because Garnet does not support arbitrary unitary operators, we will directly apply the Pauli-Z gate in this example." | |
| "To run the Hadamard test on a QPU, we replace the LocalSimulator with an AwsDevice. The cost to run this experiment is \\\\$0.3 per task and \\\\$0.00145 per shot on the IQM Garnet device, which totals \\\\$1.75 USD. Because Garnet does not support arbitrary unitary operators, we will directly apply the Pauli-Z gate in this example." |
|
Unfortunately the cell to run on hardware doesn't work; it gives the error Hardware devices don't currently support the ctrl gate modifier (because the Braket SDK currently treats them as arbitrary unitaries). Is there something else we can do here? |
| "from notebook_plotting import plot_bitstrings_formatted\n", | ||
| "import numpy as np\n", | ||
| "\n", | ||
| "%matplotlib inline\n", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "%matplotlib inline\n", |
This shouldn't be needed for modern Jupyter versions.
This PR addresses issue #72.
Description of changes: This PR adds the Hadamard test to the library's implemented algorithms, with an optional flag that can be toggled for estimating either the real or imaginary part of the controlled unitary. An extension could be implementing the modified hadamard test, which could possibly make use of Amplitude amplification (Issue #100).
Testing done: Unit tests and notebook created.
Merge Checklist
Put an
xin the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.General
Tests
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.