Skip to content

Commit

Permalink
Merge pull request #191 from qulacs/add-batch-update
Browse files Browse the repository at this point in the history
Add batch update
  • Loading branch information
Glacialte authored Dec 27, 2024
2 parents a422e09 + a014bc6 commit c2ed057
Show file tree
Hide file tree
Showing 34 changed files with 2,541 additions and 279 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,10 @@ n_qubits = 3
state = StateVector.Haar_random_state(n_qubits, 0)

circuit = Circuit(n_qubits)
circuit.add_gate(gate::X(0))
circuit.add_gate(gate::CNot(0, 1))
circuit.add_gate(gate::Y(1))
circuit.add_gate(gate::RX(1, math.pi / 2))
circuit.add_gate(gate.X(0))
circuit.add_gate(gate.CNot(0, 1))
circuit.add_gate(gate.Y(1))
circuit.add_gate(gate.RX(1, math.pi / 2))
circuit.update_quantum_state(state)

observable = Operator(n_qubits)
Expand Down
12 changes: 0 additions & 12 deletions exe/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,6 @@ int main() {
std::cout << Json(gate::Pauli<double>(pauli)) << std::endl;
std::cout << Json(gate::PauliRotation<double>(pauli, 0.5)) << std::endl;

std::cout << Json(gate::OneTargetMatrix<double>(2, {0, 1, 2, 3})) << std::endl;
std::cout << Json(gate::TwoTargetMatrix<double>(
2, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}))
<< std::endl;

auto probgate =
gate::Probablistic<double>({.1, .9}, {gate::X<double>(0), gate::I<double>()});
std::cout << Json(probgate) << std::endl;
Expand Down Expand Up @@ -119,13 +114,6 @@ int main() {
Gate<double> gate = j;
std::cout << gate << std::endl;
}
{
auto x = gate::OneTargetMatrix<double>(1, {2., 3., 0., 10.}, {0, 3});
Json j = x;
std::cout << j << std::endl;
Gate<double> gate = j;
std::cout << gate << std::endl;
}
{
PauliOperator<double> pauli("X 2 Y 1");
auto x = gate::PauliRotation<double>(pauli, 1.5, {0, 3});
Expand Down
21 changes: 6 additions & 15 deletions include/scaluq/gate/gate.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "../state/state_vector.hpp"
#include "../state/state_vector_batched.hpp"
#include "../types.hpp"
#include "../util/utility.hpp"

Expand Down Expand Up @@ -56,12 +57,8 @@ class U2GateImpl;
template <std::floating_point Fp>
class U3GateImpl;
template <std::floating_point Fp>
class OneTargetMatrixGateImpl;
template <std::floating_point Fp>
class SwapGateImpl;
template <std::floating_point Fp>
class TwoTargetMatrixGateImpl;
template <std::floating_point Fp>
class PauliGateImpl;
template <std::floating_point Fp>
class PauliRotationGateImpl;
Expand Down Expand Up @@ -98,9 +95,7 @@ enum class GateType {
U1,
U2,
U3,
OneTargetMatrix,
Swap,
TwoTargetMatrix,
Pauli,
PauliRotation,
SparseMatrix,
Expand Down Expand Up @@ -157,12 +152,8 @@ constexpr GateType get_gate_type() {
return GateType::U2;
else if constexpr (std::is_same_v<TWithoutConst, internal::U3GateImpl<S>>)
return GateType::U3;
else if constexpr (std::is_same_v<TWithoutConst, internal::OneTargetMatrixGateImpl<S>>)
return GateType::OneTargetMatrix;
else if constexpr (std::is_same_v<TWithoutConst, internal::SwapGateImpl<S>>)
return GateType::Swap;
else if constexpr (std::is_same_v<TWithoutConst, internal::TwoTargetMatrixGateImpl<S>>)
return GateType::TwoTargetMatrix;
else if constexpr (std::is_same_v<TWithoutConst, internal::PauliGateImpl<S>>)
return GateType::Pauli;
else if constexpr (std::is_same_v<TWithoutConst, internal::PauliRotationGateImpl<S>>)
Expand All @@ -188,6 +179,7 @@ class GateBase : public std::enable_shared_from_this<GateBase<_FloatType>> {
std::uint64_t _target_mask, _control_mask;

void check_qubit_mask_within_bounds(const StateVector<Fp>& state_vector) const;
void check_qubit_mask_within_bounds(const StateVectorBatched<Fp>& states) const;

std::string get_qubit_info_as_string(const std::string& indent) const;

Expand All @@ -214,6 +206,7 @@ class GateBase : public std::enable_shared_from_this<GateBase<_FloatType>> {
[[nodiscard]] virtual internal::ComplexMatrix<Fp> get_matrix() const = 0;

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

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

Expand Down Expand Up @@ -316,8 +309,6 @@ class GatePtr {
else if (type == "U2") gate = get_from_json<U2GateImpl<Fp>>(j);
else if (type == "U3") gate = get_from_json<U3GateImpl<Fp>>(j);
else if (type == "Swap") gate = get_from_json<SwapGateImpl<Fp>>(j);
else if (type == "OneTargetMatrix") gate = get_from_json<OneTargetMatrixGateImpl<Fp>>(j);
else if (type == "TwoTargetMatrix") gate = get_from_json<TwoTargetMatrixGateImpl<Fp>>(j);
else if (type == "Pauli") gate = get_from_json<PauliGateImpl<Fp>>(j);
else if (type == "PauliRotation") gate = get_from_json<PauliRotationGateImpl<Fp>>(j);
else if (type == "Probablistic") gate = get_from_json<ProbablisticGateImpl<Fp>>(j);
Expand Down Expand Up @@ -429,11 +420,11 @@ void bind_gate_gate_hpp_without_precision(nb::module_& m) {
.value("U1", GateType::U1)
.value("U2", GateType::U2)
.value("U3", GateType::U3)
.value("OneTargetMatrix", GateType::OneTargetMatrix)
.value("Swap", GateType::Swap)
.value("TwoTargetMatrix", GateType::TwoTargetMatrix)
.value("Pauli", GateType::Pauli)
.value("PauliRotation", GateType::PauliRotation);
.value("PauliRotation", GateType::PauliRotation)
.value("SparseMatrix", GateType::SparseMatrix)
.value("DenseMatrix", GateType::DenseMatrix);
}

template <std::floating_point Fp>
Expand Down
28 changes: 0 additions & 28 deletions include/scaluq/gate/gate_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,6 @@ inline Gate<Fp> U3(std::uint64_t target,
internal::vector_to_mask({target}), internal::vector_to_mask(controls), theta, phi, lambda);
}
template <std::floating_point Fp>
inline Gate<Fp> OneTargetMatrix(std::uint64_t target,
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);
}
template <std::floating_point Fp>
inline Gate<Fp> CX(std::uint64_t control, std::uint64_t target) {
return internal::GateFactory::create_gate<internal::XGateImpl<Fp>>(
internal::vector_to_mask({target}), internal::vector_to_mask({control}));
Expand Down Expand Up @@ -178,14 +171,6 @@ inline Gate<Fp> Swap(std::uint64_t target1,
internal::vector_to_mask({target1, target2}), internal::vector_to_mask(controls));
}
template <std::floating_point Fp>
inline Gate<Fp> TwoTargetMatrix(std::uint64_t target1,
std::uint64_t target2,
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);
}
template <std::floating_point Fp>
inline Gate<Fp> Pauli(const PauliOperator<Fp>& pauli,
const std::vector<std::uint64_t>& controls = {}) {
auto tar = pauli.target_qubit_list();
Expand Down Expand Up @@ -397,19 +382,6 @@ void bind_gate_gate_factory_hpp(nb::module_& mgate) {
&gate::CCX<Fp>,
"Generate general Gate class instance of Toffoli.\n\n.. note:: Toffoli is an alias "
"of CCX.");
mgate.def("OneTargetMatrix",
&gate::OneTargetMatrix<Fp>,
"Generate general Gate class instance of OneTargetMatrix.",
"target"_a,
"matrix"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("TwoTargetMatrix",
&gate::TwoTargetMatrix<Fp>,
"Generate general Gate class instance of TwoTargetMatrix.",
"target1"_a,
"target2"_a,
"matrix"_a,
"controls"_a = std::vector<std::uint64_t>{});
mgate.def("DenseMatrix",
&gate::DenseMatrix<Fp>,
"Generate general Gate class instance of DenseMatrix.",
Expand Down
160 changes: 3 additions & 157 deletions include/scaluq/gate/gate_matrix.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,105 +10,6 @@

namespace scaluq {
namespace internal {

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

public:
OneTargetMatrixGateImpl(std::uint64_t target_mask,
std::uint64_t control_mask,
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<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<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<Fp> get_matrix() const override;

void update_quantum_state(StateVector<Fp>& state_vector) const override;
std::string to_string(const std::string& indent) const override;

void get_as_json(Json& j) const override {
j = Json{{"type", "OneTargetMatrix"},
{"target", this->target_qubit_list()},
{"control", this->control_qubit_list()},
{"matrix",
std::vector<std::vector<Kokkos::complex<Fp>>>{{_matrix[0][0], _matrix[0][1]},
{_matrix[1][0], _matrix[1][1]}}}};
}
};

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

public:
TwoTargetMatrixGateImpl(std::uint64_t target_mask,
std::uint64_t control_mask,
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)) {
_matrix[i][j] = matrix[i][j];
}
}
}

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];
}
}
return matrix;
}

std::shared_ptr<const GateBase<Fp>> get_inverse() const override {
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]);
}
}
return std::make_shared<const TwoTargetMatrixGateImpl>(
this->_target_mask, this->_control_mask, matrix_dag);
}
internal::ComplexMatrix<Fp> get_matrix() const override;

void update_quantum_state(StateVector<Fp>& state_vector) const override;

std::string to_string(const std::string& indent) const override;

void get_as_json(Json& j) const override {
j = Json{{"type", "TwoTargetMatrix"},
{"target", this->target_qubit_list()},
{"control", this->control_qubit_list()},
{"matrix",
std::vector<std::vector<Kokkos::complex<Fp>>>{
{_matrix[0][0], _matrix[0][1], _matrix[0][2], _matrix[0][3]},
{_matrix[1][0], _matrix[1][1], _matrix[1][2], _matrix[1][3]},
{_matrix[2][0], _matrix[2][1], _matrix[2][2], _matrix[2][3]},
{_matrix[3][0], _matrix[3][1], _matrix[3][2], _matrix[3][3]}}}};
}
};

template <std::floating_point Fp>
class DenseMatrixGateImpl : public GateBase<Fp> {
Matrix<Fp> _matrix;
Expand All @@ -127,6 +28,7 @@ class DenseMatrixGateImpl : public GateBase<Fp> {
ComplexMatrix<Fp> get_matrix() const override;

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand Down Expand Up @@ -157,6 +59,7 @@ class SparseMatrixGateImpl : public GateBase<Fp> {
SparseComplexMatrix<Fp> get_sparse_matrix() const { return get_matrix().sparseView(); }

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand All @@ -170,74 +73,17 @@ class SparseMatrixGateImpl : public GateBase<Fp> {

} // namespace internal

template <std::floating_point Fp>
using OneTargetMatrixGate = internal::GatePtr<internal::OneTargetMatrixGateImpl<Fp>>;
template <std::floating_point Fp>
using TwoTargetMatrixGate = internal::GatePtr<internal::TwoTargetMatrixGateImpl<Fp>>;
template <std::floating_point Fp>
using SparseMatrixGate = internal::GatePtr<internal::SparseMatrixGateImpl<Fp>>;
template <std::floating_point Fp>
using DenseMatrixGate = internal::GatePtr<internal::DenseMatrixGateImpl<Fp>>;

namespace internal {
#define DECLARE_GET_FROM_JSON_ONETARGETMATRIXGATE_WITH_TYPE(Type) \
template <> \
inline std::shared_ptr<const OneTargetMatrixGateImpl<Type>> get_from_json(const Json& j) { \
auto targets = j.at("target").get<std::vector<std::uint64_t>>(); \
auto controls = j.at("control").get<std::vector<std::uint64_t>>(); \
auto matrix = j.at("matrix").get<std::vector<std::vector<Kokkos::complex<Type>>>>(); \
return std::make_shared<const OneTargetMatrixGateImpl<Type>>( \
vector_to_mask(targets), \
vector_to_mask(controls), \
std::array<std::array<Kokkos::complex<Type>, 2>, 2>{ \
matrix[0][0], matrix[0][1], matrix[1][0], matrix[1][1]}); \
}
DECLARE_GET_FROM_JSON_ONETARGETMATRIXGATE_WITH_TYPE(double)
DECLARE_GET_FROM_JSON_ONETARGETMATRIXGATE_WITH_TYPE(float)
#undef DECLARE_GET_FROM_JSON_ONETARGETMATRIXGATE_WITH_TYPE

#define DECLARE_GET_FROM_JSON_TWOTARGETMATRIXGATE_WITH_TYPE(Type) \
template <> \
inline std::shared_ptr<const TwoTargetMatrixGateImpl<Type>> get_from_json(const Json& j) { \
auto targets = j.at("target").get<std::vector<std::uint64_t>>(); \
auto controls = j.at("control").get<std::vector<std::uint64_t>>(); \
auto matrix = j.at("matrix").get<std::vector<std::vector<Kokkos::complex<Type>>>>(); \
return std::make_shared<const TwoTargetMatrixGateImpl<Type>>( \
vector_to_mask(targets), \
vector_to_mask(controls), \
std::array<std::array<Kokkos::complex<Type>, 4>, 4>{matrix[0][0], \
matrix[0][1], \
matrix[0][2], \
matrix[0][3], \
matrix[1][0], \
matrix[1][1], \
matrix[1][2], \
matrix[1][3], \
matrix[2][0], \
matrix[2][1], \
matrix[2][2], \
matrix[2][3], \
matrix[3][0], \
matrix[3][1], \
matrix[3][2], \
matrix[3][3]}); \
}
DECLARE_GET_FROM_JSON_TWOTARGETMATRIXGATE_WITH_TYPE(double)
DECLARE_GET_FROM_JSON_TWOTARGETMATRIXGATE_WITH_TYPE(float)
#undef DECLARE_GET_FROM_JSON_TWOTARGETMATRIXGATE_WITH_TYPE

} // namespace internal

#ifdef SCALUQ_USE_NANOBIND
namespace internal {
template <std::floating_point Fp>
void bind_gate_gate_matrix_hpp(nb::module_& m) {
DEF_GATE(OneTargetMatrixGate, Fp, "Specific class of one-qubit dense matrix gate.")
.def("matrix", [](const OneTargetMatrixGate<double>& gate) { return gate->matrix(); });
DEF_GATE(TwoTargetMatrixGate, Fp, "Specific class of two-qubit dense matrix gate.")
.def("matrix", [](const TwoTargetMatrixGate<double>& gate) { return gate->matrix(); });
DEF_GATE(SparseMatrixGate, Fp, "Specific class of sparse matrix gate.")
.def("matrix", [](const SparseMatrixGate<double>& gate) { return gate->get_matrix(); })
.def("matrix", [](const SparseMatrixGate<Fp>& gate) { return gate->get_matrix(); })
.def("sparse_matrix",
[](const SparseMatrixGate<Fp>& gate) { return gate->get_sparse_matrix(); });
DEF_GATE(DenseMatrixGate, Fp, "Specific class of dense matrix gate.")
Expand Down
2 changes: 2 additions & 0 deletions include/scaluq/gate/gate_pauli.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class PauliGateImpl : public GateBase<Fp> {
internal::ComplexMatrix<Fp> get_matrix() const override { return this->_pauli.get_matrix(); }

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand Down Expand Up @@ -59,6 +60,7 @@ class PauliRotationGateImpl : public GateBase<Fp> {
internal::ComplexMatrix<Fp> get_matrix() const override;

void update_quantum_state(StateVector<Fp>& state_vector) const override;
void update_quantum_state(StateVectorBatched<Fp>& states) const override;

std::string to_string(const std::string& indent) const override;

Expand Down
Loading

0 comments on commit c2ed057

Please sign in to comment.