From ac2197c721efb5f84a3b4debaa5d030ba055c1c5 Mon Sep 17 00:00:00 2001 From: gandalfr-KY Date: Fri, 24 Jan 2025 03:12:04 +0000 Subject: [PATCH] fix statevector test --- include/scaluq/util/utility.hpp | 20 +- src/operator/operator.cpp | 8 +- src/state/state_vector.cpp | 26 +- src/state/state_vector_batched.cpp | 12 +- src/util/utility.cpp | 31 -- tests/state/state_vector_test.cpp | 483 ++++++++++++----------------- 6 files changed, 241 insertions(+), 339 deletions(-) diff --git a/include/scaluq/util/utility.hpp b/include/scaluq/util/utility.hpp index c21d06a..ffbc0ad 100644 --- a/include/scaluq/util/utility.hpp +++ b/include/scaluq/util/utility.hpp @@ -135,12 +135,24 @@ inline internal::ComplexMatrix get_expanded_matrix( } // Host std::vector を Device Kokkos::View に変換する関数 -template -Kokkos::View convert_host_vector_to_device_view(const std::vector& vec); +template +Kokkos::View convert_vector_to_view(const std::vector& vec) { + Kokkos::View> host_view( + vec.data(), vec.size()); + Kokkos::View device_view("device_view", vec.size()); + Kokkos::deep_copy(device_view, host_view); + return device_view; +} // Device Kokkos::View を Host std::vector に変換する関数 -template -std::vector convert_device_view_to_host_vector(const Kokkos::View& device_view); +template +std::vector convert_view_to_vector(const Kokkos::View& device_view) { + std::vector host_vector(device_view.extent(0)); + Kokkos::View> host_view( + host_vector.data(), host_vector.size()); + Kokkos::deep_copy(host_view, device_view); + return host_vector; +} // Device Kokkos::View を Host std::vector に変換する関数 template diff --git a/src/operator/operator.cpp b/src/operator/operator.cpp index e7f5548..e752cfa 100644 --- a/src/operator/operator.cpp +++ b/src/operator/operator.cpp @@ -183,11 +183,9 @@ Complex Operator::get_transition_amplitude( _terms.begin(), _terms.end(), coefs_vector.begin(), [](const PauliOperator& pauli) { return pauli._ptr->_coef; }); - Kokkos::View bmasks = - internal::convert_host_vector_to_device_view(bmasks_vector); - Kokkos::View pmasks = - internal::convert_host_vector_to_device_view(pmasks_vector); - Kokkos::View*> coefs = internal::convert_host_vector_to_device_view(coefs_vector); + auto bmasks = internal::convert_vector_to_view(bmasks_vector); + auto pmasks = internal::convert_vector_to_view(pmasks_vector); + auto coefs = internal::convert_vector_to_view, Sp>(coefs_vector); std::uint64_t dim = state_vector_bra.dim(); Complex res; Kokkos::parallel_reduce( diff --git a/src/state/state_vector.cpp b/src/state/state_vector.cpp index 495f603..a481312 100644 --- a/src/state/state_vector.cpp +++ b/src/state/state_vector.cpp @@ -65,7 +65,7 @@ void StateVector::set_Haar_random_state(std::uint64_t n_qubits, std::uin FLOAT_AND_SPACE(Fp, Sp) [[nodiscard]] std::vector> StateVector::get_amplitudes() const { if constexpr (std::is_same_v) { - return internal::convert_device_view_to_host_vector(_raw); + return internal::convert_view_to_vector(_raw); } else { return std::vector>(_raw.data(), _raw.data() + _raw.size()); } @@ -132,8 +132,8 @@ Fp StateVector::get_marginal_probability( } Fp sum = 0.; - auto d_target_index = internal::convert_host_vector_to_device_view(target_index); - auto d_target_value = internal::convert_host_vector_to_device_view(target_value); + auto d_target_index = internal::convert_vector_to_view(target_index); + auto d_target_value = internal::convert_vector_to_view(target_value); Kokkos::parallel_reduce( "marginal_prob", @@ -169,24 +169,24 @@ Fp StateVector::get_entropy() const { FLOAT_AND_SPACE(Fp, Sp) void StateVector::add_state_vector_with_coef(ComplexType coef, const StateVector& state) { Kokkos::parallel_for( - Kokkos::RangePolicy(0, this->_dim >> 1), + Kokkos::RangePolicy(0, this->_dim), KOKKOS_CLASS_LAMBDA(std::uint64_t i) { this->_raw[i] += coef * state._raw[i]; }); Kokkos::fence(); } FLOAT_AND_SPACE(Fp, Sp) void StateVector::multiply_coef(ComplexType coef) { Kokkos::parallel_for( - Kokkos::RangePolicy(0, this->_dim >> 1), + Kokkos::RangePolicy(0, this->_dim), KOKKOS_CLASS_LAMBDA(std::uint64_t i) { this->_raw[i] *= coef; }); Kokkos::fence(); } FLOAT_AND_SPACE(Fp, Sp) std::vector StateVector::sampling(std::uint64_t sampling_count, std::uint64_t seed) const { - Kokkos::View stacked_prob("prob", _dim + 1); + Kokkos::View stacked_prob("prob", _dim + 1); Kokkos::parallel_scan( "compute_stacked_prob", - Kokkos::RangePolicy(0, this->_dim >> 1), + Kokkos::RangePolicy(0, this->_dim), KOKKOS_CLASS_LAMBDA(std::uint64_t i, Fp & update, const bool final) { update += internal::squared_norm(this->_raw[i]); if (final) { @@ -194,8 +194,8 @@ std::vector StateVector::sampling(std::uint64_t sampling_ } }); - Kokkos::View result(Kokkos::ViewAllocateWithoutInitializing("result"), - sampling_count); + Kokkos::View result(Kokkos::ViewAllocateWithoutInitializing("result"), + sampling_count); Kokkos::Random_XorShift64_Pool rand_pool(seed); Kokkos::parallel_for( Kokkos::RangePolicy(0, sampling_count), KOKKOS_LAMBDA(std::uint64_t i) { @@ -214,7 +214,7 @@ std::vector StateVector::sampling(std::uint64_t sampling_ rand_pool.free_state(rand_gen); }); Kokkos::fence(); - return internal::convert_device_view_to_host_vector(result); + return internal::convert_view_to_vector(result); } FLOAT_AND_SPACE(Fp, Sp) void StateVector::load(const std::vector>& other) { @@ -223,11 +223,7 @@ void StateVector::load(const std::vector>& other) { "Error: StateVector::load(const vector&): invalid " "length of state"); } - if constexpr (std::is_same_v) { - _raw = internal::convert_host_vector_to_device_view(other); - } else { - std::copy(other.begin(), other.end(), _raw.data()); - } + _raw = internal::convert_vector_to_view, Sp>(other); } FLOAT_AND_SPACE(Fp, Sp) StateVector StateVector::copy() const { diff --git a/src/state/state_vector_batched.cpp b/src/state/state_vector_batched.cpp index 2ca0323..615d5d7 100644 --- a/src/state/state_vector_batched.cpp +++ b/src/state/state_vector_batched.cpp @@ -184,7 +184,7 @@ std::vector StateVectorBatched::get_squared_norm() const { Kokkos::single(Kokkos::PerTeam(team), [&] { norms[batch_id] = nrm; }); }); Kokkos::fence(); - return internal::convert_device_view_to_host_vector(norms); + return internal::convert_view_to_vector(norms); } FLOAT_AND_SPACE(Fp, Sp) @@ -234,7 +234,7 @@ std::vector StateVectorBatched::get_zero_probability( Kokkos::single(Kokkos::PerTeam(team), [&] { probs[batch_id] = sum; }); }); Kokkos::fence(); - return internal::convert_device_view_to_host_vector(probs); + return internal::convert_view_to_vector(probs); } FLOAT_AND_SPACE(Fp, Sp) @@ -262,8 +262,8 @@ std::vector StateVectorBatched::get_marginal_probability( } } - auto target_index_d = internal::convert_host_vector_to_device_view(target_index); - auto target_value_d = internal::convert_host_vector_to_device_view(target_value); + auto target_index_d = internal::convert_vector_to_view(target_index); + auto target_value_d = internal::convert_vector_to_view(target_value); Kokkos::View probs("probs", _batch_size); Kokkos::parallel_for( Kokkos::TeamPolicy(Sp(), _batch_size, Kokkos::AUTO), @@ -286,7 +286,7 @@ std::vector StateVectorBatched::get_marginal_probability( Kokkos::single(Kokkos::PerTeam(team), [&] { probs[batch_id] = sum; }); }); Kokkos::fence(); - return internal::convert_device_view_to_host_vector(probs); + return internal::convert_view_to_vector(probs); } FLOAT_AND_SPACE(Fp, Sp) @@ -310,7 +310,7 @@ std::vector StateVectorBatched::get_entropy() const { Kokkos::single(Kokkos::PerTeam(team), [&] { ents[batch_id] = sum; }); }); Kokkos::fence(); - return internal::convert_device_view_to_host_vector(ents); + return internal::convert_view_to_vector(ents); } FLOAT_AND_SPACE(Fp, Sp) diff --git a/src/util/utility.cpp b/src/util/utility.cpp index cda97a7..d3b012e 100644 --- a/src/util/utility.cpp +++ b/src/util/utility.cpp @@ -4,37 +4,6 @@ namespace scaluq { namespace internal { -// Host std::vector を Device Kokkos::View に変換する関数 -template -Kokkos::View convert_host_vector_to_device_view(const std::vector& vec) { - Kokkos::View> host_view( - vec.data(), vec.size()); - Kokkos::View device_view("device_view", vec.size()); - Kokkos::deep_copy(device_view, host_view); - return device_view; -} -#define FUNC_MACRO(T) \ - template Kokkos::View convert_host_vector_to_device_view(const std::vector&); -CALL_MACRO_FOR_FLOAT(FUNC_MACRO) -CALL_MACRO_FOR_COMPLEX(FUNC_MACRO) -CALL_MACRO_FOR_UINT(FUNC_MACRO) -#undef FUNC_MACRO - -// Device Kokkos::View を Host std::vector に変換する関数 -template -std::vector convert_device_view_to_host_vector(const Kokkos::View& device_view) { - std::vector host_vector(device_view.extent(0)); - Kokkos::View> host_view( - host_vector.data(), host_vector.size()); - Kokkos::deep_copy(host_view, device_view); - return host_vector; -} -#define FUNC_MACRO(T) \ - template std::vector convert_device_view_to_host_vector(const Kokkos::View&); -CALL_MACRO_FOR_FLOAT(FUNC_MACRO) -CALL_MACRO_FOR_COMPLEX(FUNC_MACRO) -CALL_MACRO_FOR_UINT(FUNC_MACRO) -#undef FUNC_MACRO // Device Kokkos::View を Host std::vector に変換する関数 template diff --git a/tests/state/state_vector_test.cpp b/tests/state/state_vector_test.cpp index 03aba81..b56801d 100644 --- a/tests/state/state_vector_test.cpp +++ b/tests/state/state_vector_test.cpp @@ -5,320 +5,247 @@ #include "../test_environment.hpp" #include "../util/util.hpp" -using CComplex = std::complex; - using namespace scaluq; -#define TEMPLATE(Fp, Sp) template - -TEMPLATE(Fp, Sp) -void TestHaarRandomStateNorm() { - const int n_tries = 6; - for (int n = 1; n <= n_tries; n++) { - const auto state = StateVector::Haar_random_state(n); - ASSERT_NEAR(state.get_squared_norm(), 1.0, eps); +#define FLOAT_AND_SPACE(Fp, Sp) template +#define EXECUTE_TEST(Name, arg) \ + TEST(StateVectorTest, Name) { \ + Test##Name(arg); \ + Test##Name(arg); \ + Test##Name(arg); \ + Test##Name(arg); \ } -} -TEST(StateVectorTest, HaarRandomStateNorm) { - TestHaarRandomStateNorm(); - TestHaarRandomStateNorm(); - TestHaarRandomStateNorm(); - TestHaarRandomStateNorm(); +FLOAT_AND_SPACE(Fp, Sp) +void TestHaarRandomStateNorm(std::uint32_t n) { + auto state = StateVector::Haar_random_state(n); + ASSERT_NEAR(state.get_squared_norm(), 1.0, eps); } +EXECUTE_TEST(HaarRandomStateNorm, 6); -TEMPLATE(Fp, Sp) -void TestOperationAtIndex() { - auto state = StateVector::Haar_random_state(6); +FLOAT_AND_SPACE(Fp, Sp) +void TestOperationAtIndex(std::uint32_t n) { + auto state = StateVector::Haar_random_state(n); for (std::uint64_t i = 0; i < state.dim(); ++i) { state.set_amplitude_at(i, 1); ASSERT_NEAR(state.get_amplitude_at(i).real(), 1.0, eps); ASSERT_NEAR(state.get_amplitude_at(i).imag(), 0.0, eps); } } - -TEST(StateVectorTest, OperationAtIndex) { - TestOperationAtIndex(); - TestOperationAtIndex(); - TestOperationAtIndex(); - TestOperationAtIndex(); +EXECUTE_TEST(OperationAtIndex, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestCopyState(std::uint32_t n) { + const auto state = StateVector::Haar_random_state(n); + StateVector state_cp = state.copy(); + auto vec1 = state.get_amplitudes(); + auto vec2 = state_cp.get_amplitudes(); + ASSERT_EQ(vec1, vec2); } +EXECUTE_TEST(CopyState, 6); -TEST(StateVectorTest, CopyState) { - { - const int n = 5; - const auto state = StateVector::Haar_random_state(n); - StateVector state_cp = state.copy(); - auto vec1 = state.get_amplitudes(); - auto vec2 = state_cp.get_amplitudes(); - ASSERT_EQ(vec1, vec2); - } - { - const int n = 5; - const auto state = StateVector::Haar_random_state(n); - StateVector state_cp = state.copy(); - auto vec1 = state.get_amplitudes(); - auto vec2 = state_cp.get_amplitudes(); - ASSERT_EQ(vec1, vec2); +FLOAT_AND_SPACE(Fp, Sp) +void TestZeroNormState(std::uint32_t n) { + auto state = StateVector::Haar_random_state(n); + state.set_zero_norm_state(); + auto state_cp = state.get_amplitudes(); + for (std::uint64_t i = 0; i < state.dim(); ++i) { + ASSERT_EQ((StdComplex)state_cp[i], StdComplex(0, 0)); } } +EXECUTE_TEST(ZeroNormState, 6); -TEST(StateVectorTest, ZeroNormState) { - { - const std::uint64_t n = 5; - auto state = StateVector::Haar_random_state(n); - state.set_zero_norm_state(); - auto state_cp = state.get_amplitudes(); +FLOAT_AND_SPACE(Fp, Sp) +void TestComputationalBasisState(std::uint32_t n) { + auto state = StateVector::Haar_random_state(n); + state.set_computational_basis(31); + auto state_cp = state.get_amplitudes(); - for (std::uint64_t i = 0; i < state.dim(); ++i) { - ASSERT_EQ((CComplex)state_cp[i], CComplex(0, 0)); + for (std::uint64_t i = 0; i < state.dim(); ++i) { + if (i == 31) { + ASSERT_EQ((StdComplex)state_cp[i], StdComplex(1, 0)); + } else { + ASSERT_EQ((StdComplex)state_cp[i], StdComplex(0, 0)); } } - { - const std::uint64_t n = 5; - auto state = StateVector::Haar_random_state(n); - state.set_zero_norm_state(); - auto state_cp = state.get_amplitudes(); - - for (std::uint64_t i = 0; i < state.dim(); ++i) { - ASSERT_EQ((CComplex)state_cp[i], CComplex(0, 0)); - } +} +EXECUTE_TEST(ComputationalBasisState, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestHaarRandomStateSameSeed(std::uint32_t n) { + for (std::uint64_t i = 0; i < 3; ++i) { + auto state1 = StateVector::Haar_random_state(n, i), + state2 = StateVector::Haar_random_state(n, i); + ASSERT_TRUE(same_state(state1, state2)); } } +EXECUTE_TEST(HaarRandomStateSameSeed, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestHaarRandomStateWithoutSeed(std::uint32_t n) { + for (std::uint64_t i = 0; i < 3; ++i) { + auto state1 = StateVector::Haar_random_state(n, 2 * i), + state2 = StateVector::Haar_random_state(n, 2 * i + 1); + ASSERT_FALSE(same_state(state1, state2)); + } +} +EXECUTE_TEST(HaarRandomStateWithoutSeed, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestAddStateWithCoef(std::uint32_t n) { + const StdComplex coef(2.5, 1.3); + auto state1 = StateVector::Haar_random_state(n); + auto state2 = StateVector::Haar_random_state(n); + auto vec1 = state1.get_amplitudes(); + auto vec2 = state2.get_amplitudes(); + + state1.add_state_vector_with_coef(coef, state2); + auto new_vec = state1.get_amplitudes(); + + for (std::uint64_t i = 0; i < state1.dim(); ++i) { + StdComplex res = new_vec[i], + val = (StdComplex)vec1[i] + coef * (StdComplex)vec2[i]; + ASSERT_NEAR(res.real(), val.real(), eps); + ASSERT_NEAR(res.imag(), val.imag(), eps); + } +} +EXECUTE_TEST(AddStateWithCoef, 6); -TEST(StateVectorTest, ComputationalBasisState) { - { - const std::uint64_t n = 5; - auto state = StateVector::Haar_random_state(n); - state.set_computational_basis(31); - auto state_cp = state.get_amplitudes(); +FLOAT_AND_SPACE(Fp, Sp) +void TestMultiplyCoef(std::uint32_t n) { + const StdComplex coef(0.5, 0.2); + auto state = StateVector::Haar_random_state(n); + auto vec = state.get_amplitudes(); + state.multiply_coef(coef); + auto new_vec = state.get_amplitudes(); - for (std::uint64_t i = 0; i < state.dim(); ++i) { - if (i == 31) { - ASSERT_EQ((CComplex)state_cp[i], CComplex(1, 0)); - } else { - ASSERT_EQ((CComplex)state_cp[i], CComplex(0, 0)); + for (std::uint64_t i = 0; i < state.dim(); ++i) { + StdComplex res = new_vec[i], val = coef * (StdComplex)vec[i]; + ASSERT_NEAR(res.real(), val.real(), eps); + ASSERT_NEAR(res.imag(), val.imag(), eps); + } +} +EXECUTE_TEST(MultiplyCoef, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestGetZeroProbability(std::uint32_t n) { + std::uint32_t dim = 1 << n; + std::vector> vec(dim); + std::vector zero_prob(n, 0); + double denom = (double)(dim - 1) * dim / 2; + for (std::uint32_t i = 0; i < vec.size(); ++i) { + vec[i] = std::sqrt(i); + for (std::uint32_t b = 0; b < n; ++b) { + if (((i >> b) & 1) == 0) { + zero_prob[b] += i / denom; } } } - { - const std::uint64_t n = 5; - auto state = StateVector::Haar_random_state(n); - state.set_computational_basis(31); - auto state_cp = state.get_amplitudes(); + StateVector state(n); + state.load(vec); + state.normalize(); + for (std::uint64_t i = 0; i < n; ++i) { + ASSERT_NEAR(zero_prob[i], state.get_zero_probability(i), eps); + } +} +EXECUTE_TEST(GetZeroProbability, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestEntropyCalculation(std::uint32_t n) { + const std::uint64_t dim = 1ULL << n; + const std::uint64_t max_repeat = 10; - for (std::uint64_t i = 0; i < state.dim(); ++i) { - if (i == 31) { - ASSERT_EQ((CComplex)state_cp[i], CComplex(1, 0)); - } else { - ASSERT_EQ((CComplex)state_cp[i], CComplex(0, 0)); + for (std::uint64_t rep = 0; rep < max_repeat; ++rep) { + auto state = StateVector::Haar_random_state(n); + auto state_cp = state.get_amplitudes(); + ASSERT_NEAR(state.get_squared_norm(), 1, eps); + Eigen::Matrix, -1, 1> test_state(dim); + for (std::uint64_t i = 0; i < dim; ++i) test_state[i] = (StdComplex)state_cp[i]; + + for (std::uint64_t target = 0; target < n; ++target) { + Fp ent = 0; + for (std::uint64_t ind = 0; ind < dim; ++ind) { + StdComplex z = test_state[ind]; + Fp prob = z.real() * z.real() + z.imag() * z.imag(); + ent += -prob * std::log2(prob); } + ASSERT_NEAR(ent, state.get_entropy(), eps); } } } +EXECUTE_TEST(EntropyCalculation, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestGetMarginalProbability(std::uint32_t n) { + const std::uint64_t dim = 1 << n; + auto state = StateVector::Haar_random_state(n); + auto state_cp = state.get_amplitudes(); + std::vector probs(4, 0); + for (std::uint64_t i = 0; i < dim; ++i) { + probs[i & 0b11] += internal::squared_norm(state_cp[i]); + } -TEST(StateVectorTest, HaarRandomStateSameSeed) { - { - const std::uint64_t n = 6, m = 5; - for (std::uint64_t i = 0; i < m; ++i) { - auto state1 = StateVector::Haar_random_state(n, i), - state2 = StateVector::Haar_random_state(n, i); - ASSERT_TRUE(same_state(state1, state2)); + auto extend = [](std::vector v, std::int64_t n) { + while ((std::uint32_t)v.size() < n) v.push_back(StateVector::UNMEASURED); + return v; + }; + const std::uint64_t U = StateVector::UNMEASURED; + ASSERT_NEAR(state.get_marginal_probability(extend({0, 0}, n)), probs[0], eps); + ASSERT_NEAR(state.get_marginal_probability(extend({1, 0}, n)), probs[1], eps); + ASSERT_NEAR(state.get_marginal_probability(extend({0, 1}, n)), probs[2], eps); + ASSERT_NEAR(state.get_marginal_probability(extend({1, 1}, n)), probs[3], eps); + ASSERT_NEAR(state.get_marginal_probability(extend({0, U}, n)), probs[0] + probs[2], eps); + ASSERT_NEAR(state.get_marginal_probability(extend({1, U}, n)), probs[1] + probs[3], eps); + ASSERT_NEAR(state.get_marginal_probability(extend({U, 0}, n)), probs[0] + probs[1], eps); + ASSERT_NEAR(state.get_marginal_probability(extend({U, 1}, n)), probs[2] + probs[3], eps); + ASSERT_NEAR(state.get_marginal_probability(extend({U, U}, n)), 1, eps); +} +EXECUTE_TEST(GetMarginalProbability, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestSamplingSuperpositionState(std::uint32_t n) { + const std::uint64_t nshot = 65536; + const std::uint64_t test_count = 10; + std::uint64_t pass_count = 0; + for (std::uint64_t test_i = 0; test_i < test_count; test_i++) { + StateVector state(n); + state.set_computational_basis(0); + for (std::uint64_t i = 1; i <= 4; ++i) { + StateVector tmp_state(n); + tmp_state.set_computational_basis(i); + state.add_state_vector_with_coef(1 << i, tmp_state); } - } - { - const std::uint64_t n = 6, m = 5; - for (std::uint64_t i = 0; i < m; ++i) { - auto state1 = StateVector::Haar_random_state(n, i), - state2 = StateVector::Haar_random_state(n, i); - ASSERT_TRUE(same_state(state1, state2)); + state.normalize(); + std::vector res = state.sampling(nshot); + + std::array cnt = {}; + for (std::uint64_t i = 0; i < nshot; ++i) { + ASSERT_GE(res[i], 0); + ASSERT_LE(res[i], 4); + cnt[res[i]] += 1; } - } -} - -TEST(StateVectorTest, HaarRandomStateWithoutSeed) { - { - const std::uint64_t n = 6, m = 5; - for (std::uint64_t i = 0; i < m; ++i) { - auto state1 = StateVector::Haar_random_state(n, 2 * i), - state2 = StateVector::Haar_random_state(n, 2 * i + 1); - ASSERT_FALSE(same_state(state1, state2)); + bool pass = true; + for (std::uint64_t i = 0; i < 4; i++) { + std::string err_message = _CHECK_GT(cnt[i + 1], cnt[i]); + if (err_message != "") { + pass = false; + std::cerr << err_message; + } } + if (pass) pass_count++; } - { - const std::uint64_t n = 6, m = 5; - for (std::uint64_t i = 0; i < m; ++i) { - auto state1 = StateVector::Haar_random_state(n, 2 * i), - state2 = StateVector::Haar_random_state(n, 2 * i + 1); - ASSERT_FALSE(same_state(state1, state2)); - } + ASSERT_GE(pass_count, test_count - 1); +} +EXECUTE_TEST(SamplingSuperpositionState, 6); + +FLOAT_AND_SPACE(Fp, Sp) +void TestSamplingComputationalBasis(std::uint32_t n) { + const std::uint64_t nshot = 1024; + StateVector state(n); + state.set_computational_basis(6); + auto res = state.sampling(nshot); + for (std::uint64_t i = 0; i < nshot; ++i) { + ASSERT_TRUE(res[i] == 6); } } - -// TEST(StateVectorTest, AddState) { -// const std::uint64_t n = 6; -// StateVector state1(StateVector::Haar_random_state(n)); -// StateVector state2(StateVector::Haar_random_state(n)); -// auto vec1 = state1.get_amplitudes(); -// auto vec2 = state2.get_amplitudes(); -// state1.add_state_vector_with_coef(1, state2); -// auto new_vec = state1.get_amplitudes(); - -// for (std::uint64_t i = 0; i < state1.dim(); ++i) { -// CComplex res = new_vec[i], val = (CComplex)vec1[i] + (CComplex)vec2[i]; -// ASSERT_NEAR(res.real(), val.real(), eps); -// ASSERT_NEAR(res.imag(), val.imag(), eps); -// } -// } - -// TEST(StateVectorTest, AddStateWithCoef) { -// const CComplex coef(2.5, 1.3); -// const std::uint64_t n = 6; -// StateVector state1(StateVector::Haar_random_state(n)); -// StateVector state2(StateVector::Haar_random_state(n)); -// auto vec1 = state1.get_amplitudes(); -// auto vec2 = state2.get_amplitudes(); - -// state1.add_state_vector_with_coef(coef, state2); -// auto new_vec = state1.get_amplitudes(); - -// for (std::uint64_t i = 0; i < state1.dim(); ++i) { -// CComplex res = new_vec[i], val = (CComplex)vec1[i] + coef * (CComplex)vec2[i]; -// ASSERT_NEAR(res.real(), val.real(), eps); -// ASSERT_NEAR(res.imag(), val.imag(), eps); -// } -// } - -// TEST(StateVectorTest, MultiplyCoef) { -// const std::uint64_t n = 6; -// const CComplex coef(0.5, 0.2); - -// StateVector state(StateVector::Haar_random_state(n)); -// auto vec = state.get_amplitudes(); -// state.multiply_coef(coef); -// auto new_vec = state.get_amplitudes(); - -// for (std::uint64_t i = 0; i < state.dim(); ++i) { -// CComplex res = new_vec[i], val = coef * (CComplex)vec[i]; -// ASSERT_NEAR(res.real(), val.real(), eps); -// ASSERT_NEAR(res.imag(), val.imag(), eps); -// } -// } - -// TEST(StateVectorTest, GetZeroProbability) { -// const std::uint64_t n = 6; -// StateVector state(n); -// state.set_computational_basis(1); -// for (std::uint64_t i = 2; i <= 10; ++i) { -// StateVector tmp_state(n); -// tmp_state.set_computational_basis(i); -// state.add_state_vector_with_coef(std::sqrt(i), tmp_state); -// } -// state.normalize(); -// ASSERT_NEAR(state.get_zero_probability(0), 30.0 / 55.0, eps); -// ASSERT_NEAR(state.get_zero_probability(1), 27.0 / 55.0, eps); -// ASSERT_NEAR(state.get_zero_probability(2), 33.0 / 55.0, eps); -// ASSERT_NEAR(state.get_zero_probability(3), 28.0 / 55.0, eps); -// } - -// TEST(StateVectorTest, EntropyCalculation) { -// const std::uint64_t n = 6; -// const std::uint64_t dim = 1ULL << n; -// const std::uint64_t max_repeat = 10; - -// StateVector state(n); -// for (std::uint64_t rep = 0; rep < max_repeat; ++rep) { -// state = StateVector::Haar_random_state(n); -// auto state_cp = state.get_amplitudes(); -// ASSERT_NEAR(state.get_squared_norm(), 1, eps); -// Eigen::VectorXcd test_state(dim); -// for (std::uint64_t i = 0; i < dim; ++i) test_state[i] = (CComplex)state_cp[i]; - -// for (std::uint64_t target = 0; target < n; ++target) { -// double ent = 0; -// for (std::uint64_t ind = 0; ind < dim; ++ind) { -// CComplex z = test_state[ind]; -// double prob = z.real() * z.real() + z.imag() * z.imag(); -// if (prob > eps) ent += -prob * std::log2(prob); -// } -// ASSERT_NEAR(ent, state.get_entropy(), eps); -// } -// } -// } - -// TEST(StateVectorTest, GetMarginalProbability) { -// const std::uint64_t n = 2; -// const std::uint64_t dim = 1 << n; -// StateVector state(StateVector::Haar_random_state(n)); -// auto state_cp = state.get_amplitudes(); -// std::vector probs; -// for (std::uint64_t i = 0; i < dim; ++i) { -// probs.push_back(internal::squared_norm(state_cp[i])); -// } -// ASSERT_NEAR(state.get_marginal_probability({0, 0}), probs[0], eps); -// ASSERT_NEAR(state.get_marginal_probability({1, 0}), probs[1], eps); -// ASSERT_NEAR(state.get_marginal_probability({0, 1}), probs[2], eps); -// ASSERT_NEAR(state.get_marginal_probability({1, 1}), probs[3], eps); -// ASSERT_NEAR(state.get_marginal_probability({0, StateVector::UNMEASURED}), -// probs[0] + probs[2], -// eps); -// ASSERT_NEAR(state.get_marginal_probability({1, StateVector::UNMEASURED}), -// probs[1] + probs[3], -// eps); -// ASSERT_NEAR(state.get_marginal_probability({StateVector::UNMEASURED, 0}), -// probs[0] + probs[1], -// eps); -// ASSERT_NEAR(state.get_marginal_probability({StateVector::UNMEASURED, 1}), -// probs[2] + probs[3], -// eps); -// ASSERT_NEAR(state.get_marginal_probability( -// {StateVector::UNMEASURED, StateVector::UNMEASURED}), -// 1., -// eps); -// } - -// TEST(StateVectorTest, SamplingSuperpositionState) { -// const std::uint64_t n = 6; -// const std::uint64_t nshot = 65536; -// const std::uint64_t test_count = 10; -// std::uint64_t pass_count = 0; -// for (std::uint64_t test_i = 0; test_i < test_count; test_i++) { -// StateVector state(n); -// state.set_computational_basis(0); -// for (std::uint64_t i = 1; i <= 4; ++i) { -// StateVector tmp_state(n); -// tmp_state.set_computational_basis(i); -// state.add_state_vector_with_coef(1 << i, tmp_state); -// } -// state.normalize(); -// std::vector res = state.sampling(nshot); - -// std::array cnt = {}; -// for (std::uint64_t i = 0; i < nshot; ++i) { -// ASSERT_GE(res[i], 0); -// ASSERT_LE(res[i], 4); -// cnt[res[i]] += 1; -// } -// bool pass = true; -// for (std::uint64_t i = 0; i < 4; i++) { -// std::string err_message = _CHECK_GT(cnt[i + 1], cnt[i]); -// if (err_message != "") { -// pass = false; -// std::cerr << err_message; -// } -// } -// if (pass) pass_count++; -// } -// ASSERT_GE(pass_count, test_count - 1); -// } - -// TEST(StateVectorTest, SamplingComputationalBasis) { -// const std::uint64_t n = 7; -// const std::uint64_t nshot = 1024; -// StateVector state(n); -// state.set_computational_basis(100); -// auto res = state.sampling(nshot); -// for (std::uint64_t i = 0; i < nshot; ++i) { -// ASSERT_TRUE(res[i] == 100); -// } -// } +EXECUTE_TEST(SamplingComputationalBasis, 6);