microsoft/qdk
Publicmirrored from https://github.com/microsoft/qdkAvailable
samples/qre/3_building_your_own_models.ipynb
1135lines · modecode
| 1 | { |
| 2 | "cells": [ |
| 3 | { |
| 4 | "cell_type": "markdown", |
| 5 | "id": "226dfb5f", |
| 6 | "metadata": {}, |
| 7 | "source": [ |
| 8 | "# Exploring Hypothetical Hardware\n", |
| 9 | "\n", |
| 10 | "The [previous notebooks](0_getting_started.ipynb) showed how to use the quantum\n", |
| 11 | "resource estimator with built-in models like `GateBased`, `SurfaceCode`, and\n", |
| 12 | "`Litinski19Factory`. These models capture well-studied hardware assumptions,\n", |
| 13 | "but what if your hardware doesn't match them?\n", |
| 14 | "\n", |
| 15 | "In this notebook we build **custom models** to answer three \"what if\" questions:\n", |
| 16 | "\n", |
| 17 | "- **Architecture model:** What if my qubits had different gate speeds and error rates?\n", |
| 18 | "- **QEC ISA transform:** What if I had a QEC code with a higher threshold or lower overhead?\n", |
| 19 | "- **Factory transform:** What if my magic state distillation protocol were different?\n", |
| 20 | "\n", |
| 21 | "Each model plugs into the estimator's layered architecture. You implement a\n", |
| 22 | "small Python class and the estimator takes care of the rest: enumerating\n", |
| 23 | "configurations, pruning infeasible ones, and finding the Pareto-optimal results.\n", |
| 24 | "\n", |
| 25 | "We finish by composing all three custom layers into a full estimation stack and\n", |
| 26 | "comparing it against the built-in models." |
| 27 | ] |
| 28 | }, |
| 29 | { |
| 30 | "cell_type": "code", |
| 31 | "execution_count": 1, |
| 32 | "id": "5dafb171", |
| 33 | "metadata": {}, |
| 34 | "outputs": [ |
| 35 | { |
| 36 | "data": { |
| 37 | "application/javascript": "// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n// This file provides CodeMirror syntax highlighting for Q# magic cells\n// in classic Jupyter Notebooks. It does nothing in other (Jupyter Notebook 7,\n// VS Code, Azure Notebooks, etc.) environments.\n\n// Detect the prerequisites and do nothing if they don't exist.\nif (window.require && window.CodeMirror && window.Jupyter) {\n // The simple mode plugin for CodeMirror is not loaded by default, so require it.\n window.require([\"codemirror/addon/mode/simple\"], function defineMode() {\n let rules = [\n {\n token: \"comment\",\n regex: /(\\/\\/).*/,\n beginWord: false,\n },\n {\n token: \"string\",\n regex: String.raw`^\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S])*(?:\\\"|$)`,\n beginWord: false,\n },\n {\n token: \"keyword\",\n regex: String.raw`(namespace|open|as|operation|function|body|adjoint|newtype|controlled|internal)\\b`,\n beginWord: true,\n },\n {\n token: \"keyword\",\n regex: String.raw`(if|elif|else|repeat|until|fixup|for|in|return|fail|within|apply)\\b`,\n beginWord: true,\n },\n {\n token: \"keyword\",\n regex: String.raw`(Adjoint|Controlled|Adj|Ctl|is|self|auto|distribute|invert|intrinsic)\\b`,\n beginWord: true,\n },\n {\n token: \"keyword\",\n regex: String.raw`(let|set|use|borrow|mutable)\\b`,\n beginWord: true,\n },\n {\n token: \"operatorKeyword\",\n regex: String.raw`(not|and|or)\\b|(w/)`,\n beginWord: true,\n },\n {\n token: \"operatorKeyword\",\n regex: String.raw`(=)|(!)|(<)|(>)|(\\+)|(-)|(\\*)|(/)|(\\^)|(%)|(\\|)|(&&&)|(~~~)|(\\.\\.\\.)|(\\.\\.)|(\\?)`,\n beginWord: false,\n },\n {\n token: \"meta\",\n regex: String.raw`(Int|BigInt|Double|Bool|Qubit|Pauli|Result|Range|String|Unit)\\b`,\n beginWord: true,\n },\n {\n token: \"atom\",\n regex: String.raw`(true|false|Pauli(I|X|Y|Z)|One|Zero)\\b`,\n beginWord: true,\n },\n ];\n let simpleRules = [];\n for (let rule of rules) {\n simpleRules.push({\n token: rule.token,\n regex: new RegExp(rule.regex, \"g\"),\n sol: rule.beginWord,\n });\n if (rule.beginWord) {\n // Need an additional rule due to the fact that CodeMirror simple mode doesn't work with ^ token\n simpleRules.push({\n token: rule.token,\n regex: new RegExp(String.raw`\\W` + rule.regex, \"g\"),\n sol: false,\n });\n }\n }\n\n // Register the mode defined above with CodeMirror\n window.CodeMirror.defineSimpleMode(\"qsharp\", { start: simpleRules });\n window.CodeMirror.defineMIME(\"text/x-qsharp\", \"qsharp\");\n\n // Tell Jupyter to associate %%qsharp magic cells with the qsharp mode\n window.Jupyter.CodeCell.options_default.highlight_modes[\"qsharp\"] = {\n reg: [/^%%qsharp/],\n };\n\n // Force re-highlighting of all cells the first time this code runs\n for (const cell of window.Jupyter.notebook.get_cells()) {\n cell.auto_highlight();\n }\n });\n}\n", |
| 38 | "text/plain": [] |
| 39 | }, |
| 40 | "metadata": {}, |
| 41 | "output_type": "display_data" |
| 42 | } |
| 43 | ], |
| 44 | "source": [ |
| 45 | "from dataclasses import KW_ONLY, dataclass, field\n", |
| 46 | "from math import ceil\n", |
| 47 | "from typing import Generator\n", |
| 48 | "\n", |
| 49 | "import qdk\n", |
| 50 | "from qdk.qre import (\n", |
| 51 | " Architecture,\n", |
| 52 | " ISAContext,\n", |
| 53 | " ConstraintBound,\n", |
| 54 | " ISA,\n", |
| 55 | " ISARequirements,\n", |
| 56 | " ISATransform,\n", |
| 57 | " LOGICAL,\n", |
| 58 | " PHYSICAL,\n", |
| 59 | " constraint,\n", |
| 60 | " estimate,\n", |
| 61 | " linear_function,\n", |
| 62 | " plot_estimates,\n", |
| 63 | ")\n", |
| 64 | "from qdk.qre.models import GateBased, SurfaceCode, Litinski19Factory\n", |
| 65 | "from qdk.qre.application import QSharpApplication\n", |
| 66 | "from qdk.qre.instruction_ids import (\n", |
| 67 | " H, S, S_DAG, T, T_DAG, CNOT, CZ, MEAS_X, MEAS_Y, MEAS_Z, LATTICE_SURGERY,\n", |
| 68 | ")" |
| 69 | ] |
| 70 | }, |
| 71 | { |
| 72 | "cell_type": "markdown", |
| 73 | "id": "4ed9261a", |
| 74 | "metadata": {}, |
| 75 | "source": [ |
| 76 | "## Setup and baseline\n", |
| 77 | "\n", |
| 78 | "We start with a simple Q# program and a baseline estimation using the built-in\n", |
| 79 | "models. This gives us a reference point to compare against later." |
| 80 | ] |
| 81 | }, |
| 82 | { |
| 83 | "cell_type": "code", |
| 84 | "execution_count": 2, |
| 85 | "id": "ccd60531", |
| 86 | "metadata": { |
| 87 | "vscode": { |
| 88 | "languageId": "qsharp" |
| 89 | } |
| 90 | }, |
| 91 | "outputs": [], |
| 92 | "source": [ |
| 93 | "%%qsharp\n", |
| 94 | "\n", |
| 95 | "import Std.Arithmetic.*;\n", |
| 96 | "import Std.Math.*;\n", |
| 97 | "import Std.Convert.*;\n", |
| 98 | "\n", |
| 99 | "/// An 8-bit adder with single-qubit rotations.\n", |
| 100 | "/// The rotations introduce T gates via synthesis, which exercises\n", |
| 101 | "/// the magic state factory during resource estimation.\n", |
| 102 | "operation AdderWithRotations() : Unit {\n", |
| 103 | " use a = Qubit[8];\n", |
| 104 | " use b = Qubit[8];\n", |
| 105 | " for i in 0..7 {\n", |
| 106 | " Ry(PI() / IntAsDouble(i + 2), a[i]);\n", |
| 107 | " }\n", |
| 108 | " RippleCarryCGIncByLE(a, b);\n", |
| 109 | "}" |
| 110 | ] |
| 111 | }, |
| 112 | { |
| 113 | "cell_type": "code", |
| 114 | "execution_count": 3, |
| 115 | "id": "41bfdcd6", |
| 116 | "metadata": {}, |
| 117 | "outputs": [ |
| 118 | { |
| 119 | "data": { |
| 120 | "text/html": [ |
| 121 | "<div>\n", |
| 122 | "<style scoped>\n", |
| 123 | " .dataframe tbody tr th:only-of-type {\n", |
| 124 | " vertical-align: middle;\n", |
| 125 | " }\n", |
| 126 | "\n", |
| 127 | " .dataframe tbody tr th {\n", |
| 128 | " vertical-align: top;\n", |
| 129 | " }\n", |
| 130 | "\n", |
| 131 | " .dataframe thead th {\n", |
| 132 | " text-align: right;\n", |
| 133 | " }\n", |
| 134 | "</style>\n", |
| 135 | "<table border=\"1\" class=\"dataframe\">\n", |
| 136 | " <thead>\n", |
| 137 | " <tr style=\"text-align: right;\">\n", |
| 138 | " <th></th>\n", |
| 139 | " <th>name</th>\n", |
| 140 | " <th>qubits</th>\n", |
| 141 | " <th>runtime</th>\n", |
| 142 | " <th>error</th>\n", |
| 143 | " <th>physical_compute_qubits</th>\n", |
| 144 | " <th>physical_factory_qubits</th>\n", |
| 145 | " <th>physical_memory_qubits</th>\n", |
| 146 | " <th>factories</th>\n", |
| 147 | " </tr>\n", |
| 148 | " </thead>\n", |
| 149 | " <tbody>\n", |
| 150 | " <tr>\n", |
| 151 | " <th>0</th>\n", |
| 152 | " <td>Built-in models</td>\n", |
| 153 | " <td>9567</td>\n", |
| 154 | " <td>0 days 00:00:00.000225</td>\n", |
| 155 | " <td>0.007312</td>\n", |
| 156 | " <td>3087</td>\n", |
| 157 | " <td>6480</td>\n", |
| 158 | " <td>0</td>\n", |
| 159 | " <td>8×T</td>\n", |
| 160 | " </tr>\n", |
| 161 | " <tr>\n", |
| 162 | " <th>1</th>\n", |
| 163 | " <td>Built-in models</td>\n", |
| 164 | " <td>13221</td>\n", |
| 165 | " <td>0 days 00:00:00.000141</td>\n", |
| 166 | " <td>0.009416</td>\n", |
| 167 | " <td>1071</td>\n", |
| 168 | " <td>12150</td>\n", |
| 169 | " <td>0</td>\n", |
| 170 | " <td>15×T</td>\n", |
| 171 | " </tr>\n", |
| 172 | " </tbody>\n", |
| 173 | "</table>\n", |
| 174 | "</div>" |
| 175 | ], |
| 176 | "text/plain": [ |
| 177 | " name qubits runtime error \\\n", |
| 178 | "0 Built-in models 9567 0 days 00:00:00.000225 0.007312 \n", |
| 179 | "1 Built-in models 13221 0 days 00:00:00.000141 0.009416 \n", |
| 180 | "\n", |
| 181 | " physical_compute_qubits physical_factory_qubits physical_memory_qubits \\\n", |
| 182 | "0 3087 6480 0 \n", |
| 183 | "1 1071 12150 0 \n", |
| 184 | "\n", |
| 185 | " factories \n", |
| 186 | "0 8×T \n", |
| 187 | "1 15×T " |
| 188 | ] |
| 189 | }, |
| 190 | "execution_count": 3, |
| 191 | "metadata": {}, |
| 192 | "output_type": "execute_result" |
| 193 | } |
| 194 | ], |
| 195 | "source": [ |
| 196 | "app = QSharpApplication(qdk.code.AdderWithRotations)\n", |
| 197 | "\n", |
| 198 | "# Baseline: built-in architecture, QEC, and factory\n", |
| 199 | "baseline_arch = GateBased(error_rate=1e-4, gate_time=100, measurement_time=500)\n", |
| 200 | "baseline = estimate(\n", |
| 201 | " app, baseline_arch,\n", |
| 202 | " isa_query=SurfaceCode.q() * Litinski19Factory.q(),\n", |
| 203 | " max_error=0.01,\n", |
| 204 | " name=\"Built-in models\",\n", |
| 205 | ")\n", |
| 206 | "baseline.add_qubit_partition_column()\n", |
| 207 | "baseline.add_factory_summary_column()\n", |
| 208 | "baseline.as_frame()" |
| 209 | ] |
| 210 | }, |
| 211 | { |
| 212 | "cell_type": "markdown", |
| 213 | "id": "ef447c3b", |
| 214 | "metadata": {}, |
| 215 | "source": [ |
| 216 | "## Building a custom architecture model\n", |
| 217 | "\n", |
| 218 | "An `Architecture` defines the physical instruction set of a quantum computer:\n", |
| 219 | "the native operations the hardware can perform, each with a gate time and error\n", |
| 220 | "rate.\n", |
| 221 | "\n", |
| 222 | "The built-in `GateBased` architecture uses a single error rate for all gates.\n", |
| 223 | "In practice, two-qubit gates are typically noisier and slower than single-qubit\n", |
| 224 | "gates, and measurement fidelities may differ from gate fidelities. Let's build\n", |
| 225 | "a more flexible architecture that models these differences.\n", |
| 226 | "\n", |
| 227 | "To implement a custom architecture, subclass `Architecture` and implement one\n", |
| 228 | "method: `provided_isa`. This method receives an `ISAContext` and uses it to\n", |
| 229 | "register each physical instruction." |
| 230 | ] |
| 231 | }, |
| 232 | { |
| 233 | "cell_type": "code", |
| 234 | "execution_count": 4, |
| 235 | "id": "5e98f44a", |
| 236 | "metadata": {}, |
| 237 | "outputs": [], |
| 238 | "source": [ |
| 239 | "@dataclass\n", |
| 240 | "class ParameterizedArchitecture(Architecture):\n", |
| 241 | " \"\"\"\n", |
| 242 | " A configurable architecture with separate timing and error parameters for\n", |
| 243 | " single-qubit gates, two-qubit gates, and measurements.\n", |
| 244 | "\n", |
| 245 | " Unlike the built-in ``GateBased`` model (which uses one error rate for all\n", |
| 246 | " operations), this model lets you specify different error rates for each gate\n", |
| 247 | " class, reflecting hardware where two-qubit gates are noisier than\n", |
| 248 | " single-qubit gates.\n", |
| 249 | " \"\"\"\n", |
| 250 | "\n", |
| 251 | " _: KW_ONLY\n", |
| 252 | " single_qubit_gate_time: int\n", |
| 253 | " two_qubit_gate_time: int\n", |
| 254 | " measurement_time: int\n", |
| 255 | " single_qubit_error_rate: float\n", |
| 256 | " two_qubit_error_rate: float\n", |
| 257 | " measurement_error_rate: float\n", |
| 258 | "\n", |
| 259 | " def provided_isa(self, ctx: ISAContext) -> ISA:\n", |
| 260 | " instructions = []\n", |
| 261 | "\n", |
| 262 | " # Single-qubit gates: Clifford gates and T gates\n", |
| 263 | " for gate_id in [H, S, S_DAG, T, T_DAG]:\n", |
| 264 | " instructions.append(\n", |
| 265 | " ctx.add_instruction(\n", |
| 266 | " gate_id,\n", |
| 267 | " encoding=PHYSICAL,\n", |
| 268 | " arity=1,\n", |
| 269 | " time=self.single_qubit_gate_time,\n", |
| 270 | " error_rate=self.single_qubit_error_rate,\n", |
| 271 | " )\n", |
| 272 | " )\n", |
| 273 | "\n", |
| 274 | " # Measurements\n", |
| 275 | " for meas_id in [MEAS_X, MEAS_Y, MEAS_Z]:\n", |
| 276 | " instructions.append(\n", |
| 277 | " ctx.add_instruction(\n", |
| 278 | " meas_id,\n", |
| 279 | " encoding=PHYSICAL,\n", |
| 280 | " arity=1,\n", |
| 281 | " time=self.measurement_time,\n", |
| 282 | " error_rate=self.measurement_error_rate,\n", |
| 283 | " )\n", |
| 284 | " )\n", |
| 285 | "\n", |
| 286 | " # Two-qubit entangling gates\n", |
| 287 | " for gate_id in [CNOT, CZ]:\n", |
| 288 | " instructions.append(\n", |
| 289 | " ctx.add_instruction(\n", |
| 290 | " gate_id,\n", |
| 291 | " encoding=PHYSICAL,\n", |
| 292 | " arity=2,\n", |
| 293 | " time=self.two_qubit_gate_time,\n", |
| 294 | " error_rate=self.two_qubit_error_rate,\n", |
| 295 | " )\n", |
| 296 | " )\n", |
| 297 | "\n", |
| 298 | " return ctx.make_isa(*instructions)" |
| 299 | ] |
| 300 | }, |
| 301 | { |
| 302 | "cell_type": "markdown", |
| 303 | "id": "ee910f8e", |
| 304 | "metadata": {}, |
| 305 | "source": [ |
| 306 | "### What if my qubits had different characteristics?\n", |
| 307 | "\n", |
| 308 | "Let's explore two hypothetical hardware scenarios:\n", |
| 309 | "\n", |
| 310 | "- **Fast but noisy:** short gate times, higher error rates (reminiscent of\n", |
| 311 | " some superconducting platforms)\n", |
| 312 | "- **Slow but clean:** longer gate times, lower error rates (reminiscent of\n", |
| 313 | " some trapped-ion platforms)\n", |
| 314 | "\n", |
| 315 | "We use the built-in `SurfaceCode` and `Litinski19Factory` transforms so that we\n", |
| 316 | "isolate the effect of the architecture." |
| 317 | ] |
| 318 | }, |
| 319 | { |
| 320 | "cell_type": "code", |
| 321 | "execution_count": 5, |
| 322 | "id": "b7f6079c", |
| 323 | "metadata": {}, |
| 324 | "outputs": [ |
| 325 | { |
| 326 | "data": { |
| 327 | "text/html": [ |
| 328 | "<div>\n", |
| 329 | "<style scoped>\n", |
| 330 | " .dataframe tbody tr th:only-of-type {\n", |
| 331 | " vertical-align: middle;\n", |
| 332 | " }\n", |
| 333 | "\n", |
| 334 | " .dataframe tbody tr th {\n", |
| 335 | " vertical-align: top;\n", |
| 336 | " }\n", |
| 337 | "\n", |
| 338 | " .dataframe thead th {\n", |
| 339 | " text-align: right;\n", |
| 340 | " }\n", |
| 341 | "</style>\n", |
| 342 | "<table border=\"1\" class=\"dataframe\">\n", |
| 343 | " <thead>\n", |
| 344 | " <tr style=\"text-align: right;\">\n", |
| 345 | " <th></th>\n", |
| 346 | " <th>encoding</th>\n", |
| 347 | " <th>arity</th>\n", |
| 348 | " <th>space</th>\n", |
| 349 | " <th>time</th>\n", |
| 350 | " <th>error</th>\n", |
| 351 | " </tr>\n", |
| 352 | " <tr>\n", |
| 353 | " <th>id</th>\n", |
| 354 | " <th></th>\n", |
| 355 | " <th></th>\n", |
| 356 | " <th></th>\n", |
| 357 | " <th></th>\n", |
| 358 | " <th></th>\n", |
| 359 | " </tr>\n", |
| 360 | " </thead>\n", |
| 361 | " <tbody>\n", |
| 362 | " <tr>\n", |
| 363 | " <th>H</th>\n", |
| 364 | " <td>PHYSICAL</td>\n", |
| 365 | " <td>1</td>\n", |
| 366 | " <td>1</td>\n", |
| 367 | " <td>50</td>\n", |
| 368 | " <td>0.0001</td>\n", |
| 369 | " </tr>\n", |
| 370 | " <tr>\n", |
| 371 | " <th>MEAS_X</th>\n", |
| 372 | " <td>PHYSICAL</td>\n", |
| 373 | " <td>1</td>\n", |
| 374 | " <td>1</td>\n", |
| 375 | " <td>200</td>\n", |
| 376 | " <td>0.0005</td>\n", |
| 377 | " </tr>\n", |
| 378 | " <tr>\n", |
| 379 | " <th>S</th>\n", |
| 380 | " <td>PHYSICAL</td>\n", |
| 381 | " <td>1</td>\n", |
| 382 | " <td>1</td>\n", |
| 383 | " <td>50</td>\n", |
| 384 | " <td>0.0001</td>\n", |
| 385 | " </tr>\n", |
| 386 | " <tr>\n", |
| 387 | " <th>T</th>\n", |
| 388 | " <td>PHYSICAL</td>\n", |
| 389 | " <td>1</td>\n", |
| 390 | " <td>1</td>\n", |
| 391 | " <td>50</td>\n", |
| 392 | " <td>0.0001</td>\n", |
| 393 | " </tr>\n", |
| 394 | " <tr>\n", |
| 395 | " <th>MEAS_Y</th>\n", |
| 396 | " <td>PHYSICAL</td>\n", |
| 397 | " <td>1</td>\n", |
| 398 | " <td>1</td>\n", |
| 399 | " <td>200</td>\n", |
| 400 | " <td>0.0005</td>\n", |
| 401 | " </tr>\n", |
| 402 | " <tr>\n", |
| 403 | " <th>CZ</th>\n", |
| 404 | " <td>PHYSICAL</td>\n", |
| 405 | " <td>2</td>\n", |
| 406 | " <td>2</td>\n", |
| 407 | " <td>100</td>\n", |
| 408 | " <td>0.0005</td>\n", |
| 409 | " </tr>\n", |
| 410 | " <tr>\n", |
| 411 | " <th>S_DAG</th>\n", |
| 412 | " <td>PHYSICAL</td>\n", |
| 413 | " <td>1</td>\n", |
| 414 | " <td>1</td>\n", |
| 415 | " <td>50</td>\n", |
| 416 | " <td>0.0001</td>\n", |
| 417 | " </tr>\n", |
| 418 | " <tr>\n", |
| 419 | " <th>T_DAG</th>\n", |
| 420 | " <td>PHYSICAL</td>\n", |
| 421 | " <td>1</td>\n", |
| 422 | " <td>1</td>\n", |
| 423 | " <td>50</td>\n", |
| 424 | " <td>0.0001</td>\n", |
| 425 | " </tr>\n", |
| 426 | " <tr>\n", |
| 427 | " <th>MEAS_Z</th>\n", |
| 428 | " <td>PHYSICAL</td>\n", |
| 429 | " <td>1</td>\n", |
| 430 | " <td>1</td>\n", |
| 431 | " <td>200</td>\n", |
| 432 | " <td>0.0005</td>\n", |
| 433 | " </tr>\n", |
| 434 | " <tr>\n", |
| 435 | " <th>CNOT</th>\n", |
| 436 | " <td>PHYSICAL</td>\n", |
| 437 | " <td>2</td>\n", |
| 438 | " <td>2</td>\n", |
| 439 | " <td>100</td>\n", |
| 440 | " <td>0.0005</td>\n", |
| 441 | " </tr>\n", |
| 442 | " </tbody>\n", |
| 443 | "</table>\n", |
| 444 | "</div>" |
| 445 | ], |
| 446 | "text/plain": [ |
| 447 | " encoding arity space time error\n", |
| 448 | "id \n", |
| 449 | "H PHYSICAL 1 1 50 0.0001\n", |
| 450 | "MEAS_X PHYSICAL 1 1 200 0.0005\n", |
| 451 | "S PHYSICAL 1 1 50 0.0001\n", |
| 452 | "T PHYSICAL 1 1 50 0.0001\n", |
| 453 | "MEAS_Y PHYSICAL 1 1 200 0.0005\n", |
| 454 | "CZ PHYSICAL 2 2 100 0.0005\n", |
| 455 | "S_DAG PHYSICAL 1 1 50 0.0001\n", |
| 456 | "T_DAG PHYSICAL 1 1 50 0.0001\n", |
| 457 | "MEAS_Z PHYSICAL 1 1 200 0.0005\n", |
| 458 | "CNOT PHYSICAL 2 2 100 0.0005" |
| 459 | ] |
| 460 | }, |
| 461 | "execution_count": 5, |
| 462 | "metadata": {}, |
| 463 | "output_type": "execute_result" |
| 464 | } |
| 465 | ], |
| 466 | "source": [ |
| 467 | "fast_noisy = ParameterizedArchitecture(\n", |
| 468 | " single_qubit_gate_time=50,\n", |
| 469 | " two_qubit_gate_time=100,\n", |
| 470 | " measurement_time=200,\n", |
| 471 | " single_qubit_error_rate=1e-4,\n", |
| 472 | " two_qubit_error_rate=5e-4,\n", |
| 473 | " measurement_error_rate=5e-4,\n", |
| 474 | ")\n", |
| 475 | "\n", |
| 476 | "slow_clean = ParameterizedArchitecture(\n", |
| 477 | " single_qubit_gate_time=500,\n", |
| 478 | " two_qubit_gate_time=1000,\n", |
| 479 | " measurement_time=1000,\n", |
| 480 | " single_qubit_error_rate=1e-6,\n", |
| 481 | " two_qubit_error_rate=5e-6,\n", |
| 482 | " measurement_error_rate=1e-5,\n", |
| 483 | ")\n", |
| 484 | "\n", |
| 485 | "# Inspect the physical ISA provided by the fast-but-noisy architecture\n", |
| 486 | "fast_noisy.provided_isa(fast_noisy.context()).as_frame()" |
| 487 | ] |
| 488 | }, |
| 489 | { |
| 490 | "cell_type": "code", |
| 491 | "execution_count": 6, |
| 492 | "id": "de4ec193", |
| 493 | "metadata": {}, |
| 494 | "outputs": [ |
| 495 | { |
| 496 | "data": { |
| 497 | "image/png": "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rsLCQoWFhXm7HAAAAJzF2bzm8hzbwsJCFRQUOLRFRkbq0KFDKioqcr1SAAAAwA1cDra33367Pvroo3Lt//3vf3X77be7pSgAAADAVS4H21WrVqlXr17l2nv27KlVq1a5pSgAAADAVS4H25KSEp08ebJce2lpqY4dO+aWogAAAABXuRxsO3furDfffLNc++uvv66OHTu6pSgAAADAVS4/7mvixIlKTk7Whg0b1KdPH0nSokWLlJWVpYULF7q9QAAAAMAZLp+xTUpK0ooVKxQbG6v//ve/+vzzz9WiRQtt3LhR3bp180SNAAAAwHm55Tm2l6KMjAxlZGTIZrNp+/btPMcWAACgmnL2ObZOBduioiL7Rs73rNpLLRzyggYAAIDqzdm85tQc24iICOXm5qpBgwaqU6dOhW8YMwxDFotFNput6lUDAAAAVeRUsP3+++8VGRkpSVq8eLFHCwIAAACqosbOsT2NqQgAAADVm7N5zeWnIixYsEDLli2zf8/IyFC7du1055136tChQ1WrFgAAALhALgfbxx57zH4D2aZNmzRmzBj17dtXOTk5GjNmjNsLBAAAAJzh8gsacnJyFBcXJ0maM2eO+vXrp+eee07r1q1T37593V4gAAAA4AyXz9j6+/vr6NGjkqTvvvtOf/7znyVJkZGR530UGAAAAOApLp+xveaaazRmzBglJSVp9erVmj17tiRp+/btiomJcXuBAAAAgDNcPmM7depU1apVS5988ommTZumxo0bS5K+/vprpaamur1AAAAAwBk87ovHfQEAAFRrHnvcV48ePTRr1iwdO3bsggoEAAAA3MnlYNu+fXs9+uijio6O1j333KOVK1d6oi6Py8jIUFxcnBITE71dCgAAANygSlMRTp48qfnz52vmzJn6+uuv1aJFCw0fPlyDBw9WVFSUJ+r0GKYiAAAAVG8em4ogSbVq1dLNN9+szz77THv37tWdd96pp556SrGxserfv7++//77KhcOAAAAVEWVgu1pq1ev1vjx4/Xyyy+rQYMGGjdunOrVq6cbbrhBjz76qLtqBAAAAM7L5akI+fn5eu+99zR9+nTt2LFD/fr10913362UlBRZLBZJ0rJly5Samqri4mKPFO1OTEUAAACo3pzNay6/oCEmJkaXX365hg8frrS0NNWvX79cn/j4eG7KAgAAwEXlcrBdtGiRunXr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OsbSpUvVr18/NWrUSBaLRfPmzauwX0ZGhpo1a6bAwEB16dJFq1evdmsdqJpp06YpPj5eYWFhCgsLU9euXfX111+7dQyOEdc8//zzslgsGj16tFu3y+9gDr///rvuuusu1a1bV0FBQWrbtq3WrFnjtu1znFzaCLYwtSVLlmjEiBFauXKlvv32W5WWlurPf/6zrFZrhf2XL1+u0tLScu1btmzR/v37K1zHarUqISFBGRkZldYxe/ZsjRkzRuPHj9e6deuUkJCglJQU5efn2/u0a9dObdq0KffZt2+fi3sNV8TExOj555/X2rVrtWbNGvXu3Vs33nijfvrppwr7c4x4VlZWlt544w3Fx8efsx+/Q8106NAhJSUlyc/PT19//bW2bNmil19+WRERERX25zipgQygBsnPzzckGUuWLCm3zGazGQkJCcYtt9xinDx50t7+888/G1FRUcYLL7xw3u1LMubOnVuuvXPnzsaIESMcxmrUqJGRnp7uUv2LFy82BgwY4NI6cF1ERITx9ttvl2vnGPGsI0eOGFdccYXx7bffGj169DAefvjhCvvxO9RcTzzxhHHNNdc41ZfjpGbijC1qlMLCQklSZGRkuWU+Pj766quvtH79eg0ZMkRlZWX69ddf1bt3b/Xv31+PP/54lcY8ceKE1q5dq+TkZIexkpOTtWLFiqrtCDzCZrPpo48+ktVqVdeuXcst5xjxrBEjRuj66693+DtUhN+h5po/f746deqkgQMHqkGDBmrfvr3eeuutCvtynNRMtbxdAHCxlJWVafTo0UpKSlKbNm0q7NOoUSN9//336tatm+68806tWLFCycnJmjZtWpXHPXjwoGw2m6Kiohzao6Ki9PPPPzu9neTkZG3YsEFWq1UxMTH6+OOPKwxfcN2mTZvUtWtXHT9+XKGhoZo7d67i4uIq7Msx4hkfffSR1q1bp6ysLKf68zvUTL/99pumTZumMWPG6O9//7uysrI0atQo+fv7a+jQoeX6c5zUPARb1BgjRozQ5s2btWzZsnP2a9Kkid577z316NFDl112md555x1ZLJaLVGXlvvvuO2+XYFqtWrVSdna2CgsL9cknn2jo0KFasmRJpeGWY8S99uzZo4cffljffvutAgMDnV6P36HmKSsrU6dOnfTcc89Jktq3b6/Nmzfr9ddfrzDYShwnNQ1TEVAjjBw5Ul988YUWL16smJiYc/bdv3+/7r33XvXr109Hjx7V3/72twsau169evL19S13o8L+/fsVHR19QduGe/j7+6tFixbq2LGj0tPTlZCQoMmTJ1fan2PEvdauXav8/Hx16NBBtWrVUq1atbRkyRJNmTJFtWrVks1mq3A9foeap2HDhuX+D2fr1q21e/fuStfhOKlZCLYwNcMwNHLkSM2dO1fff/+9mjdvfs7+Bw8eVJ8+fdS6dWt9+umnWrRokWbPnq1HH320yjX4+/urY8eOWrRokb2trKxMixYt4rJTNVVWVqaSkpIKl3GMuF+fPn20adMmZWdn2z+dOnXSoEGDlJ2dLV9f33Lr8DvUTElJSeUe2bh9+3Y1bdq0wv4cJzWQt+9eAzzpgQceMMLDw43MzEwjNzfX/jl69Gi5vjabzejUqZPRt29fo6SkxN6enZ1tREZGGq+88kqFYxw5csRYv369sX79ekOS8corrxjr1683du3aZe/z0UcfGQEBAcaMGTOMLVu2GPfee69Rp04dIy8vz/07DZeMHTvWWLJkiZGTk2Ns3LjRGDt2rGGxWIyFCxeW68sxcvGc76kI/A410+rVq41atWoZzz77rLFjxw7jgw8+MIKDg43333+/XF+Ok5qJYAtTk1ThZ/r06RX2X7hwoXHs2LFy7evWrTP27NlT4TqLFy+ucIyhQ4c69HvttdeMJk2aGP7+/kbnzp2NlStXXujuwQ2GDx9uNG3a1PD39zfq169v9OnTp8JQexrHyMVxrmBrGPwONdnnn39utGnTxggICDCuvPJK480336y0L8dJzWMxDMO4GGeGAQAAAE9iji0AAABMgWALAAAAUyDYAgAAwBQItgAAADAFgi0AAABMgWALAAAAUyDYAgAAwBQItgAAADAFgi0AAABMgWALANVYz549NXr0aK+N3717d3344Yce2/6CBQvUrl07lZWVeWwMADUHwRYAziEtLU0Wi0UWi0V+fn5q3ry5Hn/8cR0/ftyt42RmZspisejw4cMO7Z9++qn++c9/unUsZ82fP1/79+/X7bff7rExUlNT5efnpw8++MBjYwCoOQi2AHAeqampys3N1W+//aZXX31Vb7zxhsaPH39Rxo6MjFTt2rUvylhnmzJlioYNGyYfH8/+qyItLU1Tpkzx6BgAagaCLQCcR0BAgKKjoxUbG6v+/fsrOTlZ3377rX15s2bNNGnSJId12rVrpwkTJti/WywWvf3227rpppsUHBysK664QvPnz5ck7dy5U7169ZIkRUREyGKxKC0tTVL5qQjNmjXTxIkTNWTIEIWGhqpp06aaP3++Dhw4oBtvvFGhoaGKj4/XmjVrHOpZtmyZunXrpqCgIMXGxmrUqFGyWq2V7vOBAwf0/fffq1+/fg7tFotFb7zxhm644QYFBwerdevWWrFihX755Rf17NlTISEhuvrqq/Xrr7/a19mwYYN69eql2rVrKywsTB07dnSor1+/flqzZo3DOgBQFQRbAHDB5s2b9eOPP8rf39/ldZ955hndeuut2rhxo/r27atBgwapoKBAsbGxmjNnjiRp27Ztys3N1eTJkyvdzquvvqqkpCStX79e119/vQYPHqwhQ4borrvu0rp163T55ZdryJAhMgxDkvTrr78qNTVVAwYM0MaNGzV79mwtW7ZMI0eOrHSMZcuW2YPr2f75z39qyJAhys7O1pVXXqk777xT9913n8aNG6c1a9bIMAyHbQ8aNEgxMTHKysrS2rVrNXbsWPn5+dmXN2nSRFFRUfrhhx9c/psCwJkItgBwHl988YVCQ0MVGBiotm3bKj8/X4899pjL20lLS9Mdd9yhFi1a6LnnnlNxcbFWr14tX19fRUZGSpIaNGig6OhohYeHV7qdvn376r777tMVV1yhp59+WkVFRUpMTNTAgQPVsmVLPfHEE9q6dav2798vSUpPT9egQYM0evRoXXHFFbr66qs1ZcoUzZo1q9K5wrt27VJUVFSF0xCGDRumW2+91T7Wzp07NWjQIKWkpKh169Z6+OGHlZmZae+/e/duJScn68orr9QVV1yhgQMHKiEhwWGbjRo10q5du1z9kwKAA4ItAJxHr169lJ2drVWrVmno0KEaNmyYBgwY4PJ24uPj7f8cEhKisLAw5efnX9B2oqKiJElt27Yt13Z62xs2bNCMGTMUGhpq/6SkpKisrEw5OTkVjnHs2DEFBgZWefzjx4+rqKhIkjRmzBjdfffdSk5O1vPPP1/hlIOgoCAdPXr0/DsPAOdAsAWA8wgJCVGLFi2UkJCgd999V6tWrdI777xjX+7j42O/7H9aaWlpue2cefldOjVftSqPuTpzOxaLpdK209suLi7Wfffdp+zsbPtnw4YN2rFjhy6//PIKx6hXr54OHTrklvEnTJign376Sddff72+//57xcXFae7cuQ7bLCgoUP369Z3YewCoHMEWAFzg4+Ojv//973ryySd17NgxSVL9+vWVm5tr71NUVFTpmdDKnJ6za7PZ3Ffs/+nQoYO2bNmiFi1alPtUNle4ffv2ysvLqzTcuqply5b629/+poULF+rmm2/W9OnT7cuOHz+uX3/9Ve3bt3fLWABqLoItALho4MCB8vX1VUZGhiSpd+/eeu+99/TDDz9o06ZNGjp0qHx9fV3aZtOmTWWxWPTFF1/owIEDKi4udlu9TzzxhH788UeNHDlS2dnZ2rFjhz777LNz3jzWvn171atXT8uXL7+gsY8dO6aRI0cqMzNTu3bt0vLly5WVleVwU9rKlSsVEBCgrl27XtBYAECwBQAX1apVSyNHjtSLL74oq9WqcePGqUePHrrhhht0/fXXq3///pVe4q9M48aN9cwzz2js2LGKioo6Z+h0VXx8vJYsWaLt27erW7duat++vZ5++mk1atSo0nV8fX01bNiwC35xgq+vr/744w8NGTJELVu21K233qrrrrtOzzzzjL3Pf/7zHw0aNEjBwcEXNBYAWIyzJ4YBACApLy9Pf/rTn7Ru3To1bdrUI2McPHhQrVq10po1a9S8eXOPjAGg5uCMLQCgQtHR0XrnnXe0e/duj42xc+dO/fvf/ybUAnALztgCAADAFDhjCwAAAFMg2AIAAMAUCLYAAAAwBYItAAAATIFgCwAAAFMg2AIAAMAUCLYAAAAwBYItAAAATIFgCwAAAFP4/6B/FjWe/X9dAAAAAElFTkSuQmCC", |
| 498 | "text/plain": [ |
| 499 | "<Figure size 800x500 with 1 Axes>" |
| 500 | ] |
| 501 | }, |
| 502 | "execution_count": 6, |
| 503 | "metadata": {}, |
| 504 | "output_type": "execute_result" |
| 505 | } |
| 506 | ], |
| 507 | "source": [ |
| 508 | "isa_query = SurfaceCode.q() * Litinski19Factory.q()\n", |
| 509 | "\n", |
| 510 | "results = [\n", |
| 511 | " estimate(app, fast_noisy, isa_query, max_error=0.01, name=\"Fast but noisy\"),\n", |
| 512 | " estimate(app, slow_clean, isa_query, max_error=0.01, name=\"Slow but clean\"),\n", |
| 513 | " baseline,\n", |
| 514 | "]\n", |
| 515 | "\n", |
| 516 | "plot_estimates(results, figsize=(8, 5), runtime_unit=\"ms\")" |
| 517 | ] |
| 518 | }, |
| 519 | { |
| 520 | "cell_type": "markdown", |
| 521 | "id": "f4cd8012", |
| 522 | "metadata": {}, |
| 523 | "source": [ |
| 524 | "## Building a custom QEC ISA transform\n", |
| 525 | "\n", |
| 526 | "An `ISATransform` maps one instruction set to another. A QEC transform\n", |
| 527 | "consumes physical instructions and produces logical instructions by encoding\n", |
| 528 | "qubits in an error-correcting code.\n", |
| 529 | "\n", |
| 530 | "The key relationships in any QEC code are:\n", |
| 531 | "\n", |
| 532 | "- **Space**: How many physical qubits per logical qubit? (Depends on code\n", |
| 533 | " distance.)\n", |
| 534 | "- **Time**: How long does one logical operation take? (Depends on syndrome\n", |
| 535 | " extraction cycles.)\n", |
| 536 | "- **Error**: What is the logical error rate? (Depends on physical error rate,\n", |
| 537 | " code distance, and the code's threshold.)\n", |
| 538 | "\n", |
| 539 | "To implement a QEC transform, subclass `ISATransform` and implement two\n", |
| 540 | "methods:\n", |
| 541 | "\n", |
| 542 | "1. `required_isa`: a **static method** that declares what physical\n", |
| 543 | " instructions the transform needs. Because it is static, it cannot reference\n", |
| 544 | " instance fields (such as the error-correction threshold); instead, you\n", |
| 545 | " specify fixed bounds using `ConstraintBound`. `ConstraintBound` supports\n", |
| 546 | " comparisons like `.lt(value)` (less than), `.le(value)`, `.eq(value)`,\n", |
| 547 | " `.gt(value)`, and `.ge(value)`.\n", |
| 548 | "2. `provided_isa`: computes the logical instruction properties from the\n", |
| 549 | " physical ones and yields one or more ISAs.\n", |
| 550 | "\n", |
| 551 | "The `distance` field uses `metadata={\"domain\": range(3, 22, 2)}` to tell the\n", |
| 552 | "estimator to automatically search over odd distances from 3 to 21. The\n", |
| 553 | "estimator evaluates all distances and keeps only the Pareto-optimal ones." |
| 554 | ] |
| 555 | }, |
| 556 | { |
| 557 | "cell_type": "code", |
| 558 | "execution_count": 7, |
| 559 | "id": "3f829830", |
| 560 | "metadata": {}, |
| 561 | "outputs": [], |
| 562 | "source": [ |
| 563 | "@dataclass\n", |
| 564 | "class GenericQEC(ISATransform):\n", |
| 565 | " \"\"\"\n", |
| 566 | " A configurable QEC code model with tunable threshold, overhead,\n", |
| 567 | " and error suppression.\n", |
| 568 | "\n", |
| 569 | " This transform consumes physical H, CNOT, and MEAS_Z instructions and\n", |
| 570 | " produces a logical LATTICE_SURGERY instruction. The resource formulas\n", |
| 571 | " are parameterized so you can model different QEC code families.\n", |
| 572 | "\n", |
| 573 | " The logical error rate follows:\n", |
| 574 | "\n", |
| 575 | " error = crossing_prefactor × (p_physical / threshold) ^ ⌊(d+1)/2⌋\n", |
| 576 | "\n", |
| 577 | " Space per data qubit is:\n", |
| 578 | "\n", |
| 579 | " qubits_per_data_qubit × d²\n", |
| 580 | " \"\"\"\n", |
| 581 | "\n", |
| 582 | " crossing_prefactor: float = 0.03\n", |
| 583 | " error_correction_threshold: float = 0.01\n", |
| 584 | " qubits_per_data_qubit: int = 2\n", |
| 585 | " syndrome_extraction_depth: int = 4\n", |
| 586 | " _: KW_ONLY\n", |
| 587 | " distance: int = field(default=3, metadata={\"domain\": range(3, 22, 2)})\n", |
| 588 | "\n", |
| 589 | " @staticmethod\n", |
| 590 | " def required_isa() -> ISARequirements:\n", |
| 591 | " # required_isa is static, so we cannot reference instance fields here.\n", |
| 592 | " # Instead, we use ConstraintBound to express fixed constraints on the\n", |
| 593 | " # implementation ISA. ConstraintBound supports .lt(), .le(), .eq(),\n", |
| 594 | " # .gt(), and .ge() comparisons.\n", |
| 595 | " return ISARequirements(\n", |
| 596 | " constraint(H, error_rate=ConstraintBound.lt(0.01)),\n", |
| 597 | " constraint(CNOT, arity=2, error_rate=ConstraintBound.lt(0.01)),\n", |
| 598 | " constraint(MEAS_Z, error_rate=ConstraintBound.lt(0.01)),\n", |
| 599 | " )\n", |
| 600 | "\n", |
| 601 | " def provided_isa(\n", |
| 602 | " self, impl_isa: ISA, ctx: ISAContext\n", |
| 603 | " ) -> Generator[ISA, None, None]:\n", |
| 604 | " cnot = impl_isa[CNOT]\n", |
| 605 | " h = impl_isa[H]\n", |
| 606 | " meas_z = impl_isa[MEAS_Z]\n", |
| 607 | "\n", |
| 608 | " # Physical error rate is the worst case across all required gates\n", |
| 609 | " physical_error_rate = max(\n", |
| 610 | " cnot.expect_error_rate(),\n", |
| 611 | " h.expect_error_rate(),\n", |
| 612 | " meas_z.expect_error_rate(),\n", |
| 613 | " )\n", |
| 614 | "\n", |
| 615 | " d = self.distance\n", |
| 616 | "\n", |
| 617 | " # Space: physical qubits per data qubit, scaled by distance².\n", |
| 618 | " #\n", |
| 619 | " # Because LATTICE_SURGERY has variable arity (it can operate on any\n", |
| 620 | " # number of logical qubits), space and error_rate must be provided as\n", |
| 621 | " # functions of arity rather than as fixed numbers. The estimator\n", |
| 622 | " # provides several helpers for this:\n", |
| 623 | " #\n", |
| 624 | " # linear_function(slope) → f(n) = slope × n\n", |
| 625 | " # constant_function(value) → f(n) = value\n", |
| 626 | " # block_linear_function(k, s, o) → f(n) = s × ⌈n/k⌉ + o\n", |
| 627 | " # generic_function(callable) → f(n) = callable(n)\n", |
| 628 | " #\n", |
| 629 | " # For QEC codes, resources scale linearly with the number of logical\n", |
| 630 | " # qubits, so linear_function is the natural choice.\n", |
| 631 | " space = linear_function(self.qubits_per_data_qubit * d**2)\n", |
| 632 | "\n", |
| 633 | " # Time: syndrome extraction cycle × code distance\n", |
| 634 | " code_cycle_time = (\n", |
| 635 | " h.expect_time()\n", |
| 636 | " + self.syndrome_extraction_depth * cnot.expect_time()\n", |
| 637 | " + meas_z.expect_time()\n", |
| 638 | " )\n", |
| 639 | " time = code_cycle_time * d\n", |
| 640 | "\n", |
| 641 | " # Error: exponential suppression below threshold\n", |
| 642 | " logical_error = self.crossing_prefactor * (\n", |
| 643 | " (physical_error_rate / self.error_correction_threshold)\n", |
| 644 | " ** ((d + 1) // 2)\n", |
| 645 | " )\n", |
| 646 | " error = linear_function(logical_error)\n", |
| 647 | "\n", |
| 648 | " yield ctx.make_isa(\n", |
| 649 | " ctx.add_instruction(\n", |
| 650 | " LATTICE_SURGERY,\n", |
| 651 | " encoding=LOGICAL,\n", |
| 652 | " arity=None,\n", |
| 653 | " space=space,\n", |
| 654 | " time=time,\n", |
| 655 | " error_rate=error,\n", |
| 656 | " # transform=self records that this instruction was produced by\n", |
| 657 | " # this QEC transform instance, and source=[...] records which\n", |
| 658 | " # physical instructions it was derived from. Together, they\n", |
| 659 | " # form the provenance chain that you can inspect in the\n", |
| 660 | " # estimation results (see notebook 2).\n", |
| 661 | " transform=self,\n", |
| 662 | " source=[cnot, h, meas_z],\n", |
| 663 | " # Extra keyword arguments (like distance) are stored as\n", |
| 664 | " # properties on the instruction. This lets you retrieve the\n", |
| 665 | " # code distance used for each Pareto-optimal result when\n", |
| 666 | " # analysing the estimation output. Further, the property can be\n", |
| 667 | " # required and read by a parent ISATransform to create new\n", |
| 668 | " # logical instructions based on this one.\n", |
| 669 | " distance=d,\n", |
| 670 | " ),\n", |
| 671 | " )" |
| 672 | ] |
| 673 | }, |
| 674 | { |
| 675 | "cell_type": "markdown", |
| 676 | "id": "2981ec35", |
| 677 | "metadata": {}, |
| 678 | "source": [ |
| 679 | "### What if we had a better QEC code?\n", |
| 680 | "\n", |
| 681 | "Let's compare two configurations:\n", |
| 682 | "\n", |
| 683 | "- **Surface-code-like:** threshold 1%, prefactor 0.03, ~2d² physical qubits\n", |
| 684 | " per logical qubit (the `GenericQEC` defaults).\n", |
| 685 | "- **Optimistic code:** threshold 3%, prefactor 0.01, ~d² qubits\n", |
| 686 | " per logical qubit (a hypothetical code with better parameters).\n", |
| 687 | "\n", |
| 688 | "We use the built-in `GateBased` architecture and `Litinski19Factory` to isolate\n", |
| 689 | "the effect of the QEC code. Because `GenericQEC` is a dataclass, we can pass\n", |
| 690 | "the non-default parameters directly to `.q()`. The estimator fixes those values\n", |
| 691 | "while still searching over the `distance` hyperparameter." |
| 692 | ] |
| 693 | }, |
| 694 | { |
| 695 | "cell_type": "code", |
| 696 | "execution_count": 8, |
| 697 | "id": "175568cb", |
| 698 | "metadata": {}, |
| 699 | "outputs": [ |
| 700 | { |
| 701 | "data": { |
| 702 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAs4AAAHCCAYAAAD/xk/KAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAATTdJREFUeJzt3Xt8z/X///H7e+O988aYzeyEIZJNTiEJK1Q++KgUn4wKFeUQRZ9C3/iITlI+dHAopVRCnw6iOYscR+WsOe9AY7ODme31+8PPO2/beL3Zem92u14u78ul9/P5ej2fj/fbxbp77fl8vSyGYRgCAAAAcEUuzi4AAAAAKAsIzgAAAIAJBGcAAADABIIzAAAAYALBGQAAADCB4AwAAACYQHAGAAAATKjg7AJuZPn5+Tp+/Lh8fHxksVicXQ4AAAAuYxiGzpw5o+DgYLm4XPmaMsG5BB0/flyhoaHOLgMAAABXceTIEYWEhFzxGIJzCfLx8ZF04Q/C19fXydUAAADgcunp6QoNDbXltishOJegi8szfH19Cc4AAAClmJlltWwOBAAAAEwgOAMAAAAmEJwBAAAAE1jjDABAGZeXl6fc3FxnlwGUShUrVpSrq2uxjEVwBgCgjDIMQ0lJSTp9+rSzSwFKtUqVKikoKOi6n6tBcAYAoIy6GJqrVasmT09PHrYFXMYwDGVlZSklJUWSVL169esaj+AMAEAZlJeXZwvNVapUcXY5QKnl4eEhSUpJSVG1atWua9kGmwMBACiDLq5p9vT0dHIlQOl38e/J9e4FIDgDAFCGsTwDuLri+ntCcAYAAABMIDjDYelnc5WYll1oX2JattLPckskAABw4yE4wyHpZ3MVO2ujer63QcdP24fn46ez1fO9DYqdtZHwDABwmvfff1+hoaFycXHRlClTnF1Osbrzzjs1dOjQ6xpj3Lhxio6Otr3v27evunXrVqxz3KgIznBIZs55/ZlxTodTs/TQ+3+F5+Ons/XQ+xt0ODVLf2acU2bOeSdXCgC4Gmf9BvHEiRN68sknFRYWJjc3NwUFBaljx45at27ddY+dnp6uwYMH6/nnn9exY8c0YMCAYqj4xvb2229rzpw5JT7PRx99pGbNmsnT01M+Pj5q27atvv32W7tjVq5cKYvFUugrKSnJdlx6err+/e9/66abbpK7u7uCgoIUExOjr7/+WoZhlNhnIDjDIdX9PDSzX0OFVM2xhecth1JtoTmkao5m9muo6n4ezi4VAHAFzvwNYo8ePbRt2zZ99NFH2rt3r7755hvdeeed+vPPP695TMMwdP78eR0+fFi5ubm69957Vb16de46YoKfn58qVapUonOMGDFCAwcOVM+ePbVjxw5t3LhRt99+u7p27ap33323wPF79uxRYmKi3atatWqSpNOnT6tVq1b6+OOPNXr0aG3dulWrV69Wz5499dxzzyktLa3EPgfBGQ45c+6Mxm0aKs/w923hucf09bbQ7Bn+vsZtGqoz5844u1QAwBU46zeIp0+f1po1azRp0iS1a9dO4eHhat68uUaPHq1//OMfkqSDBw/KYrEoPj7e7jyLxaKVK1dK+uvK5A8//KAmTZrIzc1Nn3zyiW655RZJUq1atWSxWHTw4EEdOHBAXbt2VWBgoLy9vdWsWTP99NNPdnXl5OTo+eefV2hoqNzc3BQZGamZM2fa+n/77Td17txZ3t7eCgwM1COPPKKTJ09e8bNebcxVq1apefPmcnNzU/Xq1TVq1CidP//X952Zmak+ffrI29tb1atX1xtvvFHoHCNGjFCNGjXk5eWlFi1a2L4jsy5fqnG57777Tn5+fvr0008lSUeOHNGDDz6oSpUqyd/fX127dtXBgweLPH/Dhg1644039Nprr2nEiBGKjIxU/fr1NWHCBA0dOlTDhw/XkSNH7M6pVq2agoKC7F4uLhdi6wsvvKCDBw/ql19+UWxsrBo0aKC6deuqf//+io+Pl7e3t0Of3xEEZzgkMzdTqdmpSsw6Jmvoe7JUOC1JslQ4LWvoe0rMOqbU7FRl5mY6t1AAwBVV9/PQ5wNuU5i/Z6G/QQzz99TnA24r9t8gent7y9vbW4sWLVJOTs51jzdq1Ci9+uqr2rVrl+666y5bIN64caMSExMVGhqqjIwM3XPPPYqLi9O2bdvUqVMndenSRYcPH7aN06dPH3322WeaOnWqdu3apffee88WwE6fPq327durcePG2rx5s5YsWaLk5GQ9+OCDV6ztSmMeO3ZM99xzj5o1a6bt27dr+vTpmjlzpsaPH287f+TIkVq1apUWL16spUuXauXKldq6davdHIMHD9b69ev1+eefa8eOHXrggQfUqVMn7du377q/W0maN2+eHn74YX366afq3bu3cnNz1bFjR/n4+GjNmjVat26dvL291alTJ507d67QMT777DN5e3tr4MCBBfqeffZZ5ebmasGCBabqyc/P1+eff67evXsrODi4QL+3t7cqVCjB5/sZKDFpaWmGJCMtLc3ZpRSrxIxE464vOhoN5zQ0Grx/h1Fz3DSjwft3GA3nNDTu+qKjkZiR6OwSAeCGl52dbezcudPIzs6+rnGOncoy2kxaboQ//63t1WbScuPYqaxiqrSgr776yqhcubLh7u5utGrVyhg9erSxfft2W39CQoIhydi2bZut7dSpU4YkY8WKFYZhGMaKFSsMScaiRYvsxt62bZshyUhISLhiDTfffLPxzjvvGIZhGHv27DEkGcuWLSv02FdeecW4++677dqOHDliSDL27NlT6DlXG/OFF14w6tWrZ+Tn59vapk2bZnh7ext5eXnGmTNnDKvVanzxxRe2/j///NPw8PAwhgwZYhiGYRw6dMhwdXU1jh07Zjd2hw4djNGjRxf52ceOHWtERUXZ3sfGxhpdu3a1vW/btq0xZMgQ49133zX8/PyMlStX2vrmzp1boO6cnBzDw8PD+PHHHwudr1OnTnbzXc7X19d48sknDcP468/Vy8vL7tWgQQPDMAwjOTnZkGS8+eabRY5XmCv9fXEkr/HIbTgsP9dPWYcGKN/vbblYU+UVMf1C+zl/ZZ0YoPxcPydXCAAwK7iSh97qGaUe09fb2t7qGaXgSiW3V6VHjx669957tWbNGm3YsEE//PCDJk+erA8//FB9+/Z1aKymTZte9ZiMjAyNGzdO3333nRITE3X+/HllZ2fbrjjHx8fL1dVVbdu2LfT87du3a8WKFYUuAThw4IA2bdpkdzX1hx9+UGJi4hXH3LVrl1q2bGn3YI7WrVsrIyNDR48e1alTp3Tu3Dm1aNHC1u/v76969erZ3v/666/Ky8tT3bp17cbOycmxPYb90pr/9a9/acaMGUV+T5f66quvlJKSonXr1qlZs2Z238X+/fvl4+Njd/zZs2d14MCBIsczrrJhz2q12r1fs2aN3RwVK1Y0NU5JIzjDIYlpF9a+HU11U7BrH53xn2Lr88voo6Mn3fTQ+xs0f2Dx/3oPAFD8jp/O1rD52+3ahs3frs8H3Fai4dnd3V133XWX7rrrLr300kt6/PHHNXbsWPXt29e2lvXSkFTUo5K9vLyuOteIESO0bNkyvf7664qMjJSHh4fuv/9+29ICD48rf86MjAx16dJFkyZNKtBXvXp15efn2wXcGjVqFFhDXRIyMjLk6uqqLVu2yNXV1a7vYmC+dJ24r6+v6bEbN26srVu3atasWWratKkt4GdkZKhJkya29c6XCggIKHSsOnXqaO3atTp37lyBgHz8+HGlp6cXCP81a9YsdMNiQECAKlWqpN27d5v+LMWJNc5wiJdbBVXxtiqkao68Q7606/MO+VIhVXNUxdsqLzf+TQYApd2lGwHD/D214MmWdmueL7/bRklq0KCBMjMv7I+5GMASExNt/ZcGQEetW7dOffv2Vffu3XXLLbcoKCjIbjPbLbfcovz8fK1atarQ82+99Vb9/vvvioiIUGRkpN3Ly8tLPj4+dm0eHh5XHbN+/fpav3693T8O1q1bJx8fH4WEhKh27dqqWLGifvnlF1v/qVOntHfvXtv7xo0bKy8vTykpKQXqCgoKkiS7tot3pTCjdu3aWrFihRYvXqynn37a7rvYt2+fqlWrVmBOP7/Cf+P88MMPKyMjQ++9916Bvtdff13u7u7q2bOnqbpcXFz00EMP6dNPP9Xx48cL9GdkZNhtsCxuBGc4xNe9oiY/FCbP8PeVmHVMId4hmtt5rkK8Q5SYdUye4e9r8kNh8nWv6OxSAQBXcPE3iJduBGwS7l9gw2BR93m+Vn/++afat2+vTz75RDt27FBCQoK+/PJLTZ48WV27dpV04QrwbbfdZtv0t2rVKr344ovXPGedOnX09ddfKz4+Xtu3b1evXr2Un59v64+IiFBsbKweffRRLVq0SAkJCVq5cqW++OILSdKgQYOUmpqqhx9+WJs2bdKBAwf0448/ql+/fsrLyyt0zquN+dRTT+nIkSN6+umntXv3bi1evFhjx47V8OHD5eLiIm9vbz322GMaOXKkli9frt9++83uarwk1a1bV71791afPn309ddfKyEhQRs3btTEiRP13XffXfP3den4K1as0IIFC2wPROndu7eqVq2qrl27as2aNbbP9cwzz+jo0aOFjtOyZUsNGTJEI0eO1BtvvKEDBw5o9+7devHFFzV16lR98MEHtqUlF6WkpCgpKcnudfG3DhMmTFBoaKhatGihjz/+WDt37tS+ffs0a9YsNW7cWBkZGdf92Yvk0MpqOORG3ByYmJFodPqqk9FwTkOj01edbBsBi2oHAJSM690cmJZ9zug2bW2hGwEvbhjsNm2tkZZ9rjjKtTl79qwxatQo49ZbbzX8/PwMT09Po169esaLL75oZGX9VcfOnTuNli1bGh4eHkZ0dLSxdOnSQjcHnjp1ym78wjYHJiQkGO3atTM8PDyM0NBQ491337VtgLsoOzvbGDZsmFG9enXDarUakZGRxqxZs2z9e/fuNbp3725UqlTJ8PDwMG666SZj6NChdpvkLne1MVeuXGk0a9bMsFqtRlBQkPH8888bubm5tv4zZ84Y//rXvwxPT08jMDDQmDx5coG6z507Z4wZM8aIiIgwKlasaFSvXt3o3r27sWPHjiLrMrs58KKdO3ca1apVM4YPH24YhmEkJiYaffr0MapWrWq4ubkZtWrVMvr373/VvDNz5kyjSZMmhru7uyHJsFqtxqpVq+yOufjnWthr/fr1tuNOnz5tjBo1yqhTp45htVqNwMBAIyYmxli4cGGhfybFtTnQYhhOXmV9A0tPT5efn5/S0tIcWldUmp05d0ZP/PSEUrNTNbvTbAV5Bdn6kjKT1G9JP/l7+GtGzAz5WH2uMBIA4HqcPXtWCQkJqlmzptzd3a9pjPSzucrMOV/onpTEtGx5uVXgN4goEQcPHlTbtm3VsmVLffrppwXWaBe3K/19cSSvsRAVDvGx+mhGzAxl5mbahWZJCvIK0uxOs+VV0YvQDABlgK97xSKDMRu8UZIiIiK0cuVKffTRR4qPj1eTJk2cXZIpBGc4zMfqU2QwvjxMAwAAFKZmzZoaN26cs8twCJsDAQAAABMIzgAAAIAJBGcAAADABIIzAAAAYALBGQAAADCB4AwAAACYQHAGAAA3nHHjxik6Ovq6xjh48KAsFovi4+OveYy+ffuqW7du11UHSg+CMwAA+NsdOXJEjz76qIKDg2W1WhUeHq4hQ4bozz//dHgsi8WiRYsW2bWNGDFCcXFx11VjaGioEhMT1bBhw6seW1TIfvvttzVnzpzrqsPsd3XnnXfKYrEUeD3xxBN2x61YsUL33HOPqlSpIk9PTzVo0EDPPvusjh07dl11lgcEZwAAyquzaVJaEWEp7diF/hLwxx9/qGnTptq3b58+++wz7d+/XzNmzFBcXJxatmyp1NTU657D29tbVapUua4xXF1dFRQUpAoVrv15cX5+fqpUqdI1n+/od9W/f38lJibavSZPnmzrf++99xQTE6OgoCAtWLBAO3fu1IwZM5SWlqY33njjmussNwyUmLS0NEOSkZaW5uxSAAA3mOzsbGPnzp1Gdnb2NQ5w2jA+6GAYUxoZxukj9n2nj1xo/6DDheOKWadOnYyQkBAjKyvLrj0xMdHw9PQ0nnjiCVtbeHi48X//93/GQw89ZHh6ehrBwcHGu+++a9cvyfYKDw83DMMwxo4da0RFRdmOi42NNbp27WpMmDDBqFatmuHn52e8/PLLRm5urjFixAijcuXKRo0aNYxZs2bZzklISDAkGdu2bTMMwzBSU1ONXr16GVWrVjXc3d2NyMhI2/GX1iDJaNu2rd28F+Xl5RmTJk0yateubVitViM0NNQYP358sXxXbdu2NYYMGVLkWEeOHDGsVqsxdOjQQvtPnTpV5Lll3ZX+vjiS17jiDABAeZSTIWWekE4dlObcK6UdvdCedvTC+1MHL/TnZBTrtKmpqfrxxx/11FNPycPDw64vKChIvXv31vz582UYhq39tddeU1RUlLZt26ZRo0ZpyJAhWrZsmSRp06ZNkqTZs2crMTHR9r4wy5cv1/Hjx7V69Wq9+eabGjt2rO677z5VrlxZv/zyi5544gkNHDhQR48eLfT8l156STt37tQPP/ygXbt2afr06apataokaePGjZKkn376SYmJifr6668LHWP06NF69dVXbWPNmzdPgYGBxfZdXcmXX36pc+fO6bnnniu0/3qujJcXBGcAAMojvxpS3++kyhF/hefDv/wVmitHXOj3q1Gs0+7bt0+GYah+/fqF9tevX1+nTp3SiRMnbG2tW7fWqFGjVLduXT399NO6//779dZbb0mSAgICJF0IfUFBQbb3hfH399fUqVNVr149Pfroo6pXr56ysrL0wgsvqE6dOho9erSsVqvWrl1b6PmHDx9W48aN1bRpU0VERCgmJkZdunSxq6NKlSoKCgqSv79/gfPPnDmjt99+W5MnT1ZsbKxq166t22+/XY8//nixfVf//e9/5e3tbff69NNPbeP5+vqqevXqRX5HuLJrX7QDAADKNr+QC+H4YliedfeFdltoDimxqc1eJZWkli1bFng/ZcoUh+e8+eab5eLy1zXDwMBAu41/rq6uqlKlilJSUgo9/8knn1SPHj20detW3X333erWrZtatWplev5du3YpJydHHTp0cKjuq31XVqvV9t+9e/fWv//9b7v+i1e0DcOQxWJxaG7Y44ozAADlmV+I1P19+7bu75dYaI6MjJTFYtGuXbsK7d+1a5cqV658xSvH16pixYp27y0WS6Ft+fn5hZ7fuXNnHTp0SMOGDdPx48fVoUMHjRgxwvT8ly+3uBoz31VAQIDdEgs/Pz9FRkbavXx8fCRJdevWVVpamhITEx2qA38hOAMAUJ6lHZUWDrBvWzjgrzXPxaxKlSq666679N///lfZ2dl2fUlJSfr000/Vs2dPuyujGzZssDtuw4YNdssXKlasqLy8vBKp93IBAQGKjY3VJ598oilTpuj99y/8o+PiVd8r1VGnTh15eHiYvk2eme+qb9++pmu///77ZbVa7e6ycanTp0+bHqu8IjgDAFBeXboRsHKE9OhS+zXPJRSe3333XeXk5Khjx45avXq1jhw5oiVLluiuu+5SjRo1NGHCBLvj161bp8mTJ2vv3r2aNm2avvzySw0ZMsTWHxERobi4OCUlJenUqVMlUrMkjRkzRosXL9b+/fv1+++/69tvv7UF+GrVqsnDw0NLlixRcnKy0tIK3srP3d1dzz//vJ577jl9/PHHOnDggDZs2KCZM2cWOeeVvqu6detqzJgxdsdnZWUpKSnJ7nXxOwkNDdVbb72lt99+W4899phWrVqlQ4cOad26dRo4cKBeeeWVYvy2bkwEZwAAyqO0YwU3Aoa1KLhhsKj7PF+HOnXqaPPmzapVq5YefPBB1a5dWwMGDFC7du20fv36Ahvrnn32WW3evFmNGzfW+PHj9eabb6pjx462/jfeeEPLli1TaGioGjduXOz1XmS1WjV69Gg1atRId9xxh1xdXfX5559LkipUqKCpU6fqvffeU3BwsLp27VroGC+99JKeffZZjRkzRvXr11fPnj2LXFMtXfiuNm3aZPuuwsPD1blzZ9WtW1fr1q2Tt7e33fEffPCBqlevbvd6+OGHbf1PPfWUli5dqmPHjql79+666aab9Pjjj8vX19ehZSfllcVwZHU+HJKeni4/Pz+lpaXJ19fX2eUAAG4gZ8+eVUJCgmrWrCl3d/drGCBN+qTHhVvOXb4R8OKVaK8A6V8LJHe/4ivcQRERERo6dKiGDh3qtBpKm7Fjx+rNN9/UsmXLdNtttzm7nDLhSn9fHMlr3FUDAIDyyN3vQijOySh4yzm/EKnv95Kbt1NDMwr38ssvKyIiQhs2bFDz5s3t7hSCkkVwBgCgvHL3KzoYF/P9m1G8+vXr5+wSyiWCMwAAKLUOHjzo7BIAG67tAwAAACYQnAEAAAATCM4AAACACQRnAAAAwASCMwAAAGACwRkAAAAwgeAMAADKpDlz5qhSpUq29+PGjVN0dLTD46xcuVIWi0WnT58uttpK0rXUGxERoSlTppRYTeUFwRkAAPyt+vbtK4vFYntVqVJFnTp10o4dOxwap2fPntq7d+8V5+nWrdtVx2nVqpUSExPl58dTEnFlBGcAAMqpM+fOKCkzqdC+pMwknTl3psTm7tSpkxITE5WYmKi4uDhVqFBB9913n0NjeHh4qFq1atddi9VqVVBQkCwWy3WPhRsbwRkAgHLozLkzeuKnJ9RvSb8C4TkpM0n9lvTTEz89UWLh2c3NTUFBQQoKClJ0dLRGjRqlI0eO6MSJE5IKX44QHx8vi8Vie5rg5Us1LjVu3Dh99NFHWrx4se3K9sqVKws99vK5Lo77448/qn79+vL29rYF/aJcHOPHH39U48aN5eHhofbt2yslJUU//PCD6tevL19fX/Xq1UtZWVm283JycvTMM8+oWrVqcnd31+23365NmzbZjf3999+rbt268vDwULt27Qp9muLatWvVpk0beXh4KDQ0VM8884wyMzMLrdUwDI0bN05hYWFyc3NTcHCwnnnmmSI/G/5CcAYAoBzKzM1UanaqjmYctQvPF0Pz0YyjSs1OVWZu4eGrOGVkZOiTTz5RZGSkqlSpUixjjhgxQg8++KDdle1WrVqZPj8rK0uvv/665s6dq9WrV+vw4cMaMWLEVc8bN26c3n33Xf388886cuSIHnzwQU2ZMkXz5s3Td999p6VLl+qdd96xHf/cc89pwYIF+uijj7R161ZFRkaqY8eOSk1NlSQdOXJE//znP9WlSxfFx8fr8ccf16hRo+zmPHDggDp16qQePXpox44dmj9/vtauXavBgwcXWuOCBQv01ltv6b333tO+ffu0aNEi3XLLLaa/m/KM4AwAQDkU5BWk2Z1mK8Q7xBae41PibaE5xDtEszvNVpBXUInM/+2338rb21ve3t7y8fHRN998o/nz58vFpXiiibe3tzw8POyubFutVtPn5+bmasaMGWratKluvfVWDR48WHFxcVc9b/z48WrdurUaN26sxx57TKtWrdL06dPVuHFjtWnT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5Ur9+OOPBY7l50YJcvZtPQCgvJFU6Gv27NmFHr906VIjOzu7QPvWrVuNI0eOFHrOihUrCp0jNjbW7rh33nnHCAsLM6xWq9G8eXNjw4YN1/vxAJSARx991AgPDzesVqsREBBgdOjQwVi6dGmRx/Nzo2RYDMMw/v64DgAAAJQtrHEGAAAATCA4AwAAACYQnAEAAAATCM4AAACACQRnAAAAwASCMwAAAGACwRkAAAAwgeAMAAAAmEBwBgAAAEwgOANAOXXnnXdq6NChTpv/jjvu0Lx580ps/CVLlig6Olr5+fklNgeA8oXgDABO0rdvX1ksFlksFlWsWFE1a9bUc889p7NnzxbrPCtXrpTFYtHp06ft2r/++mu98sorxTqXWd98842Sk5P10EMPldgcnTp1UsWKFfXpp5+W2BwAyheCMwA4UadOnZSYmKg//vhDb731lt577z2NHTv2b5nb399fPj4+f8tcl5s6dar69esnF5eS/d9Q3759NXXq1BKdA0D5QXAGACdyc3NTUFCQQkND1a1bN8XExGjZsmW2/oiICE2ZMsXunOjoaI0bN8723mKx6MMPP1T37t3l6empOnXq6JtvvpEkHTx4UO3atZMkVa5cWRaLRX379pVUcKlGRESExo8frz59+sjb21vh4eH65ptvdOLECXXt2lXe3t5q1KiRNm/ebFfP2rVr1aZNG3l4eCg0NFTPPPOMMjMzi/zMJ06c0PLly9WlSxe7dovFovfee0/33XefPD09Vb9+fa1fv1779+/XnXfeKS8vL7Vq1UoHDhywnbN9+3a1a9dOPj4+8vX1VZMmTezq69KlizZv3mx3DgBcK4IzAJQSv/32m37++WdZrVaHz3355Zf14IMPaseOHbrnnnvUu3dvpaamKjQ0VAsWLJAk7dmzR4mJiXr77beLHOett95S69attW3bNt1777165JFH1KdPH/3rX//S1q1bVbt2bfXp00eGYUiSDhw4oE6dOqlHjx7asWOH5s+fr7Vr12rw4MFFzrF27VpbML7cK6+8oj59+ig+Pl433XSTevXqpYEDB2r06NHavHmzDMOwG7t3794KCQnRpk2btGXLFo0aNUoVK1a09YeFhSkwMFBr1qxx+DsFgMsRnAHAib799lt5e3vL3d1dt9xyi1JSUjRy5EiHx+nbt68efvhhRUZG6j//+Y8yMjK0ceNGubq6yt/fX5JUrVo1BQUFyc/Pr8hx7rnnHg0cOFB16tTRmDFjlJ6ermbNmumBBx5Q3bp19fzzz2vXrl1KTk6WJE2cOFG9e/fW0KFDVadOHbVq1UpTp07Vxx9/XORa7UOHDikwMLDQZRr9+vXTgw8+aJvr4MGD6t27tzp27Kj69etryJAhWrlype34w4cPKyYmRjfddJPq1KmjBx54QFFRUXZjBgcH69ChQ45+pQBQAMEZAJyoXbt2io+P1y+//KLY2Fj169dPPXr0cHicRo0a2f7by8tLvr6+SklJua5xAgMDJUm33HJLgbaLY2/fvl1z5syRt7e37dWxY0fl5+crISGh0Dmys7Pl7u5+zfOfPXtW6enpkqThw4fr8ccfV0xMjF599dVCl2R4eHgoKyvr6h8eAK6C4AwATuTl5aXIyEhFRUVp1qxZ+uWXXzRz5kxbv4uLi21ZxEW5ubkFxrl0eYJ0Yb3wtdyG7dJxLBZLkW0Xx87IyNDAgQMVHx9ve23fvl379u1T7dq1C52jatWqOnXqVLHMP27cOP3++++69957tXz5cjVo0EALFy60GzM1NVUBAQEmPj0AXBnBGQBKCRcXF73wwgt68cUXlZ2dLUkKCAhQYmKi7Zj09PQir+QW5eKa6by8vOIr9v+79dZbtXPnTkVGRhZ4FbVWu3HjxkpKSioyPDuqbt26GjZsmJYuXap//vOfmj17tq3v7NmzOnDggBo3blwscwEo3wjOAFCKPPDAA3J1ddW0adMkSe3bt9fcuXO1Zs0a/frrr4qNjZWrq6tDY4aHh8tisejbb7/ViRMnlJGRUWz1Pv/88/r55581ePBgxcfHa9++fVq8ePEVNwc2btxYVatW1bp1665r7uzsbA0ePFgrV67UoUOHtG7dOm3atMlu0+GGDRvk5uamli1bXtdcACARnAGgVKlQoYIGDx6syZMnKzMzU6NHj1bbtm1133336d5771W3bt2KXAJRlBo1aujll1/WqFGjFBgYeMVQ66hGjRpp1apV2rt3r9q0aaPGjRtrzJgxCg4OLvIcV1dX9evX77ofTOLq6qo///xTffr0Ud26dfXggw+qc+fOevnll23HfPbZZ+rdu7c8PT2vay4AkCSLcfniOQAASlhSUpJuvvlmbd26VeHh4SUyx8mTJ1WvXj1t3rxZNWvWLJE5AJQvXHEGAPztgoKCNHPmTB0+fLjE5jh48KD++9//EpoBFBuuOAMAAAAmcMUZAAAAMIHgDAAAAJhAcAYAAABMIDgDAAAAJhCcAQAAABMIzgAAAIAJBGcAAADABIIzAAAAYALBGQAAADDh/wEL++SoBnGhLgAAAABJRU5ErkJggg==", |
| 703 | "text/plain": [ |
| 704 | "<Figure size 800x500 with 1 Axes>" |
| 705 | ] |
| 706 | }, |
| 707 | "execution_count": 8, |
| 708 | "metadata": {}, |
| 709 | "output_type": "execute_result" |
| 710 | } |
| 711 | ], |
| 712 | "source": [ |
| 713 | "arch = GateBased(error_rate=1e-4, gate_time=100, measurement_time=500)\n", |
| 714 | "\n", |
| 715 | "# Surface-code-like parameters (the defaults)\n", |
| 716 | "surface_like = GenericQEC.q() * Litinski19Factory.q()\n", |
| 717 | "\n", |
| 718 | "# Optimistic hypothetical code: higher threshold, lower overhead\n", |
| 719 | "optimistic = GenericQEC.q(\n", |
| 720 | " crossing_prefactor=0.01,\n", |
| 721 | " error_correction_threshold=0.03,\n", |
| 722 | " qubits_per_data_qubit=1,\n", |
| 723 | ") * Litinski19Factory.q()\n", |
| 724 | "\n", |
| 725 | "results = [\n", |
| 726 | " estimate(app, arch, surface_like, max_error=0.01, name=\"Surface-code-like QEC\"),\n", |
| 727 | " estimate(app, arch, optimistic, max_error=0.01, name=\"Optimistic QEC\"),\n", |
| 728 | " baseline,\n", |
| 729 | "]\n", |
| 730 | "\n", |
| 731 | "plot_estimates(results, figsize=(8, 5), runtime_unit=\"ms\")" |
| 732 | ] |
| 733 | }, |
| 734 | { |
| 735 | "cell_type": "markdown", |
| 736 | "id": "6229d30a", |
| 737 | "metadata": {}, |
| 738 | "source": [ |
| 739 | "## Building a custom factory transform\n", |
| 740 | "\n", |
| 741 | "A factory transform produces high-fidelity magic states (typically T states) by\n", |
| 742 | "consuming lower-level instructions. It models the distillation process: take\n", |
| 743 | "many noisy copies of a state, run a distillation protocol, and output fewer\n", |
| 744 | "copies with lower error.\n", |
| 745 | "\n", |
| 746 | "The built-in `Litinski19Factory` uses pre-computed protocol data from\n", |
| 747 | "[arXiv:1905.06903](https://arxiv.org/abs/1905.06903). Each entry in the table\n", |
| 748 | "specifies an output error rate, a space cost in physical qubits (which already\n", |
| 749 | "accounts for the QEC overhead inside the factory), and a time cost in syndrome\n", |
| 750 | "extraction cycles.\n", |
| 751 | "\n", |
| 752 | "We can build a custom factory that starts from this data and explores \"what if\"\n", |
| 753 | "scenarios by scaling the space and cycle costs:\n", |
| 754 | "\n", |
| 755 | "- `space_factor < 1`: What if the factory were more compact?\n", |
| 756 | "- `cycle_factor < 1`: What if distillation were faster?\n", |
| 757 | "\n", |
| 758 | "This lets you study how improvements in factory design propagate through the\n", |
| 759 | "full resource estimate, without having to derive the protocols from scratch." |
| 760 | ] |
| 761 | }, |
| 762 | { |
| 763 | "cell_type": "code", |
| 764 | "execution_count": 9, |
| 765 | "id": "3f4951e1", |
| 766 | "metadata": {}, |
| 767 | "outputs": [], |
| 768 | "source": [ |
| 769 | "# Reference data from Litinski (arXiv:1905.06903), Table 1.\n", |
| 770 | "# Assumes Clifford and T error rates at most 1e-4.\n", |
| 771 | "# Each tuple: (output_error_rate, space_in_physical_qubits, cycles)\n", |
| 772 | "_LITINSKI_TABLE = [\n", |
| 773 | " (4.4e-8, 810, 18.1),\n", |
| 774 | " (1.5e-9, 762, 36.2),\n", |
| 775 | " (9.3e-10, 1150, 18.1),\n", |
| 776 | " (1.9e-11, 2070, 30.0),\n", |
| 777 | " (2.4e-15, 16400, 90.3),\n", |
| 778 | " (6.3e-25, 18600, 67.8),\n", |
| 779 | "]\n", |
| 780 | "\n", |
| 781 | "\n", |
| 782 | "@dataclass\n", |
| 783 | "class ScaledLitinskiFactory(ISATransform):\n", |
| 784 | " \"\"\"\n", |
| 785 | " A factory transform based on the Litinski (2019) distillation protocols,\n", |
| 786 | " with configurable scaling factors for space and cycle costs.\n", |
| 787 | "\n", |
| 788 | " The base data is taken directly from Table 1 in arXiv:1905.06903.\n", |
| 789 | " Each entry specifies a distillation protocol's output error rate, space\n", |
| 790 | " footprint (in physical qubits), and time (in syndrome extraction cycles).\n", |
| 791 | " The space already includes the QEC overhead within the factory itself.\n", |
| 792 | "\n", |
| 793 | " Scaling factors let you explore hypothetical improvements:\n", |
| 794 | "\n", |
| 795 | " - ``space_factor=0.5`` models a factory that uses half the qubits.\n", |
| 796 | " - ``cycle_factor=0.5`` models a factory that runs twice as fast.\n", |
| 797 | "\n", |
| 798 | " Note:\n", |
| 799 | " The error rates are kept fixed when scaling. In practice, changing\n", |
| 800 | " space or cycles would affect error rates too, but modelling that\n", |
| 801 | " relationship requires protocol-specific analysis.\n", |
| 802 | " \"\"\"\n", |
| 803 | "\n", |
| 804 | " space_factor: float = 1.0\n", |
| 805 | " cycle_factor: float = 1.0\n", |
| 806 | "\n", |
| 807 | " @staticmethod\n", |
| 808 | " def required_isa() -> ISARequirements:\n", |
| 809 | " return ISARequirements(\n", |
| 810 | " constraint(T, error_rate=ConstraintBound.le(1e-4)),\n", |
| 811 | " constraint(H, error_rate=ConstraintBound.le(1e-4)),\n", |
| 812 | " constraint(CNOT, arity=2, error_rate=ConstraintBound.le(1e-4)),\n", |
| 813 | " constraint(MEAS_Z, error_rate=ConstraintBound.le(1e-4)),\n", |
| 814 | " )\n", |
| 815 | "\n", |
| 816 | " def provided_isa(\n", |
| 817 | " self, impl_isa: ISA, ctx: ISAContext\n", |
| 818 | " ) -> Generator[ISA, None, None]:\n", |
| 819 | " cnot = impl_isa[CNOT]\n", |
| 820 | " h = impl_isa[H]\n", |
| 821 | " meas_z = impl_isa[MEAS_Z]\n", |
| 822 | " t = impl_isa[T]\n", |
| 823 | "\n", |
| 824 | " # Syndrome extraction time from the physical ISA\n", |
| 825 | " syndrome_extraction_time = (\n", |
| 826 | " 4 * cnot.expect_time() + h.expect_time() + meas_z.expect_time()\n", |
| 827 | " )\n", |
| 828 | "\n", |
| 829 | " for error_rate, base_space, base_cycles in _LITINSKI_TABLE:\n", |
| 830 | " # Apply scaling factors to space and time\n", |
| 831 | " space = ceil(base_space * self.space_factor)\n", |
| 832 | " time = ceil(syndrome_extraction_time * base_cycles * self.cycle_factor)\n", |
| 833 | "\n", |
| 834 | " yield ctx.make_isa(\n", |
| 835 | " ctx.add_instruction(\n", |
| 836 | " T,\n", |
| 837 | " encoding=LOGICAL,\n", |
| 838 | " arity=1,\n", |
| 839 | " space=space,\n", |
| 840 | " time=time,\n", |
| 841 | " error_rate=error_rate,\n", |
| 842 | " transform=self,\n", |
| 843 | " source=[cnot, h, meas_z, t],\n", |
| 844 | " ),\n", |
| 845 | " )" |
| 846 | ] |
| 847 | }, |
| 848 | { |
| 849 | "cell_type": "markdown", |
| 850 | "id": "739582e7", |
| 851 | "metadata": {}, |
| 852 | "source": [ |
| 853 | "### What if the factory were more compact or faster?\n", |
| 854 | "\n", |
| 855 | "Let's compare three scenarios, all using the built-in `SurfaceCode` for QEC:\n", |
| 856 | "\n", |
| 857 | "- **Litinski baseline:** the built-in `Litinski19Factory` (our reference).\n", |
| 858 | "- **Compact factory:** `space_factor=0.5`: the factory uses half the physical\n", |
| 859 | " qubits (perhaps due to better routing or a denser layout).\n", |
| 860 | "- **Fast factory:** `cycle_factor=0.5`: the factory completes in half the\n", |
| 861 | " cycles (perhaps due to a faster syndrome extraction scheme)." |
| 862 | ] |
| 863 | }, |
| 864 | { |
| 865 | "cell_type": "code", |
| 866 | "execution_count": 10, |
| 867 | "id": "1de231fb", |
| 868 | "metadata": {}, |
| 869 | "outputs": [ |
| 870 | { |
| 871 | "data": { |
| 872 | "image/png": "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RPRsGBgYPPWV5hIMzkREVOfJ5fIq+xcnET2/eHMgEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkwVMHZ6VSCYVCgTt37lRFPURERERENZLWwXnixIlYt24dgIehuXPnzmjZsiXc3d0RGxtb1fUREREREdUIWgfnn3/+Gf7+/gCA3377DSkpKTh//jwmTZqEDz/8sMoLJCIiIiKqCbQOzllZWXBycgIA7Nq1C/3790fjxo3xzjvv4MyZM1VeYE1QWFgIT09PTJkyRdelEBEREZGOaB2cHR0dkZiYCKVSiejoaLz88ssAHoZLuVxe5QXWBPPmzcMLL7yg6zKIiIiISIe0Ds7Dhw/HgAED0Lx5c8hkMgQFBQEAjh49iiZNmlR5gbp28eJFnD9/HiEhIbouhYiIiIh0SOvgPGfOHHz33XcYNWoUDh8+DCMjIwCAXC7HjBkzqrzAp3Hw4EGEhobCxcUFMpkMO3bsKNVn5cqV8PLygrGxMdq1a4djx45pbJ8yZQoWLFjwjComIiIioppK6+C8YcMGhIaGYtKkSXBzc1O3v/XWW8jJyanS4p5WQUEB/P39sXLlyjK3R0VFYfLkyZg9ezZOnjwJf39/BAcHIzMzEwDwyy+/oHHjxmjcuLGk+e7du4fc3FyNFxERERHVDTIhhNBmB7lcjrS0NDg4OGi0//vvv3BwcIBSqazSAquKTCbD9u3b0bdvX3Vbu3bt0KZNG6xYsQIAoFKp4O7ujnHjxmHGjBmY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+N3oukmb3z4nIiIiomdPm7xWY9Y4ExERERHVZAzOREREREQSMDgTEREREUnA4ExEREREJAGDMxERERGRBAzOtVze/TykF6SXuS29IB159/OecUVEREREdRODcy2Wdz8P7+59F8Ojh5cKz+kF6RgePRzv7n2X4ZmIiIioCjA412IFxQW4XXQb1/Ova4TnktB8Pf86bhfdRkFxgY4rJSIiIqr9GJxrMSczJ0T0jICbuZs6PCsyFerQ7GbuhoieEXAyc9J1qURERES1Hn85sBo9q18OfPQKcwmGZiIiIqIn4y8HPmeczJywoNMCjbYFnRYwNBMRERFVIQbnOiC9IB0z/5qp0Tbzr5nlPm2DiIiIiLTH4FzLPbpMw83cDRtDNmqseWZ4JiIiIqoaDM612OOhOaJnBAIcAkrdMMjwTERERPT0GJxrMTMDM9iY2JS6EfDRp23YmNjAzMBMx5USERER1X58qkY1ehZP1ci7n4eC4oIybwRML0iHmYEZLAwtqmVuIiIiotpOm7ym/4xqompiYWhRbjDmUzWIiIiIqg6XahARERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREelUXu4NpKcrytyWnq5AXu6NZ1tQORiciYiIiEhn8nJv4N2toRi+awjS005pbEtPO4Xhu4bg3a2hNSI8MzgTERERkc4UFN7CbVGM63Jg+B9D1eE5Pe0Uhv8xFNflwG1RjILCWzqulMGZiIiIiHTIySkAESEb4KaEOjwrzvygDs1uSiAiZAOcnAJ0XSqDMxERERHplpNzoEZ4HnJyoWZodg7UdYkAGJyJiIiIqAZwcg7EgjYzNNoWtJlRY0IzwOBMRERERDVAetopzDy+UKNt5vGFpW4Y1CUGZyIiIiLSqUdvBHRTAhtbztBY81xTwjODMxERERHpTHq6otSNgAEtBpe6YbC85zw/SwzORERERKQzZqb2sJEZlLoR8NEbBm1kBjAztddxpYBMCCF0XURdlZubCysrK+Tk5MDS0lLX5RARERHVSHm5N1BQeKvMR86lpytgZmoPC0vXaplbm7ymXy0VEBERERFJZGHpWm4wrgnPby7BpRpERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBIwOBMRERERScDgTEREREQkAYMzEREREZEEDM5ERERERBLwlwOrUcmvmefm5uq4EiIiIiIqS0lOK8ltFWFwrkZ5eXkAAHd3dx1XQkREREQVycvLg5WVVYV9ZEJKvKZKUalUuHnzJiwsLCCTyapkzDZt2uD48eNVMhZRZfAcpMrgefP84rGvO+rqsRRCIC8vDy4uLtDTq3gVM684VyM9PT24ublV6ZhyuRyWlpZVOiaRNngOUmXwvHl+8djXHXX5WD7pSnMJ3hxYy4SHh+u6BHrO8RykyuB58/zisa87eCy5VIOIiIiISBJecSYiIiIikoDBmYiIiIhIAgZnIiIiIiIJGJyJiIiIiCRgcCYiIiIikoDBmSR77bXXUK9ePbzxxhu6LoWeUzwHSVs8Z+o2Ht/nQ006zgzOJNmECROwYcMGXZdBzzGeg6QtnjN1G4/v86EmHWcGZ5KsS5cusLCw0HUZ9BzjOUja4jlTt/H4Ph9q0nFmcJbo4MGDCA0NhYuLC2QyGXbs2KHV/gsXLoRMJsPEiRN1UtvKlSvh5eUFY2NjtGvXDseOHavyOqh6VfYcvHHjBt5++23Y2trCxMQELVq0wIkTJ555bTwHdUPb80apVOLjjz+Gt7c3TExM0KBBA3z22Weo6t/KkloXz5uqt2DBArRp0wYWFhZwcHBA3759kZSUVKVz8PhWLW2P2bM4xsDzeZwZnCUqKCiAv78/Vq5cqfW+x48fxzfffAM/P78K+x0+fBjFxcWl2hMTE5GRkVHp2qKiojB58mTMnj0bJ0+ehL+/P4KDg5GZmanuExAQgObNm5d63bx5U+KnpOpWmXPwzp076NixIwwMDPDHH38gMTERixcvRr169crsz3Ow7tH2vFm0aBFWr16NFStW4Ny5c1i0aBE+//xzLF++vNx9KnPeSKmL5031OHDgAMLDw3HkyBHs2bMHxcXF6NGjBwoKCsrsz+Ore9oeM237AzzOkgnSGgCxfft2SX3z8vJEo0aNxJ49e0Tnzp3FhAkTyuynVCqFv7+/eOONN8SDBw/U7efPnxeOjo5i0aJFla6tbdu2Ijw8XGMuFxcXsWDBAkljPmr//v3i9ddf13o/qlpSz8Hp06eLF198UdKYPAfrPinnTe/evcU777yj0davXz8xePDgMvtXxXlTXl1Vdd7wnKlYZmamACAOHDhQahuPb81U0TGrTH8eZ+l4xbmahYeHo3fv3ggKCqqwn56eHnbt2oVTp05h6NChUKlUSE5ORrdu3dC3b19MmzatUvPfv38f8fHxGvPr6ekhKCgIcXFxlRqTao9ff/0VrVu3Rv/+/eHg4IDAwECsXbu2zL48BwkAOnTogJiYGFy4cAEAkJCQgEOHDiEkJKTM/jxvar+cnBwAgI2NTaltPL41U0XHrDL9eZyl09d1AXXZf//7X5w8eRLHjx+X1N/FxQX79u1Dp06dMGjQIMTFxSEoKAirV6+udA1ZWVlQKpVwdHTUaHd0dMT58+e1GisoKAgJCQkoKCiAm5sbfvrpJ7Rv377StVH1u3z5MlavXo3Jkyfjgw8+wPHjxzF+/HgYGhoiLCysVH+egzRjxgzk5uaiSZMmkMvlUCqVmDdvHgYPHlzuPjX5vOE5UzGVSoWJEyeiY8eOaN68eZl9eHxrFinHrDL9eZylYXCuJteuXcOECROwZ88eGBsbS97Pw8MDGzduROfOnVG/fn2sW7cOMpmsGiuVbu/evbougbSkUqnQunVrzJ8/HwAQGBiIf/75B2vWrCkzOAM8B593W7ZswQ8//IDNmzejWbNmUCgUmDhxIlxcXMo9Z4Cae97wnKlYeHg4/vnnHxw6dKjCfjy+NYfUY1aZ/jzOT8alGtUkPj4emZmZaNmyJfT19aGvr48DBw5g2bJl0NfXh1KpLHO/jIwMjBo1CqGhoSgsLMSkSZOeqg47OzvI5fJSC/szMjLg5OT0VGNTzefs7AxfX1+NtqZNmyI1NbXcfXgOPt+mTp2KGTNm4M0330SLFi0wZMgQTJo0CQsWLKhwP543tc/YsWOxc+dO7N+/H25ubhX25fGtGbQ5ZpXpz+P8ZAzO1aR79+44c+YMFAqF+tW6dWsMHjwYCoUCcrm81D5ZWVno3r07mjZtim3btiEmJgZRUVGYMmVKpeswNDREq1atEBMTo25TqVSIiYmp8/85i4COHTuWegTRhQsX4OnpWWZ/noNUWFgIPT3NfzXI5XKoVKpy9+F5U7sIITB27Fhs374d+/btg7e3d4X9eXx1T9tjpm1/gMdZMh3fnFhr5OXliVOnTolTp04JAOKrr74Sp06dElevXhVCCLF8+XLRrVu3Csd40lM1WrduLXr16iXu3bunblcoFMLGxkZ89dVXla7tv//9rzAyMhKRkZEiMTFRjBo1SlhbW4v09HQtvwXSpcqcg8eOHRP6+vpi3rx54uLFi+KHH34QpqamYtOmTaXG5zlYN2l73oSFhQlXV1exc+dOkZKSIrZt2ybs7OzEtGnTyhy/sufNk+oSgudNdRkzZoywsrISsbGxIi0tTf0qLCws1ZfHt2Z40jF7/J9jbY6xEDzO2mBwlmj//v0CQKlXWFiYEEKI2bNnC09PzwrHqCg4CyHE7t27RVFRUan2kydPimvXrlW6NiEe/kPl4eEhDA0NRdu2bcWRI0cqrJVqnsqeg7/99pto3ry5MDIyEk2aNBHffvttuXPwHKx7tD1vcnNzxYQJE4SHh4cwNjYW9evXFx9++KHGv0wfV5nzRso5IwTPm+pQ1vcOQERERJTZn8dX9550zB7/51jbYywEj7NUMiGq+OegiIiIiIjqIK5xJiIiIiKSgMGZiIiIiEgCBmciIiIiIgkYnImIiIiIJGBwJiIiIiKSgMGZiIiIiEgCBmciIiIiIgkYnImIiIiIJGBwJiIiIiKSgMGZiOg51aVLF0ycOFFn87/00kvYvHlztY0fHR2NgIAAqFSqapuDiJ4vDM5ERDoybNgwyGQyyGQyGBgYwNvbG9OmTcPdu3erdJ7Y2FjIZDJkZ2drtG/btg2fffZZlc4l1a+//oqMjAy8+eab1TZHz549YWBggB9++KHa5iCi5wuDMxGRDvXs2RNpaWm4fPkylixZgm+++QazZ89+JnPb2NjAwsLimcz1uGXLlmH48OHQ06vefw0NGzYMy5Ytq9Y5iOj5weBMRKRDRkZGcHJygru7O/r27YugoCDs2bNHvd3LywtLly7V2CcgIABz5sxRv5fJZPjuu+/w2muvwdTUFI0aNcKvv/4KALhy5Qq6du0KAKhXrx5kMhmGDRsGoPRSDS8vL8ydOxdDhw6Fubk5PD098euvv+LWrVvo06cPzM3N4efnhxMnTmjUc+jQIXTq1AkmJiZwd3fH+PHjUVBQUO5nvnXrFvbt24fQ0FCNdplMhm+++QavvPIKTE1N0bRpU8TFxeHSpUvo0qULzMzM0KFDByQnJ6v3SUhIQNeuXWFhYQFLS0u0atVKo77Q0FCcOHFCYx8iospicCYiqiH++ecf/P333zA0NNR6308++QQDBgzA6dOn0atXLwwePBi3b9+Gu7s7tm7dCgBISkpCWloavv7663LHWbJkCTp27IhTp06hd+/eGDJkCIYOHYq3334bJ0+eRIMGDTB06FAIIQAAycnJ6NmzJ15//XWcPn0aUVFROHToEMaOHVvuHIcOHVIH48d99tlnGDp0KBQKBZo0aYJBgwZh9OjRmDlzJk6cOAEhhMbYgwcPhpubG44fP474+HjMmDEDBgYG6u0eHh5wdHTEX3/9pfV3SkT0OAZnIiId2rlzJ8zNzWFsbIwWLVogMzMTU6dO1XqcYcOG4a233kLDhg0xf/585Ofn49ixY5DL5bCxsQEAODg4wMnJCVZWVuWO06tXL4wePRqNGjXCrFmzkJubizZt2qB///5o3Lgxpk+fjnPnziEjIwMAsGDBAgwePBgTJ05Eo0aN0KFDByxbtgwbNmwod6321atX4ejoWOYyjeHDh2PAgAHqua5cuYLBgwcjODgYTZs2xYQJExAbG6vun5qaiqCgIDRp0gSNGjVC//794e/vrzGmi4sLrl69qu1XSkRUCoMzEZEOde3aFQqFAkePHkVYWBiGDx+O119/Xetx/Pz81P/fzMwMlpaWyMzMfKpxHB0dAQAtWrQo1VYydkJCAiIjI2Fubq5+BQcHQ6VSISUlpcw5ioqKYGxsXOn57969i9zcXADA5MmTMWLECAQFBWHhwoVlLskwMTFBYWHhkz88EdETMDgTEemQmZkZGjZsCH9/f3z//fc4evQo1q1bp96up6enXhZRori4uNQ4jy5PAB6uF67MY9geHUcmk5XbVjJ2fn4+Ro8eDYVCoX4lJCTg4sWLaNCgQZlz2NnZ4c6dO1Uy/5w5c3D27Fn07t0b+/btg6+vL7Zv364x5u3bt2Fvby/h0xMRVYzBmYiohtDT08MHH3yAjz76CEVFRQAAe3t7pKWlqfvk5uaWeyW3PCVrppVKZdUV+/9atmyJxMRENGzYsNSrvLXagYGBSE9PLzc8a6tx48aYNGkSdu/ejX79+iEiIkK97e7du0hOTkZgYGCVzEVEzzcGZyKiGqR///6Qy+VYuXIlAKBbt27YuHEj/vrrL5w5cwZhYWGQy+Vajenp6QmZTIadO3fi1q1byM/Pr7J6p0+fjr///htjx46FQqHAxYsX8csvv1R4c2BgYCDs7Oxw+PDhp5q7qKgIY8eORWxsLK5evYrDhw/j+PHjGjcdHjlyBEZGRmjfvv1TzUVEBDA4ExHVKPr6+hg7diw+//xzFBQUYObMmejcuTNeeeUV9O7dG3379i13CUR5XF1d8cknn2DGjBlwdHSsMNRqy8/PDwcOHMCFCxfQqVMnBAYGYtasWXBxcSl3H7lcjuHDhz/1D5PI5XL8+++/GDp0KBo3bowBAwYgJCQEn3zyibrPjz/+iMGDB8PU1PSp5iIiAgCZeHzxHBERUTVLT09Hs2bNcPLkSXh6elbLHFlZWfDx8cGJEyfg7e1dLXMQ0fOFV5yJiOiZc3Jywrp165Camlptc1y5cgWrVq1iaCaiKsMrzkREREREEvCKMxERERGRBAzOREREREQSMDgTEREREUnA4ExEREREJAGDMxERERGRBAzOREREREQSMDgTEREREUnA4ExEREREJAGDMxERERGRBP8HQrGcbLaQKyEAAAAASUVORK5CYII=", |
| 873 | "text/plain": [ |
| 874 | "<Figure size 800x500 with 1 Axes>" |
| 875 | ] |
| 876 | }, |
| 877 | "execution_count": 10, |
| 878 | "metadata": {}, |
| 879 | "output_type": "execute_result" |
| 880 | } |
| 881 | ], |
| 882 | "source": [ |
| 883 | "arch = GateBased(error_rate=1e-4, gate_time=100, measurement_time=500)\n", |
| 884 | "\n", |
| 885 | "# Litinski baseline (unscaled, should closely match built-in Litinski19Factory)\n", |
| 886 | "litinski_baseline = SurfaceCode.q() * ScaledLitinskiFactory.q()\n", |
| 887 | "\n", |
| 888 | "# Compact factory: half the physical qubits\n", |
| 889 | "compact = SurfaceCode.q() * ScaledLitinskiFactory.q(space_factor=0.5)\n", |
| 890 | "\n", |
| 891 | "# Fast factory: half the cycles\n", |
| 892 | "fast = SurfaceCode.q() * ScaledLitinskiFactory.q(cycle_factor=0.5)\n", |
| 893 | "\n", |
| 894 | "results = [\n", |
| 895 | " estimate(app, arch, litinski_baseline, max_error=0.01, name=\"Litinski baseline\"),\n", |
| 896 | " estimate(app, arch, compact, max_error=0.01, name=\"Compact factory (0.5× space)\"),\n", |
| 897 | " estimate(app, arch, fast, max_error=0.01, name=\"Fast factory (0.5× cycles)\"),\n", |
| 898 | " baseline,\n", |
| 899 | "]\n", |
| 900 | "\n", |
| 901 | "plot_estimates(results, figsize=(8, 5), runtime_unit=\"ms\")" |
| 902 | ] |
| 903 | }, |
| 904 | { |
| 905 | "cell_type": "markdown", |
| 906 | "id": "c5da8f59", |
| 907 | "metadata": {}, |
| 908 | "source": [ |
| 909 | "## Composing a full custom stack\n", |
| 910 | "\n", |
| 911 | "Now that we have all three custom layers, let's compose them into a complete\n", |
| 912 | "estimation stack. The `*` operator creates a Cartesian product over all\n", |
| 913 | "hyperparameter configurations:\n", |
| 914 | "\n", |
| 915 | "- `GenericQEC` searches over code distances 3–21\n", |
| 916 | "- `ScaledLitinskiFactory` produces multiple factory configurations from\n", |
| 917 | " the Litinski protocol table\n", |
| 918 | "\n", |
| 919 | "The estimator evaluates all combinations and returns only the Pareto-optimal\n", |
| 920 | "results." |
| 921 | ] |
| 922 | }, |
| 923 | { |
| 924 | "cell_type": "code", |
| 925 | "execution_count": 11, |
| 926 | "id": "bba890f4", |
| 927 | "metadata": {}, |
| 928 | "outputs": [ |
| 929 | { |
| 930 | "data": { |
| 931 | "text/html": [ |
| 932 | "<div>\n", |
| 933 | "<style scoped>\n", |
| 934 | " .dataframe tbody tr th:only-of-type {\n", |
| 935 | " vertical-align: middle;\n", |
| 936 | " }\n", |
| 937 | "\n", |
| 938 | " .dataframe tbody tr th {\n", |
| 939 | " vertical-align: top;\n", |
| 940 | " }\n", |
| 941 | "\n", |
| 942 | " .dataframe thead th {\n", |
| 943 | " text-align: right;\n", |
| 944 | " }\n", |
| 945 | "</style>\n", |
| 946 | "<table border=\"1\" class=\"dataframe\">\n", |
| 947 | " <thead>\n", |
| 948 | " <tr style=\"text-align: right;\">\n", |
| 949 | " <th></th>\n", |
| 950 | " <th>name</th>\n", |
| 951 | " <th>qubits</th>\n", |
| 952 | " <th>runtime</th>\n", |
| 953 | " <th>error</th>\n", |
| 954 | " <th>physical_compute_qubits</th>\n", |
| 955 | " <th>physical_factory_qubits</th>\n", |
| 956 | " <th>physical_memory_qubits</th>\n", |
| 957 | " <th>factories</th>\n", |
| 958 | " </tr>\n", |
| 959 | " </thead>\n", |
| 960 | " <tbody>\n", |
| 961 | " <tr>\n", |
| 962 | " <th>0</th>\n", |
| 963 | " <td>Full custom stack</td>\n", |
| 964 | " <td>3151</td>\n", |
| 965 | " <td>0 days 00:00:00.000299</td>\n", |
| 966 | " <td>0.006790</td>\n", |
| 967 | " <td>3150</td>\n", |
| 968 | " <td>1</td>\n", |
| 969 | " <td>0</td>\n", |
| 970 | " <td>1×T</td>\n", |
| 971 | " </tr>\n", |
| 972 | " <tr>\n", |
| 973 | " <th>1</th>\n", |
| 974 | " <td>Full custom stack</td>\n", |
| 975 | " <td>9630</td>\n", |
| 976 | " <td>0 days 00:00:00.000292500</td>\n", |
| 977 | " <td>0.007312</td>\n", |
| 978 | " <td>3150</td>\n", |
| 979 | " <td>6480</td>\n", |
| 980 | " <td>0</td>\n", |
| 981 | " <td>8×T</td>\n", |
| 982 | " </tr>\n", |
| 983 | " <tr>\n", |
| 984 | " <th>2</th>\n", |
| 985 | " <td>Full custom stack</td>\n", |
| 986 | " <td>13284</td>\n", |
| 987 | " <td>0 days 00:00:00.000183300</td>\n", |
| 988 | " <td>0.009416</td>\n", |
| 989 | " <td>1134</td>\n", |
| 990 | " <td>12150</td>\n", |
| 991 | " <td>0</td>\n", |
| 992 | " <td>15×T</td>\n", |
| 993 | " </tr>\n", |
| 994 | " </tbody>\n", |
| 995 | "</table>\n", |
| 996 | "</div>" |
| 997 | ], |
| 998 | "text/plain": [ |
| 999 | " name qubits runtime error \\\n", |
| 1000 | "0 Full custom stack 3151 0 days 00:00:00.000299 0.006790 \n", |
| 1001 | "1 Full custom stack 9630 0 days 00:00:00.000292500 0.007312 \n", |
| 1002 | "2 Full custom stack 13284 0 days 00:00:00.000183300 0.009416 \n", |
| 1003 | "\n", |
| 1004 | " physical_compute_qubits physical_factory_qubits physical_memory_qubits \\\n", |
| 1005 | "0 3150 1 0 \n", |
| 1006 | "1 3150 6480 0 \n", |
| 1007 | "2 1134 12150 0 \n", |
| 1008 | "\n", |
| 1009 | " factories \n", |
| 1010 | "0 1×T \n", |
| 1011 | "1 8×T \n", |
| 1012 | "2 15×T " |
| 1013 | ] |
| 1014 | }, |
| 1015 | "execution_count": 11, |
| 1016 | "metadata": {}, |
| 1017 | "output_type": "execute_result" |
| 1018 | } |
| 1019 | ], |
| 1020 | "source": [ |
| 1021 | "# Full custom stack: custom architecture + custom QEC + custom factory\n", |
| 1022 | "custom_arch = ParameterizedArchitecture(\n", |
| 1023 | " single_qubit_gate_time=100,\n", |
| 1024 | " two_qubit_gate_time=200,\n", |
| 1025 | " measurement_time=400,\n", |
| 1026 | " single_qubit_error_rate=5e-5,\n", |
| 1027 | " two_qubit_error_rate=1e-4,\n", |
| 1028 | " measurement_error_rate=1e-4,\n", |
| 1029 | ")\n", |
| 1030 | "\n", |
| 1031 | "custom_results = estimate(\n", |
| 1032 | " app, custom_arch,\n", |
| 1033 | " isa_query=GenericQEC.q() * ScaledLitinskiFactory.q(),\n", |
| 1034 | " max_error=0.01,\n", |
| 1035 | " name=\"Full custom stack\",\n", |
| 1036 | ")\n", |
| 1037 | "\n", |
| 1038 | "custom_results.add_qubit_partition_column()\n", |
| 1039 | "custom_results.add_factory_summary_column()\n", |
| 1040 | "custom_results.as_frame()" |
| 1041 | ] |
| 1042 | }, |
| 1043 | { |
| 1044 | "cell_type": "markdown", |
| 1045 | "id": "3ce953fa", |
| 1046 | "metadata": {}, |
| 1047 | "source": [ |
| 1048 | "> **Why does the first result show only 1 factory qubit?**\n", |
| 1049 | ">\n", |
| 1050 | "> When the physical T-gate error rate is low enough, the estimator may find that\n", |
| 1051 | "> it can meet the overall error budget *without* distillation, using the raw\n", |
| 1052 | "> physical T gate directly. In that case the \"factory\" is just a single physical\n", |
| 1053 | "> qubit producing T states one at a time, which is why the qubit count is so\n", |
| 1054 | "> small. The trade-off is a much longer runtime (thousands of serial T-gate\n", |
| 1055 | "> executions instead of a few batched factory runs). Subsequent rows in the\n", |
| 1056 | "> table use the `ScaledLitinskiFactory` and show the more typical pattern of\n", |
| 1057 | "> dedicating thousands of physical qubits to a distillation factory in exchange\n", |
| 1058 | "> for faster execution." |
| 1059 | ] |
| 1060 | }, |
| 1061 | { |
| 1062 | "cell_type": "code", |
| 1063 | "execution_count": 12, |
| 1064 | "id": "c65d0684", |
| 1065 | "metadata": {}, |
| 1066 | "outputs": [ |
| 1067 | { |
| 1068 | "data": { |
| 1069 | "image/png": "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", |
| 1070 | "text/plain": [ |
| 1071 | "<Figure size 800x500 with 1 Axes>" |
| 1072 | ] |
| 1073 | }, |
| 1074 | "execution_count": 12, |
| 1075 | "metadata": {}, |
| 1076 | "output_type": "execute_result" |
| 1077 | } |
| 1078 | ], |
| 1079 | "source": [ |
| 1080 | "plot_estimates([custom_results, baseline], figsize=(8, 5), runtime_unit=\"ms\")" |
| 1081 | ] |
| 1082 | }, |
| 1083 | { |
| 1084 | "cell_type": "markdown", |
| 1085 | "id": "ae29b99a", |
| 1086 | "metadata": {}, |
| 1087 | "source": [ |
| 1088 | "## Key takeaways\n", |
| 1089 | "\n", |
| 1090 | "1. **Three extension points.** The estimator's model stack has three layers:\n", |
| 1091 | " `Architecture`, QEC `ISATransform`, and factory `ISATransform`, each of\n", |
| 1092 | " which can be replaced independently.\n", |
| 1093 | "\n", |
| 1094 | "2. **Implement two methods.** Every custom QEC or factory model is a dataclass\n", |
| 1095 | " that implements `required_isa` (what physical instructions it needs) and\n", |
| 1096 | " `provided_isa` (what logical instructions it provides, with resource\n", |
| 1097 | " formulas). A custom architecture implements only `provided_isa`.\n", |
| 1098 | "\n", |
| 1099 | "3. **Automatic search.** Mark hyperparameters as `KW_ONLY` fields with a\n", |
| 1100 | " `metadata={\"domain\": ...}` and the estimator searches over them\n", |
| 1101 | " automatically, keeping only the Pareto-optimal configurations.\n", |
| 1102 | "\n", |
| 1103 | "4. **Mix and match.** Custom models compose freely with built-in ones using the\n", |
| 1104 | " `*` operator. You can replace one layer while keeping the others at their\n", |
| 1105 | " defaults, which is useful for isolating the effect of a single modeling choice.\n", |
| 1106 | "\n", |
| 1107 | "5. **Provenance tracking.** Pass `transform=self` and `source=[...]` when\n", |
| 1108 | " adding instructions to preserve the link between physical and logical\n", |
| 1109 | " instructions. This lets you inspect the full derivation chain in the\n", |
| 1110 | " results (see [Analysing Results](2_analysing_results.ipynb))." |
| 1111 | ] |
| 1112 | } |
| 1113 | ], |
| 1114 | "metadata": { |
| 1115 | "kernelspec": { |
| 1116 | "display_name": ".venv", |
| 1117 | "language": "python", |
| 1118 | "name": "python3" |
| 1119 | }, |
| 1120 | "language_info": { |
| 1121 | "codemirror_mode": { |
| 1122 | "name": "ipython", |
| 1123 | "version": 3 |
| 1124 | }, |
| 1125 | "file_extension": ".py", |
| 1126 | "mimetype": "text/x-python", |
| 1127 | "name": "python", |
| 1128 | "nbconvert_exporter": "python", |
| 1129 | "pygments_lexer": "ipython3", |
| 1130 | "version": "3.11.14" |
| 1131 | } |
| 1132 | }, |
| 1133 | "nbformat": 4, |
| 1134 | "nbformat_minor": 5 |
| 1135 | } |
| 1136 | |