qml.transforms.sign_expand

sign_expand(tape, circuit=False, J=10, delta=0.0, controls=('Hadamard', 'Target'))[source]

Splits a tape measuring a (fast-forwardable) Hamiltonian expectation into mutliple tapes of the Xi or sgn decomposition, and provides a function to recombine the results.

Implementation of ideas from arXiv:2207.09479

For the calculation of variances, one assumes an even distribution of shots among the groups.

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

  • circuit (bool) – Toggle the calculation of the analytical Xi decomposition or if True constructs the circuits of the approximate sign decomposition to measure the expectation value

  • J (int) – The times the time evolution of the hamiltonian is repeated in the quantum signal processing approximation of the sgn-decomposition

  • delta (float) – The minimal

  • controls (List[control1, control2]) – The two additional controls to implement the Hadamard test and the quantum signal processing part on, have to be wires on the device

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.PauliZ(0) + 0.5 * qml.PauliZ(2) + qml.PauliZ(1)

a device with auxiliary qubits,

dev = qml.device("default.qubit", wires=[0,1,2,'Hadamard','Target'])

and a circuit of the form, with the transform as decorator.

@qml.transforms.sign_expand
@qml.qnode(dev)
def circuit():
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    qml.PauliX(wires=2)
    return qml.expval(H)
>>> circuit()
-0.4999999999999999

You can also work directly on tapes:

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

We can use the sign_expand transform to generate new tapes and a classical post-processing function for computing the expectation value of the Hamiltonian in these new decompositions

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

We can evaluate these tapes on a device, it needs two additional ancilla gates labeled ‘Hadamard’ and ‘Target’ if one wants to make the circuit approximation of the decomposition:

>>> dev = qml.device("default.qubit", wires=[0,1,2,'Hadamard','Target'])
>>> res = dev.batch_execute(tapes)
>>> fn(res)
-0.4999999999999999

To evaluate the circuit approximation of the decomposition one can construct the sgn-decomposition by changing the kwarg circuit to True:

>>> tapes, fn = qml.transforms.sign_expand(tape, circuit=True, J=20, delta=0)
>>> dev = qml.device("default.qubit", wires=[0,1,2,'Hadamard','Target'])
>>> dev.batch_execute(tapes)
>>> fn(res)
-0.24999999999999994

Lastly, as the paper is about minimizing variance, one can also calculate the variance of the estimator by changing the tape:

operations = [qml.Hadamard(wires=0), qml.CNOT(wires=[0, 1]), qml.PauliX(wires=2)]
measurements = [qml.var(H)]
tape = qml.tape.QuantumTape(operations, measurements)
>>> tapes, fn = qml.transforms.sign_expand(tape, circuit=True, J=20, delta=0)
>>> dev = qml.device("default.qubit", wires=[0,1,2,'Hadamard','Target'])
>>> res = dev.batch_execute(tapes)
>>> fn(res)
10.108949481425782