Skip to content

Commit

Permalink
一旦コンパイルok
Browse files Browse the repository at this point in the history
  • Loading branch information
gandalfr-KY committed Oct 11, 2024
1 parent 0a5c7e4 commit e4a0582
Show file tree
Hide file tree
Showing 8 changed files with 503 additions and 1,378 deletions.
1 change: 1 addition & 0 deletions exe/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ int main() {
state.load({0, 1, 2, 3, 4, 5, 6, 7});
auto x_gate = scaluq::gate::X<double>(1, {0, 2});
x_gate->update_quantum_state(state);
// auto sqrtx = scaluq::gate::SqrtX<double>(1, {0, 3});

std::cout << state << std::endl;
}
Expand Down
1,342 changes: 213 additions & 1,129 deletions log.txt

Large diffs are not rendered by default.

97 changes: 54 additions & 43 deletions scaluq/gate/gate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ namespace internal {
template <std::floating_point FloatType>
class GateBase;

template <typename T>
concept GateImpl = std::derived_from<T, GateBase<typename T::FloatType>>;

template <std::floating_point FloatType>
class IGateImpl;
template <std::floating_point FloatType>
Expand Down Expand Up @@ -72,11 +69,7 @@ class PauliRotationGateImpl;
template <std::floating_point FloatType>
class ProbablisticGateImpl;

template <GateImpl T>
class GatePtr;
} // namespace internal
template <std::floating_point FloatType>
using Gate = internal::GatePtr<internal::GateBase<FloatType>>;

enum class GateType {
Unknown,
Expand Down Expand Up @@ -110,66 +103,66 @@ enum class GateType {
Probablistic
};

template <internal::GateImpl T>
template <typename T, std::floating_point S>
constexpr GateType get_gate_type() {
using TWithoutConst = std::remove_cv_t<T>;
if constexpr (std::is_same_v<TWithoutConst, internal::GateBase>)
if constexpr (std::is_same_v<TWithoutConst, internal::GateBase<S>>)
return GateType::Unknown;
else if constexpr (std::is_same_v<TWithoutConst, internal::IGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::IGateImpl<S>>)
return GateType::I;
else if constexpr (std::is_same_v<TWithoutConst, internal::GlobalPhaseGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::GlobalPhaseGateImpl<S>>)
return GateType::GlobalPhase;
else if constexpr (std::is_same_v<TWithoutConst, internal::XGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::XGateImpl<S>>)
return GateType::X;
else if constexpr (std::is_same_v<TWithoutConst, internal::YGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::YGateImpl<S>>)
return GateType::Y;
else if constexpr (std::is_same_v<TWithoutConst, internal::ZGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::ZGateImpl<S>>)
return GateType::Z;
else if constexpr (std::is_same_v<TWithoutConst, internal::HGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::HGateImpl<S>>)
return GateType::H;
else if constexpr (std::is_same_v<TWithoutConst, internal::SGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::SGateImpl<S>>)
return GateType::S;
else if constexpr (std::is_same_v<TWithoutConst, internal::SdagGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::SdagGateImpl<S>>)
return GateType::Sdag;
else if constexpr (std::is_same_v<TWithoutConst, internal::TGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::TGateImpl<S>>)
return GateType::T;
else if constexpr (std::is_same_v<TWithoutConst, internal::TdagGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::TdagGateImpl<S>>)
return GateType::Tdag;
else if constexpr (std::is_same_v<TWithoutConst, internal::SqrtXGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::SqrtXGateImpl<S>>)
return GateType::SqrtX;
else if constexpr (std::is_same_v<TWithoutConst, internal::SqrtXdagGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::SqrtXdagGateImpl<S>>)
return GateType::SqrtXdag;
else if constexpr (std::is_same_v<TWithoutConst, internal::SqrtYGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::SqrtYGateImpl<S>>)
return GateType::SqrtY;
else if constexpr (std::is_same_v<TWithoutConst, internal::SqrtYdagGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::SqrtYdagGateImpl<S>>)
return GateType::SqrtYdag;
else if constexpr (std::is_same_v<TWithoutConst, internal::P0GateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::P0GateImpl<S>>)
return GateType::P0;
else if constexpr (std::is_same_v<TWithoutConst, internal::P1GateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::P1GateImpl<S>>)
return GateType::P1;
else if constexpr (std::is_same_v<TWithoutConst, internal::RXGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::RXGateImpl<S>>)
return GateType::RX;
else if constexpr (std::is_same_v<TWithoutConst, internal::RYGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::RYGateImpl<S>>)
return GateType::RY;
else if constexpr (std::is_same_v<TWithoutConst, internal::RZGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::RZGateImpl<S>>)
return GateType::RZ;
else if constexpr (std::is_same_v<TWithoutConst, internal::U1GateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::U1GateImpl<S>>)
return GateType::U1;
else if constexpr (std::is_same_v<TWithoutConst, internal::U2GateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::U2GateImpl<S>>)
return GateType::U2;
else if constexpr (std::is_same_v<TWithoutConst, internal::U3GateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::U3GateImpl<S>>)
return GateType::U3;
else if constexpr (std::is_same_v<TWithoutConst, internal::OneTargetMatrixGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::OneTargetMatrixGateImpl<S>>)
return GateType::OneTargetMatrix;
else if constexpr (std::is_same_v<TWithoutConst, internal::SwapGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::SwapGateImpl<S>>)
return GateType::Swap;
else if constexpr (std::is_same_v<TWithoutConst, internal::TwoTargetMatrixGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::TwoTargetMatrixGateImpl<S>>)
return GateType::TwoTargetMatrix;
else if constexpr (std::is_same_v<TWithoutConst, internal::PauliGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::PauliGateImpl<S>>)
return GateType::Pauli;
else if constexpr (std::is_same_v<TWithoutConst, internal::PauliRotationGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::PauliRotationGateImpl<S>>)
return GateType::PauliRotation;
else if constexpr (std::is_same_v<TWithoutConst, internal::ProbablisticGateImpl<FloatType>>)
else if constexpr (std::is_same_v<TWithoutConst, internal::ProbablisticGateImpl<S>>)
return GateType::Probablistic;
else
static_assert(internal::lazy_false_v<T>, "unknown GateImpl");
Expand Down Expand Up @@ -235,16 +228,33 @@ class GateBase : public std::enable_shared_from_this<GateBase<_FloatType>> {
return _target_mask | _control_mask;
}

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

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

[[nodiscard]] virtual std::string to_string(const std::string& indent = "") const = 0;
};

template <typename T>
concept GateImpl = std::derived_from<T, internal::GateBase<typename T::FloatType>>;

template <GateImpl T>
class GatePtr;

} // namespace internal

template <std::floating_point FloatType>
using Gate = internal::GatePtr<internal::GateBase<FloatType>>;

namespace internal {

template <GateImpl T>
class GatePtr {
friend class GateFactory;
template <GateImpl U>
friend class GatePtr;
using FloatType = typename T::FloatType;

private:
std::shared_ptr<const T> _gate_ptr;
Expand All @@ -256,15 +266,15 @@ class GatePtr {
template <GateImpl U>
GatePtr(const std::shared_ptr<const U>& gate_ptr) {
if constexpr (std::is_same_v<T, U>) {
_gate_type = get_gate_type<T>();
_gate_type = get_gate_type<T, FloatType>();
_gate_ptr = gate_ptr;
} else if constexpr (std::is_same_v<T, internal::GateBase>) {
} else if constexpr (std::is_same_v<T, internal::GateBase<FloatType>>) {
// upcast
_gate_type = get_gate_type<U>();
_gate_type = get_gate_type<U, FloatType>();
_gate_ptr = std::static_pointer_cast<const T>(gate_ptr);
} else {
// downcast
_gate_type = get_gate_type<T>();
_gate_type = get_gate_type<T, FloatType>();
if (!(_gate_ptr = std::dynamic_pointer_cast<const T>(gate_ptr))) {
throw std::runtime_error("invalid gate cast");
}
Expand All @@ -275,13 +285,13 @@ class GatePtr {
if constexpr (std::is_same_v<T, U>) {
_gate_type = gate._gate_type;
_gate_ptr = gate._gate_ptr;
} else if constexpr (std::is_same_v<T, internal::GateBase>) {
} else if constexpr (std::is_same_v<T, internal::GateBase<FloatType>>) {
// upcast
_gate_type = gate._gate_type;
_gate_ptr = std::static_pointer_cast<const T>(gate._gate_ptr);
} else {
// downcast
if (gate._gate_type != get_gate_type<T>()) {
if (gate._gate_type != get_gate_type<T, FloatType>()) {
throw std::runtime_error("invalid gate cast");
}
_gate_type = gate._gate_type;
Expand All @@ -303,6 +313,7 @@ class GatePtr {
return os;
}
};

} // namespace internal

#ifdef SCALUQ_USE_NANOBIND
Expand Down
49 changes: 25 additions & 24 deletions scaluq/gate/gate_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,33 +218,34 @@ inline Gate<FloatType> DenseMatrix(const std::vector<std::uint64_t>& targets,
"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() == 0) return I<FloatType>();
if (targets.size() == 1) {
return OneTargetMatrix(targets[0],
std::array{std::array{Complex(matrix(0, 0)), Complex(matrix(0, 1))},
std::array{Complex(matrix(1, 0)), Complex(matrix(1, 1))}},
controls);
return OneTargetMatrix<FloatType>(
targets[0],
std::array{std::array{Complex(matrix(0, 0)), Complex(matrix(0, 1))},
std::array{Complex(matrix(1, 0)), Complex(matrix(1, 1))}},
controls);
}
if (targets.size() == 2) {
return TwoTargetMatrix(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))}},
controls);
return TwoTargetMatrix<FloatType>(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))}},
controls);
}
throw std::runtime_error(
"gate::DenseMatrix(const std::vector<std::uint64_t>&, const internal::ComplexMatrix&): "
Expand Down
32 changes: 17 additions & 15 deletions scaluq/gate/gate_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ namespace scaluq {
namespace internal {

template <std::floating_point FloatType>
class OneTargetMatrixGateImpl : public GateBase {
class OneTargetMatrixGateImpl : public GateBase<FloatType> {
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) {
: GateBase<FloatType>(target_mask, control_mask) {
_matrix[0][0] = matrix[0][0];
_matrix[0][1] = matrix[0][1];
_matrix[1][0] = matrix[1][0];
Expand All @@ -30,10 +30,10 @@ class OneTargetMatrixGateImpl : public GateBase {
return {_matrix[0][0], _matrix[0][1], _matrix[1][0], _matrix[1][1]};
}

Gate get_inverse() const override {
Gate<FloatType> get_inverse() const override {
return std::make_shared<const OneTargetMatrixGateImpl>(
_target_mask,
_control_mask,
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]),
Expand All @@ -47,26 +47,27 @@ class OneTargetMatrixGateImpl : public GateBase {

void update_quantum_state(StateVector<FloatType>& state_vector) const override {
check_qubit_mask_within_bounds(state_vector);
one_target_dense_matrix_gate(_target_mask, _control_mask, _matrix, state_vector);
one_target_dense_matrix_gate(
this->_target_mask, this->_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);
ss << indent << "Gate<FloatType> Type: OneTargetMatrix\n";
ss << this->get_qubit_info_as_string(indent);
return ss.str();
}
};

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

public:
TwoTargetMatrixGateImpl(std::uint64_t target_mask,
std::uint64_t control_mask,
const std::array<std::array<Complex, 4>, 4>& matrix)
: GateBase(target_mask, control_mask) {
: GateBase<FloatType>(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[i][j] = matrix[i][j];
Expand All @@ -84,15 +85,15 @@ class TwoTargetMatrixGateImpl : public GateBase {
return matrix;
}

Gate get_inverse() const override {
Gate<FloatType> get_inverse() const override {
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[j][i]);
}
}
return std::make_shared<const TwoTargetMatrixGateImpl>(
_target_mask, _control_mask, matrix_dag);
this->_target_mask, this->_control_mask, matrix_dag);
}
internal::ComplexMatrix get_matrix() const override {
internal::ComplexMatrix mat(4, 4);
Expand All @@ -105,13 +106,14 @@ class TwoTargetMatrixGateImpl : public GateBase {

void update_quantum_state(StateVector<FloatType>& state_vector) const override {
check_qubit_mask_within_bounds(state_vector);
two_target_dense_matrix_gate(_target_mask, _control_mask, _matrix, state_vector);
two_target_dense_matrix_gate(
this->_target_mask, this->_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);
ss << indent << "Gate<FloatType> Type: TwoTargetMatrix\n";
ss << this->get_qubit_info_as_string(indent);
return ss.str();
}
};
Expand Down
Loading

0 comments on commit e4a0582

Please sign in to comment.