hamiltonian_expand(tape, group=True)[source]

Splits a tape measuring a Hamiltonian expectation into mutliple tapes of Pauli expectations, and provides a function to recombine the results.

  • tape (QNode or QuantumTape or Callable) – the quantum circuit used when calculating the expectation value of the Hamiltonian

  • group (bool) – Whether to compute disjoint groups of commuting Pauli observables, leading to fewer tapes. If grouping information can be found in the Hamiltonian, it will be used even if group=False.


The transformed circuit as described in qml.transform.

Return type

qnode (QNode) or tuple[List[QuantumTape], function]


Given a Hamiltonian,

H = qml.PauliY(2) @ qml.PauliZ(1) + 0.5 * qml.PauliZ(2) + qml.PauliZ(1)

and a tape of the form,

ops = [qml.Hadamard(0), qml.CNOT((0,1)), qml.PauliX(2)]
tape = qml.tape.QuantumTape(ops, [qml.expval(H)])

We can use the hamiltonian_expand transform to generate new tapes and a classical post-processing function for computing the expectation value of the Hamiltonian.

>>> tapes, fn = qml.transforms.hamiltonian_expand(tape)

We can evaluate these tapes on a device:

>>> dev = qml.device("default.qubit", wires=3)
>>> res = dev.execute(tapes)

Applying the processing function results in the expectation value of the Hamiltonian:

>>> fn(res)

Fewer tapes can be constructed by grouping commuting observables. This can be achieved by the group keyword argument:

H = qml.Hamiltonian([1., 2., 3.], [qml.PauliZ(0), qml.PauliX(1), qml.PauliX(0)])

tape = qml.tape.QuantumTape(ops, [qml.expval(H)])

With grouping, the Hamiltonian gets split into two groups of observables (here [qml.PauliZ(0)] and [qml.PauliX(1), qml.PauliX(0)]):

>>> tapes, fn = qml.transforms.hamiltonian_expand(tape)
>>> len(tapes)

Without grouping it gets split into three groups ([qml.PauliZ(0)], [qml.PauliX(1)] and [qml.PauliX(0)]):

>>> tapes, fn = qml.transforms.hamiltonian_expand(tape, group=False)
>>> len(tapes)

Alternatively, if the Hamiltonian has already computed groups, they are used even if group=False:

obs = [qml.PauliZ(0), qml.PauliX(1), qml.PauliX(0)]
coeffs = [1., 2., 3.]
H = qml.Hamiltonian(coeffs, obs, grouping_type='qwc')

# the initialisation already computes grouping information and stores it in the Hamiltonian
assert H.grouping_indices is not None

tape = qml.tape.QuantumTape(ops, [qml.expval(H)])

Grouping information has been used to reduce the number of tapes from 3 to 2:

>>> tapes, fn = qml.transforms.hamiltonian_expand(tape, group=False)
>>> len(tapes)