Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalize seeding for measurements #1003

Merged
merged 44 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
b37faa2
Generalize seeding for measurements on LQ
rauletorresc Nov 22, 2024
11398e4
Auto update version from '0.40.0-dev13' to '0.40.0-dev14'
ringo-but-quantum Nov 22, 2024
45dedb1
Genaralize seeding in LK
rauletorresc Nov 22, 2024
09d4cf7
Merge branch 'master' into raultorres/generalize_measures_seeding
rauletorresc Nov 22, 2024
fe56e00
Auto update version from '0.40.0-dev14' to '0.40.0-dev15'
ringo-but-quantum Nov 22, 2024
e53d51e
Generalize seeding for LG
rauletorresc Nov 22, 2024
c8b7f4b
Reuse original measure info for new measure
rauletorresc Nov 25, 2024
dd848a3
Prepend 'this->' to gen property
rauletorresc Nov 25, 2024
be61b6c
Add optional argument to 'generate_samples' in LK and LG
rauletorresc Nov 25, 2024
373ff8a
Merge branch 'master' into raultorres/generalize_measures_seeding
rauletorresc Nov 26, 2024
1809ba1
Use a seed instead of PRNG in the derived measure class of LQ
rauletorresc Nov 26, 2024
4edd498
Use seed instead of PRNG for LK and LG
rauletorresc Nov 26, 2024
56878a7
Move seeding logic to the base class
rauletorresc Nov 27, 2024
9432fb1
Remove unnecessary get method
rauletorresc Nov 27, 2024
f718fb6
Remove unnecessary header
rauletorresc Nov 27, 2024
d00f168
Change var to a const reference
rauletorresc Nov 27, 2024
24c4a3b
Restore hard-coded seed in test
rauletorresc Nov 27, 2024
2c49df3
Remove const type from member var
rauletorresc Nov 27, 2024
d56da2f
Remove unnecessary header
rauletorresc Nov 27, 2024
541e9cb
Merge branch 'master' into raultorres/generalize_measures_seeding
rauletorresc Nov 27, 2024
858e960
Fix method naming
rauletorresc Nov 27, 2024
3e9db45
Remove unnecessary set methods
rauletorresc Nov 27, 2024
6fd513e
Add plugins tests for probs
rauletorresc Nov 28, 2024
77501e9
Auto update version from '0.40.0-dev20' to '0.40.0-dev21'
ringo-but-quantum Nov 28, 2024
86eddf5
Merge branch 'master' into raultorres/generalize_measures_seeding
rauletorresc Nov 28, 2024
4f51f28
Remove unnecessary header
rauletorresc Nov 28, 2024
a448c57
Remove unnecessary capture in lambda
rauletorresc Nov 28, 2024
844bf92
Add setDeviceShots to probs tests
rauletorresc Nov 28, 2024
cd2166f
Merge branch 'master' into raultorres/generalize_measures_seeding
rauletorresc Nov 28, 2024
ea9bb12
Auto update version from '0.40.0-dev21' to '0.40.0-dev22'
ringo-but-quantum Nov 28, 2024
f419d37
Capture shots in lambda
rauletorresc Nov 28, 2024
3d1f005
Apply code review suggestions
rauletorresc Nov 28, 2024
753dd05
Apply more code review suggestions
rauletorresc Nov 28, 2024
8684357
Auto update version from '0.40.0-dev22' to '0.40.0-dev23'
ringo-but-quantum Nov 28, 2024
59f63af
Merge branch 'master' into raultorres/generalize_measures_seeding
rauletorresc Nov 28, 2024
0c7cba3
Auto update version from '0.40.0-dev23' to '0.40.0-dev24'
ringo-but-quantum Nov 28, 2024
604982d
Set seed when generating samples
rauletorresc Nov 29, 2024
d1cb4f2
Add test for Var in LQ, LK and LGPU
rauletorresc Nov 29, 2024
cbb44dd
Add tests for Expval in LQ, LK and LG
rauletorresc Nov 29, 2024
cdb8895
Update changelog
rauletorresc Nov 29, 2024
6c8f11e
Merge branch 'master' into raultorres/generalize_measures_seeding
rauletorresc Nov 28, 2024
95b7f51
Add constexpr qualifier
rauletorresc Dec 3, 2024
56d28fc
Add constexpr
rauletorresc Dec 3, 2024
b46a8de
Remove shots from capture
rauletorresc Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pennylane_lightning/core/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
Version number (major.minor.patch[-label])
"""

__version__ = "0.40.0-dev14"
__version__ = "0.40.0-dev15"
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,8 @@ template <class StateVectorT, class Derived> class MeasurementsBase {
*/
auto sample(const std::size_t &num_shots) -> std::vector<std::size_t> {
Derived measure(_statevector);
return measure.generate_samples(num_shots);
return measure.generate_samples(num_shots,
static_cast<Derived *>(this));
}

/**
Expand Down Expand Up @@ -479,12 +480,14 @@ template <class StateVectorT, class Derived> class MeasurementsBase {
StateVectorT sv(data_storage.data(), data_storage.size());
obs.applyInPlaceShots(sv, eigenValues, obs_wires);
Derived measure(sv);
samples = measure.generate_samples(num_shots);
samples = measure.generate_samples(num_shots,
static_cast<Derived *>(this));
} else {
StateVectorT sv(_statevector);
obs.applyInPlaceShots(sv, eigenValues, obs_wires);
Derived measure(sv);
samples = measure.generate_samples(num_shots);
samples = measure.generate_samples(num_shots,
rauletorresc marked this conversation as resolved.
Show resolved Hide resolved
static_cast<Derived *>(this));
}

if (!shot_range.empty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ TEST_CASE("Var Shot- TensorProdObs", "[MeasurementsBase][Observables]") {
}

template <typename TypeList>
void testSamples(const std::optional<std::size_t> &seed = std::nullopt) {
void testSamples(const std::optional<std::mt19937 *> &gen = std::nullopt) {
if constexpr (!std::is_same_v<TypeList, void>) {
using StateVectorT = typename TypeList::Type;
using PrecisionT = typename StateVectorT::PrecisionT;
Expand All @@ -1257,6 +1257,9 @@ void testSamples(const std::optional<std::size_t> &seed = std::nullopt) {
// This object attaches to the statevector allowing several
// measurements.
Measurements<StateVectorT> Measurer(statevector);
if (gen.has_value()) {
Measurer.set_PRNG(gen.value());
}

std::vector<PrecisionT> expected_probabilities = {
0.67078706, 0.03062806, 0.0870997, 0.00397696,
Expand All @@ -1265,10 +1268,7 @@ void testSamples(const std::optional<std::size_t> &seed = std::nullopt) {
std::size_t num_qubits = 3;
std::size_t N = std::pow(2, num_qubits);
std::size_t num_samples = 100000;
auto &&samples =
seed.has_value()
? Measurer.generate_samples(num_samples, seed.value())
: Measurer.generate_samples(num_samples);
auto &&samples = Measurer.generate_samples(num_samples);

std::vector<std::size_t> counts(N, 0);
std::vector<std::size_t> samples_decimal(num_samples, 0);
Expand All @@ -1294,7 +1294,7 @@ void testSamples(const std::optional<std::size_t> &seed = std::nullopt) {
REQUIRE_THAT(probabilities,
Catch::Approx(expected_probabilities).margin(.05));
}
testSamples<typename TypeList::Next>(seed);
testSamples<typename TypeList::Next>(gen);
}
}

Expand All @@ -1306,7 +1306,8 @@ TEST_CASE("Samples", "[MeasurementsBase]") {

TEST_CASE("Seeded samples", "[MeasurementsBase]") {
if constexpr (BACKEND_FOUND) {
testSamples<TestStateVectorBackends>(37);
std::mt19937 gen(37);
testSamples<TestStateVectorBackends>(&gen);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ auto LightningGPUSimulator::Expval(ObsIdType obsKey) -> double {
Pennylane::LightningGPU::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

return device_shots ? m.expval(*obs, device_shots, {}) : m.expval(*obs);
}

Expand All @@ -261,6 +263,8 @@ auto LightningGPUSimulator::Var(ObsIdType obsKey) -> double {
Pennylane::LightningGPU::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

return device_shots ? m.var(*obs, device_shots) : m.var(*obs);
}

Expand All @@ -282,6 +286,9 @@ void LightningGPUSimulator::State(DataView<std::complex<double>, 1> &state) {
void LightningGPUSimulator::Probs(DataView<double, 1> &probs) {
Pennylane::LightningGPU::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

auto &&dv_probs = device_shots ? m.probs(device_shots) : m.probs();

RT_FAIL_IF(probs.size() != dv_probs.size(),
Expand All @@ -301,6 +308,9 @@ void LightningGPUSimulator::PartialProbs(
auto dev_wires = getDeviceWires(wires);
Pennylane::LightningGPU::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

auto &&dv_probs =
device_shots ? m.probs(dev_wires, device_shots) : m.probs(dev_wires);

Expand All @@ -315,9 +325,8 @@ std::vector<size_t> LightningGPUSimulator::GenerateSamples(size_t shots) {
Pennylane::LightningGPU::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

if (this->gen) {
return m.generate_samples(shots, (*(this->gen))());
}
m.set_PRNG(this->gen);

return m.generate_samples(shots);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class Measurements final

GateCache<PrecisionT> gate_cache_;

std::mt19937 *gen = nullptr;

public:
explicit Measurements(StateVectorT &statevector)
: BaseType{statevector},
Expand Down Expand Up @@ -215,9 +217,7 @@ class Measurements final
* be accessed using the stride sample_id*num_qubits, where sample_id is a
* number between 0 and num_samples-1.
*/
auto generate_samples(std::size_t num_samples,
const std::optional<std::size_t> &seed = std::nullopt)
-> std::vector<std::size_t> {
auto generate_samples(std::size_t num_samples) -> std::vector<std::size_t> {
std::vector<double> rand_nums(num_samples);
custatevecSamplerDescriptor_t sampler;

Expand All @@ -237,8 +237,9 @@ class Measurements final
data_type = CUDA_C_32F;
}

if (seed.has_value()) {
this->setSeed(seed.value());
if (gen != nullptr) {
std::size_t seed = (*(this->gen))();
this->setSeed(seed);
} else {
this->setRandomSeed();
}
Expand Down Expand Up @@ -713,6 +714,8 @@ class Measurements final
return BaseType::var(obs, num_shots);
}

void set_PRNG(std::mt19937 *gen) { this->gen = gen; }

private:
/**
* @brief Utility method for expectation value calculations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ auto LightningKokkosSimulator::Expval(ObsIdType obsKey) -> double {
Pennylane::LightningKokkos::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

return device_shots ? m.expval(*obs, device_shots, {}) : m.expval(*obs);
}

Expand All @@ -285,6 +287,8 @@ auto LightningKokkosSimulator::Var(ObsIdType obsKey) -> double {
Pennylane::LightningKokkos::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

return device_shots ? m.var(*obs, device_shots) : m.var(*obs);
}

Expand Down Expand Up @@ -314,6 +318,9 @@ void LightningKokkosSimulator::State(DataView<std::complex<double>, 1> &state) {
void LightningKokkosSimulator::Probs(DataView<double, 1> &probs) {
Pennylane::LightningKokkos::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

auto &&dv_probs = device_shots ? m.probs(device_shots) : m.probs();

RT_FAIL_IF(probs.size() != dv_probs.size(),
Expand All @@ -333,6 +340,9 @@ void LightningKokkosSimulator::PartialProbs(
auto dev_wires = getDeviceWires(wires);
Pennylane::LightningKokkos::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

auto &&dv_probs =
device_shots ? m.probs(dev_wires, device_shots) : m.probs(dev_wires);

Expand All @@ -347,11 +357,10 @@ std::vector<size_t> LightningKokkosSimulator::GenerateSamples(size_t shots) {
Pennylane::LightningKokkos::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

// PL-Lightning-Kokkos generates samples using the alias method.
// Reference: https://en.wikipedia.org/wiki/Inverse_transform_sampling
if (this->gen) {
return m.generate_samples(shots, (*(this->gen))());
}
return m.generate_samples(shots);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <chrono>
#include <cstdint>
#include <optional>
#include <random>

#include <Kokkos_Core.hpp>
#include <Kokkos_Random.hpp>
Expand Down Expand Up @@ -72,6 +73,8 @@ class Measurements final
using ScratchViewComplex = typename StateVectorT::ScratchViewComplex;
using TeamPolicy = typename StateVectorT::TeamPolicy;

std::mt19937 *gen = nullptr;

public:
explicit Measurements(const StateVectorT &statevector)
: BaseType{statevector} {
Expand Down Expand Up @@ -650,16 +653,13 @@ class Measurements final
* Reference https://en.wikipedia.org/wiki/Inverse_transform_sampling
*
* @param num_samples Number of Samples
* @param seed Seed to generate the samples from
*
* @return std::vector<std::size_t> to the samples.
* Each sample has a length equal to the number of qubits. Each sample can
* be accessed using the stride sample_id*num_qubits, where sample_id is a
* number between 0 and num_samples-1.
*/
auto generate_samples(std::size_t num_samples,
const std::optional<std::size_t> &seed = std::nullopt)
-> std::vector<std::size_t> {
auto generate_samples(std::size_t num_samples) -> std::vector<std::size_t> {
const std::size_t num_qubits = this->_statevector.getNumQubits();
const std::size_t N = this->_statevector.getLength();
Kokkos::View<std::size_t *> samples("num_samples",
Expand All @@ -678,12 +678,13 @@ class Measurements final
});

// Sampling using Random_XorShift64_Pool
auto rand_pool = seed.has_value()
? Kokkos::Random_XorShift64_Pool<>(seed.value())
: Kokkos::Random_XorShift64_Pool<>(
std::chrono::high_resolution_clock::now()
.time_since_epoch()
.count());
auto rand_pool =
this->gen != nullptr
? Kokkos::Random_XorShift64_Pool<>((*(this->gen))())
: Kokkos::Random_XorShift64_Pool<>(
std::chrono::high_resolution_clock::now()
.time_since_epoch()
.count());

Kokkos::parallel_for(
Kokkos::RangePolicy<KokkosExecSpace>(0, num_samples),
Expand All @@ -693,6 +694,8 @@ class Measurements final
return view2vector(samples);
}

void set_PRNG(std::mt19937 *gen) { this->gen = gen; }

private:
std::unordered_map<std::string, ExpValFunc> expval_funcs_;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ auto LightningSimulator::Expval(ObsIdType obsKey) -> double {
Pennylane::LightningQubit::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

return (device_shots != 0U) ? m.expval(*obs, device_shots, {})
: m.expval(*obs);
}
Expand All @@ -268,6 +270,8 @@ auto LightningSimulator::Var(ObsIdType obsKey) -> double {
Pennylane::LightningQubit::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

return (device_shots != 0U) ? m.var(*obs, device_shots) : m.var(*obs);
}

Expand All @@ -282,6 +286,9 @@ void LightningSimulator::State(DataView<std::complex<double>, 1> &state) {
void LightningSimulator::Probs(DataView<double, 1> &probs) {
Pennylane::LightningQubit::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

auto &&dv_probs = (device_shots != 0U) ? m.probs(device_shots) : m.probs();

RT_FAIL_IF(probs.size() != dv_probs.size(),
Expand All @@ -301,6 +308,9 @@ void LightningSimulator::PartialProbs(DataView<double, 1> &probs,
auto dev_wires = getDeviceWires(wires);
Pennylane::LightningQubit::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

auto &&dv_probs = (device_shots != 0U) ? m.probs(dev_wires, device_shots)
: m.probs(dev_wires);

Expand All @@ -316,6 +326,8 @@ LightningSimulator::GenerateSamplesMetropolis(size_t shots) {
Pennylane::LightningQubit::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

// PL-Lightning generates samples using the alias method.
// Reference: https://en.wikipedia.org/wiki/Alias_method
// Given the number of samples, returns 1-D vector of samples
Expand All @@ -335,16 +347,15 @@ std::vector<size_t> LightningSimulator::GenerateSamples(size_t shots) {
Pennylane::LightningQubit::Measures::Measurements<StateVectorT> m{
*(this->device_sv)};

m.set_PRNG(this->gen);

// PL-Lightning generates samples using the alias method.
// Reference: https://en.wikipedia.org/wiki/Alias_method
// Given the number of samples, returns 1-D vector of samples
// in binary, each sample is separated by a stride equal to
// the number of qubits.
//
// Return Value Optimization (RVO)
if (this->gen != nullptr) {
return m.generate_samples(shots, (*(this->gen))());
}
return m.generate_samples(shots);
}

Expand Down
Loading
Loading