Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add generate_samples() to lightning #247

Merged
merged 67 commits into from
Mar 18, 2022
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
93cf0ae
Add Alias sampler
Feb 25, 2022
fa6d58c
Add generate_samples function beta version
Mar 1, 2022
d2efa2f
Finish generate_samples
Mar 3, 2022
a9f6391
Finish generate_samples
Mar 4, 2022
cc23208
Rename generate_samples_test to generate_samples
Mar 4, 2022
cad88e6
Add tests
Mar 7, 2022
4fcff2b
Add more dox
Mar 7, 2022
96a7f5f
Merge master
Mar 7, 2022
0751a51
Auto update version
chaeyeunpark Mar 7, 2022
6b96efd
run black
Mar 7, 2022
57105ba
Merge branch 'add-sample' of github.com:PennyLaneAI/pennylane-lightni…
Mar 7, 2022
b359f59
Run make format
Mar 9, 2022
0bd8091
Merge branch 'master' into add-sample
trevor-vincent Mar 9, 2022
46214eb
Auto update version
chaeyeunpark Mar 9, 2022
0e54e5a
Fix ssize_t warning
Mar 9, 2022
9375ffc
Merge branch 'add-sample' of github.com:PennyLaneAI/pennylane-lightni…
Mar 9, 2022
8711acb
Fix codefactor issues
Mar 9, 2022
bdb5806
Fix more codefactor issues
Mar 9, 2022
9d16c8c
Fix more bindings issues
Mar 9, 2022
11e8446
Fix int -> size_t
Mar 9, 2022
e800d63
Fix double probabilities statement
Mar 9, 2022
58f3997
Fix typo
Mar 9, 2022
9fbd49f
Update pennylane_lightning/src/bindings/Bindings.cpp
trevor-vincent Mar 9, 2022
22bb77e
Update pennylane_lightning/src/bindings/Bindings.cpp
trevor-vincent Mar 9, 2022
8c904b9
Update pennylane_lightning/src/bindings/Bindings.cpp
trevor-vincent Mar 9, 2022
c63441c
Update pennylane_lightning/src/bindings/Bindings.cpp
trevor-vincent Mar 9, 2022
283af7d
Update pennylane_lightning/src/simulator/Measures.hpp
trevor-vincent Mar 9, 2022
d2733e9
Update pennylane_lightning/src/simulator/Measures.hpp
trevor-vincent Mar 9, 2022
8ba4315
Update pennylane_lightning/src/tests/Test_Measures.cpp
trevor-vincent Mar 9, 2022
fc38b12
Update pennylane_lightning/src/simulator/Measures.hpp
trevor-vincent Mar 9, 2022
17ceb8d
Update pennylane_lightning/src/bindings/Bindings.cpp
trevor-vincent Mar 9, 2022
f59ae94
Merge branch 'master' into add-sample
trevor-vincent Mar 9, 2022
26f0725
Auto update version
chaeyeunpark Mar 9, 2022
c7e9d02
Fix pytest
Mar 11, 2022
c19655a
Fix cpp-tests
Mar 11, 2022
3823f28
Fix clang tidy
Mar 11, 2022
86e4b0d
Fix black
Mar 11, 2022
62a61e0
Fix clang format
Mar 11, 2022
06a77a7
Add test measures
Mar 11, 2022
d9db646
Fix typo
Mar 11, 2022
87d3476
Add more codecov-related fixes
Mar 11, 2022
0d84a5e
Add small changes to test_measures
Mar 11, 2022
6bebc64
Run black
Mar 13, 2022
be0139c
Fix Windows errors
Mar 14, 2022
7709dd2
Fix comments
Mar 16, 2022
114e99d
Add float,double for variances test
Mar 16, 2022
4e7b5bf
Merge branch 'master' into add-sample
trevor-vincent Mar 16, 2022
858bb40
Auto update version
chaeyeunpark Mar 16, 2022
a5b0aab
Format Test_Measures
Mar 16, 2022
fbd5185
Revert variances
Mar 16, 2022
68a0296
Fix issue with tests
Mar 16, 2022
d8ecd65
Merge branch 'master' into add-sample
trevor-vincent Mar 16, 2022
19761d3
Auto update version
chaeyeunpark Mar 16, 2022
08004f7
Fix cpp-tests
Mar 17, 2022
f3af33f
Merge branch 'add-sample' of github.com:PennyLaneAI/pennylane-lightni…
Mar 17, 2022
678168c
Fix formatting
Mar 17, 2022
c3def04
Merge branch 'master' into add-sample
trevor-vincent Mar 17, 2022
5c8aa1a
Auto update version
chaeyeunpark Mar 17, 2022
10c2ce5
Trigger CI
Mar 17, 2022
a80642f
Merge branch 'add-sample' of github.com:PennyLaneAI/pennylane-lightni…
Mar 17, 2022
08d7fc9
Add documentation
Mar 18, 2022
43c6c49
Merge branch 'master' into add-sample
trevor-vincent Mar 18, 2022
ae737ca
Auto update version
chaeyeunpark Mar 18, 2022
a2be1ae
Add more documentation
Mar 18, 2022
8a92325
Merge branch 'add-sample' of github.com:PennyLaneAI/pennylane-lightni…
Mar 18, 2022
835a384
Update pennylane_lightning/src/tests/Test_Measures.cpp
trevor-vincent Mar 18, 2022
c616693
Fix formatting
Mar 18, 2022
File filter

Filter by extension

Filter by extension

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

__version__ = "0.22.0-dev15"
__version__ = "0.22.0-dev16"
27 changes: 27 additions & 0 deletions pennylane_lightning/lightning_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,33 @@ def probability(self, wires=None, shot_range=None, bin_size=None):

return M.probs(device_wires)

def generate_samples(self):
"""Generate samples

Returns:
Array of samples in binary
maliasadi marked this conversation as resolved.
Show resolved Hide resolved
"""

# To support np.complex64 based on the type of self._state
dtype = self._state.dtype
if dtype == np.complex64:
use_csingle = True
elif dtype == np.complex128:
use_csingle = False
else:
raise TypeError(f"Unsupported complex Type: {dtype}")

# Initialization of state
ket = np.ravel(self._state)

if use_csingle:
ket = ket.astype(np.complex64)

state_vector = StateVectorC64(ket) if use_csingle else StateVectorC128(ket)
M = MeasuresC64(state_vector) if use_csingle else MeasuresC128(state_vector)

return M.generate_samples(self.shots)

def expval(self, observable, shot_range=None, bin_size=None):
"""Expectation value of the supplied observable.

Expand Down
23 changes: 23 additions & 0 deletions pennylane_lightning/src/bindings/Bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,29 @@ void lightning_class_bindings(py::module &m) {
const std::vector<size_t> &wires) {
return M.expval(operation, wires);
})
.def("generate_samples",
[](Measures<PrecisionT> &M, size_t num_shots) {
auto &&result = M.generate_samples(num_shots);
// int num_samples = num_shots;
// std::vector<int> result(num_samples*wires.size(),0);
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved

int num_wires = result.size() / num_shots;
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
ssize_t ndim = 2;
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
std::vector<ssize_t> shape = {static_cast<ssize_t>(num_shots),
static_cast<ssize_t>(num_wires)};
std::vector<ssize_t> strides = {static_cast<ssize_t>(sizeof(int) * num_wires),
static_cast<ssize_t>(sizeof(int))};
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved

// return 2-D NumPy array
return py::array(py::buffer_info(
result.data(), /* data as contiguous array */
sizeof(int), /* size of one scalar */
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
py::format_descriptor<int>::format(), /* data type */
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
ndim, /* number of dimensions */
shape, /* shape of the matrix */
strides /* strides for each axis */
));
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
})
.def("var", [](Measures<PrecisionT> &M, const std::string &operation,
const std::vector<size_t> &wires) {
return M.var(operation, wires);
Expand Down
4 changes: 2 additions & 2 deletions pennylane_lightning/src/gates/GateUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ template <class OperatorImplementation> struct ImplementedGenerators {
};

template <class TypeList, class ValueType, template <class> class ValueClass>
auto ValueForKernelHelper(
[[maybe_unused]] Pennylane::Gates::KernelType kernel) {
auto ValueForKernelHelper([
[maybe_unused]] Pennylane::Gates::KernelType kernel) {
if constexpr (std::is_same_v<TypeList, void>) {
return std::vector<ValueType>{};
} else {
Expand Down
91 changes: 91 additions & 0 deletions pennylane_lightning/src/simulator/Measures.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@
#include <algorithm>
#include <complex>
#include <cstdio>
#include <random>
#include <stack>
#include <unordered_map>
#include <vector>

#include "LinearAlgebra.hpp"
#include "StateVectorManaged.hpp"
#include "StateVectorRaw.hpp"

namespace Pennylane {

/**
* @brief Observable's Measurement Class.
*
Expand Down Expand Up @@ -256,5 +260,92 @@ class Measures {

return expected_value_list;
};

/**
* @brief Generate samples using the alias method.
* Reference: https://en.wikipedia.org/wiki/Alias_method
*
* @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<size_t> generate_samples(size_t num_samples) {
size_t num_qubits = original_statevector.getNumQubits();
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
auto &&probabilities = probs();

std::vector<size_t> samples(num_samples * num_qubits, 0);
std::mt19937 generator(std::random_device{}());
std::uniform_real_distribution<fp_t> distribution(0.0, 1.0);
std::unordered_map<size_t, size_t> cache;

size_t N = probabilities.size();
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
std::vector<double> bucket(N);
std::vector<size_t> bucket_partner(N);
std::stack<size_t> overfull_bucket_ids;
std::stack<size_t> underfull_bucket_ids;

for (size_t i = 0; i < N; i++) {
bucket[i] = N * probabilities[i];
bucket_partner[i] = i;
if (bucket[i] > 1.0) {
overfull_bucket_ids.push(i);
}
if (bucket[i] < 1.0) {
underfull_bucket_ids.push(i);
}
}

// Run alias algorithm
while (underfull_bucket_ids.size() != 0 and
overfull_bucket_ids.size() != 0) {
// get an overfull bucket
auto i = overfull_bucket_ids.top();

// get an underfull bucket
auto j = underfull_bucket_ids.top();
underfull_bucket_ids.pop();

// underfull bucket is partned with an overfull bucket
bucket_partner[j] = i;
bucket[i] = bucket[i] + bucket[j] - 1;

// if overfull bucket is now underfull
// put in underfull stack
if (bucket[i] < 1) {
overfull_bucket_ids.pop();
underfull_bucket_ids.push(i);
}

// if overfull bucket is full -> remove
else if (bucket[i] == 1.0) {
overfull_bucket_ids.pop();
}
}

// Pick samples
for (size_t i = 0; i < num_samples; i++) {
fp_t pct = distribution(generator) * N;
size_t idx = static_cast<size_t>(pct);
if (pct - idx > bucket[idx])
idx = bucket_partner[idx];

// If cached, retrieve sample 1from cache
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
if (cache.count(idx) != 0) {
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);
}
// If not cached, compute
else {
for (size_t j = 0; j < num_qubits; j++)
samples[i * num_qubits + (num_qubits - 1 - j)] =
(idx >> j) & 1;
cache[idx] = i;
}
}

return samples;
}
}; // class Measures
} // namespace Pennylane
4 changes: 2 additions & 2 deletions pennylane_lightning/src/simulator/StateVectorBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
#define PENNYLANE_STATEVECTOR_DEFINE_GATE(GATE_NAME) \
template <Gates::KernelType kernel, typename... Ts> \
inline void apply##GATE_NAME##_(const std::vector<size_t> &wires, \
bool inverse, Ts &&...args) { \
bool inverse, Ts &&... args) { \
auto *arr = getData(); \
static_assert(Gates::static_lookup<Gates::GateOperation::GATE_NAME>( \
Gates::Constant::gate_num_params) == sizeof...(Ts), \
Expand All @@ -63,7 +63,7 @@
#define PENNYLANE_STATEVECTOR_DEFINE_DEFAULT_GATE(GATE_NAME) \
template <typename... Ts> \
inline void apply##GATE_NAME(const std::vector<size_t> &wires, \
bool inverse, Ts &&...args) { \
bool inverse, Ts &&... args) { \
constexpr auto kernel = \
Gates::static_lookup<Gates::GateOperation::GATE_NAME>( \
Gates::Constant::default_kernel_for_gates); \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ using std::vector;
template <typename PrecisionT, class GateImplementation> \
struct Apply##GATE_NAME##IsDefined< \
PrecisionT, GateImplementation, \
std::enable_if_t<std::is_pointer_v< \
decltype(&GateImplementation::template apply##GATE_NAME< \
PrecisionT>)>>> { \
std::enable_if_t<std::is_pointer_v<decltype( \
&GateImplementation::template apply##GATE_NAME<PrecisionT>)>>> { \
constexpr static bool value = true; \
}; \
template <typename PrecisionT, typename TypeList> \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ using namespace Pennylane;
template <typename PrecisionT, typename ParamT, class GateImplementation> \
struct Apply##GATE_NAME##IsDefined< \
PrecisionT, ParamT, GateImplementation, \
std::enable_if_t<std::is_pointer_v< \
decltype(&GateImplementation::template apply##GATE_NAME< \
PrecisionT, ParamT>)>>> { \
std::enable_if_t<std::is_pointer_v<decltype( \
&GateImplementation::template apply##GATE_NAME<PrecisionT, \
ParamT>)>>> { \
constexpr static bool value = true; \
}; \
template <typename PrecisionT, typename ParamT, typename TypeList> \
Expand Down
49 changes: 49 additions & 0 deletions pennylane_lightning/src/tests/Test_Measures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,55 @@ TEST_CASE("Expected Values", "[Measures]") {
}
}

TEST_CASE("Sample", "[Measures]") {
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
constexpr int twos[] = {
1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7,
1 << 8, 1 << 9, 1 << 10, 1 << 11, 1 << 12, 1 << 13, 1 << 14, 1 << 15,
1 << 16, 1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 21, 1 << 22, 1 << 23,
1 << 24, 1 << 25, 1 << 26, 1 << 27, 1 << 28, 1 << 29, 1 << 30, 1 << 31};

// Defining the State Vector that will be measured.
StateVectorManaged<double> Measured_StateVector =
Initializing_StateVector();

// Initializing the measures class.
// It will attach to the StateVector, allowing measures to keep been taken.
Measures<double, StateVectorManaged<double>> Measurer(Measured_StateVector);
vector<double> expected_probabilities = {0.687573, 0.013842, 0.089279,
0.001797, 0.180036, 0.003624,
0.023377, 0.000471};

size_t num_qubits = 3;
size_t N = std::pow(2, num_qubits);
size_t num_samples = 10000;
auto &&samples = Measurer.generate_samples(num_samples);

std::vector<int> counts(N, 0);
std::vector<int> samples_decimal(num_samples, 0);
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved

// 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<double> probabilities(counts.size());
for (size_t i = 0; i < counts.size(); i++) {
probabilities[i] = counts[i] / (double)num_samples;
}

// compare estimated probabilities to real probabilities
SECTION("No wires provided:") {
REQUIRE_THAT(probabilities,
Catch::Approx(expected_probabilities).margin(1e-3));
}
}

TEST_CASE("Variances", "[Measures]") {
trevor-vincent marked this conversation as resolved.
Show resolved Hide resolved
// Defining the State Vector that will be measured.
StateVectorManaged<double> Measured_StateVector =
Expand Down
4 changes: 2 additions & 2 deletions pennylane_lightning/src/tests/Test_OpToMemberFuncPtr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ template <typename PrecisionT, typename ParamT, size_t num_params,
size_t tuple_idx>
constexpr auto gateOpFuncPtrPairsWithNumParamsIter() {
if constexpr (tuple_idx <
std::tuple_size_v<
decltype(gate_op_func_ptr_pairs<PrecisionT, ParamT>)>) {
std::tuple_size_v<decltype(
gate_op_func_ptr_pairs<PrecisionT, ParamT>)>) {
constexpr auto elt =
std::get<tuple_idx>(gate_op_func_ptr_pairs<PrecisionT, ParamT>);
if constexpr (static_lookup<elt.first>(Constant::gate_num_params) ==
Expand Down
8 changes: 4 additions & 4 deletions tests/test_adjoint_jacobian.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def test_pauli_rotation_gradient(self, G, theta, tol, dev, C):
def test_Rot_gradient(self, theta, tol, dev, C):
"""Tests that the device gradient of an arbitrary Euler-angle-parameterized gate is
correct."""
params = np.array([theta, theta**3, np.sqrt(2) * theta])
params = np.array([theta, theta ** 3, np.sqrt(2) * theta])

dev._state = dev._state.astype(C)

Expand Down Expand Up @@ -462,8 +462,8 @@ def circuit(x, y, z):

thetas = np.linspace(-2 * np.pi, 2 * np.pi, 8)

@pytest.mark.parametrize("reused_p", thetas**3 / 19)
@pytest.mark.parametrize("other_p", thetas**2 / 1)
@pytest.mark.parametrize("reused_p", thetas ** 3 / 19)
@pytest.mark.parametrize("other_p", thetas ** 2 / 1)
def test_fanout_multiple_params(self, reused_p, other_p, tol, mocker, dev):
"""Tests that the correct gradient is computed for qnodes which
use the same parameter in multiple gates."""
Expand Down Expand Up @@ -624,7 +624,7 @@ def f(params1, params2):

def circuit_ansatz(params, wires):
"""Circuit ansatz containing all the parametrized gates"""
qml.QubitStateVector(unitary_group.rvs(2**4, random_state=0)[0], wires=wires)
qml.QubitStateVector(unitary_group.rvs(2 ** 4, random_state=0)[0], wires=wires)
qml.RX(params[0], wires=wires[0])
qml.RY(params[1], wires=wires[1])
qml.RX(params[2], wires=wires[2]).inv()
Expand Down
16 changes: 8 additions & 8 deletions tests/test_apply.py
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ def test_sample_values(self, qubit_device_2_wires, tol):

# 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)
assert np.allclose(s1 ** 2, 1, atol=tol, rtol=0)


class TestLightningQubitIntegration:
Expand Down Expand Up @@ -747,7 +747,7 @@ def circuit(x):
def test_nonzero_shots(self, tol):
"""Test that the default qubit plugin provides correct result for high shot number"""

shots = 10**4
shots = 10 ** 4
dev = qml.device("lightning.qubit", wires=1, shots=shots)

p = 0.543
Expand Down Expand Up @@ -1330,13 +1330,13 @@ def test_paulix_pauliy(self, theta, phi, varphi, shots, monkeypatch, tol):
p = dev.probability(wires=obs.wires)

# s1 should only contain 1 and -1
assert np.allclose(s1**2, 1, atol=tolerance, rtol=0)
assert np.allclose(s1 ** 2, 1, atol=tolerance, rtol=0)

mean = s1 @ p
expected = np.sin(theta) * np.sin(phi) * np.sin(varphi)
assert np.allclose(mean, expected, atol=tolerance, rtol=0)

var = (s1**2) @ p - (s1 @ p).real ** 2
var = (s1 ** 2) @ p - (s1 @ p).real ** 2
expected = (
8 * np.sin(theta) ** 2 * np.cos(2 * varphi) * np.sin(phi) ** 2
- np.cos(2 * (theta - phi))
Expand Down Expand Up @@ -1372,13 +1372,13 @@ def test_pauliz_hadamard(
p = dev.marginal_prob(dev.probability(), wires=obs.wires)

# s1 should only contain 1 and -1
assert np.allclose(s1**2, 1, atol=tol, rtol=0)
assert np.allclose(s1 ** 2, 1, atol=tol, rtol=0)

mean = s1 @ p
expected = -(np.cos(varphi) * np.sin(phi) + np.sin(varphi) * np.cos(theta)) / np.sqrt(2)
assert np.allclose(mean, expected, atol=tol, rtol=0)

var = (s1**2) @ p - (s1 @ p).real ** 2
var = (s1 ** 2) @ p - (s1 @ p).real ** 2
expected = (
3
+ np.cos(2 * phi) * np.cos(varphi) ** 2
Expand Down Expand Up @@ -1418,13 +1418,13 @@ def test_qubitunitary_rotation_hadamard(
p = dev.marginal_prob(dev.probability(), wires=obs.wires)

# s1 should only contain 1 and -1
assert np.allclose(s1**2, 1, atol=tol, rtol=0)
assert np.allclose(s1 ** 2, 1, atol=tol, rtol=0)

mean = s1 @ p
expected = -(np.cos(varphi) * np.sin(phi) + np.sin(varphi) * np.cos(theta)) / np.sqrt(2)
assert np.allclose(mean, expected, atol=tol, rtol=0)

var = (s1**2) @ p - (s1 @ p).real ** 2
var = (s1 ** 2) @ p - (s1 @ p).real ** 2
expected = (
3
+ np.cos(2 * phi) * np.cos(varphi) ** 2
Expand Down
Loading