Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into 29-add-swap
Browse files Browse the repository at this point in the history
  • Loading branch information
Glacialte committed Jan 9, 2024
2 parents 9fe6398 + 29231bd commit 00a9476
Show file tree
Hide file tree
Showing 19 changed files with 601 additions and 133 deletions.
8 changes: 3 additions & 5 deletions .github/workflows/ci_ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ jobs:
verbose: 2

- name: Install qulacs for Ubuntu
run: ./script/build_gcc.sh
run: CMAKE_BUILD_TYPE=Debug ./script/build_gcc.sh

- name: Test in Ubuntu
run: |
Expand Down Expand Up @@ -106,7 +106,5 @@ jobs:
- name: Install qulacs for Ubuntu
run: ./script/build_gcc.sh

- name: Test in Ubuntu
run: |
ninja test -C build -j $(nproc)

# GitHub Actions cannot run CUDA program
59 changes: 26 additions & 33 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,6 @@ endif(NOT DEFINED QULACS_USE_EXE)
message(STATUS "QULACS_USE_PYTHON = ${QULACS_USE_PYTHON}")
message(STATUS "QULACS_USE_TEST = ${QULACS_USE_TEST}")

### Compile Warnings ###
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
set(WARNING_CPP "-Wall -Wdate-time -Wendif-labels -Werror=format=2 \
-Werror=missing-declarations -Werror=return-type -Wextra \
-Wfloat-equal -Wimplicit-fallthrough=5 -Wlogical-op \
-Wmissing-include-dirs -Wpointer-arith -Wredundant-decls \
-Wshadow -Wstrict-aliasing=2 -Wsuggest-attribute=noreturn -Wwrite-strings \
-fdiagnostics-color=auto -fstrict-aliasing")
# -Werror=undef is eliminated due to conflict with boost
elseif ((${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang"))
set(WARNING_CPP "-Wall -Wdate-time -Wendif-labels -Werror=format=2 \
-Werror=missing-declarations -Werror=return-type -Wextra \
-Wfloat-equal -Wimplicit-fallthrough \
-Wmissing-include-dirs -Wpointer-arith -Wredundant-decls \
-Wshadow -Wstrict-aliasing=2 -Wwrite-strings \
-fdiagnostics-color=auto -fstrict-aliasing")
endif()

### Compiler options ###
if ((${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang"))
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# Enable pthread
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")

# Enable openmp
if(QULACS_USE_OMP)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
add_compile_definitions(OPENMP)
endif()
endif()

### Kokkos options ###
set(Kokkos_ENABLE_SERIAL ON CACHE BOOL "Enable Kokkos Serial backend")
if(QULACS_USE_OMP)
Expand Down Expand Up @@ -133,6 +100,32 @@ else()
message(STATUS "Skip downloding googletest")
endif(QULACS_USE_TEST)

add_library(qulacs)

### Compiler options ###
if ((${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang"))
# Standard
target_compile_features(qulacs PUBLIC cxx_std_20)

# Warning
target_compile_options(qulacs PUBLIC
-Wall -Wextra -Wunused-parameter -Wshadow -pedantic
-Wsign-compare -Wtype-limits -Wuninitialized)

# Enable pthread
target_compile_options(qulacs PUBLIC -pthread)

# Enable openmp
if(QULACS_USE_OMP)
target_compile_options(qulacs PUBLIC -fopenmp)
target_compile_definitions(qulacs PUBLIC OPENMP)
endif()

# Debug options
target_compile_options(qulacs PUBLIC $<$<CONFIG:Debug>:-O0 -g -fsanitize=address,undefined>)
target_link_options(qulacs PUBLIC $<$<CONFIG:Debug>:-fsanitize=address,undefined>)
endif()

### Add subdirectories ###
add_subdirectory(qulacs)
if(QULACS_USE_PYTHON)
Expand Down
2 changes: 1 addition & 1 deletion exe/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ using namespace qulacs;

void run() {
auto state = StateVector::Haar_random_state(3);
for (int i = 0; i < state.dim(); i++) {
for (UINT i = 0; i < state.dim(); i++) {
std::cout << state[i] << std::endl;
}
}
Expand Down
2 changes: 0 additions & 2 deletions qulacs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
cmake_minimum_required(VERSION 3.21)

add_library(qulacs)

target_sources(qulacs PRIVATE
gate/gate_npair_qubit.cpp
gate/gate_one_control_one_target.cpp
Expand Down
60 changes: 35 additions & 25 deletions qulacs/gate/constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,67 @@

namespace qulacs {
//! PI value
constexpr double PI = std::numbers::pi;
KOKKOS_INLINE_FUNCTION
double PI() { return 3.141592653589793; }

//! square root of 2
constexpr double SQRT2 = std::numbers::sqrt2;
KOKKOS_INLINE_FUNCTION
double SQRT2() { return 1.4142135623730950; }

//! inverse square root of 2
constexpr double INVERSE_SQRT2 = 0.707106781186547;
KOKKOS_INLINE_FUNCTION
double INVERSE_SQRT2() { return 0.707106781186547; }

//! cosine pi/8
constexpr double COSPI8 = 0.923879532511287;
KOKKOS_INLINE_FUNCTION
double COSPI8() { return 0.923879532511287; }

//! sine pi/8
constexpr double SINPI8 = 0.382683432365090;
KOKKOS_INLINE_FUNCTION
double SINPI8() { return 0.382683432365090; }

//! identity matrix
std::array<Complex, 4> I_GATE = {1, 0, 0, 1};
matrix_2_2 I_GATE = {1, 0, 0, 1};
//! Pauli matrix X
std::array<Complex, 4> X_GATE = {0, 1, 1, 0};
matrix_2_2 X_GATE = {0, 1, 1, 0};
//! Pauli matrix Y
std::array<Complex, 4> Y_GATE = {0, Complex(0, -1), Complex(0, 1), 0};
matrix_2_2 Y_GATE = {0, Complex(0, -1), Complex(0, 1), 0};
//! Pauli matrix Z
std::array<Complex, 4> Z_GATE = {1, 0, 0, -1};
matrix_2_2 Z_GATE = {1, 0, 0, -1};

//! list of Pauli matrix I,X,Y,Z
std::array<std::array<Complex, 4>, 4> PAULI_MATRIX = {I_GATE, X_GATE, Y_GATE, Z_GATE};
// std::array<matrix_2_2, 4> PAULI_MATRIX = {I_GATE, X_GATE, Y_GATE, Z_GATE};

//! S-gate
std::array<Complex, 4> S_GATE_MATRIX = {1, 0, 0, Complex(0, 1)};
matrix_2_2 S_GATE_MATRIX = {1, 0, 0, Complex(0, 1)};
//! Sdag-gate
std::array<Complex, 4> S_DAG_GATE_MATRIX = {1, 0, 0, Complex(0, -1)};
matrix_2_2 S_DAG_GATE_MATRIX = {1, 0, 0, Complex(0, -1)};
//! T-gate
std::array<Complex, 4> T_GATE_MATRIX = {
COSPI8 - Complex(0, 1) * SINPI8, 0., 0., COSPI8 + Complex(0, 1) * SINPI8};
matrix_2_2 T_GATE_MATRIX = {
COSPI8() - Complex(0, SINPI8()), 0., 0., COSPI8() + Complex(0, SINPI8()) * SINPI8()};
//! Tdag-gate
std::array<Complex, 4> T_DAG_GATE_MATRIX = {
COSPI8 + Complex(0, 1) * SINPI8, 0., 0., COSPI8 - Complex(0, 1) * SINPI8};
matrix_2_2 T_DAG_GATE_MATRIX = {
COSPI8() + Complex(0, SINPI8()), 0., 0., COSPI8() - Complex(0, SINPI8())};
//! Hadamard gate
std::array<Complex, 4> HADAMARD_MATRIX = {1. / SQRT2, 1. / SQRT2, 1. / SQRT2, -1. / SQRT2};
matrix_2_2 HADAMARD_MATRIX = {INVERSE_SQRT2(), INVERSE_SQRT2(), INVERSE_SQRT2(), -INVERSE_SQRT2()};
//! square root of X gate
std::array<Complex, 4> SQRT_X_GATE_MATRIX = {
matrix_2_2 SQRT_X_GATE_MATRIX = {
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
std::array<Complex, 4> SQRT_Y_GATE_MATRIX = {0.5 + 0.5i, -0.5 - 0.5i, 0.5 + 0.5i, 0.5 + 0.5i};
matrix_2_2 SQRT_Y_GATE_MATRIX = {
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
std::array<Complex, 4> SQRT_X_DAG_GATE_MATRIX = {0.5 - 0.5i, 0.5 + 0.5i, 0.5 + 0.5i, 0.5 - 0.5i};
matrix_2_2 SQRT_X_DAG_GATE_MATRIX = {
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
std::array<Complex, 4> SQRT_Y_DAG_GATE_MATRIX = {0.5 - 0.5i, 0.5 - 0.5i, -0.5 + 0.5i, 0.5 - 0.5i};
matrix_2_2 SQRT_Y_DAG_GATE_MATRIX = {
Complex(0.5, -0.5), Complex(0.5, -0.5), Complex(-0.5, 0.5), Complex(0.5, -0.5)};
//! Projection to 0
std::array<Complex, 4> PROJ_0_MATRIX = {1, 0, 0, 0};
matrix_2_2 PROJ_0_MATRIX = {1, 0, 0, 0};
//! Projection to 1
std::array<Complex, 4> PROJ_1_MATRIX = {0, 0, 0, 1};
matrix_2_2 PROJ_1_MATRIX = {0, 0, 0, 1};
//! complex values for exp(j * i*pi/4 )
std::array<Complex, 4> PHASE_90ROT = {1., 1.i, -1, -1.i};
matrix_2_2 PHASE_90ROT = {1., Complex(0, 1), -1, Complex(0, -1)};
//! complex values for exp(-j * i*pi/4 )
std::array<Complex, 4> PHASE_M90ROT = {1., -1.i, -1, 1.i};
matrix_2_2 PHASE_M90ROT = {1., Complex(0, -1), -1, Complex(0, 1)};
} // namespace qulacs
4 changes: 1 addition & 3 deletions qulacs/gate/gate_quantum_matrix.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "gate_quantum_matrix.hpp"

#include "update_ops.hpp"

namespace qulacs {
void U1::update_quantum_state(StateVector& state_vector) const {
u_gate(this->_target, this->_matrix, state_vector);
Expand All @@ -14,4 +12,4 @@ void U2::update_quantum_state(StateVector& state_vector) const {
void U3::update_quantum_state(StateVector& state_vector) const {
u_gate(this->_target, this->_matrix, state_vector);
}
} // namespace qulacs
} // namespace qulacs
12 changes: 6 additions & 6 deletions qulacs/gate/gate_quantum_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace qulacs {
class U1 : public QuantumGate {
UINT _target;
double _lambda;
std::array<Complex, 4> _matrix;
matrix_2_2 _matrix;

public:
U1(UINT target, double lambda) : _target(target), _lambda(lambda) {
Expand All @@ -20,20 +20,20 @@ class U1 : public QuantumGate {
};
class U2 : public QuantumGate {
UINT _target;
double _lambda, _phi;
std::array<Complex, 4> _matrix;
double _phi, _lambda;
matrix_2_2 _matrix;

public:
U2(UINT target, double phi, double lambda) : _target(target), _phi(phi), _lambda(lambda) {
_matrix = get_IBMQ_matrix(PI / 2.0, phi, lambda);
_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<Complex, 4> _matrix;
double _theta, _phi, _lambda;
matrix_2_2 _matrix;

public:
U3(UINT target, double theta, double phi, double lambda)
Expand Down
6 changes: 3 additions & 3 deletions qulacs/gate/update_ops.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ void cnot_gate(UINT control_qubit_index, UINT target_qubit_index, StateVector& s

void cz_gate(UINT control_qubit_index, UINT target_qubit_index, StateVector& state);

std::array<Complex, 4> get_IBMQ_matrix(double _theta, double _phi, double _lambda);
matrix_2_2 get_IBMQ_matrix(double _theta, double _phi, double _lambda);

void single_qubit_dense_matrix_gate(UINT target_qubit_index,
std::array<Complex, 4> matrix,
const matrix_2_2& matrix,
StateVector& state);

void u_gate(UINT target_qubit_index, std::array<Complex, 4> matrix, StateVector& state);
void u_gate(UINT target_qubit_index, const matrix_2_2& matrix, StateVector& state);

void swap_gate(UINT target1, UINT target2, StateVector& state);

Expand Down
12 changes: 6 additions & 6 deletions qulacs/gate/update_ops_dense_matrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@

namespace qulacs {
void single_qubit_dense_matrix_gate(UINT target_qubit_index,
std::array<Complex, 4> matrix,
const matrix_2_2& matrix,
StateVector& state) {
const UINT mask = 1ULL << target_qubit_index;
const UINT mask_low = mask - 1;
const UINT mask_high = ~mask_low;
auto amplitudes = state.amplitudes_raw();
Kokkos::parallel_for(
state.dim() / 2, KOKKOS_LAMBDA(const UINT it) {
UINT basis_0 = (it & mask_low) + ((it & mask_high) << 1);
UINT basis_1 = basis_0 + mask;
state.dim() >> 1, KOKKOS_LAMBDA(const UINT it) {
UINT basis_0 = ((it & mask_high) << 1) | (it & mask_low);
UINT basis_1 = basis_0 | mask;
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;
Complex res0 = matrix.val[0][0] * val0 + matrix.val[0][1] * val1;
Complex res1 = matrix.val[1][0] * val0 + matrix.val[1][1] * val1;
amplitudes[basis_0] = res0;
amplitudes[basis_1] = res1;
});
Expand Down
10 changes: 4 additions & 6 deletions qulacs/gate/update_ops_one_control_one_target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ void cnot_gate(UINT control_qubit_index, UINT target_qubit_index, StateVector& s
auto amplitudes = state.amplitudes_raw();
Kokkos::parallel_for(
1ULL << (n_qubits - 2), KOKKOS_LAMBDA(const UINT& it) {
UINT i = (it & low_mask) + ((it & mid_mask) << 1) +
((it & high_mask) << 2) + control_mask;
UINT i =
(it & low_mask) | ((it & mid_mask) << 1) | ((it & high_mask) << 2) | control_mask;
UINT j = i | target_mask;
Kokkos::Experimental::swap(amplitudes[i], amplitudes[j]);
});
Expand All @@ -39,14 +39,12 @@ void cz_gate(UINT control_qubit_index, UINT target_qubit_index, StateVector& sta
const UINT low_mask = min_qubit_mask - 1;
const UINT mid_mask = (max_qubit_mask - 1) ^ low_mask;
const UINT high_mask = ~(max_qubit_mask - 1);
const UINT mask = control_mask + target_mask;

auto amplitudes = state.amplitudes_raw();
Kokkos::parallel_for(
1ULL << (n_qubits - 2), KOKKOS_LAMBDA(const UINT& it) {
UINT i = (it & low_mask) +
((it & mid_mask) << 1) +
((it & high_mask) << 2) + mask;
UINT i = (it & low_mask) | ((it & mid_mask) << 1) | ((it & high_mask) << 2) |
control_mask | target_mask;
amplitudes[i] *= -1;
});
}
Expand Down
Loading

0 comments on commit 00a9476

Please sign in to comment.