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

Add support for float and double precision data #113

Merged
merged 55 commits into from
Jul 28, 2021
Merged

Conversation

mlxd
Copy link
Member

@mlxd mlxd commented Jul 20, 2021

Context: This PR will enable support for 64bit and 128bit complex datatypes, as well as restructuring the package class to allow for this extension.

Description of the Change: To enable the above, several modifications were required:

  • All gates kernels previously defined in Gates.hppand Gates.cpp are now part of the StateVector class, with gate numeric values accessible in Gates.hpp.
  • The apply functionality from Apply.hpp and Apply.cpp has been added to the StateVector class directly
  • The StateVector class was converted to a templated class, allowing all above functions to be compiled with the correct data types.
  • The C++ version was bumped from 11 to 17, to allow for use of newer features (inline static const, template argument deduction, constexpr if)
  • The StateVector class and methods can now be directly accessed from Python, using the StateVectorC64 and StateVectorC128 types. Use will require adaption of core Python implementation to utilise.
  • Tests based on the previous architecture format were removed and updated with Catch2.

Benefits: This enables use of data-types previously unavailable without casting (np.complex64), and will allow for memory and performance savings when used. Features spread over multiple additional classes and files are now made redundant, allowing for a more straight-forward implementation.

Possible Drawbacks: Structure of StateVector class has increased in size.

Related GitHub Issues:

@github-actions
Copy link
Contributor

Hello. You may have forgotten to update the changelog!
Please edit .github/CHANGELOG.md with:

  • A one-to-two sentence description of the change. You may include a small working example for new features.
  • A link back to this PR.
  • Your name (or GitHub username) in the contributors section.

@codecov
Copy link

codecov bot commented Jul 20, 2021

Codecov Report

Merging #113 (e95ec7b) into master (550ee8a) will not change coverage.
The diff coverage is 100.00%.

❗ Current head e95ec7b differs from pull request most recent head 85aad92. Consider uploading reports for the commit 85aad92 to get more accurate results
Impacted file tree graph

@@           Coverage Diff           @@
##           master     #113   +/-   ##
=======================================
  Coverage   98.14%   98.14%           
=======================================
  Files           3        3           
  Lines          54       54           
=======================================
  Hits           53       53           
  Misses          1        1           
Impacted Files Coverage Δ
pennylane_lightning/lightning_qubit.py 97.95% <100.00%> (ø)

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 550ee8a...85aad92. Read the comment docs.

@trbromley
Copy link
Contributor

trbromley commented Jul 23, 2021

[ch7526]
[ch7552]
[ch7067]

Copy link
Contributor

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

Thanks @mlxd! This looks to have tidied things up nicely 💯

CMakeLists.txt Show resolved Hide resolved
pennylane_lightning/lightning_qubit.py Show resolved Hide resolved
pennylane_lightning/lightning_qubit.py Show resolved Hide resolved
pennylane_lightning/src/Bindings.cpp Outdated Show resolved Hide resolved
pennylane_lightning/src/Bindings.cpp Show resolved Hide resolved
Comment on lines 96 to 103
StateVector(CFP_t *arr, size_t length)
: arr_{arr}, length_{length}, num_qubits_{Util::log2(length_)},
gate_wires_{
{"PauliX", 1}, {"PauliY", 1}, {"PauliZ", 1}, {"Hadamard", 1},
{"T", 1}, {"S", 1}, {"RX", 1}, {"RY", 1},
{"RZ", 1}, {"Rot", 1}, {"PhaseShift", 1}, {"CNOT", 2},
{"SWAP", 2}, {"CZ", 2}, {"CRX", 2}, {"CRY", 2},
{"CRZ", 2}, {"CRot", 2}, {"CSWAP", 3}, {"Toffoli", 3}},
Copy link
Contributor

Choose a reason for hiding this comment

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

I got a bit lost here, would you be able to give a quick rundown of what's going on?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure thing. The previous implementation had some logic to check the gate classes for the number of supported wires to act upon. Since the classes are now methods, the mapping of a gate label to supported wires needed to be elsewhere. I created a private dictionary to map between gate labels and the number of supported wires (gate_wires_). This allows minimal changes to the apply methods to match the older functionality.

Since the dictionary is declared as const it must be initialised with this initialiser list syntax. Though, we can move these to a inline static const / constexpr and put it outside the class instantiation, though for now I think this is fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks!

Comment on lines 192 to 236
static constexpr vector<CFP_t> getPauliX() {
return {ZERO, ONE, ONE, ZERO};
}
static constexpr vector<CFP_t> getPauliY() {
return {ZERO, -IMAG, IMAG, ZERO};
}
static constexpr vector<CFP_t> getPauliZ() {
return {ONE, ZERO, ZERO, -ONE};
}
static constexpr vector<CFP_t> getHadamard() {
return {INVSQRT2, INVSQRT2, INVSQRT2, -INVSQRT2};
}
static constexpr vector<CFP_t> getS() { return {ONE, ZERO, ZERO, IMAG}; }
static constexpr vector<CFP_t> getT() { return {ONE, ZERO, ZERO, IMAG}; }
static constexpr vector<CFP_t> getCNOT() {
return {ONE, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO,
ZERO, ZERO, ZERO, ONE, ZERO, ZERO, ONE, ZERO};
}
static constexpr vector<CFP_t> getSWAP() {
return {ONE, ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO,
ZERO, ONE, ZERO, ZERO, ZERO, ZERO, ZERO, ONE};
}
static constexpr vector<CFP_t> getCZ() {
return {ONE, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO,
ZERO, ZERO, ONE, ZERO, ZERO, ZERO, ZERO, -ONE};
}

static constexpr vector<CFP_t> getCSWAP() {
return {ONE, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE,
ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO,
ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ONE, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ONE};
}
static constexpr vector<CFP_t> getToffoli() {
return {ONE, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE,
ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO,
ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO, ZERO, ZERO,
ZERO, ZERO, ZERO, ZERO, ZERO, ONE, ZERO, ZERO, ZERO, ZERO,
ZERO, ZERO, ONE, ZERO};
}
Copy link
Contributor

Choose a reason for hiding this comment

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

If I understand correctly, these aren't used anywhere but are just defined for completeness?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes. These were all defined for each gate class so I implemented them for brevity. Since we do not use them here though it may be fine to move them to a separate header/class. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we just remove them entirely (unless we expect to use in future?)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yep, pulling them out of here seems fine. I use some of these for the tests, and I think it will be good practice to allow pulling the gate definition out as needed, so will likely just move these to their own namespace Pennylane::Gates and allow them to be called from there.

pennylane_lightning/src/Util.hpp Show resolved Hide resolved
mlxd added 2 commits July 26, 2021 09:49
…ntation (#115)

* Add preliminary catch2 support

* Move private methods to public for testing

* Overload applyOperations for param and non param calls

* Add testing support for X,Y,Z,H gates

* Add S, T gate tests

* Add support for RX,RY,RZ gate tests

* Add PhaseShift gate tests

* Add Rot tests

* Add CNOT tests

* Add support for CSWAP, Toffoli, CZ, CRot tests

* Update testing CI

* Fix CodeFactor complaints

* Update CI image before running tests

* Favour use of reverse iterator over counter in for loops

* Fix contructor tests

* Fix formatting

* Fix narrowing complaints

* Fix MSVC math errors

* Run black

* Remove unneeded ops for real*complex products

* Fix test builder

* Ensure cmake has a version to avoid warnings

* Fix formatting of SV

* Fix test reporting
@github-actions
Copy link
Contributor

github-actions bot commented Jul 26, 2021

Test Report (C++) on Ubuntu

    1 files  ±0      1 suites  ±0   0s ⏱️ ±0s
118 tests ±0  118 ✔️ ±0  0 💤 ±0  0 ❌ ±0 
370 runs  ±0  370 ✔️ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit bdf8aa8. ± Comparison against base commit bdf8aa8.

♻️ This comment has been updated with latest results.

Copy link
Contributor

@trevor-vincent trevor-vincent left a comment

Choose a reason for hiding this comment

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

Really awesome work Lee. I left a few comments. Since I just joined, it might be due to my lack of familiarity, but I was wondering why there are gate definitions in two different places in the code, e.g. getCSWAP in StateVector.hpp and CSWAP in GateData.hpp, is this a necessity?

CMakeLists.txt Show resolved Hide resolved
const FMap gates_;
const std::unordered_map<string, size_t> gate_wires_;

CFP_t *const arr_;
Copy link
Contributor

Choose a reason for hiding this comment

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

should we change to smart pointers? e.g unique_ptr?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a carry-over of the original design which does state-prep in numpy. To access the numpy data we point the above pointer to it via the available binding logic. I wish to completely remove the numpy prep (to be followed in a subsequent PR) and replace it with a std::vector in Cpp.

For now, I'd rather not tamper with the existing implementation (shared would be best, but not sure how numpy would handle it), since CPP doesn't own the pointer, merely just operates on it.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds like a good plan

/**
* @brief Get indices not participating in operation.
*
* @param indicesToExclude
Copy link
Contributor

@trevor-vincent trevor-vincent Jul 26, 2021

Choose a reason for hiding this comment

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

Missing some description here for the parameters I think.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yea, the docs need to follow. We have a story created for this, as the entire class docs need an update.

@mlxd
Copy link
Member Author

mlxd commented Jul 26, 2021

Really awesome work Lee. I left a few comments. Since I just joined, it might be due to my lack of familiarity, but I was wondering why there are gate definitions in two different places in the code, e.g. getCSWAP in StateVector.hpp and CSWAP in GateData.hpp, is this a necessity?

GateData.hpp was a carry-over from the googletest suite. I updated them, then decided to pull them out. You are completely correct that it can be pulled. I'll removed all the remnants of the old testing suite.

@mlxd
Copy link
Member Author

mlxd commented Jul 27, 2021

Recent changes have pulled the gate definitions from the class (fixes the CodeFactor complaint on StateVector), moved them to their own separate namespace, and used these to assist in the tests. This also fixed the second CodeFactor complaint.

I think anything else needed removal of unused libs can be moved to a separate PR and story once we have some spare time.

@mlxd mlxd requested review from trevor-vincent and trbromley July 27, 2021 09:11
Copy link
Contributor

@trevor-vincent trevor-vincent 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!

Copy link
Contributor

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

💯

### Improvements

- C++ tests have been ported to use Catch2 framework. ([#115](https://github.com/PennyLaneAI/pennylane-lightning/pull/115))

- Testing now exists for both float and double precision methods in C++ layer. ([#113](https://github.com/PennyLaneAI/pennylane-lightning/pull/113),[#115](https://github.com/PennyLaneAI/pennylane-lightning/pull/115))
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Testing now exists for both float and double precision methods in C++ layer. ([#113](https://github.com/PennyLaneAI/pennylane-lightning/pull/113),[#115](https://github.com/PennyLaneAI/pennylane-lightning/pull/115))
- Testing now exists for both float and double precision methods in C++ layer. ([#113](https://github.com/PennyLaneAI/pennylane-lightning/pull/113), [#115](https://github.com/PennyLaneAI/pennylane-lightning/pull/115))

@mlxd
Copy link
Member Author

mlxd commented Jul 28, 2021

I will update the implementation for the new gate, then merge.

@mlxd mlxd merged commit bdf8aa8 into master Jul 28, 2021
@mlxd mlxd deleted the 7067-templated-float branch July 28, 2021 18:19
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