diff --git a/doc/development/deprecations.rst b/doc/development/deprecations.rst index a62dfde5c13..cc080c1a1e6 100644 --- a/doc/development/deprecations.rst +++ b/doc/development/deprecations.rst @@ -36,8 +36,8 @@ Pending deprecations - Deprecated in v0.31 - Will be removed in v0.32 -* ``LieAlgebraOptimizer`` is renamed. Please use ``RiemannianGradientOptimizer`` instead. - +* ``LieAlgebraOptimizer`` has been renamed. Please use ``RiemannianGradientOptimizer`` instead. + - Deprecated in v0.31 - Will be removed in v0.32 @@ -86,7 +86,7 @@ Pending deprecations * ``qml.ExpvalCost`` has been deprecated, and usage will now raise a warning. - Deprecated in v0.24 - - Will be removed in v0.31 + - Will be removed in v0.32 Instead, it is recommended to simply pass Hamiltonians to the ``qml.expval`` function inside QNodes: @@ -122,17 +122,17 @@ Pending deprecations Completed deprecation cycles ---------------------------- -* The ``qml.utils.sparse_hamiltonian`` function is deprecated. ``~.Hamiltonian.sparse_matrix`` should be used instead. +* The ``qml.utils.sparse_hamiltonian`` function has been removed. ``~.Hamiltonian.sparse_matrix`` should be used instead. - Deprecated in v0.29 - Removed in v0.31 -* The ``collections`` module has been deprecated. +* The ``collections`` module has been removed. - Deprecated in v0.29 - Removed in v0.31 -* ``qml.op_sum``` is deprecated. Users should use ``qml.sum`` instead. +* ``qml.op_sum``` has been removed. Users should use ``qml.sum`` instead. - Deprecated in v0.29. - Removed in v0.31. @@ -159,11 +159,11 @@ Completed deprecation cycles - The old signature is replaced with the new one in v0.30 -* The ``grouping`` module is removed. The functionality has been moved and +* The ``grouping`` module has been removed. The functionality has been moved and reorganized in the new ``pauli`` module under ``pauli/utils.py`` or ``pauli/grouping/``. - Still accessible in v0.27, v0.28, v0.29, v0.30 - - Will be removed in v0.31 + - Removed in v0.31 The functions from ``grouping/pauli.py``, ``grouping/transformations.py`` and ``grouping/utils.py`` have been moved to ``pauli/utils.py``. The remaining functions diff --git a/pennylane/ops/qubit/matrix_ops.py b/pennylane/ops/qubit/matrix_ops.py index 8904be9cf57..0e1a69dbb62 100644 --- a/pennylane/ops/qubit/matrix_ops.py +++ b/pennylane/ops/qubit/matrix_ops.py @@ -343,8 +343,13 @@ def compute_decomposition(D, wires): .. math:: O = O_1 O_2 \dots O_n. - ``DiagonalQubitUnitary`` decomposes into :class:`~.QubitUnitary`, which has further - decompositions for one and two qubit matrices. + ``DiagonalQubitUnitary`` decomposes into :class:`~.QubitUnitary`, :class:`~.RZ`, + :class:`~.IsingZZ`, and/or :class:`~.MultiRZ` depending on the number of wires. + + .. note:: + + The parameters of the decomposed operations are cast to the ``complex128`` dtype + as real dtypes can lead to ``NaN`` values in the decomposition. .. seealso:: :meth:`~.DiagonalQubitUnitary.decomposition`. @@ -367,7 +372,11 @@ def compute_decomposition(D, wires): """ n = len(wires) - phases = qml.math.real(qml.math.log(D) * (-1j)) + + # Cast the diagonal into a complex dtype so that the logarithm works as expected + D_casted = qml.math.cast(D, "complex128") + + phases = qml.math.real(qml.math.log(D_casted) * (-1j)) coeffs = _walsh_hadamard_transform(phases, n).T global_phase = qml.math.exp(1j * coeffs[0]) # For all other gates, there is a prefactor -1/2 to be compensated. diff --git a/pennylane/qnn/keras.py b/pennylane/qnn/keras.py index 4aa76ef3782..1e1ae282023 100644 --- a/pennylane/qnn/keras.py +++ b/pennylane/qnn/keras.py @@ -133,19 +133,19 @@ def qnode(inputs, weights): return qlayer(x).shape >>> print_output_shape([qml.expval(qml.PauliZ(0))]) - (5,) + TensorShape([5]) >>> print_output_shape([qml.probs(wires=[0, 1])]) - (5, 4) + TensorShape([5, 4]) >>> print_output_shape([qml.sample(wires=[0, 1])]) - (5, 100, 2) + TensorShape([5, 100, 2]) If the QNode returns multiple measurements, then the measurement results will be flattened and concatenated, resulting in an output of shape ``(batch_dim, total_flattened_dim)``: >>> print_output_shape([qml.expval(qml.PauliZ(0)), qml.probs(wires=[0, 1])]) - (5, 5) + TensorShape([5, 5]) >>> print_output_shape([qml.probs([0, 1]), qml.sample(wires=[0, 1])]) - (5, 204) + TensorShape([5, 204]) **Initializing weights** diff --git a/tests/ops/qubit/test_matrix_ops.py b/tests/ops/qubit/test_matrix_ops.py index 05a749e2e20..79cc0291c5c 100644 --- a/tests/ops/qubit/test_matrix_ops.py +++ b/tests/ops/qubit/test_matrix_ops.py @@ -537,6 +537,21 @@ def test_decomposition_matrix_match_broadcasted(self, n): assert qml.math.allclose(orig_mat, decomp_mat) assert qml.math.allclose(orig_mat, decomp_mat2) + @pytest.mark.parametrize( + "dtype", [np.float64, np.float32, np.int64, np.int32, np.complex128, np.complex64] + ) + def test_decomposition_cast_to_complex128(self, dtype): + """Test that the parameters of decomposed operations are of the correct dtype.""" + D = np.array([1, 1, -1, -1]).astype(dtype) + wires = [0, 1] + decomp1 = qml.DiagonalQubitUnitary(D, wires).decomposition() + decomp2 = qml.DiagonalQubitUnitary.compute_decomposition(D, wires) + + assert decomp1[0].data[0].dtype == np.complex128 + assert decomp2[0].data[0].dtype == np.complex128 + assert all(op.data[0].dtype == np.float64 for op in decomp1[1:]) + assert all(op.data[0].dtype == np.float64 for op in decomp2[1:]) + def test_controlled(self): """Test that the correct controlled operation is created when controlling a qml.DiagonalQubitUnitary.""" # pylint: disable=protected-access