diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml
index 8ea39a1e5a5..07bae8e236b 100644
--- a/.github/workflows/interface-unit-tests.yml
+++ b/.github/workflows/interface-unit-tests.yml
@@ -263,9 +263,9 @@ jobs:
strategy:
matrix:
config:
- - device: default.qubit
+ - device: default.qubit.legacy
shots: None
- - device: default.qubit
+ - device: default.qubit.legacy
shots: 10000
# - device: default.qubit.tf
# shots: None
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 842d729aa2a..d4d6d286e9e 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -17,9 +17,10 @@
* Quantum information transforms are updated to the new transform program system.
[(#4569)](https://github.com/PennyLaneAI/pennylane/pull/4569)
-* `qml.devices.DefaultQubit` now implements the new device API. The old version of `default.qubit`
- is still accessible via `qml.devices.DefaultQubitLegacy`, or via short name `default.qubit.legacy`.
+* `default.qubit` now implements the new device API. The old version of the device is still
+ accessible by the short name `default.qubit.legacy`, or directly via `qml.devices.DefaultQubitLegacy`.
[(#4594)](https://github.com/PennyLaneAI/pennylane/pull/4594)
+ [(#4436)](https://github.com/PennyLaneAI/pennylane/pull/4436)
Improvements ðŸ›
@@ -184,6 +185,12 @@
which effectively just called `marginal_prob` with `np.abs(state) ** 2`.
[(#4602)](https://github.com/PennyLaneAI/pennylane/pull/4602)
+* `default.qubit` now implements the new device API. If you initialize a device
+ with `qml.device("default.qubit")`, all functions and properties that were tied to the old
+ device API will no longer be on the device. The legacy version can still be accessed with
+ `qml.device("default.qubit.legacy", wires=n_wires)`.
+ [(#4436)](https://github.com/PennyLaneAI/pennylane/pull/4436)
+
Deprecations 👋
* The ``prep`` keyword argument in ``QuantumScript`` is deprecated and will be removed from `QuantumScript`.
diff --git a/pennylane/devices/default_qubit.py b/pennylane/devices/default_qubit.py
index 6359a262269..ed029cc3653 100644
--- a/pennylane/devices/default_qubit.py
+++ b/pennylane/devices/default_qubit.py
@@ -146,7 +146,7 @@ def f(x):
@property
def name(self):
"""The name of the device."""
- return "default.qubit.2"
+ return "default.qubit"
# pylint:disable = too-many-arguments
def __init__(
@@ -193,6 +193,7 @@ def supports_derivatives(
if (
execution_config.gradient_method == "backprop"
and execution_config.device_options.get("max_workers", self._max_workers) is None
+ and execution_config.interface is not None
):
return True
diff --git a/pennylane/devices/default_qubit_legacy.py b/pennylane/devices/default_qubit_legacy.py
index dc4983933c3..e7842935d43 100644
--- a/pennylane/devices/default_qubit_legacy.py
+++ b/pennylane/devices/default_qubit_legacy.py
@@ -104,8 +104,8 @@ class DefaultQubitLegacy(QubitDevice):
returns analytical results.
"""
- name = "Default qubit PennyLane plugin"
- short_name = "default.qubit"
+ name = "Default qubit PennyLane plugin (Legacy)"
+ short_name = "default.qubit.legacy"
pennylane_requires = __version__
version = __version__
author = "Xanadu Inc."
diff --git a/pennylane/devices/device_api.py b/pennylane/devices/device_api.py
index 1fb8dcb81b1..c8bfd53a825 100644
--- a/pennylane/devices/device_api.py
+++ b/pennylane/devices/device_api.py
@@ -41,9 +41,6 @@ class Device(abc.ABC):
"""A device driver that can control one or more backends. A backend can be either a physical
Quantum Processing Unit or a virtual one such as a simulator.
- Device drivers should be configured to run under :func:`~.enable_return`, the newer
- return shape specification, as the old return shape specification is deprecated.
-
Only the ``execute`` method must be defined to construct a device driver.
.. details::
diff --git a/pennylane/devices/qubit/adjoint_jacobian.py b/pennylane/devices/qubit/adjoint_jacobian.py
index 1c6bc8ba9db..8be6a99909b 100644
--- a/pennylane/devices/qubit/adjoint_jacobian.py
+++ b/pennylane/devices/qubit/adjoint_jacobian.py
@@ -75,6 +75,8 @@ def adjoint_jacobian(tape: QuantumTape, state=None):
param_number = len(tape.get_parameters(trainable_only=False, operations_only=True)) - 1
trainable_param_number = len(tape.trainable_params) - 1
for op in reversed(tape.operations[tape.num_preps :]):
+ if isinstance(op, qml.Snapshot):
+ continue
adj_op = qml.adjoint(op)
ket = apply_operation(adj_op, ket)
diff --git a/pennylane/math/single_dispatch.py b/pennylane/math/single_dispatch.py
index dd40be00e78..2bf96bef5be 100644
--- a/pennylane/math/single_dispatch.py
+++ b/pennylane/math/single_dispatch.py
@@ -454,6 +454,7 @@ def _cond_tf(pred, true_fn, false_fn, args):
"vander",
lambda *args, **kwargs: _i("tf").experimental.numpy.vander(*args, **kwargs),
)
+ar.register_function("tensorflow", "size", lambda x: _i("tf").size(x))
# -------------------------------- Torch --------------------------------- #
diff --git a/pennylane/measurements/state.py b/pennylane/measurements/state.py
index 952223ffb1a..2cc0c576b08 100644
--- a/pennylane/measurements/state.py
+++ b/pennylane/measurements/state.py
@@ -222,4 +222,4 @@ def process_state(self, state: Sequence[complex], wire_order: Wires):
# pylint:disable=redefined-outer-name
wire_map = dict(zip(wire_order, range(len(wire_order))))
mapped_wires = [wire_map[w] for w in self.wires]
- return qml.math.reduce_statevector(state, indices=mapped_wires, c_dtype=state.dtype)
+ return qml.math.reduce_statevector(state, indices=mapped_wires)
diff --git a/pennylane/optimize/spsa.py b/pennylane/optimize/spsa.py
index a8313735640..a3a1e5faae8 100644
--- a/pennylane/optimize/spsa.py
+++ b/pennylane/optimize/spsa.py
@@ -262,11 +262,13 @@ def compute_grad(self, objective_fn, args, kwargs):
yminus = objective_fn(*thetaminus, **kwargs)
try:
# pylint: disable=protected-access
- shots = (
- Shots(objective_fn.device._raw_shot_sequence)
- if objective_fn.device.shot_vector is not None
- else Shots(None)
- )
+ dev_shots = objective_fn.device.shots
+ if isinstance(dev_shots, Shots):
+ shots = dev_shots if dev_shots.has_partitioned_shots else Shots(None)
+ elif objective_fn.device.shot_vector is not None:
+ shots = Shots(objective_fn.device._raw_shot_sequence) # pragma: no cover
+ else:
+ shots = Shots(None)
if np.prod(objective_fn.func(*args).shape(objective_fn.device, shots)) > 1:
raise ValueError(
"The objective function must be a scalar function for the gradient "
diff --git a/pennylane/qnode.py b/pennylane/qnode.py
index 6112915bd74..8c0bddcd55d 100644
--- a/pennylane/qnode.py
+++ b/pennylane/qnode.py
@@ -705,7 +705,9 @@ def _validate_backprop_method(device, interface, shots=None):
config = qml.devices.ExecutionConfig(gradient_method="backprop", interface=interface)
if device.supports_derivatives(config):
return "backprop", {}, device
- raise qml.QuantumFunctionError(f"Device {device.name} does not support backprop")
+ raise qml.QuantumFunctionError(
+ f"Device {device.name} does not support backprop with {config}"
+ )
mapped_interface = INTERFACE_MAP.get(interface, interface)
diff --git a/setup.py b/setup.py
index 5bd049958f4..34021c1c337 100644
--- a/setup.py
+++ b/setup.py
@@ -47,7 +47,7 @@
# TODO: rename entry point 'pennylane.plugins' to 'pennylane.devices'.
# This requires a rename in the setup file of all devices, and is best done during another refactor
"pennylane.plugins": [
- "default.qubit = pennylane.devices:DefaultQubitLegacy",
+ "default.qubit = pennylane.devices:DefaultQubit",
"default.qubit.legacy = pennylane.devices:DefaultQubitLegacy",
"default.gaussian = pennylane.devices:DefaultGaussian",
"default.qubit.tf = pennylane.devices.default_qubit_tf:DefaultQubitTF",
diff --git a/tests/devices/experimental/test_default_qubit_2.py b/tests/devices/experimental/test_default_qubit_2.py
index 849bc0006a2..c9233240776 100644
--- a/tests/devices/experimental/test_default_qubit_2.py
+++ b/tests/devices/experimental/test_default_qubit_2.py
@@ -27,7 +27,7 @@
def test_name():
"""Tests the name of DefaultQubit."""
- assert DefaultQubit().name == "default.qubit.2"
+ assert DefaultQubit().name == "default.qubit"
def test_shots():
@@ -200,6 +200,56 @@ def test_tracking_resources(self):
assert len(tracker.history["resources"]) == 1
assert tracker.history["resources"][0] == expected_resources
+ def test_tracking_batched_execution(self):
+ """Test the number of times the device is executed over a QNode's
+ lifetime is tracked by the device's tracker."""
+
+ dev_1 = qml.device("default.qubit", wires=2)
+
+ def circuit_1(x, y):
+ qml.RX(x, wires=[0])
+ qml.RY(y, wires=[1])
+ qml.CNOT(wires=[0, 1])
+ return qml.expval(qml.PauliZ(0) @ qml.PauliX(1))
+
+ node_1 = qml.QNode(circuit_1, dev_1)
+ num_evals_1 = 10
+
+ with qml.Tracker(dev_1, persistent=True) as tracker1:
+ for _ in range(num_evals_1):
+ node_1(0.432, np.array([0.12, 0.5, 3.2]))
+ assert tracker1.totals["executions"] == num_evals_1
+
+ # test a second instance of a default qubit device
+ dev_2 = qml.device("default.qubit", wires=2)
+
+ def circuit_2(x):
+ qml.RX(x, wires=[0])
+ qml.CNOT(wires=[0, 1])
+ return qml.expval(qml.PauliZ(0) @ qml.PauliX(1))
+
+ node_2 = qml.QNode(circuit_2, dev_2)
+ num_evals_2 = 5
+
+ with qml.Tracker(dev_2) as tracker2:
+ for _ in range(num_evals_2):
+ node_2(np.array([0.432, 0.61, 8.2]))
+ assert tracker2.totals["executions"] == num_evals_2
+
+ # test a new circuit on an existing instance of a qubit device
+ def circuit_3(y):
+ qml.RY(y, wires=[1])
+ qml.CNOT(wires=[0, 1])
+ return qml.expval(qml.PauliZ(0) @ qml.PauliX(1))
+
+ node_3 = qml.QNode(circuit_3, dev_1)
+ num_evals_3 = 7
+
+ with tracker1:
+ for _ in range(num_evals_3):
+ node_3(np.array([0.12, 1.214]))
+ assert tracker1.totals["executions"] == num_evals_1 + num_evals_3
+
# pylint: disable=too-few-public-methods
class TestPreprocessing:
@@ -302,7 +352,7 @@ def test_supports_backprop(self):
assert dev.supports_jvp() is True
assert dev.supports_vjp() is True
- config = ExecutionConfig(gradient_method="backprop")
+ config = ExecutionConfig(gradient_method="backprop", interface="auto")
assert dev.supports_derivatives(config) is True
assert dev.supports_jvp(config) is True
assert dev.supports_vjp(config) is True
@@ -317,6 +367,11 @@ def test_supports_backprop(self):
assert dev.supports_jvp(config) is False
assert dev.supports_vjp(config) is False
+ config = ExecutionConfig(gradient_method="backprop", interface=None)
+ assert dev.supports_derivatives(config) is False
+ assert dev.supports_jvp(config) is False
+ assert dev.supports_vjp(config) is False
+
def test_supports_adjoint(self):
"""Test that DefaultQubit says that it supports adjoint differentiation."""
dev = DefaultQubit()
diff --git a/tests/devices/test_default_qubit_autograd.py b/tests/devices/test_default_qubit_autograd.py
index 78094c23191..150f95e6dad 100644
--- a/tests/devices/test_default_qubit_autograd.py
+++ b/tests/devices/test_default_qubit_autograd.py
@@ -487,7 +487,7 @@ def circuit(a, b):
def cost(a, b):
prob_wire_1 = circuit(a, b)
- return prob_wire_1[1] - prob_wire_1[0]
+ return prob_wire_1[1] - prob_wire_1[0] # pylint:disable=unsubscriptable-object
res = cost(a, b)
expected = -np.cos(a) * np.cos(b)
@@ -513,7 +513,7 @@ def circuit(a, b):
def cost(a, b):
prob_wire_1 = circuit(a, b)
- return prob_wire_1[:, 1] - prob_wire_1[:, 0]
+ return prob_wire_1[:, 1] - prob_wire_1[:, 0] # pylint:disable=unsubscriptable-object
res = cost(a, b)
expected = -np.cos(a) * np.cos(b)
diff --git a/tests/devices/test_default_qubit_legacy.py b/tests/devices/test_default_qubit_legacy.py
index ec98819a7d4..aaf2f8fe6ba 100644
--- a/tests/devices/test_default_qubit_legacy.py
+++ b/tests/devices/test_default_qubit_legacy.py
@@ -643,7 +643,7 @@ def test_apply_errors_qubit_state_vector(self, qubit_device_2_wires):
with pytest.raises(
DeviceError,
match="Operation StatePrep cannot be used after other Operations have already been applied "
- "on a default.qubit device.",
+ "on a default.qubit.legacy device.",
):
qubit_device_2_wires.reset()
qubit_device_2_wires.apply(
@@ -664,7 +664,7 @@ def test_apply_errors_basis_state(self, qubit_device_2_wires):
with pytest.raises(
DeviceError,
match="Operation BasisState cannot be used after other Operations have already been applied "
- "on a default.qubit device.",
+ "on a default.qubit.legacy device.",
):
qubit_device_2_wires.reset()
qubit_device_2_wires.apply(
@@ -2091,7 +2091,7 @@ def test_apply_parametrized_evolution_raises_error(self):
param_ev = qml.evolve(ParametrizedHamiltonian([1], [qml.PauliX(0)]))
with pytest.raises(
NotImplementedError,
- match="The device default.qubit cannot execute a ParametrizedEvolution operation",
+ match="The device default.qubit.legacy cannot execute a ParametrizedEvolution operation",
):
self.dev._apply_parametrized_evolution(state=self.state, operation=param_ev)
diff --git a/tests/devices/test_default_qubit_legacy_broadcasting.py b/tests/devices/test_default_qubit_legacy_broadcasting.py
index 8040f505e4c..c737f194959 100644
--- a/tests/devices/test_default_qubit_legacy_broadcasting.py
+++ b/tests/devices/test_default_qubit_legacy_broadcasting.py
@@ -462,7 +462,7 @@ def test_apply_errors_qubit_state_vector_broadcasted(self, qubit_device_2_wires)
with pytest.raises(
DeviceError,
match="Operation StatePrep cannot be used after other Operations have already been applied "
- "on a default.qubit device.",
+ "on a default.qubit.legacy device.",
):
qubit_device_2_wires.apply([qml.RZ(0.5, wires=[0]), vec])
@@ -491,7 +491,7 @@ def test_apply_errors_basis_state_broadcasted(self, qubit_device_2_wires):
with pytest.raises(
DeviceError,
match="Operation BasisState cannot be used after other Operations have already been applied "
- "on a default.qubit device.",
+ "on a default.qubit.legacy device.",
):
qubit_device_2_wires.apply([vec])
diff --git a/tests/devices/test_default_qubit_tf.py b/tests/devices/test_default_qubit_tf.py
index f30d4d70f17..5fbfcb1820d 100644
--- a/tests/devices/test_default_qubit_tf.py
+++ b/tests/devices/test_default_qubit_tf.py
@@ -1873,7 +1873,7 @@ def circuit(a, b):
# get the probability of wire 1
prob_wire_1 = circuit(a, b)
# compute Prob(|1>_1) - Prob(|0>_1)
- res = prob_wire_1[1] - prob_wire_1[0]
+ res = prob_wire_1[1] - prob_wire_1[0] # pylint:disable=unsubscriptable-object
expected = -tf.cos(a) * tf.cos(b)
assert np.allclose(res, expected, atol=tol, rtol=0)
@@ -1900,7 +1900,7 @@ def circuit(a, b):
# get the probability of wire 1
prob_wire_1 = circuit(a, b)
# compute Prob(|1>_1) - Prob(|0>_1)
- res = prob_wire_1[:, 1] - prob_wire_1[:, 0]
+ res = prob_wire_1[:, 1] - prob_wire_1[:, 0] # pylint:disable=unsubscriptable-object
expected = -tf.cos(a) * tf.cos(b)
assert np.allclose(res, expected, atol=tol, rtol=0)
@@ -1938,6 +1938,7 @@ def circuit(a, b):
[-0.5 * np.sin(a) * (np.cos(b) + 1), 0.5 * np.sin(b) * (1 - np.cos(a))]
)
+ # pylint:disable=no-member
assert np.allclose(res.numpy(), expected_cost, atol=tol, rtol=0)
res = tape.gradient(res, [a_tf, b_tf])
@@ -1971,6 +1972,7 @@ def circuit(a, b):
[-0.5 * np.sin(a) * (np.cos(b) + 1), 0.5 * np.sin(b) * (1 - np.cos(a))]
)
+ # pylint:disable=no-member
assert np.allclose(res.numpy(), expected_cost, atol=tol, rtol=0)
jac = tape.jacobian(res, [a_tf, b_tf])
@@ -2112,8 +2114,8 @@ def circuit(a):
res = circuit(a)
assert isinstance(res, tf.Tensor)
- assert res.shape == (shots,)
- assert set(res.numpy()) == {-1, 1}
+ assert res.shape == (shots,) # pylint:disable=comparison-with-callable
+ assert set(res.numpy()) == {-1, 1} # pylint:disable=no-member
def test_estimating_marginal_probability(self, tol):
"""Test that the probability of a subset of wires is accurately estimated."""
@@ -2190,8 +2192,8 @@ def circuit(a):
res = circuit(a)
assert isinstance(res, tf.Tensor)
- assert res.shape == (3, shots)
- assert set(res.numpy().flat) == {-1, 1}
+ assert res.shape == (3, shots) # pylint:disable=comparison-with-callable
+ assert set(res.numpy().flat) == {-1, 1} # pylint:disable=no-member
@pytest.mark.parametrize("batch_size", [2, 3])
def test_estimating_marginal_probability_broadcasted(self, batch_size, tol):
diff --git a/tests/devices/test_default_qubit_torch.py b/tests/devices/test_default_qubit_torch.py
index 9c2a4c53801..52f80820318 100644
--- a/tests/devices/test_default_qubit_torch.py
+++ b/tests/devices/test_default_qubit_torch.py
@@ -1808,7 +1808,7 @@ def circuit(p):
return qml.expval(qml.PauliZ(0))
res = circuit([x, y, z])
- res.backward()
+ res.backward() # pylint:disable=no-member
expected = torch.cos(3 * x) * torch.cos(y) * torch.cos(z / 2) - torch.sin(
3 * x
@@ -1895,7 +1895,7 @@ def circuit(x):
return qml.expval(qml.PauliZ(0))
res = circuit(p)
- res.backward()
+ res.backward() # pylint:disable=no-member
expected = torch.cos(y) ** 2 - torch.sin(x) * torch.sin(y) ** 2
@@ -2033,7 +2033,7 @@ def circuit(a, b):
# get the probability of wire 1
prob_wire_1 = circuit(a, b)
# compute Prob(|1>_1) - Prob(|0>_1)
- res = prob_wire_1[1] - prob_wire_1[0]
+ res = prob_wire_1[1] - prob_wire_1[0] # pylint:disable=unsubscriptable-object
res.backward()
expected = -torch.cos(a) * torch.cos(b)
@@ -2062,7 +2062,7 @@ def cost(a, b):
# get the probability of wire 1
prob_wire_1 = circuit(a, b)
# compute Prob(|1>_1) - Prob(|0>_1)
- res = prob_wire_1[:, 1] - prob_wire_1[:, 0]
+ res = prob_wire_1[:, 1] - prob_wire_1[:, 0] # pylint:disable=unsubscriptable-object
return res
res = cost(a, b)
@@ -2087,7 +2087,7 @@ def circuit(a, b):
b = torch.tensor(0.654, dtype=torch.float64, requires_grad=True, device=torch_device)
res = circuit(a, b)
- res.backward()
+ res.backward() # pylint:disable=no-member
# the analytic result of evaluating circuit(a, b)
expected_cost = 0.5 * (torch.cos(a) * torch.cos(b) + torch.cos(a) - torch.cos(b) + 1)
@@ -2242,7 +2242,7 @@ def circuit(a):
res = circuit(a)
assert torch.is_tensor(res)
- assert res.shape == (shots,)
+ assert res.shape == (shots,) # pylint:disable=comparison-with-callable
assert torch.allclose(
torch.unique(res), torch.tensor([-1, 1], dtype=torch.int64, device=torch_device)
)
@@ -2326,7 +2326,7 @@ def circuit(a):
res = circuit(a)
assert torch.is_tensor(res)
- assert res.shape == (batch_size, shots)
+ assert res.shape == (batch_size, shots) # pylint:disable=comparison-with-callable
assert torch.allclose(
torch.unique(res), torch.tensor([-1, 1], dtype=torch.int64, device=torch_device)
)
diff --git a/tests/docs/test_supported_confs.py b/tests/docs/test_supported_confs.py
index b8d83a0d72f..84e38b40822 100644
--- a/tests/docs/test_supported_confs.py
+++ b/tests/docs/test_supported_confs.py
@@ -24,7 +24,6 @@
A configuration is supported if gradients can be computed for the
QNode without an exception being raised."""
# pylint: disable=too-many-arguments
-import re
import pytest
import pennylane as qml
@@ -47,7 +46,6 @@
jax = pytest.importorskip("jax")
jnp = pytest.importorskip("jax.numpy")
-devices = ["default.qubit"]
interfaces = [None, "autograd", "jax", "tf", "torch"]
diff_interfaces = ["autograd", "jax", "tf", "torch"]
shots_list = [None, 100]
@@ -277,13 +275,10 @@ def test_all_device(self, interface, return_type, shots, wire_specs):
@pytest.mark.parametrize("wire_specs", wire_specs_list)
def test_none_backprop(self, return_type, wire_specs):
"""Test interface=None and diff_method=backprop raises an error"""
- msg = (
- "Device default.qubit only supports diff_method='backprop' when "
- "using the ['tf', 'torch', 'autograd', 'jax'] interfaces."
- )
- msg = re.escape(msg)
-
- with pytest.raises(QuantumFunctionError, match=msg):
+ with pytest.raises(
+ QuantumFunctionError,
+ match=r"Device default\.qubit does not support backprop with .*gradient_method='backprop'.*interface=None",
+ ):
get_qnode(None, "backprop", return_type, None, wire_specs)
@pytest.mark.parametrize(
@@ -295,17 +290,33 @@ def test_none_backprop(self, return_type, wire_specs):
def test_none_all(self, diff_method, return_type, shots, wire_specs):
"""Test interface=None and diff_method in [adjoint, parameter-shift,
finite-diff, spsa, hadamard] has a working forward pass"""
- warn_msg = (
- "Requested adjoint differentiation to be computed with finite shots. "
- "Adjoint differentiation always calculated exactly."
- )
+ circuit = get_qnode(None, diff_method, return_type, shots, wire_specs)
+ x = get_variable(None, wire_specs)
+
+ msg = None
+ if not shots and return_type is Sample:
+ msg = "Analytic circuits must only contain StateMeasurements"
+ elif diff_method == "adjoint":
+ if shots:
+ msg = (
+ "Circuits with finite shots must be executed with non-analytic gradient methods"
+ )
+ elif return_type not in ("Hermitian", "Projector", Expectation):
+ msg = "Adjoint differentiation method does not support measurement .*"
+ elif shots and return_type in (
+ VnEntropy,
+ MutualInfo,
+ "DensityMatrix",
+ "StateCost",
+ "StateVector",
+ ):
+ msg = "Circuits with finite shots must only contain"
- if diff_method == "adjoint" and shots is not None:
- # this warning is still raised in the forward pass
- with pytest.warns(UserWarning, match=warn_msg):
- get_qnode(None, diff_method, return_type, shots, wire_specs)
+ if msg is not None:
+ with pytest.raises(qml.DeviceError, match=msg):
+ circuit(x)
else:
- get_qnode(None, diff_method, return_type, shots, wire_specs)
+ circuit(x)
@pytest.mark.parametrize("interface", diff_interfaces)
@pytest.mark.parametrize(
@@ -348,18 +359,16 @@ def test_all_backprop_finite_shots(self, interface, return_type, wire_specs):
def test_all_adjoint_nonexp(self, interface, return_type, shots, wire_specs):
"""Test diff_method=adjoint raises an error for non-expectation
measurements for all interfaces"""
- msg = "Adjoint differentiation method does not support measurement .*"
-
- warn_msg = (
- "Requested adjoint differentiation to be computed with finite shots. "
- "Adjoint differentiation always calculated exactly."
+ msg = (
+ "Circuits with finite shots must be executed with non-analytic gradient methods"
+ if shots
+ else "Adjoint differentiation method does not support measurement .*"
)
- with pytest.raises(QuantumFunctionError, match=msg):
- with pytest.warns(UserWarning, match=warn_msg):
- circuit = get_qnode(interface, "adjoint", return_type, shots, wire_specs)
- x = get_variable(interface, wire_specs)
- compute_gradient(x, interface, circuit, return_type)
+ circuit = get_qnode(interface, "adjoint", return_type, shots, wire_specs)
+ x = get_variable(interface, wire_specs)
+ with pytest.raises(qml.DeviceError, match=msg):
+ compute_gradient(x, interface, circuit, return_type)
@pytest.mark.parametrize("interface", diff_interfaces)
@pytest.mark.parametrize("return_type", [Expectation, "Hermitian", "Projector"])
@@ -367,11 +376,6 @@ def test_all_adjoint_nonexp(self, interface, return_type, shots, wire_specs):
@pytest.mark.parametrize("wire_specs", wire_specs_list)
def test_all_adjoint_exp(self, interface, return_type, shots, wire_specs):
"""Test diff_method=adjoint works for expectation measurements for all interfaces"""
- warn_msg = (
- "Requested adjoint differentiation to be computed with finite shots. "
- "Adjoint differentiation always calculated exactly."
- )
-
if shots is None:
# test that everything runs
# correctness is already tested in other test files
@@ -379,10 +383,12 @@ def test_all_adjoint_exp(self, interface, return_type, shots, wire_specs):
x = get_variable(interface, wire_specs)
compute_gradient(x, interface, circuit, return_type)
else:
- # test warning is raised when shots > 0
- with pytest.warns(UserWarning, match=warn_msg):
- circuit = get_qnode(interface, "adjoint", return_type, shots, wire_specs)
- x = get_variable(interface, wire_specs)
+ circuit = get_qnode(interface, "adjoint", return_type, shots, wire_specs)
+ x = get_variable(interface, wire_specs)
+ with pytest.raises(
+ qml.DeviceError,
+ match="Circuits with finite shots must be executed with non-analytic gradient methods",
+ ):
compute_gradient(x, interface, circuit, return_type)
@pytest.mark.parametrize("interface", diff_interfaces)
@@ -416,13 +422,16 @@ def test_all_paramshift_state(self, interface, return_type, shots, wire_specs):
)
complex = return_type == "StateVector"
- with pytest.raises(ValueError, match=msg):
- circuit = get_qnode(interface, "parameter-shift", return_type, shots, wire_specs)
- x = get_variable(interface, wire_specs, complex=complex)
- if shots is not None:
- with pytest.warns(UserWarning, match="the returned result is analytic"):
- compute_gradient(x, interface, circuit, return_type, complex=complex)
- else:
+ # with pytest.raises(ValueError, match=msg):
+ circuit = get_qnode(interface, "parameter-shift", return_type, shots, wire_specs)
+ x = get_variable(interface, wire_specs, complex=complex)
+ if shots is not None:
+ with pytest.raises(
+ qml.DeviceError, match="Circuits with finite shots must only contain"
+ ):
+ compute_gradient(x, interface, circuit, return_type, complex=complex)
+ else:
+ with pytest.raises(ValueError, match=msg):
compute_gradient(x, interface, circuit, return_type, complex=complex)
@pytest.mark.parametrize("interface", diff_interfaces)
@@ -441,7 +450,9 @@ def test_all_finitediff_nonstate(self, interface, return_type, shots, wire_specs
circuit = get_qnode(interface, diff_method, return_type, shots, wire_specs)
x = get_variable(interface, wire_specs)
if shots is not None and return_type in (VnEntropy, MutualInfo):
- with pytest.warns(UserWarning, match="unaffected by sampling"):
+ with pytest.raises(
+ qml.DeviceError, match="Circuits with finite shots must only contain"
+ ):
compute_gradient(x, interface, circuit, return_type)
else:
compute_gradient(x, interface, circuit, return_type)
@@ -480,12 +491,8 @@ def test_all_finitediff_state(self, interface, return_type, shots, wire_specs, d
def test_all_sample_none_shots(self, interface, diff_method, wire_specs):
"""Test sample measurement fails for all interfaces and diff_methods
when shots=None"""
- msg = (
- "The number of shots has to be explicitly set on the device "
- "when using sample-based measurements."
- )
- with pytest.raises(QuantumFunctionError, match=msg):
+ with pytest.raises(qml.DeviceError, match="Analytic circuits must only contain"):
circuit = get_qnode(interface, diff_method, Sample, None, wire_specs)
x = get_variable(interface, wire_specs)
circuit(x)
@@ -540,11 +547,13 @@ def test_all_hadamard_nonstate_non_var(
circuit = get_qnode(interface, diff_method, return_type, shots, wire_specs)
x = get_variable(interface, wire_specs)
if return_type in (VnEntropy, MutualInfo):
- msg = (
- "Computing the gradient of circuits that return the state with the "
- "Hadamard test gradient transform is not supported."
- )
- with pytest.raises(ValueError, match=msg):
+ if shots:
+ err_cls = qml.DeviceError
+ msg = "Circuits with finite shots must only contain"
+ else:
+ err_cls = ValueError
+ msg = "Computing the gradient of circuits that return the state with the Hadamard test gradient transform is not supported"
+ with pytest.raises(err_cls, match=msg):
compute_gradient(x, interface, circuit, return_type)
elif return_type == Variance:
with pytest.raises(
diff --git a/tests/gradients/core/test_gradient_transform.py b/tests/gradients/core/test_gradient_transform.py
index 3aded27707f..f592a535129 100644
--- a/tests/gradients/core/test_gradient_transform.py
+++ b/tests/gradients/core/test_gradient_transform.py
@@ -616,7 +616,7 @@ def test_setting_shots(self):
"""Test that setting the number of shots works correctly for
a gradient transform"""
- dev = qml.device("default.qubit", wires=1, shots=1000)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=1000)
@qml.qnode(dev)
def circuit(x):
diff --git a/tests/gradients/core/test_hadamard_gradient.py b/tests/gradients/core/test_hadamard_gradient.py
index 92bfbf67357..3b485b7aaab 100644
--- a/tests/gradients/core/test_hadamard_gradient.py
+++ b/tests/gradients/core/test_hadamard_gradient.py
@@ -25,7 +25,7 @@
def grad_fn(tape, dev, fn=qml.gradients.hadamard_grad, **kwargs):
"""Utility function to automate execution and processing of gradient tapes"""
tapes, fn = fn(tape, **kwargs)
- return fn(dev.batch_execute(tapes)), tapes
+ return fn(dev.execute(tapes)), tapes
def cost1(x):
@@ -548,6 +548,8 @@ def test_shots_attribute(self, shots):
class TestHadamardGradEdgeCases:
"""Test the Hadamard gradient transform and edge cases such as non diff parameters, auxiliary wires, etc..."""
+ # pylint:disable=too-many-public-methods
+
device_wires = [qml.wires.Wires([0, 1, "aux"])]
device_wires_no_aux = [qml.wires.Wires([0, 1, 2])]
@@ -725,7 +727,7 @@ def test_no_trainable_params_qnode_autograd(self, mocker):
"""Test that the correct ouput and warning is generated in the absence of any trainable
parameters"""
dev = qml.device("default.qubit", wires=2)
- spy = mocker.spy(dev, "expval")
+ spy = mocker.spy(qml.devices.qubit, "measure")
@qml.qnode(dev, interface="autograd")
def circuit(weights):
@@ -745,7 +747,7 @@ def test_no_trainable_params_qnode_torch(self, mocker):
"""Test that the correct ouput and warning is generated in the absence of any trainable
parameters"""
dev = qml.device("default.qubit", wires=2)
- spy = mocker.spy(dev, "expval")
+ spy = mocker.spy(qml.devices.qubit, "measure")
@qml.qnode(dev, interface="torch")
def circuit(weights):
@@ -765,7 +767,7 @@ def test_no_trainable_params_qnode_tf(self, mocker):
"""Test that the correct ouput and warning is generated in the absence of any trainable
parameters"""
dev = qml.device("default.qubit", wires=2)
- spy = mocker.spy(dev, "expval")
+ spy = mocker.spy(qml.devices.qubit, "measure")
@qml.qnode(dev, interface="tf")
def circuit(weights):
@@ -785,6 +787,86 @@ def test_no_trainable_params_qnode_jax(self, mocker):
"""Test that the correct ouput and warning is generated in the absence of any trainable
parameters"""
dev = qml.device("default.qubit", wires=2)
+ spy = mocker.spy(qml.devices.qubit, "measure")
+
+ @qml.qnode(dev, interface="jax")
+ def circuit(weights):
+ qml.RX(weights[0], wires=0)
+ qml.RY(weights[1], wires=0)
+ return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
+
+ weights = [0.1, 0.2]
+ with pytest.warns(UserWarning, match="gradient of a QNode with no trainable parameters"):
+ res_hadamard = qml.gradients.hadamard_grad(circuit)(weights)
+
+ assert res_hadamard == ()
+ spy.assert_not_called()
+
+ @pytest.mark.autograd
+ def test_no_trainable_params_qnode_autograd_legacy(self, mocker):
+ """Test that the correct ouput and warning is generated in the absence of any trainable
+ parameters"""
+ dev = qml.device("default.qubit.autograd", wires=2)
+ spy = mocker.spy(dev, "expval")
+
+ @qml.qnode(dev, interface="autograd")
+ def circuit(weights):
+ qml.RX(weights[0], wires=0)
+ qml.RY(weights[1], wires=0)
+ return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
+
+ weights = [0.1, 0.2]
+ with pytest.warns(UserWarning, match="gradient of a QNode with no trainable parameters"):
+ res_hadamard = qml.gradients.hadamard_grad(circuit)(weights)
+
+ assert res_hadamard == ()
+ spy.assert_not_called()
+
+ @pytest.mark.torch
+ def test_no_trainable_params_qnode_torch_legacy(self, mocker):
+ """Test that the correct ouput and warning is generated in the absence of any trainable
+ parameters"""
+ dev = qml.device("default.qubit.torch", wires=2)
+ spy = mocker.spy(dev, "expval")
+
+ @qml.qnode(dev, interface="torch")
+ def circuit(weights):
+ qml.RX(weights[0], wires=0)
+ qml.RY(weights[1], wires=0)
+ return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
+
+ weights = [0.1, 0.2]
+ with pytest.warns(UserWarning, match="gradient of a QNode with no trainable parameters"):
+ res_hadamard = qml.gradients.hadamard_grad(circuit)(weights)
+
+ assert res_hadamard == ()
+ spy.assert_not_called()
+
+ @pytest.mark.tf
+ def test_no_trainable_params_qnode_tf_legacy(self, mocker):
+ """Test that the correct ouput and warning is generated in the absence of any trainable
+ parameters"""
+ dev = qml.device("default.qubit.tf", wires=2)
+ spy = mocker.spy(dev, "expval")
+
+ @qml.qnode(dev, interface="tf")
+ def circuit(weights):
+ qml.RX(weights[0], wires=0)
+ qml.RY(weights[1], wires=0)
+ return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
+
+ weights = [0.1, 0.2]
+ with pytest.warns(UserWarning, match="gradient of a QNode with no trainable parameters"):
+ res_hadamard = qml.gradients.hadamard_grad(circuit)(weights)
+
+ assert res_hadamard == ()
+ spy.assert_not_called()
+
+ @pytest.mark.jax
+ def test_no_trainable_params_qnode_jax_legacy(self, mocker):
+ """Test that the correct ouput and warning is generated in the absence of any trainable
+ parameters"""
+ dev = qml.device("default.qubit.jax", wires=2)
spy = mocker.spy(dev, "expval")
@qml.qnode(dev, interface="jax")
@@ -971,10 +1053,12 @@ class TestHadamardTestGradDiff:
"""Test that the transform is differentiable"""
@pytest.mark.autograd
- def test_autograd(self):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name):
"""Tests that the output of the hadamard gradient transform
can be differentiated using autograd, yielding second derivatives."""
- dev = qml.device("default.qubit.autograd", wires=3)
+ dev = qml.device(dev_name, wires=3)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
def cost_fn_hadamard(x):
@@ -987,7 +1071,7 @@ def cost_fn_hadamard(x):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.hadamard_grad(tape)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return qml.math.stack(jac)
def cost_fn_param_shift(x):
@@ -1000,7 +1084,7 @@ def cost_fn_param_shift(x):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.param_shift(tape)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return qml.math.stack(jac)
res_hadamard = qml.jacobian(cost_fn_hadamard)(params)
@@ -1008,12 +1092,14 @@ def cost_fn_param_shift(x):
assert np.allclose(res_hadamard, res_param_shift)
@pytest.mark.tf
- def test_tf(self):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, dev_name):
"""Tests that the output of the hadamard gradient transform
can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
- dev = qml.device("default.qubit.tf", wires=3)
+ dev = qml.device(dev_name, wires=3)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
with tf.GradientTape() as t_h:
@@ -1026,7 +1112,7 @@ def test_tf(self):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.hadamard_grad(tape)
- jac_h = fn(dev.batch_execute(tapes))
+ jac_h = fn(execute_fn(tapes))
jac_h = qml.math.stack(jac_h)
with tf.GradientTape() as t_p:
@@ -1039,7 +1125,7 @@ def test_tf(self):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.param_shift(tape)
- jac_p = fn(dev.batch_execute(tapes))
+ jac_p = fn(execute_fn(tapes))
jac_p = qml.math.stack(jac_p)
res_hadamard = t_h.jacobian(jac_h, params)
@@ -1048,12 +1134,14 @@ def test_tf(self):
assert np.allclose(res_hadamard, res_param_shift)
@pytest.mark.torch
- def test_torch(self):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, dev_name):
"""Tests that the output of the hadamard gradient transform
can be differentiated using Torch, yielding second derivatives."""
import torch
- dev = qml.device("default.qubit.torch", wires=3)
+ dev = qml.device(dev_name, wires=3)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = torch.tensor([0.543, -0.654], dtype=torch.float64, requires_grad=True)
def cost_h(x):
@@ -1066,7 +1154,7 @@ def cost_h(x):
tape = qml.tape.QuantumScript.from_queue(q)
tapes, fn = qml.gradients.hadamard_grad(tape)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
def cost_p(x):
@@ -1079,7 +1167,7 @@ def cost_p(x):
tape = qml.tape.QuantumScript.from_queue(q)
tapes, fn = qml.gradients.param_shift(tape)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
res_hadamard = torch.autograd.functional.jacobian(cost_h, params)
@@ -1089,7 +1177,8 @@ def cost_p(x):
assert np.allclose(res_hadamard[1].detach(), res_param_shift[1].detach())
@pytest.mark.jax
- def test_jax(self):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, dev_name):
"""Tests that the output of the hadamard gradient transform
can be differentiated using JAX, yielding second derivatives."""
import jax
@@ -1098,7 +1187,8 @@ def test_jax(self):
config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=3)
+ dev = qml.device(dev_name, wires=3)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = jnp.array([0.543, -0.654])
def cost_h(x):
@@ -1112,7 +1202,7 @@ def cost_h(x):
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.hadamard_grad(tape)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
def cost_p(x):
@@ -1126,7 +1216,7 @@ def cost_p(x):
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.hadamard_grad(tape)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
res_hadamard = jax.jacobian(cost_h)(params)
diff --git a/tests/gradients/core/test_hamiltonian_gradient.py b/tests/gradients/core/test_hamiltonian_gradient.py
index 488b8e7dd8a..1bcb4bfc4fe 100644
--- a/tests/gradients/core/test_hamiltonian_gradient.py
+++ b/tests/gradients/core/test_hamiltonian_gradient.py
@@ -30,10 +30,10 @@ def test_behaviour():
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {2, 3}
tapes, processing_fn = hamiltonian_grad(tape, idx=0)
- res1 = processing_fn(dev.batch_execute(tapes))
+ res1 = processing_fn(dev.execute(tapes))
tapes, processing_fn = hamiltonian_grad(tape, idx=1)
- res2 = processing_fn(dev.batch_execute(tapes))
+ res2 = processing_fn(dev.execute(tapes))
with qml.queuing.AnnotatedQueue() as q1:
qml.RY(0.3, wires=0)
@@ -49,9 +49,7 @@ def test_behaviour():
qml.expval(qml.PauliZ(1))
tape2 = qml.tape.QuantumScript.from_queue(q2)
- dev.reset()
res_expected1 = qml.math.squeeze(dev.execute(tape1))
- dev.reset()
res_expected2 = qml.math.squeeze(dev.execute(tape2))
assert res_expected1 == res1
diff --git a/tests/gradients/core/test_jvp.py b/tests/gradients/core/test_jvp.py
index beb2cc9bf8e..ac973027534 100644
--- a/tests/gradients/core/test_jvp.py
+++ b/tests/gradients/core/test_jvp.py
@@ -484,7 +484,7 @@ def test_single_expectation_value(self, tol, batch_dim):
tapes, fn = qml.gradients.jvp(tape, tangent, param_shift)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert res.shape == () if batch_dim is None else (batch_dim,)
exp = np.sum(np.array([-np.sin(y) * np.sin(x), np.cos(y) * np.cos(x)]), axis=0)
@@ -514,7 +514,7 @@ def test_multiple_expectation_values(self, tol, batch_dim):
tapes, fn = qml.gradients.jvp(tape, tangent, param_shift)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
assert all(r.shape == () if batch_dim is None else (batch_dim,) for r in res)
@@ -546,7 +546,7 @@ def test_prob_expval_single_param(self, tol, batch_dim):
tapes, fn = qml.gradients.jvp(tape, tangent, param_shift)
assert len(tapes) == 2
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
assert res[0].shape == () if batch_dim is None else (batch_dim,)
@@ -583,7 +583,7 @@ def test_prob_expval_multi_param(self, tol, batch_dim):
tapes, fn = qml.gradients.jvp(tape, tangent, param_shift)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -655,10 +655,12 @@ class TestJVPGradients:
# Include batch_dim!=None cases once #4462 is resolved
@pytest.mark.autograd
@pytest.mark.parametrize("batch_dim", [None]) # , 1, 3])
- def test_autograd(self, tol, batch_dim):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, tol, dev_name, batch_dim):
"""Tests that the output of the JVP transform
can be differentiated using autograd."""
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
if batch_dim is not None:
params = np.outer(np.arange(1, 1 + batch_dim), params, requires_grad=True)
@@ -671,7 +673,7 @@ def cost_fn(params, tangent):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.jvp(tape, tangent, param_shift)
- jvp = fn(dev.batch_execute(tapes))
+ jvp = fn(execute_fn(tapes))
return jvp
res = cost_fn(params, tangent)
@@ -685,12 +687,14 @@ def cost_fn(params, tangent):
# Include batch_dim!=None cases once #4462 is resolved
@pytest.mark.torch
@pytest.mark.parametrize("batch_dim", [None]) # , 1, 3])
- def test_torch(self, tol, batch_dim):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, tol, dev_name, batch_dim):
"""Tests that the output of the JVP transform
can be differentiated using Torch."""
import torch
- dev = qml.device("default.qubit.torch", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params_np = np.array([0.543, -0.654], requires_grad=True)
if batch_dim is not None:
@@ -706,7 +710,7 @@ def cost_fn(params, tangent):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.jvp(tape, tangent, param_shift)
- jvp = fn(dev.batch_execute(tapes))
+ jvp = fn(execute_fn(tapes))
return jvp
res = cost_fn(params, tangent)
@@ -721,12 +725,14 @@ def cost_fn(params, tangent):
@pytest.mark.tf
@pytest.mark.slow
@pytest.mark.parametrize("batch_dim", [None]) # , 1, 3])
- def test_tf(self, tol, batch_dim):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, tol, dev_name, batch_dim):
"""Tests that the output of the JVP transform
can be differentiated using Tensorflow."""
import tensorflow as tf
- dev = qml.device("default.qubit.tf", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params_np = np.array([0.543, -0.654], requires_grad=True)
if batch_dim is not None:
params_np = np.outer(np.arange(1, 1 + batch_dim), params_np, requires_grad=True)
@@ -741,7 +747,7 @@ def cost_fn(params, tangent):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.jvp(tape, tangent, param_shift)
- jvp = fn(dev.batch_execute(tapes))
+ jvp = fn(execute_fn(tapes))
return jvp
with tf.GradientTape() as t:
@@ -757,13 +763,15 @@ def cost_fn(params, tangent):
# Include batch_dim!=None cases once #4462 is resolved
@pytest.mark.jax
@pytest.mark.parametrize("batch_dim", [None]) # , 1, 3])
- def test_jax(self, tol, batch_dim):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, tol, dev_name, batch_dim):
"""Tests that the output of the JVP transform
can be differentiated using JAX."""
import jax
from jax import numpy as jnp
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params_np = np.array([0.543, -0.654], requires_grad=True)
if batch_dim is not None:
params_np = np.outer(np.arange(1, 1 + batch_dim), params_np, requires_grad=True)
@@ -778,7 +786,7 @@ def cost_fn(params, tangent):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.jvp(tape, tangent, param_shift)
- jvp = fn(dev.batch_execute(tapes))
+ jvp = fn(execute_fn(tapes))
return jvp
res = cost_fn(params, tangent)
@@ -821,7 +829,7 @@ def test_one_tape_no_trainable_parameters(self):
# Even though there are 3 parameters, only two contribute
# to the JVP, so only 2*2=4 quantum evals
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
assert res[0] is None
assert res[1] is not None
@@ -877,7 +885,7 @@ def test_zero_tangent(self):
tangents = [np.array([0.0]), np.array([1.0, 1.0])]
v_tapes, fn = qml.gradients.batch_jvp(tapes, tangents, param_shift)
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
# Even though there are 3 parameters, only two contribute
# to the JVP, so only 2*2=4 quantum evals
@@ -909,7 +917,7 @@ def test_reduction_append(self):
tangents = [np.array([1.0]), np.array([1.0, 1.0])]
v_tapes, fn = qml.gradients.batch_jvp(tapes, tangents, param_shift, reduction="append")
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
# Returned JVPs will be appended to a list, one JVP per tape
@@ -942,7 +950,7 @@ def test_reduction_extend(self):
tangents = [np.array([1.0]), np.array([1.0])]
v_tapes, fn = qml.gradients.batch_jvp(tapes, tangents, param_shift, reduction="extend")
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
assert len(res) == 4
def test_reduction_extend_special(self):
@@ -977,7 +985,7 @@ def test_reduction_extend_special(self):
if not isinstance(x, tuple) and x.shape == ()
else jvps.extend(x),
)
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
assert len(res) == 3
@@ -1008,6 +1016,6 @@ def test_reduction_callable(self):
v_tapes, fn = qml.gradients.batch_jvp(
tapes, tangents, param_shift, reduction=lambda jvps, x: jvps.append(x)
)
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
# Returned JVPs will be appended to a list, one JVP per tape
assert len(res) == 2
diff --git a/tests/gradients/core/test_pulse_generator_gradient.py b/tests/gradients/core/test_pulse_generator_gradient.py
index 1f6b5b255f1..3396fe02210 100644
--- a/tests/gradients/core/test_pulse_generator_gradient.py
+++ b/tests/gradients/core/test_pulse_generator_gradient.py
@@ -40,7 +40,7 @@
def grad_fn(tape, dev, fn=pulse_generator, **kwargs):
"""Utility function to automate execution and processing of gradient tapes"""
_tapes, fn = fn(tape, **kwargs)
- return fn(dev.batch_execute(_tapes)), _tapes
+ return fn(dev.execute(_tapes)), _tapes
def integral_of_polyval(params, t):
@@ -474,7 +474,7 @@ def test_output_properties(self, ops_and_meas, op_idx, ops):
"""Test that the input tape and inserted ops are taken into account correctly."""
evolve_op = qml.evolve(qml.pulse.constant * Z("a"))([np.array(0.2)], 0.2)
operations, measurements = ops_and_meas
- operations = [evolve_op if op == "evolve_op" else op for op in operations]
+ operations = [evolve_op if isinstance(op, str) else op for op in operations]
tape = qml.tape.QuantumScript(operations, measurements)
new_tapes = _insert_op(tape, ops, op_idx)
assert isinstance(new_tapes, list) and len(new_tapes) == len(ops)
@@ -870,7 +870,7 @@ def test_no_trainable_params_multiple_return_tape(self):
with pytest.warns(UserWarning, match="gradient of a tape with no trainable parameters"):
_tapes, fn = pulse_generator(tape)
- res = fn(dev.batch_execute(_tapes))
+ res = fn(dev.execute(_tapes))
assert _tapes == []
assert isinstance(res, tuple)
@@ -965,19 +965,21 @@ def test_all_zero_diff_methods_multiple_returns_tape(self):
assert np.allclose(res_pulse_gen[1][2], 0)
+# TODO: add default.qubit once it supports PRNG key
@pytest.mark.jax
+@pytest.mark.parametrize("dev_name", ["default.qubit.jax"])
class TestPulseGeneratorTape:
"""Test that differentiating tapes with ``pulse_generator`` 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, dev_name, shots, tol):
"""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)
- dev = qml.device("default.qubit.jax", wires=1, shots=shots, prng_key=prng_key)
+ dev = qml.device(dev_name, wires=1, shots=shots, prng_key=prng_key)
H = jnp.polyval * X(0)
x = jnp.array([0.4, 0.2, 0.1])
@@ -1005,15 +1007,15 @@ 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, dev_name, shots, tol):
"""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)
- dev = qml.device("default.qubit.jax", wires=1, shots=None)
- dev_shots = qml.device("default.qubit.jax", wires=1, shots=shots, prng_key=prng_key)
+ dev = qml.device(dev_name, wires=1, shots=None)
+ dev_shots = qml.device(dev_name, wires=1, shots=shots, prng_key=prng_key)
H = 0.1 * Z(0) + jnp.polyval * X(0) + qml.pulse.constant * Y(0)
x = jnp.array([0.4, 0.2, 0.1])
@@ -1045,13 +1047,13 @@ def circuit(par):
assert all(qml.math.allclose(g, e, atol=tol) for g, e in zip(grad, exp_grad))
@pytest.mark.parametrize("argnum", (0, [0], 1, [1]))
- def test_single_pulse_multi_term_argnum(self, argnum):
+ def test_single_pulse_multi_term_argnum(self, dev_name, argnum):
"""Test that a single pulse with multiple Hamiltonian terms is
differentiated correctly when setting ``argnum``."""
import jax
import jax.numpy as jnp
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
H = jnp.polyval * X(0) + qml.pulse.constant * X(0)
x = jnp.array([0.4, 0.2, 0.1])
@@ -1085,15 +1087,15 @@ 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, dev_name, shots, tol):
"""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)
- dev = qml.device("default.qubit.jax", wires=1, shots=None)
- dev_shots = qml.device("default.qubit.jax", wires=1, shots=shots, prng_key=prng_key)
+ dev = qml.device(dev_name, wires=1, shots=None)
+ dev_shots = qml.device(dev_name, wires=1, shots=shots, prng_key=prng_key)
H0 = 0.1 * Z(0) + jnp.polyval * X(0)
H1 = 0.2 * Y(0) + qml.pulse.constant * Y(0) + jnp.polyval * Z(0)
@@ -1129,14 +1131,15 @@ def circuit(par):
@pytest.mark.jax
+@pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
class TestPulseGeneratorQNode:
"""Test that pulse_generator integrates correctly with QNodes."""
- def test_raises_for_application_to_qnodes(self):
+ def test_raises_for_application_to_qnodes(self, dev_name):
"""Test that an error is raised when applying ``stoch_pulse_grad``
to a QNode directly."""
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@qml.qnode(dev, interface="jax")
@@ -1150,14 +1153,14 @@ def circuit(params):
# TODO: include the following tests when #4225 is resolved.
@pytest.mark.skip("Applying this gradient transform to QNodes directly is not supported.")
- def test_qnode_expval_single_par(self):
+ def test_qnode_expval_single_par(self, dev_name):
"""Test that a simple qnode that returns an expectation value
can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.2
ham_single_q_const = qml.pulse.constant * Y(0)
@@ -1176,14 +1179,14 @@ def circuit(params):
assert tracker.totals["executions"] == 2 # two shifted tapes
@pytest.mark.skip("Applying this gradient transform to QNodes directly is not supported.")
- def test_qnode_expval_probs_single_par(self):
+ def test_qnode_expval_probs_single_par(self, dev_name):
"""Test that a simple qnode that returns an expectation value
can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.2
ham_single_q_const = jnp.polyval * Y(0)
@@ -1208,14 +1211,14 @@ def circuit(params):
assert qml.math.allclose(j, e)
@pytest.mark.skip("Applying this gradient transform to QNodes directly is not supported.")
- def test_qnode_probs_expval_multi_par(self):
+ def test_qnode_probs_expval_multi_par(self, dev_name):
"""Test that a simple qnode that returns probabilities
can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1, shots=None)
+ dev = qml.device(dev_name, wires=1, shots=None)
T = 0.2
ham_single_q_const = jnp.polyval * Y(0) + qml.pulse.constant * Y(0)
@@ -1248,17 +1251,18 @@ def circuit(params, c):
@pytest.mark.jax
+@pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
class TestPulseGeneratorIntegration:
"""Test that pulse_generator integrates correctly with QNodes."""
- def test_simple_qnode_expval(self):
+ def test_simple_qnode_expval(self, dev_name):
"""Test that a simple qnode that returns an expectation value
can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.2
ham_single_q_const = qml.pulse.constant * Y(0)
@@ -1275,14 +1279,14 @@ def circuit(params):
assert qml.math.allclose(grad, exp_grad)
assert tracker.totals["executions"] == 1 + 2 # one forward pass, two shifted tapes
- def test_simple_qnode_expval_two_evolves(self):
+ def test_simple_qnode_expval_two_evolves(self, dev_name):
"""Test that a simple qnode that returns an expectation value
can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T_x = 0.1
T_y = 0.2
ham_x = qml.pulse.constant * X(0)
@@ -1301,14 +1305,14 @@ def circuit(params):
exp_grad = [[-2 * jnp.sin(2 * (p_x + p_y)) * T_x], [-2 * jnp.sin(2 * (p_x + p_y)) * T_y]]
assert qml.math.allclose(grad, exp_grad)
- def test_simple_qnode_probs(self):
+ def test_simple_qnode_probs(self, dev_name):
"""Test that a simple qnode that returns probabilities
can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.2
ham_single_q_const = qml.pulse.constant * Y(0)
@@ -1323,14 +1327,14 @@ def circuit(params):
exp_jac = jnp.array([-1, 1]) * jnp.sin(2 * p) * T
assert qml.math.allclose(jac, exp_jac)
- def test_simple_qnode_probs_expval(self):
+ def test_simple_qnode_probs_expval(self, dev_name):
"""Test that a simple qnode that returns probabilities
can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.2
ham_single_q_const = jnp.polyval * Y(0)
@@ -1352,13 +1356,13 @@ def circuit(params):
@pytest.mark.xfail
@pytest.mark.parametrize("time_interface", ["python", "numpy", "jax"])
- def test_simple_qnode_jit(self, time_interface):
+ def test_simple_qnode_jit(self, dev_name, time_interface):
"""Test that a simple qnode can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = {"python": 0.2, "numpy": np.array(0.2), "jax": jnp.array(0.2)}[time_interface]
ham_single_q_const = qml.pulse.constant * Y(0)
@@ -1374,7 +1378,7 @@ def circuit(params, T=None):
assert qml.math.isclose(jit_grad, exp_grad)
@pytest.mark.slow
- def test_advanced_qnode(self):
+ def test_advanced_qnode(self, dev_name):
"""Test that an advanced qnode can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
@@ -1382,7 +1386,7 @@ def test_advanced_qnode(self):
jax.config.update("jax_enable_x64", True)
params = [jnp.array(0.21), jnp.array(-0.171), jnp.array([0.05, 0.03, -0.1])]
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
ham = (
qml.pulse.constant * X(0)
+ (lambda p, t: jnp.sin(p * t)) * Z(0)
@@ -1401,8 +1405,9 @@ def ansatz(params):
)
qnode_backprop = qml.QNode(ansatz, dev, interface="jax")
- grad_pulse_grad = jax.grad(qnode_pulse_grad)(params)
- assert dev.num_executions == 1 + 12 # one forward execution, dim(DLA)=6
+ with qml.Tracker(dev) as tracker:
+ grad_pulse_grad = jax.grad(qnode_pulse_grad)(params)
+ assert tracker.totals["executions"] == 1 + 12 # one forward execution, dim(DLA)=6
grad_backprop = jax.grad(qnode_backprop)(params)
assert all(
@@ -1410,14 +1415,14 @@ def ansatz(params):
)
@pytest.mark.parametrize("argnums", [[0, 1], 0, 1])
- def test_simple_qnode_expval_multiple_params(self, argnums):
+ def test_simple_qnode_expval_multiple_params(self, dev_name, argnums):
"""Test that a simple qnode with two parameters
can be differentiated with pulse_generator and `argnums` works as expected."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.2
ham1 = qml.pulse.constant * Y(0)
ham2 = qml.pulse.constant * Y(0)
@@ -1442,7 +1447,9 @@ def circuit(param1, param2):
assert tracker.totals["executions"] == 1 + 2 # one forward pass, two shifted tapes
+# TODO: port ParametrizedEvolution to new default.qubit
@pytest.mark.jax
+@pytest.mark.parametrize("dev_name", ["default.qubit.jax"])
class TestPulseGeneratorDiff:
"""Test that pulse_generator is differentiable, i.e. that computing
the derivative with pulse_generator is differentiable a second time,
@@ -1450,14 +1457,14 @@ class TestPulseGeneratorDiff:
# pylint: disable=too-few-public-methods
@pytest.mark.slow
- def test_jax(self):
+ def test_jax(self, dev_name):
"""Test that pulse_generator is differentiable,
allowing to compute the Hessian, with JAX.."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.5
ham_single_q_const = qml.pulse.constant * Y(0)
diff --git a/tests/gradients/core/test_pulse_gradient.py b/tests/gradients/core/test_pulse_gradient.py
index ac6abd9d2cb..38ea9f3af65 100644
--- a/tests/gradients/core/test_pulse_gradient.py
+++ b/tests/gradients/core/test_pulse_gradient.py
@@ -823,6 +823,7 @@ def test_raises_for_invalid_reorder_fn(self, reorder_fn):
@pytest.mark.jax
+@pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
class TestStochPulseGrad:
"""Test working cases of stoch_pulse_grad."""
@@ -856,7 +857,7 @@ def sine(p, t):
),
),
)
- def test_all_zero_grads(self, ops, arg, exp_shapes):
+ def test_all_zero_grads(self, dev_name, ops, arg, exp_shapes): # pylint:disable=unused-argument
"""Test that a zero gradient is returned when all trainable parameters are
identified to have zero gradient in advance."""
import jax
@@ -878,7 +879,7 @@ def test_all_zero_grads(self, ops, arg, exp_shapes):
assert qml.math.allclose(r, np.zeros(exp_shape))
jax.clear_caches()
- def test_some_zero_grads(self):
+ def test_some_zero_grads(self, dev_name):
"""Test that a zero gradient is returned for trainable parameters that are
identified to have a zero gradient in advance."""
import jax
@@ -894,7 +895,7 @@ def test_some_zero_grads(self):
tapes, fn = stoch_pulse_grad(tape, num_split_times=3)
assert len(tapes) == 2 * 3
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
res = fn(qml.execute(tapes, dev, None))
assert isinstance(res, tuple) and len(res) == 2
assert qml.math.allclose(res[0][0], np.zeros(5))
@@ -903,7 +904,7 @@ def test_some_zero_grads(self):
@pytest.mark.parametrize("num_split_times", [1, 3])
@pytest.mark.parametrize("t", [2.0, 3, (0.5, 0.6), (0.1, 0.9, 1.2)])
- def test_constant_ry(self, num_split_times, t):
+ def test_constant_ry(self, dev_name, num_split_times, t):
"""Test that the derivative of a pulse generated by a constant Hamiltonian,
which is a Pauli word, is computed correctly."""
import jax
@@ -916,7 +917,7 @@ def test_constant_ry(self, num_split_times, t):
op = qml.evolve(ham_single_q_const)(params, t)
tape = qml.tape.QuantumScript([op], [qml.expval(qml.PauliZ(0))])
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
# Effective rotation parameter
p = params[0] * (delta_t := (T[-1] - T[0]))
r = qml.execute([tape], dev, None)
@@ -930,7 +931,7 @@ def test_constant_ry(self, num_split_times, t):
@pytest.mark.parametrize("num_split_times", [1, 3])
@pytest.mark.parametrize("t", [2.0, 3, (0.5, 0.6), (0.1, 0.9, 1.2)])
- def test_constant_ry_rescaled(self, num_split_times, t):
+ def test_constant_ry_rescaled(self, dev_name, num_split_times, t):
"""Test that the derivative of a pulse generated by a constant Hamiltonian,
which is a Pauli sentence, is computed correctly."""
import jax
@@ -945,7 +946,7 @@ def test_constant_ry_rescaled(self, num_split_times, t):
op = qml.evolve(ham_single_q_const)(params, t)
tape = qml.tape.QuantumScript([op], [qml.expval(qml.PauliZ(0))])
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
# Prefactor due to the generator being a Pauli sentence
prefactor = np.sqrt(0.85)
# Effective rotation parameter
@@ -960,7 +961,7 @@ def test_constant_ry_rescaled(self, num_split_times, t):
jax.clear_caches()
@pytest.mark.parametrize("t", [0.02, (0.5, 0.6)])
- def test_sin_envelope_rz_expval(self, t):
+ def test_sin_envelope_rz_expval(self, dev_name, t):
"""Test that the derivative of a pulse with a sine wave envelope
is computed correctly when returning an expectation value."""
import jax
@@ -968,7 +969,7 @@ def test_sin_envelope_rz_expval(self, t):
T = t if isinstance(t, tuple) else (0, t)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
params = [jnp.array([2.3, -0.245])]
ham = self.sine * qml.PauliZ(0)
@@ -999,7 +1000,7 @@ def test_sin_envelope_rz_expval(self, t):
jax.clear_caches()
@pytest.mark.parametrize("t", [0.02, (0.5, 0.6)])
- def test_sin_envelope_rx_probs(self, t):
+ def test_sin_envelope_rx_probs(self, dev_name, t):
"""Test that the derivative of a pulse with a sine wave envelope
is computed correctly when returning probabilities."""
import jax
@@ -1007,7 +1008,7 @@ def test_sin_envelope_rx_probs(self, t):
T = t if isinstance(t, tuple) else (0, t)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
params = [jnp.array([2.3, -0.245])]
ham = self.sine * qml.PauliX(0)
@@ -1040,7 +1041,7 @@ def test_sin_envelope_rx_probs(self, t):
jax.clear_caches()
@pytest.mark.parametrize("t", [0.02, (0.5, 0.6)])
- def test_sin_envelope_rx_expval_probs(self, t):
+ def test_sin_envelope_rx_expval_probs(self, dev_name, t):
"""Test that the derivative of a pulse with a sine wave envelope
is computed correctly when returning expectation."""
import jax
@@ -1048,7 +1049,7 @@ def test_sin_envelope_rx_expval_probs(self, t):
T = t if isinstance(t, tuple) else (0, t)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
params = [jnp.array([2.3, -0.245])]
ham = self.sine * qml.PauliX(0)
@@ -1085,7 +1086,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, dev_name, t):
"""Test that the derivative of a pulse generated by a piecewise constant Hamiltonian
is computed correctly."""
import jax
@@ -1093,7 +1094,7 @@ def test_pwc_envelope_rx(self, t):
T = t if isinstance(t, tuple) else (0, t)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
params = [jnp.array([0.24, 0.9, -0.1, 2.3, -0.245])]
op = qml.evolve(qml.pulse.pwc(t) * qml.PauliZ(0))(params, t)
tape = qml.tape.QuantumScript([qml.Hadamard(0), op], [qml.expval(qml.PauliX(0))])
@@ -1115,7 +1116,7 @@ def test_pwc_envelope_rx(self, t):
jax.clear_caches()
@pytest.mark.parametrize("t", [2.0, 3, (0.5, 0.6)])
- def test_constant_commuting(self, t):
+ def test_constant_commuting(self, dev_name, t):
"""Test that the derivative of a pulse generated by two constant commuting Hamiltonians
is computed correctly."""
import jax
@@ -1129,7 +1130,7 @@ def test_constant_commuting(self, t):
)
tape = qml.tape.QuantumScript([op], [qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))])
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
r = qml.execute([tape], dev, None)
# Effective rotation parameters
p = [_p * (T[1] - T[0]) for _p in params]
@@ -1145,7 +1146,7 @@ def test_constant_commuting(self, t):
assert qml.math.allclose(res, exp_grad)
jax.clear_caches()
- def test_advanced_pulse(self):
+ def test_advanced_pulse(self, dev_name):
"""Test the derivative of a more complex pulse."""
import jax
import jax.numpy as jnp
@@ -1159,7 +1160,7 @@ def test_advanced_pulse(self):
* qml.dot([1.0, 0.4], [qml.PauliY(0) @ qml.PauliY(1), qml.PauliX(0) @ qml.PauliX(1)])
)
params = [jnp.array(1.51), jnp.array(-0.371), jnp.array([0.2, 0.2, -0.4])]
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
@qml.qnode(dev, interface="jax")
def qnode(params):
@@ -1183,7 +1184,7 @@ def qnode(params):
assert all(qml.math.allclose(r, e, rtol=0.4) for r, e in zip(res, exp_grad))
jax.clear_caches()
- def test_randomness(self):
+ def test_randomness(self, dev_name):
"""Test that the derivative of a pulse is exactly the same when reusing a seed and
that it differs when using a different seed."""
import jax
@@ -1213,7 +1214,7 @@ def test_randomness(self):
else:
assert qml.equal(op_a_0, op_a_1) and qml.equal(op_a_0, op_b)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
res_a_0 = fn_a_0(qml.execute(tapes_a_0, dev, None))
res_a_1 = fn_a_1(qml.execute(tapes_a_1, dev, None))
res_b = fn_b(qml.execute(tapes_b, dev, None))
@@ -1222,7 +1223,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, dev_name):
"""Test that the derivatives of two pulses in a circuit are computed correctly."""
import jax
import jax.numpy as jnp
@@ -1233,7 +1234,7 @@ def test_two_pulses(self):
ham_1 = qml.dot([0.3, jnp.polyval], [qml.PauliZ(0), qml.PauliY(0) @ qml.PauliY(1)])
params_0 = [jnp.array(1.51), jnp.array(-0.371)]
params_1 = [jnp.array([0.2, 0.2, -0.4])]
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
@qml.qnode(dev, interface="jax")
def qnode(params_0, params_1):
@@ -1262,13 +1263,13 @@ def qnode(params_0, params_1):
(qml.Hamiltonian([0.25, 1.2], [qml.PauliX(0), qml.PauliX(0) @ qml.PauliZ(1)]), 8, 1.45),
],
)
- def test_with_jit(self, generator, exp_num_tapes, prefactor):
+ def test_with_jit(self, dev_name, generator, exp_num_tapes, prefactor):
"""Test that the stochastic parameter-shift rule works with JITting."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=len(generator.wires))
+ dev = qml.device(dev_name, wires=len(generator.wires))
T = (0.2, 0.5)
ham_single_q_const = qml.dot([qml.pulse.constant], [generator])
meas = [qml.expval(qml.PauliZ(0))]
@@ -1280,7 +1281,7 @@ def fun(params):
tape = qml.tape.QuantumScript([op], meas)
tapes, fn = stoch_pulse_grad(tape)
assert len(tapes) == exp_num_tapes
- res = fn(qml.execute(tapes, dev, None))
+ res = fn(qml.execute(tapes, dev, "backprop"))
return res
params = [jnp.array(0.24)]
@@ -1293,7 +1294,7 @@ def fun(params):
jax.clear_caches()
@pytest.mark.parametrize("shots", [None, 100])
- def test_shots_attribute(self, shots):
+ def test_shots_attribute(self, dev_name, shots): # pylint:disable=unused-argument
"""Tests that the shots attribute is copied to the new tapes"""
tape = qml.tape.QuantumTape([], [qml.expval(qml.PauliZ(0)), qml.probs([1, 2])], shots=shots)
with pytest.warns(UserWarning, match="Attempted to compute the gradient of a tape with no"):
@@ -1303,13 +1304,14 @@ def test_shots_attribute(self, shots):
@pytest.mark.jax
+@pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
class TestStochPulseGradQNode:
"""Test that pulse_generator integrates correctly with QNodes."""
- def test_raises_for_application_to_qnodes(self):
+ def test_raises_for_application_to_qnodes(self, dev_name):
"""Test that an error is raised when applying ``stoch_pulse_grad``
to a QNode directly."""
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@qml.qnode(dev, interface="jax")
@@ -1323,14 +1325,14 @@ def circuit(params):
# TODO: include the following tests when #4225 is resolved.
@pytest.mark.skip("Applying this gradient transform to QNodes directly is not supported.")
- def test_qnode_expval_single_par(self):
+ def test_qnode_expval_single_par(self, dev_name):
"""Test that a simple qnode that returns an expectation value
can be differentiated with pulse_generator."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1350,20 +1352,22 @@ def circuit(params):
assert tracker.totals["executions"] == 4 # two shifted tapes, two splitting times
+# TODO: add default.qubit once it supports PRNG key
@pytest.mark.jax
+@pytest.mark.parametrize("dev_name", ["default.qubit.jax"])
class TestStochPulseGradIntegration:
"""Test that stoch_pulse_grad integrates correctly with QNodes and ML interfaces."""
@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, dev_name, num_split_times, shots, tol):
"""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.jax", wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
+ dev = qml.device(dev_name, wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1383,14 +1387,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_expval_two_evolves(self, num_split_times, shots, tol):
+ def test_simple_qnode_expval_two_evolves(self, dev_name, num_split_times, shots, tol):
"""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.jax", wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
+ dev = qml.device(dev_name, wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
T_x = 0.1
T_y = 0.2
ham_x = qml.pulse.constant * qml.PauliX(0)
@@ -1414,14 +1418,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, dev_name, num_split_times, shots, tol):
"""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.jax", wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
+ dev = qml.device(dev_name, wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1441,14 +1445,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, dev_name, num_split_times, shots, tol):
"""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.jax", wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
+ dev = qml.device(dev_name, wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1475,13 +1479,13 @@ def circuit(params):
@pytest.mark.xfail
@pytest.mark.parametrize("num_split_times", [1, 2])
@pytest.mark.parametrize("time_interface", ["python", "numpy", "jax"])
- def test_simple_qnode_jit(self, num_split_times, time_interface):
+ def test_simple_qnode_jit(self, dev_name, num_split_times, time_interface):
"""Test that a simple qnode 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.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = {"python": 0.2, "numpy": np.array(0.2), "jax": jnp.array(0.2)}[time_interface]
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1500,7 +1504,7 @@ def circuit(params, T=None):
jax.clear_caches()
@pytest.mark.slow
- def test_advanced_qnode(self):
+ def test_advanced_qnode(self, dev_name):
"""Test that an advanced qnode can be differentiated with stoch_pulse_grad."""
import jax
import jax.numpy as jnp
@@ -1508,7 +1512,7 @@ def test_advanced_qnode(self):
jax.config.update("jax_enable_x64", True)
params = [jnp.array(0.21), jnp.array(-0.171), jnp.array([0.05, 0.03, -0.1])]
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
ham = (
qml.pulse.constant * qml.PauliX(0)
+ (lambda p, t: jnp.sin(p * t)) * qml.PauliZ(0)
@@ -1540,7 +1544,7 @@ def ansatz(params):
)
jax.clear_caches()
- def test_multi_return_broadcasting_multi_shots_raises(self):
+ def test_multi_return_broadcasting_multi_shots_raises(self, dev_name):
"""Test that a simple qnode that returns an expectation value and probabilities
can be differentiated with stoch_pulse_grad with use_broadcasting."""
import jax
@@ -1548,7 +1552,7 @@ def test_multi_return_broadcasting_multi_shots_raises(self):
jax.config.update("jax_enable_x64", True)
shots = [100, 100]
- dev = qml.device("default.qubit.jax", wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
+ dev = qml.device(dev_name, wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1571,14 +1575,14 @@ def circuit(params):
# 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("num_split_times", [1, 2])
- def test_qnode_probs_expval_broadcasting(self, num_split_times, shots, tol):
+ def test_qnode_probs_expval_broadcasting(self, dev_name, num_split_times, shots, tol):
"""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.jax", wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
+ dev = qml.device(dev_name, wires=1, shots=shots, prng_key=jax.random.PRNGKey(74))
T = 0.2
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
@@ -1607,13 +1611,13 @@ 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, dev_name, num_split_times):
"""Test that using broadcasting or not does not change the result."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
T = 0.2
def f(p, t):
@@ -1651,7 +1655,7 @@ def ansatz(params):
assert qml.math.allclose(j0, j1)
jax.clear_caches()
- def test_with_drive_exact(self):
+ def test_with_drive_exact(self, dev_name):
"""Test that a HardwareHamiltonian only containing a drive is differentiated correctly
for a constant amplitude and zero frequency and phase."""
import jax
@@ -1660,7 +1664,7 @@ def test_with_drive_exact(self):
H = qml.pulse.transmon_drive(qml.pulse.constant, 0.0, 0.0, wires=[0])
atol = 1e-5
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
def ansatz(params):
qml.evolve(H, atol=atol)(params, t=timespan)
@@ -1676,7 +1680,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, dev_name):
"""Test that a HardwareHamiltonian only containing a drive is differentiated
approximately correctly for a constant phase and zero frequency."""
import jax
@@ -1685,7 +1689,7 @@ def test_with_drive_approx(self):
H = qml.pulse.transmon_drive(1 / (2 * np.pi), qml.pulse.constant, 0.0, wires=[0])
atol = 1e-5
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
def ansatz(params):
qml.evolve(H, atol=atol)(params, t=timespan)
@@ -1710,7 +1714,7 @@ def ansatz(params):
jax.clear_caches()
@pytest.mark.parametrize("num_params", [1, 2])
- def test_with_two_drives(self, num_params):
+ def test_with_two_drives(self, dev_name, num_params):
"""Test that a HardwareHamiltonian only containing two drives
is differentiated approximately correctly. The two cases
of the parametrization test the cases where reordered parameters
@@ -1729,7 +1733,7 @@ def test_with_two_drives(self, num_params):
amps[0], qml.pulse.constant, 0.0, wires=[0]
) + qml.pulse.rydberg_drive(amps[1], qml.pulse.constant, 0.0, wires=[1])
atol = 1e-5
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
def ansatz(params):
qml.evolve(H, atol=atol)(params, t=timespan)
@@ -1753,19 +1757,21 @@ def ansatz(params):
jax.clear_caches()
+# TODO: port ParametrizedEvolution to new default.qubit
@pytest.mark.jax
+@pytest.mark.parametrize("dev_name", ["default.qubit.jax"])
class TestStochPulseGradDiff:
"""Test that stoch_pulse_grad is differentiable."""
# pylint: disable=too-few-public-methods
@pytest.mark.slow
- def test_jax(self):
+ def test_jax(self, dev_name):
"""Test that stoch_pulse_grad is differentiable with JAX."""
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=1)
+ dev = qml.device(dev_name, wires=1)
T = 0.5
ham_single_q_const = qml.pulse.constant * qml.PauliY(0)
diff --git a/tests/gradients/core/test_vjp.py b/tests/gradients/core/test_vjp.py
index 2e3824e99a3..0904d1a19c2 100644
--- a/tests/gradients/core/test_vjp.py
+++ b/tests/gradients/core/test_vjp.py
@@ -247,7 +247,7 @@ def test_single_expectation_value(self, tol):
tapes, fn = qml.gradients.vjp(tape, dy, param_shift)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert res.shape == (2,)
exp = np.array([-np.sin(y) * np.sin(x), np.cos(y) * np.cos(x)])
@@ -274,7 +274,7 @@ def test_multiple_expectation_values(self, tol):
tapes, fn = qml.gradients.vjp(tape, dy, param_shift)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert res.shape == (2,)
exp = np.array([-np.sin(x), 2 * np.cos(y)])
@@ -301,7 +301,7 @@ def test_prob_expectation_values(self, tol):
tapes, fn = qml.gradients.vjp(tape, dy, param_shift)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert res.shape == (2,)
exp = (
@@ -374,10 +374,12 @@ class TestVJPGradients:
"""Gradient tests for the vjp function"""
@pytest.mark.autograd
- def test_autograd(self, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name, tol):
"""Tests that the output of the VJP transform
can be differentiated using autograd."""
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
def cost_fn(x, dy):
@@ -387,7 +389,7 @@ def cost_fn(x, dy):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.vjp(tape, dy, param_shift)
- vjp = fn(dev.batch_execute(tapes))
+ vjp = fn(execute_fn(tapes))
return vjp
dy = np.array([-1.0, 0.0, 0.0, 1.0], requires_grad=False)
@@ -398,12 +400,13 @@ def cost_fn(x, dy):
assert np.allclose(res, qml.jacobian(expected)(params), atol=tol, rtol=0)
@pytest.mark.torch
- def test_torch(self, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, dev_name, tol):
"""Tests that the output of the VJP transform
can be differentiated using Torch."""
import torch
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device(dev_name, wires=2)
params_np = np.array([0.543, -0.654], requires_grad=True)
params = torch.tensor(params_np, requires_grad=True, dtype=torch.float64)
@@ -427,12 +430,14 @@ def test_torch(self, tol):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf(self, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, dev_name, tol):
"""Tests that the output of the VJP transform
can be differentiated using TF."""
import tensorflow as tf
- dev = qml.device("default.qubit.tf", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params_np = np.array([0.543, -0.654], requires_grad=True)
params = tf.Variable(params_np, dtype=tf.float64)
@@ -445,7 +450,7 @@ def test_tf(self, tol):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.vjp(tape, dy, param_shift)
- vjp = fn(dev.batch_execute(tapes))
+ vjp = fn(execute_fn(tapes))
assert np.allclose(vjp, expected(params), atol=tol, rtol=0)
@@ -490,13 +495,15 @@ def test_tf(self, tol):
@pytest.mark.jax
@pytest.mark.slow
- def test_jax(self, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, dev_name, tol):
"""Tests that the output of the VJP transform
can be differentiated using JAX."""
import jax
from jax import numpy as jnp
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params_np = np.array([0.543, -0.654], requires_grad=True)
params = jnp.array(params_np)
@@ -508,7 +515,7 @@ def cost_fn(x):
dy = jax.numpy.array([-1.0, 0.0, 0.0, 1.0])
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.vjp(tape, dy, param_shift)
- vjp = fn(dev.batch_execute(tapes))
+ vjp = fn(execute_fn(tapes))
return vjp
res = cost_fn(params)
@@ -550,7 +557,7 @@ def test_one_tape_no_trainable_parameters(self):
# Even though there are 3 parameters, only two contribute
# to the VJP, so only 2*2=4 quantum evals
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
assert res[0] is None
assert res[1] is not None
@@ -604,7 +611,7 @@ def test_zero_dy(self):
dys = [np.array(0.0), np.array(1.0)]
v_tapes, fn = qml.gradients.batch_vjp(tapes, dys, param_shift)
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
# Even though there are 3 parameters, only two contribute
# to the VJP, so only 2*2=4 quantum evals
@@ -635,7 +642,7 @@ def test_reduction_append(self):
dys = [np.array(1.0), np.array(1.0)]
v_tapes, fn = qml.gradients.batch_vjp(tapes, dys, param_shift, reduction="append")
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
# Returned VJPs will be appended to a list, one vjp per tape
assert len(res) == 2
@@ -666,7 +673,7 @@ def test_reduction_extend(self):
dys = [np.array(1.0), np.array(1.0)]
v_tapes, fn = qml.gradients.batch_vjp(tapes, dys, param_shift, reduction="extend")
- res = fn(dev.batch_execute(v_tapes))
+ res = fn(dev.execute(v_tapes))
# Returned VJPs will be extended into a list. Each element of the returned
# list will correspond to a single input parameter of the combined
diff --git a/tests/gradients/finite_diff/test_finite_difference.py b/tests/gradients/finite_diff/test_finite_difference.py
index 003a3cfe665..0e2a296d4c0 100644
--- a/tests/gradients/finite_diff/test_finite_difference.py
+++ b/tests/gradients/finite_diff/test_finite_difference.py
@@ -130,7 +130,7 @@ def test_non_differentiable_error(self):
dev = qml.device("default.qubit", wires=2)
tapes, fn = finite_diff(tape)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert isinstance(res[0], numpy.ndarray)
@@ -152,7 +152,7 @@ def test_independent_parameter(self, mocker):
tape = qml.tape.QuantumScript.from_queue(q)
dev = qml.device("default.qubit", wires=2)
tapes, fn = finite_diff(tape)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -413,13 +413,14 @@ def test_independent_parameters(self):
tape2 = qml.tape.QuantumScript.from_queue(q2)
tapes, fn = finite_diff(tape1, approx_order=1)
- j1 = fn(dev.batch_execute(tapes))
+ with qml.Tracker(dev) as tracker:
+ j1 = fn(dev.execute(tapes))
# We should only be executing the device to differentiate 1 parameter (2 executions)
- assert dev.num_executions == 2
+ assert tracker.latest["executions"] == 2
tapes, fn = finite_diff(tape2, approx_order=1)
- j2 = fn(dev.batch_execute(tapes))
+ j2 = fn(dev.execute(tapes))
exp = -np.sin(1)
@@ -564,7 +565,7 @@ def test_ragged_output(self, approx_order, strategy, validate):
tapes, fn = finite_diff(
tape, approx_order=approx_order, strategy=strategy, validate_params=validate
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
@@ -597,7 +598,7 @@ def test_single_expectation_value(self, approx_order, strategy, validate, tol):
tapes, fn = finite_diff(
tape, approx_order=approx_order, strategy=strategy, validate_params=validate
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -634,7 +635,7 @@ def test_single_expectation_value_with_argnum_all(self, approx_order, strategy,
strategy=strategy,
validate_params=validate,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -671,7 +672,7 @@ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy,
tapes, fn = finite_diff(
tape, argnum=1, approx_order=approx_order, strategy=strategy, validate_params=validate
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -712,7 +713,7 @@ def test_multiple_expectation_value_with_argnum_one(
tapes, fn = finite_diff(
tape, argnum=1, approx_order=approx_order, strategy=strategy, validate_params=validate
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert isinstance(res[0], tuple)
@@ -738,7 +739,7 @@ def test_multiple_expectation_values(self, approx_order, strategy, validate, tol
tapes, fn = finite_diff(
tape, approx_order=approx_order, strategy=strategy, validate_params=validate
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -773,7 +774,7 @@ def test_var_expectation_values(self, approx_order, strategy, validate, tol):
tapes, fn = finite_diff(
tape, approx_order=approx_order, strategy=strategy, validate_params=validate
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -808,7 +809,7 @@ def test_prob_expectation_values(self, approx_order, strategy, validate, tol):
tapes, fn = finite_diff(
tape, approx_order=approx_order, strategy=strategy, validate_params=validate
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -854,10 +855,12 @@ class TestFiniteDiffGradients:
"""Test that the transform is differentiable"""
@pytest.mark.autograd
- def test_autograd(self, approx_order, strategy, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name, approx_order, strategy, tol):
"""Tests that the output of the finite-difference transform
can be differentiated using autograd, yielding second derivatives."""
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
def cost_fn(x):
@@ -870,7 +873,7 @@ def cost_fn(x):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = finite_diff(tape, n=1, approx_order=approx_order, strategy=strategy)
- jac = np.array(fn(dev.batch_execute(tapes)))
+ jac = np.array(fn(execute_fn(tapes)))
return jac
res = qml.jacobian(cost_fn)(params)
@@ -885,10 +888,12 @@ def cost_fn(x):
assert np.allclose(res, expected, atol=tol, rtol=0)
@pytest.mark.autograd
- def test_autograd_ragged(self, approx_order, strategy, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd_ragged(self, dev_name, approx_order, strategy, tol):
"""Tests that the output of the finite-difference transform
of a ragged tape can be differentiated using autograd, yielding second derivatives."""
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
def cost_fn(x):
@@ -902,7 +907,7 @@ def cost_fn(x):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = finite_diff(tape, n=1, approx_order=approx_order, strategy=strategy)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac[1][0]
x, y = params
@@ -912,12 +917,14 @@ def cost_fn(x):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf(self, approx_order, strategy, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, dev_name, approx_order, strategy, tol):
"""Tests that the output of the finite-difference transform
can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
- dev = qml.device("default.qubit.tf", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
with tf.GradientTape(persistent=True) as t:
@@ -930,7 +937,7 @@ def test_tf(self, approx_order, strategy, tol):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = finite_diff(tape, n=1, approx_order=approx_order, strategy=strategy)
- jac_0, jac_1 = fn(dev.batch_execute(tapes))
+ jac_0, jac_1 = fn(execute_fn(tapes))
x, y = 1.0 * params
@@ -946,12 +953,14 @@ def test_tf(self, approx_order, strategy, tol):
assert np.allclose([res_0, res_1], expected, atol=tol, rtol=0)
@pytest.mark.tf
- def test_tf_ragged(self, approx_order, strategy, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf_ragged(self, dev_name, approx_order, strategy, tol):
"""Tests that the output of the finite-difference transform
of a ragged tape can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
- dev = qml.device("default.qubit.tf", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
with tf.GradientTape(persistent=True) as t:
@@ -966,7 +975,7 @@ def test_tf_ragged(self, approx_order, strategy, tol):
tape.trainable_params = {0, 1}
tapes, fn = finite_diff(tape, n=1, approx_order=approx_order, strategy=strategy)
- jac_01 = fn(dev.batch_execute(tapes))[1][0]
+ jac_01 = fn(execute_fn(tapes))[1][0]
x, y = 1.0 * params
@@ -977,12 +986,14 @@ def test_tf_ragged(self, approx_order, strategy, tol):
assert np.allclose(res_01[0], expected, atol=tol, rtol=0)
@pytest.mark.torch
- def test_torch(self, approx_order, strategy, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, dev_name, approx_order, strategy, tol):
"""Tests that the output of the finite-difference transform
can be differentiated using Torch, yielding second derivatives."""
import torch
- dev = qml.device("default.qubit.torch", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = torch.tensor([0.543, -0.654], dtype=torch.float64, requires_grad=True)
def cost_fn(params):
@@ -994,7 +1005,7 @@ def cost_fn(params):
tape = qml.tape.QuantumScript.from_queue(q)
tapes, fn = finite_diff(tape, n=1, approx_order=approx_order, strategy=strategy)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
hess = torch.autograd.functional.jacobian(cost_fn, params)
@@ -1012,7 +1023,8 @@ def cost_fn(params):
assert np.allclose(hess[1].detach().numpy(), expected[1], atol=tol, rtol=0)
@pytest.mark.jax
- def test_jax(self, approx_order, strategy, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, dev_name, approx_order, strategy, tol):
"""Tests that the output of the finite-difference transform
can be differentiated using JAX, yielding second derivatives."""
import jax
@@ -1021,7 +1033,8 @@ def test_jax(self, approx_order, strategy, tol):
config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = jnp.array([0.543, -0.654])
def cost_fn(x):
@@ -1034,7 +1047,7 @@ def cost_fn(x):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1}
tapes, fn = finite_diff(tape, n=1, approx_order=approx_order, strategy=strategy)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
res = jax.jacobian(cost_fn)(params)
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 d335db4068f..b2179096206 100644
--- a/tests/gradients/finite_diff/test_finite_difference_shot_vec.py
+++ b/tests/gradients/finite_diff/test_finite_difference_shot_vec.py
@@ -60,7 +60,7 @@ def test_non_differentiable_error(self):
dev = qml.device("default.qubit", wires=2, shots=default_shot_vector)
tapes, fn = finite_diff(tape, h=h_val)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -87,7 +87,7 @@ def test_independent_parameter_skipped(self, mocker):
tape = qml.tape.QuantumScript.from_queue(q, shots=default_shot_vector)
dev = qml.device("default.qubit", wires=2, shots=default_shot_vector)
tapes, fn = finite_diff(tape, h=h_val)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -270,7 +270,7 @@ def circuit(params):
params = np.array([0.5, 0.5, 0.5], requires_grad=True)
all_result = qml.gradients.finite_diff(circuit, h=h_val)(params)
- assert len(all_result) == len(default_shot_vector)
+ assert len(all_result) == len(many_shots_shot_vector)
for result in all_result:
assert isinstance(result, tuple)
@@ -358,20 +358,21 @@ def test_independent_parameters(self):
tape2 = qml.tape.QuantumScript.from_queue(q2, shots=many_shots_shot_vector)
tapes, fn = finite_diff(tape1, approx_order=1, h=h_val)
- j1 = fn(dev.batch_execute(tapes))
+ with qml.Tracker(dev) as tracker:
+ j1 = fn(dev.execute(tapes))
# We should only be executing the device to differentiate 1 parameter (2 executions)
- assert dev.num_executions == 2
+ assert tracker.latest["executions"] == 2
tapes, fn = finite_diff(tape2, approx_order=1, h=h_val)
- j2 = fn(dev.batch_execute(tapes))
+ j2 = fn(dev.execute(tapes))
exp = -np.sin(1)
assert isinstance(j1, tuple)
- assert len(j1) == len(default_shot_vector)
+ assert len(j1) == len(many_shots_shot_vector)
assert isinstance(j2, tuple)
- assert len(j2) == len(default_shot_vector)
+ assert len(j2) == len(many_shots_shot_vector)
for _j1, _j2 in zip(j1, j2):
assert np.allclose(_j1, [exp, 0], atol=finite_diff_shot_vec_tol)
@@ -519,7 +520,7 @@ def test_ragged_output(self, approx_order, strategy, validate):
strategy=strategy,
validate_params=validate,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(many_shots_shot_vector)
@@ -551,7 +552,7 @@ def test_single_expectation_value(self, approx_order, strategy, validate):
qml.CNOT(wires=[0, 1])
qml.expval(qml.PauliZ(0) @ qml.PauliX(1))
- tape = qml.tape.QuantumScript.from_queue(q, shots=default_shot_vector)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=many_shots_shot_vector)
tapes, fn = finite_diff(
tape,
approx_order=approx_order,
@@ -559,10 +560,10 @@ def test_single_expectation_value(self, approx_order, strategy, validate):
validate_params=validate,
h=h_val,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
expected = np.array([[-np.sin(y) * np.sin(x), np.cos(y) * np.cos(x)]])
for res in all_res:
@@ -601,10 +602,10 @@ def test_single_expectation_value_with_argnum_all(self, approx_order, strategy,
validate_params=validate,
h=h_val,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
expected = np.array([[-np.sin(y) * np.sin(x), np.cos(y) * np.cos(x)]])
for res in all_res:
@@ -647,10 +648,10 @@ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy,
validate_params=validate,
h=h_val,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
expected = [0, np.cos(y) * np.cos(x)]
@@ -674,6 +675,9 @@ def test_probs_expval_with_argnum_one(self, approx_order, strategy, validate):
This test relies on the fact that exactly one term of the estimated
jacobian will match the expected analytical value.
"""
+ if approx_order == 4 and strategy != "center":
+ pytest.skip("The latest default.qubit is unreliable with an approx_order of 4")
+
dev = qml.device("default.qubit", wires=2, shots=many_shots_shot_vector)
x = 0.543
y = -0.654
@@ -695,10 +699,10 @@ def test_probs_expval_with_argnum_one(self, approx_order, strategy, validate):
validate_params=validate,
h=h_val,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
cx, sx, cy, sy = np.cos(x / 2), np.sin(x / 2), np.cos(y / 2), np.sin(y / 2)
# probability vector is [cx**2 * cy**2, cx**2 * sy**2, sx**2 * sy**2, sx**2 * cy**2]
@@ -734,10 +738,10 @@ def test_multiple_expectation_values(self, approx_order, strategy, validate):
validate_params=validate,
h=h_val,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
for res in all_res:
assert isinstance(res, tuple)
@@ -777,10 +781,10 @@ def test_var_expectation_values(self, approx_order, strategy, validate):
validate_params=validate,
h=h_val,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
for res in all_res:
assert isinstance(res, tuple)
@@ -822,10 +826,10 @@ def test_prob_expectation_values(self, approx_order, strategy, validate):
validate_params=validate,
h=h_val,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
for res in all_res:
assert isinstance(res, tuple)
@@ -873,10 +877,12 @@ class TestFiniteDiffGradients:
"""Test that the transform is differentiable"""
@pytest.mark.autograd
- def test_autograd(self, approx_order, strategy):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name, approx_order, strategy):
"""Tests that the output of the finite-difference transform
can be differentiated using autograd, yielding second derivatives."""
- dev = qml.device("default.qubit.autograd", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
def cost_fn(x):
@@ -895,13 +901,13 @@ def cost_fn(x):
strategy=strategy,
h=h_val,
)
- jac = np.array(fn(dev.batch_execute(tapes)))
+ jac = np.array(fn(execute_fn(tapes)))
return jac
all_res = qml.jacobian(cost_fn)(params)
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
for res in all_res:
x, y = params
@@ -915,10 +921,12 @@ def cost_fn(x):
assert np.allclose(res, expected, atol=finite_diff_shot_vec_tol, rtol=0)
@pytest.mark.autograd
- def test_autograd_ragged(self, approx_order, strategy):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd_ragged(self, dev_name, approx_order, strategy):
"""Tests that the output of the finite-difference transform
of a ragged tape can be differentiated using autograd, yielding second derivatives."""
- dev = qml.device("default.qubit.autograd", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
def cost_fn(x):
@@ -938,14 +946,14 @@ def cost_fn(x):
strategy=strategy,
h=h_val,
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac[1][0]
x, y = params
all_res = qml.jacobian(cost_fn)(params)[0]
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
for res in all_res:
expected = np.array([-np.cos(x) * np.cos(y) / 2, np.sin(x) * np.sin(y) / 2])
@@ -953,12 +961,14 @@ def cost_fn(x):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf(self, approx_order, strategy):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, dev_name, approx_order, strategy):
"""Tests that the output of the finite-difference transform
can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
- dev = qml.device("default.qubit.tf", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
with tf.GradientTape(persistent=True) as t:
@@ -977,7 +987,7 @@ def test_tf(self, approx_order, strategy):
strategy=strategy,
h=h_val,
)
- jac_0, jac_1 = fn(dev.batch_execute(tapes))
+ jac_0, jac_1 = fn(execute_fn(tapes))
x, y = 1.0 * params
@@ -993,12 +1003,14 @@ def test_tf(self, approx_order, strategy):
assert np.allclose([res_0, res_1], expected, atol=finite_diff_shot_vec_tol, rtol=0)
@pytest.mark.tf
- def test_tf_ragged(self, approx_order, strategy):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf_ragged(self, dev_name, approx_order, strategy):
"""Tests that the output of the finite-difference transform
of a ragged tape can be differentiated using TF, yielding second derivatives."""
import tensorflow as tf
- dev = qml.device("default.qubit.tf", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
with tf.GradientTape(persistent=True) as t:
@@ -1019,7 +1031,7 @@ def test_tf_ragged(self, approx_order, strategy):
h=h_val,
)
- jac_01 = fn(dev.batch_execute(tapes))[1][0]
+ jac_01 = fn(execute_fn(tapes))[1][0]
x, y = 1.0 * params
@@ -1030,12 +1042,14 @@ def test_tf_ragged(self, approx_order, strategy):
assert np.allclose(res_01[0], expected, atol=finite_diff_shot_vec_tol, rtol=0)
@pytest.mark.torch
- def test_torch(self, approx_order, strategy):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, dev_name, approx_order, strategy):
"""Tests that the output of the finite-difference transform
can be differentiated using Torch, yielding second derivatives."""
import torch
- dev = qml.device("default.qubit.torch", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = torch.tensor([0.543, -0.654], dtype=torch.float64, requires_grad=True)
def cost_fn(params):
@@ -1053,7 +1067,7 @@ def cost_fn(params):
strategy=strategy,
h=h_val,
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
hess = torch.autograd.functional.jacobian(cost_fn, params)
@@ -1075,7 +1089,8 @@ def cost_fn(params):
)
@pytest.mark.jax
- def test_jax(self, approx_order, strategy):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, dev_name, approx_order, strategy):
"""Tests that the output of the finite-difference transform
can be differentiated using JAX, yielding second derivatives."""
import jax
@@ -1084,7 +1099,8 @@ def test_jax(self, approx_order, strategy):
config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = jnp.array([0.543, -0.654])
def cost_fn(x):
@@ -1103,13 +1119,13 @@ def cost_fn(x):
strategy=strategy,
h=h_val,
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
all_res = jax.jacobian(cost_fn)(params)
assert isinstance(all_res, tuple)
- assert len(all_res) == len(default_shot_vector)
+ assert len(all_res) == len(many_shots_shot_vector)
x, y = params
expected = np.array(
@@ -1176,7 +1192,7 @@ def test_1_1(self, shot_vec, meas, shape, op_wires):
tape.trainable_params = {0}
tapes, fn = qml.gradients.finite_diff(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -1210,7 +1226,7 @@ def test_1_N(self, shot_vec, op_wire):
tape.trainable_params = {0}
tapes, fn = qml.gradients.finite_diff(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -1244,7 +1260,7 @@ def test_N_1(self, shot_vec, meas, shape, op_wires):
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.finite_diff(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -1286,7 +1302,7 @@ def test_N_N(self, shot_vec, op_wires):
tape.trainable_params = {0, 1, 2, 3, 4}
tapes, fn = qml.gradients.finite_diff(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
diff --git a/tests/gradients/finite_diff/test_spsa_gradient.py b/tests/gradients/finite_diff/test_spsa_gradient.py
index 44a149041cb..5897aed4b88 100644
--- a/tests/gradients/finite_diff/test_spsa_gradient.py
+++ b/tests/gradients/finite_diff/test_spsa_gradient.py
@@ -201,7 +201,7 @@ def test_non_differentiable_error(self):
dev = qml.device("default.qubit", wires=2)
tapes, fn = spsa_grad(tape)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -225,7 +225,7 @@ def test_independent_parameter(self, num_directions, mocker):
tape = qml.tape.QuantumScript.from_queue(q)
dev = qml.device("default.qubit", wires=2)
tapes, fn = spsa_grad(tape, num_directions=num_directions)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -498,13 +498,14 @@ def test_independent_parameters(self):
tapes, fn = spsa_grad(
tape1, approx_order=1, strategy="forward", num_directions=n1, sampler_rng=rng
)
- j1 = fn(dev.batch_execute(tapes))
+ with qml.Tracker(dev) as tracker:
+ j1 = fn(dev.execute(tapes))
- assert len(tapes) == dev.num_executions == n1 + 1
+ assert len(tapes) == tracker.latest["executions"] == n1 + 1
n2 = 11
tapes, fn = spsa_grad(tape2, num_directions=n2, sampler_rng=rng)
- j2 = fn(dev.batch_execute(tapes))
+ j2 = fn(dev.execute(tapes))
assert len(tapes) == 2 * n2
@@ -657,7 +658,7 @@ def test_ragged_output(self, approx_order, strategy, validate):
num_directions=11,
validate_params=validate,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
@@ -696,7 +697,7 @@ def test_single_expectation_value(self, approx_order, strategy, validate, tol):
sampler=coordinate_sampler,
validate_params=validate,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -740,7 +741,7 @@ def test_single_expectation_value_with_argnum_all(self, approx_order, strategy,
sampler=coordinate_sampler,
validate_params=validate,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -789,7 +790,7 @@ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy,
sampler=coordinate_sampler,
validate_params=validate,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -834,7 +835,7 @@ def test_multiple_expectation_value_with_argnum_one(self, approx_order, strategy
sampler=coordinate_sampler,
validate_params=validate,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert isinstance(res[0], tuple)
@@ -865,7 +866,7 @@ def test_multiple_expectation_values(self, approx_order, strategy, validate, tol
sampler=coordinate_sampler,
validate_params=validate,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -910,7 +911,7 @@ def test_var_expectation_values(self, approx_order, strategy, validate, tol):
sampler=coordinate_sampler,
num_directions=2,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -955,7 +956,7 @@ def test_prob_expectation_values(self, approx_order, strategy, validate, tol):
sampler=coordinate_sampler,
num_directions=2,
)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -1007,10 +1008,12 @@ class TestSpsaGradientDifferentiation:
"""Test that the transform is differentiable"""
@pytest.mark.autograd
- def test_autograd(self, sampler, num_directions, atol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name, sampler, num_directions, atol):
"""Tests that the output of the SPSA gradient transform
can be differentiated using autograd, yielding second derivatives."""
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
rng = np.random.default_rng(42)
@@ -1026,7 +1029,7 @@ def cost_fn(x):
tapes, fn = spsa_grad(
tape, n=1, num_directions=num_directions, sampler=sampler, sampler_rng=rng
)
- jac = np.array(fn(dev.batch_execute(tapes)))
+ jac = np.array(fn(execute_fn(tapes)))
if sampler is coordinate_sampler:
jac *= 2
return jac
@@ -1043,10 +1046,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):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd_ragged(self, dev_name, sampler, num_directions, atol):
"""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.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
rng = np.random.default_rng(42)
@@ -1063,7 +1068,7 @@ def cost_fn(x):
tapes, fn = spsa_grad(
tape, n=1, num_directions=num_directions, sampler=sampler, sampler_rng=rng
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
if sampler is coordinate_sampler:
jac = tuple(tuple(2 * _j for _j in _jac) for _jac in jac)
return jac[1][0]
@@ -1075,12 +1080,14 @@ def cost_fn(x):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf(self, sampler, num_directions, atol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, dev_name, sampler, num_directions, atol):
"""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.tf", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
rng = np.random.default_rng(42)
@@ -1096,7 +1103,7 @@ def test_tf(self, sampler, num_directions, atol):
tapes, fn = spsa_grad(
tape, n=1, num_directions=num_directions, sampler=sampler, sampler_rng=rng
)
- jac_0, jac_1 = fn(dev.batch_execute(tapes))
+ jac_0, jac_1 = fn(execute_fn(tapes))
if sampler is coordinate_sampler:
jac_0 *= 2
jac_1 *= 2
@@ -1116,12 +1123,14 @@ def test_tf(self, sampler, num_directions, atol):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf_ragged(self, sampler, num_directions, atol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf_ragged(self, dev_name, sampler, num_directions, atol):
"""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.tf", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
rng = np.random.default_rng(42)
@@ -1139,7 +1148,7 @@ def test_tf_ragged(self, sampler, num_directions, atol):
tape, n=1, num_directions=num_directions, sampler=sampler, sampler_rng=rng
)
- jac_01 = fn(dev.batch_execute(tapes))[1][0]
+ jac_01 = fn(execute_fn(tapes))[1][0]
if sampler is coordinate_sampler:
jac_01 *= 2
@@ -1152,12 +1161,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):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, dev_name, sampler, num_directions, atol):
"""Tests that the output of the SPSA gradient transform
can be differentiated using Torch, yielding second derivatives."""
import torch
- dev = qml.device("default.qubit.torch", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = torch.tensor([0.543, -0.654], dtype=torch.float64, requires_grad=True)
rng = np.random.default_rng(42)
@@ -1172,7 +1183,7 @@ def cost_fn(params):
tapes, fn = spsa_grad(
tape, n=1, num_directions=num_directions, sampler=sampler, sampler_rng=rng
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
if sampler is coordinate_sampler:
jac = tuple(2 * _jac for _jac in jac)
return jac
@@ -1192,7 +1203,8 @@ 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):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, dev_name, sampler, num_directions, atol):
"""Tests that the output of the SPSA gradient transform
can be differentiated using JAX, yielding second derivatives."""
import jax
@@ -1201,7 +1213,8 @@ def test_jax(self, sampler, num_directions, atol):
config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = jnp.array([0.543, -0.654])
rng = np.random.default_rng(42)
@@ -1217,7 +1230,7 @@ def cost_fn(x):
tapes, fn = spsa_grad(
tape, n=1, num_directions=num_directions, sampler=sampler, sampler_rng=rng
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
if sampler is coordinate_sampler:
jac = tuple(2 * _jac for _jac in jac)
return jac
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 3d8fa8017df..f04dcd7ca25 100644
--- a/tests/gradients/finite_diff/test_spsa_gradient_shot_vec.py
+++ b/tests/gradients/finite_diff/test_spsa_gradient_shot_vec.py
@@ -71,7 +71,7 @@ def test_non_differentiable_error(self):
dev = qml.device("default.qubit", wires=2, shots=default_shot_vector)
tapes, fn = spsa_grad(tape, h=h_val)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -99,7 +99,7 @@ def test_independent_parameter(self, num_directions, mocker):
tape = qml.tape.QuantumScript.from_queue(q, shots=default_shot_vector)
dev = qml.device("default.qubit", wires=2, shots=default_shot_vector)
tapes, fn = spsa_grad(tape, h=h_val, num_directions=num_directions)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -409,9 +409,10 @@ def test_independent_parameters(self):
h=h_val,
sampler_rng=rng,
)
- j1 = fn(dev.batch_execute(tapes))
+ with qml.Tracker(dev) as tracker:
+ j1 = fn(dev.execute(tapes))
- assert len(tapes) == dev.num_executions == n1 + 1
+ assert len(tapes) == tracker.latest["executions"] == n1 + 1
n2 = 3
tapes, fn = spsa_grad(
@@ -422,7 +423,7 @@ def test_independent_parameters(self):
num_directions=n2,
sampler_rng=rng,
)
- j2 = fn(dev.batch_execute(tapes))
+ j2 = fn(dev.execute(tapes))
assert len(tapes) == n2 + 1
@@ -584,7 +585,7 @@ def test_ragged_output(self, approx_order, strategy, validate):
num_directions=3,
sampler_rng=rng,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(many_shots_shot_vector)
@@ -628,7 +629,7 @@ def test_single_expectation_value(self, approx_order, strategy, validate):
sampler=coordinate_sampler,
sampler_rng=rng,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -677,7 +678,7 @@ def test_single_expectation_value_with_argnum_all(self, approx_order, strategy,
h=h_val,
sampler_rng=rng,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -730,7 +731,7 @@ def test_single_expectation_value_with_argnum_one(self, approx_order, strategy,
h=h_val,
sampler_rng=rng,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -784,7 +785,7 @@ def test_multiple_expectation_value_with_argnum_one(self, approx_order, strategy
h=h_val,
sampler_rng=rng,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -824,7 +825,7 @@ def test_multiple_expectation_values(self, approx_order, strategy, validate):
num_directions=20,
sampler_rng=rng,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -878,7 +879,7 @@ def test_var_expectation_values(self, approx_order, strategy, validate):
sampler=coordinate_sampler,
sampler_rng=rng,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -933,7 +934,7 @@ def test_prob_expectation_values(self, approx_order, strategy, validate):
h=h_val,
sampler_rng=rng,
)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(default_shot_vector)
@@ -991,10 +992,12 @@ class TestSpsaGradientDifferentiation:
"""Test that the transform is differentiable"""
@pytest.mark.autograd
- def test_autograd(self, approx_order, strategy):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name, approx_order, strategy):
"""Tests that the output of the SPSA gradient transform
can be differentiated using autograd, yielding second derivatives."""
- dev = qml.device("default.qubit.autograd", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
rng = np.random.default_rng(42)
@@ -1015,7 +1018,7 @@ def cost_fn(x):
h=h_val,
sampler_rng=rng,
)
- jac = np.array(fn(dev.batch_execute(tapes)))
+ jac = np.array(fn(execute_fn(tapes)))
return jac
all_res = qml.jacobian(cost_fn)(params)
@@ -1035,10 +1038,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):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd_ragged(self, dev_name, approx_order, strategy):
"""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.autograd", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
rng = np.random.default_rng(42)
@@ -1060,7 +1065,7 @@ def cost_fn(x):
h=h_val,
sampler_rng=rng,
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac[1][0]
x, y = params
@@ -1075,12 +1080,14 @@ def cost_fn(x):
@pytest.mark.tf
@pytest.mark.slow
- def test_tf(self, approx_order, strategy):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, dev_name, approx_order, strategy):
"""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.tf", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
rng = np.random.default_rng(42)
@@ -1101,7 +1108,7 @@ def test_tf(self, approx_order, strategy):
h=h_val,
sampler_rng=rng,
)
- jac_0, jac_1 = fn(dev.batch_execute(tapes))
+ jac_0, jac_1 = fn(execute_fn(tapes))
x, y = 1.0 * params
@@ -1117,12 +1124,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):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf_ragged(self, dev_name, approx_order, strategy):
"""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.tf", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = tf.Variable([0.543, -0.654], dtype=tf.float64)
rng = np.random.default_rng(42)
@@ -1145,7 +1154,7 @@ def test_tf_ragged(self, approx_order, strategy):
sampler_rng=rng,
)
- jac_01 = fn(dev.batch_execute(tapes))[1][0]
+ jac_01 = fn(execute_fn(tapes))[1][0]
x, y = 1.0 * params
@@ -1156,12 +1165,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):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, dev_name, approx_order, strategy):
"""Tests that the output of the SPSA gradient transform
can be differentiated using Torch, yielding second derivatives."""
import torch
- dev = qml.device("default.qubit.torch", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = torch.tensor([0.543, -0.654], dtype=torch.float64, requires_grad=True)
rng = np.random.default_rng(42)
@@ -1181,7 +1192,7 @@ def cost_fn(params):
h=h_val,
sampler_rng=rng,
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
hess = torch.autograd.functional.jacobian(cost_fn, params)
@@ -1199,7 +1210,8 @@ 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):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, dev_name, approx_order, strategy):
"""Tests that the output of the SPSA gradient transform
can be differentiated using JAX, yielding second derivatives."""
import jax
@@ -1208,7 +1220,8 @@ def test_jax(self, approx_order, strategy):
config.update("jax_enable_x64", True)
- dev = qml.device("default.qubit.jax", wires=2, shots=many_shots_shot_vector)
+ dev = qml.device(dev_name, wires=2, shots=many_shots_shot_vector)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = jnp.array([0.543, -0.654])
rng = np.random.default_rng(42)
@@ -1229,7 +1242,7 @@ def cost_fn(x):
h=h_val,
sampler_rng=rng,
)
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
all_res = jax.jacobian(cost_fn)(params)
@@ -1302,7 +1315,7 @@ def test_1_1(self, shot_vec, meas, shape, op_wires):
tape.trainable_params = {0}
tapes, fn = spsa_grad(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -1336,7 +1349,7 @@ def test_1_N(self, shot_vec, op_wire):
tape.trainable_params = {0}
tapes, fn = spsa_grad(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -1370,7 +1383,7 @@ def test_N_1(self, shot_vec, meas, shape, op_wires):
tape.trainable_params = {0, 1}
tapes, fn = spsa_grad(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -1409,7 +1422,7 @@ def test_N_N(self, shot_vec, op_wires):
tape.trainable_params = {0, 1, 2, 3, 4}
tapes, fn = spsa_grad(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
diff --git a/tests/gradients/parameter_shift/test_parameter_shift.py b/tests/gradients/parameter_shift/test_parameter_shift.py
index a8e0aaa1858..d483c065837 100644
--- a/tests/gradients/parameter_shift/test_parameter_shift.py
+++ b/tests/gradients/parameter_shift/test_parameter_shift.py
@@ -315,7 +315,7 @@ def test_multi_measure_partitioned_shots_par_shapes(self, g, par_shapes):
def grad_fn(tape, dev, fn=qml.gradients.param_shift, **kwargs):
"""Utility function to automate execution and processing of gradient tapes"""
tapes, fn = fn(tape, **kwargs)
- return fn(dev.batch_execute(tapes))
+ return fn(dev.execute(tapes))
class TestParamShift:
@@ -370,7 +370,7 @@ def test_independent_parameter(self, mocker):
assert len(tapes) == 2
assert tapes[0].batch_size == tapes[1].batch_size == None
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
assert res[0].shape == ()
@@ -761,7 +761,7 @@ def test_f0_provided(self, y_wire):
# one tape per parameter that impacts the expval
assert len(tapes) == 2 if y_wire == 0 else 1
- fn(dev.batch_execute(tapes))
+ fn(dev.execute(tapes))
def test_op_with_custom_unshifted_term(self):
"""Test that an operation with a gradient recipe that depends on
@@ -798,7 +798,7 @@ class RX(qml.RX):
assert tape.operations[0].data[0] == x[0] + expected[0]
assert tape.operations[1].data[0] == x[1] + expected[1]
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
exp = np.stack([-np.sin(x[0] + x[1]), -np.sin(x[0] + x[1]) + 0.2 * np.cos(x[0] + x[1])])
assert len(grad) == len(exp)
for (
@@ -825,15 +825,16 @@ def test_independent_parameters_analytic(self):
tape2 = qml.tape.QuantumScript.from_queue(q2)
tapes, fn = qml.gradients.param_shift(tape1)
- j1 = fn(dev.batch_execute(tapes))
+ with qml.Tracker(dev) as tracker:
+ j1 = fn(dev.execute(tapes))
# We should only be executing the device twice: Two shifted evaluations to differentiate
# one parameter overall, as the other parameter does not impact the returned measurement.
- assert dev.num_executions == 2
+ assert tracker.latest["executions"] == 2
tapes, fn = qml.gradients.param_shift(tape2)
- j2 = fn(dev.batch_execute(tapes))
+ j2 = fn(dev.execute(tapes))
exp = -np.sin(1)
@@ -863,7 +864,7 @@ def test_grad_recipe_parameter_dependent(self):
assert qml.math.allclose(tapes[0].operations[0].data[0], 0)
assert qml.math.allclose(tapes[1].operations[0].data[0], 2 * x)
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
assert np.allclose(grad, -np.sin(x))
def test_error_no_diff_info(self):
@@ -946,7 +947,7 @@ def test_with_single_parameter_broadcasted(self, dim, pos):
assert np.allclose([t.batch_size for t in tapes], dim)
dev = qml.device("default.qubit", wires=2)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -974,7 +975,7 @@ def test_with_multiple_parameters_broadcasted(self, dim, argnum):
assert np.allclose([t.batch_size for t in tapes], dim)
dev = qml.device("default.qubit", wires=2)
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 3
@@ -1001,7 +1002,7 @@ def test_independent_parameter(self, mocker):
assert len(tapes) == 1
assert tapes[0].batch_size == 2
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert len(res) == 2
assert res[0].shape == ()
assert res[1].shape == ()
@@ -1080,15 +1081,16 @@ def test_independent_parameters_analytic(self):
tape2 = qml.tape.QuantumScript.from_queue(q2)
tapes, fn = qml.gradients.param_shift(tape1, broadcast=True)
- j1 = fn(dev.batch_execute(tapes))
+ with qml.Tracker(dev) as tracker:
+ j1 = fn(dev.execute(tapes))
# We should only be executing the device to differentiate 1 parameter
# (1 broadcasted execution)
- assert dev.num_executions == 1
+ assert tracker.latest["executions"] == 1
tapes, fn = qml.gradients.param_shift(tape2, broadcast=True)
- j2 = fn(dev.batch_execute(tapes))
+ j2 = fn(dev.execute(tapes))
exp = -np.sin(1)
@@ -1122,7 +1124,7 @@ def fail(*args, **kwargs):
assert tapes[0].batch_size == 2
assert qml.math.allclose(tapes[0].operations[0].data[0], [0, 2 * x])
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
assert np.allclose(grad, -np.sin(x))
@@ -1153,12 +1155,12 @@ def test_pauli_rotation_gradient(self, mocker, G, theta, shift, tol):
tapes, fn = qml.gradients.param_shift(tape, shifts=[(shift,)])
assert len(tapes) == 2
- autograd_val = fn(dev.batch_execute(tapes))
+ autograd_val = fn(dev.execute(tapes))
tape_fwd = tape.bind_new_parameters([theta + np.pi / 2], [1])
tape_bwd = tape.bind_new_parameters([theta - np.pi / 2], [1])
- manualgrad_val = np.subtract(*dev.batch_execute([tape_fwd, tape_bwd])) / 2
+ manualgrad_val = np.subtract(*dev.execute([tape_fwd, tape_bwd])) / 2
assert np.allclose(autograd_val, manualgrad_val, atol=tol, rtol=0)
assert isinstance(autograd_val, np.ndarray)
@@ -1167,7 +1169,7 @@ def test_pauli_rotation_gradient(self, mocker, G, theta, shift, tol):
assert spy.call_args[1]["shifts"] == (shift,)
tapes, fn = qml.gradients.finite_diff(tape)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
assert np.allclose(autograd_val, numeric_val, atol=tol, rtol=0)
@pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, 2 * np.pi, 7))
@@ -1190,7 +1192,7 @@ def test_Rot_gradient(self, mocker, theta, shift, tol):
num_params = len(tape.trainable_params)
assert len(tapes) == 2 * num_params
- autograd_val = fn(dev.batch_execute(tapes))
+ autograd_val = fn(dev.execute(tapes))
assert isinstance(autograd_val, tuple)
assert len(autograd_val) == num_params
@@ -1215,7 +1217,7 @@ def test_Rot_gradient(self, mocker, theta, shift, tol):
assert spy.call_args[1]["shifts"] == (shift,)
tapes, fn = qml.gradients.finite_diff(tape)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
for a_val, n_val in zip(autograd_val, numeric_val):
assert np.allclose(a_val, n_val, atol=tol, rtol=0)
@@ -1237,12 +1239,12 @@ def test_controlled_rotation_gradient(self, G, tol):
assert np.allclose(res, -np.cos(b / 2), atol=tol, rtol=0)
tapes, fn = qml.gradients.param_shift(tape)
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
expected = np.sin(b / 2) / 2
assert np.allclose(grad, expected, atol=tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
assert np.allclose(grad, numeric_val, atol=tol, rtol=0)
@pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, np.pi, 7))
@@ -1267,7 +1269,7 @@ def test_CRot_gradient(self, theta, tol):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 4 * len(tape.trainable_params)
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
expected = np.array(
[
0.5 * np.cos(b / 2) * np.sin(0.5 * (a + c)),
@@ -1281,7 +1283,7 @@ def test_CRot_gradient(self, theta, tol):
assert np.allclose(g, expected[idx], atol=tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
for idx, g in enumerate(grad):
assert np.allclose(g, numeric_val[idx], atol=tol, rtol=0)
@@ -1373,7 +1375,7 @@ def cost_fn(params):
spy.assert_called()
assert spy.call_args[1]["argnum"] == {1}
- return fn(dev.batch_execute(tapes))
+ return fn(dev.execute(tapes))
res = cost_fn(params)
@@ -1402,10 +1404,12 @@ def cost_fn(params):
# assert np.allclose(jac[1, 1, 1], -2 * np.cos(2 * y), atol=tol, rtol=0)
@pytest.mark.autograd
- def test_fallback_single_meas(self, mocker):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_fallback_single_meas(self, dev_name, mocker):
"""Test that fallback gradient functions are correctly used for a single measurement."""
spy = mocker.spy(qml.gradients, "finite_diff")
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -1425,7 +1429,7 @@ def cost_fn(params):
spy.assert_called()
assert spy.call_args[1]["argnum"] == {1}
- return fn(dev.batch_execute(tapes))
+ return fn(execute_fn(tapes))
res = cost_fn(params)
@@ -1442,10 +1446,12 @@ def cost_fn(params):
@pytest.mark.autograd
@pytest.mark.parametrize("RX, RY, argnum", [(RX_with_F, qml.RY, 0), (qml.RX, RY_with_F, 1)])
- def test_fallback_probs(self, RX, RY, argnum, mocker):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_fallback_probs(self, dev_name, RX, RY, argnum, mocker):
"""Test that fallback gradient functions are correctly used with probs"""
spy = mocker.spy(qml.gradients, "finite_diff")
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -1467,7 +1473,7 @@ def cost_fn(params):
spy.assert_called()
assert spy.call_args[1]["argnum"] == {argnum}
- return fn(dev.batch_execute(tapes))
+ return fn(execute_fn(tapes))
res = cost_fn(params)
@@ -1524,13 +1530,15 @@ def cost_fn(params):
assert np.allclose(res[1][1], probs_expected[:, 1])
@pytest.mark.autograd
- def test_all_fallback(self, mocker, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_all_fallback(self, dev_name, mocker, tol):
"""Test that *only* the fallback logic is called if no parameters
support the parameter-shift rule"""
spy_fd = mocker.spy(qml.gradients, "finite_diff")
spy_ps = mocker.spy(qml.gradients.parameter_shift, "expval_param_shift")
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -1548,7 +1556,7 @@ def test_all_fallback(self, mocker, tol):
spy_fd.assert_called()
spy_ps.assert_not_called()
- res = fn(dev.batch_execute(tapes))
+ res = fn(execute_fn(tapes))
assert isinstance(res, tuple)
assert res[0].shape == ()
@@ -1574,7 +1582,7 @@ def test_single_expectation_value(self, tol):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert len(res) == 2
assert not isinstance(res[0], tuple)
assert not isinstance(res[1], tuple)
@@ -1619,7 +1627,7 @@ def test_multiple_expectation_values(self, tol):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert len(res) == 2
assert len(res[0]) == 2
assert len(res[1]) == 2
@@ -1646,7 +1654,7 @@ def test_var_expectation_values(self, tol):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 5
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert len(res) == 2
assert len(res[0]) == 2
assert len(res[1]) == 2
@@ -1675,7 +1683,7 @@ def test_prob_expectation_values(self):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert len(res) == 2
for r in res:
@@ -1732,13 +1740,13 @@ def test_involutory_variance_single_param(self, tol):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, np.ndarray)
assert gradA.shape == ()
assert len(tapes) == 1 + 2 * 1
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 2
expected = 2 * np.sin(a) * np.cos(a)
@@ -1765,7 +1773,7 @@ def test_involutory_variance_multi_param(self, tol):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, tuple)
assert isinstance(gradA[0], np.ndarray)
@@ -1777,7 +1785,7 @@ def test_involutory_variance_multi_param(self, tol):
assert len(tapes) == 1 + 2 * 2
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 3
expected = 2 * np.sin(a + b) * np.cos(a + b)
@@ -1806,13 +1814,13 @@ def test_non_involutory_variance_single_param(self, tol):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, np.ndarray)
assert gradA.shape == ()
assert len(tapes) == 1 + 4 * 1
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 2
expected = -35 * np.sin(2 * a) - 12 * np.cos(2 * a)
@@ -1840,7 +1848,7 @@ def test_non_involutory_variance_multi_param(self, tol):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, tuple)
assert isinstance(gradA[0], np.ndarray)
@@ -1851,7 +1859,7 @@ def test_non_involutory_variance_multi_param(self, tol):
assert len(tapes) == 1 + 4 * 2
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 3
expected = -35 * np.sin(2 * (a + b)) - 12 * np.cos(2 * (a + b))
@@ -1884,11 +1892,11 @@ def test_involutory_and_noninvolutory_variance_single_param(self, tol):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert len(tapes) == 1 + 4
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 1 + 1
expected = [2 * np.sin(a) * np.cos(a), 0]
@@ -1937,7 +1945,7 @@ def test_var_and_probs_single_param(self, ind):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, tuple)
assert len(gradA) == 3
@@ -1987,7 +1995,7 @@ def test_var_and_probs_multi_params(self):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, tuple)
assert len(gradA) == 3
@@ -2117,10 +2125,10 @@ def test_expval_and_variance_single_param(self, tol):
# # circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
expected = np.array([2 * np.cos(a) * np.sin(a), -np.cos(b) * np.sin(a), 0])
assert isinstance(gradA, tuple)
@@ -2164,10 +2172,10 @@ def test_expval_and_variance_multi_param(self, tol):
# # circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
expected = np.array(
[
@@ -2238,10 +2246,10 @@ def test_projector_variance(self, state, tol):
# # circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
expected = np.array(
[
@@ -2432,7 +2440,7 @@ def test_multi_measure_no_warning(self):
tape = qml.tape.QuantumScript.from_queue(q)
with warnings.catch_warnings(record=True) as record:
tapes, fn = qml.gradients.param_shift(tape)
- fn(dev.batch_execute(tapes))
+ fn(dev.execute(tapes))
assert len(record) == 0
@@ -2463,18 +2471,18 @@ def test_pauli_rotation_gradient(self, mocker, G, theta, shift, tol):
assert len(tapes) == 1
assert tapes[0].batch_size == 2
- autograd_val = fn(dev.batch_execute(tapes))
+ autograd_val = fn(dev.execute(tapes))
tape_fwd = tape.bind_new_parameters([theta + np.pi / 2], [1])
tape_bwd = tape.bind_new_parameters([theta - np.pi / 2], [1])
- manualgrad_val = np.subtract(*dev.batch_execute([tape_fwd, tape_bwd])) / 2
+ manualgrad_val = np.subtract(*dev.execute([tape_fwd, tape_bwd])) / 2
assert np.allclose(autograd_val, manualgrad_val, atol=tol, rtol=0)
assert spy.call_args[1]["shifts"] == (shift,)
tapes, fn = qml.gradients.finite_diff(tape)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
assert np.allclose(autograd_val, numeric_val, atol=tol, rtol=0)
@pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, 2 * np.pi, 7))
@@ -2497,7 +2505,7 @@ def test_Rot_gradient(self, mocker, theta, shift, tol):
assert len(tapes) == len(tape.trainable_params)
assert [t.batch_size for t in tapes] == [2, 2, 2]
- autograd_val = fn(dev.batch_execute(tapes))
+ autograd_val = fn(dev.execute(tapes))
manualgrad_val = np.zeros_like(autograd_val)
for idx in list(np.ndindex(*params.shape)):
@@ -2516,7 +2524,7 @@ def test_Rot_gradient(self, mocker, theta, shift, tol):
assert spy.call_args[1]["shifts"] == (shift,)
tapes, fn = qml.gradients.finite_diff(tape)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
assert len(autograd_val) == len(numeric_val)
for a, n in zip(autograd_val, numeric_val):
@@ -2540,12 +2548,12 @@ def test_controlled_rotation_gradient(self, G, tol):
assert np.allclose(res, -np.cos(b / 2), atol=tol, rtol=0)
tapes, fn = qml.gradients.param_shift(tape, broadcast=True)
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
expected = np.sin(b / 2) / 2
assert np.allclose(grad, expected, atol=tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
assert np.allclose(grad, numeric_val, atol=tol, rtol=0)
@pytest.mark.parametrize("theta", np.linspace(-2 * np.pi, np.pi, 7))
@@ -2571,7 +2579,7 @@ def test_CRot_gradient(self, theta, tol):
assert len(tapes) == len(tape.trainable_params)
assert [t.batch_size for t in tapes] == [4, 4, 4]
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
expected = np.array(
[
0.5 * np.cos(b / 2) * np.sin(0.5 * (a + c)),
@@ -2584,7 +2592,7 @@ def test_CRot_gradient(self, theta, tol):
assert np.allclose(g, e, atol=tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
assert np.allclose(grad, numeric_val, atol=tol, rtol=0)
def test_gradients_agree_finite_differences(self, tol):
@@ -2650,10 +2658,12 @@ def test_variance_gradients_agree_finite_differences(self, tol):
assert np.allclose(g, grad_F2[idx1][idx2], atol=tol, rtol=0)
@pytest.mark.autograd
- def test_fallback(self, mocker):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_fallback(self, dev_name, mocker):
"""Test that fallback gradient functions are correctly used"""
spy = mocker.spy(qml.gradients, "finite_diff")
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -2675,7 +2685,7 @@ def cost_fn(params):
spy.assert_called()
assert spy.call_args[1]["argnum"] == {1}
- return fn(dev.batch_execute(tapes))
+ return fn(execute_fn(tapes))
with pytest.raises(NotImplementedError, match="Broadcasting with multiple measurements"):
cost_fn(params)
@@ -2691,13 +2701,15 @@ def cost_fn(params):
# assert np.allclose(jac[1, 1, 1], -2 * np.cos(2 * y), atol=tol, rtol=0)
@pytest.mark.autograd
- def test_all_fallback(self, mocker, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_all_fallback(self, dev_name, mocker, tol):
"""Test that *only* the fallback logic is called if no parameters
support the parameter-shift rule"""
spy_fd = mocker.spy(qml.gradients, "finite_diff")
spy_ps = mocker.spy(qml.gradients.parameter_shift, "expval_param_shift")
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -2715,7 +2727,7 @@ def test_all_fallback(self, mocker, tol):
spy_fd.assert_called()
spy_ps.assert_not_called()
- res = fn(dev.batch_execute(tapes))
+ res = fn(execute_fn(tapes))
assert len(res) == 2
assert res[0].shape == ()
assert res[1].shape == ()
@@ -2741,7 +2753,7 @@ def test_single_expectation_value(self, tol):
assert len(tapes) == 2
assert tapes[0].batch_size == tapes[1].batch_size == 2
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert len(res) == 2
assert res[0].shape == ()
assert res[1].shape == ()
@@ -2773,7 +2785,7 @@ def test_multiple_expectation_values(self):
# assert len(tapes) == 2
# assert tapes[0].batch_size == tapes[1].batch_size == 2
- # res = fn(dev.batch_execute(tapes))
+ # res = fn(dev.execute(tapes))
# assert res.shape == (2, 2)
# expected = np.array([[-np.sin(x), 0], [0, np.cos(y)]])
@@ -2802,7 +2814,7 @@ def test_var_expectation_values(self):
# assert tapes[0].batch_size is None
# assert tapes[1].batch_size == tapes[2].batch_size == 2
- # res = fn(dev.batch_execute(tapes))
+ # res = fn(dev.execute(tapes))
# assert res.shape == (2, 2)
# expected = np.array([[-np.sin(x), 0], [0, -2 * np.cos(y) * np.sin(y)]])
@@ -2832,7 +2844,7 @@ def test_prob_expectation_values(self):
# assert len(tapes) == 2
# assert tapes[0].batch_size == tapes[1].batch_size == 2
- # res = fn(dev.batch_execute(tapes))
+ # res = fn(dev.execute(tapes))
# assert res.shape == (5, 2)
# expected = (
@@ -2878,7 +2890,7 @@ def test_involutory_variance(self, tol):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape, broadcast=True)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, np.ndarray)
assert gradA.shape == ()
@@ -2887,7 +2899,7 @@ def test_involutory_variance(self, tol):
assert tapes[1].batch_size == 2
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 2
expected = 2 * np.sin(a) * np.cos(a)
@@ -2914,7 +2926,7 @@ def test_non_involutory_variance(self, tol):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape, broadcast=True)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, np.ndarray)
assert gradA.shape == ()
@@ -2923,7 +2935,7 @@ def test_non_involutory_variance(self, tol):
assert tapes[1].batch_size == tapes[2].batch_size == 2
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 2
expected = -35 * np.sin(2 * a) - 12 * np.cos(2 * a)
@@ -2955,11 +2967,11 @@ def test_involutory_and_noninvolutory_variance(self, tol):
qml.gradients.param_shift(tape, broadcast=True)
# TODO: Uncomment the following when #2693 is resolved.
# tapes, fn = qml.gradients.param_shift(tape, broadcast=True)
- # gradA = fn(dev.batch_execute(tapes))
+ # gradA = fn(dev.execute(tapes))
# assert len(tapes) == 1 + 2 * 4
# tapes, fn = qml.gradients.finite_diff(tape)
- # gradF = fn(dev.batch_execute(tapes))
+ # gradF = fn(dev.execute(tapes))
# assert len(tapes) == 1 + 2
# expected = [2 * np.sin(a) * np.cos(a), -35 * np.sin(2 * a) - 12 * np.cos(2 * a)]
@@ -3001,10 +3013,10 @@ def test_expval_and_variance(self, tol):
qml.gradients.param_shift(tape, broadcast=True)
# TODO: Uncomment the following when #2693 is resolved.
# tapes, fn = qml.gradients.param_shift(tape, broadcast=True)
- # gradA = fn(dev.batch_execute(tapes))
+ # gradA = fn(dev.execute(tapes))
# tapes, fn = qml.gradients.finite_diff(tape)
- # gradF = fn(dev.batch_execute(tapes))
+ # gradF = fn(dev.execute(tapes))
# ca, sa, cb, sb = np.cos(a), np.sin(a), np.cos(b), np.sin(b)
# c2c, s2c = np.cos(2 * c), np.sin(2 * c)
# expected = np.array(
@@ -3038,10 +3050,10 @@ def test_projector_variance(self, state, tol):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape, broadcast=True)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
tapes, fn = qml.gradients.finite_diff(tape)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
expected = np.array(
[
@@ -3113,10 +3125,12 @@ class TestParamShiftGradients:
@pytest.mark.autograd
# TODO: support Hessian with the new return types
@pytest.mark.skip
- def test_autograd(self, tol, broadcast, expected):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name, tol, broadcast, expected):
"""Tests that the output of the parameter-shift transform
can be differentiated using autograd, yielding second derivatives."""
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
params = np.array([0.543, -0.654], requires_grad=True)
exp_num_tapes, exp_batch_sizes = expected
@@ -3132,7 +3146,7 @@ def cost_fn(x):
tapes, fn = qml.gradients.param_shift(tape, broadcast=broadcast)
assert len(tapes) == exp_num_tapes
assert [t.batch_size for t in tapes] == exp_batch_sizes
- jac = fn(dev.batch_execute(tapes))
+ jac = fn(execute_fn(tapes))
return jac
res = qml.jacobian(cost_fn)(params)
@@ -3194,7 +3208,7 @@ def test_no_trainable_coeffs(self, mocker, tol, broadcast):
x, y = weights
tape.trainable_params = {0, 1}
- res = dev.batch_execute([tape])
+ res = dev.execute([tape])
expected = -c * np.sin(x) * np.sin(y) + np.cos(x) * (a + b * np.sin(y))
assert np.allclose(res, expected, atol=tol, rtol=0)
@@ -3204,7 +3218,7 @@ def test_no_trainable_coeffs(self, mocker, tol, broadcast):
assert [t.batch_size for t in tapes] == ([2, 2] if broadcast else [None] * 4)
spy.assert_not_called()
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
@@ -3240,7 +3254,7 @@ def test_trainable_coeffs(self, mocker, tol, broadcast):
x, y = weights
tape.trainable_params = {0, 1, 2, 4}
- res = dev.batch_execute([tape])
+ res = dev.execute([tape])
expected = -c * np.sin(x) * np.sin(y) + np.cos(x) * (a + b * np.sin(y))
assert np.allclose(res, expected, atol=tol, rtol=0)
@@ -3251,7 +3265,7 @@ def test_trainable_coeffs(self, mocker, tol, broadcast):
assert [t.batch_size for t in tapes] == ([2, 2, None, None] if broadcast else [None] * 6)
spy.assert_called()
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 4
assert res[0].shape == ()
@@ -3298,7 +3312,7 @@ def test_multiple_hamiltonians(self, mocker, tol, broadcast):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1, 2, 4, 5}
- res = dev.batch_execute([tape])
+ res = dev.execute([tape])
expected = [-c * np.sin(x) * np.sin(y) + np.cos(x) * (a + b * np.sin(y)), d * np.cos(x)]
assert np.allclose(res, expected, atol=tol, rtol=0)
@@ -3313,7 +3327,7 @@ def test_multiple_hamiltonians(self, mocker, tol, broadcast):
assert len(tapes) == 2 * 2 + 3
spy.assert_called()
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
assert len(res[0]) == 5
@@ -3351,7 +3365,8 @@ def cost_fn(weights, coeffs1, coeffs2, dev=None, broadcast=False):
tape = qml.tape.QuantumScript.from_queue(q)
tape.trainable_params = {0, 1, 2, 3, 4, 5}
tapes, fn = qml.gradients.param_shift(tape, broadcast=broadcast)
- jac = fn(dev.batch_execute(tapes))
+ execute_fn = dev.batch_execute if isinstance(dev, qml.Device) else dev.execute
+ jac = fn(execute_fn(tapes))
return jac
@staticmethod
@@ -3373,13 +3388,14 @@ def cost_fn_expected(weights, coeffs1, coeffs2):
]
@pytest.mark.autograd
- def test_autograd(self, tol, broadcast):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name, tol, broadcast):
"""Test gradient of multiple trainable Hamiltonian coefficients
using autograd"""
coeffs1 = np.array([0.1, 0.2, 0.3], requires_grad=True)
coeffs2 = np.array([0.7], requires_grad=True)
weights = np.array([0.4, 0.5], requires_grad=True)
- dev = qml.device("default.qubit.autograd", wires=2)
+ dev = qml.device(dev_name, wires=2)
if broadcast:
with pytest.raises(
@@ -3399,7 +3415,8 @@ def test_autograd(self, tol, broadcast):
# assert np.allclose(res[2][:, -1], np.zeros([2, 1, 1]), atol=tol, rtol=0)
@pytest.mark.tf
- def test_tf(self, tol, broadcast):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, dev_name, tol, broadcast):
"""Test gradient of multiple trainable Hamiltonian coefficients
using tf"""
import tensorflow as tf
@@ -3408,7 +3425,7 @@ def test_tf(self, tol, broadcast):
coeffs2 = tf.Variable([0.7], dtype=tf.float64)
weights = tf.Variable([0.4, 0.5], dtype=tf.float64)
- dev = qml.device("default.qubit.tf", wires=2)
+ dev = qml.device(dev_name, wires=2)
if broadcast:
with pytest.raises(
@@ -3435,7 +3452,8 @@ def test_tf(self, tol, broadcast):
# TODO: Torch support for param-shift
@pytest.mark.torch
@pytest.mark.xfail
- def test_torch(self, tol, broadcast):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, dev_name, tol, broadcast):
"""Test gradient of multiple trainable Hamiltonian coefficients
using torch"""
import torch
@@ -3444,7 +3462,7 @@ def test_torch(self, tol, broadcast):
coeffs2 = torch.tensor([0.7], dtype=torch.float64, requires_grad=True)
weights = torch.tensor([0.4, 0.5], dtype=torch.float64, requires_grad=True)
- dev = qml.device("default.qubit.torch", wires=2)
+ dev = qml.device(dev_name, wires=2)
if broadcast:
with pytest.raises(
@@ -3466,7 +3484,8 @@ def test_torch(self, tol, broadcast):
assert np.allclose(hess[2][:, -1], np.zeros([2, 1, 1]), atol=tol, rtol=0)
@pytest.mark.jax
- def test_jax(self, tol, broadcast):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, dev_name, tol, broadcast):
"""Test gradient of multiple trainable Hamiltonian coefficients
using JAX"""
import jax
@@ -3476,7 +3495,7 @@ def test_jax(self, tol, broadcast):
coeffs1 = jnp.array([0.1, 0.2, 0.3])
coeffs2 = jnp.array([0.7])
weights = jnp.array([0.4, 0.5])
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
if broadcast:
with pytest.raises(
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 16499641081..563423a0416 100644
--- a/tests/gradients/parameter_shift/test_parameter_shift_shot_vec.py
+++ b/tests/gradients/parameter_shift/test_parameter_shift_shot_vec.py
@@ -40,7 +40,7 @@
def grad_fn(tape, dev, fn=qml.gradients.param_shift, **kwargs):
"""Utility function to automate execution and processing of gradient tapes"""
tapes, fn = fn(tape, **kwargs)
- return fn(dev.batch_execute(tapes))
+ return fn(dev.execute(tapes))
# pylint: disable=too-few-public-methods
@@ -90,7 +90,7 @@ def test_independent_parameter(self, mocker):
assert len(tapes) == 2
assert tapes[0].batch_size == tapes[1].batch_size == None
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
for r in res:
assert isinstance(r, tuple)
assert len(r) == 2
@@ -293,7 +293,7 @@ def test_all_zero_diff_methods_multiple_returns_tape(self):
g_tapes, post_processing = qml.gradients.param_shift(tape)
assert g_tapes == []
- all_result = post_processing(dev.batch_execute(g_tapes))
+ all_result = post_processing(dev.execute(g_tapes))
assert isinstance(all_result, tuple)
@@ -414,7 +414,7 @@ def test_f0_provided(self, y_wire):
# one tape per parameter that impacts the expval
assert len(tapes) == 2 if y_wire == 0 else 1
- fn(dev.batch_execute(tapes))
+ fn(dev.execute(tapes))
def test_op_with_custom_unshifted_term(self):
"""Test that an operation with a gradient recipe that depends on
@@ -451,7 +451,7 @@ class RX(qml.RX):
assert tape.operations[0].data[0] == x[0] + expected[0]
assert tape.operations[1].data[0] == x[1] + expected[1]
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
exp = np.stack([-np.sin(x[0] + x[1]), -np.sin(x[0] + x[1]) + 0.2 * np.cos(x[0] + x[1])])
assert isinstance(grad, tuple)
assert len(grad) == len(default_shot_vector)
@@ -484,15 +484,16 @@ def test_independent_parameters_analytic(self):
tape2 = qml.tape.QuantumScript.from_queue(q2, shots=shot_vec)
tapes, fn = qml.gradients.param_shift(tape1)
- j1 = fn(dev.batch_execute(tapes))
+ with qml.Tracker(dev) as tracker:
+ j1 = fn(dev.execute(tapes))
# We should only be executing the device twice: Two shifted evaluations to differentiate
# one parameter overall, as the other parameter does not impact the returned measurement.
- assert dev.num_executions == 2
+ assert tracker.latest["executions"] == 2
tapes, fn = qml.gradients.param_shift(tape2)
- j2 = fn(dev.batch_execute(tapes))
+ j2 = fn(dev.execute(tapes))
exp = -np.sin(1)
@@ -532,7 +533,7 @@ def test_grad_recipe_parameter_dependent(self):
assert qml.math.allclose(tapes[0].operations[0].data[0], 0)
assert qml.math.allclose(tapes[1].operations[0].data[0], 2 * x)
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
assert np.allclose(grad, -np.sin(x), atol=shot_vec_tol)
def test_error_no_diff_info(self):
@@ -606,14 +607,14 @@ def test_pauli_rotation_gradient(self, mocker, G, theta, shift):
tapes, fn = qml.gradients.param_shift(tape, shifts=[(shift,)])
assert len(tapes) == 2
- autograd_val = fn(dev.batch_execute(tapes))
+ autograd_val = fn(dev.execute(tapes))
tape_fwd = tape.bind_new_parameters([theta + np.pi / 2], [1])
tape_bwd = tape.bind_new_parameters([theta - np.pi / 2], [1])
- shot_vec_manual_res = dev.batch_execute([tape_fwd, tape_bwd])
+ shot_vec_manual_res = dev.execute([tape_fwd, tape_bwd])
- # Parameter axis is the first - reorder the results from batch_execute
+ # Parameter axis is the first - reorder the results from execute
shot_vec_len = len(many_shots_shot_vector)
shot_vec_manual_res = [
tuple(comp[l] for comp in shot_vec_manual_res) for l in range(shot_vec_len)
@@ -628,7 +629,7 @@ def test_pauli_rotation_gradient(self, mocker, G, theta, shift):
assert spy.call_args[1]["shifts"] == (shift,)
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
for a_val, n_val in zip(autograd_val, numeric_val):
assert np.allclose(a_val, n_val, atol=finite_diff_tol, rtol=0)
@@ -654,7 +655,7 @@ def test_Rot_gradient(self, mocker, theta, shift):
num_params = len(tape.trainable_params)
assert len(tapes) == 2 * num_params
- autograd_val = fn(dev.batch_execute(tapes))
+ autograd_val = fn(dev.execute(tapes))
assert isinstance(autograd_val, tuple)
assert len(autograd_val) == len(shot_vec)
@@ -687,7 +688,7 @@ def test_Rot_gradient(self, mocker, theta, shift):
assert spy.call_args[1]["shifts"] == (shift,)
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
for a_val, n_val in zip(autograd_val, numeric_val):
assert np.allclose(a_val, n_val, atol=finite_diff_tol, rtol=0)
@@ -710,14 +711,14 @@ def test_controlled_rotation_gradient(self, G):
assert np.allclose(res, -np.cos(b / 2), atol=shot_vec_tol, rtol=0)
tapes, fn = qml.gradients.param_shift(tape)
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
expected = np.sin(b / 2) / 2
assert isinstance(grad, tuple)
assert len(grad) == len(many_shots_shot_vector)
assert np.allclose(grad, expected, atol=shot_vec_tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
for a_val, n_val in zip(grad, numeric_val):
assert np.allclose(a_val, n_val, atol=finite_diff_tol, rtol=0)
@@ -744,7 +745,7 @@ def test_CRot_gradient(self, theta):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 4 * len(tape.trainable_params)
- grad = fn(dev.batch_execute(tapes))
+ grad = fn(dev.execute(tapes))
expected = np.array(
[
0.5 * np.cos(b / 2) * np.sin(0.5 * (a + c)),
@@ -762,7 +763,7 @@ def test_CRot_gradient(self, theta):
assert np.allclose(g, expected[idx], atol=shot_vec_tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- numeric_val = fn(dev.batch_execute(tapes))
+ numeric_val = fn(dev.execute(tapes))
for a_val, n_val in zip(grad, numeric_val):
assert np.allclose(a_val, n_val, atol=finite_diff_tol, rtol=0)
@@ -842,10 +843,12 @@ def test_variance_gradients_agree_finite_differences(self):
assert np.allclose(g, grad_F2[idx1][idx2], atol=finite_diff_tol, rtol=0)
@pytest.mark.autograd
- def test_fallback(self, mocker):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_fallback(self, dev_name, mocker):
"""Test that fallback gradient functions are correctly used"""
spy = mocker.spy(qml.gradients, "finite_diff")
- dev = qml.device("default.qubit.autograd", wires=3, shots=fallback_shot_vec)
+ dev = qml.device(dev_name, wires=3, shots=fallback_shot_vec)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -869,7 +872,7 @@ def cost_fn(params):
spy.assert_called()
assert spy.call_args[1]["argnum"] == {1}
- return fn(dev.batch_execute(tapes))
+ return fn(execute_fn(tapes))
all_res = cost_fn(params)
@@ -898,11 +901,13 @@ def cost_fn(params):
# assert np.allclose(jac[1, 1, 1], -2 * np.cos(2 * y), atol=shot_vec_tol, rtol=0)
@pytest.mark.autograd
- def test_fallback_single_meas(self, mocker):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_fallback_single_meas(self, dev_name, mocker):
"""Test that fallback gradient functions are correctly used for a single measurement."""
spy = mocker.spy(qml.gradients, "finite_diff")
shot_vec = tuple([1000000] * 4)
- dev = qml.device("default.qubit.autograd", wires=3, shots=shot_vec)
+ dev = qml.device(dev_name, wires=3, shots=shot_vec)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -923,7 +928,7 @@ def cost_fn(params):
spy.assert_called()
assert spy.call_args[1]["argnum"] == {1}
- return fn(dev.batch_execute(tapes))
+ return fn(execute_fn(tapes))
all_res = cost_fn(params)
@@ -941,10 +946,14 @@ def cost_fn(params):
@pytest.mark.autograd
@pytest.mark.parametrize("RX, RY, argnum", [(RX_with_F, qml.RY, 0), (qml.RX, RY_with_F, 1)])
- def test_fallback_probs(self, RX, RY, argnum, mocker):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_fallback_probs(
+ self, dev_name, RX, RY, argnum, mocker
+ ): # pylint:disable=too-many-arguments
"""Test that fallback gradient functions are correctly used with probs"""
spy = mocker.spy(qml.gradients, "finite_diff")
- dev = qml.device("default.qubit.autograd", wires=3, shots=fallback_shot_vec)
+ dev = qml.device(dev_name, wires=3, shots=fallback_shot_vec)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -967,7 +976,7 @@ def cost_fn(params):
spy.assert_called()
assert spy.call_args[1]["argnum"] == {argnum}
- return fn(dev.batch_execute(tapes))
+ return fn(execute_fn(tapes))
all_res = cost_fn(params)
assert isinstance(all_res, tuple)
@@ -1028,13 +1037,15 @@ def cost_fn(params):
assert np.allclose(res[1][1], probs_expected[:, 1], atol=finite_diff_tol)
@pytest.mark.autograd
- def test_all_fallback(self, mocker):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_all_fallback(self, dev_name, mocker):
"""Test that *only* the fallback logic is called if no parameters
support the parameter-shift rule"""
spy_fd = mocker.spy(qml.gradients, "finite_diff")
spy_ps = mocker.spy(qml.gradients.parameter_shift, "expval_param_shift")
- dev = qml.device("default.qubit.autograd", wires=3, shots=fallback_shot_vec)
+ dev = qml.device(dev_name, wires=3, shots=fallback_shot_vec)
+ execute_fn = dev.execute if dev_name == "default.qubit" else dev.batch_execute
x = 0.543
y = -0.654
@@ -1053,7 +1064,7 @@ def test_all_fallback(self, mocker):
spy_fd.assert_called()
spy_ps.assert_not_called()
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(execute_fn(tapes))
assert len(all_res) == len(fallback_shot_vec)
assert isinstance(all_res, tuple)
@@ -1085,7 +1096,7 @@ def test_single_expectation_value(self):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 4
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1118,7 +1129,7 @@ def test_multiple_expectation_values(self):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 4
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1151,7 +1162,7 @@ def test_var_expectation_values(self):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 5
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1185,7 +1196,7 @@ def test_prob_expectation_values(self):
tapes, fn = qml.gradients.param_shift(tape)
assert len(tapes) == 4
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == len(many_shots_shot_vector)
@@ -1272,7 +1283,7 @@ def test_involutory_variance_single_param(self):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
for _gA in gradA:
assert isinstance(_gA, np.ndarray)
assert _gA.shape == ()
@@ -1280,7 +1291,7 @@ def test_involutory_variance_single_param(self):
assert len(tapes) == 1 + 2 * 1
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- all_gradF = fn(dev.batch_execute(tapes))
+ all_gradF = fn(dev.execute(tapes))
assert len(tapes) == 2
expected = 2 * np.sin(a) * np.cos(a)
@@ -1312,7 +1323,7 @@ def test_involutory_variance_multi_param(self):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1326,7 +1337,7 @@ def test_involutory_variance_multi_param(self):
assert len(tapes) == 1 + 2 * 2
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- all_Fres = fn(dev.batch_execute(tapes))
+ all_Fres = fn(dev.execute(tapes))
for gradF, gradA in zip(all_Fres, all_res):
assert len(tapes) == 3
@@ -1359,11 +1370,11 @@ def test_non_involutory_variance_single_param(self):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert len(tapes) == 1 + 4 * 1
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- all_gradF = fn(dev.batch_execute(tapes))
+ all_gradF = fn(dev.execute(tapes))
assert len(tapes) == 2
expected = -35 * np.sin(2 * a) - 12 * np.cos(2 * a)
@@ -1401,7 +1412,7 @@ def test_non_involutory_variance_multi_param(self):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1419,7 +1430,7 @@ def test_non_involutory_variance_multi_param(self):
assert gradA[1] == pytest.approx(expected, abs=herm_shot_vec_tol)
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- all_gradF = fn(dev.batch_execute(tapes))
+ all_gradF = fn(dev.execute(tapes))
assert len(all_gradF) == len(many_shots_shot_vector)
assert isinstance(all_gradF, tuple)
for gradF in all_gradF:
@@ -1456,11 +1467,11 @@ def test_involutory_and_noninvolutory_variance_single_param(self):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert len(tapes) == 1 + 4
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 1 + 1
expected = [2 * np.sin(a) * np.cos(a), 0]
@@ -1507,7 +1518,7 @@ def test_involutory_and_noninvolutory_variance_multi_param(self):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- gradA = fn(dev.batch_execute(tapes))
+ gradA = fn(dev.execute(tapes))
assert isinstance(gradA, tuple)
assert len(gradA) == len(many_shots_shot_vector)
@@ -1524,7 +1535,7 @@ def test_involutory_and_noninvolutory_variance_multi_param(self):
assert len(tapes) == 1 + 2 * 4
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- gradF = fn(dev.batch_execute(tapes))
+ gradF = fn(dev.execute(tapes))
assert len(tapes) == 1 + 2
expected = [2 * np.sin(a) * np.cos(a), 0, 0, -35 * np.sin(2 * a) - 12 * np.cos(2 * a)]
@@ -1590,7 +1601,7 @@ def test_var_and_probs_single_param(self, ind):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1647,7 +1658,7 @@ def test_var_and_probs_multi_params(self):
# circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1750,7 +1761,7 @@ def test_expval_and_variance_single_param(self):
# # circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1764,7 +1775,7 @@ def test_expval_and_variance_single_param(self):
assert np.allclose(a_comp, e_comp, atol=shot_vec_tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- all_gradF = fn(dev.batch_execute(tapes))
+ all_gradF = fn(dev.execute(tapes))
assert isinstance(all_gradF, tuple)
for gradF in all_gradF:
@@ -1806,7 +1817,7 @@ def test_expval_and_variance_multi_param(self):
# # circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1831,7 +1842,7 @@ def test_expval_and_variance_multi_param(self):
assert np.allclose(a_comp, e_comp, atol=shot_vec_tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- all_gradF = fn(dev.batch_execute(tapes))
+ all_gradF = fn(dev.execute(tapes))
for gradF in all_gradF:
assert gradF == pytest.approx(expected, abs=finite_diff_tol)
@@ -1861,7 +1872,7 @@ def test_projector_variance(self, state):
# # circuit jacobians
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == len(many_shots_shot_vector)
assert isinstance(all_res, tuple)
@@ -1876,7 +1887,7 @@ def test_projector_variance(self, state):
assert np.allclose(gradA, expected, atol=shot_vec_tol, rtol=0)
tapes, fn = qml.gradients.finite_diff(tape, h=h_val)
- all_gradF = fn(dev.batch_execute(tapes))
+ all_gradF = fn(dev.execute(tapes))
for gradF in all_gradF:
assert gradF == pytest.approx(expected, abs=finite_diff_tol)
@@ -2074,7 +2085,7 @@ def test_multi_measure_no_warning(self):
tape = qml.tape.QuantumScript.from_queue(q, shots=shot_vec)
with warnings.catch_warnings(record=True) as record:
tapes, fn = qml.gradients.param_shift(tape)
- fn(dev.batch_execute(tapes))
+ fn(dev.execute(tapes))
assert len(record) == 0
@@ -2132,7 +2143,7 @@ def test_no_trainable_coeffs(self, mocker, broadcast, tol):
x, y = weights
tape.trainable_params = {0, 1}
- res = dev.batch_execute([tape])
+ res = dev.execute([tape])
expected = -c * np.sin(x) * np.sin(y) + np.cos(x) * (a + b * np.sin(y))
assert np.allclose(res, expected, atol=shot_vec_tol, rtol=0)
@@ -2142,7 +2153,7 @@ def test_no_trainable_coeffs(self, mocker, broadcast, tol):
assert [t.batch_size for t in tapes] == ([2, 2] if broadcast else [None] * 4)
spy.assert_not_called()
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert isinstance(all_res, tuple)
assert len(all_res) == len(many_shots_shot_vector)
@@ -2183,7 +2194,7 @@ def test_trainable_coeffs(self, mocker, broadcast, tol):
x, y = weights
tape.trainable_params = {0, 1, 2, 4}
- res = dev.batch_execute([tape])
+ res = dev.execute([tape])
expected = -c * np.sin(x) * np.sin(y) + np.cos(x) * (a + b * np.sin(y))
assert np.allclose(res, expected, atol=tol, rtol=0)
@@ -2194,7 +2205,7 @@ def test_trainable_coeffs(self, mocker, broadcast, tol):
assert [t.batch_size for t in tapes] == ([2, 2, None, None] if broadcast else [None] * 6)
spy.assert_called()
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 4
assert res[0].shape == ()
@@ -2243,7 +2254,7 @@ def test_multiple_hamiltonians(self, mocker, broadcast, tol):
tape = qml.tape.QuantumScript.from_queue(q, shots=shot_vec)
tape.trainable_params = {0, 1, 2, 4, 5}
- res = dev.batch_execute([tape])
+ res = dev.execute([tape])
expected = [-c * np.sin(x) * np.sin(y) + np.cos(x) * (a + b * np.sin(y)), d * np.cos(x)]
assert np.allclose(res, expected, atol=tol, rtol=0)
@@ -2258,7 +2269,7 @@ def test_multiple_hamiltonians(self, mocker, broadcast, tol):
assert len(tapes) == 2 * 2 + 3
spy.assert_called()
- res = fn(dev.batch_execute(tapes))
+ res = fn(dev.execute(tapes))
assert isinstance(res, tuple)
assert len(res) == 2
assert len(res[0]) == 5
@@ -2296,7 +2307,8 @@ def cost_fn(weights, coeffs1, coeffs2, dev=None, broadcast=False):
tape = qml.tape.QuantumScript.from_queue(q, shots=dev.shots)
tape.trainable_params = {0, 1, 2, 3, 4, 5}
tapes, fn = qml.gradients.param_shift(tape, broadcast=broadcast)
- return fn(dev.batch_execute(tapes))
+ execute_fn = dev.batch_execute if isinstance(dev, qml.Device) else dev.execute
+ return fn(execute_fn(tapes))
@staticmethod
def cost_fn_expected(weights, coeffs1, coeffs2):
@@ -2318,14 +2330,15 @@ def cost_fn_expected(weights, coeffs1, coeffs2):
@pytest.mark.xfail(reason="TODO")
@pytest.mark.autograd
- def test_autograd(self, broadcast, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd(self, dev_name, broadcast, tol):
"""Test gradient of multiple trainable Hamiltonian coefficients
using autograd"""
coeffs1 = np.array([0.1, 0.2, 0.3], requires_grad=True)
coeffs2 = np.array([0.7], requires_grad=True)
weights = np.array([0.4, 0.5], requires_grad=True)
shot_vec = many_shots_shot_vector
- dev = qml.device("default.qubit.autograd", wires=2, shots=shot_vec)
+ dev = qml.device(dev_name, wires=2, shots=shot_vec)
if broadcast:
with pytest.raises(
@@ -2346,7 +2359,8 @@ def test_autograd(self, broadcast, tol):
@pytest.mark.xfail(reason="TODO")
@pytest.mark.tf
- def test_tf(self, broadcast, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_tf(self, dev_name, broadcast, tol):
"""Test gradient of multiple trainable Hamiltonian coefficients
using tf"""
import tensorflow as tf
@@ -2356,7 +2370,7 @@ def test_tf(self, broadcast, tol):
weights = tf.Variable([0.4, 0.5], dtype=tf.float64)
shot_vec = many_shots_shot_vector
- dev = qml.device("default.qubit.tf", wires=2, shots=shot_vec)
+ dev = qml.device(dev_name, wires=2, shots=shot_vec)
if broadcast:
with pytest.raises(
@@ -2383,7 +2397,8 @@ def test_tf(self, broadcast, tol):
# TODO: Torch support for param-shift
@pytest.mark.torch
@pytest.mark.xfail
- def test_torch(self, broadcast, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_torch(self, dev_name, broadcast, tol):
"""Test gradient of multiple trainable Hamiltonian coefficients
using torch"""
import torch
@@ -2392,7 +2407,7 @@ def test_torch(self, broadcast, tol):
coeffs2 = torch.tensor([0.7], dtype=torch.float64, requires_grad=True)
weights = torch.tensor([0.4, 0.5], dtype=torch.float64, requires_grad=True)
- dev = qml.device("default.qubit.torch", wires=2)
+ dev = qml.device(dev_name, wires=2)
if broadcast:
with pytest.raises(
@@ -2413,9 +2428,9 @@ def test_torch(self, broadcast, tol):
assert np.allclose(hess[1][:, 2:5], np.zeros([2, 3, 3]), atol=tol, rtol=0)
assert np.allclose(hess[2][:, -1], np.zeros([2, 1, 1]), atol=tol, rtol=0)
- @pytest.mark.xfail(reason="TODO")
@pytest.mark.jax
- def test_jax(self, broadcast, tol):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_jax(self, dev_name, broadcast, tol):
"""Test gradient of multiple trainable Hamiltonian coefficients
using JAX"""
import jax
@@ -2425,7 +2440,7 @@ def test_jax(self, broadcast, tol):
coeffs1 = jnp.array([0.1, 0.2, 0.3])
coeffs2 = jnp.array([0.7])
weights = jnp.array([0.4, 0.5])
- dev = qml.device("default.qubit.jax", wires=2)
+ dev = qml.device(dev_name, wires=2)
if broadcast:
with pytest.raises(
@@ -2516,7 +2531,7 @@ def test_1_1(self, shot_vec, meas, shape, op_wires):
tape.trainable_params = {0}
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -2550,7 +2565,7 @@ def test_1_N(self, shot_vec, op_wire):
tape.trainable_params = {0}
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -2584,7 +2599,7 @@ def test_N_1(self, shot_vec, meas, shape, op_wires):
tape.trainable_params = {0, 1}
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
@@ -2624,7 +2639,7 @@ def test_N_N(self, shot_vec, op_wires):
tape.trainable_params = {0, 1, 2, 3, 4}
tapes, fn = qml.gradients.param_shift(tape)
- all_res = fn(dev.batch_execute(tapes))
+ all_res = fn(dev.execute(tapes))
assert len(all_res) == grad_transform_shots.num_copies
assert isinstance(all_res, tuple)
diff --git a/tests/logging/test_logging_autograd.py b/tests/logging/test_logging_autograd.py
index e278e674c1b..6dcafffb439 100644
--- a/tests/logging/test_logging_autograd.py
+++ b/tests/logging/test_logging_autograd.py
@@ -21,7 +21,7 @@
_grad_log_map = {
- "adjoint": "gradient_fn=device, interface=autograd, grad_on_execution=best, gradient_kwargs={'use_device_state': True, 'method': 'adjoint_jacobian'}",
+ "adjoint": "gradient_fn=adjoint, interface=autograd, grad_on_execution=best, gradient_kwargs={}",
"backprop": "gradient_fn=backprop, interface=autograd, grad_on_execution=best, gradient_kwargs={}",
"parameter-shift": "gradient_fn=,)",
- _grad_log_map[diff_method[0]],
+ _grad_log_map[diff_method],
],
),
]
- for idx, r in enumerate(caplog.records[0:2]):
- assert log_records_expected[idx][0] in r.name
- for msg in log_records_expected[idx][1]:
- assert msg in r.getMessage()
+ for expected, actual in zip(log_records_expected, caplog.records[:2]):
+ assert expected[0] in actual.name
+ assert all(msg in actual.getMessage() for msg in expected[1])
diff --git a/tests/math/test_functions.py b/tests/math/test_functions.py
index 5dceb524562..ddf8bffcc28 100644
--- a/tests/math/test_functions.py
+++ b/tests/math/test_functions.py
@@ -2569,11 +2569,17 @@ class TestSize:
([[0], [1], [2], [3], [4], [5]], 6),
]
- @pytest.mark.torch
+ @pytest.mark.parametrize(
+ "interface",
+ [
+ pytest.param("torch", marks=pytest.mark.torch),
+ pytest.param("tensorflow", marks=pytest.mark.tf),
+ ],
+ )
@pytest.mark.parametrize(("array", "size"), array_and_size)
- def test_size_torch(self, array, size):
- """Test size function with the torch interface."""
- r = fn.size(torch.tensor(array))
+ def test_size_torch_and_tf(self, array, size, interface):
+ """Test size function with the torch and tf interfaces."""
+ r = fn.size(fn.asarray(array, like=interface))
assert r == size
diff --git a/tests/measurements/test_classical_shadow.py b/tests/measurements/test_classical_shadow.py
index d67967c2ff9..47fb06f2b02 100644
--- a/tests/measurements/test_classical_shadow.py
+++ b/tests/measurements/test_classical_shadow.py
@@ -340,7 +340,6 @@ def test_return_distribution(self, wires, interface, circuit_fn, basis_recipe):
ratios2 = np.unique(bits2, return_counts=True)[1] / bits2.shape[0]
assert np.allclose(ratios2, 1 / 2, atol=1e-1)
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize("seed", seed_recipes_list)
def test_shots_none_error(self, wires, seed):
"""Test that an error is raised when a device with shots=None is used
@@ -351,7 +350,6 @@ def test_shots_none_error(self, wires, seed):
with pytest.raises(qml.DeviceError, match=msg):
circuit()
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize("shots", shots_list)
def test_multi_measurement_error(self, wires, shots):
"""Test that an error is raised when classical shadows is returned
@@ -458,7 +456,6 @@ def test_measurement_process_copy(self):
assert copied_res.k == res.k
assert copied_res.seed == res.seed
- @pytest.mark.xfail(reason="until DQ2 port")
def test_shots_none_error(self):
"""Test that an error is raised when a device with shots=None is used
to obtain classical shadows"""
@@ -469,7 +466,6 @@ def test_shots_none_error(self):
with pytest.raises(qml.DeviceError, match=msg):
_ = circuit(H, k=10)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_multi_measurement_allowed(self):
"""Test that no error is raised when classical shadows is returned
with other measurement processes"""
diff --git a/tests/measurements/test_measurements.py b/tests/measurements/test_measurements.py
index 358a72fb2ab..945ace9dd5a 100644
--- a/tests/measurements/test_measurements.py
+++ b/tests/measurements/test_measurements.py
@@ -492,7 +492,6 @@ def circuit():
assert qml.math.allequal(circuit(), [1000, 0])
- @pytest.mark.xfail(reason="until DQ2 port")
def test_sample_measurement_without_shots(self):
"""Test that executing a sampled measurement with ``shots=None`` raises an error."""
@@ -537,7 +536,6 @@ def circuit():
assert circuit() == 1
- @pytest.mark.xfail(reason="until DQ2 port")
def test_state_measurement_with_shots(self):
"""Test that executing a state measurement with shots raises an error."""
@@ -562,13 +560,13 @@ def circuit():
class TestMeasurementTransform:
"""Tests for the MeasurementTransform class."""
- @pytest.mark.xfail(reason="until DQ2 port")
def test_custom_measurement(self):
"""Test the execution of a custom measurement."""
class CountTapesMP(MeasurementTransform, SampleMeasurement):
def process(self, tape, device):
- tapes, _, _ = device.preprocess(tape)
+ program, _ = device.preprocess()
+ tapes, _ = program([tape])
return len(tapes)
def process_samples(self, samples, wire_order, shot_range=None, bin_size=None):
diff --git a/tests/measurements/test_mutual_info.py b/tests/measurements/test_mutual_info.py
index e266d1e9df4..0424b97fd8a 100644
--- a/tests/measurements/test_mutual_info.py
+++ b/tests/measurements/test_mutual_info.py
@@ -109,7 +109,6 @@ def circuit():
res = circuit()
assert np.allclose(res, expected, atol=1e-6)
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize("shots", [1000, [1, 10, 10, 1000]])
def test_finite_shots_error(self, shots):
"""Test an error is raised when using shot vectors with mutual_info."""
@@ -491,7 +490,6 @@ def circuit(params):
with pytest.raises(qml.QuantumFunctionError, match=msg):
circuit(params)
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.all_interfaces
@pytest.mark.parametrize("interface", ["autograd", "jax", "tensorflow", "torch"])
@pytest.mark.parametrize("params", [np.array([0.0, 0.0]), np.array([0.3, 0.4])])
diff --git a/tests/measurements/test_probs.py b/tests/measurements/test_probs.py
index 8365de213eb..8ad640b3efd 100644
--- a/tests/measurements/test_probs.py
+++ b/tests/measurements/test_probs.py
@@ -618,7 +618,6 @@ def test_estimate_probability_with_binsize_with_broadcasting(self, wires, expect
assert np.allclose(res, expected)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_non_commuting_probs_does_not_raises_error(self):
"""Tests that non-commuting probs with expval does not raise an error."""
dev = qml.device("default.qubit", wires=5)
diff --git a/tests/measurements/test_sample.py b/tests/measurements/test_sample.py
index 7a5a01ac713..ef40ca86b4b 100644
--- a/tests/measurements/test_sample.py
+++ b/tests/measurements/test_sample.py
@@ -46,7 +46,6 @@ def circuit():
(n_sample,) if not n_sample == 1 else ()
)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_sample_combination(self):
"""Test the output of combining expval, var and sample"""
n_sample = 10
diff --git a/tests/measurements/test_state.py b/tests/measurements/test_state.py
index a24c648052e..ab306b5b01e 100644
--- a/tests/measurements/test_state.py
+++ b/tests/measurements/test_state.py
@@ -250,22 +250,19 @@ def test_process_state_matrix_from_matrix(self, mat, wires):
class TestState:
"""Tests for the state function"""
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize("wires", range(2, 5))
- @pytest.mark.parametrize("op,dtype", [(qml.PauliX, np.float64), (qml.PauliY, np.complex128)])
- def test_state_shape_and_dtype(self, op, dtype, wires):
+ def test_state_shape_and_dtype(self, wires):
"""Test that the state is of correct size and dtype for a trivial circuit"""
dev = qml.device("default.qubit", wires=wires)
@qml.qnode(dev)
def func():
- op(0)
return state()
state_val = func()
assert state_val.shape == (2**wires,)
- assert state_val.dtype == dtype
+ assert state_val.dtype == np.complex128
def test_return_type_is_state(self):
"""Test that the return type of the observable is State"""
@@ -300,7 +297,6 @@ def func():
assert np.allclose(state_val[0], 1 / np.sqrt(2))
assert np.allclose(state_val[-1], 1 / np.sqrt(2))
- @pytest.mark.xfail(reason="until DQ2 port")
def test_return_with_other_types_works(self):
"""Test that no exception is raised when a state is returned along with another return
type"""
@@ -317,7 +313,6 @@ def func():
assert np.allclose(res[0], np.array([1, 0, 1, 0]) / np.sqrt(2))
assert np.isclose(res[1], 1)
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize("wires", range(2, 5))
def test_state_equal_to_expected_state(self, wires):
"""Test that the returned state is equal to the expected state for a template circuit"""
@@ -334,14 +329,14 @@ def func():
return state()
state_val = func()
- scripts, _, _ = dev.preprocess(func.tape)
+ program, _ = dev.preprocess()
+ scripts, _ = program([func.tape])
assert len(scripts) == 1
expected_state, _ = qml.devices.qubit.get_final_state(scripts[0])
assert np.allclose(state_val, expected_state.flatten())
@pytest.mark.tf
- @pytest.mark.parametrize("op", [qml.PauliX, qml.PauliY])
- def test_interface_tf(self, op):
+ def test_interface_tf(self):
"""Test that the state correctly outputs in the tensorflow interface"""
import tensorflow as tf
@@ -349,8 +344,6 @@ def test_interface_tf(self, op):
@qml.qnode(dev, interface="tf")
def func():
- op(0)
- op(0)
for i in range(4):
qml.Hadamard(i)
return state()
@@ -359,14 +352,12 @@ def func():
state_val = func()
assert isinstance(state_val, tf.Tensor)
- assert state_val.dtype == tf.complex128 if op is qml.PauliY else tf.float64
+ assert state_val.dtype == tf.complex128
assert np.allclose(state_expected, state_val.numpy())
assert state_val.shape == (16,)
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.torch
- @pytest.mark.parametrize("op", [qml.PauliX, qml.PauliY])
- def test_interface_torch(self, op):
+ def test_interface_torch(self):
"""Test that the state correctly outputs in the torch interface"""
import torch
@@ -374,13 +365,11 @@ def test_interface_torch(self, op):
@qml.qnode(dev, interface="torch")
def func():
- op(0)
- op(0)
for i in range(4):
qml.Hadamard(i)
return state()
- dtype = torch.complex128 if op is qml.PauliY else torch.float64
+ dtype = torch.complex128
state_expected = 0.25 * torch.ones(16, dtype=dtype)
state_val = func()
@@ -596,11 +585,9 @@ class TestDensityMatrix:
# pylint: disable=too-many-public-methods
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize("wires", range(2, 5))
@pytest.mark.parametrize("dev_name", ["default.qubit", "default.mixed"])
- @pytest.mark.parametrize("op,dtype", [(qml.PauliX, np.float64), (qml.PauliY, np.complex128)])
- def test_density_matrix_shape_and_dtype(self, dev_name, op, dtype, wires):
+ def test_density_matrix_shape_and_dtype(self, dev_name, wires):
"""Test that the density matrix is of correct size and dtype for a
trivial circuit"""
@@ -608,13 +595,12 @@ def test_density_matrix_shape_and_dtype(self, dev_name, op, dtype, wires):
@qml.qnode(dev)
def circuit():
- op(0)
return density_matrix([0])
state_val = circuit()
assert state_val.shape == (2, 2)
- assert state_val.dtype == dtype if dev_name == "default.qubit" else np.complex128
+ assert state_val.dtype == np.complex128
@pytest.mark.parametrize("dev_name", ["default.qubit", "default.mixed"])
def test_return_type_is_state(self, dev_name):
@@ -681,7 +667,6 @@ def func():
assert np.allclose(expected, density_mat)
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.tf
@pytest.mark.parametrize("diff_method", [None, "backprop"])
def test_correct_density_matrix_tf_default_qubit(self, diff_method):
@@ -720,7 +705,6 @@ def func():
assert np.allclose(expected, density_first)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_correct_density_matrix_product_state_first_default_qubit(self):
"""Test that the correct density matrix is returned when
tracing out a product state"""
@@ -758,7 +742,6 @@ def func():
expected = np.array([[0.5 + 0.0j, 0.5 + 0.0j], [0.5 + 0.0j, 0.5 + 0.0j]])
assert np.allclose(expected, density_second)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_correct_density_matrix_product_state_second_default_qubit(self):
"""Test that the correct density matrix is returned when
tracing out a product state"""
@@ -800,7 +783,6 @@ def func():
assert np.allclose(expected, density_both)
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize("return_wire_order", ([0, 1], [1, 0]))
def test_correct_density_matrix_product_state_both_default_qubit(self, return_wire_order):
"""Test that the correct density matrix is returned
@@ -851,7 +833,6 @@ def func():
)
assert np.allclose(expected, density_full)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_correct_density_matrix_three_wires_first_two_default_qubit(self):
"""Test that the correct density matrix is returned for an example with three wires,
and tracing out the third wire."""
@@ -938,7 +919,6 @@ def func():
expected = np.outer(exp_statevector.conj(), exp_statevector)
assert np.allclose(expected, density_full)
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize(
"return_wire_order", ([0], [1], [2], [0, 1], [1, 0], [0, 2], [2, 0], [1, 2, 0], [2, 1, 0])
)
@@ -1016,7 +996,6 @@ def func():
assert np.allclose(expected, density)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_correct_density_matrix_all_wires_default_qubit(self):
"""Test that the correct density matrix is returned when all wires are given"""
@@ -1044,7 +1023,6 @@ def func():
qml.density_matrix(wires=[0, 1]).process_state(state=dev_state, wire_order=dev.wires),
)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_return_with_other_types_works(self):
"""Test that no exception is raised when a state is returned along with another return
type"""
diff --git a/tests/measurements/test_vn_entropy.py b/tests/measurements/test_vn_entropy.py
index 432447227fe..b8dc7830ccf 100644
--- a/tests/measurements/test_vn_entropy.py
+++ b/tests/measurements/test_vn_entropy.py
@@ -136,7 +136,6 @@ class TestIntegration:
diff_methods = ["backprop", "finite-diff"]
- @pytest.mark.xfail(reason="until DQ2 port")
@pytest.mark.parametrize("shots", [1000, [1, 10, 10, 1000]])
def test_finite_shots_error(self, shots):
"""Test an error is raised when using shot vectors with vn_entropy."""
@@ -392,7 +391,6 @@ def circuit_entropy(x):
assert qml.math.allclose(grad_entropy, grad_expected_entropy, rtol=1e-04, atol=1e-05)
- @pytest.mark.xfail(reason="until DQ2 port")
def test_qnode_entropy_custom_wires(self):
"""Test that entropy can be returned with custom wires."""
diff --git a/tests/ops/functions/test_map_wires.py b/tests/ops/functions/test_map_wires.py
index 90115b50b7e..785364faf2e 100644
--- a/tests/ops/functions/test_map_wires.py
+++ b/tests/ops/functions/test_map_wires.py
@@ -54,7 +54,7 @@ def test_map_wires_with_operator(self):
op = build_op()
m_op = qml.map_wires(op, wire_map=wire_map)
- assert isinstance(m_op, qml.ops.Prod)
+ assert isinstance(m_op, qml.ops.Prod) # pylint:disable=no-member
assert m_op.data == mapped_op.data
assert m_op.wires == mapped_op.wires
assert m_op.arithmetic_depth == mapped_op.arithmetic_depth
@@ -112,13 +112,13 @@ def test_map_wires_tape(self, shots):
assert len(s_tape) == 1
assert s_tape.trainable_params == [0, 2]
s_op = s_tape[0]
- assert isinstance(s_op, qml.ops.Prod)
+ assert isinstance(s_op, qml.ops.Prod) # pylint:disable=no-member
assert s_op.data == mapped_op.data
assert s_op.wires == mapped_op.wires
assert s_op.arithmetic_depth == mapped_op.arithmetic_depth
assert tape.shots == s_tape.shots
- @pytest.mark.parametrize("shots", [None, 100])
+ @pytest.mark.parametrize("shots", [None, 5000])
def test_execute_mapped_tape(self, shots):
"""Test the execution of a mapped tape."""
dev = qml.device("default.qubit", wires=5)
@@ -134,13 +134,10 @@ def test_execute_mapped_tape(self, shots):
assert m_tape._qfunc_output is tape._qfunc_output # pylint: disable=protected-access
m_op = m_tape.operations[0]
m_obs = m_tape.observables[0]
- assert isinstance(m_op, qml.ops.Prod)
- assert m_op.data == mapped_op.data
- assert m_op.wires == mapped_op.wires
- assert m_op.arithmetic_depth == mapped_op.arithmetic_depth
+ assert qml.equal(m_op, mapped_op)
assert tape.shots == m_tape.shots
assert m_obs.wires == Wires(wire_map[1])
- assert qml.math.allclose(dev.execute(tape), dev.execute(m_tape))
+ assert qml.math.allclose(dev.execute(tape), dev.execute(m_tape), atol=0.05)
class TestMapWiresQNodes:
@@ -153,23 +150,18 @@ def test_map_wires_qnode(self):
@qml.qnode(dev)
def qnode():
build_op()
- return qml.expval(op=build_op())
+ return qml.expval(qml.prod(qml.PauliX(0), qml.PauliY(1), qml.PauliZ(2)))
# TODO: Use qml.equal when supported
+ mapped_obs = qml.prod(qml.PauliX(4), qml.PauliY(3), qml.PauliZ(2))
m_qnode = qml.map_wires(qnode, wire_map=wire_map)
assert m_qnode() == qnode()
assert len(m_qnode.tape) == 2
m_op = m_qnode.tape.operations[0]
m_obs = m_qnode.tape.observables[0]
- assert isinstance(m_op, qml.ops.Prod)
- assert m_op.data == mapped_op.data
- assert m_op.wires == mapped_op.wires
- assert m_op.arithmetic_depth == mapped_op.arithmetic_depth
- assert isinstance(m_obs, qml.ops.Prod)
- assert m_obs.data == mapped_op.data
- assert m_obs.wires == mapped_op.wires
- assert m_obs.arithmetic_depth == mapped_op.arithmetic_depth
+ assert qml.equal(m_op, mapped_op)
+ assert qml.equal(m_obs, mapped_obs)
class TestMapWiresCallables:
diff --git a/tests/ops/op_math/test_exp.py b/tests/ops/op_math/test_exp.py
index 2e2848b8987..9e24dcebfca 100644
--- a/tests/ops/op_math/test_exp.py
+++ b/tests/ops/op_math/test_exp.py
@@ -647,7 +647,7 @@ def test_repr_tensor(self):
def test_repr_deep_operator(self):
"""Test the __repr__ method when the base is any operator with arithmetic depth > 0."""
base = qml.S(0) @ qml.PauliX(0)
- op = qml.ops.Exp(base, 3)
+ op = qml.ops.Exp(base, 3) # pylint:disable=no-member
assert repr(op) == "Exp(3 S(wires=[0]) @ PauliX(wires=[0]))"
@@ -797,7 +797,7 @@ def circuit(phi):
res = circuit(phi)
assert qml.math.allclose(res, torch.cos(phi))
- res.backward()
+ res.backward() # pylint:disable=no-member
assert qml.math.allclose(phi.grad, -torch.sin(phi))
@pytest.mark.autograd
@@ -872,7 +872,7 @@ def circuit(x):
expected = 0.5 * (torch.exp(x) + torch.exp(-x))
assert qml.math.allclose(res, expected)
- res.backward()
+ res.backward() # pylint:disable=no-member
expected_grad = 0.5 * (torch.exp(x) - torch.exp(-x))
assert qml.math.allclose(x.grad, expected_grad)
@@ -901,9 +901,10 @@ def circuit(x):
@pytest.mark.tf
def test_tf_measurement(self):
"""Test Exp in a measurement with gradient and tensorflow."""
+ # pylint:disable=invalid-unary-operand-type
import tensorflow as tf
- x = tf.Variable(2.0)
+ x = tf.Variable(2.0, dtype=tf.float64)
@qml.qnode(qml.device("default.qubit", wires=1))
def circuit(x):
@@ -1011,7 +1012,7 @@ def test_parameter_frequency_with_parameters_in_base_operator(self):
op2 = Evolution(base_op, 1)
with pytest.raises(ParameterFrequenciesUndefinedError):
- op1.parameter_frequencies()
+ _ = op1.parameter_frequencies
assert op2.parameter_frequencies == [(4.0,)]
diff --git a/tests/ops/op_math/test_prod.py b/tests/ops/op_math/test_prod.py
index 6db76b23dab..07a5bd4644a 100644
--- a/tests/ops/op_math/test_prod.py
+++ b/tests/ops/op_math/test_prod.py
@@ -758,6 +758,7 @@ def test_is_hermitian(self, ops_lst, hermitian_status):
@pytest.mark.tf
def test_is_hermitian_tf(self):
"""Test that is_hermitian works when a tf type scalar is provided."""
+ # pylint:disable=invalid-unary-operand-type
import tensorflow as tf
theta = tf.Variable(1.23)
@@ -965,7 +966,7 @@ def test_simplify_method_product_of_sums(self):
qml.RX(1, 0) @ qml.RX(1, 1),
)
simplified_op = prod_op.simplify()
- assert isinstance(simplified_op, qml.ops.Sum)
+ assert isinstance(simplified_op, qml.ops.Sum) # pylint:disable=no-member
for s1, s2 in zip(final_op.operands, simplified_op.operands):
assert s1.name == s2.name
assert s1.wires == s2.wires
@@ -1016,7 +1017,7 @@ def test_simplify_method_with_nested_ops(self):
qml.s_prod(5, qml.PauliX(1)),
)
simplified_op = prod_op.simplify()
- assert isinstance(simplified_op, qml.ops.Sum)
+ assert isinstance(simplified_op, qml.ops.Sum) # pylint:disable=no-member
for s1, s2 in zip(final_op.operands, simplified_op.operands):
assert s1.name == s2.name
assert s1.wires.toset() == s2.wires.toset()
@@ -1050,7 +1051,7 @@ def test_simplify_method_with_pauli_words(self):
# TODO: Use qml.equal when supported for nested operators
- assert isinstance(simplified_op, qml.ops.Sum)
+ assert isinstance(simplified_op, qml.ops.Sum) # pylint:disable=no-member
for s1, s2 in zip(final_op.operands, simplified_op.operands):
assert repr(s1) == repr(s2)
assert s1.name == s2.name
@@ -1100,7 +1101,7 @@ def test_grouping_with_product_of_sum(self):
final_op = qml.sum(qml.s_prod(1j, qml.PauliX(0)), qml.s_prod(-1, qml.PauliZ(0)))
simplified_op = prod_op.simplify()
- assert isinstance(simplified_op, qml.ops.Sum)
+ assert isinstance(simplified_op, qml.ops.Sum) # pylint:disable=no-member
for s1, s2 in zip(final_op.operands, simplified_op.operands):
assert s1.name == s2.name
assert s1.wires == s2.wires
@@ -1116,7 +1117,7 @@ def test_grouping_with_product_of_sums(self):
qml.S(wires=[1]),
)
simplified_op = prod_op.simplify()
- assert isinstance(simplified_op, qml.ops.Sum)
+ assert isinstance(simplified_op, qml.ops.Sum) # pylint:disable=no-member
for s1, s2 in zip(final_op.operands, simplified_op.operands):
assert s1.name == s2.name
assert s1.wires == s2.wires
@@ -1128,7 +1129,7 @@ def test_grouping_with_barriers(self):
prod_op = qml.prod(qml.S(0), qml.Barrier(0), qml.S(0)).simplify()
simplified_op = prod_op.simplify()
assert isinstance(simplified_op, Prod)
- for s1, s2 in zip(prod_op.operands, simplified_op.operands):
+ for s1, s2 in zip(prod_op.operands, simplified_op.operands): # pylint:disable=no-member
assert s1.name == s2.name
assert s1.wires == s2.wires
assert s1.data == s2.data
@@ -1321,7 +1322,7 @@ def circuit(weights):
true_grad = -qnp.sqrt(2) * qnp.cos(weights[0] / 2) * qnp.sin(weights[0] / 2)
assert qnp.allclose(grad, true_grad)
- def test_non_hermitian_op_in_measurement_process(self):
+ def test_non_hermitian_obs_not_supported(self):
"""Test that non-hermitian ops in a measurement process will raise a warning."""
wires = [0, 1]
dev = qml.device("default.qubit", wires=wires)
@@ -1332,7 +1333,7 @@ def my_circ():
qml.PauliX(0)
return qml.expval(prod_op)
- with pytest.warns(UserWarning, match="Prod might not be hermitian."):
+ with pytest.raises(NotImplementedError):
my_circ()
def test_operation_integration(self):
@@ -1387,11 +1388,14 @@ def test_params_can_be_considered_trainable(self):
dev = qml.device("default.qubit", wires=2)
@qml.qnode(dev)
- def circuit():
- return qml.expval(qml.prod(qml.RX(1.1, 0), qml.RY(qnp.array(2.2), 1)))
+ def circuit(x, U):
+ qml.RX(x, 0)
+ return qml.expval(qml.prod(qml.Hermitian(U, 0), qml.PauliX(1)))
+
+ x = qnp.array(0.1, requires_grad=False)
+ U = qnp.array([[1.0, 0.0], [0.0, -1.0]], requires_grad=True)
- with pytest.warns(UserWarning):
- circuit()
+ circuit(x, U)
assert circuit.tape.trainable_params == [1]
diff --git a/tests/ops/op_math/test_sprod.py b/tests/ops/op_math/test_sprod.py
index bc25513af3e..014cde358da 100644
--- a/tests/ops/op_math/test_sprod.py
+++ b/tests/ops/op_math/test_sprod.py
@@ -790,7 +790,7 @@ def test_simplify_method(self):
sprod_op = SProd(
2, SProd(2, qml.RZ(1.32, wires=0)) + qml.Identity(wires=0) + qml.RX(1.9, wires=1)
)
- final_op = qml.ops.Sum(
+ final_op = qml.ops.Sum( # pylint:disable=no-member
SProd(4, qml.RZ(1.32, wires=0)),
SProd(2, qml.Identity(wires=0)),
SProd(2, qml.RX(1.9, wires=1)),
@@ -799,7 +799,7 @@ def test_simplify_method(self):
# TODO: Use qml.equal when supported for nested operators
- assert isinstance(simplified_op, qml.ops.Sum)
+ assert isinstance(simplified_op, qml.ops.Sum) # pylint:disable=no-member
for s1, s2 in zip(final_op.operands, simplified_op.operands):
assert isinstance(s2, SProd)
assert s1.name == s2.name
@@ -837,7 +837,7 @@ def test_simplify_with_sum_operator(self):
final_op = s_prod(0 - 6j, qml.PauliX(0))
simplified_op = sprod_op.simplify()
- assert isinstance(simplified_op, qml.ops.SProd)
+ assert isinstance(simplified_op, qml.ops.SProd) # pylint:disable=no-member
assert simplified_op.name == final_op.name
assert repr(simplified_op) == repr(final_op)
assert simplified_op.wires == final_op.wires
@@ -1045,7 +1045,7 @@ def circuit(weights):
true_grad = 100 * -qnp.sqrt(2) * qnp.cos(weights[0] / 2) * qnp.sin(weights[0] / 2)
assert qnp.allclose(grad, true_grad)
- def test_non_hermitian_op_in_measurement_process(self):
+ def test_non_hermitian_obs_not_supported(self):
"""Test that non-hermitian ops in a measurement process will raise a warning."""
wires = [0, 1]
dev = qml.device("default.qubit", wires=wires)
@@ -1056,7 +1056,7 @@ def my_circ():
qml.PauliX(0)
return qml.expval(sprod_op)
- with pytest.warns(UserWarning, match="SProd might not be hermitian."):
+ with pytest.raises(NotImplementedError):
my_circ()
@pytest.mark.torch
@@ -1106,7 +1106,7 @@ def test_tensorflow_qnode(self, diff_method):
def circuit(s):
return qml.expval(qml.s_prod(s, qml.PauliZ(0)))
- res = circuit(tf.Variable(2))
+ res = circuit(tf.Variable(2, dtype=tf.float64))
assert qml.math.allclose(res, 2)
diff --git a/tests/ops/qubit/test_hamiltonian.py b/tests/ops/qubit/test_hamiltonian.py
index fe1961f71a6..3a9ede92715 100644
--- a/tests/ops/qubit/test_hamiltonian.py
+++ b/tests/ops/qubit/test_hamiltonian.py
@@ -1704,7 +1704,7 @@ def combine(coeffs, param):
def test_nontrainable_coeffs_paramshift(self):
"""Test the parameter-shift method if the coefficients are explicitly set non-trainable
by not passing them to the qnode."""
- coeffs = pnp.array([-0.05, 0.17], requires_grad=False)
+ coeffs = np.array([-0.05, 0.17])
param = pnp.array(1.7, requires_grad=True)
# differentiating a circuit with measurement expval(H)
@@ -1898,7 +1898,7 @@ def circuit(coeffs, param):
)
res = circuit(coeffs, param)
- res.backward()
+ res.backward() # pylint:disable=no-member
grad = (coeffs.grad, param.grad)
# differentiating a cost that combines circuits with
@@ -1940,7 +1940,7 @@ def circuit(coeffs, param):
)
res = circuit(coeffs, param)
- res.backward()
+ res.backward() # pylint:disable=no-member
# differentiating a cost that combines circuits with
# measurements expval(Pauli)
@@ -2069,7 +2069,7 @@ def circuit(coeffs, param):
grad_fn = qml.grad(circuit)
with pytest.raises(
- qml.QuantumFunctionError,
- match="Adjoint differentiation method does not support Hamiltonian observables",
+ qml.DeviceError,
+ match="Adjoint differentiation method does not support observable Hamiltonian",
):
grad_fn(coeffs, param)
diff --git a/tests/ops/qubit/test_parametric_ops.py b/tests/ops/qubit/test_parametric_ops.py
index ba71bd3208e..7e874328911 100644
--- a/tests/ops/qubit/test_parametric_ops.py
+++ b/tests/ops/qubit/test_parametric_ops.py
@@ -2554,6 +2554,7 @@ def test_globalphase_autograd_grad(self, tol, dev_name, diff_method):
@qml.qnode(dev, diff_method=diff_method)
def circuit(x):
+ qml.Identity(0)
qml.Hadamard(1)
qml.ctrl(qml.GlobalPhase(x), 1)
qml.Hadamard(1)
@@ -2899,6 +2900,7 @@ def test_globalphase_tf_grad(self, tol, dev_name, diff_method):
@qml.qnode(dev, diff_method=diff_method)
def circuit(x):
+ qml.Identity(0)
qml.Hadamard(1)
qml.ctrl(qml.GlobalPhase(x), 1)
qml.Hadamard(1)
@@ -3055,6 +3057,7 @@ def test_globalphase_jax_grad(self, tol, dev_name, diff_method):
@qml.qnode(dev, diff_method=diff_method)
def circuit(x):
+ qml.Identity(0)
qml.Hadamard(1)
qml.ctrl(qml.GlobalPhase(x), 1)
qml.Hadamard(1)
@@ -3078,6 +3081,7 @@ def test_globalphase_torch_grad(self, tol, dev_name, diff_method):
@qml.qnode(dev, diff_method=diff_method)
def circuit(x):
+ qml.Identity(0)
qml.Hadamard(1)
qml.ctrl(qml.GlobalPhase(x), 1)
qml.Hadamard(1)
diff --git a/tests/ops/qubit/test_sparse.py b/tests/ops/qubit/test_sparse.py
index 30039971588..883c96cec32 100644
--- a/tests/ops/qubit/test_sparse.py
+++ b/tests/ops/qubit/test_sparse.py
@@ -193,8 +193,10 @@ def test_sparse_hamiltonian_expval(self, qubits, operations, hamiltonian, expect
hamiltonian = csr_matrix(hamiltonian)
dev = qml.device("default.qubit", wires=qubits, shots=None)
- dev.apply(operations)
- expval = dev.expval(qml.SparseHamiltonian(hamiltonian, range(qubits)))[0]
+ qs = qml.tape.QuantumScript(
+ operations, [qml.expval((qml.SparseHamiltonian(hamiltonian, range(qubits))))]
+ )
+ expval = dev.execute(qs)
assert np.allclose(expval, expected_output, atol=tol, rtol=0)
@@ -203,7 +205,10 @@ def test_sparse_expval_error(self):
shots is requested."""
hamiltonian = csr_matrix(np.array([[1.0, 0.0], [0.0, 1.0]]))
- dev = qml.device("default.qubit", wires=1, shots=1)
+ dev = qml.device("default.qubit", wires=1)
+ qs = qml.tape.QuantumScript(
+ measurements=[qml.expval(qml.SparseHamiltonian(hamiltonian, [0]))], shots=1
+ )
- with pytest.raises(AssertionError, match="SparseHamiltonian must be used with shots=None"):
- dev.expval(qml.SparseHamiltonian(hamiltonian, [0]))
+ with pytest.raises(qml.operation.DiagGatesUndefinedError):
+ dev.execute(qs)
diff --git a/tests/pulse/test_hardware_hamiltonian.py b/tests/pulse/test_hardware_hamiltonian.py
index 566c3c22e13..09933ba2ccf 100644
--- a/tests/pulse/test_hardware_hamiltonian.py
+++ b/tests/pulse/test_hardware_hamiltonian.py
@@ -662,7 +662,7 @@ def qnode_jit(params):
res_jit = qnode_jit(params)
assert isinstance(res, jax.Array)
- assert res == res_jit
+ assert qml.math.allclose(res, res_jit)
@pytest.mark.jax
def test_jitted_qnode_multidrive(self):
@@ -747,4 +747,4 @@ def qnode_jit(params):
res_jit = qnode_jit(params)
assert isinstance(res, jax.Array)
- assert res == res_jit
+ assert qml.math.allclose(res, res_jit)
diff --git a/tests/qchem/test_dipole.py b/tests/qchem/test_dipole.py
index e19db8fe3f3..23554cf3518 100644
--- a/tests/qchem/test_dipole.py
+++ b/tests/qchem/test_dipole.py
@@ -285,7 +285,9 @@ def test_gradient_expvalD():
mol = qchem.Molecule(symbols, geometry, charge=1, alpha=alpha)
args = [mol.alpha]
- dev = qml.device("default.qubit", wires=6)
+ # TODO: `d_qubit[0]` has coeff dtype complex, but is actually a real-valued Hamiltonian
+ # default.qubit.legacy casts Hamiltonian expectations to real, but default.qubit does not
+ dev = qml.device("default.qubit.legacy", wires=6)
def dipole(mol):
@qml.qnode(dev)
diff --git a/tests/qchem/test_hamiltonians.py b/tests/qchem/test_hamiltonians.py
index c6c9f3c091a..78caa5bf68a 100644
--- a/tests/qchem/test_hamiltonians.py
+++ b/tests/qchem/test_hamiltonians.py
@@ -284,7 +284,7 @@ def test_gradient_expvalH():
mol = qchem.Molecule(symbols, geometry, alpha=alpha)
args = [alpha]
- dev = qml.device("default.qubit", wires=4)
+ dev = qml.device("default.qubit.legacy", wires=4)
def energy(mol):
@qml.qnode(dev)
@@ -336,7 +336,7 @@ def test_gradient_expvalH(self):
mol = qchem.Molecule(symbols, geometry, alpha=alpha)
args = [jax.numpy.array(alpha)]
- dev = qml.device("default.qubit", wires=4)
+ dev = qml.device("default.qubit.legacy", wires=4)
def energy(mol):
@qml.qnode(dev, interface="jax")
diff --git a/tests/qinfo/test_fisher.py b/tests/qinfo/test_fisher.py
index 26a5456631d..7ccae1e9e29 100644
--- a/tests/qinfo/test_fisher.py
+++ b/tests/qinfo/test_fisher.py
@@ -157,7 +157,7 @@ def qfunc(params):
qml.RX(params[0], wires=0)
qml.RX(params[1], wires=0)
qml.CNOT(wires=(0, 1))
- return qml.state()
+ return qml.probs()
params = pnp.random.random(2)
diff --git a/tests/qnn/test_keras.py b/tests/qnn/test_keras.py
index f8261f3af8f..34566606cf9 100644
--- a/tests/qnn/test_keras.py
+++ b/tests/qnn/test_keras.py
@@ -915,7 +915,7 @@ def circuit(inputs, w1, w2):
assert info["num_observables"] == 2
assert info["num_diagonalizing_gates"] == 0
- assert info["num_device_wires"] == 3
+ assert info["num_device_wires"] == 2
assert info["num_trainable_params"] == 2
assert info["interface"] == "tf"
- assert info["device_name"] == "default.qubit.tf"
+ assert info["device_name"] == "default.qubit"
diff --git a/tests/qnn/test_qnn_torch.py b/tests/qnn/test_qnn_torch.py
index d1a4b385800..ba2701063a9 100644
--- a/tests/qnn/test_qnn_torch.py
+++ b/tests/qnn/test_qnn_torch.py
@@ -666,8 +666,6 @@ def compute_matrix(
z = params[0]
return np.diag([z, z])
- device.operations.add("DummyOp")
-
@qml.qnode(device=device, interface="torch", diff_method="parameter-shift")
def circ(inputs, w0): # pylint: disable=unused-argument
DummyOp(inputs[0], wires=0)
@@ -849,7 +847,7 @@ def circuit(inputs, w1, w2):
assert info["num_observables"] == 2
assert info["num_diagonalizing_gates"] == 0
- assert info["num_device_wires"] == 3
+ assert info["num_device_wires"] == 2
assert info["num_trainable_params"] == 0
assert info["interface"] == "torch"
- assert info["device_name"] == "default.qubit.torch"
+ assert info["device_name"] == "default.qubit"
diff --git a/tests/shadow/test_shadow_entropies.py b/tests/shadow/test_shadow_entropies.py
index 5987723c418..1de2af20454 100644
--- a/tests/shadow/test_shadow_entropies.py
+++ b/tests/shadow/test_shadow_entropies.py
@@ -77,9 +77,10 @@ def test_non_constant_distribution(
"""Test entropies match roughly with exact solution for a non-constant distribution using other PennyLane functionalities"""
n_wires = 4
# exact solution
+ dev_exact = qml.device("default.qubit", wires=range(n_wires), shots=None)
dev = qml.device("default.qubit", wires=range(n_wires), shots=100000)
- @qml.qnode(dev)
+ @qml.qnode(dev_exact)
def qnode_exact(x):
for i in range(n_wires):
qml.RY(x[i], wires=i)
diff --git a/tests/shadow/test_shadow_transforms.py b/tests/shadow/test_shadow_transforms.py
index c924a2dc65d..ef91d5956cf 100644
--- a/tests/shadow/test_shadow_transforms.py
+++ b/tests/shadow/test_shadow_transforms.py
@@ -197,9 +197,8 @@ def circuit_shadow():
qml.CNOT(wires=[0, 1])
return qml.classical_shadow(wires=[0, 1]), qml.expval(qml.PauliZ(0))
- msg = "Classical shadows cannot be returned in combination with other return types"
- with pytest.raises(qml.QuantumFunctionError, match=msg):
- circuit_shadow()
+ res = circuit_shadow()
+ assert isinstance(res, tuple) and len(res) == 2
@qml.qnode(dev)
def circuit_expval():
@@ -207,8 +206,8 @@ def circuit_expval():
qml.CNOT(wires=[0, 1])
return qml.shadow_expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(0))
- with pytest.raises(qml.QuantumFunctionError, match=msg):
- circuit_expval()
+ res = circuit_expval()
+ assert isinstance(res, tuple) and len(res) == 2
@pytest.mark.all_interfaces
diff --git a/tests/tape/test_qscript.py b/tests/tape/test_qscript.py
index b8618d5afc5..9e5dbca64bc 100644
--- a/tests/tape/test_qscript.py
+++ b/tests/tape/test_qscript.py
@@ -925,12 +925,6 @@ def test_diagonalizing_gates_not_queued(self):
),
]
-warnings_matches = {
- State: "Requested state or density matrix with finite shots",
- VnEntropy: "Requested Von Neumann entropy with finite shots",
- MutualInfo: "Requested mutual information with finite shots",
-}
-
class TestMeasurementProcess:
"""Tests for the shape and numeric type of a measurement process"""
@@ -1027,7 +1021,7 @@ def test_output_shapes_single(self, measurement, expected_shape, shots):
b = np.array(0.2)
ops = [qml.RY(a, 0), qml.RX(b, 0)]
- qs = QuantumScript(ops, [measurement])
+ qs = QuantumScript(ops, [measurement], shots=shots)
shot_dim = len(shots) if isinstance(shots, tuple) else shots
if expected_shape is None:
@@ -1048,10 +1042,8 @@ def test_output_shapes_single_qnode_check(self, measurement, expected_shape, sho
shape of a QNode for a single measurement."""
if shots is None and measurement.return_type is qml.measurements.Sample:
pytest.skip("Sample doesn't support analytic computations.")
- if isinstance(shots, tuple) and isinstance(
- measurement, (qml.measurements.MutualInfoMP, qml.measurements.VnEntropyMP)
- ):
- pytest.skip("Shot vectors and entropies not supported.")
+ if shots and isinstance(measurement, qml.measurements.StateMeasurement):
+ pytest.skip("State measurements with finite shots not supported.")
dev = qml.device("default.qubit", wires=3, shots=shots)
@@ -1059,15 +1051,10 @@ def test_output_shapes_single_qnode_check(self, measurement, expected_shape, sho
b = np.array(0.2)
ops = [qml.RY(a, 0), qml.RX(b, 0)]
- qs = QuantumScript(ops, [measurement])
+ qs = QuantumScript(ops, [measurement], shots=shots)
- w_match = warnings_matches.get(measurement.return_type, None)
- if shots is not None and w_match is not None:
- with pytest.warns(UserWarning, match=w_match):
- res = qml.execute([qs], dev, gradient_fn=None)[0]
- else:
- # TODO: test gradient_fn is not None when the interface `execute` functions are implemented
- res = qml.execute([qs], dev, gradient_fn=None)[0]
+ # TODO: test gradient_fn is not None when the interface `execute` functions are implemented
+ res = qml.execute([qs], dev, gradient_fn=None)[0]
if isinstance(shots, tuple):
res_shape = tuple(r.shape for r in res)
@@ -1129,7 +1116,7 @@ def test_multi_measure(self, measurements, expected, shots):
expectation value, variance and probability measurements."""
dev = qml.device("default.qubit", wires=3, shots=shots)
- qs = QuantumScript(measurements=measurements)
+ qs = QuantumScript(measurements=measurements, shots=shots)
if measurements[0].return_type is qml.measurements.Sample:
expected[1] = shots
@@ -1163,7 +1150,7 @@ def test_multi_measure_shot_vector(self, measurements, expected):
a = np.array(0.1)
b = np.array(0.2)
ops = [qml.RY(a, 0), qml.RX(b, 0)]
- qs = QuantumScript(ops, measurements)
+ qs = QuantumScript(ops, measurements, shots=shots)
# Update expected as we're using a shotvector
expected = tuple(expected for _ in shots)
@@ -1188,7 +1175,9 @@ def test_multi_measure_sample(self, shots):
num_samples = 3
ops = [qml.RY(a, 0), qml.RX(b, 0)]
- qs = QuantumScript(ops, [qml.sample(qml.PauliZ(i)) for i in range(num_samples)])
+ qs = QuantumScript(
+ ops, [qml.sample(qml.PauliZ(i)) for i in range(num_samples)], shots=shots
+ )
expected = tuple(() if shots == 1 else (shots,) for _ in range(num_samples))
@@ -1226,7 +1215,7 @@ def test_broadcasting_single(self, measurement, expected_shape, shots):
qml.RX(b, wires=0)
qml.apply(measurement)
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
expected_shape = qml.execute([tape], dev, gradient_fn=None)[0].shape
assert tape.shape(dev) == expected_shape
@@ -1254,7 +1243,7 @@ def test_broadcasting_multi(self, measurement, expected, shots):
for _ in range(2):
qml.apply(measurement)
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
expected = qml.execute([tape], dev, gradient_fn=None)[0]
actual = tape.shape(dev)
@@ -1273,7 +1262,9 @@ def test_multi_measure_sample_obs_shot_vector(self):
num_samples = 3
ops = [qml.RY(a, 0), qml.RX(b, 0)]
- qs = QuantumScript(ops, [qml.sample(qml.PauliZ(i)) for i in range(num_samples)])
+ qs = QuantumScript(
+ ops, [qml.sample(qml.PauliZ(i)) for i in range(num_samples)], shots=shots
+ )
expected = tuple(tuple(() if s == 1 else (s,) for _ in range(num_samples)) for s in shots)
@@ -1294,7 +1285,7 @@ def test_multi_measure_sample_wires_shot_vector(self):
num_samples = 3
ops = [qml.RY(0.3, 0), qml.RX(0.2, 0)]
- qs = QuantumScript(ops, [qml.sample()] * num_samples)
+ qs = QuantumScript(ops, [qml.sample()] * num_samples, shots=shots)
expected = tuple(
tuple((3,) if s == 1 else (s, 3) for _ in range(num_samples)) for s in shots
@@ -1318,7 +1309,7 @@ def test_raises_broadcasting_shot_vector(self):
qml.RX(np.array([0.3, 0.4]), wires=0)
qml.expval(qml.PauliZ(0))
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=(1, 2, 3))
msg = "Parameter broadcasting when using a shot vector is not supported yet"
with pytest.raises(NotImplementedError, match=msg):
@@ -1343,21 +1334,13 @@ def test_float_measures(self, ret, shots):
"""Test that most measurements output floating point values and that
the tape output domain correctly identifies this."""
dev = qml.device("default.qubit", wires=3, shots=shots)
- if isinstance(shots, tuple) and isinstance(
- ret, (qml.measurements.MutualInfoMP, qml.measurements.VnEntropyMP)
- ):
- pytest.skip("Shot vectors and entropies not supported.")
+ if shots and isinstance(ret, (qml.measurements.MutualInfoMP, qml.measurements.VnEntropyMP)):
+ pytest.skip("Shots and entropies not supported.")
a, b = 0.3, 0.2
ops = [qml.RY(a, 0), qml.RZ(b, 0)]
- qs = QuantumScript(ops, [ret])
-
- w_match = warnings_matches.get(ret.return_type, None)
- if shots is not None and w_match is not None:
- with pytest.warns(UserWarning, match=w_match):
- result = qml.execute([qs], dev, gradient_fn=None)[0]
- else:
- result = qml.execute([qs], dev, gradient_fn=None)[0]
+ qs = QuantumScript(ops, [ret], shots=shots)
+ result = qml.execute([qs], dev, gradient_fn=None)[0]
if not isinstance(result, tuple):
result = (result,)
@@ -1390,7 +1373,7 @@ def test_sample_int_eigvals(self, ret):
sampling measurement with a Hermitian observable with integer
eigenvalues."""
dev = qml.device("default.qubit", wires=3, shots=5)
- qs = QuantumScript([qml.RY(0.4, 0)], [ret])
+ qs = QuantumScript([qml.RY(0.4, 0)], [ret], shots=5)
result = qml.execute([qs], dev, gradient_fn=None)[0]
@@ -1413,7 +1396,7 @@ def test_sample_real_eigvals(self):
)
herm = np.outer(arr, arr)
- qs = QuantumScript([qml.RY(0.4, 0)], [qml.sample(qml.Hermitian(herm, wires=0))])
+ qs = QuantumScript([qml.RY(0.4, 0)], [qml.sample(qml.Hermitian(herm, wires=0))], shots=5)
result = qml.execute([qs], dev, gradient_fn=None)[0]
@@ -1439,7 +1422,7 @@ def test_sample_real_and_int_eigvals(self):
a, b = 0, 3
ops = [qml.RY(a, 0), qml.RX(b, 0)]
m = [qml.sample(qml.Hermitian(herm, wires=0)), qml.sample(qml.PauliZ(1))]
- qs = QuantumScript(ops, m)
+ qs = QuantumScript(ops, m, shots=5)
result = qml.execute([qs], dev, gradient_fn=None)[0]
diff --git a/tests/tape/test_tape.py b/tests/tape/test_tape.py
index a8c33a9d73f..e509694f117 100644
--- a/tests/tape/test_tape.py
+++ b/tests/tape/test_tape.py
@@ -1234,31 +1234,26 @@ def test_expand_does_not_affect_original_tape(self):
assert qml.equal(expanded.measurements[1], qml.expval(qml.PauliZ(0)))
assert expanded.shots is tape.shots
- def test_is_sampled_reserved_after_expansion(self, monkeypatch):
+ def test_is_sampled_reserved_after_expansion(self):
"""Test that the is_sampled property is correctly set when tape
expansion happens."""
dev = qml.device("default.qubit", wires=1, shots=10)
- # Remove support for an op to enforce decomposition & tape expansion
- mock_ops = copy.copy(dev.operations)
- mock_ops.remove("T")
+ class UnsupportedT(qml.operation.Operation):
+ """A T gate that provides a decomposition, but no matrix."""
- with monkeypatch.context() as m:
- m.setattr(dev, "operations", mock_ops)
+ @staticmethod
+ def compute_decomposition(wires): # pylint:disable=arguments-differ
+ return [qml.PhaseShift(np.pi / 4, wires=wires)]
- def circuit():
- qml.T(wires=0)
- return sample(qml.PauliZ(0))
-
- # Choosing parameter-shift not to swap the device under the hood
- qnode = qml.QNode(circuit, dev, diff_method="parameter-shift")
- qnode()
+ @qml.qnode(dev, diff_method="parameter-shift")
+ def circuit():
+ UnsupportedT(wires=0)
+ return sample(qml.PauliZ(0))
- # Double-checking that the T gate is not supported
- assert "T" not in qnode.device.operations
- assert "T" not in qnode._original_device.operations
+ circuit()
- assert qnode.qtape.is_sampled
+ assert circuit.qtape.is_sampled
class TestExecution:
@@ -1390,11 +1385,12 @@ def test_prob_expectation_values(self, tol):
assert isinstance(res, tuple)
assert len(res) == 2
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], np.float64)
assert np.allclose(res[0], np.cos(x), atol=tol, rtol=0)
assert isinstance(res[1], np.ndarray)
- assert np.allclose(res[1], np.abs(dev.state) ** 2, atol=tol, rtol=0)
+ final_state, _ = qml.devices.qubit.get_final_state(tape)
+ assert np.allclose(res[1], np.abs(final_state.flatten()) ** 2, atol=tol, rtol=0)
def test_single_mode_sample(self):
"""Test that there is only one array of values returned
@@ -1409,6 +1405,7 @@ def test_single_mode_sample(self):
qml.CNOT(wires=[0, 1])
qml.sample(qml.PauliZ(0) @ qml.PauliX(1))
+ tape._shots = qml.measurements.Shots(10)
res = dev.execute(tape)
assert res.shape == (10,)
@@ -1426,6 +1423,7 @@ def test_multiple_samples(self):
qml.sample(qml.PauliZ(0))
qml.sample(qml.PauliZ(1))
+ tape._shots = qml.measurements.Shots(10)
res = dev.execute(tape)
assert isinstance(res, tuple)
assert isinstance(res[0], np.ndarray)
@@ -1447,22 +1445,27 @@ def test_samples_expval(self):
qml.sample(qml.PauliZ(0))
qml.expval(qml.PauliZ(1))
+ tape._shots = qml.measurements.Shots(10)
res = dev.execute(tape)
assert isinstance(res, tuple)
assert isinstance(res[0], np.ndarray)
assert res[0].shape == (10,)
- assert isinstance(res[1], np.ndarray)
+ assert isinstance(res[1], np.float64)
assert res[1].shape == ()
def test_decomposition(self, tol):
"""Test decomposition onto a device's supported gate set"""
dev = qml.device("default.qubit", wires=1)
+ from pennylane.devices.qubit.preprocess import _accepted_operator
with QuantumTape() as tape:
qml.U3(0.1, 0.2, 0.3, wires=[0])
qml.expval(qml.PauliZ(0))
- tape = tape.expand(stop_at=lambda obj: obj.name in dev.operations)
+ def stop_fn(op):
+ return isinstance(op, qml.measurements.MeasurementProcess) or _accepted_operator(op)
+
+ tape = tape.expand(stop_at=stop_fn)
res = dev.execute(tape)
assert np.allclose(res, np.cos(0.1), atol=tol, rtol=0)
@@ -1856,7 +1859,7 @@ def test_output_shapes_single(self, measurement, expected_shape, shots):
qml.RX(b, wires=0)
qml.apply(measurement)
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
shot_dim = shots if not isinstance(shots, tuple) else len(shots)
if expected_shape is None:
expected_shape = shot_dim if shot_dim == 1 else (shot_dim,)
@@ -1900,7 +1903,7 @@ def test_output_shapes_single_qnode_check(self, measurement, _, shots):
qml.RX(b, wires=0)
qml.apply(measurement)
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
res = qml.execute([tape], dev, gradient_fn=qml.gradients.param_shift)[0]
if isinstance(res, tuple):
@@ -1976,7 +1979,7 @@ def test_multi_measure(self, measurements, expected, shots):
for m in measurements:
qml.apply(m)
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
if measurements[0].return_type is qml.measurements.Sample:
expected[1] = shots
expected = tuple(expected)
@@ -2015,7 +2018,7 @@ def test_multi_measure_shot_vector(self, measurements, expected):
for m in measurements:
qml.apply(m)
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
# Modify expected to account for shot vector
expected = tuple(expected for _ in shots)
res = tape.shape(dev)
@@ -2038,7 +2041,7 @@ def test_multi_measure_sample(self, shots):
for i in range(num_samples):
qml.sample(qml.PauliZ(i))
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
if shots == 1:
expected = tuple(() for _ in range(num_samples))
else:
@@ -2064,7 +2067,7 @@ def test_multi_measure_sample_shot_vector(self):
for i in range(num_samples):
qml.sample(qml.PauliZ(i))
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
expected = []
for s in shots:
if s == 1:
@@ -2101,7 +2104,7 @@ def test_broadcasting_single(self, measurement, _, shots):
qml.RX(b, wires=0)
qml.apply(measurement)
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
expected = qml.execute([tape], dev, gradient_fn=None)[0]
assert tape.shape(dev) == expected.shape
@@ -2128,7 +2131,7 @@ def test_broadcasting_multi(self, measurement, expected, shots):
for _ in range(2):
qml.apply(measurement)
- tape = qml.tape.QuantumScript.from_queue(q)
+ tape = qml.tape.QuantumScript.from_queue(q, shots=shots)
expected = qml.execute([tape], dev, gradient_fn=None)[0]
expected = tuple(i.shape for i in expected)
assert tape.shape(dev) == expected
@@ -2231,7 +2234,7 @@ def test_sample_real_and_int_eigvals(self):
"""Test that the tape can correctly determine the output domain for
multiple sampling measurements with a Hermitian observable with real
eigenvalues and another one with integer eigenvalues."""
- dev = qml.device("default.qubit", wires=3, shots=5, r_dtype=np.float64)
+ dev = qml.device("default.qubit", wires=3, shots=5)
arr = np.array(
[
diff --git a/tests/templates/test_embeddings/test_amplitude.py b/tests/templates/test_embeddings/test_amplitude.py
index 8b8d79ba1ab..64bdd9a6783 100644
--- a/tests/templates/test_embeddings/test_amplitude.py
+++ b/tests/templates/test_embeddings/test_amplitude.py
@@ -79,10 +79,9 @@ def test_prepares_correct_state(self, inpt, normalize):
@qml.qnode(dev)
def circuit(x=None):
qml.AmplitudeEmbedding(features=x, wires=range(n_qubits), normalize=normalize)
- return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]
+ return qml.state()
- circuit(x=inpt)
- state = circuit.device.state.ravel()
+ state = circuit(x=inpt).ravel()
assert np.allclose(state, inpt)
@pytest.mark.parametrize("normalize", (True, False))
@@ -112,10 +111,9 @@ def test_prepares_padded_state(self, inpt, pad):
@qml.qnode(dev)
def circuit(x=None):
qml.AmplitudeEmbedding(features=x, wires=range(n_qubits), pad_with=pad, normalize=False)
- return [qml.expval(qml.PauliZ(i)) for i in range(n_qubits)]
+ return qml.state()
- circuit(x=inpt)
- state = circuit.device.state.ravel()
+ state = circuit(x=inpt).ravel()
# Make sure all padded values are the same constant
# by checking how many different values there are
assert len(set(state[len(inpt) :])) == 1
@@ -148,17 +146,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.AmplitudeEmbedding(features, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.AmplitudeEmbedding(features, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_embeddings/test_angle.py b/tests/templates/test_embeddings/test_angle.py
index ef531695f3d..2cb3677269e 100644
--- a/tests/templates/test_embeddings/test_angle.py
+++ b/tests/templates/test_embeddings/test_angle.py
@@ -130,17 +130,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.AngleEmbedding(features, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.AngleEmbedding(features, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_embeddings/test_basis.py b/tests/templates/test_embeddings/test_basis.py
index 974c2e2e335..158448338bc 100644
--- a/tests/templates/test_embeddings/test_basis.py
+++ b/tests/templates/test_embeddings/test_basis.py
@@ -78,17 +78,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.BasisEmbedding(features, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.BasisEmbedding(features, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_embeddings/test_iqp_emb.py b/tests/templates/test_embeddings/test_iqp_emb.py
index 5eb25401b43..b0cc165f07e 100644
--- a/tests/templates/test_embeddings/test_iqp_emb.py
+++ b/tests/templates/test_embeddings/test_iqp_emb.py
@@ -119,17 +119,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.IQPEmbedding(features, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.IQPEmbedding(features, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_embeddings/test_qaoa_emb.py b/tests/templates/test_embeddings/test_qaoa_emb.py
index de49c972d67..a33dbac9c01 100644
--- a/tests/templates/test_embeddings/test_qaoa_emb.py
+++ b/tests/templates/test_embeddings/test_qaoa_emb.py
@@ -215,17 +215,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.QAOAEmbedding(features, weights, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.QAOAEmbedding(features, weights, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_layers/test_basic_entangler.py b/tests/templates/test_layers/test_basic_entangler.py
index 4c2ca6a83bf..1e21703333d 100644
--- a/tests/templates/test_layers/test_basic_entangler.py
+++ b/tests/templates/test_layers/test_basic_entangler.py
@@ -92,17 +92,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.BasicEntanglerLayers(weights, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.BasicEntanglerLayers(weights, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_layers/test_gate_fabric.py b/tests/templates/test_layers/test_gate_fabric.py
index 260090f79d1..fedad87a0bc 100644
--- a/tests/templates/test_layers/test_gate_fabric.py
+++ b/tests/templates/test_layers/test_gate_fabric.py
@@ -484,11 +484,9 @@ def test_decomposition_q(self, init_state, exp_state, tol):
@qml.qnode(dev)
def circuit(weight):
qml.GateFabric(weight, wires, init_state=init_state)
- return qml.expval(qml.PauliZ(0))
-
- circuit(weight)
+ return qml.state()
- assert qml.math.allclose(circuit.device.state, exp_state, atol=tol)
+ assert qml.math.allclose(circuit(weight), exp_state, atol=tol)
@pytest.mark.parametrize(
("num_qubits", "layers", "exp_state"),
@@ -608,9 +606,7 @@ def circuit(weight):
qml.GateFabric(weight, wires, init_state=init_state, include_pi=True)
return qml.state()
- circuit(weight)
-
- assert qml.math.allclose(circuit.device.state, exp_state, atol=tol)
+ assert qml.math.allclose(circuit(weight), exp_state, atol=tol)
def test_custom_wire_labels(self, tol):
"""Test that template can deal with non-numeric, nonconsecutive wire labels."""
@@ -623,17 +619,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.GateFabric(weights, wires=range(4), init_state=init_state)
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.GateFabric(weights, wires=["z", "a", "k", "r"], init_state=init_state)
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert qml.math.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_layers/test_particle_conserving_u1.py b/tests/templates/test_layers/test_particle_conserving_u1.py
index 15fd62056d3..9a5915ca886 100644
--- a/tests/templates/test_layers/test_particle_conserving_u1.py
+++ b/tests/templates/test_layers/test_particle_conserving_u1.py
@@ -134,17 +134,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.ParticleConservingU1(weights, wires=range(3), init_state=init_state)
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.ParticleConservingU1(weights, wires=["z", "a", "k"], init_state=init_state)
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
@pytest.mark.parametrize(
("init_state", "exp_state"),
@@ -198,11 +199,9 @@ def test_decomposition_u1ex(self, init_state, exp_state, tol):
@qml.qnode(dev)
def circuit(weights):
qml.ParticleConservingU1(weights, wires, init_state=init_state)
- return qml.expval(qml.PauliZ(0))
-
- circuit(weights)
+ return qml.state()
- assert np.allclose(circuit.device.state, exp_state, atol=tol)
+ assert np.allclose(circuit(weights), exp_state, atol=tol)
class TestInputs:
diff --git a/tests/templates/test_layers/test_particle_conserving_u2.py b/tests/templates/test_layers/test_particle_conserving_u2.py
index 163aa458484..55ffd0a27ba 100644
--- a/tests/templates/test_layers/test_particle_conserving_u2.py
+++ b/tests/templates/test_layers/test_particle_conserving_u2.py
@@ -111,11 +111,9 @@ def test_decomposition_u2ex(self, init_state, exp_state, tol):
def circuit(weight):
qml.BasisState(init_state, wires=wires)
qml.particle_conserving_u2.u2_ex_gate(weight, wires)
- return qml.expval(qml.PauliZ(0))
-
- circuit(weight)
+ return qml.state()
- assert np.allclose(circuit.device.state, exp_state, atol=tol)
+ assert np.allclose(circuit(weight), exp_state, atol=tol)
def test_custom_wire_labels(self, tol):
"""Test that template can deal with non-numeric, nonconsecutive wire labels."""
@@ -128,17 +126,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.ParticleConservingU2(weights, wires=range(3), init_state=init_state)
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.ParticleConservingU2(weights, wires=["z", "a", "k"], init_state=init_state)
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_layers/test_random.py b/tests/templates/test_layers/test_random.py
index c8e5a034f20..37014185720 100644
--- a/tests/templates/test_layers/test_random.py
+++ b/tests/templates/test_layers/test_random.py
@@ -136,17 +136,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.RandomLayers(weights, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.RandomLayers(weights, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_layers/test_simplified_twodesign.py b/tests/templates/test_layers/test_simplified_twodesign.py
index 7d0c8edb7eb..860d951f880 100644
--- a/tests/templates/test_layers/test_simplified_twodesign.py
+++ b/tests/templates/test_layers/test_simplified_twodesign.py
@@ -121,17 +121,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.SimplifiedTwoDesign(initial_layer, weights, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.SimplifiedTwoDesign(initial_layer, weights, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_layers/test_strongly_entangling.py b/tests/templates/test_layers/test_strongly_entangling.py
index 4569a724a35..e75a203def4 100644
--- a/tests/templates/test_layers/test_strongly_entangling.py
+++ b/tests/templates/test_layers/test_strongly_entangling.py
@@ -76,17 +76,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.StronglyEntanglingLayers(weights, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.StronglyEntanglingLayers(weights, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
@pytest.mark.parametrize(
"n_layers, n_wires, ranges", [(2, 2, [1, 1]), (1, 3, [2]), (4, 4, [2, 3, 1, 3])]
diff --git a/tests/templates/test_state_preparations/test_arbitrary_state_prep.py b/tests/templates/test_state_preparations/test_arbitrary_state_prep.py
index d96bf25f69a..ba3a88ef399 100644
--- a/tests/templates/test_state_preparations/test_arbitrary_state_prep.py
+++ b/tests/templates/test_state_preparations/test_arbitrary_state_prep.py
@@ -118,23 +118,23 @@ def test_correct_gates_two_wires(self):
assert queue[5].hyperparameters["pauli_word"] == "XY"
assert queue[5].wires.labels == (0, 1)
- def test_GHZ_generation(self, qubit_device_3_wires, tol):
+ def test_GHZ_generation(self, tol):
"""Test that the template prepares a GHZ state."""
GHZ_state = np.array([1 / np.sqrt(2), 0, 0, 0, 0, 0, 0, 1 / np.sqrt(2)])
weights = np.zeros(14)
weights[13] = np.pi / 2
- @qml.qnode(qubit_device_3_wires)
+ @qml.qnode(qml.device("default.qubit"))
def circuit(weights):
qml.ArbitraryStatePreparation(weights, [0, 1, 2])
- return qml.expval(qml.PauliZ(0))
+ return qml.expval(qml.PauliZ(0)), qml.state()
- circuit(weights)
+ _, state = circuit(weights)
- assert np.allclose(circuit.device.state, GHZ_state, atol=tol, rtol=0)
+ assert np.allclose(state, GHZ_state, atol=tol, rtol=0)
- def test_even_superposition_generation(self, qubit_device_3_wires, tol):
+ def test_even_superposition_generation(self, tol):
"""Test that the template prepares an even superposition state."""
even_superposition_state = np.ones(8) / np.sqrt(8)
@@ -143,15 +143,15 @@ def test_even_superposition_generation(self, qubit_device_3_wires, tol):
weights[3] = np.pi / 2
weights[5] = np.pi / 2
- @qml.qnode(qubit_device_3_wires)
+ @qml.qnode(qml.device("default.qubit"))
def circuit(weights):
qml.ArbitraryStatePreparation(weights, [0, 1, 2])
- return qml.expval(qml.PauliZ(0))
+ return qml.expval(qml.PauliZ(0)), qml.state()
- circuit(weights)
+ _, state = circuit(weights)
- assert np.allclose(circuit.device.state, even_superposition_state, atol=tol, rtol=0)
+ assert np.allclose(state, even_superposition_state, atol=tol, rtol=0)
def test_custom_wire_labels(self, tol):
"""Test that template can deal with non-numeric, nonconsecutive wire labels."""
@@ -163,17 +163,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.ArbitraryStatePreparation(weights, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.ArbitraryStatePreparation(weights, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_state_preparations/test_basis_state_prep.py b/tests/templates/test_state_preparations/test_basis_state_prep.py
index 5819f867e2c..b63b01a33f7 100644
--- a/tests/templates/test_state_preparations/test_basis_state_prep.py
+++ b/tests/templates/test_state_preparations/test_basis_state_prep.py
@@ -62,10 +62,10 @@ def test_correct_pl_gates(self, basis_state, wires, target_wires):
([1, 0, 1], [0, 1, 2], [1, 0, 1]),
])
# fmt: on
- def test_state_preparation(self, tol, qubit_device_3_wires, basis_state, wires, target_state):
+ def test_state_preparation(self, tol, basis_state, wires, target_state):
"""Tests that the template produces the correct expectation values."""
- @qml.qnode(qubit_device_3_wires)
+ @qml.qnode(qml.device("default.qubit"))
def circuit():
qml.BasisStatePreparation(basis_state, wires)
@@ -86,13 +86,11 @@ def circuit():
([1, 0, 1], [2, 0, 1], [0, 1, 1]),
],
)
- def test_state_preparation_jax_jit(
- self, tol, qubit_device_3_wires, basis_state, wires, target_state
- ):
+ def test_state_preparation_jax_jit(self, tol, basis_state, wires, target_state):
"""Tests that the template produces the correct expectation values."""
import jax
- @qml.qnode(qubit_device_3_wires, interface="jax")
+ @qml.qnode(qml.device("default.qubit"), interface="jax")
def circuit(state):
qml.BasisStatePreparation(state, wires)
@@ -115,14 +113,12 @@ def circuit(state):
([1, 0, 1], [2, 0, 1], [0, 1, 1]),
],
)
- def test_state_preparation_tf_autograph(
- self, tol, qubit_device_3_wires, basis_state, wires, target_state
- ):
+ def test_state_preparation_tf_autograph(self, tol, basis_state, wires, target_state):
"""Tests that the template produces the correct expectation values."""
import tensorflow as tf
@tf.function
- @qml.qnode(qubit_device_3_wires, interface="tf")
+ @qml.qnode(qml.device("default.qubit"), interface="tf")
def circuit(state):
qml.BasisStatePreparation(state, wires)
@@ -144,17 +140,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.BasisStatePreparation(basis_state, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.BasisStatePreparation(basis_state, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
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 6548e44464e..f7ac7bb3844 100644
--- a/tests/templates/test_state_preparations/test_mottonen_state_prep.py
+++ b/tests/templates/test_state_preparations/test_mottonen_state_prep.py
@@ -122,19 +122,22 @@ class TestDecomposition:
([1 / 2, 0, 1j / 2, 1j / np.sqrt(2)], [0, 1], [1 / 2, 0, 0, 0, 1j / 2, 0, 1j / np.sqrt(2), 0]),
])
# fmt: on
- def test_state_preparation_fidelity(
- self, tol, qubit_device_3_wires, state_vector, wires, target_state
- ):
+ def test_state_preparation_fidelity(self, tol, state_vector, wires, target_state):
"""Tests that the template produces correct states with high fidelity."""
- @qml.qnode(qubit_device_3_wires)
+ @qml.qnode(qml.device("default.qubit", wires=3))
def circuit():
qml.MottonenStatePreparation(state_vector, wires)
- return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1)), qml.expval(qml.PauliZ(2))
+ return (
+ qml.expval(qml.PauliZ(0)),
+ qml.expval(qml.PauliZ(1)),
+ qml.expval(qml.PauliZ(2)),
+ qml.state(),
+ )
- circuit()
+ results = circuit()
- state = circuit.device.state.ravel()
+ state = results[-1].ravel()
fidelity = abs(np.vdot(state, target_state)) ** 2
# We test for fidelity here, because the vector themselves will hardly match
@@ -207,18 +210,23 @@ def circuit():
])
# fmt: on
def test_state_preparation_probability_distribution(
- self, tol, qubit_device_3_wires, state_vector, wires, target_state
+ self, tol, state_vector, wires, target_state
):
"""Tests that the template produces states with correct probability distribution."""
- @qml.qnode(qubit_device_3_wires)
+ @qml.qnode(qml.device("default.qubit", wires=3))
def circuit():
qml.MottonenStatePreparation(state_vector, wires)
- return qml.expval(qml.PauliZ(0)), qml.expval(qml.PauliZ(1)), qml.expval(qml.PauliZ(2))
+ return (
+ qml.expval(qml.PauliZ(0)),
+ qml.expval(qml.PauliZ(1)),
+ qml.expval(qml.PauliZ(2)),
+ qml.state(),
+ )
- circuit()
+ results = circuit()
- state = circuit.device.state.ravel()
+ state = results[-1].ravel()
probabilities = np.abs(state) ** 2
target_probabilities = np.abs(target_state) ** 2
@@ -254,7 +262,7 @@ def circuit(state_vector):
# when the RZ cascade is skipped, CNOT gates should only be those required for RY cascade
spy = mocker.spy(circuit.device, "execute")
circuit(state_vector)
- tape = spy.call_args[0][0]
+ tape = spy.call_args[0][0][0]
assert tape.specs["resources"].gate_types["CNOT"] == n_CNOT
@@ -268,17 +276,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.MottonenStatePreparation(state, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.MottonenStatePreparation(state, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_subroutines/test_all_singles_doubles.py b/tests/templates/test_subroutines/test_all_singles_doubles.py
index cb37e63cd7a..a0e5413f521 100644
--- a/tests/templates/test_subroutines/test_all_singles_doubles.py
+++ b/tests/templates/test_subroutines/test_all_singles_doubles.py
@@ -120,7 +120,7 @@ def circuit():
singles=[[0, 1]],
doubles=[[0, 1, 2, 3]],
)
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
@@ -131,12 +131,13 @@ def circuit2():
singles=[["z", "a"]],
doubles=[["z", "a", "k", "e"]],
)
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
@@ -191,7 +192,7 @@ class TestInputs:
[[0, 2]],
[[0, 1, 2, 3]],
np.array([1, 1, 0, 0, 0]),
- "BasisState parameter and wires",
+ "Basis states must be of length 4",
),
(
np.array([-2.8, 1.6]),
diff --git a/tests/templates/test_subroutines/test_approx_time_evolution.py b/tests/templates/test_subroutines/test_approx_time_evolution.py
index 18e2c585f8a..82203dbd926 100644
--- a/tests/templates/test_subroutines/test_approx_time_evolution.py
+++ b/tests/templates/test_subroutines/test_approx_time_evolution.py
@@ -166,17 +166,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.ApproxTimeEvolution(hamiltonian, 0.5, 2)
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.ApproxTimeEvolution(hamiltonian2, 0.5, 2)
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
@@ -410,7 +411,7 @@ def create_tape(coeffs, t):
def cost(coeffs, t):
tape = create_tape(coeffs, t)
- if diff_method is qml.gradients.param_shift:
+ if diff_method is qml.gradients.param_shift and dev_name != "default.qubit":
tape = dev.expand_fn(tape)
return qml.execute([tape], dev, diff_method)[0]
diff --git a/tests/templates/test_subroutines/test_arbitrary_unitary.py b/tests/templates/test_subroutines/test_arbitrary_unitary.py
index afb45087a42..7f6ac28cd6a 100644
--- a/tests/templates/test_subroutines/test_arbitrary_unitary.py
+++ b/tests/templates/test_subroutines/test_arbitrary_unitary.py
@@ -158,17 +158,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.ArbitraryUnitary(weights, wires=range(3))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.ArbitraryUnitary(weights, wires=["z", "a", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_subroutines/test_basis_rotation.py b/tests/templates/test_subroutines/test_basis_rotation.py
index 7767dd763c6..f969e001ba7 100644
--- a/tests/templates/test_subroutines/test_basis_rotation.py
+++ b/tests/templates/test_subroutines/test_basis_rotation.py
@@ -101,7 +101,7 @@ def circuit():
wires=range(2),
unitary_matrix=weights,
)
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
@@ -110,12 +110,13 @@ def circuit2():
wires=["z", "a"],
unitary_matrix=weights,
)
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
@pytest.mark.parametrize(
("unitary_matrix", "eigen_values", "exp_state"),
diff --git a/tests/templates/test_subroutines/test_commuting_evolution.py b/tests/templates/test_subroutines/test_commuting_evolution.py
index 7cb8c22c02a..e36ad81c76a 100644
--- a/tests/templates/test_subroutines/test_commuting_evolution.py
+++ b/tests/templates/test_subroutines/test_commuting_evolution.py
@@ -47,32 +47,32 @@ def test_adjoint():
"""Tests the CommutingEvolution.adjoint method provides the correct adjoint operation."""
n_wires = 2
- dev1 = qml.device("default.qubit", wires=n_wires)
- dev2 = qml.device("default.qubit", wires=n_wires)
+ dev = qml.device("default.qubit", wires=n_wires)
obs = [qml.PauliX(0) @ qml.PauliY(1), qml.PauliY(0) @ qml.PauliX(1)]
coeffs = [1, -1]
hamiltonian = qml.Hamiltonian(coeffs, obs)
frequencies = (2,)
- @qml.qnode(dev1)
+ @qml.qnode(dev)
def adjoint_evolution_circuit(time):
for i in range(n_wires):
qml.Hadamard(i)
qml.adjoint(qml.CommutingEvolution)(hamiltonian, time, frequencies)
- return qml.expval(qml.PauliZ(1))
+ return qml.expval(qml.PauliZ(1)), qml.state()
- @qml.qnode(dev2)
+ @qml.qnode(dev)
def evolution_circuit(time):
for i in range(n_wires):
qml.Hadamard(i)
qml.CommutingEvolution(hamiltonian, time, frequencies)
- return qml.expval(qml.PauliZ(1))
+ return qml.expval(qml.PauliZ(1)), qml.state()
- evolution_circuit(0.13)
- adjoint_evolution_circuit(-0.13)
+ res1, state1 = evolution_circuit(0.13)
+ res2, state2 = adjoint_evolution_circuit(-0.13)
- assert all(np.isclose(dev1.state, dev2.state))
+ assert res1 == res2
+ assert all(np.isclose(state1, state2))
def test_decomposition_expand():
diff --git a/tests/templates/test_subroutines/test_double_excitation.py b/tests/templates/test_subroutines/test_double_excitation.py
index 76768b9a1fe..39b7c317428 100644
--- a/tests/templates/test_subroutines/test_double_excitation.py
+++ b/tests/templates/test_subroutines/test_double_excitation.py
@@ -242,17 +242,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.FermionicDoubleExcitation(0.4, wires1=[0, 2], wires2=[1, 4, 3])
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.FermionicDoubleExcitation(0.4, wires1=["z", "k"], wires2=["a", "s", "t"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_subroutines/test_kupccgsd.py b/tests/templates/test_subroutines/test_kupccgsd.py
index 0343cb4d34f..4a1801985ae 100644
--- a/tests/templates/test_subroutines/test_kupccgsd.py
+++ b/tests/templates/test_subroutines/test_kupccgsd.py
@@ -137,7 +137,7 @@ def circuit():
delta_sz=0,
init_state=np.array([0, 1, 0, 1]),
)
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
@@ -148,12 +148,13 @@ def circuit2():
delta_sz=0,
init_state=np.array([0, 1, 0, 1]),
)
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
@pytest.mark.parametrize(
("num_qubits", "k", "exp_state"),
@@ -256,9 +257,9 @@ def circuit(weight):
qml.kUpCCGSD(weight, wires=wires, k=k, delta_sz=0, init_state=init_state)
return qml.state()
- circuit(weight)
+ res = circuit(weight)
- assert qml.math.allclose(circuit.device.state, exp_state, atol=tol)
+ assert qml.math.allclose(res, exp_state, atol=tol)
@pytest.mark.parametrize(
("wires", "delta_sz", "generalized_singles_wires", "generalized_pair_doubles_wires"),
diff --git a/tests/templates/test_subroutines/test_permute.py b/tests/templates/test_subroutines/test_permute.py
index e2d61e75308..08f240d82e3 100644
--- a/tests/templates/test_subroutines/test_permute.py
+++ b/tests/templates/test_subroutines/test_permute.py
@@ -37,7 +37,7 @@ def identity_permutation():
identity_permutation()
# expand the Permute operation
- tape = spy.call_args[0][0]
+ tape = spy.call_args[0][0][0]
assert len(tape.operations) == 0
@@ -76,7 +76,7 @@ def two_cycle():
spy = mocker.spy(two_cycle.device, "execute")
two_cycle()
- tape = spy.call_args[0][0]
+ tape = spy.call_args[0][0][0]
# Check that the Permute operation was expanded to SWAPs when the QNode
# is evaluated, and that the wires are the same
@@ -130,7 +130,7 @@ def cycle():
spy = mocker.spy(cycle.device, "execute")
cycle()
- tape = spy.call_args[0][0]
+ tape = spy.call_args[0][0][0]
# Check that the Permute operation was expanded to SWAPs when the QNode
# is evaluated, and that the wires are the same
@@ -180,7 +180,7 @@ def arbitrary_perm():
spy = mocker.spy(arbitrary_perm.device, "execute")
arbitrary_perm()
- tape = spy.call_args[0][0]
+ tape = spy.call_args[0][0][0]
# Check that the Permute operation was expanded to SWAPs when the QNode
# is evaluated, and that the wires are the same
@@ -240,7 +240,7 @@ def subset_perm():
spy = mocker.spy(subset_perm.device, "execute")
subset_perm()
- tape = spy.call_args[0][0]
+ tape = spy.call_args[0][0][0]
# Check that the Permute operation was expanded to SWAPs when the QNode
# is evaluated, and that the wires are the same
@@ -290,17 +290,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.Permute(permutation, wires=range(4))
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.Permute(permutation2, wires=["z", "a", "k", "o"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_subroutines/test_qft.py b/tests/templates/test_subroutines/test_qft.py
index 08ddec4bb29..9e17377f215 100644
--- a/tests/templates/test_subroutines/test_qft.py
+++ b/tests/templates/test_subroutines/test_qft.py
@@ -42,10 +42,9 @@ def test_QFT_decomposition(self, n_qubits):
out_states = []
for state in np.eye(2**n_qubits):
- dev.reset()
ops = [qml.StatePrep(state, wires=range(n_qubits))] + decomp
- dev.apply(ops)
- out_states.append(dev.state)
+ qs = qml.tape.QuantumScript(ops, [qml.state()])
+ out_states.append(dev.execute(qs))
reconstructed_unitary = np.array(out_states).T
expected_unitary = qml.QFT(wires=range(n_qubits)).matrix()
diff --git a/tests/templates/test_subroutines/test_qpe.py b/tests/templates/test_subroutines/test_qpe.py
index e3bd15d8b09..8037ae9c7b3 100644
--- a/tests/templates/test_subroutines/test_qpe.py
+++ b/tests/templates/test_subroutines/test_qpe.py
@@ -99,9 +99,10 @@ def test_phase_estimated(self, phase):
qml.probs(estimation_wires)
tape = qml.tape.QuantumScript.from_queue(q)
- tape = tape.expand(depth=2, stop_at=lambda obj: obj.name in dev.operations)
+ tapes, _ = dev.preprocess()[0]([tape])
+ assert len(tapes) == 1
- res = dev.execute(tape).flatten()
+ res = dev.execute(tapes)[0].flatten()
initial_estimate = np.argmax(res) / 2 ** (wires - 1)
# We need to rescale because RX is exp(- i theta X / 2) and we expect a unitary of the
@@ -150,8 +151,9 @@ def test_phase_estimated_two_qubit(self):
qml.probs(estimation_wires)
tape = qml.tape.QuantumScript.from_queue(q)
- tape = tape.expand(depth=2, stop_at=lambda obj: obj.name in dev.operations)
- res = dev.execute(tape).flatten()
+ tapes, _ = dev.preprocess()[0]([tape])
+ assert len(tapes) == 1
+ res = dev.execute(tapes)[0].flatten()
if phase < 0:
estimate = np.argmax(res) / 2 ** (wires - 2) - 1
@@ -195,8 +197,9 @@ def test_phase_estimated_single_ops(self, param):
prep=[qml.StatePrep(eig_vec, wires=target_wires)],
)
- tape = tape.expand(depth=2, stop_at=lambda obj: obj.name in dev.operations)
- res = dev.execute(tape).flatten()
+ tapes, _ = dev.preprocess()[0]([tape])
+ res = dev.execute(tapes)[0].flatten()
+ assert len(tapes) == 1
estimate = np.argmax(res) / 2 ** (wires - 2)
estimates.append(estimate)
@@ -237,8 +240,9 @@ def test_phase_estimated_ops(self, param):
prep=[qml.StatePrep(eig_vec, wires=target_wires)],
)
- tape = tape.expand(depth=2, stop_at=lambda obj: obj.name in dev.operations)
- res = dev.execute(tape).flatten()
+ tapes, _ = dev.preprocess()[0]([tape])
+ assert len(tapes) == 1
+ res = dev.execute(tapes)[0].flatten()
estimate = np.argmax(res) / 2 ** (wires - 2)
estimates.append(estimate)
diff --git a/tests/templates/test_subroutines/test_single_excitation.py b/tests/templates/test_subroutines/test_single_excitation.py
index 69bf98d5719..76eda25a2b8 100644
--- a/tests/templates/test_subroutines/test_single_excitation.py
+++ b/tests/templates/test_subroutines/test_single_excitation.py
@@ -118,17 +118,18 @@ def test_custom_wire_labels(self, tol):
@qml.qnode(dev)
def circuit():
qml.FermionicSingleExcitation(0.4, wires=[1, 0, 2])
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
qml.FermionicSingleExcitation(0.4, wires=["a", "z", "k"])
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
diff --git a/tests/templates/test_subroutines/test_uccsd.py b/tests/templates/test_subroutines/test_uccsd.py
index 5aab270d5d6..22ed28965b3 100644
--- a/tests/templates/test_subroutines/test_uccsd.py
+++ b/tests/templates/test_subroutines/test_uccsd.py
@@ -162,7 +162,7 @@ def circuit():
d_wires=[[[0, 1], [2, 3]]],
init_state=np.array([0, 1, 0, 1]),
)
- return qml.expval(qml.Identity(0))
+ return qml.expval(qml.Identity(0)), qml.state()
@qml.qnode(dev2)
def circuit2():
@@ -173,12 +173,13 @@ def circuit2():
d_wires=[[["z", "a"], ["k", "e"]]],
init_state=np.array([0, 1, 0, 1]),
)
- return qml.expval(qml.Identity("z"))
+ return qml.expval(qml.Identity("z")), qml.state()
- circuit()
- circuit2()
+ res1, state1 = circuit()
+ res2, state2 = circuit2()
- assert np.allclose(dev.state, dev2.state, atol=tol, rtol=0)
+ assert np.allclose(res1, res2, atol=tol, rtol=0)
+ assert np.allclose(state1, state2, atol=tol, rtol=0)
class TestInputs:
@@ -213,7 +214,7 @@ class TestInputs:
[[0, 2]],
[],
np.array([1, 1, 0, 0, 0]),
- "BasisState parameter and wires",
+ "Basis states must be of length 4",
),
(
np.array([-2.8, 1.6]),
diff --git a/tests/test_debugging.py b/tests/test_debugging.py
index 38769399e42..1f95d33e3ee 100644
--- a/tests/test_debugging.py
+++ b/tests/test_debugging.py
@@ -54,30 +54,29 @@ def circuit():
assert all(np.allclose(v1, v2) for v1, v2 in zip(result.values(), expected.values()))
# pylint: disable=protected-access
- def test_default_qubit2(self):
+ @pytest.mark.parametrize("method", [None, "backprop", "parameter-shift", "adjoint"])
+ def test_default_qubit2(self, method):
"""Test that multiple snapshots are returned correctly on the new
state-vector simulator."""
- dev = qml.devices.DefaultQubit()
+ dev = qml.device("default.qubit")
# TODO: add additional QNode test once the new device supports it
- ops = [
- qml.Snapshot(),
- qml.Hadamard(wires=0),
- qml.Snapshot("very_important_state"),
- qml.CNOT(wires=[0, 1]),
- qml.Snapshot(),
- ]
- qs = qml.tape.QuantumScript(ops, [qml.expval(qml.PauliX(0))])
+ @qml.qnode(dev, diff_method=method)
+ def circuit():
+ qml.Snapshot()
+ qml.Hadamard(wires=0)
+ qml.Snapshot("very_important_state")
+ qml.CNOT(wires=[0, 1])
+ qml.Snapshot()
+ return qml.expval(qml.PauliX(0))
- dev.execute(qs)
+ circuit()
assert dev._debugger is None
+ if method is not None:
+ assert circuit.interface == "auto"
- with qml.debugging._Debugger(dev) as dbg:
- dev.execute(qs)
-
- result = dbg.snapshots
-
+ result = qml.snapshots(circuit)()
expected = {
0: np.array([1, 0, 0, 0]),
"very_important_state": np.array([1 / np.sqrt(2), 0, 1 / np.sqrt(2), 0]),
diff --git a/tests/test_qnode.py b/tests/test_qnode.py
index 2e5cb755128..3934b9ee9cf 100644
--- a/tests/test_qnode.py
+++ b/tests/test_qnode.py
@@ -43,7 +43,7 @@ class TestValidation:
def test_invalid_interface(self):
"""Test that an exception is raised for an invalid interface"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
test_interface = "something"
expected_error = rf"Unknown interface {test_interface}\. Interface must be one of"
@@ -53,7 +53,7 @@ def test_invalid_interface(self):
def test_changing_invalid_interface(self):
"""Test that an exception is raised for an invalid interface
on a pre-existing QNode"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
test_interface = "something"
@qnode(dev)
@@ -72,7 +72,7 @@ def test_valid_interface(self):
"""Test that changing to a valid interface works as expected, and the
diff method is updated as required."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
@qnode(dev, interface="autograd", diff_method="best")
def circuit(x):
@@ -95,7 +95,7 @@ def test_invalid_device(self):
def test_validate_device_method(self, monkeypatch):
"""Test that the method for validating the device diff method
tape works as expected"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
with pytest.raises(
qml.QuantumFunctionError,
@@ -124,7 +124,7 @@ def test_validate_backprop_method_invalid_device(self):
def test_validate_backprop_method_invalid_interface(self, monkeypatch):
"""Test that the method for validating the backprop diff method
tape raises an exception if the wrong interface is provided"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
test_interface = "something"
monkeypatch.setitem(dev._capabilities, "passthru_interface", test_interface)
@@ -136,7 +136,7 @@ def test_validate_backprop_method_invalid_interface(self, monkeypatch):
def test_validate_backprop_method(self, monkeypatch):
"""Test that the method for validating the backprop diff method
tape works as expected"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
test_interface = "something"
monkeypatch.setitem(dev._capabilities, "passthru_interface", test_interface)
@@ -154,7 +154,7 @@ def test_validate_backprop_method_all_interface_names(self, accepted_name, offic
if accepted_name in {None, "auto", "scipy"}:
pytest.skip("None is not a backprop interface.")
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
diff_method, _, new_dev = QNode._validate_backprop_method(dev, accepted_name)
@@ -165,7 +165,7 @@ def test_validate_backprop_method_all_interface_names(self, accepted_name, offic
def test_validate_backprop_child_method(self, monkeypatch):
"""Test that the method for validating the backprop diff method
tape works as expected if a child device supports backprop"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
test_interface = "something"
orig_capabilities = dev.capabilities().copy()
@@ -182,7 +182,7 @@ def test_validate_backprop_child_method(self, monkeypatch):
def test_validate_backprop_child_method_wrong_interface(self, monkeypatch):
"""Test that the method for validating the backprop diff method
tape raises an error if a child device supports backprop but using a different interface"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
test_interface = "something"
orig_capabilities = dev.capabilities().copy()
@@ -196,7 +196,7 @@ def test_validate_backprop_child_method_wrong_interface(self, monkeypatch):
# pylint: disable=protected-access
@pytest.mark.autograd
- @pytest.mark.parametrize("device_string", ("default.qubit", "default.qubit.autograd"))
+ @pytest.mark.parametrize("device_string", ("default.qubit.legacy", "default.qubit.autograd"))
def test_validate_backprop_finite_shots(self, device_string):
"""Test that a device with finite shots cannot be used with backpropagation."""
dev = qml.device(device_string, wires=1, shots=100)
@@ -209,7 +209,7 @@ def test_validate_backprop_finite_shots(self, device_string):
def test_parameter_shift_qubit_device(self):
"""Test that the _validate_parameter_shift method
returns the correct gradient transform for qubit devices."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
gradient_fn = QNode._validate_parameter_shift(dev)
assert gradient_fn[0] is qml.gradients.param_shift
@@ -242,7 +242,7 @@ def capabilities(cls):
return capabilities
monkeypatch.setattr(qml.devices.DefaultQubitLegacy, "capabilities", capabilities)
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
with pytest.raises(
qml.QuantumFunctionError, match="does not support the parameter-shift rule"
@@ -254,7 +254,7 @@ def capabilities(cls):
def test_best_method_is_device(self, monkeypatch):
"""Test that the method for determining the best diff method
for a given device and interface returns the device"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
monkeypatch.setitem(dev._capabilities, "passthru_interface", "some_interface")
monkeypatch.setitem(dev._capabilities, "provides_jacobian", True)
@@ -270,7 +270,7 @@ def test_best_method_is_device(self, monkeypatch):
def test_best_method_is_backprop(self, monkeypatch):
"""Test that the method for determining the best diff method
for a given device and interface returns backpropagation"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
monkeypatch.setitem(dev._capabilities, "passthru_interface", "some_interface")
monkeypatch.setitem(dev._capabilities, "provides_jacobian", False)
@@ -282,7 +282,7 @@ def test_best_method_is_backprop(self, monkeypatch):
def test_best_method_is_param_shift(self, monkeypatch):
"""Test that the method for determining the best diff method
for a given device and interface returns the parameter shift rule"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
monkeypatch.setitem(dev._capabilities, "passthru_interface", "some_interface")
monkeypatch.setitem(dev._capabilities, "provides_jacobian", False)
@@ -295,7 +295,7 @@ def test_best_method_is_param_shift(self, monkeypatch):
def test_best_method_is_finite_diff(self, monkeypatch):
"""Test that the method for determining the best diff method
for a given device and interface returns finite differences"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
monkeypatch.setitem(dev._capabilities, "passthru_interface", "some_interface")
monkeypatch.setitem(dev._capabilities, "provides_jacobian", False)
@@ -313,7 +313,7 @@ def capabilities(cls):
def test_best_method_str_is_device(self, monkeypatch):
"""Test that the method for determining the best diff method string
for a given device and interface returns 'device'"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
monkeypatch.setitem(dev._capabilities, "passthru_interface", "some_interface")
monkeypatch.setitem(dev._capabilities, "provides_jacobian", True)
@@ -329,7 +329,7 @@ def test_best_method_str_is_device(self, monkeypatch):
def test_best_method_str_is_backprop(self, monkeypatch):
"""Test that the method for determining the best diff method string
for a given device and interface returns 'backprop'"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
monkeypatch.setitem(dev._capabilities, "passthru_interface", "some_interface")
monkeypatch.setitem(dev._capabilities, "provides_jacobian", False)
@@ -341,7 +341,7 @@ def test_best_method_str_is_backprop(self, monkeypatch):
def test_best_method_str_is_param_shift(self, monkeypatch):
"""Test that the method for determining the best diff method string
for a given device and interface returns 'parameter-shift'"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
monkeypatch.setitem(dev._capabilities, "passthru_interface", "some_interface")
monkeypatch.setitem(dev._capabilities, "provides_jacobian", False)
@@ -354,7 +354,7 @@ def test_best_method_str_is_param_shift(self, monkeypatch):
def test_best_method_str_is_finite_diff(self, monkeypatch):
"""Test that the method for determining the best diff method string
for a given device and interface returns 'finite-diff'"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
monkeypatch.setitem(dev._capabilities, "passthru_interface", "some_interface")
monkeypatch.setitem(dev._capabilities, "provides_jacobian", False)
@@ -372,7 +372,7 @@ def capabilities(cls):
def test_diff_method(self, mocker):
"""Test that a user-supplied diff method correctly returns the right
diff method."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
mock_best = mocker.patch("pennylane.QNode.get_best_method")
mock_best.return_value = ("best", {}, dev)
@@ -437,7 +437,7 @@ def test_diff_method(self, mocker):
@pytest.mark.autograd
def test_gradient_transform(self, mocker):
"""Test passing a gradient transform directly to a QNode"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
spy = mocker.spy(qml.gradients.finite_difference, "finite_diff_coeffs")
@qnode(dev, diff_method=qml.gradients.finite_diff)
@@ -451,7 +451,7 @@ def circuit(x):
def test_unknown_diff_method_string(self):
"""Test that an exception is raised for an unknown differentiation method string"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
with pytest.raises(
qml.QuantumFunctionError, match="Differentiation method hello not recognized"
@@ -460,7 +460,7 @@ def test_unknown_diff_method_string(self):
def test_unknown_diff_method_type(self):
"""Test that an exception is raised for an unknown differentiation method type"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
with pytest.raises(
qml.QuantumFunctionError,
@@ -480,7 +480,7 @@ def test_validate_adjoint_invalid_device(self):
def test_validate_adjoint_finite_shots(self):
"""Test that a UserWarning is raised when device has finite shots"""
- dev = qml.device("default.qubit", wires=1, shots=1)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=1)
with pytest.warns(
UserWarning, match="Requested adjoint differentiation to be computed with finite shots."
@@ -492,7 +492,7 @@ def test_adjoint_finite_shots(self):
on QNode construction when the device has finite shots
"""
- dev = qml.device("default.qubit", wires=1, shots=1)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=1)
@qnode(dev, diff_method="adjoint")
def circ():
@@ -507,7 +507,7 @@ def circ():
def test_sparse_diffmethod_error(self):
"""Test that an error is raised when the observable is SparseHamiltonian and the
differentiation method is not parameter-shift."""
- dev = qml.device("default.qubit", wires=2, shots=None)
+ dev = qml.device("default.qubit.legacy", wires=2, shots=None)
@qnode(dev, diff_method="backprop")
def circuit(param):
@@ -523,7 +523,7 @@ def circuit(param):
def test_qnode_print(self):
"""Test that printing a QNode object yields the right information."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
def func(x):
qml.RX(x, wires=0)
@@ -533,7 +533,7 @@ def func(x):
assert (
repr(qn)
- == ""
+ == ""
)
qn = QNode(func, dev, interface="autograd")
@@ -547,7 +547,7 @@ def func(x):
def test_diff_method_none(self, tol):
"""Test that diff_method=None creates a QNode with no interface, and no
device swapping."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
@qnode(dev, diff_method=None)
def circuit(x):
@@ -569,7 +569,7 @@ def circuit(x):
# pylint: disable=unused-variable
def test_unrecognized_kwargs_raise_warning(self):
"""Test that passing gradient_kwargs not included in qml.gradients.SUPPORTED_GRADIENT_KWARGS raises warning"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
with warnings.catch_warnings(record=True) as w:
@@ -585,7 +585,7 @@ def circuit(params):
def test_incorrect_diff_method_kwargs_raise_warning(self):
"""Tests that using one of the incorrect kwargs previously used in some examples in PennyLane
(grad_method, gradient_fn) to set the qnode diff_method raises a warning"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
with warnings.catch_warnings(record=True) as w:
@@ -605,7 +605,7 @@ def circuit2(params):
def test_auto_interface_tracker_device_switched(self):
"""Test that checks that the tracker is switched to the new device."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
@qml.qnode(dev)
def circuit(params):
@@ -627,7 +627,7 @@ def circuit(params):
def test_autograd_interface_device_switched_no_warnings(self):
"""Test that checks that no warning is raised for device switch when you define an interface."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
@qml.qnode(dev, interface="autograd")
def circuit(params):
@@ -642,7 +642,7 @@ def circuit(params):
def test_not_giving_mode_kwarg_does_not_raise_warning(self):
"""Test that not providing a value for mode does not raise a warning."""
with warnings.catch_warnings(record=True) as record:
- _ = qml.QNode(lambda f: f, qml.device("default.qubit", wires=1))
+ _ = qml.QNode(lambda f: f, qml.device("default.qubit.legacy", wires=1))
assert len(record) == 0
@@ -652,7 +652,7 @@ class TestTapeConstruction:
def test_basic_tape_construction(self, tol):
"""Test that a quantum tape is properly constructed"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
def func(x, y):
qml.RX(x, wires=0)
@@ -685,7 +685,7 @@ def func(x, y):
def test_jacobian(self):
"""Test the jacobian computation"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
def func(x, y):
qml.RX(x, wires=0)
@@ -709,7 +709,7 @@ def func(x, y):
def test_returning_non_measurements(self):
"""Test that an exception is raised if a non-measurement
is returned from the QNode."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
def func0(x, y):
qml.RX(x, wires=0)
@@ -753,7 +753,7 @@ def func3(x, y):
def test_inconsistent_measurement_order(self):
"""Test that an exception is raised if measurements are returned in an
order different to how they were queued on the tape"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
def func(x, y):
qml.RX(x, wires=0)
@@ -773,7 +773,7 @@ def func(x, y):
def test_consistent_measurement_order(self):
"""Test evaluation proceeds as expected if measurements are returned in the
same order to how they were queued on the tape"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
contents = []
@@ -804,13 +804,13 @@ def circuit(x):
qml.RX(x, wires=0)
return qml.expval(qml.PauliZ(0))
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
qn = QNode(circuit, dev)
with pytest.raises(qml.QuantumFunctionError, match="Operator RX must act on all wires"):
qn(0.5)
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
qn = QNode(circuit, dev)
assert np.allclose(qn(0.5), np.cos(0.5), atol=tol, rtol=0)
@@ -842,7 +842,7 @@ def test_jit_counts_raises_error(self):
jitting raises an error."""
import jax
- dev = qml.device("default.qubit", wires=2, shots=5)
+ dev = qml.device("default.qubit.legacy", wires=2, shots=5)
def circuit1(param):
qml.Hadamard(0)
@@ -876,7 +876,7 @@ def circuit2(param):
def test_decorator(tol):
"""Test that the decorator correctly creates a QNode."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
@qnode(dev)
def func(x, y):
@@ -922,7 +922,7 @@ def func():
qml.CNOT(wires=[0, 1])
return qml.expval(qml.PauliZ(0))
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
qn = QNode(func, dev, interface="autograd")
for _ in range(2):
@@ -946,7 +946,7 @@ def func():
qml.CNOT(wires=[0, 1])
return qml.expval(qml.PauliZ(0))
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
qn = QNode(func, dev, interface=interface)
for _ in range(2):
qn()
@@ -975,7 +975,7 @@ def func():
qml.CNOT(wires=[0, 1])
return qml.expval(qml.PauliZ(0))
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
qn = QNode(func, dev, interface=interface)
for _ in range(2):
qn()
@@ -998,7 +998,7 @@ def test_num_exec_caching_device_swap(self):
"""Tests that if we swapped the original device (e.g., when
diff_method='backprop') then the number of executions recorded is
correct."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
cache = {}
@@ -1019,7 +1019,7 @@ def test_num_exec_caching_device_swap_two_exec(self):
"""Tests that if we swapped the original device (e.g., when
diff_method='backprop') then the number of executions recorded is
correct even with multiple QNode evaluations."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
cache = {}
@@ -1054,7 +1054,7 @@ def test_single_expectation_value_with_argnum_one(self, diff_method, tol):
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=3)
+ dev = qml.device("default.qubit.legacy", wires=3)
x = pnp.array(0.543, requires_grad=True)
y = pnp.array(-0.654, requires_grad=True)
@@ -1078,7 +1078,7 @@ def circuit(x, y):
def test_no_defer_measurements_if_supported(self, mocker):
"""Test that the defer_measurements transform is not used during
QNode construction if the device supports mid-circuit measurements."""
- dev = qml.device("default.qubit", wires=3)
+ dev = qml.device("default.qubit.legacy", wires=3)
mocker.patch.object(qml.Device, "_capabilities", {"supports_mid_measure": True})
spy = mocker.spy(qml, "defer_measurements")
@@ -1103,7 +1103,7 @@ def test_defer_meas_if_mcm_unsupported(self, first_par, sec_par, return_type, mo
"""Tests that the transform using the deferred measurement principle is
applied if the device doesn't support mid-circuit measurements
natively."""
- dev = qml.device("default.qubit", wires=3)
+ dev = qml.device("default.qubit.legacy", wires=3)
@qml.qnode(dev)
def cry_qnode(x, y):
@@ -1132,7 +1132,7 @@ def conditional_ry_qnode(x, y):
def test_drawing_has_deferred_measurements(self):
"""Test that `qml.draw` with qnodes uses defer_measurements
to draw circuits with mid-circuit measurements."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
@qml.qnode(dev)
def circuit(x):
@@ -1150,7 +1150,7 @@ def circuit(x):
def test_sampling_with_mcm(self, basis_state, mocker):
"""Tests that a QNode with qml.sample and mid-circuit measurements
returns the expected results."""
- dev = qml.device("default.qubit", wires=3, shots=1000)
+ dev = qml.device("default.qubit.legacy", wires=3, shots=1000)
first_par = np.pi
@@ -1182,7 +1182,7 @@ def test_conditional_ops_tensorflow(self, interface):
"""Test conditional operations with TensorFlow."""
import tensorflow as tf
- dev = qml.device("default.qubit", wires=3)
+ dev = qml.device("default.qubit.legacy", wires=3)
@qml.qnode(dev, interface=interface, diff_method="parameter-shift")
def cry_qnode(x):
@@ -1225,7 +1225,7 @@ def test_conditional_ops_torch(self, interface):
"""Test conditional operations with Torch."""
import torch
- dev = qml.device("default.qubit", wires=3)
+ dev = qml.device("default.qubit.legacy", wires=3)
@qml.qnode(dev, interface=interface, diff_method="parameter-shift")
def cry_qnode(x):
@@ -1264,7 +1264,7 @@ def test_conditional_ops_jax(self, jax_interface):
import jax
jnp = jax.numpy
- dev = qml.device("default.qubit", wires=3)
+ dev = qml.device("default.qubit.legacy", wires=3)
@qml.qnode(dev, interface=jax_interface, diff_method="parameter-shift")
def cry_qnode(x):
@@ -1295,7 +1295,7 @@ def conditional_ry_qnode(x):
def test_qnode_does_not_support_nested_queuing(self):
"""Test that operators in QNodes are not queued to surrounding contexts."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
@qml.qnode(dev)
def circuit():
@@ -1315,7 +1315,7 @@ class TestShots:
# pylint: disable=unexpected-keyword-arg
def test_specify_shots_per_call_sample(self):
"""Tests that shots can be set per call for a sample return type."""
- dev = qml.device("default.qubit", wires=1, shots=10)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=10)
@qnode(dev)
def circuit(a):
@@ -1331,7 +1331,7 @@ def circuit(a):
def test_specify_shots_per_call_expval(self):
"""Tests that shots can be set per call for an expectation value.
Note: this test has a vanishingly small probability to fail."""
- dev = qml.device("default.qubit", wires=1, shots=None)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=None)
@qnode(dev)
def circuit():
@@ -1357,7 +1357,7 @@ def test_no_shots_per_call_if_user_has_shots_qfunc_kwarg(self):
"""Tests that the per-call shots overwriting is suspended if user
has a shots keyword argument, but a warning is raised."""
- dev = qml.device("default.qubit", wires=2, shots=10)
+ dev = qml.device("default.qubit.legacy", wires=2, shots=10)
def circuit(a, shots=0):
qml.RX(a, wires=shots)
@@ -1381,7 +1381,7 @@ def circuit(a, shots=0):
def test_no_shots_per_call_if_user_has_shots_qfunc_arg(self):
"""Tests that the per-call shots overwriting is suspended
if user has a shots argument, but a warning is raised."""
- dev = qml.device("default.qubit", wires=[0, 1], shots=10)
+ dev = qml.device("default.qubit.legacy", wires=[0, 1], shots=10)
def ansatz0(a, shots):
qml.RX(a, wires=shots)
@@ -1396,7 +1396,7 @@ def ansatz0(a, shots):
assert len(circuit(0.8, 1)) == 10
assert circuit.qtape.operations[0].wires.labels == (1,)
- dev = qml.device("default.qubit", wires=2, shots=10)
+ dev = qml.device("default.qubit.legacy", wires=2, shots=10)
with pytest.warns(
UserWarning, match="The 'shots' argument name is reserved for overriding"
@@ -1414,7 +1414,7 @@ def ansatz1(a, shots):
def test_shots_setting_does_not_mutate_device(self):
"""Tests that per-call shots setting does not change the number of shots in the device."""
- dev = qml.device("default.qubit", wires=1, shots=3)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=3)
@qnode(dev)
def circuit(a):
@@ -1428,7 +1428,7 @@ def circuit(a):
def test_warning_finite_shots_dev(self):
"""Tests that a warning is raised when caching is used with finite shots."""
- dev = qml.device("default.qubit", wires=1, shots=5)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=5)
@qml.qnode(dev, cache={})
def circuit(x):
@@ -1443,7 +1443,7 @@ def circuit(x):
# pylint: disable=unexpected-keyword-arg
def test_warning_finite_shots_override(self):
"""Tests that a warning is raised when caching is used with finite shots."""
- dev = qml.device("default.qubit", wires=1, shots=5)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=5)
@qml.qnode(dev, cache={})
def circuit(x):
@@ -1457,7 +1457,7 @@ def circuit(x):
def test_warning_finite_shots_tape(self):
"""Tests that a warning is raised when caching is used with finite shots."""
- dev = qml.device("default.qubit", wires=1, shots=5)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=5)
with qml.queuing.AnnotatedQueue() as q:
qml.RZ(0.3, wires=0)
@@ -1472,7 +1472,7 @@ def test_warning_finite_shots_tape(self):
def test_no_warning_infinite_shots(self):
"""Tests that no warning is raised when caching is used with infinite shots."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
@qml.qnode(dev, cache={})
def circuit(x):
@@ -1487,7 +1487,7 @@ def circuit(x):
@pytest.mark.autograd
def test_no_warning_internal_cache_reuse(self):
"""Tests that no warning is raised when only the internal cache is reused."""
- dev = qml.device("default.qubit", wires=1, shots=5)
+ dev = qml.device("default.qubit.legacy", wires=1, shots=5)
@qml.qnode(dev, cache=True)
def circuit(x):
@@ -1510,7 +1510,7 @@ def circuit(x):
)
def test_tape_shots_set_on_call(self, shots, total_shots, shot_vector):
"""test that shots are placed on the tape if they are specified during a call."""
- dev = qml.device("default.qubit", wires=2, shots=5)
+ dev = qml.device("default.qubit.legacy", wires=2, shots=5)
def func(x, y):
qml.RX(x, wires=0)
@@ -1548,7 +1548,7 @@ def qn2(x, y):
class TestTransformProgramIntegration:
def test_transform_program_modifies_circuit(self):
"""Test qnode integration with a transform that turns the circuit into just a pauli x."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
def null_postprocessing(results):
return results[0]
@@ -1581,7 +1581,7 @@ def circuit(x):
def tet_transform_program_modifies_results(self):
"""Test integration with a transform that modifies the result output."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
@qml.transforms.core.transform
def pin_result(
@@ -1606,7 +1606,7 @@ def circuit(x):
def test_transform_order_circuit_processing(self):
"""Test that transforms are applied in the correct order in integration."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
def null_postprocessing(results):
return results[0]
@@ -1653,7 +1653,7 @@ def circuit2(x):
def test_transform_order_postprocessing(self):
"""Test that transform postprocessing is called in the right order."""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
def scale_by_factor(results, factor):
return results[0] * factor
@@ -1869,7 +1869,7 @@ class TestTapeExpansion:
)
def test_device_expansion(self, diff_method, mode, mocker):
"""Test expansion of an unsupported operation on the device"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
# pylint: disable=too-few-public-methods
class UnsupportedOp(qml.operation.Operation):
@@ -1902,7 +1902,7 @@ def circuit(x):
def test_no_gradient_expansion(self, mocker):
"""Test that an unsupported operation with defined gradient recipe is
not expanded"""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
# pylint: disable=too-few-public-methods
class UnsupportedOp(qml.operation.Operation):
@@ -1947,7 +1947,7 @@ def circuit(x):
def test_gradient_expansion(self, mocker):
"""Test that a *supported* operation with no gradient recipe is
expanded when applying the gradient transform, but not for execution."""
- dev = qml.device("default.qubit", wires=1)
+ dev = qml.device("default.qubit.legacy", wires=1)
# pylint: disable=too-few-public-methods
class PhaseShift(qml.PhaseShift):
@@ -1992,7 +1992,7 @@ def circuit(x):
def test_hamiltonian_expansion_analytic(self):
"""Test result if there are non-commuting groups and the number of shots is None"""
- dev = qml.device("default.qubit", wires=3, shots=None)
+ dev = qml.device("default.qubit.legacy", wires=3, shots=None)
obs = [qml.PauliX(0), qml.PauliX(0) @ qml.PauliZ(1), qml.PauliZ(0) @ qml.PauliZ(1)]
c = np.array([-0.6543, 0.24, 0.54])
@@ -2011,7 +2011,7 @@ def circuit():
def test_hamiltonian_expansion_finite_shots(self, mocker):
"""Test that the Hamiltonian is expanded if there
are non-commuting groups and the number of shots is finite"""
- dev = qml.device("default.qubit", wires=3, shots=50000)
+ dev = qml.device("default.qubit.legacy", wires=3, shots=50000)
obs = [qml.PauliX(0), qml.PauliX(0) @ qml.PauliZ(1), qml.PauliZ(0) @ qml.PauliZ(1)]
c = np.array([-0.6543, 0.24, 0.54])
@@ -2036,7 +2036,7 @@ def circuit():
def test_invalid_hamiltonian_expansion_finite_shots(self):
"""Test that an error is raised if multiple expectations are requested
when using finite shots"""
- dev = qml.device("default.qubit", wires=3, shots=50000)
+ dev = qml.device("default.qubit.legacy", wires=3, shots=50000)
obs = [qml.PauliX(0), qml.PauliX(0) @ qml.PauliZ(1), qml.PauliZ(0) @ qml.PauliZ(1)]
c = np.array([-0.6543, 0.24, 0.54])
@@ -2057,7 +2057,7 @@ def circuit():
def test_device_expansion_strategy(self, mocker):
"""Test that the device expansion strategy performs the device
decomposition at construction time, and not at execution time"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
x = pnp.array(0.5, requires_grad=True)
@qnode(dev, diff_method="parameter-shift", expansion_strategy="device")
@@ -2083,7 +2083,7 @@ def circuit(x):
def test_expansion_multiple_qwc_observables(self, mocker):
"""Test that the QNode correctly expands tapes that return
multiple measurements of commuting observables"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
obs = [qml.PauliX(0), qml.PauliX(0) @ qml.PauliY(1)]
@qml.qnode(dev)
diff --git a/tests/test_return_types.py b/tests/test_return_types.py
index 733ff8e6119..6fcbe5298fd 100644
--- a/tests/test_return_types.py
+++ b/tests/test_return_types.py
@@ -22,7 +22,7 @@
test_wires = [2, 3, 4]
-devices = ["default.qubit", "default.mixed"]
+devices = ["default.qubit.legacy", "default.mixed"]
@pytest.mark.parametrize("interface, shots", [["autograd", None], ["auto", 100]])
@@ -32,7 +32,7 @@ class TestSingleReturnExecute:
@pytest.mark.parametrize("wires", test_wires)
def test_state_default(self, wires, interface, shots):
"""Return state with default.qubit."""
- dev = qml.device("default.qubit", wires=wires, shots=shots)
+ dev = qml.device("default.qubit.legacy", wires=wires, shots=shots)
def circuit(x):
qml.Hadamard(wires=[0])
@@ -223,7 +223,7 @@ def test_sample(self, measurement, interface, shots):
if shots is None:
pytest.skip("Sample requires finite shots.")
- dev = qml.device("default.qubit", wires=2, shots=shots)
+ dev = qml.device("default.qubit.legacy", wires=2, shots=shots)
def circuit(x):
qml.Hadamard(wires=[0])
@@ -244,7 +244,7 @@ def test_counts(self, measurement, interface, shots):
if shots is None:
pytest.skip("Counts requires finite shots.")
- dev = qml.device("default.qubit", wires=2, shots=shots)
+ dev = qml.device("default.qubit.legacy", wires=2, shots=shots)
def circuit(x):
qml.Hadamard(wires=[0])
@@ -1221,7 +1221,7 @@ def return_type(self):
DummyMeasurement(obs=qml.PauliZ(0))
tape = qml.tape.QuantumScript.from_queue(q)
- dev = qml.device("default.qubit", wires=3)
+ dev = qml.device("default.qubit.legacy", wires=3)
with pytest.raises(
qml.QuantumFunctionError, match="Unsupported return type specified for observable"
):
@@ -1231,7 +1231,7 @@ def test_state_return_with_other_types(self):
"""Test that an exception is raised when a state is returned along with another return
type"""
- dev = qml.device("default.qubit", wires=2)
+ dev = qml.device("default.qubit.legacy", wires=2)
with qml.queuing.AnnotatedQueue() as q:
qml.PauliX(wires=0)
@@ -1248,7 +1248,7 @@ def test_state_return_with_other_types(self):
def test_entropy_no_custom_wires(self):
"""Test that entropy cannot be returned with custom wires."""
- dev = qml.device("default.qubit", wires=["a", 1])
+ dev = qml.device("default.qubit.legacy", wires=["a", 1])
with qml.queuing.AnnotatedQueue() as q:
qml.PauliX(wires="a")
@@ -1264,7 +1264,7 @@ def test_entropy_no_custom_wires(self):
def test_custom_wire_labels_error(self):
"""Tests that an error is raised when mutual information is measured
with custom wire labels"""
- dev = qml.device("default.qubit", wires=["a", "b"])
+ dev = qml.device("default.qubit.legacy", wires=["a", "b"])
with qml.queuing.AnnotatedQueue() as q:
qml.PauliX(wires="a")
diff --git a/tests/test_return_types_dq2.py b/tests/test_return_types_dq2.py
new file mode 100644
index 00000000000..3acae93dc59
--- /dev/null
+++ b/tests/test_return_types_dq2.py
@@ -0,0 +1,1265 @@
+# Copyright 2022 Xanadu Quantum Technologies Inc.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+Unit tests for the new return types.
+"""
+import numpy as np
+import pytest
+
+import pennylane as qml
+from pennylane.measurements import MeasurementProcess
+
+test_wires = [2, 3, 4]
+
+devices = ["default.qubit"]
+
+
+@pytest.mark.parametrize("interface, shots", [["autograd", None], ["auto", 100]])
+class TestSingleReturnExecute:
+ """Test that single measurements return behavior does not change."""
+
+ @pytest.mark.parametrize("wires", test_wires)
+ def test_state_default(self, wires, interface, shots):
+ """Return state with default.qubit."""
+ dev = qml.device("default.qubit", wires=wires, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.state()
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ if dev.shots:
+ pytest.skip("cannot return analytic measurements with finite shots.")
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ assert res[0].shape == (2**wires,)
+ assert isinstance(res[0], (np.ndarray, np.float64))
+
+ @pytest.mark.parametrize("device", devices)
+ @pytest.mark.parametrize("d_wires", test_wires)
+ def test_density_matrix(self, d_wires, device, interface, shots):
+ """Return density matrix."""
+ dev = qml.device(device, wires=4, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.density_matrix(wires=range(0, d_wires))
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ if dev.shots:
+ pytest.skip("cannot return analytic measurements with finite shots.")
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ assert res[0].shape == (2**d_wires, 2**d_wires)
+ assert isinstance(res[0], (np.ndarray, np.float64))
+
+ @pytest.mark.parametrize("device", devices)
+ def test_expval(self, device, interface, shots):
+ """Return a single expval."""
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.expval(qml.PauliZ(wires=1))
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ assert res[0].shape == ()
+ assert isinstance(res[0], (np.ndarray, np.float64))
+
+ @pytest.mark.parametrize("device", devices)
+ def test_var(self, device, interface, shots):
+ """Return a single var."""
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.var(qml.PauliZ(wires=1))
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ assert res[0].shape == ()
+ assert isinstance(res[0], (np.ndarray, np.float64))
+
+ @pytest.mark.parametrize("device", devices)
+ def test_vn_entropy(self, device, interface, shots):
+ """Return a single vn entropy."""
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.vn_entropy(wires=0)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ if dev.shots:
+ pytest.skip("cannot return analytic measurements with finite shots.")
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ assert res[0].shape == ()
+ assert isinstance(res[0], (np.ndarray, np.float64))
+
+ @pytest.mark.parametrize("device", devices)
+ def test_mutual_info(self, device, interface, shots):
+ """Return a single mutual information."""
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.mutual_info(wires0=[0], wires1=[1])
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ if dev.shots:
+ pytest.skip("cannot return analytic measurements with finite shots.")
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ assert res[0].shape == ()
+ assert isinstance(res[0], (np.ndarray, np.float64))
+
+ herm = np.diag([1, 2, 3, 4])
+ probs_data = [
+ (None, [0]),
+ (None, [0, 1]),
+ (qml.PauliZ(0), None),
+ (qml.Hermitian(herm, wires=[1, 0]), None),
+ ]
+
+ # pylint: disable=too-many-arguments
+ @pytest.mark.parametrize("device", devices)
+ @pytest.mark.parametrize("op,wires", probs_data)
+ def test_probs(self, op, wires, device, interface, shots):
+ """Return a single prob."""
+ dev = qml.device(device, wires=3, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.probs(op=op, wires=wires)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ if wires is None:
+ wires = op.wires
+
+ assert res[0].shape == (2 ** len(wires),)
+ assert isinstance(res[0], (np.ndarray, np.float64))
+
+ @pytest.mark.parametrize("measurement", [qml.sample(qml.PauliZ(0)), qml.sample(wires=[0])])
+ def test_sample(self, measurement, interface, shots):
+ """Test the sample measurement."""
+ if shots is None:
+ pytest.skip("Sample requires finite shots.")
+
+ dev = qml.device("default.qubit", wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(measurement)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ assert isinstance(res[0], (np.ndarray, np.float64))
+ assert res[0].shape == (shots,)
+
+ @pytest.mark.parametrize("measurement", [qml.counts(qml.PauliZ(0)), qml.counts(wires=[0])])
+ def test_counts(self, measurement, interface, shots):
+ """Test the counts measurement."""
+ if shots is None:
+ pytest.skip("Counts requires finite shots.")
+
+ dev = qml.device("default.qubit", wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(measurement)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None, interface=interface)
+
+ assert isinstance(res[0], dict)
+ assert sum(res[0].values()) == shots
+
+
+multi_return_wires = [([0], [1]), ([1], [0]), ([0], [0]), ([1], [1])]
+
+
+@pytest.mark.parametrize("shots", [None, 100])
+class TestMultipleReturns:
+ """Test the new return types for multiple measurements, it should always return a tuple containing the single
+ measurements.
+ """
+
+ @pytest.mark.parametrize("device", devices)
+ def test_multiple_expval(self, device, shots):
+ """Return multiple expvals."""
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.expval(qml.PauliZ(wires=0)), qml.expval(qml.PauliZ(wires=1))
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == 2
+
+ assert isinstance(res[0][0], (np.ndarray, np.float64))
+ assert res[0][0].shape == ()
+
+ assert isinstance(res[0][1], (np.ndarray, np.float64))
+ assert res[0][1].shape == ()
+
+ @pytest.mark.parametrize("device", devices)
+ def test_multiple_var(self, device, shots):
+ """Return multiple vars."""
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.var(qml.PauliZ(wires=0)), qml.var(qml.PauliZ(wires=1))
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == 2
+
+ assert isinstance(res[0][0], (np.ndarray, np.float64))
+ assert res[0][0].shape == ()
+
+ assert isinstance(res[0][1], (np.ndarray, np.float64))
+ assert res[0][1].shape == ()
+
+ # op1, wires1, op2, wires2
+ multi_probs_data = [
+ (None, [0], None, [0]),
+ (None, [0], None, [0, 1]),
+ (None, [0, 1], None, [0]),
+ (None, [0, 1], None, [0, 1]),
+ (qml.PauliZ(0), None, qml.PauliZ(1), None),
+ (None, [0], qml.PauliZ(1), None),
+ (qml.PauliZ(0), None, None, [0]),
+ (qml.PauliZ(1), None, qml.PauliZ(0), None),
+ ]
+
+ # pylint: disable=too-many-arguments
+ @pytest.mark.parametrize("device", devices)
+ @pytest.mark.parametrize("op1,wires1,op2,wires2", multi_probs_data)
+ def test_multiple_prob(self, op1, op2, wires1, wires2, device, shots):
+ """Return multiple probs."""
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.probs(op=op1, wires=wires1), qml.probs(op=op2, wires=wires2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == 2
+
+ if wires1 is None:
+ wires1 = op1.wires
+
+ if wires2 is None:
+ wires2 = op2.wires
+
+ assert isinstance(res[0][0], (np.ndarray, np.float64))
+ assert res[0][0].shape == (2 ** len(wires1),)
+
+ assert isinstance(res[0][1], (np.ndarray, np.float64))
+ assert res[0][1].shape == (2 ** len(wires2),)
+
+ # pylint: disable=too-many-arguments
+ @pytest.mark.parametrize("device", devices)
+ @pytest.mark.parametrize("op1,wires1,op2,wires2", multi_probs_data)
+ @pytest.mark.parametrize("wires3, wires4", multi_return_wires)
+ def test_mix_meas(self, op1, wires1, op2, wires2, wires3, wires4, device, shots):
+ """Return multiple different measurements."""
+
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return (
+ qml.probs(op=op1, wires=wires1),
+ qml.vn_entropy(wires=wires3),
+ qml.probs(op=op2, wires=wires2),
+ qml.expval(qml.PauliZ(wires=wires4)),
+ )
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ if dev.shots:
+ pytest.skip("cannot return analytic measurements with finite shots.")
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ if wires1 is None:
+ wires1 = op1.wires
+
+ if wires2 is None:
+ wires2 = op2.wires
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == 4
+
+ assert isinstance(res[0][0], (np.ndarray, np.float64))
+ assert res[0][0].shape == (2 ** len(wires1),)
+
+ assert isinstance(res[0][1], (np.ndarray, np.float64))
+ assert res[0][1].shape == ()
+
+ assert isinstance(res[0][2], (np.ndarray, np.float64))
+ assert res[0][2].shape == (2 ** len(wires2),)
+
+ assert isinstance(res[0][3], (np.ndarray, np.float64))
+ assert res[0][3].shape == ()
+
+ wires = [2, 3, 4, 5]
+
+ @pytest.mark.parametrize("device", devices)
+ @pytest.mark.parametrize("wires", wires)
+ def test_list_multiple_expval(self, wires, device, shots):
+ """Return a comprehension list of multiple expvals."""
+ dev = qml.device(device, wires=wires, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return [qml.expval(qml.PauliZ(wires=i)) for i in range(0, wires)]
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == wires
+
+ for i in range(0, wires):
+ assert isinstance(res[0][i], (np.ndarray, np.float64))
+ assert res[0][i].shape == ()
+
+ @pytest.mark.parametrize("device", devices)
+ @pytest.mark.parametrize("measurement", [qml.sample(qml.PauliZ(0)), qml.sample(wires=[0])])
+ def test_expval_sample(self, measurement, shots, device):
+ """Test the expval and sample measurements together."""
+ if shots is None:
+ pytest.skip("Sample requires finite shots.")
+
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.expval(qml.PauliX(1)), qml.apply(measurement)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ # Expval
+ assert isinstance(res[0][0], (np.ndarray, np.float64))
+ assert res[0][0].shape == ()
+
+ # Sample
+ assert isinstance(res[0][1], (np.ndarray, np.float64))
+ assert res[0][1].shape == (shots,)
+
+ @pytest.mark.parametrize("device", devices)
+ @pytest.mark.parametrize("measurement", [qml.counts(qml.PauliZ(0)), qml.counts(wires=[0])])
+ def test_expval_counts(self, measurement, shots, device):
+ """Test the expval and counts measurements together."""
+ if shots is None:
+ pytest.skip("Counts requires finite shots.")
+
+ dev = qml.device(device, wires=2, shots=shots)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.expval(qml.PauliX(1)), qml.apply(measurement)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ # Expval
+ assert isinstance(res[0][0], (np.ndarray, np.float64))
+ assert res[0][0].shape == ()
+
+ # Counts
+ assert isinstance(res[0][1], dict)
+ assert sum(res[0][1].values()) == shots
+
+
+pauliz = qml.PauliZ(wires=1)
+proj = qml.Projector([1], wires=1)
+hermitian = qml.Hermitian(np.diag([1, 2]), wires=0)
+
+# Note: mutual info and vn_entropy do not support some shot vectors
+# qml.mutual_info(wires0=[0], wires1=[1]), qml.vn_entropy(wires=[0])]
+single_scalar_output_measurements = [
+ qml.expval(pauliz),
+ qml.var(pauliz),
+ qml.expval(proj),
+ qml.var(proj),
+ qml.expval(hermitian),
+ qml.var(hermitian),
+]
+
+herm = np.diag([1, 2, 3, 4])
+probs_data = [
+ (None, [0]),
+ (None, [0, 1]),
+ (qml.PauliZ(0), None),
+ (qml.Hermitian(herm, wires=[1, 0]), None),
+]
+
+shot_vectors = [[10, 1000], [1, 10, 10, 1000], [1, (10, 2), 1000]]
+
+
+@pytest.mark.parametrize("shot_vector", shot_vectors)
+@pytest.mark.parametrize("device", devices)
+class TestShotVector:
+ """Test the support for executing tapes with single measurements using a
+ device with shot vectors."""
+
+ @pytest.mark.parametrize("measurement", single_scalar_output_measurements)
+ def test_scalar(self, shot_vector, measurement, device):
+ """Test a single scalar-valued measurement."""
+ dev = qml.device(device, wires=2, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(measurement)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(r.shape == () for r in res[0])
+
+ @pytest.mark.parametrize("op,wires", probs_data)
+ def test_probs(self, shot_vector, op, wires, device):
+ """Test a single probability measurement."""
+ dev = qml.device(device, wires=2, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.probs(op=op, wires=wires)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ wires_to_use = wires if wires else op.wires
+ assert all(r.shape == (2 ** len(wires_to_use),) for r in res[0])
+
+ @pytest.mark.parametrize("wires", [[0], [2, 0], [1, 0], [2, 0, 1]])
+ def test_density_matrix(self, shot_vector, wires, device):
+ """Test a density matrix measurement."""
+ dev = qml.device(device, wires=3, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.density_matrix(wires=wires)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ if dev.shots:
+ pytest.skip("cannot return analytic measurements with finite shots.")
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ dim = 2 ** len(wires)
+ assert all(r.shape == (dim, dim) for r in res[0])
+
+ @pytest.mark.parametrize("measurement", [qml.sample(qml.PauliZ(0)), qml.sample(wires=[0])])
+ def test_samples(self, shot_vector, measurement, device):
+ """Test the sample measurement."""
+ dev = qml.device(device, wires=2, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(measurement)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shot_copies = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ assert len(res[0]) == len(all_shot_copies)
+ for r, shots in zip(res[0], all_shot_copies):
+ if shots == 1:
+ # Scalar tensors
+ assert r.shape == ()
+ else:
+ assert r.shape == (shots,)
+
+ @pytest.mark.parametrize("measurement", [qml.counts(qml.PauliZ(0)), qml.counts(wires=[0])])
+ def test_counts(self, shot_vector, measurement, device):
+ """Test the counts measurement."""
+ dev = qml.device(device, wires=2, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(measurement)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, dict) for r in res[0])
+
+
+@pytest.mark.parametrize("shot_vector", shot_vectors)
+@pytest.mark.parametrize("device", devices)
+class TestSameMeasurementShotVector:
+ """Test the support for executing tapes with the same type of measurement
+ multiple times using a device with shot vectors"""
+
+ def test_scalar(self, shot_vector, device):
+ """Test multiple scalar-valued measurements."""
+ dev = qml.device(device, wires=2, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.expval(qml.PauliX(0)), qml.var(qml.PauliZ(1))
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ for r in res[0]:
+ assert len(r) == 2
+ assert all(r.shape == () for r in r)
+
+ probs_data2 = [
+ (None, [2]),
+ (None, [2, 3]),
+ (qml.PauliZ(2), None),
+ (qml.Hermitian(herm, wires=[3, 2]), None),
+ ]
+
+ # pylint: disable=too-many-arguments
+ @pytest.mark.parametrize("op1,wires1", probs_data)
+ @pytest.mark.parametrize("op2,wires2", reversed(probs_data2))
+ def test_probs(self, shot_vector, op1, wires1, op2, wires2, device):
+ """Test multiple probability measurements."""
+ dev = qml.device(device, wires=4, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.probs(op=op1, wires=wires1), qml.probs(op=op2, wires=wires2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+
+ wires1 = wires1 if wires1 else op1.wires
+ wires2 = wires2 if wires2 else op2.wires
+ for r in res[0]:
+ assert len(r) == 2
+ assert r[0].shape == (2 ** len(wires1),)
+ assert r[1].shape == (2 ** len(wires2),)
+
+ @pytest.mark.parametrize("measurement1", [qml.sample(qml.PauliZ(0)), qml.sample(wires=[0])])
+ @pytest.mark.parametrize("measurement2", [qml.sample(qml.PauliX(1)), qml.sample(wires=[1])])
+ def test_samples(self, shot_vector, measurement1, measurement2, device):
+ """Test multiple sample measurements."""
+ dev = qml.device(device, wires=2, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(measurement1), qml.apply(measurement2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shot_copies = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ assert len(res[0]) == len(all_shot_copies)
+ for r, shots in zip(res[0], all_shot_copies):
+ shape = () if shots == 1 else (shots,)
+ assert all(res_item.shape == shape for res_item in r)
+
+ @pytest.mark.parametrize("measurement1", [qml.counts(qml.PauliZ(0)), qml.counts(wires=[0])])
+ @pytest.mark.parametrize("measurement2", [qml.counts(qml.PauliZ(0)), qml.counts(wires=[0])])
+ def test_counts(self, shot_vector, measurement1, measurement2, device):
+ """Test multiple counts measurements."""
+ dev = qml.device(device, wires=2, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(measurement1), qml.apply(measurement2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ for r in res[0]:
+ assert isinstance(r, tuple)
+ assert all(isinstance(res_item, dict) for res_item in r)
+
+
+# -------------------------------------------------
+# Shot vector multi measurement tests - test data
+# -------------------------------------------------
+
+pauliz_w2 = qml.PauliZ(wires=2)
+proj_w2 = qml.Projector([1], wires=2)
+hermitian = qml.Hermitian(np.diag([1, 2]), wires=0)
+tensor_product = qml.PauliZ(wires=2) @ qml.PauliX(wires=1)
+
+# Expval/Var with Probs
+
+scalar_probs_multi = [
+ # Expval
+ (qml.expval(pauliz_w2), qml.probs(wires=[2, 0])),
+ (qml.expval(proj_w2), qml.probs(wires=[1, 0])),
+ (qml.expval(tensor_product), qml.probs(wires=[2, 0])),
+ # Var
+ (qml.var(qml.PauliZ(wires=1)), qml.probs(wires=[0, 1])),
+ (qml.var(proj_w2), qml.probs(wires=[1, 0])),
+ (qml.var(tensor_product), qml.probs(wires=[2, 0])),
+]
+
+# Expval/Var with Sample
+
+scalar_sample_multi = [
+ # Expval
+ (qml.expval(pauliz_w2), qml.sample(op=qml.PauliZ(1) @ qml.PauliZ(0))),
+ (qml.expval(proj_w2), qml.sample(op=qml.PauliZ(1) @ qml.PauliZ(0))),
+ (qml.expval(tensor_product), qml.sample(op=qml.PauliZ(0))),
+ # Var
+ (qml.var(proj_w2), qml.sample(op=qml.PauliZ(1) @ qml.PauliZ(0))),
+ (qml.var(pauliz_w2), qml.sample(op=qml.PauliZ(1) @ qml.PauliZ(0))),
+ (qml.var(tensor_product), qml.sample(op=qml.PauliZ(0))),
+]
+
+scalar_sample_no_obs_multi = [
+ (qml.expval(qml.PauliZ(wires=1)), qml.sample()),
+ (qml.expval(qml.PauliZ(wires=1)), qml.sample(wires=[0, 1])),
+ (qml.var(qml.PauliZ(wires=1)), qml.sample(wires=[0, 1])),
+]
+
+# Expval/Var with Counts
+
+scalar_counts_multi = [
+ # Expval
+ (qml.expval(pauliz_w2), qml.counts(op=qml.PauliZ(1) @ qml.PauliZ(0))),
+ (qml.expval(proj_w2), qml.counts(op=qml.PauliZ(1) @ qml.PauliZ(0))),
+ (qml.expval(tensor_product), qml.counts(op=qml.PauliZ(0))),
+ # Var
+ (qml.var(proj_w2), qml.counts(op=qml.PauliZ(1) @ qml.PauliZ(0))),
+ (qml.var(pauliz_w2), qml.counts(op=qml.PauliZ(1) @ qml.PauliZ(0))),
+ (qml.var(tensor_product), qml.counts(op=qml.PauliZ(0))),
+]
+
+scalar_counts_no_obs_multi = [
+ (qml.expval(qml.PauliZ(wires=1)), qml.counts()),
+ (qml.expval(qml.PauliZ(wires=1)), qml.counts(wires=[0, 1])),
+ (qml.var(qml.PauliZ(wires=1)), qml.counts(wires=[0, 1])),
+]
+
+
+@pytest.mark.parametrize("shot_vector", shot_vectors)
+@pytest.mark.parametrize("device", devices)
+class TestMixMeasurementsShotVector:
+ """Test the support for executing tapes with multiple different
+ measurements using a device with shot vectors"""
+
+ @pytest.mark.parametrize("meas1,meas2", scalar_probs_multi)
+ def test_scalar_probs(self, shot_vector, meas1, meas2, device):
+ """Test scalar-valued and probability measurements"""
+ dev = qml.device(device, wires=3, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(meas1), qml.apply(meas2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res[0]
+ for m in measurement_res
+ )
+ for meas_res in res[0]:
+ for i, r in enumerate(meas_res):
+ if i % 2 == 0:
+ # Scalar-val meas
+ assert r.shape == ()
+ else:
+ assert r.shape == (2**2,)
+
+ # Probs add up to 1
+ assert np.allclose(sum(r), 1)
+
+ @pytest.mark.parametrize("meas1,meas2", scalar_sample_multi)
+ def test_scalar_sample_with_obs(self, shot_vector, meas1, meas2, device):
+ """Test scalar-valued and sample measurements where sample takes an
+ observable."""
+ dev = qml.device(device, wires=3, shots=shot_vector)
+ raw_shot_vector = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(meas1), qml.apply(meas2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res[0]
+ for m in measurement_res
+ )
+
+ for idx, shots in enumerate(raw_shot_vector):
+ for i, r in enumerate(res[0][idx]):
+ if i % 2 == 0 or shots == 1:
+ assert meas2.obs is not None
+ expected_shape = ()
+ assert r.shape == expected_shape
+ else:
+ assert r.shape == (shots,)
+
+ @pytest.mark.parametrize("meas1,meas2", scalar_sample_no_obs_multi)
+ @pytest.mark.xfail
+ def test_scalar_sample_no_obs(self, shot_vector, meas1, meas2, device):
+ """Test scalar-valued and computational basis sample measurements."""
+ dev = qml.device(device, wires=3, shots=shot_vector)
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(meas1), qml.apply(meas2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res[0]
+ for m in measurement_res
+ )
+
+ for shot_tuple in dev.shots.shot_vector:
+ for idx in range(shot_tuple.copies):
+ for i, r in enumerate(res[0][idx]):
+ if i % 2 == 0 or shot_tuple.shots == 1:
+ assert meas2.obs is not None
+ expected_shape = ()
+ assert r.shape == expected_shape
+ else:
+ assert r.shape == (shot_tuple.shots,)
+
+ @pytest.mark.parametrize("meas1,meas2", scalar_counts_multi)
+ def test_scalar_counts_with_obs(self, shot_vector, meas1, meas2, device):
+ """Test scalar-valued and counts measurements where counts takes an
+ observable."""
+ dev = qml.device(device, wires=3, shots=shot_vector)
+ raw_shot_vector = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(meas1), qml.apply(meas2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+
+ for r in res[0]:
+ assert isinstance(r[0], (np.ndarray, np.float64))
+ assert isinstance(r[1], dict)
+
+ expected_outcomes = {-1, 1}
+
+ for idx, shots in enumerate(raw_shot_vector):
+ for i, r in enumerate(res[0][idx]):
+ if i % 2 == 0:
+ assert meas2.obs is not None
+ expected_shape = ()
+ assert r.shape == expected_shape
+ else:
+ # Samples are either -1 or 1
+ assert set(r.keys()).issubset(expected_outcomes)
+ assert sum(r.values()) == shots
+
+ @pytest.mark.parametrize("meas1,meas2", scalar_counts_no_obs_multi)
+ def test_scalar_counts_no_obs(self, shot_vector, meas1, meas2, device):
+ """Test scalar-valued and computational basis counts measurements."""
+ dev = qml.device(device, wires=3, shots=shot_vector)
+ raw_shot_vector = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return qml.apply(meas1), qml.apply(meas2)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+
+ for idx, _ in enumerate(raw_shot_vector):
+ for i, r in enumerate(res[0][idx]):
+ if i % 2 == 0:
+ assert isinstance(r, (np.ndarray, np.float64))
+ assert meas2.obs is None
+ expected_shape = ()
+ assert r.shape == expected_shape
+ else:
+ assert isinstance(r, dict)
+
+ @pytest.mark.parametrize("sample_obs", [qml.PauliZ, None])
+ def test_probs_sample(self, shot_vector, sample_obs, device):
+ """Test probs and sample measurements."""
+ dev = qml.device(device, wires=3, shots=shot_vector)
+ raw_shot_vector = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ meas1_wires = [0, 1]
+ meas2_wires = [2]
+
+ @qml.qnode(device=dev)
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ if sample_obs is not None:
+ # Observable provided to sample
+ return qml.probs(wires=meas1_wires), qml.sample(sample_obs(meas2_wires))
+
+ # Only wires provided to sample
+ return qml.probs(wires=meas1_wires), qml.sample(wires=meas2_wires)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res[0]
+ for m in measurement_res
+ )
+
+ for idx, shots in enumerate(raw_shot_vector):
+ for i, r in enumerate(res[0][idx]):
+ if i % 2 == 0:
+ expected_shape = (len(meas1_wires) ** 2,)
+ assert r.shape == expected_shape
+
+ # Probs add up to 1
+ assert np.allclose(sum(r), 1)
+ else:
+ if shots == 1:
+ assert r.shape == ()
+ else:
+ expected = (shots,)
+ assert r.shape == expected
+
+ @pytest.mark.parametrize("sample_obs", [qml.PauliZ, None])
+ def test_probs_counts(self, shot_vector, sample_obs, device):
+ """Test probs and counts measurements."""
+ dev = qml.device(device, wires=3, shots=shot_vector)
+ raw_shot_vector = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ meas1_wires = [0, 1]
+ meas2_wires = [2]
+
+ @qml.qnode(device=dev)
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ if sample_obs is not None:
+ # Observable provided to sample
+ return qml.probs(wires=meas1_wires), qml.counts(sample_obs(meas2_wires))
+
+ # Only wires provided to sample
+ return qml.probs(wires=meas1_wires), qml.counts(wires=meas2_wires)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+ assert all(
+ isinstance(measurement_res[0], (np.ndarray, np.float64)) for measurement_res in res[0]
+ )
+ assert all(isinstance(measurement_res[1], dict) for measurement_res in res[0])
+
+ expected_outcomes = {-1, 1} if sample_obs is not None else {"0", "1"}
+ for idx, shots in enumerate(raw_shot_vector):
+ for i, r in enumerate(res[0][idx]):
+ if i % 2 == 0:
+ expected_shape = (len(meas1_wires) ** 2,)
+ assert r.shape == expected_shape
+
+ # Probs add up to 1
+ assert np.allclose(sum(r), 1)
+ else:
+ # Samples are -1 or 1
+ assert set(r.keys()).issubset(expected_outcomes)
+ assert sum(r.values()) == shots
+
+ @pytest.mark.parametrize("sample_wires", [[1], [0, 2]])
+ @pytest.mark.parametrize("counts_wires", [[4], [3, 5]])
+ def test_sample_counts(self, shot_vector, sample_wires, counts_wires, device):
+ """Test sample and counts measurements, each measurement with custom
+ samples or computational basis state samples."""
+ dev = qml.device(device, wires=6, shots=shot_vector)
+ raw_shot_vector = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ @qml.qnode(device=dev)
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+
+ # 1. Sample obs and Counts obs
+ if len(sample_wires) == 1 and len(counts_wires) == 1:
+ return qml.sample(qml.PauliY(sample_wires)), qml.counts(qml.PauliX(counts_wires))
+
+ # 2. Sample no obs and Counts obs
+ if len(sample_wires) > 1 and len(counts_wires) == 1:
+ return qml.sample(wires=sample_wires), qml.counts(qml.PauliX(counts_wires))
+
+ # 3. Sample obs and Counts no obs
+ if len(sample_wires) == 1 and len(counts_wires) > 1:
+ return qml.sample(qml.PauliY(sample_wires)), qml.counts(wires=counts_wires)
+
+ # 4. Sample no obs and Counts no obs
+ return qml.sample(wires=sample_wires), qml.counts(wires=counts_wires)
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+ assert all(
+ isinstance(measurement_res[0], (np.ndarray, np.float64)) for measurement_res in res[0]
+ )
+ assert all(isinstance(measurement_res[1], dict) for measurement_res in res[0])
+
+ for idx, shots in enumerate(raw_shot_vector):
+ for i, r in enumerate(res[0][idx]):
+ num_wires = len(sample_wires)
+ if shots == 1 and i % 2 == 0:
+ expected_shape = () if num_wires == 1 else (num_wires,)
+ assert r.shape == expected_shape
+ elif i % 2 == 0:
+ expected_shape = (shots,) if num_wires == 1 else (shots, num_wires)
+ assert r.shape == expected_shape
+ else:
+ assert isinstance(r, dict)
+
+ @pytest.mark.parametrize("meas1,meas2", scalar_probs_multi)
+ def test_scalar_probs_sample_counts(self, shot_vector, meas1, meas2, device):
+ """Test scalar-valued, probability, sample and counts measurements all
+ in a single qfunc."""
+ dev = qml.device(device, wires=5, shots=shot_vector)
+ raw_shot_vector = [
+ shot_tuple.shots
+ for shot_tuple in dev.shots.shot_vector
+ for _ in range(shot_tuple.copies)
+ ]
+
+ def circuit(x):
+ qml.Hadamard(wires=[0])
+ qml.CRX(x, wires=[0, 1])
+ return (
+ qml.apply(meas1),
+ qml.apply(meas2),
+ qml.sample(qml.PauliX(4)),
+ qml.counts(qml.PauliX(3)),
+ )
+
+ qnode = qml.QNode(circuit, dev)
+ qnode.construct([0.5], {})
+
+ res = qml.execute(tapes=[qnode.tape], device=dev, gradient_fn=None)
+
+ all_shots = sum(shot_tuple.copies for shot_tuple in dev.shots.shot_vector)
+
+ assert isinstance(res[0], tuple)
+ assert len(res[0]) == all_shots
+ assert all(isinstance(r, tuple) for r in res[0])
+
+ for res_idx, meas_res in enumerate(res[0]):
+ for i, r in enumerate(meas_res):
+ num_meas = i % 4
+ expval_or_var = num_meas == 0
+ probs = num_meas == 1
+ sample = num_meas == 2
+
+ if expval_or_var:
+ assert r.shape == ()
+ elif probs:
+ assert r.shape == (2**2,)
+
+ # Probs add up to 1
+ assert np.allclose(sum(r), 1)
+ elif sample:
+ shots = raw_shot_vector[res_idx]
+ if shots == 1:
+ assert r.shape == ()
+ else:
+ expected = (shots,)
+ assert r.shape == expected
+ else:
+ # Return is Counts
+ assert isinstance(r, dict)
+
+
+class TestDeviceNewUnits:
+ """Further unit tests for some new methods of Device."""
+
+ def test_unsupported_observable_return_type_raise_error(self):
+ """Check that an error is raised if the return type of an observable is unsupported"""
+ # pylint: disable=too-few-public-methods
+
+ class UnsupportedReturnType:
+ value = "unsupported"
+
+ class DummyMeasurement(MeasurementProcess):
+ @property
+ def return_type(self):
+ return UnsupportedReturnType
+
+ with qml.queuing.AnnotatedQueue() as q:
+ qml.PauliX(wires=0)
+ DummyMeasurement(obs=qml.PauliZ(0))
+
+ tape = qml.tape.QuantumScript.from_queue(q)
+ dev = qml.device("default.qubit", wires=3)
+ with pytest.raises(qml.DeviceError, match="Analytic circuits must only contain"):
+ qml.execute(tapes=[tape], device=dev, gradient_fn=None)
+
+ def test_state_return_with_other_types(self):
+ """Test that an exception is raised when a state is returned along with another return
+ type"""
+
+ dev = qml.device("default.qubit", wires=2)
+
+ with qml.queuing.AnnotatedQueue() as q:
+ qml.PauliX(wires=0)
+ qml.state()
+ qml.expval(qml.PauliZ(1))
+
+ tape = qml.tape.QuantumScript.from_queue(q)
+ res = qml.execute(tapes=[tape], device=dev, gradient_fn=None)[0]
+ assert isinstance(res, tuple) and len(res) == 2
+ assert np.array_equal(res[0], [0.0, 0.0, 1.0, 0.0])
+ assert res[1] == 1.0
+
+ def test_entropy_no_custom_wires(self):
+ """Test that entropy cannot be returned with custom wires."""
+
+ dev = qml.device("default.qubit", wires=["a", 1])
+
+ with qml.queuing.AnnotatedQueue() as q:
+ qml.PauliX(wires="a")
+ qml.vn_entropy(wires=["a"])
+
+ tape = qml.tape.QuantumScript.from_queue(q)
+ res = qml.execute(tapes=[tape], device=dev, gradient_fn=None)
+ assert res == (0,)
+
+ def test_custom_wire_labels_error(self):
+ """Tests that an error is raised when mutual information is measured
+ with custom wire labels"""
+ dev = qml.device("default.qubit", wires=["a", "b"])
+
+ with qml.queuing.AnnotatedQueue() as q:
+ qml.PauliX(wires="a")
+ qml.mutual_info(wires0=["a"], wires1=["b"])
+
+ tape = qml.tape.QuantumScript.from_queue(q)
+ res = qml.execute(tapes=[tape], device=dev, gradient_fn=None)
+ assert res == (0,)
diff --git a/tests/test_return_types_qnode.py b/tests/test_return_types_qnode.py
index d4e2c11b86d..3a3cdb93997 100644
--- a/tests/test_return_types_qnode.py
+++ b/tests/test_return_types_qnode.py
@@ -50,7 +50,7 @@ def circuit(x):
res = qnode(0.5)
assert res.shape == (2**wires,)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
@pytest.mark.parametrize("wires", test_wires)
def test_state_mixed(self, wires):
@@ -65,7 +65,7 @@ def circuit(x):
res = qnode(0.5)
assert res.shape == (2**wires, 2**wires)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
@pytest.mark.parametrize("device", devices)
@pytest.mark.parametrize("d_wires", test_wires)
@@ -83,7 +83,7 @@ def circuit(x):
dim = 3 if device == "default.qutrit" else 2
assert res.shape == (dim**d_wires, dim**d_wires)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
@pytest.mark.parametrize("device", devices)
def test_expval(self, device):
@@ -101,7 +101,7 @@ def circuit(x):
res = qnode(0.5)
assert res.shape == ()
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
@pytest.mark.parametrize("device", devices)
def test_var(self, device):
@@ -119,7 +119,7 @@ def circuit(x):
res = qnode(0.5)
assert res.shape == ()
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
@pytest.mark.parametrize("device", devices)
def test_vn_entropy(self, device):
@@ -137,7 +137,7 @@ def circuit(x):
res = qnode(0.5)
assert res.shape == ()
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
@pytest.mark.xfail(reason="qml.execute shot vec support required with new return types")
@pytest.mark.filterwarnings("ignore:Requested Von Neumann entropy with finite shots")
@@ -171,7 +171,7 @@ def circuit(x):
res = qnode(0.5)
assert res.shape == ()
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
@pytest.mark.xfail(reason="qml.execute shot vec support required with new return types")
@pytest.mark.filterwarnings("ignore:Requested mutual information with finite shots")
@@ -218,7 +218,7 @@ def circuit(x):
wires = op.wires
assert res.shape == (2 ** len(wires),)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
probs_data_qutrit = [
(qml.GellMann(0, 3), None),
@@ -243,7 +243,7 @@ def circuit(x):
wires = op.wires
assert res.shape == (3 ** len(wires),)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
@pytest.mark.parametrize("device", devices)
@pytest.mark.parametrize(
@@ -273,7 +273,7 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
if measurement.wires.tolist() != [0, 1]:
assert res.shape == (shots,)
@@ -1020,10 +1020,10 @@ def circuit(x):
assert isinstance(res, tuple)
assert len(res) == 2
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == ()
- assert isinstance(res[1], np.ndarray)
+ assert isinstance(res[1], (np.ndarray, np.float64))
assert res[1].shape == ()
@pytest.mark.parametrize("device", devices)
@@ -1049,10 +1049,10 @@ def circuit(x):
assert isinstance(res, tuple)
assert len(res) == 2
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == ()
- assert isinstance(res[1], np.ndarray)
+ assert isinstance(res[1], (np.ndarray, np.float64))
assert res[1].shape == ()
# op1, wires1, op2, wires2
@@ -1093,10 +1093,10 @@ def circuit(x):
if wires2 is None:
wires2 = op2.wires
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == (2 ** len(wires1),)
- assert isinstance(res[1], np.ndarray)
+ assert isinstance(res[1], (np.ndarray, np.float64))
assert res[1].shape == (2 ** len(wires2),)
multi_probs_data_qutrit = [
@@ -1131,10 +1131,10 @@ def circuit(x):
if wires2 is None:
wires2 = op2.wires
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == (3 ** len(wires1),)
- assert isinstance(res[1], np.ndarray)
+ assert isinstance(res[1], (np.ndarray, np.float64))
assert res[1].shape == (3 ** len(wires2),)
# pylint: disable=too-many-arguments
@@ -1169,16 +1169,16 @@ def circuit(x):
assert isinstance(res, tuple)
assert len(res) == 4
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == (2 ** len(wires1),)
- assert isinstance(res[1], np.ndarray)
+ assert isinstance(res[1], (np.ndarray, np.float64))
assert res[1].shape == ()
- assert isinstance(res[2], np.ndarray)
+ assert isinstance(res[2], (np.ndarray, np.float64))
assert res[2].shape == (2 ** len(wires2),)
- assert isinstance(res[3], np.ndarray)
+ assert isinstance(res[3], (np.ndarray, np.float64))
assert res[3].shape == ()
# pylint: disable=too-many-arguments
@@ -1211,16 +1211,16 @@ def circuit(x):
assert isinstance(res, tuple)
assert len(res) == 4
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == (3 ** len(wires1),)
- assert isinstance(res[1], np.ndarray)
+ assert isinstance(res[1], (np.ndarray, np.float64))
assert res[1].shape == ()
- assert isinstance(res[2], np.ndarray)
+ assert isinstance(res[2], (np.ndarray, np.float64))
assert res[2].shape == (3 ** len(wires2),)
- assert isinstance(res[3], np.ndarray)
+ assert isinstance(res[3], (np.ndarray, np.float64))
assert res[3].shape == ()
@pytest.mark.parametrize("device", devices)
@@ -1248,11 +1248,11 @@ def circuit(x):
res = qnode(0.5)
# Expval
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == ()
# Sample
- assert isinstance(res[1], np.ndarray)
+ assert isinstance(res[1], (np.ndarray, np.float64))
assert res[1].shape == (shots,)
@pytest.mark.parametrize("device", devices)
@@ -1280,7 +1280,7 @@ def circuit(x):
res = qnode(0.5)
# Expval
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == ()
# Counts
@@ -1306,7 +1306,7 @@ def circuit(x):
assert isinstance(res, list)
assert len(res) == 1
- assert isinstance(res[0], np.ndarray)
+ assert isinstance(res[0], (np.ndarray, np.float64))
assert res[0].shape == ()
shot_vectors = [None, [10, 1000], [1, 10, 10, 1000], [1, (10, 2), 1000]]
@@ -1322,6 +1322,7 @@ def test_list_multiple_expval(self, wires, device, shot_vector):
def circuit(x):
func(x)
+ # pylint:disable=unexpected-keyword-arg
return [
qml.expval(obs(wires=i) if device != "default.qutrit" else obs(wires=i, index=3))
for i in range(0, wires)
@@ -1334,7 +1335,7 @@ def circuit(x):
assert isinstance(res, list)
assert len(res) == wires
for r in res:
- assert isinstance(r, np.ndarray)
+ assert isinstance(r, (np.ndarray, np.float64))
assert r.shape == ()
else:
@@ -1343,7 +1344,7 @@ def circuit(x):
assert len(r) == wires
for t in r:
- assert isinstance(t, np.ndarray)
+ assert isinstance(t, (np.ndarray, np.float64))
assert t.shape == ()
@pytest.mark.parametrize("device", devices)
@@ -1373,9 +1374,9 @@ def circuit(x):
else:
assert isinstance(res[0], dict)
- assert isinstance(res[1], qml.numpy.ndarray)
+ assert isinstance(res[1], (qml.numpy.ndarray, qml.numpy.float64))
assert res[1].shape == ()
- assert isinstance(res[2], qml.numpy.ndarray)
+ assert isinstance(res[2], (qml.numpy.ndarray, qml.numpy.float64))
assert res[2].shape == (2,)
@@ -2236,7 +2237,14 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
@@ -2257,7 +2265,14 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
@@ -2281,7 +2296,14 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
@@ -2303,7 +2325,11 @@ def circuit(x):
res = qnode(0.5)
all_shot_copies = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
assert len(res) == len(all_shot_copies)
@@ -2328,7 +2354,14 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
@@ -2353,7 +2386,14 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
@@ -2383,7 +2423,14 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
@@ -2410,7 +2457,11 @@ def circuit(x):
res = qnode(0.5)
all_shot_copies = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
assert len(res) == len(all_shot_copies)
@@ -2432,7 +2483,14 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
@@ -2522,12 +2580,23 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
assert all(isinstance(r, tuple) for r in res)
- assert all(isinstance(m, np.ndarray) for measurement_res in res for m in measurement_res)
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res
+ for m in measurement_res
+ )
for meas_res in res:
for i, r in enumerate(meas_res):
if i % 2 == 0:
@@ -2545,7 +2614,11 @@ def test_scalar_sample_with_obs(self, shot_vector, meas1, meas2, device):
observable."""
dev = qml.device(device, wires=3, shots=shot_vector)
raw_shot_vector = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
def circuit(x):
@@ -2556,12 +2629,23 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
assert all(isinstance(r, tuple) for r in res)
- assert all(isinstance(m, np.ndarray) for measurement_res in res for m in measurement_res)
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res
+ for m in measurement_res
+ )
for idx, shots in enumerate(raw_shot_vector):
for i, r in enumerate(res[idx]):
@@ -2586,14 +2670,25 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
assert all(isinstance(r, tuple) for r in res)
- assert all(isinstance(m, np.ndarray) for measurement_res in res for m in measurement_res)
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res
+ for m in measurement_res
+ )
- for shot_tuple in dev.shot_vector:
+ for shot_tuple in dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector:
for idx in range(shot_tuple.copies):
for i, r in enumerate(res[idx]):
if i % 2 == 0 or shot_tuple.shots == 1:
@@ -2609,7 +2704,11 @@ def test_scalar_counts_with_obs(self, shot_vector, meas1, meas2, device):
observable."""
dev = qml.device(device, wires=3, shots=shot_vector)
raw_shot_vector = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
def circuit(x):
@@ -2620,14 +2719,21 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
assert all(isinstance(r, tuple) for r in res)
for r in res:
- assert isinstance(r[0], np.ndarray)
+ assert isinstance(r[0], (np.ndarray, np.float64))
assert isinstance(r[1], dict)
expected_outcomes = {-1, 1}
@@ -2650,7 +2756,11 @@ def test_scalar_counts_no_obs(self, shot_vector, meas1, meas2, device):
dev = qml.device(device, wires=3, shots=shot_vector)
raw_shot_vector = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
def circuit(x):
@@ -2661,12 +2771,23 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
assert all(isinstance(r, tuple) for r in res)
- assert all(isinstance(m, np.ndarray) for measurement_res in res for m in measurement_res)
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res
+ for m in measurement_res
+ )
for idx, shots in enumerate(raw_shot_vector):
for i, r in enumerate(res[idx]):
@@ -2683,7 +2804,11 @@ def test_probs_sample(self, shot_vector, sample_obs, device):
dev = qml.device(device, wires=3, shots=shot_vector)
raw_shot_vector = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
meas1_wires = [0, 1]
@@ -2702,12 +2827,23 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
assert all(isinstance(r, tuple) for r in res)
- assert all(isinstance(m, np.ndarray) for measurement_res in res for m in measurement_res)
+ assert all(
+ isinstance(m, (np.ndarray, np.float64))
+ for measurement_res in res
+ for m in measurement_res
+ )
for idx, shots in enumerate(raw_shot_vector):
for i, r in enumerate(res[idx]):
@@ -2729,7 +2865,11 @@ def test_probs_counts(self, shot_vector, sample_obs, device):
"""Test probs and counts measurements."""
dev = qml.device(device, wires=3, shots=shot_vector)
raw_shot_vector = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
meas1_wires = [0, 1]
@@ -2748,12 +2888,21 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
assert all(isinstance(r, tuple) for r in res)
- assert all(isinstance(measurement_res[0], np.ndarray) for measurement_res in res)
+ assert all(
+ isinstance(measurement_res[0], (np.ndarray, np.float64)) for measurement_res in res
+ )
assert all(isinstance(measurement_res[1], dict) for measurement_res in res)
expected_outcomes = {-1, 1} if sample_obs is not None else {"0", "1"}
@@ -2777,7 +2926,11 @@ def test_sample_counts(self, shot_vector, sample_wires, counts_wires, device):
samples or computational basis state samples."""
dev = qml.device(device, wires=6, shots=shot_vector)
raw_shot_vector = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
def circuit(x):
@@ -2802,12 +2955,21 @@ def circuit(x):
qnode = qml.QNode(circuit, dev, diff_method=None)
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
assert all(isinstance(r, tuple) for r in res)
- assert all(isinstance(measurement_res[0], np.ndarray) for measurement_res in res)
+ assert all(
+ isinstance(measurement_res[0], (np.ndarray, np.float64)) for measurement_res in res
+ )
assert all(isinstance(measurement_res[1], dict) for measurement_res in res)
for idx, shots in enumerate(raw_shot_vector):
@@ -2828,7 +2990,11 @@ def test_scalar_probs_sample_counts(self, shot_vector, meas1, meas2, device):
in a single qfunc."""
dev = qml.device(device, wires=5, shots=shot_vector)
raw_shot_vector = [
- shot_tuple.shots for shot_tuple in dev.shot_vector for _ in range(shot_tuple.copies)
+ shot_tuple.shots
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ for _ in range(shot_tuple.copies)
]
def circuit(x):
@@ -2845,7 +3011,14 @@ def circuit(x):
res = qnode(0.5)
- all_shots = sum([shot_tuple.copies for shot_tuple in dev.shot_vector])
+ all_shots = sum(
+ [
+ shot_tuple.copies
+ for shot_tuple in (
+ dev.shot_vector if isinstance(dev, qml.Device) else dev.shots.shot_vector
+ )
+ ]
+ )
assert isinstance(res, tuple)
assert len(res) == all_shots
@@ -2901,7 +3074,7 @@ def cost(a):
res = qml.jacobian(cost)(x)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
assert res.shape == (2, 3)
@pytest.mark.torch
@@ -3068,7 +3241,7 @@ def cost(a):
res = qml.jacobian(cost)(x)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
assert res.shape == (2, 2, 3)
@pytest.mark.torch
@@ -3207,7 +3380,7 @@ def cost(a):
res = qml.jacobian(cost)(x)
- assert isinstance(res, np.ndarray)
+ assert isinstance(res, (np.ndarray, np.float64))
assert res.shape == (6, 3)
@pytest.mark.torch
diff --git a/tests/test_tensor_measurements.py b/tests/test_tensor_measurements.py
index 4f64a68b52d..bca43eba57b 100644
--- a/tests/test_tensor_measurements.py
+++ b/tests/test_tensor_measurements.py
@@ -18,7 +18,6 @@
import pytest
import numpy as np
-from gate_data import I, Z, S, Rotx, Roty, H, CNOT
import pennylane as qml
from pennylane import expval, var, sample
@@ -389,25 +388,6 @@ def circuit(a, b, c):
# s1 should only contain 1 and -1
assert np.allclose(s1**2, 1, atol=tol_stochastic, rtol=0)
- zero_state = np.zeros(2**3)
- zero_state[0] = 1
- psi = zero_state
- psi = tensor_product([Rotx(theta), I, I]) @ zero_state
- psi = tensor_product([I, Rotx(phi), I]) @ psi
- psi = tensor_product([I, I, Rotx(varphi)]) @ psi
- psi = tensor_product([CNOT, I]) @ psi
- psi = tensor_product([I, CNOT]) @ psi
-
- # Diagonalize according to the observable
- psi = tensor_product([H, I, I]) @ psi
- psi = tensor_product([I, I, Z]) @ psi
- psi = tensor_product([I, I, S]) @ psi
- psi = tensor_product([I, I, H]) @ psi
-
- expected_probabilities = np.abs(psi) ** 2
-
- assert np.allclose(dev.probability(), expected_probabilities, atol=tol_stochastic, rtol=0)
-
def test_pauliz_tensor_hadamard(self, theta, phi, varphi, tol_stochastic):
"""Test that a tensor product involving PauliZ and hadamard works correctly"""
dev = qml.device("default.qubit", wires=3, shots=int(1e6))
@@ -419,25 +399,6 @@ def circuit(a, b, c):
s1 = circuit(theta, phi, varphi)
- zero_state = np.zeros(2**3)
- zero_state[0] = 1
- psi = zero_state
- psi = tensor_product([Rotx(theta), I, I]) @ zero_state
- psi = tensor_product([I, Rotx(phi), I]) @ psi
- psi = tensor_product([I, I, Rotx(varphi)]) @ psi
- psi = tensor_product([CNOT, I]) @ psi
- psi = tensor_product([I, CNOT]) @ psi
-
- # Diagonalize according to the observable
- psi = tensor_product([I, Roty(-np.pi / 4), I]) @ psi
- psi = tensor_product([I, I, Z]) @ psi
- psi = tensor_product([I, I, S]) @ psi
- psi = tensor_product([I, I, H]) @ psi
-
- expected_probabilities = np.abs(psi) ** 2
-
- assert np.allclose(dev.probability(), expected_probabilities, atol=tol_stochastic, rtol=0)
-
# s1 should only contain 1 and -1
assert np.allclose(s1**2, 1, atol=tol_stochastic, rtol=0)
@@ -465,19 +426,3 @@ def circuit(a, b, c):
# the hermitian matrix tensor product Z
eigvals = np.linalg.eigvalsh(np.kron(Z, A))
assert set(np.round(s1, 8)).issubset(set(np.round(eigvals, 8)))
-
- zero_state = np.zeros(2**3)
- zero_state[0] = 1
- psi = tensor_product([Rotx(theta), I, I]) @ zero_state
- psi = tensor_product([I, Rotx(phi), I]) @ psi
- psi = tensor_product([I, I, Rotx(varphi)]) @ psi
- psi = tensor_product([CNOT, I]) @ psi
- psi = tensor_product([I, CNOT]) @ psi
-
- # Diagonalize according to the observable
- eigvals, eigvecs = np.linalg.eigh(A)
- psi = tensor_product([I, eigvecs.conj().T]) @ psi
-
- expected_probabilities = np.abs(psi) ** 2
-
- assert np.allclose(dev.probability(), expected_probabilities, atol=tol_stochastic, rtol=0)
diff --git a/tests/test_vqe.py b/tests/test_vqe.py
index 33c0910b447..fd881ab0df5 100644
--- a/tests/test_vqe.py
+++ b/tests/test_vqe.py
@@ -345,15 +345,19 @@ def test_optimize_torch(self, shots):
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
w = np.random.random(shape)
- c1 = cost(w)
- exec_opt = dev.num_executions
- dev._num_executions = 0
+ with qml.Tracker(dev) as tracker:
+ c1 = cost(w)
- c2 = cost2(w)
- exec_no_opt = dev.num_executions
+ exec_opt = tracker.latest["executions"]
- assert exec_opt == 5 # Number of groups in the Hamiltonian
- assert exec_no_opt == 15
+ with tracker:
+ c2 = cost2(w)
+
+ exec_no_opt = tracker.latest["executions"]
+
+ # was 5, 15 on old device
+ assert exec_opt == 1 # Number of groups in the Hamiltonian
+ assert exec_no_opt == 1
assert np.allclose(c1, c2, atol=1e-1)
@@ -391,15 +395,17 @@ def test_optimize_tf(self, shots):
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
w = np.random.random(shape)
- c1 = cost(w)
- exec_opt = dev.num_executions
- dev._num_executions = 0
+ with qml.Tracker(dev) as tracker:
+ c1 = cost(w)
+ exec_opt = tracker.latest["executions"]
- c2 = cost2(w)
- exec_no_opt = dev.num_executions
+ with tracker:
+ c2 = cost2(w)
+ exec_no_opt = tracker.latest["executions"]
- assert exec_opt == 5 # Number of groups in the Hamiltonian
- assert exec_no_opt == 15
+ # was 5, 15 on old device
+ assert exec_opt == 1 # Number of groups in the Hamiltonian
+ assert exec_no_opt == 1
assert np.allclose(c1, c2, atol=1e-1)
@@ -437,15 +443,17 @@ def test_optimize_autograd(self, shots):
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
w = np.random.random(shape)
- c1 = cost(w)
- exec_opt = dev.num_executions
- dev._num_executions = 0
+ with qml.Tracker(dev) as tracker:
+ c1 = cost(w)
+ exec_opt = tracker.latest["executions"]
- c2 = cost2(w)
- exec_no_opt = dev.num_executions
+ with tracker:
+ c2 = cost2(w)
+ exec_no_opt = tracker.latest["executions"]
- assert exec_opt == 5 # Number of groups in the Hamiltonian
- assert exec_no_opt == 15
+ # was 5, 15 on old device
+ assert exec_opt == 1 # Number of groups in the Hamiltonian
+ assert exec_no_opt == 1
assert np.allclose(c1, c2, atol=1e-1)
@@ -493,15 +501,17 @@ def test_optimize_multiple_terms_autograd(self):
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=5)
w = np.random.random(shape)
- c1 = cost(w)
- exec_opt = dev.num_executions
- dev._num_executions = 0
+ with qml.Tracker(dev) as tracker:
+ c1 = cost(w)
+ exec_opt = tracker.latest["executions"]
- c2 = cost2(w)
- exec_no_opt = dev.num_executions
+ with tracker:
+ c2 = cost2(w)
+ exec_no_opt = tracker.latest["executions"]
+ # was 1, 8 on old device
assert exec_opt == 1 # Number of groups in the Hamiltonian
- assert exec_no_opt == 8
+ assert exec_no_opt == 1
assert np.allclose(c1, c2)
@@ -549,15 +559,17 @@ def test_optimize_multiple_terms_torch(self):
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=5)
w = np.random.random(shape)
- c1 = cost(w)
- exec_opt = dev.num_executions
- dev._num_executions = 0
+ with qml.Tracker(dev) as tracker:
+ c1 = cost(w)
+ exec_opt = tracker.latest["executions"]
- c2 = cost2(w)
- exec_no_opt = dev.num_executions
+ with tracker:
+ c2 = cost2(w)
+ exec_no_opt = tracker.latest["executions"]
+ # was 1, 8 on old device
assert exec_opt == 1 # Number of groups in the Hamiltonian
- assert exec_no_opt == 8
+ assert exec_no_opt == 1
assert np.allclose(c1, c2)
@@ -605,19 +617,22 @@ def test_optimize_multiple_terms_tf(self):
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=5)
w = np.random.random(shape)
- c1 = cost(w)
- exec_opt = dev.num_executions
- dev._num_executions = 0
+ with qml.Tracker(dev) as tracker:
+ c1 = cost(w)
+ exec_opt = tracker.latest["executions"]
- c2 = cost2(w)
- exec_no_opt = dev.num_executions
+ with tracker:
+ c2 = cost2(w)
+ exec_no_opt = tracker.latest["executions"]
+ # was 1, 8 on old device
assert exec_opt == 1 # Number of groups in the Hamiltonian
- assert exec_no_opt == 8
+ assert exec_no_opt == 1
assert np.allclose(c1, c2)
# pylint: disable=protected-access
+ @pytest.mark.skip("non-opt is less executions than opt with new device")
@pytest.mark.autograd
def test_optimize_grad(self):
"""Test that the gradient of ExpvalCost is accessible and correct when using observable
@@ -646,12 +661,13 @@ def test_optimize_grad(self):
shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=2, n_wires=4)
w = pnp.random.uniform(low=0, high=2 * np.pi, size=shape, requires_grad=True)
- dc = qml.grad(cost)(w)
- exec_opt = dev.num_executions
- dev._num_executions = 0
+ with qml.Tracker(dev) as tracker:
+ dc = qml.grad(cost)(w)
+ exec_opt = tracker.latest["executions"]
- dc2 = qml.grad(cost2)(w)
- exec_no_opt = dev.num_executions
+ with tracker:
+ dc2 = qml.grad(cost2)(w)
+ exec_no_opt = tracker.latest["executions"]
assert exec_no_opt > exec_opt
assert np.allclose(dc, big_hamiltonian_grad)
@@ -750,7 +766,7 @@ def ansatz(params, **kwargs):
h = qml.Hamiltonian([1, 1], [qml.PauliZ(0), qml.PauliZ(1)])
qnodes = catch_warn_ExpvalCost(ansatz, h, dev)
- mt = qml.metric_tensor(qnodes, approx=approx)(p)
+ mt = qml.metric_tensor(qnodes, approx=approx)(p) # pylint:disable=not-callable
assert mt.shape == (3, 3)
assert isinstance(mt, pnp.ndarray)
@@ -843,10 +859,14 @@ def circuit2():
assert np.allclose(res1, res2, atol=tol)
- @pytest.mark.autograd
+ @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):
"""Tests that distributed shots work with the new VQE design."""
+ import jax
+
+ jax.config.update("jax_enable_x64", True)
+
dev = qml.device("default.qubit", wires=2, shots=shots)
@qml.qnode(dev)
@@ -857,12 +877,13 @@ def circuit(weights, coeffs):
obs = [qml.PauliZ(0), qml.PauliX(0) @ qml.PauliZ(1)]
coeffs = np.array([0.1, 0.2])
- weights = pnp.random.random([2, 2, 3], requires_grad=True)
+ key = jax.random.PRNGKey(42)
+ weights = jax.random.uniform(key, [2, 2, 3])
res = circuit(weights, coeffs)
- grad = qml.jacobian(circuit, argnum=1)(weights, coeffs)
+ grad = jax.jacobian(circuit, argnums=[1])(weights, coeffs)
assert len(res) == dim
- assert grad.shape == (dim, 2)
+ assert qml.math.shape(grad) == (dim, 1, 2)
def test_circuit_drawer(self):
"""Test that the circuit drawer displays Hamiltonians well."""
@@ -943,9 +964,7 @@ def test_error_var_measurement(self):
def circuit():
return qml.var(H)
- with pytest.raises(
- qml.operation.EigvalsUndefinedError, match="Cannot compute analytic variance"
- ):
+ with pytest.raises(NotImplementedError):
circuit()
def test_error_sample_measurement(self):
@@ -959,7 +978,7 @@ def test_error_sample_measurement(self):
def circuit():
return qml.sample(H)
- with pytest.raises(ValueError, match="Can only return the expectation of a single"):
+ with pytest.raises(qml.operation.DiagGatesUndefinedError):
circuit()
@pytest.mark.autograd
@@ -1010,7 +1029,7 @@ def circuit(w):
w = torch.tensor(PARAMS, requires_grad=True)
res = circuit(w)
- res.backward()
+ res.backward() # pylint:disable=no-member
dc = w.grad.detach().numpy()
assert np.allclose(dc, big_hamiltonian_grad, atol=tol)
diff --git a/tests/transforms/test_adjoint_metric_tensor.py b/tests/transforms/test_adjoint_metric_tensor.py
index f79572cd074..04aa867ddec 100644
--- a/tests/transforms/test_adjoint_metric_tensor.py
+++ b/tests/transforms/test_adjoint_metric_tensor.py
@@ -261,7 +261,7 @@ def test_correct_output_tape_autograd(self, ansatz, params, interface):
"""Test that the output is correct when using Autograd and
calling the adjoint metric tensor directly on a tape."""
expected = autodiff_metric_tensor(ansatz, 3)(*params)
- dev = qml.devices.DefaultQubit()
+ dev = qml.device("default.qubit")
wires = ("a", "b", "c")
@@ -281,7 +281,8 @@ def circuit(*params):
@pytest.mark.jax
@pytest.mark.skip("JAX does not support forward pass executiong of the metric tensor.")
- def test_correct_output_tape_jax(self, ansatz, params):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.jax"])
+ def test_correct_output_tape_jax(self, dev_name, ansatz, params):
"""Test that the output is correct when using JAX and
calling the adjoint metric tensor directly on a tape."""
@@ -292,7 +293,7 @@ def test_correct_output_tape_jax(self, ansatz, params):
expected = autodiff_metric_tensor(ansatz, self.num_wires)(*params)
j_params = tuple(jax.numpy.array(p) for p in params)
- dev = qml.device("default.qubit.jax", wires=self.num_wires)
+ dev = qml.device(dev_name, wires=self.num_wires)
@qml.qnode(dev, interface="jax")
def circuit(*params):
@@ -312,7 +313,8 @@ def circuit(*params):
@pytest.mark.torch
@pytest.mark.parametrize("interface", interfaces)
- def test_correct_output_tape_torch(self, ansatz, params, interface):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_correct_output_tape_torch(self, ansatz, params, interface, dev_name):
"""Test that the output is correct when using Torch and
calling the adjoint metric tensor directly on a tape."""
@@ -320,7 +322,7 @@ def test_correct_output_tape_torch(self, ansatz, params, interface):
expected = autodiff_metric_tensor(ansatz, self.num_wires)(*params)
t_params = tuple(torch.tensor(p, requires_grad=True) for p in params)
- dev = qml.device("default.qubit.torch", wires=self.num_wires)
+ dev = qml.device(dev_name, wires=self.num_wires)
@qml.qnode(dev, interface=interface)
def circuit(*params):
@@ -340,7 +342,8 @@ def circuit(*params):
@pytest.mark.tf
@pytest.mark.parametrize("interface", interfaces)
- def test_correct_output_tape_tf(self, ansatz, params, interface):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.tf"])
+ def test_correct_output_tape_tf(self, ansatz, params, interface, dev_name):
"""Test that the output is correct when using TensorFlow and
calling the adjoint metric tensor directly on a tape."""
@@ -348,7 +351,7 @@ def test_correct_output_tape_tf(self, ansatz, params, interface):
expected = autodiff_metric_tensor(ansatz, self.num_wires)(*params)
t_params = tuple(tf.Variable(p) for p in params)
- dev = qml.device("default.qubit.tf", wires=self.num_wires)
+ dev = qml.device(dev_name, wires=self.num_wires)
@qml.qnode(dev, interface=interface)
def circuit(*params):
@@ -432,7 +435,8 @@ def circuit(*params):
@pytest.mark.torch
@pytest.mark.parametrize("ansatz, params", list(zip(fubini_ansatze, fubini_params)))
@pytest.mark.parametrize("interface", interfaces)
- def test_correct_output_qnode_torch(self, ansatz, params, interface):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.torch"])
+ def test_correct_output_qnode_torch(self, ansatz, params, interface, dev_name):
"""Test that the output is correct when using Torch and
calling the adjoint metric tensor on a QNode."""
@@ -440,7 +444,7 @@ def test_correct_output_qnode_torch(self, ansatz, params, interface):
expected = autodiff_metric_tensor(ansatz, self.num_wires)(*params)
t_params = tuple(torch.tensor(p, requires_grad=True, dtype=torch.float64) for p in params)
- dev = qml.device("default.qubit.torch", wires=self.num_wires)
+ dev = qml.device(dev_name, wires=self.num_wires)
@qml.qnode(dev, interface=interface)
def circuit(*params):
@@ -485,7 +489,8 @@ def circuit(*params):
assert qml.math.allclose(mt, expected)
@pytest.mark.autograd
- def test_autograd_with_other_device(self):
+ @pytest.mark.parametrize("dev_name", ["default.qubit", "default.qubit.autograd"])
+ def test_autograd_with_other_device(self, dev_name):
"""Test passing an extra device to the QNode wrapper."""
ansatz = fubini_ansatz2
params = fubini_params[2]
@@ -493,7 +498,7 @@ def test_autograd_with_other_device(self):
exp_fn = autodiff_metric_tensor(ansatz, self.num_wires)
expected = qml.jacobian(exp_fn)(*params)
dev = qml.device("default.qubit", wires=self.num_wires)
- dev2 = qml.device("default.qubit.autograd", wires=self.num_wires)
+ dev2 = qml.device(dev_name, wires=self.num_wires)
@qml.qnode(dev)
def circuit(*params):
diff --git a/tests/transforms/test_batch_input.py b/tests/transforms/test_batch_input.py
index 9f02442d2ee..d30a12cc06c 100644
--- a/tests/transforms/test_batch_input.py
+++ b/tests/transforms/test_batch_input.py
@@ -14,7 +14,7 @@
"""
Unit tests for the ``batch_inputs`` transform.
"""
-# pylint: disable=too-few-public-methods
+# pylint: disable=too-few-public-methods,no-value-for-parameter,comparison-with-callable
from functools import partial
import pytest
@@ -183,7 +183,7 @@ def circuit(data, weights):
# weights is not batched
weights = np.random.random((10, 3, 3), requires_grad=True)
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data, weights)
assert res.shape == (batch_size, 2**3)
assert len(spy.call_args[0][0]) == batch_size
@@ -222,7 +222,7 @@ def circuit(data, weights):
# weights is not batched
weights = np.random.random((10, 3, 3), requires_grad=True)
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data, weights)
assert res.shape == (batch_size, 2**3)
assert len(spy.call_args[0][0]) == batch_size
diff --git a/tests/transforms/test_batch_params.py b/tests/transforms/test_batch_params.py
index f2333c59eb2..36accf7bb25 100644
--- a/tests/transforms/test_batch_params.py
+++ b/tests/transforms/test_batch_params.py
@@ -14,6 +14,7 @@
"""
Unit tests for the batch params transform.
"""
+# pylint:disable=comparison-with-callable
import functools
import pytest
@@ -39,7 +40,7 @@ def circuit(data, x, weights):
x = np.linspace(0.1, 0.5, batch_size, requires_grad=True)
weights = np.ones((batch_size, 10, 3, 3), requires_grad=True)
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data, x, weights)
assert res.shape == (batch_size, 4)
assert len(spy.call_args[0][0]) == batch_size
@@ -63,7 +64,7 @@ def circuit(data, x, weights):
x = np.linspace(0.1, 0.5, batch_size, requires_grad=True)
weights = np.ones((batch_size, 10, 3, 3), requires_grad=True)
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data, x, weights)
assert res.shape == (batch_size, 4)
assert len(spy.call_args[0][0]) == batch_size
@@ -90,7 +91,7 @@ def circuit(data, x, weights):
x = np.linspace(0.1, 0.5, batch_size, requires_grad=True)
weights = np.ones((batch_size, 10, 3, 3), requires_grad=True)
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data, x, weights)
assert res.shape == (batch_size, 4)
assert len(spy.call_args[0][0]) == batch_size
@@ -110,7 +111,7 @@ def circuit(weights):
batch_size = 5
weights = np.random.random((batch_size, 2, 2))
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(weights)
assert res.shape == (batch_size, 4)
assert len(spy.call_args[0][0]) == batch_size
@@ -130,7 +131,7 @@ def circuit(data):
batch_size = 5
data = np.random.random((batch_size, 3))
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data)
assert res.shape == (batch_size, 4)
assert len(spy.call_args[0][0]) == batch_size
@@ -154,7 +155,7 @@ def circuit(data, weights):
data /= np.linalg.norm(data, axis=1).reshape(-1, 1) # normalize
weights = np.random.random((batch_size, 10, 3, 3))
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data, weights)
assert res.shape == (batch_size, 2**3)
assert len(spy.call_args[0][0]) == batch_size
@@ -189,7 +190,7 @@ def circuit(data, weights):
data = np.random.randint(2, size=(batch_size, 4))
weights = np.random.random((batch_size, 10, 4, 3))
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data, weights)
assert res.shape == (batch_size, 2**4)
assert len(spy.call_args[0][0]) == batch_size
@@ -225,7 +226,7 @@ def circuit(data, weights):
data /= np.linalg.norm(data, axis=1).reshape(-1, 1) # normalize
weights = np.random.random((batch_size, 10, 3, 3))
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(data, weights)
assert res.shape == (batch_size, 2**3)
assert len(spy.call_args[0][0]) == batch_size
@@ -272,6 +273,7 @@ def circuit(data, x, weights):
def test_shot_vector():
"""Test that batching works for a simple circuit with a shot vector"""
+ # pylint:disable=not-an-iterable
dev = qml.device("default.qubit", wires=3, shots=(100, (200, 3), 300))
@qml.batch_params
@@ -801,7 +803,7 @@ def circuit(x, weights):
x = np.linspace(0.1, 0.5, batch_size, requires_grad=True)
weights = np.ones((batch_size, 10, 3, 3), requires_grad=False)
- spy = mocker.spy(circuit.device, "batch_execute")
+ spy = mocker.spy(circuit.device, "execute")
res = circuit(x, weights)
assert res.shape == (batch_size, 4)
assert len(spy.call_args[0][0]) == batch_size
diff --git a/tests/transforms/test_batch_transform.py b/tests/transforms/test_batch_transform.py
index 742e15bc78b..eb2d671da38 100644
--- a/tests/transforms/test_batch_transform.py
+++ b/tests/transforms/test_batch_transform.py
@@ -428,7 +428,7 @@ def circuit(x):
assert tapes[1].operations[1].name == "RZ"
assert tapes[1].operations[1].parameters == [b * np.sin(x)]
- expected = fn(dev.batch_execute(tapes))
+ expected = fn(dev.execute(tapes))
assert res == expected
assert circuit.interface == "auto"
@@ -464,7 +464,7 @@ def circuit(x):
assert tapes[1].operations[1].name == "RZ"
assert tapes[1].operations[1].parameters == [b * np.sin(x)]
- expected = fn(dev.batch_execute(tapes))
+ expected = fn(dev.execute(tapes))
assert res == expected
def test_custom_qnode_wrapper(self):
@@ -667,7 +667,7 @@ def circuit(weights):
qml.CNOT(wires=[0, 1])
return qml.expval(H)
- spy = mocker.spy(dev, "batch_transform")
+ spy = mocker.spy(dev, "preprocess")
res = circuit(weights)
spy.assert_called()
diff --git a/tests/transforms/test_hamiltonian_expand.py b/tests/transforms/test_hamiltonian_expand.py
index b6d4581e157..886623740fd 100644
--- a/tests/transforms/test_hamiltonian_expand.py
+++ b/tests/transforms/test_hamiltonian_expand.py
@@ -100,14 +100,14 @@ def test_hamiltonians(self, tape, output):
"""Tests that the hamiltonian_expand transform returns the correct value"""
tapes, fn = hamiltonian_expand(tape)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert np.isclose(output, expval)
qs = QuantumScript(tape.operations, tape.measurements)
tapes, fn = hamiltonian_expand(qs)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert np.isclose(output, expval)
@@ -117,14 +117,14 @@ def test_hamiltonians_no_grouping(self, tape, output):
if we switch grouping off"""
tapes, fn = hamiltonian_expand(tape, group=False)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert np.isclose(output, expval)
qs = QuantumScript(tape.operations, tape.measurements)
tapes, fn = hamiltonian_expand(qs, group=False)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert np.isclose(output, expval)
@@ -274,10 +274,10 @@ def test_hamiltonian_dif_tensorflow(self):
with tf.GradientTape() as gtape:
with AnnotatedQueue() as q:
- for i in range(2):
- qml.RX(var[i, 0], wires=0)
- qml.RX(var[i, 1], wires=1)
- qml.RX(var[i, 2], wires=2)
+ for _i in range(2):
+ qml.RX(var[_i, 0], wires=0)
+ qml.RX(var[_i, 1], wires=1)
+ qml.RX(var[_i, 2], wires=2)
qml.CNOT(wires=[0, 1])
qml.CNOT(wires=[1, 2])
qml.CNOT(wires=[2, 0])
@@ -405,8 +405,21 @@ def test_observables_on_same_wires(self):
@pytest.mark.parametrize(("qscript", "output"), zip(SUM_QSCRIPTS, SUM_OUTPUTS))
def test_sums(self, qscript, output):
"""Tests that the sum_expand transform returns the correct value"""
+ processed, _ = dev.preprocess()[0]([qscript])
+ assert len(processed) == 1
+ qscript = processed[0]
tapes, fn = sum_expand(qscript)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
+ expval = fn(results)
+
+ assert all(qml.math.allclose(o, e) for o, e in zip(output, expval))
+
+ @pytest.mark.parametrize(("qscript", "output"), zip(SUM_QSCRIPTS, SUM_OUTPUTS))
+ def test_sums_legacy(self, qscript, output):
+ """Tests that the sum_expand transform returns the correct value"""
+ dev_old = qml.device("default.qubit.legacy", wires=4)
+ tapes, fn = sum_expand(qscript)
+ results = dev_old.batch_execute(tapes)
expval = fn(results)
assert all(qml.math.allclose(o, e) for o, e in zip(output, expval))
@@ -415,8 +428,11 @@ def test_sums(self, qscript, output):
def test_sums_no_grouping(self, qscript, output):
"""Tests that the sum_expand transform returns the correct value
if we switch grouping off"""
+ processed, _ = dev.preprocess()[0]([qscript])
+ assert len(processed) == 1
+ qscript = processed[0]
tapes, fn = sum_expand(qscript, group=False)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert all(qml.math.allclose(o, e) for o, e in zip(output, expval))
@@ -559,10 +575,10 @@ def test_sum_dif_tensorflow(self):
with tf.GradientTape() as gtape:
with AnnotatedQueue() as q:
- for i in range(2):
- qml.RX(var[i, 0], wires=0)
- qml.RX(var[i, 1], wires=1)
- qml.RX(var[i, 2], wires=2)
+ for _i in range(2):
+ qml.RX(var[_i, 0], wires=0)
+ qml.RX(var[_i, 1], wires=1)
+ qml.RX(var[_i, 2], wires=2)
qml.CNOT(wires=[0, 1])
qml.CNOT(wires=[1, 2])
qml.CNOT(wires=[2, 0])
diff --git a/tests/transforms/test_metric_tensor.py b/tests/transforms/test_metric_tensor.py
index c28fcb23638..1b4c6db5807 100644
--- a/tests/transforms/test_metric_tensor.py
+++ b/tests/transforms/test_metric_tensor.py
@@ -14,7 +14,7 @@
"""
Unit tests for the metric tensor transform.
"""
-# pylint: disable=too-many-arguments,too-many-public-methods,too-few-public-methods
+# pylint: disable=too-many-arguments,too-many-public-methods,too-few-public-methods,not-callable
import pytest
from scipy.linalg import block_diag
@@ -93,6 +93,7 @@ def circuit(a):
circuit = qml.QNode(circuit, dev, diff_method=diff_method)
params = np.array([0.1], requires_grad=True)
+ # pylint:disable=unexpected-keyword-arg
result = qml.metric_tensor(circuit, hybrid=False, approx="block-diag")(*params)
assert result.shape == (2, 2)
@@ -1192,6 +1193,7 @@ def circuit(*params):
return qml.expval(qml.PauliZ(0))
if len(params) > 1:
+ # pylint:disable=unexpected-keyword-arg
mt = qml.metric_tensor(circuit, argnums=range(0, len(params)), approx=None)(*params)
else:
mt = qml.metric_tensor(circuit, approx=None)(*params)
@@ -1760,7 +1762,7 @@ def circuit(x):
return qml.expval(qml.PauliZ(0))
x = np.array([1.3, 0.2])
- with pytest.raises(qml.wires.WireError, match=r"Did not find some of the wires \(0, 1\)"):
+ with pytest.raises(qml.wires.WireError, match=r"contain wires not found on the device: \{1\}"):
qml.transforms.metric_tensor(circuit)(x)
diff --git a/tests/transforms/test_qcut.py b/tests/transforms/test_qcut.py
index e7b92977037..d6c87fd4191 100644
--- a/tests/transforms/test_qcut.py
+++ b/tests/transforms/test_qcut.py
@@ -15,7 +15,8 @@
Unit tests for the `pennylane.qcut` package.
"""
# pylint: disable=protected-access,too-few-public-methods,too-many-arguments
-# pylint: disable=too-many-public-methods
+# pylint: disable=too-many-public-methods,comparison-with-callable
+# pylint: disable=no-value-for-parameter,no-member,not-callable
import copy
import itertools
import string
@@ -3718,7 +3719,7 @@ def test_qcut_processing_fn_tf(self, use_opt_einsum):
x = tf.Variable(0.9, dtype=tf.float64)
def f(x):
- x = tf.cast(x, dtype=tf.float64)
+ x = tf.cast(x, dtype=tf.float64) # pylint:disable=unexpected-keyword-arg
t1 = x * tf.range(4, dtype=tf.float64)
t2 = x**2 * tf.range(16, dtype=tf.float64)
t3 = tf.sin(x * np.pi / 2) * tf.range(4, dtype=tf.float64)
@@ -4020,7 +4021,9 @@ def test_simple_cut_circuit_torch_trace(self, mocker, use_opt_einsum):
import torch
- dev = qml.device("default.qubit", wires=2)
+ # TODO: this passes with default.qubit locally, but fails on CI
+ # possibly an architecture-specific issue
+ dev = qml.device("default.qubit.legacy", wires=2)
@qml.qnode(dev, interface="torch")
def circuit(x):
@@ -4635,7 +4638,7 @@ def test_init_raises(self, devices, imbalance_tolerance, num_fragments_probed):
"""Test if ill-initialized instances throw errors."""
if (
- isinstance(devices, qml.Device)
+ isinstance(devices, (qml.Device, qml.devices.Device))
and imbalance_tolerance is None
and num_fragments_probed is None
):
diff --git a/tests/transforms/test_qmc_transform.py b/tests/transforms/test_qmc_transform.py
index 9e2542986b5..61446d0c6aa 100644
--- a/tests/transforms/test_qmc_transform.py
+++ b/tests/transforms/test_qmc_transform.py
@@ -85,7 +85,7 @@ def unitary_z(basis_state):
return qml.state()
bitstrings = list(itertools.product([0, 1], repeat=n_wires))
- u = [unitary_z(np.array(bitstring)).numpy() for bitstring in bitstrings]
+ u = [unitary_z(np.array(bitstring)) for bitstring in bitstrings]
u = np.array(u).T
return u
diff --git a/tests/transforms/test_sign_expand.py b/tests/transforms/test_sign_expand.py
index 2641d749f1b..eec92d9ee9d 100644
--- a/tests/transforms/test_sign_expand.py
+++ b/tests/transforms/test_sign_expand.py
@@ -98,7 +98,7 @@ def test_hamiltonians(self, tape, output):
"""Tests that the sign_expand transform returns the correct value"""
tapes, fn = qml.transforms.sign_expand(tape)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert np.isclose(output, expval)
@@ -125,7 +125,7 @@ def test_hamiltonians_circuit_impl(self, tape, output):
"""
tapes, fn = qml.transforms.sign_expand(tape, circuit=True)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert np.isclose(output, expval, 1e-2)
@@ -186,7 +186,7 @@ def test_hamiltonians_vars(self, tape, output):
"""Tests that the sign_expand transform returns the correct value"""
tapes, fn = qml.transforms.sign_expand(tape)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert np.isclose(output, expval)
@@ -198,7 +198,7 @@ def test_hamiltonians_vars_circuit_impl(self, tape, output):
"""
tapes, fn = qml.transforms.sign_expand(tape, circuit=True)
- results = dev.batch_execute(tapes)
+ results = dev.execute(tapes)
expval = fn(results)
assert np.isclose(output, expval, 1e-1)
diff --git a/tests/transforms/test_specs.py b/tests/transforms/test_specs.py
index bcc8540318a..10c499be588 100644
--- a/tests/transforms/test_specs.py
+++ b/tests/transforms/test_specs.py
@@ -49,16 +49,12 @@ def circ():
assert info["num_device_wires"] == 1
assert info["diff_method"] == diff_method
assert info["num_trainable_params"] == 0
+ assert info["device_name"] == dev.name
if diff_method == "parameter-shift":
assert info["num_gradient_executions"] == 0
assert info["gradient_fn"] == "pennylane.gradients.parameter_shift.param_shift"
- if diff_method != "backprop":
- assert info["device_name"] == "default.qubit"
- else:
- assert info["device_name"] == "default.qubit.autograd"
-
@pytest.mark.parametrize(
"diff_method, len_info", [("backprop", 11), ("parameter-shift", 12), ("adjoint", 11)]
)
@@ -96,18 +92,14 @@ def circuit(x, y, add_RY=True):
assert info["num_observables"] == 2
assert info["num_diagonalizing_gates"] == 1
- assert info["num_device_wires"] == 4
+ assert info["num_device_wires"] == 3
assert info["diff_method"] == diff_method
assert info["num_trainable_params"] == 4
+ assert info["device_name"] == dev.name
if diff_method == "parameter-shift":
assert info["num_gradient_executions"] == 6
- if diff_method != "backprop":
- assert info["device_name"] == "default.qubit"
- else:
- assert info["device_name"] == "default.qubit.autograd"
-
@pytest.mark.parametrize(
"diff_method, len_info", [("backprop", 11), ("parameter-shift", 12), ("adjoint", 11)]
)
@@ -143,10 +135,11 @@ def circuit(params):
params_shape = qml.BasicEntanglerLayers.shape(n_layers=n_layers, n_wires=n_wires)
rng = np.random.default_rng(seed=10)
- params = rng.standard_normal(params_shape)
+ params = rng.standard_normal(params_shape) # pylint:disable=no-member
return circuit, params
+ @pytest.mark.xfail(reason="DefaultQubit2 does not support custom expansion depths")
def test_max_expansion(self):
"""Test that a user can calculation specifications for a different max
expansion parameter."""
@@ -167,7 +160,7 @@ def test_max_expansion(self):
assert info["resources"] == expected_resources
assert info["num_observables"] == 1
assert info["num_device_wires"] == 5
- assert info["device_name"] == "default.qubit.autograd"
+ assert info["device_name"] == "default.qubit"
assert info["diff_method"] == "best"
assert info["gradient_fn"] == "backprop"
@@ -209,3 +202,22 @@ def circuit():
info = qml.specs(circuit)()
assert info["diff_method"] == "test_specs.my_transform"
assert info["gradient_fn"] == "test_specs.my_transform"
+
+ @pytest.mark.parametrize(
+ "device,num_wires",
+ [
+ (qml.device("default.qubit"), 1),
+ (qml.device("default.qubit", wires=2), 1),
+ (qml.device("default.qubit.legacy", wires=2), 2),
+ ],
+ )
+ def test_num_wires_source_of_truth(self, device, num_wires):
+ """Tests that num_wires behaves differently on old and new devices."""
+
+ @qml.qnode(device)
+ def circuit():
+ qml.PauliX(0)
+ return qml.state()
+
+ info = qml.specs(circuit)()
+ assert info["num_device_wires"] == num_wires