-
Notifications
You must be signed in to change notification settings - Fork 604
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
PrepSelPrep template #5756
PrepSelPrep template #5756
Conversation
Adding PrepSelPrep template and tests
@soranjh This is the PR for the PrepSelPrep template. |
@soranjh The PR is ready for review. |
Good catch. I renamed the module to be consistent with the name you used originally, but the old file didn't get removed. I'll get rid of it. |
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.
Thanks @willjmax, left three high-level comments.
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.
Hello @willjmax. Thank you for working on this template.
Here are three comments that will help you to complete the tests
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.
Great work so far, I left a few comments and suggestions for you to tackle to fix up the implementation. Feel free to re-request a review once you have addressed the feedback.
Let us know if you require any clarification.
@soranjh Thanks. I will have time to address these comments tomorrow. Edit: I was able to do this tonight. |
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.
@soranjh Please see my comments about your counterexample LCU.
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.
Thanks @willjmax, definitely a very useful template
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.
looks good to me
This PR introduces a template implementing `qml.PrepSelPrep` to perform a block encoding on a linear combination of unitaries. This is a work in progress as it does not yet support autograd or JAX. It can be used in the following way. ``` lcu = qml.dot([0.25, 0.75], [qml.Z(2), qml.X(1) @ qml.X(2)]) dev = qml.device('default.qubit') @qml.qnode(dev) def circuit(): qml.PrepSelPrep(lcu, control = 0) return qml.state() ``` Which is equivalent to ``` coeffs, unitaries = lcu.terms() normalized_coeffs = np.sqrt(coeffs) / np.linalg.norm(np.sqrt(coeffs)) @qml.qnode(dev) def circuit(): qml.StatePrep(normalized_coeffs, wires=0) qml.Select(unitaries, control=0) qml.adjoint(qml.StatePrep(normalized_coeffs, wires=0)) ``` The tests in `test_prepselprep.py` pass, and are inspired by similar tests found in `test_select.py`. However, feedback on two tests would be appreciated. 1) In the `assert_valid` test, within `_check_decomposition`, there is a check to see if the operations in the decomposition match the operations in the queue. I was able to get this test to pass by adding `with qml.QueuingManager.stop_recording()` to the decomposition function. The decomposition function calls `qml.Select` and `qml.StatePrep`, so my best guess is that the operations were being added to the queue twice: once in `qml.PrepSelPrep` and again in the two subroutines. I haven't figured out how the queue works yet, so this could be totally wrong. 2) In `assert_valid` the `_check_pytree` test fails when JAX is available, but passes otherwise. Here are two proposed autograd tests, each based off of the one found in `test_select.py`, and both fail in different ways. These are not full tests, but stripped down to the minimum required to produce the errors. ``` def test_autograd1(): dev = qml.device("default.qubit") coeffs = pnp.array([1/2, 1/2], requires_grad=True) ops = [qml.Identity(1), qml.PauliZ(1)] lcu = qml.dot(coeffs, ops) @qml.qnode(dev) def circuit(coeffs, ops): lcu = qml.dot(coeffs, ops) qml.PrepSelPrep(lcu, control=0) return qml.expval(qml.Identity(1)) qml.grad(circuit)(coeffs, ops) def test_autograd2(): dev = qml.device("default.qubit") coeffs = pnp.array([1/2, 1/2], requires_grad=True) ops = [qml.Identity(1), qml.PauliZ(1)] lcu = qml.dot(coeffs, ops) @qml.qnode(dev) def circuit(lcu): qml.PrepSelPrep(lcu, control=0) return qml.expval(qml.Identity(1)) qml.grad(circuit)(lcu) ``` 1) `test_autograd1` fails with the error `TypeError: loop of ufunc does not support argument 0 of type ArrayBox which has no callable sqrt method`. This is being caused within the decomposition function by the line `normalized_coeffs = np.sqrt(coeffs) / np.linalg.norm(np.sqrt(coeffs))`. The issue is that `coeffs` is a list of autograd Arrayboxes and `np.sqrt` cannot be called on them. I think I should be using the functions in `qml.math` as they will check the types of the input and call the appropriate functions, but there is no `qml.math.sqrt` to call. 2) `test_autograd2` passes, but with a warning since `lcu` is of type `pennylane.ops.op_math.sum.Sum` and does not have a `requires_grad` attribute. Attempting to force it to differentiate with `qml.grad(circuit, argnum=0)` results in a type error since `pennylane.ops.op_math.sum.Sum` is not differentiable. **Related GitHub Issues:** PennyLaneAI#5739 --------- Co-authored-by: soranjh <[email protected]> Co-authored-by: soranjh <[email protected]>
This PR introduces a template implementing
qml.PrepSelPrep
to perform a block encoding on a linear combination of unitaries. This is a work in progress as it does not yet support autograd or JAX. It can be used in the following way.Which is equivalent to
The tests in
test_prepselprep.py
pass, and are inspired by similar tests found intest_select.py
. However, feedback on two tests would be appreciated.In the
assert_valid
test, within_check_decomposition
, there is a check to see if the operations in the decomposition match the operations in the queue. I was able to get this test to pass by addingwith qml.QueuingManager.stop_recording()
to the decomposition function. The decomposition function callsqml.Select
andqml.StatePrep
, so my best guess is that the operations were being added to the queue twice: once inqml.PrepSelPrep
and again in the two subroutines. I haven't figured out how the queue works yet, so this could be totally wrong.In
assert_valid
the_check_pytree
test fails when JAX is available, but passes otherwise.Differentiation
Here are two proposed autograd tests, each based off of the one found in
test_select.py
, and both fail in different ways. These are not full tests, but stripped down to the minimum required to produce the errors.test_autograd1
fails with the errorTypeError: loop of ufunc does not support argument 0 of type ArrayBox which has no callable sqrt method
. This is being caused within the decomposition function by the linenormalized_coeffs = np.sqrt(coeffs) / np.linalg.norm(np.sqrt(coeffs))
. The issue is thatcoeffs
is a list of autograd Arrayboxes andnp.sqrt
cannot be called on them. I think I should be using the functions inqml.math
as they will check the types of the input and call the appropriate functions, but there is noqml.math.sqrt
to call.test_autograd2
passes, but with a warning sincelcu
is of typepennylane.ops.op_math.sum.Sum
and does not have arequires_grad
attribute. Attempting to force it to differentiate withqml.grad(circuit, argnum=0)
results in a type error sincepennylane.ops.op_math.sum.Sum
is not differentiable.Related GitHub Issues: #5739