{ "cells": [ { "cell_type": "markdown", "id": "0", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "# Logical Error Rate Evaluation" ] }, { "cell_type": "code", "execution_count": 1, "id": "1", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [ "parameters" ] }, "outputs": [], "source": [ "# This cell is tagged `parameters` and will be override by `papermill`\n", "# all `=` should be replaced by `@` in the string, otherwise papermill won't be able to parse them\n", "decoder_eval: str = '\"mwpm\"'\n", "code_eval: str = 'f\"rsc(d@{c.d},p@{p})\"'\n", "noise_eval: str = '\"none\"'\n", "config_vec_eval: str = '[dmap(d@3), dmap(d@5), dmap(d@7), dmap(d@9), dmap(d@11)]'\n", "\n", "p_center: float = 0.01 # this p value is choosen such that the logical error rate is not too high or too low\n", "per10_p_count: int = 3 # how many p to take per x10 interval\n", "p_bias: int = 0 # the center p will be adjusted to p_center * (10 ** (p_bias / per10_p_count))\n", "\n", "slurm_maximum_jobs = 30 # start with a smaller number of workers to avoid resource waste\n", "slurm_cores_per_node: int = 10 # (slurm_maximum_jobs // slurm_cores_per_node) should not exceed 200\n", "slurm_mem_per_job: int = 2 # 2GB per job\n", "slurm_extra = dict(\n", " walltime = \"1-00:00:00\", # adaptively shutdown if no more jobs\n", " queue = \"scavenge\", # use with caution: dask does not seem to handle scavenge workers well\n", " job_extra_directives = [\"--requeue\"], # use with scavenge partition will help spawn scavenged jobs\n", ")\n", "\n", "import multiprocessing\n", "local_maximum_jobs = multiprocessing.cpu_count()\n", "# local_maximum_jobs = 10\n", "\n", "json_filename: str | None = None\n", "force_finished: bool = False # only plot the figure and do not run experiments" ] }, { "cell_type": "code", "execution_count": 2, "id": "2", "metadata": {}, "outputs": [], "source": [ "# to get around papermill limitation: there cannot be = character in the string\n", "decoder_eval = decoder_eval.replace(\"@\", \"=\")\n", "code_eval = code_eval.replace(\"@\", \"=\")\n", "noise_eval = noise_eval.replace(\"@\", \"=\")\n", "config_vec_eval = config_vec_eval.replace(\"@\", \"=\")" ] }, { "cell_type": "code", "execution_count": null, "id": "3", "metadata": {}, "outputs": [], "source": [ "from slugify import slugify\n", "from dotmap import DotMap as dmap\n", "\n", "config_vec = eval(config_vec_eval)\n", "print(config_vec)\n", "\n", "if json_filename is None:\n", " json_filename = \"zdat-\" + slugify(code_eval) + \".\" + slugify(noise_eval) + \".\" + slugify(decoder_eval) + \".json\"\n", "print(json_filename)" ] }, { "cell_type": "code", "execution_count": 4, "id": "4", "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", "execution_count": 5, "id": "5", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "from qec_lego_bench.hpc.monte_carlo import *\n", "from qec_lego_bench.hpc.submitter import *\n", "from qec_lego_bench.hpc.plotter import *\n", "from typing import Iterable\n", "from qec_lego_bench.cli.logical_error_rate import logical_error_rate" ] }, { "cell_type": "markdown", "id": "6", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "### Define the job list" ] }, { "cell_type": "code", "execution_count": null, "id": "7", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "ap_vec = AdaptivePVec(p_center=p_center, per10_p_count=per10_p_count, p_bias=p_bias)\n", "jobs = [MonteCarloJob(config=config, p=ap_vec.biased_p_center) for config in config_vec]\n", "\n", "\n", "def monte_carlo_function(\n", " shots: int, config: dmap, p: float\n", ") -> tuple[int, LogicalErrorResult]:\n", " c = config\n", " decoder = eval(decoder_eval)\n", " code = eval(code_eval)\n", " noise = eval(noise_eval)\n", " stats = logical_error_rate(\n", " decoder=decoder,\n", " code=code,\n", " noise=noise,\n", " max_shots=shots,\n", " max_errors=shots,\n", " no_progress=True,\n", " no_print=True,\n", " )\n", " return stats.shots, LogicalErrorResult.from_stats(stats)\n", "\n", "print(ap_vec.biased_p_center, monte_carlo_function(1000, config_vec[0], ap_vec.biased_p_center))" ] }, { "cell_type": "markdown", "id": "8", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "### Define the strategy to submit jobs" ] }, { "cell_type": "code", "execution_count": 7, "id": "9", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "adaptive_submitter = AdaptivePVecSubmitter(\n", " config_vec=config_vec,\n", " ap_vec=ap_vec,\n", " time_limit=3600,\n", " min_shots=1000,\n", " target_precision=0.1,\n", ")\n", "precision_submitter = PrecisionSubmitter(\n", " time_limit=100 * 3600, min_precision=1, target_precision=0.03\n", ")\n", "\n", "\n", "def submitter(executor: MonteCarloJobExecutor) -> list[tuple[MonteCarloJob, int]]:\n", " submit = adaptive_submitter(executor)\n", " if len(submit) == 0 and executor.no_pending(): # previous submitter all finished\n", " submit += precision_submitter(executor)\n", " return submit" ] }, { "cell_type": "markdown", "id": "10", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "## The rest of the notebook runs the evaluation" ] }, { "cell_type": "markdown", "id": "11", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "source": [ "Start a cluster by intelligently choose Slurm or Local cluster." ] }, { "cell_type": "code", "execution_count": null, "id": "12", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "client_connector = SlurmClientConnector(\n", " slurm_maximum_jobs=slurm_maximum_jobs,\n", " slurm_cores_per_node=slurm_cores_per_node,\n", " slurm_mem_per_job=slurm_mem_per_job,\n", " slurm_extra=slurm_extra,\n", ")" ] }, { "cell_type": "code", "execution_count": 9, "id": "13", "metadata": {}, "outputs": [], "source": [ "config = MonteCarloExecutorConfig()\n", "config.max_submitted_job = max(config.max_submitted_job, 3 * slurm_maximum_jobs)\n", "executor = MonteCarloJobExecutor(\n", " monte_carlo_function,\n", " jobs,\n", " config=config,\n", " filename=json_filename,\n", ")" ] }, { "cell_type": "markdown", "id": "14", "metadata": {}, "source": [ "### Define the callback, e.g. plotting the intermediate result and the list of remaining tasks\n", "\n", "(I have to put them in the same block as the actual execution, otherwise it won't update in VScode)" ] }, { "cell_type": "code", "execution_count": null, "id": "15", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "import time # add some sleep to let them work properly in VScode Jupyter notebook\n", "\n", "time.sleep(0.2)\n", "plotter = AdaptivePVecPlotter(config_vec=config_vec, ap_vec=ap_vec)\n", "time.sleep(0.2)\n", "progress_plotter = JobProgressPlotter()\n", "time.sleep(0.2)\n", "memory_plotter = MemoryUsagePlotter()\n", "time.sleep(0.2)\n", "\n", "\n", "def callback(executor: MonteCarloJobExecutor):\n", " plotter(executor)\n", " time.sleep(0.1)\n", " progress_plotter(executor)\n", " time.sleep(0.1)\n", " memory_plotter(executor)\n", " time.sleep(0.1)\n", "\n", "print(\n", " \"will shut down the cluster after job finishes; if this is not desired, set `shutdown_cluster` to False\"\n", ")\n", "\n", "executor.execute(\n", " client_connector=client_connector,\n", " submitter=submitter,\n", " loop_callback=callback,\n", " shutdown_cluster=True,\n", " force_finished=force_finished,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "16", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "base", "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.11.6" } }, "nbformat": 4, "nbformat_minor": 5 }