From 1391e2b907fbbfdebf896fd47a0f59c9dcb48516 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 17 Jan 2025 06:51:40 +0000 Subject: [PATCH] cpu-statevector on gpu --- exe/main.cpp | 95 ++++- include/scaluq/gate/gate_factory.hpp | 326 +++++++-------- include/scaluq/gate/gate_matrix.hpp | 36 +- include/scaluq/gate/gate_pauli.hpp | 52 +-- include/scaluq/gate/gate_probablistic.hpp | 28 +- include/scaluq/gate/gate_standard.hpp | 456 +++++++++++---------- include/scaluq/operator/operator.hpp | 95 +++-- include/scaluq/operator/pauli_operator.hpp | 79 ++-- include/scaluq/state/state_vector.hpp | 8 +- src/CMakeLists.txt | 14 +- src/gate/gate_matrix.cpp | 76 ++-- src/gate/gate_pauli.cpp | 32 +- src/gate/gate_probablistic.cpp | 38 +- src/gate/gate_standard.cpp | 416 +++++++++---------- src/gate/update_ops_standard.cpp | 24 +- src/operator/apply_pauli.cpp | 56 +-- src/operator/apply_pauli.hpp | 20 +- src/operator/operator.cpp | 94 ++--- src/operator/pauli_operator.cpp | 75 ++-- src/state/state_vector.cpp | 22 +- 20 files changed, 1085 insertions(+), 957 deletions(-) diff --git a/exe/main.cpp b/exe/main.cpp index 4e3372b6..4f97312c 100644 --- a/exe/main.cpp +++ b/exe/main.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include using namespace scaluq; using namespace nlohmann; @@ -14,22 +14,89 @@ int main() { Kokkos::Timer tm; for (int i = 0; i < 10; ++i) { - // auto xgate = scaluq::gate::X(2); - // xgate->update_quantum_state(gpu_state); + auto xgate = scaluq::gate::X(2); + xgate->update_quantum_state(gpu_state); + } + std::cout << tm.seconds() << std::endl; + } + { + std::uint64_t n_qubits = 28; + scaluq::StateVector cpu_state(n_qubits); + + Kokkos::Timer tm; + for (int i = 0; i < 10; ++i) { + auto xgate = scaluq::gate::X(2); + xgate->update_quantum_state(cpu_state); + } + std::cout << tm.seconds() << std::endl; + } + { + std::uint64_t n_qubits = 28; + scaluq::StateVector gpu_state(n_qubits); + + Kokkos::Timer tm; + for (int i = 0; i < 10; ++i) { + auto xgate = scaluq::gate::X(2); + xgate->update_quantum_state(gpu_state); + } + std::cout << tm.seconds() << std::endl; + } + { + std::uint64_t n_qubits = 28; + scaluq::StateVector cpu_state(n_qubits); + + Kokkos::Timer tm; + for (int i = 0; i < 10; ++i) { + auto xgate = scaluq::gate::X(2); + xgate->update_quantum_state(cpu_state); + } + std::cout << tm.seconds() << std::endl; + } + + { + std::uint64_t n_qubits = 5; + scaluq::StateVector gpu_state(n_qubits); + + Kokkos::Timer tm; + for (int i = 0; i < 1000; ++i) { + auto xgate = scaluq::gate::X(2); + xgate->update_quantum_state(gpu_state); + } + std::cout << tm.seconds() << std::endl; + } + { + std::uint64_t n_qubits = 5; + scaluq::StateVector cpu_state(n_qubits); + + Kokkos::Timer tm; + for (int i = 0; i < 1000; ++i) { + auto xgate = scaluq::gate::X(2); + xgate->update_quantum_state(cpu_state); + } + std::cout << tm.seconds() << std::endl; + } + { + std::uint64_t n_qubits = 5; + scaluq::StateVector gpu_state(n_qubits); + + Kokkos::Timer tm; + for (int i = 0; i < 1000; ++i) { + auto xgate = scaluq::gate::X(2); + xgate->update_quantum_state(gpu_state); + } + std::cout << tm.seconds() << std::endl; + } + { + std::uint64_t n_qubits = 5; + scaluq::StateVector cpu_state(n_qubits); + + Kokkos::Timer tm; + for (int i = 0; i < 1000; ++i) { + auto xgate = scaluq::gate::X(2); + xgate->update_quantum_state(cpu_state); } std::cout << tm.seconds() << std::endl; } - // { - // std::uint64_t n_qubits = 28; - // scaluq::StateVector cpu_state(n_qubits); - - // Kokkos::Timer tm; - // for (int i = 0; i < 10; ++i) { - // // auto xgate = scaluq::gate::X(2); - // // xgate->update_quantum_state(cpu_state); - // } - // std::cout << tm.seconds() << std::endl; - // } // { // std::uint64_t n_qubits = 3; diff --git a/include/scaluq/gate/gate_factory.hpp b/include/scaluq/gate/gate_factory.hpp index 5fb79040..f485ee58 100644 --- a/include/scaluq/gate/gate_factory.hpp +++ b/include/scaluq/gate/gate_factory.hpp @@ -11,184 +11,186 @@ namespace internal { class GateFactory { public: template - static Gate create_gate(Args... args) { + static Gate create_gate(Args... args) { return {std::make_shared(args...)}; } }; } // namespace internal namespace gate { -template -inline Gate I() { - return internal::GateFactory::create_gate>(); +template +inline Gate I() { + return internal::GateFactory::create_gate>(); } -template -inline Gate GlobalPhase(Fp phase, const std::vector& control_qubits = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate GlobalPhase(Fp phase, const std::vector& control_qubits = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask(control_qubits), phase); } -template -inline Gate X(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate X(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate Y(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate Y(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate Z(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate Z(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate H(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate H(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate S(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate S(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate Sdag(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate Sdag(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate T(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate T(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate Tdag(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate Tdag(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate SqrtX(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate SqrtX(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate SqrtXdag(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate SqrtXdag(std::uint64_t target, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate SqrtY(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate SqrtY(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate SqrtYdag(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate SqrtYdag(std::uint64_t target, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate P0(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate P0(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate P1(std::uint64_t target, const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate P1(std::uint64_t target, const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls)); } -template -inline Gate RX(std::uint64_t target, - Fp angle, - const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate RX(std::uint64_t target, + Fp angle, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls), angle); } -template -inline Gate RY(std::uint64_t target, - Fp angle, - const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate RY(std::uint64_t target, + Fp angle, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls), angle); } -template -inline Gate RZ(std::uint64_t target, - Fp angle, - const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate RZ(std::uint64_t target, + Fp angle, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls), angle); } -template -inline Gate U1(std::uint64_t target, - Fp lambda, - const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate U1(std::uint64_t target, + Fp lambda, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls), lambda); } -template -inline Gate U2(std::uint64_t target, - Fp phi, - Fp lambda, - const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate U2(std::uint64_t target, + Fp phi, + Fp lambda, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls), phi, lambda); } -template -inline Gate U3(std::uint64_t target, - Fp theta, - Fp phi, - Fp lambda, - const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate U3(std::uint64_t target, + Fp theta, + Fp phi, + Fp lambda, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask(controls), theta, phi, lambda); } -template -inline Gate CX(std::uint64_t control, std::uint64_t target) { - return internal::GateFactory::create_gate>( +template +inline Gate CX(std::uint64_t control, std::uint64_t target) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask({control})); } -template -inline auto& CNot = CX; -template -inline Gate CZ(std::uint64_t control, std::uint64_t target) { - return internal::GateFactory::create_gate>( +template +inline auto& CNot = CX; +template +inline Gate CZ(std::uint64_t control, std::uint64_t target) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask({control})); } -template -inline Gate CCX(std::uint64_t control1, std::uint64_t control2, std::uint64_t target) { - return internal::GateFactory::create_gate>( +template +inline Gate CCX(std::uint64_t control1, std::uint64_t control2, std::uint64_t target) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target}), internal::vector_to_mask({control1, control2})); } -template -inline auto& Toffoli = CCX; -template -inline auto& CCNot = CCX; -template -inline Gate Swap(std::uint64_t target1, - std::uint64_t target2, - const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline auto& Toffoli = CCX; +template +inline auto& CCNot = CCX; +template +inline Gate Swap(std::uint64_t target1, + std::uint64_t target2, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask({target1, target2}), internal::vector_to_mask(controls)); } -template -inline Gate Pauli(const PauliOperator& pauli, - const std::vector& controls = {}) { +template +inline Gate Pauli(const PauliOperator& pauli, + const std::vector& controls = {}) { auto tar = pauli.target_qubit_list(); - return internal::GateFactory::create_gate>( + return internal::GateFactory::create_gate>( internal::vector_to_mask(controls), pauli); } -template -inline Gate PauliRotation(const PauliOperator& pauli, - Fp angle, - const std::vector& controls = {}) { - return internal::GateFactory::create_gate>( +template +inline Gate PauliRotation(const PauliOperator& pauli, + Fp angle, + const std::vector& controls = {}) { + return internal::GateFactory::create_gate>( internal::vector_to_mask(controls), pauli, angle); } -template -inline Gate DenseMatrix(const std::vector& targets, - const internal::ComplexMatrix& matrix, - const std::vector& controls = {}, - bool is_unitary = false) { +template +inline Gate DenseMatrix(const std::vector& targets, + const internal::ComplexMatrix& matrix, + const std::vector& controls = {}, + bool is_unitary = false) { std::uint64_t nqubits = targets.size(); std::uint64_t dim = 1ULL << nqubits; if (static_cast(matrix.rows()) != dim || @@ -199,7 +201,7 @@ inline Gate DenseMatrix(const std::vector& targets, "matrix size must be 2^{n_qubits} x 2^{n_qubits}."); } if (std::is_sorted(targets.begin(), targets.end())) { - return internal::GateFactory::create_gate>( + return internal::GateFactory::create_gate>( internal::vector_to_mask(targets), internal::vector_to_mask(controls), matrix, @@ -207,146 +209,146 @@ inline Gate DenseMatrix(const std::vector& targets, } internal::ComplexMatrix matrix_transformed = internal::transform_dense_matrix_by_order(matrix, targets); - return internal::GateFactory::create_gate>( + return internal::GateFactory::create_gate>( internal::vector_to_mask(targets), internal::vector_to_mask(controls), matrix_transformed, is_unitary); } -template -inline Gate SparseMatrix(const std::vector& targets, - const internal::SparseComplexMatrix& matrix, - const std::vector& controls = {}) { +template +inline Gate SparseMatrix(const std::vector& targets, + const internal::SparseComplexMatrix& matrix, + const std::vector& controls = {}) { if (std::is_sorted(targets.begin(), targets.end())) { - return internal::GateFactory::create_gate>( + return internal::GateFactory::create_gate>( internal::vector_to_mask(targets), internal::vector_to_mask(controls), matrix); } internal::SparseComplexMatrix matrix_transformed = internal::transform_sparse_matrix_by_order(matrix, targets); - return internal::GateFactory::create_gate>( + return internal::GateFactory::create_gate>( internal::vector_to_mask(targets), internal::vector_to_mask(controls), matrix_transformed); } -template -inline Gate Probablistic(const std::vector& distribution, - const std::vector>& gate_list) { - return internal::GateFactory::create_gate>(distribution, - gate_list); +template +inline Gate Probablistic(const std::vector& distribution, + const std::vector>& gate_list) { + return internal::GateFactory::create_gate>(distribution, + gate_list); } } // namespace gate #ifdef SCALUQ_USE_NANOBIND namespace internal { -template +template void bind_gate_gate_factory_hpp(nb::module_& mgate) { - mgate.def("I", &gate::I, "Generate general Gate class instance of I."); + mgate.def("I", &gate::I, "Generate general Gate class instance of I."); mgate.def("GlobalPhase", - &gate::GlobalPhase, + &gate::GlobalPhase, "Generate general Gate class instance of GlobalPhase.", "phase"_a, "controls"_a = std::vector{}); mgate.def("X", - &gate::X, + &gate::X, "Generate general Gate class instance of X.", "target"_a, "controls"_a = std::vector{}); mgate.def("Y", - &gate::Y, + &gate::Y, "Generate general Gate class instance of Y.", "taget"_a, "controls"_a = std::vector{}); mgate.def("Z", - &gate::Z, + &gate::Z, "Generate general Gate class instance of Z.", "target"_a, "controls"_a = std::vector{}); mgate.def("H", - &gate::H, + &gate::H, "Generate general Gate class instance of H.", "target"_a, "controls"_a = std::vector{}); mgate.def("S", - &gate::S, + &gate::S, "Generate general Gate class instance of S.", "target"_a, "controls"_a = std::vector{}); mgate.def("Sdag", - &gate::Sdag, + &gate::Sdag, "Generate general Gate class instance of Sdag.", "target"_a, "controls"_a = std::vector{}); mgate.def("T", - &gate::T, + &gate::T, "Generate general Gate class instance of T.", "target"_a, "controls"_a = std::vector{}); mgate.def("Tdag", - &gate::Tdag, + &gate::Tdag, "Generate general Gate class instance of Tdag.", "target"_a, "controls"_a = std::vector{}); mgate.def("SqrtX", - &gate::SqrtX, + &gate::SqrtX, "Generate general Gate class instance of SqrtX.", "target"_a, "controls"_a = std::vector{}); mgate.def("SqrtXdag", - &gate::SqrtXdag, + &gate::SqrtXdag, "Generate general Gate class instance of SqrtXdag.", "target"_a, "controls"_a = std::vector{}); mgate.def("SqrtY", - &gate::SqrtY, + &gate::SqrtY, "Generate general Gate class instance of SqrtY.", "target"_a, "controls"_a = std::vector{}); mgate.def("SqrtYdag", - &gate::SqrtYdag, + &gate::SqrtYdag, "Generate general Gate class instance of SqrtYdag.", "target"_a, "controls"_a = std::vector{}); mgate.def("P0", - &gate::P0, + &gate::P0, "Generate general Gate class instance of P0.", "target"_a, "controls"_a = std::vector{}); mgate.def("P1", - &gate::P1, + &gate::P1, "Generate general Gate class instance of P1.", "target"_a, "controls"_a = std::vector{}); mgate.def("RX", - &gate::RX, + &gate::RX, "Generate general Gate class instance of RX.", "target"_a, "angle"_a, "controls"_a = std::vector{}); mgate.def("RY", - &gate::RY, + &gate::RY, "Generate general Gate class instance of RY.", "target"_a, "angle"_a, "controls"_a = std::vector{}); mgate.def("RZ", - &gate::RZ, + &gate::RZ, "Generate general Gate class instance of RZ.", "target"_a, "angle"_a, "controls"_a = std::vector{}); mgate.def("U1", - &gate::U1, + &gate::U1, "Generate general Gate class instance of U1.", "target"_a, "lambda_"_a, "controls"_a = std::vector{}); mgate.def("U2", - &gate::U2, + &gate::U2, "Generate general Gate class instance of U2.", "target"_a, "phi"_a, "lambda_"_a, "controls"_a = std::vector{}); mgate.def("U3", - &gate::U3, + &gate::U3, "Generate general Gate class instance of U3.", "target"_a, "theta"_a, @@ -354,32 +356,32 @@ void bind_gate_gate_factory_hpp(nb::module_& mgate) { "lambda_"_a, "controls"_a = std::vector{}); mgate.def("Swap", - &gate::Swap, + &gate::Swap, "Generate general Gate class instance of Swap.", "target1"_a, "target2"_a, "controls"_a = std::vector{}); mgate.def( "CX", - &gate::CX, + &gate::CX, "Generate general Gate class instance of CX.\n\n.. note:: CX is a specialization of X."); mgate.def("CNot", - &gate::CX, + &gate::CX, "Generate general Gate class instance of CNot.\n\n.. note:: CNot is an alias of CX."); mgate.def( "CZ", - &gate::CZ, + &gate::CZ, "Generate general Gate class instance of CZ.\n\n.. note:: CZ is a specialization of Z."); mgate.def( "CCX", - &gate::CCX, + &gate::CCX, "Generate general Gate class instance of CXX.\n\n.. note:: CX is a specialization of X."); mgate.def( "CCNot", - &gate::CCX, + &gate::CCX, "Generate general Gate class instance of CCNot.\n\n.. note:: CCNot is an alias of CCX."); mgate.def("Toffoli", - &gate::CCX, + &gate::CCX, "Generate general Gate class instance of Toffoli.\n\n.. note:: Toffoli is an alias " "of CCX."); mgate.def("DenseMatrix", @@ -396,18 +398,18 @@ void bind_gate_gate_factory_hpp(nb::module_& mgate) { "matrix"_a, "controls"_a = std::vector{}); mgate.def("Pauli", - &gate::Pauli, + &gate::Pauli, "Generate general Gate class instance of Pauli.", "pauli"_a, "controls"_a = std::vector{}); mgate.def("PauliRotation", - &gate::PauliRotation, + &gate::PauliRotation, "Generate general Gate class instance of PauliRotation.", "pauli"_a, "angle"_a, "controls"_a = std::vector{}); mgate.def("Probablistic", - &gate::Probablistic, + &gate::Probablistic, "Generate general Gate class instance of Probablistic.", "distribution"_a, "gate_list"_a); diff --git a/include/scaluq/gate/gate_matrix.hpp b/include/scaluq/gate/gate_matrix.hpp index 4de24bd6..f30002ba 100644 --- a/include/scaluq/gate/gate_matrix.hpp +++ b/include/scaluq/gate/gate_matrix.hpp @@ -10,8 +10,8 @@ namespace scaluq { namespace internal { -template -class DenseMatrixGateImpl : public GateBase { +template +class DenseMatrixGateImpl : public GateBase { Matrix _matrix; bool _is_unitary; @@ -21,14 +21,14 @@ class DenseMatrixGateImpl : public GateBase { const ComplexMatrix& mat, bool is_unitary = false); - std::shared_ptr> get_inverse() const override; + std::shared_ptr> get_inverse() const override; Matrix get_matrix_internal() const; ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -40,8 +40,8 @@ class DenseMatrixGateImpl : public GateBase { } }; -template -class SparseMatrixGateImpl : public GateBase { +template +class SparseMatrixGateImpl : public GateBase { SparseMatrix _matrix; std::uint64_t num_nnz; @@ -50,7 +50,7 @@ class SparseMatrixGateImpl : public GateBase { std::uint64_t control_mask, const SparseComplexMatrix& mat); - std::shared_ptr> get_inverse() const override; + std::shared_ptr> get_inverse() const override; Matrix get_matrix_internal() const; @@ -58,8 +58,8 @@ class SparseMatrixGateImpl : public GateBase { SparseComplexMatrix get_sparse_matrix() const { return get_matrix().sparseView(); } - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -73,21 +73,21 @@ class SparseMatrixGateImpl : public GateBase { } // namespace internal -template -using SparseMatrixGate = internal::GatePtr>; -template -using DenseMatrixGate = internal::GatePtr>; +template +using SparseMatrixGate = internal::GatePtr>; +template +using DenseMatrixGate = internal::GatePtr>; #ifdef SCALUQ_USE_NANOBIND namespace internal { -template +template void bind_gate_gate_matrix_hpp(nb::module_& m) { DEF_GATE(SparseMatrixGate, Fp, "Specific class of sparse matrix gate.") - .def("matrix", [](const SparseMatrixGate& gate) { return gate->get_matrix(); }) + .def("matrix", [](const SparseMatrixGate& gate) { return gate->get_matrix(); }) .def("sparse_matrix", - [](const SparseMatrixGate& gate) { return gate->get_sparse_matrix(); }); + [](const SparseMatrixGate& gate) { return gate->get_sparse_matrix(); }); DEF_GATE(DenseMatrixGate, Fp, "Specific class of dense matrix gate.") - .def("matrix", [](const DenseMatrixGate& gate) { return gate->get_matrix(); }); + .def("matrix", [](const DenseMatrixGate& gate) { return gate->get_matrix(); }); } } // namespace internal #endif diff --git a/include/scaluq/gate/gate_pauli.hpp b/include/scaluq/gate/gate_pauli.hpp index 71157c63..8fce132b 100644 --- a/include/scaluq/gate/gate_pauli.hpp +++ b/include/scaluq/gate/gate_pauli.hpp @@ -9,25 +9,25 @@ namespace scaluq { namespace internal { -template -class PauliGateImpl : public GateBase { - const PauliOperator _pauli; +template +class PauliGateImpl : public GateBase { + const PauliOperator _pauli; public: - PauliGateImpl(std::uint64_t control_mask, const PauliOperator& pauli) - : GateBase(vector_to_mask(pauli.target_qubit_list()), control_mask), + PauliGateImpl(std::uint64_t control_mask, const PauliOperator& pauli) + : GateBase(vector_to_mask(pauli.target_qubit_list()), control_mask), _pauli(pauli) {} - PauliOperator pauli() const { return _pauli; }; + PauliOperator pauli() const { return _pauli; }; std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { return this->shared_from_this(); } internal::ComplexMatrix get_matrix() const override { return this->_pauli.get_matrix(); } - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -37,30 +37,30 @@ class PauliGateImpl : public GateBase { } }; -template -class PauliRotationGateImpl : public GateBase { - const PauliOperator _pauli; +template +class PauliRotationGateImpl : public GateBase { + const PauliOperator _pauli; const Fp _angle; public: - PauliRotationGateImpl(std::uint64_t control_mask, const PauliOperator& pauli, Fp angle) - : GateBase(vector_to_mask(pauli.target_qubit_list()), control_mask), + PauliRotationGateImpl(std::uint64_t control_mask, const PauliOperator& pauli, Fp angle) + : GateBase(vector_to_mask(pauli.target_qubit_list()), control_mask), _pauli(pauli), _angle(angle) {} - PauliOperator pauli() const { return _pauli; } + PauliOperator pauli() const { return _pauli; } std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } Fp angle() const { return _angle; } - std::shared_ptr> get_inverse() const override { - return std::make_shared>( + std::shared_ptr> get_inverse() const override { + return std::make_shared>( this->_control_mask, _pauli, -_angle); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -73,13 +73,13 @@ class PauliRotationGateImpl : public GateBase { }; } // namespace internal -template -using PauliGate = internal::GatePtr>; -template -using PauliRotationGate = internal::GatePtr>; +template +using PauliGate = internal::GatePtr>; +template +using PauliRotationGate = internal::GatePtr>; namespace internal { -#define DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE(Type) \ +/*#define DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE(Type) \ template <> \ inline std::shared_ptr> get_from_json(const Json& j) { \ auto controls = j.at("control").get>(); \ @@ -97,13 +97,13 @@ namespace internal { DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE(double) DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE(float) -#undef DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE +#undef DECLARE_GET_FROM_JSON_PAULIGATE_WITH_TYPE*/ } // namespace internal #ifdef SCALUQ_USE_NANOBIND namespace internal { -template +template void bind_gate_gate_pauli_hpp(nb::module_& m) { DEF_GATE(PauliGate, Fp, diff --git a/include/scaluq/gate/gate_probablistic.hpp b/include/scaluq/gate/gate_probablistic.hpp index 5d656ccd..14a280fa 100644 --- a/include/scaluq/gate/gate_probablistic.hpp +++ b/include/scaluq/gate/gate_probablistic.hpp @@ -8,16 +8,16 @@ namespace scaluq { namespace internal { -template -class ProbablisticGateImpl : public GateBase { +template +class ProbablisticGateImpl : public GateBase { std::vector _distribution; std::vector _cumulative_distribution; - std::vector> _gate_list; + std::vector> _gate_list; public: ProbablisticGateImpl(const std::vector& distribution, - const std::vector>& gate_list); - const std::vector>& gate_list() const { return _gate_list; } + const std::vector>& gate_list); + const std::vector>& gate_list() const { return _gate_list; } const std::vector& distribution() const { return _distribution; } std::vector target_qubit_list() const override { @@ -51,15 +51,15 @@ class ProbablisticGateImpl : public GateBase { "ProbablisticGateImpl."); } - std::shared_ptr> get_inverse() const override; + std::shared_ptr> get_inverse() const override; internal::ComplexMatrix get_matrix() const override { throw std::runtime_error( "ProbablisticGateImpl::get_matrix(): This function must not be used in " "ProbablisticGateImpl."); } - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -71,12 +71,12 @@ class ProbablisticGateImpl : public GateBase { }; } // namespace internal -template -using ProbablisticGate = internal::GatePtr>; +template +using ProbablisticGate = internal::GatePtr>; namespace internal { -#define DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE(Type) \ +/*#define DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE(Type) \ template <> \ inline std::shared_ptr> get_from_json(const Json& j) { \ auto distribution = j.at("distribution").get>(); \ @@ -86,7 +86,7 @@ namespace internal { DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE(double) DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE(float) -#undef DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE +#undef DECLARE_GET_FROM_JSON_PROBGATE_WITH_TYPE*/ } // namespace internal @@ -100,11 +100,11 @@ void bind_gate_gate_probablistic(nb::module_& m) { "distribution.") .def( "gate_list", - [](const ProbablisticGate& gate) { return gate->gate_list(); }, + [](const ProbablisticGate& gate) { return gate->gate_list(); }, nb::rv_policy::reference) .def( "distribution", - [](const ProbablisticGate& gate) { return gate->distribution(); }, + [](const ProbablisticGate& gate) { return gate->distribution(); }, nb::rv_policy::reference); } } // namespace internal diff --git a/include/scaluq/gate/gate_standard.hpp b/include/scaluq/gate/gate_standard.hpp index 50dc2668..8a02fde1 100644 --- a/include/scaluq/gate/gate_standard.hpp +++ b/include/scaluq/gate/gate_standard.hpp @@ -6,42 +6,42 @@ namespace scaluq { namespace internal { -template -class IGateImpl : public GateBase { +template +class IGateImpl : public GateBase { public: - IGateImpl() : GateBase(0, 0) {} + IGateImpl() : GateBase(0, 0) {} - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { return this->shared_from_this(); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; void get_as_json(Json& j) const override { j = Json{{"type", "I"}}; } }; -template -class GlobalPhaseGateImpl : public GateBase { +template +class GlobalPhaseGateImpl : public GateBase { protected: Fp _phase; public: GlobalPhaseGateImpl(std::uint64_t control_mask, Fp phase) - : GateBase(0, control_mask), _phase(phase){}; + : GateBase(0, control_mask), _phase(phase){}; [[nodiscard]] Fp phase() const { return _phase; } - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_control_mask, -_phase); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_control_mask, -_phase); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -53,30 +53,30 @@ class GlobalPhaseGateImpl : public GateBase { } }; -template -class RotationGateBase : public GateBase { +template +class RotationGateBase : public GateBase { protected: Fp _angle; public: RotationGateBase(std::uint64_t target_mask, std::uint64_t control_mask, Fp angle) - : GateBase(target_mask, control_mask), _angle(angle) {} + : GateBase(target_mask, control_mask), _angle(angle) {} Fp angle() const { return _angle; } }; -template -class XGateImpl : public GateBase { +template +class XGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { return this->shared_from_this(); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -87,18 +87,18 @@ class XGateImpl : public GateBase { } }; -template -class YGateImpl : public GateBase { +template +class YGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { return this->shared_from_this(); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -109,18 +109,18 @@ class YGateImpl : public GateBase { } }; -template -class ZGateImpl : public GateBase { +template +class ZGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { return this->shared_from_this(); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -131,18 +131,18 @@ class ZGateImpl : public GateBase { } }; -template -class HGateImpl : public GateBase { +template +class HGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { return this->shared_from_this(); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -153,35 +153,36 @@ class HGateImpl : public GateBase { } }; -template +template class SGateImpl; -template +template class SdagGateImpl; -template +template class TGateImpl; -template +template class TdagGateImpl; -template +template class SqrtXGateImpl; -template +template class SqrtXdagGateImpl; -template +template class SqrtYGateImpl; -template +template class SqrtYdagGateImpl; -template -class SGateImpl : public GateBase { +template +class SGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, this->_control_mask); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, + this->_control_mask); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -192,18 +193,18 @@ class SGateImpl : public GateBase { } }; -template -class SdagGateImpl : public GateBase { +template +class SdagGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, this->_control_mask); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, this->_control_mask); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -214,18 +215,19 @@ class SdagGateImpl : public GateBase { } }; -template -class TGateImpl : public GateBase { +template +class TGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, this->_control_mask); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, + this->_control_mask); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -236,18 +238,18 @@ class TGateImpl : public GateBase { } }; -template -class TdagGateImpl : public GateBase { +template +class TdagGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, this->_control_mask); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, this->_control_mask); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -258,20 +260,20 @@ class TdagGateImpl : public GateBase { } }; -template -class SqrtXGateImpl : public GateBase { +template +class SqrtXGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, - this->_control_mask); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, + this->_control_mask); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -282,18 +284,19 @@ class SqrtXGateImpl : public GateBase { } }; -template -class SqrtXdagGateImpl : public GateBase { +template +class SqrtXdagGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, this->_control_mask); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, + this->_control_mask); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -304,20 +307,20 @@ class SqrtXdagGateImpl : public GateBase { } }; -template -class SqrtYGateImpl : public GateBase { +template +class SqrtYGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, - this->_control_mask); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, + this->_control_mask); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -328,18 +331,19 @@ class SqrtYGateImpl : public GateBase { } }; -template -class SqrtYdagGateImpl : public GateBase { +template +class SqrtYdagGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, this->_control_mask); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, + this->_control_mask); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -350,18 +354,18 @@ class SqrtYdagGateImpl : public GateBase { } }; -template -class P0GateImpl : public GateBase { +template +class P0GateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { throw std::runtime_error("P0::get_inverse: Projection gate doesn't have inverse gate"); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -372,18 +376,18 @@ class P0GateImpl : public GateBase { } }; -template -class P1GateImpl : public GateBase { +template +class P1GateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { throw std::runtime_error("P1::get_inverse: Projection gate doesn't have inverse gate"); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -394,19 +398,19 @@ class P1GateImpl : public GateBase { } }; -template -class RXGateImpl : public RotationGateBase { +template +class RXGateImpl : public RotationGateBase { public: - using RotationGateBase::RotationGateBase; + using RotationGateBase::RotationGateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>( + std::shared_ptr> get_inverse() const override { + return std::make_shared>( this->_target_mask, this->_control_mask, -this->_angle); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -418,19 +422,19 @@ class RXGateImpl : public RotationGateBase { } }; -template -class RYGateImpl : public RotationGateBase { +template +class RYGateImpl : public RotationGateBase { public: - using RotationGateBase::RotationGateBase; + using RotationGateBase::RotationGateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>( + std::shared_ptr> get_inverse() const override { + return std::make_shared>( this->_target_mask, this->_control_mask, -this->_angle); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -442,19 +446,19 @@ class RYGateImpl : public RotationGateBase { } }; -template -class RZGateImpl : public RotationGateBase { +template +class RZGateImpl : public RotationGateBase { public: - using RotationGateBase::RotationGateBase; + using RotationGateBase::RotationGateBase; - std::shared_ptr> get_inverse() const override { - return std::make_shared>( + std::shared_ptr> get_inverse() const override { + return std::make_shared>( this->_target_mask, this->_control_mask, -this->_angle); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -466,24 +470,24 @@ class RZGateImpl : public RotationGateBase { } }; -template -class U1GateImpl : public GateBase { +template +class U1GateImpl : public GateBase { Fp _lambda; public: U1GateImpl(std::uint64_t target_mask, std::uint64_t control_mask, Fp lambda) - : GateBase(target_mask, control_mask), _lambda(lambda) {} + : GateBase(target_mask, control_mask), _lambda(lambda) {} Fp lambda() const { return _lambda; } - std::shared_ptr> get_inverse() const override { - return std::make_shared>( + std::shared_ptr> get_inverse() const override { + return std::make_shared>( this->_target_mask, this->_control_mask, -_lambda); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -494,27 +498,27 @@ class U1GateImpl : public GateBase { {"lambda", this->lambda()}}; } }; -template -class U2GateImpl : public GateBase { +template +class U2GateImpl : public GateBase { Fp _phi, _lambda; public: U2GateImpl(std::uint64_t target_mask, std::uint64_t control_mask, Fp phi, Fp lambda) - : GateBase(target_mask, control_mask), _phi(phi), _lambda(lambda) {} + : GateBase(target_mask, control_mask), _phi(phi), _lambda(lambda) {} Fp phi() const { return _phi; } Fp lambda() const { return _lambda; } - std::shared_ptr> get_inverse() const override { - return std::make_shared>(this->_target_mask, - this->_control_mask, - -_lambda - Kokkos::numbers::pi, - -_phi + Kokkos::numbers::pi); + std::shared_ptr> get_inverse() const override { + return std::make_shared>(this->_target_mask, + this->_control_mask, + -_lambda - Kokkos::numbers::pi, + -_phi + Kokkos::numbers::pi); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -527,26 +531,26 @@ class U2GateImpl : public GateBase { } }; -template -class U3GateImpl : public GateBase { +template +class U3GateImpl : public GateBase { Fp _theta, _phi, _lambda; public: U3GateImpl(std::uint64_t target_mask, std::uint64_t control_mask, Fp theta, Fp phi, Fp lambda) - : GateBase(target_mask, control_mask), _theta(theta), _phi(phi), _lambda(lambda) {} + : GateBase(target_mask, control_mask), _theta(theta), _phi(phi), _lambda(lambda) {} Fp theta() const { return _theta; } Fp phi() const { return _phi; } Fp lambda() const { return _lambda; } - std::shared_ptr> get_inverse() const override { - return std::make_shared>( + std::shared_ptr> get_inverse() const override { + return std::make_shared>( this->_target_mask, this->_control_mask, -_theta, -_lambda, -_phi); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -560,18 +564,18 @@ class U3GateImpl : public GateBase { } }; -template -class SwapGateImpl : public GateBase { +template +class SwapGateImpl : public GateBase { public: - using GateBase::GateBase; + using GateBase::GateBase; - std::shared_ptr> get_inverse() const override { + std::shared_ptr> get_inverse() const override { return this->shared_from_this(); } internal::ComplexMatrix get_matrix() const override; - void update_quantum_state(StateVector& state_vector) const override; - void update_quantum_state(StateVectorBatched& states) const override; + void update_quantum_state(StateVector& state_vector) const override; + void update_quantum_state(StateVectorBatched& states) const override; std::string to_string(const std::string& indent) const override; @@ -584,56 +588,56 @@ class SwapGateImpl : public GateBase { } // namespace internal -template -using IGate = internal::GatePtr>; -template -using GlobalPhaseGate = internal::GatePtr>; -template -using XGate = internal::GatePtr>; -template -using YGate = internal::GatePtr>; -template -using ZGate = internal::GatePtr>; -template -using HGate = internal::GatePtr>; -template -using SGate = internal::GatePtr>; -template -using SdagGate = internal::GatePtr>; -template -using TGate = internal::GatePtr>; -template -using TdagGate = internal::GatePtr>; -template -using SqrtXGate = internal::GatePtr>; -template -using SqrtXdagGate = internal::GatePtr>; -template -using SqrtYGate = internal::GatePtr>; -template -using SqrtYdagGate = internal::GatePtr>; -template -using P0Gate = internal::GatePtr>; -template -using P1Gate = internal::GatePtr>; -template -using RXGate = internal::GatePtr>; -template -using RYGate = internal::GatePtr>; -template -using RZGate = internal::GatePtr>; -template -using U1Gate = internal::GatePtr>; -template -using U2Gate = internal::GatePtr>; -template -using U3Gate = internal::GatePtr>; -template -using SwapGate = internal::GatePtr>; +template +using IGate = internal::GatePtr>; +template +using GlobalPhaseGate = internal::GatePtr>; +template +using XGate = internal::GatePtr>; +template +using YGate = internal::GatePtr>; +template +using ZGate = internal::GatePtr>; +template +using HGate = internal::GatePtr>; +template +using SGate = internal::GatePtr>; +template +using SdagGate = internal::GatePtr>; +template +using TGate = internal::GatePtr>; +template +using TdagGate = internal::GatePtr>; +template +using SqrtXGate = internal::GatePtr>; +template +using SqrtXdagGate = internal::GatePtr>; +template +using SqrtYGate = internal::GatePtr>; +template +using SqrtYdagGate = internal::GatePtr>; +template +using P0Gate = internal::GatePtr>; +template +using P1Gate = internal::GatePtr>; +template +using RXGate = internal::GatePtr>; +template +using RYGate = internal::GatePtr>; +template +using RZGate = internal::GatePtr>; +template +using U1Gate = internal::GatePtr>; +template +using U2Gate = internal::GatePtr>; +template +using U3Gate = internal::GatePtr>; +template +using SwapGate = internal::GatePtr>; namespace internal { -#define DECLARE_GET_FROM_JSON_IGATE_WITH_TYPE(Type) \ +/*#define DECLARE_GET_FROM_JSON_IGATE_WITH_TYPE(Type) \ template <> \ inline std::shared_ptr> get_from_json(const Json&) { \ return std::make_shared>(); \ @@ -741,13 +745,13 @@ DECLARE_GET_FROM_JSON_UGATE_WITH_TYPE(float) } DECLARE_GET_FROM_JSON_SWAPGATE_WITH_TYPE(double) DECLARE_GET_FROM_JSON_SWAPGATE_WITH_TYPE(float) -#undef DECLARE_GET_FROM_JSON_SWAPGATE_WITH_TYPE +#undef DECLARE_GET_FROM_JSON_SWAPGATE_WITH_TYPE*/ } // namespace internal #ifdef SCALUQ_USE_NANOBIND namespace internal { -template +template void bind_gate_gate_standard_hpp(nb::module_& m) { DEF_GATE(IGate, Fp, "Specific class of Pauli-I gate."); DEF_GATE(GlobalPhaseGate, @@ -756,7 +760,7 @@ void bind_gate_gate_standard_hpp(nb::module_& m) { "$e^{i\\mathrm{phase}}I$.") .def( "phase", - [](const GlobalPhaseGate& gate) { return gate->phase(); }, + [](const GlobalPhaseGate& gate) { return gate->phase(); }, "Get `phase` property"); DEF_GATE(XGate, Fp, "Specific class of Pauli-X gate."); DEF_GATE(YGate, Fp, "Specific class of Pauli-Y gate."); @@ -819,7 +823,7 @@ void bind_gate_gate_standard_hpp(nb::module_& m) { "$\\begin{bmatrix}\n1 & 0\\\\\n0 & e^{i\\lambda}\n\\end{bmatrix}$.") .def( "lambda_", - [](const U1Gate& gate) { return gate->lambda(); }, + [](const U1Gate& gate) { return gate->lambda(); }, "Get `lambda` property."); DEF_GATE(U2Gate, Fp, @@ -828,10 +832,10 @@ void bind_gate_gate_standard_hpp(nb::module_& m) { "$\\frac{1}{\\sqrt{2}} \\begin{bmatrix}1 & -e^{-i\\lambda}\\\\\n" "e^{i\\phi} & e^{i(\\phi+\\lambda)}\n\\end{bmatrix}$.") .def( - "phi", [](const U2Gate& gate) { return gate->phi(); }, "Get `phi` property.") + "phi", [](const U2Gate& gate) { return gate->phi(); }, "Get `phi` property.") .def( "lambda_", - [](const U2Gate& gate) { return gate->lambda(); }, + [](const U2Gate& gate) { return gate->lambda(); }, "Get `lambda` property."); DEF_GATE(U3Gate, Fp, @@ -842,12 +846,14 @@ void bind_gate_gate_standard_hpp(nb::module_& m) { "e^{i\\phi}\\sin\\frac{\\theta}{2} & " "e^{i(\\phi+\\lambda)}\\cos\\frac{\\theta}{2}\n\\end{bmatrix}$.") .def( - "theta", [](const U3Gate& gate) { return gate->theta(); }, "Get `theta` property.") + "theta", + [](const U3Gate& gate) { return gate->theta(); }, + "Get `theta` property.") .def( - "phi", [](const U3Gate& gate) { return gate->phi(); }, "Get `phi` property.") + "phi", [](const U3Gate& gate) { return gate->phi(); }, "Get `phi` property.") .def( "lambda_", - [](const U3Gate& gate) { return gate->lambda(); }, + [](const U3Gate& gate) { return gate->lambda(); }, "Get `lambda` property."); DEF_GATE(SwapGate, Fp, "Specific class of two-qubit swap gate."); } diff --git a/include/scaluq/operator/operator.hpp b/include/scaluq/operator/operator.hpp index b4e136ea..839a74a2 100644 --- a/include/scaluq/operator/operator.hpp +++ b/include/scaluq/operator/operator.hpp @@ -9,7 +9,7 @@ namespace scaluq { -template +template class Operator { public: Operator() = default; // for enable operator= from json @@ -17,11 +17,13 @@ class Operator { [[nodiscard]] inline bool is_hermitian() const { return _is_hermitian; } [[nodiscard]] inline std::uint64_t n_qubits() const { return _n_qubits; } - [[nodiscard]] inline const std::vector>& terms() const { return _terms; } + [[nodiscard]] inline const std::vector>& terms() const { return _terms; } [[nodiscard]] std::string to_string() const; - void add_operator(const PauliOperator& mpt) { add_operator(PauliOperator{mpt}); } - void add_operator(PauliOperator&& mpt); + void add_operator(const PauliOperator& mpt) { + add_operator(PauliOperator{mpt}); + } + void add_operator(PauliOperator&& mpt); void add_random_operator(const std::uint64_t operator_count = 1, std::uint64_t seed = std::random_device()()); @@ -33,19 +35,20 @@ class Operator { // not implemented yet void get_matrix() const; - void apply_to_state(StateVector& state_vector) const; + void apply_to_state(StateVector& state_vector) const; - [[nodiscard]] Complex get_expectation_value(const StateVector& state_vector) const; + [[nodiscard]] Complex get_expectation_value(const StateVector& state_vector) const; [[nodiscard]] Complex get_transition_amplitude( - const StateVector& state_vector_bra, const StateVector& state_vector_ket) const; + const StateVector& state_vector_bra, + const StateVector& state_vector_ket) const; // not implemented yet [[nodiscard]] Complex solve_gound_state_eigenvalue_by_arnoldi_method( - const StateVector& state, std::uint64_t iter_count, Complex mu = 0.) const; + const StateVector& state, std::uint64_t iter_count, Complex mu = 0.) const; // not implemented yet [[nodiscard]] Complex solve_gound_state_eigenvalue_by_power_method( - const StateVector& state, std::uint64_t iter_count, Complex mu = 0.) const; + const StateVector& state, std::uint64_t iter_count, Complex mu = 0.) const; Operator& operator*=(Complex coef); Operator operator*(Complex coef) const { return Operator(*this) *= coef; } @@ -57,12 +60,18 @@ class Operator { Operator operator-(const Operator& target) const { return Operator(*this) -= target; } Operator operator*(const Operator& target) const; Operator& operator*=(const Operator& target) { return *this = *this * target; } - Operator& operator+=(const PauliOperator& pauli); - Operator operator+(const PauliOperator& pauli) const { return Operator(*this) += pauli; } - Operator& operator-=(const PauliOperator& pauli) { return *this += pauli * -1; } - Operator operator-(const PauliOperator& pauli) const { return Operator(*this) -= pauli; } - Operator& operator*=(const PauliOperator& pauli); - Operator operator*(const PauliOperator& pauli) const { return Operator(*this) *= pauli; } + Operator& operator+=(const PauliOperator& pauli); + Operator operator+(const PauliOperator& pauli) const { + return Operator(*this) += pauli; + } + Operator& operator-=(const PauliOperator& pauli) { return *this += pauli * -1; } + Operator operator-(const PauliOperator& pauli) const { + return Operator(*this) -= pauli; + } + Operator& operator*=(const PauliOperator& pauli); + Operator operator*(const PauliOperator& pauli) const { + return Operator(*this) *= pauli; + } friend void to_json(Json& j, const Operator& op) { j = Json{{"n_qubits", op.n_qubits()}, {"terms", Json::array()}}; @@ -73,40 +82,46 @@ class Operator { } friend void from_json(const Json& j, Operator& op) { std::uint32_t n = j.at("n_qubits").get(); - Operator res(n); + Operator res(n); for (const auto& term : j.at("terms")) { std::string pauli_string = term.at("pauli_string").get(); - Kokkos::complex coef = term.at("coef").get>(); + Complex coef = term.at("coef").get>(); res.add_operator({pauli_string, coef}); } op = res; } private: - std::vector> _terms; + std::vector> _terms; std::uint64_t _n_qubits; bool _is_hermitian = true; }; #ifdef SCALUQ_USE_NANOBIND namespace internal { -template +template void bind_operator_operator_hpp(nb::module_& m) { - nb::class_>(m, "Operator", "General quantum operator class.") + nb::class_>(m, "Operator", "General quantum operator class.") .def(nb::init(), "qubit_count"_a, "Initialize operator with specified number of qubits.") - .def("is_hermitian", &Operator::is_hermitian, "Check if the operator is Hermitian.") - .def("n_qubits", &Operator::n_qubits, "Get the number of qubits the operator acts on.") + .def("is_hermitian", &Operator::is_hermitian, "Check if the operator is Hermitian.") + .def("n_qubits", + &Operator::n_qubits, + "Get the number of qubits the operator acts on.") + .def("terms", + &Operator::terms, + "Get the list of Pauli terms that make up the operator.") .def( - "terms", &Operator::terms, "Get the list of Pauli terms that make up the operator.") - .def("to_string", &Operator::to_string, "Get string representation of the operator.") + "to_string", &Operator::to_string, "Get string representation of the operator.") .def("add_operator", - nb::overload_cast&>(&Operator::add_operator), + nb::overload_cast&>(&Operator::add_operator), "Add a Pauli operator to this operator.") .def( "add_random_operator", - [](Operator& op, std::uint64_t operator_count, std::optional seed) { + [](Operator& op, + std::uint64_t operator_count, + std::optional seed) { return op.add_random_operator(operator_count, seed.value_or(std::random_device{}())); }, @@ -115,18 +130,20 @@ void bind_operator_operator_hpp(nb::module_& m) { "Add a specified number of random Pauli operators to this operator. An optional " "seed " "can be provided for reproducibility.") - .def("optimize", &Operator::optimize, "Optimize the operator by combining like terms.") + .def("optimize", + &Operator::optimize, + "Optimize the operator by combining like terms.") .def("get_dagger", - &Operator::get_dagger, + &Operator::get_dagger, "Get the adjoint (Hermitian conjugate) of the operator.") .def("apply_to_state", - &Operator::apply_to_state, + &Operator::apply_to_state, "Apply the operator to a state vector.") .def("get_expectation_value", - &Operator::get_expectation_value, + &Operator::get_expectation_value, "Get the expectation value of the operator with respect to a state vector.") .def("get_transition_amplitude", - &Operator::get_transition_amplitude, + &Operator::get_transition_amplitude, "Get the transition amplitude of the operator between two state vectors.") .def(nb::self *= Complex()) .def(nb::self * Complex()) @@ -138,19 +155,19 @@ void bind_operator_operator_hpp(nb::module_& m) { .def(nb::self - nb::self) .def(nb::self * nb::self) .def(nb::self *= nb::self) - .def(nb::self += PauliOperator()) - .def(nb::self + PauliOperator()) - .def(nb::self -= PauliOperator()) - .def(nb::self - PauliOperator()) - .def(nb::self *= PauliOperator()) - .def(nb::self * PauliOperator()) + .def(nb::self += PauliOperator()) + .def(nb::self + PauliOperator()) + .def(nb::self -= PauliOperator()) + .def(nb::self - PauliOperator()) + .def(nb::self *= PauliOperator()) + .def(nb::self * PauliOperator()) .def( "to_json", - [](const Operator& op) { return Json(op).dump(); }, + [](const Operator& op) { return Json(op).dump(); }, "Information as json style.") .def( "load_json", - [](Operator& op, const std::string& str) { op = nlohmann::json::parse(str); }, + [](Operator& op, const std::string& str) { op = nlohmann::json::parse(str); }, "Read an object from the JSON representation of the operator."); } } // namespace internal diff --git a/include/scaluq/operator/pauli_operator.hpp b/include/scaluq/operator/pauli_operator.hpp index a4fc245e..e07d1d5a 100644 --- a/include/scaluq/operator/pauli_operator.hpp +++ b/include/scaluq/operator/pauli_operator.hpp @@ -9,17 +9,17 @@ namespace scaluq { -template +template class Operator; -template +template class PauliOperator { - friend class Operator; + friend class Operator; public: class Data { - friend class PauliOperator; - friend class Operator; + friend class PauliOperator; + friend class Operator; std::vector _target_qubit_list, _pauli_id_list; Complex _coef; std::uint64_t _bit_flip_mask, _phase_flip_mask; @@ -82,11 +82,12 @@ class PauliOperator { [[nodiscard]] PauliOperator get_dagger() const; [[nodiscard]] std::uint64_t get_qubit_count() const; - void apply_to_state(StateVector& state_vector) const; + void apply_to_state(StateVector& state_vector) const; - [[nodiscard]] Complex get_expectation_value(const StateVector& state_vector) const; + [[nodiscard]] Complex get_expectation_value(const StateVector& state_vector) const; [[nodiscard]] Complex get_transition_amplitude( - const StateVector& state_vector_bra, const StateVector& state_vector_ket) const; + const StateVector& state_vector_bra, + const StateVector& state_vector_ket) const; [[nodiscard]] internal::ComplexMatrix get_matrix() const; @@ -101,8 +102,8 @@ class PauliOperator { j = Json{{"pauli_string", pauli.get_pauli_string()}, {"coef", pauli.coef()}}; } friend void from_json(const Json& j, PauliOperator& pauli) { - pauli = PauliOperator(j.at("pauli_string").get(), - j.at("coef").get>()); + pauli = + PauliOperator(j.at("pauli_string").get(), j.at("coef").get>()); } }; @@ -110,14 +111,14 @@ class PauliOperator { namespace internal { template void bind_operator_pauli_operator_hpp(nb::module_& m) { - nb::enum_::PauliID>(m, "PauliID") - .value("I", PauliOperator::I) - .value("X", PauliOperator::X) - .value("Y", PauliOperator::Y) - .value("Z", PauliOperator::Z) + nb::enum_::PauliID>(m, "PauliID") + .value("I", PauliOperator::I) + .value("X", PauliOperator::X) + .value("Y", PauliOperator::Y) + .value("Z", PauliOperator::Z) .export_values(); - nb::class_::Data>( + nb::class_::Data>( m, "PauliOperatorData", "Internal data structure for PauliOperator.") .def(nb::init>(), "coef"_a = 1., "Initialize data with coefficient.") .def(nb::init>(), @@ -140,28 +141,32 @@ void bind_operator_pauli_operator_hpp(nb::module_& m) { "phase_flip_mask"_a, "coef"_a = 1., "Initialize data with bit flip and phase flip masks.") - .def(nb::init::Data&>(), + .def(nb::init::Data&>(), "data"_a, "Initialize pauli operator from Data object.") .def("add_single_pauli", - &PauliOperator::Data::add_single_pauli, + &PauliOperator::Data::add_single_pauli, "target_qubit"_a, "pauli_id"_a, "Add a single pauli operation to the data.") - .def("coef", &PauliOperator::Data::coef, "Get the coefficient of the Pauli operator.") + .def("coef", + &PauliOperator::Data::coef, + "Get the coefficient of the Pauli operator.") .def("set_coef", - &PauliOperator::Data::set_coef, + &PauliOperator::Data::set_coef, "c"_a, "Set the coefficient of the Pauli operator.") .def("target_qubit_list", - &PauliOperator::Data::target_qubit_list, + &PauliOperator::Data::target_qubit_list, "Get the list of target qubits.") - .def("pauli_id_list", &PauliOperator::Data::pauli_id_list, "Get the list of Pauli IDs.") + .def("pauli_id_list", + &PauliOperator::Data::pauli_id_list, + "Get the list of Pauli IDs.") .def("get_XZ_mask_representation", - &PauliOperator::Data::get_XZ_mask_representation, + &PauliOperator::Data::get_XZ_mask_representation, "Get the X and Z mask representation as a tuple of vectors."); - nb::class_>( + nb::class_>( m, "PauliOperator", "Pauli operator as coef and tensor product of single pauli for each qubit.") @@ -197,44 +202,46 @@ void bind_operator_pauli_operator_hpp(nb::module_& m) { "csv-table::\n\n \"bit_flip\",\"phase_flip\",\"pauli\"\n " "\"0\",\"0\",\"I\"\n " "\"0\",\"1\",\"Z\"\n \"1\",\"0\",\"X\"\n \"1\",\"1\",\"Y\"") - .def("coef", &PauliOperator::coef, "Get property `coef`.") + .def("coef", &PauliOperator::coef, "Get property `coef`.") .def("target_qubit_list", - &PauliOperator::target_qubit_list, + &PauliOperator::target_qubit_list, "Get qubits to be applied pauli.") .def("pauli_id_list", - &PauliOperator::pauli_id_list, + &PauliOperator::pauli_id_list, "Get pauli id to be applied. The order is correspond to the result of " "`target_qubit_list`") .def("get_XZ_mask_representation", - &PauliOperator::get_XZ_mask_representation, + &PauliOperator::get_XZ_mask_representation, "Get single-pauli property as binary integer representation. See description of " "`__init__(bit_flip_mask_py: int, phase_flip_mask_py: int, coef: float=1.)` for " "details.") .def("get_pauli_string", - &PauliOperator::get_pauli_string, + &PauliOperator::get_pauli_string, "Get single-pauli property as string representation. See description of " "`__init__(pauli_string: str, coef: float=1.)` for details.") - .def("get_dagger", &PauliOperator::get_dagger, "Get adjoint operator.") + .def("get_dagger", &PauliOperator::get_dagger, "Get adjoint operator.") .def("get_qubit_count", - &PauliOperator::get_qubit_count, + &PauliOperator::get_qubit_count, "Get num of qubits to applied with, when count from 0-th qubit. Subset of $[0, " "\\mathrm{qubit_count})$ is the target.") - .def("apply_to_state", &PauliOperator::apply_to_state, "Apply pauli to state vector.") + .def("apply_to_state", + &PauliOperator::apply_to_state, + "Apply pauli to state vector.") .def("get_expectation_value", - &PauliOperator::get_expectation_value, + &PauliOperator::get_expectation_value, "Get expectation value of measuring state vector. $\\bra{\\psi}P\\ket{\\psi}$.") .def("get_transition_amplitude", - &PauliOperator::get_transition_amplitude, + &PauliOperator::get_transition_amplitude, "Get transition amplitude of measuring state vector. $\\bra{\\chi}P\\ket{\\psi}$.") .def(nb::self * nb::self) .def(nb::self * Complex()) .def( "to_json", - [](const PauliOperator& pauli) { return Json(pauli).dump(); }, + [](const PauliOperator& pauli) { return Json(pauli).dump(); }, "Information as json style.") .def( "load_json", - [](PauliOperator& pauli, const std::string& str) { + [](PauliOperator& pauli, const std::string& str) { pauli = nlohmann::json::parse(str); }, "Read an object from the JSON representation of the Pauli operator."); diff --git a/include/scaluq/state/state_vector.hpp b/include/scaluq/state/state_vector.hpp index 2c0be86d..307d7cbd 100644 --- a/include/scaluq/state/state_vector.hpp +++ b/include/scaluq/state/state_vector.hpp @@ -13,7 +13,7 @@ namespace scaluq { -using CPUSpace = Kokkos::HostSpace; +using CPUSpace = Kokkos::DefaultHostExecutionSpace; using DefaultSpace = Kokkos::DefaultExecutionSpace; template concept ExecutionSpace = std::is_same_v || std::is_same_v; @@ -29,7 +29,7 @@ class StateVector { Kokkos::View _raw; StateVector() = default; StateVector(std::uint64_t n_qubits); - StateVector(Kokkos::View view); + StateVector(Kokkos::View view); StateVector(const StateVector& other) = default; StateVector& operator=(const StateVector& other) = default; @@ -59,7 +59,7 @@ class StateVector { [[nodiscard]] std::uint64_t dim() const { return this->_dim; } - [[nodiscard]] std::vector get_amplitudes() const; + [[nodiscard]] std::vector> get_amplitudes() const; [[nodiscard]] Fp get_squared_norm() const; @@ -77,7 +77,7 @@ class StateVector { [[nodiscard]] std::vector sampling( std::uint64_t sampling_count, std::uint64_t seed = std::random_device()()) const; - void load(const std::vector& other); + void load(const std::vector>& other); [[nodiscard]] StateVector copy() const; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9a48fcba..e3bd5ac2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,10 +3,10 @@ cmake_minimum_required(VERSION 3.21) target_sources(scaluq PRIVATE # circuit/circuit.cpp # gate/merge_gate.cpp - # gate/gate_matrix.cpp - # gate/gate_pauli.cpp - # gate/gate_probablistic.cpp - # gate/gate_standard.cpp + gate/gate_matrix.cpp + gate/gate_pauli.cpp + gate/gate_probablistic.cpp + gate/gate_standard.cpp gate/gate.cpp # gate/param_gate.cpp # gate/param_gate_pauli.cpp @@ -18,9 +18,9 @@ target_sources(scaluq PRIVATE gate/update_ops_standard.cpp state/state_vector.cpp state/state_vector_batched.cpp - # operator/apply_pauli.cpp - # operator/pauli_operator.cpp - # operator/operator.cpp + operator/apply_pauli.cpp + operator/pauli_operator.cpp + operator/operator.cpp util/utility.cpp kokkos.cpp types.cpp diff --git a/src/gate/gate_matrix.cpp b/src/gate/gate_matrix.cpp index 384afccb..86a0f3e3 100644 --- a/src/gate/gate_matrix.cpp +++ b/src/gate/gate_matrix.cpp @@ -4,16 +4,16 @@ #include "update_ops.hpp" namespace scaluq::internal { -FLOAT(Fp) -DenseMatrixGateImpl::DenseMatrixGateImpl(std::uint64_t target_mask, - std::uint64_t control_mask, - const ComplexMatrix& mat, - bool is_unitary) - : GateBase(target_mask, control_mask), +FLOAT_AND_SPACE(Fp, Sp) +DenseMatrixGateImpl::DenseMatrixGateImpl(std::uint64_t target_mask, + std::uint64_t control_mask, + const ComplexMatrix& mat, + bool is_unitary) + : GateBase(target_mask, control_mask), _matrix(convert_external_matrix_to_internal_matrix(mat)), _is_unitary(is_unitary) {} -FLOAT(Fp) -std::shared_ptr> DenseMatrixGateImpl::get_inverse() const { +FLOAT_AND_SPACE(Fp, Sp) +std::shared_ptr> DenseMatrixGateImpl::get_inverse() const { ComplexMatrix mat_eigen = convert_internal_matrix_to_external_matrix(_matrix); ComplexMatrix inv_eigen; if (_is_unitary) { @@ -24,44 +24,44 @@ std::shared_ptr> DenseMatrixGateImpl::get_inverse() const return std::make_shared( this->_target_mask, this->_control_mask, inv_eigen, _is_unitary); } -FLOAT(Fp) -Matrix DenseMatrixGateImpl::get_matrix_internal() const { +FLOAT_AND_SPACE(Fp, Sp) +Matrix DenseMatrixGateImpl::get_matrix_internal() const { Matrix ret("return matrix", _matrix.extent(0), _matrix.extent(1)); Kokkos::deep_copy(ret, _matrix); return ret; } -FLOAT(Fp) -ComplexMatrix DenseMatrixGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix DenseMatrixGateImpl::get_matrix() const { return convert_internal_matrix_to_external_matrix(_matrix); } -FLOAT(Fp) -void DenseMatrixGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void DenseMatrixGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); dense_matrix_gate(this->_target_mask, this->_control_mask, _matrix, state_vector); } -FLOAT(Fp) -void DenseMatrixGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void DenseMatrixGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); dense_matrix_gate(this->_target_mask, this->_control_mask, _matrix, states); } -FLOAT(Fp) -std::string DenseMatrixGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string DenseMatrixGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: DenseMatrix\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(DenseMatrixGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(DenseMatrixGateImpl) -FLOAT(Fp) -SparseMatrixGateImpl::SparseMatrixGateImpl(std::uint64_t target_mask, - std::uint64_t control_mask, - const SparseComplexMatrix& mat) - : GateBase(target_mask, control_mask), +FLOAT_AND_SPACE(Fp, Sp) +SparseMatrixGateImpl::SparseMatrixGateImpl(std::uint64_t target_mask, + std::uint64_t control_mask, + const SparseComplexMatrix& mat) + : GateBase(target_mask, control_mask), _matrix(SparseMatrix(mat)), num_nnz(mat.nonZeros()) {} -FLOAT(Fp) -std::shared_ptr> SparseMatrixGateImpl::get_inverse() const { +FLOAT_AND_SPACE(Fp, Sp) +std::shared_ptr> SparseMatrixGateImpl::get_inverse() const { Kokkos::View*, Kokkos::HostSpace> vec_h("h_view", num_nnz); Kokkos::deep_copy(vec_h, _matrix._values); // conversion to Eigen matrix (COO format) @@ -69,37 +69,37 @@ std::shared_ptr> SparseMatrixGateImpl::get_inverse() cons for (std::size_t i = 0; i < vec_h.extent(0); i++) { eigen_matrix(vec_h(i).r, vec_h(i).c) = vec_h(i).val; } - return std::make_shared>( + return std::make_shared>( this->_target_mask, this->_control_mask, eigen_matrix.inverse().eval()); } -FLOAT(Fp) -Matrix SparseMatrixGateImpl::get_matrix_internal() const { +FLOAT_AND_SPACE(Fp, Sp) +Matrix SparseMatrixGateImpl::get_matrix_internal() const { Matrix ret("return matrix", _matrix._row, _matrix._col); auto vec = _matrix._values; Kokkos::parallel_for( vec.size(), KOKKOS_LAMBDA(int i) { ret(vec[i].r, vec[i].c) = vec[i].val; }); return ret; } -FLOAT(Fp) -ComplexMatrix SparseMatrixGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix SparseMatrixGateImpl::get_matrix() const { return convert_coo_to_external_matrix(_matrix); } -FLOAT(Fp) -void SparseMatrixGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void SparseMatrixGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); sparse_matrix_gate(this->_target_mask, this->_control_mask, _matrix, state_vector); } -FLOAT(Fp) -void SparseMatrixGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void SparseMatrixGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); sparse_matrix_gate(this->_target_mask, this->_control_mask, _matrix, states); } -FLOAT(Fp) -std::string SparseMatrixGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string SparseMatrixGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: SparseMatrix\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(SparseMatrixGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(SparseMatrixGateImpl) } // namespace scaluq::internal diff --git a/src/gate/gate_pauli.cpp b/src/gate/gate_pauli.cpp index 9a7aaef4..5c76d901 100644 --- a/src/gate/gate_pauli.cpp +++ b/src/gate/gate_pauli.cpp @@ -4,18 +4,18 @@ #include "../util/template.hpp" namespace scaluq::internal { -FLOAT(Fp) -void PauliGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void PauliGateImpl::update_quantum_state(StateVector& state_vector) const { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); apply_pauli(this->_control_mask, bit_flip_mask, phase_flip_mask, _pauli.coef(), state_vector); } -FLOAT(Fp) -void PauliGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void PauliGateImpl::update_quantum_state(StateVectorBatched& states) const { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); apply_pauli(this->_control_mask, bit_flip_mask, phase_flip_mask, _pauli.coef(), states); } -FLOAT(Fp) -std::string PauliGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string PauliGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; auto controls = this->control_qubit_list(); ss << indent << "Gate Type: Pauli\n"; @@ -26,10 +26,10 @@ std::string PauliGateImpl::to_string(const std::string& indent) const { ss << indent << " Pauli Operator: \"" << _pauli.get_pauli_string() << "\""; return ss.str(); } -FLOAT_DECLARE_CLASS(PauliGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(PauliGateImpl) -FLOAT(Fp) -ComplexMatrix PauliRotationGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix PauliRotationGateImpl::get_matrix() const { internal::ComplexMatrix mat = this->_pauli.get_matrix_ignoring_coef(); Complex true_angle = _angle * _pauli.coef(); StdComplex imag_unit(0, 1); @@ -38,20 +38,20 @@ ComplexMatrix PauliRotationGateImpl::get_matrix() const { imag_unit * (StdComplex)Kokkos::sin(-true_angle / 2) * mat; return mat; } -FLOAT(Fp) -void PauliRotationGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void PauliRotationGateImpl::update_quantum_state(StateVector& state_vector) const { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); apply_pauli_rotation( this->_control_mask, bit_flip_mask, phase_flip_mask, _pauli.coef(), _angle, state_vector); } -FLOAT(Fp) -void PauliRotationGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void PauliRotationGateImpl::update_quantum_state(StateVectorBatched& states) const { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); apply_pauli_rotation( this->_control_mask, bit_flip_mask, phase_flip_mask, _pauli.coef(), _angle, states); } -FLOAT(Fp) -std::string PauliRotationGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string PauliRotationGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; auto controls = this->control_qubit_list(); ss << indent << "Gate Type: PauliRotation\n"; @@ -63,5 +63,5 @@ std::string PauliRotationGateImpl::to_string(const std::string& indent) cons ss << indent << " Pauli Operator: \"" << _pauli.get_pauli_string() << "\""; return ss.str(); } -FLOAT_DECLARE_CLASS(PauliRotationGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(PauliRotationGateImpl) } // namespace scaluq::internal diff --git a/src/gate/gate_probablistic.cpp b/src/gate/gate_probablistic.cpp index 8f6b0f4d..2d2e97b9 100644 --- a/src/gate/gate_probablistic.cpp +++ b/src/gate/gate_probablistic.cpp @@ -3,10 +3,10 @@ #include "../util/template.hpp" namespace scaluq::internal { -FLOAT(Fp) -ProbablisticGateImpl::ProbablisticGateImpl(const std::vector& distribution, - const std::vector>& gate_list) - : GateBase(0, 0), _distribution(distribution), _gate_list(gate_list) { +FLOAT_AND_SPACE(Fp, Sp) +ProbablisticGateImpl::ProbablisticGateImpl(const std::vector& distribution, + const std::vector>& gate_list) + : GateBase(0, 0), _distribution(distribution), _gate_list(gate_list) { std::uint64_t n = distribution.size(); if (n == 0) { throw std::runtime_error("At least one gate is required."); @@ -21,17 +21,17 @@ ProbablisticGateImpl::ProbablisticGateImpl(const std::vector& distributi throw std::runtime_error("Sum of distribution must be equal to 1."); } } -FLOAT(Fp) -std::shared_ptr> ProbablisticGateImpl::get_inverse() const { - std::vector> inv_gate_list; +FLOAT_AND_SPACE(Fp, Sp) +std::shared_ptr> ProbablisticGateImpl::get_inverse() const { + std::vector> inv_gate_list; inv_gate_list.reserve(_gate_list.size()); - std::ranges::transform(_gate_list, std::back_inserter(inv_gate_list), [](const Gate& gate) { - return gate->get_inverse(); - }); - return std::make_shared(_distribution, inv_gate_list); + std::ranges::transform(_gate_list, + std::back_inserter(inv_gate_list), + [](const Gate& gate) { return gate->get_inverse(); }); + return std::make_shared>(_distribution, inv_gate_list); } -FLOAT(Fp) -void ProbablisticGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void ProbablisticGateImpl::update_quantum_state(StateVector& state_vector) const { Random random; Fp r = random.uniform(); std::uint64_t i = std::distance(_cumulative_distribution.begin(), @@ -40,8 +40,8 @@ void ProbablisticGateImpl::update_quantum_state(StateVector& state_vecto if (i >= _gate_list.size()) i = _gate_list.size() - 1; _gate_list[i]->update_quantum_state(state_vector); } -FLOAT(Fp) -void ProbablisticGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void ProbablisticGateImpl::update_quantum_state(StateVectorBatched& states) const { std::vector indices(states.batch_size()); std::vector r(states.batch_size()); @@ -52,7 +52,7 @@ void ProbablisticGateImpl::update_quantum_state(StateVectorBatched& stat std::ranges::upper_bound(_cumulative_distribution, r[i])) - 1; if (indices[i] >= _gate_list.size()) indices[i] = _gate_list.size() - 1; - auto state_vector = StateVector(Kokkos::subview(states._raw, i, Kokkos::ALL)); + auto state_vector = StateVector(Kokkos::subview(states._raw, i, Kokkos::ALL)); _gate_list[indices[i]]->update_quantum_state(state_vector); Kokkos::parallel_for( "update_states", states.dim(), KOKKOS_CLASS_LAMBDA(const int j) { @@ -60,8 +60,8 @@ void ProbablisticGateImpl::update_quantum_state(StateVectorBatched& stat }); } } -FLOAT(Fp) -std::string ProbablisticGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string ProbablisticGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; const auto dist = distribution(); ss << indent << "Gate Type: Probablistic\n"; @@ -72,5 +72,5 @@ std::string ProbablisticGateImpl::to_string(const std::string& indent) const } return ss.str(); } -FLOAT_DECLARE_CLASS(ProbablisticGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(ProbablisticGateImpl) } // namespace scaluq::internal diff --git a/src/gate/gate_standard.cpp b/src/gate/gate_standard.cpp index 6e3845c3..2ade1b13 100644 --- a/src/gate/gate_standard.cpp +++ b/src/gate/gate_standard.cpp @@ -4,513 +4,513 @@ #include "update_ops.hpp" namespace scaluq::internal { -FLOAT(Fp) -ComplexMatrix IGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix IGateImpl::get_matrix() const { return internal::ComplexMatrix::Identity(1, 1); } -FLOAT(Fp) -void IGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void IGateImpl::update_quantum_state(StateVector& state_vector) const { i_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void IGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void IGateImpl::update_quantum_state(StateVectorBatched& states) const { i_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string IGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string IGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: I\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(IGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(IGateImpl) -FLOAT(Fp) -ComplexMatrix GlobalPhaseGateImpl::get_matrix() const { - return internal::ComplexMatrix::Identity(1, 1) * std::exp(std::complex(0, _phase)); +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix GlobalPhaseGateImpl::get_matrix() const { + return internal::ComplexMatrix::Identity(1, 1) * std::exp(StdComplex(0, _phase)); } -FLOAT(Fp) -void GlobalPhaseGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void GlobalPhaseGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); global_phase_gate(this->_target_mask, this->_control_mask, _phase, state_vector); } -FLOAT(Fp) -void GlobalPhaseGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void GlobalPhaseGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); global_phase_gate(this->_target_mask, this->_control_mask, _phase, states); } -FLOAT(Fp) -std::string GlobalPhaseGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string GlobalPhaseGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: GlobalPhase\n"; ss << indent << " Phase: " << _phase << "\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(GlobalPhaseGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(GlobalPhaseGateImpl) -FLOAT(Fp) -ComplexMatrix XGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix XGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 0, 1, 1, 0; return mat; } -FLOAT(Fp) -void XGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void XGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); x_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void XGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void XGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); x_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string XGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string XGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: X\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(XGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(XGateImpl) -FLOAT(Fp) -ComplexMatrix YGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix YGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 0, StdComplex(0, -1), StdComplex(0, 1), 0; return mat; } -FLOAT(Fp) -void YGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void YGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); y_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void YGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void YGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); y_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string YGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string YGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: Y\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(YGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(YGateImpl) -FLOAT(Fp) -ComplexMatrix ZGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix ZGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, -1; return mat; } -FLOAT(Fp) -void ZGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void ZGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); z_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void ZGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void ZGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); z_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string ZGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string ZGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: Z\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(ZGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(ZGateImpl) -FLOAT(Fp) -ComplexMatrix HGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix HGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 1, 1, 1, -1; mat /= (Fp)Kokkos::numbers::sqrt2; return mat; } -FLOAT(Fp) -void HGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void HGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); h_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void HGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void HGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); h_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string HGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string HGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: H\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(HGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(HGateImpl) -FLOAT(Fp) -ComplexMatrix SGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix SGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, StdComplex(0, 1); return mat; } -FLOAT(Fp) -void SGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void SGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); s_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void SGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void SGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); s_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string SGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string SGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: S\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(SGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(SGateImpl) -FLOAT(Fp) -ComplexMatrix SdagGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix SdagGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, StdComplex(0, -1); return mat; } -FLOAT(Fp) -void SdagGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void SdagGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); sdag_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void SdagGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void SdagGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); sdag_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string SdagGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string SdagGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: Sdag\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(SdagGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(SdagGateImpl) -FLOAT(Fp) -ComplexMatrix TGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix TGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, StdComplex(1, 1) / (Fp)Kokkos::numbers::sqrt2; return mat; } -FLOAT(Fp) -void TGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void TGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); t_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void TGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void TGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); t_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string TGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string TGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: T\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(TGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(TGateImpl) -FLOAT(Fp) -ComplexMatrix TdagGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix TdagGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, StdComplex(1, -1) / (Fp)Kokkos::numbers::sqrt2; return mat; } -FLOAT(Fp) -void TdagGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void TdagGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); tdag_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void TdagGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void TdagGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); tdag_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string TdagGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string TdagGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: Tdag\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(TdagGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(TdagGateImpl) -FLOAT(Fp) -ComplexMatrix SqrtXGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix SqrtXGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << StdComplex(0.5, 0.5), StdComplex(0.5, -0.5), StdComplex(0.5, -0.5), StdComplex(0.5, 0.5); return mat; } -FLOAT(Fp) -void SqrtXGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void SqrtXGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); sqrtx_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void SqrtXGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void SqrtXGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); sqrtx_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string SqrtXGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string SqrtXGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: SqrtX\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(SqrtXGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(SqrtXGateImpl) -FLOAT(Fp) -ComplexMatrix SqrtXdagGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix SqrtXdagGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << StdComplex(0.5, -0.5), StdComplex(0.5, 0.5), StdComplex(0.5, 0.5), StdComplex(0.5, -0.5); return mat; } -FLOAT(Fp) -void SqrtXdagGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void SqrtXdagGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); sqrtxdag_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void SqrtXdagGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void SqrtXdagGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); sqrtxdag_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string SqrtXdagGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string SqrtXdagGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: SqrtXdag\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(SqrtXdagGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(SqrtXdagGateImpl) -FLOAT(Fp) -ComplexMatrix SqrtYGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix SqrtYGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << StdComplex(0.5, 0.5), StdComplex(-0.5, -0.5), StdComplex(0.5, 0.5), StdComplex(0.5, 0.5); return mat; } -FLOAT(Fp) -void SqrtYGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void SqrtYGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); sqrty_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void SqrtYGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void SqrtYGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); sqrty_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string SqrtYGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string SqrtYGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: SqrtY\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(SqrtYGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(SqrtYGateImpl) -FLOAT(Fp) -ComplexMatrix SqrtYdagGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix SqrtYdagGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << StdComplex(0.5, -0.5), StdComplex(0.5, -0.5), StdComplex(-0.5, 0.5), StdComplex(0.5, -0.5); return mat; } -FLOAT(Fp) -void SqrtYdagGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void SqrtYdagGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); sqrtydag_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void SqrtYdagGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void SqrtYdagGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); sqrtydag_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string SqrtYdagGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string SqrtYdagGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: SqrtYdag\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(SqrtYdagGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(SqrtYdagGateImpl) -FLOAT(Fp) -ComplexMatrix P0GateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix P0GateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, 0; return mat; } -FLOAT(Fp) -void P0GateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void P0GateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); p0_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void P0GateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void P0GateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); p0_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string P0GateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string P0GateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: P0\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(P0GateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(P0GateImpl) -FLOAT(Fp) -ComplexMatrix P1GateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix P1GateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 0, 0, 0, 1; return mat; } -FLOAT(Fp) -void P1GateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void P1GateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); p1_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void P1GateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void P1GateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); p1_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string P1GateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string P1GateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: P1\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(P1GateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(P1GateImpl) -FLOAT(Fp) -ComplexMatrix RXGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix RXGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << std::cos(this->_angle / 2), StdComplex(0, -std::sin(this->_angle / 2)), StdComplex(0, -std::sin(this->_angle / 2)), std::cos(this->_angle / 2); return mat; } -FLOAT(Fp) -void RXGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void RXGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); rx_gate(this->_target_mask, this->_control_mask, this->_angle, state_vector); } -FLOAT(Fp) -void RXGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void RXGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); rx_gate(this->_target_mask, this->_control_mask, this->_angle, states); } -FLOAT(Fp) -std::string RXGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string RXGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: RX\n"; ss << indent << " Angle: " << this->_angle << "\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(RXGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(RXGateImpl) -FLOAT(Fp) -ComplexMatrix RYGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix RYGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << std::cos(this->_angle / 2), -std::sin(this->_angle / 2), std::sin(this->_angle / 2), std::cos(this->_angle / 2); return mat; } -FLOAT(Fp) -void RYGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void RYGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); ry_gate(this->_target_mask, this->_control_mask, this->_angle, state_vector); } -FLOAT(Fp) -void RYGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void RYGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); ry_gate(this->_target_mask, this->_control_mask, this->_angle, states); } -FLOAT(Fp) -std::string RYGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string RYGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: RY\n"; ss << indent << " Angle: " << this->_angle << "\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(RYGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(RYGateImpl) -FLOAT(Fp) -ComplexMatrix RZGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix RZGateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << std::exp(StdComplex(0, -0.5 * this->_angle)), 0, 0, std::exp(StdComplex(0, 0.5 * this->_angle)); return mat; } -FLOAT(Fp) -void RZGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void RZGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); rz_gate(this->_target_mask, this->_control_mask, this->_angle, state_vector); } -FLOAT(Fp) -void RZGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void RZGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); rz_gate(this->_target_mask, this->_control_mask, this->_angle, states); } -FLOAT(Fp) -std::string RZGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string RZGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: RZ\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(RZGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(RZGateImpl) -FLOAT(Fp) -ComplexMatrix U1GateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix U1GateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, std::exp(StdComplex(0, _lambda)); return mat; } -FLOAT(Fp) -void U1GateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void U1GateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); u1_gate(this->_target_mask, this->_control_mask, _lambda, state_vector); } -FLOAT(Fp) -void U1GateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void U1GateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); u1_gate(this->_target_mask, this->_control_mask, _lambda, states); } -FLOAT(Fp) -std::string U1GateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string U1GateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: U1\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(U1GateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(U1GateImpl) -FLOAT(Fp) -ComplexMatrix U2GateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix U2GateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << std::cos(Kokkos::numbers::pi / 4.), -std::exp(StdComplex(0, _lambda)) * std::sin((Fp)Kokkos::numbers::pi / 4), @@ -519,27 +519,27 @@ ComplexMatrix U2GateImpl::get_matrix() const { std::cos((Fp)Kokkos::numbers::pi / 4); return mat; } -FLOAT(Fp) -void U2GateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void U2GateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); u2_gate(this->_target_mask, this->_control_mask, _phi, _lambda, state_vector); } -FLOAT(Fp) -void U2GateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void U2GateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); u2_gate(this->_target_mask, this->_control_mask, _phi, _lambda, states); } -FLOAT(Fp) -std::string U2GateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string U2GateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: U2\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(U2GateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(U2GateImpl) -FLOAT(Fp) -ComplexMatrix U3GateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix U3GateImpl::get_matrix() const { internal::ComplexMatrix mat(2, 2); mat << std::cos(_theta / 2.), -std::exp(StdComplex(0, _lambda)) * std::sin(_theta / 2), std::exp(StdComplex(0, _phi)) * std::sin(_theta / 2), @@ -547,47 +547,47 @@ ComplexMatrix U3GateImpl::get_matrix() const { std::cos(_theta / 2); return mat; } -FLOAT(Fp) -void U3GateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void U3GateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); u3_gate(this->_target_mask, this->_control_mask, _theta, _phi, _lambda, state_vector); } -FLOAT(Fp) -void U3GateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void U3GateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); u3_gate(this->_target_mask, this->_control_mask, _theta, _phi, _lambda, states); } -FLOAT(Fp) -std::string U3GateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string U3GateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: U3\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(U3GateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(U3GateImpl) -FLOAT(Fp) -ComplexMatrix SwapGateImpl::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +ComplexMatrix SwapGateImpl::get_matrix() const { internal::ComplexMatrix mat = internal::ComplexMatrix::Identity(1 << 2, 1 << 2); mat << 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1; return mat; } -FLOAT(Fp) -void SwapGateImpl::update_quantum_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void SwapGateImpl::update_quantum_state(StateVector& state_vector) const { this->check_qubit_mask_within_bounds(state_vector); swap_gate(this->_target_mask, this->_control_mask, state_vector); } -FLOAT(Fp) -void SwapGateImpl::update_quantum_state(StateVectorBatched& states) const { +FLOAT_AND_SPACE(Fp, Sp) +void SwapGateImpl::update_quantum_state(StateVectorBatched& states) const { this->check_qubit_mask_within_bounds(states); swap_gate(this->_target_mask, this->_control_mask, states); } -FLOAT(Fp) -std::string SwapGateImpl::to_string(const std::string& indent) const { +FLOAT_AND_SPACE(Fp, Sp) +std::string SwapGateImpl::to_string(const std::string& indent) const { std::ostringstream ss; ss << indent << "Gate Type: Swap\n"; ss << this->get_qubit_info_as_string(indent); return ss.str(); } -FLOAT_DECLARE_CLASS(SwapGateImpl) +FLOAT_AND_SPACE_DECLARE_CLASS(SwapGateImpl) } // namespace scaluq::internal diff --git a/src/gate/update_ops_standard.cpp b/src/gate/update_ops_standard.cpp index f98694ab..37b903ab 100644 --- a/src/gate/update_ops_standard.cpp +++ b/src/gate/update_ops_standard.cpp @@ -53,12 +53,24 @@ CALL_MACRO_FOR_FLOAT_AND_SPACE(FUNC_MACRO) FLOAT_AND_SPACE(Fp, Sp) void x_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { - Kokkos::parallel_for( - state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(std::uint64_t it) { - std::uint64_t i = - insert_zero_at_mask_positions(it, control_mask | target_mask) | control_mask; - Kokkos::Experimental::swap(state._raw[i], state._raw[i | target_mask]); - }); + if constexpr (std::is_same_v) { + Kokkos::parallel_for(Kokkos::RangePolicy( + 0, state.dim() >> std::popcount(target_mask | control_mask)), + [&](std::uint64_t it) { + std::uint64_t i = + insert_zero_at_mask_positions(it, control_mask | target_mask) | + control_mask; + std::swap(state._raw[i], state._raw[i | target_mask]); + }); + } else { + Kokkos::parallel_for( + state.dim() >> std::popcount(target_mask | control_mask), + KOKKOS_LAMBDA(std::uint64_t it) { + std::uint64_t i = + insert_zero_at_mask_positions(it, control_mask | target_mask) | control_mask; + Kokkos::Experimental::swap(state._raw[i], state._raw[i | target_mask]); + }); + } Kokkos::fence(); } #define FUNC_MACRO(Fp, Sp) template void x_gate(std::uint64_t, std::uint64_t, StateVector&); diff --git a/src/operator/apply_pauli.cpp b/src/operator/apply_pauli.cpp index e11fd2af..3a62b8e0 100644 --- a/src/operator/apply_pauli.cpp +++ b/src/operator/apply_pauli.cpp @@ -5,12 +5,12 @@ #include "../util/template.hpp" namespace scaluq::internal { -template +template void apply_pauli(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, - StateVector& state_vector) { + StateVector& state_vector) { if (bit_flip_mask == 0) { Kokkos::parallel_for( state_vector.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(std::uint64_t i) { @@ -42,12 +42,12 @@ void apply_pauli(std::uint64_t control_mask, }); Kokkos::fence(); } -template +template void apply_pauli(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, - StateVectorBatched& states) { + StateVectorBatched& states) { if (bit_flip_mask == 0) { Kokkos::parallel_for( Kokkos::MDRangePolicy>( @@ -84,24 +84,24 @@ void apply_pauli(std::uint64_t control_mask, Kokkos::fence(); } -#define FUNC_MACRO(Fp) \ +#define FUNC_MACRO(Fp, Sp) \ template void apply_pauli( \ - std::uint64_t, std::uint64_t, std::uint64_t, Complex, StateVector&); -CALL_MACRO_FOR_FLOAT(FUNC_MACRO) + std::uint64_t, std::uint64_t, std::uint64_t, Complex, StateVector&); +CALL_MACRO_FOR_FLOAT_AND_SPACE(FUNC_MACRO) #undef FUNC_MACRO -#define FUNC_MACRO(Fp) \ +#define FUNC_MACRO(Fp, Sp) \ template void apply_pauli( \ - std::uint64_t, std::uint64_t, std::uint64_t, Complex, StateVectorBatched&); -CALL_MACRO_FOR_FLOAT(FUNC_MACRO) + std::uint64_t, std::uint64_t, std::uint64_t, Complex, StateVectorBatched&); +CALL_MACRO_FOR_FLOAT_AND_SPACE(FUNC_MACRO) #undef FUNC_MACRO -template +template void apply_pauli_rotation(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, Fp angle, - StateVector& state_vector) { + StateVector& state_vector) { std::uint64_t global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); Complex true_angle = angle * coef; const Complex cosval = Kokkos::cos(-true_angle / 2); @@ -151,13 +151,13 @@ void apply_pauli_rotation(std::uint64_t control_mask, Kokkos::fence(); } } -template +template void apply_pauli_rotation(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, Fp angle, - StateVectorBatched& states) { + StateVectorBatched& states) { std::uint64_t global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); Complex true_angle = angle * coef; const Complex cosval = Kokkos::cos(-true_angle / 2); @@ -210,14 +210,14 @@ void apply_pauli_rotation(std::uint64_t control_mask, Kokkos::fence(); } } -template +template void apply_pauli_rotation(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, Fp pcoef, std::vector params, - StateVectorBatched& states) { + StateVectorBatched& states) { std::uint64_t global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); auto team_policy = Kokkos::TeamPolicy(states.batch_size(), Kokkos::AUTO); Kokkos::parallel_for( @@ -271,24 +271,28 @@ void apply_pauli_rotation(std::uint64_t control_mask, }); Kokkos::fence(); } -#define FUNC_MACRO(Fp) \ +#define FUNC_MACRO(Fp, Sp) \ template void apply_pauli_rotation( \ - std::uint64_t, std::uint64_t, std::uint64_t, Complex, Fp, StateVector&); -CALL_MACRO_FOR_FLOAT(FUNC_MACRO) + std::uint64_t, std::uint64_t, std::uint64_t, Complex, Fp, StateVector&); +CALL_MACRO_FOR_FLOAT_AND_SPACE(FUNC_MACRO) #undef FUNC_MACRO -#define FUNC_MACRO(Fp) \ - template void apply_pauli_rotation( \ - std::uint64_t, std::uint64_t, std::uint64_t, Complex, Fp, StateVectorBatched&); -CALL_MACRO_FOR_FLOAT(FUNC_MACRO) +#define FUNC_MACRO(Fp, Sp) \ + template void apply_pauli_rotation(std::uint64_t, \ + std::uint64_t, \ + std::uint64_t, \ + Complex, \ + Fp, \ + StateVectorBatched&); +CALL_MACRO_FOR_FLOAT_AND_SPACE(FUNC_MACRO) #undef FUNC_MACRO -#define FUNC_MACRO(Fp) \ +#define FUNC_MACRO(Fp, Sp) \ template void apply_pauli_rotation(std::uint64_t, \ std::uint64_t, \ std::uint64_t, \ Complex, \ Fp, \ std::vector, \ - StateVectorBatched&); -CALL_MACRO_FOR_FLOAT(FUNC_MACRO) + StateVectorBatched&); +CALL_MACRO_FOR_FLOAT_AND_SPACE(FUNC_MACRO) #undef FUNC_MACRO } // namespace scaluq::internal diff --git a/src/operator/apply_pauli.hpp b/src/operator/apply_pauli.hpp index 572c2b56..73cef2f5 100644 --- a/src/operator/apply_pauli.hpp +++ b/src/operator/apply_pauli.hpp @@ -5,38 +5,38 @@ namespace scaluq::internal { -template +template void apply_pauli(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, - StateVector& state_vector); -template + StateVector& state_vector); +template void apply_pauli(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, - StateVectorBatched& states); -template + StateVectorBatched& states); +template void apply_pauli_rotation(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, Fp angle, - StateVector& state_vector); -template + StateVector& state_vector); +template void apply_pauli_rotation(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, Fp angle, - StateVectorBatched& states); -template + StateVectorBatched& states); +template void apply_pauli_rotation(std::uint64_t control_mask, std::uint64_t bit_flip_mask, std::uint64_t phase_flip_mask, Complex coef, Fp pcoef, std::vector params, - StateVectorBatched& states); + StateVectorBatched& states); } // namespace scaluq::internal diff --git a/src/operator/operator.cpp b/src/operator/operator.cpp index eb1acd0f..e7f55486 100644 --- a/src/operator/operator.cpp +++ b/src/operator/operator.cpp @@ -3,8 +3,8 @@ #include "../util/template.hpp" namespace scaluq { -FLOAT(Fp) -std::string Operator::to_string() const { +FLOAT_AND_SPACE(Fp, Sp) +std::string Operator::to_string() const { std::stringstream ss; for (auto itr = _terms.begin(); itr != _terms.end(); ++itr) { ss << itr->coef() << " " << itr->get_pauli_string(); @@ -15,8 +15,8 @@ std::string Operator::to_string() const { return ss.str(); } -FLOAT(Fp) -void Operator::add_operator(PauliOperator&& mpt) { +FLOAT_AND_SPACE(Fp, Sp) +void Operator::add_operator(PauliOperator&& mpt) { _is_hermitian &= mpt.coef().imag() == 0.; if (![&] { const auto& target_list = mpt.target_qubit_list(); @@ -30,8 +30,8 @@ void Operator::add_operator(PauliOperator&& mpt) { this->_terms.emplace_back(std::move(mpt)); } -FLOAT(Fp) -void Operator::add_random_operator(const std::uint64_t operator_count, std::uint64_t seed) { +FLOAT_AND_SPACE(Fp, Sp) +void Operator::add_random_operator(const std::uint64_t operator_count, std::uint64_t seed) { Random random(seed); for (std::uint64_t operator_idx = 0; operator_idx < operator_count; operator_idx++) { std::vector target_qubit_list(_n_qubits), pauli_id_list(_n_qubits); @@ -40,12 +40,12 @@ void Operator::add_random_operator(const std::uint64_t operator_count, std:: pauli_id_list[qubit_idx] = random.int32() & 0b11; } Complex coef = random.uniform() * 2. - 1.; - this->add_operator(PauliOperator(target_qubit_list, pauli_id_list, coef)); + this->add_operator(PauliOperator(target_qubit_list, pauli_id_list, coef)); } } -FLOAT(Fp) -void Operator::optimize() { +FLOAT_AND_SPACE(Fp, Sp) +void Operator::optimize() { std::map, Complex> pauli_and_coef; for (const auto& pauli : _terms) { pauli_and_coef[pauli.get_XZ_mask_representation()] += pauli.coef(); @@ -57,8 +57,8 @@ void Operator::optimize() { } } -FLOAT(Fp) -Operator Operator::get_dagger() const { +FLOAT_AND_SPACE(Fp, Sp) +Operator Operator::get_dagger() const { Operator quantum_operator(_n_qubits); for (const auto& pauli : _terms) { quantum_operator.add_operator(pauli.get_dagger()); @@ -66,28 +66,29 @@ Operator Operator::get_dagger() const { return quantum_operator; } -FLOAT(Fp) -void Operator::apply_to_state(StateVector& state_vector) const { - StateVector res(state_vector.n_qubits()); +FLOAT_AND_SPACE(Fp, Sp) +void Operator::apply_to_state(StateVector& state_vector) const { + StateVector res(state_vector.n_qubits()); res.set_zero_norm_state(); for (const auto& term : _terms) { - StateVector tmp = state_vector.copy(); + StateVector tmp = state_vector.copy(); term.apply_to_state(tmp); res.add_state_vector_with_coef(1, tmp); } state_vector = res; } -FLOAT(Fp) -Complex Operator::get_expectation_value(const StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +Complex Operator::get_expectation_value(const StateVector& state_vector) const { if (_n_qubits > state_vector.n_qubits()) { throw std::runtime_error( "Operator::get_expectation_value: n_qubits of state_vector is too small"); } std::uint64_t nterms = _terms.size(); - Kokkos:: - View*, Kokkos::HostSpace, Kokkos::MemoryTraits> - terms_view(_terms.data(), nterms); + Kokkos::View*, + Kokkos::HostSpace, + Kokkos::MemoryTraits> + terms_view(_terms.data(), nterms); Kokkos::View bmasks_host("bmasks_host", nterms); Kokkos::View pmasks_host("pmasks_host", nterms); Kokkos::View*, Kokkos::HostSpace> coefs_host("coefs_host", nterms); @@ -95,17 +96,17 @@ Complex Operator::get_expectation_value(const StateVector& state_vec Kokkos::DefaultHostExecutionSpace(), terms_view, bmasks_host, - [](const PauliOperator& pauli) { return pauli._ptr->_bit_flip_mask; }); + [](const PauliOperator& pauli) { return pauli._ptr->_bit_flip_mask; }); Kokkos::Experimental::transform( Kokkos::DefaultHostExecutionSpace(), terms_view, pmasks_host, - [](const PauliOperator& pauli) { return pauli._ptr->_phase_flip_mask; }); + [](const PauliOperator& pauli) { return pauli._ptr->_phase_flip_mask; }); Kokkos::Experimental::transform( Kokkos::DefaultHostExecutionSpace(), terms_view, coefs_host, - [](const PauliOperator& pauli) { return pauli._ptr->_coef; }); + [](const PauliOperator& pauli) { return pauli._ptr->_coef; }); Kokkos::View bmasks("bmasks", nterms); Kokkos::View pmasks("pmasks", nterms); Kokkos::View*> coefs("coefs", nterms); @@ -152,9 +153,10 @@ Complex Operator::get_expectation_value(const StateVector& state_vec return res; } -FLOAT(Fp) -Complex Operator::get_transition_amplitude(const StateVector& state_vector_bra, - const StateVector& state_vector_ket) const { +FLOAT_AND_SPACE(Fp, Sp) +Complex Operator::get_transition_amplitude( + const StateVector& state_vector_bra, + const StateVector& state_vector_ket) const { if (state_vector_bra.n_qubits() != state_vector_ket.n_qubits()) { throw std::runtime_error( "Operator::get_transition_amplitude: n_qubits of state_vector_bra and " @@ -169,16 +171,16 @@ Complex Operator::get_transition_amplitude(const StateVector& state_ std::vector bmasks_vector(nterms); std::vector pmasks_vector(nterms); std::vector> coefs_vector(nterms); + std::transform(_terms.begin(), + _terms.end(), + bmasks_vector.begin(), + [](const PauliOperator& pauli) { return pauli._ptr->_bit_flip_mask; }); + std::transform(_terms.begin(), + _terms.end(), + pmasks_vector.begin(), + [](const PauliOperator& pauli) { return pauli._ptr->_phase_flip_mask; }); std::transform( - _terms.begin(), _terms.end(), bmasks_vector.begin(), [](const PauliOperator& pauli) { - return pauli._ptr->_bit_flip_mask; - }); - std::transform( - _terms.begin(), _terms.end(), pmasks_vector.begin(), [](const PauliOperator& pauli) { - return pauli._ptr->_phase_flip_mask; - }); - std::transform( - _terms.begin(), _terms.end(), coefs_vector.begin(), [](const PauliOperator& pauli) { + _terms.begin(), _terms.end(), coefs_vector.begin(), [](const PauliOperator& pauli) { return pauli._ptr->_coef; }); Kokkos::View bmasks = @@ -227,16 +229,16 @@ Complex Operator::get_transition_amplitude(const StateVector& state_ return res; } -FLOAT(Fp) -Operator& Operator::operator*=(Complex coef) { +FLOAT_AND_SPACE(Fp, Sp) +Operator& Operator::operator*=(Complex coef) { for (auto& pauli : _terms) { pauli = pauli * coef; } return *this; } -FLOAT(Fp) -Operator& Operator::operator+=(const Operator& target) { +FLOAT_AND_SPACE(Fp, Sp) +Operator& Operator::operator+=(const Operator& target) { if (_n_qubits != target._n_qubits) { throw std::runtime_error("Operator::oeprator+=: n_qubits must be equal"); } @@ -246,8 +248,8 @@ Operator& Operator::operator+=(const Operator& target) { return *this; } -FLOAT(Fp) -Operator Operator::operator*(const Operator& target) const { +FLOAT_AND_SPACE(Fp, Sp) +Operator Operator::operator*(const Operator& target) const { if (_n_qubits != target._n_qubits) { throw std::runtime_error("Operator::oeprator+=: n_qubits must be equal"); } @@ -260,20 +262,20 @@ Operator Operator::operator*(const Operator& target) const { return ret; } -FLOAT(Fp) -Operator& Operator::operator+=(const PauliOperator& pauli) { +FLOAT_AND_SPACE(Fp, Sp) +Operator& Operator::operator+=(const PauliOperator& pauli) { add_operator(pauli); return *this; } -FLOAT(Fp) -Operator& Operator::operator*=(const PauliOperator& pauli) { +FLOAT_AND_SPACE(Fp, Sp) +Operator& Operator::operator*=(const PauliOperator& pauli) { for (auto& pauli1 : _terms) { pauli1 = pauli1 * pauli; } return *this; } -FLOAT_DECLARE_CLASS(Operator) +FLOAT_AND_SPACE_DECLARE_CLASS(Operator) } // namespace scaluq diff --git a/src/operator/pauli_operator.cpp b/src/operator/pauli_operator.cpp index 041b61a8..eec55ec7 100644 --- a/src/operator/pauli_operator.cpp +++ b/src/operator/pauli_operator.cpp @@ -4,8 +4,8 @@ #include "apply_pauli.hpp" namespace scaluq { -FLOAT(Fp) -PauliOperator::Data::Data(std::string_view pauli_string, Complex coef) +FLOAT_AND_SPACE(Fp, Sp) +PauliOperator::Data::Data(std::string_view pauli_string, Complex coef) : _coef(coef), _bit_flip_mask(0), _phase_flip_mask(0) { auto ss = std::stringstream(std::string(pauli_string)); while (1) { @@ -28,10 +28,10 @@ PauliOperator::Data::Data(std::string_view pauli_string, Complex coef) } } -FLOAT(Fp) -PauliOperator::Data::Data(const std::vector& target_qubit_list, - const std::vector& pauli_id_list, - Complex coef) +FLOAT_AND_SPACE(Fp, Sp) +PauliOperator::Data::Data(const std::vector& target_qubit_list, + const std::vector& pauli_id_list, + Complex coef) : _coef(coef), _bit_flip_mask(0), _phase_flip_mask(0) { if (target_qubit_list.size() != pauli_id_list.size()) { throw std::runtime_error( @@ -45,21 +45,21 @@ PauliOperator::Data::Data(const std::vector& target_qubit_lis } } -FLOAT(Fp) -PauliOperator::Data::Data(const std::vector& pauli_id_par_qubit, - Complex coef) +FLOAT_AND_SPACE(Fp, Sp) +PauliOperator::Data::Data(const std::vector& pauli_id_par_qubit, + Complex coef) : _coef(coef), _bit_flip_mask(0), _phase_flip_mask(0) { for (std::uint64_t i = 0; i < pauli_id_par_qubit.size(); ++i) { - if (pauli_id_par_qubit[i] != PauliOperator::I) { + if (pauli_id_par_qubit[i] != PauliOperator::I) { add_single_pauli(i, pauli_id_par_qubit[i]); } } } -FLOAT(Fp) -PauliOperator::Data::Data(std::uint64_t bit_flip_mask, - std::uint64_t phase_flip_mask, - Complex coef) +FLOAT_AND_SPACE(Fp, Sp) +PauliOperator::Data::Data(std::uint64_t bit_flip_mask, + std::uint64_t phase_flip_mask, + Complex coef) : _coef(coef), _bit_flip_mask(0), _phase_flip_mask(0) { for (std::uint64_t target_idx = 0; target_idx < sizeof(std::uint64_t) * 8; target_idx++) { bool bit_flip = bit_flip_mask >> target_idx & 1; @@ -79,8 +79,9 @@ PauliOperator::Data::Data(std::uint64_t bit_flip_mask, } } -FLOAT(Fp) -void PauliOperator::Data::add_single_pauli(std::uint64_t target_qubit, std::uint64_t pauli_id) { +FLOAT_AND_SPACE(Fp, Sp) +void PauliOperator::Data::add_single_pauli(std::uint64_t target_qubit, + std::uint64_t pauli_id) { if (target_qubit >= sizeof(std::uint64_t) * 8) { throw std::runtime_error( "PauliOperator::Data::add_single_pauli: target_qubit is too large"); @@ -104,8 +105,8 @@ void PauliOperator::Data::add_single_pauli(std::uint64_t target_qubit, std:: } } -FLOAT(Fp) -std::string PauliOperator::get_pauli_string() const { +FLOAT_AND_SPACE(Fp, Sp) +std::string PauliOperator::get_pauli_string() const { std::stringstream ss; std::uint64_t size = _ptr->_target_qubit_list.size(); if (size == 0) return ""; @@ -120,19 +121,19 @@ std::string PauliOperator::get_pauli_string() const { return res; } -FLOAT(Fp) -PauliOperator PauliOperator::get_dagger() const { +FLOAT_AND_SPACE(Fp, Sp) +PauliOperator PauliOperator::get_dagger() const { return PauliOperator(_ptr->_target_qubit_list, _ptr->_pauli_id_list, Kokkos::conj(_ptr->_coef)); } -FLOAT(Fp) -std::uint64_t PauliOperator::get_qubit_count() const { +FLOAT_AND_SPACE(Fp, Sp) +std::uint64_t PauliOperator::get_qubit_count() const { if (_ptr->_target_qubit_list.empty()) return 0; return std::ranges::max(_ptr->_target_qubit_list) + 1; } -FLOAT(Fp) -void PauliOperator::apply_to_state(StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +void PauliOperator::apply_to_state(StateVector& state_vector) const { if (state_vector.n_qubits() < get_qubit_count()) { throw std::runtime_error( "PauliOperator::apply_to_state: n_qubits of state_vector is too small to apply the " @@ -142,8 +143,9 @@ void PauliOperator::apply_to_state(StateVector& state_vector) const { 0ULL, _ptr->_bit_flip_mask, _ptr->_phase_flip_mask, _ptr->_coef, state_vector); } -FLOAT(Fp) -Complex PauliOperator::get_expectation_value(const StateVector& state_vector) const { +FLOAT_AND_SPACE(Fp, Sp) +Complex PauliOperator::get_expectation_value( + const StateVector& state_vector) const { if (state_vector.n_qubits() < get_qubit_count()) { throw std::runtime_error( "PauliOperator::get_expectation_value: n_qubits of state_vector is too small to " @@ -183,9 +185,10 @@ Complex PauliOperator::get_expectation_value(const StateVector& stat return _ptr->_coef * res; } -FLOAT(Fp) -Complex PauliOperator::get_transition_amplitude( - const StateVector& state_vector_bra, const StateVector& state_vector_ket) const { +FLOAT_AND_SPACE(Fp, Sp) +Complex PauliOperator::get_transition_amplitude( + const StateVector& state_vector_bra, + const StateVector& state_vector_ket) const { if (state_vector_bra.n_qubits() != state_vector_ket.n_qubits()) { throw std::runtime_error("state_vector_bra must have same n_qubits to state_vector_ket."); } @@ -233,13 +236,13 @@ Complex PauliOperator::get_transition_amplitude( return _ptr->_coef * res; } -FLOAT(Fp) -internal::ComplexMatrix PauliOperator::get_matrix() const { +FLOAT_AND_SPACE(Fp, Sp) +internal::ComplexMatrix PauliOperator::get_matrix() const { return get_matrix_ignoring_coef() * StdComplex(_ptr->_coef); } -FLOAT(Fp) -internal::ComplexMatrix PauliOperator::get_matrix_ignoring_coef() const { +FLOAT_AND_SPACE(Fp, Sp) +internal::ComplexMatrix PauliOperator::get_matrix_ignoring_coef() const { std::uint64_t flip_mask, phase_mask, rot90_count; Kokkos::parallel_reduce( Kokkos::RangePolicy(0, _ptr->_pauli_id_list.size()), @@ -271,8 +274,8 @@ internal::ComplexMatrix PauliOperator::get_matrix_ignoring_coef() const return mat; } -FLOAT(Fp) -PauliOperator PauliOperator::operator*(const PauliOperator& target) const { +FLOAT_AND_SPACE(Fp, Sp) +PauliOperator PauliOperator::operator*(const PauliOperator& target) const { int extra_90rot_cnt = 0; auto x_left = _ptr->_bit_flip_mask & ~_ptr->_phase_flip_mask; auto y_left = _ptr->_bit_flip_mask & _ptr->_phase_flip_mask; @@ -294,6 +297,6 @@ PauliOperator PauliOperator::operator*(const PauliOperator& target) cons _ptr->_coef * target._ptr->_coef * internal::PHASE_90ROT()[extra_90rot_cnt]); } -FLOAT_DECLARE_CLASS(PauliOperator) +FLOAT_AND_SPACE_DECLARE_CLASS(PauliOperator) } // namespace scaluq diff --git a/src/state/state_vector.cpp b/src/state/state_vector.cpp index b200a8ff..331c8ad9 100644 --- a/src/state/state_vector.cpp +++ b/src/state/state_vector.cpp @@ -1,4 +1,5 @@ #include +#include #include "../util/template.hpp" @@ -11,7 +12,7 @@ StateVector::StateVector(std::uint64_t n_qubits) set_zero_state(); } FLOAT_AND_SPACE(Fp, Sp) -StateVector::StateVector(Kokkos::View view) +StateVector::StateVector(Kokkos::View view) : _n_qubits(std::bit_width(view.extent(0)) - 1), _dim(view.extent(0)), _raw(view) {} FLOAT_AND_SPACE(Fp, Sp) void StateVector::set_amplitude_at(std::uint64_t index, ComplexType c) { @@ -62,9 +63,12 @@ void StateVector::set_Haar_random_state(std::uint64_t n_qubits, std::uin *this = Haar_random_state(n_qubits, seed); } FLOAT_AND_SPACE(Fp, Sp) -[[nodiscard]] std::vector::ComplexType> -StateVector::get_amplitudes() const { - return internal::convert_device_view_to_host_vector(_raw); +[[nodiscard]] std::vector> StateVector::get_amplitudes() const { + if constexpr (std::is_same_v) { + return internal::convert_device_view_to_host_vector(_raw); + } else { + return std::vector>(_raw.data(), _raw.data() + _raw.size()); + } } FLOAT_AND_SPACE(Fp, Sp) Fp StateVector::get_squared_norm() const { @@ -211,13 +215,17 @@ std::vector StateVector::sampling(std::uint64_t sampling_ return internal::convert_device_view_to_host_vector(result); } FLOAT_AND_SPACE(Fp, Sp) -void StateVector::load(const std::vector& other) { +void StateVector::load(const std::vector>& other) { if (other.size() != _dim) { throw std::runtime_error( "Error: StateVector::load(const vector&): invalid " "length of state"); } - _raw = internal::convert_host_vector_to_device_view(other); + if constexpr (std::is_same_v) { + _raw = internal::convert_host_vector_to_device_view(other); + } else { + std::copy(other.begin(), other.end(), _raw.data()); + } } FLOAT_AND_SPACE(Fp, Sp) StateVector StateVector::copy() const { @@ -246,6 +254,6 @@ std::string StateVector::to_string() const { return os.str(); } -FLOAT_DECLARE_CLASS(StateVector) +FLOAT_AND_SPACE_DECLARE_CLASS(StateVector) } // namespace scaluq