From dccfe3e1ac64216da93254a3f087471cf38fef73 Mon Sep 17 00:00:00 2001 From: Vincent Michaud-Rioux Date: Mon, 23 Oct 2023 16:45:42 +0000 Subject: [PATCH] Send backend-specific ops in respective modules. --- .../core/src/bindings/Bindings.hpp | 88 ++----------------- .../lightning_gpu/bindings/LGPUBindings.hpp | 67 ++++++++++++++ .../bindings/LKokkosBindings.hpp | 54 ++++++++++++ .../bindings/LQubitBindings.hpp | 9 ++ 4 files changed, 135 insertions(+), 83 deletions(-) diff --git a/pennylane_lightning/core/src/bindings/Bindings.hpp b/pennylane_lightning/core/src/bindings/Bindings.hpp index 511c4ef798..ac2fdd8b7f 100644 --- a/pennylane_lightning/core/src/bindings/Bindings.hpp +++ b/pennylane_lightning/core/src/bindings/Bindings.hpp @@ -287,7 +287,8 @@ void registerInfo(py::module_ &m) { * @tparam StateVectorT * @param m Pybind module */ -template void registerObservables(py::module_ &m) { +template +void registerBackendAgnosticObservables(py::module_ &m) { using PrecisionT = typename StateVectorT::PrecisionT; // Statevector's precision. using ComplexT = @@ -406,87 +407,6 @@ template void registerObservables(py::module_ &m) { return self == other_cast; }, "Compare two observables"); - -#ifdef _ENABLE_PLGPU - class_name = "SparseHamiltonianC" + bitsize; - using np_arr_sparse_ind = typename std::conditional< - std::is_same::value, - py::array_t, - py::array_t>::type; - using IdxT = typename SparseHamiltonian::IdxT; - py::class_, - std::shared_ptr>, - Observable>(m, class_name.c_str(), - py::module_local()) - .def(py::init([](const np_arr_c &data, const np_arr_sparse_ind &indices, - const np_arr_sparse_ind &offsets, - const std::vector &wires) { - const py::buffer_info buffer_data = data.request(); - const auto *data_ptr = static_cast(buffer_data.ptr); - - const py::buffer_info buffer_indices = indices.request(); - const auto *indices_ptr = - static_cast(buffer_indices.ptr); - - const py::buffer_info buffer_offsets = offsets.request(); - const auto *offsets_ptr = - static_cast(buffer_offsets.ptr); - - return SparseHamiltonian{ - std::vector({data_ptr, data_ptr + data.size()}), - std::vector({indices_ptr, indices_ptr + indices.size()}), - std::vector({offsets_ptr, offsets_ptr + offsets.size()}), - wires}; - })) - .def("__repr__", &SparseHamiltonian::getObsName) - .def("get_wires", &SparseHamiltonian::getWires, - "Get wires of observables") - .def( - "__eq__", - [](const SparseHamiltonian &self, - py::handle other) -> bool { - if (!py::isinstance>(other)) { - return false; - } - auto other_cast = other.cast>(); - return self == other_cast; - }, - "Compare two observables"); -#endif - -#if _ENABLE_PLKOKKOS == 1 - class_name = "SparseHamiltonianC" + bitsize; - py::class_, - std::shared_ptr>, - Observable>(m, class_name.c_str(), - py::module_local()) - .def(py::init([](const np_arr_c &data, - const std::vector &indices, - const std::vector &indptr, - const std::vector &wires) { - using ComplexT = typename StateVectorT::ComplexT; - const py::buffer_info buffer_data = data.request(); - const auto *data_ptr = static_cast(buffer_data.ptr); - - return SparseHamiltonian{ - std::vector({data_ptr, data_ptr + data.size()}), - indices, indptr, wires}; - })) - .def("__repr__", &SparseHamiltonian::getObsName) - .def("get_wires", &SparseHamiltonian::getWires, - "Get wires of observables") - .def( - "__eq__", - [](const SparseHamiltonian &self, - py::handle other) -> bool { - if (!py::isinstance>(other)) { - return false; - } - auto other_cast = other.cast>(); - return self == other_cast; - }, - "Compare two observables"); -#endif } /** @@ -708,7 +628,9 @@ template void lightningClassBindings(py::module_ &m) { /* Observables submodule */ py::module_ obs_submodule = m.def_submodule("observables", "Submodule for observables classes."); - registerObservables(obs_submodule); + // registerBackendAgnosticObservables(obs_submodule); + registerBackendAgnosticObservables(obs_submodule); + registerBackendSpecificObservables(obs_submodule); //***********************************************************************// // Measurements diff --git a/pennylane_lightning/core/src/simulators/lightning_gpu/bindings/LGPUBindings.hpp b/pennylane_lightning/core/src/simulators/lightning_gpu/bindings/LGPUBindings.hpp index 3f4e81b015..2ebf7d3f95 100644 --- a/pennylane_lightning/core/src/simulators/lightning_gpu/bindings/LGPUBindings.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_gpu/bindings/LGPUBindings.hpp @@ -264,6 +264,73 @@ void registerBackendSpecificMeasurements(PyClass &pyclass) { "Variance of a sparse Hamiltonian."); } +/** + * @brief Register backend specific observables. + * + * @tparam StateVectorT + * @param m Pybind module + */ +template +void registerBackendSpecificObservables(py::module_ &m) { + using PrecisionT = + typename StateVectorT::PrecisionT; // Statevector's precision. + using ComplexT = + typename StateVectorT::ComplexT; // Statevector's complex type. + using ParamT = PrecisionT; // Parameter's data precision + + const std::string bitsize = + std::to_string(sizeof(std::complex) * 8); + + using np_arr_c = py::array_t, py::array::c_style>; + + std::string class_name; + + class_name = "SparseHamiltonianC" + bitsize; + using np_arr_sparse_ind = typename std::conditional< + std::is_same::value, + py::array_t, + py::array_t>::type; + using IdxT = typename SparseHamiltonian::IdxT; + py::class_, + std::shared_ptr>, + Observable>(m, class_name.c_str(), + py::module_local()) + .def(py::init([](const np_arr_c &data, const np_arr_sparse_ind &indices, + const np_arr_sparse_ind &offsets, + const std::vector &wires) { + const py::buffer_info buffer_data = data.request(); + const auto *data_ptr = static_cast(buffer_data.ptr); + + const py::buffer_info buffer_indices = indices.request(); + const auto *indices_ptr = + static_cast(buffer_indices.ptr); + + const py::buffer_info buffer_offsets = offsets.request(); + const auto *offsets_ptr = + static_cast(buffer_offsets.ptr); + + return SparseHamiltonian{ + std::vector({data_ptr, data_ptr + data.size()}), + std::vector({indices_ptr, indices_ptr + indices.size()}), + std::vector({offsets_ptr, offsets_ptr + offsets.size()}), + wires}; + })) + .def("__repr__", &SparseHamiltonian::getObsName) + .def("get_wires", &SparseHamiltonian::getWires, + "Get wires of observables") + .def( + "__eq__", + [](const SparseHamiltonian &self, + py::handle other) -> bool { + if (!py::isinstance>(other)) { + return false; + } + auto other_cast = other.cast>(); + return self == other_cast; + }, + "Compare two observables"); +} + /** * @brief Register backend specific adjoint Jacobian methods. * 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 bd9d89d72f..6432864c4e 100644 --- a/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_kokkos/bindings/LKokkosBindings.hpp @@ -24,6 +24,7 @@ #include "ConstantUtil.hpp" // lookup #include "GateOperation.hpp" #include "MeasurementsKokkos.hpp" +#include "ObservablesKokkos.hpp" #include "StateVectorKokkos.hpp" #include "TypeList.hpp" #include "Util.hpp" // exp2 @@ -33,6 +34,7 @@ namespace { using namespace Pennylane::Bindings; using namespace Pennylane::LightningKokkos::Algorithms; using namespace Pennylane::LightningKokkos::Measures; +using namespace Pennylane::LightningKokkos::Observables; using Kokkos::InitializationSettings; using Pennylane::LightningKokkos::StateVectorKokkos; using Pennylane::Util::exp2; @@ -214,6 +216,58 @@ void registerBackendSpecificMeasurements(PyClass &pyclass) { "Variance of a sparse Hamiltonian."); } +/** + * @brief Register observable classes. + * + * @tparam StateVectorT + * @param m Pybind module + */ +template +void registerBackendSpecificObservables(py::module_ &m) { + using PrecisionT = + typename StateVectorT::PrecisionT; // Statevector's precision. + using ParamT = PrecisionT; // Parameter's data precision + + const std::string bitsize = + std::to_string(sizeof(std::complex) * 8); + + using np_arr_c = py::array_t, py::array::c_style>; + + std::string class_name; + + class_name = "SparseHamiltonianC" + bitsize; + py::class_, + std::shared_ptr>, + Observable>(m, class_name.c_str(), + py::module_local()) + .def(py::init([](const np_arr_c &data, + const std::vector &indices, + const std::vector &indptr, + const std::vector &wires) { + using ComplexT = typename StateVectorT::ComplexT; + const py::buffer_info buffer_data = data.request(); + const auto *data_ptr = static_cast(buffer_data.ptr); + + return SparseHamiltonian{ + std::vector({data_ptr, data_ptr + data.size()}), + indices, indptr, wires}; + })) + .def("__repr__", &SparseHamiltonian::getObsName) + .def("get_wires", &SparseHamiltonian::getWires, + "Get wires of observables") + .def( + "__eq__", + [](const SparseHamiltonian &self, + py::handle other) -> bool { + if (!py::isinstance>(other)) { + return false; + } + auto other_cast = other.cast>(); + return self == other_cast; + }, + "Compare two observables"); +} + /** * @brief Register backend specific adjoint Jacobian methods. * diff --git a/pennylane_lightning/core/src/simulators/lightning_qubit/bindings/LQubitBindings.hpp b/pennylane_lightning/core/src/simulators/lightning_qubit/bindings/LQubitBindings.hpp index 190a9c6525..7cd5a1ee2e 100644 --- a/pennylane_lightning/core/src/simulators/lightning_qubit/bindings/LQubitBindings.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_qubit/bindings/LQubitBindings.hpp @@ -180,6 +180,15 @@ void registerBackendSpecificMeasurements(PyClass &pyclass) { }); } +/** + * @brief Register backend specific observables. + * + * @tparam StateVectorT + * @param m Pybind module + */ +template +void registerBackendSpecificObservables([[maybe_unused]] py::module_ &m) {} + /** * @brief Register Vector Jacobian Product. */