def test_trainable_measurement(self, tol): """Test that a trainable measurement can be differentiated""" dev = qml.device("default.gaussian", wires=2) a = 0.32 phi = 0.54 with JacobianTape() as tape: qml.Displacement(a, 0, wires=0) qml.expval(qml.QuadOperator(phi, wires=0)) tape.trainable_params = {2} res = tape.jacobian(dev) expected = np.array([[-2 * a * np.sin(phi)]]) assert np.allclose(res, expected, atol=tol, rtol=0)
def test_gradients_gaussian_circuit(self, op, obs, mocker, tol): """Tests that the gradients of circuits of gaussian gates match between the finite difference and analytic methods.""" tol = 1e-2 args = np.linspace(0.2, 0.5, op.num_params) with CVParamShiftTape() as tape: qml.Displacement(0.5, 0, wires=0) op(*args, wires=range(op.num_wires)) qml.Beamsplitter(1.3, -2.3, wires=[0, 1]) qml.Displacement(-0.5, 0.1, wires=0) qml.Squeezing(0.5, -1.5, wires=0) qml.Rotation(-1.1, wires=0) expval(obs(wires=0)) dev = qml.device("default.gaussian", wires=2) res = tape.execute(dev) tape._update_gradient_info() tape.trainable_params = set(range(2, 2 + op.num_params)) # check that every parameter is analytic for i in range(op.num_params): assert tape._par_info[2 + i]["grad_method"][0] == "A" spy = mocker.spy(CVParamShiftTape, "parameter_shift_first_order") grad_F = tape.jacobian(dev, method="numeric") grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True) spy.assert_not_called() assert np.allclose(grad_A2, grad_F, atol=tol, rtol=0) if obs.ev_order == 1: grad_A = tape.jacobian(dev, method="analytic") spy.assert_called() assert np.allclose(grad_A, grad_F, atol=tol, rtol=0)
def test_gradients_gaussian_circuit(self, op, obs, mocker, tol): """Tests that the gradients of circuits of gaussian gates match between the finite difference and analytic methods.""" tol = 1e-2 args = np.linspace(0.2, 0.5, op.num_params) with qml.tape.JacobianTape() as tape: qml.Displacement(0.5, 0, wires=0) op(*args, wires=range(op.num_wires)) qml.Beamsplitter(1.3, -2.3, wires=[0, 1]) qml.Displacement(-0.5, 0.1, wires=0) qml.Squeezing(0.5, -1.5, wires=0) qml.Rotation(-1.1, wires=0) qml.expval(obs(wires=0)) dev = qml.device("default.gaussian", wires=2) res = tape.execute(dev) tape.trainable_params = set(range(2, 2 + op.num_params)) tapes, fn = qml.gradients.finite_diff(tape) grad_F = fn(dev.batch_execute(tapes)) tapes, fn = param_shift_cv(tape, dev, force_order2=True) grad_A2 = fn(dev.batch_execute(tapes)) # check that every parameter is analytic for i in range(op.num_params): assert tape._par_info[2 + i]["grad_method"][0] == "A" assert np.allclose(grad_A2, grad_F, atol=tol, rtol=0) if obs.ev_order == 1: tapes, fn = param_shift_cv(tape, dev) grad_A = fn(dev.batch_execute(tapes)) assert np.allclose(grad_A, grad_F, atol=tol, rtol=0)
def test_error_analytic_second_order(self): """Test exception raised if attempting to use a second order observable to compute the variance derivative analytically""" dev = qml.device("default.gaussian", wires=1) with qml.tape.JacobianTape() as tape: qml.Displacement(1.0, 0, wires=0) qml.var(qml.NumberOperator(0)) tape.trainable_params = {0} with pytest.raises( ValueError, match=r"cannot be used with the argument\(s\) \{0\}"): param_shift_cv(tape, dev, fallback_fn=None)
def layer(v): """ Single layer of the quantum neural net. Args: v (array[float]): array of variables for one layer """ # Matrix multiplication of input layer qml.Rotation(v[0], wires=0) qml.Squeezing(v[1], 0., wires=0) qml.Rotation(v[2], wires=0) # Bias qml.Displacement(v[3], 0., wires=0) # Element-wise nonlinear transformation qml.Kerr(v[4], wires=0)
def test_displaced_thermal_mean_photon_variance(self, tol): """Test gradient of the photon variance of a displaced thermal state""" dev = qml.device("default.gaussian", wires=1) n = 0.12 a = 0.105 with CVParamShiftTape() as tape: qml.ThermalState(n, wires=0) qml.Displacement(a, 0, wires=0) var(qml.TensorN(wires=[0])) tape.trainable_params = {0, 1} grad = tape.jacobian(dev) expected = np.array([2 * a ** 2 + 2 * n + 1, 2 * a * (2 * n + 1)]) assert np.allclose(grad, expected, atol=tol, rtol=0)
def quantum_neural_net(var, x=None): """The quantum neural net variational circuit. Args: var (array[float]): array of variables x (array[float]): single input vector Returns: float: expectation of Homodyne measurement on Mode 0 """ # Encode input x into quantum state qml.Displacement(x, 0., wires=0) # "layer" subcircuits for v in var: layer(v) return qml.expval.X(0)
def test_single_output_value(self, tol): """Tests correct execution and output shape for a CV tape with a single expval output""" dev = qml.device("default.gaussian", wires=2) x = 0.543 y = -0.654 with QuantumTape() as tape: qml.Displacement(x, 0, wires=[0]) qml.Squeezing(y, 0, wires=[1]) qml.Beamsplitter(np.pi / 4, 0, wires=[0, 1]) qml.expval(qml.NumberOperator(0)) assert tape.output_dim == 1 res = tape.execute(dev) assert res.shape == (1, )
def test_displaced_thermal_mean_photon_variance(self, tol): """Test gradient of the photon variance of a displaced thermal state""" dev = qml.device("default.gaussian", wires=1) n = 0.12 a = 0.105 with qml.tape.JacobianTape() as tape: qml.ThermalState(n, wires=0) qml.Displacement(a, 0, wires=0) qml.var(qml.TensorN(wires=[0])) tape.trainable_params = {0, 1} tapes, fn = param_shift_cv(tape, dev) grad = fn(dev.batch_execute(tapes)) expected = np.array([2 * a**2 + 2 * n + 1, 2 * a * (2 * n + 1)]) assert np.allclose(grad, expected, atol=tol, rtol=0)
def test_squeezed_gradient(self, mocker, tol): """Test the gradient of the squeezed gate. We also ensure that the gradient is correct even when an operation with no Heisenberg representation is a descendent.""" dev = qml.device("default.gaussian", wires=2, hbar=hbar) class Rotation(qml.operation.CVOperation): """Dummy operation that does not support heisenberg representation""" num_wires = 1 num_params = 1 par_domain = "R" grad_method = "A" alpha = 0.5643 r = 0.23354 with qml.tape.JacobianTape() as tape: qml.Displacement(alpha, 0.0, wires=[0]) qml.Squeezing(r, 0.0, wires=[0]) # The following two gates have no effect # on the circuit gradient and expectation value qml.Beamsplitter(0.0, 0.0, wires=[0, 1]) Rotation(0.543, wires=[1]) qml.expval(qml.X(0)) tape.trainable_params = {2} spy2 = mocker.spy(qml.gradients.parameter_shift_cv, "second_order_param_shift") tapes, fn = param_shift_cv(tape, dev) grad_A = fn(dev.batch_execute(tapes)) spy2.assert_not_called() tapes, fn = param_shift_cv(tape, dev, force_order2=True) grad_A2 = fn(dev.batch_execute(tapes)) spy2.assert_called() expected = -np.exp(-r) * hbar * alpha assert np.allclose(grad_A, expected, atol=tol, rtol=0) assert np.allclose(grad_A2, expected, atol=tol, rtol=0)
def test_multiple_output_values(self, tol): """Tests correct output shape and evaluation for a tape with multiple measurement types""" dev = qml.device("default.gaussian", wires=2) x = 0.543 y = -0.654 with QuantumTape() as tape: qml.Displacement(x, 0, wires=[0]) qml.Squeezing(y, 0, wires=[1]) qml.Beamsplitter(np.pi / 4, 0, wires=[0, 1]) qml.expval(qml.PolyXP(np.diag([0, 1, 0]), wires=0)) # X^2 qml.var(qml.P(1)) assert tape.output_dim == 2 res = tape.execute(dev) assert res.shape == (2, )
def test_single_output_value(self, tol): """Tests correct Jacobian and output shape for a CV tape with a single output""" dev = qml.device("default.gaussian", wires=2) n = 0.543 a = -0.654 with JacobianTape() as tape: qml.ThermalState(n, wires=0) qml.Displacement(a, 0, wires=0) qml.var(qml.NumberOperator(0)) tape.trainable_params = {0, 1} res = tape.jacobian(dev) assert res.shape == (1, 2) expected = np.array([2 * a**2 + 2 * n + 1, 2 * a * (2 * n + 1)]) assert np.allclose(res, expected, atol=tol, rtol=0)
def test_squeezed_gradient(self, mocker, tol): """Test the gradient of the squeezed gate. We also ensure that the gradient is correct even when an operation with no Heisenberg representation is a descendent.""" dev = qml.device("default.gaussian", wires=2, hbar=hbar) class Rotation(qml.operation.CVOperation): """Dummy operation that does not support heisenberg representation""" num_wires = 1 num_params = 1 grad_method = "A" alpha = 0.5643 r = 0.23354 with CVParamShiftTape() as tape: qml.Displacement(alpha, 0.0, wires=[0]) qml.Squeezing(r, 0.0, wires=[0]) # The following two gates have no effect # on the circuit gradient and expectation value qml.Beamsplitter(0.0, 0.0, wires=[0, 1]) Rotation(0.543, wires=[1]) qml.expval(qml.X(0)) tape._update_gradient_info() tape.trainable_params = {2} spy1 = mocker.spy(CVParamShiftTape, "parameter_shift_first_order") spy2 = mocker.spy(CVParamShiftTape, "parameter_shift_second_order") grad_A = tape.jacobian(dev, method="analytic") spy1.assert_called() spy2.assert_not_called() grad_A2 = tape.jacobian(dev, method="analytic", force_order2=True) spy2.assert_called() expected = -np.exp(-r) * hbar * alpha assert np.allclose(grad_A, expected, atol=tol, rtol=0) assert np.allclose(grad_A2, expected, atol=tol, rtol=0)
def test_force_order2(self, mocker): """Test that if the force_order2 keyword argument is provided, the second order parameter shift rule is forced""" spy = mocker.spy(qml.gradients.parameter_shift_cv, "second_order_param_shift") dev = qml.device("default.gaussian", wires=1) with qml.tape.JacobianTape() as tape: qml.Displacement(1.0, 0.0, wires=[0]) qml.Rotation(2.0, wires=[0]) qml.expval(qml.X(0)) tape.trainable_params = {0, 1, 2} qml.gradients.param_shift_cv(tape, dev, force_order2=False) spy.assert_not_called() qml.gradients.param_shift_cv(tape, dev, force_order2=True) spy.assert_called()
def test_multiple_output_values(self, tol): """Tests correct output shape and evaluation for a tape with multiple outputs""" dev = qml.device("default.gaussian", wires=2) n = 0.543 a = -0.654 with JacobianTape() as tape: qml.ThermalState(n, wires=0) qml.Displacement(a, 0, wires=0) qml.expval(qml.NumberOperator(1)) qml.var(qml.NumberOperator(0)) tape.trainable_params = {0, 1} res = tape.jacobian(dev) assert res.shape == (2, 2) expected = np.array([[0, 0], [2 * a ** 2 + 2 * n + 1, 2 * a * (2 * n + 1)]]) assert np.allclose(res, expected, atol=tol, rtol=0)
def test_force_order2(self, mocker): """Test that if the force_order2 keyword argument is provided, the second order parameter shift rule is forced""" dev = qml.device("default.gaussian", wires=1) with CVParamShiftTape() as tape: qml.Displacement(1.0, 0.0, wires=[0]) qml.Rotation(2.0, wires=[0]) expval(qml.X(0)) tape.trainable_params = {0, 1, 2} spy1 = mocker.spy(tape, "parameter_shift_first_order") spy2 = mocker.spy(tape, "parameter_shift_second_order") tape.jacobian(dev, method="analytic", force_order2=False) spy1.assert_called() spy2.assert_not_called() tape.jacobian(dev, method="analytic", force_order2=True) spy2.assert_called()
def test_second_order_cv(self, tol): """Test variance of a second order CV expectation value""" dev = qml.device("default.gaussian", wires=1) n = 0.12 a = 0.765 with CVParamShiftTape() as tape: qml.ThermalState(n, wires=0) qml.Displacement(a, 0, wires=0) var(qml.NumberOperator(0)) tape.trainable_params = {0, 1} res = tape.execute(dev) expected = n ** 2 + n + np.abs(a) ** 2 * (1 + 2 * n) assert np.allclose(res, expected, atol=tol, rtol=0) # circuit jacobians grad_F = tape.jacobian(dev, method="numeric") expected = np.array([[2 * a ** 2 + 2 * n + 1, 2 * a * (2 * n + 1)]]) assert np.allclose(grad_F, expected, atol=tol, rtol=0)
def qfunc(a, b, c, d, e, f): qml.ThermalState(3, wires=[1]) qml.GaussianState(2 * np.eye(8), np.array([1, 1, 1, 2, 2, 3, 3, 3]), wires=[0, 1, 2, 3]) qml.Rotation(a, wires=0) qml.Rotation(b, wires=1) qml.Beamsplitter(d, 1, wires=[0, 1]) qml.Beamsplitter(e, 1, wires=[1, 2]) qml.Displacement(f, 0, wires=[3]) qml.Squeezing(2.3, 0, wires=[0]) qml.Squeezing(2.3, 0, wires=[2]) qml.Beamsplitter(d, 1, wires=[1, 2]) qml.Beamsplitter(e, 1, wires=[2, 3]) qml.TwoModeSqueezing(2, 2, wires=[3, 1]) qml.ControlledPhase(2.3, wires=[2, 1]) qml.ControlledAddition(2, wires=[0, 3]) qml.QuadraticPhase(4, wires=[0]) return [ qml.expval(qml.ops.PolyXP(np.array([0, 1, 2]), wires=0)), qml.expval(qml.ops.QuadOperator(4, wires=1)), qml.expval(qml.ops.FockStateProjector(np.array([1, 5]), wires=[2, 3])), ]
def test_non_differentiable(self): """Test that a non-differentiable parameter is correctly marked""" with CVParamShiftTape() as tape: qml.FockState(1, wires=0) qml.Displacement(0.543, 0, wires=[1]) qml.Beamsplitter(0, 0, wires=[0, 1]) expval(qml.X(wires=[0])) assert tape._grad_method(0) is None assert tape._grad_method(1) == "A" assert tape._grad_method(2) == "A" assert tape._grad_method(3) == "A" assert tape._grad_method(4) == "A" tape._update_gradient_info() assert tape._par_info[0]["grad_method"] is None assert tape._par_info[1]["grad_method"] == "A" assert tape._par_info[2]["grad_method"] == "A" assert tape._par_info[3]["grad_method"] == "A" assert tape._par_info[4]["grad_method"] == "A"
def expand(self): with qml.tape.QuantumTape() as tape: for l in range(self.n_layers): qml.Interferometer( theta=self.parameters[0][l], phi=self.parameters[1][l], varphi=self.parameters[2][l], wires=self.wires, ) for i in range(len(self.wires)): qml.Squeezing( self.parameters[3][l, i], self.parameters[4][l, i], wires=self.wires[i] ) qml.Interferometer( theta=self.parameters[5][l], phi=self.parameters[6][l], varphi=self.parameters[7][l], wires=self.wires, ) for i in range(len(self.wires)): qml.Displacement( self.parameters[8][l, i], self.parameters[9][l, i], wires=self.wires[i] ) for i in range(len(self.wires)): qml.Kerr(self.parameters[10][l, i], wires=self.wires[i]) if self.inverse: tape.inv() return tape
def test_second_order_cv(self, tol): """Test variance of a second order CV expectation value""" dev = qml.device("default.gaussian", wires=1) n = 0.12 a = 0.765 with qml.tape.JacobianTape() as tape: qml.ThermalState(n, wires=0) qml.Displacement(a, 0, wires=0) qml.var(qml.NumberOperator(0)) tape.trainable_params = {0, 1} res = tape.execute(dev) expected = n**2 + n + np.abs(a)**2 * (1 + 2 * n) assert np.allclose(res, expected, atol=tol, rtol=0) # circuit jacobians tapes, fn = qml.gradients.finite_diff(tape) grad_F = fn(dev.batch_execute(tapes)) expected = np.array([[2 * a**2 + 2 * n + 1, 2 * a * (2 * n + 1)]]) assert np.allclose(grad_F, expected, atol=tol, rtol=0)
def test_expval_and_variance(self, tol): """Test that the gradient works for a combination of CV expectation values and variances""" dev = qml.device("default.gaussian", wires=3) a, b = [0.54, -0.423] with CVParamShiftTape() as tape: qml.Displacement(0.5, 0, wires=0) qml.Squeezing(a, 0, wires=0) qml.Squeezing(b, 0, wires=1) qml.Beamsplitter(0.6, -0.3, wires=[0, 1]) qml.Squeezing(-0.3, 0, wires=2) qml.Beamsplitter(1.4, 0.5, wires=[1, 2]) var(qml.X(0)) expval(qml.X(1)) var(qml.X(2)) tape.trainable_params = {2, 4} # jacobians must match grad_F = tape.jacobian(dev, method="numeric") grad_A = tape.jacobian(dev, method="analytic") assert np.allclose(grad_A, grad_F, atol=tol, rtol=0)
def layers(self, variables): """Layers of the model. Depending on layer_type, the layers will either be custom or template Args: variables (list):weights of the model """ if self.num_q == 1 or self.layer_type == "custom": for var in variables: index = 0 # entangle qumodes for wire in range(self.num_q - 1): qml.Beamsplitter(var[index], var[index + 1], wires=[wire + 1, wire]) index += 2 # Displacement for wire in range(self.num_q): qml.Displacement(var[index], 0., wires=wire) index += 1 # Cubic for wire in range(self.num_q): qml.CubicPhase(var[index], wires=wire) index += 1 # Quadratic for wire in range(self.num_q): qml.QuadraticPhase(var[index], wires=wire) index += 1 elif self.layer_type == "template": qml.templates.layers.CVNeuralNetLayers(*variables, wires=range(self.num_q))
def circuit(): qml.Displacement(0.5, 0.1, wires=wires[0 % n_wires]) qml.Displacement(2.0, 0.2, wires=wires[1 % n_wires]) if n_wires > 1: qml.Beamsplitter(0.5, 0.2, wires=[wires[0], wires[1]]) return [qml.expval(qml.X(wires=w)) for w in wires]
def mean_photon_gaussian(mag_alpha, phase_alpha, phi): qml.Displacement(mag_alpha, phase_alpha, wires=0) qml.Rotation(phi, wires=0).inv() return qml.expval(qml.NumberOperator(0))
class TestRepresentationResolver: """Test the RepresentationResolver class.""" @pytest.mark.parametrize( "list,element,index,list_after", [ ([1, 2, 3], 2, 1, [1, 2, 3]), ([1, 2, 2, 3], 2, 1, [1, 2, 2, 3]), ([1, 2, 3], 4, 3, [1, 2, 3, 4]), ], ) def test_index_of_array_or_append(self, list, element, index, list_after): """Test the method index_of_array_or_append.""" assert RepresentationResolver.index_of_array_or_append(element, list) == index assert list == list_after @pytest.mark.parametrize( "par,expected", [ (3, "3"), (5.236422, "5.24"), ], ) def test_single_parameter_representation(self, unicode_representation_resolver, par, expected): """Test that single parameters are properly resolved.""" assert unicode_representation_resolver.single_parameter_representation( par) == expected @pytest.mark.parametrize( "op,wire,target", [ (qml.PauliX(wires=[1]), 1, "X"), (qml.CNOT(wires=[0, 1]), 1, "X"), (qml.CNOT(wires=[0, 1]), 0, "C"), (qml.Toffoli(wires=[0, 2, 1]), 1, "X"), (qml.Toffoli(wires=[0, 2, 1]), 0, "C"), (qml.Toffoli(wires=[0, 2, 1]), 2, "C"), (qml.CSWAP(wires=[0, 2, 1]), 1, "SWAP"), (qml.CSWAP(wires=[0, 2, 1]), 2, "SWAP"), (qml.CSWAP(wires=[0, 2, 1]), 0, "C"), (qml.PauliY(wires=[1]), 1, "Y"), (qml.PauliZ(wires=[1]), 1, "Z"), (qml.CZ(wires=[0, 1]), 1, "Z"), (qml.CZ(wires=[0, 1]), 0, "C"), (qml.Identity(wires=[1]), 1, "I"), (qml.Hadamard(wires=[1]), 1, "H"), (qml.PauliRot(3.14, "XX", wires=[0, 1]), 1, "RX(3.14)"), (qml.PauliRot(3.14, "YZ", wires=[0, 1]), 1, "RZ(3.14)"), (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4 ]), 0, "RI(3.14)"), (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4 ]), 1, "RX(3.14)"), (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4 ]), 2, "RY(3.14)"), (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4 ]), 3, "RZ(3.14)"), (qml.PauliRot(3.14, "IXYZI", wires=[0, 1, 2, 3, 4 ]), 4, "RI(3.14)"), (qml.MultiRZ(3.14, wires=[0, 1]), 0, "RZ(3.14)"), (qml.MultiRZ(3.14, wires=[0, 1]), 1, "RZ(3.14)"), (qml.CRX(3.14, wires=[0, 1]), 1, "RX(3.14)"), (qml.CRX(3.14, wires=[0, 1]), 0, "C"), (qml.CRY(3.14, wires=[0, 1]), 1, "RY(3.14)"), (qml.CRY(3.14, wires=[0, 1]), 0, "C"), (qml.CRZ(3.14, wires=[0, 1]), 1, "RZ(3.14)"), (qml.CRZ(3.14, wires=[0, 1]), 0, "C"), (qml.CRot(3.14, 2.14, 1.14, wires=[0, 1 ]), 1, "Rot(3.14, 2.14, 1.14)"), (qml.CRot(3.14, 2.14, 1.14, wires=[0, 1]), 0, "C"), (qml.PhaseShift(3.14, wires=[0]), 0, "Rϕ(3.14)"), (qml.Beamsplitter(1, 2, wires=[0, 1]), 1, "BS(1, 2)"), (qml.Beamsplitter(1, 2, wires=[0, 1]), 0, "BS(1, 2)"), (qml.Squeezing(1, 2, wires=[1]), 1, "S(1, 2)"), (qml.TwoModeSqueezing(1, 2, wires=[0, 1]), 1, "S(1, 2)"), (qml.TwoModeSqueezing(1, 2, wires=[0, 1]), 0, "S(1, 2)"), (qml.Displacement(1, 2, wires=[1]), 1, "D(1, 2)"), (qml.NumberOperator(wires=[1]), 1, "n"), (qml.Rotation(3.14, wires=[1]), 1, "R(3.14)"), (qml.ControlledAddition(3.14, wires=[0, 1]), 1, "X(3.14)"), (qml.ControlledAddition(3.14, wires=[0, 1]), 0, "C"), (qml.ControlledPhase(3.14, wires=[0, 1]), 1, "Z(3.14)"), (qml.ControlledPhase(3.14, wires=[0, 1]), 0, "C"), (qml.ThermalState(3, wires=[1]), 1, "Thermal(3)"), ( qml.GaussianState(np.array([[2, 0], [0, 2]]), np.array([1, 2]), wires=[1]), 1, "Gaussian(M0,M1)", ), (qml.QuadraticPhase(3.14, wires=[1]), 1, "P(3.14)"), (qml.RX(3.14, wires=[1]), 1, "RX(3.14)"), (qml.S(wires=[2]), 2, "S"), (qml.T(wires=[2]), 2, "T"), (qml.RX(3.14, wires=[1]), 1, "RX(3.14)"), (qml.RY(3.14, wires=[1]), 1, "RY(3.14)"), (qml.RZ(3.14, wires=[1]), 1, "RZ(3.14)"), (qml.Rot(3.14, 2.14, 1.14, wires=[1]), 1, "Rot(3.14, 2.14, 1.14)"), (qml.U1(3.14, wires=[1]), 1, "U1(3.14)"), (qml.U2(3.14, 2.14, wires=[1]), 1, "U2(3.14, 2.14)"), (qml.U3(3.14, 2.14, 1.14, wires=[1]), 1, "U3(3.14, 2.14, 1.14)"), (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 1, "|0⟩"), (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 2, "|1⟩"), (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 3, "|0⟩"), (qml.QubitStateVector(np.array([0, 1, 0, 0]), wires=[1, 2]), 1, "QubitStateVector(M0)"), (qml.QubitStateVector(np.array([0, 1, 0, 0]), wires=[1, 2]), 2, "QubitStateVector(M0)"), (qml.QubitUnitary(np.eye(2), wires=[1]), 1, "U0"), (qml.QubitUnitary(np.eye(4), wires=[1, 2]), 2, "U0"), (qml.Kerr(3.14, wires=[1]), 1, "Kerr(3.14)"), (qml.CrossKerr(3.14, wires=[1, 2]), 1, "CrossKerr(3.14)"), (qml.CrossKerr(3.14, wires=[1, 2]), 2, "CrossKerr(3.14)"), (qml.CubicPhase(3.14, wires=[1]), 1, "V(3.14)"), (qml.InterferometerUnitary( np.eye(4), wires=[1, 3]), 1, "InterferometerUnitary(M0)"), (qml.InterferometerUnitary( np.eye(4), wires=[1, 3]), 3, "InterferometerUnitary(M0)"), (qml.CatState(3.14, 2.14, 1, wires=[1]), 1, "CatState(3.14, 2.14, 1)"), (qml.CoherentState(3.14, 2.14, wires=[1]), 1, "CoherentState(3.14, 2.14)"), ( qml.FockDensityMatrix(np.kron(np.eye(4), np.eye(4)), wires=[1, 2]), 1, "FockDensityMatrix(M0)", ), ( qml.FockDensityMatrix(np.kron(np.eye(4), np.eye(4)), wires=[1, 2]), 2, "FockDensityMatrix(M0)", ), ( qml.DisplacedSqueezedState(3.14, 2.14, 1.14, 0.14, wires=[1]), 1, "DisplacedSqueezedState(3.14, 2.14, 1.14, 0.14)", ), (qml.FockState(7, wires=[1]), 1, "|7⟩"), (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3 ]), 1, "|4⟩"), (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3 ]), 2, "|5⟩"), (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3 ]), 3, "|7⟩"), (qml.SqueezedState(3.14, 2.14, wires=[1]), 1, "SqueezedState(3.14, 2.14)"), (qml.Hermitian(np.eye(4), wires=[1, 2]), 1, "H0"), (qml.Hermitian(np.eye(4), wires=[1, 2]), 2, "H0"), (qml.X(wires=[1]), 1, "x"), (qml.P(wires=[1]), 1, "p"), (qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]), 1, "|4,5,7╳4,5,7|"), ( qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1]), 2, "1+2x₀-1.3x₁+6p₁", ), ( qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5], [-1.3, 4.5, 2.3]]), wires=[1]), 1, "1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀", ), ( qml.PolyXP( np.array([ [1.2, 2.3, 4.5, 0, 0], [-1.2, 1.2, -1.5, 0, 0], [-1.3, 4.5, 2.3, 0, 0], [0, 2.6, 0, 0, 0], [0, 0, 0, -4.7, -1.0], ]), wires=[1], ), 1, "1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀+2.6x₀x₁-p₁²-4.7x₁p₁", ), (qml.QuadOperator(3.14, wires=[1]), 1, "cos(3.14)x+sin(3.14)p"), (qml.PauliX(wires=[1]).inv(), 1, "X⁻¹"), (qml.CNOT(wires=[0, 1]).inv(), 1, "X⁻¹"), (qml.CNOT(wires=[0, 1]).inv(), 0, "C"), (qml.Toffoli(wires=[0, 2, 1]).inv(), 1, "X⁻¹"), (qml.Toffoli(wires=[0, 2, 1]).inv(), 0, "C"), (qml.Toffoli(wires=[0, 2, 1]).inv(), 2, "C"), (qml.measure.sample(wires=[0, 1]), 0, "basis"), # not providing an observable in (qml.measure.sample(wires=[0, 1]), 1, "basis"), # sample gets displayed as raw (two_wire_quantum_tape(), 0, "QuantumTape:T0"), (two_wire_quantum_tape(), 1, "QuantumTape:T0"), ], ) def test_operator_representation_unicode(self, unicode_representation_resolver, op, wire, target): """Test that an Operator instance is properly resolved.""" assert unicode_representation_resolver.operator_representation( op, wire) == target @pytest.mark.parametrize( "op,wire,target", [ (qml.PauliX(wires=[1]), 1, "X"), (qml.CNOT(wires=[0, 1]), 1, "X"), (qml.CNOT(wires=[0, 1]), 0, "C"), (qml.Toffoli(wires=[0, 2, 1]), 1, "X"), (qml.Toffoli(wires=[0, 2, 1]), 0, "C"), (qml.Toffoli(wires=[0, 2, 1]), 2, "C"), (qml.CSWAP(wires=[0, 2, 1]), 1, "SWAP"), (qml.CSWAP(wires=[0, 2, 1]), 2, "SWAP"), (qml.CSWAP(wires=[0, 2, 1]), 0, "C"), (qml.PauliY(wires=[1]), 1, "Y"), (qml.PauliZ(wires=[1]), 1, "Z"), (qml.CZ(wires=[0, 1]), 1, "Z"), (qml.CZ(wires=[0, 1]), 0, "C"), (qml.Identity(wires=[1]), 1, "I"), (qml.Hadamard(wires=[1]), 1, "H"), (qml.CRX(3.14, wires=[0, 1]), 1, "RX(3.14)"), (qml.CRX(3.14, wires=[0, 1]), 0, "C"), (qml.CRY(3.14, wires=[0, 1]), 1, "RY(3.14)"), (qml.CRY(3.14, wires=[0, 1]), 0, "C"), (qml.CRZ(3.14, wires=[0, 1]), 1, "RZ(3.14)"), (qml.CRZ(3.14, wires=[0, 1]), 0, "C"), (qml.CRot(3.14, 2.14, 1.14, wires=[0, 1 ]), 1, "Rot(3.14, 2.14, 1.14)"), (qml.CRot(3.14, 2.14, 1.14, wires=[0, 1]), 0, "C"), (qml.PhaseShift(3.14, wires=[0]), 0, "Rϕ(3.14)"), (qml.Beamsplitter(1, 2, wires=[0, 1]), 1, "BS(1, 2)"), (qml.Beamsplitter(1, 2, wires=[0, 1]), 0, "BS(1, 2)"), (qml.Squeezing(1, 2, wires=[1]), 1, "S(1, 2)"), (qml.TwoModeSqueezing(1, 2, wires=[0, 1]), 1, "S(1, 2)"), (qml.TwoModeSqueezing(1, 2, wires=[0, 1]), 0, "S(1, 2)"), (qml.Displacement(1, 2, wires=[1]), 1, "D(1, 2)"), (qml.NumberOperator(wires=[1]), 1, "n"), (qml.Rotation(3.14, wires=[1]), 1, "R(3.14)"), (qml.ControlledAddition(3.14, wires=[0, 1]), 1, "X(3.14)"), (qml.ControlledAddition(3.14, wires=[0, 1]), 0, "C"), (qml.ControlledPhase(3.14, wires=[0, 1]), 1, "Z(3.14)"), (qml.ControlledPhase(3.14, wires=[0, 1]), 0, "C"), (qml.ThermalState(3, wires=[1]), 1, "Thermal(3)"), ( qml.GaussianState(np.array([[2, 0], [0, 2]]), np.array([1, 2]), wires=[1]), 1, "Gaussian(M0,M1)", ), (qml.QuadraticPhase(3.14, wires=[1]), 1, "P(3.14)"), (qml.RX(3.14, wires=[1]), 1, "RX(3.14)"), (qml.S(wires=[2]), 2, "S"), (qml.T(wires=[2]), 2, "T"), (qml.RX(3.14, wires=[1]), 1, "RX(3.14)"), (qml.RY(3.14, wires=[1]), 1, "RY(3.14)"), (qml.RZ(3.14, wires=[1]), 1, "RZ(3.14)"), (qml.Rot(3.14, 2.14, 1.14, wires=[1]), 1, "Rot(3.14, 2.14, 1.14)"), (qml.U1(3.14, wires=[1]), 1, "U1(3.14)"), (qml.U2(3.14, 2.14, wires=[1]), 1, "U2(3.14, 2.14)"), (qml.U3(3.14, 2.14, 1.14, wires=[1]), 1, "U3(3.14, 2.14, 1.14)"), (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 1, "|0>"), (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 2, "|1>"), (qml.BasisState(np.array([0, 1, 0]), wires=[1, 2, 3]), 3, "|0>"), (qml.QubitStateVector(np.array([0, 1, 0, 0]), wires=[1, 2]), 1, "QubitStateVector(M0)"), (qml.QubitStateVector(np.array([0, 1, 0, 0]), wires=[1, 2]), 2, "QubitStateVector(M0)"), (qml.QubitUnitary(np.eye(2), wires=[1]), 1, "U0"), (qml.QubitUnitary(np.eye(4), wires=[1, 2]), 2, "U0"), (qml.Kerr(3.14, wires=[1]), 1, "Kerr(3.14)"), (qml.CrossKerr(3.14, wires=[1, 2]), 1, "CrossKerr(3.14)"), (qml.CrossKerr(3.14, wires=[1, 2]), 2, "CrossKerr(3.14)"), (qml.CubicPhase(3.14, wires=[1]), 1, "V(3.14)"), (qml.InterferometerUnitary( np.eye(4), wires=[1, 3]), 1, "InterferometerUnitary(M0)"), (qml.InterferometerUnitary( np.eye(4), wires=[1, 3]), 3, "InterferometerUnitary(M0)"), (qml.CatState(3.14, 2.14, 1, wires=[1]), 1, "CatState(3.14, 2.14, 1)"), (qml.CoherentState(3.14, 2.14, wires=[1]), 1, "CoherentState(3.14, 2.14)"), ( qml.FockDensityMatrix(np.kron(np.eye(4), np.eye(4)), wires=[1, 2]), 1, "FockDensityMatrix(M0)", ), ( qml.FockDensityMatrix(np.kron(np.eye(4), np.eye(4)), wires=[1, 2]), 2, "FockDensityMatrix(M0)", ), ( qml.DisplacedSqueezedState(3.14, 2.14, 1.14, 0.14, wires=[1]), 1, "DisplacedSqueezedState(3.14, 2.14, 1.14, 0.14)", ), (qml.FockState(7, wires=[1]), 1, "|7>"), (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3 ]), 1, "|4>"), (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3 ]), 2, "|5>"), (qml.FockStateVector(np.array([4, 5, 7]), wires=[1, 2, 3 ]), 3, "|7>"), (qml.SqueezedState(3.14, 2.14, wires=[1]), 1, "SqueezedState(3.14, 2.14)"), (qml.Hermitian(np.eye(4), wires=[1, 2]), 1, "H0"), (qml.Hermitian(np.eye(4), wires=[1, 2]), 2, "H0"), (qml.X(wires=[1]), 1, "x"), (qml.P(wires=[1]), 1, "p"), (qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]), 1, "|4,5,7X4,5,7|"), ( qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1]), 2, "1+2x_0-1.3x_1+6p_1", ), ( qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5], [-1.3, 4.5, 2.3]]), wires=[1]), 1, "1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0", ), ( qml.PolyXP( np.array([ [1.2, 2.3, 4.5, 0, 0], [-1.2, 1.2, -1.5, 0, 0], [-1.3, 4.5, 2.3, 0, 0], [0, 2.6, 0, 0, 0], [0, 0, 0, -4.7, 0], ]), wires=[1], ), 1, "1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0+2.6x_0x_1-4.7x_1p_1", ), (qml.QuadOperator(3.14, wires=[1]), 1, "cos(3.14)x+sin(3.14)p"), (qml.QuadOperator(3.14, wires=[1]), 1, "cos(3.14)x+sin(3.14)p"), (qml.PauliX(wires=[1]).inv(), 1, "X^-1"), (qml.CNOT(wires=[0, 1]).inv(), 1, "X^-1"), (qml.CNOT(wires=[0, 1]).inv(), 0, "C"), (qml.Toffoli(wires=[0, 2, 1]).inv(), 1, "X^-1"), (qml.Toffoli(wires=[0, 2, 1]).inv(), 0, "C"), (qml.Toffoli(wires=[0, 2, 1]).inv(), 2, "C"), (qml.measure.sample(wires=[0, 1]), 0, "basis"), # not providing an observable in (qml.measure.sample(wires=[0, 1]), 1, "basis"), # sample gets displayed as raw (two_wire_quantum_tape(), 0, "QuantumTape:T0"), (two_wire_quantum_tape(), 1, "QuantumTape:T0"), ], ) def test_operator_representation_ascii(self, ascii_representation_resolver, op, wire, target): """Test that an Operator instance is properly resolved.""" assert ascii_representation_resolver.operator_representation( op, wire) == target @pytest.mark.parametrize( "obs,wire,target", [ (qml.expval(qml.PauliX(wires=[1])), 1, "⟨X⟩"), (qml.expval(qml.PauliY(wires=[1])), 1, "⟨Y⟩"), (qml.expval(qml.PauliZ(wires=[1])), 1, "⟨Z⟩"), (qml.expval(qml.Hadamard(wires=[1])), 1, "⟨H⟩"), (qml.expval(qml.Hermitian(np.eye(4), wires=[1, 2])), 1, "⟨H0⟩"), (qml.expval(qml.Hermitian(np.eye(4), wires=[1, 2])), 2, "⟨H0⟩"), (qml.expval(qml.NumberOperator(wires=[1])), 1, "⟨n⟩"), (qml.expval(qml.X(wires=[1])), 1, "⟨x⟩"), (qml.expval(qml.P(wires=[1])), 1, "⟨p⟩"), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3])), 1, "⟨|4,5,7╳4,5,7|⟩", ), ( qml.expval(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1 ])), 2, "⟨1+2x₀-1.3x₁+6p₁⟩", ), ( qml.expval( qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5], [-1.3, 4.5, 2.3]]), wires=[1])), 1, "⟨1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀⟩", ), (qml.expval(qml.QuadOperator( 3.14, wires=[1])), 1, "⟨cos(3.14)x+sin(3.14)p⟩"), (qml.var(qml.PauliX(wires=[1])), 1, "Var[X]"), (qml.var(qml.PauliY(wires=[1])), 1, "Var[Y]"), (qml.var(qml.PauliZ(wires=[1])), 1, "Var[Z]"), (qml.var(qml.Hadamard(wires=[1])), 1, "Var[H]"), (qml.var(qml.Hermitian(np.eye(4), wires=[1, 2])), 1, "Var[H0]"), (qml.var(qml.Hermitian(np.eye(4), wires=[1, 2])), 2, "Var[H0]"), (qml.var(qml.NumberOperator(wires=[1])), 1, "Var[n]"), (qml.var(qml.X(wires=[1])), 1, "Var[x]"), (qml.var(qml.P(wires=[1])), 1, "Var[p]"), ( qml.var( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3])), 1, "Var[|4,5,7╳4,5,7|]", ), ( qml.var(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1])), 2, "Var[1+2x₀-1.3x₁+6p₁]", ), ( qml.var( qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5], [-1.3, 4.5, 2.3]]), wires=[1])), 1, "Var[1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀]", ), (qml.var(qml.QuadOperator( 3.14, wires=[1])), 1, "Var[cos(3.14)x+sin(3.14)p]"), (qml.sample(qml.PauliX(wires=[1])), 1, "Sample[X]"), (qml.sample(qml.PauliY(wires=[1])), 1, "Sample[Y]"), (qml.sample(qml.PauliZ(wires=[1])), 1, "Sample[Z]"), (qml.sample(qml.Hadamard(wires=[1])), 1, "Sample[H]"), (qml.sample(qml.Hermitian(np.eye(4), wires=[1, 2 ])), 1, "Sample[H0]"), (qml.sample(qml.Hermitian(np.eye(4), wires=[1, 2 ])), 2, "Sample[H0]"), (qml.sample(qml.NumberOperator(wires=[1])), 1, "Sample[n]"), (qml.sample(qml.X(wires=[1])), 1, "Sample[x]"), (qml.sample(qml.P(wires=[1])), 1, "Sample[p]"), ( qml.sample( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3])), 1, "Sample[|4,5,7╳4,5,7|]", ), ( qml.sample(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1 ])), 2, "Sample[1+2x₀-1.3x₁+6p₁]", ), ( qml.sample( qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5], [-1.3, 4.5, 2.3]]), wires=[1])), 1, "Sample[1.2+1.1x₀+3.2p₀+1.2x₀²+2.3p₀²+3x₀p₀]", ), (qml.sample(qml.QuadOperator( 3.14, wires=[1])), 1, "Sample[cos(3.14)x+sin(3.14)p]"), ( qml.expval( qml.PauliX(wires=[1]) @ qml.PauliY(wires=[2]) @ qml.PauliZ(wires=[3])), 1, "⟨X ⊗ Y ⊗ Z⟩", ), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]) @ qml.X(wires=[4])), 1, "⟨|4,5,7╳4,5,7| ⊗ x⟩", ), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]) @ qml.X(wires=[4])), 2, "⟨|4,5,7╳4,5,7| ⊗ x⟩", ), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]) @ qml.X(wires=[4])), 3, "⟨|4,5,7╳4,5,7| ⊗ x⟩", ), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]) @ qml.X(wires=[4])), 4, "⟨|4,5,7╳4,5,7| ⊗ x⟩", ), ( qml.sample( qml.Hermitian(np.eye(4), wires=[1, 2]) @ qml.Hermitian( np.eye(4), wires=[0, 3])), 0, "Sample[H0 ⊗ H0]", ), ( qml.sample( qml.Hermitian(np.eye(4), wires=[1, 2]) @ qml.Hermitian( 2 * np.eye(4), wires=[0, 3])), 0, "Sample[H0 ⊗ H1]", ), (qml.probs([0]), 0, "Probs"), (state(), 0, "State"), ], ) def test_output_representation_unicode(self, unicode_representation_resolver, obs, wire, target): """Test that an Observable instance with return type is properly resolved.""" assert unicode_representation_resolver.output_representation( obs, wire) == target def test_fallback_output_representation_unicode( self, unicode_representation_resolver): """Test that an Observable instance with return type is properly resolved.""" obs = qml.PauliZ(0) obs.return_type = "TestReturnType" assert unicode_representation_resolver.output_representation( obs, 0) == "TestReturnType[Z]" @pytest.mark.parametrize( "obs,wire,target", [ (qml.expval(qml.PauliX(wires=[1])), 1, "<X>"), (qml.expval(qml.PauliY(wires=[1])), 1, "<Y>"), (qml.expval(qml.PauliZ(wires=[1])), 1, "<Z>"), (qml.expval(qml.Hadamard(wires=[1])), 1, "<H>"), (qml.expval(qml.Hermitian(np.eye(4), wires=[1, 2])), 1, "<H0>"), (qml.expval(qml.Hermitian(np.eye(4), wires=[1, 2])), 2, "<H0>"), (qml.expval(qml.NumberOperator(wires=[1])), 1, "<n>"), (qml.expval(qml.X(wires=[1])), 1, "<x>"), (qml.expval(qml.P(wires=[1])), 1, "<p>"), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3])), 1, "<|4,5,7X4,5,7|>", ), ( qml.expval(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1 ])), 2, "<1+2x_0-1.3x_1+6p_1>", ), ( qml.expval( qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5], [-1.3, 4.5, 2.3]]), wires=[1])), 1, "<1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0>", ), (qml.expval(qml.QuadOperator( 3.14, wires=[1])), 1, "<cos(3.14)x+sin(3.14)p>"), (qml.var(qml.PauliX(wires=[1])), 1, "Var[X]"), (qml.var(qml.PauliY(wires=[1])), 1, "Var[Y]"), (qml.var(qml.PauliZ(wires=[1])), 1, "Var[Z]"), (qml.var(qml.Hadamard(wires=[1])), 1, "Var[H]"), (qml.var(qml.Hermitian(np.eye(4), wires=[1, 2])), 1, "Var[H0]"), (qml.var(qml.Hermitian(np.eye(4), wires=[1, 2])), 2, "Var[H0]"), (qml.var(qml.NumberOperator(wires=[1])), 1, "Var[n]"), (qml.var(qml.X(wires=[1])), 1, "Var[x]"), (qml.var(qml.P(wires=[1])), 1, "Var[p]"), ( qml.var( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3])), 1, "Var[|4,5,7X4,5,7|]", ), ( qml.var(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1])), 2, "Var[1+2x_0-1.3x_1+6p_1]", ), ( qml.var( qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5], [-1.3, 4.5, 2.3]]), wires=[1])), 1, "Var[1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0]", ), (qml.var(qml.QuadOperator( 3.14, wires=[1])), 1, "Var[cos(3.14)x+sin(3.14)p]"), (qml.sample(qml.PauliX(wires=[1])), 1, "Sample[X]"), (qml.sample(qml.PauliY(wires=[1])), 1, "Sample[Y]"), (qml.sample(qml.PauliZ(wires=[1])), 1, "Sample[Z]"), (qml.sample(qml.Hadamard(wires=[1])), 1, "Sample[H]"), (qml.sample(qml.Hermitian(np.eye(4), wires=[1, 2 ])), 1, "Sample[H0]"), (qml.sample(qml.Hermitian(np.eye(4), wires=[1, 2 ])), 2, "Sample[H0]"), (qml.sample(qml.NumberOperator(wires=[1])), 1, "Sample[n]"), (qml.sample(qml.X(wires=[1])), 1, "Sample[x]"), (qml.sample(qml.P(wires=[1])), 1, "Sample[p]"), ( qml.sample( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3])), 1, "Sample[|4,5,7X4,5,7|]", ), ( qml.sample(qml.PolyXP(np.array([1, 2, 0, -1.3, 6]), wires=[1 ])), 2, "Sample[1+2x_0-1.3x_1+6p_1]", ), ( qml.sample( qml.PolyXP(np.array([[1.2, 2.3, 4.5], [-1.2, 1.2, -1.5], [-1.3, 4.5, 2.3]]), wires=[1])), 1, "Sample[1.2+1.1x_0+3.2p_0+1.2x_0^2+2.3p_0^2+3x_0p_0]", ), (qml.sample(qml.QuadOperator( 3.14, wires=[1])), 1, "Sample[cos(3.14)x+sin(3.14)p]"), ( qml.expval( qml.PauliX(wires=[1]) @ qml.PauliY(wires=[2]) @ qml.PauliZ(wires=[3])), 1, "<X @ Y @ Z>", ), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]) @ qml.X(wires=[4])), 1, "<|4,5,7X4,5,7| @ x>", ), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]) @ qml.X(wires=[4])), 2, "<|4,5,7X4,5,7| @ x>", ), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]) @ qml.X(wires=[4])), 3, "<|4,5,7X4,5,7| @ x>", ), ( qml.expval( qml.FockStateProjector(np.array([4, 5, 7]), wires=[1, 2, 3]) @ qml.X(wires=[4])), 4, "<|4,5,7X4,5,7| @ x>", ), ( qml.sample( qml.Hermitian(np.eye(4), wires=[1, 2]) @ qml.Hermitian( np.eye(4), wires=[0, 3])), 0, "Sample[H0 @ H0]", ), ( qml.sample( qml.Hermitian(np.eye(4), wires=[1, 2]) @ qml.Hermitian( 2 * np.eye(4), wires=[0, 3])), 0, "Sample[H0 @ H1]", ), (qml.probs([0]), 0, "Probs"), (state(), 0, "State"), ], ) def test_output_representation_ascii(self, ascii_representation_resolver, obs, wire, target): """Test that an Observable instance with return type is properly resolved.""" assert ascii_representation_resolver.output_representation( obs, wire) == target def test_element_representation_none(self, unicode_representation_resolver): """Test that element_representation properly handles None.""" assert unicode_representation_resolver.element_representation(None, 0) == "" def test_element_representation_str(self, unicode_representation_resolver): """Test that element_representation properly handles strings.""" assert unicode_representation_resolver.element_representation( "Test", 0) == "Test" def test_element_representation_calls_output( self, unicode_representation_resolver): """Test that element_representation calls output_representation for returned observables.""" unicode_representation_resolver.output_representation = Mock() obs = qml.sample(qml.PauliX(3)) wire = 3 unicode_representation_resolver.element_representation(obs, wire) assert unicode_representation_resolver.output_representation.call_args[ 0] == (obs, wire) def test_element_representation_calls_operator( self, unicode_representation_resolver): """Test that element_representation calls operator_representation for all operators that are not returned.""" unicode_representation_resolver.operator_representation = Mock() op = qml.PauliX(3) wire = 3 unicode_representation_resolver.element_representation(op, wire) assert unicode_representation_resolver.operator_representation.call_args[ 0] == (op, wire)
def qfunc(x): if model == "qubit": qml.RX(x, wires=0) elif model == "cv": qml.Displacement(x, 0.0, wires=0) return qml.expval(qml.Identity(wires=0))
def circuit(x): qml.Displacement(0.5, 0, wires=[0]) return qml.expval(qml.X(0))
def circuit(x): qml.RX(x, wires=[0]) qml.Displacement(0.5, 0, wires=[0]) return qml.expval(qml.PauliZ(0))
def test_interferometer(self, t, tol): """An integration test for CV gates that support analytic differentiation if succeeding the gate to be differentiated, but cannot be differentiated themselves (for example, they may be Gaussian but accept no parameters, or may accept a numerical array parameter.). This ensures that, assuming their _heisenberg_rep is defined, the quantum gradient analytic method can still be used, and returns the correct result. Currently, the only such operation is qml.Interferometer. In the future, we may consider adding a qml.GaussianTransfom operator. """ if t == 1: pytest.xfail( "There is a bug in the second order CV parameter-shift rule; " "phase arguments return the incorrect derivative.") # Note: this bug currently affects PL core as well: # # dev = qml.device("default.gaussian", wires=2) # # U = np.array([[ 0.51310276+0.81702166j, 0.13649626+0.22487759j], # [ 0.26300233+0.00556194j, -0.96414101-0.03508489j]]) # # @qml.qnode(dev) # def circuit(r, phi): # qml.Displacement(r, phi, wires=0) # qml.Interferometer(U, wires=[0, 1]) # return qml.expval(qml.X(0)) # # r = 0.543 # phi = 0. # # >>> print(circuit.jacobian([r, phi], options={"force_order2":False})) # [[ 1.02620552 0.14823494]] # >>> print(circuit.jacobian([r, phi], options={"force_order2":True})) # [[ 1.02620552 -0.88728552]] U = np.array([ [0.51310276 + 0.81702166j, 0.13649626 + 0.22487759j], [0.26300233 + 0.00556194j, -0.96414101 - 0.03508489j], ]) with qml.tape.JacobianTape() as tape: qml.Displacement(0.543, 0, wires=0) qml.Interferometer(U, wires=[0, 1]) qml.expval(qml.X(0)) tape.trainable_params = {t} dev = qml.device("default.gaussian", wires=2) tapes, fn = qml.gradients.finite_diff(tape) grad_F = fn(dev.batch_execute(tapes)) tapes, fn = param_shift_cv(tape, dev) grad_A = fn(dev.batch_execute(tapes)) tapes, fn = param_shift_cv(tape, dev, force_order2=True) grad_A2 = fn(dev.batch_execute(tapes)) assert tape._par_info[0]["grad_method"] == "A" assert tape._par_info[1]["grad_method"] == "A" # the different methods agree assert np.allclose(grad_A, grad_F, atol=tol, rtol=0) assert np.allclose(grad_A2, grad_F, atol=tol, rtol=0)