Python package for simulation and visualization of quantum error-correction on surface codes. The package provides the ability to inspect the error-correcting code during the decoding process, and tools to benchmark the decoder.

watermarkhu, updated 🕥 2022-12-17 14:05:18


PyPI version Build Documentation Status codecov Binder License DOI Unitary Fund

Qsurface is a simulation package for the surface code, and is designed to modularize 3 aspects of a surface code simulation.

  1. The surface code
  2. The error model
  3. The used decoder

New types of surface codes, error modules and decoders can be added to Qsurface by using the included templates for each of the three core module categories.

The current included decoders are:

  • The Mininum-Weight Perfect Matching (mwpm) decoder.
  • Delfosse's and Nickerson's Union-Find (unionfind) decoder, which has almost-linear worst-case time complexity.
  • Our modification to the Union-Find decoder; the Union-Find Node-Suspension (ufns) decoder, which improves the threshold of the Union-Find decoder to near MWPM performance, while retaining quasi-linear worst-case time complexity.

The compatibility of these decoders with the included surface codes are listed below.

| Decoders | toric code | planar code | |-----------|--------------|---------------| |mwpm |✅ |✅ | |unionfind|✅ |✅ | |ufns |✅ |✅ |


All required packages can be installed through:

bash pip install qsurface


  • Python 3.7+
  • Tkinter or PyQt5 for interactive plotting.
  • Matplotlib 3.4+ for plotting on a 3D lattice (Refers to a future release of matplotlib, see pull request)

MWPM decoder

The MWPM decoder utilizes networkx for finding the minimal weights in a fully connected graph. This implementation is however rather slow compared to Kolmogorov's Blossom V algorithm. Blossom V has its own license and is thus not included with Qsurface. We do provided a single function to download and compile Blossom V, and to setup the integration with Qsurface automatically.


from qsurface.decoders import mwpm mwpm.get_blossomv() ```


To simulate the toric code and simulate with bitflip error for 10 iterations and decode with the MWPM decoder:


from qsurface.main import initialize, run code, decoder = initialize((6,6), "toric", "mwpm", enabled_errors=["pauli"]) run(code, decoder, iterations=10, error_rates = {"p_bitflip": 0.1}) {'no_error': 8} ```

Benchmarking of decoders can be enabled by attaching a benchmarker object to the decoder. See the docs for the syntax and information to setup benchmarking.


from qsurface.main import initialize, run benchmarker = BenchmarkDecoder({"decode":"duration"}) run(code, decoder, iterations=10, error_rates = {"p_bitflip": 0.1}, benchmark=benchmarker) {'no_error': 8, 'benchmark': {'success_rate': [10, 10], 'seed': 12447.413636559, 'durations': {'decode': {'mean': 0.00244155000000319, 'std': 0.002170364089572033}}}} ```


The figures in Qsurface allows for step-by-step visualization of the surface code simulation (and if supported the decoding process). Each figure logs its history such that the user can move backwards in time to view past states of the surface (and decoder). Press h when the figure is open for more information.


from qsurface.main import initialize, run code, decoder = initialize((6,6), "toric", "mwpm", enabled_errors=["pauli"], plotting=True, initial_states=(0,0)) run(code, decoder, error_rates = {"p_bitflip": 0.1, "p_phaseflip": 0.1}, decode_initial=False) ```

Interactive plotting on a 6x6 toric code.

Plotting will be performed on a 3D axis if faulty measurements are enabled.


code, decoder = initialize((3,3), "toric", "mwpm", enabled_errors=["pauli"], faulty_measurements=True, plotting=True, initial_states=(0,0)) run(code, decoder, error_rates = {"p_bitflip": 0.05, "p_bitflip_plaq": 0.05}, decode_initial=False) ```

Interactive plotting on a toric code with faulty measurements.

In IPython, inline images are created for each iteration of the plot, which can be tested in the example notebook.

Command line interface

Simulations can also be initiated from the command line

bash $ python -m qsurface -e pauli -D mwpm -C toric simulation --p_bitflip 0.1 -n 10 {'no_error': 8}

For more information on command line interface:

bash $ python -m qsurface -h usage: qsurface ...

This project is proudly funded by the Unitary Fund.


An Example Code for the simplest Case

opened on 2022-10-18 08:46:16 by apassenger

Hello, I am a new starter and trying to produce the simplest case for the surface code by using qsurface.

I will be appreciate, if you can check the code: I will put no error to the simulation 1)I want to create the surface code for distance 3 2)I want to initialize all the data qubits in 0 state 3)I want to put X and Z stabilizers 4)Then I want to measure all the X stabilizers. In this case they will randomly change and commute with Z stabilizers and Z stabilizers will not change With this scenario, I want to see how mwpm is working

As code: code, decoder = initialize((3,3), "planar", "mwpm", enabled_errors=[], plotting=True, initial_states=(0,0)) run(code, decoder, error_rates = {}, decode_initial=True) #"p_bitflip": 0.1, "p_phaseflip": 0.1

But I could see nothing. Could you help me for my first code?

How to generate .gif as in example

opened on 2022-08-03 14:26:33 by Arvendui

Hi, could you provide some basic hints on how to produce an animations from a jupyter notebook like the ones you show in the example? Thanks a lot

Multiprocessing `RecursionError: maximum recursion depth exceeded while calling a Python object` [WINDOWS ISSUE]

opened on 2022-04-06 15:39:04 by siddhantphy

Running multiprocessed codes on larger lattices (for both union-find and MWPM) results in a recursion depth error for the pickled input arguments, i.e. code and decoder objects. For faulty measurements, this error happens for lattices as small as 4x4. This happens on Windows. While it works perfectly in the Unix environment. Steps to reproduce ``` from qsurface.main import initialize, run_multiprocess

code, decoder = initialize((4, 4), "toric", "unionfind", enabled_errors=["pauli"], faulty_measurements=True) if name == "main": run_multiprocess(code, decoder, iterations=100, error_rates={"p_bitflip": 0.01}) ```

Error Traceback (most recent call last): File "c:\Users\*\Desktop\", line 5, in <module> run_multiprocess(code, decoder, iterations=100, error_rates={"p_bitflip": 0.01}) File "C:\Users\*\AppData\Local\Programs\Python\Python310\lib\site-packages\qsurface\", line 276, in run_multiprocess worker.start() File "C:\Users\*\AppData\Local\Programs\Python\Python310\lib\multiprocessing\", line 121, in start self._popen = self._Popen(self) File "C:\Users\*\AppData\Local\Programs\Python\Python310\lib\multiprocessing\", line 224, in _Popen return _default_context.get_context().Process._Popen(process_obj) File "C:\Users\*\AppData\Local\Programs\Python\Python310\lib\multiprocessing\", line 327, in _Popen return Popen(process_obj) File "C:\Users\*\AppData\Local\Programs\Python\Python310\lib\multiprocessing\", line 93, in __init__ reduction.dump(process_obj, to_child) File "C:\Users\*\AppData\Local\Programs\Python\Python310\lib\multiprocessing\", line 60, in dump ForkingPickler(file, protocol).dump(obj) RecursionError: maximum recursion depth exceeded while calling a Python object PS C:\Users\*> Traceback (most recent call last): File "<string>", line 1, in <module> File "C:\Users\*\AppData\Local\Programs\Python\Python310\lib\multiprocessing\", line 116, in spawn_main exitcode = _main(fd, parent_sentinel) File "C:\Users\*\AppData\Local\Programs\Python\Python310\lib\multiprocessing\", line 126, in _main self = reduction.pickle.load(from_parent) EOFError: Ran out of input

Inquiry on plots for unionfind decoder

opened on 2022-03-10 00:34:05 by ntrqpy

Hi, first or all, thank you for making this amazing repo. I really like the plotting feature that allows me to understand what is happening. I have three issues/questions, and I would really appreciate if you could solve these, especially the first one.

1. Plotting unionfind decoder

I'm running the following in jupyter notebook.

%matplotlib qt from qsurface.main import initialize, run code, decoder = initialize((5,5), "toric", "unionfind", enabled_errors=["pauli"], plotting=True, initial_states=(0,0)) run(code, decoder, error_rates = {"p_bitflip": 0.05, "p_phaseflip": 0.05}, decode_initial=False)

For the first three plots (initialization, error applied, ancilla qubits measured, everything is fine. But when I hit next, another window pops up, and the grid doesn't show anymore. It looks like this: Capture

Could you please solve this, so that the grid shows up, just like when I use the mwpm decoder?

  1. Warning when I press "previous" in interactive plot

I have the following message: Traceback (most recent call last): File "C:\Users\lg\anaconda3\lib\site-packages\matplotlib\", line 270, in process func(args, kwargs) File "C:\Users\lg\anaconda3\lib\site-packages\matplotlib\", line 225, in return self._observers.connect('clicked', lambda event: func(event)) File "C:\Users\lg\anaconda3\lib\site-packages\qsurface\", line 695, in _draw_prev return self._draw_from_history(self.history_iter > 1, -1, kwargs) File "C:\Users\lg\anaconda3\lib\site-packages\qsurface\", line 682, in _draw_from_history self.draw_figure(*kwargs) File "C:\Users\lg\anaconda3\lib\site-packages\qsurface\", line 648, in draw_figure self.focus() File "C:\Users\lg\anaconda3\lib\site-packages\qsurface\", line 471, in focus output = self.blocking_input(self.params.blocking_wait) File "C:\Users\lg\anaconda3\lib\site-packages\qsurface\", line 159, in call return super().call(n=1, timeout=timeout) File "C:\Users\lg\anaconda3\lib\site-packages\matplotlib\", line 93, in call self.fig.canvas.start_event_loop(timeout=timeout) File "C:\Users\lg\anaconda3\lib\site-packages\matplotlib\backends\", line 424, in start_event_loop raise RuntimeError("Event loop already running") RuntimeError: Event loop already running

  1. Question: What is info / bitflip / phaseflip in this image? image

Again, I really appreciate this repo, and I hope you reply!

Update Patch3D plotting

opened on 2020-09-24 08:59:03 by watermarkhu

Previously, Patch3D objects wouldn't update colors, to which a workaround was made to plot several versions of the same object in the same location and to select one as the visible object. This bug was tracked in

A recent pull request fixes this bug The workaround can thus be removed.

Add configuration file to repeat simulations

opened on 2020-07-01 13:15:18 by nathanshammah

The file has been refactored. It should be updated in the Readme file. If possible, I'd suggest having also one basic example that produces a plot without any additional command line appended command. I.e., typing bash python generates a plot / intended outcome. I wonder whether a configuration / settings file could help to store command line configurations that one is re-using (e.g., 8 -l planar -px 0.03 -pmx 0.03 -i 1000).


Fix for manifest file. 2020-12-01 10:49:52

This release includes a fix for a breaking error as pointed out by @evanphilip in #35, in which ini files are not packaged due to a naming error of the manifest file.

(re)release as Qsurface 2020-11-17 20:08:15

This release has no new features and is simply a (re)release. OpenSurfaceSim has been rebranded to Qsurface.

If you have already installed the package through pip, make sure to uninstall the previous release pip uninstall opensurfacesim and install the new release pip install qsurface, which is the version that will be kept updated.

Qt5Agg support 2020-11-10 20:27:04

Another update with fixes following the v.0.1.1 PyPI release.

  • Support for the Qt5Agg backend for interactive plotting.
  • Fix for static forest generation in the Union-Find decoder
  • Fix for legends not properly showing
  • Fix for redrawing of temporary changes to plot objects

Added support for IPython 2020-11-05 17:30:28

For IPython, the GUI of the Tkinter backend is not available. The included examples.ipynb, for example, does not produce any figures, but raises an import error. This PR adds support for IPython, and outputs each iteration of the interactive figure as a separate image.

Additional fixes for the Pauli error legend and missing figures.

PyPI release! 2020-11-04 21:52:51

quantum-error-correction surface-code