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