def test_encoding_args(self): """Test that the spectrum is computed for the arguments specified by ``encoding_args``.""" dev = qml.device("default.qubit", wires=2) z_0 = 2.1 @qml.qnode(dev) def circuit(x, Y, z=z_0): qml.RX(z * x, wires=0) qml.RY(0.2 * Y[0, 1, 0], wires=0) qml.RY(3 * Y[0, 0, 0], wires=1) return qml.expval(qml.PauliZ(wires=0)) x = -1.5 Y = np.array([0.2, -1.2, 9.2, -0.2, 1.1, 4, -0.201, 0.8]).reshape((2, 2, 2)) z = 1.2 res = qnode_spectrum(circuit, encoding_args={"x"})(x, Y, z=z) assert res == {"x": {(): [-z, 0.0, z]}} res = qnode_spectrum(circuit, encoding_args={"x"})(x, Y) assert res == {"x": {(): [-z_0, 0.0, z_0]}} res = qnode_spectrum(circuit, encoding_args={"x": ..., "Y": [(0, 0, 0), (1, 0, 1)]})(x, Y) assert res == { "x": {(): [-z_0, 0.0, z_0]}, "Y": {(0, 0, 0): [-3.0, 0.0, 3.0], (1, 0, 1): [0.0]}, }
def test_nonlinear_error(self, circuit, args): """Test that an error is raised if non-linear preprocessing happens in a circuit.""" dev = qml.device("default.qubit", wires=2) qnode = qml.QNode(circuit, dev, interface="autograd") with pytest.raises(ValueError, match="The Jacobian of the classical preprocessing"): qnode_spectrum(qnode)(*args)
def test_nonlinear_error(self, circuit, args): """Test that an error is raised if non-linear preprocessing happens in a circuit.""" tf = pytest.importorskip("tensorflow") args = tuple(tf.Variable(arg, dtype=np.float64) for arg in args) dev = qml.device("default.qubit", wires=2) qnode = qml.QNode(circuit, dev, interface="tf") with pytest.raises(ValueError, match="The Jacobian of the classical preprocessing"): qnode_spectrum(qnode)(*args)
def test_wrong_return_type_error(self, measure_fn, measure_args): """Test that an error is thrown if the QNode has a ``MeasurementProcess`` with an inadmissable ``return_type``.""" dev = qml.device("default.qubit", wires=2) @qml.qnode(dev) def circuit(x): qml.RX(x, wires=0) return [qml.expval(qml.PauliX(1)), measure_fn(*measure_args)] with pytest.raises(ValueError, match=f"{measure_fn.__name__} is not supported"): qnode_spectrum(circuit)(1.5)
def test_multi_par_error(self): """Test that an error is thrown if the spectrum of a multi-parameter gate that cannot be decomposed is requested.""" dev = qml.device("default.qubit", wires=3) class nondecompRot(qml.Rot): @staticmethod def decomposition(phi, theta, omega, wires): """Pseudo-decomposition: Just return the gate itself.""" return [nondecompRot(phi, theta, omega, wires=wires)] @qml.qnode(dev) def circuit(x): qml.RX(x, wires=0) nondecompRot(0.2, x, 0.4, wires=1) return qml.expval(qml.PauliZ(wires=0)) with pytest.raises(ValueError, match="Can only consider one-parameter gates"): qnode_spectrum(circuit)(1.5)
def test_various_circuits(self, circuit, args, expected): """Test the spectrum for some simple standard circuits.""" dev = qml.device("default.qubit", wires=2) qnode = qml.QNode(circuit, dev) spec = qnode_spectrum(qnode)(*args) assert spec.keys() == expected.keys() for outer_key in spec.keys(): assert spec[outer_key].keys() == expected[outer_key].keys() for key in spec[outer_key]: assert np.allclose(spec[outer_key][key], expected[outer_key][key])
def test_spectrum_changes_with_qnode_args(self): """Test that the spectrum changes per call if a qnode keyword argument changes the circuit architecture.""" dev = qml.device("default.qubit", wires=3) @qml.qnode(dev) def circuit(x, last_gate=False): qml.RX(x, wires=0) qml.RX(x, wires=1) if last_gate: qml.RX(x, wires=2) return qml.expval(qml.PauliZ(wires=0)) x = 0.9 res_true = qnode_spectrum(circuit, argnum=[0])(x, last_gate=True) assert np.allclose(res_true["x"][()], range(-3, 4)) res_false = qnode_spectrum(circuit, argnum=[0])(x, last_gate=False) assert np.allclose(res_false["x"][()], range(-2, 3))
def test_integration_autograd(self): """Test that the spectra of a circuit is calculated correctly in the autograd interface.""" x = pnp.array([1.0, 2.0, 3.0]) w = pnp.array([[-1, -2, -3], [-4, -5, -6]], dtype=float) dev = qml.device("default.qubit", wires=3) qnode = qml.QNode(circuit, dev, interface="autograd") res = qnode_spectrum(qnode, argnum=0)(x, w) assert res assert res == expected_result
def test_argnum(self): """Test that the spectrum is computed for the arguments specified by ``argnum``.""" dev = qml.device("default.qubit", wires=2) @qml.qnode(dev) def circuit(x, y): qml.RX(x, wires=0) qml.RY(0.2 * y, wires=0) qml.RY(3 * y, wires=1) return qml.expval(qml.PauliZ(wires=0)) x, y = [0.2, 0.1] y_freq = [-3.2, -3.0, -2.8, -0.2, 0.0, 0.2, 2.8, 3.0, 3.2] res = qnode_spectrum(circuit, argnum=[0])(x, y) assert res == {"x": {(): [-1.0, 0.0, 1.0]}} res = qnode_spectrum(circuit, argnum=[0, 1])(x, y) assert res == {"x": {(): [-1.0, 0.0, 1.0]}, "y": {(): y_freq}} res = qnode_spectrum(circuit)(x, y) assert res == {"x": {(): [-1.0, 0.0, 1.0]}, "y": {(): y_freq}}
def test_integration_tf(self): """Test that the spectra of a circuit is calculated correctly in the tf interface.""" tf = pytest.importorskip("tensorflow") dev = qml.device("default.qubit", wires=3) qnode = qml.QNode(circuit, dev, interface="tf") x = tf.Variable([1.0, 2.0, 3.0]) w = tf.constant([[-1, -2, -3], [-4, -5, -6]], dtype=float) res = qnode_spectrum(qnode, argnum=[0])(x, w) assert res assert res == expected_result
def test_integration_torch(self): """Test that the spectra of a circuit is calculated correctly in the torch interface.""" torch = pytest.importorskip("torch") x = torch.tensor([1.0, 2.0, 3.0]) w = torch.tensor([[-1, -2, -3], [-4, -5, -6]], dtype=float) dev = qml.device("default.qubit", wires=3) qnode = qml.QNode(circuit, dev, interface="torch") res = qnode_spectrum(qnode, argnum=0)(x, w) assert res assert res == expected_result
def test_integration_jax(self): """Test that the spectra of a circuit is calculated correctly in the jax interface.""" jax = pytest.importorskip("jax") x = jax.numpy.array([1.0, 2.0, 3.0]) w = [[-1.0, -2.0, -3.0], [-4.0, -5.0, -6.0]] dev = qml.device("default.qubit", wires=3) qnode = qml.QNode(circuit, dev, interface="jax") res = qnode_spectrum(qnode, argnum=0)(x, w) assert res assert res == expected_result
def test_spectrum_grows_with_gates(self, n_layers, n_qubits): """Test that the spectrum grows linearly with the number of encoding gates if we use Pauli rotation encoding.""" dev = qml.device("default.qubit", wires=n_qubits) @qml.qnode(dev) def circuit(x): for l in range(n_layers): for i in range(n_qubits): qml.RX(x, wires=i) qml.RY(0.4, wires=i) return qml.expval(qml.PauliZ(wires=0)) res = qnode_spectrum(circuit)(0.1) expected_degree = n_qubits * n_layers assert list(res.keys()) == ["x"] and list(res["x"].keys()) == [()] assert np.allclose(res["x"][()], range(-expected_degree, expected_degree + 1))