Created
March 9, 2023 11:14
-
-
Save quantumjim/99d8714acda92f70662326222a9ecff4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"attachments": {}, | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Creating a `CssCodeCircuit`\n", | |
"\n", | |
"* Let's pretend that there exists an abstract CSS subsystem code class in `qiskit_qec.codes`, of which `HHC` is an example. Let's call it `CssCode`.\n", | |
"* With this, we could build a corresponding `CssCodeCircuit` class, which take an arbitrary `CssCode` and construct the corresponding `CodeCircuit`.\n", | |
"* Using only information from the `CssCode`, we cannot construct a fully-fault-tolerant circuit. This would need a more thoughtful approach, thinking about hook errors, flag qubits, etc.\n", | |
"* What we can do is construct naive circuits that will be fault-tolerant against phenomological noise.\n", | |
"* So let's do that!\n", | |
"* We can then extend `CssCodeCircuit` later, to allow user-defined gauge operator meaurement circuits, deflagging procedures, etc." | |
] | |
}, | |
{ | |
"attachments": {}, | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We begin by creating an example of the only `CssCode` we have." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[[9, 1, 3]] heavy-hexagon compass code\n", | |
"x_gauges = [[0, 3], [1, 4], [2, 5], [3, 6], [4, 7], [5, 8]]\n", | |
"z_gauges = [[0, 1], [1, 2, 4, 5], [3, 4, 6, 7], [7, 8]]\n", | |
"x_stabilizers = [[0, 1, 3, 4], [2, 5], [3, 6], [4, 5, 7, 8]]\n", | |
"z_stabilizers = [[0, 1, 3, 4, 6, 7], [1, 2, 4, 5, 7, 8]]\n", | |
"logical_x = [[0, 1, 2, 3, 4, 5, 6, 7, 8]]\n", | |
"logical_z = [[0, 1, 2, 3, 4, 5, 6, 7, 8]]\n", | |
"x_boundary = [[0], [1], [2], [6], [7], [8]]\n", | |
"z_boundary = [[0], [3], [6], [2], [5], [8]]" | |
] | |
}, | |
"execution_count": 1, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"from qiskit_qec.codes.hhc import HHC\n", | |
"code = HHC(3)\n", | |
"code" | |
] | |
}, | |
{ | |
"attachments": {}, | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Now we can create a corresponding `CodeCircuit` class.\n", | |
"\n", | |
"* This constructs a circuit simply by interating through the gauge operators and applying a naive measurement process.\n", | |
"* `string2nodes` combines gauge operators results into stabilizer results, and makes comparisons between measurement rounds to contruct nodes.\n", | |
"* `check_nodes` and `is_cluster_neutral` cannot be defined using information from the `CssCode` alone, and so must be provided by the user.\n", | |
"* Phenomological noise is defined by two keyword arguments: `p_depol` for between rounds, and `p_meas` for measurements. If given, corresponding error operators are inserted into the circuit." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# -*- coding: utf-8 -*-\n", | |
"\n", | |
"# This code is part of Qiskit.\n", | |
"#\n", | |
"# (C) Copyright IBM 2019.\n", | |
"#\n", | |
"# This code is licensed under the Apache License, Version 2.0. You may\n", | |
"# obtain a copy of this license in the LICENSE.txt file in the root directory\n", | |
"# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.\n", | |
"#\n", | |
"# Any modifications or derivative works of this code must retain this\n", | |
"# copyright notice, and modified files need to carry a notice indicating\n", | |
"# that they have been altered from the originals.\n", | |
"\n", | |
"# pylint: disable=invalid-name\n", | |
"\n", | |
"\"\"\"Generates circuits for CSS \"\"\"\n", | |
"from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n", | |
"from qiskit_aer.noise import depolarizing_error, pauli_error\n", | |
"\n", | |
"from qiskit_qec.circuits.code_circuit import CodeCircuit\n", | |
"\n", | |
"\n", | |
"class CssCodeCircuit():\n", | |
" \"\"\"\n", | |
" CodeCircuit class for generic CSS codes.\n", | |
" \"\"\"\n", | |
"\n", | |
" def __init__(self, code, T, basis=\"z\", round_schedule=\"zx\", p_depol=0, p_meas=0):\n", | |
" \"\"\"\n", | |
" Args:\n", | |
" code: A CSS code\n", | |
" T: Number of syndrome measurement rounds\n", | |
" basis: basis for encoding ('x' or 'z')\n", | |
" round_schedule: Order in which to measureme gauge operators ('zx' or 'xz')\n", | |
" p_depol: Probabity of depolarizing noise on code qubits between rounds\n", | |
" p_meas: Probability of measurement errors\n", | |
" \"\"\"\n", | |
"\n", | |
" self.code = code\n", | |
" self.T = T\n", | |
" self.basis = basis\n", | |
" self.base = \"0\"\n", | |
" self.round_schedule = round_schedule\n", | |
" self.p_depol = p_depol\n", | |
" self.p_meas = p_meas\n", | |
" self._noise = p_depol > 0 or p_meas > 0\n", | |
"\n", | |
" self._depol_error = depolarizing_error(p_depol, 1)\n", | |
" self._meas_error = pauli_error([(\"X\", p_meas), (\"I\", 1 - p_meas)])\n", | |
"\n", | |
" self.circuit = {}\n", | |
" for state in [\"0\", \"1\"]:\n", | |
" qc = QuantumCircuit()\n", | |
" qregs = []\n", | |
" qregs.append(QuantumRegister(code.n, name=\"code qubits\"))\n", | |
" qregs.append(QuantumRegister(len(code.z_gauges), name=\"z auxs\"))\n", | |
" qregs.append(QuantumRegister(len(code.x_gauges), name=\"x auxs\"))\n", | |
" for qreg in qregs:\n", | |
" qc.add_register(qreg)\n", | |
" # prepare initial state\n", | |
" if state == \"1\":\n", | |
" if basis == \"z\":\n", | |
" qc.x(code.logical_x[0])\n", | |
" else:\n", | |
" qc.x(code.logical_z[0])\n", | |
" if basis == \"x\":\n", | |
" qc.h(qregs[0])\n", | |
" # peform syndrome measurements\n", | |
" for t in range(T):\n", | |
" if self._noise:\n", | |
" for q in qregs[0]:\n", | |
" qc.append(self._depol_error, [q])\n", | |
" # gauge measurements\n", | |
" if round_schedule == \"zx\":\n", | |
" self._z_gauge_measurements(qc, t)\n", | |
" self._x_gauge_measurements(qc, t)\n", | |
" elif round_schedule == \"xz\":\n", | |
" self._x_gauge_measurements(qc, t)\n", | |
" self._z_gauge_measurements(qc, t)\n", | |
" else:\n", | |
" print(\"Round schedule \" + round_schedule + \" not supported.\")\n", | |
" # final readout\n", | |
" creg = ClassicalRegister(code.n, name=\"final_readout\")\n", | |
" qc.add_register(creg)\n", | |
" if basis == \"x\":\n", | |
" qc.h(qregs[0])\n", | |
" if self._noise:\n", | |
" for q in qregs[0]:\n", | |
" qc.append(self._meas_error, [q])\n", | |
" qc.measure(qregs[0], creg)\n", | |
" self.circuit[state] = qc\n", | |
"\n", | |
" self._gauges4stabilizers = []\n", | |
" self._stabilizers = [code.x_stabilizers, code.z_stabilizers]\n", | |
" self._gauges = [code.x_gauges, code.z_gauges]\n", | |
" for j in range(2):\n", | |
" self._gauges4stabilizers.append([])\n", | |
" for stabilizer in self._stabilizers[j]:\n", | |
" gauges = []\n", | |
" for g, gauge in enumerate(self._gauges[j]):\n", | |
" if set(stabilizer).intersection(set(gauge)) == set(gauge):\n", | |
" gauges.append(g)\n", | |
" self._gauges4stabilizers[j].append(gauges)\n", | |
"\n", | |
" self.n = code.n\n", | |
" self.d = code.d\n", | |
" self.blocks = T\n", | |
" self.css_x_gauge_ops = code.x_gauges\n", | |
" self.css_x_stabilizer_ops = code.x_stabilizers\n", | |
" self.css_x_logical = code.logical_x\n", | |
" self.css_x_boundary = code.x_boundary\n", | |
" self.css_z_gauge_ops = code.x_gauges\n", | |
" self.css_z_stabilizer_ops = code.z_stabilizers\n", | |
" self.css_z_logical = code.logical_z\n", | |
" self.css_z_boundary = code.z_boundary\n", | |
"\n", | |
" def _z_gauge_measurements(self, qc, t):\n", | |
" creg = ClassicalRegister(len(self.code.z_gauges), name=\"round_\" + str(t) + \"_z_bits\")\n", | |
" qc.add_register(creg)\n", | |
" for g, z_gauge in enumerate(self.code.z_gauges):\n", | |
" for q in z_gauge:\n", | |
" qc.cx(qc.qregs[0][q], qc.qregs[1][g])\n", | |
" if self._noise:\n", | |
" qc.append(self._meas_error, [qc.qregs[1][g]])\n", | |
" qc.measure(qc.qregs[1][g], creg[g])\n", | |
" qc.reset(qc.qregs[1][g])\n", | |
"\n", | |
" def _x_gauge_measurements(self, qc, t):\n", | |
" creg = ClassicalRegister(len(self.code.x_gauges), name=\"round_\" + str(t) + \"_x_bits\")\n", | |
" qc.add_register(creg)\n", | |
" for g, x_gauge in enumerate(self.code.x_gauges):\n", | |
" for q in x_gauge:\n", | |
" qc.h(qc.qregs[0][q])\n", | |
" qc.cx(qc.qregs[0][q], qc.qregs[2][g])\n", | |
" qc.h(qc.qregs[0][q])\n", | |
" if self._noise:\n", | |
" qc.append(self._meas_error, [qc.qregs[2][g]])\n", | |
" qc.measure(qc.qregs[2][g], creg[g])\n", | |
" qc.reset(qc.qregs[2][g])\n", | |
"\n", | |
" def string2nodes(self, string, **kwargs):\n", | |
" \"\"\"\n", | |
" Convert output string from circuits into a set of nodes for\n", | |
" `DecodingGraph`.\n", | |
" Args:\n", | |
" string (string): Results string to convert.\n", | |
" kwargs (dict): Any additional keyword arguments.\n", | |
" \"\"\"\n", | |
" output = string.split(\" \")[::-1]\n", | |
" gauge_outs = [[], []]\n", | |
" for t in range(self.T):\n", | |
" gauge_outs[0].append(\n", | |
" [int(b) for b in output[2 * t + self.round_schedule.find(\"x\")]][::-1]\n", | |
" )\n", | |
" gauge_outs[1].append(\n", | |
" [int(b) for b in output[2 * t + self.round_schedule.find(\"z\")]][::-1]\n", | |
" )\n", | |
" final_outs = [int(b) for b in output[-1]]\n", | |
"\n", | |
" stabilizer_outs = []\n", | |
" for j in range(2):\n", | |
" stabilizer_outs.append([])\n", | |
" for t in range(self.T):\n", | |
" round_outs = []\n", | |
" for gs in self._gauges4stabilizers[j]:\n", | |
" out = 0\n", | |
" for g in gs:\n", | |
" out += gauge_outs[j][t][g]\n", | |
" out = out % 2\n", | |
" round_outs.append(out)\n", | |
" stabilizer_outs[j].append(round_outs)\n", | |
"\n", | |
" bases = [\"x\", \"z\"]\n", | |
" j = bases.index(self.basis)\n", | |
" round_outs = []\n", | |
" for stabilizer in self._stabilizers[j]:\n", | |
" out = 0\n", | |
" for q in stabilizer:\n", | |
" out += final_outs[q]\n", | |
" out = out % 2\n", | |
" round_outs.append(out)\n", | |
" stabilizer_outs[j].append(round_outs)\n", | |
"\n", | |
" stabilizer_changes = []\n", | |
" for j in range(2):\n", | |
" stabilizer_changes.append([])\n", | |
" for t in range(self.T + (bases[j] == self.basis)):\n", | |
" stabilizer_changes[j].append([])\n", | |
" for e in range(len(stabilizer_outs[j][t])):\n", | |
" if t == 0 and j == bases.index(self.basis):\n", | |
" stabilizer_changes[j][t].append(stabilizer_outs[j][t][e])\n", | |
" else:\n", | |
" stabilizer_changes[j][t].append(\n", | |
" (stabilizer_outs[j][t][e] + stabilizer_outs[j][t - 1][e]) % 2\n", | |
" )\n", | |
"\n", | |
" nodes = []\n", | |
" for j in range(2):\n", | |
" for t, round_changes in enumerate(stabilizer_changes[j]):\n", | |
" for e, change in enumerate(round_changes):\n", | |
" if change == 1:\n", | |
" node = {\n", | |
" \"time\": t,\n", | |
" \"basis\": bases[j],\n", | |
" \"qubits\": self._stabilizers[j][e],\n", | |
" \"element\": e,\n", | |
" \"is_boundary\": False,\n", | |
" }\n", | |
" nodes.append(node)\n", | |
"\n", | |
" j = bases.index(self.basis)\n", | |
" boundary = [self.code.x_boundary, self.code.z_boundary]\n", | |
" boundary_qubits = [q[0] for q in boundary[j]]\n", | |
"\n", | |
" boundary_out = 0\n", | |
" for q in boundary_qubits:\n", | |
" boundary_out += final_outs[q]\n", | |
" boundary_out = boundary_out % 2\n", | |
"\n", | |
" if boundary_out == 1:\n", | |
" node = {\n", | |
" \"time\": 0,\n", | |
" \"basis\": self.basis,\n", | |
" \"qubits\": boundary_qubits,\n", | |
" \"element\": 0,\n", | |
" \"is_boundary\": True,\n", | |
" }\n", | |
" nodes.append(node)\n", | |
"\n", | |
" return nodes\n", | |
" \n", | |
" def partition_outcomes(\n", | |
" self, outcome\n", | |
" ):\n", | |
" \"\"\"Extract measurement outcomes.\"\"\"\n", | |
" # split into gauge and final outcomes\n", | |
" outcome = \"\".join([str(c) for c in outcome])\n", | |
" outcome = outcome.split(\" \")\n", | |
" \n", | |
" gs = [[], []]\n", | |
" for t in range(self.T):\n", | |
" for dt in range(2):\n", | |
" gs[dt].append(outcome[2*t + dt])\n", | |
" \n", | |
" gauge_outcomes = []\n", | |
" for g in gs:\n", | |
" gauge_outcomes.append([[int(c) for c in r] for r in g])\n", | |
"\n", | |
" # assign outcomes to the correct gauge ops\n", | |
" x_gauge_outcomes = gauge_outcomes[0]\n", | |
" z_gauge_outcomes = gauge_outcomes[1]\n", | |
" final_outcomes = [int(c) for c in outcome[-1]]\n", | |
"\n", | |
" return x_gauge_outcomes, z_gauge_outcomes, final_outcomes\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"T = 2\n", | |
"p = 0\n", | |
"hhc = CssCodeCircuit(code,T,basis='z',p_depol=p,p_meas=p)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from qiskit_qec.decoders import DecodingGraph\n", | |
"\n", | |
"dg = DecodingGraph(hhc)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"\"\"\"Matching Decoder for CSS Codes.\"\"\"\n", | |
"from typing import Tuple, List\n", | |
"\n", | |
"from qiskit_qec.decoders.circuit_matching_decoder import CircuitModelMatchingDecoder\n", | |
"from qiskit_qec.noise.paulinoisemodel import PauliNoiseModel\n", | |
"from qiskit_qec.decoders.decoding_graph import DecodingGraph\n", | |
"\n", | |
"\n", | |
"class CssDecoder(CircuitModelMatchingDecoder):\n", | |
" \"\"\"Instance of CircuitModelMatchingDecoder for use with\n", | |
" circuits from CssCodeCircuit.\n", | |
"\n", | |
" Args:\n", | |
" code_circuit: The QEC code circuit object for which this decoder\n", | |
" will be used.\n", | |
" model: Noise model used to generate syndrome graph.\n", | |
" uniform: Whether to use uniform weights for the syndrome graph.\n", | |
" logical: Logical value for the circuit to be used.\n", | |
" \"\"\"\n", | |
"\n", | |
" def __init__(\n", | |
" self,\n", | |
" code_circuit,\n", | |
" model: PauliNoiseModel,\n", | |
" method: str,\n", | |
" uniform: bool,\n", | |
" logical: str,\n", | |
" decoding_graph = None\n", | |
" ):\n", | |
" \"\"\"Constructor.\"\"\"\n", | |
" self.code_circuit = code_circuit\n", | |
" if decoding_graph:\n", | |
" dg = DecodingGraph(code_circuit)\n", | |
" else:\n", | |
" dg = decoding_graph\n", | |
" super().__init__(\n", | |
" code_circuit.n,\n", | |
" code_circuit.css_x_gauge_ops,\n", | |
" code_circuit.css_x_stabilizer_ops,\n", | |
" code_circuit.css_x_boundary,\n", | |
" code_circuit.css_z_gauge_ops,\n", | |
" code_circuit.css_z_stabilizer_ops,\n", | |
" code_circuit.css_z_boundary,\n", | |
" code_circuit.circuit[logical],\n", | |
" model,\n", | |
" code_circuit.basis,\n", | |
" code_circuit.round_schedule,\n", | |
" code_circuit.blocks,\n", | |
" method,\n", | |
" uniform,\n", | |
" dg,\n", | |
" )\n", | |
"\n", | |
" def _partition_outcomes(\n", | |
" self, blocks: int, round_schedule: str, outcome: List[int]\n", | |
" ) -> Tuple[List[List[int]], List[List[int]], List[int]]:\n", | |
" \"\"\"Extract measurement outcomes.\"\"\"\n", | |
" return self.code_circuit.partition_outcomes(outcome)\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from qiskit_qec.noise.paulinoisemodel import PauliNoiseModel\n", | |
"\n", | |
"pnm = PauliNoiseModel()\n", | |
"pnm.add_operation(\"id\", {\"x\": 1})\n", | |
"pnm.add_operation(\"measure\", {\"x\": 1})\n", | |
"pnm.add_operation(\"h\", {\"x\": 1, \"y\": 1, \"z\": 1})\n", | |
"pnm.set_error_probability(\"id\", p)\n", | |
"pnm.set_error_probability(\"h\", p)\n", | |
"pnm.set_error_probability(\"measure\", p)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"ename": "QiskitQECError", | |
"evalue": "'too many highlighted vertices for a single fault event'", | |
"output_type": "error", | |
"traceback": [ | |
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", | |
"\u001b[0;31mQiskitQECError\u001b[0m Traceback (most recent call last)", | |
"\u001b[1;32m/Users/jwo/Repos/->notebooks/css_code_circuit.ipynb Cell 10\u001b[0m in \u001b[0;36m<cell line: 1>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=0'>1</a>\u001b[0m decoder \u001b[39m=\u001b[39m CssDecoder(hhc, pnm, \u001b[39m\"\u001b[39;49m\u001b[39mpymatching\u001b[39;49m\u001b[39m\"\u001b[39;49m, \u001b[39mFalse\u001b[39;49;00m, \u001b[39m\"\u001b[39;49m\u001b[39m0\u001b[39;49m\u001b[39m\"\u001b[39;49m, decoding_graph \u001b[39m=\u001b[39;49m dg)\n", | |
"\u001b[1;32m/Users/jwo/Repos/->notebooks/css_code_circuit.ipynb Cell 10\u001b[0m in \u001b[0;36mCssDecoder.__init__\u001b[0;34m(self, code_circuit, model, method, uniform, logical, decoding_graph)\u001b[0m\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=33'>34</a>\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=34'>35</a>\u001b[0m dg \u001b[39m=\u001b[39m decoding_graph\n\u001b[0;32m---> <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=35'>36</a>\u001b[0m \u001b[39msuper\u001b[39;49m()\u001b[39m.\u001b[39;49m\u001b[39m__init__\u001b[39;49m(\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=36'>37</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mn,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=37'>38</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mcss_x_gauge_ops,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=38'>39</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mcss_x_stabilizer_ops,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=39'>40</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mcss_x_boundary,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=40'>41</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mcss_z_gauge_ops,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=41'>42</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mcss_z_stabilizer_ops,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=42'>43</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mcss_z_boundary,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=43'>44</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mcircuit[logical],\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=44'>45</a>\u001b[0m model,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=45'>46</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mbasis,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=46'>47</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mround_schedule,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=47'>48</a>\u001b[0m code_circuit\u001b[39m.\u001b[39;49mblocks,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=48'>49</a>\u001b[0m method,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=49'>50</a>\u001b[0m uniform,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=50'>51</a>\u001b[0m dg,\n\u001b[1;32m <a href='vscode-notebook-cell:/Users/jwo/Repos/-%3Enotebooks/css_code_circuit.ipynb#Y101sZmlsZQ%3D%3D?line=51'>52</a>\u001b[0m )\n", | |
"File \u001b[0;32m~/opt/anaconda3/envs/qiskit_qec_env/lib/python3.10/site-packages/qiskit_qec/decoders/circuit_matching_decoder.py:140\u001b[0m, in \u001b[0;36mCircuitModelMatchingDecoder.__init__\u001b[0;34m(self, n, css_x_gauge_ops, css_x_stabilizer_ops, css_x_boundary, css_z_gauge_ops, css_z_stabilizer_ops, css_z_boundary, circuit, model, basis, round_schedule, blocks, method, uniform, decoding_graph, annotate)\u001b[0m\n\u001b[1;32m 138\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39muniform:\n\u001b[1;32m 139\u001b[0m fe \u001b[39m=\u001b[39m FaultEnumerator(circuit, order\u001b[39m=\u001b[39m\u001b[39m1\u001b[39m, method\u001b[39m=\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mpropagator\u001b[39m\u001b[39m\"\u001b[39m, model\u001b[39m=\u001b[39m\u001b[39mself\u001b[39m\u001b[39m.\u001b[39mmodel)\n\u001b[0;32m--> 140\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mevent_map \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_enumerate_events(\n\u001b[1;32m 141\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mcss_x_gauge_ops,\n\u001b[1;32m 142\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mcss_x_stabilizer_ops,\n\u001b[1;32m 143\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mcss_x_boundary,\n\u001b[1;32m 144\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mx_gauge_products,\n\u001b[1;32m 145\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mcss_z_gauge_ops,\n\u001b[1;32m 146\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mcss_z_stabilizer_ops,\n\u001b[1;32m 147\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mcss_z_boundary,\n\u001b[1;32m 148\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mz_gauge_products,\n\u001b[1;32m 149\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mblocks,\n\u001b[1;32m 150\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mround_schedule,\n\u001b[1;32m 151\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mbasis,\n\u001b[1;32m 152\u001b[0m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mlayer_types,\n\u001b[1;32m 153\u001b[0m fe,\n\u001b[1;32m 154\u001b[0m )\n\u001b[1;32m 155\u001b[0m logging\u001b[39m.\u001b[39mdebug(\u001b[39m\"\u001b[39m\u001b[39mevent_map = \u001b[39m\u001b[39m%s\u001b[39;00m\u001b[39m\"\u001b[39m, \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mevent_map)\n\u001b[1;32m 156\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39msymbols, \u001b[39mself\u001b[39m\u001b[39m.\u001b[39medge_weight_polynomials \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_edge_weight_polynomials(\n\u001b[1;32m 157\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mmodel, \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mevent_map\n\u001b[1;32m 158\u001b[0m )\n", | |
"File \u001b[0;32m~/opt/anaconda3/envs/qiskit_qec_env/lib/python3.10/site-packages/qiskit_qec/decoders/circuit_matching_decoder.py:449\u001b[0m, in \u001b[0;36mCircuitModelMatchingDecoder._enumerate_events\u001b[0;34m(self, css_x_gauge_ops, css_x_stabilizer_ops, css_x_boundary, x_gauge_products, css_z_gauge_ops, css_z_stabilizer_ops, css_z_boundary, z_gauge_products, blocks, round_schedule, basis, layer_types, fault_enumerator)\u001b[0m\n\u001b[1;32m 446\u001b[0m \u001b[39m# Examine the highlighted vertices to find the edge of the\u001b[39;00m\n\u001b[1;32m 447\u001b[0m \u001b[39m# decoding graph that corresponds with this fault event\u001b[39;00m\n\u001b[1;32m 448\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mlen\u001b[39m(highlighted) \u001b[39m>\u001b[39m \u001b[39m2\u001b[39m:\n\u001b[0;32m--> 449\u001b[0m \u001b[39mraise\u001b[39;00m QiskitQECError(\u001b[39m\"\u001b[39m\u001b[39mtoo many highlighted vertices for a \u001b[39m\u001b[39m\"\u001b[39m \u001b[39m+\u001b[39m \u001b[39m\"\u001b[39m\u001b[39msingle fault event\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[1;32m 450\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mlen\u001b[39m(highlighted) \u001b[39m==\u001b[39m \u001b[39m1\u001b[39m: \u001b[39m# _highlighted_vertices highlights the boundary\u001b[39;00m\n\u001b[1;32m 451\u001b[0m \u001b[39mraise\u001b[39;00m QiskitQECError(\u001b[39m\"\u001b[39m\u001b[39monly one highlighted vertex for a \u001b[39m\u001b[39m\"\u001b[39m \u001b[39m+\u001b[39m \u001b[39m\"\u001b[39m\u001b[39msingle fault event\u001b[39m\u001b[39m\"\u001b[39m)\n", | |
"\u001b[0;31mQiskitQECError\u001b[0m: 'too many highlighted vertices for a single fault event'" | |
] | |
} | |
], | |
"source": [ | |
"decoder = CssDecoder(hhc, pnm, \"pymatching\", False, \"0\", decoding_graph = dg)" | |
] | |
}, | |
{ | |
"attachments": {}, | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Currently we need `Aer` to run it, but we should find a way to get Stim to do it." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from qiskit_aer import AerSimulator\n", | |
"\n", | |
"counts = AerSimulator().run(hhc.circuit['0']).result().get_counts()" | |
] | |
}, | |
{ | |
"attachments": {}, | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Turn qiskit strings into fault enumerator outcomes." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def gint(c):\n", | |
" \"\"\"Casts to int if possible\"\"\"\n", | |
" if c.isnumeric():\n", | |
" return int(c)\n", | |
" else:\n", | |
" return c\n", | |
"\n", | |
"def string2outcome(outcome):\n", | |
" return list(map(gint, outcome[::-1]))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"[0, 0, 0, 0, ' ', 1, 1, 1, 1, 1, 0, ' ', 0, 1, 0, 1, ' ', 0, 0, 1, 1, 1, 0, ' ', 0, 0, 0, 1, 1, 1, 1, 1, 1]\n" | |
] | |
} | |
], | |
"source": [ | |
"outcome = string2outcome('111111000 011100 1010 011111 0000')\n", | |
"print(outcome)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"([[1, 1, 1, 1, 1, 0], [0, 0, 1, 1, 1, 0]],\n", | |
" [[0, 0, 0, 0], [0, 1, 0, 1]],\n", | |
" [0, 0, 0, 1, 1, 1, 1, 1, 1])" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"hhc.partition_outcomes(outcome)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "qiskit_qec_env", | |
"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.10.4" | |
}, | |
"orig_nbformat": 4, | |
"vscode": { | |
"interpreter": { | |
"hash": "d0c97c6e336ba8a43726fa4b7f85b3d6fc40e6f311d3e8fe15ffb6db6aa1925b" | |
} | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment