From 174addc312dbebdb9ad189b0a3467f7a62561319 Mon Sep 17 00:00:00 2001 From: Thomas Germain Date: Fri, 8 Mar 2024 16:32:02 -0500 Subject: [PATCH 01/30] collapse() and normalized() with Kokkos --- .../lightning_kokkos/StateVectorKokkos.hpp | 56 +++++++++++++++++++ .../gates/GateFunctorsGenerator.hpp | 31 ++++++++++ .../tests/Test_StateVectorLKokkos.cpp | 41 +++++++++++++- .../core/src/utils/TestHelpers.hpp | 13 +++++ 4 files changed, 140 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 87ac3b302a..de6d05ee74 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -757,6 +757,62 @@ class StateVectorKokkos final return -static_cast(0.5); } + /** + * @brief Collapse the state vector as after having measured one of the + * qubits. + * + * The branch parameter imposes the measurement result on the given wire. + * + * @param wire Wire to collapse. + * @param branch Branch 0 or 1. + */ + void collapse(const std::size_t wire, const bool branch) { + + // file:///home/thomas.germain/Downloads/KokkosTutorial_04_HierarchicalParallelism.pdf + // pp. 14, 20, 26, + + auto &&num_qubits = this->getNumQubits(); + + const size_t stride = pow(2, num_qubits_ - (1 + wire)); + const size_t vec_size = pow(2, num_qubits_); + const auto section_size = vec_size / stride; + const auto half_section_size = section_size / 2; + + const size_t negbranch = branch ? 0 : 1; + + Kokkos::MDRangePolicy policy_2d( + {0, 0}, {half_section_size, stride}); + Kokkos::parallel_for( + policy_2d, + collapseFunctor(*data_, num_qubits, stride, negbranch)); + + normalize(); + } + + /** + * @brief Normalize vector (to have norm 1). + */ + void normalize() { + KokkosVector sv_view = + getView(); // circumvent error capturing this with KOKKOS_LAMBDA + + // TODO: @tomlqc what about squaredNorm() + PrecisionT squaredNorm = 0.0; + Kokkos::parallel_reduce( + sv_view.size(), + KOKKOS_LAMBDA(const size_t i, PrecisionT &sum) { + sum += std::norm(sv_view(i)); + }, + squaredNorm); + + // TODO: @tomlqc add PL_ABORT_IF + + std::complex inv_norm = 1. / std::sqrt(squaredNorm); + Kokkos::parallel_for( + sv_view.size(), + KOKKOS_LAMBDA(const size_t i) { sv_view(i) *= inv_norm; }); + } + /** * @brief Update data of the class * diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/GateFunctorsGenerator.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/GateFunctorsGenerator.hpp index eea42d7937..9abcf744f3 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/GateFunctorsGenerator.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/GateFunctorsGenerator.hpp @@ -972,4 +972,35 @@ template struct generatorMultiRZFunctor { 1 - 2 * int(Kokkos::Impl::bit_count(k & wires_parity) % 2)); } }; + +template struct collapseFunctor { + using ComplexT = Kokkos::complex; + using KokkosComplexVector = Kokkos::View; + + KokkosComplexVector arr; + std::size_t num_qubits; + std::size_t stride; + std::size_t negbranch; + + collapseFunctor(KokkosComplexVector &arr_, std::size_t num_qubits_, + std::size_t stride_, std::size_t negbranch_) { + arr = arr_; + num_qubits = num_qubits_; + stride = stride_; + negbranch = negbranch_; + } + + // zero half the entries + // the "half" entries depend on the stride + // *_*_*_*_ for stride 1 + // **__**__ for stride 2 + // ****____ for stride 4 + + KOKKOS_INLINE_FUNCTION + void operator()(const std::size_t left, const std::size_t right) const { + const size_t offset = stride * (negbranch + 2 * left); + arr[offset + right] = ComplexT{0., 0.}; + } +}; + } // namespace Pennylane::LightningKokkos::Functors \ No newline at end of file diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp index d238b3b5cb..14fc3071e8 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp @@ -308,4 +308,43 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::StateVectorKokkos", REQUIRE(sv.getDataVector() == data_); // REQUIRE(sv.getDataVector() == approx(st_data)); } -} \ No newline at end of file +} + +TEMPLATE_TEST_CASE("StateVectorKokkos::collapse", "[StateVectorKokkos]", float, + double) { + using PrecisionT = TestType; + using ComplexT = typename StateVectorKokkos::ComplexT; + using TestVectorT = TestVector; + + const std::size_t num_qubits = 3; + + // TODO @tomlqc use same template for testing all Lightning flavours? + + SECTION("Collapse the state vector as after having measured one of the " + "qubits.") { + TestVectorT init_state = createPlusState_(num_qubits); + + const ComplexT coef{0.5, PrecisionT{0.0}}; + const ComplexT zero{PrecisionT{0.0}, PrecisionT{0.0}}; + + std::vector>> expected_state = { + {{coef, coef, coef, coef, zero, zero, zero, zero}, + {coef, coef, zero, zero, coef, coef, zero, zero}, + {coef, zero, coef, zero, coef, zero, coef, zero}}, + {{zero, zero, zero, zero, coef, coef, coef, coef}, + {zero, zero, coef, coef, zero, zero, coef, coef}, + {zero, coef, zero, coef, zero, coef, zero, coef}}, + }; + + std::size_t wire = GENERATE(0, 1, 2); + std::size_t branch = GENERATE(0, 1); + StateVectorKokkos sv( + reinterpret_cast(init_state.data()), init_state.size()); + sv.collapse(wire, branch); + + PrecisionT eps = std::numeric_limits::epsilon() * 10e3; + REQUIRE(isApproxEqual(sv.getData(), sv.getDataVector().size(), + expected_state[branch][wire].data(), + expected_state[branch][wire].size(), eps)); + } +} diff --git a/pennylane_lightning/core/src/utils/TestHelpers.hpp b/pennylane_lightning/core/src/utils/TestHelpers.hpp index af1a46618a..f4263cdb0e 100644 --- a/pennylane_lightning/core/src/utils/TestHelpers.hpp +++ b/pennylane_lightning/core/src/utils/TestHelpers.hpp @@ -288,6 +288,19 @@ auto createZeroState(size_t num_qubits) -> TestVector { return res; } +/** + * @brief create |+>^N + */ +template +auto createPlusState_(size_t num_qubits) -> TestVector { + TestVector res(size_t{1U} << num_qubits, 1.0, + getBestAllocator()); + for (auto &elem : res) { + elem /= std::sqrt(1U << num_qubits); + } + return res; +} + /** * @brief create |+>^N */ From 6da13fb306feb76bba571a67fdc4ac6870c042ed Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Thu, 21 Mar 2024 20:01:26 +0000 Subject: [PATCH 02/30] Auto update version --- pennylane_lightning/core/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py index 070aab6b47..134b71b540 100644 --- a/pennylane_lightning/core/_version.py +++ b/pennylane_lightning/core/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.36.0-dev14" +__version__ = "0.36.0-dev15" From 4cecf3ecd4d5fdc65695ce4fd73299a8175b1b39 Mon Sep 17 00:00:00 2001 From: Thomas Germain Date: Thu, 21 Mar 2024 16:12:34 -0400 Subject: [PATCH 03/30] CodeFactor --- .../src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index de6d05ee74..1528504d41 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -767,10 +767,6 @@ class StateVectorKokkos final * @param branch Branch 0 or 1. */ void collapse(const std::size_t wire, const bool branch) { - - // file:///home/thomas.germain/Downloads/KokkosTutorial_04_HierarchicalParallelism.pdf - // pp. 14, 20, 26, - auto &&num_qubits = this->getNumQubits(); const size_t stride = pow(2, num_qubits_ - (1 + wire)); From e54f06fddf1dac55ef0b142b3bc5033bb0d56739 Mon Sep 17 00:00:00 2001 From: Thomas Germain Date: Thu, 21 Mar 2024 16:21:48 -0400 Subject: [PATCH 04/30] normalize() abort if norm is zero --- .../core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 1528504d41..dd9d87ea90 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -801,7 +801,8 @@ class StateVectorKokkos final }, squaredNorm); - // TODO: @tomlqc add PL_ABORT_IF + PL_ABORT_IF(squaredNorm < std::numeric_limits::epsilon() * 1e2, + "vector has norm close to zero and can't be normalized"); std::complex inv_norm = 1. / std::sqrt(squaredNorm); Kokkos::parallel_for( From 6c2bb9d82942c955c0ca4fe8f6e942bee16c8e28 Mon Sep 17 00:00:00 2001 From: Thomas Germain Date: Thu, 21 Mar 2024 16:41:48 -0400 Subject: [PATCH 05/30] unittest for normalize() --- .../lightning_kokkos/StateVectorKokkos.hpp | 3 +- .../tests/Test_StateVectorLKokkos.cpp | 29 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index dd9d87ea90..4ffb815848 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -801,7 +801,8 @@ class StateVectorKokkos final }, squaredNorm); - PL_ABORT_IF(squaredNorm < std::numeric_limits::epsilon() * 1e2, + PL_ABORT_IF(squaredNorm < + std::numeric_limits::epsilon() * 1e2, "vector has norm close to zero and can't be normalized"); std::complex inv_norm = 1. / std::sqrt(squaredNorm); diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp index 14fc3071e8..7fc6edcd79 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp @@ -348,3 +348,32 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::collapse", "[StateVectorKokkos]", float, expected_state[branch][wire].size(), eps)); } } + +TEMPLATE_TEST_CASE("StateVectorKokkos::normalize", "[StateVectorKokkos]", float, + double) { + using PrecisionT = TestType; + using ComplexT = typename StateVectorKokkos::ComplexT; + + // TODO @tomlqc use same template for testing all Lightning flavours? + + SECTION("Normalize state vector.") { + const ComplexT init{1.0, PrecisionT{0.0}}; + const ComplexT half{0.5, PrecisionT{0.0}}; + const ComplexT zero{PrecisionT{0.0}, PrecisionT{0.0}}; + + std::vector init_state = {init, zero, init, init, + zero, zero, init, zero}; + + std::vector expected_state = {half, zero, half, half, + zero, zero, half, zero}; + + StateVectorKokkos sv( + reinterpret_cast(init_state.data()), init_state.size()); + sv.normalize(); + + PrecisionT eps = std::numeric_limits::epsilon() * 1e3; + REQUIRE(isApproxEqual(sv.getData(), sv.getDataVector().size(), + expected_state.data(), expected_state.size(), + eps)); + } +} From e06ded69f9af675d42adf19f2107c0822d6e1735 Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Thu, 21 Mar 2024 20:44:34 +0000 Subject: [PATCH 06/30] Auto update version --- pennylane_lightning/core/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py index 134b71b540..778353eb5b 100644 --- a/pennylane_lightning/core/_version.py +++ b/pennylane_lightning/core/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.36.0-dev15" +__version__ = "0.36.0-dev16" From 694a62ccc8ea4108734725e391294566f5c958fb Mon Sep 17 00:00:00 2001 From: Thomas Germain Date: Thu, 21 Mar 2024 16:56:37 -0400 Subject: [PATCH 07/30] unittest for normalize() in LighningQubit --- .../tests/Test_StateVectorLQubit.cpp | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_qubit/tests/Test_StateVectorLQubit.cpp b/pennylane_lightning/core/src/simulators/lightning_qubit/tests/Test_StateVectorLQubit.cpp index 310cb4cb68..7fe7936cb8 100644 --- a/pennylane_lightning/core/src/simulators/lightning_qubit/tests/Test_StateVectorLQubit.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_qubit/tests/Test_StateVectorLQubit.cpp @@ -245,9 +245,35 @@ TEMPLATE_PRODUCT_TEST_CASE("StateVectorLQubit::collapse", "[StateVectorLQubit]", std::size_t wire = GENERATE(0, 1, 2); std::size_t branch = GENERATE(0, 1); - StateVectorLQubitManaged sv(init_state); + StateVectorT sv(init_state.data(), init_state.size()); sv.collapse(wire, branch); REQUIRE(sv.getDataVector() == approx(expected_state[branch][wire])); } } + +TEMPLATE_PRODUCT_TEST_CASE("StateVectorLQubit::normalize", + "[StateVectorLQubit]", + (StateVectorLQubitManaged, StateVectorLQubitRaw), + (float, double)) { + using StateVectorT = TestType; + using PrecisionT = typename StateVectorT::PrecisionT; + using ComplexT = typename StateVectorT::ComplexT; + + SECTION("Normalize state vector.") { + const ComplexT init{1.0, PrecisionT{0.0}}; + const ComplexT half{0.5, PrecisionT{0.0}}; + const ComplexT zero{PrecisionT{0.0}, PrecisionT{0.0}}; + + std::vector init_state = {init, zero, init, init, + zero, zero, init, zero}; + + std::vector expected_state = {half, zero, half, half, + zero, zero, half, zero}; + + StateVectorT sv(init_state.data(), init_state.size()); + sv.normalize(); + + REQUIRE(sv.getDataVector() == approx(expected_state)); + } +} From 31bc86f4e9400cb4889713858f50c2444fc00a2c Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Thu, 4 Apr 2024 20:51:00 +0000 Subject: [PATCH 08/30] Auto update version --- pennylane_lightning/core/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py index 19067082da..86e85a246a 100644 --- a/pennylane_lightning/core/_version.py +++ b/pennylane_lightning/core/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.36.0-dev21" +__version__ = "0.36.0-dev22" From 3f3ab8682f88ff604a9a0057a69839311c267e51 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Wed, 10 Apr 2024 08:55:47 -0400 Subject: [PATCH 09/30] Add MCM bindings and tests for L-Kokkos. (#672) * Add MCM bindings and tests for L-Kokkos. * Auto update version * Refactor collapse. * Try parallelizing tests. * Only run test_native_mcm once amongst all workflows since it takes quite a bit of time. * trigger ci --------- Co-authored-by: Dev version update bot --- .github/CHANGELOG.md | 3 ++ .github/workflows/tests_gpu_cuda.yml | 2 +- .github/workflows/tests_gpu_kokkos.yml | 2 +- .github/workflows/tests_linux.yml | 14 ++--- .../lightning_kokkos/StateVectorKokkos.hpp | 34 +++++------- .../bindings/LKokkosBindings.hpp | 6 ++- .../gates/GateFunctorsGenerator.hpp | 30 ----------- .../measurements/MeasurementsKokkos.hpp | 6 ++- .../lightning_kokkos/lightning_kokkos.py | 53 ++++++++++++++++--- tests/test_native_mcm.py | 21 +++++--- 10 files changed, 97 insertions(+), 74 deletions(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index b65b64aa5d..a20ebcd138 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -2,6 +2,9 @@ ### New features since last release +* `lightning.kokkos` supports mid-circuit measurements. + [(#672)](https://github.com/PennyLaneAI/pennylane-lightning/pull/672) + * `lightning.qubit` supports mid-circuit measurements. [(#650)](https://github.com/PennyLaneAI/pennylane-lightning/pull/650) diff --git a/.github/workflows/tests_gpu_cuda.yml b/.github/workflows/tests_gpu_cuda.yml index d3abac6937..68b305618d 100644 --- a/.github/workflows/tests_gpu_cuda.yml +++ b/.github/workflows/tests_gpu_cuda.yml @@ -316,7 +316,7 @@ jobs: OMP_PROC_BIND: false run: | cd main/ - PL_DEVICE=lightning.qubit python -m pytest tests/ $COVERAGE_FLAGS + PL_DEVICE=lightning.qubit python -m pytest tests/ -k "not test_native_mcm" $COVERAGE_FLAGS pl-device-test --device lightning.qubit --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.qubit --shots=None --skip-ops $COVERAGE_FLAGS --cov-append PL_DEVICE=lightning.gpu python -m pytest tests/ $COVERAGE_FLAGS diff --git a/.github/workflows/tests_gpu_kokkos.yml b/.github/workflows/tests_gpu_kokkos.yml index c31488ad40..44894634ce 100644 --- a/.github/workflows/tests_gpu_kokkos.yml +++ b/.github/workflows/tests_gpu_kokkos.yml @@ -325,7 +325,7 @@ jobs: OMP_PROC_BIND: false run: | cd main/ - PL_DEVICE=lightning.qubit python -m pytest tests/ $COVERAGE_FLAGS + PL_DEVICE=lightning.qubit python -m pytest tests/ -k "not test_native_mcm" $COVERAGE_FLAGS pl-device-test --device lightning.qubit --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.qubit --shots=None --skip-ops $COVERAGE_FLAGS --cov-append PL_DEVICE=lightning.kokkos python -m pytest tests/ $COVERAGE_FLAGS diff --git a/.github/workflows/tests_linux.yml b/.github/workflows/tests_linux.yml index a6373a8111..aed5e2580f 100644 --- a/.github/workflows/tests_linux.yml +++ b/.github/workflows/tests_linux.yml @@ -21,6 +21,7 @@ env: COVERAGE_FLAGS: "--cov=pennylane_lightning --cov-report=term-missing --no-flaky-report -p no:warnings --tb=native" GCC_VERSION: 11 OMP_NUM_THREADS: "2" + OMP_PROC_BIND: "false" concurrency: group: tests_linux-${{ github.ref }}-${{ inputs.lightning-version }}-${{ inputs.pennylane-version }} @@ -393,8 +394,8 @@ jobs: run: | cd main/ DEVICENAME=`echo ${{ matrix.pl_backend }} | sed "s/_/./g"` - OMP_NUM_THREADS=1 PL_DEVICE=${DEVICENAME} python -m pytest -n auto tests/ -k "not unitary_correct" $COVERAGE_FLAGS - PL_DEVICE=${DEVICENAME} python -m pytest tests/ -k "unitary_correct" $COVERAGE_FLAGS --cov-append + OMP_NUM_THREADS=1 PL_DEVICE=${DEVICENAME} python -m pytest -n auto tests/ -k "not unitary_correct and not test_native_mcm" $COVERAGE_FLAGS + PL_DEVICE=${DEVICENAME} python -m pytest tests/ -k "unitary_correct and not test_native_mcm" $COVERAGE_FLAGS --cov-append pl-device-test --device ${DEVICENAME} --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append pl-device-test --device ${DEVICENAME} --shots=None --skip-ops $COVERAGE_FLAGS --cov-append mv .coverage .coverage-${{ github.job }}-${{ matrix.pl_backend }} @@ -592,7 +593,8 @@ jobs: run: | cd main/ DEVICENAME=`echo ${{ matrix.pl_backend }} | sed "s/_/./g"` - PL_DEVICE=${DEVICENAME} python -m pytest tests/ $COVERAGE_FLAGS + PL_DEVICE=${DEVICENAME} python -m pytest tests/ -k "not test_native_mcm" $COVERAGE_FLAGS + OMP_NUM_THREADS=1 PL_DEVICE=${DEVICENAME} python -m pytest -n auto tests/ -k "test_native_mcm" $COVERAGE_FLAGS --cov-append pl-device-test --device ${DEVICENAME} --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append pl-device-test --device ${DEVICENAME} --shots=None --skip-ops $COVERAGE_FLAGS --cov-append mv .coverage .coverage-${{ github.job }}-${{ matrix.pl_backend }} @@ -611,11 +613,11 @@ jobs: if: ${{ matrix.pl_backend == 'all' }} run: | cd main/ - OMP_NUM_THREADS=1 PL_DEVICE=lightning.qubit python -m pytest -n auto tests/ -k "not unitary_correct" $COVERAGE_FLAGS - PL_DEVICE=lightning.qubit python -m pytest tests/ -k "unitary_correct" $COVERAGE_FLAGS --cov-append + OMP_NUM_THREADS=1 PL_DEVICE=lightning.qubit python -m pytest -n auto tests/ -k "not unitary_correct and not test_native_mcm" $COVERAGE_FLAGS + PL_DEVICE=lightning.qubit python -m pytest tests/ -k "unitary_correct and not test_native_mcm" $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.qubit --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.qubit --shots=None --skip-ops $COVERAGE_FLAGS --cov-append - PL_DEVICE=lightning.kokkos python -m pytest tests/ $COVERAGE_FLAGS --cov-append + PL_DEVICE=lightning.kokkos python -m pytest tests/ -k "not test_native_mcm" $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.kokkos --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.kokkos --shots=None --skip-ops $COVERAGE_FLAGS --cov-append mv .coverage .coverage-${{ github.job }}-${{ matrix.pl_backend }} diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 4ffb815848..5ffbc73062 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -767,21 +767,14 @@ class StateVectorKokkos final * @param branch Branch 0 or 1. */ void collapse(const std::size_t wire, const bool branch) { - auto &&num_qubits = this->getNumQubits(); - - const size_t stride = pow(2, num_qubits_ - (1 + wire)); - const size_t vec_size = pow(2, num_qubits_); - const auto section_size = vec_size / stride; - const auto half_section_size = section_size / 2; - - const size_t negbranch = branch ? 0 : 1; - - Kokkos::MDRangePolicy policy_2d( - {0, 0}, {half_section_size, stride}); + KokkosVector matrix("gate_matrix", 4); Kokkos::parallel_for( - policy_2d, - collapseFunctor(*data_, num_qubits, stride, negbranch)); - + matrix.size(), KOKKOS_LAMBDA(const std::size_t k) { + matrix(k) = ((k == 0 && branch == 0) || (k == 3 && branch == 1)) + ? ComplexT{1.0, 0.0} + : ComplexT{0.0, 0.0}; + }); + applyMultiQubitOp(matrix, {wire}, false); normalize(); } @@ -789,15 +782,15 @@ class StateVectorKokkos final * @brief Normalize vector (to have norm 1). */ void normalize() { - KokkosVector sv_view = - getView(); // circumvent error capturing this with KOKKOS_LAMBDA + auto sv_view = getView(); // TODO: @tomlqc what about squaredNorm() PrecisionT squaredNorm = 0.0; Kokkos::parallel_reduce( sv_view.size(), - KOKKOS_LAMBDA(const size_t i, PrecisionT &sum) { - sum += std::norm(sv_view(i)); + KOKKOS_LAMBDA(const std::size_t i, PrecisionT &sum) { + const PrecisionT norm = Kokkos::abs(sv_view(i)); + sum += norm * norm; }, squaredNorm); @@ -805,10 +798,11 @@ class StateVectorKokkos final std::numeric_limits::epsilon() * 1e2, "vector has norm close to zero and can't be normalized"); - std::complex inv_norm = 1. / std::sqrt(squaredNorm); + const std::complex inv_norm = + 1. / Kokkos::sqrt(squaredNorm); Kokkos::parallel_for( sv_view.size(), - KOKKOS_LAMBDA(const size_t i) { sv_view(i) *= inv_norm; }); + KOKKOS_LAMBDA(const std::size_t i) { sv_view(i) *= inv_norm; }); } /** diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp index 6432864c4e..466d1b428f 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp @@ -137,7 +137,11 @@ void registerBackendClassSpecificBindings(PyClass &pyclass) { sv.applyOperation(str, wires, inv, std::vector{}, conv_matrix); }, - "Apply operation via the gate matrix"); + "Apply operation via the gate matrix") + .def("collapse", &StateVectorT::collapse, + "Collapse the statevector onto the 0 or 1 branch of a given wire.") + .def("normalize", &StateVectorT::normalize, + "Normalizes the statevector to norm 1."); } /** diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/GateFunctorsGenerator.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/GateFunctorsGenerator.hpp index 9abcf744f3..f8c19b1425 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/GateFunctorsGenerator.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/GateFunctorsGenerator.hpp @@ -973,34 +973,4 @@ template struct generatorMultiRZFunctor { } }; -template struct collapseFunctor { - using ComplexT = Kokkos::complex; - using KokkosComplexVector = Kokkos::View; - - KokkosComplexVector arr; - std::size_t num_qubits; - std::size_t stride; - std::size_t negbranch; - - collapseFunctor(KokkosComplexVector &arr_, std::size_t num_qubits_, - std::size_t stride_, std::size_t negbranch_) { - arr = arr_; - num_qubits = num_qubits_; - stride = stride_; - negbranch = negbranch_; - } - - // zero half the entries - // the "half" entries depend on the stride - // *_*_*_*_ for stride 1 - // **__**__ for stride 2 - // ****____ for stride 4 - - KOKKOS_INLINE_FUNCTION - void operator()(const std::size_t left, const std::size_t right) const { - const size_t offset = stride * (negbranch + 2 * left); - arr[offset + right] = ComplexT{0., 0.}; - } -}; - } // namespace Pennylane::LightningKokkos::Functors \ No newline at end of file diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/measurements/MeasurementsKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/measurements/MeasurementsKokkos.hpp index 3fa7c5a0a2..d4f85aeead 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/measurements/MeasurementsKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/measurements/MeasurementsKokkos.hpp @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. #pragma once +#include #include #include @@ -682,7 +683,10 @@ class Measurements final }); // Sampling using Random_XorShift64_Pool - Kokkos::Random_XorShift64_Pool<> rand_pool(5374857); + Kokkos::Random_XorShift64_Pool<> rand_pool( + std::chrono::high_resolution_clock::now() + .time_since_epoch() + .count()); Kokkos::parallel_for( Kokkos::RangePolicy(0, num_samples), diff --git a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py index f330ff69fa..bf913fa48e 100644 --- a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py +++ b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py @@ -21,6 +21,8 @@ from warnings import warn import numpy as np +from pennylane.measurements import MidMeasureMP +from pennylane.ops import Conditional from pennylane_lightning.core.lightning_base import ( LightningBase, @@ -136,6 +138,8 @@ def _kokkos_configuration(): "QFT", "ECR", "BlockEncode", + "MidMeasureMP", + "Conditional", } allowed_observables = { @@ -210,6 +214,15 @@ def __init__( if not LightningKokkos.kokkos_config: LightningKokkos.kokkos_config = _kokkos_configuration() + # pylint: disable=missing-function-docstring + @classmethod + def capabilities(cls): + capabilities = super().capabilities().copy() + capabilities.update( + supports_mid_measure=True, + ) + return capabilities + @staticmethod def _asarray(arr, dtype=None): arr = np.asarray(arr) # arr is not copied @@ -370,7 +383,25 @@ def _apply_basis_state(self, state, wires): num = self._get_basis_state_index(state, wires) self._create_basis_state(num) - def apply_lightning(self, operations): + def _apply_lightning_midmeasure(self, operation: MidMeasureMP, mid_measurements: dict): + """Execute a MidMeasureMP operation and return the sample in mid_measurements. + Args: + operation (~pennylane.operation.Operation): mid-circuit measurement + Returns: + None + """ + wires = self.wires.indices(operation.wires) + wire = list(wires)[0] + sample = qml.math.reshape(self.generate_samples(shots=1), (-1,))[wire] + if operation.postselect is not None and sample != operation.postselect: + mid_measurements[operation] = -1 + return + mid_measurements[operation] = sample + getattr(self.state_vector, "collapse")(wire, bool(sample)) + if operation.reset and bool(sample): + self.apply([qml.PauliX(operation.wires)], mid_measurements=mid_measurements) + + def apply_lightning(self, operations, mid_measurements=None): """Apply a list of operations to the state tensor. Args: @@ -392,12 +423,17 @@ def apply_lightning(self, operations): else: name = ops.name invert_param = False - if name == "Identity": + if isinstance(ops, qml.Identity): continue method = getattr(state, name, None) wires = self.wires.indices(ops.wires) - if ops.name == "C(GlobalPhase)": + if isinstance(ops, Conditional): + if ops.meas_val.concretize(mid_measurements): + self.apply_lightning([ops.then_op]) + elif isinstance(ops, MidMeasureMP): + self._apply_lightning_midmeasure(ops, mid_measurements) + elif ops.name == "C(GlobalPhase)": controls = ops.control_wires control_values = ops.control_values param = ops.base.parameters[0] @@ -425,7 +461,7 @@ def apply_lightning(self, operations): method(wires, invert_param, param) # pylint: disable=unused-argument - def apply(self, operations, rotations=None, **kwargs): + def apply(self, operations, rotations=None, mid_measurements=None, **kwargs): """Applies a list of operations to the state tensor.""" # State preparation is currently done in Python if operations: # make sure operations[0] exists @@ -445,7 +481,9 @@ def apply(self, operations, rotations=None, **kwargs): + f"Operations have already been applied on a {self.short_name} device." ) - self.apply_lightning(operations) + self.apply_lightning(operations, mid_measurements=mid_measurements) + if mid_measurements is not None and any(v == -1 for v in mid_measurements.values()): + self._apply_basis_state(np.zeros(self.num_wires), wires=self.wires) # pylint: disable=protected-access def expval(self, observable, shot_range=None, bin_size=None): @@ -575,19 +613,20 @@ def var(self, observable, shot_range=None, bin_size=None): return measure.var(observable.name, observable_wires) - def generate_samples(self): + def generate_samples(self, shots=None): """Generate samples Returns: array[int]: array of samples in binary representation with shape ``(dev.shots, dev.num_wires)`` """ + shots = self.shots if shots is None else shots measure = ( MeasurementsC64(self._kokkos_state) if self.use_csingle else MeasurementsC128(self._kokkos_state) ) - return measure.generate_samples(len(self.wires), self.shots).astype(int, copy=False) + return measure.generate_samples(len(self.wires), shots).astype(int, copy=False) def probability_lightning(self, wires): """Return the probability of each computational basis state. diff --git a/tests/test_native_mcm.py b/tests/test_native_mcm.py index 72fe6a1c76..69d8621140 100644 --- a/tests/test_native_mcm.py +++ b/tests/test_native_mcm.py @@ -22,8 +22,8 @@ from flaky import flaky from pennylane._device import DeviceError -if not LightningDevice._new_API: - pytest.skip("Exclusive tests for new device API. Skipping.", allow_module_level=True) +if device_name not in ("lightning.qubit", "lightning.kokkos"): + pytest.skip("Native MCM not supported. Skipping.", allow_module_level=True) if not LightningDevice._CPP_BINARY_AVAILABLE: # pylint: disable=protected-access pytest.skip("No binary module found. Skipping.", allow_module_level=True) @@ -79,11 +79,18 @@ def func(x, y): qml.cond(m0, qml.RY)(y, wires=1) return qml.classical_shadow(wires=0) - with pytest.raises( - DeviceError, - match=f"not accepted with finite shots on lightning.qubit", - ): - func(*params) + if device_name == "lightning.qubit": + with pytest.raises( + DeviceError, + match=f"not accepted with finite shots on lightning.qubit", + ): + func(*params) + else: + with pytest.raises( + TypeError, + match=f"Native mid-circuit measurement mode does not support ClassicalShadowMP measurements.", + ): + func(*params) @flaky(max_runs=5) From 8e4030be2a8a62a259055a59521a6b10df0d0a8f Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Wed, 10 Apr 2024 18:43:25 +0000 Subject: [PATCH 10/30] Do not run test_native_mcm with LK-GPU. --- .github/workflows/tests_gpu_kokkos.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests_gpu_kokkos.yml b/.github/workflows/tests_gpu_kokkos.yml index 3305a8fd2a..663f020e9e 100644 --- a/.github/workflows/tests_gpu_kokkos.yml +++ b/.github/workflows/tests_gpu_kokkos.yml @@ -303,9 +303,9 @@ jobs: run: | cd main/ DEVICENAME=`echo ${{ matrix.pl_backend }} | sed "s/_/./g"` + PL_DEVICE=${DEVICENAME} python -m pytest tests/ -k "not test_native_mcm" $COVERAGE_FLAGS 2> /dev/null || echo Something went wrong with Pytest pl-device-test --device ${DEVICENAME} --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append 2> /dev/null || echo Something went wrong with pl-device-test shot=20000 pl-device-test --device ${DEVICENAME} --shots=None --skip-ops $COVERAGE_FLAGS --cov-append 2> /dev/null || echo Something went wrong with pl-device-test shot=None - PL_DEVICE=${DEVICENAME} python -m pytest tests/ $COVERAGE_FLAGS 2> /dev/null || echo Something went wrong with Pytest mv coverage.xml coverage-${{ github.job }}-${{ matrix.pl_backend }}.xml - name: Install all backend devices @@ -328,7 +328,7 @@ jobs: PL_DEVICE=lightning.qubit python -m pytest tests/ -k "not test_native_mcm" $COVERAGE_FLAGS pl-device-test --device lightning.qubit --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.qubit --shots=None --skip-ops $COVERAGE_FLAGS --cov-append - PL_DEVICE=lightning.kokkos python -m pytest tests/ $COVERAGE_FLAGS + PL_DEVICE=lightning.kokkos python -m pytest tests/ -k "not test_native_mcm" $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.kokkos --skip-ops --shots=20000 $COVERAGE_FLAGS --cov-append pl-device-test --device lightning.kokkos --shots=None --skip-ops $COVERAGE_FLAGS --cov-append mv coverage.xml coverage-${{ github.job }}-${{ matrix.pl_backend }}.xml From dff080a6ae8682b0ac0865c76f6839cc396c5dad Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Wed, 10 Apr 2024 19:12:54 +0000 Subject: [PATCH 11/30] Auto update version --- pennylane_lightning/core/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py index bdedc820ba..3180e9d655 100644 --- a/pennylane_lightning/core/_version.py +++ b/pennylane_lightning/core/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.36.0-dev25" +__version__ = "0.36.0-dev26" From 2e2a146e74182b604eaa9e41d12f849fa33ccef2 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Wed, 10 Apr 2024 19:12:58 +0000 Subject: [PATCH 12/30] trigger ci From a9564a4421dc8cc832fbbd7ac963d1dbea2b7ed4 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 09:04:48 -0400 Subject: [PATCH 13/30] Update pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp Co-authored-by: Ali Asadi <10773383+maliasadi@users.noreply.github.com> --- .../simulators/lightning_kokkos/bindings/LKokkosBindings.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp index 466d1b428f..f476ceba50 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp @@ -141,7 +141,7 @@ void registerBackendClassSpecificBindings(PyClass &pyclass) { .def("collapse", &StateVectorT::collapse, "Collapse the statevector onto the 0 or 1 branch of a given wire.") .def("normalize", &StateVectorT::normalize, - "Normalizes the statevector to norm 1."); + "Normalize the statevector to norm 1."); } /** From 699685855671bcae009c4e759c464d83c2fc8caf Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Fri, 12 Apr 2024 13:05:03 +0000 Subject: [PATCH 14/30] Auto update version --- pennylane_lightning/core/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py index 3180e9d655..9be711cbdb 100644 --- a/pennylane_lightning/core/_version.py +++ b/pennylane_lightning/core/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.36.0-dev26" +__version__ = "0.36.0-dev27" From fb35dd20866334356cb30cd291ee7fdf63827b6f Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 10:58:16 -0400 Subject: [PATCH 15/30] Update pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp Co-authored-by: Ali Asadi <10773383+maliasadi@users.noreply.github.com> --- .../core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 5ffbc73062..15b51d1fd1 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -802,7 +802,7 @@ class StateVectorKokkos final 1. / Kokkos::sqrt(squaredNorm); Kokkos::parallel_for( sv_view.size(), - KOKKOS_LAMBDA(const std::size_t i) { sv_view(i) *= inv_norm; }); + KOKKOS_LAMBDA(std::size_t i) { sv_view(i) *= inv_norm; }); } /** From b551e19ac7ce83279bc17b335cf2134f1c733e46 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 10:58:22 -0400 Subject: [PATCH 16/30] Update pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp Co-authored-by: Ali Asadi <10773383+maliasadi@users.noreply.github.com> --- .../core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 15b51d1fd1..997c9f7a24 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -769,7 +769,7 @@ class StateVectorKokkos final void collapse(const std::size_t wire, const bool branch) { KokkosVector matrix("gate_matrix", 4); Kokkos::parallel_for( - matrix.size(), KOKKOS_LAMBDA(const std::size_t k) { + matrix.size(), KOKKOS_LAMBDA(std::size_t k) { matrix(k) = ((k == 0 && branch == 0) || (k == 3 && branch == 1)) ? ComplexT{1.0, 0.0} : ComplexT{0.0, 0.0}; From b23655050ef4f6b1ca5fadeae6ed28523d1fb498 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 10:58:27 -0400 Subject: [PATCH 17/30] Update pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp Co-authored-by: Ali Asadi <10773383+maliasadi@users.noreply.github.com> --- .../core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 997c9f7a24..d2e0a97d12 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -788,7 +788,7 @@ class StateVectorKokkos final PrecisionT squaredNorm = 0.0; Kokkos::parallel_reduce( sv_view.size(), - KOKKOS_LAMBDA(const std::size_t i, PrecisionT &sum) { + KOKKOS_LAMBDA(std::size_t i, PrecisionT &sum) { const PrecisionT norm = Kokkos::abs(sv_view(i)); sum += norm * norm; }, From be8a264eb38a2fc0c9dc3b1083221e0ab6a25b60 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 10:58:33 -0400 Subject: [PATCH 18/30] Update pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp Co-authored-by: Ali Asadi <10773383+maliasadi@users.noreply.github.com> --- .../core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index d2e0a97d12..0ea2a062cb 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -766,7 +766,7 @@ class StateVectorKokkos final * @param wire Wire to collapse. * @param branch Branch 0 or 1. */ - void collapse(const std::size_t wire, const bool branch) { + void collapse(std::size_t wire, bool branch) { KokkosVector matrix("gate_matrix", 4); Kokkos::parallel_for( matrix.size(), KOKKOS_LAMBDA(std::size_t k) { From dc7ddd5837943d6494c680de628ea242bbc2b215 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 13:51:02 +0000 Subject: [PATCH 19/30] Increase shotsfor flaky test_composite_mcm_single_measure_obs --- tests/test_native_mcm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_native_mcm.py b/tests/test_native_mcm.py index 69d8621140..2e6dd41e7b 100644 --- a/tests/test_native_mcm.py +++ b/tests/test_native_mcm.py @@ -294,7 +294,7 @@ def func(x): @flaky(max_runs=5) -@pytest.mark.parametrize("shots", [5000, [5000, 5001]]) +@pytest.mark.parametrize("shots", [10000, [10000, 10001]]) @pytest.mark.parametrize("postselect", [None, 0, 1]) @pytest.mark.parametrize("reset", [False, True]) @pytest.mark.parametrize("measure_f", [qml.counts, qml.expval, qml.probs, qml.sample, qml.var]) From 23950974767c4290c2a0ab9295290e4da43175e9 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 15:47:11 +0000 Subject: [PATCH 20/30] Create separate device_allowed_operations list for ops supported by the device but not Catalyst. --- .../src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 2 +- pennylane_lightning/lightning_kokkos/lightning_kokkos.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 0ea2a062cb..67a35f78ce 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -788,7 +788,7 @@ class StateVectorKokkos final PrecisionT squaredNorm = 0.0; Kokkos::parallel_reduce( sv_view.size(), - KOKKOS_LAMBDA(std::size_t i, PrecisionT &sum) { + KOKKOS_LAMBDA(std::size_t i, PrecisionT & sum) { const PrecisionT norm = Kokkos::abs(sv_view(i)); sum += norm * norm; }, diff --git a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py index bf913fa48e..72d8d7598f 100644 --- a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py +++ b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py @@ -138,9 +138,10 @@ def _kokkos_configuration(): "QFT", "ECR", "BlockEncode", - "MidMeasureMP", - "Conditional", } + # device_allowed_operations required to preserve both PL and Catalyst support + device_allowed_operations = allowed_operations + device_allowed_operations.update({"Conditional", "MidMeasureMP"}) allowed_observables = { "PauliX", @@ -183,7 +184,7 @@ class LightningKokkos(LightningBase): name = "Lightning Kokkos PennyLane plugin" short_name = "lightning.kokkos" kokkos_config = {} - operations = allowed_operations + operations = device_allowed_operations observables = allowed_observables _backend_info = backend_info config = Path(__file__).parent / "lightning_kokkos.toml" From fbba18a7e310ffbb325f406aaf89110f4fd31087 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 15:58:28 +0000 Subject: [PATCH 21/30] Use isinstance instead of name comparison. --- .../lightning_kokkos/lightning_kokkos.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py index 72d8d7598f..c588677bf2 100644 --- a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py +++ b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py @@ -524,7 +524,7 @@ def expval(self, observable, shot_range=None, bin_size=None): if self.use_csingle else MeasurementsC128(self.state_vector) ) - if observable.name == "SparseHamiltonian": + if isinstance(observable, qml.SparseHamiltonian): csr_hamiltonian = observable.sparse_matrix(wire_order=self.wires).tocsr(copy=False) return measure.expval( csr_hamiltonian.indptr, @@ -533,13 +533,13 @@ def expval(self, observable, shot_range=None, bin_size=None): ) # use specialized functors to compute expval(Hermitian) - if observable.name == "Hermitian": + if isinstance(observable, qml.Hermitian): observable_wires = self.map_wires(observable.wires) matrix = observable.matrix() return measure.expval(matrix, observable_wires) if ( - observable.name in ["Hamiltonian", "Hermitian"] + isinstance(observable, (qml.Hamiltonian, qml.Hermitian)) or (observable.arithmetic_depth > 0) or isinstance(observable.name, List) ): @@ -591,7 +591,7 @@ def var(self, observable, shot_range=None, bin_size=None): else MeasurementsC128(self.state_vector) ) - if observable.name == "SparseHamiltonian": + if isinstance(observable, qml.SparseHamiltonian): csr_hamiltonian = observable.sparse_matrix(wire_order=self.wires).tocsr(copy=False) return measure.var( csr_hamiltonian.indptr, @@ -600,7 +600,7 @@ def var(self, observable, shot_range=None, bin_size=None): ) if ( - observable.name in ["Hamiltonian", "Hermitian"] + isinstance(observable, (qml.Hamiltonian, qml.Hermitian)) or (observable.arithmetic_depth > 0) or isinstance(observable.name, List) ): From e5c2a8ec3f57b3c8a5c9b8e0e43c943649ad748e Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 16:44:49 +0000 Subject: [PATCH 22/30] Check projector. --- pennylane_lightning/lightning_kokkos/lightning_kokkos.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py index c588677bf2..1ac03bca01 100644 --- a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py +++ b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py @@ -567,9 +567,7 @@ def var(self, observable, shot_range=None, bin_size=None): Returns: Variance of the observable """ - if observable.name in [ - "Projector", - ]: + if isinstance(observable, qml.Projector): diagonalizing_gates = observable.diagonalizing_gates() if self.shots is None and diagonalizing_gates: self.apply(diagonalizing_gates) From e5fd2004ed883700b45f42bbe62ea04a4537e483 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 16:47:59 +0000 Subject: [PATCH 23/30] Update operations at device init. --- pennylane_lightning/lightning_kokkos/lightning_kokkos.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py index 1ac03bca01..43ee066570 100644 --- a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py +++ b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py @@ -139,9 +139,6 @@ def _kokkos_configuration(): "ECR", "BlockEncode", } - # device_allowed_operations required to preserve both PL and Catalyst support - device_allowed_operations = allowed_operations - device_allowed_operations.update({"Conditional", "MidMeasureMP"}) allowed_observables = { "PauliX", @@ -184,7 +181,7 @@ class LightningKokkos(LightningBase): name = "Lightning Kokkos PennyLane plugin" short_name = "lightning.kokkos" kokkos_config = {} - operations = device_allowed_operations + operations = allowed_operations observables = allowed_observables _backend_info = backend_info config = Path(__file__).parent / "lightning_kokkos.toml" @@ -215,6 +212,9 @@ def __init__( if not LightningKokkos.kokkos_config: LightningKokkos.kokkos_config = _kokkos_configuration() + # required to preserve both PL and Catalyst support + self.operations.update({"Conditional", "MidMeasureMP"}) + # pylint: disable=missing-function-docstring @classmethod def capabilities(cls): From 193a279833cb3377376461765fe6208507dcfd4d Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 16:59:26 +0000 Subject: [PATCH 24/30] Modify stopping condition in LK. --- pennylane_lightning/core/lightning_base.py | 4 ++-- .../lightning_kokkos/lightning_kokkos.py | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/pennylane_lightning/core/lightning_base.py b/pennylane_lightning/core/lightning_base.py index c4f72293a0..38183ea784 100644 --- a/pennylane_lightning/core/lightning_base.py +++ b/pennylane_lightning/core/lightning_base.py @@ -94,9 +94,9 @@ def stopping_condition(self): and observable) and returns ``True`` if supported by the device.""" def accepts_obj(obj): - if obj.name == "QFT": + if isinstance(obj, qml.QFT): return len(obj.wires) < 10 - if obj.name == "GroverOperator": + if isinstance(obj, qml.GroverOperator): return len(obj.wires) < 13 is_not_tape = not isinstance(obj, qml.tape.QuantumTape) is_supported = getattr(self, "supports_operation", lambda name: False)(obj.name) diff --git a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py index 43ee066570..0745cbfbdd 100644 --- a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py +++ b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py @@ -212,8 +212,19 @@ def __init__( if not LightningKokkos.kokkos_config: LightningKokkos.kokkos_config = _kokkos_configuration() - # required to preserve both PL and Catalyst support - self.operations.update({"Conditional", "MidMeasureMP"}) + @property + def stopping_condition(self): + """.BooleanFn: Returns the stopping condition for the device. The returned + function accepts a queueable object (including a PennyLane operation + and observable) and returns ``True`` if supported by the device.""" + fun = super().stopping_condition + + def accepts_obj(obj): + return fun(obj) or isinstance( + obj, (qml.measurements.MidMeasureMP, qml.ops.Conditional) + ) + + return qml.BooleanFn(accepts_obj) # pylint: disable=missing-function-docstring @classmethod From 84ea17b186f035bc022c5d24679b26f6a2aa4176 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 17:49:36 +0000 Subject: [PATCH 25/30] Cannot use instance with Hamiltonian check. --- pennylane_lightning/lightning_kokkos/lightning_kokkos.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py index 0745cbfbdd..7064a49594 100644 --- a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py +++ b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py @@ -550,7 +550,7 @@ def expval(self, observable, shot_range=None, bin_size=None): return measure.expval(matrix, observable_wires) if ( - isinstance(observable, (qml.Hamiltonian, qml.Hermitian)) + observable.name in ["Hamiltonian", "Hermitian"] or (observable.arithmetic_depth > 0) or isinstance(observable.name, List) ): From dc5d8489023790f47f9c248bf02fc27f6970f76c Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 14:11:44 -0400 Subject: [PATCH 26/30] Update pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com> --- .../lightning_kokkos/tests/Test_StateVectorLKokkos.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp index 7fc6edcd79..7f94b6256b 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/tests/Test_StateVectorLKokkos.cpp @@ -320,7 +320,7 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::collapse", "[StateVectorKokkos]", float, // TODO @tomlqc use same template for testing all Lightning flavours? - SECTION("Collapse the state vector as after having measured one of the " + SECTION("Collapse the state vector after having measured one of the " "qubits.") { TestVectorT init_state = createPlusState_(num_qubits); From 098ca7e3d66b1b3cd4a825684bb414e8078ac2f3 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 14:11:50 -0400 Subject: [PATCH 27/30] Update pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com> --- .../core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 67a35f78ce..2eb4ff1ffd 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -758,7 +758,7 @@ class StateVectorKokkos final } /** - * @brief Collapse the state vector as after having measured one of the + * @brief Collapse the state vector after having measured one of the * qubits. * * The branch parameter imposes the measurement result on the given wire. From 121d403100ee3582dfa1b13a8ef67fd55c783085 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 18:13:07 +0000 Subject: [PATCH 28/30] Remove obsolete comment. --- .../core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 2eb4ff1ffd..d691526661 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -784,7 +784,6 @@ class StateVectorKokkos final void normalize() { auto sv_view = getView(); - // TODO: @tomlqc what about squaredNorm() PrecisionT squaredNorm = 0.0; Kokkos::parallel_reduce( sv_view.size(), From bfc7b6c2ac537542b7c433bec7ac900d32d39236 Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Fri, 12 Apr 2024 18:39:26 +0000 Subject: [PATCH 29/30] Auto update version --- pennylane_lightning/core/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py index 9be711cbdb..3da22800fb 100644 --- a/pennylane_lightning/core/_version.py +++ b/pennylane_lightning/core/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.36.0-dev27" +__version__ = "0.36.0-dev28" From e4f071669df52c0e96d6fc10d63a603c992f0817 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Fri, 12 Apr 2024 18:39:50 +0000 Subject: [PATCH 30/30] trigger ci