Cutting: Difference between processing functions

Hi!

I have a question regarding the two circuit-cutting postprocessing functions qcut_processing_fn_sample and qcut_processing_fn_mc:

Is qcut_processing_fn_mc with a postprocessing function fn the same as running qcut_processing_fn_sample and running np.mean([fn(s) for s in samples]) on the resulting samples?

In particular, in the following example, they seem to be the same (or at least similar), but are they by definition?

import pennylane as qml
from pennylane import numpy as np
from functools import partial

dev = qml.device("default.qubit", wires=2, shots=10000)


def fn(x):
    if x[0] == 0:
        return 1
    if x[0] == 1:
        return -1


@partial(qml.cut_circuit_mc, classical_processing_fn=fn)
@qml.qnode(dev)
def circuit(x):
    qml.RX(0.89, wires=0)
    qml.RY(0.5, wires=1)
    qml.RX(1.3, wires=2)

    qml.CNOT(wires=[0, 1])
    qml.WireCut(wires=1)
    qml.CNOT(wires=[1, 2])

    qml.RX(x, wires=0)
    qml.RY(0.7, wires=1)
    qml.RX(2.3, wires=2)
    return qml.sample(wires=[0, 1, 2])

@partial(qml.cut_circuit_mc)
@qml.qnode(dev)
def circuit2(x):
    qml.RX(0.89, wires=0)
    qml.RY(0.5, wires=1)
    qml.RX(1.3, wires=2)

    qml.CNOT(wires=[0, 1])
    qml.WireCut(wires=1)
    qml.CNOT(wires=[1, 2])

    qml.RX(x, wires=0)
    qml.RY(0.7, wires=1)
    qml.RX(2.3, wires=2)
    return qml.sample(wires=[0, 1, 2])

x = 2.90
res1 = circuit(x)

samples = circuit2(x)
res2 = np.mean([fn(s) for s in samples])

print(abs(res1-res2))

If they are the same per definition, what is the advantage of qcut_processing_fn_mc compared to qcut_processing_fn_sample?

Thank you!
Nate

Hi @Nathaniel_Tornow , welcome to the Forum and thank you for your question!

Please see Tom’s answer here.

TLDR: we recommend using qcut_processing_fn_mc.

Enjoy using PennyLane!