-
Notifications
You must be signed in to change notification settings - Fork 39
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
Support inverse gates #89
Conversation
Codecov Report
@@ Coverage Diff @@
## master #89 +/- ##
==========================================
+ Coverage 98.03% 98.14% +0.10%
==========================================
Files 3 3
Lines 51 54 +3
==========================================
+ Hits 50 53 +3
Misses 1 1
Continue to review full report at Codecov.
|
kernel_operations = { | ||
"PauliX", | ||
"PauliY", | ||
"PauliZ", | ||
"Hadamard", | ||
"Hadamard", | ||
"S", | ||
"T", | ||
"RX", | ||
"RY", | ||
"RZ", | ||
"PhaseShift", | ||
"Rot", | ||
"CNOT", | ||
"SWAP", | ||
"CZ", | ||
"CRX", | ||
"CRY", | ||
"CRZ", | ||
"CRot", | ||
"Toffoli", | ||
"CSWAP", | ||
} |
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.
These are the gates that have a kernel supported. Ideally, we would not explicitly set operations
and just let it inherit from default.qubit
. We'd then have a check in apply_lightning()
that maps the operations to QubitUnitary
if the operation is not in kernel_operations
. In such a way, we're supporting essentially all ops, even without a kernel.
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.
That's a good idea! Adding this set here seems to be out of scope for the PR, would this be related to the upcoming QubitUnitary
addition?
) | ||
|
||
|
||
@pytest.mark.xfail(strict=True) # needs support for QubitUnitary |
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.
When we add support for arbitrary unitaries, this will be a nice test for gates without a pre-defined kernel.
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 @trbromley! 💯 My main question is related to whether we'd like to have new gate tests here apart from what's there in the device test suite. Also, would we like to unit test the kernel applications?
kernel_operations = { | ||
"PauliX", | ||
"PauliY", | ||
"PauliZ", | ||
"Hadamard", | ||
"Hadamard", | ||
"S", | ||
"T", | ||
"RX", | ||
"RY", | ||
"RZ", | ||
"PhaseShift", | ||
"Rot", | ||
"CNOT", | ||
"SWAP", | ||
"CZ", | ||
"CRX", | ||
"CRY", | ||
"CRZ", | ||
"CRot", | ||
"Toffoli", | ||
"CSWAP", | ||
} |
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.
That's a good idea! Adding this set here seems to be out of scope for the PR, would this be related to the upcoming QubitUnitary
addition?
pennylane_lightning/src/Gates.cpp
Outdated
@@ -89,7 +98,8 @@ const vector<CplxType> Pennylane::XGate::matrix{ | |||
0, 1, | |||
1, 0 }; | |||
|
|||
void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector<size_t>& indices, const std::vector<size_t>& externalIndices) { | |||
void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector<size_t>& indices, const std::vector<size_t>& externalIndices, bool inverse) { | |||
(void)inverse; // gate is its own inverse |
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.
For my own understanding: what is the purpose of this statement?
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.
As far as I understand, it simply avoids the something-something-arg-not-used warning. So it's basically just "using" the inverse arg without doing anything.
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.
Hmm, how come we didn't have such warning for applyKernel
? 🤔 We had a thread with Thomas on this here: #85 (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.
Yes, I think it's motivated for two reasons:
- So we won't get the warnings:
pennylane_lightning/src/Gates.cpp:101:147: warning: unused parameter ‘inverse’ [-Wunused-parameter]
- I like having something that explicitly says the gate is it's own inverse. In other words, we're saying that we know about the
inverse
argument and don't need to do anything in this case, rather than we just forgot about it.
It'll work either way, so if we're opposed to having this line then I can remove. I don't think this has any performance implications, seems like something more for the compiler.
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.
Got it! It's odd that this warning is emitted 🤔 This is a personal opinion, but the statement looks confusing to me, as it's type casting a boolean to void
without any effect. To me, having the parameter unnamed would make up for the unused parameter. The comment is indeed nice to indicate that the gate is its own inverse.
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.
Ok, updated to just have a commend and an unnamed param: fcd1c29
tests/test_gates.py
Outdated
return getattr(qml, op_name) | ||
|
||
|
||
@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) |
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.
Isn't this test case covered by running the device test suite? See pennylane/devices/tests/test_gates.py
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.
That's a good point! From a quick look through those tests, I agree that they provide similar coverage to what's here. I'm generally happy to have some redundancy because:
- This is directly in
lightning.qubit
and it is easier for developers to quickly see this failing (often, at least for me, running the dev test suite is more of an afterthought) - I didn't see this exact test in the suite, so maybe there is some edge case covered (not sure)!
Really, having it here explicitly makes me feel more confident that things are definitely working 😆
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.
Agreed 🤔 Calling the device test suite can be overlooked. Could we
- Call on the device test suite from the lightning tests (not quite sure about the best way to do this 🤔 )
- extend
make test
with the device test command?
For 1), we could maybe call pl-device-test
from one of the test files 🤔
My worry is that we'd start off adding test cases here which will essentially diverge from the device test suite and we'll have to maintain both.
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 I agree maintainability is important! Because I'm paranoid about double making sure that things work correctly now for lightning.qubit
, I still prefer to potentially have some repetition with a benefit of increased confidence. If down the line we see issues with these local tests, we could delete them (and potentially update the dev test suite accordingly).
tests/test_gates.py
Outdated
|
||
|
||
@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) | ||
def test_inverse_unitary_correct(op): |
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.
Similarly seems to be covered by the test suite.
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.
Nice work @trbromley! 🥇
I have the same thought as @antalszava whether we want to add unit tests for the applyKernel
functions, although I wouldn't mind if we decided to add them in a separate PR.
supports_inverse_operations=False, | ||
supports_inverse_operations=True, |
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.
🥳
pennylane_lightning/src/Gates.cpp
Outdated
@@ -89,7 +98,8 @@ const vector<CplxType> Pennylane::XGate::matrix{ | |||
0, 1, | |||
1, 0 }; | |||
|
|||
void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector<size_t>& indices, const std::vector<size_t>& externalIndices) { | |||
void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector<size_t>& indices, const std::vector<size_t>& externalIndices, bool inverse) { | |||
(void)inverse; // gate is its own inverse |
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.
As far as I understand, it simply avoids the something-something-arg-not-used warning. So it's basically just "using" the inverse arg without doing anything.
Co-authored-by: antalszava <antalszava@gmail.com>
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 @antalszava @thisac!
pennylane_lightning/src/Gates.cpp
Outdated
@@ -89,7 +98,8 @@ const vector<CplxType> Pennylane::XGate::matrix{ | |||
0, 1, | |||
1, 0 }; | |||
|
|||
void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector<size_t>& indices, const std::vector<size_t>& externalIndices) { | |||
void Pennylane::XGate::applyKernel(const StateVector& state, const std::vector<size_t>& indices, const std::vector<size_t>& externalIndices, bool inverse) { | |||
(void)inverse; // gate is its own inverse |
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, I think it's motivated for two reasons:
- So we won't get the warnings:
pennylane_lightning/src/Gates.cpp:101:147: warning: unused parameter ‘inverse’ [-Wunused-parameter]
- I like having something that explicitly says the gate is it's own inverse. In other words, we're saying that we know about the
inverse
argument and don't need to do anything in this case, rather than we just forgot about it.
It'll work either way, so if we're opposed to having this line then I can remove. I don't think this has any performance implications, seems like something more for the compiler.
tests/test_gates.py
Outdated
return getattr(qml, op_name) | ||
|
||
|
||
@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations) |
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.
That's a good point! From a quick look through those tests, I agree that they provide similar coverage to what's here. I'm generally happy to have some redundancy because:
- This is directly in
lightning.qubit
and it is easier for developers to quickly see this failing (often, at least for me, running the dev test suite is more of an afterthought) - I didn't see this exact test in the suite, so maybe there is some edge case covered (not sure)!
Really, having it here explicitly makes me feel more confident that things are definitely working 😆
It's a good question 🤔 My thinking is that we can move much more quickly when writing Python tests, so if we can access and test from the Python side then we should. I think the Python tests here manage to already provide a nice check of |
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! 💯 Awesome that we can now also support inverses 😊
No description provided.