{ "cells": [ { "cell_type": "markdown", "id": "26d84d10", "metadata": {}, "source": [ "# Conversion example from Eka\n", "\n", "```{note}\n", "The widgets in this notebook are interactive!\n", "```\n", "\n", "We start by defining an `Eka` object that encodes a simple memory experiment on a distance 3 repetition code, that consists of a reset, a logical X and a measurement, with some syndromes extraction." ] }, { "cell_type": "code", "execution_count": 1, "id": "d9877ab0", "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from loom.eka.block import Block\n", "from loom.eka.eka import Eka\n", "from loom.eka.lattice import Lattice\n", "from loom.eka.operations.code_operation import (\n", " LogicalX,\n", " MeasureBlockSyndromes,\n", " MeasureLogicalZ,\n", " ResetAllDataQubits,\n", ")\n", "from loom.eka.pauli_operator import PauliOperator\n", "from loom.eka.stabilizer import Stabilizer\n", "import loom.visualizer as vis\n", "from loom.interpreter.interpreter import interpret_eka\n", "import plotly.io as pio\n", "\n", "pio.renderers.default = \"notebook\"\n", "\n", "# Set up a bit-flip repetition code with a distance of 3\n", "distance = 3\n", "lattice = Lattice.linear((distance + 1,))\n", "\n", "base_position = (1,)\n", "initial_rep_block = Block(\n", " unique_label=\"q1\",\n", " stabilizers=tuple(\n", " Stabilizer(\n", " pauli=\"ZZ\",\n", " data_qubits=(\n", " (base_position[0] + i, 0),\n", " (base_position[0] + i + 1, 0),\n", " ),\n", " ancilla_qubits=((base_position[0] + i, 1),),\n", " )\n", " for i in range(distance - 1)\n", " ),\n", " logical_x_operators=(\n", " PauliOperator(\"XXX\", tuple((base_position[0] + i, 0) for i in range(distance))),\n", " ),\n", " logical_z_operators=(PauliOperator(\"Z\", ((base_position[0], 0),)),),\n", ")\n", "\n", "\n", "meas_block_and_meas_log = [\n", " ResetAllDataQubits(initial_rep_block.unique_label, state=\"0\"),\n", " MeasureBlockSyndromes(initial_rep_block.unique_label, n_cycles=1),\n", " LogicalX(initial_rep_block.unique_label),\n", " MeasureBlockSyndromes(initial_rep_block.unique_label, n_cycles=1),\n", " MeasureLogicalZ(initial_rep_block.unique_label),\n", "]\n", "\n", "eka = Eka(lattice, blocks=[initial_rep_block], operations=meas_block_and_meas_log)\n", "\n", "interpreted_eka = interpret_eka(eka)\n", "\n", "stab_plot = vis.StabilizerPlot(\n", " lattice,\n", " title=f\"Repetition Code\",\n", ")\n", "stab_plot.add_dqubit_traces()\n", "stab_plot.plot_blocks(initial_rep_block)\n", "# Sphinx formatting\n", "stab_plot._fig.update_layout(margin=dict(t=60, l=30, b=30), width=680, height=400)\n", "stab_plot.show()" ] }, { "cell_type": "markdown", "id": "e88144dd", "metadata": {}, "source": [ "## Conversion to QASM" ] }, { "cell_type": "code", "execution_count": 2, "id": "e6701797", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Simulation results: \n" ] }, { "data": { "text/plain": [ "{'c_(1, 0)_0': [1, 1, 1],\n", " 'c_(1, 1)_0': [0, 0, 0],\n", " 'c_(1, 1)_1': [0, 0, 0],\n", " 'c_(2, 0)_0': [1, 1, 1],\n", " 'c_(2, 1)_0': [0, 0, 0],\n", " 'c_(2, 1)_1': [0, 0, 0],\n", " 'c_(3, 0)_0': [1, 1, 1]}" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from loom.executor import EkaToQasmConverter\n", "from qiskit import transpile, qasm3\n", "from qiskit_aer import Aer\n", "\n", "converter = EkaToQasmConverter()\n", "\n", "# Convert the Eka circuit to QASM string representation\n", "QASM_string, q_register, c_register = converter.convert(interpreted_eka)\n", "\n", "# Execute the QASM circuit using Qiskit Aer simulator\n", "backend = Aer.get_backend(\"aer_simulator\")\n", "qc = qasm3.loads(QASM_string) # load QASM‑3\n", "qc = transpile(qc, backend) # prepare for backend\n", "shots = 3\n", "result = backend.run(qc, shots=shots).result().get_counts() # run (no “execute”)\n", "\n", "print(\"Simulation results: \")\n", "\n", "converter.parse_target_run_outcome((result, c_register))" ] }, { "cell_type": "markdown", "id": "884b5114", "metadata": {}, "source": [ "## Conversion to Stim" ] }, { "cell_type": "code", "execution_count": 3, "id": "fb8c76ce", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Results:\n" ] }, { "data": { "text/plain": [ "{'c_(1, 0)_0': [1, 1, 1],\n", " 'c_(1, 1)_0': [0, 0, 0],\n", " 'c_(1, 1)_1': [0, 0, 0],\n", " 'c_(2, 0)_0': [1, 1, 1],\n", " 'c_(2, 1)_0': [0, 0, 0],\n", " 'c_(2, 1)_1': [0, 0, 0],\n", " 'c_(3, 0)_0': [1, 1, 1]}" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from loom.executor import EkaToStimConverter\n", "\n", "\n", "converter = EkaToStimConverter()\n", "\n", "stim_circuit, q_register, c_register = converter.convert(interpreted_eka)\n", "\n", "# Sample results\n", "sampler = stim_circuit.compile_sampler()\n", "num_samples = 3\n", "results = sampler.sample(shots=num_samples)\n", "\n", "# Format and print simulation results\n", "print(\"Results:\")\n", "converter.parse_target_run_outcome((results, c_register))" ] }, { "cell_type": "markdown", "id": "a25b95e2", "metadata": {}, "source": [ "## Other converter available :\n", "\n", "- Xanadu's Pennylane: `EkaToPennylaneConverter`\n", "- Nvidia's CudaQ: `EkaToCudaqConverter`\n", "- QPerfect's MimiQ: `EkaToMimiqConverter`" ] }, { "cell_type": "markdown", "id": "b4b47eaa", "metadata": {}, "source": [ "As expected, since there is no noise in the simulations used, the 2 rounds of syndromes extractions yield the same outputs. The measured outcome of the data qubits is always 1, which is what is expected after applying reset and X on the logical qubit." ] } ], "metadata": { "kernelspec": { "display_name": "loom-py3.12", "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 }