Skip to content

Commit

Permalink
complex -> complex<Fp>
Browse files Browse the repository at this point in the history
  • Loading branch information
gandalfr-KY committed Oct 18, 2024
1 parent 7050e72 commit 3953c6c
Show file tree
Hide file tree
Showing 25 changed files with 469 additions and 414 deletions.
117 changes: 74 additions & 43 deletions scaluq/constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ namespace scaluq {

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 Kokkos::numbers::sqrt2 / 2; }
Expand All @@ -27,70 +22,106 @@ KOKKOS_INLINE_FUNCTION
double SINPI8() { return 0.382683432365090; }

//! identity matrix
KOKKOS_INLINE_FUNCTION
Matrix2x2 I_GATE() { return {1, 0, 0, 1}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> I_GATE() {
return {1, 0, 0, 1};
}
//! Pauli matrix X
KOKKOS_INLINE_FUNCTION
Matrix2x2 X_GATE() { return {0, 1, 1, 0}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> X_GATE() {
return {0, 1, 1, 0};
}
//! Pauli matrix Y
KOKKOS_INLINE_FUNCTION
Matrix2x2 Y_GATE() { return {0, Complex(0, -1), Complex(0, 1), 0}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> Y_GATE() {
return {0, Complex<Fp>(0, -1), Complex<Fp>(0, 1), 0};
}
//! Pauli matrix Z
KOKKOS_INLINE_FUNCTION
Matrix2x2 Z_GATE() { return {1, 0, 0, -1}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> Z_GATE() {
return {1, 0, 0, -1};
}

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

//! S-gate
KOKKOS_INLINE_FUNCTION
Matrix2x2 S_GATE_MATRIX() { return {1, 0, 0, Complex(0, 1)}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> S_GATE_MATRIX() {
return {1, 0, 0, Complex<Fp>(0, 1)};
}
//! Sdag-gate
KOKKOS_INLINE_FUNCTION
Matrix2x2 S_DAG_GATE_MATRIX() { return {1, 0, 0, Complex(0, -1)}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> S_DAG_GATE_MATRIX() {
return {1, 0, 0, Complex<Fp>(0, -1)};
}
//! T-gate
KOKKOS_INLINE_FUNCTION
Matrix2x2 T_GATE_MATRIX() { return {1, 0, 0, Complex(INVERSE_SQRT2(), INVERSE_SQRT2())}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> T_GATE_MATRIX() {
return {1, 0, 0, Complex<Fp>(INVERSE_SQRT2(), INVERSE_SQRT2())};
}
//! Tdag-gate
KOKKOS_INLINE_FUNCTION
Matrix2x2 T_DAG_GATE_MATRIX() { return {1, 0, 0, Complex(INVERSE_SQRT2(), -INVERSE_SQRT2())}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> T_DAG_GATE_MATRIX() {
return {1, 0, 0, Complex<Fp>(INVERSE_SQRT2(), -INVERSE_SQRT2())};
}
//! Hadamard gate
KOKKOS_INLINE_FUNCTION
Matrix2x2 HADAMARD_MATRIX() {
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> HADAMARD_MATRIX() {
return {INVERSE_SQRT2(), INVERSE_SQRT2(), INVERSE_SQRT2(), -INVERSE_SQRT2()};
}
//! square root of X gate
KOKKOS_INLINE_FUNCTION
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)};
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> SQRT_X_GATE_MATRIX() {
return {Complex<Fp>(0.5, 0.5),
Complex<Fp>(0.5, -0.5),
Complex<Fp>(0.5, -0.5),
Complex<Fp>(0.5, 0.5)};
}
//! square root of Y gate
KOKKOS_INLINE_FUNCTION
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)};
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> SQRT_Y_GATE_MATRIX() {
return {Complex<Fp>(0.5, 0.5),
Complex<Fp>(-0.5, -0.5),
Complex<Fp>(0.5, 0.5),
Complex<Fp>(0.5, 0.5)};
}
//! square root dagger of X gate
KOKKOS_INLINE_FUNCTION
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)};
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> SQRT_X_DAG_GATE_MATRIX() {
return {Complex<Fp>(0.5, -0.5),
Complex<Fp>(0.5, 0.5),
Complex<Fp>(0.5, 0.5),
Complex<Fp>(0.5, -0.5)};
}
//! square root dagger of Y gate
KOKKOS_INLINE_FUNCTION
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)};
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> SQRT_Y_DAG_GATE_MATRIX() {
return {Complex<Fp>(0.5, -0.5),
Complex<Fp>(0.5, -0.5),
Complex<Fp>(-0.5, 0.5),
Complex<Fp>(0.5, -0.5)};
}
//! Projection to 0
KOKKOS_INLINE_FUNCTION
Matrix2x2 PROJ_0_MATRIX() { return {1, 0, 0, 0}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> PROJ_0_MATRIX() {
return {1, 0, 0, 0};
}
//! Projection to 1
KOKKOS_INLINE_FUNCTION
Matrix2x2 PROJ_1_MATRIX() { return {0, 0, 0, 1}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Matrix2x2<Fp> PROJ_1_MATRIX() {
return {0, 0, 0, 1};
}
//! complex values for exp(j * i*pi/4 )
KOKKOS_INLINE_FUNCTION
Kokkos::Array<Complex, 4> PHASE_90ROT() { return {1., Complex(0, 1), -1, Complex(0, -1)}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Kokkos::Array<Complex<Fp>, 4> PHASE_90ROT() {
return {1., Complex<Fp>(0, 1), -1, Complex<Fp>(0, -1)};
}
//! complex values for exp(-j * i*pi/4 )
KOKKOS_INLINE_FUNCTION
Kokkos::Array<Complex, 4> PHASE_M90ROT() { return {1., Complex(0, -1), -1, Complex(0, 1)}; }
template <std::floating_point Fp>
KOKKOS_INLINE_FUNCTION Kokkos::Array<Complex<Fp>, 4> PHASE_M90ROT() {
return {1., Complex<Fp>(0, -1), -1, Complex<Fp>(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 @@ -229,7 +229,7 @@ class GateBase : public std::enable_shared_from_this<GateBase<_FloatType>> {
}

[[nodiscard]] virtual std::shared_ptr<const GateBase<Fp>> get_inverse() const = 0;
[[nodiscard]] virtual internal::ComplexMatrix get_matrix() const = 0;
[[nodiscard]] virtual internal::ComplexMatrix<Fp> get_matrix() const = 0;

virtual void update_quantum_state(StateVector<Fp>& state_vector) const = 0;

Expand Down
48 changes: 25 additions & 23 deletions scaluq/gate/gate_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ inline Gate<Fp> U3(std::uint64_t target,
}
template <std::floating_point Fp>
inline Gate<Fp> OneTargetMatrix(std::uint64_t target,
const std::array<std::array<Complex, 2>, 2>& matrix,
const std::array<std::array<Complex<Fp>, 2>, 2>& matrix,
const std::vector<std::uint64_t>& controls = {}) {
return internal::GateFactory::create_gate<internal::OneTargetMatrixGateImpl<Fp>>(
internal::vector_to_mask({target}), internal::vector_to_mask(controls), matrix);
Expand Down Expand Up @@ -179,7 +179,7 @@ inline Gate<Fp> Swap(std::uint64_t target1,
template <std::floating_point Fp>
inline Gate<Fp> TwoTargetMatrix(std::uint64_t target1,
std::uint64_t target2,
const std::array<std::array<Complex, 4>, 4>& matrix,
const std::array<std::array<Complex<Fp>, 4>, 4>& matrix,
const std::vector<std::uint64_t>& controls = {}) {
return internal::GateFactory::create_gate<internal::TwoTargetMatrixGateImpl<Fp>>(
internal::vector_to_mask({target1, target2}), internal::vector_to_mask(controls), matrix);
Expand All @@ -200,47 +200,49 @@ inline Gate<Fp> PauliRotation(const PauliOperator<Fp>& pauli,
}
template <std::floating_point Fp>
inline Gate<Fp> DenseMatrix(const std::vector<std::uint64_t>& targets,
const internal::ComplexMatrix& matrix,
const internal::ComplexMatrix<Fp>& 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 internal::ComplexMatrix&): "
"gate::DenseMatrix(const std::vector<std::uint64_t>&, const "
"internal::ComplexMatrix<Fp>&): "
"matrix size must be 2^{n_qubits} x 2^{n_qubits}.");
}
if (targets.size() == 0) return I<Fp>();
if (targets.size() == 1) {
return OneTargetMatrix<Fp>(
targets[0],
std::array{std::array{Complex(matrix(0, 0)), Complex(matrix(0, 1))},
std::array{Complex(matrix(1, 0)), Complex(matrix(1, 1))}},
std::array{std::array{Complex<Fp>(matrix(0, 0)), Complex<Fp>(matrix(0, 1))},
std::array{Complex<Fp>(matrix(1, 0)), Complex<Fp>(matrix(1, 1))}},
controls);
}
if (targets.size() == 2) {
return TwoTargetMatrix<Fp>(targets[0],
targets[1],
std::array{std::array{Complex(matrix(0, 0)),
Complex(matrix(0, 1)),
Complex(matrix(0, 2)),
Complex(matrix(0, 3))},
std::array{Complex(matrix(1, 0)),
Complex(matrix(1, 1)),
Complex(matrix(1, 2)),
Complex(matrix(1, 3))},
std::array{Complex(matrix(2, 0)),
Complex(matrix(2, 1)),
Complex(matrix(2, 2)),
Complex(matrix(2, 3))},
std::array{Complex(matrix(3, 0)),
Complex(matrix(3, 1)),
Complex(matrix(3, 2)),
Complex(matrix(3, 3))}},
std::array{std::array{Complex<Fp>(matrix(0, 0)),
Complex<Fp>(matrix(0, 1)),
Complex<Fp>(matrix(0, 2)),
Complex<Fp>(matrix(0, 3))},
std::array{Complex<Fp>(matrix(1, 0)),
Complex<Fp>(matrix(1, 1)),
Complex<Fp>(matrix(1, 2)),
Complex<Fp>(matrix(1, 3))},
std::array{Complex<Fp>(matrix(2, 0)),
Complex<Fp>(matrix(2, 1)),
Complex<Fp>(matrix(2, 2)),
Complex<Fp>(matrix(2, 3))},
std::array{Complex<Fp>(matrix(3, 0)),
Complex<Fp>(matrix(3, 1)),
Complex<Fp>(matrix(3, 2)),
Complex<Fp>(matrix(3, 3))}},
controls);
}
throw std::runtime_error(
"gate::DenseMatrix(const std::vector<std::uint64_t>&, const internal::ComplexMatrix&): "
"gate::DenseMatrix(const std::vector<std::uint64_t>&, const "
"internal::ComplexMatrix<Fp>&): "
"DenseMatrix "
"gate "
"more "
Expand Down
32 changes: 16 additions & 16 deletions scaluq/gate/gate_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,34 @@ namespace internal {

template <std::floating_point Fp>
class OneTargetMatrixGateImpl : public GateBase<Fp> {
Matrix2x2 _matrix;
Matrix2x2<Fp> _matrix;

public:
OneTargetMatrixGateImpl(std::uint64_t target_mask,
std::uint64_t control_mask,
const std::array<std::array<Complex, 2>, 2>& matrix)
const std::array<std::array<Complex<Fp>, 2>, 2>& matrix)
: GateBase<Fp>(target_mask, control_mask) {
_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 {
std::array<std::array<Complex<Fp>, 2>, 2> matrix() const {
return {_matrix[0][0], _matrix[0][1], _matrix[1][0], _matrix[1][1]};
}

std::shared_ptr<const GateBase<Fp>> get_inverse() const override {
return std::make_shared<const OneTargetMatrixGateImpl>(
this->_target_mask,
this->_control_mask,
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])});
std::array<std::array<Complex<Fp>, 2>, 2>{Kokkos::conj(_matrix[0][0]),
Kokkos::conj(_matrix[1][0]),
Kokkos::conj(_matrix[0][1]),
Kokkos::conj(_matrix[1][1])});
}
internal::ComplexMatrix get_matrix() const override {
internal::ComplexMatrix mat(2, 2);
internal::ComplexMatrix<Fp> get_matrix() const override {
internal::ComplexMatrix<Fp> mat(2, 2);
mat << this->_matrix[0][0], this->_matrix[0][1], this->_matrix[1][0], this->_matrix[1][1];
return mat;
}
Expand All @@ -61,12 +61,12 @@ class OneTargetMatrixGateImpl : public GateBase<Fp> {

template <std::floating_point Fp>
class TwoTargetMatrixGateImpl : public GateBase<Fp> {
Matrix4x4 _matrix;
Matrix4x4<Fp> _matrix;

public:
TwoTargetMatrixGateImpl(std::uint64_t target_mask,
std::uint64_t control_mask,
const std::array<std::array<Complex, 4>, 4>& matrix)
const std::array<std::array<Complex<Fp>, 4>, 4>& matrix)
: GateBase<Fp>(target_mask, control_mask) {
for (std::uint64_t i : std::views::iota(0, 4)) {
for (std::uint64_t j : std::views::iota(0, 4)) {
Expand All @@ -75,8 +75,8 @@ class TwoTargetMatrixGateImpl : public GateBase<Fp> {
}
}

std::array<std::array<Complex, 4>, 4> matrix() const {
std::array<std::array<Complex, 4>, 4> matrix;
std::array<std::array<Complex<Fp>, 4>, 4> matrix() const {
std::array<std::array<Complex<Fp>, 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[i][j];
Expand All @@ -86,7 +86,7 @@ class TwoTargetMatrixGateImpl : public GateBase<Fp> {
}

std::shared_ptr<const GateBase<Fp>> get_inverse() const override {
std::array<std::array<Complex, 4>, 4> matrix_dag;
std::array<std::array<Complex<Fp>, 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[j][i]);
Expand All @@ -95,8 +95,8 @@ class TwoTargetMatrixGateImpl : public GateBase<Fp> {
return std::make_shared<const TwoTargetMatrixGateImpl>(
this->_target_mask, this->_control_mask, matrix_dag);
}
internal::ComplexMatrix get_matrix() const override {
internal::ComplexMatrix mat(4, 4);
internal::ComplexMatrix<Fp> get_matrix() const override {
internal::ComplexMatrix<Fp> 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],
Expand Down
16 changes: 8 additions & 8 deletions scaluq/gate/gate_pauli.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class PauliGateImpl : public GateBase<Fp> {
std::shared_ptr<const GateBase<Fp>> get_inverse() const override {
return this->shared_from_this();
}
internal::ComplexMatrix get_matrix() const override { return this->_pauli.get_matrix(); }
internal::ComplexMatrix<Fp> get_matrix() const override { return this->_pauli.get_matrix(); }

void update_quantum_state(StateVector<Fp>& state_vector) const override {
auto [bit_flip_mask, phase_flip_mask] = _pauli.get_XZ_mask_representation();
Expand Down Expand Up @@ -66,13 +66,13 @@ class PauliRotationGateImpl : public GateBase<Fp> {
this->_control_mask, _pauli, -_angle);
}

internal::ComplexMatrix get_matrix() const override {
internal::ComplexMatrix mat = this->_pauli.get_matrix_ignoring_coef();
Complex true_angle = _angle * _pauli.coef();
StdComplex imag_unit(0, 1);
mat = (StdComplex)Kokkos::cos(-true_angle / 2) *
internal::ComplexMatrix::Identity(mat.rows(), mat.cols()) +
imag_unit * (StdComplex)Kokkos::sin(-true_angle / 2) * mat;
internal::ComplexMatrix<Fp> get_matrix() const override {
internal::ComplexMatrix<Fp> mat = this->_pauli.get_matrix_ignoring_coef();
Complex<Fp> true_angle = _angle * _pauli.coef();
StdComplex<Fp> imag_unit(0, 1);
mat = (StdComplex<Fp>)Kokkos::cos(-true_angle / 2) *
internal::ComplexMatrix<Fp>::Identity(mat.rows(), mat.cols()) +
imag_unit * (StdComplex<Fp>)Kokkos::sin(-true_angle / 2) * mat;
return mat;
}
void update_quantum_state(StateVector<Fp>& state_vector) const override {
Expand Down
2 changes: 1 addition & 1 deletion scaluq/gate/gate_probablistic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class ProbablisticGateImpl : public GateBase<Fp> {
[](const std::shared_ptr<const GateBase<Fp>>& gate) { return gate->get_inverse(); });
return std::make_shared<const ProbablisticGateImpl>(_distribution, inv_gate_list);
}
internal::ComplexMatrix get_matrix() const override {
internal::ComplexMatrix<Fp> get_matrix() const override {
throw std::runtime_error(
"ProbablisticGateImpl::get_matrix(): This function must not be used in "
"ProbablisticGateImpl.");
Expand Down
Loading

0 comments on commit 3953c6c

Please sign in to comment.