Skip to content

Commit

Permalink
Example of stabilizer code (#3935)
Browse files Browse the repository at this point in the history
* Example of stabilizer code

* nits

* Ignore some coverage

* Address comments

* Address some comments

* Address comments

* Add annotations + tutorial entry

* Add lint

* address comments

* nits

* spelling

* Add some comments + a Jupyter notebook

* revert changes to wrong notebook

* Adding exception for testing of notebooks

* Address comments

* Address comments

* Address comments.

* Remove forgotten breakpoint(). Sorry.

* Address comments.

* trigger GitHub actions

Co-authored-by: Cirq Bot <craiggidney+github+cirqbot@google.com>
  • Loading branch information
tonybruguier and CirqBot committed May 4, 2021
1 parent 2ce47ae commit 30c337f
Show file tree
Hide file tree
Showing 5 changed files with 755 additions and 0 deletions.
2 changes: 2 additions & 0 deletions dev_tools/notebooks/isolated_notebook_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
# skipping fidelity estimation due to
# https://github.com/quantumlib/Cirq/issues/3502
"examples/*fidelity*",
# Also skipping stabilizer code testing.
"examples/*stabilizer_code*",
] + NOTEBOOKS_DEPENDING_ON_UNRELEASED_FEATURES

# As these notebooks run in an isolated env, we want to minimize dependencies that are
Expand Down
5 changes: 5 additions & 0 deletions docs/tutorials/_index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,8 @@ landing_page:
path: https://github.com/quantumlib/Cirq/blob/master/examples/hhl.py
icon:
name: code
- heading: Stabilizer code
description: An illustration of quantum error correction using stabilizer code, following the PhD thesis of Daniel Gottesman.
path: https://github.com/quantumlib/Cirq/blob/master/examples/stabilizer_code.py
icon:
name: code
284 changes: 284 additions & 0 deletions examples/stabilizer_code.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Stabilizer code tutorial\n",
"This examples goes over quantum error correction using stabilizer code.\n",
"\n",
"Useful references include:\n",
"* Stabilizer Codes and Quantum Error Correction by Daniel Gottesman (https://thesis.library.caltech.edu/2900/2/THESIS.pdf) and its errata (https://www2.perimeterinstitute.ca/personal/dgottesman/thesis-errata.html)\n",
"* Stabilizer code report (https://cs269q.stanford.edu/projects2019/stabilizer_code_report_Y.pdf)\n",
"* Quantum Computing, a Gentle Introduction by Eleanor G. Rieffel and Wolfgang H. Polak. In particular chapter 11."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"try:\n",
" import cirq\n",
"except ImportError:\n",
" print(\"installing cirq...\")\n",
" !pip install --quiet cirq\n",
" print(\"installed cirq.\")\n",
" \n",
"from cirq.contrib.svg import SVGCircuit\n",
"import examples.stabilizer_code as sc"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, let's look at a simple repetition code. We simply encode a single qubit by repeating it three times. The construction is beyond the scope of this tutorial and a good introduction can be found in chapter 11 of the book above.\n",
"\n",
"As described in section 11.1.1, the code can only correct bit flip errors (i.e. Pauli X) but cannot correct phase errors (i.e. Pauli Z). Let's build the code and look at the circuit that is generated."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"findfont: Font family ['Arial'] not found. Falling back to DejaVu Sans.\n"
]
},
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"220.0\" height=\"150.0\"><line x1=\"30.0\" x2=\"190.0\" y1=\"25.0\" y2=\"25.0\" stroke=\"#1967d2\" stroke-width=\"1\" /><line x1=\"30.0\" x2=\"190.0\" y1=\"75.0\" y2=\"75.0\" stroke=\"#1967d2\" stroke-width=\"1\" /><line x1=\"30.0\" x2=\"190.0\" y1=\"125.0\" y2=\"125.0\" stroke=\"#1967d2\" stroke-width=\"1\" /><line x1=\"90.0\" x2=\"90.0\" y1=\"25.0\" y2=\"125.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"150.0\" x2=\"150.0\" y1=\"75.0\" y2=\"125.0\" stroke=\"black\" stroke-width=\"3\" /><rect x=\"10.0\" y=\"5.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"0\" /><text x=\"30.0\" y=\"25.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"14px\" font-family=\"Arial\">0: </text><rect x=\"10.0\" y=\"55.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"0\" /><text x=\"30.0\" y=\"75.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"14px\" font-family=\"Arial\">1: </text><rect x=\"10.0\" y=\"105.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"0\" /><text x=\"30.0\" y=\"125.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"14px\" font-family=\"Arial\">c: </text><circle cx=\"90.0\" cy=\"125.0\" r=\"10.0\" /><rect x=\"70.0\" y=\"5.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"90.0\" y=\"25.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"150.0\" cy=\"125.0\" r=\"10.0\" /><rect x=\"130.0\" y=\"55.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"150.0\" y=\"75.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text></svg>"
],
"text/plain": [
"<cirq.contrib.svg.svg.SVGCircuit at 0x7f4a837f1df0>"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"code = sc.StabilizerCode(group_generators=['ZZI', 'ZIZ'], correctable_errors=['X'])\n",
"\n",
"additional_qubits = [cirq.NamedQubit(str(i)) for i in range(code.n - code.k)]\n",
"unencoded_qubits = [cirq.NamedQubit('c')]\n",
"qubits = additional_qubits + unencoded_qubits\n",
"\n",
"circuit = code.encode(additional_qubits, unencoded_qubits)\n",
"\n",
"SVGCircuit(circuit)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We see a circuit that encodes a single qubit into three qubits with the same values. These are the code words. Let's double check that we are indeed getting a repetion code. "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 becomes |000⟩\n",
"1 becomes |111⟩\n"
]
}
],
"source": [
"for initial_state in [0, 1]:\n",
" results = cirq.Simulator().simulate(circuit, qubit_order=qubits, initial_state=initial_state)\n",
" print('%d becomes %s' % (initial_state, cirq.dirac_notation(results.state_vector())))\n",
" \n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can also see that both code words commute with the generators 'ZZI' and 'ZIZ'. In other words, this is the definition of a stabilizer.\n",
"\n",
"Now, we will perturb the circuit by flipping only one qubit (let's say the middle one). We will then add a circuit that computes the syndrome and performs the correction. To do this, we need to have ancillas. We then look at the output of the circuit."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"860.0\" height=\"290.0\"><line x1=\"30.0\" x2=\"830.0\" y1=\"45.0\" y2=\"45.0\" stroke=\"#1967d2\" stroke-width=\"1\" /><line x1=\"30.0\" x2=\"830.0\" y1=\"95.0\" y2=\"95.0\" stroke=\"#1967d2\" stroke-width=\"1\" /><line x1=\"30.0\" x2=\"830.0\" y1=\"145.0\" y2=\"145.0\" stroke=\"#1967d2\" stroke-width=\"1\" /><line x1=\"30.0\" x2=\"830.0\" y1=\"195.0\" y2=\"195.0\" stroke=\"#1967d2\" stroke-width=\"1\" /><line x1=\"30.0\" x2=\"830.0\" y1=\"245.0\" y2=\"245.0\" stroke=\"#1967d2\" stroke-width=\"1\" /><line x1=\"240.0\" x2=\"330.0\" y1=\"5.0\" y2=\"5.0\" stroke=\"black\" stroke-width=\"1\" /><line x1=\"240.0\" x2=\"330.0\" y1=\"285.0\" y2=\"285.0\" stroke=\"black\" stroke-width=\"1\" /><line x1=\"90.0\" x2=\"90.0\" y1=\"45.0\" y2=\"145.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"150.0\" x2=\"150.0\" y1=\"95.0\" y2=\"145.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"260.0\" x2=\"260.0\" y1=\"45.0\" y2=\"195.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"300.0\" x2=\"300.0\" y1=\"95.0\" y2=\"245.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"370.0\" x2=\"370.0\" y1=\"145.0\" y2=\"195.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"430.0\" x2=\"430.0\" y1=\"145.0\" y2=\"245.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"550.0\" x2=\"550.0\" y1=\"45.0\" y2=\"245.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"670.0\" x2=\"670.0\" y1=\"95.0\" y2=\"245.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"790.0\" x2=\"790.0\" y1=\"145.0\" y2=\"245.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"240.0\" x2=\"240.0\" y1=\"5.0\" y2=\"15.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"330.0\" x2=\"330.0\" y1=\"5.0\" y2=\"15.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"240.0\" x2=\"240.0\" y1=\"275.0\" y2=\"285.0\" stroke=\"black\" stroke-width=\"3\" /><line x1=\"330.0\" x2=\"330.0\" y1=\"275.0\" y2=\"285.0\" stroke=\"black\" stroke-width=\"3\" /><rect x=\"10.0\" y=\"25.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"0\" /><text x=\"30.0\" y=\"45.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"14px\" font-family=\"Arial\">0: </text><rect x=\"10.0\" y=\"75.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"0\" /><text x=\"30.0\" y=\"95.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"14px\" font-family=\"Arial\">1: </text><rect x=\"10.0\" y=\"125.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"0\" /><text x=\"30.0\" y=\"145.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"14px\" font-family=\"Arial\">c: </text><rect x=\"10.0\" y=\"175.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"0\" /><text x=\"30.0\" y=\"195.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"14px\" font-family=\"Arial\">d0: </text><rect x=\"10.0\" y=\"225.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"0\" /><text x=\"30.0\" y=\"245.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"14px\" font-family=\"Arial\">d1: </text><circle cx=\"90.0\" cy=\"145.0\" r=\"10.0\" /><rect x=\"70.0\" y=\"25.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"90.0\" y=\"45.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"150.0\" cy=\"145.0\" r=\"10.0\" /><rect x=\"130.0\" y=\"75.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"150.0\" y=\"95.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><rect x=\"190.0\" y=\"75.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"210.0\" y=\"95.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"260.0\" cy=\"45.0\" r=\"10.0\" /><rect x=\"240.0\" y=\"175.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"260.0\" y=\"195.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"300.0\" cy=\"95.0\" r=\"10.0\" /><rect x=\"280.0\" y=\"225.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"300.0\" y=\"245.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"370.0\" cy=\"145.0\" r=\"10.0\" /><rect x=\"350.0\" y=\"175.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"370.0\" y=\"195.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"430.0\" cy=\"145.0\" r=\"10.0\" /><rect x=\"410.0\" y=\"225.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"430.0\" y=\"245.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><rect x=\"470.0\" y=\"225.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"490.0\" y=\"245.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"550.0\" cy=\"195.0\" r=\"10.0\" /><circle cx=\"550.0\" cy=\"245.0\" r=\"10.0\" /><rect x=\"530.0\" y=\"25.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"550.0\" y=\"45.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><rect x=\"590.0\" y=\"225.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"610.0\" y=\"245.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><rect x=\"590.0\" y=\"175.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"610.0\" y=\"195.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"670.0\" cy=\"195.0\" r=\"10.0\" /><circle cx=\"670.0\" cy=\"245.0\" r=\"10.0\" /><rect x=\"650.0\" y=\"75.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"670.0\" y=\"95.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><rect x=\"710.0\" y=\"175.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"730.0\" y=\"195.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text><circle cx=\"790.0\" cy=\"195.0\" r=\"10.0\" /><circle cx=\"790.0\" cy=\"245.0\" r=\"10.0\" /><rect x=\"770.0\" y=\"125.0\" width=\"40\" height=\"40\" stroke=\"black\" fill=\"white\" stroke-width=\"1\" /><text x=\"790.0\" y=\"145.0\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-size=\"18px\" font-family=\"Arial\">X</text></svg>"
],
"text/plain": [
"<cirq.contrib.svg.svg.SVGCircuit at 0x7f4a576b9460>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Append an error:\n",
"circuit.append(cirq.X(qubits[1]))\n",
"\n",
"# Correct the error:\n",
"ancillas = [cirq.NamedQubit(f\"d{i}\") for i in range(code.n - code.k)]\n",
"circuit += code.correct(qubits, ancillas)\n",
"\n",
"SVGCircuit(circuit)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"|00001⟩\n"
]
}
],
"source": [
"results = cirq.Simulator().simulate(circuit, qubit_order=(qubits+ancillas), initial_state=0)\n",
"print('%s' % (cirq.dirac_notation(results.state_vector())))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can see now 5 qubits. The first 3 qubits are the code word and the last 2 qubits are the syndrome. You can see that we have recovered the code words |000> and the syndrome is |01> resulting in a total state being |00001>. You can verify that the code works as expected. For example:\n",
"* If there is no error, the syndrome should be |00>\n",
"* Regardless of the input value, the syndrome should be the same for a given error\n",
"* You can have a linear combination of error on the same qubit, as described in section 11.2.9\n",
"\n",
"We can also check that the syndrome is as predicted by the code given the errors."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{(-1, 1): ('X', 0), (1, -1): ('X', 1), (-1, -1): ('X', 2)}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"code.syndromes_to_corrections"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we can decode the output by using a Pauli string measurement."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"decoded=[0]\n"
]
}
],
"source": [
"decoded = code.decode(qubits, ancillas, results.state_vector())\n",
"print('decoded=%s' % (decoded))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, let's look at a more complicated code, the five-qubit code. We can verify that we get the same code words as equations 3.17 and 3.18 in the thesis. The reader can repeat the steps above to check that the syndrome is computed correctly and that the errors can be corrected. The unit tests do check these properties."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0 becomes:\n",
" |00000⟩ - 1|00011⟩ + |00101⟩ - 1|00110⟩ + |01001⟩ + |01010⟩ - 1|01100⟩ - 1|01111⟩ - 1|10001⟩ + |10010⟩ + |10100⟩ - 1|10111⟩ - 1|11000⟩ - 1|11011⟩ - 1|11101⟩ - 1|11110⟩\n",
"\n",
"1 becomes:\n",
" |00001⟩ + |00010⟩ + |00100⟩ + |00111⟩ + |01000⟩ - 1|01011⟩ - 1|01101⟩ + |01110⟩ + |10000⟩ + |10011⟩ - 1|10101⟩ - 1|10110⟩ + |11001⟩ - 1|11010⟩ + |11100⟩ - 1|11111⟩\n",
"\n"
]
}
],
"source": [
"code = sc.StabilizerCode(group_generators=['XZZXI', 'IXZZX', 'XIXZZ', 'ZXIXZ'], correctable_errors=['X', 'Z'])\n",
"\n",
"additional_qubits = [cirq.NamedQubit(str(i)) for i in range(code.n - code.k)]\n",
"unencoded_qubits = [cirq.NamedQubit('c')]\n",
"qubits = additional_qubits + unencoded_qubits\n",
"\n",
"circuit = code.encode(additional_qubits, unencoded_qubits)\n",
"\n",
"for initial_state in [0, 1]:\n",
" results = cirq.Simulator().simulate(circuit, qubit_order=qubits, initial_state=initial_state)\n",
" print('%d becomes:\\n %s\\n' % (initial_state, cirq.dirac_notation(4.0 * results.state_vector())))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

0 comments on commit 30c337f

Please sign in to comment.