Skip to content

Commit f8740cf

Browse files
dwierichsobliviateandsurrenderPabloAMC
authored
Optimize BasisRotation for real-valued inputs and extend theory in docstring (#7765)
**Context:** `qml.BasisRotation` implements a basis rotation in the space of orbitals, mapped to quantum circuits. In general, the decomposition contains `PhaseShift` and `SingleExcitation` gates. If the rotation matrix is real-valued, and thus orthogonal, the decomposition can be simplified to Givens rotations (`SingleExcitation`) only (for special orthogonal, i.e., determinant $1$), or Givens rotations and a single `PhaseShift` (determinant $-1$). In addition, we recently gained some insight in how to understand the mapping from orbital rotations to qubits. **Description of the Change:** Add a branch to the decomposition of `qml.BasisRotation` that is triggered if the rotation matrix has a real number data type. It uses zero or one `PhaseShift` operations instead of up to $(N^2+N)/2$ phase shifts, and the same number of `SingleExcitation` gates as the complex-valued decomposition. The second major change is an extension of the theory part of the docstring of `BasisRotation`, including a Lie algebraic explanation for the mapping. **Benefits:** Cheaper decomposition. More math context in docs. **Possible Drawbacks:** More complex decomposition logic. **Related GitHub Issues:** [sc-94397] **To do** - [x] First docstring pass - [x] Second docstring pass - [x] test completion (matrix tests?) - [x] reduce logic if possible - [x] changelog --------- Co-authored-by: Utkarsh <[email protected]> Co-authored-by: Pablo Antonio Moreno Casares <[email protected]>
1 parent 3abae5c commit f8740cf

File tree

8 files changed

+806
-156
lines changed

8 files changed

+806
-156
lines changed

doc/code/qml_math.rst

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@ Overview
1313
Utility functions for decompositions
1414
------------------------------------
1515

16-
.. currentmodule:: pennylane.math.decomposition
16+
.. autosummary::
17+
:toctree: api
1718

18-
.. automodapi:: pennylane.math.decomposition
19-
:no-heading:
20-
:no-inherited-members:
19+
~decomposition.decomp_int_to_powers_of_two
20+
~decomposition.givens_decomposition
21+
~decomposition.su2su2_to_tensor_products
22+
~decomposition.xyx_rotation_angles
23+
~decomposition.xzx_rotation_angles
24+
~decomposition.zxz_rotation_angles
25+
~decomposition.zyz_rotation_angles

doc/releases/changelog-dev.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@
6464

6565
<h3>Improvements 🛠</h3>
6666

67+
* The decomposition of :class:`~.BasisRotation` has been optimized to skip redundant phase shift gates
68+
with angle :math:`\pm \pi` for real-valued, i.e., orthogonal, rotation matrices. This uses the fact that
69+
no or single :class:`~.PhaseShift` gate is required in case the matrix has a determinant :math:`\pm 1`.
70+
[(#7765)](https://github.com/PennyLaneAI/pennylane/pull/7765)
71+
6772
* Changed how basis states are assigned internally in `qml.Superposition`, improving its
6873
decomposition slightly both regarding classical computing time and gate decomposition.
6974
[(#7880)](https://github.com/PennyLaneAI/pennylane/pull/7880)
@@ -147,6 +152,12 @@
147152

148153
<h4>Other improvements</h4>
149154

155+
* The matrix factorization using :func:`~.math.decomposition.givens_decomposition` has
156+
been optimized to factor out the redundant sign in the diagonal phase matrix for the
157+
real-valued (orthogonal) rotation matrices. For example, in case the determinant of a matrix is
158+
:math:`-1`, only a single element of the phase matrix is required.
159+
[(#7765)](https://github.com/PennyLaneAI/pennylane/pull/7765)
160+
150161
* Added the `NumQubitsOp` operation to the `Quantum` dialect of the Python compiler.
151162
[(#8063)](https://github.com/PennyLaneAI/pennylane/pull/8063)
152163

@@ -169,8 +180,6 @@
169180
╚═══╝
170181
```
171182

172-
173-
174183
* PennyLane is now compatible with `quimb` 1.11.2 after a bug affecting `default.tensor` was fixed.
175184
[(#7931)](https://github.com/PennyLaneAI/pennylane/pull/7931)
176185

@@ -576,6 +585,11 @@
576585

577586
<h3>Documentation 📝</h3>
578587

588+
* The theoretical background section of :class:`~.BasisRotation` has been extended to explain
589+
the underlying Lie group/algebra homomorphism between the (dense) rotation matrix and the
590+
performed operations on the target qubits.
591+
[(#7765)](https://github.com/PennyLaneAI/pennylane/pull/7765)
592+
579593
* Updated the code examples in the documentation of :func:`~.specs`.
580594
[(#8003)](https://github.com/PennyLaneAI/pennylane/pull/8003)
581595

pennylane/math/__init__.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,39 @@ def get_dtype_name(x) -> str:
142142
return ar.get_dtype_name(x)
143143

144144

145+
def is_real_obj_or_close(obj):
146+
"""Convert an array to its real part if it is close to being real-valued, and afterwards
147+
return whether the resulting data type is real.
148+
149+
Args:
150+
obj (array): Array to check for being (close to) real.
151+
152+
Returns:
153+
bool: Whether the array ``obj``, after potentially converting it to a real matrix,
154+
has a real data type. This is obtained by checking whether the data type name starts with
155+
``"complex"`` and returning the negated result of this.
156+
157+
>>> x = jnp.array(0.4)
158+
>>> qml.math.is_real_obj_or_close(x)
159+
True
160+
161+
>>> x = tf.Variable(0.4+0.2j)
162+
>>> qml.math.is_real_obj_or_close(x)
163+
False
164+
165+
>>> x = torch.tensor(0.4+1e-13j)
166+
>>> qml.math.is_real_obj_or_close(x)
167+
True
168+
169+
Default absolute and relative tolerances of
170+
``qml.math.allclose`` are used to determine whether the
171+
input is close to real-valued.
172+
"""
173+
if not is_abstract(obj) and allclose(ar.imag(obj), 0.0):
174+
obj = ar.real(obj)
175+
return not get_dtype_name(obj).startswith("complex")
176+
177+
145178
class NumpyMimic(ar.autoray.NumpyMimic):
146179
"""Subclass of the Autoray NumpyMimic class in order to support
147180
the NumPy fft submodule"""
@@ -202,6 +235,7 @@ def __getattr__(name):
202235
"in_backprop",
203236
"is_abstract",
204237
"is_independent",
238+
"is_real_obj_or_close",
205239
"iscomplex",
206240
"jacobian",
207241
"kron",

0 commit comments

Comments
 (0)