Quick start using tqec
#
1. Define your computation#
The first step should be to define the error-corrected computation you want
to implement. For the sake of simplicity, we will take an error-corrected CNOT
implementation that has been defined using SketchUp and available at
media/user_guide/logical_cnot.dae
.
You can also interactively visualise the CNOT implementation below.
2. Import your computation#
In order to use the computation with the tqec
library you need to import it
using tqec.BlockGraph
:
from tqec import BlockGraph
block_graph = BlockGraph.from_dae_file("logical_cnot.dae")
Note
Pre-defined computations
The tqec.gallery
sub-module contains several pre-defined computation that
have already been implemented. If you only want to test the library on a simple
pre-defined computation, you can use to following code:
from tqec.gallery.logical_cnot import logical_cnot_block_graph
block_graph = logical_cnot_block_graph(port_type="Z")
3. Choose the observable(s) of interest#
The tqec
library can automatically search for valid observables in the
imported computation. To get a list of all the valid observables, you can
use the following code
correlation_surfaces = block_graph.find_correlation_surfaces()
Any observable can be plotted using the tqec dae2observables
command line. For our
specific example, the command line
tqec dae2observables --out-dir observables/ logical_cnot.dae
should populate the observables
directory with 3 .png
images representing the
3 valid observables found.
4. Compile and export the computation#
In order to get a stim.Circuit
instance, the computation first need to be compiled.
from tqec import compile_block_graph
# You can pick any number of observables from the output of
# block_graph.find_correlation_surfaces() and provide them here.
# In this example, picking only the second observable for demonstration
# purposes.
compiled_computation = compile_block_graph(block_graph, observables=[correlation_surfaces[1]])
From this compiled computation, the final stim.Circuit
instance can be generated.
from tqec.noise_model import NoiseModel
circuit = compiled_computation.generate_stim_circuit(
k=2,
noise_model=NoiseModel.uniform_depolarizing(0.001),
)
Note
The above call to generate_stim_circuit
also computed automatically
the detectors and observables that can be added to the computation and added
them to the generated circuit. If you are using a regular surface code (as we
are in this quick start guide), the default values for the detectors-related
parameters should be fine.
And that’s all! You now have a quantum circuit representing the topological error-corrected implementation of a CNOT gate shown at the beginning of this page.
You can download the circuit in a stim
format here:
media/user_guide/quick_start/logical_cnot.stim
.
6. Simulate multiple experiments#
The circuit can be simulated using the stim
and sinter
libraries.
Usually you want to simulate combinations of error rates and code distances, potentially
for multiple observables.
Multiple runs can be done in parallel using the sinter
library using the
start_simulation_using_sinter
.
The compilation of the block graph is done automatically based on the inputs.
from multiprocessing import cpu_count
import numpy as np
from tqec.noise_model import NoiseModel
from tqec.simulation.simulation import start_simulation_using_sinter
# returns a iterator
stats = start_simulation_using_sinter(
block_graph,
ks=range(1, 4), # k values for the code distance
ps=list(np.logspace(-4, -1, 10)), # error rates
noise_model_factory=NoiseModel.uniform_depolarizing, # noise model
manhattan_radius=2, # parameter for automatic detector computation
observables=[correlation_surfaces[1]], # observable of interest
decoders=["pymatching"],
num_workers=cpu_count(),
max_shots=10_000_000,
max_errors=5_000,
print_progress=True,
)
Note
While sinter
can be supplied with additional simulation parameters, full interoperability with it is not yet implemented.
See Sinter API Reference for more information.
Warning
If you happen to copy-paste the above code in an executable Python file, you should make sure that you use
if __name__ == "__main__":
...
to wrap all the code that might execute the sinter
calls. To know more about
this issue, have a look at the section “Safe importing of main module” in
the multiprocessing module documentation.
7. Plot the results#
Simulation results can be plotted with matplolib
using the
plot_simulation_results
.
import matplotlib.pyplot as plt
import sinter
from tqec.simulation.plotting.inset import plot_observable_as_inset
zx_graph = block_graph.to_zx_graph()
fig, ax = plt.subplots()
# len(stats) = 1 if we have multiple we can iterate over the results
sinter.plot_error_rate(
ax=ax,
stats=next(stats),
x_func=lambda stat: stat.json_metadata["p"],
group_func=lambda stat: stat.json_metadata["d"],
)
plot_observable_as_inset(ax, zx_graph, correlation_surfaces[1])
ax.grid(axis="both")
ax.legend()
ax.loglog()
ax.set_title("Logical CNOT Error Rate")
fig.savefig(f"logical_cnot_result_x_observable_{1}.png")
8. Conclusion#
This quick start guide has shown how to use the tqec
library to define a computation,
import it into the library, compile it to stim circuits.
Simulations are run and visualized for multiple error rates and code distances.
For an extensive example, see also the
tqec_example.
The process can be repeated through the cli using
tqec run-example --out-dir ./results