From 2db52a8f95f182978875a6536ae3dbc54cd266bc Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Oct 2024 14:41:59 +0000 Subject: [PATCH] apply features changes brought by PR#927 --- .../catalyst/LightningGPUSimulator.cpp | 41 ++++------ .../catalyst/LightningGPUSimulator.hpp | 2 + .../tests/Test_LightningGPUMeasures.cpp | 81 ++++++++++++++----- 3 files changed, 80 insertions(+), 44 deletions(-) diff --git a/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/LightningGPUSimulator.cpp b/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/LightningGPUSimulator.cpp index 39fa7a93c..354c60c0e 100644 --- a/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/LightningGPUSimulator.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/LightningGPUSimulator.cpp @@ -309,13 +309,20 @@ void LightningGPUSimulator::PartialProbs( std::move(dv_probs.begin(), dv_probs.end(), probs.begin()); } -void LightningGPUSimulator::Sample(DataView &samples, - std::size_t shots) { +std::vector LightningGPUSimulator::GenerateSamples(size_t shots) { + // generate_samples is a member function of the Measures class. Pennylane::LightningGPU::Measures::Measurements m{ *(this->device_sv)}; - // PL-Lightning-GPU generates samples using the alias method. - // Reference: https://en.wikipedia.org/wiki/Inverse_transform_sampling - auto li_samples = m.generate_samples(shots); + + if (this->gen) { + return m.generate_samples(shots, (*(this->gen))()); + } + return m.generate_samples(shots); +} + +void LightningGPUSimulator::Sample(DataView &samples, + std::size_t shots) { + auto li_samples = this->GenerateSamples(shots); RT_FAIL_IF(samples.size() != li_samples.size(), "Invalid size for the pre-allocated samples"); @@ -348,13 +355,7 @@ void LightningGPUSimulator::PartialSample(DataView &samples, // get device wires auto &&dev_wires = getDeviceWires(wires); - // generate_samples is a member function of the MeasuresGPU class. - Pennylane::LightningGPU::Measures::Measurements m{ - *(this->device_sv)}; - - // PL-Lightning-GPU generates samples using the alias method. - // Reference: https://en.wikipedia.org/wiki/Inverse_transform_sampling - auto li_samples = m.generate_samples(shots); + auto li_samples = this->GenerateSamples(shots); // The lightning samples are layed out as a single vector of size // shots*qubits, where each element represents a single bit. The @@ -378,13 +379,7 @@ void LightningGPUSimulator::Counts(DataView &eigvals, RT_FAIL_IF(eigvals.size() != numElements || counts.size() != numElements, "Invalid size for the pre-allocated counts"); - // generate_samples is a member function of the MeasuresGPU class. - Pennylane::LightningGPU::Measures::Measurements m{ - *(this->device_sv)}; - - // PL-Lightning-GPU generates samples using the alias method. - // Reference: https://en.wikipedia.org/wiki/Inverse_transform_sampling - auto li_samples = m.generate_samples(shots); + auto li_samples = this->GenerateSamples(shots); // Fill the eigenvalues with the integer representation of the corresponding // computational basis bitstring. In the future, eigenvalues can also be @@ -423,13 +418,7 @@ void LightningGPUSimulator::PartialCounts(DataView &eigvals, // get device wires auto &&dev_wires = getDeviceWires(wires); - // generate_samples is a member function of the MeasuresGPU class. - Pennylane::LightningGPU::Measures::Measurements m{ - *(this->device_sv)}; - - // PL-Lightning-GPU generates samples using the alias method. - // Reference: https://en.wikipedia.org/wiki/Inverse_transform_sampling - auto li_samples = m.generate_samples(shots); + auto li_samples = this->GenerateSamples(shots); // Fill the eigenvalues with the integer representation of the corresponding // computational basis bitstring. In the future, eigenvalues can also be diff --git a/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/LightningGPUSimulator.hpp b/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/LightningGPUSimulator.hpp index c10ef26b6..2c45b41f8 100644 --- a/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/LightningGPUSimulator.hpp +++ b/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/LightningGPUSimulator.hpp @@ -97,6 +97,8 @@ class LightningGPUSimulator final : public Catalyst::Runtime::QuantumDevice { return res; } + auto GenerateSamples(size_t shots) -> std::vector; + public: explicit LightningGPUSimulator(const std::string &kwargs = "{}") { auto &&args = Catalyst::Runtime::parse_kwargs(kwargs); diff --git a/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/tests/Test_LightningGPUMeasures.cpp b/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/tests/Test_LightningGPUMeasures.cpp index c24b03a90..1162334a3 100644 --- a/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/tests/Test_LightningGPUMeasures.cpp +++ b/pennylane_lightning/core/src/simulators/lightning_gpu/catalyst/tests/Test_LightningGPUMeasures.cpp @@ -1754,26 +1754,71 @@ TEST_CASE("Counts and PartialCounts tests with numWires=0-4 shots=100", } TEST_CASE("Measurement with a seeded device", "[Measures]") { - for (std::size_t _ = 0; _ < 5; _++) { - std::unique_ptr sim = std::make_unique(); - std::unique_ptr sim1 = std::make_unique(); + std::array, 2> sims; + std::vector gens{std::mt19937{37}, std::mt19937{37}}; - std::mt19937 gen(37); - sim->SetDevicePRNG(&gen); + auto circuit = [](LGPUSimulator &sim, std::mt19937 &gen) { + sim.SetDevicePRNG(&gen); std::vector Qs; Qs.reserve(1); - Qs.push_back(sim->AllocateQubit()); - sim->NamedOperation("Hadamard", {}, {Qs[0]}, false); - auto m = sim->Measure(Qs[0]); - - std::mt19937 gen1(37); - sim1->SetDevicePRNG(&gen1); - std::vector Qs1; - Qs1.reserve(1); - Qs1.push_back(sim1->AllocateQubit()); - sim1->NamedOperation("Hadamard", {}, {Qs1[0]}, false); - auto m1 = sim1->Measure(Qs1[0]); - - CHECK(*m == *m1); + Qs.push_back(sim.AllocateQubit()); + sim.NamedOperation("Hadamard", {}, {Qs[0]}, false); + auto m = sim.Measure(Qs[0]); + return m; + }; + + for (std::size_t trial = 0; trial < 5; trial++) { + sims[0] = std::make_unique(); + sims[1] = std::make_unique(); + + auto m0 = circuit(*(sims[0]), gens[0]); + auto m1 = circuit(*(sims[1]), gens[1]); + + CHECK(*m0 == *m1); + } +} + +TEST_CASE("Sample with a seeded device", "[Measures]") { + std::size_t shots = 100; + std::array, 2> sims; + std::vector> sample_vec(2, + std::vector(shots * 4)); + + std::vector> buffers{ + MemRefT{ + sample_vec[0].data(), sample_vec[0].data(), 0, {shots, 1}, {1, 1}}, + MemRefT{ + sample_vec[1].data(), sample_vec[1].data(), 0, {shots, 1}, {1, 1}}, + }; + std::vector> views{ + DataView(buffers[0].data_aligned, buffers[0].offset, + buffers[0].sizes, buffers[0].strides), + DataView(buffers[1].data_aligned, buffers[1].offset, + buffers[1].sizes, buffers[1].strides)}; + + std::vector gens{std::mt19937{37}, std::mt19937{37}}; + + auto circuit = [shots](LGPUSimulator &sim, DataView &view, + std::mt19937 &gen) { + sim.SetDevicePRNG(&gen); + std::vector Qs; + Qs.reserve(1); + Qs.push_back(sim.AllocateQubit()); + sim.NamedOperation("Hadamard", {}, {Qs[0]}, false); + sim.NamedOperation("RX", {0.5}, {Qs[0]}, false); + sim.Sample(view, shots); + }; + + for (std::size_t trial = 0; trial < 5; trial++) { + sims[0] = std::make_unique(); + sims[1] = std::make_unique(); + + for (std::size_t sim_idx = 0; sim_idx < sims.size(); sim_idx++) { + circuit(*(sims[sim_idx]), views[sim_idx], gens[sim_idx]); + } + + for (std::size_t i = 0; i < sample_vec[0].size(); i++) { + CHECK((sample_vec[0][i] == sample_vec[1][i])); + } } }