{ "cells": [ { "cell_type": "markdown", "id": "6f4c1137-c025-4295-a669-a113bc6d763a", "metadata": {}, "source": [ "# CutQC2 zarr file format\n", "\n", "All relevant information during `Cutqc2` processing - the original circuit specification, cut locations, subcircuit probability values, and the final reconstructed probabilities - are stored in a single [zarr](https://zarr.readthedocs.io/en/stable/quickstart.html) file.\n", "A zarr file is a directory containing multiple json files and binary data files, can be stored on disk or in cloud storage, allows for efficient access to subsets of the data without loading everything into memory,\n", "as well as parallel read and write operations. It can be accessed from Python, C++ and Rust, among other languages.\n", "\n", "See a detailed description of the Zarr format [here](https://zarr.dev/)\n", "\n", "## Creating the zarr file\n", "\n", "If we look at the `supremacy_6qubit.sh` script in the `examples/scripts` folder, it has a command to generate and cut a 6 qubit supremacy circuit." ] }, { "cell_type": "code", "execution_count": 1, "id": "aec739fc-1225-46a4-b31e-b63f3fb9a397", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(INFO) (base_tasks.py) (18-Sep-25 09:42:17) Pass: UnrollCustomDefinitions - 0.10800 (ms)\n", "(INFO) (base_tasks.py) (18-Sep-25 09:42:17) Pass: BasisTranslator - 0.03314 (ms)\n", "(INFO) (cut_circuit.py) (18-Sep-25 09:42:17) Trying with 3 subcircuits\n", "Set parameter Username\n", "(INFO) (cutter.py) (18-Sep-25 09:42:17) Set parameter Username\n", "Set parameter LicenseID to value 2646086\n", "(INFO) (cutter.py) (18-Sep-25 09:42:17) Set parameter LicenseID to value 2646086\n", "Academic license - for non-commercial use only - expires 2026-04-01\n", "(INFO) (cutter.py) (18-Sep-25 09:42:17) Academic license - for non-commercial use only - expires 2026-04-01\n", "(INFO) (cut_circuit.py) (18-Sep-25 09:42:17) Running subcircuit 0 on backend: statevector_simulator\n", "(INFO) (cut_circuit.py) (18-Sep-25 09:42:17) Running subcircuit 1 on backend: statevector_simulator\n", "(INFO) (cut_circuit.py) (18-Sep-25 09:42:17) Running subcircuit 2 on backend: statevector_simulator\n", "/media/vineetb/delta/projects/cutqc2/.venv/lib/python3.12/site-packages/zarr/core/dtype/npy/structured.py:318: UnstableSpecificationWarning: The data type (Structured(fields=(('subcircuit', Int32(endianness='little')), ('qubit', Int32(endianness='little'))))) does not have a Zarr V3 specification. That means that the representation of arrays saved with this data type may change without warning in a future version of Zarr Python. Arrays stored with this data type may be unreadable by other Zarr libraries. Use this data type at your own risk! Check https://github.com/zarr-developers/zarr-extensions/tree/main/data-types for the status of data type specifications for Zarr V3.\n", " v3_unstable_dtype_warning(self)\n", "/media/vineetb/delta/projects/cutqc2/.venv/lib/python3.12/site-packages/zarr/core/dtype/npy/string.py:248: UnstableSpecificationWarning: The data type (FixedLengthUTF32(length=20, endianness='little')) does not have a Zarr V3 specification. That means that the representation of arrays saved with this data type may change without warning in a future version of Zarr Python. Arrays stored with this data type may be unreadable by other Zarr libraries. Use this data type at your own risk! Check https://github.com/zarr-developers/zarr-extensions/tree/main/data-types for the status of data type specifications for Zarr V3.\n", " v3_unstable_dtype_warning(self)\n" ] } ], "source": [ "!cutqc2 cut \\\n", " --file supremacy_6qubit.qasm3 \\\n", " --max-subcircuit-width 5 \\\n", " --max-subcircuit-cuts 10 \\\n", " --subcircuit-size-imbalance 2 \\\n", " --max-cuts 10 \\\n", " --num-subcircuits 3 \\\n", " --output-file supremacy_6qubit.zarr" ] }, { "cell_type": "markdown", "id": "f7fd5e5a-38bf-450c-809f-5f7a20514e4b", "metadata": {}, "source": [ "Run the above command to generate the `supremacy_6qubit.zarr` \"file\".\n", "\n", "## Inspecting the zarr file\n", "\n", "In a `.zarr` file (which is actually a folder), metadata is stored in json files (in `zarr.json` files) at various levels of the directory structure." ] }, { "cell_type": "code", "execution_count": 2, "id": "e8eaf1c6-f4ce-4777-841c-7695636699f5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"attributes\": {\n", " \"version\": \"0.0.7\",\n", " \"circuit_qasm\": \"OPENQASM 3.0;\\ninclude \\\"stdgates.inc\\\";\\nqubit[6] q;\\nh q[0];\\nh q[1];\\nh q[2];\\nh q[3];\\nh q[4];\\nh q[5];\\ncz q[0], q[1];\\ncz q[4], q[5];\\nt q[2];\\nt q[3];\\ncz q[2], q[4];\\nry(pi/2) q[0];\\nry(pi/2) q[1];\\nry(pi/2) q[5];\\nt q[0];\\nt q[1];\\nt q[5];\\nry(pi/2) q[2];\\nry(pi/2) q[4];\\ncz q[0], q[2];\\nt q[4];\\ncz q[2], q[3];\\nrx(pi/2) q[0];\\ncz q[3], q[5];\\nt q[0];\\nrx(pi/2) q[2];\\nt q[2];\\nry(pi/2) q[3];\\nry(pi/2) q[5];\\ncz q[1], q[3];\\nt q[5];\\nh q[0];\\nh q[1];\\nh q[2];\\nh q[3];\\nh q[4];\\nh q[5];\\n\"\n", " },\n", " \"zarr_format\": 3,\n", " \"consolidated_metadata\": null,\n", " \"node_type\": \"group\"\n", "}" ] } ], "source": [ "!cat supremacy_6qubit.zarr/zarr.json" ] }, { "cell_type": "markdown", "id": "7ace91dd-c590-4f7d-a303-d4753fad2dfd", "metadata": {}, "source": [ "`.zarr` files are easily accessed and manipulated in Python, but to keep this discussion language-agnostic, here we will use the [jq](https://stedolan.github.io/jq/) tool to inspect and explain the contents of the json file.\n", "`jq` is a command line tool commonly available on Linux and MacOS systems, and allows us to extract arbitrary fields from json data.\n", "\n", "### Top-level metadata\n", "\n", "The root `zarr.json` file contains metadata about the zarr file itself, including the Cutqc2 version number used to create it." ] }, { "cell_type": "code", "execution_count": 3, "id": "52ed145e-6a5f-4133-a612-a8c74d855319", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.0.7\n" ] } ], "source": [ "!jq -r \".attributes.version\" supremacy_6qubit.zarr/zarr.json" ] }, { "cell_type": "markdown", "id": "b4d2fc2b-b567-4c79-8c4a-5ac63428072b", "metadata": {}, "source": [ "It is important to realize that the `.zarr` file created by one version of Cutqc2 may not be readable by another version of Cutqc2 (at least till we reach the `1.x` version).\n", "\n", "Similarly, the original circuit in QASM format is stored in the `circuit_qasm` attribute." ] }, { "cell_type": "code", "execution_count": 4, "id": "1beb6c2f-446e-4ef0-8ce1-b66c1afe38b7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "OPENQASM 3.0;\n", "include \"stdgates.inc\";\n", "qubit[6] q;\n", "h q[0];\n", "h q[1];\n" ] } ], "source": [ "!jq -r \".attributes.circuit_qasm\" supremacy_6qubit.zarr/zarr.json | head -n 5" ] }, { "cell_type": "markdown", "id": "cb121f48-c23d-49df-ae05-603994118651", "metadata": {}, "source": [ "### Subcircuits\n", "\n", "#### Number of subcircuits" ] }, { "cell_type": "code", "execution_count": 5, "id": "b93d7e85-0f23-4515-89ba-9e334360c7a2", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[0;39m3\u001b[0m\n" ] } ], "source": [ "!jq -r \".attributes.n\" supremacy_6qubit.zarr/subcircuits/zarr.json" ] }, { "cell_type": "markdown", "id": "f1198b37-eb50-452d-a17e-7db880d2b61c", "metadata": {}, "source": [ "Subcircuits are numbered from 0 to n-1, where n is the number of subcircuits.\n", "\n", "#### Subcircuit metadata\n", "\n", "The qasm3 representation of each subcircuit is stored as the `qasm` attribute in its numbered folder." ] }, { "cell_type": "code", "execution_count": 6, "id": "780bcd93-c234-48aa-8e95-9860a927896c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "OPENQASM 3.0;\n", "include \"stdgates.inc\";\n", "qubit[4] q;\n", "h q[0];\n", "h q[1];\n" ] } ], "source": [ "!jq -r \".attributes.qasm\" supremacy_6qubit.zarr/subcircuits/0/zarr.json | head -n 5" ] }, { "cell_type": "markdown", "id": "c1cbf487-4fb1-42d1-a4e3-17ba47f1be27", "metadata": {}, "source": [ "#### Subcircuit probabilities\n", "\n", "The probabilities for each subcircuit are stored in the `packed_probabilities` group in its numbered folder. Let's inspect the shape of the probability values for subcircuit 0." ] }, { "cell_type": "code", "execution_count": 7, "id": "2fbbbdf2-9fa1-49b8-b4ec-4878b0ddb44a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1;39m[\n", " \u001b[0;39m4\u001b[0m\u001b[1;39m,\n", " \u001b[0;39m4\u001b[0m\u001b[1;39m,\n", " \u001b[0;39m4\u001b[0m\u001b[1;39m,\n", " \u001b[0;39m8\u001b[0m\u001b[1;39m\n", "\u001b[1;39m]\u001b[0m\n" ] } ], "source": [ "!jq -r \".shape\" supremacy_6qubit.zarr/subcircuits/0/packed_probabilities/zarr.json" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.12.9" } }, "nbformat": 4, "nbformat_minor": 5 }