catalyst.mitigate_with_zne

mitigate_with_zne(fn=None, *, scale_factors, extrapolate=None, extrapolate_kwargs=None, folding='global')[source]

A qjit() compatible error mitigation of an input circuit using zero-noise extrapolation.

Error mitigation is a precursor to error correction and is compatible with near-term quantum devices. It aims to lower the impact of noise when evaluating a circuit on a quantum device by evaluating multiple variations of the circuit and post-processing the results into a noise-reduced estimate. This transform implements the zero-noise extrapolation (ZNE) method originally introduced by Temme et al. and Li et al..

Parameters
  • fn (qml.QNode) – the circuit to be mitigated.

  • scale_factors (list[int]) – the range of noise scale factors used.

  • extrapolate (Callable) – A qjit-compatible function taking two sequences as arguments (scale factors, and results), and returning a float by performing a fitting procedure. By default, perfect polynomial fitting polynomial_extrapolate() will be used, the exponential_extrapolate() function from PennyLane may also be used.

  • extrapolate_kwargs (dict[str, Any]) – Keyword arguments to be passed to the extrapolation function.

  • folding (str) – Unitary folding technique to be used to scale the circuit. Possible values: - global: the global unitary of the input circuit is folded - local-all: per-gate folding sequences replace original gates in-place in the circuit

Returns

A callable object that computes the mitigated of the wrapped QNode for the given arguments.

Return type

Callable

Example:

For example, given a noisy device (such as noisy hardware available through Amazon Braket):

# replace "noisy.device" with your noisy device
dev = qml.device("noisy.device", wires=2)

@qml.qnode(device=dev)
def circuit(x, n):
    @for_loop(0, n, 1)
    def loop_rx(i):
        qml.RX(x, wires=0)

    loop_rx()

    qml.Hadamard(wires=0)
    qml.RZ(x, wires=0)
    loop_rx()
    qml.RZ(x, wires=0)
    qml.CNOT(wires=[1, 0])
    qml.Hadamard(wires=1)
    return qml.expval(qml.PauliY(wires=0))

@qjit
def mitigated_circuit(args, n):
    s = [1, 3, 5]
    return mitigate_with_zne(circuit, scale_factors=s)(args, n)

Alternatively the mitigate_with_zne function can be applied directly on a qjitted function containing QNode, the mitigation will be applied on each QNode individually.

Exponential extrapolation can also be performed via the exponential_extrapolate() function from PennyLane:

from pennylane.transforms import exponential_extrapolate

dev = qml.device("lightning.qubit", wires=2, shots=100000)

@qml.qnode(dev)
def circuit(weights):
    qml.StronglyEntanglingLayers(weights, wires=[0, 1])
    return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))

@qjit
def workflow(weights, s):
    zne_circuit = mitigate_with_zne(
        circuit, scale_factors=s, extrapolate=exponential_extrapolate
    )
    return zne_circuit(weights)
>>> weights = jnp.ones([3, 2, 3])
>>> scale_factors = [1, 3, 5]
>>> workflow(weights, scale_factors)
Array(-0.19946598, dtype=float64)