From b1a5d6a6cb3d2abf4717941fd4f389af3abfbcd7 Mon Sep 17 00:00:00 2001 From: Akash Narayanan <83135130+AkashNarayanan@users.noreply.github.com> Date: Sat, 2 Oct 2021 14:43:56 +0530 Subject: [PATCH 1/5] Renamed qml.Interferometer to qml.InterferometerUnitary --- doc/introduction/operations.rst | 2 +- .../circuit_drawer/representation_resolver.py | 2 +- pennylane/devices/default_gaussian.py | 6 +++--- pennylane/ops/cv.py | 17 ++++------------- .../test_representation_resolver.py | 8 ++++---- tests/devices/test_default_gaussian.py | 8 ++++---- tests/gradients/test_parameter_shift_cv.py | 8 ++++---- tests/ops/test_cv_ops.py | 10 +--------- tests/tape/test_cv_param_shift.py | 8 ++++---- tests/test_operation.py | 2 +- 10 files changed, 27 insertions(+), 44 deletions(-) diff --git a/doc/introduction/operations.rst b/doc/introduction/operations.rst index 6faf8e7644f..8221f085021 100644 --- a/doc/introduction/operations.rst +++ b/doc/introduction/operations.rst @@ -262,7 +262,7 @@ CV Gates ~pennylane.CrossKerr ~pennylane.CubicPhase ~pennylane.Displacement - ~pennylane.Interferometer + ~pennylane.InterferometerUnitary ~pennylane.Kerr ~pennylane.QuadraticPhase ~pennylane.Rotation diff --git a/pennylane/circuit_drawer/representation_resolver.py b/pennylane/circuit_drawer/representation_resolver.py index 6a1a5bae2f7..d766dee1877 100644 --- a/pennylane/circuit_drawer/representation_resolver.py +++ b/pennylane/circuit_drawer/representation_resolver.py @@ -420,7 +420,7 @@ def operator_representation(self, op, wire): "FockDensityMatrix", "FockStateVector", "QubitStateVector", - "Interferometer", + "InterferometerUnitary", }: representation = name + RepresentationResolver._format_matrix_arguments( op.data, "M", self.matrix_cache diff --git a/pennylane/devices/default_gaussian.py b/pennylane/devices/default_gaussian.py index ea1f4eb5e69..198e176a9ac 100644 --- a/pennylane/devices/default_gaussian.py +++ b/pennylane/devices/default_gaussian.py @@ -305,8 +305,8 @@ def controlled_phase(s): return S -def interferometer(U): - """Interferometer +def interferometer_unitary(U): + """InterferometerUnitary Args: U (array): unitary matrix @@ -668,7 +668,7 @@ class DefaultGaussian(Device): "SqueezedState": squeezed_state, "ThermalState": thermal_state, "GaussianState": gaussian_state, - "Interferometer": interferometer, + "InterferometerUnitary": interferometer_unitary, } _observable_map = { diff --git a/pennylane/ops/cv.py b/pennylane/ops/cv.py index 93f416c67ee..ef7859f5b40 100644 --- a/pennylane/ops/cv.py +++ b/pennylane/ops/cv.py @@ -553,8 +553,8 @@ def adjoint(self, do_queue=False): return CubicPhase(-self.parameters[0], wires=self.wires, do_queue=do_queue) -class Interferometer(CVOperation): - r"""pennylane.Interferometer(U, wires) +class InterferometerUnitary(CVOperation): + r"""pennylane.InterferometerUnitary(U, wires) A linear interferometer transforming the bosonic operators according to the unitary matrix :math:`U`. @@ -588,15 +588,6 @@ class Interferometer(CVOperation): wires (Sequence[int] or int): the wires the operation acts on """ - def __init__(self, *args, **kwargs): - warnings.warn( - "'Interferometer' is deprecated and will be renamed 'InterferometerUnitary'", - UserWarning, - stacklevel=2, - ) - - super().__init__(*args, **kwargs) - num_params = 1 num_wires = AnyWires par_domain = "A" @@ -618,7 +609,7 @@ def _heisenberg_rep(p): def adjoint(self, do_queue=False): U = self.parameters[0] - return Interferometer(qml_math.T(qml_math.conj(U)), wires=self.wires, do_queue=do_queue) + return InterferometerUnitary(qml_math.T(qml_math.conj(U)), wires=self.wires, do_queue=do_queue) # ============================================================================= @@ -1170,7 +1161,7 @@ class FockStateProjector(CVObservable): "Squeezing", "TwoModeSqueezing", "CubicPhase", - "Interferometer", + "InterferometerUnitary", "CatState", "CoherentState", "FockDensityMatrix", diff --git a/tests/circuit_drawer/test_representation_resolver.py b/tests/circuit_drawer/test_representation_resolver.py index e22c9d74a7a..daa60f0e7e5 100644 --- a/tests/circuit_drawer/test_representation_resolver.py +++ b/tests/circuit_drawer/test_representation_resolver.py @@ -139,8 +139,8 @@ def test_single_parameter_representation(self, unicode_representation_resolver, (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.Interferometer(np.eye(4), wires=[1, 3]), 1, "Interferometer(M0)"), - (qml.Interferometer(np.eye(4), wires=[1, 3]), 3, "Interferometer(M0)"), + (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)"), ( @@ -280,8 +280,8 @@ def test_operator_representation_unicode( (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.Interferometer(np.eye(4), wires=[1, 3]), 1, "Interferometer(M0)"), - (qml.Interferometer(np.eye(4), wires=[1, 3]), 3, "Interferometer(M0)"), + (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)"), ( diff --git a/tests/devices/test_default_gaussian.py b/tests/devices/test_default_gaussian.py index c3f46cf1873..36abff15552 100644 --- a/tests/devices/test_default_gaussian.py +++ b/tests/devices/test_default_gaussian.py @@ -412,7 +412,7 @@ def test_apply(self, gaussian_dev, tol): p = [cov, mu] w = list(range(2)) expected_out = [cov, mu] - elif gate_name == "Interferometer": + elif gate_name == "InterferometerUnitary": w = list(range(2)) p = [U] S = fn(*p) @@ -464,12 +464,12 @@ def test_apply_errors(self, gaussian_dev): with pytest.raises(ValueError, match="Incorrect number of subsystems"): p = U - gaussian_dev.apply("Interferometer", wires=Wires([0]), par=[p]) + gaussian_dev.apply("InterferometerUnitary", wires=Wires([0]), par=[p]) with pytest.raises(qml.wires.WireError, match="Did not find some of the wires"): p = U2 # dev = DefaultGaussian(wires=4, shots=1000, hbar=hbar) - gaussian_dev.apply("Interferometer", wires=Wires([0, 1, 2]), par=[p]) + gaussian_dev.apply("InterferometerUnitary", wires=Wires([0, 1, 2]), par=[p]) def test_expectation(self, tol): """Test that expectation values are calculated correctly""" @@ -819,7 +819,7 @@ def reference(*x): if g == "GaussianState": p = [np.diag([0.5234] * 4), np.array([0.432, 0.123, 0.342, 0.123])] - elif g == "Interferometer": + elif g == "InterferometerUnitary": p = [U] else: p = [0.432423, -0.12312, 0.324, 0.763][: op.num_params] diff --git a/tests/gradients/test_parameter_shift_cv.py b/tests/gradients/test_parameter_shift_cv.py index c64cf5a6e95..528249ff66c 100644 --- a/tests/gradients/test_parameter_shift_cv.py +++ b/tests/gradients/test_parameter_shift_cv.py @@ -661,7 +661,7 @@ def test_gradients_gaussian_circuit(self, op, obs, mocker, tol): assert np.allclose(grad_A, grad_F, atol=tol, rtol=0) @pytest.mark.parametrize("t", [0, 1]) - def test_interferometer(self, t, tol): + def test_interferometer_unitary(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, @@ -670,7 +670,7 @@ def test_interferometer(self, t, tol): 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, + Currently, the only such operation is qml.InterferometerUnitary. In the future, we may consider adding a qml.GaussianTransfom operator. """ @@ -690,7 +690,7 @@ def test_interferometer(self, t, tol): # @qml.qnode(dev) # def circuit(r, phi): # qml.Displacement(r, phi, wires=0) - # qml.Interferometer(U, wires=[0, 1]) + # qml.InterferometerUnitary(U, wires=[0, 1]) # return qml.expval(qml.X(0)) # # r = 0.543 @@ -711,7 +711,7 @@ def test_interferometer(self, t, tol): with qml.tape.JacobianTape() as tape: qml.Displacement(0.543, 0, wires=0) - qml.Interferometer(U, wires=[0, 1]) + qml.InterferometerUnitary(U, wires=[0, 1]) qml.expval(qml.X(0)) tape.trainable_params = {t} diff --git a/tests/ops/test_cv_ops.py b/tests/ops/test_cv_ops.py index 6b0f69646b2..d5272692605 100644 --- a/tests/ops/test_cv_ops.py +++ b/tests/ops/test_cv_ops.py @@ -55,7 +55,7 @@ def test_rotation_heisenberg(self, phi): (cv.Displacement(2.004, 8.673, wires=0), 3), # phi > 2pi (cv.Beamsplitter(0.456, -0.789, wires=[0, 2]), 5), (cv.TwoModeSqueezing(2.532, 1.778, wires=[1, 2]), 5), - (cv.Interferometer(np.array([[1, 1], [1, -1]]) * -1.0j / np.sqrt(2.0), wires=1), 5), + (cv.InterferometerUnitary(np.array([[1, 1], [1, -1]]) * -1.0j / np.sqrt(2.0), wires=1), 5), (cv.ControlledAddition(2.551, wires=[0, 2]), 5), (cv.ControlledPhase(2.189, wires=[3, 1]), 5), ], @@ -70,14 +70,6 @@ def test_adjoint_cv_ops(self, op, size, tol): np_testing.assert_allclose(res2, np.eye(size), atol=tol) assert op.wires == op_d.wires - def test_Interferometer_deprecation_warning(self): - """Tests whether a ``UserWarning`` is raised when ``Interferometer`` gate is used.""" - with pytest.warns( - UserWarning, - match="'Interferometer' is deprecated and will be renamed 'InterferometerUnitary'", - ): - cv.Interferometer(np.array([[1, 1], [1, -1]]) * -1.0j / np.sqrt(2.0), wires=1) - @pytest.mark.parametrize( "op", [ diff --git a/tests/tape/test_cv_param_shift.py b/tests/tape/test_cv_param_shift.py index deee76094c4..8b410d40092 100644 --- a/tests/tape/test_cv_param_shift.py +++ b/tests/tape/test_cv_param_shift.py @@ -631,7 +631,7 @@ def test_gradients_gaussian_circuit(self, op, obs, mocker, tol): assert np.allclose(grad_A, grad_F, atol=tol, rtol=0) @pytest.mark.parametrize("t", [0, 1]) - def test_interferometer(self, t, tol): + def test_interferometer_unitary(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, @@ -640,7 +640,7 @@ def test_interferometer(self, t, tol): 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, + Currently, the only such operation is qml.InterferometerUnitary. In the future, we may consider adding a qml.GaussianTransfom operator. """ @@ -660,7 +660,7 @@ def test_interferometer(self, t, tol): # @qml.qnode(dev) # def circuit(r, phi): # qml.Displacement(r, phi, wires=0) - # qml.Interferometer(U, wires=[0, 1]) + # qml.InterferometerUnitary(U, wires=[0, 1]) # return qml.expval(qml.X(0)) # @@ -681,7 +681,7 @@ def test_interferometer(self, t, tol): with CVParamShiftTape() as tape: qml.Displacement(0.543, 0, wires=0) - qml.Interferometer(U, wires=[0, 1]) + qml.InterferometerUnitary(U, wires=[0, 1]) qml.expval(qml.X(0)) tape._update_gradient_info() diff --git a/tests/test_operation.py b/tests/test_operation.py index 42a93e2e70d..8f70fe5e238 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -57,7 +57,7 @@ def test_heisenberg(self, test_class, tol): # fixed parameter values if test_class.par_domain == "A": - if test_class.__name__ == "Interferometer": + if test_class.__name__ == "InterferometerUnitary": ww = list(range(2)) par = [ np.array( From 736a6663a38657a236e0d6e056770592399abb92 Mon Sep 17 00:00:00 2001 From: Akash Narayanan <83135130+AkashNarayanan@users.noreply.github.com> Date: Sat, 2 Oct 2021 15:12:33 +0530 Subject: [PATCH 2/5] Removed unused import --- pennylane/ops/cv.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pennylane/ops/cv.py b/pennylane/ops/cv.py index ef7859f5b40..5e0300e64d1 100644 --- a/pennylane/ops/cv.py +++ b/pennylane/ops/cv.py @@ -35,8 +35,6 @@ # As the qubit based ``decomposition``, ``_matrix``, ``diagonalizing_gates`` # abstract methods are not defined in the CV case, disabling the related check # pylint: disable=abstract-method -import warnings - import math import numpy as np from scipy.linalg import block_diag From c854c23b2dcc06798e9945e72dc911b4ffe92138 Mon Sep 17 00:00:00 2001 From: Akash Narayanan <83135130+AkashNarayanan@users.noreply.github.com> Date: Sat, 2 Oct 2021 15:19:58 +0530 Subject: [PATCH 3/5] Black formatting --- pennylane/ops/cv.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/pennylane/ops/cv.py b/pennylane/ops/cv.py index 5e0300e64d1..5e71cdc5000 100644 --- a/pennylane/ops/cv.py +++ b/pennylane/ops/cv.py @@ -607,7 +607,9 @@ def _heisenberg_rep(p): def adjoint(self, do_queue=False): U = self.parameters[0] - return InterferometerUnitary(qml_math.T(qml_math.conj(U)), wires=self.wires, do_queue=do_queue) + return InterferometerUnitary( + qml_math.T(qml_math.conj(U)), wires=self.wires, do_queue=do_queue + ) # ============================================================================= @@ -1172,15 +1174,7 @@ class FockStateProjector(CVObservable): } -obs = { - "QuadOperator", - "NumberOperator", - "TensorN", - "P", - "X", - "PolyXP", - "FockStateProjector", -} +obs = {"QuadOperator", "NumberOperator", "TensorN", "P", "X", "PolyXP", "FockStateProjector"} __all__ = list(ops | obs) From 23e314b80030b59001f06108fa1a964fccc56ddf Mon Sep 17 00:00:00 2001 From: Akash Narayanan <83135130+AkashNarayanan@users.noreply.github.com> Date: Sat, 2 Oct 2021 15:23:23 +0530 Subject: [PATCH 4/5] Black formatting --- tests/ops/test_cv_ops.py | 55 +++++++++------------------------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/tests/ops/test_cv_ops.py b/tests/ops/test_cv_ops.py index d5272692605..ec4c3cdc8ab 100644 --- a/tests/ops/test_cv_ops.py +++ b/tests/ops/test_cv_ops.py @@ -55,7 +55,12 @@ def test_rotation_heisenberg(self, phi): (cv.Displacement(2.004, 8.673, wires=0), 3), # phi > 2pi (cv.Beamsplitter(0.456, -0.789, wires=[0, 2]), 5), (cv.TwoModeSqueezing(2.532, 1.778, wires=[1, 2]), 5), - (cv.InterferometerUnitary(np.array([[1, 1], [1, -1]]) * -1.0j / np.sqrt(2.0), wires=1), 5), + ( + cv.InterferometerUnitary( + np.array([[1, 1], [1, -1]]) * -1.0j / np.sqrt(2.0), wires=1 + ), + 5, + ), (cv.ControlledAddition(2.551, wires=[0, 2]), 5), (cv.ControlledPhase(2.189, wires=[3, 1]), 5), ], @@ -121,34 +126,10 @@ def test_beamsplitter_heisenberg(self, phi, theta): true_matrix = np.array( [ [1, 0, 0, 0, 0], - [ - 0, - np.cos(theta), - 0, - -np.cos(phi) * np.sin(theta), - -np.sin(phi) * np.sin(theta), - ], - [ - 0, - 0, - np.cos(theta), - np.sin(phi) * np.sin(theta), - -np.cos(phi) * np.sin(theta), - ], - [ - 0, - np.cos(phi) * np.sin(theta), - -np.sin(phi) * np.sin(theta), - np.cos(theta), - 0, - ], - [ - 0, - np.sin(phi) * np.sin(theta), - np.cos(phi) * np.sin(theta), - 0, - np.cos(theta), - ], + [0, np.cos(theta), 0, -np.cos(phi) * np.sin(theta), -np.sin(phi) * np.sin(theta)], + [0, 0, np.cos(theta), np.sin(phi) * np.sin(theta), -np.cos(phi) * np.sin(theta)], + [0, np.cos(phi) * np.sin(theta), -np.sin(phi) * np.sin(theta), np.cos(theta), 0], + [0, np.sin(phi) * np.sin(theta), np.cos(phi) * np.sin(theta), 0, np.cos(theta)], ] ) assert np.allclose(matrix, true_matrix) @@ -182,13 +163,7 @@ def test_controlled_addition_heisenberg(self, s): """ops: Tests the Heisenberg representation of ControlledAddition gate.""" matrix = cv.ControlledAddition._heisenberg_rep([s]) true_matrix = np.array( - [ - [1, 0, 0, 0, 0], - [0, 1, 0, 0, 0], - [0, 0, 1, 0, -s], - [0, s, 0, 1, 0], - [0, 0, 0, 0, 1], - ] + [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, -s], [0, s, 0, 1, 0], [0, 0, 0, 0, 1]] ) assert np.allclose(matrix, true_matrix) @@ -197,13 +172,7 @@ def test_controlled_phase_heisenberg(self, s): """Tests the Heisenberg representation of the ControlledPhase gate.""" matrix = cv.ControlledPhase._heisenberg_rep([s]) true_matrix = np.array( - [ - [1, 0, 0, 0, 0], - [0, 1, 0, 0, 0], - [0, 0, 1, s, 0], - [0, 0, 0, 1, 0], - [0, s, 0, 0, 1], - ] + [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, s, 0], [0, 0, 0, 1, 0], [0, s, 0, 0, 1]] ) assert np.allclose(matrix, true_matrix) From 1a22509de8cfd006acdf402a98a45c0a051fe0e3 Mon Sep 17 00:00:00 2001 From: Akash Narayanan <83135130+AkashNarayanan@users.noreply.github.com> Date: Sat, 2 Oct 2021 15:38:41 +0530 Subject: [PATCH 5/5] Updated changelog --- doc/releases/changelog-dev.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md index 6d399f78ed5..f9d7b31d7c6 100644 --- a/doc/releases/changelog-dev.md +++ b/doc/releases/changelog-dev.md @@ -357,6 +357,10 @@ `requires_grad=False` was explicitly set. [(#1638)](https://github.com/PennyLaneAI/pennylane/pull/1638) +- The operation `qml.Interferometer` has been renamed `qml.InterferometerUnitary` in order to + distinguish it from the template `qml.templates.Interferometer`. + [(#1714)](https://github.com/PennyLaneAI/pennylane/pull/1714) +

Deprecations

* The `init` module, which contains functions to generate random parameter tensors for @@ -394,5 +398,5 @@ This release contains contributions from (in alphabetical order): -Utkarsh Azad, Olivia Di Matteo, Andrew Gardhouse, Josh Izaac, Christina Lee, Romain Moyard, +Utkarsh Azad, Akash Narayanan B, Olivia Di Matteo, Andrew Gardhouse, Josh Izaac, Christina Lee, Romain Moyard, Maria Schuld, Ingrid Strandberg, Antal Száva, David Wierichs.