qml.lie_closure¶
- lie_closure(generators, max_iterations=10000, verbose=False, pauli=False, tol=None)[source]¶
Compute the dynamical Lie algebra from a set of generators.
The Lie closure, pronounced “Lee” closure, is a way to compute the so-called dynamical Lie algebra (DLA) of a set of generators \(\mathcal{G} = \{G_1, .. , G_N\}\). For such generators, one computes all nested commutators \([G_i, [G_j, .., [G_k, G_\ell]]]\) until no new operators are generated from commutation. All these operators together form the DLA, see e.g. section IIB of arXiv:2308.01432.
- Parameters
generators (Iterable[Union[PauliWord, PauliSentence, Operator]]) – generating set for which to compute the Lie closure.
max_iterations (int) – maximum depth of nested commutators to consider. Default is
10000
.verbose (bool) – whether to print out progress updates during Lie closure calculation. Default is
False
.pauli (bool) – Indicates whether it is assumed that
PauliSentence
orPauliWord
instances are input and returned. This can help with performance to avoid unnecessary conversions toOperator
and vice versa. Default isFalse
.tol (float) – Numerical tolerance for the linear independence check used in
PauliVSpace
.
- Returns
a basis of either
PauliSentence
orOperator
instances that is closed under commutators (Lie closure).- Return type
Union[list[
PauliSentence
], list[Operator
]]
See also
structure_constants()
,center()
,PauliVSpace
, Demo: Introduction to Dynamical Lie Algebras for quantum practitionersExample
Let us walk through a simple example of computing the Lie closure of the generators of the transverse field Ising model on two qubits.
>>> ops = [X(0) @ X(1), Z(0), Z(1)]
A first round of commutators between all elements yields:
>>> qml.commutator(X(0) @ X(1), Z(0)) -2j * (Y(0) @ X(1)) >>> qml.commutator(X(0) @ X(1), Z(1)) -2j * (X(0) @ Y(1))
A next round of commutators between all elements further yields the new operator
Y(0) @ Y(1)
.>>> qml.commutator(X(0) @ Y(1), Z(0)) -2j * (Y(0) @ Y(1))
After that, no new operators emerge from taking nested commutators and we have the resulting DLA. This can be done in short via
lie_closure
as follows.>>> ops = [X(0) @ X(1), Z(0), Z(1)] >>> dla = qml.lie_closure(ops) >>> print(dla) [X(1) @ X(0), Z(0), Z(1), -1.0 * (Y(0) @ X(1)), -1.0 * (X(0) @ Y(1)), -1.0 * (Y(0) @ Y(1))]
Note that we normalize by removing the factors of \(2i\), though minus signs are left intact.
Usage Details
Note that by default,
lie_closure
returns PennyLane operators. Internally we use the more efficient representation in terms ofPauliSentence
by making use of theop.pauli_rep
attribute of operators composed of Pauli operators. If desired, this format can be returned by using the keywordpauli=True
. In that case, the input is also assumed to be aPauliSentence
instance.>>> ops = [ ... PauliSentence({PauliWord({0: "X", 1: "X"}): 1.}), ... PauliSentence({PauliWord({0: "Z"}): 1.}), ... PauliSentence({PauliWord({1: "Z"}): 1.}), ... ] >>> dla = qml.lie_closure(ops, pauli=True) >>> print(dla) [1.0 * X(0) @ X(1), 1.0 * Z(0), 1.0 * Z(1), -1.0 * Y(0) @ X(1), -1.0 * X(0) @ Y(1), -1.0 * Y(0) @ Y(1)] >>> type(dla[0]) pennylane.pauli.pauli_arithmetic.PauliSentence