Skip to content

Instantly share code, notes, and snippets.

@quantumjim
Created March 9, 2023 11:14
Show Gist options
  • Save quantumjim/99d8714acda92f70662326222a9ecff4 to your computer and use it in GitHub Desktop.
Save quantumjim/99d8714acda92f70662326222a9ecff4 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"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