{ "cells": [ { "cell_type": "markdown", "id": "fce4a721-17f8-4027-b2d0-6a829b5753ef", "metadata": { "tags": [] }, "source": [ "# CliffordSim Simple Examples\n", "\n", "In this notebook we shall simulate some simple Clifford circuits using CliffordSim.\n", "We will also demonstrate the propagation of Pauli frames using the simulator." ] }, { "cell_type": "markdown", "id": "9d9938a1-88b2-4921-a1d2-464f65cca204", "metadata": {}, "source": [ "\n", "## Bell Pair Circuit" ] }, { "cell_type": "code", "execution_count": 1, "id": "5c640e0c-ab5d-4239-84da-05b25b66d6f1", "metadata": {}, "outputs": [], "source": [ "from loom.cliffordsim import Engine\n", "from loom.cliffordsim.operations import (\n", " Hadamard,\n", " CNOT,\n", " Measurement,\n", " Reset,\n", " Z,\n", " Phase,\n", " PhaseInv,\n", ")\n", "import pprint" ] }, { "cell_type": "code", "execution_count": null, "id": "46e641fc-df9c-4dec-ab68-ed4b5033fca4", "metadata": {}, "outputs": [], "source": [ "# Bell Pair\n", "operation_list_bell_pair = [Hadamard(0), CNOT(0, 1), Measurement(0), Measurement(1)]\n", "nqubits = 2\n", "seed = None # Optional seed for reproducibility\n", "\n", "cliffordsim_engine = Engine(operation_list_bell_pair, nqubits, seed)" ] }, { "cell_type": "code", "execution_count": 3, "id": "4c91affa-6473-41f6-8167-514de0c81869", "metadata": {}, "outputs": [], "source": [ "# Runs the Simulator\n", "cliffordsim_engine.run()" ] }, { "cell_type": "markdown", "id": "5dc525b9-929d-46d3-9972-c3f0efc19178", "metadata": {}, "source": [ "In this example, we measure qubits 0 and 1 after applying the Hadamard and CNOT gates. \n", "\n", "CliffordSim performs the measurement and stores the result in its `DataStore` object, accessible through the `data_store` attribute." ] }, { "cell_type": "code", "execution_count": 4, "id": "08b4f3ce-0bce-4c17-a1ac-a65f717034bc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'2': {'d24f42b1-9d10-496e-ae01-32aa623566db': {'flip_results': {},\n", " 'is_random': np.True_,\n", " 'measurement_result': 1}},\n", " '3': {'c02eefd4-0c12-4c42-b2c7-fa2e0aac67c2': {'flip_results': {},\n", " 'is_random': np.False_,\n", " 'measurement_result': np.int8(1)}},\n", " 'time_step': [2, 3]}\n" ] } ], "source": [ "pprint.pprint(cliffordsim_engine.data_store.measurements)" ] }, { "cell_type": "markdown", "id": "8be9bea6-dea8-4f75-9f05-a79a40fcd1b6", "metadata": {}, "source": [ "The structure of the `DataStore.measurements` can be understood as follows:\n", "1. `time_step` are the parallelized time steps in which the measurement operations were performed.\n", "2. String-fied versions of the values in the `time_step` list as keys. The values for these keys will contain the measurement data from that particular time step.\n", "3. Measurement data, from one `Measurement` Operation is stored in the following format:\n", "```\n", "'uuid of measurement operation': {'is_random': boolean, 'measurement_result': int}\n", "```" ] }, { "cell_type": "code", "execution_count": 5, "id": "4de216e1-8afa-455d-a988-a4859b5b4b77", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'+ZZ', '-Z_'}\n" ] } ], "source": [ "print(cliffordsim_engine.stabilizer_set)" ] }, { "cell_type": "markdown", "id": "5945da51-9d1c-4152-993e-5be6930daad3", "metadata": {}, "source": [ "## Five-Qubit Code Initialization\n", "\n", "Encoding circuit taken from [here](https://www.researchgate.net/figure/Encoding-circuit-for-the-five-qubit-code-a-Circuit-to-encode-the-logical-minus-state_fig1_337273308)" ] }, { "cell_type": "code", "execution_count": null, "id": "d881af1b-77cb-4202-b5e8-5ee0a9346303", "metadata": {}, "outputs": [], "source": [ "operation_list_five_qubit = [\n", " # Layer 0\n", " Z(0),\n", " Hadamard(2),\n", " Hadamard(3),\n", " # Layer 1\n", " PhaseInv(0),\n", " CNOT(2, 4),\n", " # Layer 2\n", " CNOT(3, 1),\n", " # Layer 3\n", " Hadamard(1),\n", " CNOT(3, 4),\n", " # Layer 4\n", " CNOT(1, 0),\n", " PhaseInv(2),\n", " Phase(3),\n", " PhaseInv(4),\n", " # Layer 5\n", " Phase(0),\n", " Phase(1),\n", " Z(2),\n", " # Layer 6\n", " CNOT(4, 0),\n", " # Layer 7\n", " Hadamard(4),\n", " # Layer 8\n", " CNOT(4, 1),\n", "]\n", "nqubits = 5\n", "seed = None\n", "\n", "cliffordsim_engine = Engine(operation_list_five_qubit, nqubits, seed)" ] }, { "cell_type": "code", "execution_count": 7, "id": "ee3bba10-13a8-448a-b60f-9ca2f4b2874d", "metadata": {}, "outputs": [], "source": [ "# Runs the Simulator\n", "cliffordsim_engine.run()" ] }, { "cell_type": "code", "execution_count": 8, "id": "2f12853d-6cd9-49fb-823b-2e0aba40935a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'time_step': []}\n" ] } ], "source": [ "pprint.pprint(cliffordsim_engine.data_store.measurements)" ] }, { "cell_type": "markdown", "id": "eb30c151-6e07-4b74-93a5-59414a82489c", "metadata": {}, "source": [ "Since there are no measurement operations in this circuit, the measurements attribute of the `DataStore` Object is empty." ] }, { "cell_type": "code", "execution_count": 9, "id": "6af75741-2a60-4fc8-8d75-0f947d28ab42", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'+XXY_Y', '-ZY__Y', '+XY_YX', '+_XZZX', '+YZ_ZY'}\n" ] } ], "source": [ "print(cliffordsim_engine.stabilizer_set)" ] }, { "cell_type": "markdown", "id": "99f2d748", "metadata": {}, "source": [ "```{note}\n", "The above may not look exactly how we would expect the state to look like for the \n", "five-qubit code. Multiplying in pairs appropriately the above Paulis, we can get the\n", "standard set:\n", "\n", "- `+XZZX_`\n", "- `+_XZZX`\n", "- `+X_XZZ`\n", "- `+ZX_XZ`\n", "- `+ZZZZZ` (Z Logical operator)\n", "```" ] }, { "cell_type": "markdown", "id": "e22d898e", "metadata": {}, "source": [ "## PauliFrame basic example" ] }, { "cell_type": "markdown", "id": "d4d58e78", "metadata": {}, "source": [ "Below follows a demonstration on how to create and propagate Pauli frames using\n", "a simple circuit that is based on the Repetition code syndrome extraction circuit." ] }, { "cell_type": "code", "execution_count": null, "id": "02ac8c48", "metadata": {}, "outputs": [], "source": [ "from loom.cliffordsim.pauli_frame import PauliFrame\n", "from loom.cliffordsim.operations import CreatePauliFrame, RecordPauliFrame\n", "\n", "pframe_0 = PauliFrame.from_string(\"XIIII\")\n", "pframe_1 = PauliFrame.from_string(\"IXIII\")\n", "\n", "rep_code_pframe_operation_list = [\n", " CreatePauliFrame(pframe_0),\n", " CNOT(0, 3),\n", " CNOT(1, 3),\n", " CNOT(1, 4),\n", " CNOT(2, 4),\n", " Measurement(3),\n", " Measurement(4),\n", " Reset(3),\n", " Reset(4),\n", " RecordPauliFrame(pframe_0),\n", " CreatePauliFrame(pframe_1),\n", " CNOT(0, 3),\n", " CNOT(1, 3),\n", " CNOT(1, 4),\n", " CNOT(2, 4),\n", " Measurement(3),\n", " Measurement(4),\n", " RecordPauliFrame(pframe_1),\n", "]\n", "\n", "# Define the Engine\n", "p_frame_engine = Engine(rep_code_pframe_operation_list, 5)\n", "# Run the simulator\n", "p_frame_engine.run()" ] }, { "cell_type": "code", "execution_count": null, "id": "8a5fffcf", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "({'initial_pauli_frame': PauliFrame: X____,\n", " 'recorded_pauli_frame': PauliFrame: X__X_},\n", " {'initial_pauli_frame': PauliFrame: _X___,\n", " 'recorded_pauli_frame': PauliFrame: _X_XX})" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Show propagated pauli frames\n", "p_frame_engine.data_store.get_pframes()" ] } ], "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.7" } }, "nbformat": 4, "nbformat_minor": 5 }