From d853c2223ee1cb55def9099599d3a95d26d42e5c Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Tue, 6 Aug 2024 13:03:03 +0900 Subject: [PATCH 01/55] remove bitvector --- scaluq/operator/pauli_operator.cpp | 54 ++++----- scaluq/operator/pauli_operator.hpp | 16 +-- scaluq/util/bit_vector.hpp | 177 ----------------------------- 3 files changed, 27 insertions(+), 220 deletions(-) delete mode 100644 scaluq/util/bit_vector.hpp diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 1596cd47..48486b41 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -47,30 +47,20 @@ PauliOperator::Data::Data(const std::vector& target_qubit_list, } } -PauliOperator::Data::Data(const std::vector& bit_flip_mask, - const std::vector& phase_flip_mask, - Complex coef) - : _coef(coef) { - UINT num_y = 0; - UINT max_target = 0; - if (auto msb = internal::BitVector(bit_flip_mask).msb(); - msb != std::numeric_limits::max() && max_target < msb) - max_target = msb; - if (auto msb = internal::BitVector(phase_flip_mask).msb(); - msb != std::numeric_limits::max() && max_target < msb) - max_target = msb; - for (UINT target_idx = 0; target_idx <= max_target; target_idx++) { - if (!bit_flip_mask[target_idx]) { - if (!phase_flip_mask[target_idx]) +PauliOperator::Data::Data(UINT bit_flip_mask, UINT phase_flip_mask, Complex coef) : _coef(coef) { + for (UINT target_idx = 0; target_idx < sizeof(UINT) * 8; target_idx++) { + bool bit_flip = bit_flip_mask >> target_idx & 1; + bool phase_flip = bit_flip_mask >> target_idx & 1; + if (!bit_flip) { + if (!phase_flip) continue; else add_single_pauli(target_idx, 3); } else { - if (!phase_flip_mask[target_idx]) + if (!phase_flip) add_single_pauli(target_idx, 1); else { add_single_pauli(target_idx, 2); - ++num_y; } } } @@ -79,16 +69,16 @@ PauliOperator::Data::Data(const std::vector& bit_flip_mask, void PauliOperator::Data::add_single_pauli(UINT target_qubit, UINT pauli_id) { _target_qubit_list.push_back(target_qubit); _pauli_id_list.push_back(pauli_id); - if ((_bit_flip_mask | _phase_flip_mask)[target_qubit]) { + if ((_bit_flip_mask | _phase_flip_mask) >> target_qubit & 1) { throw std::runtime_error( "PauliOperator::Data::add_single_pauli: You cannot add single pauli twice for same " "qubit."); } if (pauli_id == PauliOperator::X || pauli_id == PauliOperator::Y) { - _bit_flip_mask[target_qubit] = true; + _bit_flip_mask |= 1ULL << target_qubit; } if (pauli_id == PauliOperator::Y || pauli_id == PauliOperator::Z) { - _phase_flip_mask[target_qubit] = true; + _phase_flip_mask |= 1ULL << target_qubit; } } @@ -113,8 +103,8 @@ void PauliOperator::apply_to_state(StateVector& state_vector) const { "PauliOperator::apply_to_state: n_qubits of state_vector is too small to apply the " "operator"); } - UINT bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; - UINT phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; + UINT bit_flip_mask = _ptr->_bit_flip_mask; + UINT phase_flip_mask = _ptr->_phase_flip_mask; Complex coef = get_coef(); if (bit_flip_mask == 0) { Kokkos::parallel_for( @@ -151,8 +141,8 @@ Complex PauliOperator::get_expectation_value(const StateVector& state_vector) co "PauliOperator::get_expectation_value: n_qubits of state_vector is too small to apply " "the operator"); } - UINT bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; - UINT phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; + UINT bit_flip_mask = _ptr->_bit_flip_mask; + UINT phase_flip_mask = _ptr->_phase_flip_mask; if (bit_flip_mask == 0) { double res; Kokkos::parallel_reduce( @@ -195,8 +185,8 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ "PauliOperator::get_expectation_value: n_qubits of state_vector is too small to apply " "the operator"); } - UINT bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; - UINT phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; + UINT bit_flip_mask = _ptr->_bit_flip_mask; + UINT phase_flip_mask = _ptr->_phase_flip_mask; if (bit_flip_mask == 0) { Complex res; Kokkos::parallel_reduce( @@ -273,12 +263,12 @@ PauliOperator PauliOperator::operator*(const PauliOperator& target) const { auto x_right = target._ptr->_bit_flip_mask - target._ptr->_phase_flip_mask; auto y_right = target._ptr->_bit_flip_mask & target._ptr->_phase_flip_mask; auto z_right = target._ptr->_phase_flip_mask - target._ptr->_bit_flip_mask; - extra_90rot_cnt += (x_left & y_right).popcount(); // XY = iZ - extra_90rot_cnt += (y_left & z_right).popcount(); // YZ = iX - extra_90rot_cnt += (z_left & x_right).popcount(); // ZX = iY - extra_90rot_cnt -= (x_left & z_right).popcount(); // XZ = -iY - extra_90rot_cnt -= (y_left & x_right).popcount(); // YX = -iZ - extra_90rot_cnt -= (z_left & y_right).popcount(); // ZY = -iX + extra_90rot_cnt += std::popcount(x_left & y_right); // XY = iZ + extra_90rot_cnt += std::popcount(y_left & z_right); // YZ = iX + extra_90rot_cnt += std::popcount(z_left & x_right); // ZX = iY + extra_90rot_cnt -= std::popcount(x_left & z_right); // XZ = -iY + extra_90rot_cnt -= std::popcount(y_left & x_right); // YX = -iZ + extra_90rot_cnt -= std::popcount(z_left & y_right); // ZY = -iX extra_90rot_cnt %= 4; if (extra_90rot_cnt < 0) extra_90rot_cnt += 4; return PauliOperator(_ptr->_bit_flip_mask ^ target._ptr->_bit_flip_mask, diff --git a/scaluq/operator/pauli_operator.hpp b/scaluq/operator/pauli_operator.hpp index 6b02f430..3f7ba5ba 100644 --- a/scaluq/operator/pauli_operator.hpp +++ b/scaluq/operator/pauli_operator.hpp @@ -5,7 +5,6 @@ #include "../state/state_vector.hpp" #include "../types.hpp" -#include "../util/bit_vector.hpp" namespace scaluq { class PauliOperator { @@ -17,7 +16,7 @@ class PauliOperator { friend class Operator; std::vector _target_qubit_list, _pauli_id_list; Complex _coef; - internal::BitVector _bit_flip_mask, _phase_flip_mask; + UINT _bit_flip_mask, _phase_flip_mask; public: explicit Data(Complex coef = 1.); @@ -26,15 +25,13 @@ class PauliOperator { const std::vector& pauli_id_list, Complex coef = 1.); Data(const std::vector& pauli_id_par_qubit, Complex coef = 1.); - Data(const std::vector& bit_flip_mask, - const std::vector& phase_flip_mask, - Complex coef); + Data(UINT bit_flip_mask, UINT phase_flip_mask, Complex coef); void add_single_pauli(UINT target_qubit, UINT pauli_id); Complex get_coef() const { return _coef; } void set_coef(Complex c) { _coef = c; } const std::vector& get_target_qubit_list() const { return _target_qubit_list; } const std::vector& get_pauli_id_list() const { return _pauli_id_list; } - std::tuple, std::vector> get_XZ_mask_representation() const { + std::tuple get_XZ_mask_representation() const { return {_bit_flip_mask, _phase_flip_mask}; } }; @@ -55,9 +52,7 @@ class PauliOperator { : _ptr(std::make_shared(target_qubit_list, pauli_id_list, coef)) {} PauliOperator(const std::vector& pauli_id_par_qubit, Complex coef = 1.) : _ptr(std::make_shared(pauli_id_par_qubit, coef)) {} - PauliOperator(const std::vector& bit_flip_mask, - const std::vector& phase_flip_mask, - Complex coef) + PauliOperator(UINT bit_flip_mask, UINT phase_flip_mask, Complex coef = 1.) : _ptr(std::make_shared(bit_flip_mask, phase_flip_mask, coef)) {} [[nodiscard]] inline Complex get_coef() const { return _ptr->get_coef(); } @@ -67,8 +62,7 @@ class PauliOperator { [[nodiscard]] inline const std::vector& get_pauli_id_list() const { return _ptr->get_pauli_id_list(); } - [[nodiscard]] inline std::tuple, std::vector> - get_XZ_mask_representation() const { + [[nodiscard]] inline std::tuple get_XZ_mask_representation() const { return _ptr->get_XZ_mask_representation(); } [[nodiscard]] std::string get_pauli_string() const; diff --git a/scaluq/util/bit_vector.hpp b/scaluq/util/bit_vector.hpp deleted file mode 100644 index 36c9f6a3..00000000 --- a/scaluq/util/bit_vector.hpp +++ /dev/null @@ -1,177 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include "../types.hpp" - -namespace scaluq { -namespace internal { -class BitVector { -public: - constexpr static UINT BIT_SIZE = sizeof(UINT) * 8; - - BitVector(UINT sz = 1) : _data((sz + BIT_SIZE - 1) / BIT_SIZE) {} - BitVector(const std::vector& vec) : _data((vec.size() + BIT_SIZE - 1) / BIT_SIZE) { - for (UINT i = 0; i < vec.size(); ++i) { - set(i, vec[i]); - } - } - - [[nodiscard]] inline const std::vector& data_raw() const { return _data; } - [[nodiscard]] inline std::vector& data_raw() { return _data; } - - [[nodiscard]] inline bool get(UINT idx) const { - if (idx >= _data.size() * BIT_SIZE) return false; - return _data[idx / BIT_SIZE] >> (idx % BIT_SIZE) & 1ULL; - } - inline void set(UINT idx, bool b) { - if (idx >= _data.size() * BIT_SIZE) _data.resize(idx / BIT_SIZE + 1); - if (b) - _data[idx / BIT_SIZE] |= 1ULL << (idx % BIT_SIZE); - else - _data[idx / BIT_SIZE] &= ~(1ULL << (idx % BIT_SIZE)); - } - - template - class _Reference { - friend BitVector; - - public: - _Reference& operator=(bool b) { - static_assert(!Const); - _container.set(_idx, b); - return *this; - } - _Reference& operator&=(bool b) { - static_assert(!Const); - _container.set(_idx, b && _container.get(_idx)); - return *this; - } - _Reference& operator|=(bool b) { - static_assert(!Const); - _container.set(_idx, b || _container.get(_idx)); - return *this; - } - _Reference& operator^=(bool b) { - static_assert(!Const); - _container.set(_idx, b ^ _container.get(_idx)); - return *this; - } - operator bool() const { return _container.get(_idx); } - - private: - using ContainerReference = std::conditional_t; - ContainerReference _container; - const int _idx; - - _Reference(ContainerReference container, int idx) : _container(container), _idx(idx) {} - }; - - using ConstReference = _Reference; - using Reference = _Reference; - - [[nodiscard]] inline ConstReference operator[](int idx) const { - return ConstReference(*this, idx); - } - [[nodiscard]] inline Reference operator[](int idx) { return Reference(*this, idx); } - - inline BitVector& operator&=(const BitVector& rhs) { - if (rhs._data.size() < _data.size()) { - _data.resize(rhs._data.size()); - } - for (UINT i = 0; i < _data.size(); i++) _data[i] &= rhs._data[i]; - return *this; - } - inline BitVector operator&(const BitVector& rhs) const { return BitVector(*this) &= rhs; } - inline BitVector& operator|=(const BitVector& rhs) { - if (rhs._data.size() > _data.size()) { - _data.resize(rhs._data.size()); - } - for (UINT i = 0; i < rhs._data.size(); i++) _data[i] |= rhs._data[i]; - return *this; - } - inline BitVector operator|(const BitVector& rhs) const { return BitVector(*this) |= rhs; } - inline BitVector& operator^=(const BitVector& rhs) { - if (rhs._data.size() > _data.size()) { - _data.resize(rhs._data.size()); - } - for (UINT i = 0; i < rhs._data.size(); i++) _data[i] ^= rhs._data[i]; - return *this; - } - inline BitVector operator^(const BitVector& rhs) const { return BitVector(*this) ^= rhs; } - inline BitVector& operator-=(const BitVector& rhs) { - for (UINT i = 0; i < std::min(_data.size(), rhs._data.size()); i++) - _data[i] &= ~rhs._data[i]; - return *this; - } - inline BitVector operator-(const BitVector& rhs) const { return BitVector(*this) -= rhs; } - - inline std::weak_ordering operator<=>(const BitVector& other) const { - UINT sz = std::max(_data.size(), other._data.size()); - for (UINT i = sz; i-- != 0;) { - UINT l = i >= _data.size() ? 0ULL : _data[i]; - UINT r = i >= other._data.size() ? 0ULL : other._data[i]; - if (l != r) return l <=> r; - if (i == 0) break; - } - return std::weak_ordering::equivalent; - } - inline bool operator==(const BitVector& other) const { - UINT sz = std::max(_data.size(), other._data.size()); - for (UINT i = sz; i-- != 0;) { - UINT l = i >= _data.size() ? 0ULL : _data[i]; - UINT r = i >= other._data.size() ? 0ULL : other._data[i]; - if (l != r) return false; - } - return true; - } - - operator std::vector() const { - std::vector vec(_data.size() * BIT_SIZE); - for (UINT i = 0; i < vec.size(); ++i) { - vec[i] = get(i); - } - return vec; - } - - inline bool empty() const { - return std::ranges::all_of(_data, [](UINT x) { return x == 0; }); - } - inline UINT msb() const { - for (UINT i = _data.size() - 1; i != std::numeric_limits::max(); i--) { - if (_data[i] != 0) return (i + 1) * BIT_SIZE - std::countl_zero(_data[i]) - 1; - } - return std::numeric_limits::max(); - } - inline UINT countr_zero() const { - UINT res = 0; - for (UINT i = 0; i < _data.size(); i++) { - UINT to_add = std::countr_zero(_data[i]); - res += to_add; - if (to_add < BIT_SIZE) break; - } - return res; - } - inline UINT countr_one() const { - UINT res = 0; - for (UINT i = 0; i < _data.size(); i++) { - UINT to_add = std::countr_one(_data[i]); - res += to_add; - if (to_add < BIT_SIZE) break; - } - return res; - } - inline UINT popcount() const { - UINT res = 0; - for (UINT i = 0; i < _data.size(); i++) res += std::popcount(_data[i]); - return res; - } - -private: - std::vector _data; -}; -} // namespace internal -} // namespace scaluq From c5fffc622b1c8baf2c7903a991230a78dda86514 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 11:29:54 +0900 Subject: [PATCH 02/55] pauli gate: adapt to control --- scaluq/CMakeLists.txt | 2 +- scaluq/gate/gate_pauli.hpp | 7 ++- scaluq/gate/param_gate_pauli.hpp | 5 +- scaluq/gate/update_ops.hpp | 7 --- scaluq/gate/update_ops_pauli.cpp | 72 ------------------------- scaluq/operator/apply_pauli.cpp | 86 ++++++++++++++++++++++++++++++ scaluq/operator/apply_pauli.hpp | 7 +++ scaluq/operator/pauli_operator.cpp | 38 ------------- scaluq/operator/pauli_operator.hpp | 10 +++- 9 files changed, 112 insertions(+), 122 deletions(-) delete mode 100644 scaluq/gate/update_ops_pauli.cpp create mode 100644 scaluq/operator/apply_pauli.cpp create mode 100644 scaluq/operator/apply_pauli.hpp diff --git a/scaluq/CMakeLists.txt b/scaluq/CMakeLists.txt index b3495995..898c3029 100644 --- a/scaluq/CMakeLists.txt +++ b/scaluq/CMakeLists.txt @@ -4,9 +4,9 @@ target_sources(scaluq PRIVATE circuit/circuit.cpp gate/update_ops_dense_matrix.cpp gate/update_ops_standard.cpp - gate/update_ops_pauli.cpp gate/update_ops_quantum_matrix.cpp # gate/merge_gate.cpp + operator/apply_pauli.cpp operator/pauli_operator.cpp operator/operator.cpp state/state_vector.cpp diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index cc796213..1109b852 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -2,6 +2,7 @@ #include +#include "../operator/apply_pauli.hpp" #include "../operator/pauli_operator.hpp" #include "../util/utility.hpp" #include "gate.hpp" @@ -23,7 +24,8 @@ class PauliGateImpl : public GateBase { ComplexMatrix get_matrix() const override { return this->_pauli.get_matrix(); } void update_quantum_state(StateVector& state_vector) const override { - pauli_gate(_control_mask, _pauli, state_vector); + auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); + apply_pauli(_control_mask, bit_flip_mask, phase_flip_mask, state_vector); } }; @@ -54,7 +56,8 @@ class PauliRotationGateImpl : public GateBase { return mat; } void update_quantum_state(StateVector& state_vector) const override { - pauli_rotation_gate(_control_mask, _pauli, _angle, state_vector); + auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); + apply_pauli_rotation(_control_mask, bit_flip_mask, phase_flip_mask, _angle, state_vector); } }; } // namespace internal diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index 8b70360d..faf3d507 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -2,6 +2,7 @@ #include +#include "../operator/apply_pauli.hpp" #include "../operator/pauli_operator.hpp" #include "../util/utility.hpp" #include "param_gate.hpp" @@ -32,7 +33,9 @@ class PPauliRotationGateImpl : public ParamGateBase { return mat; } void update_quantum_state(StateVector& state_vector, double param) const override { - pauli_rotation_gate(_control_mask, _pauli, _pcoef * param, state_vector); + auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); + apply_pauli_rotation( + _control_mask, bit_flip_mask, phase_flip_mask, _pcoef * param, state_vector); } }; } // namespace internal diff --git a/scaluq/gate/update_ops.hpp b/scaluq/gate/update_ops.hpp index d7998df7..5e9485c7 100644 --- a/scaluq/gate/update_ops.hpp +++ b/scaluq/gate/update_ops.hpp @@ -69,12 +69,5 @@ void u3_gate(UINT target_mask, StateVector& state); void swap_gate(UINT target_mask, UINT control_mask, StateVector& state); - -void pauli_gate(UINT control_mask, const PauliOperator& pauli, StateVector& state); - -void pauli_rotation_gate(UINT control_mask, - const PauliOperator& pauli, - double angle, - StateVector& state); } // namespace internal } // namespace scaluq diff --git a/scaluq/gate/update_ops_pauli.cpp b/scaluq/gate/update_ops_pauli.cpp deleted file mode 100644 index 49c1cf28..00000000 --- a/scaluq/gate/update_ops_pauli.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include - -#include "../constant.hpp" -#include "../operator/pauli_operator.hpp" -#include "../types.hpp" -#include "../util/utility.hpp" -#include "update_ops.hpp" - -namespace scaluq { -namespace internal { - -// まだ -void pauli_gate(UINT control_mask, const PauliOperator& pauli, StateVector& state) { - pauli.apply_to_state(state); -} - -// まだ -void pauli_rotation_gate(UINT control_mask, - const PauliOperator& pauli, - double angle, - StateVector& state) { - auto [bit_flip_mask_vector, phase_flip_mask_vector] = pauli.get_XZ_mask_representation(); - UINT bit_flip_mask = internal::BitVector(bit_flip_mask_vector).data_raw()[0]; - UINT phase_flip_mask = internal::BitVector(phase_flip_mask_vector).data_raw()[0]; - UINT global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex true_angle = angle * pauli.get_coef(); - const Complex cosval = Kokkos::cos(-true_angle / 2); - const Complex sinval = Kokkos::sin(-true_angle / 2); - if (bit_flip_mask == 0) { - const Complex cval_min = cosval - Complex(0, 1) * sinval; - const Complex cval_pls = cosval + Complex(0, 1) * sinval; - Kokkos::parallel_for( - state.dim(), KOKKOS_LAMBDA(UINT state_idx) { - if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { - state._raw[state_idx] *= cval_min; - } else { - state._raw[state_idx] *= cval_pls; - } - }); - Kokkos::fence(); - return; - } else { - const UINT insert_idx = internal::BitVector(bit_flip_mask_vector).msb(); - Kokkos::parallel_for( - state.dim() >> 1, KOKKOS_LAMBDA(UINT state_idx) { - UINT basis_0 = internal::insert_zero_to_basis_index(state_idx, insert_idx); - UINT basis_1 = basis_0 ^ bit_flip_mask; - - int bit_parity_0 = Kokkos::popcount(basis_0 & phase_flip_mask) & 1; - int bit_parity_1 = Kokkos::popcount(basis_1 & phase_flip_mask) & 1; - - // fetch values - Complex cval_0 = state._raw[basis_0]; - Complex cval_1 = state._raw[basis_1]; - - // set values - state._raw[basis_0] = - cosval * cval_0 + - Complex(0, 1) * sinval * cval_1 * - PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_0 * 2) % 4]; - state._raw[basis_1] = - cosval * cval_1 + - Complex(0, 1) * sinval * cval_0 * - PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_1 * 2) % 4]; - }); - Kokkos::fence(); - } -} - -} // namespace internal -} // namespace scaluq diff --git a/scaluq/operator/apply_pauli.cpp b/scaluq/operator/apply_pauli.cpp new file mode 100644 index 00000000..fbb54616 --- /dev/null +++ b/scaluq/operator/apply_pauli.cpp @@ -0,0 +1,86 @@ +#include "apply_pauli.hpp" + +namespace scaluq::internal { +void apply_pauli(UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, StateVector& state) { + Complex coef = get_coef(); + if (bit_flip_mask == 0) { + Kokkos::parallel_for( + state_vector.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(UINT i) { + UINT state_idx = insert_zero_at_mask_positions(i, control_mask) | control_mask; + if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { + state_vector._raw[state_idx] *= -coef; + } else { + state_vector._raw[state_idx] *= coef; + } + }); + Kokkos::fence(); + return; + } + UINT pivot = sizeof(UINT) * 8 - std::countl_zero(bit_flip_mask) - 1; + UINT global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); + Complex global_phase = PHASE_M90ROT().val[global_phase_90rot_count % 4]; + Kokkos::parallel_for( + state_vector.dim() >> (std::popcount(control_mask) + 1), KOKKOS_LAMBDA(UINT i) { + UINT basis_0 = + insert_zero_at_mask_positions(i, control_mask | 1ULL << pivot) | control_mask; + UINT basis_1 = basis_0 ^ bit_flip_mask; + Complex tmp1 = state_vector._raw[basis_0] * global_phase; + Complex tmp2 = state_vector._raw[basis_1] * global_phase; + if (Kokkos::popcount(basis_0 & phase_flip_mask) & 1) tmp2 = -tmp2; + if (Kokkos::popcount(basis_1 & phase_flip_mask) & 1) tmp1 = -tmp1; + state_vector._raw[basis_0] = tmp2 * coef; + state_vector._raw[basis_1] = tmp1 * coef; + }); + Kokkos::fence(); +} +void apply_pauli_rotation( + UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, double angle, StateVector& state) { + auto [bit_flip_mask, phase_flip_mask] = pauli.get_XZ_mask_representation(); + UINT global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); + Complex true_angle = angle * pauli.get_coef(); + const Complex cosval = Kokkos::cos(-true_angle / 2); + const Complex sinval = Kokkos::sin(-true_angle / 2); + if (bit_flip_mask == 0) { + const Complex cval_min = cosval - Complex(0, 1) * sinval; + const Complex cval_pls = cosval + Complex(0, 1) * sinval; + Kokkos::parallel_for( + state.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(UINT i) { + UINT state_idx = insert_zero_at_mask_positions(i, control_mask) | control_mask; + if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { + state._raw[state_idx] *= cval_min; + } else { + state._raw[state_idx] *= cval_pls; + } + }); + Kokkos::fence(); + return; + } else { + const UINT insert_idx = internal::BitVector(bit_flip_mask_vector).msb(); + Kokkos::parallel_for( + state.dim() >> (std::popcount(control_mask) + 1), KOKKOS_LAMBDA(UINT state_idx) { + UINT basis_0 = + internal::insert_zero_at_mask_positions(i, control_mask | 1ULL << pivot) | + control_mask; + UINT basis_1 = basis_0 ^ bit_flip_mask; + + int bit_parity_0 = Kokkos::popcount(basis_0 & phase_flip_mask) & 1; + int bit_parity_1 = Kokkos::popcount(basis_1 & phase_flip_mask) & 1; + + // fetch values + Complex cval_0 = state._raw[basis_0]; + Complex cval_1 = state._raw[basis_1]; + + // set values + state._raw[basis_0] = + cosval * cval_0 + + Complex(0, 1) * sinval * cval_1 * + PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_0 * 2) % 4]; + state._raw[basis_1] = + cosval * cval_1 + + Complex(0, 1) * sinval * cval_0 * + PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_1 * 2) % 4]; + }); + Kokkos::fence(); + } +} +} // namespace scaluq::internal diff --git a/scaluq/operator/apply_pauli.hpp b/scaluq/operator/apply_pauli.hpp new file mode 100644 index 00000000..413691d7 --- /dev/null +++ b/scaluq/operator/apply_pauli.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace scaluq::internal { +void apply_pauli(UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, StateVector& state); +void apply_pauli_rotation( + UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, double angle, StateVector& state); +} // namespace scaluq::internal diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 48486b41..617417f4 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -97,44 +97,6 @@ std::string PauliOperator::get_pauli_string() const { return res; } -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 " - "operator"); - } - UINT bit_flip_mask = _ptr->_bit_flip_mask; - UINT phase_flip_mask = _ptr->_phase_flip_mask; - Complex coef = get_coef(); - if (bit_flip_mask == 0) { - Kokkos::parallel_for( - state_vector.dim(), KOKKOS_LAMBDA(UINT state_idx) { - if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { - state_vector._raw[state_idx] *= -coef; - } else { - state_vector._raw[state_idx] *= coef; - } - }); - Kokkos::fence(); - return; - } - UINT pivot = sizeof(UINT) * 8 - std::countl_zero(bit_flip_mask) - 1; - UINT global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_M90ROT().val[global_phase_90rot_count % 4]; - Kokkos::parallel_for( - state_vector.dim() >> 1, KOKKOS_LAMBDA(UINT state_idx) { - UINT basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); - UINT basis_1 = basis_0 ^ bit_flip_mask; - Complex tmp1 = state_vector._raw[basis_0] * global_phase; - Complex tmp2 = state_vector._raw[basis_1] * global_phase; - if (Kokkos::popcount(basis_0 & phase_flip_mask) & 1) tmp2 = -tmp2; - if (Kokkos::popcount(basis_1 & phase_flip_mask) & 1) tmp1 = -tmp1; - state_vector._raw[basis_0] = tmp2 * coef; - state_vector._raw[basis_1] = tmp1 * coef; - }); - Kokkos::fence(); -} - Complex PauliOperator::get_expectation_value(const StateVector& state_vector) const { if (state_vector.n_qubits() < get_qubit_count()) { throw std::runtime_error( diff --git a/scaluq/operator/pauli_operator.hpp b/scaluq/operator/pauli_operator.hpp index 3f7ba5ba..de10affa 100644 --- a/scaluq/operator/pauli_operator.hpp +++ b/scaluq/operator/pauli_operator.hpp @@ -5,6 +5,7 @@ #include "../state/state_vector.hpp" #include "../types.hpp" +#include "apply_pauli.hpp" namespace scaluq { class PauliOperator { @@ -75,7 +76,14 @@ class PauliOperator { return std::ranges::max(_ptr->_target_qubit_list) + 1; } - void apply_to_state(StateVector& state_vector) const; + void 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 " + "operator"); + } + internal::apply_pauli(0ULL, _ptr->_bit_flip_mask, _ptr->_phase_flip_mask, state_vector); + } [[nodiscard]] Complex get_expectation_value(const StateVector& state_vector) const; [[nodiscard]] Complex get_transition_amplitude(const StateVector& state_vector_bra, From b22dfeac9d3fe85b908b9c0d54d53b7a1ddcc0ba Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 11:40:25 +0900 Subject: [PATCH 03/55] include --- scaluq/operator/apply_pauli.cpp | 5 +++++ scaluq/operator/apply_pauli.hpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/scaluq/operator/apply_pauli.cpp b/scaluq/operator/apply_pauli.cpp index fbb54616..312c1e46 100644 --- a/scaluq/operator/apply_pauli.cpp +++ b/scaluq/operator/apply_pauli.cpp @@ -1,5 +1,10 @@ #include "apply_pauli.hpp" +#include + +#include "../types.hpp" +#include "../util/utility.hpp" + namespace scaluq::internal { void apply_pauli(UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, StateVector& state) { Complex coef = get_coef(); diff --git a/scaluq/operator/apply_pauli.hpp b/scaluq/operator/apply_pauli.hpp index 413691d7..6ae00d18 100644 --- a/scaluq/operator/apply_pauli.hpp +++ b/scaluq/operator/apply_pauli.hpp @@ -1,5 +1,7 @@ #pragma once +#include "../state/state_vector.hpp" + namespace scaluq::internal { void apply_pauli(UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, StateVector& state); void apply_pauli_rotation( From 553bb52ca45cb4ea2e62911edc2445d9cf20254d Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 11:41:03 +0900 Subject: [PATCH 04/55] fix all --- scaluq/all.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scaluq/all.hpp b/scaluq/all.hpp index 4330187f..29ce45a5 100644 --- a/scaluq/all.hpp +++ b/scaluq/all.hpp @@ -8,6 +8,7 @@ #include "gate/param_gate.hpp" #include "gate/param_gate_factory.hpp" #include "gate/update_ops.hpp" +#include "operator/apply_sta.hpp" #include "operator/operator.hpp" #include "operator/pauli_operator.hpp" #include "state/state_vector.hpp" From 84dec24df008b13d7ffe30e4f316cd6fb84e8d36 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:05:06 +0900 Subject: [PATCH 05/55] fix apply_pauli --- scaluq/all.hpp | 2 +- scaluq/gate/gate_pauli.hpp | 5 +++-- scaluq/operator/apply_pauli.cpp | 19 +++++++++++++------ scaluq/operator/apply_pauli.hpp | 14 +++++++++++--- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/scaluq/all.hpp b/scaluq/all.hpp index 29ce45a5..f79a69a4 100644 --- a/scaluq/all.hpp +++ b/scaluq/all.hpp @@ -8,7 +8,7 @@ #include "gate/param_gate.hpp" #include "gate/param_gate_factory.hpp" #include "gate/update_ops.hpp" -#include "operator/apply_sta.hpp" +#include "operator/apply_pauli.hpp" #include "operator/operator.hpp" #include "operator/pauli_operator.hpp" #include "state/state_vector.hpp" diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index 1109b852..6eb8b4ef 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -25,7 +25,7 @@ class PauliGateImpl : public GateBase { void update_quantum_state(StateVector& state_vector) const override { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); - apply_pauli(_control_mask, bit_flip_mask, phase_flip_mask, state_vector); + apply_pauli(_control_mask, bit_flip_mask, phase_flip_mask, _pauli.get_coef(), state_vector); } }; @@ -57,7 +57,8 @@ class PauliRotationGateImpl : public GateBase { } void update_quantum_state(StateVector& state_vector) const override { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); - apply_pauli_rotation(_control_mask, bit_flip_mask, phase_flip_mask, _angle, state_vector); + apply_pauli_rotation( + _control_mask, bit_flip_mask, phase_flip_mask, _pauli.get_coef(), _angle, state_vector); } }; } // namespace internal diff --git a/scaluq/operator/apply_pauli.cpp b/scaluq/operator/apply_pauli.cpp index 312c1e46..3bf9d474 100644 --- a/scaluq/operator/apply_pauli.cpp +++ b/scaluq/operator/apply_pauli.cpp @@ -2,12 +2,16 @@ #include +#include "../constant.hpp" #include "../types.hpp" #include "../util/utility.hpp" namespace scaluq::internal { -void apply_pauli(UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, StateVector& state) { - Complex coef = get_coef(); +void apply_pauli(UINT control_mask, + UINT bit_flip_mask, + UINT phase_flip_mask, + Complex coef, + StateVector& state_vector) { if (bit_flip_mask == 0) { Kokkos::parallel_for( state_vector.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(UINT i) { @@ -38,11 +42,14 @@ void apply_pauli(UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, St }); Kokkos::fence(); } -void apply_pauli_rotation( - UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, double angle, StateVector& state) { - auto [bit_flip_mask, phase_flip_mask] = pauli.get_XZ_mask_representation(); +void apply_pauli_rotation(UINT control_mask, + UINT bit_flip_mask, + UINT phase_flip_mask, + Complex coef, + double angle, + StateVector& state_vector) { UINT global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex true_angle = angle * pauli.get_coef(); + Complex true_angle = angle * coef; const Complex cosval = Kokkos::cos(-true_angle / 2); const Complex sinval = Kokkos::sin(-true_angle / 2); if (bit_flip_mask == 0) { diff --git a/scaluq/operator/apply_pauli.hpp b/scaluq/operator/apply_pauli.hpp index 6ae00d18..713a24fc 100644 --- a/scaluq/operator/apply_pauli.hpp +++ b/scaluq/operator/apply_pauli.hpp @@ -3,7 +3,15 @@ #include "../state/state_vector.hpp" namespace scaluq::internal { -void apply_pauli(UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, StateVector& state); -void apply_pauli_rotation( - UINT control_mask, UINT bit_flip_mask, UINT phase_flip_mask, double angle, StateVector& state); +void apply_pauli(UINT control_mask, + UINT bit_flip_mask, + UINT phase_flip_mask, + Complex coef, + StateVector& state_vector); +void apply_pauli_rotation(UINT control_mask, + UINT bit_flip_mask, + UINT phase_flip_mask, + Complex coef, + double angle, + StateVector& state_vector); } // namespace scaluq::internal From ea6eb235b9edb039e4768cdf350434974753f304 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:13:02 +0900 Subject: [PATCH 06/55] fix pauli_operator, apply_pauli --- scaluq/operator/apply_pauli.cpp | 18 +++++++++--------- scaluq/operator/pauli_operator.hpp | 3 ++- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/scaluq/operator/apply_pauli.cpp b/scaluq/operator/apply_pauli.cpp index 3bf9d474..56d44c7e 100644 --- a/scaluq/operator/apply_pauli.cpp +++ b/scaluq/operator/apply_pauli.cpp @@ -56,20 +56,20 @@ void apply_pauli_rotation(UINT control_mask, const Complex cval_min = cosval - Complex(0, 1) * sinval; const Complex cval_pls = cosval + Complex(0, 1) * sinval; Kokkos::parallel_for( - state.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(UINT i) { + state_vector.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(UINT i) { UINT state_idx = insert_zero_at_mask_positions(i, control_mask) | control_mask; if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { - state._raw[state_idx] *= cval_min; + state_vector._raw[state_idx] *= cval_min; } else { - state._raw[state_idx] *= cval_pls; + state_vector._raw[state_idx] *= cval_pls; } }); Kokkos::fence(); return; } else { - const UINT insert_idx = internal::BitVector(bit_flip_mask_vector).msb(); + UINT pivot = sizeof(UINT) * 8 - std::countl_zero(bit_flip_mask) - 1; Kokkos::parallel_for( - state.dim() >> (std::popcount(control_mask) + 1), KOKKOS_LAMBDA(UINT state_idx) { + state_vector.dim() >> (std::popcount(control_mask) + 1), KOKKOS_LAMBDA(UINT state_idx) { UINT basis_0 = internal::insert_zero_at_mask_positions(i, control_mask | 1ULL << pivot) | control_mask; @@ -79,15 +79,15 @@ void apply_pauli_rotation(UINT control_mask, int bit_parity_1 = Kokkos::popcount(basis_1 & phase_flip_mask) & 1; // fetch values - Complex cval_0 = state._raw[basis_0]; - Complex cval_1 = state._raw[basis_1]; + Complex cval_0 = state_vector._raw[basis_0]; + Complex cval_1 = state_vector._raw[basis_1]; // set values - state._raw[basis_0] = + state_vector._raw[basis_0] = cosval * cval_0 + Complex(0, 1) * sinval * cval_1 * PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_0 * 2) % 4]; - state._raw[basis_1] = + state_vector._raw[basis_1] = cosval * cval_1 + Complex(0, 1) * sinval * cval_0 * PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_1 * 2) % 4]; diff --git a/scaluq/operator/pauli_operator.hpp b/scaluq/operator/pauli_operator.hpp index de10affa..70bb2e23 100644 --- a/scaluq/operator/pauli_operator.hpp +++ b/scaluq/operator/pauli_operator.hpp @@ -82,7 +82,8 @@ class PauliOperator { "PauliOperator::apply_to_state: n_qubits of state_vector is too small to apply the " "operator"); } - internal::apply_pauli(0ULL, _ptr->_bit_flip_mask, _ptr->_phase_flip_mask, state_vector); + internal::apply_pauli( + 0ULL, _ptr->_bit_flip_mask, _ptr->_phase_flip_mask, _ptr->_coef, state_vector); } [[nodiscard]] Complex get_expectation_value(const StateVector& state_vector) const; From c7594fd3504975c35a918f7bd96d88e16865713b Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:20:56 +0900 Subject: [PATCH 07/55] fix apply_to_pauli, operator --- scaluq/operator/apply_pauli.cpp | 2 +- scaluq/operator/operator.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scaluq/operator/apply_pauli.cpp b/scaluq/operator/apply_pauli.cpp index 56d44c7e..d330ab87 100644 --- a/scaluq/operator/apply_pauli.cpp +++ b/scaluq/operator/apply_pauli.cpp @@ -69,7 +69,7 @@ void apply_pauli_rotation(UINT control_mask, } else { UINT pivot = sizeof(UINT) * 8 - std::countl_zero(bit_flip_mask) - 1; Kokkos::parallel_for( - state_vector.dim() >> (std::popcount(control_mask) + 1), KOKKOS_LAMBDA(UINT state_idx) { + state_vector.dim() >> (std::popcount(control_mask) + 1), KOKKOS_LAMBDA(UINT i) { UINT basis_0 = internal::insert_zero_at_mask_positions(i, control_mask | 1ULL << pivot) | control_mask; diff --git a/scaluq/operator/operator.cpp b/scaluq/operator/operator.cpp index fcfb8e3d..a170e2c8 100644 --- a/scaluq/operator/operator.cpp +++ b/scaluq/operator/operator.cpp @@ -47,7 +47,7 @@ void Operator::add_random_operator(UINT operator_count, UINT seed) { } void Operator::optimize() { - std::map, Complex> pauli_and_coef; + std::map, Complex> pauli_and_coef; for (const auto& pauli : _terms) { pauli_and_coef[pauli.get_XZ_mask_representation()] += pauli.get_coef(); } @@ -92,12 +92,12 @@ Complex Operator::get_expectation_value(const StateVector& state_vector) const { Kokkos::DefaultHostExecutionSpace(), terms_view, bmasks_host, - [](const PauliOperator& pauli) { return pauli._ptr->_bit_flip_mask.data_raw()[0]; }); + [](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.data_raw()[0]; }); + [](const PauliOperator& pauli) { return pauli._ptr->_phase_flip_mask; }); Kokkos::Experimental::transform(Kokkos::DefaultHostExecutionSpace(), terms_view, coefs_host, @@ -164,11 +164,11 @@ Complex Operator::get_transition_amplitude(const StateVector& state_vector_bra, std::vector coefs_vector(nterms); std::transform( _terms.begin(), _terms.end(), bmasks_vector.begin(), [](const PauliOperator& pauli) { - return pauli._ptr->_bit_flip_mask.data_raw()[0]; + return pauli._ptr->_bit_flip_mask; }); std::transform( _terms.begin(), _terms.end(), pmasks_vector.begin(), [](const PauliOperator& pauli) { - return pauli._ptr->_phase_flip_mask.data_raw()[0]; + return pauli._ptr->_phase_flip_mask; }); std::transform( _terms.begin(), _terms.end(), coefs_vector.begin(), [](const PauliOperator& pauli) { From b435f3d6a2c8a17313226daedbea769a01967608 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:26:35 +0900 Subject: [PATCH 08/55] fix fix --- scaluq/gate/param_gate_pauli.hpp | 8 ++++++-- scaluq/operator/pauli_operator.cpp | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index faf3d507..d82834fe 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -34,8 +34,12 @@ class PPauliRotationGateImpl : public ParamGateBase { } void update_quantum_state(StateVector& state_vector, double param) const override { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); - apply_pauli_rotation( - _control_mask, bit_flip_mask, phase_flip_mask, _pcoef * param, state_vector); + apply_pauli_rotation(_control_mask, + bit_flip_mask, + phase_flip_mask, + _pauli.get_coef(), + _pcoef * param, + state_vector); } }; } // namespace internal diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 617417f4..bcfc8d63 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -50,7 +50,7 @@ PauliOperator::Data::Data(const std::vector& target_qubit_list, PauliOperator::Data::Data(UINT bit_flip_mask, UINT phase_flip_mask, Complex coef) : _coef(coef) { for (UINT target_idx = 0; target_idx < sizeof(UINT) * 8; target_idx++) { bool bit_flip = bit_flip_mask >> target_idx & 1; - bool phase_flip = bit_flip_mask >> target_idx & 1; + bool phase_flip = phase_flip_mask >> target_idx & 1; if (!bit_flip) { if (!phase_flip) continue; From aedbd12c8a061e522e7c1a8b5b9c29f462ac7ef7 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:34:02 +0900 Subject: [PATCH 09/55] fix binding --- python/binding.cpp | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/python/binding.cpp b/python/binding.cpp index 1ac1c250..ad322ab8 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -799,35 +799,14 @@ NB_MODULE(scaluq_core, m) { "coef"_a = 1., "Initialize pauli operator. For each `i`, single pauli correspond to " "`paul_id_per_qubit` is applied to `i`-th qubit.") - .def( - "__init__", - [](PauliOperator *t, - nb::int_ bit_flip_mask_py, - nb::int_ phase_flip_mask_py, - Complex coef) { - internal::BitVector bit_flip_mask(0), phase_flip_mask(0); - const nb::int_ mask(~0ULL); - auto &bit_flip_raw = bit_flip_mask.data_raw(); - assert(bit_flip_raw.empty()); - while (bit_flip_mask_py > nb::int_(0)) { - bit_flip_raw.push_back((UINT)nb::int_(bit_flip_mask_py & mask)); - bit_flip_mask_py >>= nb::int_(64); - } - auto &phase_flip_raw = phase_flip_mask.data_raw(); - assert(phase_flip_raw.empty()); - while (phase_flip_mask_py > nb::int_(0)) { - phase_flip_raw.push_back((UINT)nb::int_(phase_flip_mask_py & mask)); - phase_flip_mask_py >>= nb::int_(64); - } - new (t) PauliOperator(bit_flip_mask, phase_flip_mask, coef); - }, - "bit_flip_mask"_a, - "phase_flip_mask"_a, - "coef"_a = 1., - "Initialize pauli operator. For each `i`, single pauli applied to `i`-th qubit is got " - "from `i-th` bit of `bit_flip_mask` and `phase_flip_mask` as follows.\n\n.. " - "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(nb::init(), + "bit_flip_mask"_a, + "phase_flip_mask"_a, + "coef"_a = 1., + "Initialize pauli operator. For each `i`, single pauli applied to `i`-th qubit is got " + "from `i-th` bit of `bit_flip_mask` and `phase_flip_mask` as follows.\n\n.. " + "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("get_coef", &PauliOperator::get_coef, "Get property `coef`.") .def("get_target_qubit_list", &PauliOperator::get_target_qubit_list, From 71bac9207071d1f9fb9a9b225c52bf0f6315fe3a Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:38:48 +0900 Subject: [PATCH 10/55] fix binding --- python/binding.cpp | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/python/binding.cpp b/python/binding.cpp index ad322ab8..1ca90ccd 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -815,23 +815,11 @@ NB_MODULE(scaluq_core, m) { &PauliOperator::get_pauli_id_list, "Get pauli id to be applied. The order is correspond to the result of " "`get_target_qubit_list`") - .def( - "get_XZ_mask_representation", - [](const PauliOperator &pauli) { - const auto [x_mask, z_mask] = pauli.get_XZ_mask_representation(); - nb::int_ x_mask_py(0); - for (UINT i = 0; i < x_mask.size(); ++i) { - x_mask_py |= nb::int_(x_mask[i]) << nb::int_(i); - } - nb::int_ z_mask_py(0); - for (UINT i = 0; i < z_mask.size(); ++i) { - z_mask_py |= nb::int_(z_mask[i]) << nb::int_(i); - } - return std::make_tuple(x_mask_py, z_mask_py); - }, - "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_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, "Get single-pauli property as string representation. See description of " From 6d55c7ca5a36170282117de06515055fc0693a4e Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:39:01 +0900 Subject: [PATCH 11/55] add gate control test --- tests/gate/gate_test.cpp | 142 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index dd1ea1c4..22ac80fe 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -397,3 +397,145 @@ TEST(GateTest, ApplyProbablisticGate) { ASSERT_GT(i_cnt, 0); ASSERT_LT(x_cnt, i_cnt); } + +void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_mask) { + StateVector state = StateVector::Haar_random_state(n_qubits); + auto amplitudes = state.amplitudes(); + StateVector state_controlled(n_qubits - std::popcount(control_mask)); + std::vector amplitudes_controlled(state_controlled.dim()); + for (UINT i : std::views::iota(0ULL, state_controlled.dim())) { + amplitudes_controlled[i] = + amplitudes[internal::insert_zero_at_mask_positions(i, control_mask)]; + } + state_controlled.load(amplitudes_controlled); + gate_control->update_quantum_state(state); + gate_simple->update_quantum_state(state_controlled); + amplitudes = state.amplitudes(); + amplitudes_controlled = state_controlled.amplitudes(); + for (UINT i : std::views::iota(0ULL, state_controlled.dim())) { + ASSERT_NEAR( + Kokkos::abs(amplitudes_controlled[i] - + amplitudes[internal::insert_zero_at_mask_positions(i, control_mask)]), + 0., + eps); + } +} + +template +void test_standard_gates(auto factory, UINT n) { + Random random; + UINT targets = std::vector(num_target); + for (UINT i : std::views::iota(0ULL, num_target)) { + targets[i] = random.int32() % (n - i); + for (UINT j : std::views::iota(0ULL, i)) { + if (targets[i] == targets[j]) targets[i] = n - 1 - j; + } + } + UINT num_control = random.int32() % (n - num_target + 1); + std::vector controls(num_control); + for (UINT i : std::views::iota(0ULL, num_control)) { + controls[i] = random.int32() % (n - num_target - i); + for (UINT j : std::views::iota(num_target)) { + if (controls[i] == targets[j]) controls[i] = n - 1 - j; + } + for (UINT j : std::views::iota(0ULL, i)) { + if (controls[i] == controls[j]) controls[i] = n - num_target - 1 - j; + } + } + UINT control_mask = 0ULL; + for (UINT c : controls) control_mask |= 1ULL << c; + std::vector angles(num_rotation); + for (double& angle : angles) angle = random.uniform() * PI() * 2; + if constexpr (num_target == 0 && num_rotation == 1) { + Gate g1 = factory(angles[0], control_mask); + Gate g2 = factory(angles[0]); + test_gate(g1, g2, n, control_mask); + } else if constexpr (num_target == 1 && num_rotation == 0) { + Gate g1 = factory(targets[0], control_mask); + Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1))); + test_gate(g1, g2, n, control_mask); + } else if constexpr (num_target == 1 && num_rotation == 1) { + Gate g1 = factory(targets[0], angles[0], control_mask); + Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), + angles[0]); + test_gate(g1, g2, n, control_mask); + } else if constexpr (num_target == 1 && num_rotation == 2) { + Gate g1 = factory(targets[0], angles[0], angles[1], control_mask); + Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), + angles[0], + angles[1]); + test_gate(g1, g2, n, control_mask); + } else if constexpr (num_target == 1 && num_rotation == 3) { + Gate g1 = factory(targets[0], angles[0], angles[1], angles[2] control_mask); + Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), + angles[0], + angles[1], + angles[2]); + test_gate(g1, g2, n, control_mask); + } else if constexpr (num_target == 2 && num_rotation == 0) { + Gate g1 = factory(targets[0], targets[1], control_mask); + Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), + targets[1] - std::popcount(control_mask & ((1ULL << targets[1]) - 1)), + control_mask); + test_gate(g1, g2, n, control_mask); + } else { + static_assert(false); + } +} + +template +void test_pauli_control(UINT n) { + PauliOperator::Data data1, data2; + UINT control_mask = 0; + UINT num_control = 0; + Random random; + for (UINT i : std::views::iota(0ULL, n)) { + UINT dat = random.int32() % 12; + if (dat < 4) { + data1.add_single_pauli(i, dat); + data2.add_single_pauli(i - num_control, dat); + } else if (dat < 8) { + control_mask |= 1ULL << i; + num_control++; + } + } + if constexpr (!rotation) { + Gate g1 = gate::Pauli(PauliOperator(data1), control_mask); + Gate g2 = gate::Pauli(PauliOperator(data2)); + test_gate(g1, g2, n, control_mask); + } else { + double angle = random.uniform() * PI() * 2; + Gate g1 = gate::PauliRotation(PauliOperator(data1), angle, control_mask); + Gate g2 = gate::PauliRotation(PauliOperator(data2), angle); + test_gate(g1, g2, n, control_mask); + } +} + +TEST(GateTest, Control) { + UINT n = 10; + for (UINT _ : std::views::iota(0, 10)) { + test_standard_gates<0, 1>(gate::GlobalPhase, n); + test_standard_gates<1, 0>(gate::X, n); + test_standard_gates<1, 0>(gate::Y, n); + test_standard_gates<1, 0>(gate::Z, n); + test_standard_gates<1, 0>(gate::S, n); + test_standard_gates<1, 0>(gate::Sdag, n); + test_standard_gates<1, 0>(gate::T, n); + test_standard_gates<1, 0>(gate::Tdag, n); + test_standard_gates<1, 0>(gate::SqrtX, n); + test_standard_gates<1, 0>(gate::SqrtXdag, n); + test_standard_gates<1, 0>(gate::SqrtY, n); + test_standard_gates<1, 0>(gate::SqrtYdag, n); + test_standard_gates<1, 0>(gate::P0, n); + test_standard_gates<1, 0>(gate::P1, n); + test_standard_gates<1, 1>(gate::RX, n); + test_standard_gates<1, 1>(gate::RY, n); + test_standard_gates<1, 1>(gate::RZ, n); + test_standard_gates<1, 1>(gate::U1, n); + test_standard_gates<1, 2>(gate::U2, n); + test_standard_gates<1, 3>(gate::U3, n); + test_standard_gates<2, 0>(gate::Swap, n); + test_pauli_control(n); + test_pauli_control(n); + } +} From 6ce48a6ab81b8c53a182bc6cdcc1e580fbe07488 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:44:10 +0900 Subject: [PATCH 12/55] fix binding XZ_mask --- python/binding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/binding.cpp b/python/binding.cpp index 1ca90ccd..1f4af7cf 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -816,7 +816,7 @@ NB_MODULE(scaluq_core, m) { "Get pauli id to be applied. The order is correspond to the result of " "`get_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.") From c77bf4513e7cafb3bc73738583dff4dcab0ee29f Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:47:50 +0900 Subject: [PATCH 13/55] fix PauliOperator::Data init --- python/binding.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/binding.cpp b/python/binding.cpp index 1f4af7cf..b08b4690 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -747,7 +747,7 @@ NB_MODULE(scaluq_core, m) { "pauli_id_par_qubit"_a, "coef"_a = 1., "Initialize data with pauli ids per qubit.") - .def(nb::init &, const std::vector &, Complex>(), + .def(nb::init(), "bit_flip_mask"_a, "phase_flip_mask"_a, "coef"_a = 1., From 841fe3c63a198e22a98caa4442b05db9cd2c56b9 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 12:55:48 +0900 Subject: [PATCH 14/55] fix some tests --- tests/gate/gate_test.cpp | 18 +++++++++--------- tests/operator/test_operator.cpp | 2 +- tests/operator/test_pauli_operator.cpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 22ac80fe..cdc9b804 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -424,7 +424,7 @@ void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_ template void test_standard_gates(auto factory, UINT n) { Random random; - UINT targets = std::vector(num_target); + std::vector targets(num_target); for (UINT i : std::views::iota(0ULL, num_target)) { targets[i] = random.int32() % (n - i); for (UINT j : std::views::iota(0ULL, i)) { @@ -447,33 +447,33 @@ void test_standard_gates(auto factory, UINT n) { std::vector angles(num_rotation); for (double& angle : angles) angle = random.uniform() * PI() * 2; if constexpr (num_target == 0 && num_rotation == 1) { - Gate g1 = factory(angles[0], control_mask); + Gate g1 = factory(angles[0], controls); Gate g2 = factory(angles[0]); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 0) { - Gate g1 = factory(targets[0], control_mask); + Gate g1 = factory(targets[0], controls); Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1))); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 1) { - Gate g1 = factory(targets[0], angles[0], control_mask); + Gate g1 = factory(targets[0], angles[0], controls); Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), angles[0]); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 2) { - Gate g1 = factory(targets[0], angles[0], angles[1], control_mask); + Gate g1 = factory(targets[0], angles[0], angles[1], controls); Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), angles[0], angles[1]); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 3) { - Gate g1 = factory(targets[0], angles[0], angles[1], angles[2] control_mask); + Gate g1 = factory(targets[0], angles[0], angles[1], angles[2], controls); Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), angles[0], angles[1], angles[2]); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 2 && num_rotation == 0) { - Gate g1 = factory(targets[0], targets[1], control_mask); + Gate g1 = factory(targets[0], targets[1], controls); Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), targets[1] - std::popcount(control_mask & ((1ULL << targets[1]) - 1)), control_mask); @@ -500,12 +500,12 @@ void test_pauli_control(UINT n) { } } if constexpr (!rotation) { - Gate g1 = gate::Pauli(PauliOperator(data1), control_mask); + Gate g1 = gate::Pauli(PauliOperator(data1), controls); Gate g2 = gate::Pauli(PauliOperator(data2)); test_gate(g1, g2, n, control_mask); } else { double angle = random.uniform() * PI() * 2; - Gate g1 = gate::PauliRotation(PauliOperator(data1), angle, control_mask); + Gate g1 = gate::PauliRotation(PauliOperator(data1), angle, controls); Gate g2 = gate::PauliRotation(PauliOperator(data2), angle); test_gate(g1, g2, n, control_mask); } diff --git a/tests/operator/test_operator.cpp b/tests/operator/test_operator.cpp index bbfe4898..771a826e 100644 --- a/tests/operator/test_operator.cpp +++ b/tests/operator/test_operator.cpp @@ -150,7 +150,7 @@ TEST(OperatorTest, ApplyToStateTest) { }()); Operator op(n_qubits); - op.add_operator({std::vector{1, 0, 0}, std::vector{0, 1, 0}, Complex(2)}); + op.add_operator({0b001, 0b010, Complex(2)}); op.add_operator({"X 2 Y 1", 1}); op.apply_to_state(state_vector); diff --git a/tests/operator/test_pauli_operator.cpp b/tests/operator/test_pauli_operator.cpp index 6a1be45a..55d291fb 100644 --- a/tests/operator/test_pauli_operator.cpp +++ b/tests/operator/test_pauli_operator.cpp @@ -187,7 +187,7 @@ TEST(PauliOperatorTest, ApplyToStateTest) { return tmp; }()); - PauliOperator op(std::vector{1, 0, 0}, std::vector{0, 1, 0}, Complex(2)); + PauliOperator op(0b001, 0b010, Complex(2)); op.apply_to_state(state_vector); std::vector expected = {2, 0, -6, -4, 10, 8, -14, -12}; ASSERT_EQ(state_vector.amplitudes(), expected); From b0a8de23e4a1e3523616fa2e143e9f495ebe0995 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 13:03:13 +0900 Subject: [PATCH 15/55] fix gate test --- tests/gate/gate_test.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index cdc9b804..5ab86e88 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -448,44 +448,48 @@ void test_standard_gates(auto factory, UINT n) { for (double& angle : angles) angle = random.uniform() * PI() * 2; if constexpr (num_target == 0 && num_rotation == 1) { Gate g1 = factory(angles[0], controls); - Gate g2 = factory(angles[0]); + Gate g2 = factory(angles[0], {}); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 0) { Gate g1 = factory(targets[0], controls); - Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1))); + Gate g2 = + factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), {}); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 1) { Gate g1 = factory(targets[0], angles[0], controls); - Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), - angles[0]); + Gate g2 = factory( + targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), angles[0], {}); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 2) { Gate g1 = factory(targets[0], angles[0], angles[1], controls); Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), angles[0], - angles[1]); + angles[1], + {}); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 3) { Gate g1 = factory(targets[0], angles[0], angles[1], angles[2], controls); Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), angles[0], angles[1], - angles[2]); + angles[2], + {}); test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 2 && num_rotation == 0) { Gate g1 = factory(targets[0], targets[1], controls); Gate g2 = factory(targets[0] - std::popcount(control_mask & ((1ULL << targets[0]) - 1)), targets[1] - std::popcount(control_mask & ((1ULL << targets[1]) - 1)), - control_mask); + {}); test_gate(g1, g2, n, control_mask); } else { - static_assert(false); + FAIL(); } } template void test_pauli_control(UINT n) { PauliOperator::Data data1, data2; + std::vector controls; UINT control_mask = 0; UINT num_control = 0; Random random; @@ -495,25 +499,26 @@ void test_pauli_control(UINT n) { data1.add_single_pauli(i, dat); data2.add_single_pauli(i - num_control, dat); } else if (dat < 8) { + controls.push_back(i); control_mask |= 1ULL << i; num_control++; } } if constexpr (!rotation) { Gate g1 = gate::Pauli(PauliOperator(data1), controls); - Gate g2 = gate::Pauli(PauliOperator(data2)); + Gate g2 = gate::Pauli(PauliOperator(data2), {}); test_gate(g1, g2, n, control_mask); } else { double angle = random.uniform() * PI() * 2; Gate g1 = gate::PauliRotation(PauliOperator(data1), angle, controls); - Gate g2 = gate::PauliRotation(PauliOperator(data2), angle); + Gate g2 = gate::PauliRotation(PauliOperator(data2), angle, {}); test_gate(g1, g2, n, control_mask); } } TEST(GateTest, Control) { UINT n = 10; - for (UINT _ : std::views::iota(0, 10)) { + for ([[maybe_unused]] UINT _ : std::views::iota(0, 10)) { test_standard_gates<0, 1>(gate::GlobalPhase, n); test_standard_gates<1, 0>(gate::X, n); test_standard_gates<1, 0>(gate::Y, n); From f21060ea821e03b4293b8ad18960d736c479ebe0 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 16:55:06 +0900 Subject: [PATCH 16/55] fix PauliOperator::Data constructor --- scaluq/operator/pauli_operator.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index bcfc8d63..b05d1578 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -6,7 +6,8 @@ namespace scaluq { PauliOperator::Data::Data(Complex coef) : _coef(coef), _bit_flip_mask(0), _phase_flip_mask(0) {} -PauliOperator::Data::Data(std::string_view pauli_string, Complex coef) : _coef(coef) { +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) { char pauli; @@ -28,7 +29,8 @@ PauliOperator::Data::Data(std::string_view pauli_string, Complex coef) : _coef(c } } -PauliOperator::Data::Data(const std::vector& pauli_id_par_qubit, Complex coef) : _coef(coef) { +PauliOperator::Data::Data(const std::vector& pauli_id_par_qubit, Complex coef) + : _coef(coef), _bit_flip_mask(0), _phase_flip_mask(0) { for (UINT i = 0; i < pauli_id_par_qubit.size(); ++i) { add_single_pauli(i, pauli_id_par_qubit[i]); } @@ -37,7 +39,7 @@ PauliOperator::Data::Data(const std::vector& pauli_id_par_qubit, Complex c PauliOperator::Data::Data(const std::vector& target_qubit_list, const std::vector& pauli_id_list, Complex coef) - : _coef(coef) { + : _coef(coef), _bit_flip_mask(0), _phase_flip_mask(0) { if (target_qubit_list.size() != pauli_id_list.size()) { throw std::runtime_error( "PauliOperator::PauliOperator: target_qubit_list must have same size to pauli_id_list"); @@ -47,7 +49,8 @@ PauliOperator::Data::Data(const std::vector& target_qubit_list, } } -PauliOperator::Data::Data(UINT bit_flip_mask, UINT phase_flip_mask, Complex coef) : _coef(coef) { +PauliOperator::Data::Data(UINT bit_flip_mask, UINT phase_flip_mask, Complex coef) + : _coef(coef), _bit_flip_mask(0), _phase_flip_mask(0) { for (UINT target_idx = 0; target_idx < sizeof(UINT) * 8; target_idx++) { bool bit_flip = bit_flip_mask >> target_idx & 1; bool phase_flip = phase_flip_mask >> target_idx & 1; From 674c12ec4daa863f3fdb543e6192c4a66562dbcf Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 17:21:46 +0900 Subject: [PATCH 17/55] pauli target is under 64 --- scaluq/operator/pauli_operator.cpp | 6 ++++++ tests/operator/test_pauli_operator.cpp | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index b05d1578..71b9210d 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -70,6 +70,12 @@ PauliOperator::Data::Data(UINT bit_flip_mask, UINT phase_flip_mask, Complex coef } void PauliOperator::Data::add_single_pauli(UINT target_qubit, UINT pauli_id) { + if(target_qubit >= sizeof(UINT) * 8) { + throw std::runtime_error("PauliOperator::Data::add_single_pauli: target_qubit is too large"); + } + if(pauli_id >= 4) { + throw std::runtime_error("PauliOperator::Data::add_single_pauli: pauli_id is invalid"); + } _target_qubit_list.push_back(target_qubit); _pauli_id_list.push_back(pauli_id); if ((_bit_flip_mask | _phase_flip_mask) >> target_qubit & 1) { diff --git a/tests/operator/test_pauli_operator.cpp b/tests/operator/test_pauli_operator.cpp index 55d291fb..618b9370 100644 --- a/tests/operator/test_pauli_operator.cpp +++ b/tests/operator/test_pauli_operator.cpp @@ -154,7 +154,7 @@ INSTANTIATE_TEST_CASE_P( PauliOperatorMultiplyTest, []() { double coef = 2.0; - UINT MAX_TERM = 100; + UINT MAX_TERM = 64; std::string pauli_string_x = ""; std::string pauli_string_y = ""; std::string pauli_string_z = ""; From 3fbcf6c960b6e96c1c5403b2f8e1063cc9d72422 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 17:24:19 +0900 Subject: [PATCH 18/55] format --- scaluq/operator/pauli_operator.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 71b9210d..fe33c6b5 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -70,10 +70,11 @@ PauliOperator::Data::Data(UINT bit_flip_mask, UINT phase_flip_mask, Complex coef } void PauliOperator::Data::add_single_pauli(UINT target_qubit, UINT pauli_id) { - if(target_qubit >= sizeof(UINT) * 8) { - throw std::runtime_error("PauliOperator::Data::add_single_pauli: target_qubit is too large"); + if (target_qubit >= sizeof(UINT) * 8) { + throw std::runtime_error( + "PauliOperator::Data::add_single_pauli: target_qubit is too large"); } - if(pauli_id >= 4) { + if (pauli_id >= 4) { throw std::runtime_error("PauliOperator::Data::add_single_pauli: pauli_id is invalid"); } _target_qubit_list.push_back(target_qubit); From 7207dcd706b0601f9fcb6ca0ee6c4ffe4306d37b Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 17:32:30 +0900 Subject: [PATCH 19/55] factory template type --- tests/gate/gate_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 5ab86e88..3315dc72 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -421,8 +421,8 @@ void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_ } } -template -void test_standard_gates(auto factory, UINT n) { +template +void test_standard_gates(Factory factory, UINT n) { Random random; std::vector targets(num_target); for (UINT i : std::views::iota(0ULL, num_target)) { From e5f9a719f027cfcca7d62f99ac7070296329646f Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 17:47:32 +0900 Subject: [PATCH 20/55] dbg --- tests/gate/gate_test.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 3315dc72..84a526a3 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -399,6 +399,7 @@ TEST(GateTest, ApplyProbablisticGate) { } void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_mask) { + std::cerr << "test_gate" << std::endl; StateVector state = StateVector::Haar_random_state(n_qubits); auto amplitudes = state.amplitudes(); StateVector state_controlled(n_qubits - std::popcount(control_mask)); @@ -423,9 +424,11 @@ void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_ template void test_standard_gates(Factory factory, UINT n) { + std::cerr << "test_standard_gates" << std::endl; Random random; std::vector targets(num_target); for (UINT i : std::views::iota(0ULL, num_target)) { + std::cerr << "target: " << i << std::endl; targets[i] = random.int32() % (n - i); for (UINT j : std::views::iota(0ULL, i)) { if (targets[i] == targets[j]) targets[i] = n - 1 - j; @@ -434,6 +437,7 @@ void test_standard_gates(Factory factory, UINT n) { UINT num_control = random.int32() % (n - num_target + 1); std::vector controls(num_control); for (UINT i : std::views::iota(0ULL, num_control)) { + std::cerr << "control: " << i << std::endl; controls[i] = random.int32() % (n - num_target - i); for (UINT j : std::views::iota(num_target)) { if (controls[i] == targets[j]) controls[i] = n - 1 - j; @@ -444,11 +448,16 @@ void test_standard_gates(Factory factory, UINT n) { } UINT control_mask = 0ULL; for (UINT c : controls) control_mask |= 1ULL << c; + std::cerr << "preparing angles" << std::endl; std::vector angles(num_rotation); for (double& angle : angles) angle = random.uniform() * PI() * 2; + std::cerr << "prepared angles" << std::endl; if constexpr (num_target == 0 && num_rotation == 1) { + std::cerr << "gate 0" << std::endl; Gate g1 = factory(angles[0], controls); + std::cerr << "gate 1" << std::endl; Gate g2 = factory(angles[0], {}); + std::cerr << "gate 2" << std::endl; test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 0) { Gate g1 = factory(targets[0], controls); From 90c9334e9ba18d3aeba2479bcb89fc9fe1f5ae66 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 17:51:47 +0900 Subject: [PATCH 21/55] fix iota argument --- tests/gate/gate_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 84a526a3..2ce5049f 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -439,7 +439,7 @@ void test_standard_gates(Factory factory, UINT n) { for (UINT i : std::views::iota(0ULL, num_control)) { std::cerr << "control: " << i << std::endl; controls[i] = random.int32() % (n - num_target - i); - for (UINT j : std::views::iota(num_target)) { + for (UINT j : std::views::iota(0ULL, num_target)) { if (controls[i] == targets[j]) controls[i] = n - 1 - j; } for (UINT j : std::views::iota(0ULL, i)) { From 4600aa5e5802b4b456c1105462920e5e1ac490e1 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 18:02:31 +0900 Subject: [PATCH 22/55] fix test_gate --- tests/gate/gate_test.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 2ce5049f..3711ab90 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -399,14 +399,13 @@ TEST(GateTest, ApplyProbablisticGate) { } void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_mask) { - std::cerr << "test_gate" << std::endl; StateVector state = StateVector::Haar_random_state(n_qubits); auto amplitudes = state.amplitudes(); StateVector state_controlled(n_qubits - std::popcount(control_mask)); std::vector amplitudes_controlled(state_controlled.dim()); for (UINT i : std::views::iota(0ULL, state_controlled.dim())) { amplitudes_controlled[i] = - amplitudes[internal::insert_zero_at_mask_positions(i, control_mask)]; + amplitudes[internal::insert_zero_at_mask_positions(i, control_mask) | control_mask]; } state_controlled.load(amplitudes_controlled); gate_control->update_quantum_state(state); @@ -416,7 +415,8 @@ void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_ for (UINT i : std::views::iota(0ULL, state_controlled.dim())) { ASSERT_NEAR( Kokkos::abs(amplitudes_controlled[i] - - amplitudes[internal::insert_zero_at_mask_positions(i, control_mask)]), + amplitudes[internal::insert_zero_at_mask_positions(i, control_mask) | + control_mask]), 0., eps); } @@ -424,11 +424,9 @@ void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_ template void test_standard_gates(Factory factory, UINT n) { - std::cerr << "test_standard_gates" << std::endl; Random random; std::vector targets(num_target); for (UINT i : std::views::iota(0ULL, num_target)) { - std::cerr << "target: " << i << std::endl; targets[i] = random.int32() % (n - i); for (UINT j : std::views::iota(0ULL, i)) { if (targets[i] == targets[j]) targets[i] = n - 1 - j; @@ -437,7 +435,6 @@ void test_standard_gates(Factory factory, UINT n) { UINT num_control = random.int32() % (n - num_target + 1); std::vector controls(num_control); for (UINT i : std::views::iota(0ULL, num_control)) { - std::cerr << "control: " << i << std::endl; controls[i] = random.int32() % (n - num_target - i); for (UINT j : std::views::iota(0ULL, num_target)) { if (controls[i] == targets[j]) controls[i] = n - 1 - j; @@ -448,16 +445,11 @@ void test_standard_gates(Factory factory, UINT n) { } UINT control_mask = 0ULL; for (UINT c : controls) control_mask |= 1ULL << c; - std::cerr << "preparing angles" << std::endl; std::vector angles(num_rotation); for (double& angle : angles) angle = random.uniform() * PI() * 2; - std::cerr << "prepared angles" << std::endl; if constexpr (num_target == 0 && num_rotation == 1) { - std::cerr << "gate 0" << std::endl; Gate g1 = factory(angles[0], controls); - std::cerr << "gate 1" << std::endl; Gate g2 = factory(angles[0], {}); - std::cerr << "gate 2" << std::endl; test_gate(g1, g2, n, control_mask); } else if constexpr (num_target == 1 && num_rotation == 0) { Gate g1 = factory(targets[0], controls); From 5ed915f2e9e09a29560df6a5aab9924a72277f4e Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 9 Aug 2024 18:02:42 +0900 Subject: [PATCH 23/55] fix PauliOperator multiply --- scaluq/operator/pauli_operator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index fe33c6b5..b3a25638 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -229,12 +229,12 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ PauliOperator PauliOperator::operator*(const PauliOperator& target) const { int extra_90rot_cnt = 0; - auto x_left = _ptr->_bit_flip_mask - _ptr->_phase_flip_mask; + auto x_left = _ptr->_bit_flip_mask & ~_ptr->_phase_flip_mask; auto y_left = _ptr->_bit_flip_mask & _ptr->_phase_flip_mask; - auto z_left = _ptr->_phase_flip_mask - _ptr->_bit_flip_mask; - auto x_right = target._ptr->_bit_flip_mask - target._ptr->_phase_flip_mask; + auto z_left = _ptr->_phase_flip_mask & ~_ptr->_bit_flip_mask; + auto x_right = target._ptr->_bit_flip_mask & ~target._ptr->_phase_flip_mask; auto y_right = target._ptr->_bit_flip_mask & target._ptr->_phase_flip_mask; - auto z_right = target._ptr->_phase_flip_mask - target._ptr->_bit_flip_mask; + auto z_right = target._ptr->_phase_flip_mask & ~target._ptr->_bit_flip_mask; extra_90rot_cnt += std::popcount(x_left & y_right); // XY = iZ extra_90rot_cnt += std::popcount(y_left & z_right); // YZ = iX extra_90rot_cnt += std::popcount(z_left & x_right); // ZX = iY From 0f1bbcc39bbda69c436073037ebbef5247eeb364 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 27 Aug 2024 01:26:54 +0000 Subject: [PATCH 24/55] change method name --- python/binding.cpp | 76 +++++++++++------------ scaluq/circuit/circuit.cpp | 16 ++--- scaluq/circuit/circuit.hpp | 2 +- scaluq/gate/gate.hpp | 14 ++--- scaluq/gate/gate_factory.hpp | 2 +- scaluq/gate/gate_pauli.hpp | 11 ++-- scaluq/gate/gate_probablistic.hpp | 24 +++---- scaluq/gate/merge_gate.cpp | 32 +++++----- scaluq/gate/param_gate.hpp | 14 ++--- scaluq/gate/param_gate_pauli.hpp | 6 +- scaluq/gate/param_gate_probablistic.hpp | 24 +++---- scaluq/gate/update_ops_pauli.cpp | 2 +- scaluq/operator/operator.cpp | 8 +-- scaluq/operator/pauli_operator.cpp | 2 +- scaluq/operator/pauli_operator.hpp | 16 ++--- scaluq/state/state_vector.cpp | 4 +- scaluq/state/state_vector.hpp | 4 +- scaluq/state/state_vector_batched.cpp | 2 +- scaluq/state/state_vector_batched.hpp | 2 +- tests/circuit/circuit_test.cpp | 8 +-- tests/circuit/param_circuit_test.cpp | 10 +-- tests/gate/gate_test.cpp | 44 ++++++------- tests/gate/param_gate_test.cpp | 16 ++--- tests/operator/test_operator.cpp | 10 +-- tests/operator/test_pauli_operator.cpp | 16 ++--- tests/state/state_vector_batched_test.cpp | 2 +- tests/state/state_vector_test.cpp | 28 ++++----- tests/util/util.hpp | 8 +-- 28 files changed, 197 insertions(+), 206 deletions(-) diff --git a/python/binding.cpp b/python/binding.cpp index 1ac1c250..5bed3c9d 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -112,7 +112,7 @@ NB_MODULE(scaluq_core, m) { &StateVector::get_amplitude_at_index, "Get amplitude at one index.\n\n.. note:: If you want to get all amplitudes, you " "should " - "use `StateVector::amplitudes()`.") + "use `StateVector::get_amplitudes()`.") .def("set_zero_state", &StateVector::set_zero_state, "Initialize with computational basis $\\ket{00\\dots0}$.") @@ -296,28 +296,28 @@ NB_MODULE(scaluq_core, m) { nb::class_(m, #GATE_TYPE, DESCRIPTION) \ .def("gate_type", &GATE_TYPE::gate_type, "Get gate type as `GateType` enum.") \ .def( \ - "get_target_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->get_target_qubit_list(); }, \ + "target_qubit_list", \ + [](const GATE_TYPE &gate) { return gate->target_qubit_list(); }, \ "Get target qubits as `list[int]`. **Control qubits is not included.**") \ .def( \ - "get_control_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->get_control_qubit_list(); }, \ + "control_qubit_list", \ + [](const GATE_TYPE &gate) { return gate->control_qubit_list(); }, \ "Get control qubits as `list[int]`.") \ .def( \ - "get_operand_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->get_operand_qubit_list(); }, \ + "operand_qubit_list", \ + [](const GATE_TYPE &gate) { return gate->operand_qubit_list(); }, \ "Get target and control qubits as `list[int]`.") \ .def( \ - "get_target_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->get_target_qubit_mask(); }, \ + "target_qubit_mask", \ + [](const GATE_TYPE &gate) { return gate->target_qubit_mask(); }, \ "Get target qubits as mask. **Control qubits is not included.**") \ .def( \ - "get_control_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->get_control_qubit_mask(); }, \ + "control_qubit_mask", \ + [](const GATE_TYPE &gate) { return gate->control_qubit_mask(); }, \ "Get control qubits as mask.") \ .def( \ - "get_operand_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->get_operand_qubit_mask(); }, \ + "operand_qubit_mask", \ + [](const GATE_TYPE &gate) { return gate->operand_qubit_mask(); }, \ "Get target and control qubits as mask.") \ .def( \ "get_inverse", \ @@ -552,28 +552,28 @@ NB_MODULE(scaluq_core, m) { &PGATE_TYPE::param_gate_type, \ "Get parametric gate type as `ParamGateType` enum.") \ .def( \ - "get_target_qubit_list", \ - [](const PGATE_TYPE &gate) { return gate->get_target_qubit_list(); }, \ + "target_qubit_list", \ + [](const PGATE_TYPE &gate) { return gate->target_qubit_list(); }, \ "Get target qubits as `list[int]`. **Control qubits is not included.**") \ .def( \ - "get_control_qubit_list", \ - [](const PGATE_TYPE &gate) { return gate->get_control_qubit_list(); }, \ + "control_qubit_list", \ + [](const PGATE_TYPE &gate) { return gate->control_qubit_list(); }, \ "Get control qubits as `list[int]`.") \ .def( \ - "get_operand_qubit_list", \ - [](const PGATE_TYPE &gate) { return gate->get_operand_qubit_list(); }, \ + "operand_qubit_list", \ + [](const PGATE_TYPE &gate) { return gate->operand_qubit_list(); }, \ "Get target and control qubits as `list[int]`.") \ .def( \ - "get_target_qubit_mask", \ - [](const PGATE_TYPE &gate) { return gate->get_target_qubit_mask(); }, \ + "target_qubit_mask", \ + [](const PGATE_TYPE &gate) { return gate->target_qubit_mask(); }, \ "Get target qubits as mask. **Control qubits is not included.**") \ .def( \ - "get_control_qubit_mask", \ - [](const PGATE_TYPE &gate) { return gate->get_control_qubit_mask(); }, \ + "control_qubit_mask", \ + [](const PGATE_TYPE &gate) { return gate->control_qubit_mask(); }, \ "Get control qubits as mask.") \ .def( \ - "get_operand_qubit_mask", \ - [](const PGATE_TYPE &gate) { return gate->get_operand_qubit_mask(); }, \ + "operand_qubit_mask", \ + [](const PGATE_TYPE &gate) { return gate->operand_qubit_mask(); }, \ "Get target and control qubits as mask.") \ .def( \ "get_inverse", \ @@ -683,7 +683,7 @@ NB_MODULE(scaluq_core, m) { &Circuit::gate_list, "Get property of `gate_list`.", nb::rv_policy::reference) - .def("gate_count", &Circuit::gate_count, "Get property of `gate_count`.") + .def("n_gates", &Circuit::n_gates, "Get property of `n_gates`.") .def("key_set", &Circuit::key_set, "Get set of keys of parameters.") .def("get", &Circuit::get, "Get reference of i-th gate.") .def("get_key", @@ -760,19 +760,15 @@ NB_MODULE(scaluq_core, m) { "target_qubit"_a, "pauli_id"_a, "Add a single pauli operation to the data.") - .def("get_coef", - &PauliOperator::Data::get_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, "c"_a, "Set the coefficient of the Pauli operator.") - .def("get_target_qubit_list", - &PauliOperator::Data::get_target_qubit_list, + .def("target_qubit_list", + &PauliOperator::Data::target_qubit_list, "Get the list of target qubits.") - .def("get_pauli_id_list", - &PauliOperator::Data::get_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, "Get the X and Z mask representation as a tuple of vectors."); @@ -828,14 +824,14 @@ NB_MODULE(scaluq_core, m) { "from `i-th` bit of `bit_flip_mask` and `phase_flip_mask` as follows.\n\n.. " "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("get_coef", &PauliOperator::get_coef, "Get property `coef`.") - .def("get_target_qubit_list", - &PauliOperator::get_target_qubit_list, + .def("coef", &PauliOperator::coef, "Get property `coef`.") + .def("target_qubit_list", + &PauliOperator::target_qubit_list, "Get qubits to be applied pauli.") - .def("get_pauli_id_list", - &PauliOperator::get_pauli_id_list, + .def("pauli_id_list", + &PauliOperator::pauli_id_list, "Get pauli id to be applied. The order is correspond to the result of " - "`get_target_qubit_list`") + "`target_qubit_list`") .def( "get_XZ_mask_representation", [](const PauliOperator &pauli) { diff --git a/scaluq/circuit/circuit.cpp b/scaluq/circuit/circuit.cpp index 13e9518e..68f10acd 100644 --- a/scaluq/circuit/circuit.cpp +++ b/scaluq/circuit/circuit.cpp @@ -7,11 +7,11 @@ UINT Circuit::calculate_depth() const { std::vector filled_step(_n_qubits, 0ULL); for (const auto& gate : _gate_list) { std::vector control_qubits = gate.index() == 0 - ? std::get<0>(gate)->get_control_qubit_list() - : std::get<1>(gate).first->get_control_qubit_list(); + ? std::get<0>(gate)->control_qubit_list() + : std::get<1>(gate).first->control_qubit_list(); std::vector target_qubits = gate.index() == 0 - ? std::get<0>(gate)->get_target_qubit_list() - : std::get<1>(gate).first->get_target_qubit_list(); + ? std::get<0>(gate)->target_qubit_list() + : std::get<1>(gate).first->target_qubit_list(); UINT max_step_amount_target_qubits = 0; for (UINT control : control_qubits) { if (max_step_amount_target_qubits < filled_step[control]) { @@ -123,8 +123,8 @@ Circuit Circuit::get_inverse() const { } void Circuit::check_gate_is_valid(const Gate& gate) const { - auto targets = gate->get_target_qubit_list(); - auto controls = gate->get_control_qubit_list(); + auto targets = gate->target_qubit_list(); + auto controls = gate->control_qubit_list(); bool valid = true; if (!targets.empty()) valid &= *std::max_element(targets.begin(), targets.end()) < _n_qubits; if (!controls.empty()) valid &= *std::max_element(controls.begin(), controls.end()) < _n_qubits; @@ -134,8 +134,8 @@ void Circuit::check_gate_is_valid(const Gate& gate) const { } void Circuit::check_gate_is_valid(const ParamGate& param_gate) const { - auto targets = param_gate->get_target_qubit_list(); - auto controls = param_gate->get_control_qubit_list(); + auto targets = param_gate->target_qubit_list(); + auto controls = param_gate->control_qubit_list(); bool valid = true; if (!targets.empty()) valid &= *std::max_element(targets.begin(), targets.end()) < _n_qubits; if (!controls.empty()) valid &= *std::max_element(controls.begin(), controls.end()) < _n_qubits; diff --git a/scaluq/circuit/circuit.hpp b/scaluq/circuit/circuit.hpp index d3b80234..3c8a02f8 100644 --- a/scaluq/circuit/circuit.hpp +++ b/scaluq/circuit/circuit.hpp @@ -15,7 +15,7 @@ class Circuit { [[nodiscard]] inline UINT n_qubits() const { return _n_qubits; } [[nodiscard]] inline const std::vector& gate_list() const { return _gate_list; } - [[nodiscard]] inline UINT gate_count() { return _gate_list.size(); } + [[nodiscard]] inline UINT n_gates() { return _gate_list.size(); } [[nodiscard]] inline const std::set key_set() const { std::set key_set; for (auto&& gate : _gate_list) { diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 160a7f5f..1c59208b 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -147,20 +147,18 @@ class GateBase : public std::enable_shared_from_this { } virtual ~GateBase() = default; - [[nodiscard]] virtual std::vector get_target_qubit_list() const { + [[nodiscard]] virtual std::vector target_qubit_list() const { return mask_to_vector(_target_mask); } - [[nodiscard]] virtual std::vector get_control_qubit_list() const { + [[nodiscard]] virtual std::vector control_qubit_list() const { return mask_to_vector(_control_mask); } - [[nodiscard]] virtual std::vector get_operand_qubit_list() const { + [[nodiscard]] virtual std::vector operand_qubit_list() const { return mask_to_vector(_target_mask | _control_mask); } - [[nodiscard]] virtual UINT get_target_qubit_mask() const { return _target_mask; } - [[nodiscard]] virtual UINT get_control_qubit_mask() const { return _control_mask; } - [[nodiscard]] virtual UINT get_operand_qubit_mask() const { - return _target_mask | _control_mask; - } + [[nodiscard]] virtual UINT target_qubit_mask() const { return _target_mask; } + [[nodiscard]] virtual UINT control_qubit_mask() const { return _control_mask; } + [[nodiscard]] virtual UINT operand_qubit_mask() const { return _target_mask | _control_mask; } [[nodiscard]] virtual Gate get_inverse() const = 0; [[nodiscard]] virtual ComplexMatrix get_matrix() const = 0; diff --git a/scaluq/gate/gate_factory.hpp b/scaluq/gate/gate_factory.hpp index 0cdbfe9d..26cfc194 100644 --- a/scaluq/gate/gate_factory.hpp +++ b/scaluq/gate/gate_factory.hpp @@ -136,7 +136,7 @@ inline Gate TwoTargetMatrix(UINT target1, } // まだ inline Gate Pauli(const PauliOperator& pauli, const std::vector& controls = {}) { - auto tar = pauli.get_target_qubit_list(); + auto tar = pauli.target_qubit_list(); return internal::GateFactory::create_gate( internal::vector_to_mask(controls), pauli); } diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index a65db8ba..ae8ad38f 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -13,11 +13,10 @@ class PauliGateImpl : public GateBase { public: PauliGateImpl(UINT control_mask, const PauliOperator& pauli) - : GateBase(vector_to_mask(pauli.get_target_qubit_list()), control_mask), - _pauli(pauli) {} + : GateBase(vector_to_mask(pauli.target_qubit_list()), control_mask), _pauli(pauli) {} PauliOperator pauli() const { return _pauli; }; - std::vector get_pauli_id_list() const { return _pauli.get_pauli_id_list(); } + std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } Gate get_inverse() const override { return shared_from_this(); } ComplexMatrix get_matrix() const override { return this->_pauli.get_matrix(); } @@ -33,12 +32,12 @@ class PauliRotationGateImpl : public GateBase { public: PauliRotationGateImpl(UINT control_mask, const PauliOperator& pauli, double angle) - : GateBase(vector_to_mask(pauli.get_target_qubit_list()), control_mask), + : GateBase(vector_to_mask(pauli.target_qubit_list()), control_mask), _pauli(pauli), _angle(angle) {} PauliOperator pauli() const { return _pauli; } - std::vector get_pauli_id_list() const { return _pauli.get_pauli_id_list(); } + std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } double angle() const { return _angle; } Gate get_inverse() const override { @@ -47,7 +46,7 @@ class PauliRotationGateImpl : public GateBase { ComplexMatrix get_matrix() const override { ComplexMatrix mat = this->_pauli.get_matrix_ignoring_coef(); - Complex true_angle = _angle * _pauli.get_coef(); + Complex true_angle = _angle * _pauli.coef(); StdComplex imag_unit(0, 1); mat = (StdComplex)Kokkos::cos(-true_angle / 2) * ComplexMatrix::Identity(mat.rows(), mat.cols()) + diff --git a/scaluq/gate/gate_probablistic.hpp b/scaluq/gate/gate_probablistic.hpp index 672e46b2..6b151dc3 100644 --- a/scaluq/gate/gate_probablistic.hpp +++ b/scaluq/gate/gate_probablistic.hpp @@ -31,34 +31,34 @@ class ProbablisticGateImpl : public GateBase { const std::vector& gate_list() const { return _gate_list; } const std::vector& distribution() const { return _distribution; } - std::vector get_target_qubit_list() const override { + std::vector target_qubit_list() const override { throw std::runtime_error( - "ProbablisticGateImpl::get_target_qubit_list(): This function must not be used in " + "ProbablisticGateImpl::target_qubit_list(): This function must not be used in " "ProbablisticGateImpl."); } - std::vector get_control_qubit_list() const override { + std::vector control_qubit_list() const override { throw std::runtime_error( - "ProbablisticGateImpl::get_control_qubit_list(): This function must not be used in " + "ProbablisticGateImpl::control_qubit_list(): This function must not be used in " "ProbablisticGateImpl."); } - std::vector get_operand_qubit_list() const override { + std::vector operand_qubit_list() const override { throw std::runtime_error( - "ProbablisticGateImpl::get_operand_qubit_list(): This function must not be used in " + "ProbablisticGateImpl::operand_qubit_list(): This function must not be used in " "ProbablisticGateImpl."); } - UINT get_target_qubit_mask() const override { + UINT target_qubit_mask() const override { throw std::runtime_error( - "ProbablisticGateImpl::get_target_qubit_mask(): This function must not be used in " + "ProbablisticGateImpl::target_qubit_mask(): This function must not be used in " "ProbablisticGateImpl."); } - UINT get_control_qubit_mask() const override { + UINT control_qubit_mask() const override { throw std::runtime_error( - "ProbablisticGateImpl::get_control_qubit_mask(): This function must not be used in " + "ProbablisticGateImpl::control_qubit_mask(): This function must not be used in " "ProbablisticGateImpl."); } - UINT get_operand_qubit_mask() const override { + UINT operand_qubit_mask() const override { throw std::runtime_error( - "ProbablisticGateImpl::get_operand_qubit_mask(): This function must not be used in " + "ProbablisticGateImpl::operand_qubit_mask(): This function must not be used in " "ProbablisticGateImpl."); } diff --git a/scaluq/gate/merge_gate.cpp b/scaluq/gate/merge_gate.cpp index 56c31126..c55c524b 100644 --- a/scaluq/gate/merge_gate.cpp +++ b/scaluq/gate/merge_gate.cpp @@ -32,8 +32,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { assert(!pauli_id1 || pauli_id1 != 0); assert(!pauli_id2 || pauli_id2 != 0); if (pauli_id1 && pauli_id2) { - UINT target1 = gate1->get_target_qubit_list()[0]; - UINT target2 = gate2->get_target_qubit_list()[0]; + UINT target1 = gate1->target_qubit_list()[0]; + UINT target2 = gate2->target_qubit_list()[0]; if (target1 == target2) { if (pauli_id1 == pauli_id2) return {gate::I(), 0.}; if (pauli_id1 == 1) { @@ -54,11 +54,11 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { (pauli_id2 || gate2.gate_type() == GateType::Pauli)) { auto pauli1 = gate_type1 == GateType::Pauli ? PauliGate(gate1)->pauli() - : PauliOperator(std::vector{gate1->get_target_qubit_list()[0]}, + : PauliOperator(std::vector{gate1->target_qubit_list()[0]}, std::vector{pauli_id1.value()}); auto pauli2 = gate_type2 == GateType::Pauli ? PauliGate(gate2)->pauli() - : PauliOperator(std::vector{gate2->get_target_qubit_list()[0]}, + : PauliOperator(std::vector{gate2->target_qubit_list()[0]}, std::vector{pauli_id2.value()}); return {gate::Pauli(pauli2 * pauli1), 0.}; } @@ -86,8 +86,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { auto oct_phase1 = get_oct_phase(gate_type1); auto oct_phase2 = get_oct_phase(gate_type2); if (oct_phase1 && oct_phase2) { - UINT target1 = gate1->get_target_qubit_list()[0]; - UINT target2 = gate2->get_target_qubit_list()[0]; + UINT target1 = gate1->target_qubit_list()[0]; + UINT target2 = gate2->target_qubit_list()[0]; if (target1 == target2) { auto g = oct_phase_gate(oct_phase1.value() + oct_phase2.value(), target1); if (g) return {g.value(), 0.}; @@ -95,8 +95,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { } if ((oct_phase1 || gate_type1 == GateType::RZ || gate_type1 == GateType::U1) && (oct_phase2 || gate_type2 == GateType::RZ || gate_type2 == GateType::U1)) { - UINT target1 = gate1->get_target_qubit_list()[0]; - UINT target2 = gate2->get_target_qubit_list()[0]; + UINT target1 = gate1->target_qubit_list()[0]; + UINT target2 = gate2->target_qubit_list()[0]; if (target1 == target2) { double phase1 = oct_phase1 ? oct_phase1.value() * PI() / 4 : gate_type1 == GateType::RZ ? RZGate(gate1)->angle() @@ -122,8 +122,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { auto rx_param1 = get_rx_angle(gate1, gate_type1); auto rx_param2 = get_rx_angle(gate2, gate_type2); if (rx_param1 && rx_param2) { - UINT target1 = gate1->get_target_qubit_list()[0]; - UINT target2 = gate2->get_target_qubit_list()[0]; + UINT target1 = gate1->target_qubit_list()[0]; + UINT target2 = gate2->target_qubit_list()[0]; double global_phase1 = gate_type1 == GateType::RX ? 0. : rx_param1.value() / 2; double global_phase2 = gate_type2 == GateType::RX ? 0. : rx_param2.value() / 2; if (target1 == target2) { @@ -144,8 +144,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { auto ry_param1 = get_ry_angle(gate1, gate_type1); auto ry_param2 = get_ry_angle(gate2, gate_type2); if (ry_param1 && ry_param2) { - UINT target1 = gate1->get_target_qubit_list()[0]; - UINT target2 = gate2->get_target_qubit_list()[0]; + UINT target1 = gate1->target_qubit_list()[0]; + UINT target2 = gate2->target_qubit_list()[0]; double global_phase1 = gate_type1 == GateType::RY ? 0. : ry_param1.value() / 2; double global_phase2 = gate_type2 == GateType::RY ? 0. : ry_param2.value() / 2; if (target1 == target2) { @@ -187,10 +187,10 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { } // General case - auto gate1_targets = gate1->get_target_qubit_list(); - std::ranges::copy(gate1->get_control_qubit_list(), std::back_inserter(gate1_targets)); - auto gate2_targets = gate2->get_target_qubit_list(); - std::ranges::copy(gate2->get_control_qubit_list(), std::back_inserter(gate2_targets)); + auto gate1_targets = gate1->target_qubit_list(); + std::ranges::copy(gate1->control_qubit_list(), std::back_inserter(gate1_targets)); + auto gate2_targets = gate2->target_qubit_list(); + std::ranges::copy(gate2->control_qubit_list(), std::back_inserter(gate2_targets)); std::vector merged_targets(gate1_targets.size() + gate2_targets.size()); std::ranges::copy(gate1_targets, merged_targets.begin()); std::ranges::copy(gate2_targets, merged_targets.begin() + gate1_targets.size()); diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index b60dcd33..6e717700 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -63,20 +63,18 @@ class ParamGateBase { [[nodiscard]] double pcoef() { return _pcoef; } - [[nodiscard]] virtual std::vector get_target_qubit_list() const { + [[nodiscard]] virtual std::vector target_qubit_list() const { return mask_to_vector(_target_mask); } - [[nodiscard]] virtual std::vector get_control_qubit_list() const { + [[nodiscard]] virtual std::vector control_qubit_list() const { return mask_to_vector(_control_mask); } - [[nodiscard]] virtual std::vector get_operand_qubit_list() const { + [[nodiscard]] virtual std::vector operand_qubit_list() const { return mask_to_vector(_target_mask | _control_mask); } - [[nodiscard]] virtual UINT get_target_qubit_mask() const { return _target_mask; } - [[nodiscard]] virtual UINT get_control_qubit_mask() const { return _control_mask; } - [[nodiscard]] virtual UINT get_operand_qubit_mask() const { - return _target_mask | _control_mask; - } + [[nodiscard]] virtual UINT target_qubit_mask() const { return _target_mask; } + [[nodiscard]] virtual UINT control_qubit_mask() const { return _control_mask; } + [[nodiscard]] virtual UINT operand_qubit_mask() const { return _target_mask | _control_mask; } [[nodiscard]] virtual ParamGate get_inverse() const = 0; [[nodiscard]] virtual ComplexMatrix get_matrix(double param) const = 0; diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index befced0a..85f98f9f 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -13,18 +13,18 @@ class PPauliRotationGateImpl : public ParamGateBase { public: PPauliRotationGateImpl(UINT control_mask, const PauliOperator& pauli, double pcoef = 1.) - : ParamGateBase(vector_to_mask(pauli.get_target_qubit_list()), control_mask, pcoef), + : ParamGateBase(vector_to_mask(pauli.target_qubit_list()), control_mask, pcoef), _pauli(pauli) {} PauliOperator pauli() const { return _pauli; } - std::vector get_pauli_id_list() const { return _pauli.get_pauli_id_list(); } + std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } ParamGate get_inverse() const override { return std::make_shared(_control_mask, _pauli, -_pcoef); } ComplexMatrix get_matrix(double param) const override { double angle = _pcoef * param; - Complex true_angle = angle * this->_pauli.get_coef(); + Complex true_angle = angle * this->_pauli.coef(); ComplexMatrix mat = this->_pauli.get_matrix_ignoring_coef(); StdComplex imag_unit(0, 1); mat = (StdComplex)Kokkos::cos(-true_angle / 2) * diff --git a/scaluq/gate/param_gate_probablistic.hpp b/scaluq/gate/param_gate_probablistic.hpp index e7855ff6..7b5a419d 100644 --- a/scaluq/gate/param_gate_probablistic.hpp +++ b/scaluq/gate/param_gate_probablistic.hpp @@ -35,34 +35,34 @@ class PProbablisticGateImpl : public ParamGateBase { const std::vector>& gate_list() const { return _gate_list; } const std::vector& distribution() const { return _distribution; } - std::vector get_target_qubit_list() const override { + std::vector target_qubit_list() const override { throw std::runtime_error( - "PProbablisticGateImpl::get_target_qubit_list(): This function must not be used in " + "PProbablisticGateImpl::target_qubit_list(): This function must not be used in " "PProbablisticGateImpl."); } - std::vector get_control_qubit_list() const override { + std::vector control_qubit_list() const override { throw std::runtime_error( - "PProbablisticGateImpl::get_control_qubit_list(): This function must not be used in " + "PProbablisticGateImpl::control_qubit_list(): This function must not be used in " "PProbablisticGateImpl."); } - std::vector get_operand_qubit_list() const override { + std::vector operand_qubit_list() const override { throw std::runtime_error( - "PProbablisticGateImpl::get_operand_qubit_list(): This function must not be used in " + "PProbablisticGateImpl::operand_qubit_list(): This function must not be used in " "PProbablisticGateImpl."); } - UINT get_target_qubit_mask() const override { + UINT target_qubit_mask() const override { throw std::runtime_error( - "PProbablisticGateImpl::get_target_qubit_mask(): This function must not be used in " + "PProbablisticGateImpl::target_qubit_mask(): This function must not be used in " "PProbablisticGateImpl."); } - UINT get_control_qubit_mask() const override { + UINT control_qubit_mask() const override { throw std::runtime_error( - "PProbablisticGateImpl::get_control_qubit_mask(): This function must not be used in " + "PProbablisticGateImpl::control_qubit_mask(): This function must not be used in " "PProbablisticGateImpl."); } - UINT get_operand_qubit_mask() const override { + UINT operand_qubit_mask() const override { throw std::runtime_error( - "PProbablisticGateImpl::get_operand_qubit_mask(): This function must not be used in " + "PProbablisticGateImpl::operand_qubit_mask(): This function must not be used in " "PProbablisticGateImpl."); } diff --git a/scaluq/gate/update_ops_pauli.cpp b/scaluq/gate/update_ops_pauli.cpp index 49c1cf28..b26fa291 100644 --- a/scaluq/gate/update_ops_pauli.cpp +++ b/scaluq/gate/update_ops_pauli.cpp @@ -24,7 +24,7 @@ void pauli_rotation_gate(UINT control_mask, UINT bit_flip_mask = internal::BitVector(bit_flip_mask_vector).data_raw()[0]; UINT phase_flip_mask = internal::BitVector(phase_flip_mask_vector).data_raw()[0]; UINT global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex true_angle = angle * pauli.get_coef(); + Complex true_angle = angle * pauli.coef(); const Complex cosval = Kokkos::cos(-true_angle / 2); const Complex sinval = Kokkos::sin(-true_angle / 2); if (bit_flip_mask == 0) { diff --git a/scaluq/operator/operator.cpp b/scaluq/operator/operator.cpp index fcfb8e3d..b2da1400 100644 --- a/scaluq/operator/operator.cpp +++ b/scaluq/operator/operator.cpp @@ -11,7 +11,7 @@ Operator::Operator(UINT n_qubits) : _n_qubits(n_qubits) {} std::string Operator::to_string() const { std::stringstream ss; for (auto itr = _terms.begin(); itr != _terms.end(); ++itr) { - ss << itr->get_coef() << " " << itr->get_pauli_string(); + ss << itr->coef() << " " << itr->get_pauli_string(); if (itr != prev(_terms.end())) { ss << " + "; } @@ -21,9 +21,9 @@ std::string Operator::to_string() const { void Operator::add_operator(const PauliOperator& mpt) { add_operator(PauliOperator{mpt}); } void Operator::add_operator(PauliOperator&& mpt) { - _is_hermitian &= mpt.get_coef().imag() == 0.; + _is_hermitian &= mpt.coef().imag() == 0.; if (![&] { - const auto& target_list = mpt.get_target_qubit_list(); + const auto& target_list = mpt.target_qubit_list(); if (target_list.empty()) return true; return *std::max_element(target_list.begin(), target_list.end()) < _n_qubits; }()) { @@ -49,7 +49,7 @@ void Operator::add_random_operator(UINT operator_count, UINT seed) { void Operator::optimize() { std::map, Complex> pauli_and_coef; for (const auto& pauli : _terms) { - pauli_and_coef[pauli.get_XZ_mask_representation()] += pauli.get_coef(); + pauli_and_coef[pauli.get_XZ_mask_representation()] += pauli.coef(); } _terms.clear(); for (const auto& [mask, coef] : pauli_and_coef) { diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 4e079294..6858339b 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -115,7 +115,7 @@ void PauliOperator::apply_to_state(StateVector& state_vector) const { } UINT bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; UINT phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; - Complex coef = get_coef(); + Complex coef = this->coef(); if (bit_flip_mask == 0) { Kokkos::parallel_for( state_vector.dim(), KOKKOS_LAMBDA(UINT state_idx) { diff --git a/scaluq/operator/pauli_operator.hpp b/scaluq/operator/pauli_operator.hpp index 6b02f430..540a686a 100644 --- a/scaluq/operator/pauli_operator.hpp +++ b/scaluq/operator/pauli_operator.hpp @@ -30,10 +30,10 @@ class PauliOperator { const std::vector& phase_flip_mask, Complex coef); void add_single_pauli(UINT target_qubit, UINT pauli_id); - Complex get_coef() const { return _coef; } + Complex coef() const { return _coef; } void set_coef(Complex c) { _coef = c; } - const std::vector& get_target_qubit_list() const { return _target_qubit_list; } - const std::vector& get_pauli_id_list() const { return _pauli_id_list; } + const std::vector& target_qubit_list() const { return _target_qubit_list; } + const std::vector& pauli_id_list() const { return _pauli_id_list; } std::tuple, std::vector> get_XZ_mask_representation() const { return {_bit_flip_mask, _phase_flip_mask}; } @@ -60,12 +60,12 @@ class PauliOperator { Complex coef) : _ptr(std::make_shared(bit_flip_mask, phase_flip_mask, coef)) {} - [[nodiscard]] inline Complex get_coef() const { return _ptr->get_coef(); } - [[nodiscard]] inline const std::vector& get_target_qubit_list() const { - return _ptr->get_target_qubit_list(); + [[nodiscard]] inline Complex coef() const { return _ptr->coef(); } + [[nodiscard]] inline const std::vector& target_qubit_list() const { + return _ptr->target_qubit_list(); } - [[nodiscard]] inline const std::vector& get_pauli_id_list() const { - return _ptr->get_pauli_id_list(); + [[nodiscard]] inline const std::vector& pauli_id_list() const { + return _ptr->pauli_id_list(); } [[nodiscard]] inline std::tuple, std::vector> get_XZ_mask_representation() const { diff --git a/scaluq/state/state_vector.cpp b/scaluq/state/state_vector.cpp index d5d06372..f098d834 100644 --- a/scaluq/state/state_vector.cpp +++ b/scaluq/state/state_vector.cpp @@ -60,7 +60,7 @@ UINT StateVector::n_qubits() const { return this->_n_qubits; } UINT StateVector::dim() const { return this->_dim; } -std::vector StateVector::amplitudes() const { +std::vector StateVector::get_amplitudes() const { return internal::convert_device_view_to_host_vector(_raw); } @@ -214,7 +214,7 @@ std::vector StateVector::sampling(UINT sampling_count, UINT seed) const { std::string StateVector::to_string() const { std::stringstream os; - auto amp = this->amplitudes(); + auto amp = this->get_amplitudes(); os << " *** Quantum State ***\n"; os << " * Qubit Count : " << _n_qubits << '\n'; os << " * Dimension : " << _dim << '\n'; diff --git a/scaluq/state/state_vector.hpp b/scaluq/state/state_vector.hpp index ae8031a3..524af3cb 100644 --- a/scaluq/state/state_vector.hpp +++ b/scaluq/state/state_vector.hpp @@ -28,7 +28,7 @@ class StateVector { void set_amplitude_at_index(UINT index, const Complex& c); /** - * @attention Very slow. You should use amplitudes() instead if you can. + * @attention Very slow. You should use get_amplitudes() instead if you can. */ [[nodiscard]] Complex get_amplitude_at_index(UINT index) const; @@ -46,7 +46,7 @@ class StateVector { [[nodiscard]] UINT dim() const; - [[nodiscard]] std::vector amplitudes() const; + [[nodiscard]] std::vector get_amplitudes() const; [[nodiscard]] double get_squared_norm() const; diff --git a/scaluq/state/state_vector_batched.cpp b/scaluq/state/state_vector_batched.cpp index a1e2b339..fdf01fe2 100644 --- a/scaluq/state/state_vector_batched.cpp +++ b/scaluq/state/state_vector_batched.cpp @@ -129,7 +129,7 @@ std::vector> StateVectorBatched::sampling(UINT sampling_count, result); } -std::vector> StateVectorBatched::amplitudes() const { +std::vector> StateVectorBatched::get_amplitudes() const { return internal::convert_2d_device_view_to_host_vector(_raw); } diff --git a/scaluq/state/state_vector_batched.hpp b/scaluq/state/state_vector_batched.hpp index db33dc6c..99d3b794 100644 --- a/scaluq/state/state_vector_batched.hpp +++ b/scaluq/state/state_vector_batched.hpp @@ -39,7 +39,7 @@ class StateVectorBatched { bool set_same_state, UINT seed = std::random_device()()); - [[nodiscard]] std::vector> amplitudes() const; + [[nodiscard]] std::vector> get_amplitudes() const; [[nodiscard]] std::vector get_squared_norm() const; diff --git a/tests/circuit/circuit_test.cpp b/tests/circuit/circuit_test.cpp index 9740cfaf..dd722584 100644 --- a/tests/circuit/circuit_test.cpp +++ b/tests/circuit/circuit_test.cpp @@ -22,7 +22,7 @@ TEST(CircuitTest, CircuitBasic) { StateVector state = StateVector::Haar_random_state(n); Eigen::VectorXcd state_eigen(dim); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (UINT i = 0; i < dim; ++i) state_eigen[i] = state_cp[i]; Circuit circuit(n); @@ -158,7 +158,7 @@ TEST(CircuitTest, CircuitBasic) { circuit.update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); for (UINT i = 0; i < dim; ++i) ASSERT_NEAR(std::abs(state_eigen[i] - (CComplex)state_cp[i]), 0, eps); } @@ -170,7 +170,7 @@ TEST(CircuitTest, CircuitRev) { Random random; StateVector state = StateVector::Haar_random_state(n); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); Eigen::VectorXcd state_eigen(dim); for (UINT i = 0; i < dim; ++i) state_eigen[i] = state_cp[i]; @@ -256,6 +256,6 @@ TEST(CircuitTest, CircuitRev) { auto revcircuit = circuit.get_inverse(); revcircuit.update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); for (UINT i = 0; i < dim; ++i) ASSERT_NEAR(abs(state_eigen[i] - (CComplex)state_cp[i]), 0, eps); } diff --git a/tests/circuit/param_circuit_test.cpp b/tests/circuit/param_circuit_test.cpp index 2a1262ec..8e1ed094 100644 --- a/tests/circuit/param_circuit_test.cpp +++ b/tests/circuit/param_circuit_test.cpp @@ -68,11 +68,11 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { } StateVector state = StateVector::Haar_random_state(n_qubits); StateVector state_cp = state.copy(); - auto amplitudes_base = state.amplitudes(); + auto amplitudes_base = state.get_amplitudes(); circuit.update_quantum_state(state); pcircuit.update_quantum_state(state_cp, pmap); - auto amplitudes = state.amplitudes(); - auto amplitudes_cp = state_cp.amplitudes(); + auto amplitudes = state.get_amplitudes(); + auto amplitudes_cp = state_cp.get_amplitudes(); for (UINT idx : std::views::iota(UINT{0}, 1ULL << n_qubits)) { ASSERT_NEAR(Kokkos::abs(amplitudes[idx] - amplitudes_cp[idx]), 0, eps); } @@ -80,8 +80,8 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { auto ipcircuit = pcircuit.get_inverse(); icircuit.update_quantum_state(state); ipcircuit.update_quantum_state(state_cp, pmap); - amplitudes = state.amplitudes(); - amplitudes_cp = state_cp.amplitudes(); + amplitudes = state.get_amplitudes(); + amplitudes_cp = state_cp.get_amplitudes(); for (UINT idx : std::views::iota(UINT{0}, 1ULL << n_qubits)) { ASSERT_NEAR(Kokkos::abs(amplitudes[idx] - amplitudes_base[idx]), 0, eps); ASSERT_NEAR(Kokkos::abs(amplitudes_cp[idx] - amplitudes_base[idx]), 0, eps); diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index dd1ea1c4..d046df95 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -23,14 +23,14 @@ void run_random_gate_apply(UINT n_qubits) { Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); for (int repeat = 0; repeat < 10; repeat++) { auto state = StateVector::Haar_random_state(n_qubits); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (int i = 0; i < dim; i++) { test_state[i] = state_cp[i]; } const Gate gate = QuantumGateConstructor(); gate->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); test_state = test_state; @@ -48,7 +48,7 @@ void run_random_gate_apply(UINT n_qubits) { Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); for (int repeat = 0; repeat < 10; repeat++) { auto state = StateVector::Haar_random_state(n_qubits); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (int i = 0; i < dim; i++) { test_state[i] = state_cp[i]; } @@ -56,7 +56,7 @@ void run_random_gate_apply(UINT n_qubits) { const double angle = M_PI * random.uniform(); const Gate gate = QuantumGateConstructor(angle, {}); gate->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); test_state = std::polar(1., angle) * test_state; @@ -75,7 +75,7 @@ void run_random_gate_apply(UINT n_qubits, std::function matr Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); for (int repeat = 0; repeat < 10; repeat++) { auto state = StateVector::Haar_random_state(n_qubits); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (int i = 0; i < dim; i++) { test_state[i] = state_cp[i]; } @@ -83,7 +83,7 @@ void run_random_gate_apply(UINT n_qubits, std::function matr const UINT target = random.int64() % n_qubits; const Gate gate = QuantumGateConstructor(target, {}); gate->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); test_state = get_expanded_eigen_matrix_with_identity(target, matrix, n_qubits) * test_state; @@ -101,7 +101,7 @@ void run_random_gate_apply(UINT n_qubits, std::functionupdate_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); test_state = get_expanded_eigen_matrix_with_identity(target, matrix, n_qubits) * test_state; @@ -129,7 +129,7 @@ void run_random_gate_apply_IBMQ( Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); for (int repeat = 0; repeat < 10; repeat++) { auto state = StateVector::Haar_random_state(n_qubits); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (int gate_type = 0; gate_type < 3; gate_type++) { for (int i = 0; i < dim; i++) { test_state[i] = state_cp[i]; @@ -155,7 +155,7 @@ void run_random_gate_apply_IBMQ( gate = gate::U3(target, theta, phi, lambda, {}); } gate->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); test_state = get_expanded_eigen_matrix_with_identity(target, matrix, n_qubits) * test_state; @@ -177,7 +177,7 @@ void run_random_gate_apply_two_target(UINT n_qubits) { auto state = StateVector::Haar_random_state(n_qubits); for (int g = 0; g < 2; g++) { Gate gate; - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (int i = 0; i < dim; i++) { test_state[i] = state_cp[i]; } @@ -193,7 +193,7 @@ void run_random_gate_apply_two_target(UINT n_qubits) { func_eig = get_eigen_matrix_full_qubit_CZ; } gate->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); Eigen::MatrixXcd test_mat = func_eig(control, target, n_qubits); test_state = test_mat * test_state; @@ -206,7 +206,7 @@ void run_random_gate_apply_two_target(UINT n_qubits) { for (int repeat = 0; repeat < 10; repeat++) { auto state = StateVector::Haar_random_state(n_qubits); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (int i = 0; i < dim; i++) { test_state[i] = state_cp[i]; } @@ -216,7 +216,7 @@ void run_random_gate_apply_two_target(UINT n_qubits) { if (target1 == target2) target1 = (target1 + 1) % n_qubits; auto gate = gate::Swap(target1, target2); gate->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); Eigen::MatrixXcd test_mat = get_eigen_matrix_full_qubit_Swap(target1, target2, n_qubits); test_state = test_mat * test_state; @@ -236,7 +236,7 @@ void run_random_gate_apply_pauli(UINT n_qubits) { // Test for PauliGate for (int repeat = 0; repeat < 10; repeat++) { StateVector state = StateVector::Haar_random_state(n_qubits); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); auto state_bef = state.copy(); for (UINT i = 0; i < dim; i++) { @@ -274,7 +274,7 @@ void run_random_gate_apply_pauli(UINT n_qubits) { Gate pauli_gate = gate::Pauli(pauli); pauli_gate->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); test_state = matrix * test_state; // check if the state is updated correctly @@ -282,10 +282,10 @@ void run_random_gate_apply_pauli(UINT n_qubits) { ASSERT_NEAR(std::abs((CComplex)state_cp[i] - test_state[i]), 0, eps); } - auto state_bef_cp = state_bef.amplitudes(); + auto state_bef_cp = state_bef.get_amplitudes(); Gate pauli_gate_inv = pauli_gate->get_inverse(); pauli_gate_inv->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); // check if the state is restored correctly for (UINT i = 0; i < dim; i++) { @@ -296,7 +296,7 @@ void run_random_gate_apply_pauli(UINT n_qubits) { // Test for PauliRotationGate for (int repeat = 0; repeat < 10; repeat++) { StateVector state = StateVector::Haar_random_state(n_qubits); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); auto state_bef = state.copy(); assert(test_state.size() == (int)state_cp.size()); for (UINT i = 0; i < dim; i++) { @@ -334,7 +334,7 @@ void run_random_gate_apply_pauli(UINT n_qubits) { PauliOperator pauli(target_vec, pauli_id_vec, 1.0); Gate pauli_gate = gate::PauliRotation(pauli, angle); pauli_gate->update_quantum_state(state); - state_cp = state.amplitudes(); + state_cp = state.get_amplitudes(); test_state = matrix * test_state; assert((int)state_cp.size() == test_state.size()); // check if the state is updated correctly @@ -343,8 +343,8 @@ void run_random_gate_apply_pauli(UINT n_qubits) { } Gate pauli_gate_inv = pauli_gate->get_inverse(); pauli_gate_inv->update_quantum_state(state); - state_cp = state.amplitudes(); - auto state_bef_cp = state_bef.amplitudes(); + state_cp = state.get_amplitudes(); + auto state_bef_cp = state_bef.get_amplitudes(); // check if the state is restored correctly for (UINT i = 0; i < dim; i++) { ASSERT_NEAR(std::abs((CComplex)(state_cp[i] - state_bef_cp[i])), 0, eps); diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index d7a4c0ef..0b11e8ac 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -31,8 +31,8 @@ void test_apply_parametric_single_pauli_rotation(UINT n_qubits, const ParamGate pgate = factory_parametric(target, pcoef, {}); gate->update_quantum_state(state); pgate->update_quantum_state(state_cp, param); - auto state_amp = state.amplitudes(); - auto state_cp_amp = state_cp.amplitudes(); + auto state_amp = state.get_amplitudes(); + auto state_cp_amp = state_cp.get_amplitudes(); for (UINT i = 0; i < dim; i++) { ASSERT_NEAR(Kokkos::abs(state_cp_amp[i] - state_amp[i]), 0, eps); @@ -40,8 +40,8 @@ void test_apply_parametric_single_pauli_rotation(UINT n_qubits, ParamGate pgate_inv = pgate->get_inverse(); pgate_inv->update_quantum_state(state, param); - state_amp = state.amplitudes(); - auto state_bef_amp = state_bef.amplitudes(); + state_amp = state.get_amplitudes(); + auto state_bef_amp = state_bef.get_amplitudes(); for (UINT i = 0; i < dim; i++) { ASSERT_NEAR(Kokkos::abs(state_bef_amp[i] - state_amp[i]), 0, eps); } @@ -69,16 +69,16 @@ void test_apply_parametric_multi_pauli_rotation(UINT n_qubits) { ParamGate pgate = gate::PPauliRotation(pauli, pcoef); gate->update_quantum_state(state); pgate->update_quantum_state(state_cp, param); - auto state_amp = state.amplitudes(); - auto state_cp_amp = state_cp.amplitudes(); + auto state_amp = state.get_amplitudes(); + auto state_cp_amp = state_cp.get_amplitudes(); // check if the state is updated correctly for (UINT i = 0; i < dim; i++) { ASSERT_NEAR(Kokkos::abs(state_cp_amp[i] - state_amp[i]), 0, eps); } ParamGate pgate_inv = pgate->get_inverse(); pgate_inv->update_quantum_state(state, param); - state_amp = state.amplitudes(); - auto state_bef_amp = state_bef.amplitudes(); + state_amp = state.get_amplitudes(); + auto state_bef_amp = state_bef.get_amplitudes(); // check if the state is restored correctly for (UINT i = 0; i < dim; i++) { ASSERT_NEAR(Kokkos::abs((state_bef_amp[i] - state_amp[i])), 0, eps); diff --git a/tests/operator/test_operator.cpp b/tests/operator/test_operator.cpp index bbfe4898..26d8f011 100644 --- a/tests/operator/test_operator.cpp +++ b/tests/operator/test_operator.cpp @@ -56,7 +56,7 @@ TEST(OperatorTest, CheckExpectationValue) { generate_random_observable_with_eigen(n, random); auto state = StateVector::Haar_random_state(n); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); for (UINT i = 0; i < dim; ++i) test_state[i] = state_cp[i]; @@ -78,11 +78,11 @@ TEST(OperatorTest, CheckTransitionAmplitude) { generate_random_observable_with_eigen(n, random); auto state_bra = StateVector::Haar_random_state(n); - auto state_bra_cp = state_bra.amplitudes(); + auto state_bra_cp = state_bra.get_amplitudes(); Eigen::VectorXcd test_state_bra = Eigen::VectorXcd::Zero(dim); for (UINT i = 0; i < dim; ++i) test_state_bra[i] = state_bra_cp[i]; auto state_ket = StateVector::Haar_random_state(n); - auto state_ket_cp = state_ket.amplitudes(); + auto state_ket_cp = state_ket.get_amplitudes(); Eigen::VectorXcd test_state_ket = Eigen::VectorXcd::Zero(dim); for (UINT i = 0; i < dim; ++i) test_state_ket[i] = state_ket_cp[i]; @@ -164,7 +164,7 @@ TEST(OperatorTest, ApplyToStateTest) { Complex(-14, 0), Complex(-12, 1), }; - ASSERT_EQ(state_vector.amplitudes(), expected); + ASSERT_EQ(state_vector.get_amplitudes(), expected); } TEST(OperatorTest, Optimize) { @@ -180,7 +180,7 @@ TEST(OperatorTest, Optimize) { {"X 0 Y 1", 10.}, {"Y 0 Z 1", 2.}, {"Z 1", 7.}}; std::vector> test; for (const auto& pauli : op.terms()) { - test.emplace_back(pauli.get_pauli_string(), pauli.get_coef()); + test.emplace_back(pauli.get_pauli_string(), pauli.coef()); } std::ranges::sort(expected, [](const auto& l, const auto& r) { return l.first < r.first; }); std::ranges::sort(test, [](const auto& l, const auto& r) { return l.first < r.first; }); diff --git a/tests/operator/test_pauli_operator.cpp b/tests/operator/test_pauli_operator.cpp index 6a1be45a..45a9a4f2 100644 --- a/tests/operator/test_pauli_operator.cpp +++ b/tests/operator/test_pauli_operator.cpp @@ -13,15 +13,15 @@ TEST(PauliOperatorTest, ContainsExtraWhitespace) { PauliOperator expected = PauliOperator("X 0", 1.0); PauliOperator pauli_whitespace = PauliOperator("X 0 ", 1.0); - EXPECT_EQ(1, pauli_whitespace.get_target_qubit_list().size()); - EXPECT_EQ(1, pauli_whitespace.get_pauli_id_list().size()); + EXPECT_EQ(1, pauli_whitespace.target_qubit_list().size()); + EXPECT_EQ(1, pauli_whitespace.pauli_id_list().size()); EXPECT_EQ(expected.get_pauli_string(), pauli_whitespace.get_pauli_string()); } TEST(PauliOperatorTest, EmptyStringConstructsIdentity) { const auto identity = PauliOperator("", 1.0); - ASSERT_EQ(0, identity.get_target_qubit_list().size()); - ASSERT_EQ(0, identity.get_pauli_id_list().size()); + ASSERT_EQ(0, identity.target_qubit_list().size()); + ASSERT_EQ(0, identity.pauli_id_list().size()); ASSERT_EQ("", identity.get_pauli_string()); } @@ -62,7 +62,7 @@ TEST(PauliOperatorTest, SpacedPauliString) { double coef = 2.0; std::string Pauli_string = "X 0 Y 1 "; PauliOperator pauli = PauliOperator(Pauli_string, coef); - size_t PauliSize = pauli.get_target_qubit_list().size(); + size_t PauliSize = pauli.target_qubit_list().size(); ASSERT_EQ(PauliSize, 2); } @@ -95,7 +95,7 @@ TEST_P(PauliOperatorMultiplyTest, MultiplyTest) { const auto p = GetParam(); PauliOperator res = p.op1 * p.op2; EXPECT_EQ(p.expected.get_pauli_string(), res.get_pauli_string()); - EXPECT_EQ(p.expected.get_coef(), res.get_coef()); + EXPECT_EQ(p.expected.coef(), res.coef()); } TEST_P(PauliOperatorMultiplyTest, MultiplyAssignmentTest) { @@ -103,7 +103,7 @@ TEST_P(PauliOperatorMultiplyTest, MultiplyAssignmentTest) { PauliOperator res = p.op1; res = res * p.op2; EXPECT_EQ(p.expected.get_pauli_string(), res.get_pauli_string()); - EXPECT_EQ(p.expected.get_coef(), res.get_coef()); + EXPECT_EQ(p.expected.coef(), res.coef()); } INSTANTIATE_TEST_CASE_P( @@ -190,5 +190,5 @@ TEST(PauliOperatorTest, ApplyToStateTest) { PauliOperator op(std::vector{1, 0, 0}, std::vector{0, 1, 0}, Complex(2)); op.apply_to_state(state_vector); std::vector expected = {2, 0, -6, -4, 10, 8, -14, -12}; - ASSERT_EQ(state_vector.amplitudes(), expected); + ASSERT_EQ(state_vector.get_amplitudes(), expected); } diff --git a/tests/state/state_vector_batched_test.cpp b/tests/state/state_vector_batched_test.cpp index eb6b738c..0d4a848e 100644 --- a/tests/state/state_vector_batched_test.cpp +++ b/tests/state/state_vector_batched_test.cpp @@ -33,7 +33,7 @@ TEST(StateVectorBatchedTest, LoadAndAmplitues) { StateVectorBatched states(batch_size, n_qubits); states.load(states_h); - auto amps = states.amplitudes(); + auto amps = states.get_amplitudes(); for (UINT b = 0; b < batch_size; ++b) { for (UINT i = 0; i < dim; ++i) { ASSERT_EQ(amps[b][i].real(), b * dim + i); diff --git a/tests/state/state_vector_test.cpp b/tests/state/state_vector_test.cpp index 719d0cdd..a5bcdc2d 100644 --- a/tests/state/state_vector_test.cpp +++ b/tests/state/state_vector_test.cpp @@ -35,8 +35,8 @@ TEST(StateVectorTest, CopyState) { const int n = 5; const auto state = StateVector::Haar_random_state(n); StateVector state_cp = state.copy(); - auto vec1 = state.amplitudes(); - auto vec2 = state_cp.amplitudes(); + auto vec1 = state.get_amplitudes(); + auto vec2 = state_cp.get_amplitudes(); ASSERT_EQ(vec1, vec2); } @@ -45,7 +45,7 @@ TEST(StateVectorTest, ZeroNormState) { StateVector state(StateVector::Haar_random_state(n)); state.set_zero_norm_state(); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (UINT i = 0; i < state.dim(); ++i) { ASSERT_EQ((CComplex)state_cp[i], CComplex(0, 0)); @@ -57,7 +57,7 @@ TEST(StateVectorTest, ComputationalBasisState) { StateVector state(StateVector::Haar_random_state(n)); state.set_computational_basis(31); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); for (UINT i = 0; i < state.dim(); ++i) { if (i == 31) { @@ -90,10 +90,10 @@ TEST(StateVectorTest, AddState) { const UINT n = 10; StateVector state1(StateVector::Haar_random_state(n)); StateVector state2(StateVector::Haar_random_state(n)); - auto vec1 = state1.amplitudes(); - auto vec2 = state2.amplitudes(); + auto vec1 = state1.get_amplitudes(); + auto vec2 = state2.get_amplitudes(); state1.add_state_vector(state2); - auto new_vec = state1.amplitudes(); + auto new_vec = state1.get_amplitudes(); for (UINT i = 0; i < state1.dim(); ++i) { CComplex res = new_vec[i], val = (CComplex)vec1[i] + (CComplex)vec2[i]; @@ -107,11 +107,11 @@ TEST(StateVectorTest, AddStateWithCoef) { const UINT n = 10; StateVector state1(StateVector::Haar_random_state(n)); StateVector state2(StateVector::Haar_random_state(n)); - auto vec1 = state1.amplitudes(); - auto vec2 = state2.amplitudes(); + auto vec1 = state1.get_amplitudes(); + auto vec2 = state2.get_amplitudes(); state1.add_state_vector_with_coef(coef, state2); - auto new_vec = state1.amplitudes(); + auto new_vec = state1.get_amplitudes(); for (UINT i = 0; i < state1.dim(); ++i) { CComplex res = new_vec[i], val = (CComplex)vec1[i] + coef * (CComplex)vec2[i]; @@ -125,9 +125,9 @@ TEST(StateVectorTest, MultiplyCoef) { const CComplex coef(0.5, 0.2); StateVector state(StateVector::Haar_random_state(n)); - auto vec = state.amplitudes(); + auto vec = state.get_amplitudes(); state.multiply_coef(coef); - auto new_vec = state.amplitudes(); + auto new_vec = state.get_amplitudes(); for (UINT i = 0; i < state.dim(); ++i) { CComplex res = new_vec[i], val = coef * (CComplex)vec[i]; @@ -160,7 +160,7 @@ TEST(StateVectorTest, EntropyCalculation) { StateVector state(n); for (UINT rep = 0; rep < max_repeat; ++rep) { state = StateVector::Haar_random_state(n); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); ASSERT_NEAR(state.get_squared_norm(), 1, eps); Eigen::VectorXcd test_state(dim); for (UINT i = 0; i < dim; ++i) test_state[i] = (CComplex)state_cp[i]; @@ -181,7 +181,7 @@ TEST(StateVectorTest, GetMarginalProbability) { const UINT n = 2; const UINT dim = 1 << n; StateVector state(StateVector::Haar_random_state(n)); - auto state_cp = state.amplitudes(); + auto state_cp = state.get_amplitudes(); std::vector probs; for (UINT i = 0; i < dim; ++i) { probs.push_back(internal::squared_norm(state_cp[i])); diff --git a/tests/util/util.hpp b/tests/util/util.hpp index b87aae46..73a7a433 100644 --- a/tests/util/util.hpp +++ b/tests/util/util.hpp @@ -10,8 +10,8 @@ using namespace std::complex_literals; using namespace scaluq; inline bool same_state(const StateVector& s1, const StateVector& s2, const double eps = 1e-12) { - auto s1_cp = s1.amplitudes(); - auto s2_cp = s2.amplitudes(); + auto s1_cp = s1.get_amplitudes(); + auto s2_cp = s2.get_amplitudes(); assert(s1.n_qubits() == s2.n_qubits()); for (UINT i = 0; i < s1.dim(); ++i) { if (std::abs((std::complex)s1_cp[i] - (std::complex)s2_cp[i]) > eps) @@ -23,8 +23,8 @@ inline bool same_state(const StateVector& s1, const StateVector& s2, const doubl inline bool same_state_except_global_phase(const StateVector& s1, const StateVector& s2, const double eps = 1e-12) { - auto s1_cp = s1.amplitudes(); - auto s2_cp = s2.amplitudes(); + auto s1_cp = s1.get_amplitudes(); + auto s2_cp = s2.get_amplitudes(); assert(s1.n_qubits() == s2.n_qubits()); UINT significant = 0; for (UINT i = 0; i < s1.dim(); ++i) { From 042220806f3ebac2a1c62652c332dfe42d87d0ba Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 27 Aug 2024 01:40:05 +0000 Subject: [PATCH 25/55] fix binding.cpp --- python/binding.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/binding.cpp b/python/binding.cpp index 5bed3c9d..6c1fb5ed 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -122,7 +122,9 @@ NB_MODULE(scaluq_core, m) { .def("set_computational_basis", &StateVector::set_computational_basis, "Initialize with computational basis \\ket{\\mathrm{basis}}.") - .def("amplitudes", &StateVector::amplitudes, "Get all amplitudes with as `list[complex]`.") + .def("amplitudes", + &StateVector::get_amplitudes, + "Get all amplitudes with as `list[complex]`.") .def("n_qubits", &StateVector::n_qubits, "Get num of qubits.") .def("dim", &StateVector::dim, "Get dimension of the vector ($=2^\\mathrm{n\\_qubits}$).") .def("get_squared_norm", @@ -226,7 +228,7 @@ NB_MODULE(scaluq_core, m) { "Construct batched state vectors with Haar random states. If seed is not " "specified, the value from random device is used.") .def("amplitudes", - &StateVectorBatched::amplitudes, + &StateVectorBatched::get_amplitudes, "Get all amplitudes with as `list[list[complex]]`.") .def("get_squared_norm", &StateVectorBatched::get_squared_norm, From 23c0b429ae86220c65c85f5b1715bf6587f05bea Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 30 Aug 2024 10:24:32 +0900 Subject: [PATCH 26/55] fix ControlTest --- tests/gate/gate_test.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 3711ab90..cfc1652d 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -425,23 +425,20 @@ void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_ template void test_standard_gates(Factory factory, UINT n) { Random random; + std::vector shuffled(n); + std::iota(shuffled.begin(), shuffled.end(), 0ULL); + for (UINT i : std::views::iota(0ULL, n) | std::views::reverse) { + UINT j = random.int32() % (i + 1); + if (i != j) std::swap(shuffled[i], shuffled[j]); + } std::vector targets(num_target); for (UINT i : std::views::iota(0ULL, num_target)) { - targets[i] = random.int32() % (n - i); - for (UINT j : std::views::iota(0ULL, i)) { - if (targets[i] == targets[j]) targets[i] = n - 1 - j; - } + targets[i] = shuffled[i]; } UINT num_control = random.int32() % (n - num_target + 1); std::vector controls(num_control); for (UINT i : std::views::iota(0ULL, num_control)) { - controls[i] = random.int32() % (n - num_target - i); - for (UINT j : std::views::iota(0ULL, num_target)) { - if (controls[i] == targets[j]) controls[i] = n - 1 - j; - } - for (UINT j : std::views::iota(0ULL, i)) { - if (controls[i] == controls[j]) controls[i] = n - num_target - 1 - j; - } + controls[i] = shuffled[num_target + i]; } UINT control_mask = 0ULL; for (UINT c : controls) control_mask |= 1ULL << c; From 04a18e8e7760bfad92acf5ff87b73cfc01c5c597 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 30 Aug 2024 01:44:33 +0000 Subject: [PATCH 27/55] use macro --- exe/main.cpp | 10 +++++++++- scaluq/constant.hpp | 27 ++++++++++++++------------- scaluq/gate/gate_standard.hpp | 8 ++++---- scaluq/gate/merge_gate.cpp | 28 ++++++++++++++-------------- scaluq/gate/update_ops_standard.cpp | 8 +++----- tests/gate/merge_test.cpp | 26 +++++++++++++------------- tests/gate/param_gate_test.cpp | 2 +- 7 files changed, 58 insertions(+), 51 deletions(-) diff --git a/exe/main.cpp b/exe/main.cpp index 7354deb2..1c6bed85 100644 --- a/exe/main.cpp +++ b/exe/main.cpp @@ -14,7 +14,15 @@ using namespace std; void run() { std::uint64_t n_qubits = 5; - auto state = StateVector::Haar_random_state(n_qubits); + Kokkos::parallel_for( + 10, KOKKOS_LAMBDA(int i) { + Kokkos::printf("{%lf, %lf, %lf, %lf}\n", + EXAMPLE(0).real(), + EXAMPLE(1).real(), + EXAMPLE(2).real(), + EXAMPLE(3).real()); + Kokkos::printf("%lf\n", INVERSE_SQRT2); + }); } int main() { diff --git a/scaluq/constant.hpp b/scaluq/constant.hpp index 590bd9b6..c0c9081b 100644 --- a/scaluq/constant.hpp +++ b/scaluq/constant.hpp @@ -6,25 +6,26 @@ #include "types.hpp" namespace scaluq { + +#define DEF_MATH_CONSTANT(TRAIT, VALUE) \ + template \ + inline constexpr auto TRAIT##_v = std::enable_if_t, T>(VALUE); \ + inline constexpr auto TRAIT = TRAIT##_v + //! PI value -KOKKOS_INLINE_FUNCTION -double PI() { return 3.141592653589793; } +DEF_MATH_CONSTANT(PI, 3.141592653589793); //! square root of 2 -KOKKOS_INLINE_FUNCTION -double SQRT2() { return 1.4142135623730950; } +DEF_MATH_CONSTANT(SQRT2, 1.4142135623730950); //! inverse square root of 2 -KOKKOS_INLINE_FUNCTION -double INVERSE_SQRT2() { return 0.707106781186547; } +DEF_MATH_CONSTANT(INVERSE_SQRT2, 0.7071067811865475); //! cosine pi/8 -KOKKOS_INLINE_FUNCTION -double COSPI8() { return 0.923879532511287; } +DEF_MATH_CONSTANT(COSPI8, 0.923879532511287); //! sine pi/8 -KOKKOS_INLINE_FUNCTION -double SINPI8() { return 0.382683432365090; } +DEF_MATH_CONSTANT(SINPI8, 0.382683432365090); //! identity matrix KOKKOS_INLINE_FUNCTION @@ -51,17 +52,17 @@ matrix_2_2 S_DAG_GATE_MATRIX() { return {1, 0, 0, Complex(0, -1)}; } //! T-gate KOKKOS_INLINE_FUNCTION matrix_2_2 T_GATE_MATRIX() { - return {COSPI8() - Complex(0, SINPI8()), 0., 0., COSPI8() + Complex(0, SINPI8()) * SINPI8()}; + return {COSPI8 - Complex(0, SINPI8), 0., 0., COSPI8 + Complex(0, SINPI8) * SINPI8}; } //! Tdag-gate KOKKOS_INLINE_FUNCTION matrix_2_2 T_DAG_GATE_MATRIX() { - return {COSPI8() + Complex(0, SINPI8()), 0., 0., COSPI8() - Complex(0, SINPI8())}; + return {COSPI8 + Complex(0, SINPI8), 0., 0., COSPI8 - Complex(0, SINPI8)}; } //! Hadamard gate KOKKOS_INLINE_FUNCTION matrix_2_2 HADAMARD_MATRIX() { - return {INVERSE_SQRT2(), INVERSE_SQRT2(), INVERSE_SQRT2(), -INVERSE_SQRT2()}; + return {0.7071067811865475, 0.7071067811865475, 0.7071067811865475, -0.7071067811865475}; } //! square root of X gate KOKKOS_INLINE_FUNCTION diff --git a/scaluq/gate/gate_standard.hpp b/scaluq/gate/gate_standard.hpp index e1046155..f5d43de0 100644 --- a/scaluq/gate/gate_standard.hpp +++ b/scaluq/gate/gate_standard.hpp @@ -422,13 +422,13 @@ class U2GateImpl : public GateBase { Gate get_inverse() const override { return std::make_shared( - _target_mask, _control_mask, -_lambda - PI(), -_phi + PI()); + _target_mask, _control_mask, -_lambda - PI, -_phi + PI); } ComplexMatrix get_matrix() const override { ComplexMatrix mat(2, 2); - mat << std::cos(PI() / 4.), -std::exp(1i * _lambda) * std::sin(PI() / 4.), - std::exp(1i * _phi) * std::sin(PI() / 4.), - std::exp(1i * _phi) * std::exp(1i * _lambda) * std::cos(PI() / 4.); + mat << std::cos(PI / 4.), -std::exp(1i * _lambda) * std::sin(PI / 4.), + std::exp(1i * _phi) * std::sin(PI / 4.), + std::exp(1i * _phi) * std::exp(1i * _lambda) * std::cos(PI / 4.); return mat; } diff --git a/scaluq/gate/merge_gate.cpp b/scaluq/gate/merge_gate.cpp index 844984fc..5e707114 100644 --- a/scaluq/gate/merge_gate.cpp +++ b/scaluq/gate/merge_gate.cpp @@ -37,16 +37,16 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { if (target1 == target2) { if (pauli_id1 == pauli_id2) return {gate::I(), 0.}; if (pauli_id1 == 1) { - if (pauli_id2 == 2) return {gate::Z(target1), -PI() / 2}; - if (pauli_id2 == 3) return {gate::Y(target1), PI() / 2}; + if (pauli_id2 == 2) return {gate::Z(target1), -PI / 2}; + if (pauli_id2 == 3) return {gate::Y(target1), PI / 2}; } if (pauli_id1 == 2) { - if (pauli_id2 == 3) return {gate::X(target1), -PI() / 2}; - if (pauli_id2 == 1) return {gate::Z(target1), PI() / 2}; + if (pauli_id2 == 3) return {gate::X(target1), -PI / 2}; + if (pauli_id2 == 1) return {gate::Z(target1), PI / 2}; } if (pauli_id1 == 3) { - if (pauli_id2 == 1) return {gate::Y(target1), -PI() / 2}; - if (pauli_id2 == 2) return {gate::X(target1), PI() / 2}; + if (pauli_id2 == 1) return {gate::Y(target1), -PI / 2}; + if (pauli_id2 == 2) return {gate::X(target1), PI / 2}; } } } @@ -99,11 +99,11 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { std::uint64_t target1 = gate1->get_target_qubit_list()[0]; std::uint64_t target2 = gate2->get_target_qubit_list()[0]; if (target1 == target2) { - double phase1 = oct_phase1 ? oct_phase1.value() * PI() / 4 + double phase1 = oct_phase1 ? oct_phase1.value() * PI / 4 : gate_type1 == GateType::RZ ? RZGate(gate1)->angle() : U1Gate(gate1)->lambda(); double global_phase1 = gate_type1 == GateType::RZ ? -RZGate(gate1)->angle() / 2 : 0.; - double phase2 = oct_phase2 ? oct_phase2.value() * PI() / 4 + double phase2 = oct_phase2 ? oct_phase2.value() * PI / 4 : gate_type2 == GateType::RZ ? RZGate(gate2)->angle() : U1Gate(gate2)->lambda(); double global_phase2 = gate_type2 == GateType::RZ ? -RZGate(gate2)->angle() / 2 : 0.; @@ -114,9 +114,9 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { // Special case: RX auto get_rx_angle = [&](Gate gate, GateType gate_type) -> std::optional { if (gate_type == GateType::I) return 0.; - if (gate_type == GateType::X) return PI(); - if (gate_type == GateType::SqrtX) return PI() / 2; - if (gate_type == GateType::SqrtXdag) return -PI() / 2; + if (gate_type == GateType::X) return PI; + if (gate_type == GateType::SqrtX) return PI / 2; + if (gate_type == GateType::SqrtXdag) return -PI / 2; if (gate_type == GateType::RX) return RXGate(gate)->angle(); return std::nullopt; }; @@ -136,9 +136,9 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { // Special case: RY auto get_ry_angle = [&](Gate gate, GateType gate_type) -> std::optional { if (gate_type == GateType::I) return 0.; - if (gate_type == GateType::Y) return PI(); - if (gate_type == GateType::SqrtY) return PI() / 2; - if (gate_type == GateType::SqrtYdag) return -PI() / 2; + if (gate_type == GateType::Y) return PI; + if (gate_type == GateType::SqrtY) return PI / 2; + if (gate_type == GateType::SqrtYdag) return -PI / 2; if (gate_type == GateType::RY) return RYGate(gate)->angle(); return std::nullopt; }; diff --git a/scaluq/gate/update_ops_standard.cpp b/scaluq/gate/update_ops_standard.cpp index 123bd36c..7edc079a 100644 --- a/scaluq/gate/update_ops_standard.cpp +++ b/scaluq/gate/update_ops_standard.cpp @@ -79,13 +79,11 @@ void sdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVecto } void t_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { - one_target_phase_gate( - target_mask, control_mask, Complex(INVERSE_SQRT2(), INVERSE_SQRT2()), state); + one_target_phase_gate(target_mask, control_mask, Complex(INVERSE_SQRT2, INVERSE_SQRT2), state); } void tdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { - one_target_phase_gate( - target_mask, control_mask, Complex(INVERSE_SQRT2(), -INVERSE_SQRT2()), state); + one_target_phase_gate(target_mask, control_mask, Complex(INVERSE_SQRT2, -INVERSE_SQRT2), state); } void sqrtx_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { @@ -186,7 +184,7 @@ void u2_gate(std::uint64_t target_mask, double lambda, StateVector& state) { one_target_dense_matrix_gate( - target_mask, control_mask, get_IBMQ_matrix(PI() / 2., phi, lambda), state); + target_mask, control_mask, get_IBMQ_matrix(PI / 2., phi, lambda), state); } void u3_gate(std::uint64_t target_mask, diff --git a/tests/gate/merge_test.cpp b/tests/gate/merge_test.cpp index 590f36de..04d8ede4 100644 --- a/tests/gate/merge_test.cpp +++ b/tests/gate/merge_test.cpp @@ -29,15 +29,15 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::SqrtYdag(target)); gates.push_back(gate::P0(target)); gates.push_back(gate::P1(target)); - gates.push_back(gate::RX(target, random.uniform() * PI() * 2)); - gates.push_back(gate::RY(target, random.uniform() * PI() * 2)); - gates.push_back(gate::RZ(target, random.uniform() * PI() * 2)); - gates.push_back(gate::U1(target, random.uniform() * PI() * 2)); - gates.push_back(gate::U2(target, random.uniform() * PI() * 2, random.uniform() * PI() * 2)); + gates.push_back(gate::RX(target, random.uniform() * PI * 2)); + gates.push_back(gate::RY(target, random.uniform() * PI * 2)); + gates.push_back(gate::RZ(target, random.uniform() * PI * 2)); + gates.push_back(gate::U1(target, random.uniform() * PI * 2)); + gates.push_back(gate::U2(target, random.uniform() * PI * 2, random.uniform() * PI * 2)); gates.push_back(gate::U3(target, - random.uniform() * PI() * 2, - random.uniform() * PI() * 2, - random.uniform() * PI() * 2)); + random.uniform() * PI * 2, + random.uniform() * PI * 2, + random.uniform() * PI * 2)); gates.push_back( gate::OneTargetMatrix(target, {std::array{Complex(random.uniform(), random.uniform()), @@ -49,7 +49,7 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::Swap(target, target ^ 1)); } gates.push_back(gate::I()); - gates.push_back(gate::GlobalPhase(random.uniform() * PI() * 2)); + gates.push_back(gate::GlobalPhase(random.uniform() * PI * 2)); gates.push_back( gate::TwoTargetMatrix(0, 1, @@ -72,12 +72,12 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::Pauli(PauliOperator("X 0 Y 1", random.uniform()))); gates.push_back(gate::Pauli(PauliOperator("Z 0", random.uniform()))); gates.push_back(gate::Pauli(PauliOperator("Z 1", random.uniform()))); - gates.push_back(gate::PauliRotation(PauliOperator("X 0 Y 1", random.uniform()), - random.uniform() * PI() * 2)); gates.push_back( - gate::PauliRotation(PauliOperator("Z 0", random.uniform()), random.uniform() * PI() * 2)); + gate::PauliRotation(PauliOperator("X 0 Y 1", random.uniform()), random.uniform() * PI * 2)); gates.push_back( - gate::PauliRotation(PauliOperator("Z 1", random.uniform()), random.uniform() * PI() * 2)); + gate::PauliRotation(PauliOperator("Z 0", random.uniform()), random.uniform() * PI * 2)); + gates.push_back( + gate::PauliRotation(PauliOperator("Z 1", random.uniform()), random.uniform() * PI * 2)); for (auto&& g1 : gates) { for (auto&& g2 : gates) { std::uint64_t n = 2; diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index 526a50b7..551be512 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -103,7 +103,7 @@ TEST(ParamGateTest, ApplyPProbablisticGate) { StateVector state(1); for ([[maybe_unused]] auto _ : std::views::iota(0, 100)) { std::uint64_t before = state.sampling(1)[0]; - probgate->update_quantum_state(state, scaluq::PI()); + probgate->update_quantum_state(state, scaluq::PI); std::uint64_t after = state.sampling(1)[0]; if (before != after) { x_cnt++; From dbd28345fe7650fbc91332ca2c098a3ee044a4b7 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 30 Aug 2024 10:59:58 +0900 Subject: [PATCH 28/55] add param control gate test --- tests/gate/gate_test.cpp | 44 +++++++++--------- tests/gate/param_gate_test.cpp | 83 ++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 22 deletions(-) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index cfc1652d..4d43be11 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -423,7 +423,7 @@ void test_gate(Gate gate_control, Gate gate_simple, UINT n_qubits, UINT control_ } template -void test_standard_gates(Factory factory, UINT n) { +void test_standard_gate_control(Factory factory, UINT n) { Random random; std::vector shuffled(n); std::iota(shuffled.begin(), shuffled.end(), 0ULL); @@ -517,27 +517,27 @@ void test_pauli_control(UINT n) { TEST(GateTest, Control) { UINT n = 10; for ([[maybe_unused]] UINT _ : std::views::iota(0, 10)) { - test_standard_gates<0, 1>(gate::GlobalPhase, n); - test_standard_gates<1, 0>(gate::X, n); - test_standard_gates<1, 0>(gate::Y, n); - test_standard_gates<1, 0>(gate::Z, n); - test_standard_gates<1, 0>(gate::S, n); - test_standard_gates<1, 0>(gate::Sdag, n); - test_standard_gates<1, 0>(gate::T, n); - test_standard_gates<1, 0>(gate::Tdag, n); - test_standard_gates<1, 0>(gate::SqrtX, n); - test_standard_gates<1, 0>(gate::SqrtXdag, n); - test_standard_gates<1, 0>(gate::SqrtY, n); - test_standard_gates<1, 0>(gate::SqrtYdag, n); - test_standard_gates<1, 0>(gate::P0, n); - test_standard_gates<1, 0>(gate::P1, n); - test_standard_gates<1, 1>(gate::RX, n); - test_standard_gates<1, 1>(gate::RY, n); - test_standard_gates<1, 1>(gate::RZ, n); - test_standard_gates<1, 1>(gate::U1, n); - test_standard_gates<1, 2>(gate::U2, n); - test_standard_gates<1, 3>(gate::U3, n); - test_standard_gates<2, 0>(gate::Swap, n); + test_standard_gate_control<0, 1>(gate::GlobalPhase, n); + test_standard_gate_control<1, 0>(gate::X, n); + test_standard_gate_control<1, 0>(gate::Y, n); + test_standard_gate_control<1, 0>(gate::Z, n); + test_standard_gate_control<1, 0>(gate::S, n); + test_standard_gate_control<1, 0>(gate::Sdag, n); + test_standard_gate_control<1, 0>(gate::T, n); + test_standard_gate_control<1, 0>(gate::Tdag, n); + test_standard_gate_control<1, 0>(gate::SqrtX, n); + test_standard_gate_control<1, 0>(gate::SqrtXdag, n); + test_standard_gate_control<1, 0>(gate::SqrtY, n); + test_standard_gate_control<1, 0>(gate::SqrtYdag, n); + test_standard_gate_control<1, 0>(gate::P0, n); + test_standard_gate_control<1, 0>(gate::P1, n); + test_standard_gate_control<1, 1>(gate::RX, n); + test_standard_gate_control<1, 1>(gate::RY, n); + test_standard_gate_control<1, 1>(gate::RZ, n); + test_standard_gate_control<1, 1>(gate::U1, n); + test_standard_gate_control<1, 2>(gate::U2, n); + test_standard_gate_control<1, 3>(gate::U3, n); + test_standard_gate_control<2, 0>(gate::Swap, n); test_pauli_control(n); test_pauli_control(n); } diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index d7a4c0ef..15a66141 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -116,3 +116,86 @@ TEST(ParamGateTest, ApplyPProbablisticGate) { ASSERT_GT(i_cnt, 0); ASSERT_LT(x_cnt, i_cnt); } + +void test_gate( + ParamGate gate_control, ParamGate gate_simple, UINT n_qubits, UINT control_mask, double param) { + StateVector state = StateVector::Haar_random_state(n_qubits); + auto amplitudes = state.amplitudes(); + StateVector state_controlled(n_qubits - std::popcount(control_mask)); + std::vector amplitudes_controlled(state_controlled.dim()); + for (UINT i : std::views::iota(0ULL, state_controlled.dim())) { + amplitudes_controlled[i] = + amplitudes[internal::insert_zero_at_mask_positions(i, control_mask) | control_mask]; + } + state_controlled.load(amplitudes_controlled); + gate_control->update_quantum_state(state, param); + gate_simple->update_quantum_state(state_controlled, param); + amplitudes = state.amplitudes(); + amplitudes_controlled = state_controlled.amplitudes(); + for (UINT i : std::views::iota(0ULL, state_controlled.dim())) { + ASSERT_NEAR( + Kokkos::abs(amplitudes_controlled[i] - + amplitudes[internal::insert_zero_at_mask_positions(i, control_mask) | + control_mask]), + 0., + eps); + } +} + +template +void test_param_rotation_control(Factory factory, UINT n) { + std::cerr << "prx" << std::endl; + Random random; + std::vector shuffled(n); + std::iota(shuffled.begin(), shuffled.end(), 0ULL); + for (UINT i : std::views::iota(0ULL, n) | std::views::reverse) { + UINT j = random.int32() % (i + 1); + if (i != j) std::swap(shuffled[i], shuffled[j]); + } + UINT target = shuffled[0]; + UINT num_control = random.int32() % n; + std::vector controls(num_control); + for (UINT i : std::views::iota(0ULL, num_control)) { + controls[i] = shuffled[1 + i]; + } + UINT control_mask = 0ULL; + for (UINT c : controls) control_mask |= 1ULL << c; + double param = random.uniform() * PI() * 2; + ParamGate g1 = factory(target, 1., controls); + ParamGate g2 = factory(target - std::popcount(control_mask & ((1ULL << target) - 1)), 1., {}); + test_gate(g1, g2, n, control_mask, param); +} + +void test_ppauli_control(UINT n) { + std::cerr << "ppauli" << std::endl; + PauliOperator::Data data1, data2; + std::vector controls; + UINT control_mask = 0; + UINT num_control = 0; + Random random; + for (UINT i : std::views::iota(0ULL, n)) { + UINT dat = random.int32() % 12; + if (dat < 4) { + data1.add_single_pauli(i, dat); + data2.add_single_pauli(i - num_control, dat); + } else if (dat < 8) { + controls.push_back(i); + control_mask |= 1ULL << i; + num_control++; + } + } + double param = random.uniform() * PI() * 2; + ParamGate g1 = gate::PPauliRotation(PauliOperator(data1), 1., controls); + ParamGate g2 = gate::PPauliRotation(PauliOperator(data2), 1., {}); + test_gate(g1, g2, n, control_mask, param); +} + +TEST(ParamGateTest, Control) { + UINT n = 10; + for ([[maybe_unused]] UINT _ : std::views::iota(0, 10)) { + test_param_rotation_control(gate::PRX, n); + test_param_rotation_control(gate::PRY, n); + test_param_rotation_control(gate::PRZ, n); + test_ppauli_control(n); + } +} From fc4177cfd2522b0c64763187d69040106eda4395 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 30 Aug 2024 02:15:02 +0000 Subject: [PATCH 29/55] use Kokkos::Array --- scaluq/constant.hpp | 50 ++++++++++++++++--------- scaluq/gate/gate_matrix.hpp | 41 ++++++++++---------- scaluq/gate/update_ops.hpp | 10 +++-- scaluq/gate/update_ops_dense_matrix.cpp | 24 ++++++------ scaluq/gate/update_ops_pauli.cpp | 4 +- scaluq/gate/update_ops_standard.cpp | 17 +++++---- scaluq/operator/operator.cpp | 4 +- scaluq/operator/pauli_operator.cpp | 8 ++-- scaluq/types.hpp | 16 -------- scaluq/util/utility.hpp | 13 ++++--- tests/gate/gate_test.cpp | 2 +- 11 files changed, 95 insertions(+), 94 deletions(-) diff --git a/scaluq/constant.hpp b/scaluq/constant.hpp index c0c9081b..6dbf02a6 100644 --- a/scaluq/constant.hpp +++ b/scaluq/constant.hpp @@ -12,6 +12,15 @@ namespace scaluq { inline constexpr auto TRAIT##_v = std::enable_if_t, T>(VALUE); \ inline constexpr auto TRAIT = TRAIT##_v +#define DEFINE_ACCESSIBLE_ARRAY(NAME, TYPE, SIZE, ...) \ + KOKKOS_INLINE_FUNCTION \ + Kokkos::Array NAME##_ARRAY() { return {__VA_ARGS__}; } \ + KOKKOS_INLINE_FUNCTION \ + TYPE NAME(std::size_t i) { return NAME##_ARRAY()[i]; } + +KOKKOS_INLINE_FUNCTION +Kokkos::Array EXAMPLE() { return {1.0, 2.0, 3.0, 4.0}; } + //! PI value DEF_MATH_CONSTANT(PI, 3.141592653589793); @@ -29,71 +38,76 @@ DEF_MATH_CONSTANT(SINPI8, 0.382683432365090); //! identity matrix KOKKOS_INLINE_FUNCTION -matrix_2_2 I_GATE() { return {1, 0, 0, 1}; } +Kokkos::Array, 2> I_GATE() { return {1, 0, 0, 1}; } //! Pauli matrix X KOKKOS_INLINE_FUNCTION -matrix_2_2 X_GATE() { return {0, 1, 1, 0}; } +Kokkos::Array, 2> X_GATE() { return {0, 1, 1, 0}; } //! Pauli matrix Y KOKKOS_INLINE_FUNCTION -matrix_2_2 Y_GATE() { return {0, Complex(0, -1), Complex(0, 1), 0}; } +Kokkos::Array, 2> Y_GATE() { + return {0, Complex(0, -1), Complex(0, 1), 0}; +} //! Pauli matrix Z KOKKOS_INLINE_FUNCTION -matrix_2_2 Z_GATE() { return {1, 0, 0, -1}; } +Kokkos::Array, 2> Z_GATE() { return {1, 0, 0, -1}; } //! list of Pauli matrix I,X,Y,Z -// std::array PAULI_MATRIX = {I_GATE, X_GATE, Y_GATE, Z_GATE}; +// std::array, 2>, 4> PAULI_MATRIX = {I_GATE, X_GATE, +// Y_GATE, Z_GATE}; //! S-gate KOKKOS_INLINE_FUNCTION -matrix_2_2 S_GATE_MATRIX() { return {1, 0, 0, Complex(0, 1)}; } +Kokkos::Array, 2> S_GATE_MATRIX() { return {1, 0, 0, Complex(0, 1)}; } //! Sdag-gate KOKKOS_INLINE_FUNCTION -matrix_2_2 S_DAG_GATE_MATRIX() { return {1, 0, 0, Complex(0, -1)}; } +Kokkos::Array, 2> S_DAG_GATE_MATRIX() { + return {1, 0, 0, Complex(0, -1)}; +} //! T-gate KOKKOS_INLINE_FUNCTION -matrix_2_2 T_GATE_MATRIX() { +Kokkos::Array, 2> T_GATE_MATRIX() { return {COSPI8 - Complex(0, SINPI8), 0., 0., COSPI8 + Complex(0, SINPI8) * SINPI8}; } //! Tdag-gate KOKKOS_INLINE_FUNCTION -matrix_2_2 T_DAG_GATE_MATRIX() { +Kokkos::Array, 2> T_DAG_GATE_MATRIX() { return {COSPI8 + Complex(0, SINPI8), 0., 0., COSPI8 - Complex(0, SINPI8)}; } //! Hadamard gate KOKKOS_INLINE_FUNCTION -matrix_2_2 HADAMARD_MATRIX() { +Kokkos::Array, 2> HADAMARD_MATRIX() { return {0.7071067811865475, 0.7071067811865475, 0.7071067811865475, -0.7071067811865475}; } //! square root of X gate KOKKOS_INLINE_FUNCTION -matrix_2_2 SQRT_X_GATE_MATRIX() { +Kokkos::Array, 2> SQRT_X_GATE_MATRIX() { return {Complex(0.5, 0.5), Complex(0.5, -0.5), Complex(0.5, -0.5), Complex(0.5, 0.5)}; } //! square root of Y gate KOKKOS_INLINE_FUNCTION -matrix_2_2 SQRT_Y_GATE_MATRIX() { +Kokkos::Array, 2> SQRT_Y_GATE_MATRIX() { return {Complex(0.5, 0.5), Complex(-0.5, -0.5), Complex(0.5, 0.5), Complex(0.5, 0.5)}; } //! square root dagger of X gate KOKKOS_INLINE_FUNCTION -matrix_2_2 SQRT_X_DAG_GATE_MATRIX() { +Kokkos::Array, 2> SQRT_X_DAG_GATE_MATRIX() { return {Complex(0.5, -0.5), Complex(0.5, 0.5), Complex(0.5, 0.5), Complex(0.5, -0.5)}; } //! square root dagger of Y gate KOKKOS_INLINE_FUNCTION -matrix_2_2 SQRT_Y_DAG_GATE_MATRIX() { +Kokkos::Array, 2> SQRT_Y_DAG_GATE_MATRIX() { return {Complex(0.5, -0.5), Complex(0.5, -0.5), Complex(-0.5, 0.5), Complex(0.5, -0.5)}; } //! Projection to 0 KOKKOS_INLINE_FUNCTION -matrix_2_2 PROJ_0_MATRIX() { return {1, 0, 0, 0}; } +Kokkos::Array, 2> PROJ_0_MATRIX() { return {1, 0, 0, 0}; } //! Projection to 1 KOKKOS_INLINE_FUNCTION -matrix_2_2 PROJ_1_MATRIX() { return {0, 0, 0, 1}; } +Kokkos::Array, 2> PROJ_1_MATRIX() { return {0, 0, 0, 1}; } //! complex values for exp(j * i*pi/4 ) KOKKOS_INLINE_FUNCTION -array_4 PHASE_90ROT() { return {1., Complex(0, 1), -1, Complex(0, -1)}; } +Kokkos::Array PHASE_90ROT() { return {1., Complex(0, 1), -1, Complex(0, -1)}; } //! complex values for exp(-j * i*pi/4 ) KOKKOS_INLINE_FUNCTION -array_4 PHASE_M90ROT() { return {1., Complex(0, -1), -1, Complex(0, 1)}; } +Kokkos::Array PHASE_M90ROT() { return {1., Complex(0, -1), -1, Complex(0, 1)}; } } // namespace scaluq diff --git a/scaluq/gate/gate_matrix.hpp b/scaluq/gate/gate_matrix.hpp index 5d80ff23..e814f09f 100644 --- a/scaluq/gate/gate_matrix.hpp +++ b/scaluq/gate/gate_matrix.hpp @@ -11,36 +11,35 @@ namespace scaluq { namespace internal { class OneTargetMatrixGateImpl : public GateBase { - matrix_2_2 _matrix; + Kokkos::Array, 2> _matrix; public: OneTargetMatrixGateImpl(std::uint64_t target_mask, std::uint64_t control_mask, const std::array, 2>& matrix) : GateBase(target_mask, control_mask) { - _matrix.val[0][0] = matrix[0][0]; - _matrix.val[0][1] = matrix[0][1]; - _matrix.val[1][0] = matrix[1][0]; - _matrix.val[1][1] = matrix[1][1]; + _matrix[0][0] = matrix[0][0]; + _matrix[0][1] = matrix[0][1]; + _matrix[1][0] = matrix[1][0]; + _matrix[1][1] = matrix[1][1]; } std::array, 2> matrix() const { - return {_matrix.val[0][0], _matrix.val[0][1], _matrix.val[1][0], _matrix.val[1][1]}; + return {_matrix[0][0], _matrix[0][1], _matrix[1][0], _matrix[1][1]}; } Gate get_inverse() const override { return std::make_shared( _target_mask, _control_mask, - std::array, 2>{Kokkos::conj(_matrix.val[0][0]), - Kokkos::conj(_matrix.val[1][0]), - Kokkos::conj(_matrix.val[0][1]), - Kokkos::conj(_matrix.val[1][1])}); + std::array, 2>{Kokkos::conj(_matrix[0][0]), + Kokkos::conj(_matrix[1][0]), + Kokkos::conj(_matrix[0][1]), + Kokkos::conj(_matrix[1][1])}); } ComplexMatrix get_matrix() const override { ComplexMatrix mat(2, 2); - mat << this->_matrix.val[0][0], this->_matrix.val[0][1], this->_matrix.val[1][0], - this->_matrix.val[1][1]; + mat << this->_matrix[0][0], this->_matrix[0][1], this->_matrix[1][0], this->_matrix[1][1]; return mat; } @@ -51,7 +50,7 @@ class OneTargetMatrixGateImpl : public GateBase { }; class TwoTargetMatrixGateImpl : public GateBase { - matrix_4_4 _matrix; + Kokkos::Array, 4> _matrix; public: TwoTargetMatrixGateImpl(std::uint64_t target_mask, @@ -60,7 +59,7 @@ class TwoTargetMatrixGateImpl : public GateBase { : GateBase(target_mask, control_mask) { for (std::uint64_t i : std::views::iota(0, 4)) { for (std::uint64_t j : std::views::iota(0, 4)) { - _matrix.val[i][j] = matrix[i][j]; + _matrix[i][j] = matrix[i][j]; } } } @@ -69,7 +68,7 @@ class TwoTargetMatrixGateImpl : public GateBase { std::array, 4> matrix; for (std::uint64_t i : std::views::iota(0, 4)) { for (std::uint64_t j : std::views::iota(0, 4)) { - matrix[i][j] = _matrix.val[i][j]; + matrix[i][j] = _matrix[i][j]; } } return matrix; @@ -79,7 +78,7 @@ class TwoTargetMatrixGateImpl : public GateBase { std::array, 4> matrix_dag; for (std::uint64_t i : std::views::iota(0, 4)) { for (std::uint64_t j : std::views::iota(0, 4)) { - matrix_dag[i][j] = Kokkos::conj(_matrix.val[j][i]); + matrix_dag[i][j] = Kokkos::conj(_matrix[j][i]); } } return std::make_shared( @@ -87,12 +86,10 @@ class TwoTargetMatrixGateImpl : public GateBase { } ComplexMatrix get_matrix() const override { ComplexMatrix mat(4, 4); - mat << this->_matrix.val[0][0], this->_matrix.val[0][1], this->_matrix.val[0][2], - this->_matrix.val[0][3], this->_matrix.val[1][0], this->_matrix.val[1][1], - this->_matrix.val[1][2], this->_matrix.val[1][3], this->_matrix.val[2][0], - this->_matrix.val[2][1], this->_matrix.val[2][2], this->_matrix.val[2][3], - this->_matrix.val[3][0], this->_matrix.val[3][1], this->_matrix.val[3][2], - this->_matrix.val[3][3]; + mat << this->_matrix[0][0], this->_matrix[0][1], this->_matrix[0][2], this->_matrix[0][3], + this->_matrix[1][0], this->_matrix[1][1], this->_matrix[1][2], this->_matrix[1][3], + this->_matrix[2][0], this->_matrix[2][1], this->_matrix[2][2], this->_matrix[2][3], + this->_matrix[3][0], this->_matrix[3][1], this->_matrix[3][2], this->_matrix[3][3]; return mat; } diff --git a/scaluq/gate/update_ops.hpp b/scaluq/gate/update_ops.hpp index 25b9f11c..eea32b8c 100644 --- a/scaluq/gate/update_ops.hpp +++ b/scaluq/gate/update_ops.hpp @@ -57,21 +57,23 @@ void rz_gate(std::uint64_t target_mask, double angle, StateVector& state); -matrix_2_2 get_IBMQ_matrix(double _theta, double _phi, double _lambda); +Kokkos::Array, 2> get_IBMQ_matrix(double _theta, + double _phi, + double _lambda); void one_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const matrix_2_2& matrix, + const Kokkos::Array, 2>& matrix, StateVector& state); void two_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const matrix_4_4& matrix, + const Kokkos::Array, 4>& matrix, StateVector& state); void one_target_diagonal_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const diagonal_matrix_2_2& diag, + const Kokkos::Array& diag, StateVector& state); void u1_gate(std::uint64_t target_mask, diff --git a/scaluq/gate/update_ops_dense_matrix.cpp b/scaluq/gate/update_ops_dense_matrix.cpp index faabf609..80807bf8 100644 --- a/scaluq/gate/update_ops_dense_matrix.cpp +++ b/scaluq/gate/update_ops_dense_matrix.cpp @@ -9,7 +9,7 @@ namespace scaluq { namespace internal { void one_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const matrix_2_2& matrix, + const Kokkos::Array, 2>& matrix, StateVector& state) { Kokkos::parallel_for( state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(std::uint64_t it) { @@ -18,8 +18,8 @@ void one_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t basis_1 = basis_0 | target_mask; Complex val0 = state._raw[basis_0]; Complex val1 = state._raw[basis_1]; - Complex res0 = matrix.val[0][0] * val0 + matrix.val[0][1] * val1; - Complex res1 = matrix.val[1][0] * val0 + matrix.val[1][1] * val1; + Complex res0 = matrix[0][0] * val0 + matrix[0][1] * val1; + Complex res1 = matrix[1][0] * val0 + matrix[1][1] * val1; state._raw[basis_0] = res0; state._raw[basis_1] = res1; }); @@ -28,7 +28,7 @@ void one_target_dense_matrix_gate(std::uint64_t target_mask, void two_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const matrix_4_4& matrix, + const Kokkos::Array, 4>& matrix, StateVector& state) { std::uint64_t lower_target_mask = -target_mask & target_mask; std::uint64_t upper_target_mask = target_mask ^ lower_target_mask; @@ -44,14 +44,14 @@ void two_target_dense_matrix_gate(std::uint64_t target_mask, Complex val1 = state._raw[basis_1]; Complex val2 = state._raw[basis_2]; Complex val3 = state._raw[basis_3]; - Complex res0 = matrix.val[0][0] * val0 + matrix.val[0][1] * val1 + - matrix.val[0][2] * val2 + matrix.val[0][3] * val3; - Complex res1 = matrix.val[1][0] * val0 + matrix.val[1][1] * val1 + - matrix.val[1][2] * val2 + matrix.val[1][3] * val3; - Complex res2 = matrix.val[2][0] * val0 + matrix.val[2][1] * val1 + - matrix.val[2][2] * val2 + matrix.val[2][3] * val3; - Complex res3 = matrix.val[3][0] * val0 + matrix.val[3][1] * val1 + - matrix.val[3][2] * val2 + matrix.val[3][3] * val3; + Complex res0 = matrix[0][0] * val0 + matrix[0][1] * val1 + matrix[0][2] * val2 + + matrix[0][3] * val3; + Complex res1 = matrix[1][0] * val0 + matrix[1][1] * val1 + matrix[1][2] * val2 + + matrix[1][3] * val3; + Complex res2 = matrix[2][0] * val0 + matrix[2][1] * val1 + matrix[2][2] * val2 + + matrix[2][3] * val3; + Complex res3 = matrix[3][0] * val0 + matrix[3][1] * val1 + matrix[3][2] * val2 + + matrix[3][3] * val3; state._raw[basis_0] = res0; state._raw[basis_1] = res1; state._raw[basis_2] = res2; diff --git a/scaluq/gate/update_ops_pauli.cpp b/scaluq/gate/update_ops_pauli.cpp index 58695a21..d78211c4 100644 --- a/scaluq/gate/update_ops_pauli.cpp +++ b/scaluq/gate/update_ops_pauli.cpp @@ -58,11 +58,11 @@ void pauli_rotation_gate(std::uint64_t control_mask, state._raw[basis_0] = cosval * cval_0 + Complex(0, 1) * sinval * cval_1 * - PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_0 * 2) % 4]; + PHASE_M90ROT()[(global_phase_90_rot_count + bit_parity_0 * 2) % 4]; state._raw[basis_1] = cosval * cval_1 + Complex(0, 1) * sinval * cval_0 * - PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_1 * 2) % 4]; + PHASE_M90ROT()[(global_phase_90_rot_count + bit_parity_1 * 2) % 4]; }); Kokkos::fence(); } diff --git a/scaluq/gate/update_ops_standard.cpp b/scaluq/gate/update_ops_standard.cpp index 7edc079a..f51d6672 100644 --- a/scaluq/gate/update_ops_standard.cpp +++ b/scaluq/gate/update_ops_standard.cpp @@ -116,7 +116,8 @@ void rx_gate(std::uint64_t target_mask, StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); - matrix_2_2 matrix = {cosval, Complex(0, -sinval), Complex(0, -sinval), cosval}; + Kokkos::Array, 2> matrix = { + cosval, Complex(0, -sinval), Complex(0, -sinval), cosval}; one_target_dense_matrix_gate(target_mask, control_mask, matrix, state); } @@ -126,20 +127,20 @@ void ry_gate(std::uint64_t target_mask, StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); - matrix_2_2 matrix = {cosval, -sinval, sinval, cosval}; + Kokkos::Array, 2> matrix = {cosval, -sinval, sinval, cosval}; one_target_dense_matrix_gate(target_mask, control_mask, matrix, state); } void one_target_diagonal_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const diagonal_matrix_2_2& diag, + const Kokkos::Array& diag, StateVector& state) { Kokkos::parallel_for( state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(std::uint64_t it) { std::uint64_t basis = insert_zero_at_mask_positions(it, target_mask | control_mask) | control_mask; - state._raw[basis] *= diag.val[0]; - state._raw[basis | target_mask] *= diag.val[1]; + state._raw[basis] *= diag[0]; + state._raw[basis | target_mask] *= diag[1]; }); Kokkos::fence(); } @@ -150,11 +151,13 @@ void rz_gate(std::uint64_t target_mask, StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); - diagonal_matrix_2_2 diag = {Complex(cosval, -sinval), Complex(cosval, sinval)}; + Kokkos::Array diag = {Complex(cosval, -sinval), Complex(cosval, sinval)}; one_target_diagonal_matrix_gate(target_mask, control_mask, diag, state); } -matrix_2_2 get_IBMQ_matrix(double theta, double phi, double lambda) { +Kokkos::Array, 2> get_IBMQ_matrix(double theta, + double phi, + double lambda) { Complex exp_val1 = Kokkos::exp(Complex(0, phi)); Complex exp_val2 = Kokkos::exp(Complex(0, lambda)); Complex cos_val = Kokkos::cos(theta / 2.); diff --git a/scaluq/operator/operator.cpp b/scaluq/operator/operator.cpp index ee17d8d2..334f2a2d 100644 --- a/scaluq/operator/operator.cpp +++ b/scaluq/operator/operator.cpp @@ -133,7 +133,7 @@ Complex Operator::get_expectation_value(const StateVector& state_vector) const { sizeof(std::uint64_t) * 8 - Kokkos::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = Kokkos::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_90ROT().val[global_phase_90rot_count % 4]; + Complex global_phase = PHASE_90ROT()[global_phase_90rot_count % 4]; std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; double tmp = @@ -204,7 +204,7 @@ Complex Operator::get_transition_amplitude(const StateVector& state_vector_bra, sizeof(std::uint64_t) * 8 - Kokkos::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = Kokkos::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_90ROT().val[global_phase_90rot_count % 4]; + Complex global_phase = PHASE_90ROT()[global_phase_90rot_count % 4]; std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; Complex tmp1 = Kokkos::conj(state_vector_bra._raw[basis_1]) * diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 65815487..36318e98 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -131,7 +131,7 @@ void PauliOperator::apply_to_state(StateVector& state_vector) const { } std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_M90ROT().val[global_phase_90rot_count % 4]; + Complex global_phase = PHASE_M90ROT()[global_phase_90rot_count % 4]; Kokkos::parallel_for( state_vector.dim() >> 1, KOKKOS_LAMBDA(std::uint64_t state_idx) { std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); @@ -170,7 +170,7 @@ Complex PauliOperator::get_expectation_value(const StateVector& state_vector) co } std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_90ROT().val[global_phase_90rot_count % 4]; + Complex global_phase = PHASE_90ROT()[global_phase_90rot_count % 4]; double res; Kokkos::parallel_reduce( state_vector.dim() >> 1, @@ -214,7 +214,7 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ } std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_90ROT().val[global_phase_90rot_count % 4]; + Complex global_phase = PHASE_90ROT()[global_phase_90rot_count % 4]; Complex res; Kokkos::parallel_reduce( state_vector_bra.dim() >> 1, @@ -287,7 +287,7 @@ PauliOperator PauliOperator::operator*(const PauliOperator& target) const { if (extra_90rot_cnt < 0) extra_90rot_cnt += 4; return PauliOperator(_ptr->_bit_flip_mask ^ target._ptr->_bit_flip_mask, _ptr->_phase_flip_mask ^ target._ptr->_phase_flip_mask, - _ptr->_coef * target._ptr->_coef * PHASE_90ROT().val[extra_90rot_cnt]); + _ptr->_coef * target._ptr->_coef * PHASE_90ROT()[extra_90rot_cnt]); } } // namespace scaluq diff --git a/scaluq/types.hpp b/scaluq/types.hpp index e31fb92e..962ff39e 100644 --- a/scaluq/types.hpp +++ b/scaluq/types.hpp @@ -27,20 +27,4 @@ using SparseComplexMatrix = Eigen::SparseMatrix; using StateVectorView = Kokkos::View; using StateVectorBatchedView = Kokkos::View; -struct array_4 { - Complex val[4]; -}; - -struct matrix_2_2 { - Complex val[2][2]; -}; - -struct matrix_4_4 { - Complex val[4][4]; -}; - -struct diagonal_matrix_2_2 { - Complex val[2]; -}; - } // namespace scaluq diff --git a/scaluq/util/utility.hpp b/scaluq/util/utility.hpp index fee20912..fefdc4c7 100644 --- a/scaluq/util/utility.hpp +++ b/scaluq/util/utility.hpp @@ -67,12 +67,13 @@ inline std::vector mask_to_vector(std::uint64_t mask) { return indices; } -KOKKOS_INLINE_FUNCTION matrix_2_2 matrix_multiply(const matrix_2_2& matrix1, - const matrix_2_2& matrix2) { - return {matrix1.val[0][0] * matrix2.val[0][0] + matrix1.val[0][1] * matrix2.val[1][0], - matrix1.val[0][0] * matrix2.val[0][1] + matrix1.val[0][1] * matrix2.val[1][1], - matrix1.val[1][0] * matrix2.val[0][0] + matrix1.val[1][1] * matrix2.val[1][0], - matrix1.val[1][0] * matrix2.val[0][1] + matrix1.val[1][1] * matrix2.val[1][1]}; +KOKKOS_INLINE_FUNCTION Kokkos::Array, 2> matrix_multiply( + const Kokkos::Array, 2>& matrix1, + const Kokkos::Array, 2>& matrix2) { + return {matrix1[0][0] * matrix2[0][0] + matrix1[0][1] * matrix2[1][0], + matrix1[0][0] * matrix2[0][1] + matrix1[0][1] * matrix2[1][1], + matrix1[1][0] * matrix2[0][0] + matrix1[1][1] * matrix2[1][0], + matrix1[1][0] * matrix2[0][1] + matrix1[1][1] * matrix2[1][1]}; } inline ComplexMatrix kronecker_product(const ComplexMatrix& lhs, const ComplexMatrix& rhs) { diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 289c4ee8..731993f3 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -333,7 +333,7 @@ void run_random_gate_apply_pauli(std::uint64_t n_qubits) { } } matrix = std::cos(angle / 2) * Eigen::MatrixXcd::Identity(dim, dim) - - Complex(0, 1) * std::sin(angle / 2) * matrix; + StdComplex(0, 1) * std::sin(angle / 2) * matrix; PauliOperator pauli(target_vec, pauli_id_vec, 1.0); Gate pauli_gate = gate::PauliRotation(pauli, angle); pauli_gate->update_quantum_state(state); From c91971cc8167114b9dc2442fbd1b9c550b5aa24e Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 30 Aug 2024 03:12:04 +0000 Subject: [PATCH 30/55] use alias, make constants internal --- scaluq/constant.hpp | 69 ++++++++++--------------- scaluq/gate/gate_matrix.hpp | 4 +- scaluq/gate/gate_standard.hpp | 13 +++-- scaluq/gate/merge_gate.cpp | 28 +++++----- scaluq/gate/update_ops.hpp | 10 ++-- scaluq/gate/update_ops_dense_matrix.cpp | 4 +- scaluq/gate/update_ops_standard.cpp | 21 ++++---- scaluq/operator/operator.cpp | 4 +- scaluq/operator/pauli_operator.cpp | 13 ++--- scaluq/types.hpp | 4 ++ scaluq/util/utility.hpp | 5 +- tests/circuit/circuit_test.cpp | 2 +- tests/gate/merge_test.cpp | 32 ++++++------ tests/gate/param_gate_test.cpp | 2 +- 14 files changed, 100 insertions(+), 111 deletions(-) diff --git a/scaluq/constant.hpp b/scaluq/constant.hpp index 6dbf02a6..cc415f5b 100644 --- a/scaluq/constant.hpp +++ b/scaluq/constant.hpp @@ -7,107 +7,90 @@ namespace scaluq { +namespace internal { + #define DEF_MATH_CONSTANT(TRAIT, VALUE) \ template \ inline constexpr auto TRAIT##_v = std::enable_if_t, T>(VALUE); \ inline constexpr auto TRAIT = TRAIT##_v -#define DEFINE_ACCESSIBLE_ARRAY(NAME, TYPE, SIZE, ...) \ - KOKKOS_INLINE_FUNCTION \ - Kokkos::Array NAME##_ARRAY() { return {__VA_ARGS__}; } \ - KOKKOS_INLINE_FUNCTION \ - TYPE NAME(std::size_t i) { return NAME##_ARRAY()[i]; } - -KOKKOS_INLINE_FUNCTION -Kokkos::Array EXAMPLE() { return {1.0, 2.0, 3.0, 4.0}; } - -//! PI value -DEF_MATH_CONSTANT(PI, 3.141592653589793); - -//! square root of 2 -DEF_MATH_CONSTANT(SQRT2, 1.4142135623730950); - //! inverse square root of 2 -DEF_MATH_CONSTANT(INVERSE_SQRT2, 0.7071067811865475); +KOKKOS_INLINE_FUNCTION +double INVERSE_SQRT2() { return Kokkos::numbers::sqrt2 / 2; } //! cosine pi/8 -DEF_MATH_CONSTANT(COSPI8, 0.923879532511287); +KOKKOS_INLINE_FUNCTION +double COSPI8() { return 0.923879532511287; } //! sine pi/8 -DEF_MATH_CONSTANT(SINPI8, 0.382683432365090); +KOKKOS_INLINE_FUNCTION +double SINPI8() { return 0.382683432365090; } //! identity matrix KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> I_GATE() { return {1, 0, 0, 1}; } +Matrix2x2 I_GATE() { return {1, 0, 0, 1}; } //! Pauli matrix X KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> X_GATE() { return {0, 1, 1, 0}; } +Matrix2x2 X_GATE() { return {0, 1, 1, 0}; } //! Pauli matrix Y KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> Y_GATE() { - return {0, Complex(0, -1), Complex(0, 1), 0}; -} +Matrix2x2 Y_GATE() { return {0, Complex(0, -1), Complex(0, 1), 0}; } //! Pauli matrix Z KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> Z_GATE() { return {1, 0, 0, -1}; } +Matrix2x2 Z_GATE() { return {1, 0, 0, -1}; } //! list of Pauli matrix I,X,Y,Z -// std::array, 2>, 4> PAULI_MATRIX = {I_GATE, X_GATE, +// std::array PAULI_MATRIX = {I_GATE, X_GATE, // Y_GATE, Z_GATE}; //! S-gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> S_GATE_MATRIX() { return {1, 0, 0, Complex(0, 1)}; } +Matrix2x2 S_GATE_MATRIX() { return {1, 0, 0, Complex(0, 1)}; } //! Sdag-gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> S_DAG_GATE_MATRIX() { - return {1, 0, 0, Complex(0, -1)}; -} +Matrix2x2 S_DAG_GATE_MATRIX() { return {1, 0, 0, Complex(0, -1)}; } //! T-gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> T_GATE_MATRIX() { - return {COSPI8 - Complex(0, SINPI8), 0., 0., COSPI8 + Complex(0, SINPI8) * SINPI8}; -} +Matrix2x2 T_GATE_MATRIX() { return {1, 0, 0, Complex(INVERSE_SQRT2(), INVERSE_SQRT2())}; } //! Tdag-gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> T_DAG_GATE_MATRIX() { - return {COSPI8 + Complex(0, SINPI8), 0., 0., COSPI8 - Complex(0, SINPI8)}; -} +Matrix2x2 T_DAG_GATE_MATRIX() { return {1, 0, 0, Complex(INVERSE_SQRT2(), -INVERSE_SQRT2())}; } //! Hadamard gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> HADAMARD_MATRIX() { - return {0.7071067811865475, 0.7071067811865475, 0.7071067811865475, -0.7071067811865475}; +Matrix2x2 HADAMARD_MATRIX() { + return {INVERSE_SQRT2(), INVERSE_SQRT2(), INVERSE_SQRT2(), -INVERSE_SQRT2()}; } //! square root of X gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> SQRT_X_GATE_MATRIX() { +Matrix2x2 SQRT_X_GATE_MATRIX() { return {Complex(0.5, 0.5), Complex(0.5, -0.5), Complex(0.5, -0.5), Complex(0.5, 0.5)}; } //! square root of Y gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> SQRT_Y_GATE_MATRIX() { +Matrix2x2 SQRT_Y_GATE_MATRIX() { return {Complex(0.5, 0.5), Complex(-0.5, -0.5), Complex(0.5, 0.5), Complex(0.5, 0.5)}; } //! square root dagger of X gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> SQRT_X_DAG_GATE_MATRIX() { +Matrix2x2 SQRT_X_DAG_GATE_MATRIX() { return {Complex(0.5, -0.5), Complex(0.5, 0.5), Complex(0.5, 0.5), Complex(0.5, -0.5)}; } //! square root dagger of Y gate KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> SQRT_Y_DAG_GATE_MATRIX() { +Matrix2x2 SQRT_Y_DAG_GATE_MATRIX() { return {Complex(0.5, -0.5), Complex(0.5, -0.5), Complex(-0.5, 0.5), Complex(0.5, -0.5)}; } //! Projection to 0 KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> PROJ_0_MATRIX() { return {1, 0, 0, 0}; } +Matrix2x2 PROJ_0_MATRIX() { return {1, 0, 0, 0}; } //! Projection to 1 KOKKOS_INLINE_FUNCTION -Kokkos::Array, 2> PROJ_1_MATRIX() { return {0, 0, 0, 1}; } +Matrix2x2 PROJ_1_MATRIX() { return {0, 0, 0, 1}; } //! complex values for exp(j * i*pi/4 ) KOKKOS_INLINE_FUNCTION Kokkos::Array PHASE_90ROT() { return {1., Complex(0, 1), -1, Complex(0, -1)}; } //! complex values for exp(-j * i*pi/4 ) KOKKOS_INLINE_FUNCTION Kokkos::Array PHASE_M90ROT() { return {1., Complex(0, -1), -1, Complex(0, 1)}; } +} // namespace internal } // namespace scaluq diff --git a/scaluq/gate/gate_matrix.hpp b/scaluq/gate/gate_matrix.hpp index e814f09f..fc4b8118 100644 --- a/scaluq/gate/gate_matrix.hpp +++ b/scaluq/gate/gate_matrix.hpp @@ -11,7 +11,7 @@ namespace scaluq { namespace internal { class OneTargetMatrixGateImpl : public GateBase { - Kokkos::Array, 2> _matrix; + Matrix2x2 _matrix; public: OneTargetMatrixGateImpl(std::uint64_t target_mask, @@ -50,7 +50,7 @@ class OneTargetMatrixGateImpl : public GateBase { }; class TwoTargetMatrixGateImpl : public GateBase { - Kokkos::Array, 4> _matrix; + Matrix4x4 _matrix; public: TwoTargetMatrixGateImpl(std::uint64_t target_mask, diff --git a/scaluq/gate/gate_standard.hpp b/scaluq/gate/gate_standard.hpp index f5d43de0..c42e60d4 100644 --- a/scaluq/gate/gate_standard.hpp +++ b/scaluq/gate/gate_standard.hpp @@ -421,14 +421,17 @@ class U2GateImpl : public GateBase { double lambda() const { return _lambda; } Gate get_inverse() const override { - return std::make_shared( - _target_mask, _control_mask, -_lambda - PI, -_phi + PI); + return std::make_shared(_target_mask, + _control_mask, + -_lambda - Kokkos::numbers::pi, + -_phi + Kokkos::numbers::pi); } ComplexMatrix get_matrix() const override { ComplexMatrix mat(2, 2); - mat << std::cos(PI / 4.), -std::exp(1i * _lambda) * std::sin(PI / 4.), - std::exp(1i * _phi) * std::sin(PI / 4.), - std::exp(1i * _phi) * std::exp(1i * _lambda) * std::cos(PI / 4.); + mat << std::cos(Kokkos::numbers::pi / 4.), + -std::exp(1i * _lambda) * std::sin(Kokkos::numbers::pi / 4.), + std::exp(1i * _phi) * std::sin(Kokkos::numbers::pi / 4.), + std::exp(1i * _phi) * std::exp(1i * _lambda) * std::cos(Kokkos::numbers::pi / 4.); return mat; } diff --git a/scaluq/gate/merge_gate.cpp b/scaluq/gate/merge_gate.cpp index 5e707114..0e4b8dc0 100644 --- a/scaluq/gate/merge_gate.cpp +++ b/scaluq/gate/merge_gate.cpp @@ -37,16 +37,16 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { if (target1 == target2) { if (pauli_id1 == pauli_id2) return {gate::I(), 0.}; if (pauli_id1 == 1) { - if (pauli_id2 == 2) return {gate::Z(target1), -PI / 2}; - if (pauli_id2 == 3) return {gate::Y(target1), PI / 2}; + if (pauli_id2 == 2) return {gate::Z(target1), -Kokkos::numbers::pi / 2}; + if (pauli_id2 == 3) return {gate::Y(target1), Kokkos::numbers::pi / 2}; } if (pauli_id1 == 2) { - if (pauli_id2 == 3) return {gate::X(target1), -PI / 2}; - if (pauli_id2 == 1) return {gate::Z(target1), PI / 2}; + if (pauli_id2 == 3) return {gate::X(target1), -Kokkos::numbers::pi / 2}; + if (pauli_id2 == 1) return {gate::Z(target1), Kokkos::numbers::pi / 2}; } if (pauli_id1 == 3) { - if (pauli_id2 == 1) return {gate::Y(target1), -PI / 2}; - if (pauli_id2 == 2) return {gate::X(target1), PI / 2}; + if (pauli_id2 == 1) return {gate::Y(target1), -Kokkos::numbers::pi / 2}; + if (pauli_id2 == 2) return {gate::X(target1), Kokkos::numbers::pi / 2}; } } } @@ -99,11 +99,11 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { std::uint64_t target1 = gate1->get_target_qubit_list()[0]; std::uint64_t target2 = gate2->get_target_qubit_list()[0]; if (target1 == target2) { - double phase1 = oct_phase1 ? oct_phase1.value() * PI / 4 + double phase1 = oct_phase1 ? oct_phase1.value() * Kokkos::numbers::pi / 4 : gate_type1 == GateType::RZ ? RZGate(gate1)->angle() : U1Gate(gate1)->lambda(); double global_phase1 = gate_type1 == GateType::RZ ? -RZGate(gate1)->angle() / 2 : 0.; - double phase2 = oct_phase2 ? oct_phase2.value() * PI / 4 + double phase2 = oct_phase2 ? oct_phase2.value() * Kokkos::numbers::pi / 4 : gate_type2 == GateType::RZ ? RZGate(gate2)->angle() : U1Gate(gate2)->lambda(); double global_phase2 = gate_type2 == GateType::RZ ? -RZGate(gate2)->angle() / 2 : 0.; @@ -114,9 +114,9 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { // Special case: RX auto get_rx_angle = [&](Gate gate, GateType gate_type) -> std::optional { if (gate_type == GateType::I) return 0.; - if (gate_type == GateType::X) return PI; - if (gate_type == GateType::SqrtX) return PI / 2; - if (gate_type == GateType::SqrtXdag) return -PI / 2; + if (gate_type == GateType::X) return Kokkos::numbers::pi; + if (gate_type == GateType::SqrtX) return Kokkos::numbers::pi / 2; + if (gate_type == GateType::SqrtXdag) return -Kokkos::numbers::pi / 2; if (gate_type == GateType::RX) return RXGate(gate)->angle(); return std::nullopt; }; @@ -136,9 +136,9 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { // Special case: RY auto get_ry_angle = [&](Gate gate, GateType gate_type) -> std::optional { if (gate_type == GateType::I) return 0.; - if (gate_type == GateType::Y) return PI; - if (gate_type == GateType::SqrtY) return PI / 2; - if (gate_type == GateType::SqrtYdag) return -PI / 2; + if (gate_type == GateType::Y) return Kokkos::numbers::pi; + if (gate_type == GateType::SqrtY) return Kokkos::numbers::pi / 2; + if (gate_type == GateType::SqrtYdag) return -Kokkos::numbers::pi / 2; if (gate_type == GateType::RY) return RYGate(gate)->angle(); return std::nullopt; }; diff --git a/scaluq/gate/update_ops.hpp b/scaluq/gate/update_ops.hpp index eea32b8c..bc55ce1e 100644 --- a/scaluq/gate/update_ops.hpp +++ b/scaluq/gate/update_ops.hpp @@ -57,23 +57,21 @@ void rz_gate(std::uint64_t target_mask, double angle, StateVector& state); -Kokkos::Array, 2> get_IBMQ_matrix(double _theta, - double _phi, - double _lambda); +Matrix2x2 get_IBMQ_matrix(double _theta, double _phi, double _lambda); void one_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const Kokkos::Array, 2>& matrix, + const Matrix2x2& matrix, StateVector& state); void two_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const Kokkos::Array, 4>& matrix, + const Matrix4x4& matrix, StateVector& state); void one_target_diagonal_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const Kokkos::Array& diag, + const DiagonalMatrix2x2& diag, StateVector& state); void u1_gate(std::uint64_t target_mask, diff --git a/scaluq/gate/update_ops_dense_matrix.cpp b/scaluq/gate/update_ops_dense_matrix.cpp index 80807bf8..ca7141eb 100644 --- a/scaluq/gate/update_ops_dense_matrix.cpp +++ b/scaluq/gate/update_ops_dense_matrix.cpp @@ -9,7 +9,7 @@ namespace scaluq { namespace internal { void one_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const Kokkos::Array, 2>& matrix, + const Matrix2x2& matrix, StateVector& state) { Kokkos::parallel_for( state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(std::uint64_t it) { @@ -28,7 +28,7 @@ void one_target_dense_matrix_gate(std::uint64_t target_mask, void two_target_dense_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const Kokkos::Array, 4>& matrix, + const Matrix4x4& matrix, StateVector& state) { std::uint64_t lower_target_mask = -target_mask & target_mask; std::uint64_t upper_target_mask = target_mask ^ lower_target_mask; diff --git a/scaluq/gate/update_ops_standard.cpp b/scaluq/gate/update_ops_standard.cpp index f51d6672..1e64854b 100644 --- a/scaluq/gate/update_ops_standard.cpp +++ b/scaluq/gate/update_ops_standard.cpp @@ -79,11 +79,13 @@ void sdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVecto } void t_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { - one_target_phase_gate(target_mask, control_mask, Complex(INVERSE_SQRT2, INVERSE_SQRT2), state); + one_target_phase_gate( + target_mask, control_mask, Complex(INVERSE_SQRT2(), INVERSE_SQRT2()), state); } void tdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { - one_target_phase_gate(target_mask, control_mask, Complex(INVERSE_SQRT2, -INVERSE_SQRT2), state); + one_target_phase_gate( + target_mask, control_mask, Complex(INVERSE_SQRT2(), -INVERSE_SQRT2()), state); } void sqrtx_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { @@ -116,8 +118,7 @@ void rx_gate(std::uint64_t target_mask, StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); - Kokkos::Array, 2> matrix = { - cosval, Complex(0, -sinval), Complex(0, -sinval), cosval}; + Matrix2x2 matrix = {cosval, Complex(0, -sinval), Complex(0, -sinval), cosval}; one_target_dense_matrix_gate(target_mask, control_mask, matrix, state); } @@ -127,13 +128,13 @@ void ry_gate(std::uint64_t target_mask, StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); - Kokkos::Array, 2> matrix = {cosval, -sinval, sinval, cosval}; + Matrix2x2 matrix = {cosval, -sinval, sinval, cosval}; one_target_dense_matrix_gate(target_mask, control_mask, matrix, state); } void one_target_diagonal_matrix_gate(std::uint64_t target_mask, std::uint64_t control_mask, - const Kokkos::Array& diag, + const DiagonalMatrix2x2& diag, StateVector& state) { Kokkos::parallel_for( state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(std::uint64_t it) { @@ -151,13 +152,11 @@ void rz_gate(std::uint64_t target_mask, StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); - Kokkos::Array diag = {Complex(cosval, -sinval), Complex(cosval, sinval)}; + DiagonalMatrix2x2 diag = {Complex(cosval, -sinval), Complex(cosval, sinval)}; one_target_diagonal_matrix_gate(target_mask, control_mask, diag, state); } -Kokkos::Array, 2> get_IBMQ_matrix(double theta, - double phi, - double lambda) { +Matrix2x2 get_IBMQ_matrix(double theta, double phi, double lambda) { Complex exp_val1 = Kokkos::exp(Complex(0, phi)); Complex exp_val2 = Kokkos::exp(Complex(0, lambda)); Complex cos_val = Kokkos::cos(theta / 2.); @@ -187,7 +186,7 @@ void u2_gate(std::uint64_t target_mask, double lambda, StateVector& state) { one_target_dense_matrix_gate( - target_mask, control_mask, get_IBMQ_matrix(PI / 2., phi, lambda), state); + target_mask, control_mask, get_IBMQ_matrix(Kokkos::numbers::pi / 2., phi, lambda), state); } void u3_gate(std::uint64_t target_mask, diff --git a/scaluq/operator/operator.cpp b/scaluq/operator/operator.cpp index 334f2a2d..6fb5dc1d 100644 --- a/scaluq/operator/operator.cpp +++ b/scaluq/operator/operator.cpp @@ -133,7 +133,7 @@ Complex Operator::get_expectation_value(const StateVector& state_vector) const { sizeof(std::uint64_t) * 8 - Kokkos::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = Kokkos::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_90ROT()[global_phase_90rot_count % 4]; + Complex global_phase = internal::PHASE_90ROT()[global_phase_90rot_count % 4]; std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; double tmp = @@ -204,7 +204,7 @@ Complex Operator::get_transition_amplitude(const StateVector& state_vector_bra, sizeof(std::uint64_t) * 8 - Kokkos::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = Kokkos::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_90ROT()[global_phase_90rot_count % 4]; + Complex global_phase = internal::PHASE_90ROT()[global_phase_90rot_count % 4]; std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; Complex tmp1 = Kokkos::conj(state_vector_bra._raw[basis_1]) * diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 36318e98..34277557 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -131,7 +131,7 @@ void PauliOperator::apply_to_state(StateVector& state_vector) const { } std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_M90ROT()[global_phase_90rot_count % 4]; + Complex global_phase = internal::PHASE_M90ROT()[global_phase_90rot_count % 4]; Kokkos::parallel_for( state_vector.dim() >> 1, KOKKOS_LAMBDA(std::uint64_t state_idx) { std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); @@ -170,7 +170,7 @@ Complex PauliOperator::get_expectation_value(const StateVector& state_vector) co } std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_90ROT()[global_phase_90rot_count % 4]; + Complex global_phase = internal::PHASE_90ROT()[global_phase_90rot_count % 4]; double res; Kokkos::parallel_reduce( state_vector.dim() >> 1, @@ -214,7 +214,7 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ } std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_90ROT()[global_phase_90rot_count % 4]; + Complex global_phase = internal::PHASE_90ROT()[global_phase_90rot_count % 4]; Complex res; Kokkos::parallel_reduce( state_vector_bra.dim() >> 1, @@ -285,9 +285,10 @@ PauliOperator PauliOperator::operator*(const PauliOperator& target) const { extra_90rot_cnt -= (z_left & y_right).popcount(); // ZY = -iX extra_90rot_cnt %= 4; if (extra_90rot_cnt < 0) extra_90rot_cnt += 4; - return PauliOperator(_ptr->_bit_flip_mask ^ target._ptr->_bit_flip_mask, - _ptr->_phase_flip_mask ^ target._ptr->_phase_flip_mask, - _ptr->_coef * target._ptr->_coef * PHASE_90ROT()[extra_90rot_cnt]); + return PauliOperator( + _ptr->_bit_flip_mask ^ target._ptr->_bit_flip_mask, + _ptr->_phase_flip_mask ^ target._ptr->_phase_flip_mask, + _ptr->_coef * target._ptr->_coef * internal::PHASE_90ROT()[extra_90rot_cnt]); } } // namespace scaluq diff --git a/scaluq/types.hpp b/scaluq/types.hpp index 962ff39e..6c145ed2 100644 --- a/scaluq/types.hpp +++ b/scaluq/types.hpp @@ -27,4 +27,8 @@ using SparseComplexMatrix = Eigen::SparseMatrix; using StateVectorView = Kokkos::View; using StateVectorBatchedView = Kokkos::View; +using Matrix2x2 = Kokkos::Array, 2>; +using Matrix4x4 = Kokkos::Array, 4>; +using DiagonalMatrix2x2 = Kokkos::Array; + } // namespace scaluq diff --git a/scaluq/util/utility.hpp b/scaluq/util/utility.hpp index fefdc4c7..9897ded9 100644 --- a/scaluq/util/utility.hpp +++ b/scaluq/util/utility.hpp @@ -67,9 +67,8 @@ inline std::vector mask_to_vector(std::uint64_t mask) { return indices; } -KOKKOS_INLINE_FUNCTION Kokkos::Array, 2> matrix_multiply( - const Kokkos::Array, 2>& matrix1, - const Kokkos::Array, 2>& matrix2) { +KOKKOS_INLINE_FUNCTION Matrix2x2 matrix_multiply(const Matrix2x2& matrix1, + const Matrix2x2& matrix2) { return {matrix1[0][0] * matrix2[0][0] + matrix1[0][1] * matrix2[1][0], matrix1[0][0] * matrix2[0][1] + matrix1[0][1] * matrix2[1][1], matrix1[1][0] * matrix2[0][0] + matrix1[1][1] * matrix2[1][0], diff --git a/tests/circuit/circuit_test.cpp b/tests/circuit/circuit_test.cpp index acbac053..2996d324 100644 --- a/tests/circuit/circuit_test.cpp +++ b/tests/circuit/circuit_test.cpp @@ -243,7 +243,7 @@ TEST(CircuitTest, CircuitRev) { /* Observable observable(n); - angle = 2 * PI * random.uniform(); + angle = 2 * Kokkos::numbers::pi * random.uniform(); observable.add_operator(1.0, "Z 0"); observable.add_operator(2.0, "Z 0 Z 1"); diff --git a/tests/gate/merge_test.cpp b/tests/gate/merge_test.cpp index 04d8ede4..fc4566b7 100644 --- a/tests/gate/merge_test.cpp +++ b/tests/gate/merge_test.cpp @@ -29,15 +29,17 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::SqrtYdag(target)); gates.push_back(gate::P0(target)); gates.push_back(gate::P1(target)); - gates.push_back(gate::RX(target, random.uniform() * PI * 2)); - gates.push_back(gate::RY(target, random.uniform() * PI * 2)); - gates.push_back(gate::RZ(target, random.uniform() * PI * 2)); - gates.push_back(gate::U1(target, random.uniform() * PI * 2)); - gates.push_back(gate::U2(target, random.uniform() * PI * 2, random.uniform() * PI * 2)); + gates.push_back(gate::RX(target, random.uniform() * Kokkos::numbers::pi * 2)); + gates.push_back(gate::RY(target, random.uniform() * Kokkos::numbers::pi * 2)); + gates.push_back(gate::RZ(target, random.uniform() * Kokkos::numbers::pi * 2)); + gates.push_back(gate::U1(target, random.uniform() * Kokkos::numbers::pi * 2)); + gates.push_back(gate::U2(target, + random.uniform() * Kokkos::numbers::pi * 2, + random.uniform() * Kokkos::numbers::pi * 2)); gates.push_back(gate::U3(target, - random.uniform() * PI * 2, - random.uniform() * PI * 2, - random.uniform() * PI * 2)); + random.uniform() * Kokkos::numbers::pi * 2, + random.uniform() * Kokkos::numbers::pi * 2, + random.uniform() * Kokkos::numbers::pi * 2)); gates.push_back( gate::OneTargetMatrix(target, {std::array{Complex(random.uniform(), random.uniform()), @@ -49,7 +51,7 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::Swap(target, target ^ 1)); } gates.push_back(gate::I()); - gates.push_back(gate::GlobalPhase(random.uniform() * PI * 2)); + gates.push_back(gate::GlobalPhase(random.uniform() * Kokkos::numbers::pi * 2)); gates.push_back( gate::TwoTargetMatrix(0, 1, @@ -72,12 +74,12 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::Pauli(PauliOperator("X 0 Y 1", random.uniform()))); gates.push_back(gate::Pauli(PauliOperator("Z 0", random.uniform()))); gates.push_back(gate::Pauli(PauliOperator("Z 1", random.uniform()))); - gates.push_back( - gate::PauliRotation(PauliOperator("X 0 Y 1", random.uniform()), random.uniform() * PI * 2)); - gates.push_back( - gate::PauliRotation(PauliOperator("Z 0", random.uniform()), random.uniform() * PI * 2)); - gates.push_back( - gate::PauliRotation(PauliOperator("Z 1", random.uniform()), random.uniform() * PI * 2)); + gates.push_back(gate::PauliRotation(PauliOperator("X 0 Y 1", random.uniform()), + random.uniform() * Kokkos::numbers::pi * 2)); + gates.push_back(gate::PauliRotation(PauliOperator("Z 0", random.uniform()), + random.uniform() * Kokkos::numbers::pi * 2)); + gates.push_back(gate::PauliRotation(PauliOperator("Z 1", random.uniform()), + random.uniform() * Kokkos::numbers::pi * 2)); for (auto&& g1 : gates) { for (auto&& g2 : gates) { std::uint64_t n = 2; diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index 551be512..7674d81c 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -103,7 +103,7 @@ TEST(ParamGateTest, ApplyPProbablisticGate) { StateVector state(1); for ([[maybe_unused]] auto _ : std::views::iota(0, 100)) { std::uint64_t before = state.sampling(1)[0]; - probgate->update_quantum_state(state, scaluq::PI); + probgate->update_quantum_state(state, scaluq::Kokkos::numbers::pi); std::uint64_t after = state.sampling(1)[0]; if (before != after) { x_cnt++; From 2abdc611aabdbfe49d13fced82bb6135496e63b4 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 30 Aug 2024 03:26:27 +0000 Subject: [PATCH 31/55] make types.hpp internal --- scaluq/gate/gate.hpp | 2 +- scaluq/gate/gate_factory.hpp | 11 ++- scaluq/gate/gate_matrix.hpp | 8 +-- scaluq/gate/gate_pauli.hpp | 8 +-- scaluq/gate/gate_probablistic.hpp | 2 +- scaluq/gate/gate_standard.hpp | 92 +++++++++++++------------ scaluq/gate/param_gate.hpp | 2 +- scaluq/gate/param_gate_pauli.hpp | 6 +- scaluq/gate/param_gate_probablistic.hpp | 2 +- scaluq/gate/param_gate_standard.hpp | 12 ++-- scaluq/operator/pauli_operator.cpp | 6 +- scaluq/operator/pauli_operator.hpp | 4 +- scaluq/state/state_vector.hpp | 2 +- scaluq/state/state_vector_batched.cpp | 2 +- scaluq/state/state_vector_batched.hpp | 2 +- scaluq/types.hpp | 8 +-- scaluq/util/utility.hpp | 15 ++-- tests/circuit/circuit_test.cpp | 2 +- 18 files changed, 94 insertions(+), 92 deletions(-) diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 884189e9..175e136a 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -164,7 +164,7 @@ class GateBase : public std::enable_shared_from_this { } [[nodiscard]] virtual Gate get_inverse() const = 0; - [[nodiscard]] virtual ComplexMatrix get_matrix() const = 0; + [[nodiscard]] virtual internal::ComplexMatrix get_matrix() const = 0; virtual void update_quantum_state(StateVector& state_vector) const = 0; }; diff --git a/scaluq/gate/gate_factory.hpp b/scaluq/gate/gate_factory.hpp index 1c78610f..e6c87169 100644 --- a/scaluq/gate/gate_factory.hpp +++ b/scaluq/gate/gate_factory.hpp @@ -163,17 +163,15 @@ inline Gate PauliRotation(const PauliOperator& pauli, internal::vector_to_mask(controls), pauli, angle); } inline Gate DenseMatrix(const std::vector& targets, - const ComplexMatrix& matrix, + const internal::ComplexMatrix& matrix, const std::vector& controls = {}) { std::uint64_t nqubits = targets.size(); std::uint64_t dim = 1ULL << nqubits; if (static_cast(matrix.rows()) != dim || static_cast(matrix.cols()) != dim) { throw std::runtime_error( - "gate::DenseMatrix(const std::vector&, const ComplexMatrix&): matrix " - "size " - "must " - "be 2^{n_qubits} x 2^{n_qubits}."); + "gate::DenseMatrix(const std::vector&, const internal::ComplexMatrix&): " + "matrix size must be 2^{n_qubits} x 2^{n_qubits}."); } if (targets.size() == 0) return I(); if (targets.size() == 1) { @@ -204,7 +202,8 @@ inline Gate DenseMatrix(const std::vector& targets, controls); } throw std::runtime_error( - "gate::DenseMatrix(const std::vector&, const ComplexMatrix&): DenseMatrix " + "gate::DenseMatrix(const std::vector&, const internal::ComplexMatrix&): " + "DenseMatrix " "gate " "more " "than two qubits is not implemented yet."); diff --git a/scaluq/gate/gate_matrix.hpp b/scaluq/gate/gate_matrix.hpp index fc4b8118..f873e7cb 100644 --- a/scaluq/gate/gate_matrix.hpp +++ b/scaluq/gate/gate_matrix.hpp @@ -37,8 +37,8 @@ class OneTargetMatrixGateImpl : public GateBase { Kokkos::conj(_matrix[0][1]), Kokkos::conj(_matrix[1][1])}); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << this->_matrix[0][0], this->_matrix[0][1], this->_matrix[1][0], this->_matrix[1][1]; return mat; } @@ -84,8 +84,8 @@ class TwoTargetMatrixGateImpl : public GateBase { return std::make_shared( _target_mask, _control_mask, matrix_dag); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(4, 4); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(4, 4); mat << this->_matrix[0][0], this->_matrix[0][1], this->_matrix[0][2], this->_matrix[0][3], this->_matrix[1][0], this->_matrix[1][1], this->_matrix[1][2], this->_matrix[1][3], this->_matrix[2][0], this->_matrix[2][1], this->_matrix[2][2], this->_matrix[2][3], diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index ee864ae7..a0ac0493 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -20,7 +20,7 @@ class PauliGateImpl : public GateBase { std::vector get_pauli_id_list() const { return _pauli.get_pauli_id_list(); } Gate get_inverse() const override { return shared_from_this(); } - ComplexMatrix get_matrix() const override { return this->_pauli.get_matrix(); } + internal::ComplexMatrix get_matrix() const override { return this->_pauli.get_matrix(); } void update_quantum_state(StateVector& state_vector) const override { pauli_gate(_control_mask, _pauli, state_vector); @@ -45,12 +45,12 @@ class PauliRotationGateImpl : public GateBase { return std::make_shared(_control_mask, _pauli, -_angle); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat = this->_pauli.get_matrix_ignoring_coef(); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat = this->_pauli.get_matrix_ignoring_coef(); Complex true_angle = _angle * _pauli.get_coef(); StdComplex imag_unit(0, 1); mat = (StdComplex)Kokkos::cos(-true_angle / 2) * - ComplexMatrix::Identity(mat.rows(), mat.cols()) + + internal::ComplexMatrix::Identity(mat.rows(), mat.cols()) + imag_unit * (StdComplex)Kokkos::sin(-true_angle / 2) * mat; return mat; } diff --git a/scaluq/gate/gate_probablistic.hpp b/scaluq/gate/gate_probablistic.hpp index 9be3946c..704aa00b 100644 --- a/scaluq/gate/gate_probablistic.hpp +++ b/scaluq/gate/gate_probablistic.hpp @@ -70,7 +70,7 @@ class ProbablisticGateImpl : public GateBase { }); return std::make_shared(_distribution, inv_gate_list); } - ComplexMatrix get_matrix() const override { + internal::ComplexMatrix get_matrix() const override { throw std::runtime_error( "ProbablisticGateImpl::get_matrix(): This function must not be used in " "ProbablisticGateImpl."); diff --git a/scaluq/gate/gate_standard.hpp b/scaluq/gate/gate_standard.hpp index c42e60d4..cf9b3e3d 100644 --- a/scaluq/gate/gate_standard.hpp +++ b/scaluq/gate/gate_standard.hpp @@ -11,7 +11,9 @@ class IGateImpl : public GateBase { IGateImpl() : GateBase(0, 0) {} Gate get_inverse() const override { return shared_from_this(); } - ComplexMatrix get_matrix() const override { return ComplexMatrix::Identity(1, 1); } + internal::ComplexMatrix get_matrix() const override { + return internal::ComplexMatrix::Identity(1, 1); + } void update_quantum_state(StateVector& state_vector) const override { i_gate(_target_mask, _control_mask, state_vector); @@ -31,8 +33,8 @@ class GlobalPhaseGateImpl : public GateBase { Gate get_inverse() const override { return std::make_shared(_control_mask, -_phase); } - ComplexMatrix get_matrix() const override { - return ComplexMatrix::Identity(1, 1) * std::exp(std::complex(0, _phase)); + internal::ComplexMatrix get_matrix() const override { + return internal::ComplexMatrix::Identity(1, 1) * std::exp(std::complex(0, _phase)); } void update_quantum_state(StateVector& state_vector) const override { @@ -57,8 +59,8 @@ class XGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override { return shared_from_this(); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 0, 1, 1, 0; return mat; } @@ -74,8 +76,8 @@ class YGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override { return shared_from_this(); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 0, -1i, 1i, 0; return mat; } @@ -91,8 +93,8 @@ class ZGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override { return shared_from_this(); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, -1; return mat; } @@ -108,8 +110,8 @@ class HGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override { return shared_from_this(); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 1, 1, 1, -1; mat /= std::sqrt(2); return mat; @@ -135,8 +137,8 @@ class SGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override; - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, 1i; return mat; } @@ -154,8 +156,8 @@ class SdagGateImpl : public GateBase { Gate get_inverse() const override { return std::make_shared(_target_mask, _control_mask); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, -1i; return mat; } @@ -175,8 +177,8 @@ class TGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override; - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, (1. + 1i) / std::sqrt(2); return mat; } @@ -194,8 +196,8 @@ class TdagGateImpl : public GateBase { Gate get_inverse() const override { return std::make_shared(_target_mask, _control_mask); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, (1. - 1.i) / std::sqrt(2); return mat; } @@ -215,8 +217,8 @@ class SqrtXGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override; - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 0.5 + 0.5i, 0.5 - 0.5i, 0.5 - 0.5i, 0.5 + 0.5i; return mat; } @@ -234,8 +236,8 @@ class SqrtXdagGateImpl : public GateBase { Gate get_inverse() const override { return std::make_shared(_target_mask, _control_mask); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 0.5 - 0.5i, 0.5 + 0.5i, 0.5 + 0.5i, 0.5 - 0.5i; return mat; } @@ -255,8 +257,8 @@ class SqrtYGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override; - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 0.5 + 0.5i, -0.5 - 0.5i, 0.5 + 0.5i, 0.5 + 0.5i; return mat; } @@ -274,8 +276,8 @@ class SqrtYdagGateImpl : public GateBase { Gate get_inverse() const override { return std::make_shared(_target_mask, _control_mask); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 0.5 - 0.5i, 0.5 - 0.5i, -0.5 + 0.5i, 0.5 - 0.5i; return mat; } @@ -297,8 +299,8 @@ class P0GateImpl : public GateBase { Gate get_inverse() const override { throw std::runtime_error("P0::get_inverse: Projection gate doesn't have inverse gate"); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, 0; return mat; } @@ -316,8 +318,8 @@ class P1GateImpl : public GateBase { Gate get_inverse() const override { throw std::runtime_error("P1::get_inverse: Projection gate doesn't have inverse gate"); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 0, 0, 0, 1; return mat; } @@ -335,8 +337,8 @@ class RXGateImpl : public RotationGateBase { Gate get_inverse() const override { return std::make_shared(_target_mask, _control_mask, -_angle); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << std::cos(_angle / 2), -1i * std::sin(_angle / 2), -1i * std::sin(_angle / 2), std::cos(_angle / 2); return mat; @@ -355,8 +357,8 @@ class RYGateImpl : public RotationGateBase { Gate get_inverse() const override { return std::make_shared(_target_mask, _control_mask, -_angle); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << std::cos(_angle / 2), -std::sin(_angle / 2), std::sin(_angle / 2), std::cos(_angle / 2); return mat; @@ -375,8 +377,8 @@ class RZGateImpl : public RotationGateBase { Gate get_inverse() const override { return std::make_shared(_target_mask, _control_mask, -_angle); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << std::exp(-0.5i * _angle), 0, 0, std::exp(0.5i * _angle); return mat; } @@ -399,8 +401,8 @@ class U1GateImpl : public GateBase { Gate get_inverse() const override { return std::make_shared(_target_mask, _control_mask, -_lambda); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << 1, 0, 0, std::exp(1i * _lambda); return mat; } @@ -426,8 +428,8 @@ class U2GateImpl : public GateBase { -_lambda - Kokkos::numbers::pi, -_phi + Kokkos::numbers::pi); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << std::cos(Kokkos::numbers::pi / 4.), -std::exp(1i * _lambda) * std::sin(Kokkos::numbers::pi / 4.), std::exp(1i * _phi) * std::sin(Kokkos::numbers::pi / 4.), @@ -460,8 +462,8 @@ class U3GateImpl : public GateBase { return std::make_shared( _target_mask, _control_mask, -_theta, -_lambda, -_phi); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat(2, 2); + internal::ComplexMatrix get_matrix() const override { + internal::ComplexMatrix mat(2, 2); mat << std::cos(_theta / 2.), -std::exp(1i * _lambda) * std::sin(_theta / 2.), std::exp(1i * _phi) * std::sin(_theta / 2.), std::exp(1i * _phi) * std::exp(1i * _lambda) * std::cos(_theta / 2.); @@ -479,8 +481,8 @@ class SwapGateImpl : public GateBase { using GateBase::GateBase; Gate get_inverse() const override { return shared_from_this(); } - ComplexMatrix get_matrix() const override { - ComplexMatrix mat = ComplexMatrix::Identity(1 << 2, 1 << 2); + internal::ComplexMatrix get_matrix() const override { + 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; } diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index e0ff1cb8..12502eac 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -80,7 +80,7 @@ class ParamGateBase { } [[nodiscard]] virtual ParamGate get_inverse() const = 0; - [[nodiscard]] virtual ComplexMatrix get_matrix(double param) const = 0; + [[nodiscard]] virtual internal::ComplexMatrix get_matrix(double param) const = 0; virtual void update_quantum_state(StateVector& state_vector, double param) const = 0; }; diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index 0ba0a736..2e6b4d1f 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -24,13 +24,13 @@ class PPauliRotationGateImpl : public ParamGateBase { ParamGate get_inverse() const override { return std::make_shared(_control_mask, _pauli, -_pcoef); } - ComplexMatrix get_matrix(double param) const override { + internal::ComplexMatrix get_matrix(double param) const override { double angle = _pcoef * param; Complex true_angle = angle * this->_pauli.get_coef(); - ComplexMatrix mat = this->_pauli.get_matrix_ignoring_coef(); + internal::ComplexMatrix mat = this->_pauli.get_matrix_ignoring_coef(); StdComplex imag_unit(0, 1); mat = (StdComplex)Kokkos::cos(-true_angle / 2) * - ComplexMatrix::Identity(mat.rows(), mat.cols()) + + internal::ComplexMatrix::Identity(mat.rows(), mat.cols()) + imag_unit * (StdComplex)Kokkos::sin(-true_angle / 2) * mat; return mat; } diff --git a/scaluq/gate/param_gate_probablistic.hpp b/scaluq/gate/param_gate_probablistic.hpp index 063a1ea9..476d9927 100644 --- a/scaluq/gate/param_gate_probablistic.hpp +++ b/scaluq/gate/param_gate_probablistic.hpp @@ -75,7 +75,7 @@ class PProbablisticGateImpl : public ParamGateBase { }); return std::make_shared(_distribution, inv_gate_list); } - ComplexMatrix get_matrix(double) const override { + internal::ComplexMatrix get_matrix(double) const override { throw std::runtime_error( "PProbablisticGateImpl::get_matrix(): This function must not be used in " "PProbablisticGateImpl."); diff --git a/scaluq/gate/param_gate_standard.hpp b/scaluq/gate/param_gate_standard.hpp index cf12afae..1382761a 100644 --- a/scaluq/gate/param_gate_standard.hpp +++ b/scaluq/gate/param_gate_standard.hpp @@ -15,9 +15,9 @@ class PRXGateImpl : public ParamGateBase { ParamGate get_inverse() const override { return std::make_shared(_target_mask, _control_mask, -_pcoef); } - ComplexMatrix get_matrix(double param) const override { + internal::ComplexMatrix get_matrix(double param) const override { double angle = _pcoef * param; - ComplexMatrix mat(2, 2); + internal::ComplexMatrix mat(2, 2); mat << std::cos(angle / 2), -1i * std::sin(angle / 2), -1i * std::sin(angle / 2), std::cos(angle / 2); return mat; @@ -36,9 +36,9 @@ class PRYGateImpl : public ParamGateBase { ParamGate get_inverse() const override { return std::make_shared(_target_mask, _control_mask, -_pcoef); } - ComplexMatrix get_matrix(double param) const override { + internal::ComplexMatrix get_matrix(double param) const override { double angle = _pcoef * param; - ComplexMatrix mat(2, 2); + internal::ComplexMatrix mat(2, 2); mat << std::cos(angle / 2), -std::sin(angle / 2), std::sin(angle / 2), std::cos(angle / 2); return mat; } @@ -56,9 +56,9 @@ class PRZGateImpl : public ParamGateBase { ParamGate get_inverse() const override { return std::make_shared(_target_mask, _control_mask, -_pcoef); } - ComplexMatrix get_matrix(double param) const override { + internal::ComplexMatrix get_matrix(double param) const override { double angle = param * _pcoef; - ComplexMatrix mat(2, 2); + internal::ComplexMatrix mat(2, 2); mat << std::exp(-0.5i * angle), 0, 0, std::exp(0.5i * angle); return mat; } diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 34277557..0149528a 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -234,7 +234,7 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ return _ptr->_coef * res; } -[[nodiscard]] ComplexMatrix PauliOperator::get_matrix_ignoring_coef() const { +[[nodiscard]] 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()), @@ -258,14 +258,14 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ rot90_count); std::vector rot = {1, -1.i, -1, 1.i}; std::uint64_t matrix_dim = 1ULL << _ptr->_pauli_id_list.size(); - ComplexMatrix mat = ComplexMatrix::Zero(matrix_dim, matrix_dim); + internal::ComplexMatrix mat = internal::ComplexMatrix::Zero(matrix_dim, matrix_dim); for (std::uint64_t index = 0; index < matrix_dim; index++) { const StdComplex sign = 1. - 2. * (Kokkos::popcount(index & phase_mask) % 2); mat(index, index ^ flip_mask) = rot[rot90_count % 4] * sign; } return mat; } -[[nodiscard]] ComplexMatrix PauliOperator::get_matrix() const { +[[nodiscard]] internal::ComplexMatrix PauliOperator::get_matrix() const { return get_matrix_ignoring_coef() * StdComplex(_ptr->_coef); } diff --git a/scaluq/operator/pauli_operator.hpp b/scaluq/operator/pauli_operator.hpp index c5d04891..4f895714 100644 --- a/scaluq/operator/pauli_operator.hpp +++ b/scaluq/operator/pauli_operator.hpp @@ -88,8 +88,8 @@ class PauliOperator { [[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; - [[nodiscard]] ComplexMatrix get_matrix() const; - [[nodiscard]] ComplexMatrix get_matrix_ignoring_coef() const; + [[nodiscard]] internal::ComplexMatrix get_matrix() const; + [[nodiscard]] internal::ComplexMatrix get_matrix_ignoring_coef() const; [[nodiscard]] PauliOperator operator*(const PauliOperator& target) const; [[nodiscard]] inline PauliOperator operator*(Complex target) const { diff --git a/scaluq/state/state_vector.hpp b/scaluq/state/state_vector.hpp index 3ef21324..1c59793f 100644 --- a/scaluq/state/state_vector.hpp +++ b/scaluq/state/state_vector.hpp @@ -15,7 +15,7 @@ class StateVector { public: static constexpr std::uint64_t UNMEASURED = 2; - StateVectorView _raw; + Kokkos::View _raw; StateVector() = default; StateVector(std::uint64_t n_qubits); StateVector(const StateVector& other) = default; diff --git a/scaluq/state/state_vector_batched.cpp b/scaluq/state/state_vector_batched.cpp index 9d029f01..2931f91e 100644 --- a/scaluq/state/state_vector_batched.cpp +++ b/scaluq/state/state_vector_batched.cpp @@ -7,7 +7,7 @@ StateVectorBatched::StateVectorBatched(std::uint64_t batch_size, std::uint64_t n : _batch_size(batch_size), _n_qubits(n_qubits), _dim(1ULL << _n_qubits), - _raw(StateVectorBatchedView( + _raw(Kokkos::View( Kokkos::ViewAllocateWithoutInitializing("states"), _batch_size, _dim)) { set_zero_state(); } diff --git a/scaluq/state/state_vector_batched.hpp b/scaluq/state/state_vector_batched.hpp index 6c4c5048..5bd9e3ef 100644 --- a/scaluq/state/state_vector_batched.hpp +++ b/scaluq/state/state_vector_batched.hpp @@ -10,7 +10,7 @@ class StateVectorBatched { std::uint64_t _dim; public: - StateVectorBatchedView _raw; + Kokkos::View _raw; StateVectorBatched() = default; StateVectorBatched(std::uint64_t batch_size, std::uint64_t n_qubits); StateVectorBatched(const StateVectorBatched& other) = default; diff --git a/scaluq/types.hpp b/scaluq/types.hpp index 6c145ed2..16ada618 100644 --- a/scaluq/types.hpp +++ b/scaluq/types.hpp @@ -17,18 +17,18 @@ inline void finalize() { Kokkos::finalize(); } inline bool is_initialized() { return Kokkos::is_initialized(); } inline bool is_finalized() { return Kokkos::is_finalized(); } +using StdComplex = std::complex; using Complex = Kokkos::complex; using namespace std::complex_literals; -using StdComplex = std::complex; +namespace internal { + using ComplexMatrix = Eigen::Matrix; using SparseComplexMatrix = Eigen::SparseMatrix; -using StateVectorView = Kokkos::View; -using StateVectorBatchedView = Kokkos::View; - using Matrix2x2 = Kokkos::Array, 2>; using Matrix4x4 = Kokkos::Array, 4>; using DiagonalMatrix2x2 = Kokkos::Array; +} // namespace internal } // namespace scaluq diff --git a/scaluq/util/utility.hpp b/scaluq/util/utility.hpp index 9897ded9..aab4f5d1 100644 --- a/scaluq/util/utility.hpp +++ b/scaluq/util/utility.hpp @@ -75,8 +75,9 @@ KOKKOS_INLINE_FUNCTION Matrix2x2 matrix_multiply(const Matrix2x2& matrix1, matrix1[1][0] * matrix2[0][1] + matrix1[1][1] * matrix2[1][1]}; } -inline ComplexMatrix kronecker_product(const ComplexMatrix& lhs, const ComplexMatrix& rhs) { - ComplexMatrix result(lhs.rows() * rhs.rows(), lhs.cols() * rhs.cols()); +inline internal::ComplexMatrix kronecker_product(const internal::ComplexMatrix& lhs, + const internal::ComplexMatrix& rhs) { + internal::ComplexMatrix result(lhs.rows() * rhs.rows(), lhs.cols() * rhs.cols()); for (int i = 0; i < lhs.rows(); i++) { for (int j = 0; j < lhs.cols(); j++) { result.block(i * rhs.rows(), j * rhs.cols(), rhs.rows(), rhs.cols()) = lhs(i, j) * rhs; @@ -85,9 +86,9 @@ inline ComplexMatrix kronecker_product(const ComplexMatrix& lhs, const ComplexMa return result; } -inline ComplexMatrix get_expanded_matrix(const ComplexMatrix& from_matrix, - const std::vector& from_targets, - std::vector& to_targets) { +inline internal::ComplexMatrix get_expanded_matrix(const internal::ComplexMatrix& from_matrix, + const std::vector& from_targets, + std::vector& to_targets) { std::vector targets_map(from_targets.size()); std::ranges::transform(from_targets, targets_map.begin(), [&](std::uint64_t x) { return std::ranges::lower_bound(to_targets, x) - to_targets.begin(); @@ -105,8 +106,8 @@ inline ComplexMatrix get_expanded_matrix(const ComplexMatrix& from_matrix, for (std::uint64_t i : std::views::iota(0ULL, 1ULL << to_targets.size())) { if ((i & targets_idx_mask) == 0) outer_indices.push_back(i); } - ComplexMatrix to_matrix = - ComplexMatrix::Zero(1ULL << to_targets.size(), 1ULL << to_targets.size()); + internal::ComplexMatrix to_matrix = + internal::ComplexMatrix::Zero(1ULL << to_targets.size(), 1ULL << to_targets.size()); for (std::uint64_t i : std::views::iota(0ULL, 1ULL << from_targets.size())) { for (std::uint64_t j : std::views::iota(0ULL, 1ULL << from_targets.size())) { for (std::uint64_t o : outer_indices) { diff --git a/tests/circuit/circuit_test.cpp b/tests/circuit/circuit_test.cpp index 2996d324..5af0ad29 100644 --- a/tests/circuit/circuit_test.cpp +++ b/tests/circuit/circuit_test.cpp @@ -146,7 +146,7 @@ TEST(CircuitTest, CircuitBasic) { PauliOperator pauli = PauliOperator("I 0 X 1 Y 2 Z 3"); circuit.add_gate(multi_Pauli(pauli)); - ComplexMatrix mat_x(2, 2); + internal::ComplexMatrix mat_x(2, 2); target = random.int32() % n; mat_x << 0, 1, 1, 0; circuit.add_gate(dense_matrix(target, mat_x)); From 1bcd981dcc276549bb3e178fd5984a34b4ce22ba Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 30 Aug 2024 03:31:02 +0000 Subject: [PATCH 32/55] . --- exe/main.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/exe/main.cpp b/exe/main.cpp index 1c6bed85..7354deb2 100644 --- a/exe/main.cpp +++ b/exe/main.cpp @@ -14,15 +14,7 @@ using namespace std; void run() { std::uint64_t n_qubits = 5; - Kokkos::parallel_for( - 10, KOKKOS_LAMBDA(int i) { - Kokkos::printf("{%lf, %lf, %lf, %lf}\n", - EXAMPLE(0).real(), - EXAMPLE(1).real(), - EXAMPLE(2).real(), - EXAMPLE(3).real()); - Kokkos::printf("%lf\n", INVERSE_SQRT2); - }); + auto state = StateVector::Haar_random_state(n_qubits); } int main() { From 14b969e85646725f97ea5518d65b9c812027ffde Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 30 Aug 2024 03:39:26 +0000 Subject: [PATCH 33/55] use M_PI in test --- tests/circuit/circuit_test.cpp | 2 +- tests/gate/merge_test.cpp | 30 ++++++++++++++---------------- tests/gate/param_gate_test.cpp | 2 +- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/tests/circuit/circuit_test.cpp b/tests/circuit/circuit_test.cpp index 5af0ad29..24dbc5b7 100644 --- a/tests/circuit/circuit_test.cpp +++ b/tests/circuit/circuit_test.cpp @@ -243,7 +243,7 @@ TEST(CircuitTest, CircuitRev) { /* Observable observable(n); - angle = 2 * Kokkos::numbers::pi * random.uniform(); + angle = 2 * M_PI * random.uniform(); observable.add_operator(1.0, "Z 0"); observable.add_operator(2.0, "Z 0 Z 1"); diff --git a/tests/gate/merge_test.cpp b/tests/gate/merge_test.cpp index fc4566b7..2295716f 100644 --- a/tests/gate/merge_test.cpp +++ b/tests/gate/merge_test.cpp @@ -29,17 +29,15 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::SqrtYdag(target)); gates.push_back(gate::P0(target)); gates.push_back(gate::P1(target)); - gates.push_back(gate::RX(target, random.uniform() * Kokkos::numbers::pi * 2)); - gates.push_back(gate::RY(target, random.uniform() * Kokkos::numbers::pi * 2)); - gates.push_back(gate::RZ(target, random.uniform() * Kokkos::numbers::pi * 2)); - gates.push_back(gate::U1(target, random.uniform() * Kokkos::numbers::pi * 2)); - gates.push_back(gate::U2(target, - random.uniform() * Kokkos::numbers::pi * 2, - random.uniform() * Kokkos::numbers::pi * 2)); + gates.push_back(gate::RX(target, random.uniform() * M_PI * 2)); + gates.push_back(gate::RY(target, random.uniform() * M_PI * 2)); + gates.push_back(gate::RZ(target, random.uniform() * M_PI * 2)); + gates.push_back(gate::U1(target, random.uniform() * M_PI * 2)); + gates.push_back(gate::U2(target, random.uniform() * M_PI * 2, random.uniform() * M_PI * 2)); gates.push_back(gate::U3(target, - random.uniform() * Kokkos::numbers::pi * 2, - random.uniform() * Kokkos::numbers::pi * 2, - random.uniform() * Kokkos::numbers::pi * 2)); + random.uniform() * M_PI * 2, + random.uniform() * M_PI * 2, + random.uniform() * M_PI * 2)); gates.push_back( gate::OneTargetMatrix(target, {std::array{Complex(random.uniform(), random.uniform()), @@ -51,7 +49,7 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::Swap(target, target ^ 1)); } gates.push_back(gate::I()); - gates.push_back(gate::GlobalPhase(random.uniform() * Kokkos::numbers::pi * 2)); + gates.push_back(gate::GlobalPhase(random.uniform() * M_PI * 2)); gates.push_back( gate::TwoTargetMatrix(0, 1, @@ -75,11 +73,11 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::Pauli(PauliOperator("Z 0", random.uniform()))); gates.push_back(gate::Pauli(PauliOperator("Z 1", random.uniform()))); gates.push_back(gate::PauliRotation(PauliOperator("X 0 Y 1", random.uniform()), - random.uniform() * Kokkos::numbers::pi * 2)); - gates.push_back(gate::PauliRotation(PauliOperator("Z 0", random.uniform()), - random.uniform() * Kokkos::numbers::pi * 2)); - gates.push_back(gate::PauliRotation(PauliOperator("Z 1", random.uniform()), - random.uniform() * Kokkos::numbers::pi * 2)); + random.uniform() * M_PI * 2)); + gates.push_back( + gate::PauliRotation(PauliOperator("Z 0", random.uniform()), random.uniform() * M_PI * 2)); + gates.push_back( + gate::PauliRotation(PauliOperator("Z 1", random.uniform()), random.uniform() * M_PI * 2)); for (auto&& g1 : gates) { for (auto&& g2 : gates) { std::uint64_t n = 2; diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index 7674d81c..778d42a6 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -103,7 +103,7 @@ TEST(ParamGateTest, ApplyPProbablisticGate) { StateVector state(1); for ([[maybe_unused]] auto _ : std::views::iota(0, 100)) { std::uint64_t before = state.sampling(1)[0]; - probgate->update_quantum_state(state, scaluq::Kokkos::numbers::pi); + probgate->update_quantum_state(state, M_PI); std::uint64_t after = state.sampling(1)[0]; if (before != after) { x_cnt++; From 92e65b7ee659220a9168b675db937664e286def6 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 30 Aug 2024 04:04:27 +0000 Subject: [PATCH 34/55] UINT -> std::uint64_t --- README.md | 4 +- exe/main.cpp | 2 +- python/binding.cpp | 56 ++++++---- scaluq/circuit/circuit.cpp | 26 ++--- scaluq/circuit/circuit.hpp | 19 ++-- scaluq/gate/gate.hpp | 23 ++-- scaluq/gate/gate_factory.hpp | 99 +++++++++++------- scaluq/gate/gate_matrix.hpp | 20 ++-- scaluq/gate/gate_pauli.hpp | 8 +- scaluq/gate/gate_probablistic.hpp | 20 ++-- scaluq/gate/gate_standard.hpp | 14 ++- scaluq/gate/merge_gate.cpp | 29 ++--- scaluq/gate/param_gate.hpp | 23 ++-- scaluq/gate/param_gate_factory.hpp | 14 ++- scaluq/gate/param_gate_pauli.hpp | 6 +- scaluq/gate/param_gate_probablistic.hpp | 20 ++-- scaluq/gate/update_ops.hpp | 83 +++++++++------ scaluq/gate/update_ops_dense_matrix.cpp | 29 ++--- scaluq/gate/update_ops_pauli.cpp | 20 ++-- scaluq/gate/update_ops_standard.cpp | 118 +++++++++++++-------- scaluq/operator/operator.cpp | 76 +++++++------- scaluq/operator/operator.hpp | 13 +-- scaluq/operator/pauli_operator.cpp | 92 ++++++++-------- scaluq/operator/pauli_operator.hpp | 28 ++--- scaluq/state/state_vector.cpp | 81 +++++++------- scaluq/state/state_vector.hpp | 31 +++--- scaluq/state/state_vector_batched.cpp | 122 ++++++++++++---------- scaluq/state/state_vector_batched.hpp | 37 +++---- scaluq/types.hpp | 2 - scaluq/util/bit_vector.hpp | 73 ++++++------- scaluq/util/random.hpp | 5 +- scaluq/util/utility.hpp | 54 +++++----- tests/circuit/circuit_test.cpp | 25 ++--- tests/circuit/param_circuit_test.cpp | 37 +++---- tests/gate/gate_test.cpp | 67 ++++++------ tests/gate/merge_test.cpp | 4 +- tests/gate/param_gate_test.cpp | 28 ++--- tests/operator/test_operator.cpp | 52 ++++----- tests/operator/test_pauli_operator.cpp | 8 +- tests/state/state_vector_batched_test.cpp | 50 ++++----- tests/state/state_vector_test.cpp | 78 +++++++------- tests/util/util.hpp | 79 +++++++------- 42 files changed, 907 insertions(+), 768 deletions(-) diff --git a/README.md b/README.md index afd348c4..a07be6bf 100644 --- a/README.md +++ b/README.md @@ -69,12 +69,12 @@ https://scaluq.readthedocs.io/en/latest/index.html #include #include -using scaluq::UINT; +using scaluq::std::uint64_t; int main() { scaluq::initialize(); // must be called before using any scaluq methods { - const UINT n_qubits = 3; + const std::uint64_t n_qubits = 3; scaluq::StateVector state = scaluq::StateVector::Haar_random_state(n_qubits, 0); std::cout << state << std::endl; diff --git a/exe/main.cpp b/exe/main.cpp index 1fefff45..7354deb2 100644 --- a/exe/main.cpp +++ b/exe/main.cpp @@ -13,7 +13,7 @@ using namespace scaluq; using namespace std; void run() { - UINT n_qubits = 5; + std::uint64_t n_qubits = 5; auto state = StateVector::Haar_random_state(n_qubits); } diff --git a/python/binding.cpp b/python/binding.cpp index 6c1fb5ed..ba183a4c 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -91,13 +91,13 @@ NB_MODULE(scaluq_core, m) { "Vector representation of quantum state.\n\n.. note:: Qubit index is " "start from 0. If the amplitudes of $\\ket{b_{n-1}\\dots b_0}$ is " "$b_i$, the state is $\\sum_i b_i 2^i$.") - .def(nb::init(), + .def(nb::init(), "Construct state vector with specified qubits, initialized with computational " "basis $\\ket{0\\dots0}$.") .def(nb::init(), "Constructing state vector by copying other state.") .def_static( "Haar_random_state", - [](UINT n_qubits, std::optional seed) { + [](std::uint64_t n_qubits, std::optional seed) { return StateVector::Haar_random_state(n_qubits, seed.value_or(std::random_device{}())); }, @@ -159,7 +159,9 @@ NB_MODULE(scaluq_core, m) { "$\\ket{\\mathrm{this}}\\leftarrow\\mathrm{coef}\\ket{\\mathrm{this}}$.") .def( "sampling", - [](const StateVector &state, UINT sampling_count, std::optional seed) { + [](const StateVector &state, + std::uint64_t sampling_count, + std::optional seed) { return state.sampling(sampling_count, seed.value_or(std::random_device{}())); }, "sampling_count"_a, @@ -179,7 +181,7 @@ NB_MODULE(scaluq_core, m) { "Batched vector representation of quantum state.\n\n.. note:: Qubit index is start from 0. " "If the amplitudes of $\\ket{b_{n-1}\\dots b_0}$ is $b_i$, the state is $\\sum_i b_i " "2^i$.") - .def(nb::init(), + .def(nb::init(), "Construct batched state vector with specified batch size and qubits.") .def(nb::init(), "Constructing batched state vector by copying other batched state.") @@ -192,7 +194,8 @@ NB_MODULE(scaluq_core, m) { nb::overload_cast(&StateVectorBatched::set_state_vector), "Set the state vector for all batches.") .def("set_state_vector", - nb::overload_cast(&StateVectorBatched::set_state_vector), + nb::overload_cast( + &StateVectorBatched::set_state_vector), "Set the state vector for a specific batch.") .def("get_state_vector", &StateVectorBatched::get_state_vector, @@ -208,7 +211,9 @@ NB_MODULE(scaluq_core, m) { "Initialize with computational basis \\ket{\\mathrm{basis}}.") .def( "sampling", - [](const StateVectorBatched &states, UINT sampling_count, std::optional seed) { + [](const StateVectorBatched &states, + std::uint64_t sampling_count, + std::optional seed) { return states.sampling(sampling_count, seed.value_or(std::random_device{}())); }, "sampling_count"_a, @@ -217,7 +222,10 @@ NB_MODULE(scaluq_core, m) { "length.") .def_static( "Haar_random_states", - [](UINT batch_size, UINT n_qubits, bool set_same_state, std::optional seed) { + [](std::uint64_t batch_size, + std::uint64_t n_qubits, + bool set_same_state, + std::optional seed) { return StateVectorBatched::Haar_random_states( batch_size, n_qubits, set_same_state, seed.value_or(std::random_device{}())); }, @@ -641,25 +649,25 @@ NB_MODULE(scaluq_core, m) { "Generate general ParamGate class instance of PRX.", "target"_a, "coef"_a = 1., - "controls"_a = std::vector{}); + "controls"_a = std::vector{}); mgate.def("PRY", &gate::PRY, "Generate general ParamGate class instance of PRY.", "target"_a, "coef"_a = 1., - "controls"_a = std::vector{}); + "controls"_a = std::vector{}); mgate.def("PRZ", &gate::PRZ, "Generate general ParamGate class instance of PRZ.", "target"_a, "coef"_a = 1., - "controls"_a = std::vector{}); + "controls"_a = std::vector{}); mgate.def("PPauliRotation", &gate::PPauliRotation, "Generate general ParamGate class instance of PPauliRotation.", "pauli"_a, "coef"_a = 1., - "controls"_a = std::vector{}); + "controls"_a = std::vector{}); mgate.def("PProbablistic", &gate::PProbablistic, "Generate general ParamGate class instance of PProbablistic."); @@ -679,7 +687,7 @@ NB_MODULE(scaluq_core, m) { "Generate general ParamGate class instance of PProbablistic."); nb::class_(m, "Circuit", "Quantum circuit represented as gate array") - .def(nb::init(), "Initialize empty circuit of specified qubits.") + .def(nb::init(), "Initialize empty circuit of specified qubits.") .def("n_qubits", &Circuit::n_qubits, "Get property of `n_qubits`.") .def("gate_list", &Circuit::gate_list, @@ -740,12 +748,14 @@ NB_MODULE(scaluq_core, m) { "pauli_string"_a, "coef"_a = 1., "Initialize data with pauli string.") - .def(nb::init &, const std::vector &, Complex>(), + .def(nb::init &, + const std::vector &, + Complex>(), "target_qubit_list"_a, "pauli_id_list"_a, "coef"_a = 1., "Initialize data with target qubits and pauli ids.") - .def(nb::init &, Complex>(), + .def(nb::init &, Complex>(), "pauli_id_par_qubit"_a, "coef"_a = 1., "Initialize data with pauli ids per qubit.") @@ -780,7 +790,9 @@ NB_MODULE(scaluq_core, m) { "PauliOperator", "Pauli operator as coef and tensor product of single pauli for each qubit.") .def(nb::init(), "coef"_a = 1., "Initialize operator which just multiplying coef.") - .def(nb::init &, const std::vector &, Complex>(), + .def(nb::init &, + const std::vector &, + Complex>(), "target_qubit_list"_a, "pauli_id_list"_a, "coef"_a = 1., @@ -792,7 +804,7 @@ NB_MODULE(scaluq_core, m) { "Initialize pauli operator. If `pauli_string` is `\"X0Y2\"`, Pauli-X is applied to " "0-th qubit and Pauli-Y is applied to 2-th qubit. In `pauli_string`, spaces are " "ignored.") - .def(nb::init &, Complex>(), + .def(nb::init &, Complex>(), "pauli_id_par_qubit"_a, "coef"_a = 1., "Initialize pauli operator. For each `i`, single pauli correspond to " @@ -808,13 +820,13 @@ NB_MODULE(scaluq_core, m) { auto &bit_flip_raw = bit_flip_mask.data_raw(); assert(bit_flip_raw.empty()); while (bit_flip_mask_py > nb::int_(0)) { - bit_flip_raw.push_back((UINT)nb::int_(bit_flip_mask_py & mask)); + bit_flip_raw.push_back((std::uint64_t)nb::int_(bit_flip_mask_py & mask)); bit_flip_mask_py >>= nb::int_(64); } auto &phase_flip_raw = phase_flip_mask.data_raw(); assert(phase_flip_raw.empty()); while (phase_flip_mask_py > nb::int_(0)) { - phase_flip_raw.push_back((UINT)nb::int_(phase_flip_mask_py & mask)); + phase_flip_raw.push_back((std::uint64_t)nb::int_(phase_flip_mask_py & mask)); phase_flip_mask_py >>= nb::int_(64); } new (t) PauliOperator(bit_flip_mask, phase_flip_mask, coef); @@ -839,11 +851,11 @@ NB_MODULE(scaluq_core, m) { [](const PauliOperator &pauli) { const auto [x_mask, z_mask] = pauli.get_XZ_mask_representation(); nb::int_ x_mask_py(0); - for (UINT i = 0; i < x_mask.size(); ++i) { + for (std::uint64_t i = 0; i < x_mask.size(); ++i) { x_mask_py |= nb::int_(x_mask[i]) << nb::int_(i); } nb::int_ z_mask_py(0); - for (UINT i = 0; i < z_mask.size(); ++i) { + for (std::uint64_t i = 0; i < z_mask.size(); ++i) { z_mask_py |= nb::int_(z_mask[i]) << nb::int_(i); } return std::make_tuple(x_mask_py, z_mask_py); @@ -871,7 +883,7 @@ NB_MODULE(scaluq_core, m) { .def(nb::self * Complex()); nb::class_(m, "Operator", "General quantum operator class.") - .def(nb::init(), + .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.") @@ -883,7 +895,7 @@ NB_MODULE(scaluq_core, m) { "Add a Pauli operator to this operator.") .def( "add_random_operator", - [](Operator &op, UINT 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{}())); }, diff --git a/scaluq/circuit/circuit.cpp b/scaluq/circuit/circuit.cpp index 68f10acd..4cf3badb 100644 --- a/scaluq/circuit/circuit.cpp +++ b/scaluq/circuit/circuit.cpp @@ -3,30 +3,30 @@ #include namespace scaluq { -UINT Circuit::calculate_depth() const { - std::vector filled_step(_n_qubits, 0ULL); +std::uint64_t Circuit::calculate_depth() const { + std::vector filled_step(_n_qubits, 0ULL); for (const auto& gate : _gate_list) { - std::vector control_qubits = gate.index() == 0 - ? std::get<0>(gate)->control_qubit_list() - : std::get<1>(gate).first->control_qubit_list(); - std::vector target_qubits = gate.index() == 0 - ? std::get<0>(gate)->target_qubit_list() - : std::get<1>(gate).first->target_qubit_list(); - UINT max_step_amount_target_qubits = 0; - for (UINT control : control_qubits) { + std::vector control_qubits = + gate.index() == 0 ? std::get<0>(gate)->control_qubit_list() + : std::get<1>(gate).first->control_qubit_list(); + std::vector target_qubits = + gate.index() == 0 ? std::get<0>(gate)->target_qubit_list() + : std::get<1>(gate).first->target_qubit_list(); + std::uint64_t max_step_amount_target_qubits = 0; + for (std::uint64_t control : control_qubits) { if (max_step_amount_target_qubits < filled_step[control]) { max_step_amount_target_qubits = filled_step[control]; } } - for (UINT target : control_qubits) { + for (std::uint64_t target : control_qubits) { if (max_step_amount_target_qubits < filled_step[target]) { max_step_amount_target_qubits = filled_step[target]; } } - for (UINT control : control_qubits) { + for (std::uint64_t control : control_qubits) { filled_step[control] = max_step_amount_target_qubits + 1; } - for (UINT target : target_qubits) { + for (std::uint64_t target : target_qubits) { filled_step[target] = max_step_amount_target_qubits + 1; } } diff --git a/scaluq/circuit/circuit.hpp b/scaluq/circuit/circuit.hpp index 3c8a02f8..eb9a5899 100644 --- a/scaluq/circuit/circuit.hpp +++ b/scaluq/circuit/circuit.hpp @@ -11,11 +11,11 @@ namespace scaluq { class Circuit { public: using GateWithKey = std::variant>; - explicit Circuit(UINT n_qubits) : _n_qubits(n_qubits) {} + explicit Circuit(std::uint64_t n_qubits) : _n_qubits(n_qubits) {} - [[nodiscard]] inline UINT n_qubits() const { return _n_qubits; } + [[nodiscard]] inline std::uint64_t n_qubits() const { return _n_qubits; } [[nodiscard]] inline const std::vector& gate_list() const { return _gate_list; } - [[nodiscard]] inline UINT n_gates() { return _gate_list.size(); } + [[nodiscard]] inline std::uint64_t n_gates() { return _gate_list.size(); } [[nodiscard]] inline const std::set key_set() const { std::set key_set; for (auto&& gate : _gate_list) { @@ -23,22 +23,23 @@ class Circuit { } return key_set; } - [[nodiscard]] inline const GateWithKey& get(UINT idx) const { + [[nodiscard]] inline const GateWithKey& get(std::uint64_t idx) const { if (idx >= _gate_list.size()) { - throw std::runtime_error("Circuit::get(UINT): index out of bounds"); + throw std::runtime_error("Circuit::get(std::uint64_t): index out of bounds"); } return _gate_list[idx]; } - [[nodiscard]] inline std::optional get_key(UINT idx) { + [[nodiscard]] inline std::optional get_key(std::uint64_t idx) { if (idx >= _gate_list.size()) { - throw std::runtime_error("Circuit::get_parameter_key(UINT): index out of bounds"); + throw std::runtime_error( + "Circuit::get_parameter_key(std::uint64_t): index out of bounds"); } const auto& gate = _gate_list[idx]; if (gate.index() == 0) return std::nullopt; return std::get<1>(gate).second; } - [[nodiscard]] UINT calculate_depth() const; + [[nodiscard]] std::uint64_t calculate_depth() const; void add_gate(const Gate& gate); void add_gate(Gate&& gate); @@ -54,7 +55,7 @@ class Circuit { Circuit get_inverse() const; private: - UINT _n_qubits; + std::uint64_t _n_qubits; std::vector _gate_list; diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 1c59208b..527402df 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -126,9 +126,9 @@ constexpr GateType get_gate_type() { namespace internal { class GateBase : public std::enable_shared_from_this { protected: - UINT _target_mask, _control_mask; + std::uint64_t _target_mask, _control_mask; void check_qubit_mask_within_bounds(const StateVector& state_vector) const { - UINT full_mask = (1ULL << state_vector.n_qubits()) - 1; + std::uint64_t full_mask = (1ULL << state_vector.n_qubits()) - 1; if ((_target_mask | _control_mask) > full_mask) [[unlikely]] { throw std::runtime_error( "Error: Gate::update_quantum_state(StateVector& state): " @@ -137,28 +137,31 @@ class GateBase : public std::enable_shared_from_this { } public: - GateBase(UINT target_mask, UINT control_mask) + GateBase(std::uint64_t target_mask, std::uint64_t control_mask) : _target_mask(target_mask), _control_mask(control_mask) { if (_target_mask & _control_mask) [[unlikely]] { throw std::runtime_error( - "Error: Gate::Gate(UINT target_mask, UINT control_mask) : Target and " + "Error: Gate::Gate(std::uint64_t target_mask, std::uint64_t control_mask) : Target " + "and " "control qubits must not overlap."); } } virtual ~GateBase() = default; - [[nodiscard]] virtual std::vector target_qubit_list() const { + [[nodiscard]] virtual std::vector target_qubit_list() const { return mask_to_vector(_target_mask); } - [[nodiscard]] virtual std::vector control_qubit_list() const { + [[nodiscard]] virtual std::vector control_qubit_list() const { return mask_to_vector(_control_mask); } - [[nodiscard]] virtual std::vector operand_qubit_list() const { + [[nodiscard]] virtual std::vector operand_qubit_list() const { return mask_to_vector(_target_mask | _control_mask); } - [[nodiscard]] virtual UINT target_qubit_mask() const { return _target_mask; } - [[nodiscard]] virtual UINT control_qubit_mask() const { return _control_mask; } - [[nodiscard]] virtual UINT operand_qubit_mask() const { return _target_mask | _control_mask; } + [[nodiscard]] virtual std::uint64_t target_qubit_mask() const { return _target_mask; } + [[nodiscard]] virtual std::uint64_t control_qubit_mask() const { return _control_mask; } + [[nodiscard]] virtual std::uint64_t operand_qubit_mask() const { + return _target_mask | _control_mask; + } [[nodiscard]] virtual Gate get_inverse() const = 0; [[nodiscard]] virtual ComplexMatrix get_matrix() const = 0; diff --git a/scaluq/gate/gate_factory.hpp b/scaluq/gate/gate_factory.hpp index 26cfc194..6ed1580c 100644 --- a/scaluq/gate/gate_factory.hpp +++ b/scaluq/gate/gate_factory.hpp @@ -17,143 +17,161 @@ class GateFactory { } // namespace internal namespace gate { inline Gate I() { return internal::GateFactory::create_gate(); } -inline Gate GlobalPhase(double phase, const std::vector& control_qubits = {}) { +inline Gate GlobalPhase(double phase, const std::vector& control_qubits = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask(control_qubits), phase); } -inline Gate X(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate Y(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate Z(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate H(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate S(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate Sdag(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate T(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate Tdag(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate SqrtX(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate SqrtXdag(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate SqrtY(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate SqrtYdag(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate P0(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate P1(UINT target, const std::vector& controls = {}) { +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)); } -inline Gate RX(UINT target, double angle, const std::vector& controls = {}) { +inline Gate RX(std::uint64_t target, + double angle, + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), angle); } -inline Gate RY(UINT target, double angle, const std::vector& controls = {}) { +inline Gate RY(std::uint64_t target, + double angle, + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), angle); } -inline Gate RZ(UINT target, double angle, const std::vector& controls = {}) { +inline Gate RZ(std::uint64_t target, + double angle, + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), angle); } -inline Gate U1(UINT target, double lambda, const std::vector& controls = {}) { +inline Gate U1(std::uint64_t target, + double lambda, + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), lambda); } -inline Gate U2(UINT target, double phi, double lambda, const std::vector& controls = {}) { +inline Gate U2(std::uint64_t target, + double phi, + double lambda, + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), phi, lambda); } -inline Gate U3( - UINT target, double theta, double phi, double lambda, const std::vector& controls = {}) { +inline Gate U3(std::uint64_t target, + double theta, + double phi, + double lambda, + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), theta, phi, lambda); } -inline Gate OneTargetMatrix(UINT target, +inline Gate OneTargetMatrix(std::uint64_t target, const std::array, 2>& matrix, - const std::vector& controls = {}) { + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), matrix); } -inline Gate CX(UINT control, UINT target) { +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})); } inline auto& CNot = CX; -inline Gate CZ(UINT control, UINT target) { +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})); } -inline Gate CCX(UINT control1, UINT control2, UINT target) { +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})); } inline auto& Toffoli = CCX; inline auto& CCNot = CCX; -inline Gate Swap(UINT target1, UINT target2, const std::vector& controls = {}) { +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)); } -inline Gate TwoTargetMatrix(UINT target1, - UINT target2, +inline Gate TwoTargetMatrix(std::uint64_t target1, + std::uint64_t target2, const std::array, 4>& matrix, - const std::vector& controls = {}) { + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask({target1, target2}), internal::vector_to_mask(controls), matrix); } // まだ -inline Gate Pauli(const PauliOperator& pauli, const std::vector& controls = {}) { +inline Gate Pauli(const PauliOperator& pauli, const std::vector& controls = {}) { auto tar = pauli.target_qubit_list(); return internal::GateFactory::create_gate( internal::vector_to_mask(controls), pauli); } inline Gate PauliRotation(const PauliOperator& pauli, double angle, - const std::vector& controls = {}) { + const std::vector& controls = {}) { return internal::GateFactory::create_gate( internal::vector_to_mask(controls), pauli, angle); } -inline Gate DenseMatrix(const std::vector& targets, +inline Gate DenseMatrix(const std::vector& targets, const ComplexMatrix& matrix, - const std::vector& controls = {}) { - UINT nqubits = targets.size(); - UINT dim = 1ULL << nqubits; - if (static_cast(matrix.rows()) != dim || static_cast(matrix.cols()) != dim) { + const std::vector& controls = {}) { + std::uint64_t nqubits = targets.size(); + std::uint64_t dim = 1ULL << nqubits; + if (static_cast(matrix.rows()) != dim || + static_cast(matrix.cols()) != dim) { throw std::runtime_error( - "gate::DenseMatrix(const std::vector&, const ComplexMatrix&): matrix size " + "gate::DenseMatrix(const std::vector&, const ComplexMatrix&): matrix " + "size " "must " "be 2^{n_qubits} x 2^{n_qubits}."); } @@ -186,7 +204,8 @@ inline Gate DenseMatrix(const std::vector& targets, controls); } throw std::runtime_error( - "gate::DenseMatrix(const std::vector&, const ComplexMatrix&): DenseMatrix gate " + "gate::DenseMatrix(const std::vector&, const ComplexMatrix&): DenseMatrix " + "gate " "more " "than two qubits is not implemented yet."); } diff --git a/scaluq/gate/gate_matrix.hpp b/scaluq/gate/gate_matrix.hpp index e74cffc9..5d80ff23 100644 --- a/scaluq/gate/gate_matrix.hpp +++ b/scaluq/gate/gate_matrix.hpp @@ -14,8 +14,8 @@ class OneTargetMatrixGateImpl : public GateBase { matrix_2_2 _matrix; public: - OneTargetMatrixGateImpl(UINT target_mask, - UINT control_mask, + OneTargetMatrixGateImpl(std::uint64_t target_mask, + std::uint64_t control_mask, const std::array, 2>& matrix) : GateBase(target_mask, control_mask) { _matrix.val[0][0] = matrix[0][0]; @@ -54,12 +54,12 @@ class TwoTargetMatrixGateImpl : public GateBase { matrix_4_4 _matrix; public: - TwoTargetMatrixGateImpl(UINT target_mask, - UINT control_mask, + TwoTargetMatrixGateImpl(std::uint64_t target_mask, + std::uint64_t control_mask, const std::array, 4>& matrix) : GateBase(target_mask, control_mask) { - for (UINT i : std::views::iota(0, 4)) { - for (UINT j : std::views::iota(0, 4)) { + for (std::uint64_t i : std::views::iota(0, 4)) { + for (std::uint64_t j : std::views::iota(0, 4)) { _matrix.val[i][j] = matrix[i][j]; } } @@ -67,8 +67,8 @@ class TwoTargetMatrixGateImpl : public GateBase { std::array, 4> matrix() const { std::array, 4> matrix; - for (UINT i : std::views::iota(0, 4)) { - for (UINT j : std::views::iota(0, 4)) { + for (std::uint64_t i : std::views::iota(0, 4)) { + for (std::uint64_t j : std::views::iota(0, 4)) { matrix[i][j] = _matrix.val[i][j]; } } @@ -77,8 +77,8 @@ class TwoTargetMatrixGateImpl : public GateBase { Gate get_inverse() const override { std::array, 4> matrix_dag; - for (UINT i : std::views::iota(0, 4)) { - for (UINT j : std::views::iota(0, 4)) { + for (std::uint64_t i : std::views::iota(0, 4)) { + for (std::uint64_t j : std::views::iota(0, 4)) { matrix_dag[i][j] = Kokkos::conj(_matrix.val[j][i]); } } diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index ae8ad38f..0671fbb1 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -12,11 +12,11 @@ class PauliGateImpl : public GateBase { const PauliOperator _pauli; public: - PauliGateImpl(UINT control_mask, const PauliOperator& pauli) + 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; }; - std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } + std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } Gate get_inverse() const override { return shared_from_this(); } ComplexMatrix get_matrix() const override { return this->_pauli.get_matrix(); } @@ -31,13 +31,13 @@ class PauliRotationGateImpl : public GateBase { const double _angle; public: - PauliRotationGateImpl(UINT control_mask, const PauliOperator& pauli, double angle) + PauliRotationGateImpl(std::uint64_t control_mask, const PauliOperator& pauli, double angle) : GateBase(vector_to_mask(pauli.target_qubit_list()), control_mask), _pauli(pauli), _angle(angle) {} PauliOperator pauli() const { return _pauli; } - std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } + std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } double angle() const { return _angle; } Gate get_inverse() const override { diff --git a/scaluq/gate/gate_probablistic.hpp b/scaluq/gate/gate_probablistic.hpp index 6b151dc3..26a33478 100644 --- a/scaluq/gate/gate_probablistic.hpp +++ b/scaluq/gate/gate_probablistic.hpp @@ -14,7 +14,7 @@ class ProbablisticGateImpl : public GateBase { ProbablisticGateImpl(const std::vector& distribution, const std::vector& gate_list) : GateBase(0, 0), _distribution(distribution), _gate_list(gate_list) { - UINT n = distribution.size(); + std::uint64_t n = distribution.size(); if (n == 0) { throw std::runtime_error("At least one gate is required."); } @@ -31,32 +31,32 @@ class ProbablisticGateImpl : public GateBase { const std::vector& gate_list() const { return _gate_list; } const std::vector& distribution() const { return _distribution; } - std::vector target_qubit_list() const override { + std::vector target_qubit_list() const override { throw std::runtime_error( "ProbablisticGateImpl::target_qubit_list(): This function must not be used in " "ProbablisticGateImpl."); } - std::vector control_qubit_list() const override { + std::vector control_qubit_list() const override { throw std::runtime_error( "ProbablisticGateImpl::control_qubit_list(): This function must not be used in " "ProbablisticGateImpl."); } - std::vector operand_qubit_list() const override { + std::vector operand_qubit_list() const override { throw std::runtime_error( "ProbablisticGateImpl::operand_qubit_list(): This function must not be used in " "ProbablisticGateImpl."); } - UINT target_qubit_mask() const override { + std::uint64_t target_qubit_mask() const override { throw std::runtime_error( "ProbablisticGateImpl::target_qubit_mask(): This function must not be used in " "ProbablisticGateImpl."); } - UINT control_qubit_mask() const override { + std::uint64_t control_qubit_mask() const override { throw std::runtime_error( "ProbablisticGateImpl::control_qubit_mask(): This function must not be used in " "ProbablisticGateImpl."); } - UINT operand_qubit_mask() const override { + std::uint64_t operand_qubit_mask() const override { throw std::runtime_error( "ProbablisticGateImpl::operand_qubit_mask(): This function must not be used in " "ProbablisticGateImpl."); @@ -79,9 +79,9 @@ class ProbablisticGateImpl : public GateBase { void update_quantum_state(StateVector& state_vector) const override { Random random; double r = random.uniform(); - UINT i = std::distance(_cumlative_distribution.begin(), - std::ranges::upper_bound(_cumlative_distribution, r)) - - 1; + std::uint64_t i = std::distance(_cumlative_distribution.begin(), + std::ranges::upper_bound(_cumlative_distribution, r)) - + 1; if (i >= _gate_list.size()) i = _gate_list.size() - 1; _gate_list[i]->update_quantum_state(state_vector); } diff --git a/scaluq/gate/gate_standard.hpp b/scaluq/gate/gate_standard.hpp index bf4ebd5c..e1046155 100644 --- a/scaluq/gate/gate_standard.hpp +++ b/scaluq/gate/gate_standard.hpp @@ -23,7 +23,7 @@ class GlobalPhaseGateImpl : public GateBase { double _phase; public: - GlobalPhaseGateImpl(UINT control_mask, double phase) + GlobalPhaseGateImpl(std::uint64_t control_mask, double phase) : GateBase(0, control_mask), _phase(phase){}; [[nodiscard]] double phase() const { return _phase; } @@ -46,7 +46,7 @@ class RotationGateBase : public GateBase { double _angle; public: - RotationGateBase(UINT target_mask, UINT control_mask, double angle) + RotationGateBase(std::uint64_t target_mask, std::uint64_t control_mask, double angle) : GateBase(target_mask, control_mask), _angle(angle) {} double angle() const { return _angle; } @@ -391,7 +391,7 @@ class U1GateImpl : public GateBase { double _lambda; public: - U1GateImpl(UINT target_mask, UINT control_mask, double lambda) + U1GateImpl(std::uint64_t target_mask, std::uint64_t control_mask, double lambda) : GateBase(target_mask, control_mask), _lambda(lambda) {} double lambda() const { return _lambda; } @@ -414,7 +414,7 @@ class U2GateImpl : public GateBase { double _phi, _lambda; public: - U2GateImpl(UINT target_mask, UINT control_mask, double phi, double lambda) + U2GateImpl(std::uint64_t target_mask, std::uint64_t control_mask, double phi, double lambda) : GateBase(target_mask, control_mask), _phi(phi), _lambda(lambda) {} double phi() const { return _phi; } @@ -442,7 +442,11 @@ class U3GateImpl : public GateBase { double _theta, _phi, _lambda; public: - U3GateImpl(UINT target_mask, UINT control_mask, double theta, double phi, double lambda) + U3GateImpl(std::uint64_t target_mask, + std::uint64_t control_mask, + double theta, + double phi, + double lambda) : GateBase(target_mask, control_mask), _theta(theta), _phi(phi), _lambda(lambda) {} double theta() const { return _theta; } diff --git a/scaluq/gate/merge_gate.cpp b/scaluq/gate/merge_gate.cpp index c55c524b..2dc5bff1 100644 --- a/scaluq/gate/merge_gate.cpp +++ b/scaluq/gate/merge_gate.cpp @@ -20,7 +20,7 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { if (gate_type2 == GateType::GlobalPhase) return {gate1, GlobalPhaseGate(gate2)->phase()}; // Special case: Pauli - auto get_pauli_id = [&](GateType gate_type) -> std::optional { + auto get_pauli_id = [&](GateType gate_type) -> std::optional { if (gate_type == GateType::I) return 0; if (gate_type == GateType::X) return 1; if (gate_type == GateType::Y) return 2; @@ -32,8 +32,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { assert(!pauli_id1 || pauli_id1 != 0); assert(!pauli_id2 || pauli_id2 != 0); if (pauli_id1 && pauli_id2) { - UINT target1 = gate1->target_qubit_list()[0]; - UINT target2 = gate2->target_qubit_list()[0]; + std::uint64_t target1 = gate1->target_qubit_list()[0]; + std::uint64_t target2 = gate2->target_qubit_list()[0]; if (target1 == target2) { if (pauli_id1 == pauli_id2) return {gate::I(), 0.}; if (pauli_id1 == 1) { @@ -64,7 +64,7 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { } // Special case: Phase - auto get_oct_phase = [&](GateType gate_type) -> std::optional { + auto get_oct_phase = [&](GateType gate_type) -> std::optional { if (gate_type == GateType::I) return 0; if (gate_type == GateType::Z) return 4; if (gate_type == GateType::S) return 2; @@ -73,7 +73,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { if (gate_type == GateType::Tdag) return 7; return std::nullopt; }; - auto oct_phase_gate = [&](UINT oct_phase, UINT target) -> std::optional { + auto oct_phase_gate = [&](std::uint64_t oct_phase, + std::uint64_t target) -> std::optional { oct_phase &= 7; if (oct_phase == 0) return gate::I(); if (oct_phase == 4) return gate::Z(target); @@ -86,8 +87,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { auto oct_phase1 = get_oct_phase(gate_type1); auto oct_phase2 = get_oct_phase(gate_type2); if (oct_phase1 && oct_phase2) { - UINT target1 = gate1->target_qubit_list()[0]; - UINT target2 = gate2->target_qubit_list()[0]; + std::uint64_t target1 = gate1->target_qubit_list()[0]; + std::uint64_t target2 = gate2->target_qubit_list()[0]; if (target1 == target2) { auto g = oct_phase_gate(oct_phase1.value() + oct_phase2.value(), target1); if (g) return {g.value(), 0.}; @@ -95,8 +96,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { } if ((oct_phase1 || gate_type1 == GateType::RZ || gate_type1 == GateType::U1) && (oct_phase2 || gate_type2 == GateType::RZ || gate_type2 == GateType::U1)) { - UINT target1 = gate1->target_qubit_list()[0]; - UINT target2 = gate2->target_qubit_list()[0]; + std::uint64_t target1 = gate1->target_qubit_list()[0]; + std::uint64_t target2 = gate2->target_qubit_list()[0]; if (target1 == target2) { double phase1 = oct_phase1 ? oct_phase1.value() * PI() / 4 : gate_type1 == GateType::RZ ? RZGate(gate1)->angle() @@ -122,8 +123,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { auto rx_param1 = get_rx_angle(gate1, gate_type1); auto rx_param2 = get_rx_angle(gate2, gate_type2); if (rx_param1 && rx_param2) { - UINT target1 = gate1->target_qubit_list()[0]; - UINT target2 = gate2->target_qubit_list()[0]; + std::uint64_t target1 = gate1->target_qubit_list()[0]; + std::uint64_t target2 = gate2->target_qubit_list()[0]; double global_phase1 = gate_type1 == GateType::RX ? 0. : rx_param1.value() / 2; double global_phase2 = gate_type2 == GateType::RX ? 0. : rx_param2.value() / 2; if (target1 == target2) { @@ -144,8 +145,8 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { auto ry_param1 = get_ry_angle(gate1, gate_type1); auto ry_param2 = get_ry_angle(gate2, gate_type2); if (ry_param1 && ry_param2) { - UINT target1 = gate1->target_qubit_list()[0]; - UINT target2 = gate2->target_qubit_list()[0]; + std::uint64_t target1 = gate1->target_qubit_list()[0]; + std::uint64_t target2 = gate2->target_qubit_list()[0]; double global_phase1 = gate_type1 == GateType::RY ? 0. : ry_param1.value() / 2; double global_phase2 = gate_type2 == GateType::RY ? 0. : ry_param2.value() / 2; if (target1 == target2) { @@ -191,7 +192,7 @@ std::pair merge_gate(const Gate& gate1, const Gate& gate2) { std::ranges::copy(gate1->control_qubit_list(), std::back_inserter(gate1_targets)); auto gate2_targets = gate2->target_qubit_list(); std::ranges::copy(gate2->control_qubit_list(), std::back_inserter(gate2_targets)); - std::vector merged_targets(gate1_targets.size() + gate2_targets.size()); + std::vector merged_targets(gate1_targets.size() + gate2_targets.size()); std::ranges::copy(gate1_targets, merged_targets.begin()); std::ranges::copy(gate2_targets, merged_targets.begin() + gate1_targets.size()); std::ranges::sort(merged_targets); diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index 6e717700..01759eb6 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -39,10 +39,10 @@ constexpr ParamGateType get_param_gate_type() { namespace internal { class ParamGateBase { protected: - UINT _target_mask, _control_mask; + std::uint64_t _target_mask, _control_mask; double _pcoef; void check_qubit_mask_within_bounds(const StateVector& state_vector) const { - UINT full_mask = (1ULL << state_vector.n_qubits()) - 1; + std::uint64_t full_mask = (1ULL << state_vector.n_qubits()) - 1; if ((_target_mask | _control_mask) > full_mask) [[unlikely]] { throw std::runtime_error( "Error: ParamGate::update_quantum_state(StateVector& state): " @@ -51,11 +51,12 @@ class ParamGateBase { } public: - ParamGateBase(UINT target_mask, UINT control_mask, double pcoef = 1.) + ParamGateBase(std::uint64_t target_mask, std::uint64_t control_mask, double pcoef = 1.) : _target_mask(target_mask), _control_mask(control_mask), _pcoef(pcoef) { if (_target_mask & _control_mask) [[unlikely]] { throw std::runtime_error( - "Error: ParamGate::ParamGate(UINT target_mask, UINT control_mask) : Target and " + "Error: ParamGate::ParamGate(std::uint64_t target_mask, std::uint64_t " + "control_mask) : Target and " "control qubits must not overlap."); } } @@ -63,18 +64,20 @@ class ParamGateBase { [[nodiscard]] double pcoef() { return _pcoef; } - [[nodiscard]] virtual std::vector target_qubit_list() const { + [[nodiscard]] virtual std::vector target_qubit_list() const { return mask_to_vector(_target_mask); } - [[nodiscard]] virtual std::vector control_qubit_list() const { + [[nodiscard]] virtual std::vector control_qubit_list() const { return mask_to_vector(_control_mask); } - [[nodiscard]] virtual std::vector operand_qubit_list() const { + [[nodiscard]] virtual std::vector operand_qubit_list() const { return mask_to_vector(_target_mask | _control_mask); } - [[nodiscard]] virtual UINT target_qubit_mask() const { return _target_mask; } - [[nodiscard]] virtual UINT control_qubit_mask() const { return _control_mask; } - [[nodiscard]] virtual UINT operand_qubit_mask() const { return _target_mask | _control_mask; } + [[nodiscard]] virtual std::uint64_t target_qubit_mask() const { return _target_mask; } + [[nodiscard]] virtual std::uint64_t control_qubit_mask() const { return _control_mask; } + [[nodiscard]] virtual std::uint64_t operand_qubit_mask() const { + return _target_mask | _control_mask; + } [[nodiscard]] virtual ParamGate get_inverse() const = 0; [[nodiscard]] virtual ComplexMatrix get_matrix(double param) const = 0; diff --git a/scaluq/gate/param_gate_factory.hpp b/scaluq/gate/param_gate_factory.hpp index 1b8a8181..cfbd3e2f 100644 --- a/scaluq/gate/param_gate_factory.hpp +++ b/scaluq/gate/param_gate_factory.hpp @@ -15,22 +15,28 @@ class ParamGateFactory { }; } // namespace internal namespace gate { -inline ParamGate PRX(UINT target, double pcoef = 1., const std::vector& controls = {}) { +inline ParamGate PRX(std::uint64_t target, + double pcoef = 1., + const std::vector& controls = {}) { return internal::ParamGateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), pcoef); } -inline ParamGate PRY(UINT target, double pcoef = 1., const std::vector& controls = {}) { +inline ParamGate PRY(std::uint64_t target, + double pcoef = 1., + const std::vector& controls = {}) { return internal::ParamGateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), pcoef); } -inline ParamGate PRZ(UINT target, double pcoef = 1., const std::vector& controls = {}) { +inline ParamGate PRZ(std::uint64_t target, + double pcoef = 1., + const std::vector& controls = {}) { return internal::ParamGateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), pcoef); } // まだ inline ParamGate PPauliRotation(const PauliOperator& pauli, double pcoef = 1., - const std::vector& controls = {}) { + const std::vector& controls = {}) { return internal::ParamGateFactory::create_gate( internal::vector_to_mask(controls), pauli, pcoef); } diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index 85f98f9f..bbbec583 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -12,12 +12,14 @@ class PPauliRotationGateImpl : public ParamGateBase { const PauliOperator _pauli; public: - PPauliRotationGateImpl(UINT control_mask, const PauliOperator& pauli, double pcoef = 1.) + PPauliRotationGateImpl(std::uint64_t control_mask, + const PauliOperator& pauli, + double pcoef = 1.) : ParamGateBase(vector_to_mask(pauli.target_qubit_list()), control_mask, pcoef), _pauli(pauli) {} PauliOperator pauli() const { return _pauli; } - std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } + std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } ParamGate get_inverse() const override { return std::make_shared(_control_mask, _pauli, -_pcoef); diff --git a/scaluq/gate/param_gate_probablistic.hpp b/scaluq/gate/param_gate_probablistic.hpp index 7b5a419d..40355f3c 100644 --- a/scaluq/gate/param_gate_probablistic.hpp +++ b/scaluq/gate/param_gate_probablistic.hpp @@ -18,7 +18,7 @@ class PProbablisticGateImpl : public ParamGateBase { PProbablisticGateImpl(const std::vector& distribution, const std::vector>& gate_list) : ParamGateBase(0, 0), _distribution(distribution), _gate_list(gate_list) { - UINT n = distribution.size(); + std::uint64_t n = distribution.size(); if (n == 0) { throw std::runtime_error("At least one gate is required."); } @@ -35,32 +35,32 @@ class PProbablisticGateImpl : public ParamGateBase { const std::vector>& gate_list() const { return _gate_list; } const std::vector& distribution() const { return _distribution; } - std::vector target_qubit_list() const override { + std::vector target_qubit_list() const override { throw std::runtime_error( "PProbablisticGateImpl::target_qubit_list(): This function must not be used in " "PProbablisticGateImpl."); } - std::vector control_qubit_list() const override { + std::vector control_qubit_list() const override { throw std::runtime_error( "PProbablisticGateImpl::control_qubit_list(): This function must not be used in " "PProbablisticGateImpl."); } - std::vector operand_qubit_list() const override { + std::vector operand_qubit_list() const override { throw std::runtime_error( "PProbablisticGateImpl::operand_qubit_list(): This function must not be used in " "PProbablisticGateImpl."); } - UINT target_qubit_mask() const override { + std::uint64_t target_qubit_mask() const override { throw std::runtime_error( "PProbablisticGateImpl::target_qubit_mask(): This function must not be used in " "PProbablisticGateImpl."); } - UINT control_qubit_mask() const override { + std::uint64_t control_qubit_mask() const override { throw std::runtime_error( "PProbablisticGateImpl::control_qubit_mask(): This function must not be used in " "PProbablisticGateImpl."); } - UINT operand_qubit_mask() const override { + std::uint64_t operand_qubit_mask() const override { throw std::runtime_error( "PProbablisticGateImpl::operand_qubit_mask(): This function must not be used in " "PProbablisticGateImpl."); @@ -84,9 +84,9 @@ class PProbablisticGateImpl : public ParamGateBase { void update_quantum_state(StateVector& state_vector, double param) const override { Random random; double r = random.uniform(); - UINT i = std::distance(_cumlative_distribution.begin(), - std::ranges::upper_bound(_cumlative_distribution, r)) - - 1; + std::uint64_t i = std::distance(_cumlative_distribution.begin(), + std::ranges::upper_bound(_cumlative_distribution, r)) - + 1; if (i >= _gate_list.size()) i = _gate_list.size() - 1; const auto& gate = _gate_list[i]; if (gate.index() == 0) { diff --git a/scaluq/gate/update_ops.hpp b/scaluq/gate/update_ops.hpp index d65eb52e..25b9f11c 100644 --- a/scaluq/gate/update_ops.hpp +++ b/scaluq/gate/update_ops.hpp @@ -7,77 +7,96 @@ namespace scaluq { namespace internal { -void i_gate(UINT target_mask, UINT control_mask, StateVector& state); +void i_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void global_phase_gate(UINT target_mask, UINT control_mask, double angle, StateVector& state); +void global_phase_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double angle, + StateVector& state); -void x_gate(UINT target_mask, UINT control_mask, StateVector& state); +void x_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void y_gate(UINT target_mask, UINT control_mask, StateVector& state); +void y_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void z_gate(UINT target_mask, UINT control_mask, StateVector& state); +void z_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void h_gate(UINT target_mask, UINT control_mask, StateVector& state); +void h_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void s_gate(UINT target_mask, UINT control_mask, StateVector& state); +void s_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void sdag_gate(UINT target_mask, UINT control_mask, StateVector& state); +void sdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void t_gate(UINT target_mask, UINT control_mask, StateVector& state); +void t_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void tdag_gate(UINT target_mask, UINT control_mask, StateVector& state); +void tdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void sqrtx_gate(UINT target_mask, UINT control_mask, StateVector& state); +void sqrtx_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void sqrtxdag_gate(UINT target_mask, UINT control_mask, StateVector& state); +void sqrtxdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void sqrty_gate(UINT target_mask, UINT control_mask, StateVector& state); +void sqrty_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void sqrtydag_gate(UINT target_mask, UINT control_mask, StateVector& state); +void sqrtydag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void p0_gate(UINT target_mask, UINT control_mask, StateVector& state); +void p0_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void p1_gate(UINT target_mask, UINT control_mask, StateVector& state); +void p1_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void rx_gate(UINT target_mask, UINT control_mask, double angle, StateVector& state); +void rx_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double angle, + StateVector& state); -void ry_gate(UINT target_mask, UINT control_mask, double angle, StateVector& state); +void ry_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double angle, + StateVector& state); -void rz_gate(UINT target_mask, UINT control_mask, double angle, StateVector& state); +void rz_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double angle, + StateVector& state); matrix_2_2 get_IBMQ_matrix(double _theta, double _phi, double _lambda); -void one_target_dense_matrix_gate(UINT target_mask, - UINT control_mask, +void one_target_dense_matrix_gate(std::uint64_t target_mask, + std::uint64_t control_mask, const matrix_2_2& matrix, StateVector& state); -void two_target_dense_matrix_gate(UINT target_mask, - UINT control_mask, +void two_target_dense_matrix_gate(std::uint64_t target_mask, + std::uint64_t control_mask, const matrix_4_4& matrix, StateVector& state); -void one_target_diagonal_matrix_gate(UINT target_mask, - UINT control_mask, +void one_target_diagonal_matrix_gate(std::uint64_t target_mask, + std::uint64_t control_mask, const diagonal_matrix_2_2& diag, StateVector& state); -void u1_gate(UINT target_mask, UINT control_mask, double lambda, StateVector& state); +void u1_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double lambda, + StateVector& state); -void u2_gate(UINT target_mask, UINT control_mask, double phi, double lambda, StateVector& state); +void u2_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double phi, + double lambda, + StateVector& state); -void u3_gate(UINT target_mask, - UINT control_mask, +void u3_gate(std::uint64_t target_mask, + std::uint64_t control_mask, double theta, double phi, double lambda, StateVector& state); -void swap_gate(UINT target_mask, UINT control_mask, StateVector& state); +void swap_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state); -void pauli_gate(UINT control_mask, const PauliOperator& pauli, StateVector& state); +void pauli_gate(std::uint64_t control_mask, const PauliOperator& pauli, StateVector& state); -void pauli_rotation_gate(UINT control_mask, +void pauli_rotation_gate(std::uint64_t control_mask, const PauliOperator& pauli, double angle, StateVector& state); diff --git a/scaluq/gate/update_ops_dense_matrix.cpp b/scaluq/gate/update_ops_dense_matrix.cpp index 9f01b831..faabf609 100644 --- a/scaluq/gate/update_ops_dense_matrix.cpp +++ b/scaluq/gate/update_ops_dense_matrix.cpp @@ -7,15 +7,15 @@ namespace scaluq { namespace internal { -void one_target_dense_matrix_gate(UINT target_mask, - UINT control_mask, +void one_target_dense_matrix_gate(std::uint64_t target_mask, + std::uint64_t control_mask, const matrix_2_2& matrix, StateVector& state) { Kokkos::parallel_for( - state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(UINT it) { - UINT basis_0 = + state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(std::uint64_t it) { + std::uint64_t basis_0 = insert_zero_at_mask_positions(it, control_mask | target_mask) | control_mask; - UINT basis_1 = basis_0 | target_mask; + std::uint64_t basis_1 = basis_0 | target_mask; Complex val0 = state._raw[basis_0]; Complex val1 = state._raw[basis_1]; Complex res0 = matrix.val[0][0] * val0 + matrix.val[0][1] * val1; @@ -26,19 +26,20 @@ void one_target_dense_matrix_gate(UINT target_mask, Kokkos::fence(); } -void two_target_dense_matrix_gate(UINT target_mask, - UINT control_mask, +void two_target_dense_matrix_gate(std::uint64_t target_mask, + std::uint64_t control_mask, const matrix_4_4& matrix, StateVector& state) { - UINT lower_target_mask = -target_mask & target_mask; - UINT upper_target_mask = target_mask ^ lower_target_mask; + std::uint64_t lower_target_mask = -target_mask & target_mask; + std::uint64_t upper_target_mask = target_mask ^ lower_target_mask; Kokkos::parallel_for( - state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(const UINT it) { - UINT basis_0 = + state.dim() >> std::popcount(target_mask | control_mask), + KOKKOS_LAMBDA(const std::uint64_t it) { + std::uint64_t basis_0 = insert_zero_at_mask_positions(it, target_mask | control_mask) | control_mask; - UINT basis_1 = basis_0 | lower_target_mask; - UINT basis_2 = basis_0 | upper_target_mask; - UINT basis_3 = basis_1 | target_mask; + std::uint64_t basis_1 = basis_0 | lower_target_mask; + std::uint64_t basis_2 = basis_0 | upper_target_mask; + std::uint64_t basis_3 = basis_1 | target_mask; Complex val0 = state._raw[basis_0]; Complex val1 = state._raw[basis_1]; Complex val2 = state._raw[basis_2]; diff --git a/scaluq/gate/update_ops_pauli.cpp b/scaluq/gate/update_ops_pauli.cpp index b26fa291..faa06422 100644 --- a/scaluq/gate/update_ops_pauli.cpp +++ b/scaluq/gate/update_ops_pauli.cpp @@ -11,19 +11,19 @@ namespace scaluq { namespace internal { // まだ -void pauli_gate(UINT control_mask, const PauliOperator& pauli, StateVector& state) { +void pauli_gate(std::uint64_t control_mask, const PauliOperator& pauli, StateVector& state) { pauli.apply_to_state(state); } // まだ -void pauli_rotation_gate(UINT control_mask, +void pauli_rotation_gate(std::uint64_t control_mask, const PauliOperator& pauli, double angle, StateVector& state) { auto [bit_flip_mask_vector, phase_flip_mask_vector] = pauli.get_XZ_mask_representation(); - UINT bit_flip_mask = internal::BitVector(bit_flip_mask_vector).data_raw()[0]; - UINT phase_flip_mask = internal::BitVector(phase_flip_mask_vector).data_raw()[0]; - UINT global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); + std::uint64_t bit_flip_mask = internal::BitVector(bit_flip_mask_vector).data_raw()[0]; + std::uint64_t phase_flip_mask = internal::BitVector(phase_flip_mask_vector).data_raw()[0]; + std::uint64_t global_phase_90_rot_count = std::popcount(bit_flip_mask & phase_flip_mask); Complex true_angle = angle * pauli.coef(); const Complex cosval = Kokkos::cos(-true_angle / 2); const Complex sinval = Kokkos::sin(-true_angle / 2); @@ -31,7 +31,7 @@ void pauli_rotation_gate(UINT control_mask, const Complex cval_min = cosval - Complex(0, 1) * sinval; const Complex cval_pls = cosval + Complex(0, 1) * sinval; Kokkos::parallel_for( - state.dim(), KOKKOS_LAMBDA(UINT state_idx) { + state.dim(), KOKKOS_LAMBDA(std::uint64_t state_idx) { if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { state._raw[state_idx] *= cval_min; } else { @@ -41,11 +41,11 @@ void pauli_rotation_gate(UINT control_mask, Kokkos::fence(); return; } else { - const UINT insert_idx = internal::BitVector(bit_flip_mask_vector).msb(); + const std::uint64_t insert_idx = internal::BitVector(bit_flip_mask_vector).msb(); Kokkos::parallel_for( - state.dim() >> 1, KOKKOS_LAMBDA(UINT state_idx) { - UINT basis_0 = internal::insert_zero_to_basis_index(state_idx, insert_idx); - UINT basis_1 = basis_0 ^ bit_flip_mask; + state.dim() >> 1, KOKKOS_LAMBDA(std::uint64_t state_idx) { + std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, insert_idx); + std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; int bit_parity_0 = Kokkos::popcount(basis_0 & phase_flip_mask) & 1; int bit_parity_1 = Kokkos::popcount(basis_1 & phase_flip_mask) & 1; diff --git a/scaluq/gate/update_ops_standard.cpp b/scaluq/gate/update_ops_standard.cpp index dea499bc..123bd36c 100644 --- a/scaluq/gate/update_ops_standard.cpp +++ b/scaluq/gate/update_ops_standard.cpp @@ -8,29 +8,34 @@ namespace scaluq { namespace internal { -void i_gate(UINT, UINT, StateVector&) {} +void i_gate(std::uint64_t, std::uint64_t, StateVector&) {} -void global_phase_gate(UINT, UINT control_mask, double phase, StateVector& state) { +void global_phase_gate(std::uint64_t, + std::uint64_t control_mask, + double phase, + StateVector& state) { Complex coef = Kokkos::polar(1., phase); Kokkos::parallel_for( - state.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(UINT i) { + state.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(std::uint64_t i) { state._raw[insert_zero_at_mask_positions(i, control_mask) | control_mask] *= coef; }); Kokkos::fence(); } -void x_gate(UINT target_mask, UINT control_mask, StateVector& state) { +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(UINT it) { - UINT i = insert_zero_at_mask_positions(it, control_mask | target_mask) | control_mask; + 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(); } -void y_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void y_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(UINT it) { - UINT i = insert_zero_at_mask_positions(it, control_mask | target_mask) | control_mask; + 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; state._raw[i] *= Complex(0, 1); state._raw[i | target_mask] *= Complex(0, -1); Kokkos::Experimental::swap(state._raw[i], state._raw[i | target_mask]); @@ -38,91 +43,102 @@ void y_gate(UINT target_mask, UINT control_mask, StateVector& state) { Kokkos::fence(); } -void z_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void z_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(UINT it) { - UINT i = insert_zero_at_mask_positions(it, control_mask | target_mask) | control_mask; + 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; state._raw[i | target_mask] *= Complex(-1, 0); }); Kokkos::fence(); } -void h_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void h_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_dense_matrix_gate(target_mask, control_mask, HADAMARD_MATRIX(), state); } -void one_target_phase_gate(UINT target_mask, UINT control_mask, Complex phase, StateVector& state) { +void one_target_phase_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + Complex phase, + StateVector& state) { Kokkos::parallel_for( - state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(UINT it) { - UINT i = insert_zero_at_mask_positions(it, control_mask | target_mask) | control_mask; + 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; state._raw[i | target_mask] *= phase; }); Kokkos::fence(); } -void s_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void s_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_phase_gate(target_mask, control_mask, Complex(0, 1), state); } -void sdag_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void sdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_phase_gate(target_mask, control_mask, Complex(0, -1), state); } -void t_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void t_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_phase_gate( target_mask, control_mask, Complex(INVERSE_SQRT2(), INVERSE_SQRT2()), state); } -void tdag_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void tdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_phase_gate( target_mask, control_mask, Complex(INVERSE_SQRT2(), -INVERSE_SQRT2()), state); } -void sqrtx_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void sqrtx_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_dense_matrix_gate(target_mask, control_mask, SQRT_X_GATE_MATRIX(), state); } -void sqrtxdag_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void sqrtxdag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_dense_matrix_gate(target_mask, control_mask, SQRT_X_DAG_GATE_MATRIX(), state); } -void sqrty_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void sqrty_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_dense_matrix_gate(target_mask, control_mask, SQRT_Y_GATE_MATRIX(), state); } -void sqrtydag_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void sqrtydag_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_dense_matrix_gate(target_mask, control_mask, SQRT_Y_DAG_GATE_MATRIX(), state); } -void p0_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void p0_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_dense_matrix_gate(target_mask, control_mask, PROJ_0_MATRIX(), state); } -void p1_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void p1_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { one_target_dense_matrix_gate(target_mask, control_mask, PROJ_1_MATRIX(), state); } -void rx_gate(UINT target_mask, UINT control_mask, double angle, StateVector& state) { +void rx_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double angle, + StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); matrix_2_2 matrix = {cosval, Complex(0, -sinval), Complex(0, -sinval), cosval}; one_target_dense_matrix_gate(target_mask, control_mask, matrix, state); } -void ry_gate(UINT target_mask, UINT control_mask, double angle, StateVector& state) { +void ry_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double angle, + StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); matrix_2_2 matrix = {cosval, -sinval, sinval, cosval}; one_target_dense_matrix_gate(target_mask, control_mask, matrix, state); } -void one_target_diagonal_matrix_gate(UINT target_mask, - UINT control_mask, +void one_target_diagonal_matrix_gate(std::uint64_t target_mask, + std::uint64_t control_mask, const diagonal_matrix_2_2& diag, StateVector& state) { Kokkos::parallel_for( - state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(UINT it) { - UINT basis = + state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(std::uint64_t it) { + std::uint64_t basis = insert_zero_at_mask_positions(it, target_mask | control_mask) | control_mask; state._raw[basis] *= diag.val[0]; state._raw[basis | target_mask] *= diag.val[1]; @@ -130,7 +146,10 @@ void one_target_diagonal_matrix_gate(UINT target_mask, Kokkos::fence(); } -void rz_gate(UINT target_mask, UINT control_mask, double angle, StateVector& state) { +void rz_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double angle, + StateVector& state) { const double cosval = std::cos(angle / 2.); const double sinval = std::sin(angle / 2.); diagonal_matrix_2_2 diag = {Complex(cosval, -sinval), Complex(cosval, sinval)}; @@ -145,24 +164,33 @@ matrix_2_2 get_IBMQ_matrix(double theta, double phi, double lambda) { return {cos_val, -exp_val2 * sin_val, exp_val1 * sin_val, exp_val1 * exp_val2 * cos_val}; } -void u1_gate(UINT target_mask, UINT control_mask, double lambda, StateVector& state) { +void u1_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double lambda, + StateVector& state) { Complex exp_val = Kokkos::exp(Complex(0, lambda)); Kokkos::parallel_for( - state.dim() >> (std::popcount(target_mask | control_mask)), KOKKOS_LAMBDA(UINT it) { - UINT i = internal::insert_zero_at_mask_positions(it, target_mask | control_mask) | - control_mask; + state.dim() >> (std::popcount(target_mask | control_mask)), + KOKKOS_LAMBDA(std::uint64_t it) { + std::uint64_t i = + internal::insert_zero_at_mask_positions(it, target_mask | control_mask) | + control_mask; state._raw[i | target_mask] *= exp_val; }); Kokkos::fence(); } -void u2_gate(UINT target_mask, UINT control_mask, double phi, double lambda, StateVector& state) { +void u2_gate(std::uint64_t target_mask, + std::uint64_t control_mask, + double phi, + double lambda, + StateVector& state) { one_target_dense_matrix_gate( target_mask, control_mask, get_IBMQ_matrix(PI() / 2., phi, lambda), state); } -void u3_gate(UINT target_mask, - UINT control_mask, +void u3_gate(std::uint64_t target_mask, + std::uint64_t control_mask, double theta, double phi, double lambda, @@ -171,13 +199,13 @@ void u3_gate(UINT target_mask, target_mask, control_mask, get_IBMQ_matrix(theta, phi, lambda), state); } -void swap_gate(UINT target_mask, UINT control_mask, StateVector& state) { +void swap_gate(std::uint64_t target_mask, std::uint64_t control_mask, StateVector& state) { // '- target' is used for bit manipulation on unsigned type, not for its numerical meaning. - UINT lower_target_mask = target_mask & -target_mask; - UINT upper_target_mask = target_mask ^ lower_target_mask; + std::uint64_t lower_target_mask = target_mask & -target_mask; + std::uint64_t upper_target_mask = target_mask ^ lower_target_mask; Kokkos::parallel_for( - state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(UINT it) { - UINT basis = + state.dim() >> std::popcount(target_mask | control_mask), KOKKOS_LAMBDA(std::uint64_t it) { + std::uint64_t basis = insert_zero_at_mask_positions(it, target_mask | control_mask) | control_mask; Kokkos::Experimental::swap(state._raw[basis | lower_target_mask], state._raw[basis | upper_target_mask]); diff --git a/scaluq/operator/operator.cpp b/scaluq/operator/operator.cpp index b2da1400..26184e7b 100644 --- a/scaluq/operator/operator.cpp +++ b/scaluq/operator/operator.cpp @@ -6,7 +6,7 @@ #include "../util/utility.hpp" namespace scaluq { -Operator::Operator(UINT n_qubits) : _n_qubits(n_qubits) {} +Operator::Operator(std::uint64_t n_qubits) : _n_qubits(n_qubits) {} std::string Operator::to_string() const { std::stringstream ss; @@ -33,11 +33,11 @@ void Operator::add_operator(PauliOperator&& mpt) { } this->_terms.emplace_back(std::move(mpt)); } -void Operator::add_random_operator(UINT operator_count, UINT seed) { +void Operator::add_random_operator(std::uint64_t operator_count, std::uint64_t seed) { Random random(seed); - for (UINT operator_idx = 0; operator_idx < operator_count; operator_idx++) { - std::vector target_qubit_list(_n_qubits), pauli_id_list(_n_qubits); - for (UINT qubit_idx = 0; qubit_idx < _n_qubits; qubit_idx++) { + 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); + for (std::uint64_t qubit_idx = 0; qubit_idx < _n_qubits; qubit_idx++) { target_qubit_list[qubit_idx] = qubit_idx; pauli_id_list[qubit_idx] = random.int32() & 0b11; } @@ -82,11 +82,11 @@ Complex Operator::get_expectation_value(const StateVector& state_vector) const { throw std::runtime_error( "Operator::get_expectation_value: n_qubits of state_vector is too small"); } - UINT nterms = _terms.size(); + std::uint64_t nterms = _terms.size(); Kokkos::View> terms_view(_terms.data(), nterms); - Kokkos::View bmasks_host("bmasks_host", nterms); - Kokkos::View pmasks_host("pmasks_host", nterms); + Kokkos::View bmasks_host("bmasks_host", nterms); + Kokkos::View pmasks_host("pmasks_host", nterms); Kokkos::View coefs_host("coefs_host", nterms); Kokkos::Experimental::transform( Kokkos::DefaultHostExecutionSpace(), @@ -102,38 +102,40 @@ Complex Operator::get_expectation_value(const StateVector& state_vector) const { terms_view, coefs_host, [](const PauliOperator& pauli) { return pauli._ptr->_coef; }); - Kokkos::View bmasks("bmasks", nterms); - Kokkos::View pmasks("pmasks", nterms); + Kokkos::View bmasks("bmasks", nterms); + Kokkos::View pmasks("pmasks", nterms); Kokkos::View coefs("coefs", nterms); Kokkos::deep_copy(bmasks, bmasks_host); Kokkos::deep_copy(pmasks, pmasks_host); Kokkos::deep_copy(coefs, coefs_host); - UINT dim = state_vector.dim(); + std::uint64_t dim = state_vector.dim(); Complex res; Kokkos::parallel_reduce( Kokkos::MDRangePolicy>({0, 0}, {nterms, dim >> 1}), - KOKKOS_LAMBDA(UINT term_id, UINT state_idx, Complex & res_lcl) { - UINT bit_flip_mask = bmasks[term_id]; - UINT phase_flip_mask = pmasks[term_id]; + KOKKOS_LAMBDA(std::uint64_t term_id, std::uint64_t state_idx, Complex & res_lcl) { + std::uint64_t bit_flip_mask = bmasks[term_id]; + std::uint64_t phase_flip_mask = pmasks[term_id]; Complex coef = coefs[term_id]; if (bit_flip_mask == 0) { - UINT state_idx1 = state_idx << 1; + std::uint64_t state_idx1 = state_idx << 1; double tmp1 = (Kokkos::conj(state_vector._raw[state_idx1]) * state_vector._raw[state_idx1]) .real(); if (Kokkos::popcount(state_idx1 & phase_flip_mask) & 1) tmp1 = -tmp1; - UINT state_idx2 = state_idx1 | 1; + std::uint64_t state_idx2 = state_idx1 | 1; double tmp2 = (Kokkos::conj(state_vector._raw[state_idx2]) * state_vector._raw[state_idx2]) .real(); if (Kokkos::popcount(state_idx2 & phase_flip_mask) & 1) tmp2 = -tmp2; res_lcl += coef * (tmp1 + tmp2); } else { - UINT pivot = sizeof(UINT) * 8 - Kokkos::countl_zero(bit_flip_mask) - 1; - UINT global_phase_90rot_count = Kokkos::popcount(bit_flip_mask & phase_flip_mask); + std::uint64_t pivot = + sizeof(std::uint64_t) * 8 - Kokkos::countl_zero(bit_flip_mask) - 1; + std::uint64_t global_phase_90rot_count = + Kokkos::popcount(bit_flip_mask & phase_flip_mask); Complex global_phase = PHASE_90ROT().val[global_phase_90rot_count % 4]; - UINT basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); - UINT basis_1 = basis_0 ^ bit_flip_mask; + std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); + std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; double tmp = Kokkos::real(state_vector._raw[basis_0] * Kokkos::conj(state_vector._raw[basis_1]) * global_phase * 2.); @@ -158,9 +160,9 @@ Complex Operator::get_transition_amplitude(const StateVector& state_vector_bra, "Operator::get_transition_amplitude: n_qubits of state_vector is too " "small"); } - UINT nterms = _terms.size(); - std::vector bmasks_vector(nterms); - std::vector pmasks_vector(nterms); + std::uint64_t nterms = _terms.size(); + 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) { @@ -174,33 +176,37 @@ Complex Operator::get_transition_amplitude(const StateVector& state_vector_bra, _terms.begin(), _terms.end(), coefs_vector.begin(), [](const PauliOperator& pauli) { return pauli._ptr->_coef; }); - Kokkos::View bmasks = internal::convert_host_vector_to_device_view(bmasks_vector); - Kokkos::View pmasks = internal::convert_host_vector_to_device_view(pmasks_vector); + Kokkos::View bmasks = + internal::convert_host_vector_to_device_view(bmasks_vector); + Kokkos::View pmasks = + internal::convert_host_vector_to_device_view(pmasks_vector); Kokkos::View coefs = internal::convert_host_vector_to_device_view(coefs_vector); - UINT dim = state_vector_bra.dim(); + std::uint64_t dim = state_vector_bra.dim(); Complex res; Kokkos::parallel_reduce( Kokkos::MDRangePolicy>({0, 0}, {nterms, dim >> 1}), - KOKKOS_LAMBDA(UINT term_id, UINT state_idx, Complex & res_lcl) { - UINT bit_flip_mask = bmasks[term_id]; - UINT phase_flip_mask = pmasks[term_id]; + KOKKOS_LAMBDA(std::uint64_t term_id, std::uint64_t state_idx, Complex & res_lcl) { + std::uint64_t bit_flip_mask = bmasks[term_id]; + std::uint64_t phase_flip_mask = pmasks[term_id]; Complex coef = coefs[term_id]; if (bit_flip_mask == 0) { - UINT state_idx1 = state_idx << 1; + std::uint64_t state_idx1 = state_idx << 1; Complex tmp1 = (Kokkos::conj(state_vector_bra._raw[state_idx1]) * state_vector_ket._raw[state_idx1]); if (Kokkos::popcount(state_idx1 & phase_flip_mask) & 1) tmp1 = -tmp1; - UINT state_idx2 = state_idx1 | 1; + std::uint64_t state_idx2 = state_idx1 | 1; Complex tmp2 = (Kokkos::conj(state_vector_bra._raw[state_idx2]) * state_vector_ket._raw[state_idx2]); if (Kokkos::popcount(state_idx2 & phase_flip_mask) & 1) tmp2 = -tmp2; res_lcl += coef * (tmp1 + tmp2); } else { - UINT pivot = sizeof(UINT) * 8 - Kokkos::countl_zero(bit_flip_mask) - 1; - UINT global_phase_90rot_count = Kokkos::popcount(bit_flip_mask & phase_flip_mask); + std::uint64_t pivot = + sizeof(std::uint64_t) * 8 - Kokkos::countl_zero(bit_flip_mask) - 1; + std::uint64_t global_phase_90rot_count = + Kokkos::popcount(bit_flip_mask & phase_flip_mask); Complex global_phase = PHASE_90ROT().val[global_phase_90rot_count % 4]; - UINT basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); - UINT basis_1 = basis_0 ^ bit_flip_mask; + std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); + std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; Complex tmp1 = Kokkos::conj(state_vector_bra._raw[basis_1]) * state_vector_ket._raw[basis_0] * global_phase; if (Kokkos::popcount(basis_0 & phase_flip_mask) & 1) tmp1 = -tmp1; diff --git a/scaluq/operator/operator.hpp b/scaluq/operator/operator.hpp index 5ba45969..cc71abf7 100644 --- a/scaluq/operator/operator.hpp +++ b/scaluq/operator/operator.hpp @@ -10,16 +10,17 @@ namespace scaluq { class Operator { public: - explicit Operator(UINT n_qubits); + explicit Operator(std::uint64_t n_qubits); [[nodiscard]] inline bool is_hermitian() { return _is_hermitian; } - [[nodiscard]] inline UINT n_qubits() { return _n_qubits; } + [[nodiscard]] inline std::uint64_t n_qubits() { return _n_qubits; } [[nodiscard]] inline const std::vector& terms() const { return _terms; } [[nodiscard]] std::string to_string() const; void add_operator(const PauliOperator& mpt); void add_operator(PauliOperator&& mpt); - void add_random_operator(const UINT operator_count = 1, UINT seed = std::random_device()()); + void add_random_operator(const std::uint64_t operator_count = 1, + std::uint64_t seed = std::random_device()()); void optimize(); @@ -37,11 +38,11 @@ class Operator { // not implemented yet [[nodiscard]] Complex solve_gound_state_eigenvalue_by_arnoldi_method(const StateVector& state, - UINT iter_count, + std::uint64_t iter_count, Complex mu = 0.) const; // not implemented yet [[nodiscard]] Complex solve_gound_state_eigenvalue_by_power_method(const StateVector& state, - UINT iter_count, + std::uint64_t iter_count, Complex mu = 0.) const; Operator& operator*=(Complex coef); @@ -63,7 +64,7 @@ class Operator { private: std::vector _terms; - UINT _n_qubits; + std::uint64_t _n_qubits; bool _is_hermitian = true; }; } // namespace scaluq diff --git a/scaluq/operator/pauli_operator.cpp b/scaluq/operator/pauli_operator.cpp index 6858339b..575d60ea 100644 --- a/scaluq/operator/pauli_operator.cpp +++ b/scaluq/operator/pauli_operator.cpp @@ -10,14 +10,14 @@ PauliOperator::Data::Data(std::string_view pauli_string, Complex coef) : _coef(c auto ss = std::stringstream(std::string(pauli_string)); while (1) { char pauli; - UINT target; + std::uint64_t target; ss >> pauli; if (ss.fail()) break; ss >> target; if (ss.fail()) { throw std::runtime_error("PauliOperator::PauliOperator: invalid pauli_string format"); } - UINT pauli_id = [&] { + std::uint64_t pauli_id = [&] { if (pauli == 'I' || pauli == 'i') return PauliOperator::I; if (pauli == 'X' || pauli == 'x') return PauliOperator::X; if (pauli == 'Y' || pauli == 'y') return PauliOperator::Y; @@ -28,21 +28,22 @@ PauliOperator::Data::Data(std::string_view pauli_string, Complex coef) : _coef(c } } -PauliOperator::Data::Data(const std::vector& pauli_id_par_qubit, Complex coef) : _coef(coef) { - for (UINT i = 0; i < pauli_id_par_qubit.size(); ++i) { +PauliOperator::Data::Data(const std::vector& pauli_id_par_qubit, Complex coef) + : _coef(coef) { + for (std::uint64_t i = 0; i < pauli_id_par_qubit.size(); ++i) { add_single_pauli(i, pauli_id_par_qubit[i]); } } -PauliOperator::Data::Data(const std::vector& target_qubit_list, - const std::vector& pauli_id_list, +PauliOperator::Data::Data(const std::vector& target_qubit_list, + const std::vector& pauli_id_list, Complex coef) : _coef(coef) { if (target_qubit_list.size() != pauli_id_list.size()) { throw std::runtime_error( "PauliOperator::PauliOperator: target_qubit_list must have same size to pauli_id_list"); } - for (UINT term_index = 0; term_index < target_qubit_list.size(); ++term_index) { + for (std::uint64_t term_index = 0; term_index < target_qubit_list.size(); ++term_index) { add_single_pauli(target_qubit_list[term_index], pauli_id_list[term_index]); } } @@ -51,15 +52,15 @@ PauliOperator::Data::Data(const std::vector& bit_flip_mask, const std::vector& phase_flip_mask, Complex coef) : _coef(coef) { - UINT num_y = 0; - UINT max_target = 0; + std::uint64_t num_y = 0; + std::uint64_t max_target = 0; if (auto msb = internal::BitVector(bit_flip_mask).msb(); - msb != std::numeric_limits::max() && max_target < msb) + msb != std::numeric_limits::max() && max_target < msb) max_target = msb; if (auto msb = internal::BitVector(phase_flip_mask).msb(); - msb != std::numeric_limits::max() && max_target < msb) + msb != std::numeric_limits::max() && max_target < msb) max_target = msb; - for (UINT target_idx = 0; target_idx <= max_target; target_idx++) { + for (std::uint64_t target_idx = 0; target_idx <= max_target; target_idx++) { if (!bit_flip_mask[target_idx]) { if (!phase_flip_mask[target_idx]) continue; @@ -76,7 +77,7 @@ PauliOperator::Data::Data(const std::vector& bit_flip_mask, } } -void PauliOperator::Data::add_single_pauli(UINT target_qubit, UINT pauli_id) { +void PauliOperator::Data::add_single_pauli(std::uint64_t target_qubit, std::uint64_t pauli_id) { _target_qubit_list.push_back(target_qubit); _pauli_id_list.push_back(pauli_id); if ((_bit_flip_mask | _phase_flip_mask)[target_qubit]) { @@ -94,9 +95,9 @@ void PauliOperator::Data::add_single_pauli(UINT target_qubit, UINT pauli_id) { std::string PauliOperator::get_pauli_string() const { std::stringstream ss; - UINT size = _ptr->_target_qubit_list.size(); + std::uint64_t size = _ptr->_target_qubit_list.size(); if (size == 0) return ""; - for (UINT term_index = 0; term_index < size; term_index++) { + for (std::uint64_t term_index = 0; term_index < size; term_index++) { if (_ptr->_pauli_id_list[term_index] != 0) { ss << "IXYZ"[_ptr->_pauli_id_list[term_index]] << " " << _ptr->_target_qubit_list[term_index] << " "; @@ -113,12 +114,12 @@ void PauliOperator::apply_to_state(StateVector& state_vector) const { "PauliOperator::apply_to_state: n_qubits of state_vector is too small to apply the " "operator"); } - UINT bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; - UINT phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; + std::uint64_t bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; + std::uint64_t phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; Complex coef = this->coef(); if (bit_flip_mask == 0) { Kokkos::parallel_for( - state_vector.dim(), KOKKOS_LAMBDA(UINT state_idx) { + state_vector.dim(), KOKKOS_LAMBDA(std::uint64_t state_idx) { if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { state_vector._raw[state_idx] *= -coef; } else { @@ -128,13 +129,13 @@ void PauliOperator::apply_to_state(StateVector& state_vector) const { Kokkos::fence(); return; } - UINT pivot = sizeof(UINT) * 8 - std::countl_zero(bit_flip_mask) - 1; - UINT global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); + std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; + std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); Complex global_phase = PHASE_M90ROT().val[global_phase_90rot_count % 4]; Kokkos::parallel_for( - state_vector.dim() >> 1, KOKKOS_LAMBDA(UINT state_idx) { - UINT basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); - UINT basis_1 = basis_0 ^ bit_flip_mask; + state_vector.dim() >> 1, KOKKOS_LAMBDA(std::uint64_t state_idx) { + std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); + std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; Complex tmp1 = state_vector._raw[basis_0] * global_phase; Complex tmp2 = state_vector._raw[basis_1] * global_phase; if (Kokkos::popcount(basis_0 & phase_flip_mask) & 1) tmp2 = -tmp2; @@ -151,13 +152,13 @@ Complex PauliOperator::get_expectation_value(const StateVector& state_vector) co "PauliOperator::get_expectation_value: n_qubits of state_vector is too small to apply " "the operator"); } - UINT bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; - UINT phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; + std::uint64_t bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; + std::uint64_t phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; if (bit_flip_mask == 0) { double res; Kokkos::parallel_reduce( state_vector.dim(), - KOKKOS_LAMBDA(UINT state_idx, double& sum) { + KOKKOS_LAMBDA(std::uint64_t state_idx, double& sum) { double tmp = (Kokkos::conj(state_vector._raw[state_idx]) * state_vector._raw[state_idx]) .real(); @@ -167,15 +168,15 @@ Complex PauliOperator::get_expectation_value(const StateVector& state_vector) co res); return _ptr->_coef * res; } - UINT pivot = sizeof(UINT) * 8 - std::countl_zero(bit_flip_mask) - 1; - UINT global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); + std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; + std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); Complex global_phase = PHASE_90ROT().val[global_phase_90rot_count % 4]; double res; Kokkos::parallel_reduce( state_vector.dim() >> 1, - KOKKOS_LAMBDA(UINT state_idx, double& sum) { - UINT basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); - UINT basis_1 = basis_0 ^ bit_flip_mask; + KOKKOS_LAMBDA(std::uint64_t state_idx, double& sum) { + std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); + std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; double tmp = Kokkos::real(state_vector._raw[basis_0] * Kokkos::conj(state_vector._raw[basis_1]) * global_phase * 2.); if (Kokkos::popcount(basis_0 & phase_flip_mask) & 1) tmp = -tmp; @@ -195,13 +196,13 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ "PauliOperator::get_expectation_value: n_qubits of state_vector is too small to apply " "the operator"); } - UINT bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; - UINT phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; + std::uint64_t bit_flip_mask = _ptr->_bit_flip_mask.data_raw()[0]; + std::uint64_t phase_flip_mask = _ptr->_phase_flip_mask.data_raw()[0]; if (bit_flip_mask == 0) { Complex res; Kokkos::parallel_reduce( state_vector_bra.dim(), - KOKKOS_LAMBDA(UINT state_idx, Complex & sum) { + KOKKOS_LAMBDA(std::uint64_t state_idx, Complex & sum) { Complex tmp = Kokkos::conj(state_vector_bra._raw[state_idx]) * state_vector_ket._raw[state_idx]; if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) tmp = -tmp; @@ -211,15 +212,15 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ Kokkos::fence(); return _ptr->_coef * res; } - UINT pivot = sizeof(UINT) * 8 - std::countl_zero(bit_flip_mask) - 1; - UINT global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); + std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; + std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); Complex global_phase = PHASE_90ROT().val[global_phase_90rot_count % 4]; Complex res; Kokkos::parallel_reduce( state_vector_bra.dim() >> 1, - KOKKOS_LAMBDA(UINT state_idx, Complex & sum) { - UINT basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); - UINT basis_1 = basis_0 ^ bit_flip_mask; + KOKKOS_LAMBDA(std::uint64_t state_idx, Complex & sum) { + std::uint64_t basis_0 = internal::insert_zero_to_basis_index(state_idx, pivot); + std::uint64_t basis_1 = basis_0 ^ bit_flip_mask; Complex tmp1 = Kokkos::conj(state_vector_bra._raw[basis_1]) * state_vector_ket._raw[basis_0] * global_phase; if (Kokkos::popcount(basis_0 & phase_flip_mask) & 1) tmp1 = -tmp1; @@ -234,11 +235,14 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ } [[nodiscard]] ComplexMatrix PauliOperator::get_matrix_ignoring_coef() const { - UINT flip_mask, phase_mask, rot90_count; + std::uint64_t flip_mask, phase_mask, rot90_count; Kokkos::parallel_reduce( Kokkos::RangePolicy(0, _ptr->_pauli_id_list.size()), - [&](UINT i, UINT& f_mask, UINT& p_mask, UINT& rot90_cnt) { - UINT pauli_id = _ptr->_pauli_id_list[i]; + [&](std::uint64_t i, + std::uint64_t& f_mask, + std::uint64_t& p_mask, + std::uint64_t& rot90_cnt) { + std::uint64_t pauli_id = _ptr->_pauli_id_list[i]; if (pauli_id == 1) { f_mask += 1ULL << i; } else if (pauli_id == 2) { @@ -253,9 +257,9 @@ Complex PauliOperator::get_transition_amplitude(const StateVector& state_vector_ phase_mask, rot90_count); std::vector rot = {1, -1.i, -1, 1.i}; - UINT matrix_dim = 1ULL << _ptr->_pauli_id_list.size(); + std::uint64_t matrix_dim = 1ULL << _ptr->_pauli_id_list.size(); ComplexMatrix mat = ComplexMatrix::Zero(matrix_dim, matrix_dim); - for (UINT index = 0; index < matrix_dim; index++) { + for (std::uint64_t index = 0; index < matrix_dim; index++) { const StdComplex sign = 1. - 2. * (Kokkos::popcount(index & phase_mask) % 2); mat(index, index ^ flip_mask) = rot[rot90_count % 4] * sign; } diff --git a/scaluq/operator/pauli_operator.hpp b/scaluq/operator/pauli_operator.hpp index 540a686a..cbeed74f 100644 --- a/scaluq/operator/pauli_operator.hpp +++ b/scaluq/operator/pauli_operator.hpp @@ -15,25 +15,25 @@ class PauliOperator { class Data { friend class PauliOperator; friend class Operator; - std::vector _target_qubit_list, _pauli_id_list; + std::vector _target_qubit_list, _pauli_id_list; Complex _coef; internal::BitVector _bit_flip_mask, _phase_flip_mask; public: explicit Data(Complex coef = 1.); Data(std::string_view pauli_string, Complex coef = 1.); - Data(const std::vector& target_qubit_list, - const std::vector& pauli_id_list, + Data(const std::vector& target_qubit_list, + const std::vector& pauli_id_list, Complex coef = 1.); - Data(const std::vector& pauli_id_par_qubit, Complex coef = 1.); + Data(const std::vector& pauli_id_par_qubit, Complex coef = 1.); Data(const std::vector& bit_flip_mask, const std::vector& phase_flip_mask, Complex coef); - void add_single_pauli(UINT target_qubit, UINT pauli_id); + void add_single_pauli(std::uint64_t target_qubit, std::uint64_t pauli_id); Complex coef() const { return _coef; } void set_coef(Complex c) { _coef = c; } - const std::vector& target_qubit_list() const { return _target_qubit_list; } - const std::vector& pauli_id_list() const { return _pauli_id_list; } + const std::vector& target_qubit_list() const { return _target_qubit_list; } + const std::vector& pauli_id_list() const { return _pauli_id_list; } std::tuple, std::vector> get_XZ_mask_representation() const { return {_bit_flip_mask, _phase_flip_mask}; } @@ -43,17 +43,17 @@ class PauliOperator { std::shared_ptr _ptr; public: - enum PauliID : UINT { I, X, Y, Z }; + enum PauliID : std::uint64_t { I, X, Y, Z }; explicit PauliOperator(Complex coef = 1.) : _ptr(std::make_shared(coef)) {} explicit PauliOperator(Data data) : _ptr(std::make_shared(data)) {} PauliOperator(std::string_view pauli_string, Complex coef = 1.) : _ptr(std::make_shared(pauli_string, coef)) {} - PauliOperator(const std::vector& target_qubit_list, - const std::vector& pauli_id_list, + PauliOperator(const std::vector& target_qubit_list, + const std::vector& pauli_id_list, Complex coef = 1.) : _ptr(std::make_shared(target_qubit_list, pauli_id_list, coef)) {} - PauliOperator(const std::vector& pauli_id_par_qubit, Complex coef = 1.) + PauliOperator(const std::vector& pauli_id_par_qubit, Complex coef = 1.) : _ptr(std::make_shared(pauli_id_par_qubit, coef)) {} PauliOperator(const std::vector& bit_flip_mask, const std::vector& phase_flip_mask, @@ -61,10 +61,10 @@ class PauliOperator { : _ptr(std::make_shared(bit_flip_mask, phase_flip_mask, coef)) {} [[nodiscard]] inline Complex coef() const { return _ptr->coef(); } - [[nodiscard]] inline const std::vector& target_qubit_list() const { + [[nodiscard]] inline const std::vector& target_qubit_list() const { return _ptr->target_qubit_list(); } - [[nodiscard]] inline const std::vector& pauli_id_list() const { + [[nodiscard]] inline const std::vector& pauli_id_list() const { return _ptr->pauli_id_list(); } [[nodiscard]] inline std::tuple, std::vector> @@ -76,7 +76,7 @@ class PauliOperator { return PauliOperator( _ptr->_target_qubit_list, _ptr->_pauli_id_list, Kokkos::conj(_ptr->_coef)); } - [[nodiscard]] UINT get_qubit_count() const { + [[nodiscard]] std::uint64_t get_qubit_count() const { if (_ptr->_target_qubit_list.empty()) return 0; return std::ranges::max(_ptr->_target_qubit_list) + 1; } diff --git a/scaluq/state/state_vector.cpp b/scaluq/state/state_vector.cpp index f098d834..f9dd3d83 100644 --- a/scaluq/state/state_vector.cpp +++ b/scaluq/state/state_vector.cpp @@ -5,20 +5,20 @@ namespace scaluq { -StateVector::StateVector(UINT n_qubits) +StateVector::StateVector(std::uint64_t n_qubits) : _n_qubits(n_qubits), _dim(1 << n_qubits), _raw(Kokkos::ViewAllocateWithoutInitializing("state"), this->_dim) { set_zero_state(); } -void StateVector::set_amplitude_at_index(UINT index, const Complex& c) { +void StateVector::set_amplitude_at_index(std::uint64_t index, const Complex& c) { Kokkos::View host_view("single_value"); host_view() = c; Kokkos::deep_copy(Kokkos::subview(_raw, index), host_view()); } -Complex StateVector::get_amplitude_at_index(UINT index) const { +Complex StateVector::get_amplitude_at_index(std::uint64_t index) const { Kokkos::View host_view("single_value"); Kokkos::deep_copy(host_view, Kokkos::subview(_raw, index)); return host_view(); @@ -31,10 +31,10 @@ void StateVector::set_zero_state() { void StateVector::set_zero_norm_state() { Kokkos::deep_copy(_raw, 0); } -void StateVector::set_computational_basis(UINT basis) { +void StateVector::set_computational_basis(std::uint64_t basis) { if (basis >= _dim) { throw std::runtime_error( - "Error: StateVector::set_computational_basis(UINT): " + "Error: StateVector::set_computational_basis(std::uint64_t): " "index of " "computational basis must be smaller than 2^qubit_count"); } @@ -42,11 +42,11 @@ void StateVector::set_computational_basis(UINT basis) { set_amplitude_at_index(basis, 1); } -StateVector StateVector::Haar_random_state(UINT n_qubits, UINT seed) { +StateVector StateVector::Haar_random_state(std::uint64_t n_qubits, std::uint64_t seed) { Kokkos::Random_XorShift64_Pool<> rand_pool(seed); StateVector state(n_qubits); Kokkos::parallel_for( - state._dim, KOKKOS_LAMBDA(UINT i) { + state._dim, KOKKOS_LAMBDA(std::uint64_t i) { auto rand_gen = rand_pool.get_state(); state._raw[i] = Complex(rand_gen.normal(0.0, 1.0), rand_gen.normal(0.0, 1.0)); rand_pool.free_state(rand_gen); @@ -56,9 +56,9 @@ StateVector StateVector::Haar_random_state(UINT n_qubits, UINT seed) { return state; } -UINT StateVector::n_qubits() const { return this->_n_qubits; } +std::uint64_t StateVector::n_qubits() const { return this->_n_qubits; } -UINT StateVector::dim() const { return this->_dim; } +std::uint64_t StateVector::dim() const { return this->_dim; } std::vector StateVector::get_amplitudes() const { return internal::convert_device_view_to_host_vector(_raw); @@ -68,7 +68,7 @@ double StateVector::get_squared_norm() const { double norm = 0.; Kokkos::parallel_reduce( this->_dim, - KOKKOS_CLASS_LAMBDA(UINT it, double& tmp) { + KOKKOS_CLASS_LAMBDA(std::uint64_t it, double& tmp) { tmp += internal::squared_norm(this->_raw[it]); }, norm); @@ -78,47 +78,49 @@ double StateVector::get_squared_norm() const { void StateVector::normalize() { const auto norm = std::sqrt(this->get_squared_norm()); Kokkos::parallel_for( - this->_dim, KOKKOS_CLASS_LAMBDA(UINT it) { this->_raw[it] /= norm; }); + this->_dim, KOKKOS_CLASS_LAMBDA(std::uint64_t it) { this->_raw[it] /= norm; }); Kokkos::fence(); } -double StateVector::get_zero_probability(UINT target_qubit_index) const { +double StateVector::get_zero_probability(std::uint64_t target_qubit_index) const { if (target_qubit_index >= _n_qubits) { throw std::runtime_error( - "Error: StateVector::get_zero_probability(UINT): index " + "Error: StateVector::get_zero_probability(std::uint64_t): index " "of target qubit must be smaller than qubit_count"); } double sum = 0.; Kokkos::parallel_reduce( "zero_prob", _dim >> 1, - KOKKOS_CLASS_LAMBDA(UINT i, double& lsum) { - UINT basis_0 = internal::insert_zero_to_basis_index(i, target_qubit_index); + KOKKOS_CLASS_LAMBDA(std::uint64_t i, double& lsum) { + std::uint64_t basis_0 = internal::insert_zero_to_basis_index(i, target_qubit_index); lsum += internal::squared_norm(this->_raw[basis_0]); }, sum); return sum; } -double StateVector::get_marginal_probability(const std::vector& measured_values) const { +double StateVector::get_marginal_probability( + const std::vector& measured_values) const { if (measured_values.size() != _n_qubits) { throw std::runtime_error( "Error: " - "StateVector::get_marginal_probability(const vector&): " + "StateVector::get_marginal_probability(const vector&): " "the length of measured_values must be equal to qubit_count"); } - std::vector target_index; - std::vector target_value; - for (UINT i = 0; i < measured_values.size(); ++i) { - UINT measured_value = measured_values[i]; + std::vector target_index; + std::vector target_value; + for (std::uint64_t i = 0; i < measured_values.size(); ++i) { + std::uint64_t measured_value = measured_values[i]; if (measured_value == 0 || measured_value == 1) { target_index.push_back(i); target_value.push_back(measured_value); } else if (measured_value != StateVector::UNMEASURED) { throw std::runtime_error( "Error: " - "StateVector::get_marginal_probability(const vector&): Invalid qubit state " + "StateVector::get_marginal_probability(const vector&): Invalid " + "qubit state " "specified. Each qubit state must be 0, 1, or " "StateVector::UNMEASURED."); } @@ -131,10 +133,10 @@ double StateVector::get_marginal_probability(const std::vector& measured_v Kokkos::parallel_reduce( "marginal_prob", _dim >> target_index.size(), - KOKKOS_CLASS_LAMBDA(UINT i, double& lsum) { - UINT basis = i; - for (UINT cursor = 0; cursor < d_target_index.size(); cursor++) { - UINT insert_index = d_target_index[cursor]; + KOKKOS_CLASS_LAMBDA(std::uint64_t i, double& lsum) { + std::uint64_t basis = i; + for (std::uint64_t cursor = 0; cursor < d_target_index.size(); cursor++) { + std::uint64_t insert_index = d_target_index[cursor]; basis = internal::insert_zero_to_basis_index(basis, insert_index); basis ^= d_target_value[cursor] << insert_index; } @@ -151,7 +153,7 @@ double StateVector::get_entropy() const { Kokkos::parallel_reduce( "get_entropy", _dim, - KOKKOS_CLASS_LAMBDA(UINT idx, double& lsum) { + KOKKOS_CLASS_LAMBDA(std::uint64_t idx, double& lsum) { double prob = internal::squared_norm(_raw[idx]); prob = (prob > eps) ? prob : eps; lsum += -prob * Kokkos::log(prob); @@ -162,43 +164,46 @@ double StateVector::get_entropy() const { void StateVector::add_state_vector(const StateVector& state) { Kokkos::parallel_for( - this->_dim, KOKKOS_CLASS_LAMBDA(UINT i) { this->_raw[i] += state._raw[i]; }); + this->_dim, KOKKOS_CLASS_LAMBDA(std::uint64_t i) { this->_raw[i] += state._raw[i]; }); Kokkos::fence(); } void StateVector::add_state_vector_with_coef(const Complex& coef, const StateVector& state) { Kokkos::parallel_for( - this->_dim, KOKKOS_CLASS_LAMBDA(UINT i) { this->_raw[i] += coef * state._raw[i]; }); + this->_dim, + KOKKOS_CLASS_LAMBDA(std::uint64_t i) { this->_raw[i] += coef * state._raw[i]; }); Kokkos::fence(); } void StateVector::multiply_coef(const Complex& coef) { Kokkos::parallel_for( - this->_dim, KOKKOS_CLASS_LAMBDA(UINT i) { this->_raw[i] *= coef; }); + this->_dim, KOKKOS_CLASS_LAMBDA(std::uint64_t i) { this->_raw[i] *= coef; }); Kokkos::fence(); } -std::vector StateVector::sampling(UINT sampling_count, UINT seed) const { +std::vector StateVector::sampling(std::uint64_t sampling_count, + std::uint64_t seed) const { Kokkos::View stacked_prob("prob", _dim + 1); Kokkos::parallel_scan( "compute_stacked_prob", _dim, - KOKKOS_CLASS_LAMBDA(UINT i, double& update, const bool final) { + KOKKOS_CLASS_LAMBDA(std::uint64_t i, double& update, const bool final) { update += internal::squared_norm(this->_raw[i]); if (final) { stacked_prob[i + 1] = update; } }); - Kokkos::View result(Kokkos::ViewAllocateWithoutInitializing("result"), sampling_count); + Kokkos::View result(Kokkos::ViewAllocateWithoutInitializing("result"), + sampling_count); Kokkos::Random_XorShift64_Pool<> rand_pool(seed); Kokkos::parallel_for( - sampling_count, KOKKOS_LAMBDA(UINT i) { + sampling_count, KOKKOS_LAMBDA(std::uint64_t i) { auto rand_gen = rand_pool.get_state(); double r = rand_gen.drand(0., 1.); - UINT lo = 0, hi = stacked_prob.size(); + std::uint64_t lo = 0, hi = stacked_prob.size(); while (hi - lo > 1) { - UINT mid = (lo + hi) / 2; + std::uint64_t mid = (lo + hi) / 2; if (stacked_prob[mid] > r) { hi = mid; } else { @@ -219,9 +224,9 @@ std::string StateVector::to_string() const { os << " * Qubit Count : " << _n_qubits << '\n'; os << " * Dimension : " << _dim << '\n'; os << " * State vector : \n"; - for (UINT i = 0; i < _dim; ++i) { + for (std::uint64_t i = 0; i < _dim; ++i) { os << - [](UINT n, UINT len) { + [](std::uint64_t n, std::uint64_t len) { std::string tmp; while (len--) { tmp += ((n >> len) & 1) + '0'; diff --git a/scaluq/state/state_vector.hpp b/scaluq/state/state_vector.hpp index 524af3cb..a99bba42 100644 --- a/scaluq/state/state_vector.hpp +++ b/scaluq/state/state_vector.hpp @@ -10,14 +10,14 @@ namespace scaluq { class StateVector { - UINT _n_qubits; - UINT _dim; + std::uint64_t _n_qubits; + std::uint64_t _dim; public: - static constexpr UINT UNMEASURED = 2; + static constexpr std::uint64_t UNMEASURED = 2; StateVectorView _raw; StateVector() = default; - StateVector(UINT n_qubits); + StateVector(std::uint64_t n_qubits); StateVector(const StateVector& other) = default; StateVector& operator=(const StateVector& other) = default; @@ -25,26 +25,26 @@ class StateVector { /** * @attention Very slow. You should use load() instead if you can. */ - void set_amplitude_at_index(UINT index, const Complex& c); + void set_amplitude_at_index(std::uint64_t index, const Complex& c); /** * @attention Very slow. You should use get_amplitudes() instead if you can. */ - [[nodiscard]] Complex get_amplitude_at_index(UINT index) const; + [[nodiscard]] Complex get_amplitude_at_index(std::uint64_t index) const; - [[nodiscard]] static StateVector Haar_random_state(UINT n_qubits, - UINT seed = std::random_device()()); + [[nodiscard]] static StateVector Haar_random_state(std::uint64_t n_qubits, + std::uint64_t seed = std::random_device()()); /** * @brief zero-fill */ void set_zero_state(); void set_zero_norm_state(); - void set_computational_basis(UINT basis); + void set_computational_basis(std::uint64_t basis); - [[nodiscard]] UINT n_qubits() const; + [[nodiscard]] std::uint64_t n_qubits() const; - [[nodiscard]] UINT dim() const; + [[nodiscard]] std::uint64_t dim() const; [[nodiscard]] std::vector get_amplitudes() const; @@ -52,16 +52,17 @@ class StateVector { void normalize(); - [[nodiscard]] double get_zero_probability(UINT target_qubit_index) const; - [[nodiscard]] double get_marginal_probability(const std::vector& measured_values) const; + [[nodiscard]] double get_zero_probability(std::uint64_t target_qubit_index) const; + [[nodiscard]] double get_marginal_probability( + const std::vector& measured_values) const; [[nodiscard]] double get_entropy() const; void add_state_vector(const StateVector& state); void add_state_vector_with_coef(const Complex& coef, const StateVector& state); void multiply_coef(const Complex& coef); - [[nodiscard]] std::vector sampling(UINT sampling_count, - UINT seed = std::random_device()()) const; + [[nodiscard]] std::vector sampling( + std::uint64_t sampling_count, std::uint64_t seed = std::random_device()()) const; void load(const std::vector& other); diff --git a/scaluq/state/state_vector_batched.cpp b/scaluq/state/state_vector_batched.cpp index fdf01fe2..d91d2452 100644 --- a/scaluq/state/state_vector_batched.cpp +++ b/scaluq/state/state_vector_batched.cpp @@ -3,7 +3,7 @@ #include "../util/utility.hpp" namespace scaluq { -StateVectorBatched::StateVectorBatched(UINT batch_size, UINT n_qubits) +StateVectorBatched::StateVectorBatched(std::uint64_t batch_size, std::uint64_t n_qubits) : _batch_size(batch_size), _n_qubits(n_qubits), _dim(1ULL << _n_qubits), @@ -20,50 +20,53 @@ void StateVectorBatched::set_state_vector(const StateVector& state) { } Kokkos::parallel_for( Kokkos::MDRangePolicy>({0, 0}, {_batch_size, _dim}), - KOKKOS_CLASS_LAMBDA(UINT batch_id, UINT i) { _raw(batch_id, i) = state._raw(i); }); + KOKKOS_CLASS_LAMBDA(std::uint64_t batch_id, std::uint64_t i) { + _raw(batch_id, i) = state._raw(i); + }); Kokkos::fence(); } -void StateVectorBatched::set_state_vector(UINT batch_id, const StateVector& state) { +void StateVectorBatched::set_state_vector(std::uint64_t batch_id, const StateVector& state) { if (_raw.extent(1) != state._raw.extent(0)) [[unlikely]] { throw std::runtime_error( - "Error: StateVectorBatched::set_state_vector(UINT, const StateVector&): Dimensions of " + "Error: StateVectorBatched::set_state_vector(std::uint64_t, const StateVector&): " + "Dimensions of " "source and destination views do not match."); } Kokkos::parallel_for( - _dim, KOKKOS_CLASS_LAMBDA(UINT i) { _raw(batch_id, i) = state._raw(i); }); + _dim, KOKKOS_CLASS_LAMBDA(std::uint64_t i) { _raw(batch_id, i) = state._raw(i); }); Kokkos::fence(); } -StateVector StateVectorBatched::get_state_vector(UINT batch_id) const { +StateVector StateVectorBatched::get_state_vector(std::uint64_t batch_id) const { StateVector ret(_n_qubits); Kokkos::parallel_for( - _dim, KOKKOS_CLASS_LAMBDA(UINT i) { ret._raw(i) = _raw(batch_id, i); }); + _dim, KOKKOS_CLASS_LAMBDA(std::uint64_t i) { ret._raw(i) = _raw(batch_id, i); }); Kokkos::fence(); return ret; } void StateVectorBatched::set_zero_state() { set_computational_basis(0); } -void StateVectorBatched::set_computational_basis(UINT basis) { +void StateVectorBatched::set_computational_basis(std::uint64_t basis) { if (basis >= _dim) [[unlikely]] { throw std::runtime_error( - "Error: StateVectorBatched::set_computational_basis(UINT): " + "Error: StateVectorBatched::set_computational_basis(std::uint64_t): " "index of " "computational basis must be smaller than 2^qubit_count"); } Kokkos::deep_copy(_raw, 0); Kokkos::parallel_for( - _batch_size, KOKKOS_CLASS_LAMBDA(UINT i) { _raw(i, basis) = 1; }); + _batch_size, KOKKOS_CLASS_LAMBDA(std::uint64_t i) { _raw(i, basis) = 1; }); Kokkos::fence(); } void StateVectorBatched::set_zero_norm_state() { Kokkos::deep_copy(_raw, 0); } -StateVectorBatched StateVectorBatched::Haar_random_states(UINT batch_size, - UINT n_qubits, +StateVectorBatched StateVectorBatched::Haar_random_states(std::uint64_t batch_size, + std::uint64_t n_qubits, bool set_same_state, - UINT seed) { + std::uint64_t seed) { Kokkos::Random_XorShift64_Pool<> rand_pool(seed); StateVectorBatched states(batch_size, n_qubits); if (set_same_state) { @@ -71,7 +74,7 @@ StateVectorBatched StateVectorBatched::Haar_random_states(UINT batch_size, } else { Kokkos::parallel_for( Kokkos::MDRangePolicy>({0, 0}, {states.batch_size(), states.dim()}), - KOKKOS_LAMBDA(UINT b, UINT i) { + KOKKOS_LAMBDA(std::uint64_t b, std::uint64_t i) { auto rand_gen = rand_pool.get_state(); states._raw(b, i) = Complex(rand_gen.normal(0.0, 1.0), rand_gen.normal(0.0, 1.0)); rand_pool.free_state(rand_gen); @@ -83,7 +86,8 @@ StateVectorBatched StateVectorBatched::Haar_random_states(UINT batch_size, return states; } -std::vector> StateVectorBatched::sampling(UINT sampling_count, UINT seed) const { +std::vector> StateVectorBatched::sampling(std::uint64_t sampling_count, + std::uint64_t seed) const { Kokkos::View stacked_prob("prob", _batch_size, _dim + 1); Kokkos::parallel_for( @@ -91,9 +95,9 @@ std::vector> StateVectorBatched::sampling(UINT sampling_count, KOKKOS_CLASS_LAMBDA( const Kokkos::TeamPolicy::TeamPolicy::member_type& team) { - UINT batch_id = team.league_rank(); + std::uint64_t batch_id = team.league_rank(); Kokkos::parallel_scan(Kokkos::TeamThreadRange(team, _dim), - [&](UINT i, double& update, const bool final) { + [&](std::uint64_t i, double& update, const bool final) { update += internal::squared_norm(this->_raw(batch_id, i)); if (final) { stacked_prob(batch_id, i + 1) = update; @@ -102,18 +106,18 @@ std::vector> StateVectorBatched::sampling(UINT sampling_count, }); Kokkos::fence(); - Kokkos::View result( + Kokkos::View result( Kokkos::ViewAllocateWithoutInitializing("result"), _batch_size, sampling_count); Kokkos::Random_XorShift64_Pool<> rand_pool(seed); Kokkos::parallel_for( Kokkos::MDRangePolicy>({0, 0}, {_batch_size, sampling_count}), - KOKKOS_CLASS_LAMBDA(UINT batch_id, UINT i) { + KOKKOS_CLASS_LAMBDA(std::uint64_t batch_id, std::uint64_t i) { auto rand_gen = rand_pool.get_state(); double r = rand_gen.drand(0., 1.); - UINT lo = 0, hi = stacked_prob.extent(1); + std::uint64_t lo = 0, hi = stacked_prob.extent(1); while (hi - lo > 1) { - UINT mid = (lo + hi) / 2; + std::uint64_t mid = (lo + hi) / 2; if (stacked_prob(batch_id, mid) > r) { hi = mid; } else { @@ -124,9 +128,9 @@ std::vector> StateVectorBatched::sampling(UINT sampling_count, rand_pool.free_state(rand_gen); }); Kokkos::fence(); - return internal:: - convert_2d_device_view_to_host_vector( - result); + return internal::convert_2d_device_view_to_host_vector< + std::uint64_t, + Kokkos::DefaultExecutionSpace::array_layout>(result); } std::vector> StateVectorBatched::get_amplitudes() const { @@ -141,10 +145,10 @@ std::vector StateVectorBatched::get_squared_norm() const { const Kokkos::TeamPolicy::TeamPolicy::member_type& team) { double nrm = 0; - UINT batch_id = team.league_rank(); + std::uint64_t batch_id = team.league_rank(); Kokkos::parallel_reduce( Kokkos::TeamThreadRange(team, _dim), - [=, *this](const UINT& i, double& lcl) { + [=, *this](const std::uint64_t& i, double& lcl) { lcl += internal::squared_norm(_raw(batch_id, i)); }, nrm); @@ -162,25 +166,26 @@ void StateVectorBatched::normalize() { const Kokkos::TeamPolicy::TeamPolicy::member_type& team) { double nrm = 0; - UINT batch_id = team.league_rank(); + std::uint64_t batch_id = team.league_rank(); Kokkos::parallel_reduce( Kokkos::TeamThreadRange(team, _dim), - [=, *this](const UINT& i, double& lcl) { + [=, *this](const std::uint64_t& i, double& lcl) { lcl += internal::squared_norm(_raw(batch_id, i)); }, nrm); team.team_barrier(); nrm = Kokkos::sqrt(nrm); Kokkos::parallel_for(Kokkos::TeamThreadRange(team, _dim), - [=, *this](const UINT& i) { _raw(batch_id, i) /= nrm; }); + [=, *this](const std::uint64_t& i) { _raw(batch_id, i) /= nrm; }); }); Kokkos::fence(); } -std::vector StateVectorBatched::get_zero_probability(UINT target_qubit_index) const { +std::vector StateVectorBatched::get_zero_probability( + std::uint64_t target_qubit_index) const { if (target_qubit_index >= _n_qubits) { throw std::runtime_error( - "Error: StateVectorBatched::get_zero_probability(UINT): index " + "Error: StateVectorBatched::get_zero_probability(std::uint64_t): index " "of target qubit must be smaller than qubit_count"); } Kokkos::View probs("probs", _batch_size); @@ -190,11 +195,12 @@ std::vector StateVectorBatched::get_zero_probability(UINT target_qubit_i const Kokkos::TeamPolicy::TeamPolicy::member_type& team) { double sum = 0; - UINT batch_id = team.league_rank(); + std::uint64_t batch_id = team.league_rank(); Kokkos::parallel_reduce( Kokkos::TeamThreadRange(team, _dim >> 1), - [&](UINT i, double& lsum) { - UINT basis_0 = internal::insert_zero_to_basis_index(i, target_qubit_index); + [&](std::uint64_t i, double& lsum) { + std::uint64_t basis_0 = + internal::insert_zero_to_basis_index(i, target_qubit_index); lsum += internal::squared_norm(_raw(batch_id, basis_0)); }, sum); @@ -206,24 +212,24 @@ std::vector StateVectorBatched::get_zero_probability(UINT target_qubit_i } std::vector StateVectorBatched::get_marginal_probability( - const std::vector& measured_values) const { + const std::vector& measured_values) const { if (measured_values.size() != _n_qubits) { throw std::runtime_error( "Error: " - "StateVectorBatched::get_marginal_probability(const vector&): " + "StateVectorBatched::get_marginal_probability(const vector&): " "the length of measured_values must be equal to qubit_count"); } - std::vector target_index; - std::vector target_value; - for (UINT i = 0; i < measured_values.size(); ++i) { - UINT measured_value = measured_values[i]; + std::vector target_index; + std::vector target_value; + for (std::uint64_t i = 0; i < measured_values.size(); ++i) { + std::uint64_t measured_value = measured_values[i]; if (measured_value == 0 || measured_value == 1) { target_index.push_back(i); target_value.push_back(measured_value); } else if (measured_value != StateVector::UNMEASURED) { throw std::runtime_error( - "Error:StateVectorBatched::get_marginal_probability(const vector&): " + "Error:StateVectorBatched::get_marginal_probability(const vector&): " "Invalid " "qubit state specified. Each qubit state must be 0, 1, or " "StateVector::UNMEASURED."); @@ -239,13 +245,13 @@ std::vector StateVectorBatched::get_marginal_probability( const Kokkos::TeamPolicy::TeamPolicy::member_type& team) { double sum = 0; - UINT batch_id = team.league_rank(); + std::uint64_t batch_id = team.league_rank(); Kokkos::parallel_reduce( Kokkos::TeamThreadRange(team, _dim >> target_index_d.size()), - [&](UINT i, double& lsum) { - UINT basis = i; - for (UINT cursor = 0; cursor < target_index_d.size(); cursor++) { - UINT insert_index = target_index_d[cursor]; + [&](std::uint64_t i, double& lsum) { + std::uint64_t basis = i; + for (std::uint64_t cursor = 0; cursor < target_index_d.size(); cursor++) { + std::uint64_t insert_index = target_index_d[cursor]; basis = internal::insert_zero_to_basis_index(basis, insert_index); basis ^= target_value_d[cursor] << insert_index; } @@ -268,10 +274,10 @@ std::vector StateVectorBatched::get_entropy() const { const Kokkos::TeamPolicy::TeamPolicy::member_type& team) { double sum = 0; - UINT batch_id = team.league_rank(); + std::uint64_t batch_id = team.league_rank(); Kokkos::parallel_reduce( Kokkos::TeamThreadRange(team, _dim), - [&](UINT idx, double& lsum) { + [&](std::uint64_t idx, double& lsum) { double prob = internal::squared_norm(_raw(batch_id, idx)); prob = Kokkos::max(prob, eps); lsum += -prob * Kokkos::log(prob); @@ -292,7 +298,7 @@ void StateVectorBatched::add_state_vector(const StateVectorBatched& states) { } Kokkos::parallel_for( Kokkos::MDRangePolicy>({0, 0}, {_batch_size, _dim}), - KOKKOS_CLASS_LAMBDA(UINT batch_id, UINT i) { + KOKKOS_CLASS_LAMBDA(std::uint64_t batch_id, std::uint64_t i) { _raw(batch_id, i) += states._raw(batch_id, i); }); Kokkos::fence(); @@ -306,7 +312,7 @@ void StateVectorBatched::add_state_vector_with_coef(const Complex& coef, } Kokkos::parallel_for( Kokkos::MDRangePolicy>({0, 0}, {_batch_size, _dim}), - KOKKOS_CLASS_LAMBDA(UINT batch_id, UINT i) { + KOKKOS_CLASS_LAMBDA(std::uint64_t batch_id, std::uint64_t i) { _raw(batch_id, i) += coef * states._raw(batch_id, i); }); Kokkos::fence(); @@ -314,7 +320,9 @@ void StateVectorBatched::add_state_vector_with_coef(const Complex& coef, void StateVectorBatched::multiply_coef(const Complex& coef) { Kokkos::parallel_for( Kokkos::MDRangePolicy>({0, 0}, {_batch_size, _dim}), - KOKKOS_CLASS_LAMBDA(UINT batch_id, UINT i) { _raw(batch_id, i) *= coef; }); + KOKKOS_CLASS_LAMBDA(std::uint64_t batch_id, std::uint64_t i) { + _raw(batch_id, i) *= coef; + }); Kokkos::fence(); } @@ -324,7 +332,7 @@ void StateVectorBatched::load(const std::vector>& states) { "Error: StateVectorBatched::load(std::vector>&): invalid " "batch_size"); } - for (UINT b = 0; b < states.size(); ++b) { + for (std::uint64_t b = 0; b < states.size(); ++b) { if (states[b].size() != _dim) { throw std::runtime_error( "Error: StateVectorBatched::load(std::vector>&): invalid " @@ -334,8 +342,8 @@ void StateVectorBatched::load(const std::vector>& states) { auto view_h = Kokkos::create_mirror_view(Kokkos::HostSpace(), _raw); Kokkos::fence(); - for (UINT b = 0; b < states.size(); ++b) { - for (UINT i = 0; i < states[0].size(); ++i) { + for (std::uint64_t b = 0; b < states.size(); ++b) { + for (std::uint64_t i = 0; i < states[0].size(); ++i) { view_h(b, i) = states[b][i]; } } @@ -356,14 +364,14 @@ std::string StateVectorBatched::to_string() const { os << " *** Quantum States ***\n"; os << " * Qubit Count : " << _n_qubits << '\n'; os << " * Dimension : " << _dim << '\n'; - for (UINT b = 0; b < _batch_size; ++b) { + for (std::uint64_t b = 0; b < _batch_size; ++b) { StateVector tmp(_n_qubits); os << "--------------------\n"; os << " * Batch_id : " << b << '\n'; os << " * State vector : \n"; - for (UINT i = 0; i < _dim; ++i) { + for (std::uint64_t i = 0; i < _dim; ++i) { os << - [](UINT n, UINT len) { + [](std::uint64_t n, std::uint64_t len) { std::string tmp; while (len--) { tmp += ((n >> len) & 1) + '0'; diff --git a/scaluq/state/state_vector_batched.hpp b/scaluq/state/state_vector_batched.hpp index 99d3b794..5ab494f9 100644 --- a/scaluq/state/state_vector_batched.hpp +++ b/scaluq/state/state_vector_batched.hpp @@ -5,39 +5,40 @@ namespace scaluq { class StateVectorBatched { - UINT _batch_size; - UINT _n_qubits; - UINT _dim; + std::uint64_t _batch_size; + std::uint64_t _n_qubits; + std::uint64_t _dim; public: StateVectorBatchedView _raw; StateVectorBatched() = default; - StateVectorBatched(UINT batch_size, UINT n_qubits); + StateVectorBatched(std::uint64_t batch_size, std::uint64_t n_qubits); StateVectorBatched(const StateVectorBatched& other) = default; StateVectorBatched& operator=(const StateVectorBatched& other) = default; - [[nodiscard]] UINT n_qubits() const { return this->_n_qubits; } + [[nodiscard]] std::uint64_t n_qubits() const { return this->_n_qubits; } - [[nodiscard]] UINT dim() const { return this->_dim; } + [[nodiscard]] std::uint64_t dim() const { return this->_dim; } - [[nodiscard]] UINT batch_size() const { return this->_batch_size; } + [[nodiscard]] std::uint64_t batch_size() const { return this->_batch_size; } void set_state_vector(const StateVector& state); - void set_state_vector(UINT batch_id, const StateVector& state); - [[nodiscard]] StateVector get_state_vector(UINT batch_id) const; + void set_state_vector(std::uint64_t batch_id, const StateVector& state); + [[nodiscard]] StateVector get_state_vector(std::uint64_t batch_id) const; void set_zero_state(); - void set_computational_basis(UINT basis); + void set_computational_basis(std::uint64_t basis); void set_zero_norm_state(); - [[nodiscard]] std::vector> sampling(UINT sampling_count, - UINT seed = std::random_device()()) const; + [[nodiscard]] std::vector> sampling( + std::uint64_t sampling_count, std::uint64_t seed = std::random_device()()) const; - [[nodiscard]] static StateVectorBatched Haar_random_states(UINT batch_size, - UINT n_qubits, - bool set_same_state, - UINT seed = std::random_device()()); + [[nodiscard]] static StateVectorBatched Haar_random_states( + std::uint64_t batch_size, + std::uint64_t n_qubits, + bool set_same_state, + std::uint64_t seed = std::random_device()()); [[nodiscard]] std::vector> get_amplitudes() const; @@ -45,9 +46,9 @@ class StateVectorBatched { void normalize(); - [[nodiscard]] std::vector get_zero_probability(UINT target_qubit_index) const; + [[nodiscard]] std::vector get_zero_probability(std::uint64_t target_qubit_index) const; [[nodiscard]] std::vector get_marginal_probability( - const std::vector& measured_values) const; + const std::vector& measured_values) const; [[nodiscard]] std::vector get_entropy() const; void add_state_vector(const StateVectorBatched& states); diff --git a/scaluq/types.hpp b/scaluq/types.hpp index 0e9503e4..e31fb92e 100644 --- a/scaluq/types.hpp +++ b/scaluq/types.hpp @@ -17,8 +17,6 @@ inline void finalize() { Kokkos::finalize(); } inline bool is_initialized() { return Kokkos::is_initialized(); } inline bool is_finalized() { return Kokkos::is_finalized(); } -using UINT = std::uint64_t; - using Complex = Kokkos::complex; using namespace std::complex_literals; diff --git a/scaluq/util/bit_vector.hpp b/scaluq/util/bit_vector.hpp index 36c9f6a3..909f4810 100644 --- a/scaluq/util/bit_vector.hpp +++ b/scaluq/util/bit_vector.hpp @@ -11,23 +11,23 @@ namespace scaluq { namespace internal { class BitVector { public: - constexpr static UINT BIT_SIZE = sizeof(UINT) * 8; + constexpr static std::uint64_t BIT_SIZE = sizeof(std::uint64_t) * 8; - BitVector(UINT sz = 1) : _data((sz + BIT_SIZE - 1) / BIT_SIZE) {} + BitVector(std::uint64_t sz = 1) : _data((sz + BIT_SIZE - 1) / BIT_SIZE) {} BitVector(const std::vector& vec) : _data((vec.size() + BIT_SIZE - 1) / BIT_SIZE) { - for (UINT i = 0; i < vec.size(); ++i) { + for (std::uint64_t i = 0; i < vec.size(); ++i) { set(i, vec[i]); } } - [[nodiscard]] inline const std::vector& data_raw() const { return _data; } - [[nodiscard]] inline std::vector& data_raw() { return _data; } + [[nodiscard]] inline const std::vector& data_raw() const { return _data; } + [[nodiscard]] inline std::vector& data_raw() { return _data; } - [[nodiscard]] inline bool get(UINT idx) const { + [[nodiscard]] inline bool get(std::uint64_t idx) const { if (idx >= _data.size() * BIT_SIZE) return false; return _data[idx / BIT_SIZE] >> (idx % BIT_SIZE) & 1ULL; } - inline void set(UINT idx, bool b) { + inline void set(std::uint64_t idx, bool b) { if (idx >= _data.size() * BIT_SIZE) _data.resize(idx / BIT_SIZE + 1); if (b) _data[idx / BIT_SIZE] |= 1ULL << (idx % BIT_SIZE); @@ -82,7 +82,7 @@ class BitVector { if (rhs._data.size() < _data.size()) { _data.resize(rhs._data.size()); } - for (UINT i = 0; i < _data.size(); i++) _data[i] &= rhs._data[i]; + for (std::uint64_t i = 0; i < _data.size(); i++) _data[i] &= rhs._data[i]; return *this; } inline BitVector operator&(const BitVector& rhs) const { return BitVector(*this) &= rhs; } @@ -90,7 +90,7 @@ class BitVector { if (rhs._data.size() > _data.size()) { _data.resize(rhs._data.size()); } - for (UINT i = 0; i < rhs._data.size(); i++) _data[i] |= rhs._data[i]; + for (std::uint64_t i = 0; i < rhs._data.size(); i++) _data[i] |= rhs._data[i]; return *this; } inline BitVector operator|(const BitVector& rhs) const { return BitVector(*this) |= rhs; } @@ -98,32 +98,32 @@ class BitVector { if (rhs._data.size() > _data.size()) { _data.resize(rhs._data.size()); } - for (UINT i = 0; i < rhs._data.size(); i++) _data[i] ^= rhs._data[i]; + for (std::uint64_t i = 0; i < rhs._data.size(); i++) _data[i] ^= rhs._data[i]; return *this; } inline BitVector operator^(const BitVector& rhs) const { return BitVector(*this) ^= rhs; } inline BitVector& operator-=(const BitVector& rhs) { - for (UINT i = 0; i < std::min(_data.size(), rhs._data.size()); i++) + for (std::uint64_t i = 0; i < std::min(_data.size(), rhs._data.size()); i++) _data[i] &= ~rhs._data[i]; return *this; } inline BitVector operator-(const BitVector& rhs) const { return BitVector(*this) -= rhs; } inline std::weak_ordering operator<=>(const BitVector& other) const { - UINT sz = std::max(_data.size(), other._data.size()); - for (UINT i = sz; i-- != 0;) { - UINT l = i >= _data.size() ? 0ULL : _data[i]; - UINT r = i >= other._data.size() ? 0ULL : other._data[i]; + std::uint64_t sz = std::max(_data.size(), other._data.size()); + for (std::uint64_t i = sz; i-- != 0;) { + std::uint64_t l = i >= _data.size() ? 0ULL : _data[i]; + std::uint64_t r = i >= other._data.size() ? 0ULL : other._data[i]; if (l != r) return l <=> r; if (i == 0) break; } return std::weak_ordering::equivalent; } inline bool operator==(const BitVector& other) const { - UINT sz = std::max(_data.size(), other._data.size()); - for (UINT i = sz; i-- != 0;) { - UINT l = i >= _data.size() ? 0ULL : _data[i]; - UINT r = i >= other._data.size() ? 0ULL : other._data[i]; + std::uint64_t sz = std::max(_data.size(), other._data.size()); + for (std::uint64_t i = sz; i-- != 0;) { + std::uint64_t l = i >= _data.size() ? 0ULL : _data[i]; + std::uint64_t r = i >= other._data.size() ? 0ULL : other._data[i]; if (l != r) return false; } return true; @@ -131,47 +131,48 @@ class BitVector { operator std::vector() const { std::vector vec(_data.size() * BIT_SIZE); - for (UINT i = 0; i < vec.size(); ++i) { + for (std::uint64_t i = 0; i < vec.size(); ++i) { vec[i] = get(i); } return vec; } inline bool empty() const { - return std::ranges::all_of(_data, [](UINT x) { return x == 0; }); + return std::ranges::all_of(_data, [](std::uint64_t x) { return x == 0; }); } - inline UINT msb() const { - for (UINT i = _data.size() - 1; i != std::numeric_limits::max(); i--) { + inline std::uint64_t msb() const { + for (std::uint64_t i = _data.size() - 1; i != std::numeric_limits::max(); + i--) { if (_data[i] != 0) return (i + 1) * BIT_SIZE - std::countl_zero(_data[i]) - 1; } - return std::numeric_limits::max(); + return std::numeric_limits::max(); } - inline UINT countr_zero() const { - UINT res = 0; - for (UINT i = 0; i < _data.size(); i++) { - UINT to_add = std::countr_zero(_data[i]); + inline std::uint64_t countr_zero() const { + std::uint64_t res = 0; + for (std::uint64_t i = 0; i < _data.size(); i++) { + std::uint64_t to_add = std::countr_zero(_data[i]); res += to_add; if (to_add < BIT_SIZE) break; } return res; } - inline UINT countr_one() const { - UINT res = 0; - for (UINT i = 0; i < _data.size(); i++) { - UINT to_add = std::countr_one(_data[i]); + inline std::uint64_t countr_one() const { + std::uint64_t res = 0; + for (std::uint64_t i = 0; i < _data.size(); i++) { + std::uint64_t to_add = std::countr_one(_data[i]); res += to_add; if (to_add < BIT_SIZE) break; } return res; } - inline UINT popcount() const { - UINT res = 0; - for (UINT i = 0; i < _data.size(); i++) res += std::popcount(_data[i]); + inline std::uint64_t popcount() const { + std::uint64_t res = 0; + for (std::uint64_t i = 0; i < _data.size(); i++) res += std::popcount(_data[i]); return res; } private: - std::vector _data; + std::vector _data; }; } // namespace internal } // namespace scaluq diff --git a/scaluq/util/random.hpp b/scaluq/util/random.hpp index 146399d2..5d4ca49e 100644 --- a/scaluq/util/random.hpp +++ b/scaluq/util/random.hpp @@ -11,13 +11,14 @@ class Random { std::normal_distribution normal_dist; public: - Random(UINT seed = std::random_device()()) : mt(seed), uniform_dist(0, 1), normal_dist(0, 1) {} + Random(std::uint64_t seed = std::random_device()()) + : mt(seed), uniform_dist(0, 1), normal_dist(0, 1) {} [[nodiscard]] double uniform() { return this->uniform_dist(this->mt); } [[nodiscard]] double normal() { return this->normal_dist(this->mt); } - [[nodiscard]] UINT int64() { return this->mt(); } + [[nodiscard]] std::uint64_t int64() { return this->mt(); } [[nodiscard]] std::uint32_t int32() { return this->mt() % UINT32_MAX; } }; diff --git a/scaluq/util/utility.hpp b/scaluq/util/utility.hpp index c0e0830f..fee20912 100644 --- a/scaluq/util/utility.hpp +++ b/scaluq/util/utility.hpp @@ -19,9 +19,10 @@ namespace internal { * Example: insert_zero_to_basis_index(0b1001, 1) -> 0b10001. * ^ */ -KOKKOS_INLINE_FUNCTION UINT insert_zero_to_basis_index(UINT basis_index, UINT insert_index) { - UINT mask = (1ULL << insert_index) - 1; - UINT temp_basis = (basis_index >> insert_index) << (insert_index + 1); +KOKKOS_INLINE_FUNCTION std::uint64_t insert_zero_to_basis_index(std::uint64_t basis_index, + std::uint64_t insert_index) { + std::uint64_t mask = (1ULL << insert_index) - 1; + std::uint64_t temp_basis = (basis_index >> insert_index) << (insert_index + 1); return temp_basis | (basis_index & mask); } @@ -30,22 +31,23 @@ KOKKOS_INLINE_FUNCTION UINT insert_zero_to_basis_index(UINT basis_index, UINT in * Example: insert_zero_to_basis_index(0b11111, 0x100101) -> 0b11011010. * ^ ^ ^ */ -KOKKOS_INLINE_FUNCTION UINT insert_zero_at_mask_positions(UINT basis_index, UINT insert_mask) { - for (UINT bit_mask = insert_mask; bit_mask; +KOKKOS_INLINE_FUNCTION std::uint64_t insert_zero_at_mask_positions(std::uint64_t basis_index, + std::uint64_t insert_mask) { + for (std::uint64_t bit_mask = insert_mask; bit_mask; bit_mask &= (bit_mask - 1)) { // loop through set bits - UINT lower_mask = ~bit_mask & (bit_mask - 1); - UINT upper_mask = ~lower_mask; + std::uint64_t lower_mask = ~bit_mask & (bit_mask - 1); + std::uint64_t upper_mask = ~lower_mask; basis_index = ((basis_index & upper_mask) << 1) | (basis_index & lower_mask); } return basis_index; } template -inline UINT vector_to_mask(const std::vector& v) { - UINT mask = 0; +inline std::uint64_t vector_to_mask(const std::vector& v) { + std::uint64_t mask = 0; for (auto x : v) { if constexpr (enable_validate) { - if (x >= sizeof(UINT) * 8) [[unlikely]] { + if (x >= sizeof(std::uint64_t) * 8) [[unlikely]] { throw std::runtime_error("The size of the qubit system must be less than 64."); } if ((mask >> x) & 1) [[unlikely]] { @@ -57,9 +59,9 @@ inline UINT vector_to_mask(const std::vector& v) { return mask; } -inline std::vector mask_to_vector(UINT mask) { - std::vector indices; - for (UINT sub_mask = mask; sub_mask; sub_mask &= (sub_mask - 1)) { +inline std::vector mask_to_vector(std::uint64_t mask) { + std::vector indices; + for (std::uint64_t sub_mask = mask; sub_mask; sub_mask &= (sub_mask - 1)) { indices.push_back(std::countr_zero(sub_mask)); } return indices; @@ -84,30 +86,30 @@ inline ComplexMatrix kronecker_product(const ComplexMatrix& lhs, const ComplexMa } inline ComplexMatrix get_expanded_matrix(const ComplexMatrix& from_matrix, - const std::vector& from_targets, - std::vector& to_targets) { - std::vector targets_map(from_targets.size()); - std::ranges::transform(from_targets, targets_map.begin(), [&](UINT x) { + const std::vector& from_targets, + std::vector& to_targets) { + std::vector targets_map(from_targets.size()); + std::ranges::transform(from_targets, targets_map.begin(), [&](std::uint64_t x) { return std::ranges::lower_bound(to_targets, x) - to_targets.begin(); }); - std::vector idx_map(1ULL << from_targets.size()); - for (UINT i : std::views::iota(0ULL, 1ULL << from_targets.size())) { - for (UINT j : std::views::iota(0ULL, from_targets.size())) { + std::vector idx_map(1ULL << from_targets.size()); + for (std::uint64_t i : std::views::iota(0ULL, 1ULL << from_targets.size())) { + for (std::uint64_t j : std::views::iota(0ULL, from_targets.size())) { idx_map[i] |= (i >> j & 1) << targets_map[j]; } } - UINT targets_idx_mask = idx_map.back(); - std::vector outer_indices; + std::uint64_t targets_idx_mask = idx_map.back(); + std::vector outer_indices; outer_indices.reserve(1ULL << (to_targets.size() - from_targets.size())); - for (UINT i : std::views::iota(0ULL, 1ULL << to_targets.size())) { + for (std::uint64_t i : std::views::iota(0ULL, 1ULL << to_targets.size())) { if ((i & targets_idx_mask) == 0) outer_indices.push_back(i); } ComplexMatrix to_matrix = ComplexMatrix::Zero(1ULL << to_targets.size(), 1ULL << to_targets.size()); - for (UINT i : std::views::iota(0ULL, 1ULL << from_targets.size())) { - for (UINT j : std::views::iota(0ULL, 1ULL << from_targets.size())) { - for (UINT o : outer_indices) { + for (std::uint64_t i : std::views::iota(0ULL, 1ULL << from_targets.size())) { + for (std::uint64_t j : std::views::iota(0ULL, 1ULL << from_targets.size())) { + for (std::uint64_t o : outer_indices) { to_matrix(idx_map[i] | o, idx_map[j] | o) = from_matrix(i, j); } } diff --git a/tests/circuit/circuit_test.cpp b/tests/circuit/circuit_test.cpp index dd722584..932cb25c 100644 --- a/tests/circuit/circuit_test.cpp +++ b/tests/circuit/circuit_test.cpp @@ -14,8 +14,8 @@ const auto eps = 1e-12; using CComplex = std::complex; TEST(CircuitTest, CircuitBasic) { - const UINT n = 4; - const UINT dim = 1ULL << n; + const std::uint64_t n = 4; + const std::uint64_t dim = 1ULL << n; Random random; @@ -23,10 +23,10 @@ TEST(CircuitTest, CircuitBasic) { Eigen::VectorXcd state_eigen(dim); auto state_cp = state.get_amplitudes(); - for (UINT i = 0; i < dim; ++i) state_eigen[i] = state_cp[i]; + for (std::uint64_t i = 0; i < dim; ++i) state_eigen[i] = state_cp[i]; Circuit circuit(n); - UINT target, target_sub; + std::uint64_t target, target_sub; double angle; std::complex imag_unit(0, 1); @@ -138,8 +138,8 @@ TEST(CircuitTest, CircuitBasic) { get_expanded_eigen_matrix_with_identity(target, make_U(-angle, 0, 0), n) * state_eigen; /* - std::vector target_index_list{0, 1, 2, 3}; - std::vector pauli_id_list{0, 1, 2, 3}; + std::vector target_index_list{0, 1, 2, 3}; + std::vector pauli_id_list{0, 1, 2, 3}; circuit.add_gate(multi_Pauli(target_index_list, pauli_id_list)); // add same gate == cancel above pauli gate @@ -159,23 +159,23 @@ TEST(CircuitTest, CircuitBasic) { circuit.update_quantum_state(state); state_cp = state.get_amplitudes(); - for (UINT i = 0; i < dim; ++i) + for (std::uint64_t i = 0; i < dim; ++i) ASSERT_NEAR(std::abs(state_eigen[i] - (CComplex)state_cp[i]), 0, eps); } TEST(CircuitTest, CircuitRev) { - const UINT n = 4; - const UINT dim = 1ULL << n; + const std::uint64_t n = 4; + const std::uint64_t dim = 1ULL << n; Random random; StateVector state = StateVector::Haar_random_state(n); auto state_cp = state.get_amplitudes(); Eigen::VectorXcd state_eigen(dim); - for (UINT i = 0; i < dim; ++i) state_eigen[i] = state_cp[i]; + for (std::uint64_t i = 0; i < dim; ++i) state_eigen[i] = state_cp[i]; Circuit circuit(n); - UINT target, target_sub; + std::uint64_t target, target_sub; double angle; target = random.int32() % n; @@ -257,5 +257,6 @@ TEST(CircuitTest, CircuitRev) { revcircuit.update_quantum_state(state); state_cp = state.get_amplitudes(); - for (UINT i = 0; i < dim; ++i) ASSERT_NEAR(abs(state_eigen[i] - (CComplex)state_cp[i]), 0, eps); + for (std::uint64_t i = 0; i < dim; ++i) + ASSERT_NEAR(abs(state_eigen[i] - (CComplex)state_cp[i]), 0, eps); } diff --git a/tests/circuit/param_circuit_test.cpp b/tests/circuit/param_circuit_test.cpp index 8e1ed094..40f8b13f 100644 --- a/tests/circuit/param_circuit_test.cpp +++ b/tests/circuit/param_circuit_test.cpp @@ -14,40 +14,41 @@ using namespace scaluq; constexpr double eps = 1e-12; TEST(ParamCircuitTest, ApplyParamCircuit) { - UINT n_qubits = 5; + std::uint64_t n_qubits = 5; Random random; - for ([[maybe_unused]] UINT repeat : std::views::iota(0, 10)) { + for ([[maybe_unused]] std::uint64_t repeat : std::views::iota(0, 10)) { Circuit circuit(n_qubits); Circuit pcircuit(n_qubits); - constexpr UINT nparams = 5; + constexpr std::uint64_t nparams = 5; std::array pkeys = {}; - for (UINT pidx : std::views::iota(UINT{0}, nparams)) + for (std::uint64_t pidx : std::views::iota(std::uint64_t{0}, nparams)) pkeys[pidx] = "p" + std::to_string(pidx); std::array params = {}; - for (UINT pidx : std::views::iota(UINT{0}, nparams)) + for (std::uint64_t pidx : std::views::iota(std::uint64_t{0}, nparams)) params[pidx] = random.uniform() * M_PI * 2; std::map pmap; - for (UINT pidx : std::views::iota(UINT{0}, nparams)) pmap[pkeys[pidx]] = params[pidx]; + for (std::uint64_t pidx : std::views::iota(std::uint64_t{0}, nparams)) + pmap[pkeys[pidx]] = params[pidx]; auto add_random_rotation_or_cnot = [&] { if (random.int32() & 1) { - UINT param_gate_kind = random.int32() % 4; + std::uint64_t param_gate_kind = random.int32() % 4; double coef = random.uniform() * 2 - 1; - UINT pidx = random.int32() % nparams; + std::uint64_t pidx = random.int32() % nparams; if (param_gate_kind == 0) { - UINT target = random.int32() % n_qubits; + std::uint64_t target = random.int32() % n_qubits; circuit.add_gate(gate::RX(target, coef * params[pidx])); pcircuit.add_param_gate(gate::PRX(target, coef), pkeys[pidx]); } else if (param_gate_kind == 1) { - UINT target = random.int32() % n_qubits; + std::uint64_t target = random.int32() % n_qubits; circuit.add_gate(gate::RY(target, coef * params[pidx])); pcircuit.add_param_gate(gate::PRY(target, coef), pkeys[pidx]); } else if (param_gate_kind == 2) { - UINT target = random.int32() % n_qubits; + std::uint64_t target = random.int32() % n_qubits; circuit.add_gate(gate::RZ(target, coef * params[pidx])); pcircuit.add_param_gate(gate::PRZ(target, coef), pkeys[pidx]); } else { - std::vector target_vec, pauli_id_vec; - for (UINT target = 0; target < n_qubits; target++) { + std::vector target_vec, pauli_id_vec; + for (std::uint64_t target = 0; target < n_qubits; target++) { target_vec.emplace_back(target); pauli_id_vec.emplace_back(random.int64() % 4); } @@ -56,14 +57,14 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { pcircuit.add_param_gate(gate::PPauliRotation(pauli, coef), pkeys[pidx]); } } else { - UINT control = random.int32() % n_qubits; - UINT target = random.int32() % (n_qubits - 1); + std::uint64_t control = random.int32() % n_qubits; + std::uint64_t target = random.int32() % (n_qubits - 1); if (target == control) target = n_qubits - 1; circuit.add_gate(gate::CX(control, target)); pcircuit.add_gate(gate::CX(control, target)); } }; - for ([[maybe_unused]] UINT _ : std::views::iota(0ULL, 20ULL)) { + for ([[maybe_unused]] std::uint64_t _ : std::views::iota(0ULL, 20ULL)) { add_random_rotation_or_cnot(); } StateVector state = StateVector::Haar_random_state(n_qubits); @@ -73,7 +74,7 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { pcircuit.update_quantum_state(state_cp, pmap); auto amplitudes = state.get_amplitudes(); auto amplitudes_cp = state_cp.get_amplitudes(); - for (UINT idx : std::views::iota(UINT{0}, 1ULL << n_qubits)) { + for (std::uint64_t idx : std::views::iota(std::uint64_t{0}, 1ULL << n_qubits)) { ASSERT_NEAR(Kokkos::abs(amplitudes[idx] - amplitudes_cp[idx]), 0, eps); } auto icircuit = circuit.get_inverse(); @@ -82,7 +83,7 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { ipcircuit.update_quantum_state(state_cp, pmap); amplitudes = state.get_amplitudes(); amplitudes_cp = state_cp.get_amplitudes(); - for (UINT idx : std::views::iota(UINT{0}, 1ULL << n_qubits)) { + for (std::uint64_t idx : std::views::iota(std::uint64_t{0}, 1ULL << n_qubits)) { ASSERT_NEAR(Kokkos::abs(amplitudes[idx] - amplitudes_base[idx]), 0, eps); ASSERT_NEAR(Kokkos::abs(amplitudes_cp[idx] - amplitudes_base[idx]), 0, eps); } diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index d046df95..1a4459f9 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -17,7 +17,7 @@ const auto eps = 1e-12; using CComplex = std::complex; template -void run_random_gate_apply(UINT n_qubits) { +void run_random_gate_apply(std::uint64_t n_qubits) { const int dim = 1ULL << n_qubits; Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); @@ -40,8 +40,8 @@ void run_random_gate_apply(UINT n_qubits) { } } -template &)> -void run_random_gate_apply(UINT n_qubits) { +template &)> +void run_random_gate_apply(std::uint64_t n_qubits) { const int dim = 1ULL << n_qubits; Random random; @@ -66,8 +66,9 @@ void run_random_gate_apply(UINT n_qubits) { } } -template &)> -void run_random_gate_apply(UINT n_qubits, std::function matrix_factory) { +template &)> +void run_random_gate_apply(std::uint64_t n_qubits, + std::function matrix_factory) { const auto matrix = matrix_factory(); const int dim = 1ULL << n_qubits; Random random; @@ -80,7 +81,7 @@ void run_random_gate_apply(UINT n_qubits, std::function matr test_state[i] = state_cp[i]; } - const UINT target = random.int64() % n_qubits; + const std::uint64_t target = random.int64() % n_qubits; const Gate gate = QuantumGateConstructor(target, {}); gate->update_quantum_state(state); state_cp = state.get_amplitudes(); @@ -93,8 +94,9 @@ void run_random_gate_apply(UINT n_qubits, std::function matr } } -template &)> -void run_random_gate_apply(UINT n_qubits, std::function matrix_factory) { +template &)> +void run_random_gate_apply(std::uint64_t n_qubits, + std::function matrix_factory) { const int dim = 1ULL << n_qubits; Random random; @@ -108,7 +110,7 @@ void run_random_gate_apply(UINT n_qubits, std::functionupdate_quantum_state(state); state_cp = state.get_amplitudes(); @@ -122,7 +124,8 @@ void run_random_gate_apply(UINT n_qubits, std::function matrix_factory) { + std::uint64_t n_qubits, + std::function matrix_factory) { const int dim = 1ULL << n_qubits; Random random; @@ -145,7 +148,7 @@ void run_random_gate_apply_IBMQ( theta = M_PI / 2; } const auto matrix = matrix_factory(theta, phi, lambda); - const UINT target = random.int64() % n_qubits; + const std::uint64_t target = random.int64() % n_qubits; Gate gate; if (gate_type == 0) { gate = gate::U1(target, lambda, {}); @@ -167,12 +170,12 @@ void run_random_gate_apply_IBMQ( } } -void run_random_gate_apply_two_target(UINT n_qubits) { +void run_random_gate_apply_two_target(std::uint64_t n_qubits) { const int dim = 1ULL << n_qubits; Random random; Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); - std::function func_eig; + std::function func_eig; for (int repeat = 0; repeat < 10; repeat++) { auto state = StateVector::Haar_random_state(n_qubits); for (int g = 0; g < 2; g++) { @@ -182,8 +185,8 @@ void run_random_gate_apply_two_target(UINT n_qubits) { test_state[i] = state_cp[i]; } - UINT target = random.int64() % n_qubits; - UINT control = random.int64() % n_qubits; + std::uint64_t target = random.int64() % n_qubits; + std::uint64_t control = random.int64() % n_qubits; if (target == control) target = (target + 1) % n_qubits; if (g == 0) { gate = gate::CX(control, target); @@ -211,8 +214,8 @@ void run_random_gate_apply_two_target(UINT n_qubits) { test_state[i] = state_cp[i]; } - UINT target1 = random.int64() % n_qubits; - UINT target2 = random.int64() % n_qubits; + std::uint64_t target1 = random.int64() % n_qubits; + std::uint64_t target2 = random.int64() % n_qubits; if (target1 == target2) target1 = (target1 + 1) % n_qubits; auto gate = gate::Swap(target1, target2); gate->update_quantum_state(state); @@ -227,8 +230,8 @@ void run_random_gate_apply_two_target(UINT n_qubits) { } } -void run_random_gate_apply_pauli(UINT n_qubits) { - const UINT dim = 1ULL << n_qubits; +void run_random_gate_apply_pauli(std::uint64_t n_qubits) { + const std::uint64_t dim = 1ULL << n_qubits; Random random; Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); Eigen::MatrixXcd matrix; @@ -239,12 +242,12 @@ void run_random_gate_apply_pauli(UINT n_qubits) { auto state_cp = state.get_amplitudes(); auto state_bef = state.copy(); - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { test_state[i] = state_cp[i]; } - std::vector target_vec, pauli_id_vec; - for (UINT target = 0; target < n_qubits; target++) { + std::vector target_vec, pauli_id_vec; + for (std::uint64_t target = 0; target < n_qubits; target++) { target_vec.emplace_back(target); pauli_id_vec.emplace_back(random.int64() % 4); } @@ -278,7 +281,7 @@ void run_random_gate_apply_pauli(UINT n_qubits) { test_state = matrix * test_state; // check if the state is updated correctly - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { ASSERT_NEAR(std::abs((CComplex)state_cp[i] - test_state[i]), 0, eps); } @@ -288,7 +291,7 @@ void run_random_gate_apply_pauli(UINT n_qubits) { state_cp = state.get_amplitudes(); // check if the state is restored correctly - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { ASSERT_NEAR(std::abs((CComplex)(state_cp[i] - state_bef_cp[i])), 0, eps); } } @@ -299,12 +302,12 @@ void run_random_gate_apply_pauli(UINT n_qubits) { auto state_cp = state.get_amplitudes(); auto state_bef = state.copy(); assert(test_state.size() == (int)state_cp.size()); - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { test_state[i] = state_cp[i]; } const double angle = M_PI * random.uniform(); - std::vector target_vec, pauli_id_vec; - for (UINT target = 0; target < n_qubits; target++) { + std::vector target_vec, pauli_id_vec; + for (std::uint64_t target = 0; target < n_qubits; target++) { target_vec.emplace_back(target); pauli_id_vec.emplace_back(random.int64() % 4); } @@ -338,7 +341,7 @@ void run_random_gate_apply_pauli(UINT n_qubits) { test_state = matrix * test_state; assert((int)state_cp.size() == test_state.size()); // check if the state is updated correctly - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { ASSERT_NEAR(std::abs((CComplex)state_cp[i] - test_state[i]), 0, eps); } Gate pauli_gate_inv = pauli_gate->get_inverse(); @@ -346,7 +349,7 @@ void run_random_gate_apply_pauli(UINT n_qubits) { state_cp = state.get_amplitudes(); auto state_bef_cp = state_bef.get_amplitudes(); // check if the state is restored correctly - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { ASSERT_NEAR(std::abs((CComplex)(state_cp[i] - state_bef_cp[i])), 0, eps); } } @@ -380,12 +383,12 @@ TEST(GateTest, ApplyPauliGate) { run_random_gate_apply_pauli(5); } TEST(GateTest, ApplyProbablisticGate) { auto probgate = gate::Probablistic({.1, .9}, {gate::X(0), gate::I()}); - UINT x_cnt = 0, i_cnt = 0; + std::uint64_t x_cnt = 0, i_cnt = 0; StateVector state(1); for ([[maybe_unused]] auto _ : std::views::iota(0, 100)) { - UINT before = state.sampling(1)[0]; + std::uint64_t before = state.sampling(1)[0]; probgate->update_quantum_state(state); - UINT after = state.sampling(1)[0]; + std::uint64_t after = state.sampling(1)[0]; if (before != after) { x_cnt++; } else { diff --git a/tests/gate/merge_test.cpp b/tests/gate/merge_test.cpp index 96e768d3..590f36de 100644 --- a/tests/gate/merge_test.cpp +++ b/tests/gate/merge_test.cpp @@ -14,7 +14,7 @@ using namespace scaluq; TEST(GateTest, MergeGate) { std::vector gates; Random random; - for (UINT target = 0; target < 2; target++) { + for (std::uint64_t target = 0; target < 2; target++) { gates.push_back(gate::X(target)); gates.push_back(gate::Y(target)); gates.push_back(gate::Z(target)); @@ -80,7 +80,7 @@ TEST(GateTest, MergeGate) { gate::PauliRotation(PauliOperator("Z 1", random.uniform()), random.uniform() * PI() * 2)); for (auto&& g1 : gates) { for (auto&& g2 : gates) { - UINT n = 2; + std::uint64_t n = 2; auto state1 = StateVector::Haar_random_state(n); auto state2 = state1.copy(); auto [mg, phase] = merge_gate(g1, g2); diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index 0b11e8ac..9a7fed63 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -13,10 +13,10 @@ using namespace scaluq; const auto eps = 1e-12; template -void test_apply_parametric_single_pauli_rotation(UINT n_qubits, +void test_apply_parametric_single_pauli_rotation(std::uint64_t n_qubits, FactoryFixed factory_fixed, FactoryParametric factory_parametric) { - const UINT dim = 1ULL << n_qubits; + const std::uint64_t dim = 1ULL << n_qubits; Random random; for (int repeat = 0; repeat < 10; repeat++) { @@ -24,7 +24,7 @@ void test_apply_parametric_single_pauli_rotation(UINT n_qubits, auto state_cp = state.copy(); auto state_bef = state.copy(); - const UINT target = random.int32() % n_qubits; + const std::uint64_t target = random.int32() % n_qubits; const double param = M_PI * random.uniform(); const double pcoef = random.uniform() * 2 - 1; const Gate gate = factory_fixed(target, pcoef * param, {}); @@ -34,7 +34,7 @@ void test_apply_parametric_single_pauli_rotation(UINT n_qubits, auto state_amp = state.get_amplitudes(); auto state_cp_amp = state_cp.get_amplitudes(); - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { ASSERT_NEAR(Kokkos::abs(state_cp_amp[i] - state_amp[i]), 0, eps); } @@ -42,14 +42,14 @@ void test_apply_parametric_single_pauli_rotation(UINT n_qubits, pgate_inv->update_quantum_state(state, param); state_amp = state.get_amplitudes(); auto state_bef_amp = state_bef.get_amplitudes(); - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { ASSERT_NEAR(Kokkos::abs(state_bef_amp[i] - state_amp[i]), 0, eps); } } } -void test_apply_parametric_multi_pauli_rotation(UINT n_qubits) { - const UINT dim = 1ULL << n_qubits; +void test_apply_parametric_multi_pauli_rotation(std::uint64_t n_qubits) { + const std::uint64_t dim = 1ULL << n_qubits; Random random; for (int repeat = 0; repeat < 10; repeat++) { @@ -58,8 +58,8 @@ void test_apply_parametric_multi_pauli_rotation(UINT n_qubits) { auto state_bef = state.copy(); const double param = M_PI * random.uniform(); const double pcoef = random.uniform() * 2 - 1; - std::vector target_vec, pauli_id_vec; - for (UINT target = 0; target < n_qubits; target++) { + std::vector target_vec, pauli_id_vec; + for (std::uint64_t target = 0; target < n_qubits; target++) { target_vec.emplace_back(target); pauli_id_vec.emplace_back(random.int64() % 4); } @@ -72,7 +72,7 @@ void test_apply_parametric_multi_pauli_rotation(UINT n_qubits) { auto state_amp = state.get_amplitudes(); auto state_cp_amp = state_cp.get_amplitudes(); // check if the state is updated correctly - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { ASSERT_NEAR(Kokkos::abs(state_cp_amp[i] - state_amp[i]), 0, eps); } ParamGate pgate_inv = pgate->get_inverse(); @@ -80,7 +80,7 @@ void test_apply_parametric_multi_pauli_rotation(UINT n_qubits) { state_amp = state.get_amplitudes(); auto state_bef_amp = state_bef.get_amplitudes(); // check if the state is restored correctly - for (UINT i = 0; i < dim; i++) { + for (std::uint64_t i = 0; i < dim; i++) { ASSERT_NEAR(Kokkos::abs((state_bef_amp[i] - state_amp[i])), 0, eps); } } @@ -99,12 +99,12 @@ TEST(ParamGateTest, ApplyPPauliRotationGate) { test_apply_parametric_multi_pauli TEST(ParamGateTest, ApplyPProbablisticGate) { auto probgate = gate::PProbablistic({.1, .9}, {gate::PRX(0), gate::I()}); - UINT x_cnt = 0, i_cnt = 0; + std::uint64_t x_cnt = 0, i_cnt = 0; StateVector state(1); for ([[maybe_unused]] auto _ : std::views::iota(0, 100)) { - UINT before = state.sampling(1)[0]; + std::uint64_t before = state.sampling(1)[0]; probgate->update_quantum_state(state, scaluq::PI()); - UINT after = state.sampling(1)[0]; + std::uint64_t after = state.sampling(1)[0]; if (before != after) { x_cnt++; } else { diff --git a/tests/operator/test_operator.cpp b/tests/operator/test_operator.cpp index 26d8f011..3dd17683 100644 --- a/tests/operator/test_operator.cpp +++ b/tests/operator/test_operator.cpp @@ -9,18 +9,18 @@ using namespace scaluq; const double eps = 1e-12; -std::pair generate_random_observable_with_eigen(UINT n, +std::pair generate_random_observable_with_eigen(std::uint64_t n, Random& random) { - UINT dim = 1ULL << n; + std::uint64_t dim = 1ULL << n; Operator rand_observable(n); Eigen::MatrixXcd test_rand_observable = Eigen::MatrixXcd::Zero(dim, dim); - UINT term_count = random.int32() % 10 + 1; - for (UINT term = 0; term < term_count; ++term) { - std::vector paulis(n, 0); + std::uint64_t term_count = random.int32() % 10 + 1; + for (std::uint64_t term = 0; term < term_count; ++term) { + std::vector paulis(n, 0); Eigen::MatrixXcd test_rand_operator_term = Eigen::MatrixXcd::Identity(dim, dim); double coef = random.uniform(); - for (UINT i = 0; i < paulis.size(); ++i) { + for (std::uint64_t i = 0; i < paulis.size(); ++i) { paulis[i] = random.int32() % 4; test_rand_operator_term *= get_expanded_eigen_matrix_with_identity( @@ -29,8 +29,8 @@ std::pair generate_random_observable_with_eigen(UINT test_rand_observable += coef * test_rand_operator_term; std::string str = ""; - for (UINT ind = 0; ind < paulis.size(); ind++) { - UINT val = paulis[ind]; + for (std::uint64_t ind = 0; ind < paulis.size(); ind++) { + std::uint64_t val = paulis[ind]; if (val != 0) { if (val == 1) str += " X"; @@ -47,18 +47,18 @@ std::pair generate_random_observable_with_eigen(UINT } TEST(OperatorTest, CheckExpectationValue) { - UINT n = 4; - UINT dim = 1ULL << n; + std::uint64_t n = 4; + std::uint64_t dim = 1ULL << n; Random random; - for (UINT repeat = 0; repeat < 10; ++repeat) { + for (std::uint64_t repeat = 0; repeat < 10; ++repeat) { auto [rand_observable, test_rand_observable] = generate_random_observable_with_eigen(n, random); auto state = StateVector::Haar_random_state(n); auto state_cp = state.get_amplitudes(); Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); - for (UINT i = 0; i < dim; ++i) test_state[i] = state_cp[i]; + for (std::uint64_t i = 0; i < dim; ++i) test_state[i] = state_cp[i]; Complex res = rand_observable.get_expectation_value(state); Complex test_res = (test_state.adjoint() * test_rand_observable * test_state)(0, 0); @@ -69,22 +69,22 @@ TEST(OperatorTest, CheckExpectationValue) { } TEST(OperatorTest, CheckTransitionAmplitude) { - UINT n = 4; - UINT dim = 1ULL << n; + std::uint64_t n = 4; + std::uint64_t dim = 1ULL << n; Random random; - for (UINT repeat = 0; repeat < 10; ++repeat) { + for (std::uint64_t repeat = 0; repeat < 10; ++repeat) { auto [rand_observable, test_rand_observable] = generate_random_observable_with_eigen(n, random); auto state_bra = StateVector::Haar_random_state(n); auto state_bra_cp = state_bra.get_amplitudes(); Eigen::VectorXcd test_state_bra = Eigen::VectorXcd::Zero(dim); - for (UINT i = 0; i < dim; ++i) test_state_bra[i] = state_bra_cp[i]; + for (std::uint64_t i = 0; i < dim; ++i) test_state_bra[i] = state_bra_cp[i]; auto state_ket = StateVector::Haar_random_state(n); auto state_ket_cp = state_ket.get_amplitudes(); Eigen::VectorXcd test_state_ket = Eigen::VectorXcd::Zero(dim); - for (UINT i = 0; i < dim; ++i) test_state_ket[i] = state_ket_cp[i]; + for (std::uint64_t i = 0; i < dim; ++i) test_state_ket[i] = state_ket_cp[i]; Complex res = rand_observable.get_transition_amplitude(state_bra, state_ket); Complex test_res = (test_state_bra.adjoint() * test_rand_observable * test_state_ket)(0, 0); @@ -94,10 +94,10 @@ TEST(OperatorTest, CheckTransitionAmplitude) { } TEST(OperatorTest, AddTest) { - UINT n = 4; + std::uint64_t n = 4; Random random; - for (UINT repeat = 0; repeat < 10; ++repeat) { + for (std::uint64_t repeat = 0; repeat < 10; ++repeat) { auto op1 = generate_random_observable_with_eigen(n, random).first; auto op2 = generate_random_observable_with_eigen(n, random).first; auto op = op1 + op2; @@ -110,10 +110,10 @@ TEST(OperatorTest, AddTest) { } TEST(OperatorTest, SubTest) { - UINT n = 4; + std::uint64_t n = 4; Random random; - for (UINT repeat = 0; repeat < 10; ++repeat) { + for (std::uint64_t repeat = 0; repeat < 10; ++repeat) { auto op1 = generate_random_observable_with_eigen(n, random).first; auto op2 = generate_random_observable_with_eigen(n, random).first; auto op = op1 - op2; @@ -126,10 +126,10 @@ TEST(OperatorTest, SubTest) { } TEST(OperatorTest, MultiCoefTest) { - UINT n = 4; + std::uint64_t n = 4; Random random; - for (UINT repeat = 0; repeat < 10; ++repeat) { + for (std::uint64_t repeat = 0; repeat < 10; ++repeat) { auto op1 = generate_random_observable_with_eigen(n, random).first; auto coef = Complex(random.normal(), random.normal()); auto op = op1 * coef; @@ -141,11 +141,11 @@ TEST(OperatorTest, MultiCoefTest) { } TEST(OperatorTest, ApplyToStateTest) { - const UINT n_qubits = 3; + const std::uint64_t n_qubits = 3; StateVector state_vector(n_qubits); state_vector.load([n_qubits] { std::vector tmp(1 << n_qubits); - for (UINT i = 0; i < tmp.size(); ++i) tmp[i] = Complex(i, 0); + for (std::uint64_t i = 0; i < tmp.size(); ++i) tmp[i] = Complex(i, 0); return tmp; }()); @@ -185,7 +185,7 @@ TEST(OperatorTest, Optimize) { std::ranges::sort(expected, [](const auto& l, const auto& r) { return l.first < r.first; }); std::ranges::sort(test, [](const auto& l, const auto& r) { return l.first < r.first; }); ASSERT_EQ(expected.size(), test.size()); - for (UINT i = 0; i < expected.size(); i++) { + for (std::uint64_t i = 0; i < expected.size(); i++) { ASSERT_EQ(expected[i].first, test[i].first); ASSERT_NEAR(Kokkos::abs(expected[i].second - test[i].second), 0, eps); } diff --git a/tests/operator/test_pauli_operator.cpp b/tests/operator/test_pauli_operator.cpp index 45a9a4f2..5d47d5e1 100644 --- a/tests/operator/test_pauli_operator.cpp +++ b/tests/operator/test_pauli_operator.cpp @@ -154,12 +154,12 @@ INSTANTIATE_TEST_CASE_P( PauliOperatorMultiplyTest, []() { double coef = 2.0; - UINT MAX_TERM = 100; + std::uint64_t MAX_TERM = 100; std::string pauli_string_x = ""; std::string pauli_string_y = ""; std::string pauli_string_z = ""; - for (UINT i = 0; i < MAX_TERM; i++) { + for (std::uint64_t i = 0; i < MAX_TERM; i++) { pauli_string_x += "X " + std::to_string(i); pauli_string_y += "Y " + std::to_string(i); pauli_string_z += "Z " + std::to_string(i); @@ -179,11 +179,11 @@ INSTANTIATE_TEST_CASE_P( testing::PrintToStringParamName()); TEST(PauliOperatorTest, ApplyToStateTest) { - const UINT n_qubits = 3; + const std::uint64_t n_qubits = 3; StateVector state_vector(n_qubits); state_vector.load([n_qubits] { std::vector tmp(1 << n_qubits); - for (UINT i = 0; i < tmp.size(); ++i) tmp[i] = Complex(i, 0); + for (std::uint64_t i = 0; i < tmp.size(); ++i) tmp[i] = Complex(i, 0); return tmp; }()); diff --git a/tests/state/state_vector_batched_test.cpp b/tests/state/state_vector_batched_test.cpp index 0d4a848e..1b202d8b 100644 --- a/tests/state/state_vector_batched_test.cpp +++ b/tests/state/state_vector_batched_test.cpp @@ -15,18 +15,18 @@ using namespace scaluq; const double eps = 1e-12; TEST(StateVectorBatchedTest, HaarRandomStateNorm) { - const UINT batch_size = 10, n_qubits = 3; + const std::uint64_t batch_size = 10, n_qubits = 3; const auto states = StateVectorBatched::Haar_random_states(batch_size, n_qubits, false); auto norms = states.get_squared_norm(); for (auto x : norms) ASSERT_NEAR(x, 1., eps); } TEST(StateVectorBatchedTest, LoadAndAmplitues) { - const UINT batch_size = 4, n_qubits = 3; - const UINT dim = 1 << n_qubits; + const std::uint64_t batch_size = 4, n_qubits = 3; + const std::uint64_t dim = 1 << n_qubits; std::vector states_h(batch_size, std::vector(dim)); - for (UINT b = 0; b < batch_size; ++b) { - for (UINT i = 0; i < dim; ++i) { + for (std::uint64_t b = 0; b < batch_size; ++b) { + for (std::uint64_t i = 0; i < dim; ++i) { states_h[b][i] = b * dim + i; } } @@ -34,26 +34,26 @@ TEST(StateVectorBatchedTest, LoadAndAmplitues) { states.load(states_h); auto amps = states.get_amplitudes(); - for (UINT b = 0; b < batch_size; ++b) { - for (UINT i = 0; i < dim; ++i) { + for (std::uint64_t b = 0; b < batch_size; ++b) { + for (std::uint64_t i = 0; i < dim; ++i) { ASSERT_EQ(amps[b][i].real(), b * dim + i); } } } TEST(StateVectorBatchedTest, OperateState) { - const UINT batch_size = 4, n_qubits = 3; + const std::uint64_t batch_size = 4, n_qubits = 3; auto states = StateVectorBatched::Haar_random_states(batch_size, n_qubits, 0); auto states_add = StateVectorBatched::Haar_random_states(batch_size, n_qubits, false); const Complex coef(2.1, 3.5); auto states_cp = states.copy(); - for (UINT b = 0; b < batch_size; ++b) { + for (std::uint64_t b = 0; b < batch_size; ++b) { ASSERT_TRUE(same_state(states.get_state_vector(b), states_cp.get_state_vector(b))); } states.add_state_vector(states_add); - for (UINT b = 0; b < batch_size; ++b) { + for (std::uint64_t b = 0; b < batch_size; ++b) { auto v = states_cp.get_state_vector(b); v.add_state_vector(states_add.get_state_vector(b)); ASSERT_TRUE(same_state(v, states.get_state_vector(b))); @@ -61,7 +61,7 @@ TEST(StateVectorBatchedTest, OperateState) { states_cp = states.copy(); states.add_state_vector_with_coef(coef, states_add); - for (UINT b = 0; b < batch_size; ++b) { + for (std::uint64_t b = 0; b < batch_size; ++b) { auto v = states_cp.get_state_vector(b); v.add_state_vector_with_coef(coef, states_add.get_state_vector(b)); ASSERT_TRUE(same_state(v, states.get_state_vector(b))); @@ -69,7 +69,7 @@ TEST(StateVectorBatchedTest, OperateState) { states_cp = states.copy(); states.multiply_coef(coef); - for (UINT b = 0; b < batch_size; ++b) { + for (std::uint64_t b = 0; b < batch_size; ++b) { auto v = states_cp.get_state_vector(b); v.multiply_coef(coef); ASSERT_TRUE(same_state(v, states.get_state_vector(b))); @@ -77,12 +77,12 @@ TEST(StateVectorBatchedTest, OperateState) { } TEST(StateVectorBatchedTest, ZeroProbs) { - const UINT batch_size = 4, n_qubits = 3; + const std::uint64_t batch_size = 4, n_qubits = 3; auto states = StateVectorBatched::Haar_random_states(batch_size, n_qubits, false); - for (UINT i = 0; i < n_qubits; ++i) { + for (std::uint64_t i = 0; i < n_qubits; ++i) { auto zero_probs = states.get_zero_probability(i); - for (UINT b = 0; b < batch_size; ++b) { + for (std::uint64_t b = 0; b < batch_size; ++b) { auto state = states.get_state_vector(b); ASSERT_NEAR(zero_probs[b], state.get_zero_probability(i), eps); } @@ -90,17 +90,17 @@ TEST(StateVectorBatchedTest, ZeroProbs) { } TEST(StateVectorBatchedTest, MarginalProbs) { - const UINT batch_size = 4, n_qubits = 5; + const std::uint64_t batch_size = 4, n_qubits = 5; auto states = StateVectorBatched::Haar_random_states(batch_size, n_qubits, false); Random rd(0); - for (UINT i = 0; i < 10; ++i) { - std::vector targets; - for (UINT j = 0; j < n_qubits; ++j) { + for (std::uint64_t i = 0; i < 10; ++i) { + std::vector targets; + for (std::uint64_t j = 0; j < n_qubits; ++j) { targets.push_back(rd.int32() % 3); } auto mg_probs = states.get_marginal_probability(targets); - for (UINT b = 0; b < batch_size; ++b) { + for (std::uint64_t b = 0; b < batch_size; ++b) { auto state = states.get_state_vector(b); ASSERT_NEAR(mg_probs[b], state.get_marginal_probability(targets), eps); } @@ -108,25 +108,25 @@ TEST(StateVectorBatchedTest, MarginalProbs) { } TEST(StateVectorBatchedTest, Entropy) { - const UINT batch_size = 4, n_qubits = 3; + const std::uint64_t batch_size = 4, n_qubits = 3; auto states = StateVectorBatched::Haar_random_states(batch_size, n_qubits, false); auto entropies = states.get_entropy(); - for (UINT b = 0; b < batch_size; ++b) { + for (std::uint64_t b = 0; b < batch_size; ++b) { auto state = states.get_state_vector(b); ASSERT_NEAR(entropies[b], state.get_entropy(), eps); } } TEST(StateVectorBatchedTest, Sampling) { - const UINT batch_size = 2, n_qubits = 3; + const std::uint64_t batch_size = 2, n_qubits = 3; StateVectorBatched states(batch_size, n_qubits); states.load( std::vector>{{1, 4, 5, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 6, 4, 1}}); states.normalize(); auto result = states.sampling(4096); - std::vector cnt(2, std::vector(states.dim(), 0)); - for (UINT i = 0; i < 2; ++i) { + std::vector cnt(2, std::vector(states.dim(), 0)); + for (std::uint64_t i = 0; i < 2; ++i) { for (auto x : result[i]) { ++cnt[i][x]; } diff --git a/tests/state/state_vector_test.cpp b/tests/state/state_vector_test.cpp index a5bcdc2d..b7c16521 100644 --- a/tests/state/state_vector_test.cpp +++ b/tests/state/state_vector_test.cpp @@ -24,7 +24,7 @@ TEST(StateVectorTest, HaarRandomStateNorm) { TEST(StateVectorTest, OperationAtIndex) { auto state = StateVector::Haar_random_state(10); - for (UINT i = 0; i < state.dim(); ++i) { + for (std::uint64_t i = 0; i < state.dim(); ++i) { state.set_amplitude_at_index(i, 1); ASSERT_NEAR(state.get_amplitude_at_index(i).real(), 1, eps); ASSERT_NEAR(state.get_amplitude_at_index(i).imag(), 0., eps); @@ -41,25 +41,25 @@ TEST(StateVectorTest, CopyState) { } TEST(StateVectorTest, ZeroNormState) { - const UINT n = 5; + const std::uint64_t n = 5; StateVector state(StateVector::Haar_random_state(n)); state.set_zero_norm_state(); auto state_cp = state.get_amplitudes(); - for (UINT i = 0; i < state.dim(); ++i) { + for (std::uint64_t i = 0; i < state.dim(); ++i) { ASSERT_EQ((CComplex)state_cp[i], CComplex(0, 0)); } } TEST(StateVectorTest, ComputationalBasisState) { - const UINT n = 5; + const std::uint64_t n = 5; StateVector state(StateVector::Haar_random_state(n)); state.set_computational_basis(31); auto state_cp = state.get_amplitudes(); - for (UINT i = 0; i < state.dim(); ++i) { + for (std::uint64_t i = 0; i < state.dim(); ++i) { if (i == 31) { ASSERT_EQ((CComplex)state_cp[i], CComplex(1, 0)); } else { @@ -69,8 +69,8 @@ TEST(StateVectorTest, ComputationalBasisState) { } TEST(StateVectorTest, HaarRandomStateSameSeed) { - const UINT n = 10, m = 5; - for (UINT i = 0; i < m; ++i) { + const std::uint64_t n = 10, m = 5; + for (std::uint64_t i = 0; i < m; ++i) { StateVector state1(StateVector::Haar_random_state(n, i)), state2(StateVector::Haar_random_state(n, i)); ASSERT_TRUE(same_state(state1, state2)); @@ -78,8 +78,8 @@ TEST(StateVectorTest, HaarRandomStateSameSeed) { } TEST(StateVectorTest, HaarRandomStateWithoutSeed) { - const UINT n = 10, m = 5; - for (UINT i = 0; i < m; ++i) { + const std::uint64_t n = 10, m = 5; + for (std::uint64_t i = 0; i < m; ++i) { StateVector state1(StateVector::Haar_random_state(n)), state2(StateVector::Haar_random_state(n)); ASSERT_FALSE(same_state(state1, state2)); @@ -87,7 +87,7 @@ TEST(StateVectorTest, HaarRandomStateWithoutSeed) { } TEST(StateVectorTest, AddState) { - const UINT n = 10; + const std::uint64_t n = 10; StateVector state1(StateVector::Haar_random_state(n)); StateVector state2(StateVector::Haar_random_state(n)); auto vec1 = state1.get_amplitudes(); @@ -95,7 +95,7 @@ TEST(StateVectorTest, AddState) { state1.add_state_vector(state2); auto new_vec = state1.get_amplitudes(); - for (UINT i = 0; i < state1.dim(); ++i) { + for (std::uint64_t i = 0; i < state1.dim(); ++i) { CComplex res = new_vec[i], val = (CComplex)vec1[i] + (CComplex)vec2[i]; ASSERT_NEAR(res.real(), val.real(), eps); ASSERT_NEAR(res.imag(), val.imag(), eps); @@ -104,7 +104,7 @@ TEST(StateVectorTest, AddState) { TEST(StateVectorTest, AddStateWithCoef) { const CComplex coef(2.5, 1.3); - const UINT n = 10; + const std::uint64_t n = 10; StateVector state1(StateVector::Haar_random_state(n)); StateVector state2(StateVector::Haar_random_state(n)); auto vec1 = state1.get_amplitudes(); @@ -113,7 +113,7 @@ TEST(StateVectorTest, AddStateWithCoef) { state1.add_state_vector_with_coef(coef, state2); auto new_vec = state1.get_amplitudes(); - for (UINT i = 0; i < state1.dim(); ++i) { + for (std::uint64_t i = 0; i < state1.dim(); ++i) { CComplex res = new_vec[i], val = (CComplex)vec1[i] + coef * (CComplex)vec2[i]; ASSERT_NEAR(res.real(), val.real(), eps); ASSERT_NEAR(res.imag(), val.imag(), eps); @@ -121,7 +121,7 @@ TEST(StateVectorTest, AddStateWithCoef) { } TEST(StateVectorTest, MultiplyCoef) { - const UINT n = 10; + const std::uint64_t n = 10; const CComplex coef(0.5, 0.2); StateVector state(StateVector::Haar_random_state(n)); @@ -129,7 +129,7 @@ TEST(StateVectorTest, MultiplyCoef) { state.multiply_coef(coef); auto new_vec = state.get_amplitudes(); - for (UINT i = 0; i < state.dim(); ++i) { + for (std::uint64_t i = 0; i < state.dim(); ++i) { CComplex res = new_vec[i], val = coef * (CComplex)vec[i]; ASSERT_NEAR(res.real(), val.real(), eps); ASSERT_NEAR(res.imag(), val.imag(), eps); @@ -137,10 +137,10 @@ TEST(StateVectorTest, MultiplyCoef) { } TEST(StateVectorTest, GetZeroProbability) { - const UINT n = 10; + const std::uint64_t n = 10; StateVector state(n); state.set_computational_basis(1); - for (UINT i = 2; i <= 10; ++i) { + for (std::uint64_t i = 2; i <= 10; ++i) { StateVector tmp_state(n); tmp_state.set_computational_basis(i); state.add_state_vector_with_coef(std::sqrt(i), tmp_state); @@ -153,21 +153,21 @@ TEST(StateVectorTest, GetZeroProbability) { } TEST(StateVectorTest, EntropyCalculation) { - const UINT n = 6; - const UINT dim = 1ULL << n; - const UINT max_repeat = 10; + const std::uint64_t n = 6; + const std::uint64_t dim = 1ULL << n; + const std::uint64_t max_repeat = 10; StateVector state(n); - for (UINT rep = 0; rep < max_repeat; ++rep) { + for (std::uint64_t rep = 0; rep < max_repeat; ++rep) { state = StateVector::Haar_random_state(n); auto state_cp = state.get_amplitudes(); ASSERT_NEAR(state.get_squared_norm(), 1, eps); Eigen::VectorXcd test_state(dim); - for (UINT i = 0; i < dim; ++i) test_state[i] = (CComplex)state_cp[i]; + for (std::uint64_t i = 0; i < dim; ++i) test_state[i] = (CComplex)state_cp[i]; - for (UINT target = 0; target < n; ++target) { + for (std::uint64_t target = 0; target < n; ++target) { double ent = 0; - for (UINT ind = 0; ind < dim; ++ind) { + for (std::uint64_t ind = 0; ind < dim; ++ind) { CComplex z = test_state[ind]; double prob = z.real() * z.real() + z.imag() * z.imag(); if (prob > eps) ent += -prob * log(prob); @@ -178,12 +178,12 @@ TEST(StateVectorTest, EntropyCalculation) { } TEST(StateVectorTest, GetMarginalProbability) { - const UINT n = 2; - const UINT dim = 1 << n; + const std::uint64_t n = 2; + const std::uint64_t dim = 1 << n; StateVector state(StateVector::Haar_random_state(n)); auto state_cp = state.get_amplitudes(); std::vector probs; - for (UINT i = 0; i < dim; ++i) { + for (std::uint64_t i = 0; i < dim; ++i) { probs.push_back(internal::squared_norm(state_cp[i])); } ASSERT_NEAR(state.get_marginal_probability({0, 0}), probs[0], eps); @@ -204,14 +204,14 @@ TEST(StateVectorTest, GetMarginalProbability) { } TEST(StateVectorTest, SamplingSuperpositionState) { - const UINT n = 10; - const UINT nshot = 65536; - const UINT test_count = 10; - UINT pass_count = 0; - for (UINT test_i = 0; test_i < test_count; test_i++) { + const std::uint64_t n = 10; + const std::uint64_t nshot = 65536; + const std::uint64_t test_count = 10; + std::uint64_t pass_count = 0; + for (std::uint64_t test_i = 0; test_i < test_count; test_i++) { StateVector state(n); state.set_computational_basis(0); - for (UINT i = 1; i <= 4; ++i) { + for (std::uint64_t i = 1; i <= 4; ++i) { StateVector tmp_state(n); tmp_state.set_computational_basis(i); state.add_state_vector_with_coef(1 << i, tmp_state); @@ -219,14 +219,14 @@ TEST(StateVectorTest, SamplingSuperpositionState) { state.normalize(); std::vector res = state.sampling(nshot); - std::array cnt = {}; - for (UINT i = 0; i < nshot; ++i) { + std::array cnt = {}; + for (std::uint64_t i = 0; i < nshot; ++i) { ASSERT_GE(res[i], 0); ASSERT_LE(res[i], 4); cnt[res[i]] += 1; } bool pass = true; - for (UINT i = 0; i < 4; i++) { + for (std::uint64_t i = 0; i < 4; i++) { std::string err_message = _CHECK_GT(cnt[i + 1], cnt[i]); if (err_message != "") { pass = false; @@ -239,12 +239,12 @@ TEST(StateVectorTest, SamplingSuperpositionState) { } TEST(StateVectorTest, SamplingComputationalBasis) { - const UINT n = 10; - const UINT nshot = 1024; + const std::uint64_t n = 10; + const std::uint64_t nshot = 1024; StateVector state(n); state.set_computational_basis(100); auto res = state.sampling(nshot); - for (UINT i = 0; i < nshot; ++i) { + for (std::uint64_t i = 0; i < nshot; ++i) { ASSERT_TRUE(res[i] == 100); } } diff --git a/tests/util/util.hpp b/tests/util/util.hpp index 73a7a433..45fe050a 100644 --- a/tests/util/util.hpp +++ b/tests/util/util.hpp @@ -13,7 +13,7 @@ inline bool same_state(const StateVector& s1, const StateVector& s2, const doubl auto s1_cp = s1.get_amplitudes(); auto s2_cp = s2.get_amplitudes(); assert(s1.n_qubits() == s2.n_qubits()); - for (UINT i = 0; i < s1.dim(); ++i) { + for (std::uint64_t i = 0; i < s1.dim(); ++i) { if (std::abs((std::complex)s1_cp[i] - (std::complex)s2_cp[i]) > eps) return false; } @@ -26,22 +26,22 @@ inline bool same_state_except_global_phase(const StateVector& s1, auto s1_cp = s1.get_amplitudes(); auto s2_cp = s2.get_amplitudes(); assert(s1.n_qubits() == s2.n_qubits()); - UINT significant = 0; - for (UINT i = 0; i < s1.dim(); ++i) { + std::uint64_t significant = 0; + for (std::uint64_t i = 0; i < s1.dim(); ++i) { if (std::abs((std::complex)s1_cp[i]) > std::abs((std::complex)s1_cp[significant])) { significant = i; } } if (std::abs((std::complex)s1_cp[significant]) < eps) { - for (UINT i = 0; i < s2.dim(); ++i) { + for (std::uint64_t i = 0; i < s2.dim(); ++i) { if (std::abs((std::complex)s2_cp[i]) > eps) return false; } return true; } double phase = std::arg(std::complex(s2_cp[significant] / s1_cp[significant])); std::complex phase_coef = std::polar(1., phase); - for (UINT i = 0; i < s1.dim(); ++i) { + for (std::uint64_t i = 0; i < s1.dim(); ++i) { if (std::abs(phase_coef * (std::complex)s1_cp[i] - (std::complex)s2_cp[i]) > eps) return false; @@ -51,8 +51,12 @@ inline bool same_state_except_global_phase(const StateVector& s1, #define _CHECK_GT(val1, val2) _check_gt(val1, val2, #val1, #val2, __FILE__, __LINE__) template -inline std::string _check_gt( - T val1, T val2, std::string val1_name, std::string val2_name, std::string file, UINT line) { +inline std::string _check_gt(T val1, + T val2, + std::string val1_name, + std::string val2_name, + std::string file, + std::uint64_t line) { if (val1 > val2) return ""; std::stringstream error_message_stream; error_message_stream << file << ":" << line << ": Failure\n" @@ -62,7 +66,7 @@ inline std::string _check_gt( } // obtain single dense matrix -inline Eigen::MatrixXcd get_eigen_matrix_single_Pauli(UINT pauli_id) { +inline Eigen::MatrixXcd get_eigen_matrix_single_Pauli(std::uint64_t pauli_id) { Eigen::MatrixXcd mat(2, 2); if (pauli_id == 0) mat << 1, 0, 0, 1; @@ -94,11 +98,12 @@ inline Eigen::MatrixXcd get_eigen_matrix_random_one_target_unitary() { zcoef /= norm; return icoef * Identity + 1.i * xcoef * X + 1.i * ycoef * Y + 1.i * zcoef * Z; } -inline Eigen::VectorXcd get_eigen_diagonal_matrix_random_multi_qubit_unitary(UINT qubit_count) { - UINT dim = (1ULL) << qubit_count; +inline Eigen::VectorXcd get_eigen_diagonal_matrix_random_multi_qubit_unitary( + std::uint64_t qubit_count) { + std::uint64_t dim = (1ULL) << qubit_count; auto vec = Eigen::VectorXcd(dim); Random random; - for (UINT i = 0; i < dim; ++i) { + for (std::uint64_t i = 0; i < dim; ++i) { double angle = random.uniform() * 2 * 3.14159; vec[i] = std::cos(angle) + 1.i * std::sin(angle); } @@ -106,9 +111,11 @@ inline Eigen::VectorXcd get_eigen_diagonal_matrix_random_multi_qubit_unitary(UIN } inline Eigen::MatrixXcd get_expanded_eigen_matrix_with_identity( - UINT target_qubit_index, const Eigen::MatrixXcd& one_target_matrix, UINT qubit_count) { - const UINT left_dim = 1ULL << target_qubit_index; - const UINT right_dim = 1ULL << (qubit_count - target_qubit_index - 1); + std::uint64_t target_qubit_index, + const Eigen::MatrixXcd& one_target_matrix, + std::uint64_t qubit_count) { + const std::uint64_t left_dim = 1ULL << target_qubit_index; + const std::uint64_t right_dim = 1ULL << (qubit_count - target_qubit_index - 1); auto left_identity = Eigen::MatrixXcd::Identity(left_dim, left_dim); auto right_identity = Eigen::MatrixXcd::Identity(right_dim, right_dim); return internal::kronecker_product( @@ -116,29 +123,29 @@ inline Eigen::MatrixXcd get_expanded_eigen_matrix_with_identity( } // get expanded matrix -inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_pauli(std::vector pauli_ids) { +inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_pauli(std::vector pauli_ids) { Eigen::MatrixXcd result = Eigen::MatrixXcd::Identity(1, 1); - for (UINT i = 0; i < pauli_ids.size(); ++i) { + for (std::uint64_t i = 0; i < pauli_ids.size(); ++i) { result = internal::kronecker_product(get_eigen_matrix_single_Pauli(pauli_ids[i]), result).eval(); } return result; } -inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_pauli(std::vector index_list, - std::vector pauli_list, - UINT qubit_count) { - std::vector whole_pauli_ids(qubit_count, 0); - for (UINT i = 0; i < index_list.size(); ++i) { +inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_pauli(std::vector index_list, + std::vector pauli_list, + std::uint64_t qubit_count) { + std::vector whole_pauli_ids(qubit_count, 0); + for (std::uint64_t i = 0; i < index_list.size(); ++i) { whole_pauli_ids[index_list[i]] = pauli_list[i]; } return get_eigen_matrix_full_qubit_pauli(whole_pauli_ids); } -inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_CX(UINT control_qubit_index, - UINT target_qubit_index, - UINT qubit_count) { - UINT dim = 1ULL << qubit_count; +inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_CX(std::uint64_t control_qubit_index, + std::uint64_t target_qubit_index, + std::uint64_t qubit_count) { + std::uint64_t dim = 1ULL << qubit_count; Eigen::MatrixXcd result = Eigen::MatrixXcd::Zero(dim, dim); - for (UINT ind = 0; ind < dim; ++ind) { + for (std::uint64_t ind = 0; ind < dim; ++ind) { if (ind & (1ULL << control_qubit_index)) { result(ind, ind ^ (1ULL << target_qubit_index)) = 1; } else { @@ -147,12 +154,12 @@ inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_CX(UINT control_qubit_index, } return result; } -inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_CZ(UINT control_qubit_index, - UINT target_qubit_index, - UINT qubit_count) { - UINT dim = 1ULL << qubit_count; +inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_CZ(std::uint64_t control_qubit_index, + std::uint64_t target_qubit_index, + std::uint64_t qubit_count) { + std::uint64_t dim = 1ULL << qubit_count; Eigen::MatrixXcd result = Eigen::MatrixXcd::Zero(dim, dim); - for (UINT ind = 0; ind < dim; ++ind) { + for (std::uint64_t ind = 0; ind < dim; ++ind) { if ((ind & (1ULL << control_qubit_index)) != 0 && (ind & (1ULL << target_qubit_index)) != 0) { result(ind, ind) = -1; @@ -162,12 +169,12 @@ inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_CZ(UINT control_qubit_index, } return result; } -inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_Swap(UINT target_qubit_index1, - UINT target_qubit_index2, - UINT qubit_count) { - UINT dim = 1ULL << qubit_count; +inline Eigen::MatrixXcd get_eigen_matrix_full_qubit_Swap(std::uint64_t target_qubit_index1, + std::uint64_t target_qubit_index2, + std::uint64_t qubit_count) { + std::uint64_t dim = 1ULL << qubit_count; Eigen::MatrixXcd result = Eigen::MatrixXcd::Zero(dim, dim); - for (UINT ind = 0; ind < dim; ++ind) { + for (std::uint64_t ind = 0; ind < dim; ++ind) { bool flag1, flag2; flag1 = (ind & (1ULL << target_qubit_index1)) != 0; flag2 = (ind & (1ULL << target_qubit_index2)) != 0; From b216ee1b1a90eb11260ad327baa564f88370911a Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 3 Sep 2024 00:27:34 +0000 Subject: [PATCH 35/55] changed method name --- python/binding.cpp | 18 ++++++++--------- scaluq/circuit/circuit.hpp | 6 +++--- scaluq/state/state_vector.cpp | 8 ++++---- scaluq/state/state_vector.hpp | 4 ++-- scaluq/state/state_vector_batched.cpp | 2 +- scaluq/state/state_vector_batched.hpp | 2 +- tests/state/state_vector_batched_test.cpp | 24 +++++++++++------------ tests/state/state_vector_test.cpp | 6 +++--- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/python/binding.cpp b/python/binding.cpp index ba183a4c..b579bcfd 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -105,11 +105,11 @@ NB_MODULE(scaluq_core, m) { "seed"_a = std::nullopt, "Constructing state vector with Haar random state. If seed is not specified, the value " "from random device is used.") - .def("set_amplitude_at_index", - &StateVector::set_amplitude_at_index, + .def("set_amplitude_at", + &StateVector::set_amplitude_at, "Manually set amplitude at one index.") - .def("get_amplitude_at_index", - &StateVector::get_amplitude_at_index, + .def("get_amplitude_at", + &StateVector::get_amplitude_at, "Get amplitude at one index.\n\n.. note:: If you want to get all amplitudes, you " "should " "use `StateVector::get_amplitudes()`.") @@ -197,8 +197,8 @@ NB_MODULE(scaluq_core, m) { nb::overload_cast( &StateVectorBatched::set_state_vector), "Set the state vector for a specific batch.") - .def("get_state_vector", - &StateVectorBatched::get_state_vector, + .def("get_state_vector_at", + &StateVectorBatched::get_state_vector_at, "Get the state vector for a specific batch.") .def("set_zero_state", &StateVectorBatched::set_zero_state, @@ -695,9 +695,9 @@ NB_MODULE(scaluq_core, m) { nb::rv_policy::reference) .def("n_gates", &Circuit::n_gates, "Get property of `n_gates`.") .def("key_set", &Circuit::key_set, "Get set of keys of parameters.") - .def("get", &Circuit::get, "Get reference of i-th gate.") - .def("get_key", - &Circuit::get_key, + .def("get_gate_at", &Circuit::get_gate_at, "Get reference of i-th gate.") + .def("get_param_key_at", + &Circuit::get_param_key_at, "Get parameter key of i-th gate. If it is not parametric, return None.") .def("calculate_depth", &Circuit::calculate_depth, "Get depth of circuit.") .def("add_gate", diff --git a/scaluq/circuit/circuit.hpp b/scaluq/circuit/circuit.hpp index eb9a5899..21a21768 100644 --- a/scaluq/circuit/circuit.hpp +++ b/scaluq/circuit/circuit.hpp @@ -23,13 +23,13 @@ class Circuit { } return key_set; } - [[nodiscard]] inline const GateWithKey& get(std::uint64_t idx) const { + [[nodiscard]] inline const GateWithKey& get_gate_at(std::uint64_t idx) const { if (idx >= _gate_list.size()) { - throw std::runtime_error("Circuit::get(std::uint64_t): index out of bounds"); + throw std::runtime_error("Circuit::get_gate_at(std::uint64_t): index out of bounds"); } return _gate_list[idx]; } - [[nodiscard]] inline std::optional get_key(std::uint64_t idx) { + [[nodiscard]] inline std::optional get_param_key_at(std::uint64_t idx) { if (idx >= _gate_list.size()) { throw std::runtime_error( "Circuit::get_parameter_key(std::uint64_t): index out of bounds"); diff --git a/scaluq/state/state_vector.cpp b/scaluq/state/state_vector.cpp index f9dd3d83..440c2419 100644 --- a/scaluq/state/state_vector.cpp +++ b/scaluq/state/state_vector.cpp @@ -12,13 +12,13 @@ StateVector::StateVector(std::uint64_t n_qubits) set_zero_state(); } -void StateVector::set_amplitude_at_index(std::uint64_t index, const Complex& c) { +void StateVector::set_amplitude_at(std::uint64_t index, const Complex& c) { Kokkos::View host_view("single_value"); host_view() = c; Kokkos::deep_copy(Kokkos::subview(_raw, index), host_view()); } -Complex StateVector::get_amplitude_at_index(std::uint64_t index) const { +Complex StateVector::get_amplitude_at(std::uint64_t index) const { Kokkos::View host_view("single_value"); Kokkos::deep_copy(host_view, Kokkos::subview(_raw, index)); return host_view(); @@ -26,7 +26,7 @@ Complex StateVector::get_amplitude_at_index(std::uint64_t index) const { void StateVector::set_zero_state() { Kokkos::deep_copy(_raw, 0); - set_amplitude_at_index(0, 1); + set_amplitude_at(0, 1); } void StateVector::set_zero_norm_state() { Kokkos::deep_copy(_raw, 0); } @@ -39,7 +39,7 @@ void StateVector::set_computational_basis(std::uint64_t basis) { "computational basis must be smaller than 2^qubit_count"); } Kokkos::deep_copy(_raw, 0); - set_amplitude_at_index(basis, 1); + set_amplitude_at(basis, 1); } StateVector StateVector::Haar_random_state(std::uint64_t n_qubits, std::uint64_t seed) { diff --git a/scaluq/state/state_vector.hpp b/scaluq/state/state_vector.hpp index a99bba42..e294ee68 100644 --- a/scaluq/state/state_vector.hpp +++ b/scaluq/state/state_vector.hpp @@ -25,12 +25,12 @@ class StateVector { /** * @attention Very slow. You should use load() instead if you can. */ - void set_amplitude_at_index(std::uint64_t index, const Complex& c); + void set_amplitude_at(std::uint64_t index, const Complex& c); /** * @attention Very slow. You should use get_amplitudes() instead if you can. */ - [[nodiscard]] Complex get_amplitude_at_index(std::uint64_t index) const; + [[nodiscard]] Complex get_amplitude_at(std::uint64_t index) const; [[nodiscard]] static StateVector Haar_random_state(std::uint64_t n_qubits, std::uint64_t seed = std::random_device()()); diff --git a/scaluq/state/state_vector_batched.cpp b/scaluq/state/state_vector_batched.cpp index d91d2452..f56fc861 100644 --- a/scaluq/state/state_vector_batched.cpp +++ b/scaluq/state/state_vector_batched.cpp @@ -38,7 +38,7 @@ void StateVectorBatched::set_state_vector(std::uint64_t batch_id, const StateVec Kokkos::fence(); } -StateVector StateVectorBatched::get_state_vector(std::uint64_t batch_id) const { +StateVector StateVectorBatched::get_state_vector_at(std::uint64_t batch_id) const { StateVector ret(_n_qubits); Kokkos::parallel_for( _dim, KOKKOS_CLASS_LAMBDA(std::uint64_t i) { ret._raw(i) = _raw(batch_id, i); }); diff --git a/scaluq/state/state_vector_batched.hpp b/scaluq/state/state_vector_batched.hpp index 5ab494f9..60127e3d 100644 --- a/scaluq/state/state_vector_batched.hpp +++ b/scaluq/state/state_vector_batched.hpp @@ -25,7 +25,7 @@ class StateVectorBatched { void set_state_vector(const StateVector& state); void set_state_vector(std::uint64_t batch_id, const StateVector& state); - [[nodiscard]] StateVector get_state_vector(std::uint64_t batch_id) const; + [[nodiscard]] StateVector get_state_vector_at(std::uint64_t batch_id) const; void set_zero_state(); void set_computational_basis(std::uint64_t basis); diff --git a/tests/state/state_vector_batched_test.cpp b/tests/state/state_vector_batched_test.cpp index 1b202d8b..354a555b 100644 --- a/tests/state/state_vector_batched_test.cpp +++ b/tests/state/state_vector_batched_test.cpp @@ -49,30 +49,30 @@ TEST(StateVectorBatchedTest, OperateState) { auto states_cp = states.copy(); for (std::uint64_t b = 0; b < batch_size; ++b) { - ASSERT_TRUE(same_state(states.get_state_vector(b), states_cp.get_state_vector(b))); + ASSERT_TRUE(same_state(states.get_state_vector_at(b), states_cp.get_state_vector_at(b))); } states.add_state_vector(states_add); for (std::uint64_t b = 0; b < batch_size; ++b) { - auto v = states_cp.get_state_vector(b); - v.add_state_vector(states_add.get_state_vector(b)); - ASSERT_TRUE(same_state(v, states.get_state_vector(b))); + auto v = states_cp.get_state_vector_at(b); + v.add_state_vector(states_add.get_state_vector_at(b)); + ASSERT_TRUE(same_state(v, states.get_state_vector_at(b))); } states_cp = states.copy(); states.add_state_vector_with_coef(coef, states_add); for (std::uint64_t b = 0; b < batch_size; ++b) { - auto v = states_cp.get_state_vector(b); - v.add_state_vector_with_coef(coef, states_add.get_state_vector(b)); - ASSERT_TRUE(same_state(v, states.get_state_vector(b))); + auto v = states_cp.get_state_vector_at(b); + v.add_state_vector_with_coef(coef, states_add.get_state_vector_at(b)); + ASSERT_TRUE(same_state(v, states.get_state_vector_at(b))); } states_cp = states.copy(); states.multiply_coef(coef); for (std::uint64_t b = 0; b < batch_size; ++b) { - auto v = states_cp.get_state_vector(b); + auto v = states_cp.get_state_vector_at(b); v.multiply_coef(coef); - ASSERT_TRUE(same_state(v, states.get_state_vector(b))); + ASSERT_TRUE(same_state(v, states.get_state_vector_at(b))); } } @@ -83,7 +83,7 @@ TEST(StateVectorBatchedTest, ZeroProbs) { for (std::uint64_t i = 0; i < n_qubits; ++i) { auto zero_probs = states.get_zero_probability(i); for (std::uint64_t b = 0; b < batch_size; ++b) { - auto state = states.get_state_vector(b); + auto state = states.get_state_vector_at(b); ASSERT_NEAR(zero_probs[b], state.get_zero_probability(i), eps); } } @@ -101,7 +101,7 @@ TEST(StateVectorBatchedTest, MarginalProbs) { } auto mg_probs = states.get_marginal_probability(targets); for (std::uint64_t b = 0; b < batch_size; ++b) { - auto state = states.get_state_vector(b); + auto state = states.get_state_vector_at(b); ASSERT_NEAR(mg_probs[b], state.get_marginal_probability(targets), eps); } } @@ -113,7 +113,7 @@ TEST(StateVectorBatchedTest, Entropy) { auto entropies = states.get_entropy(); for (std::uint64_t b = 0; b < batch_size; ++b) { - auto state = states.get_state_vector(b); + auto state = states.get_state_vector_at(b); ASSERT_NEAR(entropies[b], state.get_entropy(), eps); } } diff --git a/tests/state/state_vector_test.cpp b/tests/state/state_vector_test.cpp index b7c16521..e40356d1 100644 --- a/tests/state/state_vector_test.cpp +++ b/tests/state/state_vector_test.cpp @@ -25,9 +25,9 @@ TEST(StateVectorTest, HaarRandomStateNorm) { TEST(StateVectorTest, OperationAtIndex) { auto state = StateVector::Haar_random_state(10); for (std::uint64_t i = 0; i < state.dim(); ++i) { - state.set_amplitude_at_index(i, 1); - ASSERT_NEAR(state.get_amplitude_at_index(i).real(), 1, eps); - ASSERT_NEAR(state.get_amplitude_at_index(i).imag(), 0., eps); + state.set_amplitude_at(i, 1); + ASSERT_NEAR(state.get_amplitude_at(i).real(), 1, eps); + ASSERT_NEAR(state.get_amplitude_at(i).imag(), 0., eps); } } From 1128a80f5902bee35f2816c3986f87502068984d Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 3 Sep 2024 00:43:04 +0000 Subject: [PATCH 36/55] P -> Param --- python/binding.cpp | 74 ++++++++++++------------- scaluq/gate/param_gate.hpp | 26 ++++----- scaluq/gate/param_gate_factory.hpp | 48 ++++++++-------- scaluq/gate/param_gate_pauli.hpp | 14 ++--- scaluq/gate/param_gate_probablistic.hpp | 38 ++++++------- scaluq/gate/param_gate_standard.hpp | 18 +++--- tests/circuit/param_circuit_test.cpp | 14 ++--- tests/gate/param_gate_test.cpp | 30 +++++----- 8 files changed, 131 insertions(+), 131 deletions(-) diff --git a/python/binding.cpp b/python/binding.cpp index b579bcfd..812c0285 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -548,10 +548,10 @@ NB_MODULE(scaluq_core, m) { DEF_GATE_FACTORY(Probablistic); nb::enum_(m, "ParamGateType", "Enum of ParamGate Type.") - .value("PRX", ParamGateType::PRX) - .value("PRY", ParamGateType::PRY) - .value("PRZ", ParamGateType::PRZ) - .value("PPauliRotation", ParamGateType::PPauliRotation); + .value("ParamRX", ParamGateType::ParamRX) + .value("ParamRY", ParamGateType::ParamRY) + .value("ParamRZ", ParamGateType::ParamRZ) + .value("ParamPauliRotation", ParamGateType::ParamPauliRotation); m.def( "merge_gate", &merge_gate, "Merge two gates. return value is (merged gate, global phase)."); @@ -612,67 +612,67 @@ NB_MODULE(scaluq_core, m) { ParamGate, "General class of parametric quantum gate.\n\n.. note:: Downcast to requred to use " "gate-specific functions.") - .def(nb::init(), "Upcast from `PRXGate`.") - .def(nb::init(), "Upcast from `PRYGate`.") - .def(nb::init(), "Upcast from `PRZGate`.") - .def(nb::init(), "Upcast from `PPauliRotationGate`."); + .def(nb::init(), "Upcast from `ParamRXGate`.") + .def(nb::init(), "Upcast from `ParamRYGate`.") + .def(nb::init(), "Upcast from `ParamRZGate`.") + .def(nb::init(), "Upcast from `ParamPauliRotationGate`."); - DEF_PGATE(PRXGate, + DEF_PGATE(ParamRXGate, "Specific class of parametric X rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}X}$. `angle` is given as `param * pcoef`."); - DEF_PGATE(PRYGate, + "$e^{-i\\frac{\\mathrm{angle}}{2}X}$. `angle` is given as `param * param_coef`."); + DEF_PGATE(ParamRYGate, "Specific class of parametric Y rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}Y}$. `angle` is given as `param * pcoef`."); - DEF_PGATE(PRZGate, + "$e^{-i\\frac{\\mathrm{angle}}{2}Y}$. `angle` is given as `param * param_coef`."); + DEF_PGATE(ParamRZGate, "Specific class of parametric Z rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}Z}$. `angle` is given as `param * pcoef`."); + "$e^{-i\\frac{\\mathrm{angle}}{2}Z}$. `angle` is given as `param * param_coef`."); - DEF_PGATE(PPauliRotationGate, + DEF_PGATE(ParamPauliRotationGate, "Specific class of parametric multi-qubit pauli-rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}P}$. `angle` is given as `param * pcoef`."); + "$e^{-i\\frac{\\mathrm{angle}}{2}P}$. `angle` is given as `param * param_coef`."); - DEF_PGATE(PProbablisticGate, + DEF_PGATE(ParamProbablisticGate, "Specific class of parametric probablistic gate. The gate to apply is picked from a " "cirtain " "distribution.") .def( "gate_list", - [](const PProbablisticGate &gate) { return gate->gate_list(); }, + [](const ParamProbablisticGate &gate) { return gate->gate_list(); }, nb::rv_policy::reference) .def( "distribution", - [](const PProbablisticGate &gate) { return gate->distribution(); }, + [](const ParamProbablisticGate &gate) { return gate->distribution(); }, nb::rv_policy::reference); - mgate.def("PRX", - &gate::PRX, - "Generate general ParamGate class instance of PRX.", + mgate.def("ParamRX", + &gate::ParamRX, + "Generate general ParamGate class instance of ParamRX.", "target"_a, "coef"_a = 1., "controls"_a = std::vector{}); - mgate.def("PRY", - &gate::PRY, - "Generate general ParamGate class instance of PRY.", + mgate.def("ParamRY", + &gate::ParamRY, + "Generate general ParamGate class instance of ParamRY.", "target"_a, "coef"_a = 1., "controls"_a = std::vector{}); - mgate.def("PRZ", - &gate::PRZ, - "Generate general ParamGate class instance of PRZ.", + mgate.def("ParamRZ", + &gate::ParamRZ, + "Generate general ParamGate class instance of ParamRZ.", "target"_a, "coef"_a = 1., "controls"_a = std::vector{}); - mgate.def("PPauliRotation", - &gate::PPauliRotation, - "Generate general ParamGate class instance of PPauliRotation.", + mgate.def("ParamPauliRotation", + &gate::ParamPauliRotation, + "Generate general ParamGate class instance of ParamPauliRotation.", "pauli"_a, "coef"_a = 1., "controls"_a = std::vector{}); - mgate.def("PProbablistic", - &gate::PProbablistic, - "Generate general ParamGate class instance of PProbablistic."); + mgate.def("ParamProbablistic", + &gate::ParamProbablistic, + "Generate general ParamGate class instance of ParamProbablistic."); mgate.def( - "PProbablistic", + "ParamProbablistic", [](const std::vector>> &prob_gate_list) { std::vector distribution; std::vector> gate_list; @@ -682,9 +682,9 @@ NB_MODULE(scaluq_core, m) { distribution.push_back(prob); gate_list.push_back(gate); } - return gate::PProbablistic(distribution, gate_list); + return gate::ParamProbablistic(distribution, gate_list); }, - "Generate general ParamGate class instance of PProbablistic."); + "Generate general ParamGate class instance of ParamProbablistic."); nb::class_(m, "Circuit", "Quantum circuit represented as gate array") .def(nb::init(), "Initialize empty circuit of specified qubits.") diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index 01759eb6..edc159dd 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -12,26 +12,26 @@ class ParamGateBase; template concept ParamGateImpl = std::derived_from; -class PRXGateImpl; -class PRYGateImpl; -class PRZGateImpl; -class PPauliRotationGateImpl; +class ParamRXGateImpl; +class ParamRYGateImpl; +class ParamRZGateImpl; +class ParamPauliRotationGateImpl; template class ParamGatePtr; } // namespace internal using ParamGate = internal::ParamGatePtr; -enum class ParamGateType { Unknown, PRX, PRY, PRZ, PPauliRotation }; +enum class ParamGateType { Unknown, ParamRX, ParamRY, ParamRZ, ParamPauliRotation }; template constexpr ParamGateType get_param_gate_type() { if constexpr (std::is_same_v) return ParamGateType::Unknown; - if constexpr (std::is_same_v) return ParamGateType::PRX; - if constexpr (std::is_same_v) return ParamGateType::PRY; - if constexpr (std::is_same_v) return ParamGateType::PRZ; - if constexpr (std::is_same_v) - return ParamGateType::PPauliRotation; + if constexpr (std::is_same_v) return ParamGateType::ParamRX; + if constexpr (std::is_same_v) return ParamGateType::ParamRY; + if constexpr (std::is_same_v) return ParamGateType::ParamRZ; + if constexpr (std::is_same_v) + return ParamGateType::ParamPauliRotation; static_assert("unknown ParamGateImpl"); return ParamGateType::Unknown; } @@ -51,8 +51,8 @@ class ParamGateBase { } public: - ParamGateBase(std::uint64_t target_mask, std::uint64_t control_mask, double pcoef = 1.) - : _target_mask(target_mask), _control_mask(control_mask), _pcoef(pcoef) { + ParamGateBase(std::uint64_t target_mask, std::uint64_t control_mask, double param_coef = 1.) + : _target_mask(target_mask), _control_mask(control_mask), _pcoef(param_coef) { if (_target_mask & _control_mask) [[unlikely]] { throw std::runtime_error( "Error: ParamGate::ParamGate(std::uint64_t target_mask, std::uint64_t " @@ -62,7 +62,7 @@ class ParamGateBase { } virtual ~ParamGateBase() = default; - [[nodiscard]] double pcoef() { return _pcoef; } + [[nodiscard]] double param_coef() { return _pcoef; } [[nodiscard]] virtual std::vector target_qubit_list() const { return mask_to_vector(_target_mask); diff --git a/scaluq/gate/param_gate_factory.hpp b/scaluq/gate/param_gate_factory.hpp index cfbd3e2f..c76e0a9d 100644 --- a/scaluq/gate/param_gate_factory.hpp +++ b/scaluq/gate/param_gate_factory.hpp @@ -15,35 +15,35 @@ class ParamGateFactory { }; } // namespace internal namespace gate { -inline ParamGate PRX(std::uint64_t target, - double pcoef = 1., - const std::vector& controls = {}) { - return internal::ParamGateFactory::create_gate( - internal::vector_to_mask({target}), internal::vector_to_mask(controls), pcoef); +inline ParamGate ParamRX(std::uint64_t target, + double param_coef = 1., + const std::vector& controls = {}) { + return internal::ParamGateFactory::create_gate( + internal::vector_to_mask({target}), internal::vector_to_mask(controls), param_coef); } -inline ParamGate PRY(std::uint64_t target, - double pcoef = 1., - const std::vector& controls = {}) { - return internal::ParamGateFactory::create_gate( - internal::vector_to_mask({target}), internal::vector_to_mask(controls), pcoef); +inline ParamGate ParamRY(std::uint64_t target, + double param_coef = 1., + const std::vector& controls = {}) { + return internal::ParamGateFactory::create_gate( + internal::vector_to_mask({target}), internal::vector_to_mask(controls), param_coef); } -inline ParamGate PRZ(std::uint64_t target, - double pcoef = 1., - const std::vector& controls = {}) { - return internal::ParamGateFactory::create_gate( - internal::vector_to_mask({target}), internal::vector_to_mask(controls), pcoef); +inline ParamGate ParamRZ(std::uint64_t target, + double param_coef = 1., + const std::vector& controls = {}) { + return internal::ParamGateFactory::create_gate( + internal::vector_to_mask({target}), internal::vector_to_mask(controls), param_coef); } // まだ -inline ParamGate PPauliRotation(const PauliOperator& pauli, - double pcoef = 1., - const std::vector& controls = {}) { - return internal::ParamGateFactory::create_gate( - internal::vector_to_mask(controls), pauli, pcoef); +inline ParamGate ParamPauliRotation(const PauliOperator& pauli, + double param_coef = 1., + const std::vector& controls = {}) { + return internal::ParamGateFactory::create_gate( + internal::vector_to_mask(controls), pauli, param_coef); } -inline ParamGate PProbablistic(const std::vector& distribution, - const std::vector>& gate_list) { - return internal::ParamGateFactory::create_gate(distribution, - gate_list); +inline ParamGate ParamProbablistic(const std::vector& distribution, + const std::vector>& gate_list) { + return internal::ParamGateFactory::create_gate( + distribution, gate_list); } } // namespace gate } // namespace scaluq diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index bbbec583..f9f1d959 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -8,21 +8,21 @@ namespace scaluq { namespace internal { -class PPauliRotationGateImpl : public ParamGateBase { +class ParamPauliRotationGateImpl : public ParamGateBase { const PauliOperator _pauli; public: - PPauliRotationGateImpl(std::uint64_t control_mask, - const PauliOperator& pauli, - double pcoef = 1.) - : ParamGateBase(vector_to_mask(pauli.target_qubit_list()), control_mask, pcoef), + ParamPauliRotationGateImpl(std::uint64_t control_mask, + const PauliOperator& pauli, + double param_coef = 1.) + : ParamGateBase(vector_to_mask(pauli.target_qubit_list()), control_mask, param_coef), _pauli(pauli) {} PauliOperator pauli() const { return _pauli; } std::vector pauli_id_list() const { return _pauli.pauli_id_list(); } ParamGate get_inverse() const override { - return std::make_shared(_control_mask, _pauli, -_pcoef); + return std::make_shared(_control_mask, _pauli, -_pcoef); } ComplexMatrix get_matrix(double param) const override { double angle = _pcoef * param; @@ -40,5 +40,5 @@ class PPauliRotationGateImpl : public ParamGateBase { }; } // namespace internal -using PPauliRotationGate = internal::ParamGatePtr; +using ParamPauliRotationGate = internal::ParamGatePtr; } // namespace scaluq diff --git a/scaluq/gate/param_gate_probablistic.hpp b/scaluq/gate/param_gate_probablistic.hpp index 40355f3c..a6622299 100644 --- a/scaluq/gate/param_gate_probablistic.hpp +++ b/scaluq/gate/param_gate_probablistic.hpp @@ -8,15 +8,15 @@ namespace scaluq { namespace internal { -class PProbablisticGateImpl : public ParamGateBase { +class ParamProbablisticGateImpl : public ParamGateBase { using EitherGate = std::variant; std::vector _distribution; std::vector _cumlative_distribution; std::vector _gate_list; public: - PProbablisticGateImpl(const std::vector& distribution, - const std::vector>& gate_list) + ParamProbablisticGateImpl(const std::vector& distribution, + const std::vector>& gate_list) : ParamGateBase(0, 0), _distribution(distribution), _gate_list(gate_list) { std::uint64_t n = distribution.size(); if (n == 0) { @@ -37,33 +37,33 @@ class PProbablisticGateImpl : public ParamGateBase { std::vector target_qubit_list() const override { throw std::runtime_error( - "PProbablisticGateImpl::target_qubit_list(): This function must not be used in " - "PProbablisticGateImpl."); + "ParamProbablisticGateImpl::target_qubit_list(): This function must not be used in " + "ParamProbablisticGateImpl."); } std::vector control_qubit_list() const override { throw std::runtime_error( - "PProbablisticGateImpl::control_qubit_list(): This function must not be used in " - "PProbablisticGateImpl."); + "ParamProbablisticGateImpl::control_qubit_list(): This function must not be used in " + "ParamProbablisticGateImpl."); } std::vector operand_qubit_list() const override { throw std::runtime_error( - "PProbablisticGateImpl::operand_qubit_list(): This function must not be used in " - "PProbablisticGateImpl."); + "ParamProbablisticGateImpl::operand_qubit_list(): This function must not be used in " + "ParamProbablisticGateImpl."); } std::uint64_t target_qubit_mask() const override { throw std::runtime_error( - "PProbablisticGateImpl::target_qubit_mask(): This function must not be used in " - "PProbablisticGateImpl."); + "ParamProbablisticGateImpl::target_qubit_mask(): This function must not be used in " + "ParamProbablisticGateImpl."); } std::uint64_t control_qubit_mask() const override { throw std::runtime_error( - "PProbablisticGateImpl::control_qubit_mask(): This function must not be used in " - "PProbablisticGateImpl."); + "ParamProbablisticGateImpl::control_qubit_mask(): This function must not be used in " + "ParamProbablisticGateImpl."); } std::uint64_t operand_qubit_mask() const override { throw std::runtime_error( - "PProbablisticGateImpl::operand_qubit_mask(): This function must not be used in " - "PProbablisticGateImpl."); + "ParamProbablisticGateImpl::operand_qubit_mask(): This function must not be used in " + "ParamProbablisticGateImpl."); } ParamGate get_inverse() const override { @@ -73,12 +73,12 @@ class PProbablisticGateImpl : public ParamGateBase { _gate_list, std::back_inserter(inv_gate_list), [](const EitherGate& gate) { return std::visit([](const auto& g) { return EitherGate{g->get_inverse()}; }, gate); }); - return std::make_shared(_distribution, inv_gate_list); + return std::make_shared(_distribution, inv_gate_list); } ComplexMatrix get_matrix(double) const override { throw std::runtime_error( - "PProbablisticGateImpl::get_matrix(): This function must not be used in " - "PProbablisticGateImpl."); + "ParamProbablisticGateImpl::get_matrix(): This function must not be used in " + "ParamProbablisticGateImpl."); } void update_quantum_state(StateVector& state_vector, double param) const override { @@ -98,5 +98,5 @@ class PProbablisticGateImpl : public ParamGateBase { }; } // namespace internal -using PProbablisticGate = internal::ParamGatePtr; +using ParamProbablisticGate = internal::ParamGatePtr; } // namespace scaluq diff --git a/scaluq/gate/param_gate_standard.hpp b/scaluq/gate/param_gate_standard.hpp index cf12afae..23da71b4 100644 --- a/scaluq/gate/param_gate_standard.hpp +++ b/scaluq/gate/param_gate_standard.hpp @@ -8,12 +8,12 @@ namespace scaluq { namespace internal { -class PRXGateImpl : public ParamGateBase { +class ParamRXGateImpl : public ParamGateBase { public: using ParamGateBase::ParamGateBase; ParamGate get_inverse() const override { - return std::make_shared(_target_mask, _control_mask, -_pcoef); + return std::make_shared(_target_mask, _control_mask, -_pcoef); } ComplexMatrix get_matrix(double param) const override { double angle = _pcoef * param; @@ -29,12 +29,12 @@ class PRXGateImpl : public ParamGateBase { } }; -class PRYGateImpl : public ParamGateBase { +class ParamRYGateImpl : public ParamGateBase { public: using ParamGateBase::ParamGateBase; ParamGate get_inverse() const override { - return std::make_shared(_target_mask, _control_mask, -_pcoef); + return std::make_shared(_target_mask, _control_mask, -_pcoef); } ComplexMatrix get_matrix(double param) const override { double angle = _pcoef * param; @@ -49,12 +49,12 @@ class PRYGateImpl : public ParamGateBase { } }; -class PRZGateImpl : public ParamGateBase { +class ParamRZGateImpl : public ParamGateBase { public: using ParamGateBase::ParamGateBase; ParamGate get_inverse() const override { - return std::make_shared(_target_mask, _control_mask, -_pcoef); + return std::make_shared(_target_mask, _control_mask, -_pcoef); } ComplexMatrix get_matrix(double param) const override { double angle = param * _pcoef; @@ -71,8 +71,8 @@ class PRZGateImpl : public ParamGateBase { } // namespace internal -using PRXGate = internal::ParamGatePtr; -using PRYGate = internal::ParamGatePtr; -using PRZGate = internal::ParamGatePtr; +using ParamRXGate = internal::ParamGatePtr; +using ParamRYGate = internal::ParamGatePtr; +using ParamRZGate = internal::ParamGatePtr; } // namespace scaluq diff --git a/tests/circuit/param_circuit_test.cpp b/tests/circuit/param_circuit_test.cpp index 40f8b13f..b59e13c4 100644 --- a/tests/circuit/param_circuit_test.cpp +++ b/tests/circuit/param_circuit_test.cpp @@ -37,15 +37,15 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { if (param_gate_kind == 0) { std::uint64_t target = random.int32() % n_qubits; circuit.add_gate(gate::RX(target, coef * params[pidx])); - pcircuit.add_param_gate(gate::PRX(target, coef), pkeys[pidx]); + pcircuit.add_param_gate(gate::ParamRX(target, coef), pkeys[pidx]); } else if (param_gate_kind == 1) { std::uint64_t target = random.int32() % n_qubits; circuit.add_gate(gate::RY(target, coef * params[pidx])); - pcircuit.add_param_gate(gate::PRY(target, coef), pkeys[pidx]); + pcircuit.add_param_gate(gate::ParamRY(target, coef), pkeys[pidx]); } else if (param_gate_kind == 2) { std::uint64_t target = random.int32() % n_qubits; circuit.add_gate(gate::RZ(target, coef * params[pidx])); - pcircuit.add_param_gate(gate::PRZ(target, coef), pkeys[pidx]); + pcircuit.add_param_gate(gate::ParamRZ(target, coef), pkeys[pidx]); } else { std::vector target_vec, pauli_id_vec; for (std::uint64_t target = 0; target < n_qubits; target++) { @@ -54,7 +54,7 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { } PauliOperator pauli(target_vec, pauli_id_vec, 1.0); circuit.add_gate(gate::PauliRotation(pauli, coef * params[pidx])); - pcircuit.add_param_gate(gate::PPauliRotation(pauli, coef), pkeys[pidx]); + pcircuit.add_param_gate(gate::ParamPauliRotation(pauli, coef), pkeys[pidx]); } } else { std::uint64_t control = random.int32() % n_qubits; @@ -92,9 +92,9 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { TEST(ParamCircuitTest, InsufficientParameterGiven) { Circuit circuit(1); - circuit.add_param_gate(gate::PRX(0), "0"); - circuit.add_param_gate(gate::PRX(0), "1"); - circuit.add_param_gate(gate::PRX(0), "0"); + circuit.add_param_gate(gate::ParamRX(0), "0"); + circuit.add_param_gate(gate::ParamRX(0), "1"); + circuit.add_param_gate(gate::ParamRX(0), "0"); StateVector state(1); ASSERT_NO_THROW(circuit.update_quantum_state(state, {{"0", 0}, {"1", 0}})); ASSERT_NO_THROW(circuit.update_quantum_state(state, {{"0", 0}, {"1", 0}, {"2", 0}})); diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index 9a7fed63..383caf0e 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -26,9 +26,9 @@ void test_apply_parametric_single_pauli_rotation(std::uint64_t n_qubits, const std::uint64_t target = random.int32() % n_qubits; const double param = M_PI * random.uniform(); - const double pcoef = random.uniform() * 2 - 1; - const Gate gate = factory_fixed(target, pcoef * param, {}); - const ParamGate pgate = factory_parametric(target, pcoef, {}); + const double param_coef = random.uniform() * 2 - 1; + const Gate gate = factory_fixed(target, param_coef * param, {}); + const ParamGate pgate = factory_parametric(target, param_coef, {}); gate->update_quantum_state(state); pgate->update_quantum_state(state_cp, param); auto state_amp = state.get_amplitudes(); @@ -57,7 +57,7 @@ void test_apply_parametric_multi_pauli_rotation(std::uint64_t n_qubits) { auto state_cp = state.copy(); auto state_bef = state.copy(); const double param = M_PI * random.uniform(); - const double pcoef = random.uniform() * 2 - 1; + const double param_coef = random.uniform() * 2 - 1; std::vector target_vec, pauli_id_vec; for (std::uint64_t target = 0; target < n_qubits; target++) { target_vec.emplace_back(target); @@ -65,8 +65,8 @@ void test_apply_parametric_multi_pauli_rotation(std::uint64_t n_qubits) { } PauliOperator pauli(target_vec, pauli_id_vec, 1.0); - Gate gate = gate::PauliRotation(pauli, pcoef * param); - ParamGate pgate = gate::PPauliRotation(pauli, pcoef); + Gate gate = gate::PauliRotation(pauli, param_coef * param); + ParamGate pgate = gate::ParamPauliRotation(pauli, param_coef); gate->update_quantum_state(state); pgate->update_quantum_state(state_cp, param); auto state_amp = state.get_amplitudes(); @@ -86,19 +86,19 @@ void test_apply_parametric_multi_pauli_rotation(std::uint64_t n_qubits) { } } -TEST(ParamGateTest, ApplyPRXGate) { - test_apply_parametric_single_pauli_rotation(5, &gate::RX, &gate::PRX); +TEST(ParamGateTest, ApplyParamRXGate) { + test_apply_parametric_single_pauli_rotation(5, &gate::RX, &gate::ParamRX); } -TEST(ParamGateTest, ApplyPRYGate) { - test_apply_parametric_single_pauli_rotation(5, &gate::RX, &gate::PRX); +TEST(ParamGateTest, ApplyParamRYGate) { + test_apply_parametric_single_pauli_rotation(5, &gate::RX, &gate::ParamRX); } -TEST(ParamGateTest, ApplyPRZGate) { - test_apply_parametric_single_pauli_rotation(5, &gate::RX, &gate::PRX); +TEST(ParamGateTest, ApplyParamRZGate) { + test_apply_parametric_single_pauli_rotation(5, &gate::RX, &gate::ParamRX); } -TEST(ParamGateTest, ApplyPPauliRotationGate) { test_apply_parametric_multi_pauli_rotation(5); } +TEST(ParamGateTest, ApplyParamPauliRotationGate) { test_apply_parametric_multi_pauli_rotation(5); } -TEST(ParamGateTest, ApplyPProbablisticGate) { - auto probgate = gate::PProbablistic({.1, .9}, {gate::PRX(0), gate::I()}); +TEST(ParamGateTest, ApplyParamProbablisticGate) { + auto probgate = gate::ParamProbablistic({.1, .9}, {gate::ParamRX(0), gate::I()}); std::uint64_t x_cnt = 0, i_cnt = 0; StateVector state(1); for ([[maybe_unused]] auto _ : std::views::iota(0, 100)) { From 3c5bfd0b23a6a19dfa758513d815887e63628834 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Tue, 3 Sep 2024 09:43:49 +0900 Subject: [PATCH 37/55] format --- scaluq/operator/apply_pauli.cpp | 9 ++++++--- scaluq/operator/pauli_operator.hpp | 7 +++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/scaluq/operator/apply_pauli.cpp b/scaluq/operator/apply_pauli.cpp index ba0edbc9..c57a6f5b 100644 --- a/scaluq/operator/apply_pauli.cpp +++ b/scaluq/operator/apply_pauli.cpp @@ -15,7 +15,8 @@ void apply_pauli(std::uint64_t control_mask, if (bit_flip_mask == 0) { Kokkos::parallel_for( state_vector.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(std::uint64_t i) { - std::uint64_t state_idx = insert_zero_at_mask_positions(i, control_mask) | control_mask; + std::uint64_t state_idx = + insert_zero_at_mask_positions(i, control_mask) | control_mask; if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { state_vector._raw[state_idx] *= -coef; } else { @@ -57,7 +58,8 @@ void apply_pauli_rotation(std::uint64_t control_mask, const Complex cval_pls = cosval + Complex(0, 1) * sinval; Kokkos::parallel_for( state_vector.dim() >> std::popcount(control_mask), KOKKOS_LAMBDA(std::uint64_t i) { - std::uint64_t state_idx = insert_zero_at_mask_positions(i, control_mask) | control_mask; + std::uint64_t state_idx = + insert_zero_at_mask_positions(i, control_mask) | control_mask; if (Kokkos::popcount(state_idx & phase_flip_mask) & 1) { state_vector._raw[state_idx] *= cval_min; } else { @@ -69,7 +71,8 @@ void apply_pauli_rotation(std::uint64_t control_mask, } else { std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; Kokkos::parallel_for( - state_vector.dim() >> (std::popcount(control_mask) + 1), KOKKOS_LAMBDA(std::uint64_t i) { + state_vector.dim() >> (std::popcount(control_mask) + 1), + KOKKOS_LAMBDA(std::uint64_t i) { std::uint64_t basis_0 = internal::insert_zero_at_mask_positions(i, control_mask | 1ULL << pivot) | control_mask; diff --git a/scaluq/operator/pauli_operator.hpp b/scaluq/operator/pauli_operator.hpp index bf808229..5980fdf4 100644 --- a/scaluq/operator/pauli_operator.hpp +++ b/scaluq/operator/pauli_operator.hpp @@ -30,7 +30,9 @@ class PauliOperator { void add_single_pauli(std::uint64_t target_qubit, std::uint64_t pauli_id); Complex get_coef() const { return _coef; } void set_coef(Complex c) { _coef = c; } - const std::vector& get_target_qubit_list() const { return _target_qubit_list; } + const std::vector& get_target_qubit_list() const { + return _target_qubit_list; + } const std::vector& get_pauli_id_list() const { return _pauli_id_list; } std::tuple get_XZ_mask_representation() const { return {_bit_flip_mask, _phase_flip_mask}; @@ -63,7 +65,8 @@ class PauliOperator { [[nodiscard]] inline const std::vector& get_pauli_id_list() const { return _ptr->get_pauli_id_list(); } - [[nodiscard]] inline std::tuple get_XZ_mask_representation() const { + [[nodiscard]] inline std::tuple get_XZ_mask_representation() + const { return _ptr->get_XZ_mask_representation(); } [[nodiscard]] std::string get_pauli_string() const; From b156fe744f7f7863171c789ccb6876f396035de5 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 3 Sep 2024 01:00:07 +0000 Subject: [PATCH 38/55] M_PI -> std::numbers::pi --- README.md | 2 +- tests/circuit/circuit_test.cpp | 7 ++++--- tests/circuit/param_circuit_test.cpp | 3 ++- tests/gate/gate_test.cpp | 15 +++++++------- tests/gate/merge_test.cpp | 31 +++++++++++++++------------- tests/gate/param_gate_test.cpp | 7 ++++--- 6 files changed, 36 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 8074e3ba..31e5755b 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ int main() { circuit.add_gate(scaluq::gate::X(0)); circuit.add_gate(scaluq::gate::CNot(0, 1)); circuit.add_gate(scaluq::gate::Y(1)); - circuit.add_gate(scaluq::gate::RX(1, M_PI / 2)); + circuit.add_gate(scaluq::gate::RX(1, std::numbers::pi / 2)); circuit.update_quantum_state(state); scaluq::Operator observable(n_qubits); diff --git a/tests/circuit/circuit_test.cpp b/tests/circuit/circuit_test.cpp index 24dbc5b7..66e754fc 100644 --- a/tests/circuit/circuit_test.cpp +++ b/tests/circuit/circuit_test.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "../util/util.hpp" #include "gate/gate_factory.hpp" @@ -124,11 +125,11 @@ TEST(CircuitTest, CircuitBasic) { state_eigen = get_eigen_matrix_full_qubit_Swap(target, target_sub, n) * state_eigen; target = random.int32() % n; - circuit.add_gate(gate::U1(target, M_PI)); + circuit.add_gate(gate::U1(target, std::numbers::pi)); state_eigen = get_expanded_eigen_matrix_with_identity(target, make_Z(), n) * state_eigen; target = random.int32() % n; - circuit.add_gate(gate::U2(target, 0, M_PI)); + circuit.add_gate(gate::U2(target, 0, std::numbers::pi)); state_eigen = get_expanded_eigen_matrix_with_identity(target, make_H(), n) * state_eigen; target = random.int32() % n; @@ -243,7 +244,7 @@ TEST(CircuitTest, CircuitRev) { /* Observable observable(n); - angle = 2 * M_PI * random.uniform(); + angle = 2 * std::numbers::pi * random.uniform(); observable.add_operator(1.0, "Z 0"); observable.add_operator(2.0, "Z 0 Z 1"); diff --git a/tests/circuit/param_circuit_test.cpp b/tests/circuit/param_circuit_test.cpp index 1fd7f553..a79f37fe 100644 --- a/tests/circuit/param_circuit_test.cpp +++ b/tests/circuit/param_circuit_test.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +26,7 @@ TEST(ParamCircuitTest, ApplyParamCircuit) { pkeys[pidx] = "p" + std::to_string(pidx); std::array params = {}; for (std::uint64_t pidx : std::views::iota(std::uint64_t{0}, nparams)) - params[pidx] = random.uniform() * M_PI * 2; + params[pidx] = random.uniform() * std::numbers::pi * 2; std::map pmap; for (std::uint64_t pidx : std::views::iota(std::uint64_t{0}, nparams)) pmap[pkeys[pidx]] = params[pidx]; diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 731993f3..344f2d4a 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,7 @@ void run_random_gate_apply(std::uint64_t n_qubits) { test_state[i] = state_cp[i]; } - const double angle = M_PI * random.uniform(); + const double angle = std::numbers::pi * random.uniform(); const Gate gate = QuantumGateConstructor(angle, {}); gate->update_quantum_state(state); state_cp = state.amplitudes(); @@ -108,7 +109,7 @@ void run_random_gate_apply(std::uint64_t n_qubits, test_state[i] = state_cp[i]; } - const double angle = M_PI * random.uniform(); + const double angle = std::numbers::pi * random.uniform(); const auto matrix = matrix_factory(angle); const std::uint64_t target = random.int64() % n_qubits; const Gate gate = QuantumGateConstructor(target, angle, {}); @@ -138,14 +139,14 @@ void run_random_gate_apply_IBMQ( test_state[i] = state_cp[i]; } - double theta = M_PI * random.uniform(); - double phi = M_PI * random.uniform(); - double lambda = M_PI * random.uniform(); + double theta = std::numbers::pi * random.uniform(); + double phi = std::numbers::pi * random.uniform(); + double lambda = std::numbers::pi * random.uniform(); if (gate_type == 0) { theta = 0; phi = 0; } else if (gate_type == 1) { - theta = M_PI / 2; + theta = std::numbers::pi / 2; } const auto matrix = matrix_factory(theta, phi, lambda); const std::uint64_t target = random.int64() % n_qubits; @@ -305,7 +306,7 @@ void run_random_gate_apply_pauli(std::uint64_t n_qubits) { for (std::uint64_t i = 0; i < dim; i++) { test_state[i] = state_cp[i]; } - const double angle = M_PI * random.uniform(); + const double angle = std::numbers::pi * random.uniform(); std::vector target_vec, pauli_id_vec; for (std::uint64_t target = 0; target < n_qubits; target++) { target_vec.emplace_back(target); diff --git a/tests/gate/merge_test.cpp b/tests/gate/merge_test.cpp index 2295716f..98234d16 100644 --- a/tests/gate/merge_test.cpp +++ b/tests/gate/merge_test.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -29,15 +30,17 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::SqrtYdag(target)); gates.push_back(gate::P0(target)); gates.push_back(gate::P1(target)); - gates.push_back(gate::RX(target, random.uniform() * M_PI * 2)); - gates.push_back(gate::RY(target, random.uniform() * M_PI * 2)); - gates.push_back(gate::RZ(target, random.uniform() * M_PI * 2)); - gates.push_back(gate::U1(target, random.uniform() * M_PI * 2)); - gates.push_back(gate::U2(target, random.uniform() * M_PI * 2, random.uniform() * M_PI * 2)); + gates.push_back(gate::RX(target, random.uniform() * std::numbers::pi * 2)); + gates.push_back(gate::RY(target, random.uniform() * std::numbers::pi * 2)); + gates.push_back(gate::RZ(target, random.uniform() * std::numbers::pi * 2)); + gates.push_back(gate::U1(target, random.uniform() * std::numbers::pi * 2)); + gates.push_back(gate::U2(target, + random.uniform() * std::numbers::pi * 2, + random.uniform() * std::numbers::pi * 2)); gates.push_back(gate::U3(target, - random.uniform() * M_PI * 2, - random.uniform() * M_PI * 2, - random.uniform() * M_PI * 2)); + random.uniform() * std::numbers::pi * 2, + random.uniform() * std::numbers::pi * 2, + random.uniform() * std::numbers::pi * 2)); gates.push_back( gate::OneTargetMatrix(target, {std::array{Complex(random.uniform(), random.uniform()), @@ -49,7 +52,7 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::Swap(target, target ^ 1)); } gates.push_back(gate::I()); - gates.push_back(gate::GlobalPhase(random.uniform() * M_PI * 2)); + gates.push_back(gate::GlobalPhase(random.uniform() * std::numbers::pi * 2)); gates.push_back( gate::TwoTargetMatrix(0, 1, @@ -73,11 +76,11 @@ TEST(GateTest, MergeGate) { gates.push_back(gate::Pauli(PauliOperator("Z 0", random.uniform()))); gates.push_back(gate::Pauli(PauliOperator("Z 1", random.uniform()))); gates.push_back(gate::PauliRotation(PauliOperator("X 0 Y 1", random.uniform()), - random.uniform() * M_PI * 2)); - gates.push_back( - gate::PauliRotation(PauliOperator("Z 0", random.uniform()), random.uniform() * M_PI * 2)); - gates.push_back( - gate::PauliRotation(PauliOperator("Z 1", random.uniform()), random.uniform() * M_PI * 2)); + random.uniform() * std::numbers::pi * 2)); + gates.push_back(gate::PauliRotation(PauliOperator("Z 0", random.uniform()), + random.uniform() * std::numbers::pi * 2)); + gates.push_back(gate::PauliRotation(PauliOperator("Z 1", random.uniform()), + random.uniform() * std::numbers::pi * 2)); for (auto&& g1 : gates) { for (auto&& g2 : gates) { std::uint64_t n = 2; diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index 778d42a6..1a4ada90 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -25,7 +26,7 @@ void test_apply_parametric_single_pauli_rotation(std::uint64_t n_qubits, auto state_bef = state.copy(); const std::uint64_t target = random.int32() % n_qubits; - const double param = M_PI * random.uniform(); + const double param = std::numbers::pi * random.uniform(); const double pcoef = random.uniform() * 2 - 1; const Gate gate = factory_fixed(target, pcoef * param, {}); const ParamGate pgate = factory_parametric(target, pcoef, {}); @@ -56,7 +57,7 @@ void test_apply_parametric_multi_pauli_rotation(std::uint64_t n_qubits) { StateVector state = StateVector::Haar_random_state(n_qubits); auto state_cp = state.copy(); auto state_bef = state.copy(); - const double param = M_PI * random.uniform(); + const double param = std::numbers::pi * random.uniform(); const double pcoef = random.uniform() * 2 - 1; std::vector target_vec, pauli_id_vec; for (std::uint64_t target = 0; target < n_qubits; target++) { @@ -103,7 +104,7 @@ TEST(ParamGateTest, ApplyPProbablisticGate) { StateVector state(1); for ([[maybe_unused]] auto _ : std::views::iota(0, 100)) { std::uint64_t before = state.sampling(1)[0]; - probgate->update_quantum_state(state, M_PI); + probgate->update_quantum_state(state, std::numbers::pi); std::uint64_t after = state.sampling(1)[0]; if (before != after) { x_cnt++; From 5904fa22ce2cfa302206d45dd60134cb57081e61 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 3 Sep 2024 01:17:09 +0000 Subject: [PATCH 39/55] . --- tests/gate/param_gate_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index a80a26dc..ba7600a6 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -28,7 +28,7 @@ void test_apply_parametric_single_pauli_rotation(std::uint64_t n_qubits, const std::uint64_t target = random.int32() % n_qubits; const double param = std::numbers::pi * random.uniform(); const double param_coef = random.uniform() * 2 - 1; - const Gate gate = factory_fixed(target, pcoef * param, {}); + const Gate gate = factory_fixed(target, param_coef * param, {}); const ParamGate pgate = factory_parametric(target, param_coef, {}); gate->update_quantum_state(state); pgate->update_quantum_state(state_cp, param); From 81fb866df3896b91bc76007f86defc7c6447517d Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Tue, 3 Sep 2024 10:43:14 +0900 Subject: [PATCH 40/55] fix merging --- scaluq/gate/gate_pauli.hpp | 4 ++-- scaluq/gate/param_gate_pauli.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index 215bf8d8..103b4efa 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -24,7 +24,7 @@ class PauliGateImpl : public GateBase { void update_quantum_state(StateVector& state_vector) const override { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); - apply_pauli(_control_mask, bit_flip_mask, phase_flip_mask, _pauli.get_coef(), state_vector); + apply_pauli(_control_mask, bit_flip_mask, phase_flip_mask, _pauli.coef(), state_vector); } }; @@ -58,7 +58,7 @@ class PauliRotationGateImpl : public GateBase { void update_quantum_state(StateVector& state_vector) const override { auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation(); apply_pauli_rotation( - _control_mask, bit_flip_mask, phase_flip_mask, _pauli.get_coef(), _angle, state_vector); + _control_mask, bit_flip_mask, phase_flip_mask, _pauli.coef(), _angle, state_vector); } }; } // namespace internal diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index c23adbb8..d451cc2c 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -40,7 +40,7 @@ class ParamPauliRotationGateImpl : public ParamGateBase { apply_pauli_rotation(_control_mask, bit_flip_mask, phase_flip_mask, - _pauli.get_coef(), + _pauli.coef(), _pcoef * param, state_vector); } From bccc0e93ee86212114ff4725b160c88f70ab56c1 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 3 Sep 2024 03:26:10 +0000 Subject: [PATCH 41/55] add ostream difinition of GatePtr --- exe/main.cpp | 14 ++- scaluq/gate/gate.hpp | 7 +- scaluq/gate/gate_factory.hpp | 131 ++++++++++++++++++++++++++ scaluq/gate/param_gate.hpp | 37 ++++++++ scaluq/state/state_vector.cpp | 2 +- scaluq/state/state_vector_batched.cpp | 4 +- 6 files changed, 189 insertions(+), 6 deletions(-) diff --git a/exe/main.cpp b/exe/main.cpp index 7354deb2..cb4a5f46 100644 --- a/exe/main.cpp +++ b/exe/main.cpp @@ -13,8 +13,18 @@ using namespace scaluq; using namespace std; void run() { - std::uint64_t n_qubits = 5; - auto state = StateVector::Haar_random_state(n_qubits); + auto x_gate = gate::X(2); + std::cout << x_gate << std::endl; + auto y_gate = gate::Y(2); + std::cout << y_gate << std::endl; + auto swap_gate = gate::Swap(2, 3, {4, 6}); + std::cout << swap_gate << "\n\n"; + + auto prob_gate = gate::Probablistic({0.1, 0.1, 0.8}, {x_gate, y_gate, swap_gate}); + std::cout << prob_gate << "\n\n"; + + auto prob_prob_gate = gate::Probablistic({0.5, 0.5}, {x_gate, prob_gate}); + std::cout << prob_prob_gate << "\n\n"; } int main() { diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 527402df..64e77d7b 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -43,6 +43,7 @@ class SwapGateImpl; class TwoTargetMatrixGateImpl; class PauliGateImpl; class PauliRotationGateImpl; +class ProbablisticGateImpl; template class GatePtr; @@ -80,7 +81,8 @@ enum class GateType { Swap, TwoTargetMatrix, Pauli, - PauliRotation + PauliRotation, + Probablistic }; template @@ -119,6 +121,7 @@ constexpr GateType get_gate_type() { if constexpr (std::is_same_v) return GateType::Pauli; if constexpr (std::is_same_v) return GateType::PauliRotation; + if constexpr (std::is_same_v) return GateType::Probablistic; static_assert("unknown GateImpl"); return GateType::Unknown; } @@ -226,6 +229,8 @@ class GatePtr { } return _gate_ptr.get(); } + + // 依存関係により、operator<< の定義は gate_factory.hpp に定義 }; } // namespace internal diff --git a/scaluq/gate/gate_factory.hpp b/scaluq/gate/gate_factory.hpp index 6ed1580c..b6026b60 100644 --- a/scaluq/gate/gate_factory.hpp +++ b/scaluq/gate/gate_factory.hpp @@ -215,4 +215,135 @@ inline Gate Probablistic(const std::vector& distribution, gate_list); } } // namespace gate + +template +std::ostream& operator<<(std::ostream& os, const internal::GatePtr& obj) { + std::string indent = " "; + if (obj.gate_type() == GateType::Probablistic) { + const auto prob_gate = ProbablisticGate(obj); + const auto distribution = prob_gate->distribution(); + const auto gates = prob_gate->gate_list(); + os << "Gate Type: Probablistic\n"; + for (std::size_t i = 0; i < distribution.size(); ++i) { + std::ostringstream gate_ss; + gate_ss << gates[i]; + std::istringstream gate_is(gate_ss.str()); + std::string line; + // os << indent << "--------------------\n"; + os << indent << "Probability: " << distribution[i] << "\n"; + while (std::getline(gate_is, line)) { + os << indent << line << (gate_is.peek() == EOF ? "" : "\n"); + } + } + return os; + } + auto targets = internal::mask_to_vector(obj->target_qubit_mask()); + auto controls = internal::mask_to_vector(obj->control_qubit_mask()); + os << "Gate Type: "; + switch (obj.gate_type()) { + case GateType::I: + os << "I"; + break; + case GateType::GlobalPhase: + os << "GlobalPhase"; + break; + case GateType::X: + os << "X"; + break; + case GateType::Y: + os << "Y"; + break; + case GateType::Z: + os << "Z"; + break; + case GateType::H: + os << "H"; + break; + case GateType::S: + os << "S"; + break; + case GateType::Sdag: + os << "Sdag"; + break; + case GateType::T: + os << "T"; + break; + case GateType::Tdag: + os << "Tdag"; + break; + case GateType::SqrtX: + os << "SqrtX"; + break; + case GateType::SqrtXdag: + os << "SqrtXdag"; + break; + case GateType::SqrtY: + os << "SqrtY"; + break; + case GateType::SqrtYdag: + os << "SqrtYdag"; + break; + case GateType::P0: + os << "P0"; + break; + case GateType::P1: + os << "P1"; + break; + case GateType::RX: + os << "RX"; + break; + case GateType::RY: + os << "RY"; + break; + case GateType::RZ: + os << "RZ"; + break; + case GateType::U1: + os << "U1"; + break; + case GateType::U2: + os << "U2"; + break; + case GateType::U3: + os << "U3"; + break; + case GateType::OneTargetMatrix: + os << "OneTargetMatrix"; + break; + case GateType::CX: + os << "CX"; + break; + case GateType::CZ: + os << "CZ"; + break; + case GateType::CCX: + os << "CCX"; + break; + case GateType::Swap: + os << "Swap"; + break; + case GateType::TwoTargetMatrix: + os << "TwoTargetMatrix"; + break; + case GateType::Pauli: + os << "Pauli"; + break; + case GateType::PauliRotation: + os << "PauliRotation"; + break; + case GateType::Unknown: + default: + os << "Unknown"; + break; + } + os << "\n" << indent << "Target Qubits: {"; + for (std::uint32_t i = 0; i < targets.size(); ++i) + os << targets[i] << (i == targets.size() - 1 ? "" : ", "); + os << "}\n" << indent << "Control Qubits: {"; + for (std::uint32_t i = 0; i < controls.size(); ++i) + os << controls[i] << (i == controls.size() - 1 ? "" : ", "); + os << "}"; + return os; +} + } // namespace scaluq diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index edc159dd..e34c9e3a 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -142,6 +142,43 @@ class ParamGatePtr { } return _param_gate_ptr.get(); } + + friend std::ostream& operator<<(std::ostream& os, const ParamGatePtr& obj) { + if (!obj._param_gate_ptr) { + os << "Gate Type: Null"; + return os; + } + auto targets = internal::mask_to_vector(obj->target_qubit_mask()); + auto controls = internal::mask_to_vector(obj->control_qubit_mask()); + os << "Gate Type: "; + switch (obj.param_gate_type()) { + case ParamGateType::ParamRX: + os << "ParamRX"; + break; + case ParamGateType::ParamRY: + os << "ParamRY"; + break; + case ParamGateType::ParamRZ: + os << "ParamRZ"; + break; + case ParamGateType::ParamPauliRotation: + os << "ParamPauliRotation"; + break; + default: + os << "Undefined"; + break; + } + os << "\n" + "Target Qubits: {"; + for (std::uint32_t i = 0; i < targets.size(); ++i) + os << targets[i] << (i == targets.size() - 1 ? "" : ", "); + os << "}\n" + "Control Qubits: {"; + for (std::uint32_t i = 0; i < controls.size(); ++i) + os << controls[i] << (i == controls.size() - 1 ? "" : ", "); + os << "}"; + return os; + } }; } // namespace internal diff --git a/scaluq/state/state_vector.cpp b/scaluq/state/state_vector.cpp index 440c2419..2913ba21 100644 --- a/scaluq/state/state_vector.cpp +++ b/scaluq/state/state_vector.cpp @@ -233,7 +233,7 @@ std::string StateVector::to_string() const { } return tmp; }(i, _n_qubits) - << ": " << amp[i] << std::endl; + << ": " << amp[i] << (i < _dim - 1 ? "\n" : ""); } return os.str(); } diff --git a/scaluq/state/state_vector_batched.cpp b/scaluq/state/state_vector_batched.cpp index f56fc861..782a0fc9 100644 --- a/scaluq/state/state_vector_batched.cpp +++ b/scaluq/state/state_vector_batched.cpp @@ -367,7 +367,7 @@ std::string StateVectorBatched::to_string() const { for (std::uint64_t b = 0; b < _batch_size; ++b) { StateVector tmp(_n_qubits); os << "--------------------\n"; - os << " * Batch_id : " << b << '\n'; + os << " * Batch id : " << b << '\n'; os << " * State vector : \n"; for (std::uint64_t i = 0; i < _dim; ++i) { os << @@ -378,7 +378,7 @@ std::string StateVectorBatched::to_string() const { } return tmp; }(i, _n_qubits) - << ": " << states_h(b, i) << std::endl; + << ": " << states_h(b, i) << (b < _batch_size - 1 || i < _dim - 1 ? "\n" : ""); } } return os.str(); From be291f648e649e56a4e3c243e1ccb9adc941b014 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Tue, 3 Sep 2024 12:41:50 +0900 Subject: [PATCH 42/55] rename ParamGates in test --- tests/gate/gate_test.cpp | 11 +++++++---- tests/gate/param_gate_test.cpp | 23 +++++++++++++---------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 359e4e50..804e50a0 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -401,9 +401,12 @@ TEST(GateTest, ApplyProbablisticGate) { ASSERT_LT(x_cnt, i_cnt); } -void test_gate(Gate gate_control, Gate gate_simple, std::uint64_t n_qubits, std::uint64_t control_mask) { +void test_gate(Gate gate_control, + Gate gate_simple, + std::uint64_t n_qubits, + std::uint64_t control_mask) { StateVector state = StateVector::Haar_random_state(n_qubits); - auto amplitudes = state.amplitudes(); + auto amplitudes = state.get_amplitudes(); StateVector state_controlled(n_qubits - std::popcount(control_mask)); std::vector amplitudes_controlled(state_controlled.dim()); for (std::uint64_t i : std::views::iota(0ULL, state_controlled.dim())) { @@ -413,8 +416,8 @@ void test_gate(Gate gate_control, Gate gate_simple, std::uint64_t n_qubits, std: state_controlled.load(amplitudes_controlled); gate_control->update_quantum_state(state); gate_simple->update_quantum_state(state_controlled); - amplitudes = state.amplitudes(); - amplitudes_controlled = state_controlled.amplitudes(); + amplitudes = state.get_amplitudes(); + amplitudes_controlled = state_controlled.get_amplitudes(); for (std::uint64_t i : std::views::iota(0ULL, state_controlled.dim())) { ASSERT_NEAR( Kokkos::abs(amplitudes_controlled[i] - diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index 4d8989c6..a6683d73 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -117,10 +117,13 @@ TEST(ParamGateTest, ApplyParamProbablisticGate) { ASSERT_LT(x_cnt, i_cnt); } -void test_gate( - ParamGate gate_control, ParamGate gate_simple, std::uint64_t n_qubits, std::uint64_t control_mask, double param) { +void test_gate(ParamGate gate_control, + ParamGate gate_simple, + std::uint64_t n_qubits, + std::uint64_t control_mask, + double param) { StateVector state = StateVector::Haar_random_state(n_qubits); - auto amplitudes = state.amplitudes(); + auto amplitudes = state.get_amplitudes(); StateVector state_controlled(n_qubits - std::popcount(control_mask)); std::vector amplitudes_controlled(state_controlled.dim()); for (std::uint64_t i : std::views::iota(0ULL, state_controlled.dim())) { @@ -130,8 +133,8 @@ void test_gate( state_controlled.load(amplitudes_controlled); gate_control->update_quantum_state(state, param); gate_simple->update_quantum_state(state_controlled, param); - amplitudes = state.amplitudes(); - amplitudes_controlled = state_controlled.amplitudes(); + amplitudes = state.get_amplitudes(); + amplitudes_controlled = state_controlled.get_amplitudes(); for (std::uint64_t i : std::views::iota(0ULL, state_controlled.dim())) { ASSERT_NEAR( Kokkos::abs(amplitudes_controlled[i] - @@ -185,17 +188,17 @@ void test_ppauli_control(std::uint64_t n) { } } double param = random.uniform() * PI() * 2; - ParamGate g1 = gate::PPauliRotation(PauliOperator(data1), 1., controls); - ParamGate g2 = gate::PPauliRotation(PauliOperator(data2), 1., {}); + ParamGate g1 = gate::ParamPauliRotation(PauliOperator(data1), 1., controls); + ParamGate g2 = gate::ParamPauliRotation(PauliOperator(data2), 1., {}); test_gate(g1, g2, n, control_mask, param); } TEST(ParamGateTest, Control) { std::uint64_t n = 10; for ([[maybe_unused]] std::uint64_t _ : std::views::iota(0, 10)) { - test_param_rotation_control(gate::PRX, n); - test_param_rotation_control(gate::PRY, n); - test_param_rotation_control(gate::PRZ, n); + test_param_rotation_control(gate::ParamRX, n); + test_param_rotation_control(gate::ParamRY, n); + test_param_rotation_control(gate::ParamRZ, n); test_ppauli_control(n); } } From 56178e5fd4a0e22745bc5804f4ae400844783320 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Tue, 3 Sep 2024 13:07:32 +0900 Subject: [PATCH 43/55] deal with new Matrix2x2 --- scaluq/operator/apply_pauli.cpp | 6 +++--- tests/gate/gate_test.cpp | 4 ++-- tests/gate/param_gate_test.cpp | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scaluq/operator/apply_pauli.cpp b/scaluq/operator/apply_pauli.cpp index c57a6f5b..27549754 100644 --- a/scaluq/operator/apply_pauli.cpp +++ b/scaluq/operator/apply_pauli.cpp @@ -28,7 +28,7 @@ void apply_pauli(std::uint64_t control_mask, } std::uint64_t pivot = sizeof(std::uint64_t) * 8 - std::countl_zero(bit_flip_mask) - 1; std::uint64_t global_phase_90rot_count = std::popcount(bit_flip_mask & phase_flip_mask); - Complex global_phase = PHASE_M90ROT().val[global_phase_90rot_count % 4]; + Complex global_phase = PHASE_M90ROT()[global_phase_90rot_count % 4]; Kokkos::parallel_for( state_vector.dim() >> (std::popcount(control_mask) + 1), KOKKOS_LAMBDA(std::uint64_t i) { std::uint64_t basis_0 = @@ -89,11 +89,11 @@ void apply_pauli_rotation(std::uint64_t control_mask, state_vector._raw[basis_0] = cosval * cval_0 + Complex(0, 1) * sinval * cval_1 * - PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_0 * 2) % 4]; + PHASE_M90ROT()[(global_phase_90_rot_count + bit_parity_0 * 2) % 4]; state_vector._raw[basis_1] = cosval * cval_1 + Complex(0, 1) * sinval * cval_0 * - PHASE_M90ROT().val[(global_phase_90_rot_count + bit_parity_1 * 2) % 4]; + PHASE_M90ROT()[(global_phase_90_rot_count + bit_parity_1 * 2) % 4]; }); Kokkos::fence(); } diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 324dfb77..37211295 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -450,7 +450,7 @@ void test_standard_gate_control(Factory factory, std::uint64_t n) { std::uint64_t control_mask = 0ULL; for (std::uint64_t c : controls) control_mask |= 1ULL << c; std::vector angles(num_rotation); - for (double& angle : angles) angle = random.uniform() * PI() * 2; + for (double& angle : angles) angle = random.uniform() * std::numbers::pi * 2; if constexpr (num_target == 0 && num_rotation == 1) { Gate g1 = factory(angles[0], controls); Gate g2 = factory(angles[0], {}); @@ -514,7 +514,7 @@ void test_pauli_control(std::uint64_t n) { Gate g2 = gate::Pauli(PauliOperator(data2), {}); test_gate(g1, g2, n, control_mask); } else { - double angle = random.uniform() * PI() * 2; + double angle = random.uniform() * std::numbers::pi * 2; Gate g1 = gate::PauliRotation(PauliOperator(data1), angle, controls); Gate g2 = gate::PauliRotation(PauliOperator(data2), angle, {}); test_gate(g1, g2, n, control_mask); diff --git a/tests/gate/param_gate_test.cpp b/tests/gate/param_gate_test.cpp index 4b187995..2d5e5c6f 100644 --- a/tests/gate/param_gate_test.cpp +++ b/tests/gate/param_gate_test.cpp @@ -164,7 +164,7 @@ void test_param_rotation_control(Factory factory, std::uint64_t n) { } std::uint64_t control_mask = 0ULL; for (std::uint64_t c : controls) control_mask |= 1ULL << c; - double param = random.uniform() * PI() * 2; + double param = random.uniform() * std::numbers::pi * 2; ParamGate g1 = factory(target, 1., controls); ParamGate g2 = factory(target - std::popcount(control_mask & ((1ULL << target) - 1)), 1., {}); test_gate(g1, g2, n, control_mask, param); @@ -188,7 +188,7 @@ void test_ppauli_control(std::uint64_t n) { num_control++; } } - double param = random.uniform() * PI() * 2; + double param = random.uniform() * std::numbers::pi * 2; ParamGate g1 = gate::ParamPauliRotation(PauliOperator(data1), 1., controls); ParamGate g2 = gate::ParamPauliRotation(PauliOperator(data2), 1., {}); test_gate(g1, g2, n, control_mask, param); From 4876fbb136f046a8e29f487b395345e42d2d576e Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 6 Sep 2024 02:02:25 +0000 Subject: [PATCH 44/55] implement param_gate ostream --- scaluq/gate/gate.hpp | 92 ++++++++++++----------- scaluq/gate/gate_factory.hpp | 114 ++++++++++++++++------------- scaluq/gate/param_gate.hpp | 87 +++++++++------------- scaluq/gate/param_gate_factory.hpp | 70 ++++++++++++++++++ 4 files changed, 220 insertions(+), 143 deletions(-) diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 64e77d7b..6fd11554 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -82,48 +82,53 @@ enum class GateType { TwoTargetMatrix, Pauli, PauliRotation, - Probablistic + Probablistic, + Error }; template constexpr GateType get_gate_type() { - if constexpr (std::is_same_v) return GateType::Unknown; - if constexpr (std::is_same_v) return GateType::I; - if constexpr (std::is_same_v) return GateType::GlobalPhase; - if constexpr (std::is_same_v) return GateType::X; - if constexpr (std::is_same_v) return GateType::Y; - if constexpr (std::is_same_v) return GateType::Z; - if constexpr (std::is_same_v) return GateType::H; - if constexpr (std::is_same_v) return GateType::S; - if constexpr (std::is_same_v) return GateType::Sdag; - if constexpr (std::is_same_v) return GateType::T; - if constexpr (std::is_same_v) return GateType::Tdag; - if constexpr (std::is_same_v) return GateType::SqrtX; - if constexpr (std::is_same_v) return GateType::SqrtXdag; - if constexpr (std::is_same_v) return GateType::SqrtY; - if constexpr (std::is_same_v) return GateType::SqrtYdag; - if constexpr (std::is_same_v) return GateType::P0; - if constexpr (std::is_same_v) return GateType::P1; - if constexpr (std::is_same_v) return GateType::RX; - if constexpr (std::is_same_v) return GateType::RY; - if constexpr (std::is_same_v) return GateType::RZ; - if constexpr (std::is_same_v) return GateType::U1; - if constexpr (std::is_same_v) return GateType::U2; - if constexpr (std::is_same_v) return GateType::U3; - if constexpr (std::is_same_v) + using TWithoutConst = std::remove_cv_t; + if constexpr (std::is_same_v) return GateType::Unknown; + if constexpr (std::is_same_v) return GateType::I; + if constexpr (std::is_same_v) + return GateType::GlobalPhase; + if constexpr (std::is_same_v) return GateType::X; + if constexpr (std::is_same_v) return GateType::Y; + if constexpr (std::is_same_v) return GateType::Z; + if constexpr (std::is_same_v) return GateType::H; + if constexpr (std::is_same_v) return GateType::S; + if constexpr (std::is_same_v) return GateType::Sdag; + if constexpr (std::is_same_v) return GateType::T; + if constexpr (std::is_same_v) return GateType::Tdag; + if constexpr (std::is_same_v) return GateType::SqrtX; + if constexpr (std::is_same_v) + return GateType::SqrtXdag; + if constexpr (std::is_same_v) return GateType::SqrtY; + if constexpr (std::is_same_v) + return GateType::SqrtYdag; + if constexpr (std::is_same_v) return GateType::P0; + if constexpr (std::is_same_v) return GateType::P1; + if constexpr (std::is_same_v) return GateType::RX; + if constexpr (std::is_same_v) return GateType::RY; + if constexpr (std::is_same_v) return GateType::RZ; + if constexpr (std::is_same_v) return GateType::U1; + if constexpr (std::is_same_v) return GateType::U2; + if constexpr (std::is_same_v) return GateType::U3; + if constexpr (std::is_same_v) return GateType::OneTargetMatrix; - if constexpr (std::is_same_v) return GateType::CX; - if constexpr (std::is_same_v) return GateType::CZ; - if constexpr (std::is_same_v) return GateType::CCX; - if constexpr (std::is_same_v) return GateType::Swap; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return GateType::CX; + if constexpr (std::is_same_v) return GateType::CZ; + if constexpr (std::is_same_v) return GateType::CCX; + if constexpr (std::is_same_v) return GateType::Swap; + if constexpr (std::is_same_v) return GateType::TwoTargetMatrix; - if constexpr (std::is_same_v) return GateType::Pauli; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return GateType::Pauli; + if constexpr (std::is_same_v) return GateType::PauliRotation; - if constexpr (std::is_same_v) return GateType::Probablistic; - static_assert("unknown GateImpl"); - return GateType::Unknown; + if constexpr (std::is_same_v) + return GateType::Probablistic; + return GateType::Error; } namespace internal { @@ -145,8 +150,7 @@ class GateBase : public std::enable_shared_from_this { if (_target_mask & _control_mask) [[unlikely]] { throw std::runtime_error( "Error: Gate::Gate(std::uint64_t target_mask, std::uint64_t control_mask) : Target " - "and " - "control qubits must not overlap."); + "and control qubits must not overlap."); } } virtual ~GateBase() = default; @@ -188,15 +192,21 @@ class GatePtr { template GatePtr(const std::shared_ptr& gate_ptr) { if constexpr (std::is_same_v) { - _gate_type = get_gate_type(); + if ((_gate_type = get_gate_type()) == GateType::Error) { + throw std::runtime_error("Unknown GateType"); + } _gate_ptr = gate_ptr; } else if constexpr (std::is_same_v) { // upcast - _gate_type = get_gate_type(); + if ((_gate_type = get_gate_type()) == GateType::Error) { + throw std::runtime_error("Unknown GateType"); + } _gate_ptr = std::static_pointer_cast(gate_ptr); } else { // downcast - _gate_type = get_gate_type(); + if ((_gate_type = get_gate_type()) == GateType::Error) { + throw std::runtime_error("Unknown GateType"); + } if (!(_gate_ptr = std::dynamic_pointer_cast(gate_ptr))) { throw std::runtime_error("invalid gate cast"); } @@ -230,7 +240,7 @@ class GatePtr { return _gate_ptr.get(); } - // 依存関係により、operator<< の定義は gate_factory.hpp に定義 + // 依存関係の都合上、operator<< の定義は gate_factory.hpp に定義 }; } // namespace internal diff --git a/scaluq/gate/gate_factory.hpp b/scaluq/gate/gate_factory.hpp index b6026b60..475d9ad4 100644 --- a/scaluq/gate/gate_factory.hpp +++ b/scaluq/gate/gate_factory.hpp @@ -216,133 +216,145 @@ inline Gate Probablistic(const std::vector& distribution, } } // namespace gate -template -std::ostream& operator<<(std::ostream& os, const internal::GatePtr& obj) { - std::string indent = " "; +namespace internal { + +template +std::string gate_to_string(const GatePtr& obj, std::uint32_t depth = 0) { + std::ostringstream ss; + std::string indent(depth * 2, ' '); + if (obj.gate_type() == GateType::Probablistic) { const auto prob_gate = ProbablisticGate(obj); const auto distribution = prob_gate->distribution(); const auto gates = prob_gate->gate_list(); - os << "Gate Type: Probablistic\n"; + ss << indent << "Gate Type: Probablistic\n"; for (std::size_t i = 0; i < distribution.size(); ++i) { - std::ostringstream gate_ss; - gate_ss << gates[i]; - std::istringstream gate_is(gate_ss.str()); - std::string line; - // os << indent << "--------------------\n"; - os << indent << "Probability: " << distribution[i] << "\n"; - while (std::getline(gate_is, line)) { - os << indent << line << (gate_is.peek() == EOF ? "" : "\n"); - } + ss << indent << " --------------------\n"; + ss << indent << " Probability: " << distribution[i] << "\n"; + ss << gate_to_string(gates[i], depth + 1) << (i == distribution.size() - 1 ? "" : "\n"); } - return os; + return ss.str(); } + auto targets = internal::mask_to_vector(obj->target_qubit_mask()); auto controls = internal::mask_to_vector(obj->control_qubit_mask()); - os << "Gate Type: "; + + ss << indent << "Gate Type: "; switch (obj.gate_type()) { case GateType::I: - os << "I"; + ss << "I"; break; case GateType::GlobalPhase: - os << "GlobalPhase"; + ss << "GlobalPhase"; break; case GateType::X: - os << "X"; + ss << "X"; break; case GateType::Y: - os << "Y"; + ss << "Y"; break; case GateType::Z: - os << "Z"; + ss << "Z"; break; case GateType::H: - os << "H"; + ss << "H"; break; case GateType::S: - os << "S"; + ss << "S"; break; case GateType::Sdag: - os << "Sdag"; + ss << "Sdag"; break; case GateType::T: - os << "T"; + ss << "T"; break; case GateType::Tdag: - os << "Tdag"; + ss << "Tdag"; break; case GateType::SqrtX: - os << "SqrtX"; + ss << "SqrtX"; break; case GateType::SqrtXdag: - os << "SqrtXdag"; + ss << "SqrtXdag"; break; case GateType::SqrtY: - os << "SqrtY"; + ss << "SqrtY"; break; case GateType::SqrtYdag: - os << "SqrtYdag"; + ss << "SqrtYdag"; break; case GateType::P0: - os << "P0"; + ss << "P0"; break; case GateType::P1: - os << "P1"; + ss << "P1"; break; case GateType::RX: - os << "RX"; + ss << "RX"; break; case GateType::RY: - os << "RY"; + ss << "RY"; break; case GateType::RZ: - os << "RZ"; + ss << "RZ"; break; case GateType::U1: - os << "U1"; + ss << "U1"; break; case GateType::U2: - os << "U2"; + ss << "U2"; break; case GateType::U3: - os << "U3"; + ss << "U3"; break; case GateType::OneTargetMatrix: - os << "OneTargetMatrix"; + ss << "OneTargetMatrix"; break; case GateType::CX: - os << "CX"; + ss << "CX"; break; case GateType::CZ: - os << "CZ"; + ss << "CZ"; break; case GateType::CCX: - os << "CCX"; + ss << "CCX"; break; case GateType::Swap: - os << "Swap"; + ss << "Swap"; break; case GateType::TwoTargetMatrix: - os << "TwoTargetMatrix"; + ss << "TwoTargetMatrix"; break; case GateType::Pauli: - os << "Pauli"; + ss << "Pauli"; break; case GateType::PauliRotation: - os << "PauliRotation"; + ss << "PauliRotation"; break; case GateType::Unknown: default: - os << "Unknown"; + ss << "Unknown"; break; } - os << "\n" << indent << "Target Qubits: {"; + + ss << "\n"; + ss << indent << " Target Qubits: {"; for (std::uint32_t i = 0; i < targets.size(); ++i) - os << targets[i] << (i == targets.size() - 1 ? "" : ", "); - os << "}\n" << indent << "Control Qubits: {"; + ss << targets[i] << (i == targets.size() - 1 ? "" : ", "); + ss << "}\n"; + ss << indent << " Control Qubits: {"; for (std::uint32_t i = 0; i < controls.size(); ++i) - os << controls[i] << (i == controls.size() - 1 ? "" : ", "); - os << "}"; + ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); + ss << "}"; + + return ss.str(); +} + +} // namespace internal + +template +std::ostream& operator<<(std::ostream& os, const internal::GatePtr& obj) { + os << internal::gate_to_string(obj); return os; } diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index e34c9e3a..f1a3be91 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -16,24 +16,39 @@ class ParamRXGateImpl; class ParamRYGateImpl; class ParamRZGateImpl; class ParamPauliRotationGateImpl; +class ParamProbablisticGateImpl; template class ParamGatePtr; } // namespace internal using ParamGate = internal::ParamGatePtr; -enum class ParamGateType { Unknown, ParamRX, ParamRY, ParamRZ, ParamPauliRotation }; +enum class ParamGateType { + Unknown, + ParamRX, + ParamRY, + ParamRZ, + ParamPauliRotation, + ParamProbablistic, + Error +}; template constexpr ParamGateType get_param_gate_type() { - if constexpr (std::is_same_v) return ParamGateType::Unknown; - if constexpr (std::is_same_v) return ParamGateType::ParamRX; - if constexpr (std::is_same_v) return ParamGateType::ParamRY; - if constexpr (std::is_same_v) return ParamGateType::ParamRZ; - if constexpr (std::is_same_v) + using TWithoutConst = std::remove_cv_t; + if constexpr (std::is_same_v) + return ParamGateType::Unknown; + if constexpr (std::is_same_v) + return ParamGateType::ParamRX; + if constexpr (std::is_same_v) + return ParamGateType::ParamRY; + if constexpr (std::is_same_v) + return ParamGateType::ParamRZ; + if constexpr (std::is_same_v) return ParamGateType::ParamPauliRotation; - static_assert("unknown ParamGateImpl"); - return ParamGateType::Unknown; + if constexpr (std::is_same_v) + return ParamGateType::ParamProbablistic; + return ParamGateType::Error; } namespace internal { @@ -56,13 +71,12 @@ class ParamGateBase { if (_target_mask & _control_mask) [[unlikely]] { throw std::runtime_error( "Error: ParamGate::ParamGate(std::uint64_t target_mask, std::uint64_t " - "control_mask) : Target and " - "control qubits must not overlap."); + "control_mask) : Target and control qubits must not overlap."); } } virtual ~ParamGateBase() = default; - [[nodiscard]] double param_coef() { return _pcoef; } + [[nodiscard]] double param_coef() const { return _pcoef; } [[nodiscard]] virtual std::vector target_qubit_list() const { return mask_to_vector(_target_mask); @@ -99,17 +113,23 @@ class ParamGatePtr { ParamGatePtr() : _param_gate_ptr(nullptr), _param_gate_type(get_param_gate_type()) {} ParamGatePtr(const ParamGatePtr& param_gate) = default; template - ParamGatePtr(const std::shared_ptr& param_gate_ptr) { + ParamGatePtr(const std::shared_ptr& param_gate_ptr) { if constexpr (std::is_same_v) { - _param_gate_type = get_param_gate_type(); + if ((_param_gate_type = get_param_gate_type()) == ParamGateType::Error) { + throw std::runtime_error("Unknown GateType"); + } _param_gate_ptr = param_gate_ptr; } else if constexpr (std::is_same_v) { // upcast - _param_gate_type = get_param_gate_type(); + if ((_param_gate_type = get_param_gate_type()) == ParamGateType::Error) { + throw std::runtime_error("Unknown GateType"); + } _param_gate_ptr = std::static_pointer_cast(param_gate_ptr); } else { // downcast - _param_gate_type = get_param_gate_type(); + if ((_param_gate_type = get_param_gate_type()) == ParamGateType::Error) { + throw std::runtime_error("Unknown GateType"); + } if (!(_param_gate_ptr = std::dynamic_pointer_cast(param_gate_ptr))) { throw std::runtime_error("invalid gate cast"); } @@ -143,42 +163,7 @@ class ParamGatePtr { return _param_gate_ptr.get(); } - friend std::ostream& operator<<(std::ostream& os, const ParamGatePtr& obj) { - if (!obj._param_gate_ptr) { - os << "Gate Type: Null"; - return os; - } - auto targets = internal::mask_to_vector(obj->target_qubit_mask()); - auto controls = internal::mask_to_vector(obj->control_qubit_mask()); - os << "Gate Type: "; - switch (obj.param_gate_type()) { - case ParamGateType::ParamRX: - os << "ParamRX"; - break; - case ParamGateType::ParamRY: - os << "ParamRY"; - break; - case ParamGateType::ParamRZ: - os << "ParamRZ"; - break; - case ParamGateType::ParamPauliRotation: - os << "ParamPauliRotation"; - break; - default: - os << "Undefined"; - break; - } - os << "\n" - "Target Qubits: {"; - for (std::uint32_t i = 0; i < targets.size(); ++i) - os << targets[i] << (i == targets.size() - 1 ? "" : ", "); - os << "}\n" - "Control Qubits: {"; - for (std::uint32_t i = 0; i < controls.size(); ++i) - os << controls[i] << (i == controls.size() - 1 ? "" : ", "); - os << "}"; - return os; - } + // 依存関係の都合上、operator<< の定義は gate_factory.hpp に定義 }; } // namespace internal diff --git a/scaluq/gate/param_gate_factory.hpp b/scaluq/gate/param_gate_factory.hpp index c76e0a9d..88c33413 100644 --- a/scaluq/gate/param_gate_factory.hpp +++ b/scaluq/gate/param_gate_factory.hpp @@ -46,4 +46,74 @@ inline ParamGate ParamProbablistic(const std::vector& distribution, distribution, gate_list); } } // namespace gate + +namespace internal { + +template +std::string gate_to_string(const ParamGatePtr& obj, std::uint32_t depth = 0) { + std::ostringstream ss; + std::string indent(depth * 2, ' '); + + if (obj.param_gate_type() == ParamGateType::ParamProbablistic) { + const auto prob_gate = ParamProbablisticGate(obj); + const auto distribution = prob_gate->distribution(); + const auto gates = prob_gate->gate_list(); + ss << indent << "Gate Type: Probablistic\n"; + for (std::size_t i = 0; i < distribution.size(); ++i) { + ss << indent << " --------------------\n"; + ss << indent << " Probability: " << distribution[i] << "\n"; + std::visit( + [&](auto&& arg) { + ss << gate_to_string(arg, depth + 1) + << (i == distribution.size() - 1 ? "" : "\n"); + }, + gates[i]); + } + return ss.str(); + } + + auto targets = internal::mask_to_vector(obj->target_qubit_mask()); + auto controls = internal::mask_to_vector(obj->control_qubit_mask()); + auto param_coef = obj->param_coef(); + + ss << indent << "Gate Type: "; + switch (obj.param_gate_type()) { + case ParamGateType::ParamRX: + ss << "ParamRX"; + break; + case ParamGateType::ParamRY: + ss << "ParamRY"; + break; + case ParamGateType::ParamRZ: + ss << "ParamRZ"; + break; + case ParamGateType::ParamPauliRotation: + ss << "ParamPauliRotation"; + break; + case ParamGateType::Unknown: + default: + ss << "Undefined"; + break; + } + + ss << "\n"; + ss << indent << " Parameter Coefficient: " << param_coef << "\n"; + ss << indent << " Target Qubits: {"; + for (std::uint32_t i = 0; i < targets.size(); ++i) + ss << targets[i] << (i == targets.size() - 1 ? "" : ", "); + ss << "}\n"; + ss << indent << " Control Qubits: {"; + for (std::uint32_t i = 0; i < controls.size(); ++i) + ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); + ss << "}"; + return ss.str(); +} +} // namespace internal + +template +std::ostream& operator<<(std::ostream& os, const internal::ParamGatePtr& obj) { + os << internal::gate_to_string(obj); + return os; +} + } // namespace scaluq From c770217133b55f662beae290c53f7aa9e7034fb5 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 6 Sep 2024 11:31:28 +0900 Subject: [PATCH 45/55] =?UTF-8?q?binding=E3=82=92=E5=88=86=E5=89=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/binding.cpp | 870 +----------------------- scaluq/circuit/circuit.hpp | 54 ++ scaluq/gate/gate.hpp | 105 ++- scaluq/gate/gate_factory.hpp | 189 ++++- scaluq/gate/gate_matrix.hpp | 11 + scaluq/gate/gate_pauli.hpp | 14 + scaluq/gate/gate_probablistic.hpp | 18 + scaluq/gate/gate_standard.hpp | 86 +++ scaluq/gate/merge_gate.hpp | 9 + scaluq/gate/param_gate.hpp | 91 ++- scaluq/gate/param_gate_factory.hpp | 49 +- scaluq/gate/param_gate_probablistic.hpp | 20 + scaluq/gate/param_gate_standard.hpp | 10 + scaluq/operator/operator.hpp | 55 ++ scaluq/operator/pauli_operator.hpp | 153 +++++ scaluq/state/state_vector.hpp | 95 +++ scaluq/state/state_vector_batched.hpp | 105 +++ scaluq/types.hpp | 15 + 18 files changed, 1085 insertions(+), 864 deletions(-) diff --git a/python/binding.cpp b/python/binding.cpp index 812c0285..319b5bb9 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -13,10 +13,13 @@ #include #include -#include - namespace nb = nanobind; using namespace nb::literals; + +#define SCALUQ_USE_NANOBIND + +#include + using namespace scaluq; using namespace std::string_literals; @@ -76,860 +79,29 @@ void cleanup() { } NB_MODULE(scaluq_core, m) { - m.def("finalize", - &finalize, - "Terminate the Kokkos execution environment. Release the resources.\n\n.. note:: " - "Finalization fails if there exists `StateVector` allocated. You must use " - "`StateVector` only inside inner scopes than the usage of `finalize` or delete all of " - "existing `StateVector`.\n\n.. note:: This is " - "automatically called when the program exits. If you call this manually, you cannot use " - "most of scaluq's functions until the program exits."); - m.def("is_finalized", &is_initialized, "Return true if `finalize()` is already called."); - - nb::class_(m, - "StateVector", - "Vector representation of quantum state.\n\n.. note:: Qubit index is " - "start from 0. If the amplitudes of $\\ket{b_{n-1}\\dots b_0}$ is " - "$b_i$, the state is $\\sum_i b_i 2^i$.") - .def(nb::init(), - "Construct state vector with specified qubits, initialized with computational " - "basis $\\ket{0\\dots0}$.") - .def(nb::init(), "Constructing state vector by copying other state.") - .def_static( - "Haar_random_state", - [](std::uint64_t n_qubits, std::optional seed) { - return StateVector::Haar_random_state(n_qubits, - seed.value_or(std::random_device{}())); - }, - "n_qubits"_a, - "seed"_a = std::nullopt, - "Constructing state vector with Haar random state. If seed is not specified, the value " - "from random device is used.") - .def("set_amplitude_at", - &StateVector::set_amplitude_at, - "Manually set amplitude at one index.") - .def("get_amplitude_at", - &StateVector::get_amplitude_at, - "Get amplitude at one index.\n\n.. note:: If you want to get all amplitudes, you " - "should " - "use `StateVector::get_amplitudes()`.") - .def("set_zero_state", - &StateVector::set_zero_state, - "Initialize with computational basis $\\ket{00\\dots0}$.") - .def("set_zero_norm_state", - &StateVector::set_zero_norm_state, - "Initialize with 0 (null vector).") - .def("set_computational_basis", - &StateVector::set_computational_basis, - "Initialize with computational basis \\ket{\\mathrm{basis}}.") - .def("amplitudes", - &StateVector::get_amplitudes, - "Get all amplitudes with as `list[complex]`.") - .def("n_qubits", &StateVector::n_qubits, "Get num of qubits.") - .def("dim", &StateVector::dim, "Get dimension of the vector ($=2^\\mathrm{n\\_qubits}$).") - .def("get_squared_norm", - &StateVector::get_squared_norm, - "Get squared norm of the state. $\\braket{\\psi|\\psi}$.") - .def("normalize", - &StateVector::normalize, - "Normalize state (let $\\braket{\\psi|\\psi} = 1$ by multiplying coef).") - .def("get_zero_probability", - &StateVector::get_zero_probability, - "Get the probability to observe $\\ket{0}$ at specified index.") - .def("get_marginal_probability", - &StateVector::get_marginal_probability, - "Get the marginal probability to observe as specified. Specify the result as n-length " - "list. `0` and `1` represent the qubit is observed and get the value. `2` represents " - "the qubit is not observed.") - .def("get_entropy", &StateVector::get_entropy, "Get the entropy of the vector.") - .def("add_state_vector", - &StateVector::add_state_vector, - "Add other state vector and make superposition. $\\ket{\\mathrm{this}} " - "\\leftarrow " - "\\ket{\\mathrm{this}} + \\ket{\\mathrm{state}}$.") - .def("add_state_vector_with_coef", - &StateVector::add_state_vector_with_coef, - "add other state vector with multiplying the coef and make superposition. " - "$\\ket{\\mathrm{this}}\\leftarrow\\ket{\\mathrm{this}}+\\mathrm{coef}" - "\\ket{\\mathrm{" - "state}}$.") - .def("multiply_coef", - &StateVector::multiply_coef, - "Multiply coef. " - "$\\ket{\\mathrm{this}}\\leftarrow\\mathrm{coef}\\ket{\\mathrm{this}}$.") - .def( - "sampling", - [](const StateVector &state, - std::uint64_t sampling_count, - std::optional seed) { - return state.sampling(sampling_count, seed.value_or(std::random_device{}())); - }, - "sampling_count"_a, - "seed"_a = std::nullopt, - "Sampling specified times. Result is `list[int]` with the `sampling_count` length.") - .def("to_string", &StateVector::to_string, "Information as `str`.") - .def("load", &StateVector::load, "Load amplitudes of `list[int]` with `dim` length.") - .def("__str__", &StateVector::to_string, "Information as `str`.") - .def_ro_static("UNMEASURED", - &StateVector::UNMEASURED, - "Constant used for `StateVector::get_marginal_probability` to express the " - "the qubit is not measured."); - - nb::class_( - m, - "StateVectorBatched", - "Batched vector representation of quantum state.\n\n.. note:: Qubit index is start from 0. " - "If the amplitudes of $\\ket{b_{n-1}\\dots b_0}$ is $b_i$, the state is $\\sum_i b_i " - "2^i$.") - .def(nb::init(), - "Construct batched state vector with specified batch size and qubits.") - .def(nb::init(), - "Constructing batched state vector by copying other batched state.") - .def("n_qubits", &StateVectorBatched::n_qubits, "Get num of qubits.") - .def("dim", - &StateVectorBatched::dim, - "Get dimension of the vector ($=2^\\mathrm{n\\_qubits}$).") - .def("batch_size", &StateVectorBatched::batch_size, "Get batch size.") - .def("set_state_vector", - nb::overload_cast(&StateVectorBatched::set_state_vector), - "Set the state vector for all batches.") - .def("set_state_vector", - nb::overload_cast( - &StateVectorBatched::set_state_vector), - "Set the state vector for a specific batch.") - .def("get_state_vector_at", - &StateVectorBatched::get_state_vector_at, - "Get the state vector for a specific batch.") - .def("set_zero_state", - &StateVectorBatched::set_zero_state, - "Initialize all batches with computational basis $\\ket{00\\dots0}$.") - .def("set_zero_norm_state", - &StateVectorBatched::set_zero_norm_state, - "Initialize with 0 (null vector).") - .def("set_computational_basis", - &StateVectorBatched::set_computational_basis, - "Initialize with computational basis \\ket{\\mathrm{basis}}.") - .def( - "sampling", - [](const StateVectorBatched &states, - std::uint64_t sampling_count, - std::optional seed) { - return states.sampling(sampling_count, seed.value_or(std::random_device{}())); - }, - "sampling_count"_a, - "seed"_a = std::nullopt, - "Sampling specified times. Result is `list[list[int]]` with the `sampling_count` " - "length.") - .def_static( - "Haar_random_states", - [](std::uint64_t batch_size, - std::uint64_t n_qubits, - bool set_same_state, - std::optional seed) { - return StateVectorBatched::Haar_random_states( - batch_size, n_qubits, set_same_state, seed.value_or(std::random_device{}())); - }, - "batch_size"_a, - "n_qubits"_a, - "set_same_state"_a, - "seed"_a = std::nullopt, - "Construct batched state vectors with Haar random states. If seed is not " - "specified, the value from random device is used.") - .def("amplitudes", - &StateVectorBatched::get_amplitudes, - "Get all amplitudes with as `list[list[complex]]`.") - .def("get_squared_norm", - &StateVectorBatched::get_squared_norm, - "Get squared norm of each state in the batch. $\\braket{\\psi|\\psi}$.") - .def("normalize", - &StateVectorBatched::normalize, - "Normalize each state in the batch (let $\\braket{\\psi|\\psi} = 1$ by " - "multiplying coef).") - .def("get_zero_probability", - &StateVectorBatched::get_zero_probability, - "Get the probability to observe $\\ket{0}$ at specified index for each state in " - "the batch.") - .def("get_marginal_probability", - &StateVectorBatched::get_marginal_probability, - "Get the marginal probability to observe as specified for each state in the batch. " - "Specify the result as n-length list. `0` and `1` represent the qubit is observed " - "and get the value. `2` represents the qubit is not observed.") - .def("get_entropy", - &StateVectorBatched::get_entropy, - "Get the entropy of each state in the batch.") - .def("add_state_vector", - &StateVectorBatched::add_state_vector, - "Add other batched state vectors and make superposition. $\\ket{\\mathrm{this}} " - "\\leftarrow \\ket{\\mathrm{this}} + \\ket{\\mathrm{states}}$.") - .def("add_state_vector_with_coef", - &StateVectorBatched::add_state_vector_with_coef, - "Add other batched state vectors with multiplying the coef and make superposition. " - "$\\ket{\\mathrm{this}}\\leftarrow\\ket{\\mathrm{this}}+\\mathrm{coef}" - "\\ket{\\mathrm{states}}$.") - .def("load", - &StateVectorBatched::load, - "Load batched amplitudes from `list[list[complex]]`.") - .def("copy", &StateVectorBatched::copy, "Create a copy of the batched state vector.") - .def("to_string", &StateVectorBatched::to_string, "Information as `str`.") - .def("__str__", &StateVectorBatched::to_string, "Information as `str`."); - - nb::enum_(m, "GateType", "Enum of Gate Type.") - .value("I", GateType::I) - .value("GlobalPhase", GateType::GlobalPhase) - .value("X", GateType::X) - .value("Y", GateType::Y) - .value("Z", GateType::Z) - .value("H", GateType::H) - .value("S", GateType::S) - .value("Sdag", GateType::Sdag) - .value("T", GateType::T) - .value("Tdag", GateType::Tdag) - .value("SqrtX", GateType::SqrtX) - .value("SqrtXdag", GateType::SqrtXdag) - .value("SqrtY", GateType::SqrtY) - .value("SqrtYdag", GateType::SqrtYdag) - .value("P0", GateType::P0) - .value("P1", GateType::P1) - .value("RX", GateType::RX) - .value("RY", GateType::RY) - .value("RZ", GateType::RZ) - .value("U1", GateType::U1) - .value("U2", GateType::U2) - .value("U3", GateType::U3) - .value("OneTargetMatrix", GateType::OneTargetMatrix) - .value("Swap", GateType::Swap) - .value("TwoTargetMatrix", GateType::TwoTargetMatrix) - .value("Pauli", GateType::Pauli) - .value("PauliRotation", GateType::PauliRotation); - -#define DEF_GATE_BASE(GATE_TYPE, DESCRIPTION) \ - nb::class_(m, #GATE_TYPE, DESCRIPTION) \ - .def("gate_type", &GATE_TYPE::gate_type, "Get gate type as `GateType` enum.") \ - .def( \ - "target_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->target_qubit_list(); }, \ - "Get target qubits as `list[int]`. **Control qubits is not included.**") \ - .def( \ - "control_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->control_qubit_list(); }, \ - "Get control qubits as `list[int]`.") \ - .def( \ - "operand_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->operand_qubit_list(); }, \ - "Get target and control qubits as `list[int]`.") \ - .def( \ - "target_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->target_qubit_mask(); }, \ - "Get target qubits as mask. **Control qubits is not included.**") \ - .def( \ - "control_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->control_qubit_mask(); }, \ - "Get control qubits as mask.") \ - .def( \ - "operand_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->operand_qubit_mask(); }, \ - "Get target and control qubits as mask.") \ - .def( \ - "get_inverse", \ - [](const GATE_TYPE &gate) { return gate->get_inverse(); }, \ - "Generate inverse gate as `Gate` type. If not exists, return None.") \ - .def( \ - "update_quantum_state", \ - [](const GATE_TYPE &gate, StateVector &state_vector) { \ - gate->update_quantum_state(state_vector); \ - }, \ - "Apply gate to `state_vector`. `state_vector` in args is directly updated.") \ - .def( \ - "get_matrix", \ - [](const GATE_TYPE &gate) { return gate->get_matrix(); }, \ - "Get matrix representation of the gate.") - -#define DEF_GATE(GATE_TYPE, DESCRIPTION) \ - DEF_GATE_BASE( \ - GATE_TYPE, \ - DESCRIPTION \ - "\n\n.. note:: Upcast is required to use gate-general functions (ex: add to Circuit).") \ - .def(nb::init()) - - DEF_GATE_BASE(Gate, - "General class of QuantumGate.\n\n.. note:: Downcast to requred to use " - "gate-specific functions.") - .def(nb::init(), "Upcast from `IGate`.") - .def(nb::init(), "Upcast from `GlobalPhaseGate`.") - .def(nb::init(), "Upcast from `XGate`.") - .def(nb::init(), "Upcast from `YGate`.") - .def(nb::init(), "Upcast from `ZGate`.") - .def(nb::init(), "Upcast from `HGate`.") - .def(nb::init(), "Upcast from `SGate`.") - .def(nb::init(), "Upcast from `SdagGate`.") - .def(nb::init(), "Upcast from `TGate`.") - .def(nb::init(), "Upcast from `TdagGate`.") - .def(nb::init(), "Upcast from `SqrtXGate`.") - .def(nb::init(), "Upcast from `SqrtXdagGate`.") - .def(nb::init(), "Upcast from `SqrtYGate`.") - .def(nb::init(), "Upcast from `SqrtYdagGate`.") - .def(nb::init(), "Upcast from `P0Gate`.") - .def(nb::init(), "Upcast from `P1Gate`.") - .def(nb::init(), "Upcast from `RXGate`.") - .def(nb::init(), "Upcast from `RYGate`.") - .def(nb::init(), "Upcast from `RZGate`.") - .def(nb::init(), "Upcast from `U1Gate`.") - .def(nb::init(), "Upcast from `U2Gate`.") - .def(nb::init(), "Upcast from `U3Gate`.") - .def(nb::init(), "Upcast from `OneTargetMatrixGate`.") - .def(nb::init(), "Upcast from `SwapGate`.") - .def(nb::init(), "Upcast from `TwoTargetMatrixGate`.") - .def(nb::init(), "Upcast from `PauliGate`.") - .def(nb::init(), "Upcast from `PauliRotationGate`."); - - DEF_GATE(IGate, "Specific class of Pauli-I gate."); - DEF_GATE(GlobalPhaseGate, - "Specific class of gate, which rotate global phase, represented as " - "$e^{i\\mathrm{phase}}I$.") - .def( - "phase", - [](const GlobalPhaseGate &gate) { return gate->phase(); }, - "Get `phase` property"); - DEF_GATE(XGate, "Specific class of Pauli-X gate."); - DEF_GATE(YGate, "Specific class of Pauli-Y gate."); - DEF_GATE(ZGate, "Specific class of Pauli-Z gate."); - DEF_GATE(HGate, "Specific class of Hadamard gate."); - DEF_GATE(SGate, - "Specific class of S gate, represented as $\\begin{bmatrix}\n1 & 0\\\\\n0 & " - "i\n\\end{bmatrix}$."); - DEF_GATE(SdagGate, "Specific class of inverse of S gate."); - DEF_GATE(TGate, - "Specific class of T gate, represented as $\\begin{bmatrix}\n1 & 0\\\\\n0 & " - "e^{i\\pi/4}\n\\end{bmatrix}$."); - DEF_GATE(TdagGate, "Specific class of inverse of T gate."); - DEF_GATE(SqrtXGate, - "Specific class of sqrt(X) gate, represented as $\\begin{bmatrix}\n1+i & 1-i\\\\\n1-i " - "& 1+i\n\\end{bmatrix}$."); - DEF_GATE(SqrtXdagGate, "Specific class of inverse of sqrt(X) gate."); - DEF_GATE(SqrtYGate, - "Specific class of sqrt(Y) gate, represented as $\\begin{bmatrix}\n1+i & -1-i " - "\\\\\n1+i & 1+i\n\\end{bmatrix}$."); - DEF_GATE(SqrtYdagGate, "Specific class of inverse of sqrt(Y) gate."); - DEF_GATE( - P0Gate, - "Specific class of projection gate to $\\ket{0}$.\n\n.. note:: This gate is not unitary."); - DEF_GATE( - P1Gate, - "Specific class of projection gate to $\\ket{1}$.\n\n.. note:: This gate is not unitary."); - -#define DEF_ROTATION_GATE(GATE_TYPE, DESCRIPTION) \ - DEF_GATE(GATE_TYPE, DESCRIPTION) \ - .def( \ - "angle", [](const GATE_TYPE &gate) { return gate->angle(); }, "Get `angle` property.") - - DEF_ROTATION_GATE( - RXGate, - "Specific class of X rotation gate, represented as $e^{-i\\frac{\\mathrm{angle}}{2}X}$."); - DEF_ROTATION_GATE( - RYGate, - "Specific class of Y rotation gate, represented as $e^{-i\\frac{\\mathrm{angle}}{2}Y}$."); - DEF_ROTATION_GATE( - RZGate, - "Specific class of Z rotation gate, represented as $e^{-i\\frac{\\mathrm{angle}}{2}Z}$."); - - DEF_GATE(U1Gate, - "Specific class of IBMQ's U1 Gate, which is a rotation abount Z-axis, " - "represented as " - "$\\begin{bmatrix}\n1 & 0\\\\\n0 & e^{i\\lambda}\n\\end{bmatrix}$.") - .def( - "lambda_", [](const U1Gate &gate) { return gate->lambda(); }, "Get `lambda` property."); - DEF_GATE(U2Gate, - "Specific class of IBMQ's U2 Gate, which is a rotation about X+Z-axis, " - "represented as " - "$\\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.") - .def( - "lambda_", [](const U2Gate &gate) { return gate->lambda(); }, "Get `lambda` property."); - DEF_GATE(U3Gate, - "Specific class of IBMQ's U3 Gate, which is a rotation abount 3 axis, " - "represented as " - "$\\begin{bmatrix}\n\\cos \\frac{\\theta}{2} & " - "-e^{i\\lambda}\\sin\\frac{\\theta}{2}\\\\\n" - "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.") - .def( - "phi", [](const U3Gate &gate) { return gate->phi(); }, "Get `phi` property.") - .def( - "lambda_", [](const U3Gate &gate) { return gate->lambda(); }, "Get `lambda` property."); - - DEF_GATE(OneTargetMatrixGate, "Specific class of single-qubit dense matrix gate.") - .def("matrix", [](const OneTargetMatrixGate &gate) { return gate->matrix(); }); - - DEF_GATE(PauliGate, - "Specific class of multi-qubit pauli gate, which applies single-qubit Pauli " - "gate to " - "each of qubit."); - DEF_GATE(PauliRotationGate, - "Specific class of multi-qubit pauli-rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}P}$."); + internal::bind_types_hpp(m); - DEF_GATE(ProbablisticGate, - "Specific class of probablistic gate. The gate to apply is picked from a cirtain " - "distribution.") - .def( - "gate_list", - [](const ProbablisticGate &gate) { return gate->gate_list(); }, - nb::rv_policy::reference) - .def( - "distribution", - [](const ProbablisticGate &gate) { return gate->distribution(); }, - nb::rv_policy::reference); + internal::bind_state_state_vector_hpp(m); + internal::bind_state_state_vector_batched_hpp(m); auto mgate = m.def_submodule("gate", "Define gates."); -#define DEF_GATE_FACTORY(GATE_NAME) \ - mgate.def( \ - #GATE_NAME, &gate::GATE_NAME, "Generate general Gate class instance of " #GATE_NAME ".") + internal::bind_gate_gate_hpp(m); + internal::bind_gate_gate_standard_hpp(m); + internal::bind_gate_gate_matrix_hpp(m); + internal::bind_gate_gate_pauli_hpp(m); + internal::bind_gate_gate_factory_hpp(mgate); + internal::bind_gate_param_gate_hpp(m); + internal::bind_gate_param_gate_standard_hpp(m); + internal::bind_gate_param_gate_probablistic_hpp(m); + internal::bind_gate_param_gate_factory(mgate); + // internal::bind_gate_merge_gate_hpp(m); - DEF_GATE_FACTORY(I); - DEF_GATE_FACTORY(GlobalPhase); - DEF_GATE_FACTORY(X); - DEF_GATE_FACTORY(Y); - DEF_GATE_FACTORY(Z); - DEF_GATE_FACTORY(H); - DEF_GATE_FACTORY(S); - DEF_GATE_FACTORY(Sdag); - DEF_GATE_FACTORY(T); - DEF_GATE_FACTORY(Tdag); - DEF_GATE_FACTORY(SqrtX); - DEF_GATE_FACTORY(SqrtXdag); - DEF_GATE_FACTORY(SqrtY); - DEF_GATE_FACTORY(SqrtYdag); - DEF_GATE_FACTORY(P0); - DEF_GATE_FACTORY(P1); - DEF_GATE_FACTORY(RX); - DEF_GATE_FACTORY(RY); - DEF_GATE_FACTORY(RZ); - DEF_GATE_FACTORY(U1); - DEF_GATE_FACTORY(U2); - DEF_GATE_FACTORY(U3); - DEF_GATE_FACTORY(OneTargetMatrix); - mgate.def( - "CX", - &gate::CX, - "Generate general Gate class instance of CX.\n\n.. note:: CX is a specialization of X."); - mgate.def("CNot", - &gate::CX, - "Generate general Gate class instance of CNot.\n\n.. note:: CNot is an alias of CX."); - mgate.def( - "CZ", - &gate::CZ, - "Generate general Gate class instance of CZ.\n\n.. note:: CZ is a specialization of Z."); - mgate.def( - "CCX", - &gate::CCX, - "Generate general Gate class instance of CXX.\n\n.. note:: CX is a specialization of X."); - mgate.def( - "CCNot", - &gate::CCX, - "Generate general Gate class instance of CCNot.\n\n.. note:: CCNot is an alias of CCX."); - mgate.def("Toffoli", - &gate::CCX, - "Generate general Gate class instance of Toffoli.\n\n.. note:: Toffoli is an alias " - "of CCX."); - DEF_GATE_FACTORY(Swap); - DEF_GATE_FACTORY(TwoTargetMatrix); - DEF_GATE_FACTORY(Pauli); - DEF_GATE_FACTORY(PauliRotation); - mgate.def("DenseMatrix", - &gate::DenseMatrix, - "Generate general Gate class instance of DenseMatrix. IGate, OneTargetMatrixGate or " - "TwoTargetMatrixGate correspond to len(target) is created. The case len(target) >= 3 " - "is currently not supported."); - DEF_GATE_FACTORY(Probablistic); + internal::bind_circuit_circuit_hpp(m); - nb::enum_(m, "ParamGateType", "Enum of ParamGate Type.") - .value("ParamRX", ParamGateType::ParamRX) - .value("ParamRY", ParamGateType::ParamRY) - .value("ParamRZ", ParamGateType::ParamRZ) - .value("ParamPauliRotation", ParamGateType::ParamPauliRotation); - - m.def( - "merge_gate", &merge_gate, "Merge two gates. return value is (merged gate, global phase)."); - -#define DEF_PGATE_BASE(PGATE_TYPE, DESCRIPTION) \ - nb::class_(m, #PGATE_TYPE, DESCRIPTION) \ - .def("param_gate_type", \ - &PGATE_TYPE::param_gate_type, \ - "Get parametric gate type as `ParamGateType` enum.") \ - .def( \ - "target_qubit_list", \ - [](const PGATE_TYPE &gate) { return gate->target_qubit_list(); }, \ - "Get target qubits as `list[int]`. **Control qubits is not included.**") \ - .def( \ - "control_qubit_list", \ - [](const PGATE_TYPE &gate) { return gate->control_qubit_list(); }, \ - "Get control qubits as `list[int]`.") \ - .def( \ - "operand_qubit_list", \ - [](const PGATE_TYPE &gate) { return gate->operand_qubit_list(); }, \ - "Get target and control qubits as `list[int]`.") \ - .def( \ - "target_qubit_mask", \ - [](const PGATE_TYPE &gate) { return gate->target_qubit_mask(); }, \ - "Get target qubits as mask. **Control qubits is not included.**") \ - .def( \ - "control_qubit_mask", \ - [](const PGATE_TYPE &gate) { return gate->control_qubit_mask(); }, \ - "Get control qubits as mask.") \ - .def( \ - "operand_qubit_mask", \ - [](const PGATE_TYPE &gate) { return gate->operand_qubit_mask(); }, \ - "Get target and control qubits as mask.") \ - .def( \ - "get_inverse", \ - [](const PGATE_TYPE ¶m_gate) { return param_gate->get_inverse(); }, \ - "Generate inverse parametric-gate as `ParamGate` type. If not exists, return None.") \ - .def( \ - "update_quantum_state", \ - [](const PGATE_TYPE ¶m_gate, StateVector &state_vector, double param) { \ - param_gate->update_quantum_state(state_vector, param); \ - }, \ - "Apply gate to `state_vector` with holding the parameter. `state_vector` in args is " \ - "directly updated.") \ - .def( \ - "get_matrix", \ - [](const PGATE_TYPE &gate, double param) { return gate->get_matrix(param); }, \ - "Get matrix representation of the gate with holding the parameter.") - -#define DEF_PGATE(PGATE_TYPE, DESCRIPTION) \ - DEF_PGATE_BASE( \ - PGATE_TYPE, \ - DESCRIPTION \ - "\n\n.. note:: Upcast is required to use gate-general functions (ex: add to Circuit).") \ - .def(nb::init()) - - DEF_PGATE_BASE( - ParamGate, - "General class of parametric quantum gate.\n\n.. note:: Downcast to requred to use " - "gate-specific functions.") - .def(nb::init(), "Upcast from `ParamRXGate`.") - .def(nb::init(), "Upcast from `ParamRYGate`.") - .def(nb::init(), "Upcast from `ParamRZGate`.") - .def(nb::init(), "Upcast from `ParamPauliRotationGate`."); - - DEF_PGATE(ParamRXGate, - "Specific class of parametric X rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}X}$. `angle` is given as `param * param_coef`."); - DEF_PGATE(ParamRYGate, - "Specific class of parametric Y rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}Y}$. `angle` is given as `param * param_coef`."); - DEF_PGATE(ParamRZGate, - "Specific class of parametric Z rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}Z}$. `angle` is given as `param * param_coef`."); - - DEF_PGATE(ParamPauliRotationGate, - "Specific class of parametric multi-qubit pauli-rotation gate, represented as " - "$e^{-i\\frac{\\mathrm{angle}}{2}P}$. `angle` is given as `param * param_coef`."); - - DEF_PGATE(ParamProbablisticGate, - "Specific class of parametric probablistic gate. The gate to apply is picked from a " - "cirtain " - "distribution.") - .def( - "gate_list", - [](const ParamProbablisticGate &gate) { return gate->gate_list(); }, - nb::rv_policy::reference) - .def( - "distribution", - [](const ParamProbablisticGate &gate) { return gate->distribution(); }, - nb::rv_policy::reference); - - mgate.def("ParamRX", - &gate::ParamRX, - "Generate general ParamGate class instance of ParamRX.", - "target"_a, - "coef"_a = 1., - "controls"_a = std::vector{}); - mgate.def("ParamRY", - &gate::ParamRY, - "Generate general ParamGate class instance of ParamRY.", - "target"_a, - "coef"_a = 1., - "controls"_a = std::vector{}); - mgate.def("ParamRZ", - &gate::ParamRZ, - "Generate general ParamGate class instance of ParamRZ.", - "target"_a, - "coef"_a = 1., - "controls"_a = std::vector{}); - mgate.def("ParamPauliRotation", - &gate::ParamPauliRotation, - "Generate general ParamGate class instance of ParamPauliRotation.", - "pauli"_a, - "coef"_a = 1., - "controls"_a = std::vector{}); - mgate.def("ParamProbablistic", - &gate::ParamProbablistic, - "Generate general ParamGate class instance of ParamProbablistic."); - mgate.def( - "ParamProbablistic", - [](const std::vector>> &prob_gate_list) { - std::vector distribution; - std::vector> gate_list; - distribution.reserve(prob_gate_list.size()); - gate_list.reserve(prob_gate_list.size()); - for (const auto &[prob, gate] : prob_gate_list) { - distribution.push_back(prob); - gate_list.push_back(gate); - } - return gate::ParamProbablistic(distribution, gate_list); - }, - "Generate general ParamGate class instance of ParamProbablistic."); - - nb::class_(m, "Circuit", "Quantum circuit represented as gate array") - .def(nb::init(), "Initialize empty circuit of specified qubits.") - .def("n_qubits", &Circuit::n_qubits, "Get property of `n_qubits`.") - .def("gate_list", - &Circuit::gate_list, - "Get property of `gate_list`.", - nb::rv_policy::reference) - .def("n_gates", &Circuit::n_gates, "Get property of `n_gates`.") - .def("key_set", &Circuit::key_set, "Get set of keys of parameters.") - .def("get_gate_at", &Circuit::get_gate_at, "Get reference of i-th gate.") - .def("get_param_key_at", - &Circuit::get_param_key_at, - "Get parameter key of i-th gate. If it is not parametric, return None.") - .def("calculate_depth", &Circuit::calculate_depth, "Get depth of circuit.") - .def("add_gate", - nb::overload_cast(&Circuit::add_gate), - "Add gate. Given gate is copied.") - .def("add_param_gate", - nb::overload_cast(&Circuit::add_param_gate), - "Add parametric gate with specifing key. Given param_gate is copied.") - .def("add_circuit", - nb::overload_cast(&Circuit::add_circuit), - "Add all gates in specified circuit. Given gates are copied.") - .def("update_quantum_state", - &Circuit::update_quantum_state, - "Apply gate to the StateVector. StateVector in args is directly updated. If the " - "circuit contains parametric gate, you have to give real value of parameter as " - "dict[str, float] in 2nd arg.") - .def( - "update_quantum_state", - [&](const Circuit &circuit, StateVector &state, nb::kwargs kwargs) { - std::map parameters; - for (auto &&[key, param] : kwargs) { - parameters[nb::cast(key)] = nb::cast(param); - } - circuit.update_quantum_state(state, parameters); - }, - "Apply gate to the StateVector. StateVector in args is directly updated. If the " - "circuit contains parametric gate, you have to give real value of parameter as " - "\"name=value\" format in kwargs.") - .def( - "update_quantum_state", - [](const Circuit &circuit, StateVector &state) { circuit.update_quantum_state(state); }) - .def("copy", &Circuit::copy, "Copy circuit. All the gates inside is copied.") - .def("get_inverse", - &Circuit::get_inverse, - "Get inverse of circuit. ALl the gates are newly created."); - - nb::enum_(m, "PauliID") - .value("I", PauliOperator::I) - .value("X", PauliOperator::X) - .value("Y", PauliOperator::Y) - .value("Z", PauliOperator::Z) - .export_values(); - - nb::class_( - m, "PauliOperatorData", "Internal data structure for PauliOperator.") - .def(nb::init(), "coef"_a = 1., "Initialize data with coefficient.") - .def(nb::init(), - "pauli_string"_a, - "coef"_a = 1., - "Initialize data with pauli string.") - .def(nb::init &, - const std::vector &, - Complex>(), - "target_qubit_list"_a, - "pauli_id_list"_a, - "coef"_a = 1., - "Initialize data with target qubits and pauli ids.") - .def(nb::init &, Complex>(), - "pauli_id_par_qubit"_a, - "coef"_a = 1., - "Initialize data with pauli ids per qubit.") - .def(nb::init &, const std::vector &, Complex>(), - "bit_flip_mask"_a, - "phase_flip_mask"_a, - "coef"_a = 1., - "Initialize data with bit flip and phase flip masks.") - .def(nb::init(), - "data"_a, - "Initialize pauli operator from Data object.") - .def("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("set_coef", - &PauliOperator::Data::set_coef, - "c"_a, - "Set the coefficient of the Pauli operator.") - .def("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("get_XZ_mask_representation", - &PauliOperator::Data::get_XZ_mask_representation, - "Get the X and Z mask representation as a tuple of vectors."); - - nb::class_( - m, - "PauliOperator", - "Pauli operator as coef and tensor product of single pauli for each qubit.") - .def(nb::init(), "coef"_a = 1., "Initialize operator which just multiplying coef.") - .def(nb::init &, - const std::vector &, - Complex>(), - "target_qubit_list"_a, - "pauli_id_list"_a, - "coef"_a = 1., - "Initialize pauli operator. For each `i`, single pauli correspond to " - "`pauli_id_list[i]` is applied to `target_qubit_list`-th qubit.") - .def(nb::init(), - "pauli_string"_a, - "coef"_a = 1., - "Initialize pauli operator. If `pauli_string` is `\"X0Y2\"`, Pauli-X is applied to " - "0-th qubit and Pauli-Y is applied to 2-th qubit. In `pauli_string`, spaces are " - "ignored.") - .def(nb::init &, Complex>(), - "pauli_id_par_qubit"_a, - "coef"_a = 1., - "Initialize pauli operator. For each `i`, single pauli correspond to " - "`paul_id_per_qubit` is applied to `i`-th qubit.") - .def( - "__init__", - [](PauliOperator *t, - nb::int_ bit_flip_mask_py, - nb::int_ phase_flip_mask_py, - Complex coef) { - internal::BitVector bit_flip_mask(0), phase_flip_mask(0); - const nb::int_ mask(~0ULL); - auto &bit_flip_raw = bit_flip_mask.data_raw(); - assert(bit_flip_raw.empty()); - while (bit_flip_mask_py > nb::int_(0)) { - bit_flip_raw.push_back((std::uint64_t)nb::int_(bit_flip_mask_py & mask)); - bit_flip_mask_py >>= nb::int_(64); - } - auto &phase_flip_raw = phase_flip_mask.data_raw(); - assert(phase_flip_raw.empty()); - while (phase_flip_mask_py > nb::int_(0)) { - phase_flip_raw.push_back((std::uint64_t)nb::int_(phase_flip_mask_py & mask)); - phase_flip_mask_py >>= nb::int_(64); - } - new (t) PauliOperator(bit_flip_mask, phase_flip_mask, coef); - }, - "bit_flip_mask"_a, - "phase_flip_mask"_a, - "coef"_a = 1., - "Initialize pauli operator. For each `i`, single pauli applied to `i`-th qubit is got " - "from `i-th` bit of `bit_flip_mask` and `phase_flip_mask` as follows.\n\n.. " - "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("target_qubit_list", - &PauliOperator::target_qubit_list, - "Get qubits to be applied pauli.") - .def("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", - [](const PauliOperator &pauli) { - const auto [x_mask, z_mask] = pauli.get_XZ_mask_representation(); - nb::int_ x_mask_py(0); - for (std::uint64_t i = 0; i < x_mask.size(); ++i) { - x_mask_py |= nb::int_(x_mask[i]) << nb::int_(i); - } - nb::int_ z_mask_py(0); - for (std::uint64_t i = 0; i < z_mask.size(); ++i) { - z_mask_py |= nb::int_(z_mask[i]) << nb::int_(i); - } - return std::make_tuple(x_mask_py, z_mask_py); - }, - "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, - "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_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("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, - "Get transition amplitude of measuring state vector. $\\bra{\\chi}P\\ket{\\psi}$.") - .def(nb::self * nb::self) - .def(nb::self * Complex()); + internal::bind_operator_pauli_operator_hpp(m); + internal::bind_operator_operator_hpp(m); - 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("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.") - .def("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) { - return op.add_random_operator(operator_count, - seed.value_or(std::random_device{}())); - }, - "operator_count"_a, - "seed"_a = std::nullopt, - "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("get_dagger", - &Operator::get_dagger, - "Get the adjoint (Hermitian conjugate) of the operator.") - .def("apply_to_state", &Operator::apply_to_state, "Apply the operator to a state vector.") - .def("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, - "Get the transition amplitude of the operator between two state vectors.") - .def(nb::self *= Complex()) - .def(nb::self * Complex()) - .def(+nb::self) - .def(-nb::self) - .def(nb::self += nb::self) - .def(nb::self + nb::self) - .def(nb::self -= nb::self) - .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()); initialize(); std::atexit(&cleanup); } diff --git a/scaluq/circuit/circuit.hpp b/scaluq/circuit/circuit.hpp index 21a21768..05d22cf5 100644 --- a/scaluq/circuit/circuit.hpp +++ b/scaluq/circuit/circuit.hpp @@ -62,4 +62,58 @@ class Circuit { void check_gate_is_valid(const Gate& gate) const; void check_gate_is_valid(const ParamGate& gate) const; }; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_circuit_circuit_hpp(nb::module_& m) { + nb::class_(m, "Circuit", "Quantum circuit represented as gate array") + .def(nb::init(), "Initialize empty circuit of specified qubits.") + .def("n_qubits", &Circuit::n_qubits, "Get property of `n_qubits`.") + .def("gate_list", + &Circuit::gate_list, + "Get property of `gate_list`.", + nb::rv_policy::reference) + .def("n_gates", &Circuit::n_gates, "Get property of `n_gates`.") + .def("key_set", &Circuit::key_set, "Get set of keys of parameters.") + .def("get_gate_at", &Circuit::get_gate_at, "Get reference of i-th gate.") + .def("get_param_key_at", + &Circuit::get_param_key_at, + "Get parameter key of i-th gate. If it is not parametric, return None.") + .def("calculate_depth", &Circuit::calculate_depth, "Get depth of circuit.") + .def("add_gate", + nb::overload_cast(&Circuit::add_gate), + "Add gate. Given gate is copied.") + .def("add_param_gate", + nb::overload_cast(&Circuit::add_param_gate), + "Add parametric gate with specifing key. Given param_gate is copied.") + .def("add_circuit", + nb::overload_cast(&Circuit::add_circuit), + "Add all gates in specified circuit. Given gates are copied.") + .def("update_quantum_state", + &Circuit::update_quantum_state, + "Apply gate to the StateVector. StateVector in args is directly updated. If the " + "circuit contains parametric gate, you have to give real value of parameter as " + "dict[str, float] in 2nd arg.") + .def( + "update_quantum_state", + [&](const Circuit& circuit, StateVector& state, nb::kwargs kwargs) { + std::map parameters; + for (auto&& [key, param] : kwargs) { + parameters[nb::cast(key)] = nb::cast(param); + } + circuit.update_quantum_state(state, parameters); + }, + "Apply gate to the StateVector. StateVector in args is directly updated. If the " + "circuit contains parametric gate, you have to give real value of parameter as " + "\"name=value\" format in kwargs.") + .def( + "update_quantum_state", + [](const Circuit& circuit, StateVector& state) { circuit.update_quantum_state(state); }) + .def("copy", &Circuit::copy, "Copy circuit. All the gates inside is copied.") + .def("get_inverse", + &Circuit::get_inverse, + "Get inverse of circuit. ALl the gates are newly created."); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 527402df..a5949b64 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -127,7 +127,7 @@ namespace internal { class GateBase : public std::enable_shared_from_this { protected: std::uint64_t _target_mask, _control_mask; - void check_qubit_mask_within_bounds(const StateVector& state_vector) const { + void check_qubit_mask_within_bounds(const StateVector &state_vector) const { std::uint64_t full_mask = (1ULL << state_vector.n_qubits()) - 1; if ((_target_mask | _control_mask) > full_mask) [[unlikely]] { throw std::runtime_error( @@ -166,7 +166,7 @@ class GateBase : public std::enable_shared_from_this { [[nodiscard]] virtual Gate get_inverse() const = 0; [[nodiscard]] virtual ComplexMatrix get_matrix() const = 0; - virtual void update_quantum_state(StateVector& state_vector) const = 0; + virtual void update_quantum_state(StateVector &state_vector) const = 0; }; template @@ -181,9 +181,9 @@ class GatePtr { public: GatePtr() : _gate_ptr(nullptr), _gate_type(get_gate_type()) {} - GatePtr(const GatePtr& gate) = default; + GatePtr(const GatePtr &gate) = default; template - GatePtr(const std::shared_ptr& gate_ptr) { + GatePtr(const std::shared_ptr &gate_ptr) { if constexpr (std::is_same_v) { _gate_type = get_gate_type(); _gate_ptr = gate_ptr; @@ -200,7 +200,7 @@ class GatePtr { } } template - GatePtr(const GatePtr& gate) { + GatePtr(const GatePtr &gate) { if constexpr (std::is_same_v) { _gate_type = gate._gate_type; _gate_ptr = gate._gate_ptr; @@ -220,7 +220,7 @@ class GatePtr { GateType gate_type() const { return _gate_type; } - const T* operator->() const { + const T *operator->() const { if (!_gate_ptr) { throw std::runtime_error("GatePtr::operator->(): Gate is Null"); } @@ -229,4 +229,97 @@ class GatePtr { }; } // namespace internal +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +#define DEF_GATE_BASE(GATE_TYPE, DESCRIPTION) \ + nb::class_(m, #GATE_TYPE, DESCRIPTION) \ + .def("gate_type", &GATE_TYPE::gate_type, "Get gate type as `GateType` enum.") \ + .def( \ + "target_qubit_list", \ + [](const GATE_TYPE &gate) { return gate->target_qubit_list(); }, \ + "Get target qubits as `list[int]`. **Control qubits is not included.**") \ + .def( \ + "control_qubit_list", \ + [](const GATE_TYPE &gate) { return gate->control_qubit_list(); }, \ + "Get control qubits as `list[int]`.") \ + .def( \ + "operand_qubit_list", \ + [](const GATE_TYPE &gate) { return gate->operand_qubit_list(); }, \ + "Get target and control qubits as `list[int]`.") \ + .def( \ + "target_qubit_mask", \ + [](const GATE_TYPE &gate) { return gate->target_qubit_mask(); }, \ + "Get target qubits as mask. **Control qubits is not included.**") \ + .def( \ + "control_qubit_mask", \ + [](const GATE_TYPE &gate) { return gate->control_qubit_mask(); }, \ + "Get control qubits as mask.") \ + .def( \ + "operand_qubit_mask", \ + [](const GATE_TYPE &gate) { return gate->operand_qubit_mask(); }, \ + "Get target and control qubits as mask.") \ + .def( \ + "get_inverse", \ + [](const GATE_TYPE &gate) { return gate->get_inverse(); }, \ + "Generate inverse gate as `Gate` type. If not exists, return None.") \ + .def( \ + "update_quantum_state", \ + [](const GATE_TYPE &gate, StateVector &state_vector) { \ + gate->update_quantum_state(state_vector); \ + }, \ + "Apply gate to `state_vector`. `state_vector` in args is directly updated.") \ + .def( \ + "get_matrix", \ + [](const GATE_TYPE &gate) { return gate->get_matrix(); }, \ + "Get matrix representation of the gate.") + +nb::class_ gate_base_def; + +#define DEF_GATE(GATE_TYPE, DESCRIPTION) \ + ::scaluq::internal::gate_base_def.def(nb::init(), "Upcast from `" #GATE_TYPE "`."); \ + DEF_GATE_BASE( \ + GATE_TYPE, \ + DESCRIPTION \ + "\n\n.. note:: Upcast is required to use gate-general functions (ex: add to Circuit).") \ + .def(nb::init()) + +void bind_gate_gate_hpp(nb::module_ &m) { + nb::enum_(m, "GateType", "Enum of Gate Type.") + .value("I", GateType::I) + .value("GlobalPhase", GateType::GlobalPhase) + .value("X", GateType::X) + .value("Y", GateType::Y) + .value("Z", GateType::Z) + .value("H", GateType::H) + .value("S", GateType::S) + .value("Sdag", GateType::Sdag) + .value("T", GateType::T) + .value("Tdag", GateType::Tdag) + .value("SqrtX", GateType::SqrtX) + .value("SqrtXdag", GateType::SqrtXdag) + .value("SqrtY", GateType::SqrtY) + .value("SqrtYdag", GateType::SqrtYdag) + .value("P0", GateType::P0) + .value("P1", GateType::P1) + .value("RX", GateType::RX) + .value("RY", GateType::RY) + .value("RZ", GateType::RZ) + .value("U1", GateType::U1) + .value("U2", GateType::U2) + .value("U3", GateType::U3) + .value("OneTargetMatrix", GateType::OneTargetMatrix) + .value("Swap", GateType::Swap) + .value("TwoTargetMatrix", GateType::TwoTargetMatrix) + .value("Pauli", GateType::Pauli) + .value("PauliRotation", GateType::PauliRotation); + + gate_base_def = + DEF_GATE_BASE(Gate, + "General class of QuantumGate.\n\n.. note:: Downcast to requred to use " + "gate-specific functions.") + .def(nb::init(), "Just copy shallowly."); +} +} // namespace internal +#endif + } // namespace scaluq diff --git a/scaluq/gate/gate_factory.hpp b/scaluq/gate/gate_factory.hpp index 6ed1580c..f8e54c9d 100644 --- a/scaluq/gate/gate_factory.hpp +++ b/scaluq/gate/gate_factory.hpp @@ -150,7 +150,6 @@ inline Gate TwoTargetMatrix(std::uint64_t target1, return internal::GateFactory::create_gate( internal::vector_to_mask({target1, target2}), internal::vector_to_mask(controls), matrix); } -// まだ inline Gate Pauli(const PauliOperator& pauli, const std::vector& controls = {}) { auto tar = pauli.target_qubit_list(); return internal::GateFactory::create_gate( @@ -215,4 +214,192 @@ inline Gate Probablistic(const std::vector& distribution, gate_list); } } // namespace gate + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_gate_factory_hpp(nb::module_& mgate) { + mgate.def("I", &gate::I, "Generate general Gate class instance of I."); + mgate.def("GlobalPhase", + &gate::GlobalPhase, + "Generate general Gate class instance of GlobalPhase.", + "phase"_a, + "controls"_a = std::vector{}); + mgate.def("X", + &gate::X, + "Generate general Gate class instance of X.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("Y", + &gate::Y, + "Generate general Gate class instance of Y.", + "taget"_a, + "controls"_a = std::vector{}); + mgate.def("Z", + &gate::Z, + "Generate general Gate class instance of Z.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("H", + &gate::H, + "Generate general Gate class instance of H.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("S", + &gate::S, + "Generate general Gate class instance of S.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("Sdag", + &gate::Sdag, + "Generate general Gate class instance of Sdag.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("T", + &gate::T, + "Generate general Gate class instance of T.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("Tdag", + &gate::Tdag, + "Generate general Gate class instance of Tdag.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("SqrtX", + &gate::SqrtX, + "Generate general Gate class instance of SqrtX.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("SqrtXdag", + &gate::SqrtXdag, + "Generate general Gate class instance of SqrtXdag.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("SqrtY", + &gate::SqrtY, + "Generate general Gate class instance of SqrtY.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("SqrtYdag", + &gate::SqrtYdag, + "Generate general Gate class instance of SqrtYdag.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("P0", + &gate::P0, + "Generate general Gate class instance of P0.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("P1", + &gate::P1, + "Generate general Gate class instance of P1.", + "target"_a, + "controls"_a = std::vector{}); + mgate.def("RX", + &gate::RX, + "Generate general Gate class instance of RX.", + "target"_a, + "angle"_a, + "controls"_a = std::vector{}); + mgate.def("RY", + &gate::RY, + "Generate general Gate class instance of RY.", + "target"_a, + "angle"_a, + "controls"_a = std::vector{}); + mgate.def("RZ", + &gate::RZ, + "Generate general Gate class instance of RZ.", + "target"_a, + "angle"_a, + "controls"_a = std::vector{}); + mgate.def("U1", + &gate::U1, + "Generate general Gate class instance of U1.", + "target"_a, + "lambda_"_a, + "controls"_a = std::vector{}); + mgate.def("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, + "Generate general Gate class instance of U3.", + "target"_a, + "theta"_a, + "phi"_a, + "lambda_"_a, + "controls"_a = std::vector{}); + mgate.def("Swap", + &gate::Swap, + "Generate general Gate class instance of Swap.", + "target1"_a, + "target2"_a, + "controls"_a = std::vector{}); + mgate.def( + "CX", + &gate::CX, + "Generate general Gate class instance of CX.\n\n.. note:: CX is a specialization of X."); + mgate.def("CNot", + &gate::CX, + "Generate general Gate class instance of CNot.\n\n.. note:: CNot is an alias of CX."); + mgate.def( + "CZ", + &gate::CZ, + "Generate general Gate class instance of CZ.\n\n.. note:: CZ is a specialization of Z."); + mgate.def( + "CCX", + &gate::CCX, + "Generate general Gate class instance of CXX.\n\n.. note:: CX is a specialization of X."); + mgate.def( + "CCNot", + &gate::CCX, + "Generate general Gate class instance of CCNot.\n\n.. note:: CCNot is an alias of CCX."); + mgate.def("Toffoli", + &gate::CCX, + "Generate general Gate class instance of Toffoli.\n\n.. note:: Toffoli is an alias " + "of CCX."); + mgate.def("OneTargetMatrix", + &gate::OneTargetMatrix, + "Generate general Gate class instance of OneTargetMatrix.", + "target"_a, + "matrix"_a, + "controls"_a = std::vector{}); + mgate.def("TwoTargetMatrix", + &gate::TwoTargetMatrix, + "Generate general Gate class instance of TwoTargetMatrix.", + "target1"_a, + "target2"_a, + "matrix"_a, + "controls"_a = std::vector{}); + mgate.def("DenseMatrix", + &gate::DenseMatrix, + "Generate general Gate class instance of DenseMatrix. IGate, OneTargetMatrixGate or " + "TwoTargetMatrixGate correspond to len(target) is created. The case len(target) >= 3 " + "is currently not supported.", + "targets"_a, + "matrix"_a, + "controls"_a = std::vector{}); + mgate.def("Pauli", + &gate::Pauli, + "Generate general Gate class instance of Pauli.", + "pauli"_a, + "controls"_a = std::vector{}); + mgate.def("PauliRotation", + &gate::PauliRotation, + "Generate general Gate class instance of PauliRotation.", + "pauli"_a, + "angle"_a, + "controls"_a = std::vector{}); + mgate.def("Probablistic", + &gate::Probablistic, + "Generate general Gate class instance of Probablistic.", + "distribution"_a, + "gate_list"_a); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/gate_matrix.hpp b/scaluq/gate/gate_matrix.hpp index 5d80ff23..82c04c15 100644 --- a/scaluq/gate/gate_matrix.hpp +++ b/scaluq/gate/gate_matrix.hpp @@ -105,4 +105,15 @@ class TwoTargetMatrixGateImpl : public GateBase { using OneTargetMatrixGate = internal::GatePtr; using TwoTargetMatrixGate = internal::GatePtr; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_gate_matrix_hpp(nb::module_& m) { + DEF_GATE(OneTargetMatrixGate, "Specific class of one-qubit dense matrix gate.") + .def("matrix", [](const OneTargetMatrixGate& gate) { return gate->matrix(); }); + DEF_GATE(TwoTargetMatrixGate, "Specific class of two-qubit dense matrix gate.") + .def("matrix", [](const TwoTargetMatrixGate& gate) { return gate->matrix(); }); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index 0671fbb1..da19bed2 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -61,4 +61,18 @@ class PauliRotationGateImpl : public GateBase { using PauliGate = internal::GatePtr; using PauliRotationGate = internal::GatePtr; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_gate_pauli_hpp(nb::module_& m) { + DEF_GATE(PauliGate, + "Specific class of multi-qubit pauli gate, which applies single-qubit Pauli " + "gate to " + "each of qubit."); + DEF_GATE(PauliRotationGate, + "Specific class of multi-qubit pauli-rotation gate, represented as " + "$e^{-i\\frac{\\mathrm{angle}}{2}P}$."); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/gate_probablistic.hpp b/scaluq/gate/gate_probablistic.hpp index 26a33478..c111f077 100644 --- a/scaluq/gate/gate_probablistic.hpp +++ b/scaluq/gate/gate_probablistic.hpp @@ -89,4 +89,22 @@ class ProbablisticGateImpl : public GateBase { } // namespace internal using ProbablisticGate = internal::GatePtr; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_gate_probablistic(nb::module_& m) { + DEF_GATE(ProbablisticGate, + "Specific class of probablistic gate. The gate to apply is picked from a cirtain " + "distribution.") + .def( + "gate_list", + [](const ProbablisticGate& gate) { return gate->gate_list(); }, + nb::rv_policy::reference) + .def( + "distribution", + [](const ProbablisticGate& gate) { return gate->distribution(); }, + nb::rv_policy::reference); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/gate_standard.hpp b/scaluq/gate/gate_standard.hpp index e1046155..405ffdc4 100644 --- a/scaluq/gate/gate_standard.hpp +++ b/scaluq/gate/gate_standard.hpp @@ -515,4 +515,90 @@ using U2Gate = internal::GatePtr; using U3Gate = internal::GatePtr; using SwapGate = internal::GatePtr; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_gate_standard_hpp(nb::module_& m) { + DEF_GATE(IGate, "Specific class of Pauli-I gate."); + DEF_GATE(GlobalPhaseGate, + "Specific class of gate, which rotate global phase, represented as " + "$e^{i\\mathrm{phase}}I$.") + .def( + "phase", + [](const GlobalPhaseGate& gate) { return gate->phase(); }, + "Get `phase` property"); + DEF_GATE(XGate, "Specific class of Pauli-X gate."); + DEF_GATE(YGate, "Specific class of Pauli-Y gate."); + DEF_GATE(ZGate, "Specific class of Pauli-Z gate."); + DEF_GATE(HGate, "Specific class of Hadamard gate."); + DEF_GATE(SGate, + "Specific class of S gate, represented as $\\begin{bmatrix}\n1 & 0\\\\\n0 & " + "i\n\\end{bmatrix}$."); + DEF_GATE(SdagGate, "Specific class of inverse of S gate."); + DEF_GATE(TGate, + "Specific class of T gate, represented as $\\begin{bmatrix}\n1 & 0\\\\\n0 & " + "e^{i\\pi/4}\n\\end{bmatrix}$."); + DEF_GATE(TdagGate, "Specific class of inverse of T gate."); + DEF_GATE(SqrtXGate, + "Specific class of sqrt(X) gate, represented as $\\begin{bmatrix}\n1+i & 1-i\\\\\n1-i " + "& 1+i\n\\end{bmatrix}$."); + DEF_GATE(SqrtXdagGate, "Specific class of inverse of sqrt(X) gate."); + DEF_GATE(SqrtYGate, + "Specific class of sqrt(Y) gate, represented as $\\begin{bmatrix}\n1+i & -1-i " + "\\\\\n1+i & 1+i\n\\end{bmatrix}$."); + DEF_GATE(SqrtYdagGate, "Specific class of inverse of sqrt(Y) gate."); + DEF_GATE( + P0Gate, + "Specific class of projection gate to $\\ket{0}$.\n\n.. note:: This gate is not unitary."); + DEF_GATE( + P1Gate, + "Specific class of projection gate to $\\ket{1}$.\n\n.. note:: This gate is not unitary."); + +#define DEF_ROTATION_GATE(GATE_TYPE, DESCRIPTION) \ + DEF_GATE(GATE_TYPE, DESCRIPTION) \ + .def( \ + "angle", [](const GATE_TYPE& gate) { return gate->angle(); }, "Get `angle` property.") + + DEF_ROTATION_GATE( + RXGate, + "Specific class of X rotation gate, represented as $e^{-i\\frac{\\mathrm{angle}}{2}X}$."); + DEF_ROTATION_GATE( + RYGate, + "Specific class of Y rotation gate, represented as $e^{-i\\frac{\\mathrm{angle}}{2}Y}$."); + DEF_ROTATION_GATE( + RZGate, + "Specific class of Z rotation gate, represented as $e^{-i\\frac{\\mathrm{angle}}{2}Z}$."); + + DEF_GATE(U1Gate, + "Specific class of IBMQ's U1 Gate, which is a rotation abount Z-axis, " + "represented as " + "$\\begin{bmatrix}\n1 & 0\\\\\n0 & e^{i\\lambda}\n\\end{bmatrix}$.") + .def( + "lambda_", [](const U1Gate& gate) { return gate->lambda(); }, "Get `lambda` property."); + DEF_GATE(U2Gate, + "Specific class of IBMQ's U2 Gate, which is a rotation about X+Z-axis, " + "represented as " + "$\\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.") + .def( + "lambda_", [](const U2Gate& gate) { return gate->lambda(); }, "Get `lambda` property."); + DEF_GATE(U3Gate, + "Specific class of IBMQ's U3 Gate, which is a rotation abount 3 axis, " + "represented as " + "$\\begin{bmatrix}\n\\cos \\frac{\\theta}{2} & " + "-e^{i\\lambda}\\sin\\frac{\\theta}{2}\\\\\n" + "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.") + .def( + "phi", [](const U3Gate& gate) { return gate->phi(); }, "Get `phi` property.") + .def( + "lambda_", [](const U3Gate& gate) { return gate->lambda(); }, "Get `lambda` property."); + DEF_GATE(SwapGate, "Specific class of two-qubit swap gate."); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/merge_gate.hpp b/scaluq/gate/merge_gate.hpp index c92281dc..55130d1f 100644 --- a/scaluq/gate/merge_gate.hpp +++ b/scaluq/gate/merge_gate.hpp @@ -4,4 +4,13 @@ namespace scaluq { std::pair merge_gate(const Gate& gate1, const Gate& gate2); + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_merge_gate_hpp(nb::module_& m) { + m.def( + "merge_gate", &merge_gate, "Merge two gates. return value is (merged gate, global phase)."); } +} // namespace internal +#endif +} // namespace scaluq diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index edc159dd..a46c6f0c 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -41,7 +41,7 @@ class ParamGateBase { protected: std::uint64_t _target_mask, _control_mask; double _pcoef; - void check_qubit_mask_within_bounds(const StateVector& state_vector) const { + void check_qubit_mask_within_bounds(const StateVector &state_vector) const { std::uint64_t full_mask = (1ULL << state_vector.n_qubits()) - 1; if ((_target_mask | _control_mask) > full_mask) [[unlikely]] { throw std::runtime_error( @@ -62,7 +62,7 @@ class ParamGateBase { } virtual ~ParamGateBase() = default; - [[nodiscard]] double param_coef() { return _pcoef; } + [[nodiscard]] double param_coef() const { return _pcoef; } [[nodiscard]] virtual std::vector target_qubit_list() const { return mask_to_vector(_target_mask); @@ -82,7 +82,7 @@ class ParamGateBase { [[nodiscard]] virtual ParamGate get_inverse() const = 0; [[nodiscard]] virtual ComplexMatrix get_matrix(double param) const = 0; - virtual void update_quantum_state(StateVector& state_vector, double param) const = 0; + virtual void update_quantum_state(StateVector &state_vector, double param) const = 0; }; template @@ -97,9 +97,9 @@ class ParamGatePtr { public: ParamGatePtr() : _param_gate_ptr(nullptr), _param_gate_type(get_param_gate_type()) {} - ParamGatePtr(const ParamGatePtr& param_gate) = default; + ParamGatePtr(const ParamGatePtr ¶m_gate) = default; template - ParamGatePtr(const std::shared_ptr& param_gate_ptr) { + ParamGatePtr(const std::shared_ptr ¶m_gate_ptr) { if constexpr (std::is_same_v) { _param_gate_type = get_param_gate_type(); _param_gate_ptr = param_gate_ptr; @@ -116,7 +116,7 @@ class ParamGatePtr { } } template - ParamGatePtr(const ParamGatePtr& param_gate) { + ParamGatePtr(const ParamGatePtr ¶m_gate) { if constexpr (std::is_same_v) { _param_gate_type = param_gate._param_gate_type; _param_gate_ptr = param_gate._param_gate_ptr; @@ -136,7 +136,7 @@ class ParamGatePtr { ParamGateType param_gate_type() const { return _param_gate_type; } - const T* operator->() const { + const T *operator->() const { if (!_param_gate_ptr) { throw std::runtime_error("ParamGatePtr::operator->(): ParamGate is Null"); } @@ -145,4 +145,81 @@ class ParamGatePtr { }; } // namespace internal +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +#define DEF_PARAM_GATE_BASE(PARAM_GATE_TYPE, DESCRIPTION) \ + nb::class_(m, #PARAM_GATE_TYPE, DESCRIPTION) \ + .def("param_gate_type", \ + &PARAM_GATE_TYPE::param_gate_type, \ + "Get parametric gate type as `ParamGateType` enum.") \ + .def( \ + "param_coef", \ + [](const PARAM_GATE_TYPE &gate) { return gate->param_coef(); }, \ + "Get coefficient of parameter.") \ + .def( \ + "target_qubit_list", \ + [](const PARAM_GATE_TYPE &gate) { return gate->target_qubit_list(); }, \ + "Get target qubits as `list[int]`. **Control qubits is not included.**") \ + .def( \ + "control_qubit_list", \ + [](const PARAM_GATE_TYPE &gate) { return gate->control_qubit_list(); }, \ + "Get control qubits as `list[int]`.") \ + .def( \ + "operand_qubit_list", \ + [](const PARAM_GATE_TYPE &gate) { return gate->operand_qubit_list(); }, \ + "Get target and control qubits as `list[int]`.") \ + .def( \ + "target_qubit_mask", \ + [](const PARAM_GATE_TYPE &gate) { return gate->target_qubit_mask(); }, \ + "Get target qubits as mask. **Control qubits is not included.**") \ + .def( \ + "control_qubit_mask", \ + [](const PARAM_GATE_TYPE &gate) { return gate->control_qubit_mask(); }, \ + "Get control qubits as mask.") \ + .def( \ + "operand_qubit_mask", \ + [](const PARAM_GATE_TYPE &gate) { return gate->operand_qubit_mask(); }, \ + "Get target and control qubits as mask.") \ + .def( \ + "get_inverse", \ + [](const PARAM_GATE_TYPE ¶m_gate) { return param_gate->get_inverse(); }, \ + "Generate inverse parametric-gate as `ParamGate` type. If not exists, return None.") \ + .def( \ + "update_quantum_state", \ + [](const PARAM_GATE_TYPE ¶m_gate, StateVector &state_vector, double param) { \ + param_gate->update_quantum_state(state_vector, param); \ + }, \ + "Apply gate to `state_vector` with holding the parameter. `state_vector` in args is " \ + "directly updated.") \ + .def( \ + "get_matrix", \ + [](const PARAM_GATE_TYPE &gate, double param) { return gate->get_matrix(param); }, \ + "Get matrix representation of the gate with holding the parameter.") + +nb::class_ param_gate_base_def; + +#define DEF_PARAM_GATE(PARAM_GATE_TYPE, DESCRIPTION) \ + ::scaluq::internal::param_gate_base_def.def(nb::init(), \ + "Upcast from `" #PARAM_GATE_TYPE "`."); \ + DEF_PARAM_GATE_BASE( \ + PARAM_GATE_TYPE, \ + DESCRIPTION \ + "\n\n.. note:: Upcast is required to use gate-general functions (ex: add to Circuit).") \ + .def(nb::init()) + +void bind_gate_param_gate_hpp(nb::module_ &m) { + nb::enum_(m, "ParamGateType", "Enum of ParamGate Type.") + .value("ParamRX", ParamGateType::ParamRX) + .value("ParamRY", ParamGateType::ParamRY) + .value("ParamRZ", ParamGateType::ParamRZ) + .value("ParamPauliRotation", ParamGateType::ParamPauliRotation); + + param_gate_base_def = DEF_PARAM_GATE_BASE( + ParamGate, + "General class of parametric quantum gate.\n\n.. note:: Downcast to requred to use " + "gate-specific functions."); +} + +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/param_gate_factory.hpp b/scaluq/gate/param_gate_factory.hpp index c76e0a9d..bc7a7ec6 100644 --- a/scaluq/gate/param_gate_factory.hpp +++ b/scaluq/gate/param_gate_factory.hpp @@ -33,7 +33,6 @@ inline ParamGate ParamRZ(std::uint64_t target, return internal::ParamGateFactory::create_gate( internal::vector_to_mask({target}), internal::vector_to_mask(controls), param_coef); } -// まだ inline ParamGate ParamPauliRotation(const PauliOperator& pauli, double param_coef = 1., const std::vector& controls = {}) { @@ -46,4 +45,52 @@ inline ParamGate ParamProbablistic(const std::vector& distribution, distribution, gate_list); } } // namespace gate + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_param_gate_factory(nb::module_& mgate) { + mgate.def("ParamRX", + &gate::ParamRX, + "Generate general ParamGate class instance of ParamRX.", + "target"_a, + "coef"_a = 1., + "controls"_a = std::vector{}); + mgate.def("ParamRY", + &gate::ParamRY, + "Generate general ParamGate class instance of ParamRY.", + "target"_a, + "coef"_a = 1., + "controls"_a = std::vector{}); + mgate.def("ParamRZ", + &gate::ParamRZ, + "Generate general ParamGate class instance of ParamRZ.", + "target"_a, + "coef"_a = 1., + "controls"_a = std::vector{}); + mgate.def("ParamPauliRotation", + &gate::ParamPauliRotation, + "Generate general ParamGate class instance of ParamPauliRotation.", + "pauli"_a, + "coef"_a = 1., + "controls"_a = std::vector{}); + mgate.def("ParamProbablistic", + &gate::ParamProbablistic, + "Generate general ParamGate class instance of ParamProbablistic."); + mgate.def( + "ParamProbablistic", + [](const std::vector>>& prob_gate_list) { + std::vector distribution; + std::vector> gate_list; + distribution.reserve(prob_gate_list.size()); + gate_list.reserve(prob_gate_list.size()); + for (const auto& [prob, gate] : prob_gate_list) { + distribution.push_back(prob); + gate_list.push_back(gate); + } + return gate::ParamProbablistic(distribution, gate_list); + }, + "Generate general ParamGate class instance of ParamProbablistic."); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/param_gate_probablistic.hpp b/scaluq/gate/param_gate_probablistic.hpp index a6622299..84db0088 100644 --- a/scaluq/gate/param_gate_probablistic.hpp +++ b/scaluq/gate/param_gate_probablistic.hpp @@ -99,4 +99,24 @@ class ParamProbablisticGateImpl : public ParamGateBase { } // namespace internal using ParamProbablisticGate = internal::ParamGatePtr; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_param_gate_probablistic_hpp(nb::module_& m) { + DEF_PARAM_GATE( + ParamProbablisticGate, + "Specific class of parametric probablistic gate. The gate to apply is picked from a " + "cirtain " + "distribution.") + .def( + "gate_list", + [](const ParamProbablisticGate& gate) { return gate->gate_list(); }, + nb::rv_policy::reference) + .def( + "distribution", + [](const ParamProbablisticGate& gate) { return gate->distribution(); }, + nb::rv_policy::reference); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/gate/param_gate_standard.hpp b/scaluq/gate/param_gate_standard.hpp index 23da71b4..a755d480 100644 --- a/scaluq/gate/param_gate_standard.hpp +++ b/scaluq/gate/param_gate_standard.hpp @@ -75,4 +75,14 @@ using ParamRXGate = internal::ParamGatePtr; using ParamRYGate = internal::ParamGatePtr; using ParamRZGate = internal::ParamGatePtr; +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_gate_param_gate_standard_hpp(nb::module_& m) { + DEF_PARAM_GATE( + ParamPauliRotationGate, + "Specific class of parametric multi-qubit pauli-rotation gate, represented as " + "$e^{-i\\frac{\\mathrm{angle}}{2}P}$. `angle` is given as `param * param_coef`."); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/operator/operator.hpp b/scaluq/operator/operator.hpp index cc71abf7..2c472dda 100644 --- a/scaluq/operator/operator.hpp +++ b/scaluq/operator/operator.hpp @@ -67,4 +67,59 @@ class Operator { std::uint64_t _n_qubits; bool _is_hermitian = true; }; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_operator_operator_hpp(nb::module_& m) { + 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("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.") + .def("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) { + return op.add_random_operator(operator_count, + seed.value_or(std::random_device{}())); + }, + "operator_count"_a, + "seed"_a = std::nullopt, + "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("get_dagger", + &Operator::get_dagger, + "Get the adjoint (Hermitian conjugate) of the operator.") + .def("apply_to_state", &Operator::apply_to_state, "Apply the operator to a state vector.") + .def("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, + "Get the transition amplitude of the operator between two state vectors.") + .def(nb::self *= Complex()) + .def(nb::self * Complex()) + .def(+nb::self) + .def(-nb::self) + .def(nb::self += nb::self) + .def(nb::self + nb::self) + .def(nb::self -= nb::self) + .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()); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/operator/pauli_operator.hpp b/scaluq/operator/pauli_operator.hpp index cbeed74f..69cdd923 100644 --- a/scaluq/operator/pauli_operator.hpp +++ b/scaluq/operator/pauli_operator.hpp @@ -95,4 +95,157 @@ class PauliOperator { } }; +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_operator_pauli_operator_hpp(nb::module_& m) { + nb::enum_(m, "PauliID") + .value("I", PauliOperator::I) + .value("X", PauliOperator::X) + .value("Y", PauliOperator::Y) + .value("Z", PauliOperator::Z) + .export_values(); + + nb::class_( + m, "PauliOperatorData", "Internal data structure for PauliOperator.") + .def(nb::init(), "coef"_a = 1., "Initialize data with coefficient.") + .def(nb::init(), + "pauli_string"_a, + "coef"_a = 1., + "Initialize data with pauli string.") + .def(nb::init&, + const std::vector&, + Complex>(), + "target_qubit_list"_a, + "pauli_id_list"_a, + "coef"_a = 1., + "Initialize data with target qubits and pauli ids.") + .def(nb::init&, Complex>(), + "pauli_id_par_qubit"_a, + "coef"_a = 1., + "Initialize data with pauli ids per qubit.") + .def(nb::init&, const std::vector&, Complex>(), + "bit_flip_mask"_a, + "phase_flip_mask"_a, + "coef"_a = 1., + "Initialize data with bit flip and phase flip masks.") + .def(nb::init(), + "data"_a, + "Initialize pauli operator from Data object.") + .def("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("set_coef", + &PauliOperator::Data::set_coef, + "c"_a, + "Set the coefficient of the Pauli operator.") + .def("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("get_XZ_mask_representation", + &PauliOperator::Data::get_XZ_mask_representation, + "Get the X and Z mask representation as a tuple of vectors."); + + nb::class_( + m, + "PauliOperator", + "Pauli operator as coef and tensor product of single pauli for each qubit.") + .def(nb::init(), "coef"_a = 1., "Initialize operator which just multiplying coef.") + .def(nb::init&, + const std::vector&, + Complex>(), + "target_qubit_list"_a, + "pauli_id_list"_a, + "coef"_a = 1., + "Initialize pauli operator. For each `i`, single pauli correspond to " + "`pauli_id_list[i]` is applied to `target_qubit_list`-th qubit.") + .def(nb::init(), + "pauli_string"_a, + "coef"_a = 1., + "Initialize pauli operator. If `pauli_string` is `\"X0Y2\"`, Pauli-X is applied to " + "0-th qubit and Pauli-Y is applied to 2-th qubit. In `pauli_string`, spaces are " + "ignored.") + .def(nb::init&, Complex>(), + "pauli_id_par_qubit"_a, + "coef"_a = 1., + "Initialize pauli operator. For each `i`, single pauli correspond to " + "`paul_id_per_qubit` is applied to `i`-th qubit.") + .def( + "__init__", + [](PauliOperator* t, + nb::int_ bit_flip_mask_py, + nb::int_ phase_flip_mask_py, + Complex coef) { + internal::BitVector bit_flip_mask(0), phase_flip_mask(0); + const nb::int_ mask(~0ULL); + auto& bit_flip_raw = bit_flip_mask.data_raw(); + assert(bit_flip_raw.empty()); + while (bit_flip_mask_py > nb::int_(0)) { + bit_flip_raw.push_back((std::uint64_t)nb::int_(bit_flip_mask_py & mask)); + bit_flip_mask_py >>= nb::int_(64); + } + auto& phase_flip_raw = phase_flip_mask.data_raw(); + assert(phase_flip_raw.empty()); + while (phase_flip_mask_py > nb::int_(0)) { + phase_flip_raw.push_back((std::uint64_t)nb::int_(phase_flip_mask_py & mask)); + phase_flip_mask_py >>= nb::int_(64); + } + new (t) PauliOperator(bit_flip_mask, phase_flip_mask, coef); + }, + "bit_flip_mask"_a, + "phase_flip_mask"_a, + "coef"_a = 1., + "Initialize pauli operator. For each `i`, single pauli applied to `i`-th qubit is got " + "from `i-th` bit of `bit_flip_mask` and `phase_flip_mask` as follows.\n\n.. " + "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("target_qubit_list", + &PauliOperator::target_qubit_list, + "Get qubits to be applied pauli.") + .def("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", + [](const PauliOperator& pauli) { + const auto [x_mask, z_mask] = pauli.get_XZ_mask_representation(); + nb::int_ x_mask_py(0); + for (std::uint64_t i = 0; i < x_mask.size(); ++i) { + x_mask_py |= nb::int_(x_mask[i]) << nb::int_(i); + } + nb::int_ z_mask_py(0); + for (std::uint64_t i = 0; i < z_mask.size(); ++i) { + z_mask_py |= nb::int_(z_mask[i]) << nb::int_(i); + } + return std::make_tuple(x_mask_py, z_mask_py); + }, + "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, + "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_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("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, + "Get transition amplitude of measuring state vector. $\\bra{\\chi}P\\ket{\\psi}$.") + .def(nb::self * nb::self) + .def(nb::self * Complex()); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/state/state_vector.hpp b/scaluq/state/state_vector.hpp index e294ee68..0be871c2 100644 --- a/scaluq/state/state_vector.hpp +++ b/scaluq/state/state_vector.hpp @@ -72,4 +72,99 @@ class StateVector { [[nodiscard]] std::string to_string() const; }; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_state_state_vector_hpp(nb::module_& m) { + nb::class_(m, + "StateVector", + "Vector representation of quantum state.\n\n.. note:: Qubit index is " + "start from 0. If the amplitudes of $\\ket{b_{n-1}\\dots b_0}$ is " + "$b_i$, the state is $\\sum_i b_i 2^i$.") + .def(nb::init(), + "Construct state vector with specified qubits, initialized with computational " + "basis $\\ket{0\\dots0}$.") + .def(nb::init(), "Constructing state vector by copying other state.") + .def_static( + "Haar_random_state", + [](std::uint64_t n_qubits, std::optional seed) { + return StateVector::Haar_random_state(n_qubits, + seed.value_or(std::random_device{}())); + }, + "n_qubits"_a, + "seed"_a = std::nullopt, + "Constructing state vector with Haar random state. If seed is not specified, the value " + "from random device is used.") + .def("set_amplitude_at", + &StateVector::set_amplitude_at, + "Manually set amplitude at one index.") + .def("get_amplitude_at", + &StateVector::get_amplitude_at, + "Get amplitude at one index.\n\n.. note:: If you want to get all amplitudes, you " + "should " + "use `StateVector::get_amplitudes()`.") + .def("set_zero_state", + &StateVector::set_zero_state, + "Initialize with computational basis $\\ket{00\\dots0}$.") + .def("set_zero_norm_state", + &StateVector::set_zero_norm_state, + "Initialize with 0 (null vector).") + .def("set_computational_basis", + &StateVector::set_computational_basis, + "Initialize with computational basis \\ket{\\mathrm{basis}}.") + .def("amplitudes", + &StateVector::get_amplitudes, + "Get all amplitudes with as `list[complex]`.") + .def("n_qubits", &StateVector::n_qubits, "Get num of qubits.") + .def("dim", &StateVector::dim, "Get dimension of the vector ($=2^\\mathrm{n\\_qubits}$).") + .def("get_squared_norm", + &StateVector::get_squared_norm, + "Get squared norm of the state. $\\braket{\\psi|\\psi}$.") + .def("normalize", + &StateVector::normalize, + "Normalize state (let $\\braket{\\psi|\\psi} = 1$ by multiplying coef).") + .def("get_zero_probability", + &StateVector::get_zero_probability, + "Get the probability to observe $\\ket{0}$ at specified index.") + .def("get_marginal_probability", + &StateVector::get_marginal_probability, + "Get the marginal probability to observe as specified. Specify the result as n-length " + "list. `0` and `1` represent the qubit is observed and get the value. `2` represents " + "the qubit is not observed.") + .def("get_entropy", &StateVector::get_entropy, "Get the entropy of the vector.") + .def("add_state_vector", + &StateVector::add_state_vector, + "Add other state vector and make superposition. $\\ket{\\mathrm{this}} " + "\\leftarrow " + "\\ket{\\mathrm{this}} + \\ket{\\mathrm{state}}$.") + .def("add_state_vector_with_coef", + &StateVector::add_state_vector_with_coef, + "add other state vector with multiplying the coef and make superposition. " + "$\\ket{\\mathrm{this}}\\leftarrow\\ket{\\mathrm{this}}+\\mathrm{coef}" + "\\ket{\\mathrm{" + "state}}$.") + .def("multiply_coef", + &StateVector::multiply_coef, + "Multiply coef. " + "$\\ket{\\mathrm{this}}\\leftarrow\\mathrm{coef}\\ket{\\mathrm{this}}$.") + .def( + "sampling", + [](const StateVector& state, + std::uint64_t sampling_count, + std::optional seed) { + return state.sampling(sampling_count, seed.value_or(std::random_device{}())); + }, + "sampling_count"_a, + "seed"_a = std::nullopt, + "Sampling specified times. Result is `list[int]` with the `sampling_count` length.") + .def("to_string", &StateVector::to_string, "Information as `str`.") + .def("load", &StateVector::load, "Load amplitudes of `list[int]` with `dim` length.") + .def("__str__", &StateVector::to_string, "Information as `str`.") + .def_ro_static("UNMEASURED", + &StateVector::UNMEASURED, + "Constant used for `StateVector::get_marginal_probability` to express the " + "the qubit is not measured."); +} +} // namespace internal +#endif } // namespace scaluq diff --git a/scaluq/state/state_vector_batched.hpp b/scaluq/state/state_vector_batched.hpp index 60127e3d..37e8ff40 100644 --- a/scaluq/state/state_vector_batched.hpp +++ b/scaluq/state/state_vector_batched.hpp @@ -61,4 +61,109 @@ class StateVectorBatched { std::string to_string() const; friend std::ostream& operator<<(std::ostream& os, const StateVectorBatched& states); }; + +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_state_state_vector_batched_hpp(nb::module_& m) { + nb::class_( + m, + "StateVectorBatched", + "Batched vector representation of quantum state.\n\n.. note:: Qubit index is start from 0. " + "If the amplitudes of $\\ket{b_{n-1}\\dots b_0}$ is $b_i$, the state is $\\sum_i b_i " + "2^i$.") + .def(nb::init(), + "Construct batched state vector with specified batch size and qubits.") + .def(nb::init(), + "Constructing batched state vector by copying other batched state.") + .def("n_qubits", &StateVectorBatched::n_qubits, "Get num of qubits.") + .def("dim", + &StateVectorBatched::dim, + "Get dimension of the vector ($=2^\\mathrm{n\\_qubits}$).") + .def("batch_size", &StateVectorBatched::batch_size, "Get batch size.") + .def("set_state_vector", + nb::overload_cast(&StateVectorBatched::set_state_vector), + "Set the state vector for all batches.") + .def("set_state_vector", + nb::overload_cast( + &StateVectorBatched::set_state_vector), + "Set the state vector for a specific batch.") + .def("get_state_vector_at", + &StateVectorBatched::get_state_vector_at, + "Get the state vector for a specific batch.") + .def("set_zero_state", + &StateVectorBatched::set_zero_state, + "Initialize all batches with computational basis $\\ket{00\\dots0}$.") + .def("set_zero_norm_state", + &StateVectorBatched::set_zero_norm_state, + "Initialize with 0 (null vector).") + .def("set_computational_basis", + &StateVectorBatched::set_computational_basis, + "Initialize with computational basis \\ket{\\mathrm{basis}}.") + .def( + "sampling", + [](const StateVectorBatched& states, + std::uint64_t sampling_count, + std::optional seed) { + return states.sampling(sampling_count, seed.value_or(std::random_device{}())); + }, + "sampling_count"_a, + "seed"_a = std::nullopt, + "Sampling specified times. Result is `list[list[int]]` with the `sampling_count` " + "length.") + .def_static( + "Haar_random_states", + [](std::uint64_t batch_size, + std::uint64_t n_qubits, + bool set_same_state, + std::optional seed) { + return StateVectorBatched::Haar_random_states( + batch_size, n_qubits, set_same_state, seed.value_or(std::random_device{}())); + }, + "batch_size"_a, + "n_qubits"_a, + "set_same_state"_a, + "seed"_a = std::nullopt, + "Construct batched state vectors with Haar random states. If seed is not " + "specified, the value from random device is used.") + .def("amplitudes", + &StateVectorBatched::get_amplitudes, + "Get all amplitudes with as `list[list[complex]]`.") + .def("get_squared_norm", + &StateVectorBatched::get_squared_norm, + "Get squared norm of each state in the batch. $\\braket{\\psi|\\psi}$.") + .def("normalize", + &StateVectorBatched::normalize, + "Normalize each state in the batch (let $\\braket{\\psi|\\psi} = 1$ by " + "multiplying coef).") + .def("get_zero_probability", + &StateVectorBatched::get_zero_probability, + "Get the probability to observe $\\ket{0}$ at specified index for each state in " + "the batch.") + .def("get_marginal_probability", + &StateVectorBatched::get_marginal_probability, + "Get the marginal probability to observe as specified for each state in the batch. " + "Specify the result as n-length list. `0` and `1` represent the qubit is observed " + "and get the value. `2` represents the qubit is not observed.") + .def("get_entropy", + &StateVectorBatched::get_entropy, + "Get the entropy of each state in the batch.") + .def("add_state_vector", + &StateVectorBatched::add_state_vector, + "Add other batched state vectors and make superposition. $\\ket{\\mathrm{this}} " + "\\leftarrow \\ket{\\mathrm{this}} + \\ket{\\mathrm{states}}$.") + .def("add_state_vector_with_coef", + &StateVectorBatched::add_state_vector_with_coef, + "Add other batched state vectors with multiplying the coef and make superposition. " + "$\\ket{\\mathrm{this}}\\leftarrow\\ket{\\mathrm{this}}+\\mathrm{coef}" + "\\ket{\\mathrm{states}}$.") + .def("load", + &StateVectorBatched::load, + "Load batched amplitudes from `list[list[complex]]`.") + .def("copy", &StateVectorBatched::copy, "Create a copy of the batched state vector.") + .def("to_string", &StateVectorBatched::to_string, "Information as `str`.") + .def("__str__", &StateVectorBatched::to_string, "Information as `str`."); +} +} // namespace internal +#endif + } // namespace scaluq diff --git a/scaluq/types.hpp b/scaluq/types.hpp index e31fb92e..74c836f9 100644 --- a/scaluq/types.hpp +++ b/scaluq/types.hpp @@ -43,4 +43,19 @@ struct diagonal_matrix_2_2 { Complex val[2]; }; +#ifdef SCALUQ_USE_NANOBIND +namespace internal { +void bind_types_hpp(nb::module_& m) { + m.def("finalize", + &finalize, + "Terminate the Kokkos execution environment. Release the resources.\n\n.. note:: " + "Finalization fails if there exists `StateVector` allocated. You must use " + "`StateVector` only inside inner scopes than the usage of `finalize` or delete all of " + "existing `StateVector`.\n\n.. note:: This is " + "automatically called when the program exits. If you call this manually, you cannot use " + "most of scaluq's functions until the program exits."); + m.def("is_finalized", &is_initialized, "Return true if `finalize()` is already called."); +} +} // namespace internal +#endif } // namespace scaluq From d4c9b67bdd51bde866ec8c8090d2553995cdfcfe Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 6 Sep 2024 03:00:03 +0000 Subject: [PATCH 46/55] change namespace of gate_to_string --- exe/main.cpp | 23 +++++++++++++++-------- scaluq/gate/gate.hpp | 11 +---------- scaluq/gate/gate_factory.hpp | 19 +++---------------- scaluq/gate/param_gate.hpp | 2 +- scaluq/gate/param_gate_factory.hpp | 9 +++------ 5 files changed, 23 insertions(+), 41 deletions(-) diff --git a/exe/main.cpp b/exe/main.cpp index cb4a5f46..e7adfdb7 100644 --- a/exe/main.cpp +++ b/exe/main.cpp @@ -1,30 +1,37 @@ -#include - -#include #include #include #include #include #include "../scaluq/all.hpp" -#include "../scaluq/util/utility.hpp" using namespace scaluq; using namespace std; void run() { - auto x_gate = gate::X(2); - std::cout << x_gate << std::endl; auto y_gate = gate::Y(2); std::cout << y_gate << std::endl; + + auto cx_gate = gate::CX(0, 2); + std::cout << cx_gate << std::endl; + auto swap_gate = gate::Swap(2, 3, {4, 6}); std::cout << swap_gate << "\n\n"; - auto prob_gate = gate::Probablistic({0.1, 0.1, 0.8}, {x_gate, y_gate, swap_gate}); + auto prob_gate = gate::Probablistic({0.1, 0.1, 0.8}, {cx_gate, y_gate, swap_gate}); std::cout << prob_gate << "\n\n"; - auto prob_prob_gate = gate::Probablistic({0.5, 0.5}, {x_gate, prob_gate}); + auto prob_prob_gate = gate::Probablistic({0.5, 0.5}, {cx_gate, prob_gate}); std::cout << prob_prob_gate << "\n\n"; + + auto prx_gate = gate::ParamRX(2); + std::cout << prx_gate << "\n\n"; + + auto pry_gate = gate::ParamRY(2, 2.5, {1, 3}); + std::cout << pry_gate << "\n\n"; + + auto pprob_gate = gate::ParamProbablistic({0.7, 0.3}, {prx_gate, pry_gate}); + std::cout << pprob_gate << std::endl; } int main() { diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 6fd11554..9a57d3c8 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -36,9 +36,6 @@ class U1GateImpl; class U2GateImpl; class U3GateImpl; class OneTargetMatrixGateImpl; -class CXGateImpl; -class CZGateImpl; -class CCXGateImpl; class SwapGateImpl; class TwoTargetMatrixGateImpl; class PauliGateImpl; @@ -75,9 +72,6 @@ enum class GateType { U2, U3, OneTargetMatrix, - CX, - CZ, - CCX, Swap, TwoTargetMatrix, Pauli, @@ -117,9 +111,6 @@ constexpr GateType get_gate_type() { if constexpr (std::is_same_v) return GateType::U3; if constexpr (std::is_same_v) return GateType::OneTargetMatrix; - if constexpr (std::is_same_v) return GateType::CX; - if constexpr (std::is_same_v) return GateType::CZ; - if constexpr (std::is_same_v) return GateType::CCX; if constexpr (std::is_same_v) return GateType::Swap; if constexpr (std::is_same_v) return GateType::TwoTargetMatrix; @@ -240,7 +231,7 @@ class GatePtr { return _gate_ptr.get(); } - // 依存関係の都合上、operator<< の定義は gate_factory.hpp に定義 + // Due to dependency reasons, the definition of operator<< is in gate_factory.hpp }; } // namespace internal diff --git a/scaluq/gate/gate_factory.hpp b/scaluq/gate/gate_factory.hpp index 475d9ad4..4951dfff 100644 --- a/scaluq/gate/gate_factory.hpp +++ b/scaluq/gate/gate_factory.hpp @@ -216,10 +216,8 @@ inline Gate Probablistic(const std::vector& distribution, } } // namespace gate -namespace internal { - -template -std::string gate_to_string(const GatePtr& obj, std::uint32_t depth = 0) { +template +std::string gate_to_string(const internal::GatePtr& obj, std::uint32_t depth = 0) { std::ostringstream ss; std::string indent(depth * 2, ' '); @@ -310,15 +308,6 @@ std::string gate_to_string(const GatePtr& obj, std::uint32_t depth = 0) { case GateType::OneTargetMatrix: ss << "OneTargetMatrix"; break; - case GateType::CX: - ss << "CX"; - break; - case GateType::CZ: - ss << "CZ"; - break; - case GateType::CCX: - ss << "CCX"; - break; case GateType::Swap: ss << "Swap"; break; @@ -350,11 +339,9 @@ std::string gate_to_string(const GatePtr& obj, std::uint32_t depth = 0) { return ss.str(); } -} // namespace internal - template std::ostream& operator<<(std::ostream& os, const internal::GatePtr& obj) { - os << internal::gate_to_string(obj); + os << gate_to_string(obj); return os; } diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index f1a3be91..f5b395b4 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -163,7 +163,7 @@ class ParamGatePtr { return _param_gate_ptr.get(); } - // 依存関係の都合上、operator<< の定義は gate_factory.hpp に定義 + // Due to dependency reasons, the definition of operator<< is in param_gate_factory.hpp }; } // namespace internal diff --git a/scaluq/gate/param_gate_factory.hpp b/scaluq/gate/param_gate_factory.hpp index 88c33413..60466300 100644 --- a/scaluq/gate/param_gate_factory.hpp +++ b/scaluq/gate/param_gate_factory.hpp @@ -47,10 +47,8 @@ inline ParamGate ParamProbablistic(const std::vector& distribution, } } // namespace gate -namespace internal { - -template -std::string gate_to_string(const ParamGatePtr& obj, std::uint32_t depth = 0) { +template +std::string gate_to_string(const internal::ParamGatePtr& obj, std::uint32_t depth = 0) { std::ostringstream ss; std::string indent(depth * 2, ' '); @@ -108,11 +106,10 @@ std::string gate_to_string(const ParamGatePtr& obj, std::uint32_t depth = 0) ss << "}"; return ss.str(); } -} // namespace internal template std::ostream& operator<<(std::ostream& os, const internal::ParamGatePtr& obj) { - os << internal::gate_to_string(obj); + os << gate_to_string(obj); return os; } From d503768de3e78fb0c8627365967b775afb08e3a2 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 6 Sep 2024 12:19:50 +0900 Subject: [PATCH 47/55] check stub --- .github/workflows/ci_ubuntu.yml | 5 +++++ pyproject.toml | 2 ++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/ci_ubuntu.yml b/.github/workflows/ci_ubuntu.yml index 2727155c..cebee819 100644 --- a/.github/workflows/ci_ubuntu.yml +++ b/.github/workflows/ci_ubuntu.yml @@ -65,6 +65,11 @@ jobs: - name: Test in Ubuntu run: | OMP_PROC_BIND=false ninja test -C build -j $(nproc) + + - name: Test if stub exists + run: | + echo -e "from scaluq import StateVector\nfrom.scaluq.gate import I" > /tmp/stub_sample.py + mypy /tmp/stub_sample.py nvcc-build: name: NVCC build diff --git a/pyproject.toml b/pyproject.toml index d36eff54..939ee578 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ homepage = "http://www.scaluq.org" [project.optional-dependencies] dev = [ + "mypy == 1.11.2", "scikit-build == 0.17.6", "typing_extensions == 4.12.0", "numpy == 1.26.0", @@ -56,6 +57,7 @@ dev = [ ] ci = [ + "mypy == 1.11.2", "scikit-build == 0.17.6", "typing_extensions == 4.12.0", "numpy == 1.26.0", From 35f6d1ebeb835914b32eee0b3920b6d6c53d1229 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Fri, 6 Sep 2024 12:29:06 +0900 Subject: [PATCH 48/55] fix typo --- .github/workflows/ci_ubuntu.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_ubuntu.yml b/.github/workflows/ci_ubuntu.yml index cebee819..3f1a341a 100644 --- a/.github/workflows/ci_ubuntu.yml +++ b/.github/workflows/ci_ubuntu.yml @@ -68,7 +68,7 @@ jobs: - name: Test if stub exists run: | - echo -e "from scaluq import StateVector\nfrom.scaluq.gate import I" > /tmp/stub_sample.py + echo -e "from scaluq import StateVector\nfrom scaluq.gate import I" > /tmp/stub_sample.py mypy /tmp/stub_sample.py nvcc-build: From f42f382e4c178a9a301f018d39b4dbcadec58b14 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 6 Sep 2024 04:19:45 +0000 Subject: [PATCH 49/55] add to_string to each GateImpl --- exe/main.cpp | 7 +- scaluq/gate/gate.hpp | 23 +++- scaluq/gate/gate_factory.hpp | 130 ------------------- scaluq/gate/gate_matrix.hpp | 14 ++ scaluq/gate/gate_pauli.hpp | 15 +++ scaluq/gate/gate_probablistic.hpp | 12 ++ scaluq/gate/gate_standard.hpp | 165 ++++++++++++++++++++++++ scaluq/gate/param_gate.hpp | 24 +++- scaluq/gate/param_gate_factory.hpp | 67 ---------- scaluq/gate/param_gate_pauli.hpp | 7 + scaluq/gate/param_gate_probablistic.hpp | 16 +++ scaluq/gate/param_gate_standard.hpp | 21 +++ 12 files changed, 300 insertions(+), 201 deletions(-) diff --git a/exe/main.cpp b/exe/main.cpp index e7adfdb7..68b52618 100644 --- a/exe/main.cpp +++ b/exe/main.cpp @@ -10,14 +10,17 @@ using namespace std; void run() { auto y_gate = gate::Y(2); - std::cout << y_gate << std::endl; + std::cout << y_gate->to_string() << "\n\n"; auto cx_gate = gate::CX(0, 2); - std::cout << cx_gate << std::endl; + std::cout << cx_gate << "\n\n"; auto swap_gate = gate::Swap(2, 3, {4, 6}); std::cout << swap_gate << "\n\n"; + auto rx_gate = gate::RX(2, 0.5); + std::cout << rx_gate << "\n\n"; + auto prob_gate = gate::Probablistic({0.1, 0.1, 0.8}, {cx_gate, y_gate, swap_gate}); std::cout << prob_gate << "\n\n"; diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 9a57d3c8..64b5e542 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -135,6 +135,21 @@ class GateBase : public std::enable_shared_from_this { } } + std::string get_qubit_info_as_string(const std::string& indent) const { + std::ostringstream ss; + auto targets = target_qubit_list(); + auto controls = control_qubit_list(); + ss << indent << " Target Qubits: {"; + for (std::uint32_t i = 0; i < targets.size(); ++i) + ss << targets[i] << (i == targets.size() - 1 ? "" : ", "); + ss << "}\n"; + ss << indent << " Control Qubits: {"; + for (std::uint32_t i = 0; i < controls.size(); ++i) + ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); + ss << "}"; + return ss.str(); + } + public: GateBase(std::uint64_t target_mask, std::uint64_t control_mask) : _target_mask(target_mask), _control_mask(control_mask) { @@ -165,6 +180,8 @@ class GateBase : public std::enable_shared_from_this { [[nodiscard]] virtual ComplexMatrix get_matrix() const = 0; virtual void update_quantum_state(StateVector& state_vector) const = 0; + + [[nodiscard]] virtual std::string to_string(const std::string& indent = "") const = 0; }; template @@ -231,7 +248,11 @@ class GatePtr { return _gate_ptr.get(); } - // Due to dependency reasons, the definition of operator<< is in gate_factory.hpp + template + friend std::ostream& operator<<(std::ostream& os, GatePtr gate) { + os << gate->to_string(); + return os; + } }; } // namespace internal diff --git a/scaluq/gate/gate_factory.hpp b/scaluq/gate/gate_factory.hpp index 4951dfff..6ed1580c 100644 --- a/scaluq/gate/gate_factory.hpp +++ b/scaluq/gate/gate_factory.hpp @@ -215,134 +215,4 @@ inline Gate Probablistic(const std::vector& distribution, gate_list); } } // namespace gate - -template -std::string gate_to_string(const internal::GatePtr& obj, std::uint32_t depth = 0) { - std::ostringstream ss; - std::string indent(depth * 2, ' '); - - if (obj.gate_type() == GateType::Probablistic) { - const auto prob_gate = ProbablisticGate(obj); - const auto distribution = prob_gate->distribution(); - const auto gates = prob_gate->gate_list(); - ss << indent << "Gate Type: Probablistic\n"; - for (std::size_t i = 0; i < distribution.size(); ++i) { - ss << indent << " --------------------\n"; - ss << indent << " Probability: " << distribution[i] << "\n"; - ss << gate_to_string(gates[i], depth + 1) << (i == distribution.size() - 1 ? "" : "\n"); - } - return ss.str(); - } - - auto targets = internal::mask_to_vector(obj->target_qubit_mask()); - auto controls = internal::mask_to_vector(obj->control_qubit_mask()); - - ss << indent << "Gate Type: "; - switch (obj.gate_type()) { - case GateType::I: - ss << "I"; - break; - case GateType::GlobalPhase: - ss << "GlobalPhase"; - break; - case GateType::X: - ss << "X"; - break; - case GateType::Y: - ss << "Y"; - break; - case GateType::Z: - ss << "Z"; - break; - case GateType::H: - ss << "H"; - break; - case GateType::S: - ss << "S"; - break; - case GateType::Sdag: - ss << "Sdag"; - break; - case GateType::T: - ss << "T"; - break; - case GateType::Tdag: - ss << "Tdag"; - break; - case GateType::SqrtX: - ss << "SqrtX"; - break; - case GateType::SqrtXdag: - ss << "SqrtXdag"; - break; - case GateType::SqrtY: - ss << "SqrtY"; - break; - case GateType::SqrtYdag: - ss << "SqrtYdag"; - break; - case GateType::P0: - ss << "P0"; - break; - case GateType::P1: - ss << "P1"; - break; - case GateType::RX: - ss << "RX"; - break; - case GateType::RY: - ss << "RY"; - break; - case GateType::RZ: - ss << "RZ"; - break; - case GateType::U1: - ss << "U1"; - break; - case GateType::U2: - ss << "U2"; - break; - case GateType::U3: - ss << "U3"; - break; - case GateType::OneTargetMatrix: - ss << "OneTargetMatrix"; - break; - case GateType::Swap: - ss << "Swap"; - break; - case GateType::TwoTargetMatrix: - ss << "TwoTargetMatrix"; - break; - case GateType::Pauli: - ss << "Pauli"; - break; - case GateType::PauliRotation: - ss << "PauliRotation"; - break; - case GateType::Unknown: - default: - ss << "Unknown"; - break; - } - - ss << "\n"; - ss << indent << " Target Qubits: {"; - for (std::uint32_t i = 0; i < targets.size(); ++i) - ss << targets[i] << (i == targets.size() - 1 ? "" : ", "); - ss << "}\n"; - ss << indent << " Control Qubits: {"; - for (std::uint32_t i = 0; i < controls.size(); ++i) - ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); - ss << "}"; - - return ss.str(); -} - -template -std::ostream& operator<<(std::ostream& os, const internal::GatePtr& obj) { - os << gate_to_string(obj); - return os; -} - } // namespace scaluq diff --git a/scaluq/gate/gate_matrix.hpp b/scaluq/gate/gate_matrix.hpp index 5d80ff23..fbc72cef 100644 --- a/scaluq/gate/gate_matrix.hpp +++ b/scaluq/gate/gate_matrix.hpp @@ -48,6 +48,13 @@ class OneTargetMatrixGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); one_target_dense_matrix_gate(_target_mask, _control_mask, _matrix, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: OneTargetMatrix\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class TwoTargetMatrixGateImpl : public GateBase { @@ -100,6 +107,13 @@ class TwoTargetMatrixGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); two_target_dense_matrix_gate(_target_mask, _control_mask, _matrix, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: TwoTargetMatrix\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; } // namespace internal diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index 0671fbb1..babeaad0 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -24,6 +24,13 @@ class PauliGateImpl : public GateBase { void update_quantum_state(StateVector& state_vector) const override { pauli_gate(_control_mask, _pauli, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: Pauli\n"; + ss << _pauli.get_pauli_string(); + return ss.str(); + } }; class PauliRotationGateImpl : public GateBase { @@ -56,6 +63,14 @@ class PauliRotationGateImpl : public GateBase { void update_quantum_state(StateVector& state_vector) const override { pauli_rotation_gate(_control_mask, _pauli, _angle, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: PauliRotation\n"; + ss << indent << " Angle: " << _angle << "\n"; + ss << _pauli.get_pauli_string(); + return ss.str(); + } }; } // namespace internal diff --git a/scaluq/gate/gate_probablistic.hpp b/scaluq/gate/gate_probablistic.hpp index 26a33478..661ab905 100644 --- a/scaluq/gate/gate_probablistic.hpp +++ b/scaluq/gate/gate_probablistic.hpp @@ -85,6 +85,18 @@ class ProbablisticGateImpl : public GateBase { if (i >= _gate_list.size()) i = _gate_list.size() - 1; _gate_list[i]->update_quantum_state(state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + const auto dist = distribution(); + ss << indent << "Gate Type: Probablistic\n"; + for (std::size_t i = 0; i < dist.size(); ++i) { + ss << indent << " --------------------\n"; + ss << indent << " Probability: " << dist[i] << "\n"; + ss << gate_list()[i]->to_string(indent + " ") << (i == dist.size() - 1 ? "" : "\n"); + } + return ss.str(); + } }; } // namespace internal diff --git a/scaluq/gate/gate_standard.hpp b/scaluq/gate/gate_standard.hpp index e1046155..2b473b1e 100644 --- a/scaluq/gate/gate_standard.hpp +++ b/scaluq/gate/gate_standard.hpp @@ -16,6 +16,13 @@ class IGateImpl : public GateBase { void update_quantum_state(StateVector& state_vector) const override { i_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: I\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class GlobalPhaseGateImpl : public GateBase { @@ -39,6 +46,14 @@ class GlobalPhaseGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); global_phase_gate(_target_mask, _control_mask, _phase, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: GlobalPhase\n"; + ss << indent << " Phase: " << _phase << "\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class RotationGateBase : public GateBase { @@ -67,6 +82,13 @@ class XGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); x_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: X\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class YGateImpl : public GateBase { @@ -84,6 +106,13 @@ class YGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); y_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: Y\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class ZGateImpl : public GateBase { @@ -101,6 +130,13 @@ class ZGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); z_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: Z\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class HGateImpl : public GateBase { @@ -119,6 +155,13 @@ class HGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); h_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: H\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class SGateImpl; @@ -145,6 +188,13 @@ class SGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); s_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: S\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class SdagGateImpl : public GateBase { @@ -164,6 +214,13 @@ class SdagGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); sdag_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: Sdag\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; // for resolving dependency issues inline Gate SGateImpl::get_inverse() const { @@ -185,6 +242,13 @@ class TGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); t_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: T\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class TdagGateImpl : public GateBase { @@ -204,6 +268,13 @@ class TdagGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); tdag_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: Tdag\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; // for resolving dependency issues inline Gate TGateImpl::get_inverse() const { @@ -225,6 +296,13 @@ class SqrtXGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); sqrtx_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: SqrtX\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class SqrtXdagGateImpl : public GateBase { @@ -244,6 +322,13 @@ class SqrtXdagGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); sqrtxdag_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: SqrtXdag\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; // for resolving dependency issues inline Gate SqrtXGateImpl::get_inverse() const { @@ -265,6 +350,13 @@ class SqrtYGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); sqrty_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: SqrtY\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class SqrtYdagGateImpl : public GateBase { @@ -284,6 +376,13 @@ class SqrtYdagGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); sqrtydag_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: SqrtYdag\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; // for resolving dependency issues inline Gate SqrtYGateImpl::get_inverse() const { @@ -307,6 +406,13 @@ class P0GateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); p0_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: P0\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class P1GateImpl : public GateBase { @@ -326,6 +432,13 @@ class P1GateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); p1_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: P1\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class RXGateImpl : public RotationGateBase { @@ -346,6 +459,14 @@ class RXGateImpl : public RotationGateBase { check_qubit_mask_within_bounds(state_vector); rx_gate(_target_mask, _control_mask, _angle, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: RX\n"; + ss << indent << " Angle: " << this->_angle << "\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class RYGateImpl : public RotationGateBase { @@ -366,6 +487,14 @@ class RYGateImpl : public RotationGateBase { check_qubit_mask_within_bounds(state_vector); ry_gate(_target_mask, _control_mask, _angle, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: RY\n"; + ss << indent << " Angle: " << this->_angle << "\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class RZGateImpl : public RotationGateBase { @@ -385,6 +514,14 @@ class RZGateImpl : public RotationGateBase { check_qubit_mask_within_bounds(state_vector); rz_gate(_target_mask, _control_mask, _angle, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: RZ\n"; + ss << indent << " Angle: " << this->_angle << "\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class U1GateImpl : public GateBase { @@ -409,6 +546,13 @@ class U1GateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); u1_gate(_target_mask, _control_mask, _lambda, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: U1\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class U2GateImpl : public GateBase { double _phi, _lambda; @@ -436,6 +580,13 @@ class U2GateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); u2_gate(_target_mask, _control_mask, _phi, _lambda, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: U2\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class U3GateImpl : public GateBase { @@ -469,6 +620,13 @@ class U3GateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); u3_gate(_target_mask, _control_mask, _theta, _phi, _lambda, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: U3\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class SwapGateImpl : public GateBase { @@ -486,6 +644,13 @@ class SwapGateImpl : public GateBase { check_qubit_mask_within_bounds(state_vector); swap_gate(_target_mask, _control_mask, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: Swap\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; } // namespace internal diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index f5b395b4..b871e893 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -65,6 +65,22 @@ class ParamGateBase { } } + std::string get_qubit_info_as_string(const std::string& indent) const { + std::ostringstream ss; + auto targets = target_qubit_list(); + auto controls = control_qubit_list(); + ss << indent << " Parameter Coefficient: " << _pcoef << "\n"; + ss << indent << " Target Qubits: {"; + for (std::uint32_t i = 0; i < targets.size(); ++i) + ss << targets[i] << (i == targets.size() - 1 ? "" : ", "); + ss << "}\n"; + ss << indent << " Control Qubits: {"; + for (std::uint32_t i = 0; i < controls.size(); ++i) + ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); + ss << "}"; + return ss.str(); + } + public: ParamGateBase(std::uint64_t target_mask, std::uint64_t control_mask, double param_coef = 1.) : _target_mask(target_mask), _control_mask(control_mask), _pcoef(param_coef) { @@ -97,6 +113,8 @@ class ParamGateBase { [[nodiscard]] virtual ComplexMatrix get_matrix(double param) const = 0; virtual void update_quantum_state(StateVector& state_vector, double param) const = 0; + + [[nodiscard]] virtual std::string to_string(const std::string& indent = "") const = 0; }; template @@ -163,7 +181,11 @@ class ParamGatePtr { return _param_gate_ptr.get(); } - // Due to dependency reasons, the definition of operator<< is in param_gate_factory.hpp + template + friend std::ostream& operator<<(std::ostream& os, ParamGatePtr gate) { + os << gate->to_string(); + return os; + } }; } // namespace internal diff --git a/scaluq/gate/param_gate_factory.hpp b/scaluq/gate/param_gate_factory.hpp index 60466300..c76e0a9d 100644 --- a/scaluq/gate/param_gate_factory.hpp +++ b/scaluq/gate/param_gate_factory.hpp @@ -46,71 +46,4 @@ inline ParamGate ParamProbablistic(const std::vector& distribution, distribution, gate_list); } } // namespace gate - -template -std::string gate_to_string(const internal::ParamGatePtr& obj, std::uint32_t depth = 0) { - std::ostringstream ss; - std::string indent(depth * 2, ' '); - - if (obj.param_gate_type() == ParamGateType::ParamProbablistic) { - const auto prob_gate = ParamProbablisticGate(obj); - const auto distribution = prob_gate->distribution(); - const auto gates = prob_gate->gate_list(); - ss << indent << "Gate Type: Probablistic\n"; - for (std::size_t i = 0; i < distribution.size(); ++i) { - ss << indent << " --------------------\n"; - ss << indent << " Probability: " << distribution[i] << "\n"; - std::visit( - [&](auto&& arg) { - ss << gate_to_string(arg, depth + 1) - << (i == distribution.size() - 1 ? "" : "\n"); - }, - gates[i]); - } - return ss.str(); - } - - auto targets = internal::mask_to_vector(obj->target_qubit_mask()); - auto controls = internal::mask_to_vector(obj->control_qubit_mask()); - auto param_coef = obj->param_coef(); - - ss << indent << "Gate Type: "; - switch (obj.param_gate_type()) { - case ParamGateType::ParamRX: - ss << "ParamRX"; - break; - case ParamGateType::ParamRY: - ss << "ParamRY"; - break; - case ParamGateType::ParamRZ: - ss << "ParamRZ"; - break; - case ParamGateType::ParamPauliRotation: - ss << "ParamPauliRotation"; - break; - case ParamGateType::Unknown: - default: - ss << "Undefined"; - break; - } - - ss << "\n"; - ss << indent << " Parameter Coefficient: " << param_coef << "\n"; - ss << indent << " Target Qubits: {"; - for (std::uint32_t i = 0; i < targets.size(); ++i) - ss << targets[i] << (i == targets.size() - 1 ? "" : ", "); - ss << "}\n"; - ss << indent << " Control Qubits: {"; - for (std::uint32_t i = 0; i < controls.size(); ++i) - ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); - ss << "}"; - return ss.str(); -} - -template -std::ostream& operator<<(std::ostream& os, const internal::ParamGatePtr& obj) { - os << gate_to_string(obj); - return os; -} - } // namespace scaluq diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index f9f1d959..cfb17531 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -37,6 +37,13 @@ class ParamPauliRotationGateImpl : public ParamGateBase { void update_quantum_state(StateVector& state_vector, double param) const override { pauli_rotation_gate(_control_mask, _pauli, _pcoef * param, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: ParamPauliRotation\n"; + ss << _pauli.get_pauli_string(); + return ss.str(); + } }; } // namespace internal diff --git a/scaluq/gate/param_gate_probablistic.hpp b/scaluq/gate/param_gate_probablistic.hpp index a6622299..85f8cb71 100644 --- a/scaluq/gate/param_gate_probablistic.hpp +++ b/scaluq/gate/param_gate_probablistic.hpp @@ -95,6 +95,22 @@ class ParamProbablisticGateImpl : public ParamGateBase { std::get<1>(gate)->update_quantum_state(state_vector, param); } } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + const auto dist = distribution(); + ss << indent << "Gate Type: Probablistic\n"; + for (std::size_t i = 0; i < dist.size(); ++i) { + ss << indent << " --------------------\n"; + ss << indent << " Probability: " << dist[i] << "\n"; + std::visit( + [&](auto&& arg) { + ss << arg->to_string(indent + " ") << (i == dist.size() - 1 ? "" : "\n"); + }, + gate_list()[i]); + } + return ss.str(); + } }; } // namespace internal diff --git a/scaluq/gate/param_gate_standard.hpp b/scaluq/gate/param_gate_standard.hpp index 23da71b4..36e35a37 100644 --- a/scaluq/gate/param_gate_standard.hpp +++ b/scaluq/gate/param_gate_standard.hpp @@ -27,6 +27,13 @@ class ParamRXGateImpl : public ParamGateBase { check_qubit_mask_within_bounds(state_vector); rx_gate(_target_mask, _control_mask, _pcoef * param, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: ParamRX\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class ParamRYGateImpl : public ParamGateBase { @@ -47,6 +54,13 @@ class ParamRYGateImpl : public ParamGateBase { check_qubit_mask_within_bounds(state_vector); ry_gate(_target_mask, _control_mask, _pcoef * param, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: ParamRY\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; class ParamRZGateImpl : public ParamGateBase { @@ -67,6 +81,13 @@ class ParamRZGateImpl : public ParamGateBase { check_qubit_mask_within_bounds(state_vector); rz_gate(_target_mask, _control_mask, _pcoef * param, state_vector); } + + std::string to_string(const std::string& indent) const override { + std::ostringstream ss; + ss << indent << "Gate Type: ParamRZ\n"; + ss << get_qubit_info_as_string(indent); + return ss.str(); + } }; } // namespace internal From 815f24f049ce58890381f5c25d19e34a61c3f223 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Mon, 9 Sep 2024 09:48:39 +0900 Subject: [PATCH 50/55] fix typo --- scaluq/circuit/circuit.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scaluq/circuit/circuit.hpp b/scaluq/circuit/circuit.hpp index 05d22cf5..5d173d5a 100644 --- a/scaluq/circuit/circuit.hpp +++ b/scaluq/circuit/circuit.hpp @@ -112,7 +112,7 @@ void bind_circuit_circuit_hpp(nb::module_& m) { .def("copy", &Circuit::copy, "Copy circuit. All the gates inside is copied.") .def("get_inverse", &Circuit::get_inverse, - "Get inverse of circuit. ALl the gates are newly created."); + "Get inverse of circuit. All the gates are newly created."); } } // namespace internal #endif From ddcf43bded4a75758696124172fa788b29c82212 Mon Sep 17 00:00:00 2001 From: KowerKoint Date: Mon, 9 Sep 2024 10:00:35 +0900 Subject: [PATCH 51/55] PointerAlighment: Left --- .clang-format | 2 ++ python/binding.cpp | 4 ++-- scaluq/gate/gate.hpp | 32 ++++++++++++++++---------------- scaluq/gate/param_gate.hpp | 34 +++++++++++++++++----------------- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/.clang-format b/.clang-format index a49304f2..f496c47a 100644 --- a/.clang-format +++ b/.clang-format @@ -7,3 +7,5 @@ AccessModifierOffset: -4 BinPackArguments: false BinPackParameters: false ColumnLimit: 100 +DerivePointerAlignment: false +PointerAlignment: Left diff --git a/python/binding.cpp b/python/binding.cpp index 971504f0..dcd732ae 100644 --- a/python/binding.cpp +++ b/python/binding.cpp @@ -31,7 +31,7 @@ struct type_caster> { NB_TYPE_CASTER(Kokkos::complex, const_name("complex")) template - bool from_python(handle src, uint8_t flags, cleanup_list *cleanup) noexcept { + bool from_python(handle src, uint8_t flags, cleanup_list* cleanup) noexcept { (void)flags; (void)cleanup; @@ -63,7 +63,7 @@ struct type_caster> { } template - static handle from_cpp(T2 &&value, rv_policy policy, cleanup_list *cleanup) noexcept { + static handle from_cpp(T2&& value, rv_policy policy, cleanup_list* cleanup) noexcept { (void)policy; (void)cleanup; diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index bfaddcf4..0d2a8cf3 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -127,7 +127,7 @@ namespace internal { class GateBase : public std::enable_shared_from_this { protected: std::uint64_t _target_mask, _control_mask; - void check_qubit_mask_within_bounds(const StateVector &state_vector) const { + void check_qubit_mask_within_bounds(const StateVector& state_vector) const { std::uint64_t full_mask = (1ULL << state_vector.n_qubits()) - 1; if ((_target_mask | _control_mask) > full_mask) [[unlikely]] { throw std::runtime_error( @@ -166,7 +166,7 @@ class GateBase : public std::enable_shared_from_this { [[nodiscard]] virtual Gate get_inverse() const = 0; [[nodiscard]] virtual internal::ComplexMatrix get_matrix() const = 0; - virtual void update_quantum_state(StateVector &state_vector) const = 0; + virtual void update_quantum_state(StateVector& state_vector) const = 0; }; template @@ -181,9 +181,9 @@ class GatePtr { public: GatePtr() : _gate_ptr(nullptr), _gate_type(get_gate_type()) {} - GatePtr(const GatePtr &gate) = default; + GatePtr(const GatePtr& gate) = default; template - GatePtr(const std::shared_ptr &gate_ptr) { + GatePtr(const std::shared_ptr& gate_ptr) { if constexpr (std::is_same_v) { _gate_type = get_gate_type(); _gate_ptr = gate_ptr; @@ -200,7 +200,7 @@ class GatePtr { } } template - GatePtr(const GatePtr &gate) { + GatePtr(const GatePtr& gate) { if constexpr (std::is_same_v) { _gate_type = gate._gate_type; _gate_ptr = gate._gate_ptr; @@ -220,7 +220,7 @@ class GatePtr { GateType gate_type() const { return _gate_type; } - const T *operator->() const { + const T* operator->() const { if (!_gate_ptr) { throw std::runtime_error("GatePtr::operator->(): Gate is Null"); } @@ -236,41 +236,41 @@ namespace internal { .def("gate_type", &GATE_TYPE::gate_type, "Get gate type as `GateType` enum.") \ .def( \ "target_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->target_qubit_list(); }, \ + [](const GATE_TYPE& gate) { return gate->target_qubit_list(); }, \ "Get target qubits as `list[int]`. **Control qubits is not included.**") \ .def( \ "control_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->control_qubit_list(); }, \ + [](const GATE_TYPE& gate) { return gate->control_qubit_list(); }, \ "Get control qubits as `list[int]`.") \ .def( \ "operand_qubit_list", \ - [](const GATE_TYPE &gate) { return gate->operand_qubit_list(); }, \ + [](const GATE_TYPE& gate) { return gate->operand_qubit_list(); }, \ "Get target and control qubits as `list[int]`.") \ .def( \ "target_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->target_qubit_mask(); }, \ + [](const GATE_TYPE& gate) { return gate->target_qubit_mask(); }, \ "Get target qubits as mask. **Control qubits is not included.**") \ .def( \ "control_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->control_qubit_mask(); }, \ + [](const GATE_TYPE& gate) { return gate->control_qubit_mask(); }, \ "Get control qubits as mask.") \ .def( \ "operand_qubit_mask", \ - [](const GATE_TYPE &gate) { return gate->operand_qubit_mask(); }, \ + [](const GATE_TYPE& gate) { return gate->operand_qubit_mask(); }, \ "Get target and control qubits as mask.") \ .def( \ "get_inverse", \ - [](const GATE_TYPE &gate) { return gate->get_inverse(); }, \ + [](const GATE_TYPE& gate) { return gate->get_inverse(); }, \ "Generate inverse gate as `Gate` type. If not exists, return None.") \ .def( \ "update_quantum_state", \ - [](const GATE_TYPE &gate, StateVector &state_vector) { \ + [](const GATE_TYPE& gate, StateVector& state_vector) { \ gate->update_quantum_state(state_vector); \ }, \ "Apply gate to `state_vector`. `state_vector` in args is directly updated.") \ .def( \ "get_matrix", \ - [](const GATE_TYPE &gate) { return gate->get_matrix(); }, \ + [](const GATE_TYPE& gate) { return gate->get_matrix(); }, \ "Get matrix representation of the gate.") nb::class_ gate_base_def; @@ -283,7 +283,7 @@ nb::class_ gate_base_def; "\n\n.. note:: Upcast is required to use gate-general functions (ex: add to Circuit).") \ .def(nb::init()) -void bind_gate_gate_hpp(nb::module_ &m) { +void bind_gate_gate_hpp(nb::module_& m) { nb::enum_(m, "GateType", "Enum of Gate Type.") .value("I", GateType::I) .value("GlobalPhase", GateType::GlobalPhase) diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index eea4ad39..476f35a9 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -41,7 +41,7 @@ class ParamGateBase { protected: std::uint64_t _target_mask, _control_mask; double _pcoef; - void check_qubit_mask_within_bounds(const StateVector &state_vector) const { + void check_qubit_mask_within_bounds(const StateVector& state_vector) const { std::uint64_t full_mask = (1ULL << state_vector.n_qubits()) - 1; if ((_target_mask | _control_mask) > full_mask) [[unlikely]] { throw std::runtime_error( @@ -82,7 +82,7 @@ class ParamGateBase { [[nodiscard]] virtual ParamGate get_inverse() const = 0; [[nodiscard]] virtual internal::ComplexMatrix get_matrix(double param) const = 0; - virtual void update_quantum_state(StateVector &state_vector, double param) const = 0; + virtual void update_quantum_state(StateVector& state_vector, double param) const = 0; }; template @@ -97,9 +97,9 @@ class ParamGatePtr { public: ParamGatePtr() : _param_gate_ptr(nullptr), _param_gate_type(get_param_gate_type()) {} - ParamGatePtr(const ParamGatePtr ¶m_gate) = default; + ParamGatePtr(const ParamGatePtr& param_gate) = default; template - ParamGatePtr(const std::shared_ptr ¶m_gate_ptr) { + ParamGatePtr(const std::shared_ptr& param_gate_ptr) { if constexpr (std::is_same_v) { _param_gate_type = get_param_gate_type(); _param_gate_ptr = param_gate_ptr; @@ -116,7 +116,7 @@ class ParamGatePtr { } } template - ParamGatePtr(const ParamGatePtr ¶m_gate) { + ParamGatePtr(const ParamGatePtr& param_gate) { if constexpr (std::is_same_v) { _param_gate_type = param_gate._param_gate_type; _param_gate_ptr = param_gate._param_gate_ptr; @@ -136,7 +136,7 @@ class ParamGatePtr { ParamGateType param_gate_type() const { return _param_gate_type; } - const T *operator->() const { + const T* operator->() const { if (!_param_gate_ptr) { throw std::runtime_error("ParamGatePtr::operator->(): ParamGate is Null"); } @@ -154,46 +154,46 @@ namespace internal { "Get parametric gate type as `ParamGateType` enum.") \ .def( \ "param_coef", \ - [](const PARAM_GATE_TYPE &gate) { return gate->param_coef(); }, \ + [](const PARAM_GATE_TYPE& gate) { return gate->param_coef(); }, \ "Get coefficient of parameter.") \ .def( \ "target_qubit_list", \ - [](const PARAM_GATE_TYPE &gate) { return gate->target_qubit_list(); }, \ + [](const PARAM_GATE_TYPE& gate) { return gate->target_qubit_list(); }, \ "Get target qubits as `list[int]`. **Control qubits is not included.**") \ .def( \ "control_qubit_list", \ - [](const PARAM_GATE_TYPE &gate) { return gate->control_qubit_list(); }, \ + [](const PARAM_GATE_TYPE& gate) { return gate->control_qubit_list(); }, \ "Get control qubits as `list[int]`.") \ .def( \ "operand_qubit_list", \ - [](const PARAM_GATE_TYPE &gate) { return gate->operand_qubit_list(); }, \ + [](const PARAM_GATE_TYPE& gate) { return gate->operand_qubit_list(); }, \ "Get target and control qubits as `list[int]`.") \ .def( \ "target_qubit_mask", \ - [](const PARAM_GATE_TYPE &gate) { return gate->target_qubit_mask(); }, \ + [](const PARAM_GATE_TYPE& gate) { return gate->target_qubit_mask(); }, \ "Get target qubits as mask. **Control qubits is not included.**") \ .def( \ "control_qubit_mask", \ - [](const PARAM_GATE_TYPE &gate) { return gate->control_qubit_mask(); }, \ + [](const PARAM_GATE_TYPE& gate) { return gate->control_qubit_mask(); }, \ "Get control qubits as mask.") \ .def( \ "operand_qubit_mask", \ - [](const PARAM_GATE_TYPE &gate) { return gate->operand_qubit_mask(); }, \ + [](const PARAM_GATE_TYPE& gate) { return gate->operand_qubit_mask(); }, \ "Get target and control qubits as mask.") \ .def( \ "get_inverse", \ - [](const PARAM_GATE_TYPE ¶m_gate) { return param_gate->get_inverse(); }, \ + [](const PARAM_GATE_TYPE& param_gate) { return param_gate->get_inverse(); }, \ "Generate inverse parametric-gate as `ParamGate` type. If not exists, return None.") \ .def( \ "update_quantum_state", \ - [](const PARAM_GATE_TYPE ¶m_gate, StateVector &state_vector, double param) { \ + [](const PARAM_GATE_TYPE& param_gate, StateVector& state_vector, double param) { \ param_gate->update_quantum_state(state_vector, param); \ }, \ "Apply gate to `state_vector` with holding the parameter. `state_vector` in args is " \ "directly updated.") \ .def( \ "get_matrix", \ - [](const PARAM_GATE_TYPE &gate, double param) { return gate->get_matrix(param); }, \ + [](const PARAM_GATE_TYPE& gate, double param) { return gate->get_matrix(param); }, \ "Get matrix representation of the gate with holding the parameter.") nb::class_ param_gate_base_def; @@ -207,7 +207,7 @@ nb::class_ param_gate_base_def; "\n\n.. note:: Upcast is required to use gate-general functions (ex: add to Circuit).") \ .def(nb::init()) -void bind_gate_param_gate_hpp(nb::module_ &m) { +void bind_gate_param_gate_hpp(nb::module_& m) { nb::enum_(m, "ParamGateType", "Enum of ParamGate Type.") .value("ParamRX", ParamGateType::ParamRX) .value("ParamRY", ParamGateType::ParamRY) From 7c4bcef45e3ce9db2f8a2eafd2012a8ba1e2c05f Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Mon, 9 Sep 2024 13:30:45 +0000 Subject: [PATCH 52/55] remove template difinition in friend function --- scaluq/gate/gate.hpp | 3 +-- scaluq/gate/param_gate.hpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 64b5e542..d72c2cc5 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -248,8 +248,7 @@ class GatePtr { return _gate_ptr.get(); } - template - friend std::ostream& operator<<(std::ostream& os, GatePtr gate) { + friend std::ostream& operator<<(std::ostream& os, GatePtr gate) { os << gate->to_string(); return os; } diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index b871e893..8ce03eaa 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -181,8 +181,7 @@ class ParamGatePtr { return _param_gate_ptr.get(); } - template - friend std::ostream& operator<<(std::ostream& os, ParamGatePtr gate) { + friend std::ostream& operator<<(std::ostream& os, ParamGatePtr gate) { os << gate->to_string(); return os; } From f8183275695164f9f4da4085637cdec8692ec896 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Mon, 9 Sep 2024 14:06:13 +0000 Subject: [PATCH 53/55] fix output of pauli --- scaluq/gate/gate_pauli.hpp | 14 ++++++++++++-- scaluq/gate/param_gate_pauli.hpp | 7 ++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/scaluq/gate/gate_pauli.hpp b/scaluq/gate/gate_pauli.hpp index d861ac24..3b9c7d94 100644 --- a/scaluq/gate/gate_pauli.hpp +++ b/scaluq/gate/gate_pauli.hpp @@ -29,8 +29,13 @@ class PauliGateImpl : public GateBase { std::string to_string(const std::string& indent) const override { std::ostringstream ss; + auto controls = control_qubit_list(); ss << indent << "Gate Type: Pauli\n"; - ss << _pauli.get_pauli_string(); + ss << indent << " Control Qubits: {"; + for (std::uint32_t i = 0; i < controls.size(); ++i) + ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); + ss << "}\n"; + ss << indent << " Pauli Operator: \"" << _pauli.get_pauli_string() << "\""; return ss.str(); } }; @@ -70,9 +75,14 @@ class PauliRotationGateImpl : public GateBase { std::string to_string(const std::string& indent) const override { std::ostringstream ss; + auto controls = control_qubit_list(); ss << indent << "Gate Type: PauliRotation\n"; ss << indent << " Angle: " << _angle << "\n"; - ss << _pauli.get_pauli_string(); + ss << indent << " Control Qubits: {"; + for (std::uint32_t i = 0; i < controls.size(); ++i) + ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); + ss << "}\n"; + ss << indent << " Pauli Operator: \"" << _pauli.get_pauli_string() << "\""; return ss.str(); } }; diff --git a/scaluq/gate/param_gate_pauli.hpp b/scaluq/gate/param_gate_pauli.hpp index 03202a57..985378d1 100644 --- a/scaluq/gate/param_gate_pauli.hpp +++ b/scaluq/gate/param_gate_pauli.hpp @@ -47,8 +47,13 @@ class ParamPauliRotationGateImpl : public ParamGateBase { std::string to_string(const std::string& indent) const override { std::ostringstream ss; + auto controls = control_qubit_list(); ss << indent << "Gate Type: ParamPauliRotation\n"; - ss << _pauli.get_pauli_string(); + ss << indent << " Control Qubits: {"; + for (std::uint32_t i = 0; i < controls.size(); ++i) + ss << controls[i] << (i == controls.size() - 1 ? "" : ", "); + ss << "}\n"; + ss << indent << " Pauli Operator: \"" << _pauli.get_pauli_string() << "\""; return ss.str(); } }; From 67575336672f9639f32b6166648e464a7908a004 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 10 Sep 2024 01:59:43 +0000 Subject: [PATCH 54/55] add binding --- exe/main.py | 12 ++++-------- scaluq/gate/gate.hpp | 10 +++++++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/exe/main.py b/exe/main.py index 349abafb..e67893b9 100644 --- a/exe/main.py +++ b/exe/main.py @@ -1,15 +1,11 @@ from scaluq import * +# from scaluq.gate import S def main(): state = StateVector(2) - gate = SWAP(0, 1) - gate = SWAPGate(gate) - mat = gate.get_matrix() - print(mat) - t = type(mat[0][0]) - print(t) + swap_gate = gate.Swap(0, 1) + print(state) + print(swap_gate) if __name__ == "__main__": - initialize(InitializationSettings().set_num_threads(8)) main() - finalize() diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 4ecf07a9..309705b2 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -297,7 +297,15 @@ namespace internal { .def( \ "get_matrix", \ [](const GATE_TYPE& gate) { return gate->get_matrix(); }, \ - "Get matrix representation of the gate.") + "Get matrix representation of the gate.") \ + .def( \ + "to_string", \ + [](const GATE_TYPE& gate) { return gate->to_string(""); }, \ + "Get string representation of the gate.") \ + .def( \ + "__str__", \ + [](const GATE_TYPE& gate) { return gate->to_string(""); }, \ + "Get string representation of the gate.") nb::class_ gate_base_def; From ea34abfe0e8bf76c55f9d0c6cb430473bd1886d4 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Tue, 10 Sep 2024 11:27:15 +0000 Subject: [PATCH 55/55] lazy evaluation of static_assert --- scaluq/gate/gate.hpp | 98 ++++++++++++++++++++++---------------- scaluq/gate/param_gate.hpp | 25 ++++------ scaluq/types.hpp | 3 +- 3 files changed, 69 insertions(+), 57 deletions(-) diff --git a/scaluq/gate/gate.hpp b/scaluq/gate/gate.hpp index 309705b2..51e34539 100644 --- a/scaluq/gate/gate.hpp +++ b/scaluq/gate/gate.hpp @@ -76,50 +76,72 @@ enum class GateType { TwoTargetMatrix, Pauli, PauliRotation, - Probablistic, - Error + Probablistic }; template constexpr GateType get_gate_type() { using TWithoutConst = std::remove_cv_t; - if constexpr (std::is_same_v) return GateType::Unknown; - if constexpr (std::is_same_v) return GateType::I; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) + return GateType::Unknown; + else if constexpr (std::is_same_v) + return GateType::I; + else if constexpr (std::is_same_v) return GateType::GlobalPhase; - if constexpr (std::is_same_v) return GateType::X; - if constexpr (std::is_same_v) return GateType::Y; - if constexpr (std::is_same_v) return GateType::Z; - if constexpr (std::is_same_v) return GateType::H; - if constexpr (std::is_same_v) return GateType::S; - if constexpr (std::is_same_v) return GateType::Sdag; - if constexpr (std::is_same_v) return GateType::T; - if constexpr (std::is_same_v) return GateType::Tdag; - if constexpr (std::is_same_v) return GateType::SqrtX; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) + return GateType::X; + else if constexpr (std::is_same_v) + return GateType::Y; + else if constexpr (std::is_same_v) + return GateType::Z; + else if constexpr (std::is_same_v) + return GateType::H; + else if constexpr (std::is_same_v) + return GateType::S; + else if constexpr (std::is_same_v) + return GateType::Sdag; + else if constexpr (std::is_same_v) + return GateType::T; + else if constexpr (std::is_same_v) + return GateType::Tdag; + else if constexpr (std::is_same_v) + return GateType::SqrtX; + else if constexpr (std::is_same_v) return GateType::SqrtXdag; - if constexpr (std::is_same_v) return GateType::SqrtY; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) + return GateType::SqrtY; + else if constexpr (std::is_same_v) return GateType::SqrtYdag; - if constexpr (std::is_same_v) return GateType::P0; - if constexpr (std::is_same_v) return GateType::P1; - if constexpr (std::is_same_v) return GateType::RX; - if constexpr (std::is_same_v) return GateType::RY; - if constexpr (std::is_same_v) return GateType::RZ; - if constexpr (std::is_same_v) return GateType::U1; - if constexpr (std::is_same_v) return GateType::U2; - if constexpr (std::is_same_v) return GateType::U3; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) + return GateType::P0; + else if constexpr (std::is_same_v) + return GateType::P1; + else if constexpr (std::is_same_v) + return GateType::RX; + else if constexpr (std::is_same_v) + return GateType::RY; + else if constexpr (std::is_same_v) + return GateType::RZ; + else if constexpr (std::is_same_v) + return GateType::U1; + else if constexpr (std::is_same_v) + return GateType::U2; + else if constexpr (std::is_same_v) + return GateType::U3; + else if constexpr (std::is_same_v) return GateType::OneTargetMatrix; - if constexpr (std::is_same_v) return GateType::Swap; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) + return GateType::Swap; + else if constexpr (std::is_same_v) return GateType::TwoTargetMatrix; - if constexpr (std::is_same_v) return GateType::Pauli; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) + return GateType::Pauli; + else if constexpr (std::is_same_v) return GateType::PauliRotation; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return GateType::Probablistic; - return GateType::Error; + else + static_assert(internal::lazy_false_v, "unknown GateImpl"); } namespace internal { @@ -200,21 +222,15 @@ class GatePtr { template GatePtr(const std::shared_ptr& gate_ptr) { if constexpr (std::is_same_v) { - if ((_gate_type = get_gate_type()) == GateType::Error) { - throw std::runtime_error("Unknown GateType"); - } + _gate_type = get_gate_type(); _gate_ptr = gate_ptr; } else if constexpr (std::is_same_v) { // upcast - if ((_gate_type = get_gate_type()) == GateType::Error) { - throw std::runtime_error("Unknown GateType"); - } + _gate_type = get_gate_type(); _gate_ptr = std::static_pointer_cast(gate_ptr); } else { // downcast - if ((_gate_type = get_gate_type()) == GateType::Error) { - throw std::runtime_error("Unknown GateType"); - } + _gate_type = get_gate_type(); if (!(_gate_ptr = std::dynamic_pointer_cast(gate_ptr))) { throw std::runtime_error("invalid gate cast"); } diff --git a/scaluq/gate/param_gate.hpp b/scaluq/gate/param_gate.hpp index 430a83cd..d1e86050 100644 --- a/scaluq/gate/param_gate.hpp +++ b/scaluq/gate/param_gate.hpp @@ -38,17 +38,18 @@ constexpr ParamGateType get_param_gate_type() { using TWithoutConst = std::remove_cv_t; if constexpr (std::is_same_v) return ParamGateType::Unknown; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return ParamGateType::ParamRX; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return ParamGateType::ParamRY; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return ParamGateType::ParamRZ; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return ParamGateType::ParamPauliRotation; - if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return ParamGateType::ParamProbablistic; - return ParamGateType::Error; + else + static_assert(internal::lazy_false_v, "unknown GateImpl"); } namespace internal { @@ -133,21 +134,15 @@ class ParamGatePtr { template ParamGatePtr(const std::shared_ptr& param_gate_ptr) { if constexpr (std::is_same_v) { - if ((_param_gate_type = get_param_gate_type()) == ParamGateType::Error) { - throw std::runtime_error("Unknown GateType"); - } + _param_gate_type = get_param_gate_type(); _param_gate_ptr = param_gate_ptr; } else if constexpr (std::is_same_v) { // upcast - if ((_param_gate_type = get_param_gate_type()) == ParamGateType::Error) { - throw std::runtime_error("Unknown GateType"); - } + _param_gate_type = get_param_gate_type(); _param_gate_ptr = std::static_pointer_cast(param_gate_ptr); } else { // downcast - if ((_param_gate_type = get_param_gate_type()) == ParamGateType::Error) { - throw std::runtime_error("Unknown GateType"); - } + _param_gate_type = get_param_gate_type(); if (!(_param_gate_ptr = std::dynamic_pointer_cast(param_gate_ptr))) { throw std::runtime_error("invalid gate cast"); } diff --git a/scaluq/types.hpp b/scaluq/types.hpp index 4e3d028c..6b64f09d 100644 --- a/scaluq/types.hpp +++ b/scaluq/types.hpp @@ -22,7 +22,8 @@ using Complex = Kokkos::complex; using namespace std::complex_literals; namespace internal { - +template +constexpr bool lazy_false_v = false; // Used for lazy evaluation in static_assert. using ComplexMatrix = Eigen::Matrix; using SparseComplexMatrix = Eigen::SparseMatrix;