Skip to content

Commit

Permalink
Merge branch 'main' into 142-gate-ostream
Browse files Browse the repository at this point in the history
  • Loading branch information
gandalfr-KY committed Sep 9, 2024
2 parents 7c4bcef + b8baf55 commit 1c2153a
Show file tree
Hide file tree
Showing 38 changed files with 683 additions and 649 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
61 changes: 14 additions & 47 deletions python/binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,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<bool> &, const std::vector<bool> &, Complex>(),
.def(nb::init<std::uint64_t, std::uint64_t, Complex>(),
"bit_flip_mask"_a,
"phase_flip_mask"_a,
"coef"_a = 1.,
Expand Down Expand Up @@ -809,35 +809,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((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(nb::init<std::uint64_t, std::uint64_t, Complex>(),
"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,
Expand All @@ -846,23 +825,11 @@ NB_MODULE(scaluq_core, m) {
&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_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 "
Expand Down
2 changes: 1 addition & 1 deletion scaluq/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ target_sources(scaluq PRIVATE
circuit/circuit.cpp
gate/update_ops_dense_matrix.cpp
gate/update_ops_standard.cpp
gate/update_ops_pauli.cpp
# gate/merge_gate.cpp
operator/apply_pauli.cpp
operator/pauli_operator.cpp
operator/operator.cpp
state/state_vector.cpp
Expand Down
1 change: 1 addition & 0 deletions scaluq/all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "gate/param_gate.hpp"
#include "gate/param_gate_factory.hpp"
#include "gate/update_ops.hpp"
#include "operator/apply_pauli.hpp"
#include "operator/operator.hpp"
#include "operator/pauli_operator.hpp"
#include "state/state_vector.hpp"
Expand Down
56 changes: 27 additions & 29 deletions scaluq/constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
#include "types.hpp"

namespace scaluq {
//! PI value
KOKKOS_INLINE_FUNCTION
double PI() { return 3.141592653589793; }

//! square root of 2
KOKKOS_INLINE_FUNCTION
double SQRT2() { return 1.4142135623730950; }
namespace internal {

#define DEF_MATH_CONSTANT(TRAIT, VALUE) \
template <class T> \
inline constexpr auto TRAIT##_v = std::enable_if_t<std::is_floating_point_v<T>, T>(VALUE); \
inline constexpr auto TRAIT = TRAIT##_v<double>

//! inverse square root of 2
KOKKOS_INLINE_FUNCTION
double INVERSE_SQRT2() { return 0.707106781186547; }
double INVERSE_SQRT2() { return Kokkos::numbers::sqrt2 / 2; }

//! cosine pi/8
KOKKOS_INLINE_FUNCTION
Expand All @@ -28,71 +28,69 @@ double SINPI8() { return 0.382683432365090; }

//! identity matrix
KOKKOS_INLINE_FUNCTION
matrix_2_2 I_GATE() { return {1, 0, 0, 1}; }
Matrix2x2 I_GATE() { return {1, 0, 0, 1}; }
//! Pauli matrix X
KOKKOS_INLINE_FUNCTION
matrix_2_2 X_GATE() { return {0, 1, 1, 0}; }
Matrix2x2 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}; }
Matrix2x2 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}; }
Matrix2x2 Z_GATE() { return {1, 0, 0, -1}; }

//! list of Pauli matrix I,X,Y,Z
// std::array<matrix_2_2, 4> PAULI_MATRIX = {I_GATE, X_GATE, Y_GATE, Z_GATE};
// std::array<Matrix2x2, 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)}; }
Matrix2x2 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)}; }
Matrix2x2 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()};
}
Matrix2x2 T_GATE_MATRIX() { return {1, 0, 0, Complex(INVERSE_SQRT2(), INVERSE_SQRT2())}; }
//! Tdag-gate
KOKKOS_INLINE_FUNCTION
matrix_2_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
matrix_2_2 HADAMARD_MATRIX() {
Matrix2x2 HADAMARD_MATRIX() {
return {INVERSE_SQRT2(), INVERSE_SQRT2(), INVERSE_SQRT2(), -INVERSE_SQRT2()};
}
//! square root of X gate
KOKKOS_INLINE_FUNCTION
matrix_2_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
matrix_2_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
matrix_2_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
matrix_2_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
matrix_2_2 PROJ_0_MATRIX() { return {1, 0, 0, 0}; }
Matrix2x2 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}; }
Matrix2x2 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<Complex, 4> 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<Complex, 4> PHASE_M90ROT() { return {1., Complex(0, -1), -1, Complex(0, 1)}; }
} // namespace internal
} // namespace scaluq
2 changes: 1 addition & 1 deletion scaluq/gate/gate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class GateBase : public std::enable_shared_from_this<GateBase> {
}

[[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;

Expand Down
11 changes: 5 additions & 6 deletions scaluq/gate/gate_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,17 +163,15 @@ inline Gate PauliRotation(const PauliOperator& pauli,
internal::vector_to_mask(controls), pauli, angle);
}
inline Gate DenseMatrix(const std::vector<std::uint64_t>& targets,
const ComplexMatrix& matrix,
const internal::ComplexMatrix& matrix,
const std::vector<std::uint64_t>& controls = {}) {
std::uint64_t nqubits = targets.size();
std::uint64_t dim = 1ULL << nqubits;
if (static_cast<std::uint64_t>(matrix.rows()) != dim ||
static_cast<std::uint64_t>(matrix.cols()) != dim) {
throw std::runtime_error(
"gate::DenseMatrix(const std::vector<std::uint64_t>&, const ComplexMatrix&): matrix "
"size "
"must "
"be 2^{n_qubits} x 2^{n_qubits}.");
"gate::DenseMatrix(const std::vector<std::uint64_t>&, const internal::ComplexMatrix&): "
"matrix size must be 2^{n_qubits} x 2^{n_qubits}.");
}
if (targets.size() == 0) return I();
if (targets.size() == 1) {
Expand Down Expand Up @@ -204,7 +202,8 @@ inline Gate DenseMatrix(const std::vector<std::uint64_t>& targets,
controls);
}
throw std::runtime_error(
"gate::DenseMatrix(const std::vector<std::uint64_t>&, const ComplexMatrix&): DenseMatrix "
"gate::DenseMatrix(const std::vector<std::uint64_t>&, const internal::ComplexMatrix&): "
"DenseMatrix "
"gate "
"more "
"than two qubits is not implemented yet.");
Expand Down
49 changes: 23 additions & 26 deletions scaluq/gate/gate_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,36 +11,35 @@
namespace scaluq {
namespace internal {
class OneTargetMatrixGateImpl : public GateBase {
matrix_2_2 _matrix;
Matrix2x2 _matrix;

public:
OneTargetMatrixGateImpl(std::uint64_t target_mask,
std::uint64_t control_mask,
const std::array<std::array<Complex, 2>, 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<std::array<Complex, 2>, 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<const OneTargetMatrixGateImpl>(
_target_mask,
_control_mask,
std::array<std::array<Complex, 2>, 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<std::array<Complex, 2>, 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];
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;
}

Expand All @@ -58,7 +57,7 @@ class OneTargetMatrixGateImpl : public GateBase {
};

class TwoTargetMatrixGateImpl : public GateBase {
matrix_4_4 _matrix;
Matrix4x4 _matrix;

public:
TwoTargetMatrixGateImpl(std::uint64_t target_mask,
Expand All @@ -67,7 +66,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];
}
}
}
Expand All @@ -76,7 +75,7 @@ class TwoTargetMatrixGateImpl : public GateBase {
std::array<std::array<Complex, 4>, 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;
Expand All @@ -86,20 +85,18 @@ class TwoTargetMatrixGateImpl : public GateBase {
std::array<std::array<Complex, 4>, 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<const TwoTargetMatrixGateImpl>(
_target_mask, _control_mask, matrix_dag);
}
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];
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],
this->_matrix[3][0], this->_matrix[3][1], this->_matrix[3][2], this->_matrix[3][3];
return mat;
}

Expand Down
Loading

0 comments on commit 1c2153a

Please sign in to comment.