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 (QNode or QuantumTape) – the quantum circuit 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

The transformed circuit as described in qml.transform.

Return type

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

Example

Given a Hamiltonian,

H = qml.Z(0) + 0.5 * qml.Z(2) + qml.Z(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.X(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.X(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.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.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.X(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.execute(tapes)
>>> fn(res)
10.108949481425782