qml.transforms.hamiltonian_expand

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.

Parameters
  • tape (QuantumTape) – the tape 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.

Returns

Returns a tuple containing a list of quantum tapes to be evaluated, and a function to be applied to these tape executions to compute the expectation value.

Return type

tuple[list[QuantumTape], function]

Example

Given a Hamiltonian,

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

and a tape of the form,

with qml.tape.QuantumTape() as tape:
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    qml.PauliX(wires=2)

    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.batch_execute(tapes)

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

>>> fn(res)
-0.5

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)])

with qml.tape.QuantumTape() as tape:
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    qml.PauliX(wires=2)
    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)
2

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)
3

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

with qml.tape.QuantumTape() as tape:
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    qml.PauliX(wires=2)
    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)
2