diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 9fe50728861..6b99fcbe0c0 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -210,6 +210,9 @@
* `qml.AmplitudeEmbedding` has better support for features using low precision integer data types.
[(#5969)](https://github.com/PennyLaneAI/pennylane/pull/5969)
+* `qml.lie_closure` works with sums of Paulis.
+ [(#6023)](https://github.com/PennyLaneAI/pennylane/pull/6023)
+
Contributors ✍️
@@ -226,6 +229,7 @@ Emiliano Godinez,
Renke Huang,
Josh Izaac,
Soran Jahangiri,
+Korbinian Kottmann,
Christina Lee,
Austin Huang,
William Maxwell,
diff --git a/pennylane/pauli/dla/lie_closure.py b/pennylane/pauli/dla/lie_closure.py
index 931befcfd4f..7ed9a939314 100644
--- a/pennylane/pauli/dla/lie_closure.py
+++ b/pennylane/pauli/dla/lie_closure.py
@@ -14,6 +14,7 @@
"""A function to compute the Lie closure of a set of operators"""
# pylint: disable=too-many-arguments
import itertools
+import warnings
from collections.abc import Iterable
from copy import copy
from functools import reduce
@@ -135,8 +136,11 @@ def lie_closure(
while (new_length > old_length) and (epoch < max_iterations):
if verbose:
print(f"epoch {epoch+1} of lie_closure, DLA size is {new_length}")
+
for ps1, ps2 in itertools.combinations(vspace.basis, 2):
com = ps1.commutator(ps2)
+ com.simplify()
+
if len(com) == 0: # skip because operators commute
continue
@@ -144,6 +148,7 @@ def lie_closure(
# remove common factor 2 with Pauli commutators
for pw, val in com.items():
com[pw] = val.imag / 2
+
vspace.add(com, tol=tol)
# Updated number of linearly independent PauliSentences from previous and current step
@@ -151,6 +156,9 @@ def lie_closure(
new_length = len(vspace)
epoch += 1
+ if epoch == max_iterations:
+ warnings.warn(f"reached the maximum number of iterations {max_iterations}", UserWarning)
+
if verbose > 0:
print(f"After {epoch} epochs, reached a DLA size of {new_length}")
diff --git a/tests/pauli/dla/test_lie_closure.py b/tests/pauli/dla/test_lie_closure.py
index fc2f4361e90..50babf8e000 100644
--- a/tests/pauli/dla/test_lie_closure.py
+++ b/tests/pauli/dla/test_lie_closure.py
@@ -344,7 +344,9 @@ def test_max_iterations(self, capsys):
PauliSentence({PauliWord({i: "X", (i + 1) % n: "Z"}): 1.0}) for i in range(n - 1)
]
- res = qml.pauli.lie_closure(generators, verbose=True, max_iterations=1)
+ with pytest.warns(UserWarning, match="reached the maximum number of iterations"):
+ res = qml.pauli.lie_closure(generators, verbose=True, max_iterations=1)
+
captured = capsys.readouterr()
assert (
captured.out
@@ -501,6 +503,17 @@ def test_lie_closure_heisenberg_generators_even(self):
res = qml.pauli.lie_closure(generators)
assert len(res) == 4 * ((2 ** (n - 2)) ** 2 - 1)
+ @pytest.mark.parametrize("n, res", [(3, 4), (4, 12)])
+ def test_lie_closure_heisenberg(self, n, res):
+ """Test the resulting DLA from Heisenberg model with summed generators"""
+ genXX = [X(i) @ X(i + 1) for i in range(n - 1)]
+ genYY = [Y(i) @ Y(i + 1) for i in range(n - 1)]
+ genZZ = [Z(i) @ Z(i + 1) for i in range(n - 1)]
+
+ generators = [qml.sum(XX + YY + ZZ) for XX, YY, ZZ in zip(genXX, genYY, genZZ)]
+ g = qml.lie_closure(generators)
+ assert len(g) == res
+
def test_universal_gate_set(self):
"""Test universal gate set"""
n = 3