def test_higher_order_observable(self, monkeypatch): """An exception should be raised if the observable is higher than 2nd order.""" monkeypatch.setattr(qml.P, "ev_order", 3) with pytest.raises(NotImplementedError, match="order > 2 not implemented"): _transform_observable(qml.P(0), np.identity(3), device_wires=[0])
def test_incorrect_heisenberg_size(self, monkeypatch): """The number of dimensions of a CV observable Heisenberg representation does not match the ev_order attribute.""" monkeypatch.setattr(qml.P, "ev_order", 2) with pytest.raises(ValueError, match="Mismatch between the polynomial order"): _transform_observable(qml.P(0), np.identity(3), device_wires=[0])
def test_first_order_transform(self, tol): """Test that a first order observable is transformed correctly""" # create a symmetric transformation Z = np.arange(3**2).reshape(3, 3) Z = Z.T + Z obs = qml.X(0) res = _transform_observable(obs, Z, device_wires=[0]) # The Heisenberg representation of the X # operator is simply... X expected = np.array([0, 1, 0]) @ Z assert isinstance(res, qml.PolyXP) assert res.wires.labels == (0, ) assert np.allclose(res.data[0], expected, atol=tol, rtol=0)
def test_second_order_transform(self, tol): """Test that a second order observable is transformed correctly""" # create a symmetric transformation Z = np.arange(3**2).reshape(3, 3) Z = Z.T + Z obs = qml.NumberOperator(0) res = _transform_observable(obs, Z, device_wires=[0]) # The Heisenberg representation of the number operator # is (X^2 + P^2) / (2*hbar) - 1/2 A = np.array([[-0.5, 0, 0], [0, 0.25, 0], [0, 0, 0.25]]) expected = A @ Z + Z @ A assert isinstance(res, qml.PolyXP) assert res.wires.labels == (0, ) assert np.allclose(res.data[0], expected, atol=tol, rtol=0)
def test_device_wire_expansion(self, tol): """Test that the transformation works correctly for the case where the transformation applies to more wires than the observable.""" # create a 3-mode symmetric transformation wires = qml.wires.Wires([0, "a", 2]) ndim = 1 + 2 * len(wires) Z = np.arange(ndim**2).reshape(ndim, ndim) Z = Z.T + Z obs = qml.NumberOperator(0) res = _transform_observable(obs, Z, device_wires=wires) # The Heisenberg representation of the number operator # is (X^2 + P^2) / (2*hbar) - 1/2. We use the ordering # I, X0, Xa, X2, P0, Pa, P2. A = np.diag([-0.5, 0.25, 0.25, 0, 0, 0, 0]) expected = A @ Z + Z @ A assert isinstance(res, qml.PolyXP) assert res.wires == wires assert np.allclose(res.data[0], expected, atol=tol, rtol=0)