From 4dab2de66b66cc30a6ae4e563f58e27f77fa609a Mon Sep 17 00:00:00 2001 From: Glacialte Date: Thu, 16 Nov 2023 10:01:16 +0000 Subject: [PATCH 1/6] adding u1 gate --- qulacs/gate/gate_quantum_matrix.cpp | 9 ++++++++ qulacs/gate/gate_quantum_matrix.hpp | 20 +++++++++++++++++ qulacs/gate/update_ops.hpp | 4 ++++ qulacs/gate/update_ops_quantum_matrix.cpp | 26 +++++++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 qulacs/gate/gate_quantum_matrix.cpp create mode 100644 qulacs/gate/gate_quantum_matrix.hpp create mode 100644 qulacs/gate/update_ops_quantum_matrix.cpp diff --git a/qulacs/gate/gate_quantum_matrix.cpp b/qulacs/gate/gate_quantum_matrix.cpp new file mode 100644 index 00000000..34126f31 --- /dev/null +++ b/qulacs/gate/gate_quantum_matrix.cpp @@ -0,0 +1,9 @@ +#include "gate_quantum_matrix.hpp" + +#include "update_ops.hpp" + +namespace qulacs { +void U1::update_quantum_state(StateVector& state_vector) const { + u1_gate(this->_target, this->_matrix, state_vector); +} +} // namespace qulacs \ No newline at end of file diff --git a/qulacs/gate/gate_quantum_matrix.hpp b/qulacs/gate/gate_quantum_matrix.hpp new file mode 100644 index 00000000..ec23a29a --- /dev/null +++ b/qulacs/gate/gate_quantum_matrix.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "gate.hpp" +#include "update_ops.hpp" + +namespace qulacs { +class U1 : public QuantumGate { + UINT _target; + double _lambda; + std::array _matrix; + +public: + U1(UINT target, UINT lambda) : _target(target), _lambda(lambda) { + _matrix = get_IBMQ_matrix(0, 0, lambda); + }; + void update_quantum_state(StateVector& state_vector) const override; +} +} // namespace qulacs diff --git a/qulacs/gate/update_ops.hpp b/qulacs/gate/update_ops.hpp index 71e878d9..b034c1df 100644 --- a/qulacs/gate/update_ops.hpp +++ b/qulacs/gate/update_ops.hpp @@ -44,4 +44,8 @@ void rz_gate(UINT target_qubit_index, double angle, StateVector& state); void cnot_gate(UINT control_qubit_index, UINT target_qubit_index, StateVector& state); void cz_gate(UINT control_qubit_index, UINT target_qubit_index, StateVector& state); + +std::array get_IBMQ_matrix(double _theta, double _phi, double _lambda); + +void u1_gate(UINT target_qubit_index, std::array matrix, StateVector& state); } // namespace qulacs diff --git a/qulacs/gate/update_ops_quantum_matrix.cpp b/qulacs/gate/update_ops_quantum_matrix.cpp new file mode 100644 index 00000000..d0544eb0 --- /dev/null +++ b/qulacs/gate/update_ops_quantum_matrix.cpp @@ -0,0 +1,26 @@ +#include +#include + +#include "../types.hpp" +#include "constant.hpp" +#include "update_ops.hpp" + +namespace qulacs { +std::array get_IBMQ_matrix(double theta, double phi, double lambda) { + std::array matrix; + Complex im = Complex(0, 1); + Complex exp_val1 = std::exp(im * phi); + Complex exp_val2 = std::exp(im * lambda); + Complex cos_val = std::cos(theta / 2.); + Complex sin_val = std::sin(theta / 2.); + matrix[0] = cos_val; + matrix[1] = -exp_val2 * sin_val; + matrix[2] = exp_val1 * sin_val; + matrix[3] = exp_val1 * exp_val2 * cos_val; + return matrix; +} + +void u1_gate(UINT target_qubit_index, std::array matrix, StateVector& state) { + +} +} // namespace qulacs From fb26ba7e2c6369d121d40950cd6b3da65ebb000a Mon Sep 17 00:00:00 2001 From: Glacialte Date: Tue, 21 Nov 2023 09:56:53 +0900 Subject: [PATCH 2/6] add U1, U2, U3 gate --- qulacs/gate/gate_quantum_matrix.cpp | 10 ++++++- qulacs/gate/gate_quantum_matrix.hpp | 26 ++++++++++++++++++- qulacs/gate/update_ops.hpp | 4 ++- .../gate/update_ops_matrix_dense_single.cpp | 22 ++++++++++++++++ qulacs/gate/update_ops_quantum_matrix.cpp | 4 +-- 5 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 qulacs/gate/update_ops_matrix_dense_single.cpp diff --git a/qulacs/gate/gate_quantum_matrix.cpp b/qulacs/gate/gate_quantum_matrix.cpp index 34126f31..ffb628ca 100644 --- a/qulacs/gate/gate_quantum_matrix.cpp +++ b/qulacs/gate/gate_quantum_matrix.cpp @@ -4,6 +4,14 @@ namespace qulacs { void U1::update_quantum_state(StateVector& state_vector) const { - u1_gate(this->_target, this->_matrix, state_vector); + u_gate(this->_target, this->_matrix, state_vector); +} + +void U2::update_quantum_state(StateVector& state_vector) const { + u_gate(this->_target, this->_matrix, state_vector); +} + +void U3::update_quantum_state(StateVector& state_vector) const { + u_gate(this->_target, this->_matrix, state_vector); } } // namespace qulacs \ No newline at end of file diff --git a/qulacs/gate/gate_quantum_matrix.hpp b/qulacs/gate/gate_quantum_matrix.hpp index ec23a29a..910dc8a9 100644 --- a/qulacs/gate/gate_quantum_matrix.hpp +++ b/qulacs/gate/gate_quantum_matrix.hpp @@ -4,6 +4,7 @@ #include "gate.hpp" #include "update_ops.hpp" +#include "constant.hpp" namespace qulacs { class U1 : public QuantumGate { @@ -16,5 +17,28 @@ class U1 : public QuantumGate { _matrix = get_IBMQ_matrix(0, 0, lambda); }; void update_quantum_state(StateVector& state_vector) const override; -} +}; +class U2 : public QuantumGate { + UINT _target; + double _lambda, _phi; + std::array _matrix; + +public: + U2(UINT target, UINT lambda, UINT phi) : _target(target), _lambda(lambda), _phi(phi) { + _matrix = get_IBMQ_matrix(PI / 2.0, phi, lambda); + }; + void update_quantum_state(StateVector& state_vector) const override; +}; + +class U3 : public QuantumGate { + UINT _target; + double _theta, _lambda, _phi; + std::array _matrix; + +public: + U3(UINT target, UINT theta, UINT lambda, UINT phi) : _target(target), _theta(theta), _lambda(lambda), _phi(phi) { + _matrix = get_IBMQ_matrix(theta, phi, lambda); + }; + void update_quantum_state(StateVector& state_vector) const override; +}; } // namespace qulacs diff --git a/qulacs/gate/update_ops.hpp b/qulacs/gate/update_ops.hpp index b034c1df..f96854e0 100644 --- a/qulacs/gate/update_ops.hpp +++ b/qulacs/gate/update_ops.hpp @@ -47,5 +47,7 @@ void cz_gate(UINT control_qubit_index, UINT target_qubit_index, StateVector& sta std::array get_IBMQ_matrix(double _theta, double _phi, double _lambda); -void u1_gate(UINT target_qubit_index, std::array matrix, StateVector& state); +void single_qubit_dense_matrix_gate(UINT target_qubit_index, std::array matrix, StateVector& state); + +void u_gate(UINT target_qubit_index, std::array matrix, StateVector& state); } // namespace qulacs diff --git a/qulacs/gate/update_ops_matrix_dense_single.cpp b/qulacs/gate/update_ops_matrix_dense_single.cpp new file mode 100644 index 00000000..4ebf832c --- /dev/null +++ b/qulacs/gate/update_ops_matrix_dense_single.cpp @@ -0,0 +1,22 @@ +#include "update_ops.hpp" +#include +#include +#include "../types.hpp" + +namespace qulacs { +void single_qubit_dense_matrix_gate(UINT target_qubit_index, std::array matrix, StateVector& state) { + const UINT mask = 1ULL << target_qubit_index; + const mask_low = mask - 1; + const mask_high = ~mask_low; + Kokkos::parallel_for(state.size(), KOKKOS_LAMBDA(const UINT it) { + UINT basis_0 = (it & mask_low) + ((it & mask_high) << 1); + UINT basis_1 = basis_0 + mask; + Complex val0 = state[basis_0]; + Complex val1 = state[basis_1]; + Complex res0 = matrix[0] * val0 + matrix[1] * val1; + Complex res1 = matrix[2] * val0 + matrix[3] * val1; + state[basis_0] = res0; + state[basis_1] = res1; + }); +} +} \ No newline at end of file diff --git a/qulacs/gate/update_ops_quantum_matrix.cpp b/qulacs/gate/update_ops_quantum_matrix.cpp index d0544eb0..618d8590 100644 --- a/qulacs/gate/update_ops_quantum_matrix.cpp +++ b/qulacs/gate/update_ops_quantum_matrix.cpp @@ -20,7 +20,7 @@ std::array get_IBMQ_matrix(double theta, double phi, double lambda) return matrix; } -void u1_gate(UINT target_qubit_index, std::array matrix, StateVector& state) { - +void u_gate(UINT target_qubit_index, std::array matrix, StateVector& state) { + single_qubit_dense_matrix_gate(target_qubit_index, matrix, state); } } // namespace qulacs From da75de0f415f834657b371d37db2f24f0aae0956 Mon Sep 17 00:00:00 2001 From: Glacialte Date: Tue, 21 Nov 2023 12:04:05 +0900 Subject: [PATCH 3/6] fix CMakeLists.txt, and some --- qulacs/CMakeLists.txt | 5 +++ qulacs/gate/gate_one_control_one_target.cpp | 2 +- .../gate/update_ops_matrix_dense_single.cpp | 35 +++++++++++-------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/qulacs/CMakeLists.txt b/qulacs/CMakeLists.txt index 7b739581..2efc5bb4 100644 --- a/qulacs/CMakeLists.txt +++ b/qulacs/CMakeLists.txt @@ -3,8 +3,13 @@ cmake_minimum_required(VERSION 3.11) add_library(qulacs) target_sources(qulacs PRIVATE + gate/gate_one_control_one_target.cpp gate/gate_one_qubit.cpp + gate/gate_quantum_matrix.cpp + gate/update_ops_matrix_dense_single.cpp gate/update_ops_one_qubit.cpp + gate/update_ops_one_target_one_control.cpp + gate/update_ops_quantum_matrix.cpp state/state_vector.cpp util/random.cpp ) diff --git a/qulacs/gate/gate_one_control_one_target.cpp b/qulacs/gate/gate_one_control_one_target.cpp index 4142c23a..368c5eca 100644 --- a/qulacs/gate/gate_one_control_one_target.cpp +++ b/qulacs/gate/gate_one_control_one_target.cpp @@ -1,6 +1,6 @@ #include "gate_one_control_one_target.hpp" -#include "update_ops_one_target_one_control.hpp" +#include "update_ops.hpp" namespace qulacs { void CNOT::update_quantum_state(StateVector& state_vector) const { diff --git a/qulacs/gate/update_ops_matrix_dense_single.cpp b/qulacs/gate/update_ops_matrix_dense_single.cpp index 4ebf832c..9f42c78b 100644 --- a/qulacs/gate/update_ops_matrix_dense_single.cpp +++ b/qulacs/gate/update_ops_matrix_dense_single.cpp @@ -1,22 +1,27 @@ -#include "update_ops.hpp" #include #include + #include "../types.hpp" +#include "update_ops.hpp" namespace qulacs { -void single_qubit_dense_matrix_gate(UINT target_qubit_index, std::array matrix, StateVector& state) { +void single_qubit_dense_matrix_gate(UINT target_qubit_index, + std::array matrix, + StateVector& state) { const UINT mask = 1ULL << target_qubit_index; - const mask_low = mask - 1; - const mask_high = ~mask_low; - Kokkos::parallel_for(state.size(), KOKKOS_LAMBDA(const UINT it) { - UINT basis_0 = (it & mask_low) + ((it & mask_high) << 1); - UINT basis_1 = basis_0 + mask; - Complex val0 = state[basis_0]; - Complex val1 = state[basis_1]; - Complex res0 = matrix[0] * val0 + matrix[1] * val1; - Complex res1 = matrix[2] * val0 + matrix[3] * val1; - state[basis_0] = res0; - state[basis_1] = res1; - }); + const UINT mask_low = mask - 1; + const UINT mask_high = ~mask_low; + auto amplitudes = state.amplitudes_raw(); + Kokkos::parallel_for( + state.dim() - 1, KOKKOS_LAMBDA(const UINT it) { + UINT basis_0 = (it & mask_low) + ((it & mask_high) << 1); + UINT basis_1 = basis_0 + mask; + Complex val0 = state[basis_0]; + Complex val1 = state[basis_1]; + Complex res0 = matrix[0] * val0 + matrix[1] * val1; + Complex res1 = matrix[2] * val0 + matrix[3] * val1; + amplitudes[basis_0] = res0; + amplitudes[basis_1] = res1; + }); } -} \ No newline at end of file +} // namespace qulacs From fa22176125d71a7a1bf0aaddd9a14a204880a9f9 Mon Sep 17 00:00:00 2001 From: Glacialte Date: Tue, 5 Dec 2023 11:03:50 +0900 Subject: [PATCH 4/6] add ugate test, remove ppa:tool-chain/test --- .devcontainer/cpu/Dockerfile | 1 - .devcontainer/gpu/Dockerfile | 1 - qulacs/gate/gate_quantum_matrix.hpp | 4 +- .../gate/update_ops_matrix_dense_single.cpp | 4 +- tests/gate/gate_test.cpp | 45 ++++++++++++++++++- tests/gate/util.hpp | 9 ++++ 6 files changed, 57 insertions(+), 7 deletions(-) diff --git a/.devcontainer/cpu/Dockerfile b/.devcontainer/cpu/Dockerfile index c3a93a09..c9152abd 100644 --- a/.devcontainer/cpu/Dockerfile +++ b/.devcontainer/cpu/Dockerfile @@ -15,7 +15,6 @@ ENV PYTHONPATH="${PROJECT_DIR}/build:${PYTHONPATH}" RUN apt-get update && \ apt-get install -y software-properties-common && \ - add-apt-repository ppa:ubuntu-toolchain-r/test && \ apt-get update && \ apt-get install -y gcc-10 g++-10 && \ update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 && \ diff --git a/.devcontainer/gpu/Dockerfile b/.devcontainer/gpu/Dockerfile index 21af6f2f..e6cfeb09 100644 --- a/.devcontainer/gpu/Dockerfile +++ b/.devcontainer/gpu/Dockerfile @@ -10,7 +10,6 @@ ENV PYTHONPATH="${PROJECT_DIR}/build:${PYTHONPATH}" RUN apt-get update && \ apt-get install -y software-properties-common && \ - add-apt-repository ppa:ubuntu-toolchain-r/test && \ apt-get update && \ apt-get install -y gcc-10 g++-10 && \ update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 && \ diff --git a/qulacs/gate/gate_quantum_matrix.hpp b/qulacs/gate/gate_quantum_matrix.hpp index 910dc8a9..973f280b 100644 --- a/qulacs/gate/gate_quantum_matrix.hpp +++ b/qulacs/gate/gate_quantum_matrix.hpp @@ -24,7 +24,7 @@ class U2 : public QuantumGate { std::array _matrix; public: - U2(UINT target, UINT lambda, UINT phi) : _target(target), _lambda(lambda), _phi(phi) { + U2(UINT target, UINT lambda, UINT phi) : _target(target), _phi(phi), _lambda(lambda) { _matrix = get_IBMQ_matrix(PI / 2.0, phi, lambda); }; void update_quantum_state(StateVector& state_vector) const override; @@ -36,7 +36,7 @@ class U3 : public QuantumGate { std::array _matrix; public: - U3(UINT target, UINT theta, UINT lambda, UINT phi) : _target(target), _theta(theta), _lambda(lambda), _phi(phi) { + U3(UINT target, UINT theta, UINT lambda, UINT phi) : _target(target), _theta(theta), _phi(phi), _lambda(lambda) { _matrix = get_IBMQ_matrix(theta, phi, lambda); }; void update_quantum_state(StateVector& state_vector) const override; diff --git a/qulacs/gate/update_ops_matrix_dense_single.cpp b/qulacs/gate/update_ops_matrix_dense_single.cpp index 9f42c78b..84038896 100644 --- a/qulacs/gate/update_ops_matrix_dense_single.cpp +++ b/qulacs/gate/update_ops_matrix_dense_single.cpp @@ -16,8 +16,8 @@ void single_qubit_dense_matrix_gate(UINT target_qubit_index, state.dim() - 1, KOKKOS_LAMBDA(const UINT it) { UINT basis_0 = (it & mask_low) + ((it & mask_high) << 1); UINT basis_1 = basis_0 + mask; - Complex val0 = state[basis_0]; - Complex val1 = state[basis_1]; + Complex val0 = amplitudes[basis_0]; + Complex val1 = amplitudes[basis_1]; Complex res0 = matrix[0] * val0 + matrix[1] * val1; Complex res1 = matrix[2] * val0 + matrix[3] * val1; amplitudes[basis_0] = res0; diff --git a/tests/gate/gate_test.cpp b/tests/gate/gate_test.cpp index 747f39ff..4f14c293 100644 --- a/tests/gate/gate_test.cpp +++ b/tests/gate/gate_test.cpp @@ -65,6 +65,47 @@ void run_random_gate_apply(UINT n_qubits, std::function +void run_random_gate_apply(UINT n_qubits, std::function matrix_factory) { + const int dim = 1ULL << n_qubits; + Random random; + + Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim); + for (int repeat = 0; repeat < 10; repeat++) { + auto state = StateVector::Haar_random_state(n_qubits); + for (int i = 0; i < dim; i++) { + test_state[i] = state[i]; + } + + const double theta = M_PI * random.uniform(); + const double phi = M_PI * random.uniform(); + const double lambda = M_PI * random.uniform(); + const QuantumGateConstructor gate; + if(typeid(QuantumGateConstructor) == typeid(U1)){ + theta = 0; + phi = 0; + gate = QuantumGateConstructor(lambda); + } else if(typeid(QuantumGateConstructor) == typeid(U2)){ + theta = M_PI / 2; + gate = QuantumGateConstructor(phi, lambda); + } else if(typeid(QuantumGateConstructor) == typeid(U3)){ + gate = QuantumGateConstructor(theta, phi, lambda); + } else { + throw std::runtime_error("Invalid gate type"); + } + + const auto matrix = matrix_factory(theta, phi, lambda); + const UINT target = random.int64() % n_qubits; + gate.update_quantum_state(state); + + test_state = get_expanded_eigen_matrix_with_identity(target, matrix, n_qubits) * test_state; + + for (int i = 0; i < dim; i++) { + ASSERT_NEAR(std::abs(state[i] - test_state[i]), 0, eps); + } + } +} + TEST(GateTest, ApplyI) { run_random_gate_apply(5, make_I); } TEST(GateTest, ApplyX) { run_random_gate_apply(5, make_X); } TEST(GateTest, ApplyY) { run_random_gate_apply(5, make_Y); } @@ -83,5 +124,7 @@ TEST(GateTest, ApplyP1) { run_random_gate_apply(5, make_P1); } TEST(GateTest, ApplyRX) { run_random_gate_apply(5, make_RX); } TEST(GateTest, ApplyRY) { run_random_gate_apply(5, make_RY); } TEST(GateTest, ApplyRZ) { run_random_gate_apply(5, make_RZ); } - +TEST(GateTest, ApplyU1) { run_random_gate_apply(5, make_U); } +TEST(GateTest, ApplyU2) { run_random_gate_apply(5, make_U); } +TEST(GateTest, ApplyU3) { run_random_gate_apply(5, make_U); } } // namespace qulacs diff --git a/tests/gate/util.hpp b/tests/gate/util.hpp index 60331025..5920edf2 100644 --- a/tests/gate/util.hpp +++ b/tests/gate/util.hpp @@ -136,4 +136,13 @@ static Eigen::MatrixXcd make_RZ(double angle) { return make_2x2_matrix(std::exp(-1i * (angle / 2)), 0, 0, std::exp(1i * (angle / 2))); } +static Eigen::MatrixXcd make_U(double theta, double phi, double lambda) { + double expval1 = std::exp(1i * phi); + double expval2 = std::exp(1i * lambda); + double cosval = std::cos(theta / 2.); + double sinval = std::sin(theta / 2.); + return make_2x2_matrix(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.)); +} + } // namespace qulacs From f8277e5d8bf6bda2c64c736465815b6d22b535c4 Mon Sep 17 00:00:00 2001 From: Glacialte Date: Tue, 5 Dec 2023 11:14:51 +0900 Subject: [PATCH 5/6] fix order of ugate's param --- qulacs/gate/gate_quantum_matrix.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/qulacs/gate/gate_quantum_matrix.hpp b/qulacs/gate/gate_quantum_matrix.hpp index 973f280b..2c6d082d 100644 --- a/qulacs/gate/gate_quantum_matrix.hpp +++ b/qulacs/gate/gate_quantum_matrix.hpp @@ -2,9 +2,9 @@ #include +#include "constant.hpp" #include "gate.hpp" #include "update_ops.hpp" -#include "constant.hpp" namespace qulacs { class U1 : public QuantumGate { @@ -24,7 +24,7 @@ class U2 : public QuantumGate { std::array _matrix; public: - U2(UINT target, UINT lambda, UINT phi) : _target(target), _phi(phi), _lambda(lambda) { + U2(UINT target, UINT phi, UINT lambda) : _target(target), _phi(phi), _lambda(lambda) { _matrix = get_IBMQ_matrix(PI / 2.0, phi, lambda); }; void update_quantum_state(StateVector& state_vector) const override; @@ -36,7 +36,8 @@ class U3 : public QuantumGate { std::array _matrix; public: - U3(UINT target, UINT theta, UINT lambda, UINT phi) : _target(target), _theta(theta), _phi(phi), _lambda(lambda) { + U3(UINT target, UINT theta, UINT phi, UINT lambda) + : _target(target), _theta(theta), _phi(phi), _lambda(lambda) { _matrix = get_IBMQ_matrix(theta, phi, lambda); }; void update_quantum_state(StateVector& state_vector) const override; From be9e17ed0ef86ec0ec29f7c8323a1f44ecbea3f1 Mon Sep 17 00:00:00 2001 From: Glacialte Date: Tue, 5 Dec 2023 11:18:10 +0900 Subject: [PATCH 6/6] fix tests/gate/util.hpp --- tests/gate/util.hpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/gate/util.hpp b/tests/gate/util.hpp index 5920edf2..36330c7b 100644 --- a/tests/gate/util.hpp +++ b/tests/gate/util.hpp @@ -137,12 +137,10 @@ static Eigen::MatrixXcd make_RZ(double angle) { } static Eigen::MatrixXcd make_U(double theta, double phi, double lambda) { - double expval1 = std::exp(1i * phi); - double expval2 = std::exp(1i * lambda); - double cosval = std::cos(theta / 2.); - double sinval = std::sin(theta / 2.); - return make_2x2_matrix(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.)); + return make_2x2_matrix(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.)); } } // namespace qulacs