diff --git a/doc/getting_started.ipynb b/doc/getting_started.ipynb
index bab6b62f..4bd015a6 100644
--- a/doc/getting_started.ipynb
+++ b/doc/getting_started.ipynb
@@ -1,20963 +1,20997 @@
{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "7vg1S92NEAXs"
- },
- "source": [
- "## Index\n",
- "\n",
- "1. [What is stim?](#what-is-stim)\n",
- "2. [Install the `stim` python package.](#install-stim)\n",
- "3. [Create a simple circuit, and sample from it.](#make-circuit)\n",
- "4. [Add detector annotations to a circuit, and sample them.](#sample-detectors)\n",
- "5. [Generate example error correction circuits.](#make-qec-circuits)\n",
- "6. [Use `pymatching` to correct errors in a circuit.](#use-pymatching)\n",
- "7. [Estimate the threshold of a repetition code using Monte Carlo sampling.](#rep-code)\n",
- "8. [Use `sinter` to streamline the Monte Carlo sampling process.](#use-sinter)\n",
- "9. [Estimate the threshold and footprint of a surface code.](#surface-code)\n",
- "10. [Additional resources](additional-resources)\n",
- "\n",
- "## Prereqs\n",
- "\n",
- "This tutorial assumes you can read and write Python code, and that you have a working Python 3.7+ environment (perhaps you are reading this notebook in such an environment).\n",
- "\n",
- "This tutorial assumes you understand what a quantum circuit is. For example, it assumes you know what a qubit is, what a Hadamard gate is, and what a CNOT gate is.\n",
- "\n",
- "This tutorial assumes you are a *little* familiar with stabilizer circuits. For example, it assumes you've heard that they can be simulated cheaply and that they can represent protocols such as quantum error correction.\n",
- "\n",
- "This tutorial assumes you are a *little* familiar with quantum error correcting codes. For example, it assumes you've heard the term \"surface code\" and \"threshold\"."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "ulLKqhVxmfxr",
- "jp-MarkdownHeadingCollapsed": true
- },
- "source": [
- "\n",
- "# 1. What is Stim?\n",
- "\n",
- "Stim is an [open source tool](https://github.com/quantumlib/Stim) for high performance analysis and simulation of quantum stabilizer circuits, with a focus on quantum error correction circuits.\n",
- "\n",
- "Here is a plot from the [paper introducing Stim](https://doi.org/10.22331/q-2021-07-06-497), showing that Stim is thousands of times faster than other tools at sampling stabilizer circuits:\n",
- "\n",
- "\n",
- "\n",
- "In addition to fast simulation, Stim provides general utilities for editing, inspecting, and transforming stabilizer circuits. In particular, Stim can automatically derive a matching graph from a stabilizer circuit annotated with detectors and noise channels."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "fh8rot1PYyDh"
- },
- "source": [
- "\n",
- "# 2. Install the Stim python package.\n",
- "\n",
- "The first thing to do is to install and import stim.\n",
- "Thanks to the python ecosystem, this is easy!\n",
- "Stim is available as a pypi package, and can be installed using `pip install stim` and then imported with `import stim`.\n",
- "Just like any other python package."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "7vg1S92NEAXs"
+ },
+ "source": [
+ "\n",
+ "
Welcome to the Stim tutorial!
\n",
+ "\n",
+ "This Jupyter notebook is a tutorial for [Stim](https://github.com/quantumlib/stim), a tool for high-performance simulation and analysis of quantum stabilizer circuits. You can run this notebook in your browser using [Google Colab](https://colab.google/), or download it to your computer and run it using [Jupyter](https://docs.jupyter.org/en/latest/running.html).\n"
+ ]
},
- "id": "fMf_vlB7D6fR",
- "outputId": "d100e5e2-53a3-4205-931e-916fa67940dc"
- },
- "outputs": [],
- "source": [
- "!pip install stim~=1.14\n",
- "!pip install numpy~=1.0 # 1.0 instead of 2.0 for pymatching compatibility later\n",
- "!pip install scipy"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "id": "P0lD6ilJD8Pi"
- },
- "outputs": [
{
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1.14.0\n"
- ]
- }
- ],
- "source": [
- "import stim\n",
- "print(stim.__version__)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "vah6-5YpGdaG"
- },
- "source": [
- "\n",
- "# 3. Create a simple circuit, and sample from it.\n",
- "\n",
- "In Stim, circuits are instances of the `stim.Circuit` class. You create a new empty circuit with `stim.Circuit()`, and add operations to it by calling `circuit.append(name_of_gate, list_of_targets)`.\n",
- "\n",
- "You can find the name of the gate you want from the [stim gates reference](https://github.com/quantumlib/Stim/blob/main/doc/gates.md). Most of them are straightforward, like \"H\" for the Hadamard gate. Targets are just a number indicating a qubit. There's a qubit `0`, a qubit `1`, etc.\n",
- "\n",
- "The first circuit you'll make is a circuit that prepares a Bell pair and then measures it:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
+ "cell_type": "markdown",
+ "source": [
+ "# Table of contents\n",
+ "\n",
+ "0. [Prerequisites](#prerequisites)\n",
+ "1. [What is Stim?](#what-is-stim)\n",
+ "2. [Copy and use this Jupyter/Colab notebook](#using-this-notebook)\n",
+ "3. [Install the `stim` Python package](#install-stim)\n",
+ "4. [Create a simple circuit, and sample from it](#make-circuit)\n",
+ "5. [Add detector annotations to a circuit, and sample them](#sample-detectors)\n",
+ "6. [Generate example error correction circuits](#make-qec-circuits)\n",
+ "7. [Use `pymatching` to correct errors in a circuit](#use-pymatching)\n",
+ "8. [Estimate the threshold of a repetition code using Monte Carlo sampling](#rep-code)\n",
+ "9. [Use `sinter` to streamline the Monte Carlo sampling process](#use-sinter)\n",
+ "10. [Estimate the threshold and footprint of a surface code](#surface-code)\n",
+ "11. [Conclusion](#end-of-tutorial)\n",
+ "12. [Additional resources](additional-resources)"
+ ],
+ "metadata": {
+ "id": "0V2LXIBKKqA9"
+ }
},
- "id": "UP84FdeWGodO",
- "outputId": "9b6d4b2f-1cb9-4941-d533-db148aaaf86f"
- },
- "outputs": [],
- "source": [
- "circuit = stim.Circuit()\n",
- "\n",
- "# First, the circuit will initialize a Bell pair.\n",
- "circuit.append(\"H\", [0])\n",
- "circuit.append(\"CNOT\", [0, 1])\n",
- "\n",
- "# Then, the circuit will measure both qubits of the Bell pair in the Z basis.\n",
- "circuit.append(\"M\", [0, 1])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "vah6-5YpGdaG"
- },
- "source": [
- "Stim has a few ways to look at the circuits you've made. The circuit's `repr` is an expression that recreates the circuit using [stim's circuit file syntax](https://github.com/quantumlib/Stim/blob/main/doc/file_format_stim_circuit.md):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
+ {
+ "cell_type": "markdown",
+ "source": [
+ "\n",
+ "# 0. Prerequisites\n",
+ "\n",
+ "To get the most out of this tutorial, it's helpful to have the following background:\n",
+ "\n",
+ "- Familiarity with basic Python syntax, and having a working Python 3.7+ environment. (Perhaps you are reading this notebook in such an environment.)\n",
+ "\n",
+ "- Familiarity with the basic concepts of *quantum circuits*, such as qubits and common quantum gates like Hadamard and CNOT.\n",
+ "\n",
+ "- A basic understanding of stabilizer circuits. For example, this tutorial assumes you've heard that they can be simulated cheaply and that they can represent protocols such as quantum error correction.\n",
+ "\n",
+ "- *Some* familiarity with quantum error-correcting codes. For example, this tutorial assumes that you've heard the terms \"surface code\" and \"threshold\".\n",
+ "\n",
+ "If you don't have these prerequisites yet, take a look at the [additional resources](additional-resources) at the end of this tutorial for suggestions about how to learn more."
+ ],
+ "metadata": {
+ "id": "43rMSrBhKtyX"
+ }
},
- "id": "UP84FdeWGodO",
- "outputId": "9b6d4b2f-1cb9-4941-d533-db148aaaf86f"
- },
- "outputs": [
{
- "data": {
- "text/plain": [
- "stim.Circuit('''\n",
- " H 0\n",
- " CX 0 1\n",
- " M 0 1\n",
- "''')"
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "ulLKqhVxmfxr",
+ "jp-MarkdownHeadingCollapsed": true
+ },
+ "source": [
+ "\n",
+ "# 1. What is Stim?\n",
+ "\n",
+ "Stim is an [open-source tool](https://github.com/quantumlib/Stim) for high-performance analysis and simulation of quantum stabilizer circuits, with a focus on quantum error correction circuits.\n",
+ "\n",
+ "Here is a plot from the [paper introducing Stim](https://doi.org/10.22331/q-2021-07-06-497), showing that Stim is thousands of times faster than other tools at sampling stabilizer circuits:\n",
+ "\n",
+ "\n",
+ "\n",
+ "In addition to fast simulation, Stim provides general utilities for editing, inspecting, and transforming stabilizer circuits. In particular, Stim can automatically derive a matching graph from a stabilizer circuit annotated with detectors and noise channels."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "fh8rot1PYyDh"
+ },
+ "source": [
+ "\n",
+ "# 2. Install the Stim python package\n",
+ "\n",
+ "The first thing to do is to install and import Stim.\n",
+ "Thanks to the Python ecosystem, this is easy to do!\n",
+ "Stim is available as a [PyPI](https://pypi.org/project/stim/) package, and can be installed using `pip install stim` and then imported with `import stim` (just like any other python package)."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "fMf_vlB7D6fR"
+ },
+ "outputs": [],
+ "source": [
+ "!pip install stim~=1.14\n",
+ "!pip install numpy~=1.0 # 1.0 instead of 2.0 for pymatching compatibility later\n",
+ "!pip install scipy"
]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "circuit"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "vah6-5YpGdaG"
- },
- "source": [
- "You can also use the `circuit.diagram` method to get an annotated text diagram of the circuit:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
},
- "id": "UP84FdeWGodO",
- "outputId": "9b6d4b2f-1cb9-4941-d533-db148aaaf86f"
- },
- "outputs": [
{
- "data": {
- "text/html": [
- "
"
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "P0lD6ilJD8Pi",
+ "outputId": "79a7cd42-9677-46f7-df1e-1cd4a518f601"
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "1.14.0\n"
+ ]
+ }
],
- "text/plain": [
- "q0: -H-@-M:rec[0]-\n",
- " |\n",
- "q1: ---X-M:rec[1]-"
+ "source": [
+ "import stim\n",
+ "print(stim.__version__)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "vah6-5YpGdaG"
+ },
+ "source": [
+ "\n",
+ "# 3. Create a simple circuit, and sample from it\n",
+ "\n",
+ "In Stim, circuits are instances of the `stim.Circuit` class. You create a new empty circuit with `stim.Circuit()`, and add operations to it by calling `circuit.append(name_of_gate, list_of_targets)`.\n",
+ "\n",
+ "You can find the name of the gate you want from the [Stim gates reference](https://github.com/quantumlib/Stim/blob/main/doc/gates.md). Most of them are straightforward, like \"H\" for the Hadamard gate. Targets are just a number indicating a qubit. There's a qubit `0`, a qubit `1`, etc.\n",
+ "\n",
+ "The first circuit you'll make is a circuit that prepares a [Bell pair](https://en.wikipedia.org/wiki/Bell_state) and then measures it:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "id": "UP84FdeWGodO"
+ },
+ "outputs": [],
+ "source": [
+ "circuit = stim.Circuit()\n",
+ "\n",
+ "# First, the circuit will initialize a Bell pair.\n",
+ "circuit.append(\"H\", [0])\n",
+ "circuit.append(\"CNOT\", [0, 1])\n",
+ "\n",
+ "# Then, the circuit will measure both qubits of the Bell pair in the Z basis.\n",
+ "circuit.append(\"M\", [0, 1])"
]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "circuit.diagram()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "vah6-5YpGdaG"
- },
- "source": [
- "There's also other types diagrams. For example, specifying `timeline-svg` will return a Scalable Vector Graphics picture of the circuit instead of a text diagram:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
},
- "id": "UP84FdeWGodO",
- "outputId": "9b6d4b2f-1cb9-4941-d533-db148aaaf86f"
- },
- "outputs": [
{
- "data": {
- "image/svg+xml": [
- ""
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "ySG_dqfQ-qOQ"
+ },
+ "source": [
+ "Stim has a few ways to look at the circuits you've made. The circuit's `repr` is an expression that recreates the circuit using [Stim's circuit file syntax](https://github.com/quantumlib/Stim/blob/main/doc/file_format_stim_circuit.md):"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "outputId": "9b6d4b2f-1cb9-4941-d533-db148aaaf86f",
+ "id": "L51yrzUW-qOQ"
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "stim.Circuit('''\n",
+ " H 0\n",
+ " CX 0 1\n",
+ " M 0 1\n",
+ "''')"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
],
- "text/plain": [
- ""
+ "source": [
+ "circuit"
]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "circuit.diagram('timeline-svg')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "5dRl_-WZHDP2"
- },
- "source": [
- "Anyways, let's stop looking at your circuit and start using it. You can sample from the circuit by using the `circuit.compile_sampler()` method to get a sampler object, and then calling `sample` on that object.\n",
- "\n",
- "Try taking 10 shots from the circuit:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
},
- "id": "sJVtzniUHL1X",
- "outputId": "2b54c59c-0d0a-492f-fae7-87f4751f8415"
- },
- "outputs": [
{
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[False False]\n",
- " [ True True]\n",
- " [False False]\n",
- " [False False]\n",
- " [ True True]\n",
- " [False False]\n",
- " [ True True]\n",
- " [False False]\n",
- " [False False]\n",
- " [ True True]]\n"
- ]
- }
- ],
- "source": [
- "sampler = circuit.compile_sampler()\n",
- "print(sampler.sample(shots=10))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "D5KUSysIJB5g"
- },
- "source": [
- "Notice how there are ten rows (because you took ten shots) with two results per row (because there were two measurements in the circuit).\n",
- "Also notice how the results are random from row to row, but always agree within each row.\n",
- "That makes sense; that's what's supposed to happen when you repeatedly prepare and measure the |00> + |11> state."
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "zX7ZyHVAHfF_"
- },
- "source": [
- "\n",
- "# 4. Add detector annotations to a circuit, and sample them.\n",
- "\n",
- "Stim circuits can include error correction annotations.\n",
- "In particular, you can annotate that certain sets of measurements can be used to detect errors.\n",
- "For example, in the circuit you created above, the two measurement results should always be equal.\n",
- "You can tell Stim you care about that by adding a `DETECTOR` annotation to the circuit.\n",
- "\n",
- "The `DETECTOR` annotation will take two targets: the two measurements whose parity you are asserting should be consistent from run to run. You point at the measurements by using the `stim.target_rec` method (short for \"target measurement record\"). The most recent measurement is `stim.target_rec(-1)` (also known as `rec[-1]` in stim's circuit language), and the second most recent measurement is `stim.target_rec(-2)`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "D-RpRUTw-qOQ"
+ },
+ "source": [
+ "You can also use the `circuit.diagram` method to get an annotated text diagram of the circuit:"
+ ]
},
- "id": "GxViFukZIVI4",
- "outputId": "218d0843-da8c-482a-d736-242b918aabc0"
- },
- "outputs": [
{
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "stim.Circuit('''\n",
- " H 0\n",
- " CX 0 1\n",
- " M 0 1\n",
- " DETECTOR rec[-1] rec[-2]\n",
- "''')\n"
- ]
- }
- ],
- "source": [
- "# Indicate the two previous measurements are supposed to consistently agree.\n",
- "circuit.append(\"DETECTOR\", [stim.target_rec(-1), stim.target_rec(-2)])\n",
- "print(repr(circuit))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "id": "tEz4G3OjI164"
- },
- "source": [
- "A slightly subtle point about detectors is that they only assert that the parity of the measurements is *always the same under noiseless execution*.\n",
- "A detector doesn't say whether the parity should be even or should be odd, only that it should always be the same.\n",
- "You annotate that a pair of measurements is always different in the same way that you annotate that a pair of measurements is always the same; it's the *consistency* that's key.\n",
- "\n",
- "Anyways, now that you've annotated the circuit with a detector, you can sample from the circuit's detectors instead of sampling from its measurements.\n",
- "You do that by creating a detector sampler, using the `compile_detector_sampler` method, and then calling `sample` on it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "outputId": "9b6d4b2f-1cb9-4941-d533-db148aaaf86f",
+ "id": "_75gRftr-qOQ"
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "