From daabc6788b6b3a39d24e04447e3ca109633d5d72 Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Tue, 1 Nov 2022 19:08:02 -0400 Subject: [PATCH 01/53] Add skeleton fo mcmc --- .../src/simulator/Measures.hpp | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index be7f86fe36..299b41888c 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -309,6 +309,65 @@ class Measures { return expected_value_list; }; + template + size_t mcmc_step + ( + const StateVectorManagedCPU & sv, + TransitionKernel & tk, + std::mt19937 & gen, + std::uniform_real_distribution & distrib, + size_t s1 + ) + { + auto s1_plog = log((sv_[s1]*std::conj(sv_[s1])).real()); + + auto s1_qratio = tk(s1); + auto & s2 = s1_qratio.first; + auto & qratio = s1_qratio.second; + + auto s2_plog = log((sv_[s2]*std::conj(sv_[s2])).real()); + + auto alph = std::min(1.,qratio*exp(s2_plog-s1_plog)); + auto ran = distrib(gen); + + if (ran < alph) { + return s2; + } + else { + return s1; + } + } + + template + std::vector generate_samples_mcmc + ( + const StateVectorManagedCPU & sv, + size_t num_burnin, + size_t num_shots + ) + { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution distrib(0.0,1.0); + + + TransitionKernel tk(sv); + size_t s1 = tk.InitState(); + + //Burn In + for (size_t i=0;i shots(num_shots); + auto t1 = high_resolution_clock::now(); + for (size_t i=0;i Date: Thu, 3 Nov 2022 03:23:02 -0400 Subject: [PATCH 02/53] Add transition kernel infrastructure --- .../src/simulator/Measures.hpp | 90 +++++++++++++++++-- 1 file changed, 82 insertions(+), 8 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 299b41888c..2a720576f1 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -309,11 +309,66 @@ class Measures { return expected_value_list; }; - template + + class TransitionKernel { + public: + virtual size_t init_state () = 0; + virtual std::pair operator() (size_t) = 0; + }; + + class LocalTransitionKernel : TransitionKernel { + // : public TransitionKernel { + private: + + std::random_device rd_; + std::mt19937 gen_; + std::uniform_int_distribution distrib_num_qubits_; + std::uniform_int_distribution distrib_binary_; + size_t num_qubits_; + + public: + + LocalTransitionKernel(size_t num_qubits) { + num_qubits_ = num_qubits; + gen_ = std::mt19937(rd_()); + distrib_num_qubits_ = std::uniform_int_distribution(0,num_qubits-1); + distrib_binary_ = std::uniform_int_distribution(0,1); + } + + size_t init_state(){ + return 0; + } + + std::pair operator() (size_t s1) { + size_t qubit_site = distrib_num_qubits_(gen_); + size_t qubit_value = distrib_binary_(gen_); + size_t current_bit = (s1 >> qubit_site) & 1; + + if (qubit_value == current_bit) + return std::pair(s1,1); + else if (current_bit == 0){ + return std::pair(s1+std::pow(2,qubit_site),1); + } + else { + return std::pair(s1-std::pow(2,qubit_site),1); + } + } + }; + + TransitionKernel* kernel_factory(const std::string & kernel_name, + const StateVectorManagedCPU & sv) + { + if (kernel_name == "local"){ + return new LocalTransitionKernel(sv.getNumQubits()); + } + else { //local is the default as well + return new LocalTransitionKernel(sv.getNumQubits()); + } + } + size_t mcmc_step ( const StateVectorManagedCPU & sv, - TransitionKernel & tk, std::mt19937 & gen, std::uniform_real_distribution & distrib, size_t s1 @@ -338,10 +393,10 @@ class Measures { } } - template std::vector generate_samples_mcmc ( const StateVectorManagedCPU & sv, + const std::string & transition_kernel, size_t num_burnin, size_t num_shots ) @@ -349,10 +404,11 @@ class Measures { std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution distrib(0.0,1.0); - + std::vector samples(num_samples * num_qubits, 0); + std::unordered_map cache; - TransitionKernel tk(sv); - size_t s1 = tk.InitState(); + TransitionKernel* tk = kernel_factory(transition_kernel, sv); + size_t s1 = tk->InitState(); //Burn In for (size_t i=0;i shots(num_shots); auto t1 = high_resolution_clock::now(); for (size_t i=0;i> j) & 1U; + } + cache[idx] = i; + } + } + + delete tk; } /** From c8c1d2e903c225ecc2a5a6bf176df5a7577856d9 Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Thu, 3 Nov 2022 03:41:40 -0400 Subject: [PATCH 03/53] Make new file for transition kernels --- .../src/simulator/Measures.hpp | 56 --------- .../src/simulator/TransitionKernels.hpp | 107 ++++++++++++++++++ 2 files changed, 107 insertions(+), 56 deletions(-) create mode 100644 pennylane_lightning/src/simulator/TransitionKernels.hpp diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 2a720576f1..8a1fc00041 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -309,62 +309,6 @@ class Measures { return expected_value_list; }; - - class TransitionKernel { - public: - virtual size_t init_state () = 0; - virtual std::pair operator() (size_t) = 0; - }; - - class LocalTransitionKernel : TransitionKernel { - // : public TransitionKernel { - private: - - std::random_device rd_; - std::mt19937 gen_; - std::uniform_int_distribution distrib_num_qubits_; - std::uniform_int_distribution distrib_binary_; - size_t num_qubits_; - - public: - - LocalTransitionKernel(size_t num_qubits) { - num_qubits_ = num_qubits; - gen_ = std::mt19937(rd_()); - distrib_num_qubits_ = std::uniform_int_distribution(0,num_qubits-1); - distrib_binary_ = std::uniform_int_distribution(0,1); - } - - size_t init_state(){ - return 0; - } - - std::pair operator() (size_t s1) { - size_t qubit_site = distrib_num_qubits_(gen_); - size_t qubit_value = distrib_binary_(gen_); - size_t current_bit = (s1 >> qubit_site) & 1; - - if (qubit_value == current_bit) - return std::pair(s1,1); - else if (current_bit == 0){ - return std::pair(s1+std::pow(2,qubit_site),1); - } - else { - return std::pair(s1-std::pow(2,qubit_site),1); - } - } - }; - - TransitionKernel* kernel_factory(const std::string & kernel_name, - const StateVectorManagedCPU & sv) - { - if (kernel_name == "local"){ - return new LocalTransitionKernel(sv.getNumQubits()); - } - else { //local is the default as well - return new LocalTransitionKernel(sv.getNumQubits()); - } - } size_t mcmc_step ( diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp new file mode 100644 index 0000000000..5dcfee6cf4 --- /dev/null +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "StateVectorManagedCPU.hpp" +#include "StateVectorRawCPU.hpp" + +namespace Pennylane { + + class TransitionKernel { + public: + virtual size_t init_state () = 0; + virtual std::pair operator() (size_t) = 0; + }; + + class LocalTransitionKernel : TransitionKernel { + // : public TransitionKernel { + private: + + std::random_device rd_; + std::mt19937 gen_; + std::uniform_int_distribution distrib_num_qubits_; + std::uniform_int_distribution distrib_binary_; + size_t num_qubits_; + + public: + + LocalTransitionKernel(size_t num_qubits) { + num_qubits_ = num_qubits; + gen_ = std::mt19937(rd_()); + distrib_num_qubits_ = std::uniform_int_distribution(0,num_qubits-1); + distrib_binary_ = std::uniform_int_distribution(0,1); + } + + size_t init_state(){ + return 0; + } + + std::pair operator() (size_t s1) { + size_t qubit_site = distrib_num_qubits_(gen_); + size_t qubit_value = distrib_binary_(gen_); + size_t current_bit = (s1 >> qubit_site) & 1; + + if (qubit_value == current_bit) + return std::pair(s1,1); + else if (current_bit == 0){ + return std::pair(s1+std::pow(2,qubit_site),1); + } + else { + return std::pair(s1-std::pow(2,qubit_site),1); + } + } + }; + + class NonZeroRandomTransitionKernel{ + // : public TransitionKernel { + private: + std::random_device rd_; + std::mt19937 gen_; + std::uniform_int_distribution distrib_; + size_t sv_length_; + std::vector non_zeros_; + + public: + size_t init_state(){ + return 0; + } + + NonZeroRandomTransitionKernel(const StateVectorManagedCPU & sv, fp_t min_error) { + auto data = sv.getData(); + sv_length_ = sv.getLength(); + + //find nonzero candidates + for (size_t i = 0; i < sv_length_; i++){ + if (fabs(data[i].real()) > min_error || + fabs(data[i].imag()) > min_error){ + non_zeros_.push_back(i); + } + } + gen_ = std::mt19937(rd_()); + distrib_ = std::uniform_int_distribution(0,non_zeros_.size()-1); + } + + std::pair operator() (size_t s1) { + auto s2 = distrib_(gen_); + return std::pair(non_zeros_[s2],1); + } + }; + + + TransitionKernel* kernel_factory(const std::string & kernel_name, + const StateVectorManagedCPU & sv) + { + if (kernel_name == "local"){ + return new NonZeroRandomKernel(sv.getNumQubits()); + } + else { //local is the default + return new LocalTransitionKernel(sv.getNumQubits()); + } + } +} From 0bdabadaa0e9d4a67d06a6dad465dcae2c19e2bd Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Fri, 4 Nov 2022 02:52:58 -0400 Subject: [PATCH 04/53] Add fixes for compilation errors --- .../src/simulator/Measures.hpp | 23 +++---- .../src/simulator/TransitionKernels.hpp | 29 ++++++--- .../src/tests/Test_Measures.cpp | 61 +++++++++++++++++++ 3 files changed, 92 insertions(+), 21 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 8a1fc00041..5acffd9581 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -31,6 +31,7 @@ #include "Kokkos_Sparse.hpp" #include "LinearAlgebra.hpp" #include "Observables.hpp" +#include "TransitionKernels.hpp" #include "StateVectorManagedCPU.hpp" #include "StateVectorRawCPU.hpp" @@ -313,18 +314,21 @@ class Measures { size_t mcmc_step ( const StateVectorManagedCPU & sv, + std::unique_ptr> & tk, std::mt19937 & gen, std::uniform_real_distribution & distrib, size_t s1 ) { - auto s1_plog = log((sv_[s1]*std::conj(sv_[s1])).real()); + auto s1_plog = log((sv[s1]*std::conj(sv[s1])).real()); - auto s1_qratio = tk(s1); + auto s1_qratio = tk->(s1); + + //transition kernel outputs these two auto & s2 = s1_qratio.first; auto & qratio = s1_qratio.second; - auto s2_plog = log((sv_[s2]*std::conj(sv_[s2])).real()); + auto s2_plog = log((sv[s2]*std::conj(sv[s2])).real()); auto alph = std::min(1.,qratio*exp(s2_plog-s1_plog)); auto ran = distrib(gen); @@ -337,10 +341,9 @@ class Measures { } } - std::vector generate_samples_mcmc + std::vector generate_samples_metropolis ( - const StateVectorManagedCPU & sv, - const std::string & transition_kernel, + const TransitionKernelType & transition_kernel, size_t num_burnin, size_t num_shots ) @@ -350,8 +353,9 @@ class Measures { std::uniform_real_distribution distrib(0.0,1.0); std::vector samples(num_samples * num_qubits, 0); std::unordered_map cache; - - TransitionKernel* tk = kernel_factory(transition_kernel, sv); + + //unique_ptr and enum + auto tk = kernel_factory(transition_kernel, original_statevector); size_t s1 = tk->InitState(); //Burn In @@ -360,8 +364,6 @@ class Measures { } //Sample - std::vector shots(num_shots); - auto t1 = high_resolution_clock::now(); for (size_t i=0;i class TransitionKernel { public: virtual size_t init_state () = 0; + //outputs the next state and the qratio virtual std::pair operator() (size_t) = 0; }; - class LocalTransitionKernel : TransitionKernel { - // : public TransitionKernel { + template + class LocalTransitionKernel : public TransitionKernel { private: std::random_device rd_; @@ -58,7 +62,8 @@ namespace Pennylane { } }; - class NonZeroRandomTransitionKernel{ + template + class NonZeroRandomTransitionKernel : public TransitionKernel { // : public TransitionKernel { private: std::random_device rd_; @@ -92,16 +97,20 @@ namespace Pennylane { return std::pair(non_zeros_[s2],1); } }; - - TransitionKernel* kernel_factory(const std::string & kernel_name, - const StateVectorManagedCPU & sv) + + template + std::unique_ptr> kernel_factory + ( + const TransitionKernelType kernel_type, + const StateVectorManagedCPU & sv + ) { - if (kernel_name == "local"){ - return new NonZeroRandomKernel(sv.getNumQubits()); + if (kernel_type == TransitionKernelType::Local){ + return std::make_unique(NonZeroRandomKernel(sv.getNumQubits())); } else { //local is the default - return new LocalTransitionKernel(sv.getNumQubits()); + return std::make_unique(LocalTransitionKernel(sv.getNumQubits())); } } } diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp index eeef76bcd2..aa16b3fe28 100644 --- a/pennylane_lightning/src/tests/Test_Measures.cpp +++ b/pennylane_lightning/src/tests/Test_Measures.cpp @@ -196,6 +196,64 @@ TEMPLATE_TEST_CASE("Sample", "[Measures]", float, double) { } } + +TEMPLATE_TEST_CASE("Sample with Metropolis", "[Measures]", float, double) { + constexpr uint32_t twos[] = { + 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, 1U << 4U, 1U << 5U, + 1U << 6U, 1U << 7U, 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U, + 1U << 12U, 1U << 13U, 1U << 14U, 1U << 15U, 1U << 16U, 1U << 17U, + 1U << 18U, 1U << 19U, 1U << 20U, 1U << 21U, 1U << 22U, 1U << 23U, + 1U << 24U, 1U << 25U, 1U << 26U, 1U << 27U, 1U << 28U, 1U << 29U, + 1U << 30U, 1U << 31U}; + + // Defining the State Vector that will be measured. + StateVectorManagedCPU Measured_StateVector = + Initializing_StateVector(); + + // Initializing the measures class. + // This object attaches to the statevector allowing several measures. + Measures> Measurer( + Measured_StateVector); + vector expected_probabilities = { + 0.67078706, 0.03062806, 0.0870997, 0.00397696, + 0.17564072, 0.00801973, 0.02280642, 0.00104134}; + + size_t num_qubits = 3; + size_t N = std::pow(2, num_qubits); + size_t num_samples = 100000; + size_t num_burnin = 1000; + + auto &&samples = Measurer.generate_samples_metropolis(TransitionKernel::Local, + num_burnin, + num_samples); + + std::vector counts(N, 0); + std::vector samples_decimal(num_samples, 0); + + // convert samples to decimal and then bin them in counts + for (size_t i = 0; i < num_samples; i++) { + for (size_t j = 0; j < num_qubits; j++) { + if (samples[i * num_qubits + j] != 0) { + samples_decimal[i] += twos[(num_qubits - 1 - j)]; + } + } + counts[samples_decimal[i]] += 1; + } + + // compute estimated probabilities from histogram + std::vector probabilities(counts.size()); + for (size_t i = 0; i < counts.size(); i++) { + probabilities[i] = counts[i] / (TestType)num_samples; + } + + // compare estimated probabilities to real probabilities + SECTION("No wires provided:") { + REQUIRE_THAT(probabilities, + Catch::Approx(expected_probabilities).margin(.05)); + } +} + + TEMPLATE_TEST_CASE("Variances", "[Measures]", float, double) { // Defining the State Vector that will be measured. StateVectorManagedCPU Measured_StateVector = @@ -271,4 +329,7 @@ TEMPLATE_TEST_CASE("Variances", "[Measures]", float, double) { variances_ref = {0.6577942, 0.4068672, 0.1670374}; REQUIRE_THAT(variances, Catch::Approx(variances_ref).margin(1e-6)); } + + + } From 502451f584307181a43406ffee1155ab2abb5d57 Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Tue, 8 Nov 2022 00:39:59 -0500 Subject: [PATCH 05/53] Fix all compiler errors --- .../src/simulator/Measures.hpp | 34 +++++++++---------- .../src/simulator/TransitionKernels.cpp | 5 +++ .../src/simulator/TransitionKernels.hpp | 20 ++++++----- .../src/tests/Test_Measures.cpp | 3 +- 4 files changed, 36 insertions(+), 26 deletions(-) create mode 100644 pennylane_lightning/src/simulator/TransitionKernels.cpp diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 5acffd9581..d4246cd5cd 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -310,25 +310,25 @@ class Measures { return expected_value_list; }; - + size_t mcmc_step ( - const StateVectorManagedCPU & sv, + const SVType & sv, std::unique_ptr> & tk, std::mt19937 & gen, std::uniform_real_distribution & distrib, size_t s1 ) { - auto s1_plog = log((sv[s1]*std::conj(sv[s1])).real()); + auto s1_plog = log((sv.getData()[s1]*std::conj(sv.getData()[s1])).real()); - auto s1_qratio = tk->(s1); + auto s1_qratio = tk->operator()(s1); //transition kernel outputs these two auto & s2 = s1_qratio.first; auto & qratio = s1_qratio.second; - auto s2_plog = log((sv[s2]*std::conj(sv[s2])).real()); + auto s2_plog = log((sv.getData()[s2]*std::conj(sv.getData()[s2])).real()); auto alph = std::min(1.,qratio*exp(s2_plog-s1_plog)); auto ran = distrib(gen); @@ -345,30 +345,30 @@ class Measures { ( const TransitionKernelType & transition_kernel, size_t num_burnin, - size_t num_shots + size_t num_samples ) { + size_t num_qubits = original_statevector.getNumQubits(); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution distrib(0.0,1.0); std::vector samples(num_samples * num_qubits, 0); std::unordered_map cache; - //unique_ptr and enum - auto tk = kernel_factory(transition_kernel, original_statevector); - size_t s1 = tk->InitState(); + auto tk = kernel_factory(transition_kernel, original_statevector.getData(), original_statevector.getNumQubits()); + size_t s1 = tk->init_state(); //Burn In for (size_t i=0;i> j) & 1U; + (s1 >> j) & 1U; } - cache[idx] = i; + cache[s1] = i; } } - + return samples; } /** diff --git a/pennylane_lightning/src/simulator/TransitionKernels.cpp b/pennylane_lightning/src/simulator/TransitionKernels.cpp new file mode 100644 index 0000000000..a706eda2d4 --- /dev/null +++ b/pennylane_lightning/src/simulator/TransitionKernels.cpp @@ -0,0 +1,5 @@ +#include "StateVectorRawCPU.hpp" + +// explicit instantiation +template class Pennylane::StateVectorRawCPU; +template class Pennylane::StateVectorRawCPU; diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 8c9e714e3e..bd4dd31675 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "StateVectorManagedCPU.hpp" #include "StateVectorRawCPU.hpp" @@ -62,7 +63,7 @@ namespace Pennylane { } }; - template + template class NonZeroRandomTransitionKernel : public TransitionKernel { // : public TransitionKernel { private: @@ -77,9 +78,9 @@ namespace Pennylane { return 0; } - NonZeroRandomTransitionKernel(const StateVectorManagedCPU & sv, fp_t min_error) { - auto data = sv.getData(); - sv_length_ = sv.getLength(); + NonZeroRandomTransitionKernel(const std::complex* sv, size_t sv_length, fp_t min_error) { + auto data = sv; + sv_length_ = sv_length; //find nonzero candidates for (size_t i = 0; i < sv_length_; i++){ @@ -92,7 +93,7 @@ namespace Pennylane { distrib_ = std::uniform_int_distribution(0,non_zeros_.size()-1); } - std::pair operator() (size_t s1) { + std::pair operator() ([[maybe_unused]] size_t s1) { auto s2 = distrib_(gen_); return std::pair(non_zeros_[s2],1); } @@ -103,14 +104,17 @@ namespace Pennylane { std::unique_ptr> kernel_factory ( const TransitionKernelType kernel_type, - const StateVectorManagedCPU & sv + const std::complex* sv, + size_t num_qubits ) { + + auto sv_length = Util::exp2(num_qubits); if (kernel_type == TransitionKernelType::Local){ - return std::make_unique(NonZeroRandomKernel(sv.getNumQubits())); + return std::unique_ptr>(new NonZeroRandomTransitionKernel(sv,sv_length,std::numeric_limits::epsilon())); } else { //local is the default - return std::make_unique(LocalTransitionKernel(sv.getNumQubits())); + return std::unique_ptr>(new LocalTransitionKernel(num_qubits)); } } } diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp index aa16b3fe28..97fe8ac17b 100644 --- a/pennylane_lightning/src/tests/Test_Measures.cpp +++ b/pennylane_lightning/src/tests/Test_Measures.cpp @@ -222,8 +222,9 @@ TEMPLATE_TEST_CASE("Sample with Metropolis", "[Measures]", float, double) { size_t N = std::pow(2, num_qubits); size_t num_samples = 100000; size_t num_burnin = 1000; + - auto &&samples = Measurer.generate_samples_metropolis(TransitionKernel::Local, + auto &&samples = Measurer.generate_samples_metropolis(TransitionKernelType::Local, num_burnin, num_samples); From 95dba4f99a64d2f5e06a958467bbaf3b9a9d9435 Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Tue, 8 Nov 2022 00:40:30 -0500 Subject: [PATCH 06/53] Run make format --- .../src/simulator/Measures.hpp | 141 ++++++++--------- .../src/simulator/TransitionKernels.hpp | 144 +++++++++--------- .../src/tests/Test_Measures.cpp | 11 +- 3 files changed, 137 insertions(+), 159 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index d4246cd5cd..b2afa2e257 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -31,9 +31,9 @@ #include "Kokkos_Sparse.hpp" #include "LinearAlgebra.hpp" #include "Observables.hpp" -#include "TransitionKernels.hpp" #include "StateVectorManagedCPU.hpp" #include "StateVectorRawCPU.hpp" +#include "TransitionKernels.hpp" namespace Pennylane::Simulators { @@ -310,83 +310,76 @@ class Measures { return expected_value_list; }; + size_t mcmc_step(const SVType &sv, + std::unique_ptr> &tk, + std::mt19937 &gen, + std::uniform_real_distribution &distrib, size_t s1) { + auto s1_plog = + log((sv.getData()[s1] * std::conj(sv.getData()[s1])).real()); - size_t mcmc_step - ( - const SVType & sv, - std::unique_ptr> & tk, - std::mt19937 & gen, - std::uniform_real_distribution & distrib, - size_t s1 - ) - { - auto s1_plog = log((sv.getData()[s1]*std::conj(sv.getData()[s1])).real()); - - auto s1_qratio = tk->operator()(s1); - - //transition kernel outputs these two - auto & s2 = s1_qratio.first; - auto & qratio = s1_qratio.second; - - auto s2_plog = log((sv.getData()[s2]*std::conj(sv.getData()[s2])).real()); - - auto alph = std::min(1.,qratio*exp(s2_plog-s1_plog)); - auto ran = distrib(gen); - - if (ran < alph) { - return s2; - } - else { - return s1; - } - } - - std::vector generate_samples_metropolis - ( - const TransitionKernelType & transition_kernel, - size_t num_burnin, - size_t num_samples - ) - { - size_t num_qubits = original_statevector.getNumQubits(); - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_real_distribution distrib(0.0,1.0); - std::vector samples(num_samples * num_qubits, 0); - std::unordered_map cache; - - auto tk = kernel_factory(transition_kernel, original_statevector.getData(), original_statevector.getNumQubits()); - size_t s1 = tk->init_state(); - - //Burn In - for (size_t i=0;ioperator()(s1); + + // transition kernel outputs these two + auto &s2 = s1_qratio.first; + auto &qratio = s1_qratio.second; + + auto s2_plog = + log((sv.getData()[s2] * std::conj(sv.getData()[s2])).real()); + + auto alph = std::min(1., qratio * exp(s2_plog - s1_plog)); + auto ran = distrib(gen); + + if (ran < alph) { + return s2; + } else { + return s1; + } } - //Sample - for (size_t i=0;i> j) & 1U; - } - cache[s1] = i; - } - + std::vector + generate_samples_metropolis(const TransitionKernelType &transition_kernel, + size_t num_burnin, size_t num_samples) { + size_t num_qubits = original_statevector.getNumQubits(); + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution distrib(0.0, 1.0); + std::vector samples(num_samples * num_qubits, 0); + std::unordered_map cache; + + auto tk = + kernel_factory(transition_kernel, original_statevector.getData(), + original_statevector.getNumQubits()); + size_t s1 = tk->init_state(); + + // Burn In + for (size_t i = 0; i < num_burnin; i++) { + s1 = mcmc_step(original_statevector, tk, gen, distrib, + s1); // Burn-in. + } + + // Sample + for (size_t i = 0; i < num_samples; i++) { + s1 = mcmc_step(original_statevector, tk, gen, distrib, s1); + + if (cache.contains(s1)) { + size_t cache_id = cache[s1]; + auto it_temp = samples.begin() + cache_id * num_qubits; + std::copy(it_temp, it_temp + num_qubits, + samples.begin() + i * num_qubits); + } + + // If not cached, compute + else { + for (size_t j = 0; j < num_qubits; j++) { + samples[i * num_qubits + (num_qubits - 1 - j)] = + (s1 >> j) & 1U; + } + cache[s1] = i; + } + } + return samples; } - return samples; - } - + /** * @brief Generate samples using the alias method. * Reference: https://en.wikipedia.org/wiki/Alias_method diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index bd4dd31675..407e85d059 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -5,66 +5,61 @@ #include #include #include +#include #include #include -#include #include "StateVectorManagedCPU.hpp" #include "StateVectorRawCPU.hpp" namespace Pennylane { - enum class TransitionKernelType {Local, NonRandom}; +enum class TransitionKernelType { Local, NonRandom }; - template - class TransitionKernel { +template class TransitionKernel { public: - virtual size_t init_state () = 0; - //outputs the next state and the qratio - virtual std::pair operator() (size_t) = 0; - }; + virtual size_t init_state() = 0; + // outputs the next state and the qratio + virtual std::pair operator()(size_t) = 0; +}; - template - class LocalTransitionKernel : public TransitionKernel { +template +class LocalTransitionKernel : public TransitionKernel { private: - std::random_device rd_; std::mt19937 gen_; std::uniform_int_distribution distrib_num_qubits_; std::uniform_int_distribution distrib_binary_; size_t num_qubits_; - + public: - LocalTransitionKernel(size_t num_qubits) { - num_qubits_ = num_qubits; - gen_ = std::mt19937(rd_()); - distrib_num_qubits_ = std::uniform_int_distribution(0,num_qubits-1); - distrib_binary_ = std::uniform_int_distribution(0,1); + num_qubits_ = num_qubits; + gen_ = std::mt19937(rd_()); + distrib_num_qubits_ = + std::uniform_int_distribution(0, num_qubits - 1); + distrib_binary_ = std::uniform_int_distribution(0, 1); } - size_t init_state(){ - return 0; - } - - std::pair operator() (size_t s1) { - size_t qubit_site = distrib_num_qubits_(gen_); - size_t qubit_value = distrib_binary_(gen_); - size_t current_bit = (s1 >> qubit_site) & 1; - - if (qubit_value == current_bit) - return std::pair(s1,1); - else if (current_bit == 0){ - return std::pair(s1+std::pow(2,qubit_site),1); - } - else { - return std::pair(s1-std::pow(2,qubit_site),1); - } + size_t init_state() { return 0; } + + std::pair operator()(size_t s1) { + size_t qubit_site = distrib_num_qubits_(gen_); + size_t qubit_value = distrib_binary_(gen_); + size_t current_bit = (s1 >> qubit_site) & 1; + + if (qubit_value == current_bit) + return std::pair(s1, 1); + else if (current_bit == 0) { + return std::pair(s1 + std::pow(2, qubit_site), 1); + } else { + return std::pair(s1 - std::pow(2, qubit_site), 1); + } } - }; +}; - template - class NonZeroRandomTransitionKernel : public TransitionKernel { +template +class NonZeroRandomTransitionKernel : public TransitionKernel { // : public TransitionKernel { private: std::random_device rd_; @@ -72,49 +67,46 @@ namespace Pennylane { std::uniform_int_distribution distrib_; size_t sv_length_; std::vector non_zeros_; - + public: - size_t init_state(){ - return 0; - } - - NonZeroRandomTransitionKernel(const std::complex* sv, size_t sv_length, fp_t min_error) { - auto data = sv; - sv_length_ = sv_length; - - //find nonzero candidates - for (size_t i = 0; i < sv_length_; i++){ - if (fabs(data[i].real()) > min_error || - fabs(data[i].imag()) > min_error){ - non_zeros_.push_back(i); - } - } - gen_ = std::mt19937(rd_()); - distrib_ = std::uniform_int_distribution(0,non_zeros_.size()-1); + size_t init_state() { return 0; } + + NonZeroRandomTransitionKernel(const std::complex *sv, + size_t sv_length, fp_t min_error) { + auto data = sv; + sv_length_ = sv_length; + + // find nonzero candidates + for (size_t i = 0; i < sv_length_; i++) { + if (fabs(data[i].real()) > min_error || + fabs(data[i].imag()) > min_error) { + non_zeros_.push_back(i); + } + } + gen_ = std::mt19937(rd_()); + distrib_ = + std::uniform_int_distribution(0, non_zeros_.size() - 1); } - - std::pair operator() ([[maybe_unused]] size_t s1) { - auto s2 = distrib_(gen_); - return std::pair(non_zeros_[s2],1); + + std::pair operator()([[maybe_unused]] size_t s1) { + auto s2 = distrib_(gen_); + return std::pair(non_zeros_[s2], 1); } - }; - - - template - std::unique_ptr> kernel_factory - ( - const TransitionKernelType kernel_type, - const std::complex* sv, - size_t num_qubits - ) - { +}; + +template +std::unique_ptr> +kernel_factory(const TransitionKernelType kernel_type, + const std::complex *sv, size_t num_qubits) { auto sv_length = Util::exp2(num_qubits); - if (kernel_type == TransitionKernelType::Local){ - return std::unique_ptr>(new NonZeroRandomTransitionKernel(sv,sv_length,std::numeric_limits::epsilon())); - } - else { //local is the default - return std::unique_ptr>(new LocalTransitionKernel(num_qubits)); + if (kernel_type == TransitionKernelType::Local) { + return std::unique_ptr>( + new NonZeroRandomTransitionKernel( + sv, sv_length, std::numeric_limits::epsilon())); + } else { // local is the default + return std::unique_ptr>( + new LocalTransitionKernel(num_qubits)); } - } } +} // namespace Pennylane diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp index 97fe8ac17b..09b22f8f80 100644 --- a/pennylane_lightning/src/tests/Test_Measures.cpp +++ b/pennylane_lightning/src/tests/Test_Measures.cpp @@ -196,7 +196,6 @@ TEMPLATE_TEST_CASE("Sample", "[Measures]", float, double) { } } - TEMPLATE_TEST_CASE("Sample with Metropolis", "[Measures]", float, double) { constexpr uint32_t twos[] = { 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, 1U << 4U, 1U << 5U, @@ -223,10 +222,8 @@ TEMPLATE_TEST_CASE("Sample with Metropolis", "[Measures]", float, double) { size_t num_samples = 100000; size_t num_burnin = 1000; - - auto &&samples = Measurer.generate_samples_metropolis(TransitionKernelType::Local, - num_burnin, - num_samples); + auto &&samples = Measurer.generate_samples_metropolis( + TransitionKernelType::Local, num_burnin, num_samples); std::vector counts(N, 0); std::vector samples_decimal(num_samples, 0); @@ -254,7 +251,6 @@ TEMPLATE_TEST_CASE("Sample with Metropolis", "[Measures]", float, double) { } } - TEMPLATE_TEST_CASE("Variances", "[Measures]", float, double) { // Defining the State Vector that will be measured. StateVectorManagedCPU Measured_StateVector = @@ -330,7 +326,4 @@ TEMPLATE_TEST_CASE("Variances", "[Measures]", float, double) { variances_ref = {0.6577942, 0.4068672, 0.1670374}; REQUIRE_THAT(variances, Catch::Approx(variances_ref).margin(1e-6)); } - - - } From d5d3ec0f8d56c452d9ff409c7b76e1be6ded1b2e Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Tue, 8 Nov 2022 16:55:22 -0500 Subject: [PATCH 07/53] Update pennylane_lightning/src/simulator/Measures.hpp Co-authored-by: Lee James O'Riordan --- pennylane_lightning/src/simulator/Measures.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index b2afa2e257..6f0e18e6a8 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -326,7 +326,7 @@ class Measures { auto s2_plog = log((sv.getData()[s2] * std::conj(sv.getData()[s2])).real()); - auto alph = std::min(1., qratio * exp(s2_plog - s1_plog)); + auto alph = std::min(1., qratio * exp(s2_plog - s1_plog)); auto ran = distrib(gen); if (ran < alph) { From b475961838d8da5726f30cf787ffb4e91b594b00 Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Wed, 9 Nov 2022 14:04:25 +0000 Subject: [PATCH 08/53] Auto update version --- pennylane_lightning/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/_version.py b/pennylane_lightning/_version.py index eb70131508..4a0f24e318 100644 --- a/pennylane_lightning/_version.py +++ b/pennylane_lightning/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.27.0-dev16" +__version__ = "0.27.0-dev17" From 08f14b39b186281746456979e75726627da409ac Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Mon, 14 Nov 2022 03:41:59 -0500 Subject: [PATCH 09/53] Add comments --- .../src/simulator/Measures.hpp | 36 +++++++++++++++---- .../src/simulator/TransitionKernels.hpp | 31 +++++++++++++++- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 6f0e18e6a8..c9ae7c86b1 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -310,10 +310,21 @@ class Measures { return expected_value_list; }; - size_t mcmc_step(const SVType &sv, - std::unique_ptr> &tk, - std::mt19937 &gen, - std::uniform_real_distribution &distrib, size_t s1) { + /** + * @brief Complete a single Metropolis-Hastings step. + * + * @param sv state vector + * @param tk User-defined functor for producing transitions + * between metropolis states. + * @param gen Random number generator. + * @param distrib Random number distribution. + * @param s1 initial state + */ + size_t metropolis_step(const SVType &sv, + std::unique_ptr> &tk, + std::mt19937 &gen, + std::uniform_real_distribution &distrib, + size_t s1) { auto s1_plog = log((sv.getData()[s1] * std::conj(sv.getData()[s1])).real()); @@ -336,6 +347,17 @@ class Measures { } } + /** + * @brief Generate samples using the Metropolis-Hastings method. + * Reference: Numerical Recipes, NetKet paper + * + * @param transition_kernel User-defined functor for producing transitions + * between metropolis states. + * @param num_burnin Number of Metropolis burn-in steps. + * @param num_samples The number of samples to generate. + * @return 1-D vector of samples in binary, each sample is + * separated by a stride equal to the number of qubits. + */ std::vector generate_samples_metropolis(const TransitionKernelType &transition_kernel, size_t num_burnin, size_t num_samples) { @@ -353,13 +375,13 @@ class Measures { // Burn In for (size_t i = 0; i < num_burnin; i++) { - s1 = mcmc_step(original_statevector, tk, gen, distrib, - s1); // Burn-in. + s1 = metropolis_step(original_statevector, tk, gen, distrib, + s1); // Burn-in. } // Sample for (size_t i = 0; i < num_samples; i++) { - s1 = mcmc_step(original_statevector, tk, gen, distrib, s1); + s1 = metropolis_step(original_statevector, tk, gen, distrib, s1); if (cache.contains(s1)) { size_t cache_id = cache[s1]; diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 407e85d059..9d957fdd13 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -16,6 +16,11 @@ namespace Pennylane { enum class TransitionKernelType { Local, NonRandom }; +/** + * @brief Parent class to define interface for Transition Kernel + * + * @tparam fp_t Floating point precision of underlying measurements. + */ template class TransitionKernel { public: virtual size_t init_state() = 0; @@ -23,6 +28,14 @@ template class TransitionKernel { virtual std::pair operator()(size_t) = 0; }; +/** + * @brief Transition Kernel for a 'SpinFlip' local transition between states + * + * This class implements a local transition kernel for a spin flip operation. + * It goes about this by generating a random qubit site and then generating + * a random number to determine the new bit at that qubit site. + * @tparam fp_t Floating point precision of underlying measurements. + */ template class LocalTransitionKernel : public TransitionKernel { private: @@ -58,9 +71,16 @@ class LocalTransitionKernel : public TransitionKernel { } }; +/** + * @brief Transition Kernel for a random transition between non-zero states + * + * This class randomly transitions between states that have nonzero probability. + * To determine the states with non-zero probability we have O(2^num_qubits) + * overhead. Despite this, this method is still fast. This transition kernel + * can sample even GHZ states. + */ template class NonZeroRandomTransitionKernel : public TransitionKernel { - // : public TransitionKernel { private: std::random_device rd_; std::mt19937 gen_; @@ -94,6 +114,15 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { } }; +/** + * @brief Factory function to create a transition kernel + * + * @param kernel_type Type of transition kernel to create + * @param sv pointer to the statevector data + * @param num_qubits number of qubits + * @tparam fp_t Floating point precision of underlying measurements. + * @return std::unique_ptr of the transition kernel + */ template std::unique_ptr> kernel_factory(const TransitionKernelType kernel_type, From 8736d60e56bb2c1e7e4a3c1825516830198c78e2 Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Mon, 14 Nov 2022 04:16:44 -0500 Subject: [PATCH 10/53] Add initializer list --- .../src/simulator/TransitionKernels.hpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 9d957fdd13..08a224be32 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -46,13 +46,11 @@ class LocalTransitionKernel : public TransitionKernel { size_t num_qubits_; public: - LocalTransitionKernel(size_t num_qubits) { - num_qubits_ = num_qubits; - gen_ = std::mt19937(rd_()); - distrib_num_qubits_ = - std::uniform_int_distribution(0, num_qubits - 1); - distrib_binary_ = std::uniform_int_distribution(0, 1); - } + LocalTransitionKernel(size_t num_qubits) + : num_qubits_(num_qubits), gen_(std::mt19937(rd_())), + distrib_num_qubits_( + std::uniform_int_distribution(0, num_qubits - 1)), + distrib_binary_(std::uniform_int_distribution(0, 1)) {} size_t init_state() { return 0; } From 7ce3a7e36e65c715e0188e527106461fb5bbfc0a Mon Sep 17 00:00:00 2001 From: Trevor Vincent Date: Mon, 14 Nov 2022 04:20:04 -0500 Subject: [PATCH 11/53] Add test for other transition kernel --- .../src/simulator/TransitionKernels.hpp | 2 +- .../src/tests/Test_Measures.cpp | 59 ++++++++++++++++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 08a224be32..769faf7fa4 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -14,7 +14,7 @@ namespace Pennylane { -enum class TransitionKernelType { Local, NonRandom }; +enum class TransitionKernelType { Local, NonZeroRandom }; /** * @brief Parent class to define interface for Transition Kernel diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp index 09b22f8f80..9fb9d40a40 100644 --- a/pennylane_lightning/src/tests/Test_Measures.cpp +++ b/pennylane_lightning/src/tests/Test_Measures.cpp @@ -196,7 +196,8 @@ TEMPLATE_TEST_CASE("Sample", "[Measures]", float, double) { } } -TEMPLATE_TEST_CASE("Sample with Metropolis", "[Measures]", float, double) { +TEMPLATE_TEST_CASE("Sample with Metropolis (Local Kernel)", "[Measures]", float, + double) { constexpr uint32_t twos[] = { 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, 1U << 4U, 1U << 5U, 1U << 6U, 1U << 7U, 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U, @@ -251,6 +252,62 @@ TEMPLATE_TEST_CASE("Sample with Metropolis", "[Measures]", float, double) { } } +TEMPLATE_TEST_CASE("Sample with Metropolis (NonZeroRandom Kernel)", + "[Measures]", float, double) { + constexpr uint32_t twos[] = { + 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, 1U << 4U, 1U << 5U, + 1U << 6U, 1U << 7U, 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U, + 1U << 12U, 1U << 13U, 1U << 14U, 1U << 15U, 1U << 16U, 1U << 17U, + 1U << 18U, 1U << 19U, 1U << 20U, 1U << 21U, 1U << 22U, 1U << 23U, + 1U << 24U, 1U << 25U, 1U << 26U, 1U << 27U, 1U << 28U, 1U << 29U, + 1U << 30U, 1U << 31U}; + + // Defining the State Vector that will be measured. + StateVectorManagedCPU Measured_StateVector = + Initializing_StateVector(); + + // Initializing the measures class. + // This object attaches to the statevector allowing several measures. + Measures> Measurer( + Measured_StateVector); + vector expected_probabilities = { + 0.67078706, 0.03062806, 0.0870997, 0.00397696, + 0.17564072, 0.00801973, 0.02280642, 0.00104134}; + + size_t num_qubits = 3; + size_t N = std::pow(2, num_qubits); + size_t num_samples = 100000; + size_t num_burnin = 1000; + + auto &&samples = Measurer.generate_samples_metropolis( + TransitionKernelType::NonZeroRandom, num_burnin, num_samples); + + std::vector counts(N, 0); + std::vector samples_decimal(num_samples, 0); + + // convert samples to decimal and then bin them in counts + for (size_t i = 0; i < num_samples; i++) { + for (size_t j = 0; j < num_qubits; j++) { + if (samples[i * num_qubits + j] != 0) { + samples_decimal[i] += twos[(num_qubits - 1 - j)]; + } + } + counts[samples_decimal[i]] += 1; + } + + // compute estimated probabilities from histogram + std::vector probabilities(counts.size()); + for (size_t i = 0; i < counts.size(); i++) { + probabilities[i] = counts[i] / (TestType)num_samples; + } + + // compare estimated probabilities to real probabilities + SECTION("No wires provided:") { + REQUIRE_THAT(probabilities, + Catch::Approx(expected_probabilities).margin(.05)); + } +} + TEMPLATE_TEST_CASE("Variances", "[Measures]", float, double) { // Defining the State Vector that will be measured. StateVectorManagedCPU Measured_StateVector = From 60f6f662c3dbb058d8f4b0ff804622dc6e4684dd Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Tue, 15 Nov 2022 14:03:28 +0000 Subject: [PATCH 12/53] fix instantiation errors --- pennylane_lightning/src/simulator/CMakeLists.txt | 2 +- .../src/simulator/TransitionKernels.cpp | 10 +++++++--- .../src/simulator/TransitionKernels.hpp | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pennylane_lightning/src/simulator/CMakeLists.txt b/pennylane_lightning/src/simulator/CMakeLists.txt index e1ea946e93..f4f80d4e37 100644 --- a/pennylane_lightning/src/simulator/CMakeLists.txt +++ b/pennylane_lightning/src/simulator/CMakeLists.txt @@ -1,6 +1,6 @@ project(lightning_simulator) -set(SIMULATOR_FILES StateVectorRawCPU.cpp Observables.cpp StateVectorManagedCPU.cpp Measures.cpp CACHE INTERNAL "" FORCE) +set(SIMULATOR_FILES StateVectorRawCPU.cpp Observables.cpp StateVectorManagedCPU.cpp TransitionKernels.cpp Measures.cpp CACHE INTERNAL "" FORCE) add_library(lightning_simulator STATIC ${SIMULATOR_FILES}) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.cpp b/pennylane_lightning/src/simulator/TransitionKernels.cpp index a706eda2d4..d426e367c3 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.cpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.cpp @@ -1,5 +1,9 @@ -#include "StateVectorRawCPU.hpp" +#include "TransitionKernels.hpp" // explicit instantiation -template class Pennylane::StateVectorRawCPU; -template class Pennylane::StateVectorRawCPU; +template class Pennylane::TransitionKernel; +template class Pennylane::TransitionKernel; +template class Pennylane::LocalTransitionKernel; +template class Pennylane::LocalTransitionKernel; +template class Pennylane::NonZeroRandomTransitionKernel; +template class Pennylane::NonZeroRandomTransitionKernel; diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 769faf7fa4..e7447a188d 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -39,11 +39,11 @@ template class TransitionKernel { template class LocalTransitionKernel : public TransitionKernel { private: + size_t num_qubits_; std::random_device rd_; std::mt19937 gen_; std::uniform_int_distribution distrib_num_qubits_; std::uniform_int_distribution distrib_binary_; - size_t num_qubits_; public: LocalTransitionKernel(size_t num_qubits) From f9eaf240fe66b9ecba5961c692ea59109fd2362d Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Tue, 15 Nov 2022 14:18:40 +0000 Subject: [PATCH 13/53] Auto update version --- pennylane_lightning/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/_version.py b/pennylane_lightning/_version.py index 1632b972c8..0eb6948f91 100644 --- a/pennylane_lightning/_version.py +++ b/pennylane_lightning/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.28.0-dev" +__version__ = "0.28.0-dev1" From 851c8a8f9235dc2b7c82ef9a0c1cbf0b55e18f3e Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Tue, 15 Nov 2022 22:18:28 +0000 Subject: [PATCH 14/53] add python layer --- .github/CHANGELOG.md | 4 + pennylane_lightning/lightning_qubit.py | 26 ++++ pennylane_lightning/src/bindings/Bindings.cpp | 26 ++++ tests/test_measures.py | 112 ++++++++++++++++++ 4 files changed, 168 insertions(+) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index f17c7c61f4..15b53c1939 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -2,6 +2,9 @@ ### New features since last release +* Add MCMC sampler. +[(#384)] (https://github.com/PennyLaneAI/pennylane-lightning/pull/384) + ### Breaking changes ### Improvements @@ -14,6 +17,7 @@ This release contains contributions from (in alphabetical order): +Shuli Shu, Trevor Vincent --- # Release 0.27.0 diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 6ee8da254f..7c59e6c69a 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -782,6 +782,32 @@ def generate_samples(self): return M.generate_samples(len(self.wires), self.shots).astype(int, copy=False) + def generate_mcmc_samples(self, kernel_name="Local", num_burnin=100): + """Generate Markov chain Monte Carlo(MCMC) samples + Args: + kernel_name (str): name of transition kernel. + num_burnin (int): number of steps that will be dropped. + + Returns: + array[int]: array of samples in binary representation with shape ``(dev.shots, dev.num_wires)`` + """ + if kernel_name not in [ + "Local", + "NonZeroRandom", + ]: + raise NotImplementedError( + f"The {kernel_name} is not supported and currently only 'Local' and 'NonZeroRandom' kernels are supported." + ) + # Initialization of state + ket = np.ravel(self._state) + + state_vector = StateVectorC64(ket) if self.use_csingle else StateVectorC128(ket) + M = MeasuresC64(state_vector) if self.use_csingle else MeasuresC128(state_vector) + + return M.generate_mcmc_samples(len(self.wires), kernel_name, num_burnin, self.shots).astype( + int, copy=False + ) + def expval(self, observable, shot_range=None, bin_size=None): """Expectation value of the supplied observable. diff --git a/pennylane_lightning/src/bindings/Bindings.cpp b/pennylane_lightning/src/bindings/Bindings.cpp index 92caecefe9..3a374796af 100644 --- a/pennylane_lightning/src/bindings/Bindings.cpp +++ b/pennylane_lightning/src/bindings/Bindings.cpp @@ -134,6 +134,32 @@ void lightning_class_bindings(py::module_ &m) { strides /* strides for each axis */ )); }) + .def("generate_mcmc_samples", + [](Measures &M, size_t num_wires, + const std::string &kernelname, size_t num_burnin, + size_t num_shots) { + TransitionKernelType kerneltype = + Pennylane::TransitionKernelType::Local; + if (kernelname == "NonZeroRandom") + kerneltype = + Pennylane::TransitionKernelType::NonZeroRandom; + auto &&result = M.generate_samples_metropolis( + kerneltype, num_burnin, num_shots); + + const size_t ndim = 2; + const std::vector shape{num_shots, num_wires}; + constexpr auto sz = sizeof(size_t); + const std::vector strides{sz * num_wires, sz}; + // return 2-D NumPy array + return py::array(py::buffer_info( + result.data(), /* data as contiguous array */ + sz, /* size of one scalar */ + py::format_descriptor::format(), /* data type */ + ndim, /* number of dimensions */ + shape, /* shape of the matrix */ + strides /* strides for each axis */ + )); + }) .def("var", [](Measures &M, const std::string &operation, const std::vector &wires) { return M.var(operation, wires); diff --git a/tests/test_measures.py b/tests/test_measures.py index 690d9c1995..e788686ab4 100644 --- a/tests/test_measures.py +++ b/tests/test_measures.py @@ -560,6 +560,118 @@ def test_sample_values(self, dev, tol): assert np.allclose(s1**2, 1, atol=tol, rtol=0) +class TestMCMCSample: + """Tests that samples are properly calculated.""" + + @pytest.fixture(params=[np.complex64, np.complex128]) + def dev(self, request): + return qml.device("lightning.qubit", wires=2, shots=1000, c_dtype=request.param) + + def test_mcmc_sample_dimensions(self, dev): + """Tests if the samples returned by sample have + the correct dimensions + """ + + dev.apply([qml.RX(1.5708, wires=[0]), qml.RX(1.5708, wires=[1])]) + + kernel = "Local" + num_burnin = 10 + dev.shots = 10 + dev._wires_measured = {0} + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + s1 = dev.sample(qml.PauliZ(wires=[0])) + assert np.array_equal(s1.shape, (10,)) + + dev.reset() + kernel = "Local" + num_burnin = 12 + dev.shots = 12 + dev._wires_measured = {1} + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + s2 = dev.sample(qml.PauliZ(wires=[1])) + assert np.array_equal(s2.shape, (12,)) + + dev.reset() + kernel = "Local" + num_burnin = 17 + dev.shots = 17 + dev._wires_measured = {0, 1} + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + s3 = dev.sample(qml.PauliX(0) @ qml.PauliZ(1)) + assert np.array_equal(s3.shape, (17,)) + + dev.reset() + kernel = "NonZeroRandom" + num_burnin = 10 + dev.shots = 10 + dev._wires_measured = {0} + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + s2 = dev.sample(qml.PauliZ(wires=[0])) + assert np.array_equal(s2.shape, (10,)) + + dev.reset() + kernel = "NonZeroRandom" + num_burnin = 12 + dev.shots = 12 + dev._wires_measured = {1} + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + s2 = dev.sample(qml.PauliZ(wires=[1])) + assert np.array_equal(s2.shape, (12,)) + + dev.reset() + kernel = "NonZeroRandom" + num_burnin = 17 + dev.shots = 17 + dev._wires_measured = {0, 1} + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + s3 = dev.sample(qml.PauliX(0) @ qml.PauliZ(1)) + assert np.array_equal(s3.shape, (17,)) + + def test_sample_values(self, dev, tol): + """Tests if the samples returned by sample have + the correct values + """ + + dev.apply([qml.RX(1.5708, wires=[0])]) + kernel = "Local" + num_burnin = 100 + dev._wires_measured = {0} + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + + s1 = dev.sample(qml.PauliZ(0)) + + # s1 should only contain 1 and -1, which is guaranteed if + # they square to 1 + assert np.allclose(s1**2, 1, atol=tol, rtol=0) + + dev.reset() + kernel = "NonZeroRandom" + num_burnin = 100 + dev._wires_measured = {0} + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + + s1 = dev.sample(qml.PauliZ(0)) + + # s1 should only contain 1 and -1, which is guaranteed if + # they square to 1 + assert np.allclose(s1**2, 1, atol=tol, rtol=0) + + def test_unsupported_sample_kernels(self, dev, tol): + """Tests if the samples returned by sample have + the correct values + """ + + dev.apply([qml.RX(1.5708, wires=[0])]) + kernel = "Global" + num_burnin = 100 + dev._wires_measured = {0} + with pytest.raises( + NotImplementedError, + match=f"The {kernel} is not supported and currently only 'Local' and 'NonZeroRandom' kernels are supported.", + ): + dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + + class TestWiresInVar: """Test different Wires settings in Lightning's var.""" From 5c462dcf0b934232fd78a6a047046254abcef8a4 Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Wed, 16 Nov 2022 00:28:20 +0000 Subject: [PATCH 15/53] remove init_state --- pennylane_lightning/src/simulator/Measures.hpp | 3 ++- .../src/simulator/TransitionKernels.hpp | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index c9ae7c86b1..b75b1178bf 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -371,7 +371,8 @@ class Measures { auto tk = kernel_factory(transition_kernel, original_statevector.getData(), original_statevector.getNumQubits()); - size_t s1 = tk->init_state(); + size_t s1 = 0; + // size_t s1 = tk->init_state(); // Burn In for (size_t i = 0; i < num_burnin; i++) { diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index e7447a188d..56d48c9355 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -23,8 +23,8 @@ enum class TransitionKernelType { Local, NonZeroRandom }; */ template class TransitionKernel { public: - virtual size_t init_state() = 0; - // outputs the next state and the qratio + // virtual size_t init_state() = 0; + // outputs the next state and the qratio virtual std::pair operator()(size_t) = 0; }; @@ -46,18 +46,18 @@ class LocalTransitionKernel : public TransitionKernel { std::uniform_int_distribution distrib_binary_; public: - LocalTransitionKernel(size_t num_qubits) + explicit LocalTransitionKernel(size_t num_qubits) : num_qubits_(num_qubits), gen_(std::mt19937(rd_())), distrib_num_qubits_( std::uniform_int_distribution(0, num_qubits - 1)), distrib_binary_(std::uniform_int_distribution(0, 1)) {} - size_t init_state() { return 0; } + // size_t init_state() override { return 0; } std::pair operator()(size_t s1) { size_t qubit_site = distrib_num_qubits_(gen_); size_t qubit_value = distrib_binary_(gen_); - size_t current_bit = (s1 >> qubit_site) & 1; + size_t current_bit = ((unsigned)s1 >> qubit_site) & 1; if (qubit_value == current_bit) return std::pair(s1, 1); @@ -87,7 +87,7 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { std::vector non_zeros_; public: - size_t init_state() { return 0; } + // size_t init_state() override { return 0; } NonZeroRandomTransitionKernel(const std::complex *sv, size_t sv_length, fp_t min_error) { From f6e0855d640e357e5fbe4cf7dfd21644d64240c9 Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Wed, 16 Nov 2022 01:17:23 +0000 Subject: [PATCH 16/53] clean code --- .../src/simulator/Measures.hpp | 7 ++--- .../src/simulator/TransitionKernels.hpp | 28 ++++++++----------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index b75b1178bf..8d043788eb 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -326,7 +326,7 @@ class Measures { std::uniform_real_distribution &distrib, size_t s1) { auto s1_plog = - log((sv.getData()[s1] * std::conj(sv.getData()[s1])).real()); + std::log((sv.getData()[s1] * std::conj(sv.getData()[s1])).real()); auto s1_qratio = tk->operator()(s1); @@ -335,16 +335,15 @@ class Measures { auto &qratio = s1_qratio.second; auto s2_plog = - log((sv.getData()[s2] * std::conj(sv.getData()[s2])).real()); + std::log((sv.getData()[s2] * std::conj(sv.getData()[s2])).real()); auto alph = std::min(1., qratio * exp(s2_plog - s1_plog)); auto ran = distrib(gen); if (ran < alph) { return s2; - } else { - return s1; } + return s1; } /** diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 56d48c9355..f7b7c927c6 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -23,7 +23,6 @@ enum class TransitionKernelType { Local, NonZeroRandom }; */ template class TransitionKernel { public: - // virtual size_t init_state() = 0; // outputs the next state and the qratio virtual std::pair operator()(size_t) = 0; }; @@ -52,20 +51,18 @@ class LocalTransitionKernel : public TransitionKernel { std::uniform_int_distribution(0, num_qubits - 1)), distrib_binary_(std::uniform_int_distribution(0, 1)) {} - // size_t init_state() override { return 0; } - - std::pair operator()(size_t s1) { + std::pair operator()(size_t s1) final { size_t qubit_site = distrib_num_qubits_(gen_); size_t qubit_value = distrib_binary_(gen_); - size_t current_bit = ((unsigned)s1 >> qubit_site) & 1; + size_t current_bit = ((unsigned)s1 >> (unsigned)qubit_site) & 1u; - if (qubit_value == current_bit) + if (qubit_value == current_bit) { return std::pair(s1, 1); - else if (current_bit == 0) { + } + if (current_bit == 0) { return std::pair(s1 + std::pow(2, qubit_site), 1); - } else { - return std::pair(s1 - std::pow(2, qubit_site), 1); } + return std::pair(s1 - std::pow(2, qubit_site), 1); } }; @@ -87,8 +84,6 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { std::vector non_zeros_; public: - // size_t init_state() override { return 0; } - NonZeroRandomTransitionKernel(const std::complex *sv, size_t sv_length, fp_t min_error) { auto data = sv; @@ -96,8 +91,8 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { // find nonzero candidates for (size_t i = 0; i < sv_length_; i++) { - if (fabs(data[i].real()) > min_error || - fabs(data[i].imag()) > min_error) { + if (std::fabs(data[i].real()) > min_error || + std::fabs(data[i].imag()) > min_error) { non_zeros_.push_back(i); } } @@ -106,7 +101,7 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { std::uniform_int_distribution(0, non_zeros_.size() - 1); } - std::pair operator()([[maybe_unused]] size_t s1) { + std::pair operator()([[maybe_unused]] size_t s1) final { auto s2 = distrib_(gen_); return std::pair(non_zeros_[s2], 1); } @@ -131,9 +126,8 @@ kernel_factory(const TransitionKernelType kernel_type, return std::unique_ptr>( new NonZeroRandomTransitionKernel( sv, sv_length, std::numeric_limits::epsilon())); - } else { // local is the default - return std::unique_ptr>( - new LocalTransitionKernel(num_qubits)); } + return std::unique_ptr>( + new LocalTransitionKernel(num_qubits)); } } // namespace Pennylane From a7c5cb07c4d745f8c05826f8081337eaacaa7d2a Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Wed, 16 Nov 2022 01:32:40 +0000 Subject: [PATCH 17/53] code clean --- pennylane_lightning/src/simulator/Measures.hpp | 2 +- pennylane_lightning/src/simulator/TransitionKernels.hpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 8d043788eb..89f65a3855 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -337,7 +337,7 @@ class Measures { auto s2_plog = std::log((sv.getData()[s2] * std::conj(sv.getData()[s2])).real()); - auto alph = std::min(1., qratio * exp(s2_plog - s1_plog)); + auto alph = std::min(1., qratio * std::exp(s2_plog - s1_plog)); auto ran = distrib(gen); if (ran < alph) { diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index f7b7c927c6..b91eec1183 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -54,7 +54,7 @@ class LocalTransitionKernel : public TransitionKernel { std::pair operator()(size_t s1) final { size_t qubit_site = distrib_num_qubits_(gen_); size_t qubit_value = distrib_binary_(gen_); - size_t current_bit = ((unsigned)s1 >> (unsigned)qubit_site) & 1u; + size_t current_bit = ((unsigned)s1 >> (unsigned)qubit_site) & 1U; if (qubit_value == current_bit) { return std::pair(s1, 1); @@ -117,9 +117,9 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { * @return std::unique_ptr of the transition kernel */ template -std::unique_ptr> -kernel_factory(const TransitionKernelType kernel_type, - const std::complex *sv, size_t num_qubits) { +// std::unique_ptr> +auto kernel_factory(const TransitionKernelType kernel_type, + const std::complex *sv, size_t num_qubits) { auto sv_length = Util::exp2(num_qubits); if (kernel_type == TransitionKernelType::Local) { From b4823a5f48e419fc3bfff136fac8ac3cdb3257ec Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Wed, 16 Nov 2022 02:05:57 +0000 Subject: [PATCH 18/53] add destructor to transitional kernels --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index b91eec1183..31d5810f0a 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -25,6 +25,7 @@ template class TransitionKernel { public: // outputs the next state and the qratio virtual std::pair operator()(size_t) = 0; + virtual ~TransitionKernel()=default; }; /** @@ -124,10 +125,12 @@ auto kernel_factory(const TransitionKernelType kernel_type, auto sv_length = Util::exp2(num_qubits); if (kernel_type == TransitionKernelType::Local) { return std::unique_ptr>( + // return std::make_unique>( new NonZeroRandomTransitionKernel( sv, sv_length, std::numeric_limits::epsilon())); } return std::unique_ptr>( + // return std::make_unique>( new LocalTransitionKernel(num_qubits)); } } // namespace Pennylane From 86d80b7129601f3e5f0f9333a09d39d732d1f96c Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Wed, 16 Nov 2022 02:15:31 +0000 Subject: [PATCH 19/53] add constructor to TransitionKernel --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 31d5810f0a..7c50051fc9 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -23,9 +23,14 @@ enum class TransitionKernelType { Local, NonZeroRandom }; */ template class TransitionKernel { public: + TransitionKernel() = default; + TransitionKernel(const TransitionKernel &) = default; + TransitionKernel(TransitionKernel &&) noexcept = default; + TransitionKernel &operator=(const TransitionKernel &) = default; + TransitionKernel &operator=(TransitionKernel &&) noexcept = default; // outputs the next state and the qratio virtual std::pair operator()(size_t) = 0; - virtual ~TransitionKernel()=default; + virtual ~TransitionKernel() = default; }; /** From aae4fe5216edcff864a41c29887af1543bcc7719 Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Wed, 16 Nov 2022 02:28:53 +0000 Subject: [PATCH 20/53] further clean code --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 7c50051fc9..abb3cb1a4c 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -94,7 +94,6 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { size_t sv_length, fp_t min_error) { auto data = sv; sv_length_ = sv_length; - // find nonzero candidates for (size_t i = 0; i < sv_length_; i++) { if (std::fabs(data[i].real()) > min_error || @@ -123,19 +122,17 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { * @return std::unique_ptr of the transition kernel */ template -// std::unique_ptr> -auto kernel_factory(const TransitionKernelType kernel_type, - const std::complex *sv, size_t num_qubits) { +std::unique_ptr> +kernel_factory(const TransitionKernelType kernel_type, + const std::complex *sv, size_t num_qubits) { auto sv_length = Util::exp2(num_qubits); if (kernel_type == TransitionKernelType::Local) { return std::unique_ptr>( - // return std::make_unique>( new NonZeroRandomTransitionKernel( sv, sv_length, std::numeric_limits::epsilon())); } return std::unique_ptr>( - // return std::make_unique>( new LocalTransitionKernel(num_qubits)); } } // namespace Pennylane From d22b97e011065bde30a8a6198e8b9552b136bfc6 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 07:44:20 -0500 Subject: [PATCH 21/53] add more tests for codecov --- pennylane_lightning/src/tests/TestHelpers.hpp | 37 ++++++++++++ .../src/tests/Test_Measures.cpp | 57 +++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/pennylane_lightning/src/tests/TestHelpers.hpp b/pennylane_lightning/src/tests/TestHelpers.hpp index acdf740705..e2c23547fe 100644 --- a/pennylane_lightning/src/tests/TestHelpers.hpp +++ b/pennylane_lightning/src/tests/TestHelpers.hpp @@ -395,6 +395,43 @@ StateVectorManagedCPU Initializing_StateVector(size_t num_qubits = 3) { return Measured_StateVector; } +/** + * @brief Initialize the statevector in a non-trivial configuration. + * + * @tparam T statevector float point precision. + * @param num_qubits number of qubits + * @return StateVectorManaged + */ +template +StateVectorManagedCPU Initializing_StateVector_Imag(size_t num_qubits = 3) { + size_t data_size = Util::exp2(num_qubits); + + std::vector> arr(data_size, 0); + arr[0] = {0,1}; + StateVectorManagedCPU Measured_StateVector(arr.data(), data_size); + + std::vector gates; + std::vector> wires; + std::vector inv_op(num_qubits * 2, false); + std::vector> phase; + + T initial_phase = 0.7; + for (size_t n_qubit = 0; n_qubit < num_qubits; n_qubit++) { + gates.emplace_back("RX"); + gates.emplace_back("RY"); + + wires.push_back({n_qubit}); + wires.push_back({n_qubit}); + + phase.push_back({initial_phase}); + phase.push_back({initial_phase}); + initial_phase -= 0.2; + } + Measured_StateVector.applyOperations(gates, wires, inv_op, phase); + + return Measured_StateVector; +} + /** * @brief Fills the empty vectors with the CSR (Compressed Sparse Row) sparse * matrix representation for a tridiagonal + periodic boundary conditions diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp index 9fb9d40a40..69192bb268 100644 --- a/pennylane_lightning/src/tests/Test_Measures.cpp +++ b/pennylane_lightning/src/tests/Test_Measures.cpp @@ -308,6 +308,63 @@ TEMPLATE_TEST_CASE("Sample with Metropolis (NonZeroRandom Kernel)", } } +TEMPLATE_TEST_CASE("Sample with Metropolis (Local Kernel) with different initial sv", "[Measures]", float, + double) { + constexpr uint32_t twos[] = { + 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, 1U << 4U, 1U << 5U, + 1U << 6U, 1U << 7U, 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U, + 1U << 12U, 1U << 13U, 1U << 14U, 1U << 15U, 1U << 16U, 1U << 17U, + 1U << 18U, 1U << 19U, 1U << 20U, 1U << 21U, 1U << 22U, 1U << 23U, + 1U << 24U, 1U << 25U, 1U << 26U, 1U << 27U, 1U << 28U, 1U << 29U, + 1U << 30U, 1U << 31U}; + + // Defining the State Vector that will be measured. + StateVectorManagedCPU Measured_StateVector = + Initializing_StateVector_Imag(); + + // Initializing the measures class. + // This object attaches to the statevector allowing several measures. + Measures> Measurer( + Measured_StateVector); + vector expected_probabilities = { + 0.67078706, 0.03062806, 0.0870997, 0.00397696, + 0.17564072, 0.00801973, 0.02280642, 0.00104134}; + + size_t num_qubits = 3; + size_t N = std::pow(2, num_qubits); + size_t num_samples = 100000; + size_t num_burnin = 1000; + + auto &&samples = Measurer.generate_samples_metropolis( + TransitionKernelType::Local, num_burnin, num_samples); + + std::vector counts(N, 0); + std::vector samples_decimal(num_samples, 0); + + // convert samples to decimal and then bin them in counts + for (size_t i = 0; i < num_samples; i++) { + for (size_t j = 0; j < num_qubits; j++) { + if (samples[i * num_qubits + j] != 0) { + samples_decimal[i] += twos[(num_qubits - 1 - j)]; + } + } + counts[samples_decimal[i]] += 1; + } + + // compute estimated probabilities from histogram + std::vector probabilities(counts.size()); + for (size_t i = 0; i < counts.size(); i++) { + probabilities[i] = counts[i] / (TestType)num_samples; + } + + // compare estimated probabilities to real probabilities + SECTION("No wires provided:") { + REQUIRE_THAT(probabilities, + Catch::Approx(expected_probabilities).margin(.05)); + } +} + + TEMPLATE_TEST_CASE("Variances", "[Measures]", float, double) { // Defining the State Vector that will be measured. StateVectorManagedCPU Measured_StateVector = From 2b64c3155d5938520f3d9dd2ae1447ad1e2cd467 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 08:28:44 -0500 Subject: [PATCH 22/53] codecov fix test --- pennylane_lightning/src/tests/TestHelpers.hpp | 2 +- pennylane_lightning/src/tests/Test_Measures.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pennylane_lightning/src/tests/TestHelpers.hpp b/pennylane_lightning/src/tests/TestHelpers.hpp index e2c23547fe..942a47bffc 100644 --- a/pennylane_lightning/src/tests/TestHelpers.hpp +++ b/pennylane_lightning/src/tests/TestHelpers.hpp @@ -407,7 +407,7 @@ StateVectorManagedCPU Initializing_StateVector_Imag(size_t num_qubits = 3) { size_t data_size = Util::exp2(num_qubits); std::vector> arr(data_size, 0); - arr[0] = {0,1}; + arr[0] = {0, 1}; StateVectorManagedCPU Measured_StateVector(arr.data(), data_size); std::vector gates; diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp index 69192bb268..aa0e17f294 100644 --- a/pennylane_lightning/src/tests/Test_Measures.cpp +++ b/pennylane_lightning/src/tests/Test_Measures.cpp @@ -308,8 +308,9 @@ TEMPLATE_TEST_CASE("Sample with Metropolis (NonZeroRandom Kernel)", } } -TEMPLATE_TEST_CASE("Sample with Metropolis (Local Kernel) with different initial sv", "[Measures]", float, - double) { +TEMPLATE_TEST_CASE( + "Sample with Metropolis (NonZeroRandom Kernel) with different initial sv", + "[Measures]", float, double) { constexpr uint32_t twos[] = { 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, 1U << 4U, 1U << 5U, 1U << 6U, 1U << 7U, 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U, @@ -336,7 +337,7 @@ TEMPLATE_TEST_CASE("Sample with Metropolis (Local Kernel) with different initial size_t num_burnin = 1000; auto &&samples = Measurer.generate_samples_metropolis( - TransitionKernelType::Local, num_burnin, num_samples); + TransitionKernelType::NonZeroRandom, num_burnin, num_samples); std::vector counts(N, 0); std::vector samples_decimal(num_samples, 0); @@ -364,7 +365,6 @@ TEMPLATE_TEST_CASE("Sample with Metropolis (Local Kernel) with different initial } } - TEMPLATE_TEST_CASE("Variances", "[Measures]", float, double) { // Defining the State Vector that will be measured. StateVectorManagedCPU Measured_StateVector = From 5eb235384f95b3cdf46dc0ea40b1a819bc143d14 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 08:53:02 -0500 Subject: [PATCH 23/53] fix in testhelper --- pennylane_lightning/src/tests/TestHelpers.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pennylane_lightning/src/tests/TestHelpers.hpp b/pennylane_lightning/src/tests/TestHelpers.hpp index 942a47bffc..c6a9e5032d 100644 --- a/pennylane_lightning/src/tests/TestHelpers.hpp +++ b/pennylane_lightning/src/tests/TestHelpers.hpp @@ -369,8 +369,8 @@ template StateVectorManagedCPU Initializing_StateVector(size_t num_qubits = 3) { size_t data_size = Util::exp2(num_qubits); - std::vector> arr(data_size, 0); - arr[0] = 1; + std::vector> arr(data_size, {0, 0}); + arr[0] = {1, 0}; StateVectorManagedCPU Measured_StateVector(arr.data(), data_size); std::vector gates; @@ -406,7 +406,7 @@ template StateVectorManagedCPU Initializing_StateVector_Imag(size_t num_qubits = 3) { size_t data_size = Util::exp2(num_qubits); - std::vector> arr(data_size, 0); + std::vector> arr(data_size, {0, 0}); arr[0] = {0, 1}; StateVectorManagedCPU Measured_StateVector(arr.data(), data_size); From e51c12e7df4d2a71e48ec1fb742c087fff6b4ac9 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 11:26:26 -0500 Subject: [PATCH 24/53] codecov fix try --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index abb3cb1a4c..75be3a52b2 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -22,12 +22,14 @@ enum class TransitionKernelType { Local, NonZeroRandom }; * @tparam fp_t Floating point precision of underlying measurements. */ template class TransitionKernel { - public: + protected: TransitionKernel() = default; TransitionKernel(const TransitionKernel &) = default; TransitionKernel(TransitionKernel &&) noexcept = default; TransitionKernel &operator=(const TransitionKernel &) = default; TransitionKernel &operator=(TransitionKernel &&) noexcept = default; + + public: // outputs the next state and the qratio virtual std::pair operator()(size_t) = 0; virtual ~TransitionKernel() = default; From 1deba1c270d0ed066409c9249aedaaeaba6cbb5e Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 11:49:38 -0500 Subject: [PATCH 25/53] codecov test --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 75be3a52b2..ada3049c08 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -98,8 +98,8 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { sv_length_ = sv_length; // find nonzero candidates for (size_t i = 0; i < sv_length_; i++) { - if (std::fabs(data[i].real()) > min_error || - std::fabs(data[i].imag()) > min_error) { + if ((std::fabs(data[i].real()) > min_error) || + (std::fabs(data[i].imag()) > min_error)) { non_zeros_.push_back(i); } } From 1d663e7892321e263f56045e701b8dfce4fd2567 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 15:59:13 -0500 Subject: [PATCH 26/53] codecov fix test --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index ada3049c08..0aa4a0b114 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -98,8 +98,8 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { sv_length_ = sv_length; // find nonzero candidates for (size_t i = 0; i < sv_length_; i++) { - if ((std::fabs(data[i].real()) > min_error) || - (std::fabs(data[i].imag()) > min_error)) { + if (std::fabs(data[i].imag()) > min_error || + std::fabs(data[i].real()) > min_error) { non_zeros_.push_back(i); } } From 73de232870a692be455792a8acf74bfb326a1d6f Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 16:05:31 -0500 Subject: [PATCH 27/53] codecov fix test --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 0aa4a0b114..b57f0f79bb 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -98,8 +98,9 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { sv_length_ = sv_length; // find nonzero candidates for (size_t i = 0; i < sv_length_; i++) { - if (std::fabs(data[i].imag()) > min_error || - std::fabs(data[i].real()) > min_error) { + // if (std::fabs(data[i].imag()) > min_error || + // std::fabs(data[i].real()) > min_error) { + if (std::abs(data[i]) > min_error) { non_zeros_.push_back(i); } } From 4050e8a1af2ba4261f3c4b319664f2747677a58c Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 16:28:24 -0500 Subject: [PATCH 28/53] codecov fix --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index b57f0f79bb..9ad5851fa1 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -98,8 +98,6 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { sv_length_ = sv_length; // find nonzero candidates for (size_t i = 0; i < sv_length_; i++) { - // if (std::fabs(data[i].imag()) > min_error || - // std::fabs(data[i].real()) > min_error) { if (std::abs(data[i]) > min_error) { non_zeros_.push_back(i); } From 53725cf3d6c9b1cd9f90bb18ffc43b89941f9b0f Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 16:47:00 -0500 Subject: [PATCH 29/53] codecov fix --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 9ad5851fa1..6c1e1edfeb 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -96,7 +96,6 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { size_t sv_length, fp_t min_error) { auto data = sv; sv_length_ = sv_length; - // find nonzero candidates for (size_t i = 0; i < sv_length_; i++) { if (std::abs(data[i]) > min_error) { non_zeros_.push_back(i); From d7593c9ec058812ca019630b48b175159f43ad69 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 17:42:23 -0500 Subject: [PATCH 30/53] codefactor fix try --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 6c1e1edfeb..59e06d6bac 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -96,11 +96,11 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { size_t sv_length, fp_t min_error) { auto data = sv; sv_length_ = sv_length; - for (size_t i = 0; i < sv_length_; i++) { - if (std::abs(data[i]) > min_error) { + for (size_t i = 0; i < sv_length_; i++) //{ + if (std::abs(data[i]) > min_error) //{ non_zeros_.push_back(i); - } - } + //} + //} gen_ = std::mt19937(rd_()); distrib_ = std::uniform_int_distribution(0, non_zeros_.size() - 1); From 2979ccfc90ad79bc22a789af92fac6ac67f40709 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 16 Nov 2022 17:50:50 -0500 Subject: [PATCH 31/53] codefactor fix try --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 59e06d6bac..adb00d3227 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -94,13 +94,14 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { public: NonZeroRandomTransitionKernel(const std::complex *sv, size_t sv_length, fp_t min_error) { + auto data = sv; sv_length_ = sv_length; - for (size_t i = 0; i < sv_length_; i++) //{ - if (std::abs(data[i]) > min_error) //{ + for (size_t i = 0; i < sv_length_; i++) { + if (std::abs(data[i]) > min_error) { non_zeros_.push_back(i); - //} - //} + } + } gen_ = std::mt19937(rd_()); distrib_ = std::uniform_int_distribution(0, non_zeros_.size() - 1); From ab62fb1bbabec9522f5fce1ceeb03089701e450e Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Wed, 16 Nov 2022 22:52:50 +0000 Subject: [PATCH 32/53] remove blank lines --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index adb00d3227..95dade8ae1 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -94,7 +94,6 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { public: NonZeroRandomTransitionKernel(const std::complex *sv, size_t sv_length, fp_t min_error) { - auto data = sv; sv_length_ = sv_length; for (size_t i = 0; i < sv_length_; i++) { @@ -106,7 +105,6 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { distrib_ = std::uniform_int_distribution(0, non_zeros_.size() - 1); } - std::pair operator()([[maybe_unused]] size_t s1) final { auto s2 = distrib_(gen_); return std::pair(non_zeros_[s2], 1); @@ -126,7 +124,6 @@ template std::unique_ptr> kernel_factory(const TransitionKernelType kernel_type, const std::complex *sv, size_t num_qubits) { - auto sv_length = Util::exp2(num_qubits); if (kernel_type == TransitionKernelType::Local) { return std::unique_ptr>( From e05b2912730cbf0d46ff7ef4627e7b55f61d12e8 Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Wed, 16 Nov 2022 22:57:07 +0000 Subject: [PATCH 33/53] add comments --- pennylane_lightning/src/simulator/TransitionKernels.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index 95dade8ae1..ba97f3fb0d 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -96,6 +96,7 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { size_t sv_length, fp_t min_error) { auto data = sv; sv_length_ = sv_length; + // find nonzero candidates for (size_t i = 0; i < sv_length_; i++) { if (std::abs(data[i]) > min_error) { non_zeros_.push_back(i); From 603c8bc4d22b9a603a5020faa333fcd9766771f5 Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Thu, 17 Nov 2022 13:36:43 +0000 Subject: [PATCH 34/53] clean testing --- pennylane_lightning/src/tests/TestHelpers.hpp | 37 ------------ .../src/tests/Test_Measures.cpp | 57 ------------------- 2 files changed, 94 deletions(-) diff --git a/pennylane_lightning/src/tests/TestHelpers.hpp b/pennylane_lightning/src/tests/TestHelpers.hpp index c6a9e5032d..d381b06f99 100644 --- a/pennylane_lightning/src/tests/TestHelpers.hpp +++ b/pennylane_lightning/src/tests/TestHelpers.hpp @@ -395,43 +395,6 @@ StateVectorManagedCPU Initializing_StateVector(size_t num_qubits = 3) { return Measured_StateVector; } -/** - * @brief Initialize the statevector in a non-trivial configuration. - * - * @tparam T statevector float point precision. - * @param num_qubits number of qubits - * @return StateVectorManaged - */ -template -StateVectorManagedCPU Initializing_StateVector_Imag(size_t num_qubits = 3) { - size_t data_size = Util::exp2(num_qubits); - - std::vector> arr(data_size, {0, 0}); - arr[0] = {0, 1}; - StateVectorManagedCPU Measured_StateVector(arr.data(), data_size); - - std::vector gates; - std::vector> wires; - std::vector inv_op(num_qubits * 2, false); - std::vector> phase; - - T initial_phase = 0.7; - for (size_t n_qubit = 0; n_qubit < num_qubits; n_qubit++) { - gates.emplace_back("RX"); - gates.emplace_back("RY"); - - wires.push_back({n_qubit}); - wires.push_back({n_qubit}); - - phase.push_back({initial_phase}); - phase.push_back({initial_phase}); - initial_phase -= 0.2; - } - Measured_StateVector.applyOperations(gates, wires, inv_op, phase); - - return Measured_StateVector; -} - /** * @brief Fills the empty vectors with the CSR (Compressed Sparse Row) sparse * matrix representation for a tridiagonal + periodic boundary conditions diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp index aa0e17f294..9fb9d40a40 100644 --- a/pennylane_lightning/src/tests/Test_Measures.cpp +++ b/pennylane_lightning/src/tests/Test_Measures.cpp @@ -308,63 +308,6 @@ TEMPLATE_TEST_CASE("Sample with Metropolis (NonZeroRandom Kernel)", } } -TEMPLATE_TEST_CASE( - "Sample with Metropolis (NonZeroRandom Kernel) with different initial sv", - "[Measures]", float, double) { - constexpr uint32_t twos[] = { - 1U << 0U, 1U << 1U, 1U << 2U, 1U << 3U, 1U << 4U, 1U << 5U, - 1U << 6U, 1U << 7U, 1U << 8U, 1U << 9U, 1U << 10U, 1U << 11U, - 1U << 12U, 1U << 13U, 1U << 14U, 1U << 15U, 1U << 16U, 1U << 17U, - 1U << 18U, 1U << 19U, 1U << 20U, 1U << 21U, 1U << 22U, 1U << 23U, - 1U << 24U, 1U << 25U, 1U << 26U, 1U << 27U, 1U << 28U, 1U << 29U, - 1U << 30U, 1U << 31U}; - - // Defining the State Vector that will be measured. - StateVectorManagedCPU Measured_StateVector = - Initializing_StateVector_Imag(); - - // Initializing the measures class. - // This object attaches to the statevector allowing several measures. - Measures> Measurer( - Measured_StateVector); - vector expected_probabilities = { - 0.67078706, 0.03062806, 0.0870997, 0.00397696, - 0.17564072, 0.00801973, 0.02280642, 0.00104134}; - - size_t num_qubits = 3; - size_t N = std::pow(2, num_qubits); - size_t num_samples = 100000; - size_t num_burnin = 1000; - - auto &&samples = Measurer.generate_samples_metropolis( - TransitionKernelType::NonZeroRandom, num_burnin, num_samples); - - std::vector counts(N, 0); - std::vector samples_decimal(num_samples, 0); - - // convert samples to decimal and then bin them in counts - for (size_t i = 0; i < num_samples; i++) { - for (size_t j = 0; j < num_qubits; j++) { - if (samples[i * num_qubits + j] != 0) { - samples_decimal[i] += twos[(num_qubits - 1 - j)]; - } - } - counts[samples_decimal[i]] += 1; - } - - // compute estimated probabilities from histogram - std::vector probabilities(counts.size()); - for (size_t i = 0; i < counts.size(); i++) { - probabilities[i] = counts[i] / (TestType)num_samples; - } - - // compare estimated probabilities to real probabilities - SECTION("No wires provided:") { - REQUIRE_THAT(probabilities, - Catch::Approx(expected_probabilities).margin(.05)); - } -} - TEMPLATE_TEST_CASE("Variances", "[Measures]", float, double) { // Defining the State Vector that will be measured. StateVectorManagedCPU Measured_StateVector = From f40510f26f6053bc6b37287c35590323e5b32805 Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Mon, 21 Nov 2022 17:17:01 +0000 Subject: [PATCH 35/53] update code based on comments --- pennylane_lightning/lightning_qubit.py | 6 +- pennylane_lightning/src/bindings/Bindings.cpp | 9 +- .../src/simulator/Measures.hpp | 8 +- .../src/tests/Test_Measures.cpp | 10 ++- tests/test_measures.py | 86 +++++-------------- 5 files changed, 40 insertions(+), 79 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 7c59e6c69a..ed32613388 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -785,7 +785,11 @@ def generate_samples(self): def generate_mcmc_samples(self, kernel_name="Local", num_burnin=100): """Generate Markov chain Monte Carlo(MCMC) samples Args: - kernel_name (str): name of transition kernel. + kernel_name (str): name of transition kernel. Current version supports two kernels: + ``Local`` and ``NonZeroRandom``. The ``Local`` kernel conducts a 'SpinFlip' local transition + between states. The ``Local`` kernel generates a random qubit site and then generates + a random number to determine the new bit at that qubit site. The ``NonZeroRandom`` randomly transits + between states that have nonzero probability num_burnin (int): number of steps that will be dropped. Returns: diff --git a/pennylane_lightning/src/bindings/Bindings.cpp b/pennylane_lightning/src/bindings/Bindings.cpp index 3a374796af..6fef87d8ca 100644 --- a/pennylane_lightning/src/bindings/Bindings.cpp +++ b/pennylane_lightning/src/bindings/Bindings.cpp @@ -138,13 +138,8 @@ void lightning_class_bindings(py::module_ &m) { [](Measures &M, size_t num_wires, const std::string &kernelname, size_t num_burnin, size_t num_shots) { - TransitionKernelType kerneltype = - Pennylane::TransitionKernelType::Local; - if (kernelname == "NonZeroRandom") - kerneltype = - Pennylane::TransitionKernelType::NonZeroRandom; - auto &&result = M.generate_samples_metropolis( - kerneltype, num_burnin, num_shots); + std::vector &&result = M.generate_samples_metropolis( + kernelname, num_burnin, num_shots); const size_t ndim = 2; const std::vector shape{num_shots, num_wires}; diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 89f65a3855..e64e68fb38 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -358,7 +358,7 @@ class Measures { * separated by a stride equal to the number of qubits. */ std::vector - generate_samples_metropolis(const TransitionKernelType &transition_kernel, + generate_samples_metropolis(const std::string &kernelname, size_t num_burnin, size_t num_samples) { size_t num_qubits = original_statevector.getNumQubits(); std::random_device rd; @@ -367,11 +367,15 @@ class Measures { std::vector samples(num_samples * num_qubits, 0); std::unordered_map cache; + TransitionKernelType transition_kernel = + Pennylane::TransitionKernelType::Local; + if (kernelname == "NonZeroRandom") + transition_kernel = Pennylane::TransitionKernelType::NonZeroRandom; + auto tk = kernel_factory(transition_kernel, original_statevector.getData(), original_statevector.getNumQubits()); size_t s1 = 0; - // size_t s1 = tk->init_state(); // Burn In for (size_t i = 0; i < num_burnin; i++) { diff --git a/pennylane_lightning/src/tests/Test_Measures.cpp b/pennylane_lightning/src/tests/Test_Measures.cpp index 9fb9d40a40..4a4cc5307f 100644 --- a/pennylane_lightning/src/tests/Test_Measures.cpp +++ b/pennylane_lightning/src/tests/Test_Measures.cpp @@ -223,8 +223,9 @@ TEMPLATE_TEST_CASE("Sample with Metropolis (Local Kernel)", "[Measures]", float, size_t num_samples = 100000; size_t num_burnin = 1000; - auto &&samples = Measurer.generate_samples_metropolis( - TransitionKernelType::Local, num_burnin, num_samples); + std::string kernel = "Local"; + auto &&samples = + Measurer.generate_samples_metropolis(kernel, num_burnin, num_samples); std::vector counts(N, 0); std::vector samples_decimal(num_samples, 0); @@ -279,8 +280,9 @@ TEMPLATE_TEST_CASE("Sample with Metropolis (NonZeroRandom Kernel)", size_t num_samples = 100000; size_t num_burnin = 1000; - auto &&samples = Measurer.generate_samples_metropolis( - TransitionKernelType::NonZeroRandom, num_burnin, num_samples); + const std::string kernel = "NonZeroRandom"; + auto &&samples = + Measurer.generate_samples_metropolis(kernel, num_burnin, num_samples); std::vector counts(N, 0); std::vector samples_decimal(num_samples, 0); diff --git a/tests/test_measures.py b/tests/test_measures.py index e788686ab4..555c9fb097 100644 --- a/tests/test_measures.py +++ b/tests/test_measures.py @@ -567,85 +567,41 @@ class TestMCMCSample: def dev(self, request): return qml.device("lightning.qubit", wires=2, shots=1000, c_dtype=request.param) - def test_mcmc_sample_dimensions(self, dev): + test_data_no_parameters = [ + ("Local", 10, 100, [0], qml.PauliZ(wires=[0]), 100), + ("Local", 10, 110, [1], qml.PauliZ(wires=[1]), 110), + ("Local", 10, 120, [0, 1], qml.PauliX(0) @ qml.PauliZ(1), 120), + ("NonZeroRandom", 10, 100, [0], qml.PauliZ(wires=[0]), 100), + ("NonZeroRandom", 10, 110, [1], qml.PauliZ(wires=[1]), 110), + ("NonZeroRandom", 10, 120, [0, 1], qml.PauliX(0) @ qml.PauliZ(1), 120), + ] + + @pytest.mark.parametrize( + "kernel,num_burnin,num_shots,measured_wires,operation,shape", test_data_no_parameters + ) + def test_mcmc_sample_dimensions( + self, dev, kernel, num_burnin, num_shots, measured_wires, operation, shape + ): """Tests if the samples returned by sample have the correct dimensions """ dev.apply([qml.RX(1.5708, wires=[0]), qml.RX(1.5708, wires=[1])]) - kernel = "Local" - num_burnin = 10 - dev.shots = 10 - dev._wires_measured = {0} - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) - s1 = dev.sample(qml.PauliZ(wires=[0])) - assert np.array_equal(s1.shape, (10,)) - - dev.reset() - kernel = "Local" - num_burnin = 12 - dev.shots = 12 - dev._wires_measured = {1} - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) - s2 = dev.sample(qml.PauliZ(wires=[1])) - assert np.array_equal(s2.shape, (12,)) - - dev.reset() - kernel = "Local" - num_burnin = 17 - dev.shots = 17 - dev._wires_measured = {0, 1} + dev.shots = num_shots + dev._wires_measured = measured_wires dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) - s3 = dev.sample(qml.PauliX(0) @ qml.PauliZ(1)) - assert np.array_equal(s3.shape, (17,)) + s1 = dev.sample(operation) - dev.reset() - kernel = "NonZeroRandom" - num_burnin = 10 - dev.shots = 10 - dev._wires_measured = {0} - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) - s2 = dev.sample(qml.PauliZ(wires=[0])) - assert np.array_equal(s2.shape, (10,)) + assert np.array_equal(s1.shape, (shape,)) - dev.reset() - kernel = "NonZeroRandom" - num_burnin = 12 - dev.shots = 12 - dev._wires_measured = {1} - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) - s2 = dev.sample(qml.PauliZ(wires=[1])) - assert np.array_equal(s2.shape, (12,)) - - dev.reset() - kernel = "NonZeroRandom" - num_burnin = 17 - dev.shots = 17 - dev._wires_measured = {0, 1} - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) - s3 = dev.sample(qml.PauliX(0) @ qml.PauliZ(1)) - assert np.array_equal(s3.shape, (17,)) - - def test_sample_values(self, dev, tol): + @pytest.mark.parametrize("kernel", ["Local", "NonZeroRandom"]) + def test_sample_values(self, dev, tol, kernel): """Tests if the samples returned by sample have the correct values """ dev.apply([qml.RX(1.5708, wires=[0])]) - kernel = "Local" - num_burnin = 100 - dev._wires_measured = {0} - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) - - s1 = dev.sample(qml.PauliZ(0)) - - # s1 should only contain 1 and -1, which is guaranteed if - # they square to 1 - assert np.allclose(s1**2, 1, atol=tol, rtol=0) - - dev.reset() - kernel = "NonZeroRandom" num_burnin = 100 dev._wires_measured = {0} dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) From bbdb9b6eca60c048f56a6e34519dc9122924696d Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Mon, 21 Nov 2022 20:03:09 +0000 Subject: [PATCH 36/53] nomenclature change --- .../src/simulator/Measures.hpp | 43 ++++++++++--------- .../src/simulator/TransitionKernels.hpp | 17 ++++---- tests/test_measures.py | 4 +- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index e64e68fb38..0bff00497e 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -318,32 +318,35 @@ class Measures { * between metropolis states. * @param gen Random number generator. * @param distrib Random number distribution. - * @param s1 initial state + * @param init_idx Init index of basis state. */ size_t metropolis_step(const SVType &sv, std::unique_ptr> &tk, std::mt19937 &gen, std::uniform_real_distribution &distrib, - size_t s1) { - auto s1_plog = - std::log((sv.getData()[s1] * std::conj(sv.getData()[s1])).real()); + size_t init_idx) { + auto init_plog = std::log( + (sv.getData()[init_idx] * std::conj(sv.getData()[init_idx])) + .real()); - auto s1_qratio = tk->operator()(s1); + auto init_qratio = tk->operator()(init_idx); // transition kernel outputs these two - auto &s2 = s1_qratio.first; - auto &qratio = s1_qratio.second; + auto &trans_idx = init_qratio.first; + auto &trans_qratio = init_qratio.second; - auto s2_plog = - std::log((sv.getData()[s2] * std::conj(sv.getData()[s2])).real()); + auto trans_plog = std::log( + (sv.getData()[trans_idx] * std::conj(sv.getData()[trans_idx])) + .real()); - auto alph = std::min(1., qratio * std::exp(s2_plog - s1_plog)); + auto alph = + std::min(1., trans_qratio * std::exp(trans_plog - init_plog)); auto ran = distrib(gen); if (ran < alph) { - return s2; + return trans_idx; } - return s1; + return init_idx; } /** @@ -375,20 +378,20 @@ class Measures { auto tk = kernel_factory(transition_kernel, original_statevector.getData(), original_statevector.getNumQubits()); - size_t s1 = 0; + size_t idx = 0; // Burn In for (size_t i = 0; i < num_burnin; i++) { - s1 = metropolis_step(original_statevector, tk, gen, distrib, - s1); // Burn-in. + idx = metropolis_step(original_statevector, tk, gen, distrib, + idx); // Burn-in. } // Sample for (size_t i = 0; i < num_samples; i++) { - s1 = metropolis_step(original_statevector, tk, gen, distrib, s1); + idx = metropolis_step(original_statevector, tk, gen, distrib, idx); - if (cache.contains(s1)) { - size_t cache_id = cache[s1]; + if (cache.contains(idx)) { + size_t cache_id = cache[idx]; auto it_temp = samples.begin() + cache_id * num_qubits; std::copy(it_temp, it_temp + num_qubits, samples.begin() + i * num_qubits); @@ -398,9 +401,9 @@ class Measures { else { for (size_t j = 0; j < num_qubits; j++) { samples[i * num_qubits + (num_qubits - 1 - j)] = - (s1 >> j) & 1U; + (idx >> j) & 1U; } - cache[s1] = i; + cache[idx] = i; } } return samples; diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index ba97f3fb0d..fc3c6eaa2c 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -59,18 +59,19 @@ class LocalTransitionKernel : public TransitionKernel { std::uniform_int_distribution(0, num_qubits - 1)), distrib_binary_(std::uniform_int_distribution(0, 1)) {} - std::pair operator()(size_t s1) final { + std::pair operator()(size_t init_idx) final { size_t qubit_site = distrib_num_qubits_(gen_); size_t qubit_value = distrib_binary_(gen_); - size_t current_bit = ((unsigned)s1 >> (unsigned)qubit_site) & 1U; + size_t current_bit = ((unsigned)init_idx >> (unsigned)qubit_site) & 1U; if (qubit_value == current_bit) { - return std::pair(s1, 1); + return std::pair(init_idx, 1); } if (current_bit == 0) { - return std::pair(s1 + std::pow(2, qubit_site), 1); + return std::pair(init_idx + std::pow(2, qubit_site), + 1); } - return std::pair(s1 - std::pow(2, qubit_site), 1); + return std::pair(init_idx - std::pow(2, qubit_site), 1); } }; @@ -106,9 +107,9 @@ class NonZeroRandomTransitionKernel : public TransitionKernel { distrib_ = std::uniform_int_distribution(0, non_zeros_.size() - 1); } - std::pair operator()([[maybe_unused]] size_t s1) final { - auto s2 = distrib_(gen_); - return std::pair(non_zeros_[s2], 1); + std::pair operator()([[maybe_unused]] size_t init_idx) final { + auto trans_idx = distrib_(gen_); + return std::pair(non_zeros_[trans_idx], 1); } }; diff --git a/tests/test_measures.py b/tests/test_measures.py index 555c9fb097..4d563187d8 100644 --- a/tests/test_measures.py +++ b/tests/test_measures.py @@ -612,13 +612,13 @@ def test_sample_values(self, dev, tol, kernel): # they square to 1 assert np.allclose(s1**2, 1, atol=tol, rtol=0) - def test_unsupported_sample_kernels(self, dev, tol): + @pytest.mark.parametrize("kernel", ["local", "nonZeroRandom", "Global", "global"]) + def test_unsupported_sample_kernels(self, dev, tol, kernel): """Tests if the samples returned by sample have the correct values """ dev.apply([qml.RX(1.5708, wires=[0])]) - kernel = "Global" num_burnin = 100 dev._wires_measured = {0} with pytest.raises( From d621227c63e7ac032704b1dbae9471be5eed3ffc Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Mon, 21 Nov 2022 20:15:11 +0000 Subject: [PATCH 37/53] make format --- pennylane_lightning/src/simulator/Measures.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 0bff00497e..5295b5b84e 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -372,8 +372,9 @@ class Measures { TransitionKernelType transition_kernel = Pennylane::TransitionKernelType::Local; - if (kernelname == "NonZeroRandom") + if (kernelname == "NonZeroRandom") { transition_kernel = Pennylane::TransitionKernelType::NonZeroRandom; + } auto tk = kernel_factory(transition_kernel, original_statevector.getData(), From a224a8162a560e657766a051a58f381b7eaaae9c Mon Sep 17 00:00:00 2001 From: Shuli Shu Date: Tue, 22 Nov 2022 19:23:20 +0000 Subject: [PATCH 38/53] update code --- pennylane_lightning/src/simulator/Measures.hpp | 2 +- pennylane_lightning/src/simulator/TransitionKernels.hpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 5295b5b84e..b9088c27c0 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -321,7 +321,7 @@ class Measures { * @param init_idx Init index of basis state. */ size_t metropolis_step(const SVType &sv, - std::unique_ptr> &tk, + const std::unique_ptr> &tk, std::mt19937 &gen, std::uniform_real_distribution &distrib, size_t init_idx) { diff --git a/pennylane_lightning/src/simulator/TransitionKernels.hpp b/pennylane_lightning/src/simulator/TransitionKernels.hpp index fc3c6eaa2c..926e114086 100644 --- a/pennylane_lightning/src/simulator/TransitionKernels.hpp +++ b/pennylane_lightning/src/simulator/TransitionKernels.hpp @@ -62,7 +62,9 @@ class LocalTransitionKernel : public TransitionKernel { std::pair operator()(size_t init_idx) final { size_t qubit_site = distrib_num_qubits_(gen_); size_t qubit_value = distrib_binary_(gen_); - size_t current_bit = ((unsigned)init_idx >> (unsigned)qubit_site) & 1U; + size_t current_bit = (static_cast(init_idx) >> + static_cast(qubit_site)) & + 1U; if (qubit_value == current_bit) { return std::pair(init_idx, 1); From 2fcb7bb483ddfbd90fb216fbe509ca667ab08534 Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Wed, 8 Feb 2023 13:50:31 +0000 Subject: [PATCH 39/53] Auto update version --- pennylane_lightning/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/_version.py b/pennylane_lightning/_version.py index e0b04f640b..e7b9c36e20 100644 --- a/pennylane_lightning/_version.py +++ b/pennylane_lightning/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.29.0-dev9" +__version__ = "0.29.0-dev10" From b77208ba27daab5e81e954f0065cb596ee17dcb7 Mon Sep 17 00:00:00 2001 From: Dev version update bot Date: Fri, 10 Mar 2023 19:57:27 +0000 Subject: [PATCH 40/53] Auto update version --- pennylane_lightning/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/_version.py b/pennylane_lightning/_version.py index 2af226f590..ae308c22f6 100644 --- a/pennylane_lightning/_version.py +++ b/pennylane_lightning/_version.py @@ -16,4 +16,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "0.30.0-dev" +__version__ = "0.30.0-dev1" From bc96c282674bd9a575c7da9d352a8a5f82f85abe Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Fri, 10 Mar 2023 15:51:57 -0500 Subject: [PATCH 41/53] quick fix --- pennylane_lightning/src/simulator/Measures.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index 29be71c826..ffaa995f36 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -431,6 +431,8 @@ class Measures { } return samples; } + + /** * @brief Variance of a Sparse Hamiltonian. * * @tparam index_type integer type used as indices of the sparse matrix. From c042a384e5e95a527e6f467b5d66ecf81bc17635 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Fri, 10 Mar 2023 15:52:18 -0500 Subject: [PATCH 42/53] make format --- pennylane_lightning/src/simulator/Measures.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/src/simulator/Measures.hpp b/pennylane_lightning/src/simulator/Measures.hpp index ffaa995f36..07b93f9e95 100644 --- a/pennylane_lightning/src/simulator/Measures.hpp +++ b/pennylane_lightning/src/simulator/Measures.hpp @@ -431,7 +431,7 @@ class Measures { } return samples; } - + /** * @brief Variance of a Sparse Hamiltonian. * From a93a6f7279a8536cfd6e4b95f33f955ad1c6b1e0 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Tue, 14 Mar 2023 09:54:20 -0400 Subject: [PATCH 43/53] update docstring --- pennylane_lightning/lightning_qubit.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index f7574171a9..42ef73b87a 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -786,13 +786,13 @@ def generate_samples(self): return M.generate_samples(len(self.wires), self.shots).astype(int, copy=False) def generate_mcmc_samples(self, kernel_name="Local", num_burnin=100): - """Generate Markov chain Monte Carlo(MCMC) samples + """Generate Markov chain Monte Carlo (MCMC) samples Args: - kernel_name (str): name of transition kernel. Current version supports two kernels: - ``Local`` and ``NonZeroRandom``. The ``Local`` kernel conducts a 'SpinFlip' local transition - between states. The ``Local`` kernel generates a random qubit site and then generates - a random number to determine the new bit at that qubit site. The ``NonZeroRandom`` randomly transits - between states that have nonzero probability + kernel_name (str): name of transition kernel. Current version supports two kernels: ``Local`` and + ``NonZeroRandom``. The ``Local`` kernel conducts a ``SpinFlip`` local transition between states. + The ``Local`` kernel generates a random qubit site and then generates a random number to determine + the new bit at that qubit site. The ``NonZeroRandom`` randomly transits between states that have + nonzero probability. num_burnin (int): number of steps that will be dropped. Returns: From 789edaf82fe895287dae7eeaf4498f5ea36ab915 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Tue, 14 Mar 2023 10:52:30 -0400 Subject: [PATCH 44/53] update docstring --- pennylane_lightning/lightning_qubit.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 42ef73b87a..152895a6b1 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -788,11 +788,9 @@ def generate_samples(self): def generate_mcmc_samples(self, kernel_name="Local", num_burnin=100): """Generate Markov chain Monte Carlo (MCMC) samples Args: - kernel_name (str): name of transition kernel. Current version supports two kernels: ``Local`` and - ``NonZeroRandom``. The ``Local`` kernel conducts a ``SpinFlip`` local transition between states. - The ``Local`` kernel generates a random qubit site and then generates a random number to determine - the new bit at that qubit site. The ``NonZeroRandom`` randomly transits between states that have - nonzero probability. + kernel_name (str): name of transition kernel. Current version supports two kernels: ``Local`` and ``NonZeroRandom``. The ``Local`` kernel + conducts a ``SpinFlip`` local transition between states. The ``Local`` kernel generates a random qubit site and then generates a random + number to determine the new bit at that qubit site. The ``NonZeroRandom`` randomly transits between states that have nonzero probability. num_burnin (int): number of steps that will be dropped. Returns: From 89ae6efc6f05a75a6f66b8937c7e9c647c62defc Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Tue, 14 Mar 2023 13:15:34 -0700 Subject: [PATCH 45/53] add mcmc to ctor --- pennylane_lightning/lightning_qubit.py | 64 +++++++++++++------------- tests/test_measures.py | 33 +++++++------ 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 152895a6b1..d62882961f 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -173,7 +173,18 @@ class LightningQubit(QubitDevice): operations = allowed_operations observables = allowed_observables - def __init__(self, wires, *, c_dtype=np.complex128, shots=None, batch_obs=False, analytic=None): + def __init__( + self, + wires, + *, + c_dtype=np.complex128, + shots=None, + mcmc=False, + kernel_name="Local", + num_burnin=100, + batch_obs=False, + analytic=None, + ): if c_dtype is np.complex64: r_dtype = np.float32 self.use_csingle = True @@ -190,6 +201,20 @@ def __init__(self, wires, *, c_dtype=np.complex128, shots=None, batch_obs=False, self._state = self._create_basis_state(0) self._pre_rotated_state = self._state + self._mcmc = mcmc + if self._mcmc: + if kernel_name not in [ + "Local", + "NonZeroRandom", + ]: + raise NotImplementedError( + f"The {kernel_name} is not supported and currently only 'Local' and 'NonZeroRandom' kernels are supported." + ) + if num_burnin >= shots: + raise ValueError("Shots should be greater than num_burnin.") + self._kernel_name = kernel_name + self._num_burnin = num_burnin + @property def stopping_condition(self): """.BooleanFn: Returns the stopping condition for the device. The returned @@ -776,42 +801,17 @@ def generate_samples(self): Returns: array[int]: array of samples in binary representation with shape ``(dev.shots, dev.num_wires)`` """ - - # Initialization of state - ket = np.ravel(self._state) - - state_vector = StateVectorC64(ket) if self.use_csingle else StateVectorC128(ket) - M = MeasuresC64(state_vector) if self.use_csingle else MeasuresC128(state_vector) - - return M.generate_samples(len(self.wires), self.shots).astype(int, copy=False) - - def generate_mcmc_samples(self, kernel_name="Local", num_burnin=100): - """Generate Markov chain Monte Carlo (MCMC) samples - Args: - kernel_name (str): name of transition kernel. Current version supports two kernels: ``Local`` and ``NonZeroRandom``. The ``Local`` kernel - conducts a ``SpinFlip`` local transition between states. The ``Local`` kernel generates a random qubit site and then generates a random - number to determine the new bit at that qubit site. The ``NonZeroRandom`` randomly transits between states that have nonzero probability. - num_burnin (int): number of steps that will be dropped. - - Returns: - array[int]: array of samples in binary representation with shape ``(dev.shots, dev.num_wires)`` - """ - if kernel_name not in [ - "Local", - "NonZeroRandom", - ]: - raise NotImplementedError( - f"The {kernel_name} is not supported and currently only 'Local' and 'NonZeroRandom' kernels are supported." - ) # Initialization of state ket = np.ravel(self._state) state_vector = StateVectorC64(ket) if self.use_csingle else StateVectorC128(ket) M = MeasuresC64(state_vector) if self.use_csingle else MeasuresC128(state_vector) - - return M.generate_mcmc_samples(len(self.wires), kernel_name, num_burnin, self.shots).astype( - int, copy=False - ) + if self._mcmc: + return M.generate_mcmc_samples( + len(self.wires), self._kernel_name, self._num_burnin, self.shots + ).astype(int, copy=False) + else: + return M.generate_samples(len(self.wires), self.shots).astype(int, copy=False) def expval(self, observable, shot_range=None, bin_size=None): """Expectation value of the supplied observable. diff --git a/tests/test_measures.py b/tests/test_measures.py index a053558418..9998d6692d 100644 --- a/tests/test_measures.py +++ b/tests/test_measures.py @@ -616,7 +616,7 @@ class TestMCMCSample: @pytest.fixture(params=[np.complex64, np.complex128]) def dev(self, request): - return qml.device("lightning.qubit", wires=2, shots=1000, c_dtype=request.param) + return qml.device("lightning.qubit", wires=2, shots=1000, mcmc=True, c_dtype=request.param) test_data_no_parameters = [ ("Local", 10, 100, [0], qml.PauliZ(wires=[0]), 100), @@ -636,27 +636,27 @@ def test_mcmc_sample_dimensions( """Tests if the samples returned by sample have the correct dimensions """ - dev.apply([qml.RX(1.5708, wires=[0]), qml.RX(1.5708, wires=[1])]) dev.shots = num_shots dev._wires_measured = measured_wires - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + dev._samples = dev.generate_samples() s1 = dev.sample(operation) assert np.array_equal(s1.shape, (shape,)) @pytest.mark.parametrize("kernel", ["Local", "NonZeroRandom"]) - def test_sample_values(self, dev, tol, kernel): + def test_sample_values(self, tol, kernel): """Tests if the samples returned by sample have the correct values """ + dev = qml.device( + "lightning.qubit", wires=2, shots=1000, mcmc=True, kernel_name=kernel, num_burnin=100 + ) dev.apply([qml.RX(1.5708, wires=[0])]) - num_burnin = 100 dev._wires_measured = {0} - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) - + dev._samples = dev.generate_samples() s1 = dev.sample(qml.PauliZ(0)) # s1 should only contain 1 and -1, which is guaranteed if @@ -664,19 +664,26 @@ def test_sample_values(self, dev, tol, kernel): assert np.allclose(s1**2, 1, atol=tol, rtol=0) @pytest.mark.parametrize("kernel", ["local", "nonZeroRandom", "Global", "global"]) - def test_unsupported_sample_kernels(self, dev, tol, kernel): + def test_unsupported_sample_kernels(self, tol, kernel): """Tests if the samples returned by sample have the correct values """ - - dev.apply([qml.RX(1.5708, wires=[0])]) - num_burnin = 100 - dev._wires_measured = {0} with pytest.raises( NotImplementedError, match=f"The {kernel} is not supported and currently only 'Local' and 'NonZeroRandom' kernels are supported.", ): - dev._samples = dev.generate_mcmc_samples(kernel, num_burnin) + dev = qml.device( + "lightning.qubit", + wires=2, + shots=1000, + mcmc=True, + kernel_name=kernel, + num_burnin=100, + ) + + def test_wrong_num_burnin(self): + with pytest.raises(ValueError, match="Shots should be greater than num_burnin."): + dev = qml.device("lightning.qubit", wires=2, shots=1000, mcmc=True, num_burnin=1000) class TestWiresInVar: From 5b037dc7fe9501b0702657e409912cb9c43bb314 Mon Sep 17 00:00:00 2001 From: Shuli Shu <08cnbj@gmail.com> Date: Wed, 15 Mar 2023 16:43:59 -0400 Subject: [PATCH 46/53] add docstrings --- doc/devices.rst | 23 +++++++++++++++++++++++ pennylane_lightning/lightning_qubit.py | 6 ++++++ 2 files changed, 29 insertions(+) diff --git a/doc/devices.rst b/doc/devices.rst index 253f17b4cb..c628760c26 100644 --- a/doc/devices.rst +++ b/doc/devices.rst @@ -98,3 +98,26 @@ If you are computing a large number of expectation values, or if you are using a os.environ["OMP_NUM_THREADS"] = 4 import pennylane as qml dev = qml.device("lightning.qubit", wires=2, batch_obs=True) + +.. raw:: html + + + +**Markov Chain Monte Carlo sampling support:** + +The ``lightning.qubit`` device allows users to use Markov Chain Monte Carlo (MCMC) sampling method to generate samples. To enable MCMC sampling method for sample generation, initialize a ``lightning.qubit`` device with the ``mcmc=True`` keyword argument, as: + +.. code-block:: python + + import pennylane as qml + dev = qml.device("lightning.qubit", wires=2, shots=1000, mcmc=True) + +By default, the ``kernel_name`` is ``Local`` and ``num_burnin`` is ``100``. The ``Local`` kernel conducts a ``SpinFlip`` local transition between states. The ``Local`` kernel generates a random qubit site and then generates a random number to determine the new bit at that qubit site. + +Current version also supports the ``NonZeroRandom`` kernel. The ``NonZeroRandom`` randomly transits between states that have nonzero probability. To enable the ``NonZeroRandom`` kernel and set ``num_burnin``, initialize a ``lightning.qubit`` device as: + +.. code-block:: python + + import pennylane as qml + dev = qml.device("lightning.qubit", wires=2, shots=1000, mcmc=True, kernel_name="NonZeroRandom", num_burnin=200) + diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index d62882961f..4aee1cd349 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -160,6 +160,12 @@ class LightningQubit(QubitDevice): the expectation values. Defaults to ``None`` if not specified. Setting to ``None`` results in computing statistics like expectation values and variances analytically. + mcmc (bool): Determine whether we use Markov Chain Monte Carlo sampling method when generating samples. + kernel_name (str): name of transition kernel. Current version supports two kernels: ``Local`` and ``NonZeroRandom``. + The ``Local`` kernel conducts a ``SpinFlip`` local transition between states. The ``Local`` kernel generates a + random qubit site and then generates a random number to determine the new bit at that qubit site. The ``NonZeroRandom`` + randomly transits between states that have nonzero probability. + num_burnin (int): number of steps that will be dropped. batch_obs (bool): Determine whether we process observables parallelly when computing the jacobian. This value is only relevant when the lightning qubit is built with OpenMP. """ From 1dadfc9058d47dee6411f1938ca20dc3e3494f7a Mon Sep 17 00:00:00 2001 From: Shuli Shu <31480676+multiphaseCFD@users.noreply.github.com> Date: Fri, 17 Mar 2023 11:25:53 -0400 Subject: [PATCH 47/53] Update tests/test_measures.py Co-authored-by: Vincent Michaud-Rioux --- tests/test_measures.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/test_measures.py b/tests/test_measures.py index 9998d6692d..504c7adcec 100644 --- a/tests/test_measures.py +++ b/tests/test_measures.py @@ -619,16 +619,14 @@ def dev(self, request): return qml.device("lightning.qubit", wires=2, shots=1000, mcmc=True, c_dtype=request.param) test_data_no_parameters = [ - ("Local", 10, 100, [0], qml.PauliZ(wires=[0]), 100), - ("Local", 10, 110, [1], qml.PauliZ(wires=[1]), 110), - ("Local", 10, 120, [0, 1], qml.PauliX(0) @ qml.PauliZ(1), 120), - ("NonZeroRandom", 10, 100, [0], qml.PauliZ(wires=[0]), 100), - ("NonZeroRandom", 10, 110, [1], qml.PauliZ(wires=[1]), 110), - ("NonZeroRandom", 10, 120, [0, 1], qml.PauliX(0) @ qml.PauliZ(1), 120), + (10, 100, [0], qml.PauliZ(wires=[0]), 100), + (10, 110, [1], qml.PauliZ(wires=[1]), 110), + (10, 120, [0, 1], qml.PauliX(0) @ qml.PauliZ(1), 120), ] + @pytest.mark.parametrize("kernel", ["Local", "NonZeroRandom"]) @pytest.mark.parametrize( - "kernel,num_burnin,num_shots,measured_wires,operation,shape", test_data_no_parameters + "num_burnin,num_shots,measured_wires,operation,shape", test_data_no_parameters ) def test_mcmc_sample_dimensions( self, dev, kernel, num_burnin, num_shots, measured_wires, operation, shape From d789e1af59005b2fc62c5308ff5a166efa76018b Mon Sep 17 00:00:00 2001 From: Shuli Shu <31480676+multiphaseCFD@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:52:52 -0400 Subject: [PATCH 48/53] Update doc/devices.rst Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com> --- doc/devices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/devices.rst b/doc/devices.rst index c628760c26..86a3740671 100644 --- a/doc/devices.rst +++ b/doc/devices.rst @@ -105,7 +105,7 @@ If you are computing a large number of expectation values, or if you are using a **Markov Chain Monte Carlo sampling support:** -The ``lightning.qubit`` device allows users to use Markov Chain Monte Carlo (MCMC) sampling method to generate samples. To enable MCMC sampling method for sample generation, initialize a ``lightning.qubit`` device with the ``mcmc=True`` keyword argument, as: +The ``lightning.qubit`` device allows users to use the Markov Chain Monte Carlo (MCMC) sampling method to generate approximate samples. To enable the MCMC sampling method for sample generation, initialize a ``lightning.qubit`` device with the ``mcmc=True`` keyword argument, as: .. code-block:: python From 1e748455fea435fbe642e63efc1f82024f4036d7 Mon Sep 17 00:00:00 2001 From: Shuli Shu <31480676+multiphaseCFD@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:53:17 -0400 Subject: [PATCH 49/53] Update doc/devices.rst Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com> --- doc/devices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/devices.rst b/doc/devices.rst index 86a3740671..188d9899fc 100644 --- a/doc/devices.rst +++ b/doc/devices.rst @@ -112,7 +112,7 @@ The ``lightning.qubit`` device allows users to use the Markov Chain Monte Carlo import pennylane as qml dev = qml.device("lightning.qubit", wires=2, shots=1000, mcmc=True) -By default, the ``kernel_name`` is ``Local`` and ``num_burnin`` is ``100``. The ``Local`` kernel conducts a ``SpinFlip`` local transition between states. The ``Local`` kernel generates a random qubit site and then generates a random number to determine the new bit at that qubit site. +By default, the ``kernel_name`` is ``"Local"`` and ``num_burnin`` is ``100``. The local kernel conducts a bit-flip local transition between states. The local kernel generates a random qubit site and then generates a random number to determine the new bit at that qubit site. Current version also supports the ``NonZeroRandom`` kernel. The ``NonZeroRandom`` randomly transits between states that have nonzero probability. To enable the ``NonZeroRandom`` kernel and set ``num_burnin``, initialize a ``lightning.qubit`` device as: From 204851ebf88ede23da439efb3bd1bd0f5f276c7b Mon Sep 17 00:00:00 2001 From: Shuli Shu <31480676+multiphaseCFD@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:53:27 -0400 Subject: [PATCH 50/53] Update doc/devices.rst Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com> --- doc/devices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/devices.rst b/doc/devices.rst index 188d9899fc..10b6aab1c7 100644 --- a/doc/devices.rst +++ b/doc/devices.rst @@ -114,7 +114,7 @@ The ``lightning.qubit`` device allows users to use the Markov Chain Monte Carlo By default, the ``kernel_name`` is ``"Local"`` and ``num_burnin`` is ``100``. The local kernel conducts a bit-flip local transition between states. The local kernel generates a random qubit site and then generates a random number to determine the new bit at that qubit site. -Current version also supports the ``NonZeroRandom`` kernel. The ``NonZeroRandom`` randomly transits between states that have nonzero probability. To enable the ``NonZeroRandom`` kernel and set ``num_burnin``, initialize a ``lightning.qubit`` device as: +The ``lightning.qubit`` device also supports a ``"NonZeroRandom"`` kernel. This kernel randomly transits between states that have nonzero probability. It can be enabled by initializing the device as: .. code-block:: python From b6850c857d43d22e24c0940efafdd652b77119b7 Mon Sep 17 00:00:00 2001 From: Shuli Shu <31480676+multiphaseCFD@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:53:35 -0400 Subject: [PATCH 51/53] Update pennylane_lightning/lightning_qubit.py Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com> --- pennylane_lightning/lightning_qubit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 4aee1cd349..79b65bce0c 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -160,7 +160,7 @@ class LightningQubit(QubitDevice): the expectation values. Defaults to ``None`` if not specified. Setting to ``None`` results in computing statistics like expectation values and variances analytically. - mcmc (bool): Determine whether we use Markov Chain Monte Carlo sampling method when generating samples. + mcmc (bool): Determine whether to use the approximate Markov Chain Monte Carlo sampling method when generating samples. kernel_name (str): name of transition kernel. Current version supports two kernels: ``Local`` and ``NonZeroRandom``. The ``Local`` kernel conducts a ``SpinFlip`` local transition between states. The ``Local`` kernel generates a random qubit site and then generates a random number to determine the new bit at that qubit site. The ``NonZeroRandom`` From ce3c50d4f5b390e3adfc1819b211ca6091d31085 Mon Sep 17 00:00:00 2001 From: Shuli Shu <31480676+multiphaseCFD@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:53:47 -0400 Subject: [PATCH 52/53] Update pennylane_lightning/lightning_qubit.py Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com> --- pennylane_lightning/lightning_qubit.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 79b65bce0c..22f1dcea67 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -161,9 +161,9 @@ class LightningQubit(QubitDevice): to ``None`` results in computing statistics like expectation values and variances analytically. mcmc (bool): Determine whether to use the approximate Markov Chain Monte Carlo sampling method when generating samples. - kernel_name (str): name of transition kernel. Current version supports two kernels: ``Local`` and ``NonZeroRandom``. - The ``Local`` kernel conducts a ``SpinFlip`` local transition between states. The ``Local`` kernel generates a - random qubit site and then generates a random number to determine the new bit at that qubit site. The ``NonZeroRandom`` + kernel_name (str): name of transition kernel. The current version supports two kernels: ``"Local"`` and ``"NonZeroRandom"``. + The local kernel conducts a bit-flip local transition between states. The local kernel generates a + random qubit site and then generates a random number to determine the new bit at that qubit site. The ``"NonZeroRandom"`` kernel randomly transits between states that have nonzero probability. num_burnin (int): number of steps that will be dropped. batch_obs (bool): Determine whether we process observables parallelly when computing the From f51d1d57284e749e7440c0293615e98cd10ed0b1 Mon Sep 17 00:00:00 2001 From: Shuli Shu <31480676+multiphaseCFD@users.noreply.github.com> Date: Fri, 17 Mar 2023 15:53:54 -0400 Subject: [PATCH 53/53] Update pennylane_lightning/lightning_qubit.py Co-authored-by: Tom Bromley <49409390+trbromley@users.noreply.github.com> --- pennylane_lightning/lightning_qubit.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pennylane_lightning/lightning_qubit.py b/pennylane_lightning/lightning_qubit.py index 22f1dcea67..1dfe776e95 100644 --- a/pennylane_lightning/lightning_qubit.py +++ b/pennylane_lightning/lightning_qubit.py @@ -165,7 +165,8 @@ class LightningQubit(QubitDevice): The local kernel conducts a bit-flip local transition between states. The local kernel generates a random qubit site and then generates a random number to determine the new bit at that qubit site. The ``"NonZeroRandom"`` kernel randomly transits between states that have nonzero probability. - num_burnin (int): number of steps that will be dropped. + num_burnin (int): number of steps that will be dropped. Increasing this value will + result in a closer approximation but increased runtime. batch_obs (bool): Determine whether we process observables parallelly when computing the jacobian. This value is only relevant when the lightning qubit is built with OpenMP. """