mirror of https://github.com/intel/intel-qs.git
244 lines
9.6 KiB
C++
244 lines
9.6 KiB
C++
#ifndef CHUNKING_COMMUNICATION_TEST_HPP
|
|
#define CHUNKING_COMMUNICATION_TEST_HPP
|
|
|
|
#include "../../include/qureg.hpp"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Test fixture class.
|
|
|
|
class ChunkingCommunicationTest : public ::testing::Test
|
|
{
|
|
protected:
|
|
|
|
ChunkingCommunicationTest()
|
|
{ }
|
|
|
|
// just after the 'constructor'
|
|
void SetUp() override
|
|
{
|
|
// All tests are skipped if the rank is dummy.
|
|
if (qhipster::mpi::Environment::IsUsefulRank() == false)
|
|
GTEST_SKIP();
|
|
|
|
// All tests are skipped if the 14-qubit state is distributed in more than 2^11 ranks.
|
|
// In fact the MPI version needs to allocate eighth-the-local-storage for communication.
|
|
// If the local storage is a eight amplitudes, this cannot be further divided.
|
|
if (qhipster::mpi::Environment::GetStateSize() > 2048)
|
|
GTEST_SKIP();
|
|
}
|
|
|
|
const std::size_t num_qubits_ = 14;
|
|
double accepted_error_ = 1e-15;
|
|
double accepted_error_loose_ = 1e-12;
|
|
|
|
unsigned nprocs_ = qhipster::mpi::Environment::GetStateSize();
|
|
unsigned log2_nprocs_ = qhipster::ilog2( qhipster::floor_power_of_two(nprocs_));
|
|
std::size_t local_size_ = std::size_t(1UL << std::size_t(num_qubits_ - log2_nprocs_));
|
|
std::size_t tmp_spacesize_half_ = local_size_/2UL;
|
|
std::size_t tmp_spacesize_quarter_ = local_size_/4UL;
|
|
std::size_t tmp_spacesize_eighth_ = local_size_/8UL;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// Test macros:
|
|
|
|
TEST_F(ChunkingCommunicationTest, Initialization)
|
|
{
|
|
// Consider 3 different sizes for the tmp_spacesize:
|
|
// 1/2 (default with MPI), 1/4 , 1/8 of the local_size.
|
|
QubitRegister<ComplexDP> psi_half (num_qubits_, "base", 1, tmp_spacesize_half_ );
|
|
QubitRegister<ComplexDP> psi_quarter (num_qubits_, "base", 10200, tmp_spacesize_quarter_);
|
|
QubitRegister<ComplexDP> psi_eighth (num_qubits_, "base", 5003, tmp_spacesize_eighth_ );
|
|
|
|
// Test the norm.
|
|
ASSERT_LE( std::abs(psi_half.ComputeNorm()-1) , accepted_error_ );
|
|
ASSERT_LE( std::abs(psi_quarter.ComputeNorm()-1) , accepted_error_ );
|
|
ASSERT_LE( std::abs(psi_eighth.ComputeNorm()-1) , accepted_error_ );
|
|
|
|
ComplexDP amplitude;
|
|
// Test the only non-zero entry.
|
|
ASSERT_DOUBLE_EQ(psi_half.GetGlobalAmplitude(1).real(), 1.);
|
|
ASSERT_DOUBLE_EQ(psi_quarter.GetGlobalAmplitude(10200).real(), 1.);
|
|
ASSERT_DOUBLE_EQ(psi_eighth.GetGlobalAmplitude(5003).real(), 1.);
|
|
|
|
// Apply gates such that |psi_half> = |+++...+>
|
|
psi_half.ApplyPauliX(0);
|
|
for (unsigned qubit=0; qubit<num_qubits_; ++qubit)
|
|
psi_half.ApplyHadamard(qubit);
|
|
// Verify overlap with a newly initialized state.
|
|
QubitRegister<ComplexDP> psi (num_qubits_, "++++", 0);
|
|
ASSERT_COMPLEX_NEAR(psi_half.ComputeOverlap(psi), ComplexDP(1,0), accepted_error_);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
TEST_F(ChunkingCommunicationTest, HadamardGate)
|
|
{
|
|
// Consider 3 different sizes for the tmp_spacesize:
|
|
// 1/2 (default with MPI), 1/4 , 1/8 of the local_size.
|
|
QubitRegister<ComplexDP> psi_half (num_qubits_, "base", 0, tmp_spacesize_half_ );
|
|
QubitRegister<ComplexDP> psi_quarter (num_qubits_, "base", 0, tmp_spacesize_quarter_);
|
|
QubitRegister<ComplexDP> psi_eighth (num_qubits_, "base", 0, tmp_spacesize_eighth_ );
|
|
|
|
// Test the norm.
|
|
ASSERT_LE( std::abs(psi_half.ComputeNorm()-1) , accepted_error_ );
|
|
ASSERT_LE( std::abs(psi_quarter.ComputeNorm()-1) , accepted_error_ );
|
|
ASSERT_LE( std::abs(psi_eighth.ComputeNorm()-1) , accepted_error_ );
|
|
|
|
// Apply Hadamard on all qubits.
|
|
for (unsigned qubit=0; qubit<num_qubits_; ++qubit)
|
|
{
|
|
psi_half.ApplyHadamard(qubit);
|
|
psi_quarter.ApplyHadamard(qubit);
|
|
psi_eighth.ApplyHadamard(qubit);
|
|
}
|
|
|
|
// Verify overlap.
|
|
ComplexDP overlap = {1,0};
|
|
ASSERT_COMPLEX_NEAR(psi_half.ComputeOverlap(psi_quarter), overlap, accepted_error_);
|
|
ASSERT_COMPLEX_NEAR(psi_half.ComputeOverlap(psi_eighth), overlap, accepted_error_);
|
|
ASSERT_COMPLEX_NEAR(psi_eighth.ComputeOverlap(psi_quarter), overlap, accepted_error_);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
TEST_F(ChunkingCommunicationTest, CustomGate)
|
|
{
|
|
// Consider 3 different sizes for the tmp_spacesize:
|
|
// 1/2 (default with MPI), 1/4 , 1/8 of the local_size.
|
|
QubitRegister<ComplexDP> psi_half (num_qubits_, "base", 0, tmp_spacesize_half_ );
|
|
QubitRegister<ComplexDP> psi_quarter (num_qubits_, "base", 0, tmp_spacesize_quarter_);
|
|
QubitRegister<ComplexDP> psi_eighth (num_qubits_, "base", 0, tmp_spacesize_eighth_ );
|
|
|
|
TM2x2<ComplexDP> G;
|
|
G(0, 0) = {0.592056606032915, 0.459533060553574};
|
|
G(0, 1) = {-0.314948020757856, -0.582328159830658};
|
|
G(1, 0) = {0.658235557641767, 0.070882241549507};
|
|
G(1, 1) = {0.649564427121402, 0.373855203932477};
|
|
|
|
// Apply custom gate on all qubits.
|
|
for (unsigned qubit=0; qubit<num_qubits_; ++qubit)
|
|
{
|
|
psi_half.Apply1QubitGate(qubit, G);
|
|
psi_quarter.Apply1QubitGate(qubit, G);
|
|
psi_eighth.Apply1QubitGate(qubit, G);
|
|
}
|
|
|
|
// Verify overlap.
|
|
ComplexDP overlap = {1,0};
|
|
ASSERT_COMPLEX_NEAR(psi_half.ComputeOverlap(psi_quarter), overlap, accepted_error_loose_);
|
|
ASSERT_COMPLEX_NEAR(psi_half.ComputeOverlap(psi_eighth), overlap, accepted_error_loose_);
|
|
ASSERT_COMPLEX_NEAR(psi_eighth.ComputeOverlap(psi_quarter), overlap, accepted_error_loose_);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
TEST_F(ChunkingCommunicationTest, CnotGate)
|
|
{
|
|
// Consider 3 different sizes for the tmp_spacesize:
|
|
// 1/2 (default with MPI), 1/4 , 1/8 of the local_size.
|
|
QubitRegister<ComplexDP> psi_half (num_qubits_, "base", 0, tmp_spacesize_half_ );
|
|
QubitRegister<ComplexDP> psi_quarter (num_qubits_, "base", 0, tmp_spacesize_quarter_);
|
|
QubitRegister<ComplexDP> psi_eighth (num_qubits_, "base", 0, tmp_spacesize_eighth_ );
|
|
|
|
// Apply CNOT on all (ordered) qubit-pairs for the highest 6 indices.
|
|
for (unsigned q0=num_qubits_-6; q0<num_qubits_; ++q0)
|
|
for (unsigned q1=q0+1; q1<num_qubits_; ++q1)
|
|
{
|
|
psi_half.ApplyCPauliX(q0, q1);
|
|
psi_half.ApplyCPauliX(q1, q0);
|
|
psi_quarter.ApplyCPauliX(q0, q1);
|
|
psi_quarter.ApplyCPauliX(q1, q0);
|
|
psi_eighth.ApplyCPauliX(q0, q1);
|
|
psi_eighth.ApplyCPauliX(q1, q0);
|
|
}
|
|
|
|
// Verify overlap.
|
|
ComplexDP overlap = {1,0};
|
|
ASSERT_COMPLEX_NEAR(psi_half.ComputeOverlap(psi_quarter), overlap, accepted_error_);
|
|
ASSERT_COMPLEX_NEAR(psi_half.ComputeOverlap(psi_eighth), overlap, accepted_error_);
|
|
ASSERT_COMPLEX_NEAR(psi_eighth.ComputeOverlap(psi_quarter), overlap, accepted_error_);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
/*
|
|
TEST_F(ChunkingCommunicationTest, InitializeRandomlyButSame)
|
|
{
|
|
// |psi> = |00>
|
|
QubitRegister<ComplexDP> psi (num_qubits_,"base",0);
|
|
// random number generator
|
|
std::size_t rng_seed = 7777;
|
|
qhipster::RandomNumberGenerator<double> rng;
|
|
rng.SetSeedStreamPtrs(rng_seed);
|
|
psi.SetRngPtr(&rng);
|
|
//
|
|
int num_states = qhipster::mpi::Environment::GetNumStates();
|
|
assert (num_states==1);
|
|
psi.Initialize("rand",num_states);
|
|
// |psi> = |rand>
|
|
|
|
// Initilize the copy: |copy> = |psi>
|
|
QubitRegister<ComplexDP> psi_copy (psi);
|
|
ASSERT_DOUBLE_EQ(psi_copy.MaxAbsDiff(psi), 0 );
|
|
ASSERT_DOUBLE_EQ(psi_copy.MaxL2NormDiff(psi), 0 );
|
|
//
|
|
// Reinitialize |copy> by generating its amplitudes.
|
|
qhipster::RandomNumberGenerator<double> rng_copy;
|
|
rng_copy.SetSeedStreamPtrs(rng_seed);
|
|
psi_copy.SetRngPtr(&rng_copy);
|
|
psi_copy.Initialize("rand",num_states);
|
|
ASSERT_DOUBLE_EQ(psi_copy.MaxAbsDiff(psi), 0 );
|
|
ASSERT_DOUBLE_EQ(psi_copy.MaxL2NormDiff(psi), 0 );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
TEST_F(ChunkingCommunicationTest, Hadamard)
|
|
{
|
|
QubitRegister<ComplexDP> psi_0 (num_qubits_,"base",0);
|
|
psi_0.ApplyHadamard(0);
|
|
// |psi_0> = |+0> = |q0=+> x |q1=0>
|
|
ASSERT_NEAR( psi_0.GetProbability(0), 0.5, accepted_error_ );
|
|
psi_0.ApplyPauliZ(0);
|
|
// |psi_0> = |-0> = |q0=-> x |q1=0>
|
|
ASSERT_NEAR( psi_0.GetProbability(0), 0.5, accepted_error_ );
|
|
psi_0.ApplyHadamard(0);
|
|
// |psi_0> = |10> = |q0=1> x |q1=0>
|
|
ASSERT_NEAR( psi_0.GetProbability(0), 1. , accepted_error_ );
|
|
|
|
QubitRegister<ComplexDP> psi_1 (num_qubits_,"base",1);
|
|
psi_1.ApplyHadamard(0);
|
|
// |psi_1> = |-0> = |q0=-> x |q1=0>
|
|
ASSERT_NEAR( psi_1.GetProbability(0), 0.5, accepted_error_ );
|
|
|
|
QubitRegister<ComplexDP> psi_2 (num_qubits_,"base",2);
|
|
psi_2.ApplyHadamard(1);
|
|
// |psi_2> = |0-> = |q0=0> x |q1=->
|
|
ComplexDP amplitude = ComplexDP(1./std::sqrt(2.), 0. );
|
|
ASSERT_EQ(psi_2.GetGlobalAmplitude(0), amplitude);
|
|
ASSERT_DOUBLE_EQ(psi_2.GetGlobalAmplitude(1).real(), 0.);
|
|
ASSERT_EQ(psi_2.GetGlobalAmplitude(2),-amplitude);
|
|
ASSERT_DOUBLE_EQ(psi_2.GetGlobalAmplitude(3).imag(), 0.);
|
|
|
|
QubitRegister<ComplexDP> psi_3 (num_qubits_,"base",3);
|
|
psi_3.ApplyHadamard(0);
|
|
psi_3.ApplyHadamard(1);
|
|
// |psi_3> = |--> = |q0=-> x |q1=->
|
|
amplitude = ComplexDP(1./2., 0. );
|
|
ASSERT_COMPLEX_NEAR(psi_3.GetGlobalAmplitude(0), amplitude, accepted_error_);
|
|
ASSERT_COMPLEX_NEAR(psi_3.GetGlobalAmplitude(1), -amplitude, accepted_error_);
|
|
ASSERT_COMPLEX_NEAR(psi_3.GetGlobalAmplitude(2), -amplitude, accepted_error_);
|
|
ASSERT_COMPLEX_NEAR(psi_3.GetGlobalAmplitude(3), amplitude, accepted_error_);
|
|
// Verify that the Hadamard is self-inverse, at least on |psi_3>.
|
|
psi_3.ApplyHadamard(0);
|
|
psi_3.ApplyHadamard(1);
|
|
// |psi_3> = |11>
|
|
ASSERT_NEAR(psi_3.GetProbability(0),1, accepted_error_);
|
|
ASSERT_NEAR(psi_3.GetProbability(1),1, accepted_error_);
|
|
ASSERT_NEAR(psi_3.GetGlobalAmplitude(3).imag(), 0., accepted_error_);
|
|
}
|
|
*/
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#endif // header guard CHUNKING_COMMUNICATION_TEST_HPP
|