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 shot expval in C++ layer #556

Merged
merged 58 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
8b61616
init commit with PauliX,Y,Z, Hardmard support
multiphaseCFD Nov 7, 2023
fba9221
add unit tests & sample
multiphaseCFD Nov 8, 2023
5c8c286
add PauliX, Y, Z & Hadamard support
multiphaseCFD Nov 9, 2023
56f02e8
move expval shots to base class
multiphaseCFD Nov 9, 2023
d9cacbc
Auto update version
github-actions[bot] Nov 9, 2023
b3a21d1
add MPI support
multiphaseCFD Nov 9, 2023
62b3714
add samples_to_counts to measurement base class
multiphaseCFD Nov 9, 2023
05cfb89
tidy up tests
multiphaseCFD Nov 9, 2023
ddfdb72
move tests to measurement base
multiphaseCFD Nov 9, 2023
44df765
move mpi tests to measurement base class
multiphaseCFD Nov 9, 2023
b3931e9
make format
multiphaseCFD Nov 9, 2023
3a52184
add python layer
multiphaseCFD Nov 10, 2023
d714e0e
add mpi tests
multiphaseCFD Nov 10, 2023
9d1a418
remove else
multiphaseCFD Nov 10, 2023
d9d7a7d
add tensor product support
multiphaseCFD Nov 12, 2023
5745f4f
add more tests for tensor prod obs shots
multiphaseCFD Nov 12, 2023
bcb46d1
make format
multiphaseCFD Nov 12, 2023
68f2865
add Hamiltonian support
multiphaseCFD Nov 14, 2023
bc58332
make format
multiphaseCFD Nov 14, 2023
5288491
quick fix
multiphaseCFD Nov 14, 2023
c7f5ea2
add hamiltonian tests
multiphaseCFD Nov 14, 2023
4b56805
add more py tests for tensorprod
multiphaseCFD Nov 14, 2023
f09342f
remove changes made in py layer
multiphaseCFD Nov 15, 2023
d13e9f2
revert more changes in py layer
multiphaseCFD Nov 15, 2023
9ef8dac
tidy up code
multiphaseCFD Nov 15, 2023
bd8fd5a
update measurement base and kokkos
multiphaseCFD Nov 15, 2023
15d8244
make format
multiphaseCFD Nov 15, 2023
1bc196f
refactor and add _sample_state method
multiphaseCFD Nov 15, 2023
e5b64a0
for loop sum to accumulate sum
multiphaseCFD Nov 15, 2023
6fda049
refactor and add _preprocess_state() method
multiphaseCFD Nov 15, 2023
2949500
add more unit tests for LK backend
multiphaseCFD Nov 16, 2023
70637dc
Merge branch 'master' into add_shot_expval
multiphaseCFD Nov 16, 2023
2cbd160
Auto update version
github-actions[bot] Nov 16, 2023
5595a8a
tidy up docstring
multiphaseCFD Nov 16, 2023
d41f2b2
remove samples() and samples2counts method
multiphaseCFD Nov 16, 2023
ebf80f0
fix typo
multiphaseCFD Nov 16, 2023
3238a08
quick fix
multiphaseCFD Nov 16, 2023
35065d1
update LQRaw object creation
multiphaseCFD Nov 16, 2023
264481f
fix for multiple backends
multiphaseCFD Nov 16, 2023
2d3cf11
update format
multiphaseCFD Nov 16, 2023
b12885d
format fix
multiphaseCFD Nov 16, 2023
ad1e11d
format update
multiphaseCFD Nov 16, 2023
288e01e
make format & trigger MPI CI
multiphaseCFD Nov 16, 2023
e08cb85
add changelog and codecov for expval(obs) method
multiphaseCFD Nov 16, 2023
2e495db
add shot_range coverage
multiphaseCFD Nov 16, 2023
0acc096
tidy up code
multiphaseCFD Nov 16, 2023
4f5f634
add more unit tests
multiphaseCFD Nov 16, 2023
fe042f6
fix typos
multiphaseCFD Nov 16, 2023
06ecd06
add MPI Hamiltonian tests for shots
multiphaseCFD Nov 17, 2023
602f16c
add HamBase tests for applyInPlaceShots
multiphaseCFD Nov 17, 2023
e839cf2
update based on comments
multiphaseCFD Nov 17, 2023
7408813
add more unit tests
multiphaseCFD Nov 17, 2023
00be785
move tests for non-distributed backends to base
multiphaseCFD Nov 17, 2023
6c4dfbd
move all unit tests into the base class
multiphaseCFD Nov 17, 2023
0d07d9c
move getTotalNumQubits to base and tidy up code
multiphaseCFD Nov 17, 2023
055d6b3
tidy up code
multiphaseCFD Nov 17, 2023
1a92ebf
revert changes in Test_MeasurementLQ
multiphaseCFD Nov 17, 2023
62ad2cc
fix typo
multiphaseCFD Nov 17, 2023
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
158 changes: 145 additions & 13 deletions mpitests/test_expval.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
def test_identity_expectation(self, theta, phi, tol):
"""Test that identity expectation value (i.e. the trace) is 1"""
dev = qml.device(device_name, mpi=True, wires=3)
if device_name == "lightning.gpu" and dev.R_DTYPE == np.float32:
pytest.skip("Skipped FP32 tests for expval in lightning.gpu")

O1 = qml.Identity(wires=[0])
O2 = qml.Identity(wires=[1])
Expand All @@ -49,9 +47,6 @@
"""Test that PauliZ expectation value is correct"""
dev = qml.device(device_name, mpi=True, wires=3)

if device_name == "lightning.gpu" and dev.R_DTYPE == np.float32:
pytest.skip("Skipped FP32 tests for expval in lightning.gpu")

O1 = qml.PauliZ(wires=[0])
O2 = qml.PauliZ(wires=[1])

Expand All @@ -63,13 +58,26 @@
res = np.array([dev.expval(O1), dev.expval(O2)])
assert np.allclose(res, np.array([np.cos(theta), np.cos(theta) * np.cos(phi)]), tol)

def test_pauliz_expectation_shots(self, theta, phi, tol):

Check notice on line 61 in mpitests/test_expval.py

View check run for this annotation

codefactor.io / CodeFactor

mpitests/test_expval.py#L61

Unused argument 'tol' (unused-argument)
"""Test that PauliZ expectation value is correct"""
TOL = 5e-2
dev = qml.device(device_name, mpi=True, wires=3, shots=1000)

O1 = qml.PauliZ(wires=[0])
O2 = qml.PauliZ(wires=[1])

dev.apply(
[qml.RX(theta, wires=[0]), qml.RX(phi, wires=[1]), qml.CNOT(wires=[0, 1])],
rotations=[*O1.diagonalizing_gates(), *O2.diagonalizing_gates()],
)

res = np.array([dev.expval(O1), dev.expval(O2)])
assert np.allclose(res, np.array([np.cos(theta), np.cos(theta) * np.cos(phi)]), atol=TOL)

def test_paulix_expectation(self, theta, phi, tol):
"""Test that PauliX expectation value is correct"""
dev = qml.device(device_name, mpi=True, wires=3)

if device_name == "lightning.gpu" and dev.R_DTYPE == np.float32:
pytest.skip("Skipped FP32 tests for expval in lightning.gpu")

O1 = qml.PauliX(wires=[0])
O2 = qml.PauliX(wires=[1])

Expand All @@ -85,13 +93,46 @@
tol * 10,
)

def test_paulix_expectation_shots(self, theta, phi, tol):

Check notice on line 96 in mpitests/test_expval.py

View check run for this annotation

codefactor.io / CodeFactor

mpitests/test_expval.py#L96

Unused argument 'tol' (unused-argument)
"""Test that PauliX expectation value is correct"""
TOL = 5e-2
dev = qml.device(device_name, mpi=True, wires=3, shots=1000)

O1 = qml.PauliX(wires=[0])
O2 = qml.PauliX(wires=[1])

dev.apply(
[qml.RY(theta, wires=[0]), qml.RY(phi, wires=[1]), qml.CNOT(wires=[0, 1])],
rotations=[*O1.diagonalizing_gates(), *O2.diagonalizing_gates()],
)

res = np.array([dev.expval(O1), dev.expval(O2)], dtype=dev.C_DTYPE)
assert np.allclose(
res,
np.array([np.sin(theta) * np.sin(phi), np.sin(phi)], dtype=dev.C_DTYPE),
atol=TOL,
)

def test_pauliy_expectation_shots(self, theta, phi, tol):

Check notice on line 116 in mpitests/test_expval.py

View check run for this annotation

codefactor.io / CodeFactor

mpitests/test_expval.py#L116

Unused argument 'tol' (unused-argument)
"""Test that PauliY expectation value is correct"""
TOL = 5e-2
dev = qml.device(device_name, mpi=True, wires=3, shots=1000)

O1 = qml.PauliY(wires=[0])
O2 = qml.PauliY(wires=[1])

dev.apply(
[qml.RX(theta, wires=[0]), qml.RX(phi, wires=[1]), qml.CNOT(wires=[0, 1])],
rotations=[*O1.diagonalizing_gates(), *O2.diagonalizing_gates()],
)

res = np.array([dev.expval(O1), dev.expval(O2)])
assert np.allclose(res, np.array([0, -np.cos(theta) * np.sin(phi)]), atol=TOL)

def test_pauliy_expectation(self, theta, phi, tol):
"""Test that PauliY expectation value is correct"""
dev = qml.device(device_name, mpi=True, wires=3)

if device_name == "lightning.gpu" and dev.R_DTYPE == np.float32:
pytest.skip("Skipped FP32 tests for expval in lightning.gpu")

O1 = qml.PauliY(wires=[0])
O2 = qml.PauliY(wires=[1])

Expand Down Expand Up @@ -124,14 +165,35 @@
) / np.sqrt(2)
assert np.allclose(res, expected, tol)

def test_hadamard_expectation_shots(self, theta, phi, tol):

Check notice on line 168 in mpitests/test_expval.py

View check run for this annotation

codefactor.io / CodeFactor

mpitests/test_expval.py#L168

Unused argument 'tol' (unused-argument)
"""Test that Hadamard expectation value is correct"""
TOL = 5e-2
dev = qml.device(device_name, mpi=True, wires=3, shots=1000)

O1 = qml.Hadamard(wires=[0])
O2 = qml.Hadamard(wires=[1])

dev.apply(
[qml.RY(theta, wires=[0]), qml.RY(phi, wires=[1]), qml.CNOT(wires=[0, 1])],
rotations=[*O1.diagonalizing_gates(), *O2.diagonalizing_gates()],
)

res = np.array([dev.expval(O1), dev.expval(O2)])
expected = np.array(
[
np.sin(theta) * np.sin(phi) + np.cos(theta),
np.cos(theta) * np.cos(phi) + np.sin(phi),
]
) / np.sqrt(2)
assert np.allclose(res, expected, atol=TOL)

@pytest.mark.parametrize("n_wires", range(1, 8))
def test_hermitian_expectation(self, n_wires, theta, phi, tol):
"""Test that Hadamard expectation value is correct"""
n_qubits = 7
dev_def = qml.device("default.qubit", wires=n_qubits)
dev = qml.device(device_name, mpi=True, wires=n_qubits)
if device_name == "lightning.gpu" and dev.R_DTYPE == np.float32:
pytest.skip("Skipped FP32 tests for expval in lightning.gpu")

comm = MPI.COMM_WORLD

m = 2**n_wires
Expand Down Expand Up @@ -285,6 +347,29 @@
expected = np.sin(theta) * np.sin(phi) * np.sin(varphi)

assert np.allclose(res, expected, atol=tol)

Check notice on line 350 in mpitests/test_expval.py

View check run for this annotation

codefactor.io / CodeFactor

mpitests/test_expval.py#L350

Trailing whitespace (trailing-whitespace)
def test_paulix_pauliy_shots(self, theta, phi, varphi):
"""Test that a tensor product involving PauliX and PauliY works
correctly"""
TOL = 5e-2
dev = qml.device(device_name, mpi=True, wires=3, shots=1000)
obs = qml.PauliX(0) @ qml.PauliY(2)

dev.apply(
[
qml.RX(theta, wires=[0]),
qml.RX(phi, wires=[1]),
qml.RX(varphi, wires=[2]),
qml.CNOT(wires=[0, 1]),
qml.CNOT(wires=[1, 2]),
],
rotations=obs.diagonalizing_gates(),
)
res = dev.expval(obs)

expected = np.sin(theta) * np.sin(phi) * np.sin(varphi)

assert np.allclose(res, expected, atol=TOL)

def test_pauliz_identity(self, theta, phi, varphi, tol):
"""Test that a tensor product involving PauliZ and Identity works
Expand All @@ -308,6 +393,30 @@
expected = np.cos(varphi) * np.cos(phi)

assert np.allclose(res, expected, tol)

Check notice on line 396 in mpitests/test_expval.py

View check run for this annotation

codefactor.io / CodeFactor

mpitests/test_expval.py#L396

Trailing whitespace (trailing-whitespace)
def test_pauliz_identity_shots(self, theta, phi, varphi):
"""Test that a tensor product involving PauliZ and Identity works
correctly"""
TOL = 5e-2
dev = qml.device(device_name, mpi=True, wires=3, shots=1000)
obs = qml.PauliZ(0) @ qml.Identity(1) @ qml.PauliZ(2)

dev.apply(
[
qml.RX(theta, wires=[0]),
qml.RX(phi, wires=[1]),
qml.RX(varphi, wires=[2]),
qml.CNOT(wires=[0, 1]),
qml.CNOT(wires=[1, 2]),
],
rotations=obs.diagonalizing_gates(),
)

res = dev.expval(obs)

expected = np.cos(varphi) * np.cos(phi)

assert np.allclose(res, expected, atol=TOL)

def test_pauliz_hadamard_pauliy(self, theta, phi, varphi, tol):
"""Test that a tensor product involving PauliZ and PauliY and Hadamard
Expand All @@ -330,3 +439,26 @@
expected = -(np.cos(varphi) * np.sin(phi) + np.sin(varphi) * np.cos(theta)) / np.sqrt(2)

assert np.allclose(res, expected, tol)

Check notice on line 442 in mpitests/test_expval.py

View check run for this annotation

codefactor.io / CodeFactor

mpitests/test_expval.py#L442

Trailing whitespace (trailing-whitespace)
def test_pauliz_hadamard_pauliy_shots(self, theta, phi, varphi):
"""Test that a tensor product involving PauliZ and PauliY and Hadamard
works correctly"""
TOL = 5e-2
dev = qml.device(device_name, mpi=True, wires=3, shots=1000)
obs = qml.PauliZ(0) @ qml.Hadamard(1) @ qml.PauliY(2)

dev.apply(
[
qml.RX(theta, wires=[0]),
qml.RX(phi, wires=[1]),
qml.RX(varphi, wires=[2]),
qml.CNOT(wires=[0, 1]),
qml.CNOT(wires=[1, 2]),
],
rotations=obs.diagonalizing_gates(),
)

res = dev.expval(obs)
expected = -(np.cos(varphi) * np.sin(phi) + np.sin(varphi) * np.cos(theta)) / np.sqrt(2)

assert np.allclose(res, expected, atol=TOL)
2 changes: 1 addition & 1 deletion pennylane_lightning/core/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
Version number (major.minor.patch[-label])
"""

__version__ = "0.34.0-dev4"
__version__ = "0.34.0-dev5"
17 changes: 17 additions & 0 deletions pennylane_lightning/core/src/bindings/Bindings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,23 @@ void registerBackendAgnosticMeasurements(PyClass &pyclass) {
return M.expval(*ob);
},
"Expected value of an observable object.")
.def(
"expval",
[](Measurements<StateVectorT> &M,
const std::shared_ptr<Observable<StateVectorT>> &ob,
const size_t &num_shots) {
const std::vector<size_t> &shot_range = {};
return M.expval(*ob, num_shots, shot_range);
},
"Expected value of an observable object.")
.def(
"expval",
[](Measurements<StateVectorT> &M,
const std::shared_ptr<Observable<StateVectorT>> &ob,
const size_t &num_shots, const std::vector<size_t> &shot_range) {
return M.expval(*ob, num_shots, shot_range);
},
"Expected value of an observable object.")
.def(
"var",
[](Measurements<StateVectorT> &M,
Expand Down
17 changes: 17 additions & 0 deletions pennylane_lightning/core/src/bindings/BindingsMPI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,23 @@ void registerBackendAgnosticMeasurementsMPI(PyClass &pyclass) {
return M.expval(*ob);
},
"Expected value of an observable object.")
.def(
"expval",
[](MeasurementsMPI<StateVectorT> &M,
const std::shared_ptr<Observable<StateVectorT>> &ob,
const size_t &num_shots) {
const std::vector<size_t> &shot_range = {};
return M.expval(*ob, num_shots, shot_range);
},
"Expected value of an observable object.")
.def(
"expval",
[](MeasurementsMPI<StateVectorT> &M,
const std::shared_ptr<Observable<StateVectorT>> &ob,
const size_t &num_shots, const std::vector<size_t> &shot_range) {
return M.expval(*ob, num_shots, shot_range);
},
"Expected value of an observable object.")
.def(
"var",
[](MeasurementsMPI<StateVectorT> &M,
Expand Down
Loading