diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index f8c1fe42d6..cb2ca1fd6f 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -15,6 +15,9 @@ ### Improvements +* Initialize the private attributes `gates_indices_` and `generators_indices_` of `StateVectorKokkos` using the definitions of the `Pennylane::Gates::Constant` namespace. + [(#641)](https://github.com/PennyLaneAI/pennylane-lightning/pull/641) + * Add `isort` to `requirements-dev.txt` and run before `black` upon `make format` to sort Python imports. [(#623)](https://github.com/PennyLaneAI/pennylane-lightning/pull/623) diff --git a/pennylane_lightning/core/_version.py b/pennylane_lightning/core/_version.py index 3e0eaf1eed..60d2bbb0bf 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-dev7" +__version__ = "0.36.0-dev8" diff --git a/pennylane_lightning/core/src/gates/Constant.hpp b/pennylane_lightning/core/src/gates/Constant.hpp index 29544237c3..b84159d80a 100644 --- a/pennylane_lightning/core/src/gates/Constant.hpp +++ b/pennylane_lightning/core/src/gates/Constant.hpp @@ -121,38 +121,34 @@ using CGateView = typename std::pair; /** * @brief Generator names. * - * Note that a name of generators must be "Generator" + - * the name of the corresponding gate. */ using GeneratorView = typename std::pair; [[maybe_unused]] constexpr std::array generator_names = { - GeneratorView{GeneratorOperation::PhaseShift, "GeneratorPhaseShift"}, - GeneratorView{GeneratorOperation::RX, "GeneratorRX"}, - GeneratorView{GeneratorOperation::RY, "GeneratorRY"}, - GeneratorView{GeneratorOperation::RZ, "GeneratorRZ"}, - GeneratorView{GeneratorOperation::CRX, "GeneratorCRX"}, - GeneratorView{GeneratorOperation::CRY, "GeneratorCRY"}, - GeneratorView{GeneratorOperation::CRZ, "GeneratorCRZ"}, - GeneratorView{GeneratorOperation::IsingXX, "GeneratorIsingXX"}, - GeneratorView{GeneratorOperation::IsingXY, "GeneratorIsingXY"}, - GeneratorView{GeneratorOperation::IsingYY, "GeneratorIsingYY"}, - GeneratorView{GeneratorOperation::IsingZZ, "GeneratorIsingZZ"}, + GeneratorView{GeneratorOperation::PhaseShift, "PhaseShift"}, + GeneratorView{GeneratorOperation::RX, "RX"}, + GeneratorView{GeneratorOperation::RY, "RY"}, + GeneratorView{GeneratorOperation::RZ, "RZ"}, + GeneratorView{GeneratorOperation::CRX, "CRX"}, + GeneratorView{GeneratorOperation::CRY, "CRY"}, + GeneratorView{GeneratorOperation::CRZ, "CRZ"}, + GeneratorView{GeneratorOperation::IsingXX, "IsingXX"}, + GeneratorView{GeneratorOperation::IsingXY, "IsingXY"}, + GeneratorView{GeneratorOperation::IsingYY, "IsingYY"}, + GeneratorView{GeneratorOperation::IsingZZ, "IsingZZ"}, GeneratorView{GeneratorOperation::ControlledPhaseShift, - "GeneratorControlledPhaseShift"}, - GeneratorView{GeneratorOperation::SingleExcitation, - "GeneratorSingleExcitation"}, + "ControlledPhaseShift"}, + GeneratorView{GeneratorOperation::SingleExcitation, "SingleExcitation"}, GeneratorView{GeneratorOperation::SingleExcitationMinus, - "GeneratorSingleExcitationMinus"}, + "SingleExcitationMinus"}, GeneratorView{GeneratorOperation::SingleExcitationPlus, - "GeneratorSingleExcitationPlus"}, - GeneratorView{GeneratorOperation::MultiRZ, "GeneratorMultiRZ"}, - GeneratorView{GeneratorOperation::DoubleExcitation, - "GeneratorDoubleExcitation"}, + "SingleExcitationPlus"}, + GeneratorView{GeneratorOperation::MultiRZ, "MultiRZ"}, + GeneratorView{GeneratorOperation::DoubleExcitation, "DoubleExcitation"}, GeneratorView{GeneratorOperation::DoubleExcitationMinus, - "GeneratorDoubleExcitationMinus"}, + "DoubleExcitationMinus"}, GeneratorView{GeneratorOperation::DoubleExcitationPlus, - "GeneratorDoubleExcitationPlus"}, - GeneratorView{GeneratorOperation::GlobalPhase, "GeneratorGlobalPhase"}, + "DoubleExcitationPlus"}, + GeneratorView{GeneratorOperation::GlobalPhase, "GlobalPhase"}, }; using CGeneratorView = diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp index 4a72135bd9..87ac3b302a 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/StateVectorKokkos.hpp @@ -29,6 +29,8 @@ #include #include "BitUtil.hpp" // isPerfectPowerOf2 +#include "Constant.hpp" +#include "ConstantUtil.hpp" #include "Error.hpp" #include "GateFunctors.hpp" #include "GateOperation.hpp" @@ -39,12 +41,15 @@ /// @cond DEV namespace { +using namespace Pennylane::Gates::Constant; +using namespace Pennylane::LightningKokkos::Functors; using Pennylane::Gates::GateOperation; using Pennylane::Gates::GeneratorOperation; +using Pennylane::Util::array_contains; using Pennylane::Util::exp2; using Pennylane::Util::isPerfectPowerOf2; using Pennylane::Util::log2; -using namespace Pennylane::LightningKokkos::Functors; +using Pennylane::Util::reverse_lookup; using std::size_t; } // namespace /// @endcond @@ -110,9 +115,6 @@ class StateVectorKokkos final data_ = std::make_unique("data_", exp2(num_qubits)); setBasisState(0U); } - - init_gates_indices_(); - init_generators_indices_(); }; /** @@ -265,7 +267,7 @@ class StateVectorKokkos final } else { applyControlledGlobalPhase(gate_matrix); } - } else if (gates_indices_.contains(opName)) { + } else if (array_contains(gate_names, std::string_view{opName})) { applyNamedOperation(opName, wires, inverse, params); } else { PL_ABORT_IF(gate_matrix.size() == 0, @@ -449,7 +451,7 @@ class StateVectorKokkos final const std::vector &wires, bool inverse = false, const std::vector ¶ms = {}) { - switch (gates_indices_[opName]) { + switch (reverse_lookup(gate_names, std::string_view{opName})) { case GateOperation::PauliX: applyGateFunctor(wires, inverse, params); return; @@ -576,10 +578,7 @@ class StateVectorKokkos final auto applyGenerator(const std::string &opName, const std::vector &wires, bool inverse = false, const std::vector ¶ms = {}) -> fp_t { - if (!generators_indices_.contains(opName)) { - PL_ABORT(std::string("Generator does not exist for ") + opName); - } - switch (generators_indices_[opName]) { + switch (reverse_lookup(generator_names, std::string_view{opName})) { case GeneratorOperation::RX: applyGateFunctor(wires, inverse, params); return -static_cast(0.5); @@ -855,81 +854,10 @@ class StateVectorKokkos final } private: - std::unordered_map gates_indices_; - std::unordered_map generators_indices_; - size_t num_qubits_; std::mutex init_mutex_; std::unique_ptr data_; inline static bool is_exit_reg_ = false; - // clang-format off - /** - * @brief Register gate operations in the gates_indices_ attribute: - * an unordered_map mapping strings to GateOperation enumeration keywords. - */ - void init_gates_indices_() { - gates_indices_["PauliX"] = GateOperation::PauliX; - gates_indices_["PauliY"] = GateOperation::PauliY; - gates_indices_["PauliZ"] = GateOperation::PauliZ; - gates_indices_["Hadamard"] = GateOperation::Hadamard; - gates_indices_["S"] = GateOperation::S; - gates_indices_["T"] = GateOperation::T; - gates_indices_["RX"] = GateOperation::RX; - gates_indices_["RY"] = GateOperation::RY; - gates_indices_["RZ"] = GateOperation::RZ; - gates_indices_["PhaseShift"] = GateOperation::PhaseShift; - gates_indices_["Rot"] = GateOperation::Rot; - gates_indices_["CY"] = GateOperation::CY; - gates_indices_["CZ"] = GateOperation::CZ; - gates_indices_["CNOT"] = GateOperation::CNOT; - gates_indices_["SWAP"] = GateOperation::SWAP; - gates_indices_["ControlledPhaseShift"] = GateOperation::ControlledPhaseShift; - gates_indices_["CRX"] = GateOperation::CRX; - gates_indices_["CRY"] = GateOperation::CRY; - gates_indices_["CRZ"] = GateOperation::CRZ; - gates_indices_["CRot"] = GateOperation::CRot; - gates_indices_["IsingXX"] = GateOperation::IsingXX; - gates_indices_["IsingXY"] = GateOperation::IsingXY; - gates_indices_["IsingYY"] = GateOperation::IsingYY; - gates_indices_["IsingZZ"] = GateOperation::IsingZZ; - gates_indices_["SingleExcitation"] = GateOperation::SingleExcitation; - gates_indices_["SingleExcitationMinus"] = GateOperation::SingleExcitationMinus; - gates_indices_["SingleExcitationPlus"] = GateOperation::SingleExcitationPlus; - gates_indices_["DoubleExcitation"] = GateOperation::DoubleExcitation; - gates_indices_["DoubleExcitationMinus"] = GateOperation::DoubleExcitationMinus; - gates_indices_["DoubleExcitationPlus"] = GateOperation::DoubleExcitationPlus; - gates_indices_["MultiRZ"] = GateOperation::MultiRZ; - gates_indices_["GlobalPhase"] = GateOperation::GlobalPhase; - gates_indices_["CSWAP"] = GateOperation::CSWAP; - gates_indices_["Toffoli"] = GateOperation::Toffoli; - } - /** - * @brief Register generator operations in the generators_indices_ attribute: - * an unordered_map mapping strings to GateOperation enumeration keywords. - */ - void init_generators_indices_() { - generators_indices_["RX"] = GeneratorOperation::RX; - generators_indices_["RY"] = GeneratorOperation::RY; - generators_indices_["RZ"] = GeneratorOperation::RZ; - generators_indices_["ControlledPhaseShift"] = GeneratorOperation::ControlledPhaseShift; - generators_indices_["CRX"] = GeneratorOperation::CRX; - generators_indices_["CRY"] = GeneratorOperation::CRY; - generators_indices_["CRZ"] = GeneratorOperation::CRZ; - generators_indices_["IsingXX"] = GeneratorOperation::IsingXX; - generators_indices_["IsingXY"] = GeneratorOperation::IsingXY; - generators_indices_["IsingYY"] = GeneratorOperation::IsingYY; - generators_indices_["IsingZZ"] = GeneratorOperation::IsingZZ; - generators_indices_["SingleExcitation"] = GeneratorOperation::SingleExcitation; - generators_indices_["SingleExcitationMinus"] = GeneratorOperation::SingleExcitationMinus; - generators_indices_["SingleExcitationPlus"] = GeneratorOperation::SingleExcitationPlus; - generators_indices_["DoubleExcitation"] = GeneratorOperation::DoubleExcitation; - generators_indices_["DoubleExcitationMinus"] = GeneratorOperation::DoubleExcitationMinus; - generators_indices_["DoubleExcitationPlus"] = GeneratorOperation::DoubleExcitationPlus; - generators_indices_["PhaseShift"] = GeneratorOperation::PhaseShift; - generators_indices_["MultiRZ"] = GeneratorOperation::MultiRZ; - generators_indices_["GlobalPhase"] = GeneratorOperation::GlobalPhase; - } - // clang-format on }; }; // namespace Pennylane::LightningKokkos diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/tests/Test_StateVectorKokkos_Generator.cpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/tests/Test_StateVectorKokkos_Generator.cpp index 39cfe78199..bb335f4006 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/tests/Test_StateVectorKokkos_Generator.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/tests/Test_StateVectorKokkos_Generator.cpp @@ -49,7 +49,7 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::applyGenerator - errors", StateVectorKokkos state_vector{num_qubits}; PL_REQUIRE_THROWS_MATCHES(state_vector.applyGenerator("XXX", {0}), LightningException, - "Generator does not exist for"); + "The given value does not exist."); } } diff --git a/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/tests/Test_StateVectorKokkos_NonParam.cpp b/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/tests/Test_StateVectorKokkos_NonParam.cpp index 5c79d08cc2..67064195cd 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/tests/Test_StateVectorKokkos_NonParam.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/gates/tests/Test_StateVectorKokkos_NonParam.cpp @@ -78,7 +78,7 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::applyNamedOperation", StateVectorKokkos state_vector{num_qubits}; PL_REQUIRE_THROWS_MATCHES(state_vector.applyNamedOperation("XXX", {0}), LightningException, - "Operation does not exist for"); + "The given value does not exist."); } } diff --git a/pennylane_lightning/core/src/simulators/lightning_qubit/gates/DynamicDispatcher.hpp b/pennylane_lightning/core/src/simulators/lightning_qubit/gates/DynamicDispatcher.hpp index 8686a20ba5..d26b84e28f 100644 --- a/pennylane_lightning/core/src/simulators/lightning_qubit/gates/DynamicDispatcher.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_qubit/gates/DynamicDispatcher.hpp @@ -51,7 +51,6 @@ using Pennylane::Util::PairHash; namespace Pennylane::LightningQubit::Internal { constexpr auto generatorNamesWithoutPrefix() { - constexpr std::string_view prefix{"Generator"}; namespace GateConstant = Pennylane::Gates::Constant; std::array, GateConstant::generator_names.size()> @@ -60,7 +59,7 @@ constexpr auto generatorNamesWithoutPrefix() { // NOLINTBEGIN(cppcoreguidelines-pro-bounds-constant-array-index) const auto [gntr_op, gntr_name] = GateConstant::generator_names[i]; res[i].first = gntr_op; - res[i].second = gntr_name.substr(prefix.size()); + res[i].second = gntr_name.substr(0); // NOLINTEND(cppcoreguidelines-pro-bounds-constant-array-index) } return res; diff --git a/pennylane_lightning/core/src/simulators/lightning_qubit/gates/tests/TestConstant.hpp b/pennylane_lightning/core/src/simulators/lightning_qubit/gates/tests/TestConstant.hpp index c734da5ad9..a7e1923fb9 100644 --- a/pennylane_lightning/core/src/simulators/lightning_qubit/gates/tests/TestConstant.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_qubit/gates/tests/TestConstant.hpp @@ -75,8 +75,6 @@ static_assert( Util::count_unique(Util::second_elems_of(Constant::generator_names)) == Constant::generator_names.size(), "Second elements of generator_names must be distinct."); -static_assert(check_generator_names_starts_with(), - "Names of generators must start with \"Generator\""); /******************************************************************************* * Check gate_wires is well defined diff --git a/pennylane_lightning/core/src/simulators/lightning_qubit/gates/tests/Test_GateImplementations_Generator.cpp b/pennylane_lightning/core/src/simulators/lightning_qubit/gates/tests/Test_GateImplementations_Generator.cpp index 58a2f82344..be5e3a0ea4 100644 --- a/pennylane_lightning/core/src/simulators/lightning_qubit/gates/tests/Test_GateImplementations_Generator.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_qubit/gates/tests/Test_GateImplementations_Generator.cpp @@ -46,18 +46,9 @@ using namespace Pennylane::Util; } // namespace /// @endcond -/** - * @brief As clang does not support constexpr string_view::remove_prefix yet. - */ -constexpr std::string_view remove_prefix(const std::string_view &str, - size_t len) { - return {str.data() + len, str.length() - len}; -} - template constexpr auto findGateOpForGenerator() -> GateOperation { - constexpr auto gntr_name = - remove_prefix(lookup(Constant::generator_names, gntr_op), 9); + constexpr auto gntr_name = lookup(Constant::generator_names, gntr_op); for (const auto &[gate_op, gate_name] : Constant::gate_names) { if (gate_name == gntr_name) { diff --git a/pennylane_lightning/core/src/utils/ConstantUtil.hpp b/pennylane_lightning/core/src/utils/ConstantUtil.hpp index a111c8afb8..1d11765dfa 100644 --- a/pennylane_lightning/core/src/utils/ConstantUtil.hpp +++ b/pennylane_lightning/core/src/utils/ConstantUtil.hpp @@ -23,11 +23,13 @@ #include #include #include +#include #if __has_include() #include #endif +#include "Error.hpp" #include "TypeTraits.hpp" #include "Util.hpp" @@ -49,7 +51,29 @@ constexpr auto lookup(const std::array, size> &arr, return std::get<1>(arr[idx]); } } - throw std::range_error("The given key does not exist."); + PL_ABORT("The given key does not exist."); +} + +/** + * @brief Reverse lookup value in array of pairs. For a constexpr map-like + * behavior. + * + * @tparam Key Type of keys + * @tparam Value Type of values + * @tparam size Size of std::array + * @param arr Array to lookup + * @param value Value to find + */ +template +constexpr auto +reverse_lookup(const std::array, size> &arr, + const Value &value) -> Key { + for (size_t idx = 0; idx < size; idx++) { + if (std::get<1>(arr[idx]) == value) { + return std::get<0>(arr[idx]); + } + } + PL_ABORT("The given value does not exist."); } /** @@ -71,6 +95,27 @@ constexpr auto array_has_elem(const std::array &arr, const U &elem) return false; } +/** + * @brief Check an array of pairs contains a certain value. + * + * @tparam Key Type of keys + * @tparam Value Type of values + * @tparam size Size of std::array + * @param arr Array to lookup + * @param value Value to find + */ +template +constexpr auto +array_contains(const std::array, size> &arr, + const Value &value) -> bool { + for (size_t idx = 0; idx < size; idx++) { + if (std::get<1>(arr[idx]) == value) { + return true; + } + } + return false; +} + /// @cond DEV namespace Internal { /** diff --git a/pennylane_lightning/lightning_gpu/lightning_gpu.py b/pennylane_lightning/lightning_gpu/lightning_gpu.py index cbc4a48340..185115985b 100644 --- a/pennylane_lightning/lightning_gpu/lightning_gpu.py +++ b/pennylane_lightning/lightning_gpu/lightning_gpu.py @@ -91,6 +91,13 @@ from pennylane.ops.op_math import Adjoint from pennylane.wires import Wires + # pylint: disable=import-error, no-name-in-module, ungrouped-imports + from pennylane_lightning.core._serialize import ( + QuantumScriptSerializer, + global_phase_diagonal, + ) + from pennylane_lightning.core._version import __version__ + # pylint: disable=no-name-in-module, ungrouped-imports from pennylane_lightning.lightning_gpu_ops.algorithms import ( AdjointJacobianC64, @@ -99,13 +106,6 @@ create_ops_listC128, ) - # pylint: disable=import-error, no-name-in-module, ungrouped-imports - from pennylane_lightning.core._serialize import ( - QuantumScriptSerializer, - global_phase_diagonal, - ) - from pennylane_lightning.core._version import __version__ - if MPI_SUPPORT: from pennylane_lightning.lightning_gpu_ops.algorithmsMPI import ( AdjointJacobianMPIC64, diff --git a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py index d7821660bf..499d9a588b 100644 --- a/pennylane_lightning/lightning_kokkos/lightning_kokkos.py +++ b/pennylane_lightning/lightning_kokkos/lightning_kokkos.py @@ -64,6 +64,13 @@ from pennylane.ops.op_math import Adjoint from pennylane.wires import Wires + # pylint: disable=import-error, no-name-in-module, ungrouped-imports + from pennylane_lightning.core._serialize import ( + QuantumScriptSerializer, + global_phase_diagonal, + ) + from pennylane_lightning.core._version import __version__ + # pylint: disable=import-error, no-name-in-module, ungrouped-imports from pennylane_lightning.lightning_kokkos_ops.algorithms import ( AdjointJacobianC64, @@ -72,13 +79,6 @@ create_ops_listC128, ) - # pylint: disable=import-error, no-name-in-module, ungrouped-imports - from pennylane_lightning.core._serialize import ( - QuantumScriptSerializer, - global_phase_diagonal, - ) - from pennylane_lightning.core._version import __version__ - def _kokkos_dtype(dtype): if dtype not in [np.complex128, np.complex64]: # pragma: no cover raise ValueError(f"Data type is not supported for state-vector computation: {dtype}") diff --git a/tests/lightning_qubit/test_measurements_class.py b/tests/lightning_qubit/test_measurements_class.py index 23de856293..7865359907 100644 --- a/tests/lightning_qubit/test_measurements_class.py +++ b/tests/lightning_qubit/test_measurements_class.py @@ -20,6 +20,7 @@ import pennylane as qml import pytest from conftest import LightningDevice # tested device +from flaky import flaky from pennylane.devices import DefaultQubit from pennylane.measurements import VarianceMP from scipy.sparse import csr_matrix, random_array @@ -470,6 +471,7 @@ def test_single_return_value(self, measurement, observable, lightning_sv, tol): # a few tests may fail in single precision, and hence we increase the tolerance assert np.allclose(result, expected, max(tol, 1.0e-5)) + @flaky(max_runs=5) @pytest.mark.parametrize("measurement", [qml.expval, qml.probs, qml.var]) @pytest.mark.parametrize( "obs0_",