Skip to content

Commit

Permalink
operator一旦ok
Browse files Browse the repository at this point in the history
  • Loading branch information
gandalfr-KY committed Oct 11, 2024
1 parent eee5326 commit 32abd04
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 124 deletions.
4 changes: 2 additions & 2 deletions scaluq/operator/operator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ class Operator {
StateVector<FloatType> res(state_vector.n_qubits());
res.set_zero_norm_state();
for (const auto& term : _terms) {
StateVector tmp = state_vector.copy();
StateVector<double> tmp = state_vector.copy();
term.apply_to_state(tmp);
res.add_state_vector(tmp);
res.add_state_vector_with_coef(1, tmp);
}
state_vector = res;
}
Expand Down
5 changes: 2 additions & 3 deletions scaluq/state/state_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <Kokkos_Core.hpp>
#include <Kokkos_Random.hpp>
#include <random>
#include <ranges>
#include <stdexcept>
#include <vector>

Expand All @@ -15,9 +16,7 @@ namespace scaluq {
using HostSpace = Kokkos::HostSpace;
using DefaultSpace = Kokkos::DefaultExecutionSpace;

#define STATE_VECTOR_TEMPLATE(FloatType) template <std::floating_point FloatType = double>

template <std::floating_point FloatType = double>
template <std::floating_point FloatType>
class StateVector {
std::uint64_t _n_qubits;
std::uint64_t _dim;
Expand Down
2 changes: 1 addition & 1 deletion scaluq/state/state_vector_batched.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace scaluq {

STATE_VECTOR_TEMPLATE(FloatType)
template <std::floating_point FloatType>
class StateVectorBatched {
std::uint64_t _batch_size;
std::uint64_t _n_qubits;
Expand Down
4 changes: 2 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ add_executable(scaluq_test EXCLUDE_FROM_ALL
gate/gate_test.cpp
# # gate/merge_test.cpp
# gate/param_gate_test.cpp
# operator/test_pauli_operator.cpp
# operator/test_operator.cpp
operator/test_pauli_operator.cpp
operator/test_operator.cpp
state/state_vector_test.cpp
state/state_vector_batched_test.cpp
)
Expand Down
38 changes: 19 additions & 19 deletions tests/operator/test_operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ using namespace scaluq;

const double eps = 1e-12;

std::pair<Operator, Eigen::MatrixXcd> generate_random_observable_with_eigen(std::uint64_t n,
Random& random) {
std::pair<Operator<double>, Eigen::MatrixXcd> generate_random_observable_with_eigen(
std::uint64_t n, Random& random) {
std::uint64_t dim = 1ULL << n;
Operator rand_observable(n);
Operator<double> rand_observable(n);
Eigen::MatrixXcd test_rand_observable = Eigen::MatrixXcd::Zero(dim, dim);

std::uint64_t term_count = random.int32() % 10 + 1;
Expand Down Expand Up @@ -41,7 +41,7 @@ std::pair<Operator, Eigen::MatrixXcd> generate_random_observable_with_eigen(std:
str += " " + std::to_string(ind);
}
}
rand_observable.add_operator(PauliOperator(str.c_str(), coef));
rand_observable.add_operator(PauliOperator<double>(str.c_str(), coef));
}
return {std::move(rand_observable), std::move(test_rand_observable)};
}
Expand All @@ -55,7 +55,7 @@ TEST(OperatorTest, CheckExpectationValue) {
auto [rand_observable, test_rand_observable] =
generate_random_observable_with_eigen(n, random);

auto state = StateVector::Haar_random_state(n);
auto state = StateVector<double>::Haar_random_state(n);
auto state_cp = state.get_amplitudes();
Eigen::VectorXcd test_state = Eigen::VectorXcd::Zero(dim);
for (std::uint64_t i = 0; i < dim; ++i) test_state[i] = state_cp[i];
Expand All @@ -77,11 +77,11 @@ TEST(OperatorTest, CheckTransitionAmplitude) {
auto [rand_observable, test_rand_observable] =
generate_random_observable_with_eigen(n, random);

auto state_bra = StateVector::Haar_random_state(n);
auto state_bra = StateVector<double>::Haar_random_state(n);
auto state_bra_cp = state_bra.get_amplitudes();
Eigen::VectorXcd test_state_bra = Eigen::VectorXcd::Zero(dim);
for (std::uint64_t i = 0; i < dim; ++i) test_state_bra[i] = state_bra_cp[i];
auto state_ket = StateVector::Haar_random_state(n);
auto state_ket = StateVector<double>::Haar_random_state(n);
auto state_ket_cp = state_ket.get_amplitudes();
Eigen::VectorXcd test_state_ket = Eigen::VectorXcd::Zero(dim);
for (std::uint64_t i = 0; i < dim; ++i) test_state_ket[i] = state_ket_cp[i];
Expand All @@ -101,7 +101,7 @@ TEST(OperatorTest, AddTest) {
auto op1 = generate_random_observable_with_eigen(n, random).first;
auto op2 = generate_random_observable_with_eigen(n, random).first;
auto op = op1 + op2;
auto state = StateVector::Haar_random_state(n);
auto state = StateVector<double>::Haar_random_state(n);
auto exp1 = op1.get_expectation_value(state);
auto exp2 = op2.get_expectation_value(state);
auto exp = op.get_expectation_value(state);
Expand All @@ -117,7 +117,7 @@ TEST(OperatorTest, SubTest) {
auto op1 = generate_random_observable_with_eigen(n, random).first;
auto op2 = generate_random_observable_with_eigen(n, random).first;
auto op = op1 - op2;
auto state = StateVector::Haar_random_state(n);
auto state = StateVector<double>::Haar_random_state(n);
auto exp1 = op1.get_expectation_value(state);
auto exp2 = op2.get_expectation_value(state);
auto exp = op.get_expectation_value(state);
Expand All @@ -133,7 +133,7 @@ TEST(OperatorTest, MultiCoefTest) {
auto op1 = generate_random_observable_with_eigen(n, random).first;
auto coef = Complex(random.normal(), random.normal());
auto op = op1 * coef;
auto state = StateVector::Haar_random_state(n);
auto state = StateVector<double>::Haar_random_state(n);
auto exp1 = op1.get_expectation_value(state);
auto exp = op.get_expectation_value(state);
ASSERT_NEAR(Kokkos::abs(exp1 * coef - exp), 0, eps);
Expand All @@ -142,14 +142,14 @@ TEST(OperatorTest, MultiCoefTest) {

TEST(OperatorTest, ApplyToStateTest) {
const std::uint64_t n_qubits = 3;
StateVector state_vector(n_qubits);
StateVector<double> state_vector(n_qubits);
state_vector.load([n_qubits] {
std::vector<Complex> tmp(1 << n_qubits);
for (std::uint64_t i = 0; i < tmp.size(); ++i) tmp[i] = Complex(i, 0);
return tmp;
}());

Operator op(n_qubits);
Operator<double> op(n_qubits);
op.add_operator({0b001, 0b010, Complex(2)});
op.add_operator({"X 2 Y 1", 1});
op.apply_to_state(state_vector);
Expand All @@ -168,13 +168,13 @@ TEST(OperatorTest, ApplyToStateTest) {
}

TEST(OperatorTest, Optimize) {
Operator op(2);
op.add_operator(PauliOperator("X 0 Y 1", 1.));
op.add_operator(PauliOperator("Y 0 Z 1", 2.));
op.add_operator(PauliOperator("Z 1", 3.));
op.add_operator(PauliOperator("X 0 Y 1", 4.));
op.add_operator(PauliOperator("Z 1", 4.));
op.add_operator(PauliOperator("X 0 Y 1", 5.));
Operator<double> op(2);
op.add_operator(PauliOperator<double>("X 0 Y 1", 1.));
op.add_operator(PauliOperator<double>("Y 0 Z 1", 2.));
op.add_operator(PauliOperator<double>("Z 1", 3.));
op.add_operator(PauliOperator<double>("X 0 Y 1", 4.));
op.add_operator(PauliOperator<double>("Z 1", 4.));
op.add_operator(PauliOperator<double>("X 0 Y 1", 5.));
op.optimize();
std::vector<std::pair<std::string, Complex>> expected = {
{"X 0 Y 1", 10.}, {"Y 0 Z 1", 2.}, {"Z 1", 7.}};
Expand Down
128 changes: 69 additions & 59 deletions tests/operator/test_pauli_operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ using namespace scaluq;
const double eps = 1e-12;

TEST(PauliOperatorTest, ContainsExtraWhitespace) {
PauliOperator expected = PauliOperator("X 0", 1.0);
PauliOperator pauli_whitespace = PauliOperator("X 0 ", 1.0);
PauliOperator<double> expected = PauliOperator<double>("X 0", 1.0);
PauliOperator<double> pauli_whitespace = PauliOperator<double>("X 0 ", 1.0);

EXPECT_EQ(1, pauli_whitespace.target_qubit_list().size());
EXPECT_EQ(1, pauli_whitespace.pauli_id_list().size());
EXPECT_EQ(expected.get_pauli_string(), pauli_whitespace.get_pauli_string());
}

TEST(PauliOperatorTest, EmptyStringConstructsIdentity) {
const auto identity = PauliOperator("", 1.0);
const auto identity = PauliOperator<double>("", 1.0);
ASSERT_EQ(0, identity.target_qubit_list().size());
ASSERT_EQ(0, identity.pauli_id_list().size());
ASSERT_EQ("", identity.get_pauli_string());
Expand All @@ -29,59 +29,59 @@ TEST(PauliOperatorTest, PauliQubitOverflow) {
int n = 2;
double coef = 2.0;
std::string Pauli_string = "X 0 X 1 X 3";
PauliOperator pauli = PauliOperator(Pauli_string, coef);
StateVector state = StateVector::Haar_random_state(n);
PauliOperator<double> pauli = PauliOperator<double>(Pauli_string, coef);
StateVector state = StateVector<double>::Haar_random_state(n);
EXPECT_THROW((void)pauli.get_expectation_value(state), std::runtime_error);
}

TEST(PauliOperatorTest, BrokenPauliStringA) {
double coef = 2.0;
std::string Pauli_string = "X 0 X Z 1 Y 2";
EXPECT_THROW(PauliOperator(Pauli_string, coef), std::runtime_error);
EXPECT_THROW(PauliOperator<double>(Pauli_string, coef), std::runtime_error);
}

TEST(PauliOperatorTest, BrokenPauliStringB) {
double coef = 2.0;
std::string Pauli_string = "X {i}";
EXPECT_THROW(PauliOperator(Pauli_string, coef), std::runtime_error);
EXPECT_THROW(PauliOperator<double>(Pauli_string, coef), std::runtime_error);
}

TEST(PauliOperatorTest, BrokenPauliStringC) {
double coef = 2.0;
std::string Pauli_string = "X 4x";
EXPECT_THROW(PauliOperator(Pauli_string, coef), std::runtime_error);
EXPECT_THROW(PauliOperator<double>(Pauli_string, coef), std::runtime_error);
}

TEST(PauliOperatorTest, BrokenPauliStringD) {
double coef = 2.0;
std::string Pauli_string = "4 X";
EXPECT_THROW(PauliOperator(Pauli_string, coef), std::runtime_error);
EXPECT_THROW(PauliOperator<double>(Pauli_string, coef), std::runtime_error);
}

TEST(PauliOperatorTest, SpacedPauliString) {
double coef = 2.0;
std::string Pauli_string = "X 0 Y 1 ";
PauliOperator pauli = PauliOperator(Pauli_string, coef);
PauliOperator<double> pauli = PauliOperator<double>(Pauli_string, coef);
size_t PauliSize = pauli.target_qubit_list().size();
ASSERT_EQ(PauliSize, 2);
}

TEST(PauliOperatorTest, PartedPauliString) {
double coef = 2.0;
std::string Pauli_string = "X 0 Y ";
EXPECT_THROW(PauliOperator(Pauli_string, coef), std::runtime_error);
EXPECT_THROW(PauliOperator<double>(Pauli_string, coef), std::runtime_error);
}

struct PauliTestParam {
std::string test_name;
PauliOperator op1;
PauliOperator op2;
PauliOperator expected;
PauliOperator<double> op1;
PauliOperator<double> op2;
PauliOperator<double> expected;

PauliTestParam(const std::string& test_name_,
const PauliOperator& op1_,
const PauliOperator& op2_,
const PauliOperator& expected_)
const PauliOperator<double>& op1_,
const PauliOperator<double>& op2_,
const PauliOperator<double>& expected_)
: test_name(test_name_), op1(op1_), op2(op2_), expected(expected_) {}
};

Expand All @@ -93,59 +93,69 @@ class PauliOperatorMultiplyTest : public testing::TestWithParam<PauliTestParam>

TEST_P(PauliOperatorMultiplyTest, MultiplyTest) {
const auto p = GetParam();
PauliOperator res = p.op1 * p.op2;
PauliOperator<double> res = p.op1 * p.op2;
EXPECT_EQ(p.expected.get_pauli_string(), res.get_pauli_string());
EXPECT_EQ(p.expected.coef(), res.coef());
}

TEST_P(PauliOperatorMultiplyTest, MultiplyAssignmentTest) {
const auto p = GetParam();
PauliOperator res = p.op1;
PauliOperator<double> res = p.op1;
res = res * p.op2;
EXPECT_EQ(p.expected.get_pauli_string(), res.get_pauli_string());
EXPECT_EQ(p.expected.coef(), res.coef());
}

INSTANTIATE_TEST_CASE_P(
SinglePauli,
PauliOperatorMultiplyTest,
testing::Values(
PauliTestParam(
"XX", PauliOperator("X 0", 2.0), PauliOperator("X 0", 2.0), PauliOperator("I 0", 4.0)),
PauliTestParam(
"XY", PauliOperator("X 0", 2.0), PauliOperator("Y 0", 2.0), PauliOperator("Z 0", 4.0i)),
PauliTestParam("XZ",
PauliOperator("X 0", 2.0),
PauliOperator("Z 0", 2.0),
PauliOperator("Y 0", -4.0i)),
PauliTestParam("YX",
PauliOperator("Y 0", 2.0),
PauliOperator("X 0", 2.0),
PauliOperator("Z 0", -4.0i)),
PauliTestParam(
"YY", PauliOperator("Y 0", 2.0), PauliOperator("Y 0", 2.0), PauliOperator("I 0", 4.0)),
PauliTestParam(
"YZ", PauliOperator("Y 0", 2.0), PauliOperator("Z 0", 2.0), PauliOperator("X 0", 4.0i)),
PauliTestParam(
"ZX", PauliOperator("Z 0", 2.0), PauliOperator("X 0", 2.0), PauliOperator("Y 0", 4.0i)),
PauliTestParam("ZY",
PauliOperator("Z 0", 2.0),
PauliOperator("Y 0", 2.0),
PauliOperator("X 0", -4.0i)),
PauliTestParam(
"ZZ", PauliOperator("Z 0", 2.0), PauliOperator("Z 0", 2.0), PauliOperator("I 0", 4.0))),
testing::PrintToStringParamName());
INSTANTIATE_TEST_CASE_P(SinglePauli,
PauliOperatorMultiplyTest,
testing::Values(PauliTestParam("XX",
PauliOperator<double>("X 0", 2.0),
PauliOperator<double>("X 0", 2.0),
PauliOperator<double>("I 0", 4.0)),
PauliTestParam("XY",
PauliOperator<double>("X 0", 2.0),
PauliOperator<double>("Y 0", 2.0),
PauliOperator<double>("Z 0", 4.0i)),
PauliTestParam("XZ",
PauliOperator<double>("X 0", 2.0),
PauliOperator<double>("Z 0", 2.0),
PauliOperator<double>("Y 0", -4.0i)),
PauliTestParam("YX",
PauliOperator<double>("Y 0", 2.0),
PauliOperator<double>("X 0", 2.0),
PauliOperator<double>("Z 0", -4.0i)),
PauliTestParam("YY",
PauliOperator<double>("Y 0", 2.0),
PauliOperator<double>("Y 0", 2.0),
PauliOperator<double>("I 0", 4.0)),
PauliTestParam("YZ",
PauliOperator<double>("Y 0", 2.0),
PauliOperator<double>("Z 0", 2.0),
PauliOperator<double>("X 0", 4.0i)),
PauliTestParam("ZX",
PauliOperator<double>("Z 0", 2.0),
PauliOperator<double>("X 0", 2.0),
PauliOperator<double>("Y 0", 4.0i)),
PauliTestParam("ZY",
PauliOperator<double>("Z 0", 2.0),
PauliOperator<double>("Y 0", 2.0),
PauliOperator<double>("X 0", -4.0i)),
PauliTestParam("ZZ",
PauliOperator<double>("Z 0", 2.0),
PauliOperator<double>("Z 0", 2.0),
PauliOperator<double>("I 0", 4.0))),
testing::PrintToStringParamName());

INSTANTIATE_TEST_CASE_P(MultiPauli,
PauliOperatorMultiplyTest,
testing::Values(PauliTestParam("X_Y",
PauliOperator("X 0", 2.0),
PauliOperator("Y 1", 2.0),
PauliOperator("X 0 Y 1", 4.0)),
PauliOperator<double>("X 0", 2.0),
PauliOperator<double>("Y 1", 2.0),
PauliOperator<double>("X 0 Y 1", 4.0)),
PauliTestParam("XY_YX",
PauliOperator("X 0 Y 1", 2.0),
PauliOperator("Y 0 X 1", 2.0),
PauliOperator("Z 0 Z 1", 4.0))),
PauliOperator<double>("X 0 Y 1", 2.0),
PauliOperator<double>("Y 0 X 1", 2.0),
PauliOperator<double>("Z 0 Z 1", 4.0))),
testing::PrintToStringParamName());

// 並列化した場合でも、計算結果のindexの順序が保たれることを確認する
Expand All @@ -170,24 +180,24 @@ INSTANTIATE_TEST_CASE_P(
}
}

PauliOperator expected = PauliOperator(pauli_string_x, coef * coef);
PauliOperator pauli_y = PauliOperator(pauli_string_y, coef);
PauliOperator pauli_z = PauliOperator(pauli_string_z, coef);
PauliOperator<double> expected = PauliOperator<double>(pauli_string_x, coef * coef);
PauliOperator<double> pauli_y = PauliOperator<double>(pauli_string_y, coef);
PauliOperator<double> pauli_z = PauliOperator<double>(pauli_string_z, coef);

return testing::Values(PauliTestParam("Z_Y", pauli_z, pauli_y, expected));
}(),
testing::PrintToStringParamName());

TEST(PauliOperatorTest, ApplyToStateTest) {
const std::uint64_t n_qubits = 3;
StateVector state_vector(n_qubits);
StateVector<double> state_vector(n_qubits);
state_vector.load([n_qubits] {
std::vector<Complex> tmp(1 << n_qubits);
for (std::uint64_t i = 0; i < tmp.size(); ++i) tmp[i] = Complex(i, 0);
return tmp;
}());

PauliOperator op(0b001, 0b010, Complex(2));
PauliOperator<double> op(0b001, 0b010, Complex(2));
op.apply_to_state(state_vector);
std::vector<Complex> expected = {2, 0, -6, -4, 10, 8, -14, -12};
ASSERT_EQ(state_vector.get_amplitudes(), expected);
Expand Down
Loading

0 comments on commit 32abd04

Please sign in to comment.