qml.transforms.sum_expand

sum_expand(tape, group=True)[source]

Splits a quantum tape measuring a Sum expectation into multiple tapes of summand expectations, and provides a function to recombine the results.

Parameters
  • tape (QuantumTape) – the quantum tape used when calculating the expectation value of the Hamiltonian

  • group (bool) – Whether to compute disjoint groups of Pauli observables acting on different wires, leading to fewer tapes.

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[Sequence[QuantumTape], Callable]

Example

Given a Sum operator,

S = qml.sum(qml.prod(qml.Y(2), qml.Z(1)), qml.s_prod(0.5, qml.Z(2)), qml.Z(1))

and a tape of the form,

ops = [qml.Hadamard(0), qml.CNOT((0,1)), qml.X(2)]
measurements = [
    qml.expval(S),
    qml.expval(qml.Z(0)),
    qml.expval(qml.X(1)),
    qml.expval(qml.Z(2))
]
tape = qml.tape.QuantumTape(ops, measurements)

We can use the sum_expand transform to generate new tapes and a classical post-processing function to speed-up the computation of the expectation value of the Sum.

>>> tapes, fn = qml.transforms.sum_expand(tape, group=False)
>>> for tape in tapes:
...     print(tape.measurements)
[expval(Y(2) @ Z(1))]
[expval(Z(2))]
[expval(Z(1))]
[expval(Z(0))]
[expval(X(1))]

Five tapes are generated: the first three contain the summands of the Sum operator, and the last two contain the remaining observables. Note that the scalars of the scalar products have been removed. In the processing function, these values will be multiplied by the result obtained from executing the tapes.

Additionally, the observable expval(Z(2)) occurs twice in the original tape, but only once in the transformed tapes. When there are multipe identical measurements in the circuit, the measurement is performed once and the outcome is copied when obtaining the final result. This will also be resolved when the processing function is applied.

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)
[-0.5, 0.0, 0.0, -0.9999999999999996]

Fewer tapes can be constructed by grouping observables acting on different wires. This can be achieved by the group keyword argument:

S = qml.sum(qml.Z(0), qml.s_prod(2, qml.X(1)), qml.s_prod(3, qml.X(0)))

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

With grouping, the Sum gets split into two groups of observables (here [qml.Z(0), qml.s_prod(2, qml.X(1))] and [qml.s_prod(3, qml.X(0))]):

>>> tapes, fn = qml.transforms.sum_expand(tape, group=True)
>>> for tape in tapes:
...     print(tape.measurements)
[expval(Z(0)), expval(X(1))]
[expval(X(0))]