Skip to content
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

Merged
merged 27 commits into from
Mar 22, 2021
Merged

Support inverse gates #89

merged 27 commits into from
Mar 22, 2021

Conversation

trbromley
Copy link
Contributor

No description provided.

@codecov
Copy link

codecov bot commented Mar 16, 2021

Codecov Report

Merging #89 (6e59a18) into master (fd41d8f) will increase coverage by 0.10%.
The diff coverage is 100.00%.

❗ Current head 6e59a18 differs from pull request most recent head 006ff7f. Consider uploading reports for the commit 006ff7f to get more accurate results
Impacted file tree graph

@@            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              
Impacted Files Coverage Δ
pennylane_lightning/lightning_qubit.py 97.95% <100.00%> (+0.13%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update fd41d8f...006ff7f. Read the comment docs.

Comment on lines 77 to 99
kernel_operations = {
"PauliX",
"PauliY",
"PauliZ",
"Hadamard",
"Hadamard",
"S",
"T",
"RX",
"RY",
"RZ",
"PhaseShift",
"Rot",
"CNOT",
"SWAP",
"CZ",
"CRX",
"CRY",
"CRZ",
"CRot",
"Toffoli",
"CSWAP",
}
Copy link
Contributor Author

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.

Copy link
Contributor

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
Copy link
Contributor Author

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.

@trbromley
Copy link
Contributor Author

The performance comparison looks like no change vs master (as expected):
image

@trbromley trbromley marked this pull request as ready for review March 18, 2021 18:32
@trbromley trbromley requested review from antalszava and thisac March 18, 2021 18:32
Copy link
Contributor

@antalszava antalszava left a 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?

pennylane_lightning/lightning_qubit.py Show resolved Hide resolved
pennylane_lightning/lightning_qubit.py Outdated Show resolved Hide resolved
Comment on lines 77 to 99
kernel_operations = {
"PauliX",
"PauliY",
"PauliZ",
"Hadamard",
"Hadamard",
"S",
"T",
"RX",
"RY",
"RZ",
"PhaseShift",
"Rot",
"CNOT",
"SWAP",
"CZ",
"CRX",
"CRY",
"CRZ",
"CRot",
"Toffoli",
"CSWAP",
}
Copy link
Contributor

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/Apply.cpp Outdated Show resolved Hide resolved
pennylane_lightning/src/Apply.hpp Outdated Show resolved Hide resolved
@@ -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
Copy link
Contributor

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?

Copy link

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.

Copy link
Contributor

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).

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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

pennylane_lightning/src/Gates.cpp Outdated Show resolved Hide resolved
tests/test_gates.py Outdated Show resolved Hide resolved
return getattr(qml, op_name)


@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations)
Copy link
Contributor

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

Copy link
Contributor Author

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 😆

Copy link
Contributor

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

  1. Call on the device test suite from the lightning tests (not quite sure about the best way to do this 🤔 )
  2. 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.

Copy link
Contributor Author

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).



@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations)
def test_inverse_unitary_correct(op):
Copy link
Contributor

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.

Copy link

@thisac thisac left a 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.

Comment on lines -88 to +112
supports_inverse_operations=False,
supports_inverse_operations=True,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥳

pennylane_lightning/lightning_qubit.py Outdated Show resolved Hide resolved
@@ -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
Copy link

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.

pennylane_lightning/src/Gates.cpp Outdated Show resolved Hide resolved
Copy link
Contributor Author

@trbromley trbromley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pennylane_lightning/lightning_qubit.py Outdated Show resolved Hide resolved
pennylane_lightning/lightning_qubit.py Show resolved Hide resolved
@@ -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
Copy link
Contributor Author

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.

pennylane_lightning/src/Gates.cpp Outdated Show resolved Hide resolved
return getattr(qml, op_name)


@pytest.mark.parametrize("op_name", LightningQubit.kernel_operations)
Copy link
Contributor Author

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 😆

@trbromley
Copy link
Contributor Author

trbromley commented Mar 19, 2021

Also, would we like to unit test the kernel applications?

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 applyKernel(), even if they are not exactly unit tests.

@trbromley trbromley requested a review from antalszava March 19, 2021 18:14
Copy link
Contributor

@antalszava antalszava left a 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 😊

@trbromley trbromley merged commit 457bc55 into master Mar 22, 2021
@trbromley trbromley deleted the support_inverse_gates branch March 22, 2021 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants