diff --git a/doc/development/release_notes.md b/doc/development/release_notes.md
index 8156f3cf4c3..8941bde392a 100644
--- a/doc/development/release_notes.md
+++ b/doc/development/release_notes.md
@@ -3,6 +3,8 @@ Release notes
This page contains the release notes for PennyLane.
+.. mdinclude:: ../releases/changelog-dev.md
+
.. mdinclude:: ../releases/changelog-0.39.0.md
.. mdinclude:: ../releases/changelog-0.38.0.md
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
new file mode 100644
index 00000000000..1e798c14440
--- /dev/null
+++ b/doc/releases/changelog-dev.md
@@ -0,0 +1,24 @@
+:orphan:
+
+# Release 0.40.0-dev (development release)
+
+
New features since last release
+
+Improvements 🛠
+
+Breaking changes 💔
+
+Deprecations 👋
+
+Documentation 📝
+
+Bug fixes 🐛
+
+* Fixes a bug where `qml.ctrl` and `qml.adjoint` queued extra operators if they were defined as the arguments.
+ [(#6284)](https://github.com/PennyLaneAI/pennylane/pull/6284)
+
+Contributors ✍️
+
+This release contains contributions from (in alphabetical order):
+
+Guillermo Alonso
diff --git a/pennylane/_version.py b/pennylane/_version.py
index 04c54fed9c2..55aacf482da 100644
--- a/pennylane/_version.py
+++ b/pennylane/_version.py
@@ -16,4 +16,5 @@
Version number (major.minor.patch[-label])
"""
+
__version__ = "0.39.0"
diff --git a/pennylane/gradients/pulse_gradient.py b/pennylane/gradients/pulse_gradient.py
index f862c676d73..74eb41d6cbf 100644
--- a/pennylane/gradients/pulse_gradient.py
+++ b/pennylane/gradients/pulse_gradient.py
@@ -272,13 +272,6 @@ def _psr_and_contract(res_list, cjacs, int_prefactor):
# Single measurement without shot vector
return _psr_and_contract(results, cjacs, int_prefactor)
- # Multiple measurements with shot vector. Not supported with broadcasting yet.
- if use_broadcasting:
- # TODO: Remove once #2690 is resolved
- raise NotImplementedError(
- "Broadcasting, multiple measurements and shot vectors are currently not "
- "supported all simultaneously by stoch_pulse_grad."
- )
return tuple(
tuple(_psr_and_contract(_r, cjacs, int_prefactor) for _r in zip(*r)) for r in zip(*results)
)
diff --git a/pennylane/ops/op_math/adjoint.py b/pennylane/ops/op_math/adjoint.py
index e09ea4b007d..f0ebacfe5e2 100644
--- a/pennylane/ops/op_math/adjoint.py
+++ b/pennylane/ops/op_math/adjoint.py
@@ -236,6 +236,10 @@ def _adjoint_transform(qfunc: Callable, lazy=True) -> Callable:
@wraps(qfunc)
def wrapper(*args, **kwargs):
qscript = make_qscript(qfunc)(*args, **kwargs)
+
+ leaves, _ = qml.pytrees.flatten((args, kwargs), lambda obj: isinstance(obj, Operator))
+ _ = [qml.QueuingManager.remove(l) for l in leaves if isinstance(l, Operator)]
+
if lazy:
adjoint_ops = [Adjoint(op) for op in reversed(qscript.operations)]
else:
diff --git a/pennylane/ops/op_math/controlled.py b/pennylane/ops/op_math/controlled.py
index 6448f1dc061..6ac000cefd5 100644
--- a/pennylane/ops/op_math/controlled.py
+++ b/pennylane/ops/op_math/controlled.py
@@ -204,6 +204,9 @@ def _ctrl_transform(op, control, control_values, work_wires):
def wrapper(*args, **kwargs):
qscript = qml.tape.make_qscript(op)(*args, **kwargs)
+ leaves, _ = qml.pytrees.flatten((args, kwargs), lambda obj: isinstance(obj, Operator))
+ _ = [qml.QueuingManager.remove(l) for l in leaves if isinstance(l, Operator)]
+
# flip control_values == 0 wires here, so we don't have to do it for each individual op.
flip_control_on_zero = (len(qscript) > 1) and (control_values is not None)
op_control_values = None if flip_control_on_zero else control_values
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 65652b401ad..cfff525c3c7 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -3,6 +3,7 @@ pytest>=7.1.2
pytest-cov>=3.0.0
pytest-mock>=3.7.0
pytest-xdist>=2.5.0
+pytest-rng
flaky>=3.7.0
pytest-forked>=1.4.0
pytest-benchmark
diff --git a/tests/capture/test_capture_cond.py b/tests/capture/test_capture_cond.py
index 32ba9e46355..56ece6b7619 100644
--- a/tests/capture/test_capture_cond.py
+++ b/tests/capture/test_capture_cond.py
@@ -653,13 +653,14 @@ def test_circuit_consts(self, pred, arg, expected):
res_ev_jxpr = jax.core.eval_jaxpr(jaxpr.jaxpr, jaxpr.consts, *args)
assert np.allclose(res_ev_jxpr, expected), f"Expected {expected}, but got {res_ev_jxpr}"
+ @pytest.mark.local_salt(1)
@pytest.mark.parametrize("reset", [True, False])
@pytest.mark.parametrize("postselect", [None, 0, 1])
@pytest.mark.parametrize("shots", [None, 20])
- def test_mcm_predicate_execution(self, reset, postselect, shots):
+ def test_mcm_predicate_execution(self, reset, postselect, shots, seed):
"""Test that QNodes executed with mid-circuit measurement predicates for
qml.cond give correct results."""
- device = qml.device("default.qubit", wires=3, shots=shots, seed=jax.random.PRNGKey(1234))
+ device = qml.device("default.qubit", wires=3, shots=shots, seed=jax.random.PRNGKey(seed))
def true_fn(arg):
qml.RX(arg, 0)
@@ -682,7 +683,7 @@ def f(x, y):
assert np.allclose(res, expected), f"Expected {expected}, but got {res}"
- @pytest.mark.parametrize("shots", [None, 100])
+ @pytest.mark.parametrize("shots", [None, 300])
@pytest.mark.parametrize(
"params, expected",
# The parameters used here will essentially apply a PauliX just before mid-circuit
@@ -696,11 +697,11 @@ def f(x, y):
([0, 0, 0, 0], (1 / np.sqrt(2), 0, 0, 1)), # false_fn, PauliZ basis
],
)
- def test_mcm_predicate_execution_with_elifs(self, params, expected, shots, tol):
+ def test_mcm_predicate_execution_with_elifs(self, params, expected, shots, tol, seed):
"""Test that QNodes executed with mid-circuit measurement predicates for
qml.cond give correct results when there are also elifs present."""
# pylint: disable=expression-not-assigned
- device = qml.device("default.qubit", wires=5, shots=shots, seed=jax.random.PRNGKey(10))
+ device = qml.device("default.qubit", wires=5, shots=shots, seed=jax.random.PRNGKey(seed))
def true_fn():
# Adjoint Hadamard diagonalizing gates to get Hadamard basis state
diff --git a/tests/capture/test_capture_mid_measure.py b/tests/capture/test_capture_mid_measure.py
index 1f246d798fb..a44fd9e342c 100644
--- a/tests/capture/test_capture_mid_measure.py
+++ b/tests/capture/test_capture_mid_measure.py
@@ -322,12 +322,12 @@ class TestMidMeasureExecute:
@pytest.mark.parametrize("reset", [True, False])
@pytest.mark.parametrize("postselect", [None, 0, 1])
@pytest.mark.parametrize("phi", jnp.arange(1.0, 2 * jnp.pi, 1.5))
- def test_simple_circuit_execution(self, phi, reset, postselect, get_device, shots, mp_fn):
+ def test_simple_circuit_execution(self, phi, reset, postselect, get_device, shots, mp_fn, seed):
"""Test that circuits with mid-circuit measurements can be executed in a QNode."""
if shots is None and mp_fn is qml.sample:
pytest.skip("Cannot measure samples in analytic mode")
- dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(12345))
+ dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev)
def f(x):
@@ -340,7 +340,7 @@ def f(x):
@pytest.mark.parametrize("phi", jnp.arange(1.0, 2 * jnp.pi, 1.5))
@pytest.mark.parametrize("multi_mcm", [True, False])
def test_circuit_with_terminal_measurement_execution(
- self, phi, get_device, shots, mp_fn, multi_mcm
+ self, phi, get_device, shots, mp_fn, multi_mcm, seed
):
"""Test that circuits with mid-circuit measurements that also collect statistics
on the mid-circuit measurements can be executed in a QNode."""
@@ -350,7 +350,7 @@ def test_circuit_with_terminal_measurement_execution(
if multi_mcm and mp_fn in (qml.expval, qml.var):
pytest.skip("Cannot measure sequences of MCMs with expval or var")
- dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(12345))
+ dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev)
def f(x, y):
@@ -364,13 +364,13 @@ def f(x, y):
@pytest.mark.xfail
@pytest.mark.parametrize("phi", jnp.arange(1.0, 2 * jnp.pi, 1.5))
- def test_circuit_with_boolean_arithmetic_execution(self, phi, get_device, shots, mp_fn):
+ def test_circuit_with_boolean_arithmetic_execution(self, phi, get_device, shots, mp_fn, seed):
"""Test that circuits that apply boolean logic to mid-circuit measurement values
can be executed."""
if shots is None and mp_fn is qml.sample:
pytest.skip("Cannot measure samples in analytic mode")
- dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(12345))
+ dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev)
def f(x, y):
@@ -386,13 +386,13 @@ def f(x, y):
@pytest.mark.xfail
@pytest.mark.parametrize("phi", jnp.arange(1.0, 2 * jnp.pi, 1.5))
- def test_circuit_with_classical_processing_execution(self, phi, get_device, shots, mp_fn):
+ def test_circuit_with_classical_processing_execution(self, phi, get_device, shots, mp_fn, seed):
"""Test that circuits that apply non-boolean operations to mid-circuit measurement
values can be executed."""
if shots is None and mp_fn is qml.sample:
pytest.skip("Cannot measure samples in analytic mode")
- dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(12345))
+ dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev)
def f(x, y):
@@ -409,13 +409,15 @@ def f(x, y):
@pytest.mark.xfail
@pytest.mark.parametrize("phi", jnp.arange(1.0, 2 * jnp.pi, 1.5))
@pytest.mark.parametrize("fn", [jnp.sin, jnp.sqrt, jnp.log, jnp.exp])
- def mid_measure_processed_with_jax_numpy_execution(self, phi, fn, get_device, shots, mp_fn):
+ def mid_measure_processed_with_jax_numpy_execution(
+ self, phi, fn, get_device, shots, mp_fn, seed
+ ):
"""Test that a circuit containing mid-circuit measurements processed using jax.numpy
can be executed."""
if shots is None and mp_fn is qml.sample:
pytest.skip("Cannot measure samples in analytic mode")
- dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(12345))
+ dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev)
def f(x):
@@ -428,13 +430,13 @@ def f(x):
@pytest.mark.xfail
@pytest.mark.parametrize("phi", jnp.arange(1.0, 2 * jnp.pi, 1.5))
- def test_mid_measure_as_gate_parameter_execution(self, phi, get_device, shots, mp_fn):
+ def test_mid_measure_as_gate_parameter_execution(self, phi, get_device, shots, mp_fn, seed):
"""Test that mid-circuit measurements (simple or classical processed) used as gate
parameters can be executed."""
if shots is None and mp_fn is qml.sample:
pytest.skip("Cannot measure samples in analytic mode")
- dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(12345))
+ dev = get_device(wires=2, shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev)
def f(x):
diff --git a/tests/capture/test_measurements_capture.py b/tests/capture/test_measurements_capture.py
index e43ed204526..21c186fb98c 100644
--- a/tests/capture/test_measurements_capture.py
+++ b/tests/capture/test_measurements_capture.py
@@ -545,14 +545,14 @@ def f():
@pytest.mark.parametrize("x64_mode", (True, False))
-def test_shadow_expval(x64_mode):
+def test_shadow_expval(x64_mode, seed):
"""Test that the shadow expval of an observable can be captured."""
initial_mode = jax.config.jax_enable_x64
jax.config.update("jax_enable_x64", x64_mode)
def f():
- return qml.shadow_expval(qml.X(0), seed=887, k=4)
+ return qml.shadow_expval(qml.X(0), seed=seed, k=4)
jaxpr = jax.make_jaxpr(f)()
@@ -561,7 +561,7 @@ def f():
assert jaxpr.eqns[1].primitive == ShadowExpvalMP._obs_primitive
assert jaxpr.eqns[0].outvars == jaxpr.eqns[1].invars
- assert jaxpr.eqns[1].params == {"seed": 887, "k": 4}
+ assert jaxpr.eqns[1].params == {"seed": seed, "k": 4}
am = jaxpr.eqns[1].outvars[0].aval
assert isinstance(am, AbstractMeasurement)
@@ -638,11 +638,11 @@ def f(w1, w2):
jax.config.update("jax_enable_x64", initial_mode)
-def test_ClassicalShadow():
+def test_ClassicalShadow(seed):
"""Test that the classical shadow measurement can be captured."""
def f():
- return qml.classical_shadow(wires=(0, 1, 2), seed=95)
+ return qml.classical_shadow(wires=(0, 1, 2), seed=seed)
jaxpr = jax.make_jaxpr(f)()
@@ -650,7 +650,7 @@ def f():
assert len(jaxpr.eqns) == 1
assert jaxpr.eqns[0].primitive == ClassicalShadowMP._wires_primitive
- assert jaxpr.eqns[0].params == {"seed": 95}
+ assert jaxpr.eqns[0].params == {"seed": seed}
assert len(jaxpr.eqns[0].invars) == 3
mp = jaxpr.eqns[0].outvars[0].aval
assert isinstance(mp, AbstractMeasurement)
diff --git a/tests/conftest.py b/tests/conftest.py
index d885f74338f..82e1f843169 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -43,12 +43,6 @@ class DummyDevice(DefaultGaussian):
_operation_map["Kerr"] = lambda *x, **y: np.identity(2)
-@pytest.fixture(autouse=True)
-def set_numpy_seed():
- np.random.seed(9872653)
- yield
-
-
@pytest.fixture(scope="session")
def tol():
"""Numerical tolerance for equality tests."""
@@ -106,12 +100,6 @@ def qutrit_device_3_wires(request):
#######################################################################
-@pytest.fixture(scope="module", params=[1, 2, 3])
-def seed(request):
- """Different seeds."""
- return request.param
-
-
@pytest.fixture(scope="function")
def mock_device(monkeypatch):
"""A mock instance of the abstract Device class"""
@@ -190,6 +178,44 @@ def legacy_opmath_only():
pytest.skip("This test exclusively tests legacy opmath")
+#######################################################################
+
+
+@pytest.fixture(autouse=True)
+def restore_global_seed():
+ original_state = np.random.get_state()
+ yield
+ np.random.set_state(original_state)
+
+
+@pytest.fixture
+def seed(request):
+ """An integer random number generator seed
+
+ This fixture overrides the ``seed`` fixture provided by pytest-rng, adding the flexibility
+ of locally getting a new seed for a test case by applying the ``local_salt`` marker. This is
+ useful when the seed from pytest-rng happens to be a bad seed that causes your test to fail.
+
+ .. code_block:: python
+
+ @pytest.mark.local_salt(42)
+ def test_something(seed):
+ ...
+
+ The value passed to ``local_salt`` needs to be an integer.
+
+ """
+
+ fixture_manager = request._fixturemanager # pylint:disable=protected-access
+ fixture_defs = fixture_manager.getfixturedefs("seed", request.node)
+ original_fixture_def = fixture_defs[0] # the original seed fixture provided by pytest-rng
+ original_seed = original_fixture_def.func(request)
+ marker = request.node.get_closest_marker("local_salt")
+ if marker and marker.args:
+ return original_seed + marker.args[0]
+ return original_seed
+
+
#######################################################################
try:
diff --git a/tests/devices/default_qubit/test_default_qubit.py b/tests/devices/default_qubit/test_default_qubit.py
index ff17a6600d7..0ac9bc2cffd 100644
--- a/tests/devices/default_qubit/test_default_qubit.py
+++ b/tests/devices/default_qubit/test_default_qubit.py
@@ -598,12 +598,12 @@ def test_batch_tapes(self, max_workers):
assert results[1].shape == (50,)
@pytest.mark.parametrize("max_workers", max_workers_list)
- def test_counts_wires(self, max_workers):
+ def test_counts_wires(self, max_workers, seed):
"""Test that a Counts measurement with wires works as expected"""
x = np.array(np.pi / 2)
qs = qml.tape.QuantumScript([qml.RY(x, wires=0)], [qml.counts(wires=[0, 1])], shots=10000)
- dev = DefaultQubit(seed=123, max_workers=max_workers)
+ dev = DefaultQubit(seed=seed, max_workers=max_workers)
result = dev.execute(qs)
assert isinstance(result, dict)
@@ -611,11 +611,11 @@ def test_counts_wires(self, max_workers):
# check that the count values match the expected
values = list(result.values())
- assert np.allclose(values[0] / (values[0] + values[1]), 0.5, atol=0.01)
+ assert np.allclose(values[0] / (values[0] + values[1]), 0.5, atol=0.02)
@pytest.mark.parametrize("max_workers", max_workers_list)
@pytest.mark.parametrize("all_outcomes", [False, True])
- def test_counts_obs(self, all_outcomes, max_workers):
+ def test_counts_obs(self, all_outcomes, max_workers, seed):
"""Test that a Counts measurement with an observable works as expected"""
x = np.array(np.pi / 2)
qs = qml.tape.QuantumScript(
@@ -624,7 +624,7 @@ def test_counts_obs(self, all_outcomes, max_workers):
shots=10000,
)
- dev = DefaultQubit(seed=123, max_workers=max_workers)
+ dev = DefaultQubit(seed=seed, max_workers=max_workers)
result = dev.execute(qs)
assert isinstance(result, dict)
@@ -632,7 +632,7 @@ def test_counts_obs(self, all_outcomes, max_workers):
# check that the count values match the expected
values = list(result.values())
- assert np.allclose(values[0] / (values[0] + values[1]), 0.5, atol=0.01)
+ assert np.allclose(values[0] / (values[0] + values[1]), 0.5, rtol=0.05)
class TestExecutingBatches:
@@ -1499,13 +1499,13 @@ class TestHamiltonianSamples:
This is a copy of the tests in test_sampling.py, but using the device instead"""
@pytest.mark.parametrize("max_workers", max_workers_list)
- def test_hamiltonian_expval(self, max_workers):
+ def test_hamiltonian_expval(self, max_workers, seed):
"""Test that sampling works well for Hamiltonian observables"""
x, y = np.array(0.67), np.array(0.95)
ops = [qml.RY(x, wires=0), qml.RZ(y, wires=0)]
meas = [qml.expval(qml.Hamiltonian([0.8, 0.5], [qml.PauliZ(0), qml.PauliX(0)]))]
- dev = DefaultQubit(seed=100, max_workers=max_workers)
+ dev = DefaultQubit(seed=seed, max_workers=max_workers)
qs = qml.tape.QuantumScript(ops, meas, shots=10000)
res = dev.execute(qs)
@@ -1513,13 +1513,13 @@ def test_hamiltonian_expval(self, max_workers):
assert np.allclose(res, expected, atol=0.01)
@pytest.mark.parametrize("max_workers", max_workers_list)
- def test_sum_expval(self, max_workers):
+ def test_sum_expval(self, max_workers, seed):
"""Test that sampling works well for Sum observables"""
x, y = np.array(0.67), np.array(0.95)
ops = [qml.RY(x, wires=0), qml.RZ(y, wires=0)]
meas = [qml.expval(qml.s_prod(0.8, qml.PauliZ(0)) + qml.s_prod(0.5, qml.PauliX(0)))]
- dev = DefaultQubit(seed=100, max_workers=max_workers)
+ dev = DefaultQubit(seed=seed, max_workers=max_workers)
qs = qml.tape.QuantumScript(ops, meas, shots=10000)
res = dev.execute(qs)
@@ -1527,7 +1527,7 @@ def test_sum_expval(self, max_workers):
assert np.allclose(res, expected, atol=0.01)
@pytest.mark.parametrize("max_workers", max_workers_list)
- def test_multi_wires(self, max_workers):
+ def test_multi_wires(self, max_workers, seed):
"""Test that sampling works for Sums with large numbers of wires"""
n_wires = 10
scale = 0.05
@@ -1539,8 +1539,8 @@ def test_multi_wires(self, max_workers):
t2 = 6.2 * qml.prod(*(qml.PauliY(i) for i in range(n_wires)))
H = t1 + t2
- dev = DefaultQubit(seed=100, max_workers=max_workers)
- qs = qml.tape.QuantumScript(ops, [qml.expval(H)], shots=100000)
+ dev = DefaultQubit(seed=seed, max_workers=max_workers)
+ qs = qml.tape.QuantumScript(ops, [qml.expval(H)], shots=30000)
res = dev.execute(qs)
phase = offset + scale * np.array(range(n_wires))
@@ -1548,10 +1548,10 @@ def test_multi_wires(self, max_workers):
sines = qml.math.sin(phase)
expected = 2.5 * qml.math.prod(cosines) + 6.2 * qml.math.prod(sines)
- assert np.allclose(res, expected, atol=0.05)
+ assert np.allclose(res, expected, rtol=0.05)
@pytest.mark.parametrize("max_workers", max_workers_list)
- def test_complex_hamiltonian(self, max_workers):
+ def test_complex_hamiltonian(self, max_workers, seed):
"""Test that sampling works for complex Hamiltonians"""
scale = 0.05
offset = 0.4
@@ -1608,8 +1608,8 @@ def test_complex_hamiltonian(self, max_workers):
],
)
- dev = DefaultQubit(seed=100, max_workers=max_workers)
- qs = qml.tape.QuantumScript(ops, [qml.expval(H)], shots=100000)
+ dev = DefaultQubit(seed=seed, max_workers=max_workers)
+ qs = qml.tape.QuantumScript(ops, [qml.expval(H)], shots=50000)
res = dev.execute(qs)
qs_exp = qml.tape.QuantumScript(ops, [qml.expval(H)])
@@ -1641,17 +1641,18 @@ def test_shape_and_dtype(self, max_workers, n_qubits):
assert np.all(np.logical_or(np.logical_or(res[1] == 0, res[1] == 1), res[1] == 2))
@pytest.mark.parametrize("max_workers", max_workers_list)
- def test_expval(self, max_workers):
+ def test_expval(self, max_workers, seed):
"""Test that shadow expval measurements work as expected"""
- dev = DefaultQubit(seed=100, max_workers=max_workers)
+
+ dev = DefaultQubit(seed=seed, max_workers=max_workers)
ops = [qml.Hadamard(0), qml.Hadamard(1)]
- meas = [qml.shadow_expval(qml.PauliX(0) @ qml.PauliX(1), seed=200)]
- qs = qml.tape.QuantumScript(ops, meas, shots=1000)
+ meas = [qml.shadow_expval(qml.PauliX(0) @ qml.PauliX(1), seed=seed)]
+ qs = qml.tape.QuantumScript(ops, meas, shots=10000)
res = dev.execute(qs)
assert res.shape == ()
- assert np.allclose(res, 1.0, atol=0.05)
+ assert np.allclose(res, 1.0, rtol=0.05)
@pytest.mark.parametrize("n_qubits", [1, 2, 3])
@pytest.mark.parametrize("max_workers", max_workers_list)
@@ -1681,12 +1682,12 @@ def test_multiple_shadow_measurements(self, n_qubits, max_workers):
assert not np.all(res[0] == res[1])
@pytest.mark.parametrize("max_workers", max_workers_list)
- def test_reconstruct_bell_state(self, max_workers):
+ def test_reconstruct_bell_state(self, max_workers, seed):
"""Test that a bell state can be faithfully reconstructed"""
- dev = DefaultQubit(seed=100, max_workers=max_workers)
+ dev = DefaultQubit(seed=seed, max_workers=max_workers)
ops = [qml.Hadamard(0), qml.CNOT([0, 1])]
- meas = [qml.classical_shadow(wires=[0, 1], seed=200)]
+ meas = [qml.classical_shadow(wires=[0, 1], seed=seed)]
qs = qml.tape.QuantumScript(ops, meas, shots=10000)
# should prepare the bell state
@@ -1704,7 +1705,7 @@ def test_reconstruct_bell_state(self, max_workers):
# alternative computation
ops = [qml.Hadamard(0), qml.CNOT([0, 1])]
- meas = [qml.classical_shadow(wires=[0], seed=200)]
+ meas = [qml.classical_shadow(wires=[0], seed=seed)]
qs = qml.tape.QuantumScript(ops, meas, shots=10000)
bits, recipes = dev.execute(qs)
@@ -1837,13 +1838,13 @@ def circ_expected():
)
@pytest.mark.parametrize("param", np.linspace(np.pi / 4, 3 * np.pi / 4, 3))
@pytest.mark.parametrize("shots", [50000, (50000, 50000)])
- def test_postselection_valid_finite_shots(self, param, mp, shots, interface, use_jit):
+ def test_postselection_valid_finite_shots(self, param, mp, shots, interface, use_jit, seed):
"""Test that the results of a circuit with postselection is expected with
finite shots."""
if use_jit and (interface != "jax" or isinstance(shots, tuple)):
pytest.skip("Cannot JIT in non-JAX interfaces, or with shot vectors.")
- dev = qml.device("default.qubit", seed=1971)
+ dev = qml.device("default.qubit", seed=seed)
param = qml.math.asarray(param, like=interface)
@qml.defer_measurements
diff --git a/tests/devices/default_qubit/test_default_qubit_native_mcm.py b/tests/devices/default_qubit/test_default_qubit_native_mcm.py
index 80467c66d3b..eed50f29e0f 100644
--- a/tests/devices/default_qubit/test_default_qubit_native_mcm.py
+++ b/tests/devices/default_qubit/test_default_qubit_native_mcm.py
@@ -27,10 +27,7 @@
pytestmark = pytest.mark.slow
-def get_device(**kwargs):
- kwargs.setdefault("shots", None)
- kwargs.setdefault("seed", 8237945)
- return qml.device("default.qubit", **kwargs)
+# pylint: disable=too-many-arguments
def test_combine_measurements_core():
@@ -57,8 +54,9 @@ def test_measurement_with_no_shots():
@pytest.mark.parametrize("mcm_method", ["one-shot", "tree-traversal"])
def test_all_invalid_shots_circuit(obs, mcm_method):
"""Test that circuits in which all shots mismatch with post-selection conditions return the same answer as ``defer_measurements``."""
- dev = get_device()
- dev_shots = get_device(shots=10)
+
+ dev = qml.device("default.qubit")
+ dev_shots = qml.device("default.qubit", shots=10)
def circuit_op():
m = qml.measure(0, postselect=1)
@@ -85,7 +83,8 @@ def circuit_op():
@pytest.mark.parametrize("mcm_method", ["one-shot", "tree-traversal"])
def test_unsupported_measurement(mcm_method):
"""Test that circuits with unsupported measurements raise the correct error."""
- dev = get_device(shots=1000)
+
+ dev = qml.device("default.qubit", shots=1000)
params = np.pi / 4 * np.ones(2)
@qml.qnode(dev, mcm_method=mcm_method)
@@ -132,7 +131,7 @@ def obs_tape(x, y, z, reset=False, postselect=None):
)
@pytest.mark.parametrize("postselect", [None, 0, 1])
@pytest.mark.parametrize("reset", [False, True])
-def test_multiple_measurements_and_reset(mcm_method, shots, params, postselect, reset):
+def test_multiple_measurements_and_reset(mcm_method, shots, params, postselect, reset, seed):
"""Tests that DefaultQubit handles a circuit with a single mid-circuit measurement with reset
and a conditional gate. Multiple measurements of the mid-circuit measurement value are
performed. This function also tests `reset` parametrizing over the parameter."""
@@ -150,7 +149,7 @@ def test_multiple_measurements_and_reset(mcm_method, shots, params, postselect,
if batch_size is not None and shots is not None and postselect is not None:
pytest.skip("Postselection with samples doesn't work with broadcasting")
- dev = get_device(shots=shots)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
obs = qml.PauliY(1)
state = qml.math.zeros((4,))
state[0] = 1.0
@@ -212,7 +211,7 @@ def func(x, y, z):
],
)
@pytest.mark.parametrize("measure_f", [qml.counts, qml.expval, qml.probs, qml.sample, qml.var])
-def test_composite_mcms(mcm_method, shots, mcm_name, mcm_func, measure_f):
+def test_composite_mcms(mcm_method, shots, mcm_name, mcm_func, measure_f, seed):
"""Tests that DefaultQubit handles a circuit with a composite mid-circuit measurement and a
conditional gate. A single measurement of a composite mid-circuit measurement is performed
at the end."""
@@ -233,7 +232,7 @@ def test_composite_mcms(mcm_method, shots, mcm_name, mcm_func, measure_f):
"Cannot use qml.probs() when measuring multiple mid-circuit measurements collected using arithmetic operators."
)
- dev = get_device(shots=shots)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
param = qml.numpy.array([np.pi / 3, np.pi / 6])
def func(x, y):
@@ -260,12 +259,12 @@ def func(x, y):
@pytest.mark.parametrize("postselect", [None, 0, 1])
@pytest.mark.parametrize("reset", [False, True])
@pytest.mark.parametrize("measure_f", [qml.expval])
-def composite_mcm_gradient_measure_obs(shots, postselect, reset, measure_f):
+def composite_mcm_gradient_measure_obs(shots, postselect, reset, measure_f, seed):
"""Tests that DefaultQubit can differentiate a circuit with a composite mid-circuit
measurement and a conditional gate. A single measurement of a common observable is
performed at the end."""
- dev = get_device(shots=shots)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
param = qml.numpy.array([np.pi / 3, np.pi / 6])
obs = qml.PauliZ(0) @ qml.PauliZ(1)
@@ -294,7 +293,7 @@ def func(x, y):
@pytest.mark.parametrize("mcm_method", ["one-shot", "tree-traversal"])
-def test_sample_with_broadcasting_and_postselection_error(mcm_method):
+def test_sample_with_broadcasting_and_postselection_error(mcm_method, seed):
"""Test that an error is raised if returning qml.sample if postselecting with broadcasting"""
tape = qml.tape.QuantumScript(
[qml.RX([0.1, 0.2], 0), MidMeasureMP(0, postselect=1)], [qml.sample(wires=0)], shots=10
@@ -302,7 +301,7 @@ def test_sample_with_broadcasting_and_postselection_error(mcm_method):
with pytest.raises(ValueError, match="Returning qml.sample is not supported when"):
qml.transforms.dynamic_one_shot(tape)
- dev = get_device(shots=10)
+ dev = qml.device("default.qubit", shots=10, seed=seed)
@qml.qnode(dev, mcm_method=mcm_method)
def circuit(x):
@@ -317,11 +316,11 @@ def circuit(x):
@pytest.mark.all_interfaces
@pytest.mark.parametrize("interface", ["torch", "tensorflow", "jax", "autograd"])
@pytest.mark.parametrize("mcm_method", ["one-shot", "tree-traversal"])
-def test_finite_diff_in_transform_program(interface, mcm_method):
+def test_finite_diff_in_transform_program(interface, mcm_method, seed):
"""Test that finite diff is in the transform program of a qnode containing
mid-circuit measurements"""
- dev = get_device(shots=10)
+ dev = qml.device("default.qubit", shots=10, seed=seed)
@qml.qnode(dev, mcm_method=mcm_method, diff_method="finite-diff")
def circuit(x):
@@ -348,13 +347,13 @@ class TestJaxIntegration:
@pytest.mark.parametrize("mcm_method", ["one-shot", "tree-traversal"])
@pytest.mark.parametrize("shots", [100, [100, 101], [100, 100, 101]])
@pytest.mark.parametrize("postselect", [None, 0, 1])
- def test_sample_with_prng_key(self, mcm_method, shots, postselect):
+ def test_sample_with_prng_key(self, mcm_method, shots, postselect, seed):
"""Test that setting a PRNGKey gives the expected behaviour. With separate calls
to DefaultQubit.execute, the same results are expected when using a PRNGKey"""
# pylint: disable=import-outside-toplevel
from jax.random import PRNGKey
- dev = get_device(shots=shots, seed=PRNGKey(678))
+ dev = qml.device("default.qubit", shots=shots, seed=PRNGKey(seed))
params = [np.pi / 4, np.pi / 3]
obs = qml.PauliZ(0) @ qml.PauliZ(1)
@@ -389,14 +388,14 @@ def func(x, y):
@pytest.mark.parametrize("diff_method", [None, "best"])
@pytest.mark.parametrize("postselect", [None, 1])
@pytest.mark.parametrize("reset", [False, True])
- def test_jax_jit(self, diff_method, postselect, reset):
+ def test_jax_jit(self, diff_method, postselect, reset, seed):
"""Tests that DefaultQubit handles a circuit with a single mid-circuit measurement and a
conditional gate. A single measurement of a common observable is performed at the end."""
import jax
shots = 10
- dev = get_device(shots=shots, seed=jax.random.PRNGKey(678))
+ dev = qml.device("default.qubit", shots=shots, seed=jax.random.PRNGKey(seed))
params = [np.pi / 2.5, np.pi / 3, -np.pi / 3.5]
obs = qml.PauliY(0)
diff --git a/tests/devices/qubit/test_apply_operation.py b/tests/devices/qubit/test_apply_operation.py
index ec4a31804bb..08235091ee6 100644
--- a/tests/devices/qubit/test_apply_operation.py
+++ b/tests/devices/qubit/test_apply_operation.py
@@ -1329,8 +1329,8 @@ def test_conditional(self, wires, unitary, batched, ml_framework):
qml.math.squeeze(initial_state), qml.math.reshape(new_state, (n_states, 4))
)
- @pytest.mark.parametrize("rng_seed, m_res", ((12, (0, 0)), (42, (1, 1))))
- def test_mid_measure(self, rng_seed, m_res):
+ @pytest.mark.parametrize("m_res", [(0, 0), (1, 1)])
+ def test_mid_measure(self, m_res, monkeypatch):
"""Test the application of a MidMeasureMP on an arbitrary state to give a basis state."""
initial_state = np.array(
@@ -1344,14 +1344,15 @@ def test_mid_measure(self, rng_seed, m_res):
mid_state[m_res[0]] = initial_state[m_res[0]] / np.linalg.norm(initial_state[m_res[0]])
end_state[m_res] = mid_state[m_res] / np.abs(mid_state[m_res])
- rng = np.random.default_rng(rng_seed)
m0, m1 = qml.measure(0).measurements[0], qml.measure(1).measurements[0]
mid_meas = {}
- res_state = apply_operation(m0, initial_state, mid_measurements=mid_meas, rng=rng)
+ monkeypatch.setattr(np.random, "binomial", lambda *args: m_res[0])
+
+ res_state = apply_operation(m0, initial_state, mid_measurements=mid_meas)
assert qml.math.allclose(mid_state, res_state)
- res_state = apply_operation(m1, res_state, mid_measurements=mid_meas, rng=rng)
+ res_state = apply_operation(m1, res_state, mid_measurements=mid_meas)
assert qml.math.allclose(end_state, res_state)
assert mid_meas == {m0: m_res[0], m1: m_res[1]}
diff --git a/tests/devices/qubit/test_sampling.py b/tests/devices/qubit/test_sampling.py
index f0ebc8aa3ac..1675508b98b 100644
--- a/tests/devices/qubit/test_sampling.py
+++ b/tests/devices/qubit/test_sampling.py
@@ -32,9 +32,9 @@
def fixture_init_state():
"""Generates a random initial state"""
- def _init_state(n):
+ def _init_state(n, seed):
"""random initial state"""
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
state = rng.random([1 << n]) + rng.random([1 << n]) * 1j
state /= np.linalg.norm(state)
return state.reshape((2,) * n)
@@ -98,13 +98,13 @@ def test_prng_key_as_seed_uses_sample_state_jax(self, mocker):
spy.assert_called_once()
@pytest.mark.jax
- def test_sample_state_jax(self):
+ def test_sample_state_jax(self, seed):
"""Tests that the returned samples are as expected when explicitly calling sample_state."""
import jax
state = qml.math.array(two_qubit_state, like="jax")
- samples = sample_state(state, 10, prng_key=jax.random.PRNGKey(84))
+ samples = sample_state(state, 10, prng_key=jax.random.PRNGKey(seed))
assert samples.shape == (10, 2)
assert samples.dtype == np.int64
@@ -141,11 +141,11 @@ def test_sample_state_custom_rng(self):
expected = [[0, 1], [0, 1], [1, 0], [1, 0]]
assert qml.math.allequal(samples, expected)
- def test_approximate_probs_from_samples(self, init_state):
+ def test_approximate_probs_from_samples(self, init_state, seed):
"""Tests that the generated samples are approximately as expected."""
n = 4
shots = 20000
- state = init_state(n)
+ state = init_state(n, seed)
flat_state = state.flatten()
expected_probs = np.real(flat_state) ** 2 + np.imag(flat_state) ** 2
@@ -310,47 +310,47 @@ def test_var_measure_single_wire(self):
assert result0 == 0
assert result1 == 0
- def test_approximate_sample_measure(self):
+ def test_approximate_sample_measure(self, seed):
"""Test that a sample measurement returns approximately the correct distribution"""
state = qml.math.array(two_qubit_state)
shots = qml.measurements.Shots(10000)
mp = qml.sample(wires=range(2))
- result = measure_with_samples([mp], state, shots=shots, rng=123)[0]
+ result = measure_with_samples([mp], state, shots=shots, rng=seed)[0]
one_prob = np.count_nonzero(result[:, 0]) / result.shape[0]
assert np.allclose(one_prob, 0.5, atol=0.05)
- def test_approximate_prob_measure(self):
+ def test_approximate_prob_measure(self, seed):
"""Test that a probability measurement works as expected"""
state = qml.math.array(two_qubit_state)
shots = qml.measurements.Shots(10000)
mp = qml.probs(wires=range(2))
- result = measure_with_samples([mp], state, shots=shots, rng=123)[0]
+ result = measure_with_samples([mp], state, shots=shots, rng=seed)[0]
assert np.allclose(result[1], 0.5, atol=0.05)
assert np.allclose(result[2], 0.5, atol=0.05)
assert result[1] + result[2] == 1
- def test_approximate_expval_measure(self):
+ def test_approximate_expval_measure(self, seed):
"""Test that an expval measurement works as expected"""
state = qml.math.array(two_qubit_state)
shots = qml.measurements.Shots(10000)
mp = qml.expval(qml.prod(qml.PauliX(0), qml.PauliX(1)))
- result = measure_with_samples([mp], state, shots=shots, rng=123)[0]
+ result = measure_with_samples([mp], state, shots=shots, rng=seed)[0]
assert result != 0
assert np.allclose(result, 0, atol=0.05)
- def test_approximate_var_measure(self):
+ def test_approximate_var_measure(self, seed):
"""Test that a variance measurement works as expected"""
state = qml.math.array(two_qubit_state)
shots = qml.measurements.Shots(10000)
mp = qml.var(qml.prod(qml.PauliX(0), qml.PauliX(1)))
- result = measure_with_samples([mp], state, shots=shots, rng=123)[0]
+ result = measure_with_samples([mp], state, shots=shots, rng=seed)[0]
assert result != 1
assert np.allclose(result, 1, atol=0.05)
@@ -782,10 +782,10 @@ def test_sample_batched_state_renorm_error(self, interface):
class TestBroadcasting:
"""Test that measurements work when the state has a batch dim"""
- def test_sample_measure(self):
+ def test_sample_measure(self, seed):
"""Test that broadcasting works for qml.sample and single shots"""
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(100)
state = [
@@ -821,10 +821,9 @@ def test_sample_measure(self):
(qml.var(qml.PauliZ(1)), np.array([0, 0, 1])),
],
)
- def test_nonsample_measure(self, measurement, expected):
+ def test_nonsample_measure(self, measurement, expected, seed):
"""Test that broadcasting works for the other sample measurements and single shots"""
- rng = np.random.default_rng(123)
shots = qml.measurements.Shots(10000)
state = [
@@ -834,8 +833,8 @@ def test_nonsample_measure(self, measurement, expected):
]
state = np.stack(state)
- res = measure_with_samples([measurement], state, shots, is_state_batched=True, rng=rng)
- assert np.allclose(res, expected, atol=0.01)
+ res = measure_with_samples([measurement], state, shots, is_state_batched=True, rng=seed)
+ assert np.allclose(res, expected, atol=0.03)
@pytest.mark.parametrize(
"shots",
@@ -847,10 +846,10 @@ def test_nonsample_measure(self, measurement, expected):
(200, (100, 2)),
],
)
- def test_sample_measure_shot_vector(self, shots):
+ def test_sample_measure_shot_vector(self, shots, seed):
"""Test that broadcasting works for qml.sample and shot vectors"""
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(shots)
state = [
@@ -905,10 +904,10 @@ def test_sample_measure_shot_vector(self, shots):
(qml.var(qml.PauliZ(1)), np.array([0, 0, 1])),
],
)
- def test_nonsample_measure_shot_vector(self, shots, measurement, expected):
+ def test_nonsample_measure_shot_vector(self, shots, measurement, expected, seed):
"""Test that broadcasting works for the other sample measurements and shot vectors"""
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(shots)
state = [
@@ -937,7 +936,7 @@ class TestBroadcastingPRNG:
"""Test that measurements work and use sample_state when the state has a batch dim
and a PRNG key is provided"""
- def test_sample_measure(self, mocker):
+ def test_sample_measure(self, mocker, seed):
"""Test that broadcasting works for qml.sample and single shots"""
import jax
@@ -945,7 +944,7 @@ def test_sample_measure(self, mocker):
spy = mocker.spy(qml.devices.qubit.sampling, "_sample_probs_jax")
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(100)
state = [
@@ -962,7 +961,7 @@ def test_sample_measure(self, mocker):
shots,
is_state_batched=True,
rng=rng,
- prng_key=jax.random.PRNGKey(184),
+ prng_key=jax.random.PRNGKey(seed),
)[0]
spy.assert_called()
@@ -993,13 +992,13 @@ def test_sample_measure(self, mocker):
(qml.var(qml.PauliZ(1)), np.array([0, 0, 1])),
],
)
- def test_nonsample_measure(self, mocker, measurement, expected):
+ def test_nonsample_measure(self, mocker, measurement, expected, seed):
"""Test that broadcasting works for the other sample measurements and single shots"""
import jax
spy = mocker.spy(qml.devices.qubit.sampling, "_sample_probs_jax")
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(10000)
state = [
@@ -1015,7 +1014,7 @@ def test_nonsample_measure(self, mocker, measurement, expected):
shots,
is_state_batched=True,
rng=rng,
- prng_key=jax.random.PRNGKey(184),
+ prng_key=jax.random.PRNGKey(seed),
)
spy.assert_called()
@@ -1031,14 +1030,14 @@ def test_nonsample_measure(self, mocker, measurement, expected):
(200, (100, 2)),
],
)
- def test_sample_measure_shot_vector(self, mocker, shots):
+ def test_sample_measure_shot_vector(self, mocker, shots, seed):
"""Test that broadcasting works for qml.sample and shot vectors"""
import jax
spy = mocker.spy(qml.devices.qubit.sampling, "_sample_probs_jax")
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(shots)
state = [
@@ -1055,7 +1054,7 @@ def test_sample_measure_shot_vector(self, mocker, shots):
shots,
is_state_batched=True,
rng=rng,
- prng_key=jax.random.PRNGKey(184),
+ prng_key=jax.random.PRNGKey(seed),
)
spy.assert_called()
@@ -1107,14 +1106,14 @@ def test_sample_measure_shot_vector(self, mocker, shots):
(qml.var(qml.PauliZ(1)), np.array([0, 0, 1])),
],
)
- def test_nonsample_measure_shot_vector(self, mocker, shots, measurement, expected):
+ def test_nonsample_measure_shot_vector(self, mocker, shots, measurement, expected, seed):
"""Test that broadcasting works for the other sample measurements and shot vectors"""
import jax
spy = mocker.spy(qml.devices.qubit.sampling, "_sample_probs_jax")
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(shots)
state = [
@@ -1130,7 +1129,7 @@ def test_nonsample_measure_shot_vector(self, mocker, shots, measurement, expecte
shots,
is_state_batched=True,
rng=rng,
- prng_key=jax.random.PRNGKey(0),
+ prng_key=jax.random.PRNGKey(seed),
)
spy.assert_called()
@@ -1152,26 +1151,26 @@ class TestHamiltonianSamples:
Hamiltonian and Sum observables"""
@pytest.mark.usefixtures("use_legacy_and_new_opmath")
- def test_hamiltonian_expval(self):
+ def test_hamiltonian_expval(self, seed):
"""Test that sampling works well for Hamiltonian observables"""
x, y = np.array(0.67), np.array(0.95)
ops = [qml.RY(x, wires=0), qml.RZ(y, wires=0)]
meas = [qml.expval(qml.Hamiltonian([0.8, 0.5], [qml.PauliZ(0), qml.PauliX(0)]))]
qs = qml.tape.QuantumScript(ops, meas, shots=10000)
- res = simulate(qs, rng=200)
+ res = simulate(qs, rng=seed)
expected = 0.8 * np.cos(x) + 0.5 * np.real(np.exp(y * 1j)) * np.sin(x)
- assert np.allclose(res, expected, atol=0.01)
+ assert np.allclose(res, expected, atol=0.02)
- def test_hamiltonian_expval_shot_vector(self):
+ def test_hamiltonian_expval_shot_vector(self, seed):
"""Test that sampling works well for Hamiltonian observables with a shot vector"""
x, y = np.array(0.67), np.array(0.95)
ops = [qml.RY(x, wires=0), qml.RZ(y, wires=0)]
meas = [qml.expval(qml.Hamiltonian([0.8, 0.5], [qml.PauliZ(0), qml.PauliX(0)]))]
qs = qml.tape.QuantumScript(ops, meas, shots=(10000, 10000))
- res = simulate(qs, rng=200)
+ res = simulate(qs, rng=seed)
expected = 0.8 * np.cos(x) + 0.5 * np.real(np.exp(y * 1j)) * np.sin(x)
@@ -1180,7 +1179,7 @@ def test_hamiltonian_expval_shot_vector(self):
assert np.allclose(res[0], expected, atol=0.01)
assert np.allclose(res[1], expected, atol=0.01)
- def test_sum_expval(self):
+ def test_sum_expval(self, seed):
"""Test that sampling works well for Sum observables"""
x, y = np.array(0.67), np.array(0.95)
@@ -1188,19 +1187,19 @@ def test_sum_expval(self):
meas = [qml.expval(qml.s_prod(0.8, qml.PauliZ(0)) + qml.s_prod(0.5, qml.PauliX(0)))]
qs = qml.tape.QuantumScript(ops, meas, shots=10000)
- res = simulate(qs, rng=200)
+ res = simulate(qs, rng=seed)
expected = 0.8 * np.cos(x) + 0.5 * np.real(np.exp(y * 1j)) * np.sin(x)
assert np.allclose(res, expected, atol=0.01)
- def test_sum_expval_shot_vector(self):
+ def test_sum_expval_shot_vector(self, seed):
"""Test that sampling works well for Sum observables with a shot vector."""
x, y = np.array(0.67), np.array(0.95)
ops = [qml.RY(x, wires=0), qml.RZ(y, wires=0)]
meas = [qml.expval(qml.s_prod(0.8, qml.PauliZ(0)) + qml.s_prod(0.5, qml.PauliX(0)))]
qs = qml.tape.QuantumScript(ops, meas, shots=(10000, 10000))
- res = simulate(qs, rng=200)
+ res = simulate(qs, rng=seed)
expected = 0.8 * np.cos(x) + 0.5 * np.real(np.exp(y * 1j)) * np.sin(x)
@@ -1209,7 +1208,7 @@ def test_sum_expval_shot_vector(self):
assert np.allclose(res[0], expected, atol=0.01)
assert np.allclose(res[1], expected, atol=0.01)
- def test_prod_expval(self):
+ def test_prod_expval(self, seed):
"""Tests that sampling works for Prod observables"""
x, y = np.array(0.67), np.array(0.95)
@@ -1218,11 +1217,11 @@ def test_prod_expval(self):
tape = qml.tape.QuantumScript(
ops, measurements=[qml.expval(qml.PauliX(0)), qml.expval(H)], shots=10000
)
- res = simulate(tape, rng=200)
+ res = simulate(tape, rng=seed)
expected = [np.sin(y), -np.sin(y) * np.sin(x)]
assert np.allclose(res, expected, atol=0.05)
- def test_sprod_expval(self):
+ def test_sprod_expval(self, seed):
"""Tests that sampling works for SProd observables"""
y = np.array(0.95)
@@ -1231,11 +1230,11 @@ def test_sprod_expval(self):
tape = qml.tape.QuantumScript(
ops, measurements=[qml.expval(qml.PauliX(0)), qml.expval(H)], shots=10000
)
- res = simulate(tape, rng=200)
+ res = simulate(tape, rng=seed)
expected = [np.sin(y), 1.5 * np.sin(y)]
assert np.allclose(res, expected, atol=0.05)
- def test_multi_wires(self):
+ def test_multi_wires(self, seed):
"""Test that sampling works for Sums with large numbers of wires"""
n_wires = 10
scale = 0.05
@@ -1248,7 +1247,7 @@ def test_multi_wires(self):
H = t1 + t2
qs = qml.tape.QuantumScript(ops, [qml.expval(H)], shots=100000)
- res = simulate(qs, rng=100)
+ res = simulate(qs, rng=seed)
phase = offset + scale * np.array(range(n_wires))
cosines = qml.math.cos(phase)
@@ -1257,7 +1256,7 @@ def test_multi_wires(self):
assert np.allclose(res, expected, atol=0.05)
- def test_complex_hamiltonian(self):
+ def test_complex_hamiltonian(self, seed):
"""Test that sampling works for complex Hamiltonians"""
scale = 0.05
offset = 0.4
@@ -1315,7 +1314,7 @@ def test_complex_hamiltonian(self):
)
qs = qml.tape.QuantumScript(ops, [qml.expval(H)], shots=100000)
- res = simulate(qs, rng=100)
+ res = simulate(qs, rng=seed)
qs_exp = qml.tape.QuantumScript(ops, [qml.expval(H)])
expected = simulate(qs_exp)
@@ -1324,43 +1323,39 @@ def test_complex_hamiltonian(self):
class TestSampleProbs:
- # pylint: disable=attribute-defined-outside-init
- @pytest.fixture(autouse=True)
- def setup(self):
- self.rng = np.random.default_rng(42) # Fixed seed for reproducibility
- def test_basic_sampling(self):
+ def test_basic_sampling(self, seed):
"""One Qubit, two outcomes"""
probs = np.array([0.3, 0.7])
- samples = sample_probs(probs, shots=1000, num_wires=1, is_state_batched=False, rng=self.rng)
+ samples = sample_probs(probs, shots=1000, num_wires=1, is_state_batched=False, rng=seed)
assert samples.shape == (1000, 1)
# Check if the distribution is roughly correct (allowing for some variance)
zeros = np.sum(samples == 0)
assert 250 <= zeros <= 350 # Approx 30% of 1000, with some leeway
- def test_multi_qubit_sampling(self):
+ def test_multi_qubit_sampling(self, seed):
"""Two Qubit, four outcomes"""
probs = np.array([0.1, 0.2, 0.3, 0.4])
- samples = sample_probs(probs, shots=1000, num_wires=2, is_state_batched=False, rng=self.rng)
+ samples = sample_probs(probs, shots=1000, num_wires=2, is_state_batched=False, rng=seed)
assert samples.shape == (1000, 2)
# Check if all possible states are present
unique_samples = set(map(tuple, samples))
assert len(unique_samples) == 4
- def test_batched_sampling(self):
+ def test_batched_sampling(self, seed):
"""A batch of two circuits, each with two outcomes"""
probs = np.array([[0.5, 0.5], [0.3, 0.7]])
- samples = sample_probs(probs, shots=1000, num_wires=1, is_state_batched=True, rng=self.rng)
+ samples = sample_probs(probs, shots=1000, num_wires=1, is_state_batched=True, rng=seed)
assert samples.shape == (2, 1000, 1)
- def test_cutoff_edge_case_failure(self):
+ def test_cutoff_edge_case_failure(self, seed):
"""Test sampling with probabilities just outside the cutoff."""
cutoff = 1e-7 # Assuming this is the cutoff used in sample_probs
probs = np.array([0.5, 0.5 - 2 * cutoff])
with pytest.raises(ValueError, match=r"(?i)probabilities do not sum to 1"):
- sample_probs(probs, shots=1000, num_wires=1, is_state_batched=False, rng=self.rng)
+ sample_probs(probs, shots=1000, num_wires=1, is_state_batched=False, rng=seed)
- def test_batched_cutoff_edge_case_failure(self):
+ def test_batched_cutoff_edge_case_failure(self, seed):
"""Test sampling with probabilities just outside the cutoff."""
cutoff = 1e-7 # Assuming this is the cutoff used in sample_probs
probs = np.array(
@@ -1370,4 +1365,4 @@ def test_batched_cutoff_edge_case_failure(self):
]
)
with pytest.raises(ValueError, match=r"(?i)probabilities do not sum to 1"):
- sample_probs(probs, shots=1000, num_wires=1, is_state_batched=True, rng=self.rng)
+ sample_probs(probs, shots=1000, num_wires=1, is_state_batched=True, rng=seed)
diff --git a/tests/devices/qubit/test_simulate.py b/tests/devices/qubit/test_simulate.py
index 5de0c6c14a5..c926a4d655c 100644
--- a/tests/devices/qubit/test_simulate.py
+++ b/tests/devices/qubit/test_simulate.py
@@ -18,7 +18,6 @@
import pytest
import scipy as sp
from dummy_debugger import Debugger
-from flaky import flaky
from stat_utils import fisher_exact_test
import pennylane as qml
@@ -304,7 +303,7 @@ def test_broadcasted_op_state(self):
assert np.allclose(res[0], np.cos(x))
assert np.allclose(res[1], -np.cos(x))
- def test_broadcasted_prep_sample(self):
+ def test_broadcasted_prep_sample(self, seed):
"""Test that simulate works for sample measurements
when the state prep has broadcasted parameters"""
x = np.array(1.2)
@@ -313,8 +312,8 @@ def test_broadcasted_prep_sample(self):
measurements = [qml.expval(qml.PauliZ(i)) for i in range(2)]
prep = [qml.StatePrep(np.eye(4), wires=[0, 1])]
- qs = qml.tape.QuantumScript(prep + ops, measurements, shots=qml.measurements.Shots(10000))
- res = simulate(qs, rng=123)
+ qs = qml.tape.QuantumScript(prep + ops, measurements, shots=qml.measurements.Shots(5000))
+ res = simulate(qs, rng=seed)
assert isinstance(res, tuple)
assert len(res) == 2
@@ -326,7 +325,7 @@ def test_broadcasted_prep_sample(self):
)
state, is_state_batched = get_final_state(qs)
- res = measure_final_state(qs, state, is_state_batched, rng=123)
+ res = measure_final_state(qs, state, is_state_batched, rng=seed)
expected_state = np.array(
[
[np.cos(x / 2), 0, 0, np.sin(x / 2)],
@@ -347,7 +346,7 @@ def test_broadcasted_prep_sample(self):
res[1], np.array([np.cos(x), -np.cos(x), -np.cos(x), np.cos(x)]), atol=0.05
)
- def test_broadcasted_op_sample(self):
+ def test_broadcasted_op_sample(self, seed):
"""Test that simulate works for sample measurements
when an operation has broadcasted parameters"""
x = np.array([0.8, 1.0, 1.2, 1.4])
@@ -355,8 +354,8 @@ def test_broadcasted_op_sample(self):
ops = [qml.PauliX(wires=1), qml.RY(x, wires=0), qml.CNOT(wires=[0, 1])]
measurements = [qml.expval(qml.PauliZ(i)) for i in range(2)]
- qs = qml.tape.QuantumScript(ops, measurements, shots=qml.measurements.Shots(10000))
- res = simulate(qs, rng=123)
+ qs = qml.tape.QuantumScript(ops, measurements, shots=qml.measurements.Shots(5000))
+ res = simulate(qs, rng=seed)
assert isinstance(res, tuple)
assert len(res) == 2
@@ -364,7 +363,7 @@ def test_broadcasted_op_sample(self):
assert np.allclose(res[1], -np.cos(x), atol=0.05)
state, is_state_batched = get_final_state(qs)
- res = measure_final_state(qs, state, is_state_batched, rng=123)
+ res = measure_final_state(qs, state, is_state_batched, rng=seed)
expected_state = np.zeros((4, 2, 2))
expected_state[:, 0, 1] = np.cos(x / 2)
@@ -1295,7 +1294,7 @@ def test_basic_mid_meas_circuit_with_reset(self):
@pytest.mark.parametrize(
"meas_obj", [qml.Y(0), [1], [1, 0], "mcm", "composite_mcm", "mcm_list"]
)
- def test_simple_dynamic_circuit(self, shots, measure_f, postselect, reset, meas_obj):
+ def test_simple_dynamic_circuit(self, shots, measure_f, postselect, reset, meas_obj, seed):
"""Tests that `simulate` can handles a simple dynamic circuit with the following measurements:
* qml.counts with obs (comp basis or not), single wire, multiple wires (ordered/unordered), MCM, f(MCM), MCM list
@@ -1361,7 +1360,7 @@ def test_simple_dynamic_circuit(self, shots, measure_f, postselect, reset, meas_
shots=shots,
)
- rng = np.random.default_rng(1234)
+ rng = np.random.default_rng(seed)
results0 = simulate(qscript, mcm_method="tree-traversal", rng=rng)
deferred_tapes, deferred_func = qml.defer_measurements(qscript)
@@ -1378,10 +1377,9 @@ def test_simple_dynamic_circuit(self, shots, measure_f, postselect, reset, meas_
mcm_utils.validate_measurements(measure_f, shots, results2, results0)
@pytest.mark.parametrize("shots", [None, 5500, [5500, 5500]])
- @pytest.mark.parametrize("rng", [None, 42, np.array([37])])
@pytest.mark.parametrize("angles", [(0.123, 0.015), (0.543, 0.057)])
@pytest.mark.parametrize("measure_f", [qml.probs, qml.sample])
- def test_approx_dynamic_mid_meas_circuit(self, shots, rng, angles, measure_f):
+ def test_approx_dynamic_mid_meas_circuit(self, shots, angles, measure_f, seed):
"""Test execution of a dynamic circuit with an equivalent static one."""
if measure_f in (qml.sample,) and shots is None:
@@ -1422,8 +1420,8 @@ def test_approx_dynamic_mid_meas_circuit(self, shots, rng, angles, measure_f):
[measure_f(wires=[0, 1, 2, 3])],
shots=shots,
) # approximate compiled circuit of the above
- res1 = simulate_tree_mcm(qs_with_mid_meas, rng=rng)
- res2 = simulate(qs_without_mid_meas, rng=rng)
+ res1 = simulate_tree_mcm(qs_with_mid_meas, rng=seed)
+ res2 = simulate(qs_without_mid_meas, rng=seed)
if not isinstance(shots, list):
res1, res2 = (res1,), (res2,)
@@ -1447,7 +1445,7 @@ def test_approx_dynamic_mid_meas_circuit(self, shots, rng, angles, measure_f):
@pytest.mark.parametrize(
"postselect_mode", [None, "hw-like", "pad-invalid-samples", "fill-shots"]
)
- def test_tree_traversal_interface_mcm(self, ml_framework, postselect_mode):
+ def test_tree_traversal_interface_mcm(self, ml_framework, postselect_mode, seed):
"""Test that tree traversal works numerically with different interfaces"""
# pylint:disable = singleton-comparison, import-outside-toplevel
@@ -1461,7 +1459,7 @@ def test_tree_traversal_interface_mcm(self, ml_framework, postselect_mode):
shots=5500,
)
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
res1, res2 = simulate_tree_mcm(qscript, interface=ml_framework, rng=rng)
p1 = [qml.math.mean(res1 == -1), qml.math.mean(res1 == 1)]
@@ -1561,12 +1559,12 @@ def test_tree_traversal_combine_measurements(self, measurements, expected):
else:
assert qml.math.allclose(combined_measurement, expected)
- @flaky(max_runs=3, min_passes=1)
+ @pytest.mark.local_salt(2)
@pytest.mark.parametrize("ml_framework", ml_frameworks_list)
@pytest.mark.parametrize(
"postselect_mode", [None, "hw-like", "pad-invalid-samples", "fill-shots"]
)
- def test_simulate_one_shot_native_mcm(self, ml_framework, postselect_mode):
+ def test_simulate_one_shot_native_mcm(self, ml_framework, postselect_mode, seed):
"""Unit tests for simulate_one_shot_native_mcm"""
with qml.queuing.AnnotatedQueue() as q:
@@ -1576,8 +1574,8 @@ def test_simulate_one_shot_native_mcm(self, ml_framework, postselect_mode):
circuit = qml.tape.QuantumScript(q.queue, [qml.expval(qml.Z(0)), qml.sample(m)], shots=[1])
- rng = np.random.default_rng(1234)
- n_shots = 500
+ rng = np.random.default_rng(seed)
+ n_shots = 1000
results = [
simulate_one_shot_native_mcm(
circuit,
diff --git a/tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py b/tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py
index 8471ceb48fb..176d9c92b31 100644
--- a/tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py
+++ b/tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py
@@ -13,6 +13,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit tests for sampling states in devices/qutrit_mixed."""
+
+# pylint: disable=unused-argument,too-many-arguments
+
import numpy as np
import pytest
from flaky import flaky
@@ -148,13 +151,13 @@ def test_prng_key_as_seed_uses_sample_state_jax(self, mocker, two_qutrit_state):
spy.assert_called_once()
@pytest.mark.jax
- def test_sample_state_jax(self, two_qutrit_pure_state):
+ def test_sample_state_jax(self, two_qutrit_pure_state, seed):
"""Tests that the returned samples are as expected when explicitly calling _sample_state_jax."""
import jax
state = qml.math.array(two_qutrit_pure_state, like="jax")
- samples = _sample_state_jax(state, 10, prng_key=jax.random.PRNGKey(84))
+ samples = _sample_state_jax(state, 10, prng_key=jax.random.PRNGKey(seed))
assert samples.shape == (10, 2)
assert samples.dtype == np.int64
@@ -181,15 +184,14 @@ def test_sample_state_custom_rng(self, two_qutrit_state):
expected = [[0, 2], [1, 0], [2, 1], [1, 2]]
assert qml.math.allequal(samples, expected)
- @flaky
- def test_entangled_qutrit_samples_always_match(self):
+ def test_entangled_qutrit_samples_always_match(self, seed):
"""Tests that entangled qutrits are always in the same state."""
num_samples = 10000
bell_state_vector = np.array([[1, 0, 0, 0, 1, 0, 0, 0, 1]])
bell_state = get_dm_of_state(bell_state_vector, 2, 3)
- samples = sample_state(bell_state, num_samples)
+ samples = sample_state(bell_state, num_samples, rng=seed)
assert samples.shape == (num_samples, 2)
assert not any(samples[:, 0] ^ samples[:, 1]) # all samples are entangled
@@ -272,25 +274,25 @@ def test_sample_measure_single_wire(self):
assert result1.dtype == np.int64
assert len(np.unique(result1)) == 3
- def test_approximate_sample_measure(self, two_qutrit_pure_state):
+ def test_approximate_sample_measure(self, two_qutrit_pure_state, seed):
"""Test that a sample measurement returns approximately the correct distribution"""
shots = qml.measurements.Shots(10000)
mp = qml.sample(wires=range(2))
- result = measure_with_samples(mp, two_qutrit_pure_state, shots=shots, rng=1234)
+ result = measure_with_samples(mp, two_qutrit_pure_state, shots=shots, rng=seed)
one_or_two_prob = np.count_nonzero(result[:, 0]) / result.shape[0]
one_prob = np.count_nonzero(result[:, 0] == 1) / result.shape[0]
assert np.allclose(one_or_two_prob, 2 / 3, atol=APPROX_ATOL)
assert np.allclose(one_prob, 1 / 3, atol=APPROX_ATOL)
- def test_approximate_expval_measure(self, two_qutrit_state):
+ def test_approximate_expval_measure(self, two_qutrit_state, seed):
"""Test that an expval measurement works as expected"""
state = qml.math.array(two_qutrit_state)
shots = qml.measurements.Shots(10000)
mp = qml.expval(qml.GellMann(0, 1) @ qml.GellMann(1, 1))
- result = measure_with_samples(mp, state, shots=shots, rng=1234)
+ result = measure_with_samples(mp, state, shots=shots, rng=seed)
gellmann_1_matrix = qml.GellMann.compute_matrix(1)
observable_matrix = np.kron(gellmann_1_matrix, gellmann_1_matrix)
@@ -299,13 +301,13 @@ def test_approximate_expval_measure(self, two_qutrit_state):
assert isinstance(result, np.float64)
assert np.allclose(result, expected, atol=APPROX_ATOL)
- def test_approximate_var_measure(self, two_qutrit_state):
+ def test_approximate_var_measure(self, two_qutrit_state, seed):
"""Test that a variance measurement works as expected"""
state = qml.math.array(two_qutrit_state)
shots = qml.measurements.Shots(10000)
mp = qml.var(qml.GellMann(0, 1) @ qml.GellMann(1, 1))
- result = measure_with_samples(mp, state, shots=shots, rng=123)
+ result = measure_with_samples(mp, state, shots=shots, rng=seed)
gellmann_1_matrix = qml.GellMann.compute_matrix(1)
obs_mat = np.kron(gellmann_1_matrix, gellmann_1_matrix)
@@ -441,9 +443,9 @@ def test_currently_unsupported_observable(self, mp, two_qutrit_state):
class TestBroadcasting:
"""Test that measurements work when the state has a batch dim"""
- def test_sample_measure(self, batched_two_qutrit_pure_state):
+ def test_sample_measure(self, batched_two_qutrit_pure_state, seed):
"""Test that broadcasting works for qml.sample and single shots"""
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(100)
state = batched_two_qutrit_pure_state
@@ -453,9 +455,9 @@ def test_sample_measure(self, batched_two_qutrit_pure_state):
assert res.shape == (3, shots.total_shots, 2)
assert res.dtype == np.int64
- def test_counts_measure(self, batched_two_qutrit_pure_state):
+ def test_counts_measure(self, batched_two_qutrit_pure_state, seed):
"""Test that broadcasting works for qml.sample and single shots"""
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(100)
state = batched_two_qutrit_pure_state
@@ -468,9 +470,9 @@ def test_counts_measure(self, batched_two_qutrit_pure_state):
assert list(res[2].keys()) == ["01", "10", "21", "22"]
@pytest.mark.parametrize("shots", shots_to_test_samples)
- def test_sample_measure_shot_vector(self, shots, batched_two_qutrit_pure_state):
+ def test_sample_measure_shot_vector(self, shots, batched_two_qutrit_pure_state, seed):
"""Test that broadcasting works for qml.sample and shot vectors"""
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(shots)
measurement = qml.sample(wires=[0, 1])
@@ -503,15 +505,10 @@ def test_sample_measure_shot_vector(self, shots, batched_two_qutrit_pure_state):
(qml.var(qml.GellMann(1, 3)), np.array([1 / 4, 0, 1])),
],
)
- def test_nonsample_measure_shot_vector(
- self,
- shots,
- measurement,
- expected,
- ):
+ def test_nonsample_measure_shot_vector(self, shots, measurement, expected, seed):
"""Test that broadcasting works for the other sample measurements and shot vectors"""
- rng = np.random.default_rng(123456)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(shots)
state = [
@@ -537,13 +534,13 @@ class TestBroadcastingPRNG:
"""Test that measurements work and use _sample_state_jax when the state has a batch dim
and a PRNG key is provided"""
- def test_sample_measure(self, mocker, batched_two_qutrit_pure_state):
+ def test_sample_measure(self, mocker, batched_two_qutrit_pure_state, seed):
"""Test that broadcasting works for qml.sample and single shots"""
import jax
spy = mocker.spy(qml.devices.qutrit_mixed.sampling, "_sample_state_jax")
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(100)
measurement = qml.sample(wires=[0, 1])
@@ -553,7 +550,7 @@ def test_sample_measure(self, mocker, batched_two_qutrit_pure_state):
shots,
is_state_batched=True,
rng=rng,
- prng_key=jax.random.PRNGKey(184),
+ prng_key=jax.random.PRNGKey(seed),
)
spy.assert_called()
@@ -567,7 +564,7 @@ def test_sample_measure(self, mocker, batched_two_qutrit_pure_state):
assert_correct_sampled_batched_two_qutrit_pure_state(res)
@pytest.mark.parametrize("shots", shots_to_test_samples)
- def test_sample_measure_shot_vector(self, mocker, shots, batched_two_qutrit_pure_state):
+ def test_sample_measure_shot_vector(self, mocker, shots, batched_two_qutrit_pure_state, seed):
"""Test that broadcasting works for qml.sample and shot vectors"""
import jax
@@ -575,7 +572,7 @@ def test_sample_measure_shot_vector(self, mocker, shots, batched_two_qutrit_pure
spy = mocker.spy(qml.devices.qutrit_mixed.sampling, "_sample_state_jax")
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(shots)
measurement = qml.sample(wires=[0, 1])
@@ -585,7 +582,7 @@ def test_sample_measure_shot_vector(self, mocker, shots, batched_two_qutrit_pure
shots,
is_state_batched=True,
rng=rng,
- prng_key=jax.random.PRNGKey(184),
+ prng_key=jax.random.PRNGKey(seed),
)
spy.assert_called()
@@ -611,13 +608,13 @@ def test_sample_measure_shot_vector(self, mocker, shots, batched_two_qutrit_pure
(qml.var(qml.GellMann(1, 3)), np.array([1 / 4, 0, 1])),
],
)
- def test_nonsample_measure_shot_vector(self, mocker, shots, measurement, expected):
+ def test_nonsample_measure_shot_vector(self, mocker, shots, measurement, expected, seed):
"""Test that broadcasting works for the other sample measurements and shot vectors"""
import jax
spy = mocker.spy(qml.devices.qutrit_mixed.sampling, "_sample_state_jax")
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
shots = qml.measurements.Shots(shots)
state = [
@@ -633,7 +630,7 @@ def test_nonsample_measure_shot_vector(self, mocker, shots, measurement, expecte
shots,
is_state_batched=True,
rng=rng,
- prng_key=jax.random.PRNGKey(184),
+ prng_key=jax.random.PRNGKey(seed),
)
spy.assert_called()
@@ -643,7 +640,7 @@ def test_nonsample_measure_shot_vector(self, mocker, shots, measurement, expecte
for r in res:
assert r.shape == expected.shape
- assert np.allclose(r, expected, atol=0.01)
+ assert np.allclose(r, expected, atol=0.02)
@pytest.mark.parametrize(
@@ -658,7 +655,7 @@ class TestHamiltonianSamples:
Hamiltonian and Sum observables"""
@pytest.mark.usefixtures("use_legacy_and_new_opmath")
- def test_hamiltonian_expval(self, obs):
+ def test_hamiltonian_expval(self, obs, seed):
"""Test that sampling works well for Hamiltonian and Sum observables"""
if not qml.operation.active_new_opmath():
@@ -671,14 +668,14 @@ def test_hamiltonian_expval(self, obs):
for op in ops:
state = apply_operation(op, state)
- res = measure_with_samples(qml.expval(obs), state, shots=shots, rng=300)
+ res = measure_with_samples(qml.expval(obs), state, shots=shots, rng=seed)
expected = 0.8 * np.cos(x) + 0.5 * np.cos(y) * np.sin(x)
assert isinstance(res, np.float64)
assert np.allclose(res, expected, atol=APPROX_ATOL)
@pytest.mark.usefixtures("use_legacy_and_new_opmath")
- def test_hamiltonian_expval_shot_vector(self, obs):
+ def test_hamiltonian_expval_shot_vector(self, obs, seed):
"""Test that sampling works well for Hamiltonian and Sum observables with a shot vector"""
if not qml.operation.active_new_opmath():
@@ -691,7 +688,7 @@ def test_hamiltonian_expval_shot_vector(self, obs):
for op in ops:
state = apply_operation(op, state)
- res = measure_with_samples(qml.expval(obs), state, shots=shots, rng=300)
+ res = measure_with_samples(qml.expval(obs), state, shots=shots, rng=seed)
expected = 0.8 * np.cos(x) + 0.5 * np.cos(y) * np.sin(x)
@@ -704,11 +701,12 @@ def test_hamiltonian_expval_shot_vector(self, obs):
class TestSampleProbs:
# pylint: disable=attribute-defined-outside-init
@pytest.fixture(autouse=True)
- def setup(self):
- self.rng = np.random.default_rng(42)
+ def setup(self, request):
+ seed = request.getfixturevalue("seed")
+ self.rng = np.random.default_rng(seed)
self.shots = 1000
- def test_sample_probs_basic(self):
+ def test_sample_probs_basic(self, seed):
probs = np.array([0.2, 0.3, 0.5])
num_wires = 1
is_state_batched = False
@@ -722,7 +720,7 @@ def test_sample_probs_basic(self):
observed_probs = counts / self.shots
np.testing.assert_allclose(observed_probs, probs, atol=0.05)
- def test_sample_probs_multi_wire(self):
+ def test_sample_probs_multi_wire(self, seed):
probs = np.array(
[0.1, 0.2, 0.3, 0.15, 0.1, 0.05, 0.05, 0.03, 0.02]
) # 3^2 = 9 probabilities for 2 wires
@@ -734,7 +732,7 @@ def test_sample_probs_multi_wire(self):
assert result.shape == (self.shots, num_wires)
assert np.all(result >= 0) and np.all(result < QUDIT_DIM)
- def test_sample_probs_batched(self):
+ def test_sample_probs_batched(self, seed):
probs = np.array([[0.2, 0.3, 0.5], [0.4, 0.1, 0.5]])
num_wires = 1
is_state_batched = True
@@ -752,11 +750,11 @@ def test_sample_probs_batched(self):
(np.array([[0.2, 0.3, 0.5], [0.4, 0.1, 0.5]]), 1, True, (2, 1000, 1)),
],
)
- def test_sample_probs_shapes(self, probs, num_wires, is_state_batched, expected_shape):
+ def test_sample_probs_shapes(self, probs, num_wires, is_state_batched, expected_shape, seed):
result = sample_probs(probs, self.shots, num_wires, is_state_batched, self.rng)
assert result.shape == expected_shape
- def test_invalid_probs(self):
+ def test_invalid_probs(self, seed):
probs = np.array(
[0.1, 0.2, 0.3, 0.4]
) # 4 probabilities, which is invalid for qutrit system
@@ -770,14 +768,15 @@ def test_invalid_probs(self):
class TestSampleProbsJax:
# pylint: disable=attribute-defined-outside-init
@pytest.fixture(autouse=True)
- def setup(self):
+ def setup(self, request):
import jax
- self.jax_key = jax.random.PRNGKey(42)
+ seed = request.getfixturevalue("seed")
+ self.jax_key = jax.random.PRNGKey(seed)
self.shots = 1000
@pytest.mark.jax
- def test_sample_probs_jax_basic(self):
+ def test_sample_probs_jax_basic(self, seed):
probs = np.array([0.2, 0.3, 0.5])
num_wires = 1
is_state_batched = False
@@ -795,7 +794,7 @@ def test_sample_probs_jax_basic(self):
np.testing.assert_allclose(observed_probs, probs, atol=0.05)
@pytest.mark.jax
- def test_sample_probs_jax_multi_wire(self):
+ def test_sample_probs_jax_multi_wire(self, seed):
probs = qml.math.array(
[0.1, 0.2, 0.3, 0.15, 0.1, 0.05, 0.05, 0.03, 0.02]
) # 3^2 = 9 probabilities for 2 wires
@@ -811,7 +810,7 @@ def test_sample_probs_jax_multi_wire(self):
assert qml.math.all(result >= 0) and qml.math.all(result < QUDIT_DIM)
@pytest.mark.jax
- def test_sample_probs_jax_batched(self):
+ def test_sample_probs_jax_batched(self, seed):
probs = qml.math.array([[0.2, 0.3, 0.5], [0.4, 0.1, 0.5]])
num_wires = 1
is_state_batched = True
@@ -841,7 +840,7 @@ def test_sample_probs_jax_batched(self):
)
@pytest.mark.jax
def test_sample_probs_jax_shapes(
- self, probs, num_wires, is_state_batched, expected_shape, state_len
+ self, probs, num_wires, is_state_batched, expected_shape, state_len, seed
):
result = _sample_probs_jax(
probs, self.shots, num_wires, is_state_batched, self.jax_key, state_len
@@ -849,7 +848,7 @@ def test_sample_probs_jax_shapes(
assert result.shape == expected_shape
@pytest.mark.jax
- def test_invalid_probs_jax(self):
+ def test_invalid_probs_jax(self, seed):
probs = qml.math.array(
[0.1, 0.2, 0.3, 0.4]
) # 4 probabilities, which is invalid for qutrit system
diff --git a/tests/devices/qutrit_mixed/test_qutrit_mixed_simulate.py b/tests/devices/qutrit_mixed/test_qutrit_mixed_simulate.py
index 90c36e89d92..cfe7231d345 100644
--- a/tests/devices/qutrit_mixed/test_qutrit_mixed_simulate.py
+++ b/tests/devices/qutrit_mixed/test_qutrit_mixed_simulate.py
@@ -301,13 +301,13 @@ def test_broadcasted_op_state(self, subspace):
assert len(res) == 2
assert np.allclose(res, expected)
- def test_broadcasted_op_sample(self, subspace):
+ def test_broadcasted_op_sample(self, subspace, seed):
"""Test that simulate works for sample measurements
when an operation has broadcasted parameters"""
x = np.array([0.8, 1.0, 1.2, 1.4])
qs = self.get_quantum_script(x, subspace, shots=qml.measurements.Shots(10000))
- res = simulate(qs, rng=123)
+ res = simulate(qs, rng=seed)
expected = self.get_expectation_values(x, subspace)
assert isinstance(res, tuple)
@@ -315,7 +315,7 @@ def test_broadcasted_op_sample(self, subspace):
assert np.allclose(res, expected, atol=0.05)
state, is_state_batched = get_final_state(qs)
- res = measure_final_state(qs, state, is_state_batched, rng=123)
+ res = measure_final_state(qs, state, is_state_batched, rng=seed)
assert np.allclose(state, self.get_expected_state(x, subspace))
assert is_state_batched
diff --git a/tests/devices/test_default_clifford.py b/tests/devices/test_default_clifford.py
index 29294dc4a2c..fac9de067cf 100644
--- a/tests/devices/test_default_clifford.py
+++ b/tests/devices/test_default_clifford.py
@@ -190,10 +190,10 @@ def circuit_fn():
qml.Projector([1, 0], [0, 1]),
],
)
-def test_meas_expval(shots, ops):
+def test_meas_expval(shots, ops, seed):
"""Test that expectation value measurements with `default.clifford` is possible
and agrees with `default.qubit`."""
- dev_c = qml.device("default.clifford", shots=shots, seed=24)
+ dev_c = qml.device("default.clifford", shots=shots, seed=seed)
dev_q = qml.device("default.qubit")
def circuit_fn():
@@ -269,10 +269,10 @@ def circuit_fn():
qml.Projector([0, 1], wires=[0, 1]),
],
)
-def test_meas_probs(tableau, shots, ops):
+def test_meas_probs(tableau, shots, ops, seed):
"""Test if probabilities are returned in the clifford device."""
- dev_c = qml.device("default.clifford", tableau=tableau, shots=shots, seed=24)
+ dev_c = qml.device("default.clifford", tableau=tableau, shots=shots, seed=seed)
dev_q = qml.device("default.qubit")
def circuit_fn():
@@ -290,11 +290,9 @@ def circuit_fn():
assert qml.math.allclose(gotten_probs, target_probs, atol=5e-2 if shots else 1e-8)
-def test_meas_probs_large():
+def test_meas_probs_large(seed):
"""Test if probabilities are returned in the clifford device with target basis states"""
- dev_c = qml.device("default.clifford", seed=24)
-
def single_op(idx):
return [qml.PauliX, qml.PauliY, qml.Hadamard, qml.PauliZ][idx]
@@ -304,7 +302,7 @@ def circuit_fn2(meas):
qml.CNOT([wire, wire + 1])
return qml.apply(meas)
- dev_c = qml.device("default.clifford", seed=24)
+ dev_c = qml.device("default.clifford", seed=seed)
qnode_clfrd = qml.QNode(circuit_fn2, dev_c)
meas1 = qml.probs(op=qml.Projector([1, 1, 0], wires=[0, 6, 14]))
@@ -321,11 +319,11 @@ def circuit_fn2(meas):
"ops",
[None, qml.PauliY(0), qml.PauliX(0) @ qml.PauliY(1)],
)
-def test_meas_counts(shots, ops):
+def test_meas_counts(shots, ops, seed):
"""Test if counts are returned with shots given in the clifford device."""
- dev_c = qml.device("default.clifford", shots=shots, seed=24)
- dev_q = qml.device("default.qubit", shots=shots, seed=24)
+ dev_c = qml.device("default.clifford", shots=shots, seed=seed)
+ dev_q = qml.device("default.qubit", shots=shots, seed=seed)
def circuit_fn():
qml.PauliX(0)
@@ -352,7 +350,7 @@ def circuit_fn():
qml.PauliZ(0) @ qml.PauliY(1),
],
)
-def test_meas_classical_shadows(shots, ops):
+def test_meas_classical_shadows(shots, ops, seed):
"""Test if classical shadows measurements are returned with shots
given in the clifford device."""
@@ -367,7 +365,7 @@ def circuit():
def circuit_shadow():
circuit()
- return qml.classical_shadow(wires=[0, 1], seed=13)
+ return qml.classical_shadow(wires=[0, 1], seed=seed)
qnode_clfrd_shadow = qml.QNode(circuit_shadow, dev_c)
qnode_qubit_shadow = qml.QNode(circuit_shadow, dev_q)
@@ -381,7 +379,7 @@ def circuit_shadow():
def circuit_expval():
circuit()
- return qml.shadow_expval(ops, seed=13)
+ return qml.shadow_expval(ops, seed=seed)
qnode_clfrd_expval = qml.QNode(circuit_expval, dev_c)
expval = qnode_clfrd_expval()
diff --git a/tests/devices/test_default_qutrit_mixed.py b/tests/devices/test_default_qutrit_mixed.py
index 13f3d744bb1..8c9c635509a 100644
--- a/tests/devices/test_default_qutrit_mixed.py
+++ b/tests/devices/test_default_qutrit_mixed.py
@@ -573,7 +573,7 @@ def test_batch_tapes(self, subspace):
assert results[1].shape == (50,)
@pytest.mark.parametrize("all_outcomes", [False, True])
- def test_counts_obs(self, all_outcomes, subspace):
+ def test_counts_obs(self, all_outcomes, subspace, seed):
"""Test that a Counts measurement with an observable works as expected."""
x = np.array(np.pi / 2)
qs = qml.tape.QuantumScript(
@@ -582,7 +582,7 @@ def test_counts_obs(self, all_outcomes, subspace):
shots=10000,
)
- dev = DefaultQutritMixed(seed=123)
+ dev = DefaultQutritMixed(seed=seed)
result = dev.execute(qs)
assert isinstance(result, dict)
@@ -591,7 +591,7 @@ def test_counts_obs(self, all_outcomes, subspace):
# check that the count values match the expected
values = list(result.values())
- assert np.allclose(values[0] / (values[0] + values[1]), 0.5, atol=0.01)
+ assert np.allclose(values[0] / (values[0] + values[1]), 0.5, atol=0.02)
class TestExecutingBatches:
@@ -1149,7 +1149,7 @@ class TestHamiltonianSamples:
This is a copy of the tests in `test_qutrit_mixed_sampling.py`, but using the device instead.
"""
- def test_hamiltonian_expval(self, obs):
+ def test_hamiltonian_expval(self, obs, seed):
"""Tests that sampling works well for Hamiltonian and Sum observables."""
if not qml.operation.active_new_opmath():
obs = qml.operation.convert_to_legacy_H(obs)
@@ -1157,14 +1157,14 @@ def test_hamiltonian_expval(self, obs):
x, y = np.array(0.67), np.array(0.95)
ops = [qml.TRY(x, wires=0), qml.TRZ(y, wires=0)]
- dev = DefaultQutritMixed(seed=100)
+ dev = DefaultQutritMixed(seed=seed)
qs = qml.tape.QuantumScript(ops, [qml.expval(obs)], shots=10000)
res = dev.execute(qs)
expected = 0.8 * np.cos(x) + 0.5 * np.cos(y) * np.sin(x)
assert np.allclose(res, expected, atol=0.01)
- def test_hamiltonian_expval_shot_vector(self, obs):
+ def test_hamiltonian_expval_shot_vector(self, obs, seed):
"""Test that sampling works well for Hamiltonian and Sum observables with a shot vector."""
if not qml.operation.active_new_opmath():
@@ -1173,7 +1173,7 @@ def test_hamiltonian_expval_shot_vector(self, obs):
shots = qml.measurements.Shots((10000, 100000))
x, y = np.array(0.67), np.array(0.95)
ops = [qml.TRY(x, wires=0), qml.TRZ(y, wires=0)]
- dev = DefaultQutritMixed(seed=100)
+ dev = DefaultQutritMixed(seed=seed)
qs = qml.tape.QuantumScript(ops, [qml.expval(obs)], shots=shots)
res = dev.execute(qs)
@@ -1181,8 +1181,8 @@ def test_hamiltonian_expval_shot_vector(self, obs):
assert len(res) == 2
assert isinstance(res, tuple)
- assert np.allclose(res[0], expected, atol=0.01)
- assert np.allclose(res[1], expected, atol=0.01)
+ assert np.allclose(res[0], expected, atol=0.02)
+ assert np.allclose(res[1], expected, atol=0.02)
class TestIntegration:
@@ -1556,6 +1556,7 @@ def circuit():
res = circuit()
assert res == expected
+ # pylint:disable=too-many-arguments
@pytest.mark.parametrize(
"relaxations, misclassifications, expected",
[
@@ -1564,7 +1565,9 @@ def circuit():
[(0.2, 0.1, 0.4), (0.1, 0.2, 0.5), [11 / 24, 7 / 30, 37 / 120]],
],
)
- def test_approximate_readout_counts(self, num_wires, relaxations, misclassifications, expected):
+ def test_approximate_readout_counts(
+ self, num_wires, relaxations, misclassifications, expected, seed
+ ):
"""Tests the counts output with readout error"""
num_shots = 10000
dev = qml.device(
@@ -1573,7 +1576,7 @@ def test_approximate_readout_counts(self, num_wires, relaxations, misclassificat
wires=num_wires,
readout_relaxation_probs=relaxations,
readout_misclassification_probs=misclassifications,
- seed=221349,
+ seed=seed,
)
@qml.qnode(dev)
diff --git a/tests/devices/test_null_qubit.py b/tests/devices/test_null_qubit.py
index fd7f5b4638f..d0565b1b9e6 100644
--- a/tests/devices/test_null_qubit.py
+++ b/tests/devices/test_null_qubit.py
@@ -976,12 +976,12 @@ def test_shape_and_dtype(self, n_qubits):
assert np.array_equal(res, np.zeros((2, 100, n_qubits)))
assert res.dtype == np.int8
- def test_expval(self):
+ def test_expval(self, seed):
"""Test that shadow expval measurements work as expected"""
dev = NullQubit()
ops = [qml.Hadamard(0), qml.Hadamard(1)]
- meas = [qml.shadow_expval(qml.PauliX(0) @ qml.PauliX(1), seed=200)]
+ meas = [qml.shadow_expval(qml.PauliX(0) @ qml.PauliX(1), seed=seed)]
qs = qml.tape.QuantumScript(ops, meas, shots=1000)
assert dev.execute(qs) == np.array(0.0)
@@ -1135,12 +1135,12 @@ def circuit():
@pytest.mark.parametrize(
"diff_method", ["device", "adjoint", "backprop", "finite-diff", "parameter-shift"]
)
- def test_expected_shape_all_methods(self, diff_method):
+ def test_expected_shape_all_methods(self, diff_method, seed):
"""Test that the gradient shape is as expected with all diff methods."""
n_wires = 4
shape = qml.StronglyEntanglingLayers.shape(n_layers=5, n_wires=n_wires)
- rng = np.random.default_rng(seed=1239594)
+ rng = np.random.default_rng(seed=seed)
params = qml.numpy.array(rng.random(shape))
dev = qml.device("null.qubit")
diff --git a/tests/gradients/core/test_fisher.py b/tests/gradients/core/test_fisher.py
index 8d921701461..7f24aff648a 100644
--- a/tests/gradients/core/test_fisher.py
+++ b/tests/gradients/core/test_fisher.py
@@ -151,13 +151,13 @@ def circ(params):
qml.device("lightning.qubit", wires=3),
),
)
- def test_quantum_fisher_info(self, dev):
+ def test_quantum_fisher_info(self, dev, seed):
"""Integration test of quantum fisher information matrix CFIM. This is just calling
``qml.metric_tensor`` or ``qml.adjoint_metric_tensor`` and multiplying by a factor of 4"""
n_wires = 2
- rng = pnp.random.default_rng(200)
+ rng = pnp.random.default_rng(seed)
dev_hard = qml.device("default.qubit", wires=n_wires + 1, shots=1000, seed=rng)
def qfunc(params):
diff --git a/tests/gradients/core/test_gradient_transform.py b/tests/gradients/core/test_gradient_transform.py
index f98bff71b2d..74d484b4bf4 100644
--- a/tests/gradients/core/test_gradient_transform.py
+++ b/tests/gradients/core/test_gradient_transform.py
@@ -250,11 +250,12 @@ def circuit(weights):
else:
assert np.allclose(res, expected, atol=atol, rtol=0)
- @pytest.mark.parametrize("shots, atol", [(None, 1e-6), (1000, 1e-1), ([1000, 100], 2e-1)])
+ @pytest.mark.parametrize("shots, atol", [(None, 1e-6), (1000, 2e-1), ([1000, 1500], 2e-1)])
@pytest.mark.parametrize("prefactor", [1.0, 2.0])
- def test_acting_on_qnodes_multi_param(self, shots, prefactor, atol):
+ def test_acting_on_qnodes_multi_param(self, shots, prefactor, atol, seed):
"""Test that a gradient transform acts on QNodes with multiple parameters correctly"""
- dev = qml.device("default.qubit", wires=2, shots=shots)
+
+ dev = qml.device("default.qubit", wires=2, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit(weights):
@@ -280,9 +281,9 @@ def circuit(weights):
]
)
if isinstance(shots, list):
- assert all(np.allclose(r, expected, atol=atol, rtol=0) for r in res)
+ assert all(np.allclose(r, expected, atol=atol) for r in res)
else:
- assert np.allclose(res, expected, atol=atol, rtol=0)
+ assert np.allclose(res, expected, atol=atol)
@pytest.mark.xfail(reason="Gradient transforms are not compatible with shots and mixed shapes")
@pytest.mark.parametrize("shots, atol", [(None, 1e-6), (1000, 1e-1), ([1000, 100], 2e-1)])
diff --git a/tests/gradients/core/test_pulse_gradient.py b/tests/gradients/core/test_pulse_gradient.py
index f3154689ba0..164c047c776 100644
--- a/tests/gradients/core/test_pulse_gradient.py
+++ b/tests/gradients/core/test_pulse_gradient.py
@@ -64,14 +64,14 @@ class TestSplitEvolOps:
# pylint: disable=too-many-arguments
@pytest.mark.parametrize("ham, params, time, ob, word", split_evol_ops_test_cases_pauliword)
- def test_with_pauliword(self, ham, params, time, ob, word):
+ def test_with_pauliword(self, ham, params, time, ob, word, seed):
"""Test that _split_evol_ops returns the right ops with correct
relations to the input operation for a Pauli word as ``ob``."""
import jax
ham = ham(None)
- key = jax.random.PRNGKey(5324)
+ key = jax.random.PRNGKey(seed)
op = qml.evolve(ham)(params, time)
op_copy = copy.deepcopy(op)
exp_time = [0, time] if qml.math.ndim(time) == 0 else time
@@ -138,14 +138,14 @@ def test_with_pauliword(self, ham, params, time, ob, word):
]
@pytest.mark.parametrize("ham, params, time, ob", split_evol_ops_test_cases_general)
- def test_with_general_ob(self, ham, params, time, ob):
+ def test_with_general_ob(self, ham, params, time, ob, seed):
"""Test that _split_evol_ops returns the right ops with correct
relations to the input operation for a general Hermitian as ``ob``."""
import jax
ham = ham(None)
- key = jax.random.PRNGKey(5324)
+ key = jax.random.PRNGKey(seed)
op = qml.evolve(ham)(params, time)
op_copy = copy.deepcopy(op)
exp_time = [0, time] if qml.math.ndim(time) == 0 else time
@@ -618,9 +618,6 @@ def test_multi_measure_multi_shots(
expected = np.einsum(contraction, _psr_coeffs, _results, _cjacs)
assert np.allclose(np.stack(res), expected * prefactor)
- # TODO: Once #2690 is resolved and the corresponding error is removed,
- # unskip the following test
- @pytest.mark.skip("Broadcasting, shot vector and multi-measurement not supported.")
@pytest.mark.parametrize("multi_term", [1, 4])
@pytest.mark.parametrize("meas_shape", [(), (4,)])
@pytest.mark.parametrize("par_shape", [(), (3,), (2, 2)])
@@ -697,25 +694,6 @@ def test_multi_measure_multi_shots_broadcast(
expected = np.einsum(contraction, _psr_coeffs, _results, _cjacs)
assert np.allclose(np.stack(res), expected * prefactor)
- # TODO: Once #2690 is resolved and the corresponding error is removed,
- # remove the following test
- def test_raises_multi_measure_multi_shots_broadcasting(self):
- """Test that an error is raised if multiple measurements, a shot vector and broadcasting
- all are used simultaneously."""
-
- _match = "Broadcasting, multiple measurements and shot vectors are currently"
- with pytest.raises(NotImplementedError, match=_match):
- # Dummy input values that are barely used before raising the error.
- _parshift_and_integrate(
- [],
- [],
- [],
- [],
- single_measure=False,
- has_partitioned_shots=True,
- use_broadcasting=True,
- )
-
@pytest.mark.jax
class TestStochPulseGradErrors:
@@ -818,12 +796,11 @@ def test_raises_non_pulse_marked_as_trainable(self):
with pytest.raises(ValueError, match="stoch_pulse_grad does not support differentiating"):
stoch_pulse_grad(tape)
- @pytest.mark.skip(reason="This test fails because broadcasted tapes are not allowed at all.")
def test_raises_use_broadcasting_with_broadcasted_tape(self):
"""Test that an error is raised if the option `use_broadcasting` is activated
for a tape that already is broadcasted."""
ham = qml.dot([qml.pulse.constant], [qml.PauliX(0)])
- ops = [qml.evolve(ham, return_intermediate=True)([0.152], 0.3)]
+ ops = [qml.RX(0.5, wires=0), qml.evolve(ham, return_intermediate=True)([0.152], 0.3)]
tape = qml.tape.QuantumScript(ops, measurements=[qml.expval(qml.PauliZ(0))])
tape.trainable_params = [0]
with pytest.raises(ValueError, match="Broadcasting is not supported for tapes that"):
@@ -1142,7 +1119,7 @@ def test_sin_envelope_rx_expval_probs(self, t):
jax.clear_caches()
@pytest.mark.parametrize("t", [0.02, (0.5, 0.6)])
- def test_pwc_envelope_rx(self, t):
+ def test_pwc_envelope_rx(self, t, seed):
"""Test that the derivative of a pulse generated by a piecewise constant Hamiltonian
is computed correctly."""
import jax
@@ -1160,7 +1137,7 @@ def test_pwc_envelope_rx(self, t):
r = qml.execute([tape], dev, None)
assert qml.math.isclose(r, jnp.cos(2 * p))
num_split_times = 5
- tapes, fn = stoch_pulse_grad(tape, num_split_times=num_split_times, sampler_seed=7512)
+ tapes, fn = stoch_pulse_grad(tape, num_split_times=num_split_times, sampler_seed=seed)
assert len(tapes) == 2 * num_split_times
res = fn(qml.execute(tapes, dev, None))
@@ -1229,6 +1206,11 @@ def qnode(params):
num_split_times = 5
qnode.tape.trainable_params = [0, 1, 2]
+ # FIXME: This test case is not updated to use the pytest-rng generated seed because I'm
+ # unable to find a local salt that actually allows this test to pass. The 7123 here
+ # is basically a magic number. Every other seed I tried fails. I believe this test
+ # should be rewritten to use a better testing strategy because this currently goes
+ # against the spirit of seeding.
tapes, fn = stoch_pulse_grad(qnode.tape, num_split_times=num_split_times, sampler_seed=7123)
# Two generating terms with two shifts (X_0 and Z_0), one with eight shifts
# (Y_0Y_1+0.4 X_1 has eigenvalues [-1.4, -0.6, 0.6, 1.4] yielding frequencies
@@ -1281,7 +1263,7 @@ def test_randomness(self):
assert not res_a_0 == res_b
jax.clear_caches()
- def test_two_pulses(self):
+ def test_two_pulses(self, seed):
"""Test that the derivatives of two pulses in a circuit are computed correctly."""
import jax
import jax.numpy as jnp
@@ -1304,7 +1286,7 @@ def qnode(params_0, params_1):
num_split_times = 3
qnode.tape.trainable_params = [0, 1, 2]
- tapes, fn = stoch_pulse_grad(qnode.tape, num_split_times=num_split_times, sampler_seed=7123)
+ tapes, fn = stoch_pulse_grad(qnode.tape, num_split_times=num_split_times, sampler_seed=seed)
assert len(tapes) == 3 * 2 * num_split_times
res = fn(qml.execute(tapes, dev, None))
@@ -1415,14 +1397,14 @@ class TestStochPulseGradIntegration:
@pytest.mark.parametrize("shots, tol", [(None, 1e-4), (100, 0.1), ([100, 99], 0.1)])
@pytest.mark.parametrize("num_split_times", [1, 2])
- def test_simple_qnode_expval(self, num_split_times, shots, tol):
+ def test_simple_qnode_expval(self, num_split_times, shots, tol, seed):
"""Test that a simple qnode that returns an expectation value
can be differentiated with stoch_pulse_grad."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(74))
+ dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(seed))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1443,14 +1425,14 @@ def circuit(params):
@pytest.mark.slow
@pytest.mark.parametrize("shots, tol", [(None, 1e-4), (100, 0.1), ([100, 99], 0.1)])
@pytest.mark.parametrize("num_split_times", [1, 2])
- def test_simple_qnode_expval_two_evolves(self, num_split_times, shots, tol):
+ def test_simple_qnode_expval_two_evolves(self, num_split_times, shots, tol, seed):
"""Test that a simple qnode that returns an expectation value
can be differentiated with stoch_pulse_grad."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(74))
+ dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(seed))
T_x = 0.1
T_y = 0.2
ham_x = qml.pulse.constant * qml.PauliX(0)
@@ -1474,14 +1456,14 @@ def circuit(params):
@pytest.mark.parametrize("shots, tol", [(None, 1e-4), (100, 0.1), ([100, 99], 0.1)])
@pytest.mark.parametrize("num_split_times", [1, 2])
- def test_simple_qnode_probs(self, num_split_times, shots, tol):
+ def test_simple_qnode_probs(self, num_split_times, shots, tol, seed):
"""Test that a simple qnode that returns an probabilities
can be differentiated with stoch_pulse_grad."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(74))
+ dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(seed))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1501,14 +1483,14 @@ def circuit(params):
@pytest.mark.parametrize("shots, tol", [(None, 1e-4), (100, 0.1), ([100, 100], 0.1)])
@pytest.mark.parametrize("num_split_times", [1, 2])
- def test_simple_qnode_probs_expval(self, num_split_times, shots, tol):
+ def test_simple_qnode_probs_expval(self, num_split_times, shots, tol, seed):
"""Test that a simple qnode that returns an probabilities
can be differentiated with stoch_pulse_grad."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(74))
+ dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(seed))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1560,7 +1542,7 @@ def circuit(params, T=None):
jax.clear_caches()
@pytest.mark.slow
- def test_advanced_qnode(self):
+ def test_advanced_qnode(self, seed):
"""Test that an advanced qnode can be differentiated with stoch_pulse_grad."""
import jax
import jax.numpy as jnp
@@ -1586,7 +1568,7 @@ def ansatz(params):
interface="jax",
diff_method=stoch_pulse_grad,
num_split_times=num_split_times,
- sampler_seed=7123,
+ sampler_seed=seed,
)
qnode_backprop = qml.QNode(ansatz, dev, interface="jax")
@@ -1600,45 +1582,16 @@ def ansatz(params):
)
jax.clear_caches()
- def test_multi_return_broadcasting_multi_shots_raises(self):
- """Test that a simple qnode that returns an expectation value and probabilities
- can be differentiated with stoch_pulse_grad with use_broadcasting."""
- import jax
- import jax.numpy as jnp
-
- jax.config.update("jax_enable_x64", True)
- shots = [100, 100]
- dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(74))
- T = 0.2
- ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
-
- @qml.qnode(
- dev,
- interface="jax",
- diff_method=stoch_pulse_grad,
- num_split_times=3,
- use_broadcasting=True,
- )
- def circuit(params):
- qml.evolve(ham_single_q_const)(params, T)
- return qml.probs(wires=0), qml.expval(qml.PauliZ(0))
-
- params = [jnp.array(0.4)]
- with pytest.raises(NotImplementedError, match="Broadcasting, multiple measurements and"):
- jax.jacobian(circuit)(params)
- jax.clear_caches()
-
- # TODO: delete error test above and uncomment the following test case once #2690 is resolved.
- @pytest.mark.parametrize("shots, tol", [(None, 1e-4), (100, 0.1)]) # , ([100, 100], 0.1)])
+ @pytest.mark.parametrize("shots, tol", [(None, 1e-4), (100, 0.1), ([100, 100], 0.1)])
@pytest.mark.parametrize("num_split_times", [1, 2])
- def test_qnode_probs_expval_broadcasting(self, num_split_times, shots, tol):
+ def test_qnode_probs_expval_broadcasting(self, num_split_times, shots, tol, seed):
"""Test that a simple qnode that returns an expectation value and probabilities
can be differentiated with stoch_pulse_grad with use_broadcasting."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(74))
+ dev = qml.device("default.qubit", wires=1, shots=shots, seed=jax.random.PRNGKey(seed))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1667,7 +1620,7 @@ def circuit(params):
jax.clear_caches()
@pytest.mark.parametrize("num_split_times", [1, 2])
- def test_broadcasting_coincides_with_nonbroadcasting(self, num_split_times):
+ def test_broadcasting_coincides_with_nonbroadcasting(self, num_split_times, seed):
"""Test that using broadcasting or not does not change the result."""
import jax
import jax.numpy as jnp
@@ -1693,7 +1646,7 @@ def ansatz(params):
diff_method=stoch_pulse_grad,
num_split_times=num_split_times,
use_broadcasting=True,
- sampler_seed=324,
+ sampler_seed=seed,
)
circuit_no_bc = qml.QNode(
ansatz,
@@ -1702,7 +1655,7 @@ def ansatz(params):
diff_method=stoch_pulse_grad,
num_split_times=num_split_times,
use_broadcasting=False,
- sampler_seed=324,
+ sampler_seed=seed,
)
params = [jnp.array(0.4)]
jac_bc = jax.jacobian(circuit_bc)(params)
@@ -1736,7 +1689,7 @@ def ansatz(params):
assert qml.math.allclose(res, exact, atol=6e-5)
jax.clear_caches()
- def test_with_drive_approx(self):
+ def test_with_drive_approx(self, seed):
"""Test that a HardwareHamiltonian only containing a drive is differentiated
approximately correctly for a constant phase and zero frequency."""
import jax
@@ -1758,7 +1711,7 @@ def ansatz(params):
diff_method=qml.gradients.stoch_pulse_grad,
num_split_times=7,
use_broadcasting=True,
- sampler_seed=4123,
+ sampler_seed=seed,
)
cost_jax = qml.QNode(ansatz, dev, interface="jax")
params = (0.42,)
@@ -1771,7 +1724,7 @@ def ansatz(params):
@pytest.mark.slow
@pytest.mark.parametrize("num_params", [1, 2])
- def test_with_two_drives(self, num_params):
+ def test_with_two_drives(self, num_params, seed):
"""Test that a HardwareHamiltonian only containing two drives
is differentiated approximately correctly. The two cases
of the parametrization test the cases where reordered parameters
@@ -1803,7 +1756,7 @@ def ansatz(params):
diff_method=qml.gradients.stoch_pulse_grad,
num_split_times=7,
use_broadcasting=True,
- sampler_seed=4123,
+ sampler_seed=seed,
)
cost_jax = qml.QNode(ansatz, dev, interface="jax")
diff --git a/tests/gradients/core/test_pulse_odegen.py b/tests/gradients/core/test_pulse_odegen.py
index 3a7dbd4bddc..dd8d50c4887 100644
--- a/tests/gradients/core/test_pulse_odegen.py
+++ b/tests/gradients/core/test_pulse_odegen.py
@@ -386,11 +386,11 @@ def test_all_zero(self, num_wires):
assert words == []
@pytest.mark.parametrize("num_wires", [1, 2, 3])
- def test_separate_nonzero(self, num_wires):
+ def test_separate_nonzero(self, num_wires, seed):
"""Test that a single coefficient in any of the coefficients is sufficient
to keep the Pauli word in the filter."""
# Create many coefficients, each greater or equal ``1`` at distinct places.
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
coeffs = tuple(rng.uniform(1, 2, size=(4**num_wires - 1, 4**num_wires - 1)))
new_coeffs, words = _nonzero_coeffs_and_words(coeffs, num_wires)
@@ -1001,13 +1001,13 @@ class TestPulseOdegenTape:
"""Test that differentiating tapes with ``pulse_odegen`` works."""
@pytest.mark.parametrize("shots, tol", [(None, 1e-7), (1000, 0.05), ([1000, 100], 0.05)])
- def test_single_pulse_single_term(self, shots, tol):
+ def test_single_pulse_single_term(self, shots, tol, seed):
"""Test that a single pulse with a single Hamiltonian term is
differentiated correctly."""
import jax
import jax.numpy as jnp
- prng_key = jax.random.PRNGKey(8251)
+ prng_key = jax.random.PRNGKey(seed)
dev = qml.device("default.qubit", wires=1, shots=shots, seed=prng_key)
H = jnp.polyval * X(0)
@@ -1036,13 +1036,13 @@ def test_single_pulse_single_term(self, shots, tol):
@pytest.mark.slow
@pytest.mark.parametrize("shots, tol", [(None, 1e-7), ([1000, 100], 0.05)])
- def test_single_pulse_multi_term(self, shots, tol):
+ def test_single_pulse_multi_term(self, shots, tol, seed):
"""Test that a single pulse with multiple Hamiltonian terms is
differentiated correctly."""
import jax
import jax.numpy as jnp
- prng_key = jax.random.PRNGKey(8251)
+ prng_key = jax.random.PRNGKey(seed)
dev = qml.device("default.qubit", wires=1, shots=None)
dev_shots = qml.device("default.qubit", wires=1, shots=shots, seed=prng_key)
@@ -1116,13 +1116,13 @@ def test_single_pulse_multi_term_argnum(self, argnum):
@pytest.mark.slow
@pytest.mark.parametrize("shots, tol", [(None, 1e-7), ([1000, 100], 0.05)])
- def test_multi_pulse(self, shots, tol):
+ def test_multi_pulse(self, shots, tol, seed):
"""Test that a single pulse with multiple Hamiltonian terms is
differentiated correctly."""
import jax
import jax.numpy as jnp
- prng_key = jax.random.PRNGKey(8251)
+ prng_key = jax.random.PRNGKey(seed)
dev = qml.device("default.qubit", wires=1, shots=None)
dev_shots = qml.device("default.qubit", wires=1, shots=shots, seed=prng_key)
diff --git a/tests/gradients/core/test_vjp.py b/tests/gradients/core/test_vjp.py
index 6917207f715..ecc398094e5 100644
--- a/tests/gradients/core/test_vjp.py
+++ b/tests/gradients/core/test_vjp.py
@@ -423,12 +423,12 @@ def test_torch(self, tol):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf(self, tol):
+ def test_tf(self, tol, seed):
"""Tests that the output of the VJP transform
can be differentiated using TF."""
import tensorflow as tf
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit", wires=2, seed=seed)
params_np = np.array([0.543, -0.654], requires_grad=True)
params = tf.Variable(params_np, dtype=tf.float64)
@@ -468,7 +468,7 @@ def test_tf(self, tol):
# qml.RX(weights[i], wires=i)
# return [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1))]
- # vanilla_numpy.random.seed(42)
+ # vanilla_numpy.random.seed(seed)
# ndata = 100
# data = [vanilla_numpy.random.randn(nwires).astype("float32") for _ in range(ndata)]
diff --git a/tests/gradients/finite_diff/test_finite_difference_shot_vec.py b/tests/gradients/finite_diff/test_finite_difference_shot_vec.py
index 14bece2585e..ac6d19f575f 100644
--- a/tests/gradients/finite_diff/test_finite_difference_shot_vec.py
+++ b/tests/gradients/finite_diff/test_finite_difference_shot_vec.py
@@ -548,11 +548,11 @@ def test_single_expectation_value(self, approx_order, strategy, validate):
assert np.allclose(res, expected, atol=0.15, rtol=0)
- def test_single_expectation_value_with_argnum_all(self, approx_order, strategy, validate):
+ def test_single_expectation_value_with_argnum_all(self, approx_order, strategy, validate, seed):
"""Tests correct output shape and evaluation for a tape
with a single expval output where all parameters are chosen to compute
the jacobian"""
- dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector, seed=seed)
x = 0.543
y = -0.654
@@ -590,7 +590,7 @@ def test_single_expectation_value_with_argnum_all(self, approx_order, strategy,
assert np.allclose(res, expected, atol=0.15, rtol=0)
- def test_single_expectation_value_with_argnum_one(self, approx_order, strategy, validate):
+ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy, validate, seed):
"""Tests correct output shape and evaluation for a tape
with a single expval output where only one parameter is chosen to
estimate the jacobian.
@@ -598,7 +598,7 @@ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy,
This test relies on the fact that exactly one term of the estimated
jacobian will match the expected analytical value.
"""
- dev = qml.device("default.qubit", wires=2, seed=1967, shots=many_shots_shot_vector)
+ dev = qml.device("default.qubit", wires=2, seed=seed, shots=many_shots_shot_vector)
x = 0.543
y = -0.654
diff --git a/tests/gradients/finite_diff/test_spsa_gradient.py b/tests/gradients/finite_diff/test_spsa_gradient.py
index fb543381335..1bd2a198bca 100644
--- a/tests/gradients/finite_diff/test_spsa_gradient.py
+++ b/tests/gradients/finite_diff/test_spsa_gradient.py
@@ -90,10 +90,10 @@ def test_same_seeds(self):
"ids, num", [(list(range(5)), 5), ([0, 2, 4], 5), ([0], 1), ([2, 3], 5)]
)
@pytest.mark.parametrize("N", [10, 10000])
- def test_mean_and_var(self, ids, num, N):
+ def test_mean_and_var(self, ids, num, N, seed):
"""Test that the mean and variance of many produced samples are
close to the theoretical values."""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
ids_mask = np.zeros(num, dtype=bool)
ids_mask[ids] = True
outputs = [_rademacher_sampler(ids, num, rng=rng) for _ in range(N)]
@@ -110,7 +110,7 @@ def test_mean_and_var(self, ids, num, N):
class TestSpsaGradient:
"""Tests for the SPSA gradient transform"""
- def test_sampler_argument(self):
+ def test_sampler_argument(self, seed):
"""Make sure that custom samplers can be created as defined in the docs of spsa_grad."""
def sampler_required_kwarg(
@@ -141,7 +141,7 @@ def sampler_required_arg(
results = []
for sampler in [sampler_required_arg_or_kwarg, sampler_required_kwarg]:
- sampler_rng = np.random.default_rng(42)
+ sampler_rng = np.random.default_rng(seed)
tapes, proc_fn = spsa_grad(
tape, sampler=sampler, num_directions=100, sampler_rng=sampler_rng
)
@@ -446,10 +446,10 @@ def test_y0_provided(self):
# one tape per direction, the unshifted one already was evaluated above
assert len(tapes) == n
- def test_independent_parameters(self):
+ def test_independent_parameters(self, seed):
"""Test the case where expectation values are independent of some parameters. For those
parameters, the gradient should be evaluated to zero without executing the device."""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2)
with qml.queuing.AnnotatedQueue() as q1:
@@ -987,12 +987,12 @@ class TestSpsaGradientDifferentiation:
"""Test that the transform is differentiable"""
@pytest.mark.autograd
- def test_autograd(self, sampler, num_directions, atol):
+ def test_autograd(self, sampler, num_directions, atol, seed):
"""Tests that the output of the SPSA gradient transform
can be differentiated using autograd, yielding second derivatives."""
dev = qml.device("default.qubit", wires=2)
params = pnp.array([0.543, -0.654], requires_grad=True)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
def cost_fn(x):
with qml.queuing.AnnotatedQueue() as q:
@@ -1023,12 +1023,12 @@ def cost_fn(x):
assert np.allclose(res, expected, atol=atol, rtol=0)
@pytest.mark.autograd
- def test_autograd_ragged(self, sampler, num_directions, atol):
+ def test_autograd_ragged(self, sampler, num_directions, atol, seed):
"""Tests that the output of the SPSA gradient transform
of a ragged tape can be differentiated using autograd, yielding second derivatives."""
dev = qml.device("default.qubit", wires=2)
params = pnp.array([0.543, -0.654], requires_grad=True)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
def cost_fn(x):
with qml.queuing.AnnotatedQueue() as q:
@@ -1055,14 +1055,14 @@ def cost_fn(x):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf(self, sampler, num_directions, atol):
+ def test_tf(self, sampler, num_directions, atol, seed):
"""Tests that the output of the SPSA gradient transform
can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
dev = qml.device("default.qubit", wires=2)
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
with tf.GradientTape(persistent=True) as t:
with qml.queuing.AnnotatedQueue() as q:
@@ -1096,14 +1096,14 @@ def test_tf(self, sampler, num_directions, atol):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf_ragged(self, sampler, num_directions, atol):
+ def test_tf_ragged(self, sampler, num_directions, atol, seed):
"""Tests that the output of the SPSA gradient transform
of a ragged tape can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
dev = qml.device("default.qubit", wires=2)
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
with tf.GradientTape(persistent=True) as t:
with qml.queuing.AnnotatedQueue() as q:
@@ -1132,14 +1132,14 @@ def test_tf_ragged(self, sampler, num_directions, atol):
assert np.allclose(res_01[0], expected, atol=atol, rtol=0)
@pytest.mark.torch
- def test_torch(self, sampler, num_directions, atol):
+ def test_torch(self, sampler, num_directions, atol, seed):
"""Tests that the output of the SPSA gradient transform
can be differentiated using Torch, yielding second derivatives."""
import torch
dev = qml.device("default.qubit", wires=2)
params = torch.tensor([0.543, -0.654], dtype=torch.float64, requires_grad=True)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
def cost_fn(params):
with qml.queuing.AnnotatedQueue() as q:
@@ -1172,7 +1172,7 @@ def cost_fn(params):
assert np.allclose(hess[1].detach().numpy(), expected[1], atol=atol, rtol=0)
@pytest.mark.jax
- def test_jax(self, sampler, num_directions, atol):
+ def test_jax(self, sampler, num_directions, atol, seed):
"""Tests that the output of the SPSA gradient transform
can be differentiated using JAX, yielding second derivatives."""
import jax
@@ -1180,7 +1180,7 @@ def test_jax(self, sampler, num_directions, atol):
dev = qml.device("default.qubit", wires=2)
params = jnp.array([0.543, -0.654])
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
def cost_fn(x):
with qml.queuing.AnnotatedQueue() as q:
diff --git a/tests/gradients/finite_diff/test_spsa_gradient_shot_vec.py b/tests/gradients/finite_diff/test_spsa_gradient_shot_vec.py
index 69646131de2..37035171a5d 100644
--- a/tests/gradients/finite_diff/test_spsa_gradient_shot_vec.py
+++ b/tests/gradients/finite_diff/test_spsa_gradient_shot_vec.py
@@ -236,10 +236,10 @@ def circuit(weights):
with pytest.raises(qml.QuantumFunctionError, match="No trainable parameters."):
spsa_grad(circuit, h=h_val)(weights)
- def test_all_zero_diff_methods(self):
+ def test_all_zero_diff_methods(self, seed):
"""Test that the transform works correctly when the diff method for every parameter is
identified to be 0, and that no tapes were generated."""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=4, shots=default_shot_vector)
@qml.qnode(dev)
@@ -260,10 +260,10 @@ def circuit(params):
assert result.shape == (4, 3)
assert np.allclose(result, 0)
- def test_all_zero_diff_methods_multiple_returns(self):
+ def test_all_zero_diff_methods_multiple_returns(self, seed):
"""Test that the transform works correctly when the diff method for every parameter is
identified to be 0, and that no tapes were generated."""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=4, shots=many_shots_shot_vector)
@@ -333,10 +333,10 @@ def test_y0_provided(self):
assert len(tapes) == n
- def test_independent_parameters(self):
+ def test_independent_parameters(self, seed):
"""Test the case where expectation values are independent of some parameters. For those
parameters, the gradient should be evaluated to zero without executing the device."""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
with qml.queuing.AnnotatedQueue() as q1:
@@ -514,11 +514,11 @@ def reference_qnode(x):
class TestSpsaGradientIntegration:
"""Tests for the SPSA gradient transform"""
- def test_ragged_output(self, approx_order, strategy, validate):
+ def test_ragged_output(self, approx_order, strategy, validate, seed):
"""Test that the Jacobian is correctly returned for a tape with ragged output"""
dev = qml.device("default.qubit", wires=3, shots=many_shots_shot_vector)
params = [1.0, 1.0, 1.0]
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
with qml.queuing.AnnotatedQueue() as q:
qml.RX(params[0], wires=[0])
@@ -556,10 +556,10 @@ def test_ragged_output(self, approx_order, strategy, validate):
assert res[1][1].shape == (4,)
assert res[1][2].shape == (4,)
- def test_single_expectation_value(self, approx_order, strategy, validate):
+ def test_single_expectation_value(self, approx_order, strategy, validate, seed):
"""Tests correct output shape and evaluation for a tape
with a single expval output"""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
x = 0.543
y = -0.654
@@ -602,11 +602,11 @@ def test_single_expectation_value(self, approx_order, strategy, validate):
# 1 / num_params here.
assert np.allclose([2 * r for r in res], expected, atol=spsa_shot_vec_tol, rtol=0)
- def test_single_expectation_value_with_argnum_all(self, approx_order, strategy, validate):
+ def test_single_expectation_value_with_argnum_all(self, approx_order, strategy, validate, seed):
"""Tests correct output shape and evaluation for a tape
with a single expval output where all parameters are chosen to compute
the jacobian"""
- rng = np.random.default_rng(5214)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
x = 0.543
y = -0.654
@@ -651,7 +651,7 @@ def test_single_expectation_value_with_argnum_all(self, approx_order, strategy,
# 1 / num_params here.
assert np.allclose([2 * r for r in res], expected, atol=spsa_shot_vec_tol, rtol=0)
- def test_single_expectation_value_with_argnum_one(self, approx_order, strategy, validate):
+ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy, validate, seed):
"""Tests correct output shape and evaluation for a tape
with a single expval output where only one parameter is chosen to
estimate the jacobian.
@@ -659,7 +659,7 @@ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy,
This test relies on the fact that exactly one term of the estimated
jacobian will match the expected analytical value.
"""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
x = 0.543
y = -0.654
@@ -704,7 +704,9 @@ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy,
# parameter, so that we do not need to compensate like in the other tests
assert np.allclose(res, expected, atol=spsa_shot_vec_tol, rtol=0)
- def test_multiple_expectation_value_with_argnum_one(self, approx_order, strategy, validate):
+ def test_multiple_expectation_value_with_argnum_one(
+ self, approx_order, strategy, validate, seed
+ ):
"""Tests correct output shape and evaluation for a tape
with a multiple measurement, where only one parameter is chosen to
be trainable.
@@ -712,7 +714,7 @@ def test_multiple_expectation_value_with_argnum_one(self, approx_order, strategy
This test relies on the fact that exactly one term of the estimated
jacobian will match the expected analytical value.
"""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
x = 0.543
y = -0.654
@@ -751,10 +753,10 @@ def test_multiple_expectation_value_with_argnum_one(self, approx_order, strategy
assert isinstance(res[1], tuple)
assert np.allclose(res[1][0], 0)
- def test_multiple_expectation_values(self, approx_order, strategy, validate):
+ def test_multiple_expectation_values(self, approx_order, strategy, validate, seed):
"""Tests correct output shape and evaluation for a tape
with multiple expval outputs"""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
x = 0.543
y = -0.654
@@ -805,10 +807,10 @@ def test_multiple_expectation_values(self, approx_order, strategy, validate):
res_1 = (2 * res[1][0], 2 * res[1][1])
assert np.allclose(res_1, [0, np.cos(y)], atol=spsa_shot_vec_tol, rtol=0)
- def test_var_expectation_values(self, approx_order, strategy, validate):
+ def test_var_expectation_values(self, approx_order, strategy, validate, seed):
"""Tests correct output shape and evaluation for a tape
with expval and var outputs"""
- rng = np.random.default_rng(52)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector, seed=rng)
x = 0.543
@@ -860,10 +862,10 @@ def test_var_expectation_values(self, approx_order, strategy, validate):
res_1, [0, -2 * np.cos(y) * np.sin(y)], atol=spsa_shot_vec_tol, rtol=0
)
- def test_prob_expectation_values(self, approx_order, strategy, validate):
+ def test_prob_expectation_values(self, approx_order, strategy, validate, seed):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
x = 0.543
y = -0.654
@@ -944,12 +946,12 @@ class TestSpsaGradientDifferentiation:
"""Test that the transform is differentiable"""
@pytest.mark.autograd
- def test_autograd(self, approx_order, strategy):
+ def test_autograd(self, approx_order, strategy, seed):
"""Tests that the output of the SPSA gradient transform
can be differentiated using autograd, yielding second derivatives."""
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
params = pnp.array([0.543, -0.654], requires_grad=True)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
def cost_fn(x):
with qml.queuing.AnnotatedQueue() as q:
@@ -987,12 +989,12 @@ def cost_fn(x):
assert np.allclose(res, expected, atol=spsa_shot_vec_tol, rtol=0)
@pytest.mark.autograd
- def test_autograd_ragged(self, approx_order, strategy):
+ def test_autograd_ragged(self, approx_order, strategy, seed):
"""Tests that the output of the SPSA gradient transform
of a ragged tape can be differentiated using autograd, yielding second derivatives."""
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
params = pnp.array([0.543, -0.654], requires_grad=True)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
def cost_fn(x):
with qml.queuing.AnnotatedQueue() as q:
@@ -1027,14 +1029,14 @@ def cost_fn(x):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf(self, approx_order, strategy):
+ def test_tf(self, approx_order, strategy, seed):
"""Tests that the output of the SPSA gradient transform
can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
with tf.GradientTape(persistent=True) as t:
with qml.queuing.AnnotatedQueue() as q:
@@ -1069,14 +1071,14 @@ def test_tf(self, approx_order, strategy):
assert np.allclose([res_0, res_1], expected, atol=spsa_shot_vec_tol, rtol=0)
@pytest.mark.tf
- def test_tf_ragged(self, approx_order, strategy):
+ def test_tf_ragged(self, approx_order, strategy, seed):
"""Tests that the output of the SPSA gradient transform
of a ragged tape can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
with tf.GradientTape(persistent=True) as t:
with qml.queuing.AnnotatedQueue() as q:
@@ -1108,14 +1110,14 @@ def test_tf_ragged(self, approx_order, strategy):
assert np.allclose(res_01[0], expected, atol=spsa_shot_vec_tol, rtol=0)
@pytest.mark.torch
- def test_torch(self, approx_order, strategy):
+ def test_torch(self, approx_order, strategy, seed):
"""Tests that the output of the SPSA gradient transform
can be differentiated using Torch, yielding second derivatives."""
import torch
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
params = torch.tensor([0.543, -0.654], dtype=torch.float64, requires_grad=True)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
def cost_fn(params):
with qml.queuing.AnnotatedQueue() as q:
@@ -1150,7 +1152,7 @@ def cost_fn(params):
assert np.allclose(hess[1].detach().numpy(), expected[1], atol=spsa_shot_vec_tol, rtol=0)
@pytest.mark.jax
- def test_jax(self, approx_order, strategy):
+ def test_jax(self, approx_order, strategy, seed):
"""Tests that the output of the SPSA gradient transform
can be differentiated using JAX, yielding second derivatives."""
import jax
@@ -1158,7 +1160,7 @@ def test_jax(self, approx_order, strategy):
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
params = jnp.array([0.543, -0.654])
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
def cost_fn(x):
with qml.queuing.AnnotatedQueue() as q:
diff --git a/tests/gradients/parameter_shift/test_parameter_shift.py b/tests/gradients/parameter_shift/test_parameter_shift.py
index 8d8d17bfaa7..5f8d6308a51 100644
--- a/tests/gradients/parameter_shift/test_parameter_shift.py
+++ b/tests/gradients/parameter_shift/test_parameter_shift.py
@@ -2062,10 +2062,10 @@ def test_non_involutory_variance_multi_param(self, tol):
assert gradA[1] == pytest.approx(expected, abs=tol)
assert gradF[1] == pytest.approx(expected, abs=tol)
- def test_involutory_and_noninvolutory_variance_single_param(self, tol):
+ def test_involutory_and_noninvolutory_variance_single_param(self, tol, seed):
"""Tests a qubit Hermitian observable that is not involutory alongside
an involutory observable when there's a single trainable parameter."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit", wires=2, seed=seed)
A = np.array([[4, -1 + 6j], [-1 - 6j, 2]])
a = 0.54
diff --git a/tests/gradients/parameter_shift/test_parameter_shift_shot_vec.py b/tests/gradients/parameter_shift/test_parameter_shift_shot_vec.py
index 4ad2b84007f..ca55758062c 100644
--- a/tests/gradients/parameter_shift/test_parameter_shift_shot_vec.py
+++ b/tests/gradients/parameter_shift/test_parameter_shift_shot_vec.py
@@ -1312,11 +1312,10 @@ def test_non_involutory_variance_single_param(self, broadcast):
assert gradF.shape == ()
assert qml.math.allclose(gradF, expected, atol=2 * _herm_shot_vec_tol)
- @flaky(max_runs=5)
- def test_non_involutory_variance_multi_param(self, broadcast):
+ def test_non_involutory_variance_multi_param(self, broadcast, seed):
"""Tests a qubit Hermitian observable that is not involutory with multiple trainable parameters"""
shot_vec = many_shots_shot_vector
- dev = qml.device("default.qubit", wires=1, shots=shot_vec)
+ dev = qml.device("default.qubit", wires=1, shots=shot_vec, seed=seed)
a = 0.34
b = 0.20
@@ -1721,11 +1720,11 @@ def test_expval_and_variance_single_param(self, broadcast):
assert isinstance(gradF, tuple)
assert gradF == pytest.approx(expected, abs=finite_diff_tol)
- def test_expval_and_variance_multi_param(self, broadcast):
+ def test_expval_and_variance_multi_param(self, broadcast, seed):
"""Test an expectation value and the variance of involutory and non-involutory observables work well with
multiple trainable parameters"""
shot_vec = many_shots_shot_vector
- dev = qml.device("default.qubit", wires=3, shots=shot_vec, seed=12393)
+ dev = qml.device("default.qubit", wires=3, shots=shot_vec, seed=seed)
a = 0.54
b = -0.423
diff --git a/tests/interfaces/test_autograd.py b/tests/interfaces/test_autograd.py
index d206f1758d3..589ebed952b 100644
--- a/tests/interfaces/test_autograd.py
+++ b/tests/interfaces/test_autograd.py
@@ -27,6 +27,12 @@
pytestmark = pytest.mark.autograd
+def get_device(device_name, seed):
+ if device_name == "param_shift.qubit":
+ return ParamShiftDerivativesDevice(seed=seed)
+ return qml.device(device_name, seed=seed)
+
+
# pylint: disable=too-few-public-methods
class TestCaching:
"""Tests for caching behaviour"""
@@ -126,14 +132,14 @@ def f(x):
# add tests for lightning 2 when possible
# set rng for device when possible
test_matrix = [
- ({"gradient_fn": param_shift}, Shots(50000), DefaultQubit(seed=42)),
- ({"gradient_fn": param_shift}, Shots((50000, 50000)), DefaultQubit(seed=42)),
- ({"gradient_fn": param_shift}, Shots(None), DefaultQubit()),
- ({"gradient_fn": "backprop"}, Shots(None), DefaultQubit()),
+ ({"gradient_fn": param_shift}, Shots(50000), "default.qubit"),
+ ({"gradient_fn": param_shift}, Shots((50000, 50000)), "default.qubit"),
+ ({"gradient_fn": param_shift}, Shots(None), "default.qubit"),
+ ({"gradient_fn": "backprop"}, Shots(None), "default.qubit"),
(
{"gradient_fn": "adjoint", "grad_on_execution": True, "device_vjp": False},
Shots(None),
- DefaultQubit(),
+ "default.qubit",
),
(
{
@@ -142,33 +148,33 @@ def f(x):
"device_vjp": False,
},
Shots(None),
- DefaultQubit(),
+ "default.qubit",
),
- ({"gradient_fn": "adjoint", "device_vjp": True}, Shots(None), DefaultQubit()),
+ ({"gradient_fn": "adjoint", "device_vjp": True}, Shots(None), "default.qubit"),
(
{"gradient_fn": "device", "device_vjp": False},
Shots((50000, 50000)),
- ParamShiftDerivativesDevice(seed=904747894),
+ "param_shift.qubit",
),
(
{"gradient_fn": "device", "device_vjp": True},
Shots((100000, 100000)),
- ParamShiftDerivativesDevice(seed=10490244),
+ "param_shift.qubit",
),
(
{"gradient_fn": param_shift},
Shots(None),
- qml.device("reference.qubit"),
+ "reference.qubit",
),
(
{"gradient_fn": param_shift},
Shots(50000),
- qml.device("reference.qubit", seed=8743274),
+ "reference.qubit",
),
(
{"gradient_fn": param_shift},
Shots((50000, 50000)),
- qml.device("reference.qubit", seed=8743274),
+ "reference.qubit",
),
]
@@ -178,14 +184,16 @@ def atol_for_shots(shots):
return 5e-2 if shots else 1e-6
-@pytest.mark.parametrize("execute_kwargs, shots, device", test_matrix)
+@pytest.mark.parametrize("execute_kwargs, shots, device_name", test_matrix)
class TestAutogradExecuteIntegration:
"""Test the autograd interface execute function
integrates well for both forward and backward execution"""
- def test_execution(self, execute_kwargs, shots, device):
+ def test_execution(self, execute_kwargs, shots, device_name, seed):
"""Test execution"""
+ device = get_device(device_name, seed=seed)
+
def cost(a, b):
ops1 = [qml.RY(a, wires=0), qml.RX(b, wires=0)]
tape1 = qml.tape.QuantumScript(ops1, [qml.expval(qml.PauliZ(0))], shots=shots)
@@ -214,8 +222,10 @@ def cost(a, b):
assert qml.math.allclose(res[0], np.cos(a) * np.cos(b), atol=atol_for_shots(shots))
assert qml.math.allclose(res[1], np.cos(a) * np.cos(b), atol=atol_for_shots(shots))
- def test_scalar_jacobian(self, execute_kwargs, shots, device):
+ def test_scalar_jacobian(self, execute_kwargs, shots, device_name, seed):
"""Test scalar jacobian calculation"""
+
+ device = get_device(device_name, seed=seed)
a = pnp.array(0.1, requires_grad=True)
def cost(a):
@@ -238,11 +248,13 @@ def cost(a):
assert np.allclose(res, expected, atol=atol_for_shots(shots), rtol=0)
assert np.allclose(res, -np.sin(a), atol=atol_for_shots(shots))
- def test_jacobian(self, execute_kwargs, shots, device):
+ def test_jacobian(self, execute_kwargs, shots, device_name, seed):
"""Test jacobian calculation"""
a = pnp.array(0.1, requires_grad=True)
b = pnp.array(0.2, requires_grad=True)
+ device = get_device(device_name, seed=seed)
+
def cost(a, b):
ops = [qml.RY(a, wires=0), qml.RX(b, wires=1), qml.CNOT(wires=[0, 1])]
m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))]
@@ -276,10 +288,12 @@ def cost(a, b):
assert np.allclose(_r, _e, atol=atol_for_shots(shots))
@pytest.mark.filterwarnings("ignore:Attempted to compute the gradient")
- def test_tape_no_parameters(self, execute_kwargs, shots, device):
+ def test_tape_no_parameters(self, execute_kwargs, shots, device_name, seed):
"""Test that a tape with no parameters is correctly
ignored during the gradient computation"""
+ device = get_device(device_name, seed=seed)
+
def cost(params):
tape1 = qml.tape.QuantumScript(
[qml.Hadamard(0)], [qml.expval(qml.PauliX(0))], shots=shots
@@ -323,12 +337,14 @@ def cost(params):
assert np.allclose(grad, expected, atol=atol_for_shots(shots), rtol=0)
@pytest.mark.filterwarnings("ignore:Attempted to compute the gradient")
- def test_tapes_with_different_return_size(self, execute_kwargs, shots, device):
+ def test_tapes_with_different_return_size(self, execute_kwargs, shots, device_name, seed):
"""Test that tapes wit different can be executed and differentiated."""
if execute_kwargs["gradient_fn"] == "backprop":
pytest.xfail("backprop is not compatible with something about this situation.")
+ device = get_device(device_name, seed=seed)
+
def cost(params):
tape1 = qml.tape.QuantumScript(
[qml.RY(params[0], 0), qml.RX(params[1], 0)],
@@ -406,8 +422,11 @@ def cost(params):
assert np.allclose(jac[0, 1], d2, atol=atol_for_shots(shots))
assert np.allclose(jac[3, 1], d2, atol=atol_for_shots(shots))
- def test_reusing_quantum_tape(self, execute_kwargs, shots, device):
+ def test_reusing_quantum_tape(self, execute_kwargs, shots, device_name, seed):
"""Test re-using a quantum tape by passing new parameters"""
+
+ device = get_device(device_name, seed=seed)
+
a = pnp.array(0.1, requires_grad=True)
b = pnp.array(0.2, requires_grad=True)
@@ -443,12 +462,14 @@ def cost(a, b):
for _j, _e in zip(jac, expected):
assert np.allclose(_j, _e, atol=atol_for_shots(shots), rtol=0)
- def test_classical_processing(self, execute_kwargs, device, shots):
+ def test_classical_processing(self, execute_kwargs, device_name, seed, shots):
"""Test classical processing within the quantum tape"""
a = pnp.array(0.1, requires_grad=True)
b = pnp.array(0.2, requires_grad=False)
c = pnp.array(0.3, requires_grad=True)
+ device = get_device(device_name, seed=seed)
+
def cost(a, b, c):
ops = [
qml.RY(a * c, wires=0),
@@ -471,11 +492,13 @@ def cost(a, b, c):
# I tried getting analytic results for this circuit but I kept being wrong and am giving up
- def test_no_trainable_parameters(self, execute_kwargs, shots, device):
+ def test_no_trainable_parameters(self, execute_kwargs, shots, device_name, seed):
"""Test evaluation and Jacobian if there are no trainable parameters"""
a = pnp.array(0.1, requires_grad=False)
b = pnp.array(0.2, requires_grad=False)
+ device = get_device(device_name, seed=seed)
+
def cost(a, b):
ops = [qml.RY(a, 0), qml.RX(b, 0), qml.CNOT((0, 1))]
m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1))]
@@ -497,9 +520,10 @@ def loss(a, b):
assert np.allclose(res, 0)
- def test_matrix_parameter(self, execute_kwargs, device, shots):
+ def test_matrix_parameter(self, execute_kwargs, device_name, seed, shots):
"""Test that the autograd interface works correctly
with a matrix parameter"""
+ device = get_device(device_name, seed=seed)
U = pnp.array([[0, 1], [1, 0]], requires_grad=False)
a = pnp.array(0.1, requires_grad=True)
@@ -516,10 +540,12 @@ def cost(a, U):
assert isinstance(jac, np.ndarray)
assert np.allclose(jac, np.sin(a), atol=atol_for_shots(shots), rtol=0)
- def test_differentiable_expand(self, execute_kwargs, device, shots):
+ def test_differentiable_expand(self, execute_kwargs, device_name, seed, shots):
"""Test that operation and nested tapes expansion
is differentiable"""
+ device = get_device(device_name, seed=seed)
+
class U3(qml.U3):
"""Dummy operator."""
@@ -574,10 +600,12 @@ def cost_fn(a, p):
)
assert np.allclose(res, expected, atol=atol_for_shots(shots), rtol=0)
- def test_probability_differentiation(self, execute_kwargs, device, shots):
+ def test_probability_differentiation(self, execute_kwargs, device_name, seed, shots):
"""Tests correct output shape and evaluation for a tape
with prob outputs"""
+ device = get_device(device_name, seed=seed)
+
def cost(x, y):
ops = [qml.RX(x, 0), qml.RY(y, 1), qml.CNOT((0, 1))]
m = [qml.probs(wires=0), qml.probs(wires=1)]
@@ -627,10 +655,12 @@ def cost(x, y):
assert np.allclose(res[0], expected[0], atol=atol_for_shots(shots), rtol=0)
assert np.allclose(res[1], expected[1], atol=atol_for_shots(shots), rtol=0)
- def test_ragged_differentiation(self, execute_kwargs, device, shots):
+ def test_ragged_differentiation(self, execute_kwargs, device_name, seed, shots):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
+ device = get_device(device_name, seed=seed)
+
def cost(x, y):
ops = [qml.RX(x, wires=0), qml.RY(y, 1), qml.CNOT((0, 1))]
m = [qml.expval(qml.PauliZ(0)), qml.probs(wires=1)]
@@ -739,16 +769,18 @@ def cost_fn(x):
assert np.allclose(res, expected, atol=tol, rtol=0)
-@pytest.mark.parametrize("execute_kwargs, shots, device", test_matrix)
+@pytest.mark.parametrize("execute_kwargs, shots, device_name", test_matrix)
@pytest.mark.usefixtures("use_legacy_and_new_opmath")
class TestHamiltonianWorkflows:
"""Test that tapes ending with expectations
of Hamiltonians provide correct results and gradients"""
@pytest.fixture
- def cost_fn(self, execute_kwargs, shots, device):
+ def cost_fn(self, execute_kwargs, shots, device_name, seed):
"""Cost function for gradient tests"""
+ device = get_device(device_name, seed=seed)
+
def _cost_fn(weights, coeffs1, coeffs2):
obs1 = [qml.PauliZ(0), qml.PauliZ(0) @ qml.PauliX(1), qml.PauliY(0)]
H1 = qml.Hamiltonian(coeffs1, obs1)
diff --git a/tests/interfaces/test_autograd_qnode.py b/tests/interfaces/test_autograd_qnode.py
index 1d6dcfe397b..f203041279f 100644
--- a/tests/interfaces/test_autograd_qnode.py
+++ b/tests/interfaces/test_autograd_qnode.py
@@ -69,7 +69,6 @@
pytestmark = pytest.mark.autograd
TOL_FOR_SPSA = 1.0
-SEED_FOR_SPSA = 32651
H_FOR_SPSA = 0.01
@@ -128,7 +127,7 @@ def circuit(a):
assert grad.shape == tuple()
- def test_jacobian(self, interface, dev, diff_method, grad_on_execution, tol, device_vjp):
+ def test_jacobian(self, interface, dev, diff_method, grad_on_execution, tol, device_vjp, seed):
"""Test jacobian calculation"""
kwargs = dict(
diff_method=diff_method,
@@ -138,7 +137,7 @@ def test_jacobian(self, interface, dev, diff_method, grad_on_execution, tol, dev
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
a = np.array(0.1, requires_grad=True)
@@ -175,7 +174,7 @@ def cost(x, y):
assert np.allclose(res[1], expected[1], atol=tol, rtol=0)
def test_jacobian_no_evaluate(
- self, interface, dev, diff_method, grad_on_execution, tol, device_vjp
+ self, interface, dev, diff_method, grad_on_execution, tol, device_vjp, seed
):
"""Test jacobian calculation when no prior circuit evaluation has been performed"""
kwargs = dict(
@@ -185,7 +184,7 @@ def test_jacobian_no_evaluate(
device_vjp=device_vjp,
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
a = np.array(0.1, requires_grad=True)
@@ -416,7 +415,7 @@ def circuit(data1):
grad_fn(data1)
def test_differentiable_expand(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Test that operation and nested tape expansion
is differentiable"""
@@ -428,7 +427,7 @@ def test_differentiable_expand(
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 10
tol = TOL_FOR_SPSA
@@ -572,7 +571,7 @@ class TestQubitIntegration:
"""Tests that ensure various qubit circuits integrate correctly"""
def test_probability_differentiation(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with a single prob output"""
@@ -587,7 +586,7 @@ def test_probability_differentiation(
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
x = np.array(0.543, requires_grad=True)
@@ -610,7 +609,7 @@ def circuit(x, y):
assert all(np.allclose(r, e, atol=tol, rtol=0) for r, e in zip(res, expected))
def test_multiple_probability_differentiation(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with multiple prob outputs"""
@@ -624,7 +623,7 @@ def test_multiple_probability_differentiation(
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
x = np.array(0.543, requires_grad=True)
@@ -676,7 +675,7 @@ def cost(x, y):
assert all(np.allclose(r, e, atol=tol, rtol=0) for r, e in zip(res, expected))
def test_ragged_differentiation(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
@@ -691,7 +690,7 @@ def test_ragged_differentiation(
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
x = np.array(0.543, requires_grad=True)
@@ -728,7 +727,7 @@ def cost(x, y):
assert np.allclose(res[1], expected[1], atol=tol, rtol=0)
def test_ragged_differentiation_variance(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with prob and variance outputs"""
@@ -742,7 +741,7 @@ def test_ragged_differentiation_variance(
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
elif diff_method == "hadamard":
pytest.skip("Hadamard gradient does not support variances.")
@@ -845,7 +844,7 @@ def cost(w1, w2):
assert len(res) == 2
def test_chained_gradient_value(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Test that the returned gradient value for two chained qubit QNodes
is correct."""
@@ -857,7 +856,7 @@ def test_chained_gradient_value(
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
dev1 = qml.device("default.qubit")
@@ -1375,7 +1374,7 @@ def cost_fn(x, y):
@pytest.mark.parametrize("state", [[1], [0, 1]]) # Basis state and state vector
def test_projector(
- self, state, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, state, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Test that the variance of a projector is correctly returned"""
if diff_method == "adjoint":
@@ -1390,7 +1389,7 @@ def test_projector(
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
elif diff_method == "hadamard":
pytest.skip("Hadamard gradient does not support variances.")
@@ -1526,7 +1525,7 @@ def circuit(x, y):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_expansion_analytic(
- self, dev, diff_method, grad_on_execution, max_diff, tol, device_vjp
+ self, dev, diff_method, grad_on_execution, max_diff, tol, device_vjp, seed
):
"""Test that if there are non-commuting groups and the number of shots is None
the first and second order gradients are correctly evaluated"""
@@ -1540,7 +1539,7 @@ def test_hamiltonian_expansion_analytic(
if diff_method in ["adjoint", "hadamard"]:
pytest.skip("The diff method requested does not yet support Hamiltonians")
elif diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 10
tol = TOL_FOR_SPSA
@@ -1596,7 +1595,7 @@ def circuit(data, weights, coeffs):
@pytest.mark.slow
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_finite_shots(
- self, dev, diff_method, grad_on_execution, max_diff, device_vjp
+ self, dev, diff_method, grad_on_execution, max_diff, device_vjp, seed
):
"""Test that the Hamiltonian is correctly measured if there
are non-commuting groups and the number of shots is finite
@@ -1608,7 +1607,7 @@ def test_hamiltonian_finite_shots(
elif diff_method == "spsa":
gradient_kwargs = {
"h": H_FOR_SPSA,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
"num_directions": 10,
}
tol = TOL_FOR_SPSA
diff --git a/tests/interfaces/test_jax.py b/tests/interfaces/test_jax.py
index 561f5ab6512..97f8abaa79c 100644
--- a/tests/interfaces/test_jax.py
+++ b/tests/interfaces/test_jax.py
@@ -29,6 +29,12 @@
pytestmark = pytest.mark.jax
+def get_device(device_name, seed):
+ if device_name == "param_shift.qubit":
+ return ParamShiftDerivativesDevice(seed=seed)
+ return qml.device(device_name, seed=seed)
+
+
def test_jit_execution():
"""Test that qml.execute can be directly jitted."""
dev = qml.device("default.qubit")
@@ -124,20 +130,17 @@ def cost(x, cache):
no_shots = Shots(None)
shots_10k = Shots(10000)
shots_2_10k = Shots((10000, 10000))
-dev_def = DefaultQubit(seed=42)
-dev_ps = ParamShiftDerivativesDevice(seed=54353453)
-dev_ref = qml.device("reference.qubit", seed=786345)
test_matrix = [
- ({"gradient_fn": param_shift}, shots_10k, dev_def), # 0
- ({"gradient_fn": param_shift}, shots_2_10k, dev_def), # 1
- ({"gradient_fn": param_shift}, no_shots, dev_def), # 2
- ({"gradient_fn": "backprop"}, no_shots, dev_def), # 3
- ({"gradient_fn": "adjoint"}, no_shots, dev_def), # 4
- ({"gradient_fn": "adjoint", "device_vjp": True}, no_shots, dev_def), # 5
- ({"gradient_fn": "device"}, shots_2_10k, dev_ps), # 6
- ({"gradient_fn": param_shift}, no_shots, dev_ref), # 7
- ({"gradient_fn": param_shift}, shots_10k, dev_ref), # 8
- ({"gradient_fn": param_shift}, shots_2_10k, dev_ref), # 9
+ ({"gradient_fn": param_shift}, shots_10k, "default.qubit"), # 0
+ ({"gradient_fn": param_shift}, shots_2_10k, "default.qubit"), # 1
+ ({"gradient_fn": param_shift}, no_shots, "default.qubit"), # 2
+ ({"gradient_fn": "backprop"}, no_shots, "default.qubit"), # 3
+ ({"gradient_fn": "adjoint"}, no_shots, "default.qubit"), # 4
+ ({"gradient_fn": "adjoint", "device_vjp": True}, no_shots, "default.qubit"), # 5
+ ({"gradient_fn": "device"}, shots_2_10k, "param_shift.qubit"), # 6
+ ({"gradient_fn": param_shift}, no_shots, "reference.qubit"), # 7
+ ({"gradient_fn": param_shift}, shots_10k, "reference.qubit"), # 8
+ ({"gradient_fn": param_shift}, shots_2_10k, "reference.qubit"), # 9
]
@@ -146,14 +149,16 @@ def atol_for_shots(shots):
return 3e-2 if shots else 1e-6
-@pytest.mark.parametrize("execute_kwargs, shots, device", test_matrix)
+@pytest.mark.parametrize("execute_kwargs, shots, device_name", test_matrix)
class TestJaxExecuteIntegration:
"""Test the jax interface execute function
integrates well for both forward and backward execution"""
- def test_execution(self, execute_kwargs, shots, device):
+ def test_execution(self, execute_kwargs, shots, device_name, seed):
"""Test execution"""
+ device = get_device(device_name, seed)
+
def cost(a, b):
ops1 = [qml.RY(a, wires=0), qml.RX(b, wires=0)]
tape1 = qml.tape.QuantumScript(ops1, [qml.expval(qml.PauliZ(0))], shots=shots)
@@ -182,10 +187,12 @@ def cost(a, b):
assert qml.math.allclose(res[0], jnp.cos(a) * jnp.cos(b), atol=atol_for_shots(shots))
assert qml.math.allclose(res[1], jnp.cos(a) * jnp.cos(b), atol=atol_for_shots(shots))
- def test_scalar_jacobian(self, execute_kwargs, shots, device):
+ def test_scalar_jacobian(self, execute_kwargs, shots, device_name, seed):
"""Test scalar jacobian calculation"""
a = jnp.array(0.1)
+ device = get_device(device_name, seed)
+
def cost(a):
tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots)
return execute([tape], device, **execute_kwargs)[0]
@@ -204,12 +211,14 @@ def cost(a):
assert np.allclose(res, expected, atol=atol_for_shots(shots), rtol=0)
assert np.allclose(res, -jnp.sin(a), atol=atol_for_shots(shots))
- def test_jacobian(self, execute_kwargs, shots, device):
+ def test_jacobian(self, execute_kwargs, shots, device_name, seed):
"""Test jacobian calculation"""
a = jnp.array(0.1)
b = jnp.array(0.2)
+ device = get_device(device_name, seed)
+
def cost(a, b):
ops = [qml.RY(a, wires=0), qml.RX(b, wires=1), qml.CNOT(wires=[0, 1])]
m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))]
@@ -241,10 +250,12 @@ def cost(a, b):
assert np.allclose(g[0][1], expected[1][0], atol=atol_for_shots(shots), rtol=0)
assert np.allclose(g[1][1], expected[1][1], atol=atol_for_shots(shots), rtol=0)
- def test_tape_no_parameters(self, execute_kwargs, shots, device):
+ def test_tape_no_parameters(self, execute_kwargs, shots, device_name, seed):
"""Test that a tape with no parameters is correctly
ignored during the gradient computation"""
+ device = get_device(device_name, seed)
+
def cost(params):
tape1 = qml.tape.QuantumScript(
[qml.Hadamard(0)], [qml.expval(qml.PauliX(0))], shots=shots
@@ -285,9 +296,11 @@ def cost(params):
assert np.allclose(grad, expected, atol=atol_for_shots(shots), rtol=0)
# pylint: disable=too-many-statements
- def test_tapes_with_different_return_size(self, execute_kwargs, shots, device):
+ def test_tapes_with_different_return_size(self, execute_kwargs, shots, device_name, seed):
"""Test that tapes wit different can be executed and differentiated."""
+ device = get_device(device_name, seed)
+
def cost(params):
tape1 = qml.tape.QuantumScript(
[qml.RY(params[0], 0), qml.RX(params[1], 0)],
@@ -362,11 +375,13 @@ def cost(params):
assert np.allclose(jac[0, 1], d2, atol=atol_for_shots(shots))
assert np.allclose(jac[3, 1], d2, atol=atol_for_shots(shots))
- def test_reusing_quantum_tape(self, execute_kwargs, shots, device):
+ def test_reusing_quantum_tape(self, execute_kwargs, shots, device_name, seed):
"""Test re-using a quantum tape by passing new parameters"""
if execute_kwargs["gradient_fn"] == param_shift:
pytest.skip("Basic QNode execution wipes out trainable params with param-shift")
+ device = get_device(device_name, seed)
+
a = jnp.array(0.1)
b = jnp.array(0.2)
@@ -414,12 +429,14 @@ def cost(a, b):
for _j, _e in zip(jac, expected):
assert np.allclose(_j, _e, atol=atol_for_shots(shots), rtol=0)
- def test_classical_processing(self, execute_kwargs, shots, device):
+ def test_classical_processing(self, execute_kwargs, shots, device_name, seed):
"""Test classical processing within the quantum tape"""
a = jnp.array(0.1)
b = jnp.array(0.2)
c = jnp.array(0.3)
+ device = get_device(device_name, seed)
+
def cost(a, b, c):
ops = [
qml.RY(a * c, wires=0),
@@ -440,12 +457,14 @@ def cost(a, b, c):
# I tried getting analytic results for this circuit but I kept being wrong and am giving up
- def test_matrix_parameter(self, execute_kwargs, device, shots):
+ def test_matrix_parameter(self, execute_kwargs, device_name, seed, shots):
"""Test that the jax interface works correctly
with a matrix parameter"""
U = jnp.array([[0, 1], [1, 0]])
a = jnp.array(0.1)
+ device = get_device(device_name, seed)
+
def cost(a, U):
ops = [qml.QubitUnitary(U, wires=0), qml.RY(a, wires=0)]
tape = qml.tape.QuantumScript(ops, [qml.expval(qml.PauliZ(0))], shots=shots)
@@ -460,10 +479,12 @@ def cost(a, U):
assert isinstance(jac, jnp.ndarray)
assert np.allclose(jac, jnp.sin(a), atol=atol_for_shots(shots), rtol=0)
- def test_differentiable_expand(self, execute_kwargs, device, shots):
+ def test_differentiable_expand(self, execute_kwargs, device_name, seed, shots):
"""Test that operation and nested tapes expansion
is differentiable"""
+ device = get_device(device_name, seed)
+
class U3(qml.U3):
"""Dummy operator."""
@@ -520,10 +541,12 @@ def cost_fn(a, p):
)
assert np.allclose(res, expected, atol=atol_for_shots(shots), rtol=0)
- def test_probability_differentiation(self, execute_kwargs, device, shots):
+ def test_probability_differentiation(self, execute_kwargs, device_name, seed, shots):
"""Tests correct output shape and evaluation for a tape
with prob outputs"""
+ device = get_device(device_name, seed)
+
def cost(x, y):
ops = [qml.RX(x, 0), qml.RY(y, 1), qml.CNOT((0, 1))]
m = [qml.probs(wires=0), qml.probs(wires=1)]
@@ -583,10 +606,12 @@ def cost(x, y):
assert np.allclose(res[0], expected[0], atol=atol_for_shots(shots), rtol=0)
assert np.allclose(res[1], expected[1], atol=atol_for_shots(shots), rtol=0)
- def test_ragged_differentiation(self, execute_kwargs, device, shots):
+ def test_ragged_differentiation(self, execute_kwargs, device_name, seed, shots):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
+ device = get_device(device_name, seed)
+
def cost(x, y):
ops = [qml.RX(x, wires=0), qml.RY(y, 1), qml.CNOT((0, 1))]
m = [qml.expval(qml.PauliZ(0)), qml.probs(wires=1)]
@@ -704,16 +729,18 @@ def cost_fn(x):
assert np.allclose(res, expected, atol=tol, rtol=0)
-@pytest.mark.parametrize("execute_kwargs, shots, device", test_matrix)
+@pytest.mark.parametrize("execute_kwargs, shots, device_name", test_matrix)
@pytest.mark.usefixtures("use_legacy_and_new_opmath")
class TestHamiltonianWorkflows:
"""Test that tapes ending with expectations
of Hamiltonians provide correct results and gradients"""
@pytest.fixture
- def cost_fn(self, execute_kwargs, shots, device):
+ def cost_fn(self, execute_kwargs, shots, device_name, seed):
"""Cost function for gradient tests"""
+ device = get_device(device_name, seed)
+
def _cost_fn(weights, coeffs1, coeffs2):
obs1 = [qml.PauliZ(0), qml.PauliZ(0) @ qml.PauliX(1), qml.PauliY(0)]
H1 = qml.Hamiltonian(coeffs1, obs1)
diff --git a/tests/interfaces/test_jax_jit_qnode.py b/tests/interfaces/test_jax_jit_qnode.py
index ea30329106c..fdb4094160d 100644
--- a/tests/interfaces/test_jax_jit_qnode.py
+++ b/tests/interfaces/test_jax_jit_qnode.py
@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Integration tests for using the JAX-JIT interface with a QNode"""
-import copy
# pylint: disable=too-many-arguments,too-few-public-methods,protected-access
from functools import partial
@@ -25,27 +24,33 @@
from pennylane import qnode
from pennylane.devices import DefaultQubit
-# device, diff_method, grad_on_execution, device_vjp
-qubit_device_and_diff_method = [
- [DefaultQubit(seed=123), "backprop", True, False],
- [DefaultQubit(seed=123), "finite-diff", False, False],
- [DefaultQubit(seed=123), "parameter-shift", False, False],
- [DefaultQubit(seed=123), "adjoint", True, False],
- [DefaultQubit(seed=123), "adjoint", True, True],
- [ParamShiftDerivativesDevice(seed=123), "device", False, True],
- [DefaultQubit(seed=123), "adjoint", False, False],
- [DefaultQubit(seed=123), "spsa", False, False],
- [DefaultQubit(seed=123), "hadamard", False, False],
- [qml.device("lightning.qubit", wires=5), "adjoint", False, True],
- [qml.device("lightning.qubit", wires=5), "adjoint", True, False],
- [qml.device("lightning.qubit", wires=5), "adjoint", False, False],
- [qml.device("lightning.qubit", wires=5), "adjoint", True, True],
- [qml.device("lightning.qubit", wires=5), "parameter-shift", False, False],
- [qml.device("reference.qubit", seed=123), "parameter-shift", False, False],
+
+def get_device(device_name, wires, seed):
+ if device_name == "param_shift.qubit":
+ return ParamShiftDerivativesDevice(seed=seed)
+ if device_name == "lightning.qubit":
+ return qml.device("lightning.qubit", wires=wires)
+ return qml.device(device_name, seed=seed)
+
+
+# device_name, diff_method, grad_on_execution, device_vjp
+device_test_cases = [
+ ("default.qubit", "backprop", True, False),
+ ("default.qubit", "finite-diff", False, False),
+ ("default.qubit", "parameter-shift", False, False),
+ ("default.qubit", "adjoint", True, False),
+ ("default.qubit", "adjoint", True, True),
+ ("default.qubit", "adjoint", False, False),
+ ("default.qubit", "spsa", False, False),
+ ("default.qubit", "hadamard", False, False),
+ ("param_shift.qubit", "device", False, True),
+ ("lightning.qubit", "adjoint", False, True),
+ ("lightning.qubit", "adjoint", True, True),
+ ("lightning.qubit", "adjoint", False, False),
+ ("lightning.qubit", "adjoint", True, False),
+ ("lightning.qubit", "parameter-shift", False, False),
+ ("reference.qubit", "parameter-shift", False, False),
]
-interface_and_qubit_device_and_diff_method = [
- ["auto"] + inner_list for inner_list in qubit_device_and_diff_method
-] + [["jax-jit"] + inner_list for inner_list in qubit_device_and_diff_method]
pytestmark = pytest.mark.jax
@@ -53,25 +58,28 @@
jax.config.update("jax_enable_x64", True)
TOL_FOR_SPSA = 1.0
-SEED_FOR_SPSA = 32651
H_FOR_SPSA = 0.05
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution,device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution,device_vjp",
+ device_test_cases,
)
class TestQNode:
"""Test that using the QNode with JAX integrates with the PennyLane
stack"""
def test_execution_with_interface(
- self, dev, diff_method, grad_on_execution, interface, device_vjp
+ self, interface, dev_name, diff_method, grad_on_execution, device_vjp, seed
):
"""Test execution works with the interface"""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention")
+ dev = get_device(dev_name, wires=1, seed=seed)
+
@qnode(
dev,
interface=interface,
@@ -98,10 +106,11 @@ def circuit(a):
assert grad.shape == ()
def test_changing_trainability(
- self, dev, diff_method, grad_on_execution, interface, device_vjp, tol
+ self, interface, dev_name, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Test changing the trainability of parameters changes the
number of differentiation requests made"""
+
if diff_method != "parameter-shift":
pytest.skip("Test only supports parameter-shift")
@@ -109,7 +118,7 @@ def test_changing_trainability(
b = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method="parameter-shift",
grad_on_execution=grad_on_execution,
@@ -146,17 +155,20 @@ def circuit(a, b):
circuit(a, b)
assert circuit.qtape.trainable_params == [1]
- def test_classical_processing(self, dev, diff_method, grad_on_execution, device_vjp, interface):
+ def test_classical_processing(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, seed
+ ):
"""Test classical processing within the quantum tape"""
+
+ if dev_name == "param_shift.qubit":
+ pytest.xfail("gradient transforms have a different vjp shape convention.")
+
a = jax.numpy.array(0.1)
b = jax.numpy.array(0.2)
c = jax.numpy.array(0.3)
- if dev.name == "param_shift.qubit":
- pytest.xfail("gradient transforms have a different vjp shape convention.")
-
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -176,19 +188,19 @@ def circuit(a, b, c):
assert len(res) == 2
def test_matrix_parameter(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test that the jax interface works correctly
with a matrix parameter"""
- if dev.name == "param_shift.qubit":
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
U = jax.numpy.array([[0, 1], [1, 0]])
a = jax.numpy.array(0.1)
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -206,17 +218,17 @@ def circuit(U, a):
assert circuit.qtape.trainable_params == [1]
def test_differentiable_expand(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test that operation and nested tape expansion
is differentiable"""
- if dev.name == "param_shift.qubit":
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
gradient_kwargs = {}
if diff_method == "spsa":
- gradient_kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ gradient_kwargs["sampler_rng"] = np.random.default_rng(seed)
gradient_kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -233,7 +245,7 @@ def decomposition(self):
p = jax.numpy.array([0.1, 0.2, 0.3])
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -264,14 +276,18 @@ def circuit(a, p):
)
assert np.allclose(res, expected, atol=tol, rtol=0)
- def test_jacobian_options(self, dev, diff_method, grad_on_execution, device_vjp, interface):
+ def test_jacobian_options(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, seed
+ ):
"""Test setting jacobian options"""
+
if diff_method != "finite-diff":
pytest.skip("Test only applies to finite diff.")
+
a = np.array([0.1, 0.2], requires_grad=True)
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method="finite-diff",
h=1e-8,
@@ -291,26 +307,30 @@ def circuit(a):
jax.jit(jax.jacobian(circuit))(a)
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution, device_vjp",
+ device_test_cases,
)
class TestVectorValuedQNode:
"""Test that using vector-valued QNodes with JAX integrate with the
PennyLane stack"""
def test_diff_expval_expval(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test jacobian calculation"""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if dev_name == "lightning.qubit":
pytest.xfail("lightning does not support device vjps with jax jacobians.")
+
gradient_kwargs = {}
if diff_method == "spsa":
- gradient_kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ gradient_kwargs["sampler_rng"] = np.random.default_rng(seed)
gradient_kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -318,7 +338,7 @@ def test_diff_expval_expval(
b = np.array(0.2, requires_grad=True)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -365,17 +385,20 @@ def circuit(a, b):
assert np.allclose(res[1][1], expected[1][1], atol=tol, rtol=0)
def test_jacobian_no_evaluate(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test jacobian calculation when no prior circuit evaluation has been performed"""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if dev_name == "lightning.qubit":
pytest.xfail("lightning does not support device vjps with jax jacobians.")
+
gradient_kwargs = {}
if diff_method == "spsa":
- gradient_kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ gradient_kwargs["sampler_rng"] = np.random.default_rng(seed)
gradient_kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -383,7 +406,7 @@ def test_jacobian_no_evaluate(
b = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -429,17 +452,20 @@ def circuit(a, b):
assert np.allclose(r, e, atol=tol, rtol=0)
def test_diff_single_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with a single prob output"""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if dev_name == "lightning.qubit":
pytest.xfail("lightning does not support device vjps with jax jacobians.")
+
gradient_kwargs = {}
if diff_method == "spsa":
- gradient_kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ gradient_kwargs["sampler_rng"] = np.random.default_rng(seed)
gradient_kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -447,7 +473,7 @@ def test_diff_single_probs(
y = jax.numpy.array(-0.654)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -482,17 +508,20 @@ def circuit(x, y):
assert np.allclose(res[1], expected.T[1], atol=tol, rtol=0)
def test_diff_multi_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with multiple prob outputs"""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if dev_name == "lightning.qubit":
pytest.xfail("lightning does not support device vjps with jax jacobians.")
+
gradient_kwargs = {}
if diff_method == "spsa":
- gradient_kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ gradient_kwargs["sampler_rng"] = np.random.default_rng(seed)
gradient_kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -500,7 +529,7 @@ def test_diff_multi_probs(
y = jax.numpy.array(-0.654)
@qnode(
- dev,
+ get_device(dev_name, wires=3, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -568,17 +597,20 @@ def circuit(x, y):
assert np.allclose(jac[1][1], expected_1[1], atol=tol, rtol=0)
def test_diff_expval_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if dev_name == "lightning.qubit":
pytest.xfail("lightning does not support device vjps with jax jacobians.")
+
gradient_kwargs = {}
if diff_method == "spsa":
- gradient_kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ gradient_kwargs["sampler_rng"] = np.random.default_rng(seed)
gradient_kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -586,7 +618,7 @@ def test_diff_expval_probs(
y = jax.numpy.array(-0.654)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -644,24 +676,27 @@ def circuit(x, y):
assert np.allclose(jac[1][1], expected[1][1], atol=tol, rtol=0)
def test_diff_expval_probs_sub_argnums(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Tests correct output shape and evaluation for a tape with prob and expval outputs with less
trainable parameters (argnums) than parameters."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if dev_name == "lightning.qubit":
pytest.xfail("lightning does not support device vjps with jax jacobians.")
+
kwargs = {}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
x = jax.numpy.array(0.543)
y = jax.numpy.array(-0.654)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -698,18 +733,23 @@ def circuit(x, y):
assert jac[1][0].shape == (2,)
assert np.allclose(jac[1][0], expected[1][0], atol=tol, rtol=0)
- def test_diff_var_probs(self, dev, diff_method, grad_on_execution, device_vjp, interface, tol):
+ def test_diff_var_probs(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
+ ):
"""Tests correct output shape and evaluation for a tape
with prob and variance outputs"""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if dev_name == "lightning.qubit":
pytest.xfail("lightning does not support device vjps with jax jacobians.")
+
gradient_kwargs = {}
if diff_method == "hadamard":
pytest.skip("Hadamard does not support var")
elif diff_method == "spsa":
- gradient_kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ gradient_kwargs["sampler_rng"] = np.random.default_rng(seed)
gradient_kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -717,7 +757,7 @@ def test_diff_var_probs(self, dev, diff_method, grad_on_execution, device_vjp, i
y = jax.numpy.array(-0.654)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -864,10 +904,10 @@ def cost_fn(a, b):
assert spy.call_args[1]["gradient_fn"] == "backprop"
@pytest.mark.parametrize("shots", [(10000, 10000), (10000, 10005)])
- def test_shot_vectors_single_measurements(self, interface, shots):
+ def test_shot_vectors_single_measurements(self, interface, shots, seed):
"""Test jax-jit can work with shot vectors."""
- dev = qml.device("default.qubit", shots=shots, seed=4747)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
@jax.jit
@qml.qnode(dev, interface=interface, diff_method="parameter-shift")
@@ -877,20 +917,19 @@ def circuit(x):
res = circuit(0.5)
expected = 1 - np.cos(0.5) ** 2
- assert qml.math.allclose(res[0], expected, atol=1e-2)
- assert qml.math.allclose(res[1], expected, atol=3e-2)
+ assert qml.math.allclose(res[0], expected, atol=5e-2)
+ assert qml.math.allclose(res[1], expected, rtol=5e-2)
g = jax.jacobian(circuit)(0.5)
-
expected_g = 2 * np.cos(0.5) * np.sin(0.5)
- assert qml.math.allclose(g[0], expected_g, atol=2e-2)
- assert qml.math.allclose(g[1], expected_g, atol=2e-2)
+ assert qml.math.allclose(g[0], expected_g, rtol=5e-2)
+ assert qml.math.allclose(g[1], expected_g, rtol=5e-2)
@pytest.mark.parametrize("shots", [(10000, 10000), (10000, 10005)])
- def test_shot_vectors_multiple_measurements(self, interface, shots):
+ def test_shot_vectors_multiple_measurements(self, interface, shots, seed):
"""Test jax-jit can work with shot vectors."""
- dev = qml.device("default.qubit", shots=shots, seed=987548)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
@jax.jit
@qml.qnode(dev, interface=interface, diff_method="parameter-shift")
@@ -899,23 +938,27 @@ def circuit(x):
return qml.expval(qml.PauliZ(0)), qml.probs(wires=0)
res = circuit(0.5)
- assert qml.math.allclose(res[0][0], np.cos(0.5), atol=5e-3)
- assert qml.math.allclose(res[1][0], np.cos(0.5), atol=5e-3)
+ assert qml.math.allclose(res[0][0], np.cos(0.5), rtol=5e-2)
+ assert qml.math.allclose(res[1][0], np.cos(0.5), rtol=5e-2)
+
expected_probs = np.array([np.cos(0.25) ** 2, np.sin(0.25) ** 2])
- assert qml.math.allclose(res[0][1], expected_probs, atol=5e-3)
- assert qml.math.allclose(res[1][1], expected_probs, atol=5e-3)
+ assert qml.math.allclose(res[0][1], expected_probs, rtol=5e-2)
+ assert qml.math.allclose(res[1][1][0], expected_probs[0], rtol=5e-2)
+ assert qml.math.allclose(res[1][1][1], expected_probs[1], atol=5e-3)
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution, device_vjp",
+ device_test_cases,
)
class TestQubitIntegration:
"""Tests that ensure various qubit circuits integrate correctly"""
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
- def test_sampling(self, dev, diff_method, grad_on_execution, device_vjp, interface):
+ def test_sampling(self, dev_name, diff_method, grad_on_execution, device_vjp, interface, seed):
"""Test sampling works as expected"""
+
if grad_on_execution:
pytest.skip("Sampling not possible with forward grad_on_execution differentiation.")
@@ -923,7 +966,7 @@ def test_sampling(self, dev, diff_method, grad_on_execution, device_vjp, interfa
pytest.skip("Adjoint warns with finite shots")
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -944,19 +987,17 @@ def circuit():
assert res[1].shape == (10,)
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
- def test_counts(self, dev, diff_method, grad_on_execution, device_vjp, interface):
+ def test_counts(self, dev_name, diff_method, grad_on_execution, device_vjp, interface, seed):
"""Test counts works as expected"""
+
if grad_on_execution:
pytest.skip("Sampling not possible with forward grad_on_execution differentiation.")
if diff_method == "adjoint":
pytest.skip("Adjoint warns with finite shots")
- if isinstance(dev, qml.devices.DefaultQubit):
- dev._rng = np.random.default_rng(987654321)
-
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -982,15 +1023,20 @@ def circuit():
assert isinstance(res[1], dict)
assert len(res[1]) == 2
- def test_chained_qnodes(self, dev, diff_method, grad_on_execution, device_vjp, interface):
+ def test_chained_qnodes(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, seed
+ ):
"""Test that the gradient of chained QNodes works without error"""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
class Template(qml.templates.StronglyEntanglingLayers):
def decomposition(self):
return [qml.templates.StronglyEntanglingLayers(*self.parameters, self.wires)]
+ dev = get_device(dev_name, wires=2, seed=seed)
+
@qnode(
dev,
interface=interface,
@@ -1034,19 +1080,21 @@ def cost(weights):
assert len(res) == 2
def test_postselection_differentiation(
- self, dev, diff_method, grad_on_execution, device_vjp, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, seed
):
"""Test that when postselecting with default.qubit, differentiation works correctly."""
if diff_method in ["adjoint", "spsa", "hadamard"]:
pytest.skip("Diff method does not support postselection.")
- if dev.name == "param_shift.qubit":
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention")
- elif dev.name == "lightning.qubit":
+ elif dev_name == "lightning.qubit":
pytest.xfail("lightning qubit does not support postselection.")
- if dev.name == "reference.qubit":
+ if dev_name == "reference.qubit":
pytest.skip("reference.qubit does not support postselection.")
+ dev = get_device(dev_name, wires=2, seed=seed)
+
@qml.qnode(
dev, diff_method=diff_method, interface=interface, grad_on_execution=grad_on_execution
)
@@ -1079,26 +1127,29 @@ def expected_circuit(theta):
assert np.allclose(gradient, [0.0, exp_theta_grad])
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution,device_vjp",
+ device_test_cases,
)
class TestQubitIntegrationHigherOrder:
"""Tests that ensure various qubit circuits integrate correctly when computing higher-order derivatives"""
def test_second_derivative(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test second derivative calculation of a scalar-valued QNode"""
gradient_kwargs = {}
if diff_method in {"adjoint", "device"}:
pytest.skip("Adjoint does not support second derivatives.")
elif diff_method == "spsa":
- gradient_kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ gradient_kwargs["sampler_rng"] = np.random.default_rng(seed)
gradient_kwargs["num_directions"] = 20
gradient_kwargs["h"] = H_FOR_SPSA
tol = TOL_FOR_SPSA
+ dev = get_device(dev_name, wires=1, seed=seed)
+
@qnode(
dev,
diff_method=diff_method,
@@ -1135,7 +1186,9 @@ def circuit(x):
else:
assert np.allclose(g2, expected_g2, atol=tol, rtol=0)
- def test_hessian(self, dev, diff_method, grad_on_execution, device_vjp, interface, tol):
+ def test_hessian(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
+ ):
"""Test hessian calculation of a scalar-valued QNode"""
gradient_kwargs = {}
if diff_method in {"adjoint", "device"}:
@@ -1144,10 +1197,12 @@ def test_hessian(self, dev, diff_method, grad_on_execution, device_vjp, interfac
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 40,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
+ dev = get_device(dev_name, wires=1, seed=seed)
+
@qnode(
dev,
diff_method=diff_method,
@@ -1188,7 +1243,7 @@ def circuit(x):
assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
def test_hessian_vector_valued(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test hessian calculation of a vector-valued QNode"""
gradient_kwargs = {}
@@ -1198,12 +1253,12 @@ def test_hessian_vector_valued(
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1251,7 +1306,7 @@ def circuit(x):
assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
def test_hessian_vector_valued_postprocessing(
- self, dev, diff_method, interface, device_vjp, grad_on_execution, tol
+ self, dev_name, diff_method, interface, device_vjp, grad_on_execution, tol, seed
):
"""Test hessian calculation of a vector valued QNode with post-processing"""
gradient_kwargs = {}
@@ -1261,12 +1316,12 @@ def test_hessian_vector_valued_postprocessing(
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1317,7 +1372,7 @@ def cost_fn(x):
assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
def test_hessian_vector_valued_separate_args(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test hessian calculation of a vector valued QNode that has separate input arguments"""
gradient_kwargs = {}
@@ -1327,12 +1382,12 @@ def test_hessian_vector_valued_separate_args(
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1382,17 +1437,18 @@ def circuit(a, b):
else:
assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
- def test_state(self, dev, diff_method, grad_on_execution, device_vjp, interface, tol):
+ def test_state(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
+ ):
"""Test that the state can be returned and differentiated"""
- if dev.name == "lightning.qubit" and diff_method == "adjoint":
+ if dev_name == "lightning.qubit" and diff_method == "adjoint":
pytest.xfail("lightning.qubit does not support adjoint with the state.")
+ dev = get_device(dev_name, wires=2, seed=seed)
+
x = jax.numpy.array(0.543)
y = jax.numpy.array(-0.654)
- if not dev.wires:
- dev = copy.copy(dev)
- dev._wires = qml.wires.Wires([0, 1]) # pylint:disable=protected-access
@qnode(
dev,
@@ -1424,27 +1480,27 @@ def cost_fn(x, y):
@pytest.mark.parametrize("state", [[1], [0, 1]]) # Basis state and state vector
def test_projector(
- self, state, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, state, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test that the variance of a projector is correctly returned"""
gradient_kwargs = {}
- if dev.name == "param_shift.qubit":
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
if diff_method == "adjoint":
pytest.skip("Adjoint does not support projectors")
elif diff_method == "hadamard":
pytest.skip("Hadamard does not support var")
elif diff_method == "spsa":
- gradient_kwargs = {"h": H_FOR_SPSA, "sampler_rng": np.random.default_rng(SEED_FOR_SPSA)}
+ gradient_kwargs = {"h": H_FOR_SPSA, "sampler_rng": np.random.default_rng(seed)}
tol = TOL_FOR_SPSA
- if dev.name == "reference.qubit":
+ if dev_name == "reference.qubit":
pytest.xfail("diagonalize_measurements do not support projectors (sc-72911)")
P = jax.numpy.array(state)
x, y = 0.765, -0.654
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1471,9 +1527,10 @@ def circuit(x, y):
assert np.allclose(res, expected, atol=tol, rtol=0)
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution, device_vjp",
+ device_test_cases,
)
class TestTapeExpansion:
"""Test that tape expansion within the QNode integrates correctly
@@ -1481,10 +1538,11 @@ class TestTapeExpansion:
@pytest.mark.parametrize("max_diff", [1, 2])
def test_gradient_expansion_trainable_only(
- self, dev, diff_method, grad_on_execution, device_vjp, max_diff, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, max_diff, interface, seed
):
"""Test that a *supported* operation with no gradient recipe is only
expanded for parameter-shift and finite-differences when it is trainable."""
+
if diff_method not in ("parameter-shift", "finite-diff", "spsa"):
pytest.skip("Only supports gradient transforms")
@@ -1495,7 +1553,7 @@ def decomposition(self):
return [qml.RY(3 * self.data[0], wires=self.wires)]
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
grad_on_execution=grad_on_execution,
max_diff=max_diff,
@@ -1516,18 +1574,28 @@ def circuit(x, y):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_expansion_analytic(
- self, dev, diff_method, grad_on_execution, max_diff, device_vjp, interface, mocker, tol
+ self,
+ dev_name,
+ diff_method,
+ grad_on_execution,
+ max_diff,
+ device_vjp,
+ interface,
+ mocker,
+ tol,
+ seed,
):
"""Test that the Hamiltonian is not expanded if there
are non-commuting groups and the number of shots is None
and the first and second order gradients are correctly evaluated"""
+
gradient_kwargs = {}
- if dev.name == "reference.qubit":
+ if dev_name == "reference.qubit":
pytest.skip(
"Cannot add transform to the transform program in preprocessing"
"when using mocker.spy on it."
)
- if dev.name == "param_shift.qubit":
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradients transforms have a different vjp shape convention.")
if diff_method == "adjoint":
pytest.skip("The adjoint method does not yet support Hamiltonians")
@@ -1537,7 +1605,7 @@ def test_hamiltonian_expansion_analytic(
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
@@ -1546,7 +1614,7 @@ def test_hamiltonian_expansion_analytic(
@jax.jit
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1596,27 +1664,27 @@ def circuit(data, weights, coeffs):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_finite_shots(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, max_diff
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, max_diff, seed
):
"""Test that the Hamiltonian is correctly measured if there
are non-commuting groups and the number of shots is finite
and the first and second order gradients are correctly evaluated"""
gradient_kwargs = {}
tol = 0.3
- if dev.name == "param_shift.qubit":
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
if diff_method in ("adjoint", "backprop", "finite-diff"):
pytest.skip("The adjoint and backprop methods do not yet support sampling")
elif diff_method == "hadamard":
pytest.skip("The Hadamard method does not yet support Hamiltonians")
elif diff_method == "spsa":
- gradient_kwargs = {"sampler_rng": SEED_FOR_SPSA, "h": H_FOR_SPSA, "num_directions": 20}
+ gradient_kwargs = {"sampler_rng": seed, "h": H_FOR_SPSA, "num_directions": 20}
tol = TOL_FOR_SPSA
obs = [qml.PauliX(0), qml.PauliX(0) @ qml.PauliZ(1), qml.PauliZ(0) @ qml.PauliZ(1)]
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1667,12 +1735,12 @@ def circuit(data, weights, coeffs):
# assert np.allclose(grad2_w_c, expected, atol=tol)
def test_vmap_compared_param_broadcasting(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test that jax.vmap works just as well as parameter-broadcasting with JAX JIT on the forward pass when
vectorized=True is specified for the callback when caching is disabled."""
if (
- dev.name == "default.qubit"
+ dev_name == "default.qubit"
and diff_method == "adjoint"
and grad_on_execution
and not device_vjp
@@ -1685,7 +1753,7 @@ def test_vmap_compared_param_broadcasting(
def minimal_circ(params):
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1705,13 +1773,13 @@ def _measure_operator():
assert np.allclose(res1, res2, tol)
def test_vmap_compared_param_broadcasting_multi_output(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test that jax.vmap works just as well as parameter-broadcasting with JAX JIT on the forward pass when
vectorized=True is specified for the callback when caching is disabled and when multiple output values
are returned."""
if (
- dev.name == "default.qubit"
+ dev_name == "default.qubit"
and diff_method == "adjoint"
and grad_on_execution
and not device_vjp
@@ -1724,7 +1792,7 @@ def test_vmap_compared_param_broadcasting_multi_output(
def minimal_circ(params):
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1745,19 +1813,19 @@ def _measure_operator():
assert np.allclose(res2, vres2, tol)
def test_vmap_compared_param_broadcasting_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test that jax.vmap works just as well as parameter-broadcasting with JAX JIT on the forward pass when
vectorized=True is specified for the callback when caching is disabled and when multiple output values
are returned."""
if (
- dev.name == "default.qubit"
+ dev_name == "default.qubit"
and diff_method == "adjoint"
and grad_on_execution
and not device_vjp
):
pytest.xfail("adjoint is incompatible with parameter broadcasting.")
- elif dev.name == "lightning.qubit" and diff_method == "adjoint":
+ elif dev_name == "lightning.qubit" and diff_method == "adjoint":
pytest.xfail("lightning adjoign cannot differentiate probabilities.")
interface = "jax-jit"
@@ -1766,7 +1834,7 @@ def test_vmap_compared_param_broadcasting_probs(
def minimal_circ(params):
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1790,32 +1858,33 @@ def _measure_operator():
jacobian_fn = [jax.jacobian, jax.jacrev, jax.jacfwd]
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize("jacobian", jacobian_fn)
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution,device_vjp",
+ device_test_cases,
)
class TestJIT:
"""Test JAX JIT integration with the QNode and automatic resolution of the
correct JAX interface variant."""
def test_gradient(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, tol, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, tol, interface, seed
):
"""Test derivative calculation of a scalar valued QNode"""
gradient_kwargs = {}
- if dev.name == "param_shift.qubit":
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
if device_vjp and jacobian == jax.jacfwd:
pytest.skip("device vjps not compatible with forward diff.")
elif diff_method == "spsa":
- gradient_kwargs = {"h": H_FOR_SPSA, "sampler_rng": np.random.default_rng(SEED_FOR_SPSA)}
+ gradient_kwargs = {"h": H_FOR_SPSA, "sampler_rng": np.random.default_rng(seed)}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1844,7 +1913,7 @@ def circuit(x):
)
@pytest.mark.parametrize("shots", [10, 1000])
def test_hermitian(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, jacobian, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, jacobian, interface, seed
):
"""Test that the jax device works with qml.Hermitian and jitting even
when shots>0.
@@ -1853,7 +1922,7 @@ def test_hermitian(
to different reasons, hence the parametrization in the test.
"""
# pylint: disable=unused-argument
- if dev.name == "reference.qubit":
+ if dev_name == "reference.qubit":
pytest.xfail("diagonalize_measurements do not support Hermitians (sc-72911)")
if diff_method == "backprop":
@@ -1865,7 +1934,7 @@ def test_hermitian(
projector = np.array(qml.matrix(qml.PauliZ(0) @ qml.PauliZ(1)))
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1882,7 +1951,7 @@ def circ(projector):
)
@pytest.mark.parametrize("shots", [10, 1000])
def test_probs_obs_none(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, jacobian, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, jacobian, interface, seed
):
"""Test that the jax device works with qml.probs, a MeasurementProcess
that has obs=None even when shots>0."""
@@ -1891,7 +1960,7 @@ def test_probs_obs_none(
pytest.skip("Backpropagation is unsupported if shots > 0.")
@qml.qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1902,17 +1971,16 @@ def circuit():
assert jax.numpy.allclose(circuit(), jax.numpy.array([1.0, 0.0]))
- # @pytest.mark.xfail(
- # reason="Non-trainable parameters are not being correctly unwrapped by the interface"
- # )
def test_gradient_subset(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, tol, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, tol, interface, seed
):
"""Test derivative calculation of a scalar valued QNode with respect
to a subset of arguments"""
+
if diff_method == "spsa" and not grad_on_execution and not device_vjp:
pytest.xfail(reason="incorrect jacobian results")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
if diff_method == "device" and not grad_on_execution and device_vjp:
@@ -1925,7 +1993,7 @@ def test_gradient_subset(
b = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1946,23 +2014,28 @@ def circuit(a, b, c):
assert np.allclose(g, expected_g, atol=tol, rtol=0)
def test_gradient_scalar_cost_vector_valued_qnode(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, tol, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, tol, interface, seed
):
"""Test derivative calculation of a scalar valued cost function that
uses the output of a vector-valued QNode"""
+
gradient_kwargs = {}
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
elif jacobian == jax.jacfwd and device_vjp:
pytest.skip("device vjps are not compatible with forward differentiation.")
+
elif diff_method == "spsa":
- gradient_kwargs = {"h": H_FOR_SPSA, "sampler_rng": np.random.default_rng(SEED_FOR_SPSA)}
+ gradient_kwargs = {"h": H_FOR_SPSA, "sampler_rng": np.random.default_rng(seed)}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -2001,20 +2074,22 @@ def cost(x, y, idx):
# pylint: disable=unused-argument
def test_matrix_parameter(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, tol, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, tol, interface, seed
):
- """Test that the JAX-JIT interface works correctly with a matrix
- parameter"""
- if dev.name == "param_shift.qubit":
+ """Test that the JAX-JIT interface works correctly with a matrix parameter"""
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("device vjps are not compatible with forward differentiation.")
# pylint: disable=unused-argument
@qml.qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -2037,29 +2112,34 @@ def circ(p, U):
@pytest.mark.parametrize("shots", [None, 10000])
@pytest.mark.parametrize("jacobian", jacobian_fn)
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution, device_vjp",
+ device_test_cases,
)
class TestReturn:
"""Class to test the shape of the Grad/Jacobian with different return types."""
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_grad_single_measurement_param(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""For one measurement and one param, the gradient is a float."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2079,20 +2159,24 @@ def circuit(a):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_grad_single_measurement_multiple_param(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""For one measurement and multiple param, the gradient is a tuple of arrays."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2117,20 +2201,24 @@ def circuit(a, b):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_grad_single_measurement_multiple_param_array(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""For one measurement and multiple param as a single array params, the gradient is an array."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2150,21 +2238,25 @@ def circuit(a):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_single_measurement_param_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
- """For a multi dimensional measurement (probs), check that a single array is returned with the correct
- dimension"""
- if dev.name == "param_shift.qubit":
+ """For a multi-dimensional measurement (probs), check that a single array is returned
+ with the correct dimension"""
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2184,21 +2276,25 @@ def circuit(a):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_single_measurement_probs_multiple_param(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
- """For a multi dimensional measurement (probs), check that a single tuple is returned containing arrays with
- the correct dimension"""
- if dev.name == "param_shift.qubit":
+ """For a multi-dimensional measurement (probs), check that a single tuple is returned
+ containing arrays with the correct dimension"""
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2224,21 +2320,25 @@ def circuit(a, b):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_single_measurement_probs_multiple_param_single_array(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
- """For a multi dimensional measurement (probs), check that a single tuple is returned containing arrays with
- the correct dimension"""
- if dev.name == "param_shift.qubit":
+ """For a multi-dimensional measurement (probs), check that a single tuple is returned
+ containing arrays with the correct dimension"""
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2257,15 +2357,19 @@ def circuit(a):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_expval_expval_multiple_params(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The jacobian of multiple measurements with multiple params return a tuple of arrays."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@@ -2273,7 +2377,7 @@ def test_jacobian_expval_expval_multiple_params(
par_1 = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2307,20 +2411,24 @@ def circuit(x, y):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_expval_expval_multiple_params_array(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2346,17 +2454,22 @@ def circuit(a):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_var_var_multiple_params(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The jacobian of multiple measurements with multiple params return a tuple of arrays."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
+
elif diff_method == "hadamard":
pytest.skip("Test does not supports hadamard because of var.")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
+
if diff_method == "adjoint":
pytest.skip("adjoint supports either all expvals or only diagonal measurements")
@@ -2364,7 +2477,7 @@ def test_jacobian_var_var_multiple_params(
par_1 = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2399,22 +2512,27 @@ def circuit(x, y):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_var_var_multiple_params_array(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
+
elif diff_method == "hadamard":
pytest.skip("Test does not supports hadamard because of var.")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
+
if diff_method == "adjoint":
pytest.skip("adjoint supports either all expvals or only diagonal measurements")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2440,20 +2558,24 @@ def circuit(a):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_multiple_measurement_single_param(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The jacobian of multiple measurements with a single params return an array."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if device_vjp and jacobian == jax.jacfwd:
pytest.skip("device vjp not compatible with forward differentiation.")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2479,20 +2601,24 @@ def circuit(a):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_multiple_measurement_multiple_param(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The jacobian of multiple measurements with a multiple params return a tuple of arrays."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2527,20 +2653,24 @@ def circuit(a, b):
@pytest.mark.xfail(reason="'shots' cannot be a static_argname for 'jit' in JAX 0.4.28")
def test_jacobian_multiple_measurement_multiple_param_array(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transforms have a different vjp shape convention.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
+
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2573,15 +2703,16 @@ def circuit(a):
@pytest.mark.parametrize("hessian", hessian_fn)
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution, device_vjp",
+ device_test_cases,
)
class TestReturnHessian:
"""Class to test the shape of the Hessian with different return types."""
def test_hessian_expval_multiple_params(
- self, dev, diff_method, hessian, device_vjp, grad_on_execution, interface
+ self, dev_name, diff_method, hessian, device_vjp, grad_on_execution, interface, seed
):
"""The hessian of single a measurement with multiple params return a tuple of arrays."""
if diff_method in {"adjoint", "device"}:
@@ -2591,7 +2722,7 @@ def test_hessian_expval_multiple_params(
par_1 = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2624,7 +2755,7 @@ def circuit(x, y):
assert hess[1][1].shape == ()
def test_hessian_expval_multiple_param_array(
- self, dev, diff_method, hessian, grad_on_execution, device_vjp, interface
+ self, dev_name, diff_method, hessian, grad_on_execution, device_vjp, interface, seed
):
"""The hessian of single measurement with a multiple params array return a single array."""
@@ -2634,7 +2765,7 @@ def test_hessian_expval_multiple_param_array(
params = jax.numpy.array([0.1, 0.2], dtype=jax.numpy.float64)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2653,7 +2784,7 @@ def circuit(x):
assert hess.shape == (2, 2)
def test_hessian_var_multiple_params(
- self, dev, diff_method, hessian, device_vjp, grad_on_execution, interface
+ self, dev_name, diff_method, hessian, device_vjp, grad_on_execution, interface, seed
):
"""The hessian of single a measurement with multiple params return a tuple of arrays."""
if diff_method in {"adjoint", "device"}:
@@ -2665,7 +2796,7 @@ def test_hessian_var_multiple_params(
par_1 = jax.numpy.array(0.2, dtype=jax.numpy.float64)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2698,18 +2829,20 @@ def circuit(x, y):
assert hess[1][1].shape == ()
def test_hessian_var_multiple_param_array(
- self, dev, diff_method, hessian, grad_on_execution, device_vjp, interface
+ self, dev_name, diff_method, hessian, grad_on_execution, device_vjp, interface, seed
):
"""The hessian of single measurement with a multiple params array return a single array."""
+
if diff_method in {"adjoint", "device"}:
pytest.skip("Test does not supports adjoint because second order diff.")
+
elif diff_method == "hadamard":
pytest.skip("Test does not supports hadamard because of var.")
params = jax.numpy.array([0.1, 0.2], dtype=jax.numpy.float64)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2728,11 +2861,13 @@ def circuit(x):
assert hess.shape == (2, 2)
def test_hessian_probs_expval_multiple_params(
- self, dev, diff_method, hessian, grad_on_execution, device_vjp, interface
+ self, dev_name, diff_method, hessian, grad_on_execution, device_vjp, interface, seed
):
"""The hessian of multiple measurements with multiple params return a tuple of arrays."""
+
if diff_method in {"adjoint", "device"}:
pytest.skip("Test does not supports adjoint because second order diff.")
+
elif diff_method == "hadamard":
pytest.skip("Test does not supports hadamard because of non commuting obs.")
@@ -2740,7 +2875,7 @@ def test_hessian_probs_expval_multiple_params(
par_1 = jax.numpy.array(0.2, dtype=jax.numpy.float64)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2772,7 +2907,7 @@ def circuit(x, y):
assert h_comp.shape == (2,)
def test_hessian_probs_expval_multiple_param_array(
- self, dev, diff_method, hessian, grad_on_execution, device_vjp, interface
+ self, dev_name, diff_method, hessian, grad_on_execution, device_vjp, interface, seed
):
"""The hessian of multiple measurements with a multiple param array return a single array."""
@@ -2784,7 +2919,7 @@ def test_hessian_probs_expval_multiple_param_array(
params = jax.numpy.array([0.1, 0.2], dtype=jax.numpy.float64)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2808,7 +2943,7 @@ def circuit(x):
assert hess[1].shape == (2, 2, 2)
def test_hessian_probs_var_multiple_params(
- self, dev, diff_method, hessian, grad_on_execution, device_vjp, interface
+ self, dev_name, diff_method, hessian, grad_on_execution, device_vjp, interface, seed
):
"""The hessian of multiple measurements with multiple params return a tuple of arrays."""
if diff_method in {"adjoint", "device"}:
@@ -2820,7 +2955,7 @@ def test_hessian_probs_var_multiple_params(
par_1 = jax.numpy.array(0.2, dtype=jax.numpy.float64)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2852,7 +2987,7 @@ def circuit(x, y):
assert h_comp.shape == (2,)
def test_hessian_probs_var_multiple_param_array(
- self, dev, diff_method, hessian, grad_on_execution, device_vjp, interface
+ self, dev_name, diff_method, hessian, grad_on_execution, device_vjp, interface, seed
):
"""The hessian of multiple measurements with a multiple param array return a single array."""
if diff_method in {"adjoint", "device"}:
@@ -2863,7 +2998,7 @@ def test_hessian_probs_var_multiple_param_array(
params = jax.numpy.array([0.1, 0.2], dtype=jax.numpy.float64)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2914,17 +3049,18 @@ def circuit(x):
@pytest.mark.parametrize("jit_inside", [True, False])
+@pytest.mark.parametrize("interface", ["auto", "jax-jit"])
@pytest.mark.parametrize("argnums", [0, 1, [0, 1]])
@pytest.mark.parametrize("jacobian", jacobian_fn)
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp",
- interface_and_qubit_device_and_diff_method,
+ "dev_name,diff_method,grad_on_execution, device_vjp",
+ device_test_cases,
)
class TestSubsetArgnums:
def test_single_measurement(
self,
interface,
- dev,
+ dev_name,
diff_method,
grad_on_execution,
device_vjp,
@@ -2932,21 +3068,22 @@ def test_single_measurement(
argnums,
jit_inside,
tol,
+ seed,
):
"""Test single measurement with different diff methods with argnums."""
kwargs = {}
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
- if dev.name == "param_shift.qubit":
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transform have a different vjp shape convention.")
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2981,7 +3118,7 @@ def circuit(a, b):
def test_multi_measurements(
self,
interface,
- dev,
+ dev_name,
diff_method,
grad_on_execution,
device_vjp,
@@ -2989,22 +3126,26 @@ def test_multi_measurements(
argnums,
jit_inside,
tol,
+ seed,
):
"""Test multiple measurements with different diff methods with argnums."""
+
if jacobian == jax.jacfwd and device_vjp:
pytest.skip("jacfwd is not compatible with device_vjp=True.")
- if "lightning" in dev.name:
+
+ if "lightning" in dev_name:
pytest.xfail("lightning device vjps are not compatible with jax jaocbians")
- if dev.name == "param_shift.qubit":
+
+ if dev_name == "param_shift.qubit":
pytest.xfail("gradient transform have a different vjp shape convention.")
kwargs = {}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
diff --git a/tests/interfaces/test_jax_qnode.py b/tests/interfaces/test_jax_qnode.py
index d536288fa4b..261a93a3e18 100644
--- a/tests/interfaces/test_jax_qnode.py
+++ b/tests/interfaces/test_jax_qnode.py
@@ -23,57 +23,57 @@
from pennylane import qnode
from pennylane.devices import DefaultQubit
-device_seed = 42
+
+def get_device(device_name, wires, seed):
+ if device_name == "lightning.qubit":
+ return qml.device("lightning.qubit", wires=wires)
+ return qml.device(device_name, seed=seed)
+
# device, diff_method, grad_on_execution, device_vjp
device_and_diff_method = [
- [DefaultQubit(seed=device_seed), "backprop", True, False],
- [DefaultQubit(seed=device_seed), "finite-diff", False, False],
- [DefaultQubit(seed=device_seed), "parameter-shift", False, False],
- [DefaultQubit(seed=device_seed), "adjoint", True, False],
- [DefaultQubit(seed=device_seed), "adjoint", False, False],
- [DefaultQubit(seed=device_seed), "adjoint", True, True],
- [DefaultQubit(seed=device_seed), "adjoint", False, True],
- [DefaultQubit(seed=device_seed), "spsa", False, False],
- [DefaultQubit(seed=device_seed), "hadamard", False, False],
- [qml.device("lightning.qubit", wires=5), "adjoint", False, True],
- [qml.device("lightning.qubit", wires=5), "adjoint", True, True],
- [qml.device("lightning.qubit", wires=5), "adjoint", False, False],
- [qml.device("lightning.qubit", wires=5), "adjoint", True, False],
- [qml.device("reference.qubit"), "parameter-shift", False, False],
+ ["default.qubit", "backprop", True, False],
+ ["default.qubit", "finite-diff", False, False],
+ ["default.qubit", "parameter-shift", False, False],
+ ["default.qubit", "adjoint", True, False],
+ ["default.qubit", "adjoint", False, False],
+ ["default.qubit", "adjoint", True, True],
+ ["default.qubit", "adjoint", False, True],
+ ["default.qubit", "spsa", False, False],
+ ["default.qubit", "hadamard", False, False],
+ ["lightning.qubit", "adjoint", False, True],
+ ["lightning.qubit", "adjoint", True, True],
+ ["lightning.qubit", "adjoint", False, False],
+ ["lightning.qubit", "adjoint", True, False],
+ ["reference.qubit", "parameter-shift", False, False],
]
-interface_and_device_and_diff_method = [
- ["auto"] + inner_list for inner_list in device_and_diff_method
-] + [["jax"] + inner_list for inner_list in device_and_diff_method]
-
-
pytestmark = pytest.mark.jax
jax = pytest.importorskip("jax")
jax.config.update("jax_enable_x64", True)
TOL_FOR_SPSA = 1.0
-SEED_FOR_SPSA = 32651
H_FOR_SPSA = 0.05
+@pytest.mark.parametrize("interface", ["auto", "jax"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution,device_vjp", interface_and_device_and_diff_method
+ "dev_name,diff_method,grad_on_execution,device_vjp", device_and_diff_method
)
class TestQNode:
"""Test that using the QNode with JAX integrates with the PennyLane
stack"""
def test_execution_with_interface(
- self, dev, diff_method, grad_on_execution, interface, device_vjp
+ self, dev_name, diff_method, grad_on_execution, interface, device_vjp, seed
):
"""Test execution works with the interface"""
if diff_method == "backprop":
pytest.skip("Test does not support backprop")
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -100,7 +100,7 @@ def circuit(a):
assert grad.shape == ()
def test_changing_trainability(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
): # pylint:disable=unused-argument
"""Test changing the trainability of parameters changes the
number of differentiation requests made"""
@@ -110,7 +110,11 @@ def test_changing_trainability(
a = jax.numpy.array(0.1)
b = jax.numpy.array(0.2)
- @qnode(dev, interface=interface, diff_method="parameter-shift")
+ @qnode(
+ get_device(dev_name, wires=2, seed=seed),
+ interface=interface,
+ diff_method="parameter-shift",
+ )
def circuit(a, b):
qml.RY(a, wires=0)
qml.RX(b, wires=1)
@@ -136,14 +140,16 @@ def circuit(a, b):
expected = [-np.sin(a) + np.sin(a) * np.sin(b)]
assert np.allclose(res, expected, atol=tol, rtol=0)
- def test_classical_processing(self, dev, diff_method, grad_on_execution, device_vjp, interface):
+ def test_classical_processing(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, seed
+ ):
"""Test classical processing within the quantum tape"""
a = jax.numpy.array(0.1)
b = jax.numpy.array(0.2)
c = jax.numpy.array(0.3)
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -163,7 +169,7 @@ def circuit(a, b, c):
assert len(res) == 2
def test_matrix_parameter(
- self, dev, diff_method, grad_on_execution, interface, device_vjp, tol
+ self, dev_name, diff_method, grad_on_execution, interface, device_vjp, tol, seed
):
"""Test that the jax interface works correctly
with a matrix parameter"""
@@ -171,7 +177,7 @@ def test_matrix_parameter(
a = jax.numpy.array(0.1)
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -189,7 +195,7 @@ def circuit(U, a):
assert circuit.qtape.trainable_params == [1]
def test_differentiable_expand(
- self, dev, diff_method, grad_on_execution, interface, device_vjp, tol
+ self, dev_name, diff_method, grad_on_execution, interface, device_vjp, tol, seed
):
"""Test that operation and nested tape expansion
is differentiable"""
@@ -201,7 +207,7 @@ def test_differentiable_expand(
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 10
tol = TOL_FOR_SPSA
@@ -217,7 +223,7 @@ def decomposition(self):
a = jax.numpy.array(0.1)
p = jax.numpy.array([0.1, 0.2, 0.3])
- @qnode(dev, **kwargs)
+ @qnode(get_device(dev_name, wires=1, seed=seed), **kwargs)
def circuit(a, p):
qml.RX(a, wires=0)
U3(p[0], p[1], p[2], wires=0)
@@ -243,7 +249,7 @@ def circuit(a, p):
assert np.allclose(res, expected, atol=tol, rtol=0)
def test_jacobian_options(
- self, dev, diff_method, grad_on_execution, device_vjp, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, seed
): # pylint:disable=unused-argument
"""Test setting jacobian options"""
if diff_method != "finite-diff":
@@ -251,7 +257,13 @@ def test_jacobian_options(
a = jax.numpy.array([0.1, 0.2])
- @qnode(dev, interface=interface, diff_method="finite-diff", h=1e-8, approx_order=2)
+ @qnode(
+ get_device(dev_name, wires=1, seed=seed),
+ interface=interface,
+ diff_method="finite-diff",
+ h=1e-8,
+ approx_order=2,
+ )
def circuit(a):
qml.RY(a[0], wires=0)
qml.RX(a[1], wires=0)
@@ -260,15 +272,16 @@ def circuit(a):
jax.jacobian(circuit)(a)
+@pytest.mark.parametrize("interface", ["auto", "jax"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp", interface_and_device_and_diff_method
+ "dev_name,diff_method,grad_on_execution, device_vjp", device_and_diff_method
)
class TestVectorValuedQNode:
"""Test that using vector-valued QNodes with JAX integrate with the
PennyLane stack"""
def test_diff_expval_expval(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test jacobian calculation"""
kwargs = {
@@ -279,15 +292,15 @@ def test_diff_expval_expval(
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
a = jax.numpy.array(0.1)
b = jax.numpy.array(0.2)
- @qnode(dev, **kwargs)
+ @qnode(get_device(dev_name, wires=2, seed=seed), **kwargs)
def circuit(a, b):
qml.RY(a, wires=0)
qml.RX(b, wires=1)
@@ -327,7 +340,7 @@ def circuit(a, b):
assert np.allclose(res[1][1], expected[1][1], atol=tol, rtol=0)
def test_jacobian_no_evaluate(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test jacobian calculation when no prior circuit evaluation has been performed"""
kwargs = {
@@ -337,17 +350,17 @@ def test_jacobian_no_evaluate(
"device_vjp": device_vjp,
}
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
a = jax.numpy.array(0.1)
b = jax.numpy.array(0.2)
- @qnode(dev, **kwargs)
+ @qnode(get_device(dev_name, wires=2, seed=seed), **kwargs)
def circuit(a, b):
qml.RY(a, wires=0)
qml.RX(b, wires=1)
@@ -383,7 +396,7 @@ def circuit(a, b):
assert np.allclose(res[i][j], expected[i][j], atol=tol, rtol=0)
def test_diff_single_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with a single prob output"""
@@ -394,15 +407,15 @@ def test_diff_single_probs(
"device_vjp": device_vjp,
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
x = jax.numpy.array(0.543)
y = jax.numpy.array(-0.654)
- @qnode(dev, **kwargs)
+ @qnode(get_device(dev_name, wires=2, seed=seed), **kwargs)
def circuit(x, y):
qml.RX(x, wires=[0])
qml.RY(y, wires=[1])
@@ -431,7 +444,7 @@ def circuit(x, y):
assert np.allclose(res[1], expected.T[1], atol=tol, rtol=0)
def test_diff_multi_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with multiple prob outputs"""
@@ -443,15 +456,15 @@ def test_diff_multi_probs(
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
x = jax.numpy.array(0.543)
y = jax.numpy.array(-0.654)
- @qnode(dev, **kwargs)
+ @qnode(get_device(dev_name, wires=1, seed=seed), **kwargs)
def circuit(x, y):
qml.RX(x, wires=[0])
qml.RY(y, wires=[1])
@@ -513,7 +526,7 @@ def circuit(x, y):
assert np.allclose(jac[1][1], expected_1[1], atol=tol, rtol=0)
def test_diff_expval_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
@@ -524,15 +537,15 @@ def test_diff_expval_probs(
"device_vjp": device_vjp,
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
x = jax.numpy.array(0.543)
y = jax.numpy.array(-0.654)
- @qnode(dev, **kwargs)
+ @qnode(get_device(dev_name, wires=1, seed=seed), **kwargs)
def circuit(x, y):
qml.RX(x, wires=[0])
qml.RY(y, wires=[1])
@@ -583,13 +596,13 @@ def circuit(x, y):
assert np.allclose(jac[1][1], expected[1][1], atol=tol, rtol=0)
def test_diff_expval_probs_sub_argnums(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Tests correct output shape and evaluation for a tape with prob and expval outputs with less
trainable parameters (argnums) than parameters."""
kwargs = {}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
x = jax.numpy.array(0.543)
@@ -600,7 +613,7 @@ def test_diff_expval_probs_sub_argnums(
y = y + 0j
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -613,8 +626,9 @@ def circuit(x, y):
qml.CNOT(wires=[0, 1])
return qml.expval(qml.PauliZ(0)), qml.probs(wires=[1])
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning does not support measuring probabilities with adjoint.")
+
jac = jax.jacobian(circuit, argnums=[0])(x, y)
expected = [
@@ -639,7 +653,9 @@ def circuit(x, y):
assert jac[1][0].shape == (2,)
assert np.allclose(jac[1][0], expected[1][0], atol=tol, rtol=0)
- def test_diff_var_probs(self, dev, diff_method, grad_on_execution, device_vjp, interface, tol):
+ def test_diff_var_probs(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
+ ):
"""Tests correct output shape and evaluation for a tape
with prob and variance outputs"""
kwargs = {
@@ -651,16 +667,16 @@ def test_diff_var_probs(self, dev, diff_method, grad_on_execution, device_vjp, i
if diff_method == "hadamard":
pytest.skip("Hadamard does not support var")
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
elif diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
x = jax.numpy.array(0.543)
y = jax.numpy.array(-0.654)
- @qnode(dev, **kwargs)
+ @qnode(get_device(dev_name, wires=1, seed=seed), **kwargs)
def circuit(x, y):
qml.RX(x, wires=[0])
qml.RY(y, wires=[1])
@@ -795,11 +811,13 @@ def cost_fn(a, b):
assert spy.call_args[1]["gradient_fn"] == "backprop"
-@pytest.mark.parametrize("dev,diff_method,grad_on_execution, device_vjp", device_and_diff_method)
+@pytest.mark.parametrize(
+ "dev_name,diff_method,grad_on_execution,device_vjp", device_and_diff_method
+)
class TestQubitIntegration:
"""Tests that ensure various qubit circuits integrate correctly"""
- def test_sampling(self, dev, diff_method, grad_on_execution, device_vjp):
+ def test_sampling(self, dev_name, diff_method, grad_on_execution, device_vjp, seed):
"""Test sampling works as expected"""
if grad_on_execution is True:
pytest.skip("Sampling not possible with grad_on_execution differentiation.")
@@ -808,7 +826,7 @@ def test_sampling(self, dev, diff_method, grad_on_execution, device_vjp):
pytest.skip("Adjoint warns with finite shots")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface="jax",
grad_on_execution=grad_on_execution,
@@ -828,7 +846,7 @@ def circuit():
assert isinstance(res[1], jax.Array)
assert res[1].shape == (10,) # pylint:disable=comparison-with-callable
- def test_counts(self, dev, diff_method, grad_on_execution, device_vjp):
+ def test_counts(self, dev_name, diff_method, grad_on_execution, device_vjp, seed):
"""Test counts works as expected"""
if grad_on_execution is True:
pytest.skip("Sampling not possible with grad_on_execution differentiation.")
@@ -837,7 +855,7 @@ def test_counts(self, dev, diff_method, grad_on_execution, device_vjp):
pytest.skip("Adjoint errors with finite shots")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface="jax",
grad_on_execution=grad_on_execution,
@@ -860,7 +878,7 @@ def circuit():
assert isinstance(res[1], dict)
assert len(res[1]) == 2
- def test_chained_qnodes(self, dev, diff_method, grad_on_execution, device_vjp):
+ def test_chained_qnodes(self, dev_name, diff_method, grad_on_execution, device_vjp, seed):
"""Test that the gradient of chained QNodes works without error"""
# pylint:disable=too-few-public-methods
@@ -869,7 +887,7 @@ def decomposition(self):
return [qml.templates.StronglyEntanglingLayers(*self.parameters, self.wires)]
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface="jax",
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -880,7 +898,7 @@ def circuit1(weights):
return qml.expval(qml.PauliZ(0))
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface="jax",
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -910,16 +928,18 @@ def cost(weights):
assert len(res) == 2
- def test_postselection_differentiation(self, dev, diff_method, grad_on_execution, device_vjp):
+ def test_postselection_differentiation(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, seed
+ ):
"""Test that when postselecting with default.qubit, differentiation works correctly."""
if diff_method in ["adjoint", "spsa", "hadamard"]:
pytest.skip("Diff method does not support postselection.")
- if dev.name == "reference.qubit":
+ if dev_name == "reference.qubit":
pytest.xfail("reference.qubit does not support postselection.")
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface="jax",
grad_on_execution=grad_on_execution,
@@ -933,7 +953,7 @@ def circuit(phi, theta):
return qml.expval(qml.PauliZ(1))
@qml.qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface="jax",
grad_on_execution=grad_on_execution,
@@ -954,14 +974,16 @@ def expected_circuit(theta):
assert np.allclose(gradient, [0.0, exp_theta_grad])
+@pytest.mark.parametrize("interface", ["auto", "jax"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp", interface_and_device_and_diff_method
+ "dev_name,diff_method,grad_on_execution, device_vjp", device_and_diff_method
)
class TestQubitIntegrationHigherOrder:
"""Tests that ensure various qubit circuits integrate correctly when computing higher-order derivatives"""
+ @pytest.mark.local_salt(1)
def test_second_derivative(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test second derivative calculation of a scalar-valued QNode"""
kwargs = {
@@ -975,10 +997,10 @@ def test_second_derivative(
if diff_method == "adjoint":
pytest.skip("Adjoint does not second derivative.")
elif diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
- @qnode(dev, **kwargs)
+ @qnode(get_device(dev_name, wires=0, seed=seed), **kwargs)
def circuit(x):
qml.RY(x[0], wires=0)
qml.RX(x[1], wires=0)
@@ -1006,7 +1028,9 @@ def circuit(x):
else:
assert np.allclose(g2, expected_g2, atol=tol, rtol=0)
- def test_hessian(self, dev, diff_method, grad_on_execution, device_vjp, interface, tol):
+ def test_hessian(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
+ ):
"""Test hessian calculation of a scalar-valued QNode"""
gradient_kwargs = {}
if diff_method == "adjoint":
@@ -1015,12 +1039,12 @@ def test_hessian(self, dev, diff_method, grad_on_execution, device_vjp, interfac
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1059,23 +1083,23 @@ def circuit(x):
assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
def test_hessian_vector_valued(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test hessian calculation of a vector-valued QNode"""
gradient_kwargs = {}
if diff_method == "adjoint":
pytest.skip("Adjoint does not support second derivative.")
elif diff_method == "spsa":
- qml.math.random.seed(42)
+ qml.math.random.seed(seed)
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=0, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1123,7 +1147,7 @@ def circuit(x):
assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
def test_hessian_vector_valued_postprocessing(
- self, dev, diff_method, interface, grad_on_execution, device_vjp, tol
+ self, dev_name, diff_method, interface, grad_on_execution, device_vjp, tol, seed
):
"""Test hessian calculation of a vector valued QNode with post-processing"""
gradient_kwargs = {}
@@ -1133,12 +1157,12 @@ def test_hessian_vector_valued_postprocessing(
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1189,7 +1213,7 @@ def cost_fn(x):
assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
def test_hessian_vector_valued_separate_args(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test hessian calculation of a vector valued QNode that has separate input arguments"""
gradient_kwargs = {}
@@ -1199,12 +1223,12 @@ def test_hessian_vector_valued_separate_args(
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1254,17 +1278,19 @@ def circuit(a, b):
else:
assert np.allclose(hess, expected_hess, atol=tol, rtol=0)
- def test_state(self, dev, diff_method, grad_on_execution, device_vjp, interface, tol):
+ def test_state(
+ self, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
+ ):
"""Test that the state can be returned and differentiated"""
- if "lightning" in getattr(dev, "name", "").lower():
+ if "lightning" in dev_name:
pytest.xfail("Lightning does not support state adjoint differentiation.")
x = jax.numpy.array(0.543)
y = jax.numpy.array(-0.654)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1293,7 +1319,7 @@ def cost_fn(x, y):
@pytest.mark.parametrize("state", [[1], [0, 1]]) # Basis state and state vector
def test_projector(
- self, state, dev, diff_method, grad_on_execution, device_vjp, interface, tol
+ self, state, dev_name, diff_method, grad_on_execution, device_vjp, interface, tol, seed
):
"""Test that the variance of a projector is correctly returned"""
gradient_kwargs = {}
@@ -1302,16 +1328,16 @@ def test_projector(
if diff_method == "hadamard":
pytest.skip("Hadamard does not support var.")
elif diff_method == "spsa":
- gradient_kwargs = {"h": H_FOR_SPSA, "sampler_rng": np.random.default_rng(SEED_FOR_SPSA)}
+ gradient_kwargs = {"h": H_FOR_SPSA, "sampler_rng": np.random.default_rng(seed)}
tol = TOL_FOR_SPSA
- if dev.name == "reference.qubit":
+ if dev_name == "reference.qubit":
pytest.xfail("diagonalize_measurements do not support projectors (sc-72911)")
P = jax.numpy.array(state)
x, y = 0.765, -0.654
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
diff_method=diff_method,
interface=interface,
grad_on_execution=grad_on_execution,
@@ -1338,8 +1364,9 @@ def circuit(x, y):
assert np.allclose(res, expected, atol=tol, rtol=0)
+@pytest.mark.parametrize("interface", ["auto", "jax"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp", interface_and_device_and_diff_method
+ "dev_name,diff_method,grad_on_execution, device_vjp", device_and_diff_method
)
class TestTapeExpansion:
"""Test that tape expansion within the QNode integrates correctly
@@ -1347,7 +1374,7 @@ class TestTapeExpansion:
@pytest.mark.parametrize("max_diff", [1, 2])
def test_gradient_expansion_trainable_only(
- self, dev, diff_method, grad_on_execution, device_vjp, max_diff, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, max_diff, interface, seed
):
"""Test that a *supported* operation with no gradient recipe is only
expanded for parameter-shift and finite-differences when it is trainable."""
@@ -1361,7 +1388,7 @@ def decomposition(self):
return [qml.RY(3 * self.data[0], wires=self.wires)]
@qnode(
- dev,
+ get_device(dev_name, wires=1, seed=seed),
diff_method=diff_method,
grad_on_execution=grad_on_execution,
max_diff=max_diff,
@@ -1382,7 +1409,16 @@ def circuit(x, y):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_split_non_commuting_analytic(
- self, dev, diff_method, grad_on_execution, max_diff, interface, device_vjp, mocker, tol
+ self,
+ dev_name,
+ diff_method,
+ grad_on_execution,
+ max_diff,
+ interface,
+ device_vjp,
+ mocker,
+ tol,
+ seed,
):
"""Test that the Hamiltonian is not expanded if there
are non-commuting groups and the number of shots is None
@@ -1396,10 +1432,10 @@ def test_split_non_commuting_analytic(
gradient_kwargs = {
"h": H_FOR_SPSA,
"num_directions": 20,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
}
tol = TOL_FOR_SPSA
- if dev.name == "reference.qubit":
+ if dev_name == "reference.qubit":
pytest.skip(
"Cannot add transform to the transform program in preprocessing"
"when using mocker.spy on it."
@@ -1409,7 +1445,7 @@ def test_split_non_commuting_analytic(
obs = [qml.PauliX(0), qml.PauliX(0) @ qml.PauliZ(1), qml.PauliZ(0) @ qml.PauliZ(1)]
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1459,13 +1495,21 @@ def circuit(data, weights, coeffs):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_finite_shots(
- self, dev, diff_method, grad_on_execution, device_vjp, interface, max_diff, mocker
+ self,
+ dev_name,
+ diff_method,
+ grad_on_execution,
+ device_vjp,
+ interface,
+ max_diff,
+ mocker,
+ seed,
):
"""Test that the Hamiltonian is correctly measured (and not expanded)
if there are non-commuting groups and the number of shots is finite
and the first and second order gradients are correctly evaluated"""
- if dev.name == "reference.qubit":
+ if dev_name == "reference.qubit":
pytest.skip(
"Cannot added to a transform to the transform program in "
"preprocessing when using mocker.spy on it."
@@ -1480,7 +1524,7 @@ def test_hamiltonian_finite_shots(
elif diff_method == "spsa":
gradient_kwargs = {
"h": H_FOR_SPSA,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
"num_directions": 20,
}
tol = TOL_FOR_SPSA
@@ -1489,7 +1533,7 @@ def test_hamiltonian_finite_shots(
obs = [qml.PauliX(0), qml.PauliX(0) @ qml.PauliZ(1), qml.PauliZ(0) @ qml.PauliZ(1)]
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1545,21 +1589,22 @@ def circuit(data, weights, coeffs):
@pytest.mark.parametrize("shots", [None, 10000])
+@pytest.mark.parametrize("interface", ["auto", "jax"])
@pytest.mark.parametrize(
- "interface,dev,diff_method,grad_on_execution, device_vjp", interface_and_device_and_diff_method
+ "dev_name,diff_method,grad_on_execution, device_vjp", device_and_diff_method
)
class TestReturn: # pylint:disable=too-many-public-methods
"""Class to test the shape of the Grad/Jacobian/Hessian with different return types."""
def test_grad_single_measurement_param(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""For one measurement and one param, the gradient is a float."""
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1578,14 +1623,14 @@ def circuit(a):
assert grad.shape == ()
def test_grad_single_measurement_multiple_param(
- self, dev, diff_method, grad_on_execution, shots, device_vjp, interface
+ self, dev_name, diff_method, grad_on_execution, shots, device_vjp, interface, seed
):
"""For one measurement and multiple param, the gradient is a tuple of arrays."""
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1607,14 +1652,14 @@ def circuit(a, b):
assert grad[1].shape == ()
def test_grad_single_measurement_multiple_param_array(
- self, dev, diff_method, grad_on_execution, shots, device_vjp, interface
+ self, dev_name, diff_method, grad_on_execution, shots, device_vjp, interface, seed
):
"""For one measurement and multiple param as a single array params, the gradient is an array."""
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1634,7 +1679,7 @@ def circuit(a):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_single_measurement_param_probs(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""For a multi dimensional measurement (probs), check that a single array is returned with the correct
dimension"""
@@ -1645,7 +1690,7 @@ def test_jacobian_single_measurement_param_probs(
pytest.skip("Test does not supports adjoint because of probabilities.")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1665,7 +1710,7 @@ def circuit(a):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_single_measurement_probs_multiple_param(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""For a multi dimensional measurement (probs), check that a single tuple is returned containing arrays with
the correct dimension"""
@@ -1675,7 +1720,7 @@ def test_jacobian_single_measurement_probs_multiple_param(
pytest.skip("Test does not support finite shots and adjoint/backprop")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1701,7 +1746,7 @@ def circuit(a, b):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_single_measurement_probs_multiple_param_single_array(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""For a multi dimensional measurement (probs), check that a single tuple is returned containing arrays with
the correct dimension"""
@@ -1711,7 +1756,7 @@ def test_jacobian_single_measurement_probs_multiple_param_single_array(
pytest.skip("Test does not support finite shots and adjoint/backprop")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1730,27 +1775,20 @@ def circuit(a):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_expval_expval_multiple_params(
- self,
- dev,
- diff_method,
- grad_on_execution,
- jacobian,
- shots,
- interface,
- device_vjp,
+ self, dev_name, diff_method, grad_on_execution, jacobian, shots, interface, device_vjp, seed
):
"""The hessian of multiple measurements with multiple params return a tuple of arrays."""
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
if device_vjp and jacobian is jax.jacfwd:
pytest.skip("forward pass can't be done with registered vjp.")
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
par_0 = jax.numpy.array(0.1)
par_1 = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -1783,18 +1821,18 @@ def circuit(x, y):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_expval_expval_multiple_params_array(
- self, dev, diff_method, grad_on_execution, jacobian, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, jacobian, device_vjp, shots, interface, seed
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
if device_vjp and jacobian is jax.jacfwd:
pytest.skip("forward pass can't be done with registered vjp.")
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1820,7 +1858,7 @@ def circuit(a):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_var_var_multiple_params(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The hessian of multiple measurements with multiple params return a tuple of arrays."""
if diff_method == "adjoint":
@@ -1834,7 +1872,7 @@ def test_jacobian_var_var_multiple_params(
par_1 = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -1868,7 +1906,7 @@ def circuit(x, y):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_var_var_multiple_params_array(
- self, dev, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, jacobian, shots, interface, seed
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
if diff_method == "adjoint":
@@ -1879,7 +1917,7 @@ def test_jacobian_var_var_multiple_params_array(
pytest.skip("Test does not support finite shots and adjoint/backprop")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1905,18 +1943,18 @@ def circuit(a):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_multiple_measurement_single_param(
- self, dev, diff_method, grad_on_execution, jacobian, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, jacobian, device_vjp, shots, interface, seed
):
"""The jacobian of multiple measurements with a single params return an array."""
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
if diff_method == "adjoint" and jacobian == jax.jacfwd:
pytest.skip("jacfwd doesn't like complex numbers")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1942,18 +1980,18 @@ def circuit(a):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_multiple_measurement_multiple_param(
- self, dev, diff_method, grad_on_execution, jacobian, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, jacobian, device_vjp, shots, interface, seed
):
"""The jacobian of multiple measurements with a multiple params return a tuple of arrays."""
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
if diff_method == "adjoint" and jacobian == jax.jacfwd:
pytest.skip("jacfwd doesn't like complex numbers")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -1988,18 +2026,18 @@ def circuit(a, b):
@pytest.mark.parametrize("jacobian", jacobian_fn)
def test_jacobian_multiple_measurement_multiple_param_array(
- self, dev, diff_method, grad_on_execution, jacobian, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, jacobian, device_vjp, shots, interface, seed
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
if shots is not None and diff_method in ("backprop", "adjoint"):
pytest.skip("Test does not support finite shots and adjoint/backprop")
- if "lightning" in dev.name:
+ if "lightning" in dev_name:
pytest.xfail("lightning device_vjp not compatible with jax.jacobian.")
if diff_method == "adjoint" and jacobian == jax.jacfwd:
pytest.skip("jacfwd doesn't like complex numbers")
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
grad_on_execution=grad_on_execution,
@@ -2024,7 +2062,7 @@ def circuit(a):
assert jac[1].shape == (4, 2)
def test_hessian_expval_multiple_params(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""The hessian of single a measurement with multiple params return a tuple of arrays."""
if shots is not None and diff_method in ("backprop", "adjoint"):
@@ -2037,7 +2075,7 @@ def test_hessian_expval_multiple_params(
par_1 = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2068,7 +2106,7 @@ def circuit(x, y):
assert hess[1][1].shape == ()
def test_hessian_expval_multiple_param_array(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""The hessian of single measurement with a multiple params array return a single array."""
if diff_method == "adjoint":
@@ -2079,7 +2117,7 @@ def test_hessian_expval_multiple_param_array(
params = jax.numpy.array([0.1, 0.2])
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2098,7 +2136,7 @@ def circuit(x):
assert hess.shape == (2, 2)
def test_hessian_var_multiple_params(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""The hessian of single a measurement with multiple params return a tuple of arrays."""
if diff_method == "adjoint":
@@ -2112,7 +2150,7 @@ def test_hessian_var_multiple_params(
par_1 = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2143,7 +2181,7 @@ def circuit(x, y):
assert hess[1][1].shape == ()
def test_hessian_var_multiple_param_array(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""The hessian of single measurement with a multiple params array return a single array."""
if diff_method == "adjoint":
@@ -2156,7 +2194,7 @@ def test_hessian_var_multiple_param_array(
params = jax.numpy.array([0.1, 0.2])
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2175,7 +2213,7 @@ def circuit(x):
assert hess.shape == (2, 2)
def test_hessian_probs_expval_multiple_params(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""The hessian of multiple measurements with multiple params return a tuple of arrays."""
if diff_method == "adjoint":
@@ -2190,7 +2228,7 @@ def test_hessian_probs_expval_multiple_params(
par_1 = jax.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2239,7 +2277,7 @@ def circuit(x, y):
assert hess[1][1][1].shape == (2,)
def test_hessian_expval_probs_multiple_param_array(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""The hessian of multiple measurements with a multiple param array return a single array."""
if diff_method == "adjoint":
@@ -2252,7 +2290,7 @@ def test_hessian_expval_probs_multiple_param_array(
params = jax.numpy.array([0.1, 0.2])
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
device_vjp=device_vjp,
@@ -2277,7 +2315,7 @@ def circuit(x):
assert hess[1].shape == (2, 2, 2)
def test_hessian_probs_var_multiple_params(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""The hessian of multiple measurements with multiple params return a tuple of arrays."""
if diff_method == "adjoint":
@@ -2291,7 +2329,7 @@ def test_hessian_probs_var_multiple_params(
par_1 = qml.numpy.array(0.2)
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
@@ -2340,7 +2378,7 @@ def circuit(x, y):
assert hess[1][1][1].shape == (2,)
def test_hessian_var_probs_multiple_param_array(
- self, dev, diff_method, grad_on_execution, device_vjp, shots, interface
+ self, dev_name, diff_method, grad_on_execution, device_vjp, shots, interface, seed
):
"""The hessian of multiple measurements with a multiple param array return a single array."""
if diff_method == "adjoint":
@@ -2353,7 +2391,7 @@ def test_hessian_var_probs_multiple_param_array(
params = jax.numpy.array([0.1, 0.2])
@qnode(
- dev,
+ get_device(dev_name, wires=2, seed=seed),
interface=interface,
diff_method=diff_method,
max_diff=2,
diff --git a/tests/interfaces/test_tensorflow.py b/tests/interfaces/test_tensorflow.py
index 0abe82c1942..57a38669445 100644
--- a/tests/interfaces/test_tensorflow.py
+++ b/tests/interfaces/test_tensorflow.py
@@ -109,24 +109,20 @@ def cost(x, cache):
# add tests for lightning 2 when possible
# set rng for device when possible
test_matrix = [
- ({"gradient_fn": param_shift, "interface": "tensorflow"}, 100000, DefaultQubit(seed=42)), # 0
- ({"gradient_fn": param_shift, "interface": "tensorflow"}, None, DefaultQubit()), # 1
- ({"gradient_fn": "backprop", "interface": "tensorflow"}, None, DefaultQubit()), # 2
- ({"gradient_fn": "adjoint", "interface": "tensorflow"}, None, DefaultQubit()), # 3
- ({"gradient_fn": param_shift, "interface": "tf-autograph"}, 100000, DefaultQubit(seed=42)), # 4
- ({"gradient_fn": param_shift, "interface": "tf-autograph"}, None, DefaultQubit()), # 5
- ({"gradient_fn": "backprop", "interface": "tf-autograph"}, None, DefaultQubit()), # 6
- ({"gradient_fn": "adjoint", "interface": "tf-autograph"}, None, DefaultQubit()), # 7
- ({"gradient_fn": "adjoint", "interface": "tf", "device_vjp": True}, None, DefaultQubit()), # 8
- (
- {"gradient_fn": param_shift, "interface": "tensorflow"},
- None,
- qml.device("reference.qubit"),
- ), # 9
+ ({"gradient_fn": param_shift, "interface": "tensorflow"}, 100000, "default.qubit"), # 0
+ ({"gradient_fn": param_shift, "interface": "tensorflow"}, None, "default.qubit"), # 1
+ ({"gradient_fn": "backprop", "interface": "tensorflow"}, None, "default.qubit"), # 2
+ ({"gradient_fn": "adjoint", "interface": "tensorflow"}, None, "default.qubit"), # 3
+ ({"gradient_fn": param_shift, "interface": "tf-autograph"}, 100000, "default.qubit"), # 4
+ ({"gradient_fn": param_shift, "interface": "tf-autograph"}, None, "default.qubit"), # 5
+ ({"gradient_fn": "backprop", "interface": "tf-autograph"}, None, "default.qubit"), # 6
+ ({"gradient_fn": "adjoint", "interface": "tf-autograph"}, None, "default.qubit"), # 7
+ ({"gradient_fn": "adjoint", "interface": "tf", "device_vjp": True}, None, "default.qubit"), # 8
+ ({"gradient_fn": param_shift, "interface": "tensorflow"}, None, "reference.qubit"), # 9
(
{"gradient_fn": param_shift, "interface": "tensorflow"},
100000,
- qml.device("reference.qubit"),
+ "reference.qubit",
), # 10
]
@@ -136,14 +132,16 @@ def atol_for_shots(shots):
return 1e-2 if shots else 1e-6
-@pytest.mark.parametrize("execute_kwargs, shots, device", test_matrix)
+@pytest.mark.parametrize("execute_kwargs, shots, device_name", test_matrix)
class TestTensorflowExecuteIntegration:
"""Test the tensorflow interface execute function
integrates well for both forward and backward execution"""
- def test_execution(self, execute_kwargs, shots, device):
+ def test_execution(self, execute_kwargs, shots, device_name, seed):
"""Test execution"""
+ device = qml.device(device_name, seed=seed)
+
def cost(a, b):
ops1 = [qml.RY(a, wires=0), qml.RX(b, wires=0)]
tape1 = qml.tape.QuantumScript(ops1, [qml.expval(qml.PauliZ(0))], shots=shots)
@@ -173,12 +171,14 @@ def cost(a, b):
assert qml.math.allclose(res[0], tf.cos(a) * tf.cos(b), atol=atol_for_shots(shots))
assert qml.math.allclose(res[1], tf.cos(a) * tf.cos(b), atol=atol_for_shots(shots))
- def test_scalar_jacobian(self, execute_kwargs, shots, device):
+ def test_scalar_jacobian(self, execute_kwargs, shots, device_name, seed):
"""Test scalar jacobian calculation"""
a = tf.Variable(0.1, dtype=tf.float64)
device_vjp = execute_kwargs.get("device_vjp", False)
+ device = qml.device(device_name, seed=seed)
+
def cost(a):
tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots)
return execute([tape], device, **execute_kwargs)[0]
@@ -198,11 +198,12 @@ def cost(a):
assert np.allclose(res, expected, atol=atol_for_shots(shots), rtol=0)
assert np.allclose(res, -tf.sin(a), atol=atol_for_shots(shots))
- def test_jacobian(self, execute_kwargs, shots, device):
+ def test_jacobian(self, execute_kwargs, shots, device_name, seed):
"""Test jacobian calculation"""
a = tf.Variable(0.1)
b = tf.Variable(0.2)
+ device = qml.device(device_name, seed=seed)
device_vjp = execute_kwargs.get("device_vjp", False)
def cost(a, b):
@@ -225,10 +226,12 @@ def cost(a, b):
for _r, _e in zip(jac, expected):
assert np.allclose(_r, _e, atol=atol_for_shots(shots))
- def test_tape_no_parameters(self, execute_kwargs, shots, device):
+ def test_tape_no_parameters(self, execute_kwargs, shots, device_name, seed):
"""Test that a tape with no parameters is correctly
ignored during the gradient computation"""
+ device = qml.device(device_name, seed=seed)
+
def cost(params):
tape1 = qml.tape.QuantumScript(
[qml.Hadamard(0)], [qml.expval(qml.PauliX(0))], shots=shots
@@ -278,9 +281,11 @@ def cost(params):
expected = [-tf.cos(y) * tf.sin(x), -tf.cos(x) * tf.sin(y)]
assert np.allclose(grad, expected, atol=atol_for_shots(shots), rtol=0)
- def test_tapes_with_different_return_size(self, execute_kwargs, shots, device):
+ def test_tapes_with_different_return_size(self, execute_kwargs, shots, device_name, seed):
"""Test that tapes wit different can be executed and differentiated."""
+ device = qml.device(device_name, seed=seed)
+
if (
execute_kwargs["gradient_fn"] == "adjoint"
and execute_kwargs["interface"] == "tf-autograph"
@@ -339,10 +344,11 @@ def cost(params):
assert np.allclose(jac[0, 1], d2, atol=atol_for_shots(shots))
assert np.allclose(jac[3, 1], d2, atol=atol_for_shots(shots))
- def test_reusing_quantum_tape(self, execute_kwargs, shots, device):
+ def test_reusing_quantum_tape(self, execute_kwargs, shots, device_name, seed):
"""Test re-using a quantum tape by passing new parameters"""
a = tf.Variable(0.1)
b = tf.Variable(0.2)
+ device = qml.device(device_name, seed=seed)
tape = qml.tape.QuantumScript(
[qml.RY(a, 0), qml.RX(b, 1), qml.CNOT((0, 1))],
@@ -386,11 +392,12 @@ def cost(a, b):
for _j, _e in zip(jac, expected):
assert np.allclose(_j, _e, atol=atol_for_shots(shots), rtol=0)
- def test_classical_processing(self, execute_kwargs, device, shots):
+ def test_classical_processing(self, execute_kwargs, device_name, seed, shots):
"""Test classical processing within the quantum tape"""
a = tf.Variable(0.1, dtype=tf.float64)
b = tf.constant(0.2, dtype=tf.float64)
c = tf.Variable(0.3, dtype=tf.float64)
+ device = qml.device(device_name, seed=seed)
device_vjp = execute_kwargs.get("device_vjp", False)
@@ -416,10 +423,11 @@ def cost(a, b, c):
# I tried getting analytic results for this circuit but I kept being wrong and am giving up
- def test_no_trainable_parameters(self, execute_kwargs, shots, device):
+ def test_no_trainable_parameters(self, execute_kwargs, shots, device_name, seed):
"""Test evaluation and Jacobian if there are no trainable parameters"""
a = tf.constant(0.1)
b = tf.constant(0.2)
+ device = qml.device(device_name, seed=seed)
def cost(a, b):
ops = [qml.RY(a, 0), qml.RX(b, 0), qml.CNOT((0, 1))]
@@ -445,12 +453,12 @@ def loss(a, b):
res = tape.gradient(loss_res, [a, b])
assert all(r is None for r in res)
- def test_matrix_parameter(self, execute_kwargs, device, shots):
+ def test_matrix_parameter(self, execute_kwargs, device_name, seed, shots):
"""Test that the tensorflow interface works correctly
with a matrix parameter"""
U = tf.constant([[0, 1], [1, 0]], dtype=tf.complex128)
a = tf.Variable(0.1)
-
+ device = qml.device(device_name, seed=seed)
device_vjp = execute_kwargs.get("device_vjp", False)
def cost(a, U):
@@ -467,10 +475,11 @@ def cost(a, U):
assert isinstance(jac, tf.Tensor)
assert np.allclose(jac, tf.sin(a), atol=atol_for_shots(shots), rtol=0)
- def test_differentiable_expand(self, execute_kwargs, device, shots):
+ def test_differentiable_expand(self, execute_kwargs, device_name, seed, shots):
"""Test that operation and nested tapes expansion
is differentiable"""
+ device = qml.device(device_name, seed=seed)
device_vjp = execute_kwargs.get("device_vjp", False)
class U3(qml.U3):
@@ -527,10 +536,12 @@ def cost_fn(a, p):
)
assert np.allclose(res, expected, atol=atol_for_shots(shots), rtol=0)
- def test_probability_differentiation(self, execute_kwargs, device, shots):
+ def test_probability_differentiation(self, execute_kwargs, device_name, seed, shots):
"""Tests correct output shape and evaluation for a tape
with prob outputs"""
+ device = qml.device(device_name, seed=seed)
+
def cost(x, y):
ops = [qml.RX(x, 0), qml.RY(y, 1), qml.CNOT((0, 1))]
m = [qml.probs(wires=0), qml.probs(wires=1)]
@@ -590,11 +601,12 @@ def cost(x, y):
assert np.allclose(res[0], expected[0], atol=atol_for_shots(shots), rtol=0)
assert np.allclose(res[1], expected[1], atol=atol_for_shots(shots), rtol=0)
- def test_ragged_differentiation(self, execute_kwargs, device, shots):
+ def test_ragged_differentiation(self, execute_kwargs, device_name, seed, shots):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
device_vjp = execute_kwargs.get("device_vjp", False)
+ device = qml.device(device_name, seed=seed)
def cost(x, y):
ops = [qml.RX(x, wires=0), qml.RY(y, 1), qml.CNOT((0, 1))]
@@ -716,16 +728,18 @@ def cost_fn(x):
assert hess is None
-@pytest.mark.parametrize("execute_kwargs, shots, device", test_matrix)
+@pytest.mark.parametrize("execute_kwargs, shots, device_name", test_matrix)
@pytest.mark.usefixtures("use_legacy_and_new_opmath")
class TestHamiltonianWorkflows:
"""Test that tapes ending with expectations
of Hamiltonians provide correct results and gradients"""
@pytest.fixture
- def cost_fn(self, execute_kwargs, shots, device):
+ def cost_fn(self, execute_kwargs, shots, device_name, seed):
"""Cost function for gradient tests"""
+ device = qml.device(device_name, seed=seed)
+
def _cost_fn(weights, coeffs1, coeffs2):
obs1 = [qml.PauliZ(0), qml.PauliZ(0) @ qml.PauliX(1), qml.PauliY(0)]
H1 = qml.Hamiltonian(coeffs1, obs1)
diff --git a/tests/interfaces/test_tensorflow_autograph_qnode_shot_vector.py b/tests/interfaces/test_tensorflow_autograph_qnode_shot_vector.py
index 227e8a96e3c..9045992d467 100644
--- a/tests/interfaces/test_tensorflow_autograph_qnode_shot_vector.py
+++ b/tests/interfaces/test_tensorflow_autograph_qnode_shot_vector.py
@@ -18,7 +18,6 @@
import pennylane as qml
from pennylane import numpy as np
from pennylane import qnode
-from pennylane.devices import DefaultQubit
pytestmark = pytest.mark.tf
@@ -34,9 +33,9 @@
}
qubit_device_and_diff_method = [
- [DefaultQubit(seed=123), "finite-diff"],
- [DefaultQubit(seed=123), "parameter-shift"],
- [DefaultQubit(seed=123), "spsa"],
+ ["default.qubit", "finite-diff"],
+ ["default.qubit", "parameter-shift"],
+ ["default.qubit", "spsa"],
]
TOLS = {
@@ -49,13 +48,14 @@
@pytest.fixture
def gradient_kwargs(request):
diff_method = request.node.funcargs["diff_method"]
+ seed = request.getfixturevalue("seed")
return kwargs[diff_method] | (
- {"sampler_rng": np.random.default_rng(42)} if diff_method == "spsa" else {}
+ {"sampler_rng": np.random.default_rng(seed)} if diff_method == "spsa" else {}
)
@pytest.mark.parametrize("shots,num_copies", shots_and_num_copies)
-@pytest.mark.parametrize("dev,diff_method", qubit_device_and_diff_method)
+@pytest.mark.parametrize("dev_name,diff_method", qubit_device_and_diff_method)
@pytest.mark.parametrize(
"decorator,interface",
[(tf.function, "tf"), (lambda x: x, "tf-autograph")],
@@ -64,12 +64,17 @@ class TestReturnWithShotVectors:
"""Class to test the shape of the Grad/Jacobian/Hessian with different return types and shot vectors."""
def test_jac_single_measurement_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""For one measurement and one param, the gradient is a float."""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, **_):
qml.RY(a, wires=0)
qml.RX(0.7, wires=0)
@@ -87,12 +92,17 @@ def circuit(a, **_):
assert jac.shape == (num_copies,)
def test_jac_single_measurement_multiple_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""For one measurement and multiple param, the gradient is a tuple of arrays."""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, b, **_):
qml.RY(a, wires=0)
qml.RX(b, wires=0)
@@ -114,12 +124,17 @@ def circuit(a, b, **_):
assert j.shape == (num_copies,)
def test_jacobian_single_measurement_multiple_param_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""For one measurement and multiple param as a single array params, the gradient is an array."""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, **_):
qml.RY(a[0], wires=0)
qml.RX(a[1], wires=0)
@@ -137,13 +152,18 @@ def circuit(a, **_):
assert jac.shape == (num_copies, 2)
def test_jacobian_single_measurement_param_probs(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""For a multi dimensional measurement (probs), check that a single array is returned with the correct
dimension"""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, **_):
qml.RY(a, wires=0)
qml.RX(0.7, wires=0)
@@ -161,13 +181,18 @@ def circuit(a, **_):
assert jac.shape == (num_copies, 4)
def test_jacobian_single_measurement_probs_multiple_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""For a multi dimensional measurement (probs), check that a single tuple is returned containing arrays with
the correct dimension"""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, b, **_):
qml.RY(a, wires=0)
qml.RX(b, wires=0)
@@ -189,13 +214,18 @@ def circuit(a, b, **_):
assert j.shape == (num_copies, 4)
def test_jacobian_single_measurement_probs_multiple_param_single_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""For a multi dimensional measurement (probs), check that a single tuple is returned containing arrays with
the correct dimension"""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, **_):
qml.RY(a[0], wires=0)
qml.RX(a[1], wires=0)
@@ -213,14 +243,20 @@ def circuit(a, **_):
assert jac.shape == (num_copies, 4, 2)
def test_jacobian_expval_expval_multiple_params(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""The gradient of multiple measurements with multiple params return a tuple of arrays."""
par_0 = tf.Variable(1.5, dtype=tf.float64)
par_1 = tf.Variable(0.7, dtype=tf.float64)
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, max_diff=1, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ max_diff=1,
+ **gradient_kwargs,
+ )
def circuit(x, y, **_):
qml.RX(x, wires=[0])
qml.RY(y, wires=[1])
@@ -240,12 +276,17 @@ def circuit(x, y, **_):
assert j.shape == (num_copies, 2)
def test_jacobian_expval_expval_multiple_params_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, **_):
qml.RY(a[0], wires=0)
qml.RX(a[1], wires=0)
@@ -264,12 +305,17 @@ def circuit(a, **_):
assert jac.shape == (num_copies, 2, 3)
def test_jacobian_multiple_measurement_single_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""The jacobian of multiple measurements with a single params return an array."""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, **_):
qml.RY(a, wires=0)
qml.RX(0.7, wires=0)
@@ -287,12 +333,17 @@ def circuit(a, **_):
assert jac.shape == (num_copies, 5)
def test_jacobian_multiple_measurement_multiple_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, diff_method, gradient_kwargs, shots, num_copies, decorator, interface, seed
):
"""The jacobian of multiple measurements with a multiple params return a tuple of arrays."""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, b, **_):
qml.RY(a, wires=0)
qml.RX(b, wires=0)
@@ -314,12 +365,17 @@ def circuit(a, b, **_):
assert j.shape == (num_copies, 5)
def test_jacobian_multiple_measurement_multiple_param_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(a, **_):
qml.RY(a[0], wires=0)
qml.RX(a[1], wires=0)
@@ -339,7 +395,7 @@ def circuit(a, **_):
@pytest.mark.slow
@pytest.mark.parametrize("shots,num_copies", shots_and_num_copies_hess)
-@pytest.mark.parametrize("dev,diff_method", qubit_device_and_diff_method)
+@pytest.mark.parametrize("dev_name,diff_method", qubit_device_and_diff_method)
@pytest.mark.parametrize(
"decorator,interface",
[(tf.function, "tf"), (lambda x: x, "tf-autograph")],
@@ -348,7 +404,7 @@ class TestReturnShotVectorHessian:
"""Class to test the shape of the Hessian with different return types and shot vectors."""
def test_hessian_expval_multiple_params(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""The hessian of a single measurement with multiple params return a tuple of arrays."""
@@ -360,7 +416,13 @@ def test_hessian_expval_multiple_params(
par_1 = tf.Variable(0.7, dtype=tf.float64)
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, max_diff=2, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ max_diff=2,
+ **gradient_kwargs,
+ )
def circuit(x, y, **_):
qml.RX(x, wires=[0])
qml.RY(y, wires=[1])
@@ -388,7 +450,7 @@ def circuit(x, y, **_):
@pytest.mark.parametrize("shots,num_copies", shots_and_num_copies)
-@pytest.mark.parametrize("dev,diff_method", qubit_device_and_diff_method)
+@pytest.mark.parametrize("dev_name,diff_method", qubit_device_and_diff_method)
@pytest.mark.parametrize(
"decorator,interface",
[(tf.function, "tf"), (lambda x: x, "tf-autograph")],
@@ -397,7 +459,7 @@ class TestReturnShotVectorIntegration:
"""Tests for the integration of shots with the TF interface."""
def test_single_expectation_value(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""Tests correct output shape and evaluation for a tape
with a single expval output"""
@@ -405,7 +467,12 @@ def test_single_expectation_value(
y = tf.Variable(-0.654, dtype=tf.float64)
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(x, y, **_):
qml.RX(x, wires=[0])
qml.RY(y, wires=[1])
@@ -430,7 +497,7 @@ def circuit(x, y, **_):
assert np.allclose(res, exp, atol=tol, rtol=0)
def test_prob_expectation_values(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
+ self, dev_name, seed, diff_method, gradient_kwargs, shots, num_copies, decorator, interface
):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
@@ -438,7 +505,12 @@ def test_prob_expectation_values(
y = tf.Variable(-0.654, dtype=tf.float64)
@decorator
- @qnode(dev, diff_method=diff_method, interface=interface, **gradient_kwargs)
+ @qnode(
+ qml.device(dev_name, seed=seed),
+ diff_method=diff_method,
+ interface=interface,
+ **gradient_kwargs,
+ )
def circuit(x, y, **_):
qml.RX(x, wires=[0])
qml.RY(y, wires=[1])
diff --git a/tests/interfaces/test_tensorflow_qnode.py b/tests/interfaces/test_tensorflow_qnode.py
index c01d32091c6..109f5d5cf4e 100644
--- a/tests/interfaces/test_tensorflow_qnode.py
+++ b/tests/interfaces/test_tensorflow_qnode.py
@@ -42,7 +42,6 @@
]
TOL_FOR_SPSA = 1.0
-SEED_FOR_SPSA = 32651
H_FOR_SPSA = 0.01
interface_and_qubit_device_and_diff_method = [
@@ -163,7 +162,7 @@ def circuit(p1, p2=y, **kwargs):
expected = "0: ──RX(0.10)──RX(0.40)─╭●─┤ \n1: ──RY(0.06)───────────╰X─┤ "
assert result == expected
- def test_jacobian(self, dev, diff_method, grad_on_execution, device_vjp, tol, interface):
+ def test_jacobian(self, dev, diff_method, grad_on_execution, device_vjp, tol, interface, seed):
"""Test jacobian calculation"""
kwargs = {
"diff_method": diff_method,
@@ -172,7 +171,7 @@ def test_jacobian(self, dev, diff_method, grad_on_execution, device_vjp, tol, in
"device_vjp": device_vjp,
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -391,7 +390,7 @@ def circuit(U, a):
assert np.allclose(res, tf.sin(a), atol=tol, rtol=0)
def test_differentiable_expand(
- self, dev, diff_method, grad_on_execution, device_vjp, tol, interface
+ self, dev, diff_method, grad_on_execution, device_vjp, tol, interface, seed
):
"""Test that operation and nested tapes expansion
is differentiable"""
@@ -402,7 +401,7 @@ def test_differentiable_expand(
"device_vjp": device_vjp,
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -564,7 +563,7 @@ class TestQubitIntegration:
"""Tests that ensure various qubit circuits integrate correctly"""
def test_probability_differentiation(
- self, dev, diff_method, grad_on_execution, device_vjp, tol, interface
+ self, dev, diff_method, grad_on_execution, device_vjp, tol, interface, seed
):
"""Tests correct output shape and evaluation for a tape
with multiple probs outputs"""
@@ -579,7 +578,7 @@ def test_probability_differentiation(
"device_vjp": device_vjp,
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -621,7 +620,7 @@ def circuit(x, y):
assert np.allclose(res, expected, atol=tol, rtol=0)
def test_ragged_differentiation(
- self, dev, diff_method, grad_on_execution, device_vjp, tol, interface
+ self, dev, diff_method, grad_on_execution, device_vjp, tol, interface, seed
):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
@@ -636,7 +635,7 @@ def test_ragged_differentiation(
"device_vjp": device_vjp,
}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -964,7 +963,7 @@ def cost_fn(x, y):
@pytest.mark.parametrize("state", [[1], [0, 1]]) # Basis state and state vector
@pytest.mark.parametrize("dtype", ("int32", "int64"))
def test_projector(
- self, state, dev, diff_method, grad_on_execution, device_vjp, tol, interface, dtype
+ self, state, dev, diff_method, grad_on_execution, device_vjp, tol, interface, dtype, seed
):
"""Test that the variance of a projector is correctly returned"""
kwargs = {
@@ -978,7 +977,7 @@ def test_projector(
if diff_method == "hadamard":
pytest.skip("Variance not implemented yet.")
elif diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
if dev.name == "reference.qubit":
@@ -1148,7 +1147,7 @@ def circuit(x, y):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_expansion_analytic(
- self, dev, diff_method, grad_on_execution, device_vjp, max_diff, tol, interface
+ self, dev, diff_method, grad_on_execution, device_vjp, max_diff, tol, interface, seed
):
"""Test that if there are non-commuting groups and the number of shots is None
the first and second order gradients are correctly evaluated"""
@@ -1162,7 +1161,7 @@ def test_hamiltonian_expansion_analytic(
if diff_method in ["adjoint", "hadamard"]:
pytest.skip("The adjoint/hadamard method does not yet support Hamiltonians")
elif diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -1213,7 +1212,7 @@ def circuit(data, weights, coeffs):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_finite_shots(
- self, dev, diff_method, grad_on_execution, device_vjp, max_diff, interface
+ self, dev, diff_method, grad_on_execution, device_vjp, max_diff, interface, seed
):
"""Test that the Hamiltonian is correctly measured if there
are non-commuting groups and the number of shots is finite
@@ -1225,7 +1224,7 @@ def test_hamiltonian_finite_shots(
elif diff_method == "spsa":
gradient_kwargs = {
"h": H_FOR_SPSA,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
"num_directions": 20,
}
tol = TOL_FOR_SPSA
diff --git a/tests/interfaces/test_tensorflow_qnode_shot_vector.py b/tests/interfaces/test_tensorflow_qnode_shot_vector.py
index be55538c3e4..037469657bc 100644
--- a/tests/interfaces/test_tensorflow_qnode_shot_vector.py
+++ b/tests/interfaces/test_tensorflow_qnode_shot_vector.py
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Integration tests for using the TF interface with shot vectors and with a QNode"""
-# pylint: disable=too-many-arguments,unexpected-keyword-arg,redefined-outer-name
+# pylint: disable=too-many-arguments,unexpected-keyword-arg,redefined-outer-name,unused-argument
import pytest
import pennylane as qml
@@ -54,7 +54,9 @@
def gradient_kwargs(request):
diff_method = request.node.funcargs["diff_method"]
return kwargs[diff_method] | (
- {"sampler_rng": np.random.default_rng(42)} if diff_method == "spsa" else {}
+ {"sampler_rng": np.random.default_rng(request.getfixturevalue("seed"))}
+ if diff_method == "spsa"
+ else {}
)
@@ -64,7 +66,7 @@ class TestReturnWithShotVectors:
"""Class to test the shape of the Grad/Jacobian/Hessian with different return types and shot vectors."""
def test_jac_single_measurement_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""For one measurement and one param, the gradient is a float."""
@@ -86,7 +88,7 @@ def circuit(a):
assert jac.shape == (num_copies,)
def test_jac_single_measurement_multiple_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""For one measurement and multiple param, the gradient is a tuple of arrays."""
@@ -112,7 +114,7 @@ def circuit(a, b):
assert j.shape == (num_copies,)
def test_jacobian_single_measurement_multiple_param_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""For one measurement and multiple param as a single array params, the gradient is an array."""
@@ -134,7 +136,7 @@ def circuit(a):
assert jac.shape == (num_copies, 2)
def test_jacobian_single_measurement_param_probs(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""For a multi dimensional measurement (probs), check that a single array is returned with the correct
dimension"""
@@ -157,7 +159,7 @@ def circuit(a):
assert jac.shape == (num_copies, 4)
def test_jacobian_single_measurement_probs_multiple_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""For a multi dimensional measurement (probs), check that a single tuple is returned containing arrays with
the correct dimension"""
@@ -184,7 +186,7 @@ def circuit(a, b):
assert j.shape == (num_copies, 4)
def test_jacobian_single_measurement_probs_multiple_param_single_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""For a multi dimensional measurement (probs), check that a single tuple is returned containing arrays with
the correct dimension"""
@@ -207,7 +209,7 @@ def circuit(a):
assert jac.shape == (num_copies, 4, 2)
def test_jacobian_expval_expval_multiple_params(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The gradient of multiple measurements with multiple params return a tuple of arrays."""
@@ -234,7 +236,7 @@ def circuit(x, y):
assert j.shape == (num_copies, 2)
def test_jacobian_expval_expval_multiple_params_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
@@ -257,7 +259,7 @@ def circuit(a):
assert jac.shape == (num_copies, 2, 3)
def test_jacobian_multiple_measurement_single_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The jacobian of multiple measurements with a single params return an array."""
@@ -279,7 +281,7 @@ def circuit(a):
assert jac.shape == (num_copies, 5)
def test_jacobian_multiple_measurement_multiple_param(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The jacobian of multiple measurements with a multiple params return a tuple of arrays."""
@@ -305,7 +307,7 @@ def circuit(a, b):
assert j.shape == (num_copies, 5)
def test_jacobian_multiple_measurement_multiple_param_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The jacobian of multiple measurements with a multiple params array return a single array."""
@@ -334,7 +336,7 @@ class TestReturnShotVectorHessian:
"""Class to test the shape of the Hessian with different return types and shot vectors."""
def test_hessian_expval_multiple_params(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The hessian of a single measurement with multiple params return a tuple of arrays."""
@@ -365,7 +367,7 @@ def circuit(x, y):
assert h.shape == (2, num_copies)
def test_hessian_expval_multiple_param_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The hessian of single measurement with a multiple params array return a single array."""
@@ -391,7 +393,7 @@ def circuit(x):
assert hess.shape == (num_copies, 2, 2)
def test_hessian_probs_expval_multiple_params(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The hessian of multiple measurements with multiple params return a tuple of arrays."""
@@ -422,7 +424,7 @@ def circuit(x, y):
assert h.shape == (2, num_copies, 3)
def test_hessian_expval_probs_multiple_param_array(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""The hessian of multiple measurements with a multiple param array return a single array."""
@@ -457,7 +459,7 @@ class TestReturnShotVectorIntegration:
"""Tests for the integration of shots with the TF interface."""
def test_single_expectation_value(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""Tests correct output shape and evaluation for a tape
with a single expval output"""
@@ -490,7 +492,7 @@ def circuit(x, y):
assert np.allclose(res, exp, atol=tol, rtol=0)
def test_prob_expectation_values(
- self, dev, diff_method, gradient_kwargs, shots, num_copies, interface
+ self, dev, diff_method, gradient_kwargs, shots, num_copies, interface, seed
):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
diff --git a/tests/interfaces/test_torch.py b/tests/interfaces/test_torch.py
index d70fdcc39c1..8b1d5ddb978 100644
--- a/tests/interfaces/test_torch.py
+++ b/tests/interfaces/test_torch.py
@@ -127,17 +127,23 @@ def cost_cache(x):
assert expected_runs_ideal < expected_runs
+def get_device(dev_name, seed):
+ if dev_name == "param_shift.qubit":
+ return ParamShiftDerivativesDevice(seed=seed)
+ return qml.device(dev_name, seed=seed)
+
+
# add tests for lightning 2 when possible
# set rng for device when possible
test_matrix = [
- ({"gradient_fn": param_shift}, Shots(100000), DefaultQubit(seed=42)),
- ({"gradient_fn": param_shift}, Shots((100000, 100000)), DefaultQubit(seed=42)),
- ({"gradient_fn": param_shift}, Shots(None), DefaultQubit()),
- ({"gradient_fn": "backprop"}, Shots(None), DefaultQubit()),
+ ({"gradient_fn": param_shift}, Shots(100000), "default.qubit"),
+ ({"gradient_fn": param_shift}, Shots((100000, 100000)), "default.qubit"),
+ ({"gradient_fn": param_shift}, Shots(None), "default.qubit"),
+ ({"gradient_fn": "backprop"}, Shots(None), "default.qubit"),
(
{"gradient_fn": "adjoint", "grad_on_execution": True, "device_vjp": False},
Shots(None),
- DefaultQubit(),
+ "default.qubit",
),
(
{
@@ -146,35 +152,25 @@ def cost_cache(x):
"device_vjp": False,
},
Shots(None),
- DefaultQubit(),
- ),
- ({"gradient_fn": "adjoint", "device_vjp": True}, Shots(None), DefaultQubit()),
- (
- {"gradient_fn": "device", "device_vjp": False},
- Shots((100000, 100000)),
- ParamShiftDerivativesDevice(seed=42),
- ),
- (
- {"gradient_fn": "device", "device_vjp": True},
- Shots((100000, 100000)),
- ParamShiftDerivativesDevice(seed=42),
+ "default.qubit",
),
+ ({"gradient_fn": "adjoint", "device_vjp": True}, Shots(None), "default.qubit"),
+ ({"gradient_fn": "device", "device_vjp": False}, Shots((100000, 100000)), "param_shift.qubit"),
+ ({"gradient_fn": "device", "device_vjp": True}, Shots((100000, 100000)), "param_shift.qubit"),
(
{"gradient_fn": param_shift},
Shots(None),
- qml.device(
- "reference.qubit",
- ),
+ "reference.qubit",
),
(
{"gradient_fn": param_shift},
Shots(100000),
- qml.device("reference.qubit", seed=42),
+ "reference.qubit",
),
(
{"gradient_fn": param_shift},
Shots((100000, 100000)),
- qml.device("reference.qubit", seed=42),
+ "reference.qubit",
),
]
@@ -184,14 +180,16 @@ def atol_for_shots(shots):
return 1e-2 if shots else 1e-6
-@pytest.mark.parametrize("execute_kwargs, shots, device", test_matrix)
+@pytest.mark.parametrize("execute_kwargs, shots, device_name", test_matrix)
class TestTorchExecuteIntegration:
"""Test the torch interface execute function
integrates well for both forward and backward execution"""
- def test_execution(self, execute_kwargs, shots, device):
+ def test_execution(self, execute_kwargs, shots, device_name, seed):
"""Test execution"""
+ device = get_device(device_name, seed)
+
def cost(a, b):
ops1 = [qml.RY(a, wires=0), qml.RX(b, wires=0)]
tape1 = qml.tape.QuantumScript(ops1, [qml.expval(qml.PauliZ(0))], shots=shots)
@@ -226,9 +224,10 @@ def cost(a, b):
for wire in range(2):
assert qml.math.allclose(res[wire], exp, atol=atol_for_shots(shots))
- def test_scalar_jacobian(self, execute_kwargs, shots, device):
+ def test_scalar_jacobian(self, execute_kwargs, shots, device_name, seed):
"""Test scalar jacobian calculation"""
a = torch.tensor(0.1, requires_grad=True)
+ device = get_device(device_name, seed)
def cost(a):
tape = qml.tape.QuantumScript([qml.RY(a, 0)], [qml.expval(qml.PauliZ(0))], shots=shots)
@@ -253,11 +252,14 @@ def cost(a):
assert torch.allclose(res, expected, atol=atol_for_shots(shots), rtol=0)
assert torch.allclose(res, -torch.sin(a), atol=atol_for_shots(shots))
- def test_jacobian(self, execute_kwargs, shots, device):
+ @pytest.mark.local_salt(1)
+ def test_jacobian(self, execute_kwargs, shots, device_name, seed):
"""Test jacobian calculation"""
a = torch.tensor(0.1, requires_grad=True)
b = torch.tensor(0.2, requires_grad=True)
+ device = get_device(device_name, seed)
+
def cost(a, b):
ops = [qml.RY(a, wires=0), qml.RX(b, wires=1), qml.CNOT(wires=[0, 1])]
m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliY(1))]
@@ -297,10 +299,12 @@ def cost(a, b):
for _r, _e in zip(res, expected):
assert torch.allclose(_r, _e, atol=atol_for_shots(shots))
- def test_tape_no_parameters(self, execute_kwargs, shots, device):
+ def test_tape_no_parameters(self, execute_kwargs, shots, device_name, seed):
"""Test that a tape with no parameters is correctly
ignored during the gradient computation"""
+ device = get_device(device_name, seed)
+
def cost(params):
tape1 = qml.tape.QuantumScript(
[qml.Hadamard(0)], [qml.expval(qml.PauliX(0))], shots=shots
@@ -349,12 +353,14 @@ def cost(params):
assert torch.allclose(params.grad, expected, atol=atol_for_shots(shots), rtol=0)
@pytest.mark.skip("torch cannot reuse tensors in various computations")
- def test_tapes_with_different_return_size(self, execute_kwargs, shots, device):
+ def test_tapes_with_different_return_size(self, execute_kwargs, shots, device_name, seed):
"""Test that tapes wit different can be executed and differentiated."""
if execute_kwargs["gradient_fn"] == "backprop":
pytest.xfail("backprop is not compatible with something about this situation.")
+ device = get_device(device_name, seed)
+
def cost(params):
tape1 = qml.tape.QuantumScript(
[qml.RY(params[0], 0), qml.RX(params[1], 0)],
@@ -402,10 +408,11 @@ def cost(params):
assert torch.allclose(jac[0, 1], d2, atol=atol_for_shots(shots)) # fails for torch
assert torch.allclose(jac[3, 1], d2, atol=atol_for_shots(shots))
- def test_reusing_quantum_tape(self, execute_kwargs, shots, device):
+ def test_reusing_quantum_tape(self, execute_kwargs, shots, device_name, seed):
"""Test re-using a quantum tape by passing new parameters"""
a = torch.tensor(0.1, requires_grad=True)
b = torch.tensor(0.2, requires_grad=True)
+ device = get_device(device_name, seed)
tape = qml.tape.QuantumScript(
[qml.RY(a, 0), qml.RX(b, 1), qml.CNOT((0, 1))],
@@ -437,11 +444,12 @@ def cost(a, b):
for _j, _e in zip(jac, expected):
assert torch.allclose(_j, _e, atol=atol_for_shots(shots), rtol=0)
- def test_classical_processing(self, execute_kwargs, device, shots):
+ def test_classical_processing(self, execute_kwargs, device_name, seed, shots):
"""Test classical processing within the quantum tape"""
a = torch.tensor(0.1, requires_grad=True)
b = torch.tensor(0.2, requires_grad=False)
c = torch.tensor(0.3, requires_grad=True)
+ device = get_device(device_name, seed)
def cost(a, b, c):
ops = [
@@ -466,11 +474,13 @@ def cost(a, b, c):
# I tried getting analytic results for this circuit but I kept being wrong and am giving up
@pytest.mark.skip("torch handles gradients and jacobians differently")
- def test_no_trainable_parameters(self, execute_kwargs, shots, device):
+ def test_no_trainable_parameters(self, execute_kwargs, shots, device_name, seed):
"""Test evaluation and Jacobian if there are no trainable parameters"""
a = torch.tensor(0.1, requires_grad=False)
b = torch.tensor(0.2, requires_grad=False)
+ device = get_device(device_name, seed)
+
def cost(a, b):
ops = [qml.RY(a, 0), qml.RX(b, 0), qml.CNOT((0, 1))]
m = [qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1))]
@@ -491,11 +501,12 @@ def loss(a, b):
assert torch.allclose(torch.tensor([a.grad, b.grad]), 0)
- def test_matrix_parameter(self, execute_kwargs, device, shots):
+ def test_matrix_parameter(self, execute_kwargs, device_name, seed, shots):
"""Test that the torch interface works correctly
with a matrix parameter"""
U = torch.tensor([[0, 1], [1, 0]], requires_grad=False, dtype=torch.float64)
a = torch.tensor(0.1, requires_grad=True)
+ device = get_device(device_name, seed)
def cost(a, U):
ops = [qml.QubitUnitary(U, wires=0), qml.RY(a, wires=0)]
@@ -509,10 +520,12 @@ def cost(a, U):
assert isinstance(jac, torch.Tensor)
assert torch.allclose(jac, torch.sin(a), atol=atol_for_shots(shots), rtol=0)
- def test_differentiable_expand(self, execute_kwargs, device, shots):
+ def test_differentiable_expand(self, execute_kwargs, device_name, seed, shots):
"""Test that operation and nested tapes expansion
is differentiable"""
+ device = get_device(device_name, seed)
+
class U3(qml.U3):
"""Dummy operator."""
@@ -575,9 +588,10 @@ def cost_fn(a, p):
)
assert torch.allclose(res, expected, atol=atol_for_shots(shots), rtol=0)
- def test_probability_differentiation(self, execute_kwargs, device, shots):
+ def test_probability_differentiation(self, execute_kwargs, device_name, seed, shots):
"""Tests correct output shape and evaluation for a tape
with prob outputs"""
+ device = get_device(device_name, seed)
def cost(x, y):
ops = [qml.RX(x, 0), qml.RY(y, 1), qml.CNOT((0, 1))]
@@ -627,9 +641,10 @@ def cost(x, y):
assert torch.allclose(res[0], expected[0], atol=atol_for_shots(shots), rtol=0)
assert torch.allclose(res[1], expected[1], atol=atol_for_shots(shots), rtol=0)
- def test_ragged_differentiation(self, execute_kwargs, device, shots):
+ def test_ragged_differentiation(self, execute_kwargs, device_name, seed, shots):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
+ device = get_device(device_name, seed)
def cost(x, y):
ops = [qml.RX(x, wires=0), qml.RY(y, 1), qml.CNOT((0, 1))]
@@ -742,15 +757,16 @@ def cost_fn(x):
assert torch.allclose(res, expected, atol=tol, rtol=0)
-@pytest.mark.parametrize("execute_kwargs, shots, device", test_matrix)
+@pytest.mark.parametrize("execute_kwargs, shots, device_name", test_matrix)
@pytest.mark.usefixtures("use_legacy_and_new_opmath")
class TestHamiltonianWorkflows:
"""Test that tapes ending with expectations
of Hamiltonians provide correct results and gradients"""
@pytest.fixture
- def cost_fn(self, execute_kwargs, shots, device):
+ def cost_fn(self, execute_kwargs, shots, device_name, seed):
"""Cost function for gradient tests"""
+ device = get_device(device_name, seed)
def _cost_fn(weights, coeffs1, coeffs2):
obs1 = [qml.PauliZ(0), qml.PauliZ(0) @ qml.PauliX(1), qml.PauliY(0)]
diff --git a/tests/interfaces/test_torch_qnode.py b/tests/interfaces/test_torch_qnode.py
index 5ecf181d343..c71b74108be 100644
--- a/tests/interfaces/test_torch_qnode.py
+++ b/tests/interfaces/test_torch_qnode.py
@@ -55,7 +55,6 @@
] + [["torch"] + inner_list for inner_list in qubit_device_and_diff_method]
TOL_FOR_SPSA = 1.0
-SEED_FOR_SPSA = 32651
H_FOR_SPSA = 0.01
@@ -168,7 +167,7 @@ def circuit(p1, p2=y, **kwargs):
assert result == expected
- def test_jacobian(self, interface, dev, diff_method, grad_on_execution, device_vjp, tol):
+ def test_jacobian(self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed):
"""Test jacobian calculation"""
kwargs = dict(
diff_method=diff_method,
@@ -177,7 +176,7 @@ def test_jacobian(self, interface, dev, diff_method, grad_on_execution, device_v
device_vjp=device_vjp,
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -495,7 +494,7 @@ def circuit(U, a):
assert np.allclose(a.grad, np.sin(a_val), atol=tol, rtol=0)
def test_differentiable_expand(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Test that operation and nested tapes expansion
is differentiable"""
@@ -506,7 +505,7 @@ def test_differentiable_expand(
device_vjp=device_vjp,
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -662,7 +661,7 @@ class TestQubitIntegration:
"""Tests that ensure various qubit circuits integrate correctly"""
def test_probability_differentiation(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
@@ -670,7 +669,7 @@ def test_probability_differentiation(
pytest.xfail("lightning does not support measureing probabilities with adjoint.")
kwargs = {}
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
tol = TOL_FOR_SPSA
x_val = 0.543
@@ -720,7 +719,7 @@ def circuit(x, y):
assert np.allclose(jac[1][1], res_3, atol=tol, rtol=0)
def test_ragged_differentiation(
- self, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Tests correct output shape and evaluation for a tape
with prob and expval outputs"""
@@ -733,7 +732,7 @@ def test_ragged_differentiation(
device_vjp=device_vjp,
)
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
@@ -1115,7 +1114,7 @@ def cost_fn(x, y):
@pytest.mark.parametrize("state", [[1], [0, 1]]) # Basis state and state vector
def test_projector(
- self, state, interface, dev, diff_method, grad_on_execution, device_vjp, tol
+ self, state, interface, dev, diff_method, grad_on_execution, device_vjp, tol, seed
):
"""Test that the variance of a projector is correctly returned"""
kwargs = dict(
@@ -1127,7 +1126,7 @@ def test_projector(
if diff_method == "adjoint":
pytest.skip("adjoint supports either all expvals or all diagonal measurements")
if diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
elif diff_method == "hadamard":
@@ -1297,7 +1296,7 @@ def circuit(x, y):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_expansion_analytic(
- self, dev, diff_method, grad_on_execution, max_diff, device_vjp, tol
+ self, dev, diff_method, grad_on_execution, max_diff, device_vjp, tol, seed
):
"""Test that if there
are non-commuting groups and the number of shots is None
@@ -1312,7 +1311,7 @@ def test_hamiltonian_expansion_analytic(
if diff_method == "adjoint":
pytest.skip("The adjoint method does not yet support Hamiltonians")
elif diff_method == "spsa":
- kwargs["sampler_rng"] = np.random.default_rng(SEED_FOR_SPSA)
+ kwargs["sampler_rng"] = np.random.default_rng(seed)
kwargs["num_directions"] = 20
tol = TOL_FOR_SPSA
elif diff_method == "hadamard":
@@ -1382,7 +1381,7 @@ def circuit(data, weights, coeffs):
@pytest.mark.parametrize("max_diff", [1, 2])
def test_hamiltonian_finite_shots(
- self, dev, diff_method, device_vjp, grad_on_execution, max_diff
+ self, dev, diff_method, device_vjp, grad_on_execution, max_diff, seed
):
"""Test that the Hamiltonian is correctly measured if there
are non-commuting groups and the number of shots is finite
@@ -1394,7 +1393,7 @@ def test_hamiltonian_finite_shots(
elif diff_method == "spsa":
gradient_kwargs = {
"h": H_FOR_SPSA,
- "sampler_rng": np.random.default_rng(SEED_FOR_SPSA),
+ "sampler_rng": np.random.default_rng(seed),
"num_directions": 20,
}
tol = TOL_FOR_SPSA
diff --git a/tests/measurements/test_counts.py b/tests/measurements/test_counts.py
index 08da35015c9..e49ab042718 100644
--- a/tests/measurements/test_counts.py
+++ b/tests/measurements/test_counts.py
@@ -91,10 +91,10 @@ def test_repr(self):
class TestProcessSamples:
"""Unit tests for the counts.process_samples method"""
- def test_counts_shape_single_wires(self):
+ def test_counts_shape_single_wires(self, seed):
"""Test that the counts output is correct for single wires"""
shots = 1000
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
result = qml.counts(wires=0).process_samples(samples, wire_order=[0])
@@ -104,11 +104,11 @@ def test_counts_shape_single_wires(self):
assert result["0"] == np.count_nonzero(samples[:, 0] == 0)
assert result["1"] == np.count_nonzero(samples[:, 0] == 1)
- def test_counts_shape_multi_wires(self):
+ def test_counts_shape_multi_wires(self, seed):
"""Test that the counts function outputs counts of the right size
for multiple wires"""
shots = 1000
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
result = qml.counts(wires=[0, 1]).process_samples(samples, wire_order=[0, 1])
@@ -128,11 +128,11 @@ def test_counts_shape_multi_wires(self):
np.logical_and(samples[:, 0] == 1, samples[:, 1] == 1)
)
- def test_counts_with_nan_samples(self):
+ def test_counts_with_nan_samples(self, seed):
"""Test that the counts function disregards failed measurements (samples including
NaN values) when totalling counts"""
shots = 1000
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.float64)
samples[0][0] = np.nan
@@ -173,10 +173,10 @@ def test_counts_multi_wires_no_overflow(self, n_wires, all_outcomes, batch_size)
assert sum(result.values()) == shots
assert all("-" not in sample for sample in result.keys())
- def test_counts_obs(self):
+ def test_counts_obs(self, seed):
"""Test that the counts function outputs counts of the right size for observables"""
shots = 1000
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
result = qml.counts(qml.PauliZ(0)).process_samples(samples, wire_order=[0])
@@ -186,11 +186,11 @@ def test_counts_obs(self):
assert result[1] == np.count_nonzero(samples[:, 0] == 0)
assert result[-1] == np.count_nonzero(samples[:, 0] == 1)
- def test_count_eigvals(self):
+ def test_count_eigvals(self, seed):
"""Tests that eigvals are used instead of obs for counts"""
shots = 100
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
result = CountsMP(eigvals=[1, -1], wires=0).process_samples(samples, wire_order=[0])
assert len(result) == 2
@@ -198,11 +198,11 @@ def test_count_eigvals(self):
assert result[1] == np.count_nonzero(samples[:, 0] == 0)
assert result[-1] == np.count_nonzero(samples[:, 0] == 1)
- def test_counts_shape_single_measurement_value(self):
+ def test_counts_shape_single_measurement_value(self, seed):
"""Test that the counts output is correct for single mid-circuit measurement
values."""
shots = 1000
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
mv = qml.measure(0)
@@ -213,11 +213,11 @@ def test_counts_shape_single_measurement_value(self):
assert result[0] == np.count_nonzero(samples[:, 0] == 0)
assert result[1] == np.count_nonzero(samples[:, 0] == 1)
- def test_counts_shape_composite_measurement_value(self):
+ def test_counts_shape_composite_measurement_value(self, seed):
"""Test that the counts output is correct for composite mid-circuit measurement
values."""
shots = 1000
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
m0 = qml.measure(0)
m1 = qml.measure(1)
@@ -230,11 +230,11 @@ def test_counts_shape_composite_measurement_value(self):
assert result[0] == np.count_nonzero(samples == 0)
assert result[1] == np.count_nonzero(samples == 1)
- def test_counts_shape_measurement_value_list(self):
+ def test_counts_shape_measurement_value_list(self, seed):
"""Test that the counts output is correct for list mid-circuit measurement
values."""
shots = 1000
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
m0 = qml.measure(0)
m1 = qml.measure(1)
diff --git a/tests/measurements/test_expval.py b/tests/measurements/test_expval.py
index 2ff27d0a91c..0aebcec600c 100644
--- a/tests/measurements/test_expval.py
+++ b/tests/measurements/test_expval.py
@@ -109,11 +109,11 @@ def circuit(phi):
@pytest.mark.parametrize("shots", [None, 1111, [1111, 1111]])
@pytest.mark.parametrize("phi", np.arange(0, 2 * np.pi, np.pi / 3))
def test_observable_is_composite_measurement_value(
- self, shots, phi, tol, tol_stochastic
+ self, shots, phi, tol, tol_stochastic, seed
): # pylint: disable=too-many-arguments
"""Test that expectation values for mid-circuit measurement values
are correct for a composite measurement value."""
- dev = qml.device("default.qubit", seed=123)
+ dev = qml.device("default.qubit", seed=seed)
@qml.qnode(dev)
def circuit(phi):
@@ -144,11 +144,11 @@ def expected_circuit(phi):
res = func(phi, shots=shots)
assert np.allclose(np.array(res), expected, atol=atol, rtol=0)
- def test_eigvals_instead_of_observable(self):
+ def test_eigvals_instead_of_observable(self, seed):
"""Tests process samples with eigvals instead of observables"""
shots = 100
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
expected = qml.expval(qml.PauliZ(0)).process_samples(samples, [0, 1])
assert (
@@ -186,12 +186,13 @@ def test_shape(self, obs):
assert res.shape(None, 1) == ()
assert res.shape(100, 1) == ()
+ @pytest.mark.local_salt(2)
@pytest.mark.parametrize("state", [np.array([0, 0, 0]), np.array([1, 0, 0, 0, 0, 0, 0, 0])])
@pytest.mark.parametrize("shots", [None, 1000, [1000, 1111]])
- def test_projector_expval(self, state, shots):
+ def test_projector_expval(self, state, shots, seed):
"""Tests that the expectation of a ``Projector`` object is computed correctly for both of
its subclasses."""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=123)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit():
@@ -335,7 +336,7 @@ def test_expval_process_density_matrix_no_wires(self, state, expected):
result = mp.process_density_matrix(state, wire_order=qml.wires.Wires([0]))
assert np.allclose(result, expected)
- def test_batched_hamiltonian(self):
+ def test_batched_hamiltonian(self, seed):
"""Test that the expval interface works"""
dev = qml.device("default.qubit")
ops = (qml.Hadamard(0), qml.PauliZ(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliX(3))
@@ -347,7 +348,7 @@ def cost_circuit(params):
qml.CNOT([0, 1])
return qml.expval(H)
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
params = rng.normal(0, np.pi, 4)
energy = [cost_circuit(p) for p in params]
energy_batched = cost_circuit(params)
diff --git a/tests/measurements/test_probs.py b/tests/measurements/test_probs.py
index 3c04b6de861..03e4b78d797 100644
--- a/tests/measurements/test_probs.py
+++ b/tests/measurements/test_probs.py
@@ -12,6 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Unit tests for the probs module"""
+
+# pylint:disable=too-many-arguments
+
from collections.abc import Sequence
import numpy as np
@@ -27,9 +30,9 @@
def fixture_init_state():
"""Fixture that creates an initial state"""
- def _init_state(n):
+ def _init_state(n, seed):
"""An initial state over n wires"""
- rng = np.random.default_rng(42)
+ rng = np.random.default_rng(seed)
state = rng.random([2**n]) + rng.random([2**n]) * 1j
state /= np.linalg.norm(state)
return state
@@ -104,11 +107,11 @@ def circuit():
assert qml.math.allequal(res, [1, 0, 0, 0, 0, 0, 0, 0])
- def test_full_prob(self, init_state, tol):
+ def test_full_prob(self, init_state, tol, seed):
"""Test that the correct probability is returned."""
dev = qml.device("default.qubit", wires=4)
- state = init_state(4)
+ state = init_state(4, seed)
@qml.qnode(dev)
def circuit():
@@ -119,11 +122,11 @@ def circuit():
expected = np.abs(state) ** 2
assert np.allclose(res, expected, atol=tol, rtol=0)
- def test_marginal_prob(self, init_state, tol):
+ def test_marginal_prob(self, init_state, tol, seed):
"""Test that the correct marginal probability is returned."""
dev = qml.device("default.qubit", wires=4)
- state = init_state(4)
+ state = init_state(4, seed)
@qml.qnode(dev)
def circuit():
@@ -135,11 +138,11 @@ def circuit():
expected = np.einsum("ijkl->jl", expected).flatten()
assert np.allclose(res, expected, atol=tol, rtol=0)
- def test_marginal_prob_more_wires(self, init_state, tol):
+ def test_marginal_prob_more_wires(self, init_state, tol, seed):
"""Test that the correct marginal probability is returned, when the
states_to_binary method is used for probability computations."""
dev = qml.device("default.qubit", wires=4)
- state = init_state(4)
+ state = init_state(4, seed)
@qml.qnode(dev)
def circuit():
@@ -332,11 +335,11 @@ def circuit():
@pytest.mark.parametrize("shots", (None, 500))
@pytest.mark.parametrize("obs", ([0, 1], qml.PauliZ(0) @ qml.PauliZ(1)))
@pytest.mark.parametrize("params", ([np.pi / 2], [np.pi / 2, np.pi / 2, np.pi / 2]))
- def test_integration_jax(self, tol_stochastic, shots, obs, params):
+ def test_integration_jax(self, tol_stochastic, shots, obs, params, seed):
"""Test the probability is correct for a known state preparation when jitted with JAX."""
jax = pytest.importorskip("jax")
- dev = qml.device("default.qubit", wires=2, shots=shots, seed=jax.random.PRNGKey(0))
+ dev = qml.device("default.qubit", wires=2, shots=shots, seed=jax.random.PRNGKey(seed))
params = jax.numpy.array(params)
@qml.qnode(dev, diff_method=None)
@@ -635,12 +638,12 @@ def circuit_rotated(x, y):
@pytest.mark.parametrize("hermitian", [1 / np.sqrt(2) * np.array([[1, 1], [1, -1]])])
@pytest.mark.parametrize("wire", [0, 1, 2, 3])
- def test_prob_generalize_initial_state(self, hermitian, wire, init_state, tol):
+ def test_prob_generalize_initial_state(self, hermitian, wire, init_state, tol, seed):
"""Test that the correct probability is returned."""
# pylint:disable=too-many-arguments
dev = qml.device("default.qubit", wires=4)
- state = init_state(4)
+ state = init_state(4, seed)
@qml.qnode(dev)
def circuit():
@@ -677,12 +680,12 @@ def circuit_rotated():
@pytest.mark.parametrize("operation", [qml.PauliX, qml.PauliY, qml.Hadamard])
@pytest.mark.parametrize("wire", [0, 1, 2, 3])
- def test_operation_prob(self, operation, wire, init_state, tol):
+ def test_operation_prob(self, operation, wire, init_state, tol, seed):
"Test the rotated probability with different wires and rotating operations."
# pylint:disable=too-many-arguments
dev = qml.device("default.qubit", wires=4)
- state = init_state(4)
+ state = init_state(4, seed)
@qml.qnode(dev)
def circuit():
@@ -718,11 +721,11 @@ def circuit_rotated():
assert np.allclose(res, expected, atol=tol, rtol=0)
@pytest.mark.parametrize("observable", [(qml.PauliX, qml.PauliY)])
- def test_observable_tensor_prob(self, observable, init_state, tol):
+ def test_observable_tensor_prob(self, observable, init_state, tol, seed):
"Test the rotated probability with a tensor observable."
dev = qml.device("default.qubit", wires=4)
- state = init_state(4)
+ state = init_state(4, seed)
@qml.qnode(dev)
def circuit():
@@ -752,12 +755,12 @@ def circuit_rotated():
assert np.allclose(res, expected, atol=tol, rtol=0)
@pytest.mark.parametrize("coeffs, obs", [([1, 1], [qml.PauliX(wires=0), qml.PauliX(wires=1)])])
- def test_hamiltonian_error(self, coeffs, obs, init_state):
+ def test_hamiltonian_error(self, coeffs, obs, init_state, seed):
"Test that an error is returned for hamiltonians."
H = qml.Hamiltonian(coeffs, obs)
dev = qml.device("default.qubit", wires=4)
- state = init_state(4)
+ state = init_state(4, seed)
@qml.qnode(dev)
def circuit():
diff --git a/tests/measurements/test_var.py b/tests/measurements/test_var.py
index 96da58662ce..3eec826f0dd 100644
--- a/tests/measurements/test_var.py
+++ b/tests/measurements/test_var.py
@@ -15,7 +15,6 @@
import numpy as np
import pytest
-from flaky import flaky
import pennylane as qml
from pennylane.measurements import Variance, VarianceMP
@@ -82,15 +81,14 @@ def circuit(phi):
res = func(phi)
assert np.allclose(np.array(res), expected, atol=atol, rtol=0)
- @flaky(max_runs=5)
@pytest.mark.parametrize("shots", [None, 5555, [5555, 5555]])
@pytest.mark.parametrize("phi", np.arange(0, 2 * np.pi, np.pi / 3))
def test_observable_is_composite_measurement_value(
- self, shots, phi, tol, tol_stochastic
+ self, shots, phi, tol, tol_stochastic, seed
): # pylint: disable=too-many-arguments
"""Test that expectation values for mid-circuit measurement values
are correct for a composite measurement value."""
- dev = qml.device("default.qubit")
+ dev = qml.device("default.qubit", seed=seed)
@qml.qnode(dev)
def circuit(phi):
@@ -122,11 +120,11 @@ def expected_circuit(phi):
res = func(phi, shots=shots)
assert np.allclose(np.array(res), expected, atol=atol, rtol=0)
- def test_eigvals_instead_of_observable(self):
+ def test_eigvals_instead_of_observable(self, seed):
"""Tests process samples with eigvals instead of observables"""
shots = 100
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
samples = rng.choice([0, 1], size=(shots, 2)).astype(np.int64)
expected = qml.var(qml.PauliZ(0)).process_samples(samples, [0, 1])
assert VarianceMP(eigvals=[1, -1], wires=[0]).process_samples(samples, [0, 1]) == expected
diff --git a/tests/ops/op_math/test_adjoint.py b/tests/ops/op_math/test_adjoint.py
index da4a446098c..6017b16bdf9 100644
--- a/tests/ops/op_math/test_adjoint.py
+++ b/tests/ops/op_math/test_adjoint.py
@@ -161,9 +161,9 @@ def test_parametric_ops(self):
assert op.wires == qml.wires.Wires("b")
- def test_template_base(self):
+ def test_template_base(self, seed):
"""Test adjoint initialization for a template."""
- rng = np.random.default_rng(seed=42)
+ rng = np.random.default_rng(seed=seed)
shape = qml.StronglyEntanglingLayers.shape(n_layers=2, n_wires=2)
params = rng.random(shape)
@@ -642,9 +642,9 @@ def test_matrix_tf(self):
self.check_matrix(tf.Variable(1.2345), "tensorflow")
- def test_no_matrix_defined(self):
+ def test_no_matrix_defined(self, seed):
"""Test that if the base has no matrix defined, then Adjoint.matrix also raises a MatrixUndefinedError."""
- rng = np.random.default_rng(seed=42)
+ rng = np.random.default_rng(seed=seed)
shape = qml.StronglyEntanglingLayers.shape(n_layers=2, n_wires=2)
params = rng.random(shape)
@@ -868,6 +868,7 @@ def test_single_op_defined_outside_queue_eager(self):
assert len(q) == 1
assert q.queue[0] is out
+
@pytest.mark.usefixtures("legacy_opmath_only")
def test_single_observable(self):
"""Test passing a single preconstructed observable in a queuing context."""
diff --git a/tests/ops/op_math/test_controlled.py b/tests/ops/op_math/test_controlled.py
index 1cc3c5241f9..03ce3c0bb00 100644
--- a/tests/ops/op_math/test_controlled.py
+++ b/tests/ops/op_math/test_controlled.py
@@ -1872,6 +1872,23 @@ def test_nested_pauli_x_based_ctrl_ops(self):
expected = qml.MultiControlledX(wires=[3, 2, 1, 0], control_values=[1, 0, 1])
assert op == expected
+ def test_correct_queued_operators(self):
+ """Test that args and kwargs do not add operators to the queue."""
+
+ def func(dic):
+ for gate in dic.values():
+ qml.apply(gate)
+
+ dev = qml.device("default.qubit")
+
+ @qml.qnode(dev)
+ def circuit():
+ qml.ctrl(func, control=0)({1: qml.X(1), 2: qml.Z(1)})
+ return qml.state()
+
+ circuit()
+ assert len(circuit.tape.operations) == 2
+
class _Rot(Operation):
"""A rotation operation that is not an instance of Rot
diff --git a/tests/ops/op_math/test_controlled_decompositions.py b/tests/ops/op_math/test_controlled_decompositions.py
index 03290fca0d5..25f1e37f572 100644
--- a/tests/ops/op_math/test_controlled_decompositions.py
+++ b/tests/ops/op_math/test_controlled_decompositions.py
@@ -158,11 +158,11 @@ def decomp_circuit():
decomp_circuit()
@pytest.mark.parametrize("control_wires", ([1], [1, 2], [1, 2, 3]))
- def test_decomposition_circuit_gradient(self, control_wires, tol):
+ def test_decomposition_circuit_gradient(self, control_wires, tol, seed):
"""Tests that the controlled decomposition of a single-qubit operation
behaves as expected in a quantum circuit"""
n_qubits = 4
- rng = np.random.default_rng(1337)
+ rng = np.random.default_rng(seed)
dev = qml.device("default.qubit", wires=n_qubits)
init_state = rng.random(2**n_qubits) + 1.0j * rng.random(2**n_qubits)
diff --git a/tests/ops/op_math/test_pow_op.py b/tests/ops/op_math/test_pow_op.py
index b323744c56f..cefb6bfec10 100644
--- a/tests/ops/op_math/test_pow_op.py
+++ b/tests/ops/op_math/test_pow_op.py
@@ -236,9 +236,9 @@ def test_parametric_ops(self, power_method):
assert op.wires == qml.wires.Wires("b")
assert op.num_wires == 1
- def test_template_base(self, power_method):
+ def test_template_base(self, power_method, seed):
"""Test pow initialization for a template."""
- rng = np.random.default_rng(seed=42)
+ rng = np.random.default_rng(seed=seed)
shape = qml.StronglyEntanglingLayers.shape(n_layers=2, n_wires=2)
params = rng.random(shape) # pylint:disable=no-member
diff --git a/tests/ops/op_math/test_prod.py b/tests/ops/op_math/test_prod.py
index bebc7112f93..1d1c6756e53 100644
--- a/tests/ops/op_math/test_prod.py
+++ b/tests/ops/op_math/test_prod.py
@@ -1425,6 +1425,21 @@ def test_nonlazy_mode_queueing(self):
assert len(q) == 1
assert q.queue[0] is prod2
+ def test_correct_queued_operators(self):
+ """Test that args and kwargs do not add operators to the queue."""
+
+ dev = qml.device("default.qubit")
+
+ @qml.qnode(dev)
+ def circuit():
+ qml.prod(qml.QSVT)(qml.X(1), [qml.Z(1)])
+ qml.prod(qml.QSVT(qml.X(1), [qml.Z(1)]))
+ return qml.state()
+
+ circuit()
+ for op in circuit.tape.operations:
+ assert op.name == "QSVT"
+
class TestIntegration:
"""Integration tests for the Prod class."""
diff --git a/tests/ops/qubit/test_matrix_ops.py b/tests/ops/qubit/test_matrix_ops.py
index 54e56e1d3c5..c432eacf2b7 100644
--- a/tests/ops/qubit/test_matrix_ops.py
+++ b/tests/ops/qubit/test_matrix_ops.py
@@ -385,9 +385,9 @@ def test_compare_analytic_results(self, inp, exp):
@pytest.mark.parametrize("n", [1, 2, 3])
@pytest.mark.parametrize("provide_n", [True, False])
- def test_compare_matrix_mult(self, n, provide_n):
+ def test_compare_matrix_mult(self, n, provide_n, seed):
"""Test against matrix multiplication for a few random inputs."""
- rng = np.random.default_rng(382)
+ rng = np.random.default_rng(seed)
inp = rng.random(2**n)
output = _walsh_hadamard_transform(inp, n=n if provide_n else None)
h = np.array([[0.5, 0.5], [0.5, -0.5]])
@@ -404,9 +404,9 @@ def test_compare_analytic_results_broadcasted(self):
@pytest.mark.parametrize("n", [1, 2, 3])
@pytest.mark.parametrize("provide_n", [True, False])
- def test_compare_matrix_mult_broadcasted(self, n, provide_n):
+ def test_compare_matrix_mult_broadcasted(self, n, provide_n, seed):
"""Test against matrix multiplication for a few random inputs."""
- rng = np.random.default_rng(382)
+ rng = np.random.default_rng(seed)
inp = rng.random((5, 2**n))
output = _walsh_hadamard_transform(inp, n=n if provide_n else None)
h = np.array([[0.5, 0.5], [0.5, -0.5]])
@@ -529,9 +529,9 @@ def test_decomposition_three_qubits_broadcasted(self):
qml.assert_equal(decomp[7], qml.MultiRZ(angles[6], [0, 1, 2]))
@pytest.mark.parametrize("n", [1, 2, 3])
- def test_decomposition_matrix_match(self, n):
+ def test_decomposition_matrix_match(self, n, seed):
"""Test that the matrix of the decomposition matches the original matrix."""
- rng = np.random.default_rng(382)
+ rng = np.random.default_rng(seed)
D = np.exp(1j * rng.random(2**n))
wires = list(range(n))
decomp = qml.DiagonalQubitUnitary.compute_decomposition(D, wires)
@@ -544,9 +544,9 @@ def test_decomposition_matrix_match(self, n):
assert qml.math.allclose(orig_mat, decomp_mat2)
@pytest.mark.parametrize("n", [1, 2, 3])
- def test_decomposition_matrix_match_broadcasted(self, n):
+ def test_decomposition_matrix_match_broadcasted(self, n, seed):
"""Test that the broadcasted matrix of the decomposition matches the original matrix."""
- rng = np.random.default_rng(382)
+ rng = np.random.default_rng(seed)
D = np.exp(1j * rng.random((5, 2**n)))
wires = list(range(n))
decomp = qml.DiagonalQubitUnitary.compute_decomposition(D, wires)
diff --git a/tests/ops/qubit/test_special_unitary.py b/tests/ops/qubit/test_special_unitary.py
index 7b84f99fd2f..85201219306 100644
--- a/tests/ops/qubit/test_special_unitary.py
+++ b/tests/ops/qubit/test_special_unitary.py
@@ -113,14 +113,14 @@ def get_one_parameter_generators(theta, num_wires, interface):
@pytest.mark.jax
@pytest.mark.parametrize("n", [1, 2, 3])
@pytest.mark.parametrize("use_jit", [True, False])
- def test_jax(self, n, use_jit):
+ def test_jax(self, n, use_jit, seed):
"""Test that generators are computed correctly in JAX."""
import jax
jax.config.update("jax_enable_x64", True)
from jax import numpy as jnp
- rng = np.random.default_rng(14521)
+ rng = np.random.default_rng(seed)
d = 4**n - 1
theta = jnp.array(rng.random(d))
fn = (
@@ -406,7 +406,6 @@ def interface_array(x, interface):
@pytest.mark.parametrize("interface", interfaces)
@pytest.mark.parametrize("n", [1, 2, 3])
- @pytest.mark.parametrize("seed", [214, 2491, 8623])
def test_compute_matrix_random(self, n, seed, interface):
"""Test that ``compute_matrix`` returns a correctly-shaped
unitary matrix for random input parameters."""
@@ -426,7 +425,6 @@ def test_compute_matrix_random(self, n, seed, interface):
assert np.allclose(matrix @ qml.math.conj(qml.math.T(matrix)), I)
@pytest.mark.parametrize("interface", interfaces)
- @pytest.mark.parametrize("seed", [214, 8623])
def test_compute_matrix_random_many_wires(self, seed, interface):
"""Test that ``compute_matrix`` returns a correctly-shaped
unitary matrix for random input parameters and more than 5 wires."""
@@ -448,7 +446,6 @@ def test_compute_matrix_random_many_wires(self, seed, interface):
@pytest.mark.parametrize("interface", interfaces)
@pytest.mark.parametrize("n", [1, 2])
- @pytest.mark.parametrize("seed", [214, 2491, 8623])
def test_compute_matrix_random_broadcasted(self, n, seed, interface):
"""Test that ``compute_matrix`` returns a correctly-shaped
unitary matrix for broadcasted random input parameters."""
diff --git a/tests/optimize/test_optimize_shot_adaptive.py b/tests/optimize/test_optimize_shot_adaptive.py
index b8643143cbb..e1c4c3256ed 100644
--- a/tests/optimize/test_optimize_shot_adaptive.py
+++ b/tests/optimize/test_optimize_shot_adaptive.py
@@ -627,9 +627,8 @@ def circuit(x):
assert np.allclose(circuit(params), -1, atol=0.1, rtol=0.2)
assert opt.shots_used > min_shots
- @flaky(max_runs=3)
@pytest.mark.slow
- def test_vqe_optimization(self):
+ def test_vqe_optimization(self, seed):
"""Test that a simple VQE circuit can be optimized"""
dev = qml.device("default.qubit", wires=2, shots=100)
coeffs = [0.1, 0.2]
@@ -649,7 +648,7 @@ def cost(params):
ansatz(params)
return qml.expval(H)
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
params = rng.random((4, 3), requires_grad=True)
initial_loss = cost(params)
diff --git a/tests/optimize/test_qnspsa.py b/tests/optimize/test_qnspsa.py
index 66fa613cdd6..c9292c57876 100644
--- a/tests/optimize/test_qnspsa.py
+++ b/tests/optimize/test_qnspsa.py
@@ -129,7 +129,6 @@ def get_state_overlap(params1, params2):
return metric_tensor_expected
-@pytest.mark.parametrize("seed", [1, 151, 1231])
@pytest.mark.parametrize("finite_diff_step", [1e-3, 1e-2, 1e-1])
class TestQNSPSAOptimizer:
def test_gradient_from_single_input(self, finite_diff_step, seed):
@@ -424,7 +423,7 @@ def test_blocking(self, finite_diff_step, seed):
assert np.allclose(new_params, params)
-def test_template_no_adjoint():
+def test_template_no_adjoint(seed):
"""Test that qnspsa iterates when the operations do not have a custom adjoint."""
num_qubits = 2
@@ -432,7 +431,7 @@ def test_template_no_adjoint():
@qml.qnode(dev)
def cost(params):
- qml.RandomLayers(weights=params, wires=range(num_qubits), seed=42)
+ qml.RandomLayers(weights=params, wires=range(num_qubits), seed=seed)
return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
params = np.random.normal(0, np.pi, (2, 4))
diff --git a/tests/pytest.ini b/tests/pytest.ini
index 2cdb4b8ef8f..036b5196116 100644
--- a/tests/pytest.ini
+++ b/tests/pytest.ini
@@ -19,6 +19,7 @@ markers =
logging: marks tests for pennylane logging
external: marks tests that require external packages such as matplotlib and PyZX
catalyst: marks tests for catalyst testing (select with '-m "catalyst"')
+ local_salt(salt): adds a salt to the seed provided by the pytest-rng fixture
filterwarnings =
ignore::DeprecationWarning:autograd.numpy.numpy_wrapper
ignore:Casting complex values to real::autograd.numpy.numpy_wrapper
@@ -33,3 +34,4 @@ filterwarnings =
ignore:PauliWord.hamiltonian:pennylane.PennyLaneDeprecationWarning
addopts = --benchmark-disable
xfail_strict=true
+rng_salt = v0.39.0
diff --git a/tests/resource/test_specs.py b/tests/resource/test_specs.py
index 00af26777f5..aebe0af0d19 100644
--- a/tests/resource/test_specs.py
+++ b/tests/resource/test_specs.py
@@ -248,7 +248,7 @@ def circuit(x):
assert specs_list[1]["num_device_wires"] == specs_list[1]["num_tape_wires"] == 3
assert specs_list[2]["num_device_wires"] == specs_list[1]["num_tape_wires"] == 3
- def make_qnode_and_params(self):
+ def make_qnode_and_params(self, seed):
"""Generates a qnode and params for use in other tests"""
n_layers = 2
n_wires = 5
@@ -261,7 +261,7 @@ def circuit(params):
return qml.expval(qml.PauliZ(0))
params_shape = qml.BasicEntanglerLayers.shape(n_layers=n_layers, n_wires=n_wires)
- rng = pnp.random.default_rng(seed=10)
+ rng = pnp.random.default_rng(seed=seed)
params = rng.standard_normal(params_shape) # pylint:disable=no-member
return circuit, params
diff --git a/tests/shadow/test_shadow_transforms.py b/tests/shadow/test_shadow_transforms.py
index 1910293264b..90300a13030 100644
--- a/tests/shadow/test_shadow_transforms.py
+++ b/tests/shadow/test_shadow_transforms.py
@@ -360,7 +360,7 @@ def test_hadamard_forward(self):
assert qml.math.allclose(actual, expected, atol=1e-1)
- def test_basic_entangler_backward(self):
+ def test_basic_entangler_backward(self, seed):
"""Test the gradient of the expval transform"""
obs = [
@@ -377,7 +377,7 @@ def test_basic_entangler_backward(self):
shadow_circuit = qml.shadows.shadow_expval(shadow_circuit, obs)
exact_circuit = basic_entangler_circuit_exact_expval(3, "autograd")
- rng = np.random.default_rng(123)
+ rng = np.random.default_rng(seed)
x = rng.uniform(0.8, 2, size=qml.BasicEntanglerLayers.shape(n_layers=1, n_wires=3))
def shadow_cost(x):
diff --git a/tests/templates/test_embeddings/test_amplitude.py b/tests/templates/test_embeddings/test_amplitude.py
index 7096b3206e6..6909cd22387 100644
--- a/tests/templates/test_embeddings/test_amplitude.py
+++ b/tests/templates/test_embeddings/test_amplitude.py
@@ -592,12 +592,12 @@ def test_torch(self, tol, features, pad_with, dtype):
@pytest.mark.jax
@pytest.mark.parametrize("shots, atol", [(10000, 0.05), (None, 1e-8)])
-def test_jacobian_with_and_without_jit_has_same_output(shots, atol):
+def test_jacobian_with_and_without_jit_has_same_output(shots, atol, seed):
"""Test that the jacobian of AmplitudeEmbedding is the same with and without jit."""
import jax
- dev = qml.device("default.qubit", shots=shots, seed=7890234)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
@qml.qnode(dev, diff_method="parameter-shift")
def circuit(coeffs):
diff --git a/tests/templates/test_state_preparations/test_mottonen_state_prep.py b/tests/templates/test_state_preparations/test_mottonen_state_prep.py
index d1c0e194c4f..1a9f0aa6219 100644
--- a/tests/templates/test_state_preparations/test_mottonen_state_prep.py
+++ b/tests/templates/test_state_preparations/test_mottonen_state_prep.py
@@ -418,11 +418,11 @@ def circuit(state):
@pytest.mark.jax
@pytest.mark.parametrize("shots, atol", [(None, 0.005), (1000000, 0.05)])
-def test_jacobians_with_and_without_jit_match(shots, atol):
+def test_jacobians_with_and_without_jit_match(shots, atol, seed):
"""Test that the Jacobian of the circuit is the same with and without jit."""
import jax
- dev = qml.device("default.qubit", shots=shots, seed=7890234)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
dev_no_shots = qml.device("default.qubit", shots=None)
def circuit(coeffs):
diff --git a/tests/templates/test_subroutines/test_amplitude_amplification.py b/tests/templates/test_subroutines/test_amplitude_amplification.py
index 484e924f359..1c7ca4c2c97 100644
--- a/tests/templates/test_subroutines/test_amplitude_amplification.py
+++ b/tests/templates/test_subroutines/test_amplitude_amplification.py
@@ -172,14 +172,14 @@ def test_qnode_autograd(self, shots):
@pytest.mark.jax
@pytest.mark.parametrize("use_jit", [False, True])
@pytest.mark.parametrize("shots", [None, 50000])
- def test_qnode_jax(self, shots, use_jit):
+ def test_qnode_jax(self, shots, use_jit, seed):
"""Test that the QNode executes and is differentiable with JAX. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import jax
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="jax", diff_method=diff_method)
@@ -198,12 +198,12 @@ def test_qnode_jax(self, shots, use_jit):
@pytest.mark.torch
@pytest.mark.parametrize("shots", [None, 50000])
- def test_qnode_torch(self, shots):
+ def test_qnode_torch(self, shots, seed):
"""Test that the QNode executes and is differentiable with Torch. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import torch
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="torch", diff_method=diff_method)
@@ -216,12 +216,12 @@ def test_qnode_torch(self, shots):
@pytest.mark.tf
@pytest.mark.parametrize("shots", [None, 50000])
@pytest.mark.xfail(reason="tf gradient doesn't seem to be working, returns ()")
- def test_qnode_tf(self, shots):
+ def test_qnode_tf(self, shots, seed):
"""Test that the QNode executes and is differentiable with TensorFlow. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import tensorflow as tf
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="tf", diff_method=diff_method)
diff --git a/tests/templates/test_subroutines/test_controlled_sequence.py b/tests/templates/test_subroutines/test_controlled_sequence.py
index d0401a0288c..494c521cdb0 100644
--- a/tests/templates/test_subroutines/test_controlled_sequence.py
+++ b/tests/templates/test_subroutines/test_controlled_sequence.py
@@ -212,7 +212,7 @@ def test_qnode_autograd(self, shots):
@pytest.mark.jax
@pytest.mark.parametrize("use_jit", [False, True])
@pytest.mark.parametrize("shots", [None, 50000])
- def test_qnode_jax(self, shots, use_jit):
+ def test_qnode_jax(self, shots, use_jit, seed):
"""Test that the QNode executes and is differentiable with JAX. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
@@ -220,7 +220,7 @@ def test_qnode_jax(self, shots, use_jit):
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="jax", diff_method=diff_method)
@@ -242,13 +242,13 @@ def test_qnode_jax(self, shots, use_jit):
@pytest.mark.torch
@pytest.mark.parametrize("shots", [None, 50000])
- def test_qnode_torch(self, shots):
+ def test_qnode_torch(self, shots, seed):
"""Test that the QNode executes and is differentiable with Torch. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import torch
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="torch", diff_method=diff_method)
@@ -265,13 +265,13 @@ def test_qnode_torch(self, shots):
@pytest.mark.tf
@pytest.mark.parametrize("shots", [None, 10000])
@pytest.mark.xfail(reason="tf gradient doesn't seem to be working, returns ()")
- def test_qnode_tf(self, shots):
+ def test_qnode_tf(self, shots, seed):
"""Test that the QNode executes and is differentiable with TensorFlow. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import tensorflow as tf
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="tf", diff_method=diff_method)
diff --git a/tests/templates/test_subroutines/test_qdrift.py b/tests/templates/test_subroutines/test_qdrift.py
index 2f0f25b9eb8..33c168dc7a1 100644
--- a/tests/templates/test_subroutines/test_qdrift.py
+++ b/tests/templates/test_subroutines/test_qdrift.py
@@ -55,7 +55,6 @@ def test_queuing(self):
@pytest.mark.parametrize("n", (1, 2, 3))
@pytest.mark.parametrize("time", (0.5, 1, 2))
- @pytest.mark.parametrize("seed", (None, 1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_init_correctly(self, coeffs, ops, time, n, seed): # pylint: disable=too-many-arguments
"""Test that all of the attributes are initialized correctly."""
@@ -77,7 +76,6 @@ def test_init_correctly(self, coeffs, ops, time, n, seed): # pylint: disable=to
@pytest.mark.parametrize("n", (1, 2, 3))
@pytest.mark.parametrize("time", (0.5, 1, 2))
- @pytest.mark.parametrize("seed", (None, 1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_copy(self, coeffs, ops, time, n, seed): # pylint: disable=too-many-arguments
"""Test that we can make copies of QDrift correctly."""
@@ -126,7 +124,6 @@ class TestDecomposition:
@pytest.mark.parametrize("n", (1, 2, 3))
@pytest.mark.parametrize("time", (0.5, 1, 2))
- @pytest.mark.parametrize("seed", (None, 1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_private_sample(self, coeffs, ops, time, seed, n): # pylint: disable=too-many-arguments
"""Test the private function which samples the decomposition"""
@@ -146,15 +143,14 @@ def test_private_sample(self, coeffs, ops, time, seed, n): # pylint: disable=to
assert term.coeff == (s * normalization * time * 1j / n) # with this exponent
@pytest.mark.parametrize("coeffs", ([0.99, 0.01], [0.5 + 0.49j, -0.01j]))
- def test_private_sample_statistics(self, coeffs):
+ def test_private_sample_statistics(self, coeffs, seed):
"""Test the private function samples from the right distribution"""
ops = [qml.PauliX(0), qml.PauliZ(1)]
- decomp = _sample_decomposition(coeffs, ops, 1.23, n=10, seed=1234)
+ decomp = _sample_decomposition(coeffs, ops, 1.23, n=10, seed=seed)
# High probability we only sample PauliX!
assert all(isinstance(op.base, qml.PauliX) for op in decomp)
- @pytest.mark.parametrize("seed", (1234, 42))
def test_compute_decomposition(self, seed):
"""Test that the decomposition is computed and queues correctly."""
coeffs = [1, -0.5, 0.5]
@@ -182,9 +178,9 @@ def test_compute_decomposition(self, seed):
class TestIntegration:
"""Test that the QDrift template integrates well with the rest of PennyLane"""
+ @pytest.mark.local_salt(8)
@pytest.mark.parametrize("n", (1, 2, 3))
@pytest.mark.parametrize("time", (0.5, 1, 2))
- @pytest.mark.parametrize("seed", (1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_execution(self, coeffs, ops, time, n, seed): # pylint: disable=too-many-arguments
"""Test that the circuit executes as expected"""
@@ -213,8 +209,8 @@ def circ():
assert allclose(expected_state, state)
+ @pytest.mark.local_salt(8)
@pytest.mark.autograd
- @pytest.mark.parametrize("seed", (1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_execution_autograd(self, coeffs, ops, seed):
"""Test that the circuit executes as expected using autograd"""
@@ -246,7 +242,6 @@ def circ(time):
assert allclose(expected_state, state)
@pytest.mark.torch
- @pytest.mark.parametrize("seed", (1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_execution_torch(self, coeffs, ops, seed):
"""Test that the circuit executes as expected using torch"""
@@ -277,7 +272,6 @@ def circ(time):
assert allclose(expected_state, state)
@pytest.mark.tf
- @pytest.mark.parametrize("seed", (1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_execution_tf(self, coeffs, ops, seed):
"""Test that the circuit executes as expected using tensorflow"""
@@ -308,7 +302,6 @@ def circ(time):
assert allclose(expected_state, state)
@pytest.mark.jax
- @pytest.mark.parametrize("seed", (1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_execution_jax(self, coeffs, ops, seed):
"""Test that the circuit executes as expected using jax"""
@@ -339,7 +332,6 @@ def circ(time):
assert allclose(expected_state, state)
@pytest.mark.jax
- @pytest.mark.parametrize("seed", (1234, 42))
@pytest.mark.parametrize("coeffs, ops", test_hamiltonians)
def test_execution_jaxjit(self, coeffs, ops, seed):
"""Test that the circuit executes as expected using jax jit"""
@@ -462,7 +454,6 @@ def circ(time, coeffs):
@pytest.mark.autograd
@pytest.mark.parametrize("n", (1, 5, 10))
- @pytest.mark.parametrize("seed", (1234, 42))
def test_autograd_gradient(self, n, seed):
"""Test that the gradient is computed correctly"""
time = qnp.array(1.5)
@@ -493,7 +484,6 @@ def reference_circ(time, coeffs):
@pytest.mark.torch
@pytest.mark.parametrize("n", (1, 5, 10))
- @pytest.mark.parametrize("seed", (1234, 42))
def test_torch_gradient(self, n, seed):
"""Test that the gradient is computed correctly using torch"""
import torch
@@ -534,7 +524,6 @@ def reference_circ(time, coeffs):
@pytest.mark.tf
@pytest.mark.parametrize("n", (1, 5, 10))
- @pytest.mark.parametrize("seed", (1234, 42))
def test_tf_gradient(self, n, seed):
"""Test that the gradient is computed correctly using tensorflow"""
import tensorflow as tf
@@ -573,7 +562,6 @@ def reference_circ(time, coeffs):
@pytest.mark.jax
@pytest.mark.parametrize("n", (1, 5, 10))
- @pytest.mark.parametrize("seed", (1234, 42))
def test_jax_gradient(self, n, seed):
"""Test that the gradient is computed correctly using jax"""
import jax
diff --git a/tests/templates/test_subroutines/test_qubitization.py b/tests/templates/test_subroutines/test_qubitization.py
index 66e40066eca..7b8e439d77c 100644
--- a/tests/templates/test_subroutines/test_qubitization.py
+++ b/tests/templates/test_subroutines/test_qubitization.py
@@ -176,7 +176,7 @@ def test_qnode_autograd(self):
@pytest.mark.jax
@pytest.mark.parametrize("use_jit", (False, True))
@pytest.mark.parametrize("shots", (None, 50000))
- def test_qnode_jax(self, shots, use_jit):
+ def test_qnode_jax(self, shots, use_jit, seed):
""" "Test that the QNode executes and is differentiable with JAX. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import jax
@@ -191,7 +191,7 @@ def test_qnode_jax(self, shots, use_jit):
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="jax", diff_method=diff_method)
@@ -210,7 +210,7 @@ def test_qnode_jax(self, shots, use_jit):
@pytest.mark.torch
@pytest.mark.parametrize("shots", [None, 50000])
- def test_qnode_torch(self, shots):
+ def test_qnode_torch(self, shots, seed):
""" "Test that the QNode executes and is differentiable with Torch. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import torch
@@ -219,7 +219,7 @@ def test_qnode_torch(self, shots):
if shots is not None:
pytest.xfail()
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="torch", diff_method=diff_method)
@@ -231,12 +231,12 @@ def test_qnode_torch(self, shots):
@pytest.mark.tf
@pytest.mark.parametrize("shots", [None, 50000])
@pytest.mark.xfail(reason="tf gradient doesn't seem to be working, returns ()")
- def test_qnode_tf(self, shots):
+ def test_qnode_tf(self, shots, seed):
""" "Test that the QNode executes and is differentiable with TensorFlow. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import tensorflow as tf
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="tf", diff_method=diff_method)
diff --git a/tests/templates/test_subroutines/test_reflection.py b/tests/templates/test_subroutines/test_reflection.py
index d47a822efab..6123daed312 100644
--- a/tests/templates/test_subroutines/test_reflection.py
+++ b/tests/templates/test_subroutines/test_reflection.py
@@ -183,14 +183,14 @@ def test_qnode_autograd(self, shots):
@pytest.mark.jax
@pytest.mark.parametrize("use_jit", [False, True])
@pytest.mark.parametrize("shots", [None, 50000])
- def test_qnode_jax(self, shots, use_jit):
+ def test_qnode_jax(self, shots, use_jit, seed):
"""Test that the QNode executes and is differentiable with JAX. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import jax
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="jax", diff_method=diff_method)
@@ -212,13 +212,13 @@ def test_qnode_jax(self, shots, use_jit):
@pytest.mark.torch
@pytest.mark.parametrize("shots", [None, 50000])
- def test_qnode_torch(self, shots):
+ def test_qnode_torch(self, shots, seed):
"""Test that the QNode executes and is differentiable with Torch. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import torch
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="torch", diff_method=diff_method)
@@ -235,12 +235,12 @@ def test_qnode_torch(self, shots):
@pytest.mark.tf
@pytest.mark.parametrize("shots", [None, 50000])
@pytest.mark.xfail(reason="tf gradient doesn't seem to be working, returns ()")
- def test_qnode_tf(self, shots):
+ def test_qnode_tf(self, shots, seed):
"""Test that the QNode executes and is differentiable with TensorFlow. The shots
argument controls whether autodiff or parameter-shift gradients are used."""
import tensorflow as tf
- dev = qml.device("default.qubit", shots=shots, seed=10)
+ dev = qml.device("default.qubit", shots=shots, seed=seed)
diff_method = "backprop" if shots is None else "parameter-shift"
qnode = qml.QNode(self.circuit, dev, interface="tf", diff_method=diff_method)
diff --git a/tests/test_compiler.py b/tests/test_compiler.py
index 6ceb2378614..8d8b18e499c 100644
--- a/tests/test_compiler.py
+++ b/tests/test_compiler.py
@@ -864,7 +864,7 @@ class TestCatalystMCMs:
@pytest.mark.parametrize("measure_f", [qml.counts, qml.expval, qml.probs])
@pytest.mark.parametrize("meas_obj", [qml.PauliZ(0), [0], "mcm"])
# pylint: disable=too-many-arguments
- def test_dynamic_one_shot_simple(self, measure_f, meas_obj):
+ def test_dynamic_one_shot_simple(self, measure_f, meas_obj, seed):
"""Tests that Catalyst yields the same results as PennyLane's DefaultQubit for a simple
circuit with a mid-circuit measurement."""
if measure_f in (qml.counts, qml.probs, qml.sample) and (
@@ -879,7 +879,7 @@ def test_dynamic_one_shot_simple(self, measure_f, meas_obj):
pytest.xfail("isa")
shots = 8000
- dq = qml.device("default.qubit", shots=shots, seed=8237945)
+ dq = qml.device("default.qubit", shots=shots, seed=seed)
@qml.defer_measurements
@qml.qnode(dq)
diff --git a/tests/test_debugging.py b/tests/test_debugging.py
index e575017f5a1..99585f44e2c 100644
--- a/tests/test_debugging.py
+++ b/tests/test_debugging.py
@@ -364,6 +364,10 @@ def circuit():
@pytest.mark.parametrize("diff_method", [None, "parameter-shift"])
def test_default_qutrit_mixed_finite_shot(self, diff_method):
"""Test that multiple snapshots are returned correctly on the qutrit density-matrix simulator."""
+
+ # TODO: not sure what to do with this test so leaving this here for now.
+ np.random.seed(9872653)
+
dev = qml.device("default.qutrit.mixed", wires=2, shots=100)
assert qml.debugging.snapshot._is_snapshot_compatible(dev)
@@ -482,6 +486,10 @@ def qnode(params):
def test_adjoint_circuit(self):
"""Test that snapshots are returned correctly when adjointed."""
+
+ # TODO: not sure what to do with this test so leaving this here for now.
+ np.random.seed(9872653)
+
dev = qml.device("default.qubit", wires=2)
def circuit(params, wire):
@@ -508,6 +516,10 @@ def qnode(params):
def test_all_sample_measurement_snapshot(self):
"""Test that the correct measurement snapshots are returned for different measurement types."""
+
+ # TODO: The fact that this entire test depends on a global seed is not good
+ np.random.seed(9872653)
+
dev = qml.device("default.qubit", wires=1, shots=10)
@qml.qnode(dev)
diff --git a/tests/test_hermitian_edge_cases.py b/tests/test_hermitian_edge_cases.py
index 41224a00b7c..4297b52a8ec 100644
--- a/tests/test_hermitian_edge_cases.py
+++ b/tests/test_hermitian_edge_cases.py
@@ -21,6 +21,8 @@
import pennylane as qml
+# pylint:disable=too-many-arguments
+
THETA = np.linspace(0.11, 1, 3)
PHI = np.linspace(0.32, 1, 3)
@@ -87,9 +89,9 @@ def circuit():
@pytest.mark.parametrize("theta", THETA)
@pytest.mark.parametrize("w1, w2", list(itertools.permutations(range(4), 2)))
- def test_hermitian_two_wires_permuted(self, w1, w2, shots, theta):
+ def test_hermitian_two_wires_permuted(self, w1, w2, shots, theta, seed):
"""Test that an hermitian expectation with various wires permuted works"""
- dev = qml.device("default.qubit", wires=4, shots=shots, seed=123545)
+ dev = qml.device("default.qubit", wires=4, shots=shots, seed=seed)
theta = 0.543
A = np.array(
diff --git a/tests/test_operation.py b/tests/test_operation.py
index cdcdc48fb4d..f1c9c6bd5d4 100644
--- a/tests/test_operation.py
+++ b/tests/test_operation.py
@@ -511,11 +511,11 @@ class MyOp(qml.operation.Operator):
assert MyOp.has_matrix is False
assert MyOp(wires=0).has_matrix is False
- def test_has_matrix_false_concrete_template(self):
+ def test_has_matrix_false_concrete_template(self, seed):
"""Test has_matrix with a concrete operation (StronglyEntanglingLayers)
that does not have a matrix defined."""
- rng = qml.numpy.random.default_rng(seed=42)
+ rng = qml.numpy.random.default_rng(seed=seed)
shape = qml.StronglyEntanglingLayers.shape(n_layers=2, n_wires=2)
params = rng.random(shape)
op = qml.StronglyEntanglingLayers(params, wires=range(2))
diff --git a/tests/test_qnode.py b/tests/test_qnode.py
index 841bf4a8315..67b54593d9c 100644
--- a/tests/test_qnode.py
+++ b/tests/test_qnode.py
@@ -1723,7 +1723,7 @@ def f(x):
@pytest.mark.jax
@pytest.mark.parametrize("diff_method", [None, "best"])
- def test_defer_measurements_with_jit(self, diff_method, mocker):
+ def test_defer_measurements_with_jit(self, diff_method, mocker, seed):
"""Test that using mcm_method="deferred" defaults to behaviour like
postselect_mode="fill-shots" when using jax jit."""
import jax # pylint: disable=import-outside-toplevel
@@ -1734,7 +1734,7 @@ def test_defer_measurements_with_jit(self, diff_method, mocker):
spy = mocker.spy(qml.defer_measurements, "_transform")
spy_one_shot = mocker.spy(qml.dynamic_one_shot, "_transform")
- dev = qml.device("default.qubit", wires=4, shots=shots, seed=jax.random.PRNGKey(123))
+ dev = qml.device("default.qubit", wires=4, shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev, diff_method=diff_method, mcm_method="deferred")
def f(x):
@@ -1755,9 +1755,8 @@ def f(x):
assert qml.math.allclose(res_jit, postselect)
@pytest.mark.jax
- # @pytest.mark.parametrize("diff_method", [None, "best"])
- @pytest.mark.parametrize("diff_method", ["best"])
- def test_deferred_hw_like_error_with_jit(self, diff_method):
+ @pytest.mark.parametrize("diff_method", [None, "best"])
+ def test_deferred_hw_like_error_with_jit(self, diff_method, seed):
"""Test that an error is raised if attempting to use postselect_mode="hw-like"
with jax jit with mcm_method="deferred"."""
import jax # pylint: disable=import-outside-toplevel
@@ -1766,7 +1765,7 @@ def test_deferred_hw_like_error_with_jit(self, diff_method):
postselect = 1
param = jax.numpy.array(np.pi / 2)
- dev = qml.device("default.qubit", wires=4, shots=shots, seed=jax.random.PRNGKey(123))
+ dev = qml.device("default.qubit", wires=4, shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev, diff_method=diff_method, mcm_method="deferred", postselect_mode="hw-like")
def f(x):
diff --git a/tests/test_tensor_measurements.py b/tests/test_tensor_measurements.py
index 543eba1618b..6e726b1a9cb 100644
--- a/tests/test_tensor_measurements.py
+++ b/tests/test_tensor_measurements.py
@@ -49,10 +49,10 @@ def tolerance(self, shots, tol):
return {"atol": tol, "rtol": 0}
- def test_tensor_product(self, shots, theta, phi, varphi, tolerance):
+ def test_tensor_product(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product ZxZ gives the same result as simply
using an Hermitian matrix"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=1851)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit1(a, b, c):
@@ -69,10 +69,10 @@ def circuit2(a, b, c):
assert np.allclose(res1, res2, **tolerance)
- def test_combine_tensor_with_non_tensor(self, shots, theta, phi, varphi, tolerance):
+ def test_combine_tensor_with_non_tensor(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product along with a non-tensor product
continues to function correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=181)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit1(a, b, c):
@@ -94,9 +94,9 @@ def circuit3(a, b, c):
assert np.allclose(res1, res2, **tolerance)
- def test_paulix_tensor_pauliy(self, shots, theta, phi, varphi, tolerance):
+ def test_paulix_tensor_pauliy(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving PauliX and PauliY works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=164)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit(a, b, c):
@@ -109,9 +109,9 @@ def circuit(a, b, c):
assert np.allclose(res, expected, **tolerance)
@pytest.mark.autograd
- def test_paulix_tensor_pauliy_gradient(self, shots, theta, phi, varphi, tolerance):
+ def test_paulix_tensor_pauliy_gradient(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving PauliX and PauliY works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=144)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit(a, b, c):
@@ -124,9 +124,9 @@ def circuit(a, b, c):
assert np.allclose(res, expected, **tolerance)
- def test_pauliz_tensor_identity(self, shots, theta, phi, varphi, tolerance):
+ def test_pauliz_tensor_identity(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving PauliZ and Identity works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=134)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit(a, b, c):
@@ -138,9 +138,9 @@ def circuit(a, b, c):
assert np.allclose(res, expected, **tolerance)
- def test_pauliz_tensor_hadamard(self, shots, theta, phi, varphi, tolerance):
+ def test_pauliz_tensor_hadamard(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving PauliZ and hadamard works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=324)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit(a, b, c):
@@ -152,9 +152,9 @@ def circuit(a, b, c):
assert np.allclose(res, expected, **tolerance)
- def test_hermitian(self, shots, theta, phi, varphi, tolerance):
+ def test_hermitian(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving an Hermitian matrix works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=125)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
A = np.array(
[
@@ -180,9 +180,9 @@ def circuit(a, b, c):
assert np.allclose(res, expected, **tolerance)
- def test_hermitian_tensor_hermitian(self, shots, theta, phi, varphi, tolerance):
+ def test_hermitian_tensor_hermitian(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving two Hermitian matrices works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=224)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
A1 = np.array([[1, 2], [2, 4]])
@@ -220,9 +220,11 @@ def circuit(a, b, c):
assert np.allclose(res, expected, **tolerance)
- def test_hermitian_tensor_identity_expectation(self, shots, theta, phi, varphi, tolerance):
+ def test_hermitian_tensor_identity_expectation(
+ self, shots, theta, phi, varphi, tolerance, seed
+ ):
"""Test that a tensor product involving an Hermitian matrix and the identity works correctly"""
- dev = qml.device("default.qubit", wires=2, shots=shots, seed=144)
+ dev = qml.device("default.qubit", wires=2, shots=shots, seed=seed)
A = np.array(
[[1.02789352, 1.61296440 - 0.3498192j], [1.61296440 + 0.3498192j, 1.23920938 + 0j]]
@@ -258,9 +260,9 @@ def tolerance(self, shots, tol):
return {"atol": tol, "rtol": 0}
- def test_paulix_tensor_pauliy(self, shots, theta, phi, varphi, tolerance):
+ def test_paulix_tensor_pauliy(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving PauliX and PauliY works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=924)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit(a, b, c):
@@ -279,9 +281,9 @@ def circuit(a, b, c):
assert np.allclose(res, expected, **tolerance)
- def test_pauliz_tensor_hadamard(self, shots, theta, phi, varphi, tolerance):
+ def test_pauliz_tensor_hadamard(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving PauliZ and hadamard works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=167)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit(a, b, c):
@@ -298,9 +300,9 @@ def circuit(a, b, c):
assert np.allclose(res, expected, **tolerance)
- def test_tensor_hermitian(self, shots, theta, phi, varphi, tolerance):
+ def test_tensor_hermitian(self, shots, theta, phi, varphi, tolerance, seed):
"""Test that a tensor product involving qml.Hermitian works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=shots, seed=824)
+ dev = qml.device("default.qubit", wires=3, shots=shots, seed=seed)
A = np.array(
[
@@ -360,9 +362,9 @@ class TestTensorSample:
"""Tests for samples of tensor observables"""
# pylint: disable=unused-argument
- def test_paulix_tensor_pauliz(self, theta, phi, varphi, tol_stochastic):
+ def test_paulix_tensor_pauliz(self, theta, phi, varphi, tol_stochastic, seed):
"""Test that a tensor product involving PauliX and PauliZ works correctly"""
- dev = qml.device("default.qubit", wires=2, shots=int(1e6), seed=524)
+ dev = qml.device("default.qubit", wires=2, shots=int(1e6), seed=seed)
@qml.qnode(dev)
def circuit():
@@ -374,9 +376,9 @@ def circuit():
# s1 should only contain 1
assert np.allclose(s1, 1, atol=tol_stochastic, rtol=0)
- def test_paulix_tensor_pauliy(self, theta, phi, varphi, tol_stochastic):
+ def test_paulix_tensor_pauliy(self, theta, phi, varphi, tol_stochastic, seed):
"""Test that a tensor product involving PauliX and PauliY works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=int(1e6), seed=173)
+ dev = qml.device("default.qubit", wires=3, shots=int(1e6), seed=seed)
@qml.qnode(dev, diff_method="parameter-shift")
def circuit(a, b, c):
@@ -388,9 +390,9 @@ def circuit(a, b, c):
# s1 should only contain 1 and -1
assert np.allclose(s1**2, 1, atol=tol_stochastic, rtol=0)
- def test_pauliz_tensor_hadamard(self, theta, phi, varphi, tol_stochastic):
+ def test_pauliz_tensor_hadamard(self, theta, phi, varphi, tol_stochastic, seed):
"""Test that a tensor product involving PauliZ and hadamard works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=int(1e6), seed=814)
+ dev = qml.device("default.qubit", wires=3, shots=int(1e6), seed=seed)
@qml.qnode(dev, diff_method="parameter-shift")
def circuit(a, b, c):
@@ -402,9 +404,9 @@ def circuit(a, b, c):
# s1 should only contain 1 and -1
assert np.allclose(s1**2, 1, atol=tol_stochastic, rtol=0)
- def test_tensor_hermitian(self, theta, phi, varphi, tol_stochastic):
+ def test_tensor_hermitian(self, theta, phi, varphi, tol_stochastic, seed):
"""Test that a tensor product involving qml.Hermitian works correctly"""
- dev = qml.device("default.qubit", wires=3, shots=int(1e6), seed=124)
+ dev = qml.device("default.qubit", wires=3, shots=int(1e6), seed=seed)
A = np.array(
[
diff --git a/tests/test_vqe.py b/tests/test_vqe.py
index f4d3da8c034..60b16bd2fc1 100644
--- a/tests/test_vqe.py
+++ b/tests/test_vqe.py
@@ -280,7 +280,7 @@ def test_cost_expvals(self, coeffs, observables, expected):
@pytest.mark.torch
@pytest.mark.slow
@pytest.mark.parametrize("shots", [None, [(8000, 5)], [(8000, 5), (9000, 4)]])
- def test_optimize_torch(self, shots):
+ def test_optimize_torch(self, shots, seed):
"""Test that a Hamiltonian cost function is the same with and without
grouping optimization when using the Torch interface."""
@@ -306,7 +306,7 @@ def test_optimize_torch(self, shots):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
- _rng = np.random.default_rng(1234)
+ _rng = np.random.default_rng(seed)
w = _rng.random(shape)
with qml.Tracker(dev) as tracker:
@@ -328,7 +328,7 @@ def test_optimize_torch(self, shots):
@pytest.mark.tf
@pytest.mark.slow
@pytest.mark.parametrize("shots", [None, [(8000, 5)], [(8000, 5), (9000, 4)]])
- def test_optimize_tf(self, shots):
+ def test_optimize_tf(self, shots, seed):
"""Test that a Hamiltonian cost function is the same with and without
grouping optimization when using the TensorFlow interface."""
@@ -354,7 +354,7 @@ def test_optimize_tf(self, shots):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
- _rng = np.random.default_rng(1234)
+ _rng = np.random.default_rng(seed)
w = _rng.random(shape)
with qml.Tracker(dev) as tracker:
@@ -374,7 +374,7 @@ def test_optimize_tf(self, shots):
@pytest.mark.autograd
@pytest.mark.slow
@pytest.mark.parametrize("shots", [None, [(8000, 5)], [(8000, 5), (9000, 4)]])
- def test_optimize_autograd(self, shots):
+ def test_optimize_autograd(self, shots, seed):
"""Test that a Hamiltonian cost function is the same with and without
grouping optimization when using the autograd interface."""
@@ -400,7 +400,7 @@ def test_optimize_autograd(self, shots):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
- _rng = np.random.default_rng(1234)
+ _rng = np.random.default_rng(seed)
w = _rng.random(shape)
with qml.Tracker(dev) as tracker:
@@ -418,7 +418,7 @@ def test_optimize_autograd(self, shots):
# pylint: disable=protected-access
@pytest.mark.autograd
- def test_optimize_multiple_terms_autograd(self):
+ def test_optimize_multiple_terms_autograd(self, seed):
"""Test that a Hamiltonian cost function is the same with and without
grouping optimization when using the autograd interface, even when
there are non-unique Hamiltonian terms."""
@@ -456,7 +456,7 @@ def test_optimize_multiple_terms_autograd(self):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=5)
- _rng = np.random.default_rng(1234)
+ _rng = np.random.default_rng(seed)
w = _rng.random(shape)
with qml.Tracker(dev) as tracker:
@@ -474,7 +474,7 @@ def test_optimize_multiple_terms_autograd(self):
# pylint: disable=protected-access
@pytest.mark.torch
- def test_optimize_multiple_terms_torch(self):
+ def test_optimize_multiple_terms_torch(self, seed):
"""Test that a Hamiltonian cost function is the same with and without
grouping optimization when using the Torch interface, even when there
are non-unique Hamiltonian terms."""
@@ -512,7 +512,7 @@ def test_optimize_multiple_terms_torch(self):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=5)
- _rng = np.random.default_rng(1234)
+ _rng = np.random.default_rng(seed)
w = _rng.random(shape)
with qml.Tracker(dev) as tracker:
@@ -530,7 +530,7 @@ def test_optimize_multiple_terms_torch(self):
# pylint: disable=protected-access
@pytest.mark.tf
- def test_optimize_multiple_terms_tf(self):
+ def test_optimize_multiple_terms_tf(self, seed):
"""Test that a Hamiltonian cost function is the same with and without
grouping optimization when using the TensorFlow interface, even when
there are non-unique Hamiltonian terms."""
@@ -568,7 +568,7 @@ def test_optimize_multiple_terms_tf(self):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=5)
- _rng = np.random.default_rng(1234)
+ _rng = np.random.default_rng(seed)
w = _rng.random(shape)
with qml.Tracker(dev) as tracker:
@@ -610,6 +610,9 @@ def test_optimize_grad(self):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
+ # TODO: This is another case of a magic number in the sense that no other number allows
+ # this test to pass. This is likely because the expected `big_hamiltonian_grad`
+ # was calculated using this exact seed. This test needs to be revisited.
_rng = pnp.random.default_rng(1967)
w = _rng.uniform(low=0, high=2 * np.pi, size=shape, requires_grad=True)
@@ -669,6 +672,9 @@ def test_optimize_grad_torch(self):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
+ # TODO: This is another case of a magic number in the sense that no other number allows
+ # this test to pass. This is likely because the expected `big_hamiltonian_grad`
+ # was calculated using this exact seed. This test needs to be revisited.
_rng = np.random.default_rng(1967)
w = _rng.uniform(low=0, high=2 * np.pi, size=shape)
w = torch.tensor(w, requires_grad=True)
@@ -696,6 +702,9 @@ def test_optimize_grad_tf(self):
)
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
+ # TODO: This is another case of a magic number in the sense that no other number allows
+ # this test to pass. This is likely because the expected `big_hamiltonian_grad`
+ # was calculated using this exact seed. This test needs to be revisited.
_rng = np.random.default_rng(1967)
w = _rng.uniform(low=0, high=2 * np.pi, size=shape)
w = tf.Variable(w)
@@ -782,7 +791,7 @@ def circuit2():
@pytest.mark.jax
@pytest.mark.parametrize("shots, dim", [([(1000, 2)], 2), ([30, 30], 2), ([2, 3, 4], 3)])
- def test_shot_distribution(self, shots, dim):
+ def test_shot_distribution(self, shots, dim, seed):
"""Tests that distributed shots work with the new VQE design."""
import jax
@@ -798,7 +807,7 @@ def circuit(weights, coeffs):
obs = [qml.PauliZ(0), qml.PauliX(0) @ qml.PauliZ(1)]
coeffs = np.array([0.1, 0.2])
- key = jax.random.PRNGKey(42)
+ key = jax.random.PRNGKey(seed)
weights = jax.random.uniform(key, [2, 2, 3])
res = circuit(weights, coeffs)
diff --git a/tests/transforms/test_broadcast_expand.py b/tests/transforms/test_broadcast_expand.py
index e1212626fc8..0e0d71bb6b8 100644
--- a/tests/transforms/test_broadcast_expand.py
+++ b/tests/transforms/test_broadcast_expand.py
@@ -23,7 +23,8 @@
from pennylane import numpy as pnp
-def get_device(name="default.qubit", wires=2, seed=123):
+def get_device(name="default.qubit", wires=2, seed=None):
+ assert seed is not None, "Please use the pytest-rng provided seed"
return qml.device(name, wires=wires, seed=seed)
@@ -90,7 +91,7 @@ class TestBroadcastExpand:
@pytest.mark.parametrize("params, size", list(zip(parameters, sizes)))
@pytest.mark.parametrize("obs, exp_fn", observables_and_exp_fns)
- def test_expansion(self, params, size, obs, exp_fn):
+ def test_expansion(self, params, size, obs, exp_fn, seed):
"""Test that the expansion works as expected."""
ops = make_ops(*params)
expvals = [qml.expval(ob) for ob in obs]
@@ -101,18 +102,18 @@ def test_expansion(self, params, size, obs, exp_fn):
assert len(tapes) == size
assert all(_tape.batch_size is None for _tape in tapes)
- result = fn(qml.execute(tapes, get_device(), None))
+ result = fn(qml.execute(tapes, get_device(seed=seed), None))
expected = exp_fn(*params)
assert qml.math.allclose(result, expected)
@pytest.mark.parametrize("params", parameters)
@pytest.mark.parametrize("obs, exp_fn", observables_and_exp_fns)
- def test_expansion_qnode(self, params, obs, exp_fn):
+ def test_expansion_qnode(self, params, obs, exp_fn, seed):
"""Test that the transform integrates correctly with the transform program"""
@qml.transforms.broadcast_expand
- @qml.qnode(get_device())
+ @qml.qnode(get_device(seed=seed))
def circuit(x, y, z, obs):
qml.StatePrep(np.array([1, 0, 0, 0]), wires=[0, 1])
_ = make_ops(x, y, z)
@@ -125,7 +126,7 @@ def circuit(x, y, z, obs):
@pytest.mark.parametrize("params, size", list(zip(parameters, sizes)))
@pytest.mark.parametrize("obs, exp_fn", observables_and_exp_fns)
- def test_shot_vector_expval(self, params, size, obs, exp_fn, tol_stochastic):
+ def test_shot_vector_expval(self, params, size, obs, exp_fn, tol_stochastic, seed):
"""Test that expansion works as expected with shot vectors"""
ops = make_ops(*params)
expvals = [qml.expval(ob) for ob in obs]
@@ -137,7 +138,7 @@ def test_shot_vector_expval(self, params, size, obs, exp_fn, tol_stochastic):
assert len(tapes) == size
assert all(_tape.batch_size is None for _tape in tapes)
- result = fn(qml.execute(tapes, get_device(seed=1), None))
+ result = fn(qml.execute(tapes, get_device(seed=seed), None))
expected = exp_fn(*params)
assert len(result) == len(shots)
@@ -153,7 +154,7 @@ def test_shot_vector_expval(self, params, size, obs, exp_fn, tol_stochastic):
([{"op": qml.PauliZ(0)}, {"wires": [0, 1]}], [2, 4]),
],
)
- def test_shot_vector_probs(self, params, size, args, shapes):
+ def test_shot_vector_probs(self, params, size, args, shapes, seed):
"""Test that expansion works as expected with shot vectors"""
ops = make_ops(*params)
mps = [qml.probs(**a) for a in args]
@@ -165,7 +166,7 @@ def test_shot_vector_probs(self, params, size, args, shapes):
assert len(tapes) == size
assert all(_tape.batch_size is None for _tape in tapes)
- result = fn(qml.execute(tapes, get_device(), None))
+ result = fn(qml.execute(tapes, get_device(seed=seed), None))
assert len(result) == len(shots)
for r in result:
for i, _r in enumerate(r):
@@ -180,7 +181,7 @@ def test_shot_vector_probs(self, params, size, args, shapes):
([{"op": qml.PauliZ(0)}, {"wires": [0, 1]}], [(), (2,)]),
],
)
- def test_shot_vector_sample(self, params, size, args, shapes):
+ def test_shot_vector_sample(self, params, size, args, shapes, seed):
"""Test that expansion works as expected with shot vectors"""
ops = make_ops(*params)
mps = [qml.sample(**a) for a in args]
@@ -192,7 +193,7 @@ def test_shot_vector_sample(self, params, size, args, shapes):
assert len(tapes) == size
assert all(_tape.batch_size is None for _tape in tapes)
- result = fn(qml.execute(tapes, get_device(), None))
+ result = fn(qml.execute(tapes, get_device(seed=seed), None))
assert len(result) == len(shots)
for i, r in enumerate(result):
for j, _r in enumerate(r):
@@ -211,7 +212,7 @@ def test_shot_vector_sample(self, params, size, args, shapes):
[{"op": qml.PauliZ(0)}, {"wires": [0, 1]}],
],
)
- def test_shot_vector_counts(self, params, size, args):
+ def test_shot_vector_counts(self, params, size, args, seed):
"""Test that expansion works as expected with shot vectors"""
ops = make_ops(*params)
mps = [qml.counts(**a) for a in args]
@@ -223,7 +224,7 @@ def test_shot_vector_counts(self, params, size, args):
assert len(tapes) == size
assert all(_tape.batch_size is None for _tape in tapes)
- result = fn(qml.execute(tapes, get_device(), None))
+ result = fn(qml.execute(tapes, get_device(seed=seed), None))
assert len(result) == len(shots)
for r in result:
for _r in r:
@@ -234,7 +235,7 @@ def test_shot_vector_counts(self, params, size, args):
# TODO: Update broadcast_expand to unwrap counts dictionaries from 0-D numpy arrays
assert isinstance(_r.item(), dict)
- def test_state_prep(self):
+ def test_state_prep(self, seed):
"""Test that expansion works for state preparations"""
ops = [qml.CNOT([0, 1])]
meas = [qml.expval(qml.PauliZ(1))]
@@ -245,7 +246,7 @@ def test_state_prep(self):
assert len(tapes) == 4
assert all(t.batch_size is None for t in tapes)
- result = fn(qml.execute(tapes, get_device(), None))
+ result = fn(qml.execute(tapes, get_device(seed=seed), None))
expected = np.array([1, -1, -1, 1])
assert qml.math.allclose(result, expected)
@@ -275,12 +276,12 @@ def test_not_copied(self):
@pytest.mark.parametrize("params", parameters)
@pytest.mark.parametrize("obs, exp_fn", observables_and_exp_fns)
@pytest.mark.parametrize("diff_method", ["parameter-shift", "backprop"])
- def test_autograd(self, params, obs, exp_fn, diff_method):
+ def test_autograd(self, params, obs, exp_fn, diff_method, seed):
"""Test that the expansion works with autograd and is differentiable."""
params = tuple(pnp.array(p, requires_grad=True) for p in params)
@qml.transforms.broadcast_expand
- @qml.qnode(get_device(), interface="autograd", diff_method=diff_method)
+ @qml.qnode(get_device(seed=seed), interface="autograd", diff_method=diff_method)
def cost(*params):
make_ops(*params)
return qml.math.stack([qml.expval(ob) for ob in obs])
@@ -299,7 +300,7 @@ def cost(*params):
@pytest.mark.parametrize("obs, exp_fn", observables_and_exp_fns)
@pytest.mark.parametrize("use_jit", [True, False])
@pytest.mark.parametrize("diff_method", ["parameter-shift", "backprop"])
- def test_jax(self, params, obs, exp_fn, use_jit, diff_method):
+ def test_jax(self, params, obs, exp_fn, use_jit, diff_method, seed):
"""Test that the expansion works with jax and is differentiable."""
# pylint: disable=too-many-arguments
import jax
@@ -309,7 +310,7 @@ def test_jax(self, params, obs, exp_fn, use_jit, diff_method):
params = tuple(jax.numpy.array(p) for p in params)
@qml.transforms.broadcast_expand
- @qml.qnode(get_device(), interface="jax", diff_method=diff_method)
+ @qml.qnode(get_device(seed=seed), interface="jax", diff_method=diff_method)
def cost(*params):
make_ops(*params)
return tuple(qml.expval(ob) for ob in obs)
@@ -335,14 +336,14 @@ def cost(*params):
@pytest.mark.tf
@pytest.mark.parametrize("params", parameters)
@pytest.mark.parametrize("obs, exp_fn", observables_and_exp_fns)
- def test_tf(self, params, obs, exp_fn):
+ def test_tf(self, params, obs, exp_fn, seed):
"""Test that the expansion works with TensorFlow and is differentiable."""
import tensorflow as tf
params = tuple(tf.Variable(p, dtype=tf.float64) for p in params)
@qml.transforms.broadcast_expand
- @qml.qnode(get_device(), interface="tensorflow")
+ @qml.qnode(get_device(seed=seed), interface="tensorflow")
def cost(*params):
make_ops(*params)
return tuple(qml.expval(ob) for ob in obs)
@@ -365,7 +366,7 @@ def cost(*params):
@pytest.mark.parametrize("params", parameters)
@pytest.mark.parametrize("obs, exp_fn", observables_and_exp_fns)
@pytest.mark.parametrize("diff_method", ["parameter-shift", "backprop"])
- def test_torch(self, params, obs, exp_fn, diff_method):
+ def test_torch(self, params, obs, exp_fn, diff_method, seed):
"""Test that the expansion works with torch and is differentiable."""
import torch
@@ -375,7 +376,7 @@ def test_torch(self, params, obs, exp_fn, diff_method):
params = tuple(pnp.array(p, requires_grad=True) for p in params)
@qml.transforms.broadcast_expand
- @qml.qnode(get_device(), interface="torch", diff_method=diff_method)
+ @qml.qnode(get_device(seed=seed), interface="torch", diff_method=diff_method)
def cost(*params):
make_ops(*params)
return tuple(qml.expval(ob) for ob in obs)
diff --git a/tests/transforms/test_defer_measurements.py b/tests/transforms/test_defer_measurements.py
index b85de016d3f..1c3b483c871 100644
--- a/tests/transforms/test_defer_measurements.py
+++ b/tests/transforms/test_defer_measurements.py
@@ -368,10 +368,12 @@ def circ1(phi):
@pytest.mark.parametrize("reduce_postselected", [None, True, False])
@pytest.mark.parametrize("shots", [None, 1000])
@pytest.mark.parametrize("phi", np.linspace(np.pi / 2, 7 * np.pi / 2, 6))
- def test_some_postselection_qnode(self, phi, shots, reduce_postselected, tol, tol_stochastic):
+ def test_some_postselection_qnode(
+ self, phi, shots, reduce_postselected, tol, tol_stochastic, seed
+ ):
"""Test that a qnode with some mid-circuit measurements with postselection
is transformed correctly by defer_measurements"""
- dev = DefaultQubit(seed=822)
+ dev = DefaultQubit(seed=seed)
dm_transform = qml.defer_measurements
if reduce_postselected is not None:
@@ -491,10 +493,10 @@ def circ2():
qml.assert_equal(op, expected_op)
@pytest.mark.parametrize("shots", [None, 1000, [1000, 1000]])
- def test_measurement_statistics_single_wire(self, shots):
+ def test_measurement_statistics_single_wire(self, shots, seed):
"""Test that users can collect measurement statistics on
a single mid-circuit measurement."""
- dev = DefaultQubit(seed=10)
+ dev = DefaultQubit(seed=seed)
@qml.defer_measurements
@qml.qnode(dev)
@@ -503,7 +505,7 @@ def circ1(x):
m0 = qml.measure(0)
return qml.probs(op=m0)
- dev = DefaultQubit(seed=10)
+ dev = DefaultQubit(seed=seed)
@qml.qnode(dev)
def circ2(x):
@@ -548,11 +550,11 @@ def circ2(x):
assert mp.mv.wires == qml.wires.Wires([1])
@pytest.mark.parametrize("shots", [None, 1000, [1000, 1000]])
- def test_terminal_measurements(self, shots):
+ def test_terminal_measurements(self, shots, seed):
"""Test that mid-circuit measurement statistics and terminal measurements
can be made together."""
# Using DefaultQubit to allow non-commuting measurements
- dev = DefaultQubit(seed=10)
+ dev = DefaultQubit(seed=seed)
@qml.defer_measurements
@qml.qnode(dev)
@@ -562,7 +564,7 @@ def circ1(x, y):
qml.RY(y, 1)
return qml.expval(qml.PauliX(1)), qml.probs(op=m0)
- dev = DefaultQubit(seed=10)
+ dev = DefaultQubit(seed=seed)
@qml.qnode(dev)
def circ2(x, y):
diff --git a/tests/transforms/test_dynamic_one_shot.py b/tests/transforms/test_dynamic_one_shot.py
index 903a54628f1..56d40256ce4 100644
--- a/tests/transforms/test_dynamic_one_shot.py
+++ b/tests/transforms/test_dynamic_one_shot.py
@@ -90,13 +90,13 @@ def f(x):
@pytest.mark.jax
@pytest.mark.parametrize("use_jit", [True, False])
@pytest.mark.parametrize("diff_method", [None, "best"])
-def test_hw_like_with_jax(use_jit, diff_method):
+def test_hw_like_with_jax(use_jit, diff_method, seed):
"""Test that invalid shots are replaced with INTEGER_MIN_VAL if
postselect_mode="hw-like" with JAX"""
import jax # pylint: disable=import-outside-toplevel
shots = 10
- dev = qml.device("default.qubit", shots=shots, seed=jax.random.PRNGKey(123))
+ dev = qml.device("default.qubit", shots=shots, seed=jax.random.PRNGKey(seed))
@qml.qnode(dev, postselect_mode="hw-like", diff_method=diff_method)
def f(x):
@@ -280,15 +280,13 @@ class TestInterfaces:
@pytest.mark.parametrize("shots", [1, 20, [20, 21]])
@pytest.mark.parametrize("n_mcms", [1, 3])
def test_interface_tape_results(
- self, shots, n_mcms, measure_f, interface, use_interface_for_results
+ self, shots, n_mcms, measure_f, interface, use_interface_for_results, seed
): # pylint: disable=unused-argument
"""Test that the simulation results of a tape are correct with interface parameters"""
if interface == "jax":
from jax.random import PRNGKey
- seed = PRNGKey(123)
- else:
- seed = 123
+ seed = PRNGKey(seed)
dev = qml.device("default.qubit", wires=4, shots=shots, seed=seed)
param = qml.math.array(np.pi / 2, like=interface)
diff --git a/tests/transforms/test_mitigate.py b/tests/transforms/test_mitigate.py
index 05cd77b65da..6a05309d437 100644
--- a/tests/transforms/test_mitigate.py
+++ b/tests/transforms/test_mitigate.py
@@ -196,7 +196,7 @@ def test_reps_per_factor_not_1(self, mocker):
assert args[0][0] == scale_factors
assert np.allclose(args[0][1], np.mean(np.reshape(random_results, (3, 2)), axis=1))
- def test_broadcasting(self):
+ def test_broadcasting(self, seed):
"""Tests that mitigate_with_zne supports batch arguments"""
batch_size = 2
@@ -214,7 +214,7 @@ def original_qnode(inputs):
mitigated_qnode_expanded = qml.transforms.mitigate_with_zne(
expanded_qnode, [1, 2, 3], fold_global, richardson_extrapolate
)
- rng = np.random.default_rng(seed=18954959)
+ rng = np.random.default_rng(seed=seed)
inputs = rng.uniform(0, 1, size=(batch_size, 2**2))
result_orig = mitigated_qnode_orig(inputs)
result_expanded = mitigated_qnode_expanded(inputs)
diff --git a/tests/transforms/test_qcut.py b/tests/transforms/test_qcut.py
index e5af9c16aff..d0bc675ca81 100644
--- a/tests/transforms/test_qcut.py
+++ b/tests/transforms/test_qcut.py
@@ -28,7 +28,6 @@
import numpy as onp
import pytest
-from flaky import flaky
from networkx import MultiDiGraph
from networkx import __version__ as networkx_version
from networkx import number_of_selfloops
@@ -2513,14 +2512,13 @@ class TestCutCircuitMCTransform:
Tests that the `cut_circuit_mc` transform gives the correct results.
"""
- @flaky(max_runs=3)
- def test_cut_circuit_mc_expval(self, dev_fn):
+ def test_cut_circuit_mc_expval(self, dev_fn, seed):
"""
Tests that a circuit containing sampling measurements can be cut and
recombined to give the correct expectation value
"""
- dev_sim = dev_fn(wires=3)
+ dev_sim = dev_fn(wires=3, seed=seed)
@qml.qnode(dev_sim)
def target_circuit(v):
@@ -3878,9 +3876,8 @@ class TestCutCircuitTransform:
Tests for the cut_circuit transform
"""
- @flaky(max_runs=3)
@pytest.mark.parametrize("shots", [None, int(1e7)])
- def test_simple_cut_circuit(self, mocker, use_opt_einsum, shots):
+ def test_simple_cut_circuit(self, mocker, use_opt_einsum, shots, seed):
"""
Tests the full circuit cutting pipeline returns the correct value and
gradient for a simple circuit using the `cut_circuit` transform.
@@ -3888,7 +3885,7 @@ def test_simple_cut_circuit(self, mocker, use_opt_einsum, shots):
if use_opt_einsum:
pytest.importorskip("opt_einsum")
- dev = qml.device("default.qubit", wires=2, shots=shots)
+ dev = qml.device("default.qubit", wires=2, shots=shots, seed=seed)
@qml.qnode(dev)
def circuit(x):
@@ -4423,9 +4420,8 @@ def f(params):
assert np.isclose(res, res_expected)
assert np.allclose(grad, grad_expected)
- @flaky(max_runs=3)
@pytest.mark.parametrize("shots", [None, int(1e7)])
- def test_standard_circuit(self, mocker, use_opt_einsum, shots):
+ def test_standard_circuit(self, mocker, use_opt_einsum, shots, seed):
"""
Tests that the full circuit cutting pipeline returns the correct value for a typical
scenario. The circuit is drawn below:
@@ -4438,7 +4434,7 @@ def test_standard_circuit(self, mocker, use_opt_einsum, shots):
if use_opt_einsum:
pytest.importorskip("opt_einsum")
- dev_original = qml.device("default.qubit", wires=4)
+ dev_original = qml.device("default.qubit", wires=4, seed=seed)
# We need a 3-qubit device
dev_cut = qml.device("default.qubit", wires=3, shots=shots)