# Stochastic Calibration (SC)¶

This example will show how to characterize the noise acting in a system so that it can be corrected. We begin by initializing a noisy simulator with a 2-qubit rotation about $$Z$$ by some angle $$\theta$$. Then we show how to find $$\theta$$ using stochastic calibration.

import numpy as np
import matplotlib.pyplot as plt
import trueq as tq

# make a noisy simulator

# adding a rotation by 12 degrees to the first qubit in every 2-qubit gate,
# i.e. Z(12) is the noise we are going to try to characterize
mat = tq.Gate.from_generators("Z", 12).mat


Out:

<trueq.simulation.simulator.Simulator object at 0x7efce682c470>


We are going to perform stochastic calibration for a $$CZ$$ gate. We choose to look at the $$XI$$ Pauli decay because it anticommutes with our suspected error, $$ZI$$. Equivalently, we could have have chosen to use the $$YI$$ Pauli decay to characterize our $$ZI$$ error. To minimize the experimental footprint, we use data at a single sequence length as in [2].

cycle = tq.Cycle({(0, 1): tq.Gate.cz}, immutable=True)

# generate SC circuits with 24 random cycles to get decays associated with XI
circuits = tq.make_sc(cycle, [24], pauli_decays=["XI"])
print(len(circuits))


Out:

30


Find the expectation value and standard deviation of the circuit when corrections of the form $$Z(\phi)$$ are applied on the first qubit prior to each $$CZ$$ gate. The expectation values correspond to the $$XI$$ diagonal entry of the superoperator in the Pauli basis; values close to $$1$$ indicate that the suspected error is small.

# 20 equidistant points between -40 and 40 for trial values of phi
angles = np.linspace(-40, 40, 20)

# initialize ev and stds as all zeros with length of angles.
# ev stores expectation values; sds stores standard deviations
ev = np.zeros_like(angles)
sds = np.zeros_like(angles)

for j, phi in enumerate(angles):
# adds a Z(phi) rotation on qubit 0 gate before every CZ gate
c = tq.compilation.CycleSandwich(
cycle, before=tq.Cycle({(0): tq.Gate.from_generators("Z", phi)})
)
new_circs = tq.CircuitCollection(map(c.apply, circuits))

# run circuit collection (with Z(phi)s inserted)
sim.run(new_circs)

# make a vector of expectation values for new_circs
vec = [v for _, v in new_circs.expectation_values().items()]

# take the mean expectation value and find standard deviation
ev[j] = np.mean(vec)
sds[j] = np.std(vec) / np.sqrt(len(circuits))


plot the expectation values as a function of $$\phi$$:

plt.errorbar(angles, ev, sds)
plt.xlabel("Z compensation angle")
plt.ylabel("Expectation value after 24 applications")


Out:

Text(0, 0.5, 'Expectation value after 24 applications')


The maximum expectation value corresponds to the value of $$XI$$ closest to 1, so finding the angle at which the plot peaks tells us which angle to rotate by to correct the noise. The peak occurs at approximately $$\phi = -12$$, which is consistent with the noise applied by the simulator.

Total running time of the script: ( 0 minutes 5.292 seconds)

Gallery generated by Sphinx-Gallery