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

Fix Lightning fallbacks to support PL 0.29 changes #416

Merged
merged 19 commits into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
6 changes: 6 additions & 0 deletions pennylane_lightning/lightning_qubit.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,11 @@ def probability(self, wires=None, shot_range=None, bin_size=None):
Returns:
array[float]: list of the probabilities
"""
if wires and len(wires) > 1 and (not np.all(list(wires)[:-1] <= list(wires)[1:])):
mlxd marked this conversation as resolved.
Show resolved Hide resolved
raise RuntimeError(
"Lightning does not currently support out-of-order indices for probabilities"
)

mlxd marked this conversation as resolved.
Show resolved Hide resolved
if self.shots is not None:
return self.estimate_probability(wires=wires, shot_range=shot_range, bin_size=bin_size)

Expand All @@ -756,6 +761,7 @@ def probability(self, wires=None, shot_range=None, bin_size=None):
# To support np.complex64 based on the type of self._state
dtype = self._state.dtype
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.probs(device_wires)
Expand Down
7 changes: 4 additions & 3 deletions pennylane_lightning/src/bindings/Bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ void lightning_class_bindings(py::module_ &m) {
.def(py::init<const StateVectorRawCPU<PrecisionT> &>())
.def("probs",
[](Measures<PrecisionT> &M, const std::vector<size_t> &wires) {
if (wires.empty()) {
return py::array_t<ParamT>(py::cast(M.probs()));
}
return py::array_t<ParamT>(py::cast(M.probs(wires)));
})
.def("probs",
[](Measures<PrecisionT> &M) {
return py::array_t<ParamT>(py::cast(M.probs()));
})
.def("expval",
static_cast<PrecisionT (Measures<PrecisionT>::*)(
const std::string &, const std::vector<size_t> &)>(
Expand Down
4 changes: 3 additions & 1 deletion pennylane_lightning/src/simulator/Measures.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ class Measures {
* @return Floating point std::vector with probabilities.
* The basis columns are rearranged according to wires.
*/
std::vector<fp_t> probs(const std::vector<size_t> &wires) {
std::vector<fp_t>
probs(const std::vector<size_t> &wires,
[[maybe_unused]] const std::vector<size_t> &device_wires = {}) {
// Determining index that would sort the vector.
// This information is needed later.
const auto sorted_ind_wires = Util::sorting_indices(wires);
Expand Down
54 changes: 49 additions & 5 deletions tests/test_measures.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ def circuit():
"cases",
[
[[0, 1], [0.9165164490394898, 0.0, 0.08348355096051052, 0.0]],
[[1, 0], [0.9165164490394898, 0.08348355096051052, 0.0, 0.0]],
[0, [0.9165164490394898, 0.08348355096051052]],
[[0], [0.9165164490394898, 0.08348355096051052]],
],
Expand All @@ -116,6 +115,31 @@ def circuit():

assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)

@pytest.mark.parametrize(
"cases",
[
[[1, 0], [0.9165164490394898, 0.08348355096051052, 0.0, 0.0]],
[["a", "0"], [0.9165164490394898, 0.08348355096051052]],
mlxd marked this conversation as resolved.
Show resolved Hide resolved
],
)
def test_fail_probs_tape_unordered_wires(self, cases, tol, dev):
"""Test probs with a circuit on wires=[0]"""

x, y, z = [0.5, 0.3, -0.7]

@qml.qnode(dev)
def circuit():
qml.RX(0.4, wires=[0])
qml.Rot(x, y, z, wires=[0])
qml.RY(-0.2, wires=[0])
return qml.probs(wires=cases[0])

with pytest.raises(
RuntimeError,
match="Lightning does not currently support out-of-order indices for probabilities",
):
assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)

@pytest.mark.parametrize(
"cases",
[
Expand All @@ -128,6 +152,24 @@ def circuit():
0.0013668981445561978,
],
],
[0, [0.938791280945186, 0.061208719054813635]],
[[0], [0.938791280945186, 0.061208719054813635]],
],
)
def test_probs_tape_wire01(self, cases, tol, dev):
"""Test probs with a circuit on wires=[0,1]"""

@qml.qnode(dev)
def circuit():
qml.RX(0.5, wires=[0])
qml.RY(0.3, wires=[1])
return qml.probs(wires=cases[0])

assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)

@pytest.mark.parametrize(
"cases",
[
[
[1, 0],
[
Expand All @@ -137,11 +179,9 @@ def circuit():
0.0013668981445561978,
],
],
[0, [0.938791280945186, 0.061208719054813635]],
[[0], [0.938791280945186, 0.061208719054813635]],
],
)
def test_probs_tape_wire01(self, cases, tol, dev):
def test_fail_probs_tape_wire01(self, cases, tol, dev):
"""Test probs with a circuit on wires=[0,1]"""

@qml.qnode(dev)
Expand All @@ -150,7 +190,11 @@ def circuit():
qml.RY(0.3, wires=[1])
return qml.probs(wires=cases[0])

assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)
with pytest.raises(
RuntimeError,
match="Lightning does not currently support out-of-order indices for probabilities",
):
assert np.allclose(circuit(), cases[1], atol=tol, rtol=0)


class TestExpval:
Expand Down