From 5d1b605875caeb6ddd6bf51e66e4c4cdd5cd60ec Mon Sep 17 00:00:00 2001 From: Elenbaas Date: Fri, 23 Feb 2024 16:06:29 +0100 Subject: [PATCH] Add notebook support to MkDocs. --- .gitignore | 4 +- docs/index.md | 7 +- docs/reference.md | 6 + docs/tutorial.ipynb | 1449 +++++++++++++++++ mkdocs.yaml | 8 +- opensquirrel/circuit.py | 4 +- .../export/__init__.py | 0 poetry.lock | 429 +++-- pyproject.toml | 10 +- 9 files changed, 1812 insertions(+), 105 deletions(-) create mode 100644 docs/tutorial.ipynb rename docs/explanation.md => opensquirrel/export/__init__.py (100%) diff --git a/.gitignore b/.gitignore index 68bc17f9..81e1b53e 100644 --- a/.gitignore +++ b/.gitignore @@ -68,8 +68,8 @@ instance/ # Scrapy stuff: .scrapy -# Sphinx documentation -docs/_build/ +# MkDocs documentation +site/ # PyBuilder .pybuilder/ diff --git a/docs/index.md b/docs/index.md index df184259..495fa79a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,10 +10,9 @@ PyPI: The following documentation structure is used: [Diátaxis documentation framework](https://diataxis.fr/). -1. [Tutorials](tutorials.md) +1. [Tutorial](tutorial.ipynb) 2. [How-To Guides](how-to-guides.md) 3. [Reference](reference.md) -4. [Explanation](explanation.md) ## Authors @@ -25,4 +24,6 @@ The following documentation structure is used: [Diátaxis documentation framewor ## Acknowledgements -__ +The Quantum Inspire project +QuTech TNO +TU Delft diff --git a/docs/reference.md b/docs/reference.md index 27d1d067..3e847124 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -3,10 +3,15 @@ ::: opensquirrel.circuit ::: opensquirrel.circuit_builder ::: opensquirrel.circuit_matrix_calculator +::: opensquirrel.cnot_decomposer ::: opensquirrel.common ::: opensquirrel.default_gates +::: opensquirrel.export.quantify_scheduler_exporter +::: opensquirrel.export_format ::: opensquirrel.gate_library +::: opensquirrel.identity_filter ::: opensquirrel.mckay_decomposer +::: opensquirrel.merger ::: opensquirrel.parsing.antlr.generated.CQasm3Lexer ::: opensquirrel.parsing.antlr.generated.CQasm3Listener ::: opensquirrel.parsing.antlr.generated.CQasm3Parser @@ -22,4 +27,5 @@ ::: opensquirrel.squirrel_ir ::: opensquirrel.utils.matrix_expander ::: opensquirrel.writer +::: opensquirrel.zyz_decomposer diff --git a/docs/tutorial.ipynb b/docs/tutorial.ipynb new file mode 100644 index 00000000..c078838e --- /dev/null +++ b/docs/tutorial.ipynb @@ -0,0 +1,1449 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Tutorial\n", + "\n", + "> **_NOTE:_** This tutorial is based on OpenSquirrel version 0.0.6, so make sure it is up-to-date.\n", + "\n", + "### Why should I use it?\n", + "\n", + "It has a user-friendly interface, is easy to extend with your own custom code, and is well tested and reliable.\n", + "\n", + "As a quantum circuits compiler, it is fully aware of the semantics of each gate that you use and arbitrary quantum gates can be constructed.\n", + "\n", + "It understands the quantum programming language cQASM 3.0 and will support additional quantum programming languages in the future.\n", + "\n", + "It is being developed in modern Python and follows best practices.\n", + "\n", + "### Who is maintaining it?\n", + "\n", + "Engineers from QuTech (TNO/TU Delft) for Quantum Inspire 2.0; in particular,\n", + "\n", + "- Pablo Le Henaff p.lehenaff@tudelft.nl\n", + "\n", + "- Chris Elenbaas chris.elenbaas@tno.nl\n", + "\n", + "- Roberto Turrado r.turradocamblor@tudelft.nl\n", + "\n", + "### Where can I find the source code?\n", + "\n", + "OpenSquirrel is open source and is hosted through GitHub:\n", + "https://github.com/QuTech-Delft/OpenSquirrel\n", + "\n" + ], + "metadata": { + "id": "eGWItVPT3Ell" + } + }, + { + "cell_type": "markdown", + "source": [ + "## Installation\n", + "\n", + "... is as easy as ABC:" + ], + "metadata": { + "id": "t8yyUlX-4TPX" + } + }, + { + "cell_type": "code", + "source": [ + "! pip install opensquirrel==0.0.6\n", + "\n", + "import opensquirrel" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "3U8xFfy24WFu", + "outputId": "90cb4b15-f5c2-49b3-84b6-74b25831d005", + "is_executing": true + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "## Creation of a circuit\n", + "\n", + "OpenSquirrel's entrypoint is the `Circuit` class, which represents a quantum circuit. Currently, you can create a `Circuit` instance in two different ways:\n", + " - form a string written in cQASM 3.0, or;\n", + " - by using the _circuit builder_.\n", + "\n", + "### From a cQASM 3.0 string" + ], + "metadata": { + "id": "StoCwwPW4rpn" + } + }, + { + "cell_type": "code", + "source": [ + "my_circuit = opensquirrel.Circuit.from_string(\"\"\"\n", + "version 3.0\n", + "\n", + "qubit[2] q\n", + "h q[0]; cnot q[0], q[1] // Create a Bell pair\n", + "\"\"\")\n", + "\n", + "my_circuit" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "tmxqGpjp5DCa", + "outputId": "467c2871-9a5e-4315-8c75-d1738e83b60b" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "version 3.0\n", + "\n", + "qubit[2] q\n", + "\n", + "h q[0]\n", + "cnot q[0], q[1]" + ] + }, + "metadata": {}, + "execution_count": 3 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + ">__Note__: Currently OpenSquirrel only supports a limited version of cQASM 3.0. This is due to the fact that the latter is still under development. When new features are introduced to the language, OpenSquirrel will follow in due course. For example, at the time of writing, OpenSquirrel only supports the declaration of a single qubit register per quantum program, whereas the language already allows for the declaration of multiple qubit registers within the global scope of the quantum program. Also unsupported are control flow, arbitrary types, _etcetera_. Both the language and OpenSquirrel are under continuous development, yet the language features that are supported by OpenSquirrel function properly.\n" + ], + "metadata": { + "id": "sF1iOmO97vL2" + } + }, + { + "cell_type": "markdown", + "source": [ + "### Using the circuit builder\n", + "\n", + "For creation of a circuit, directly through Python, you can use the `CircuitBuilder` class, accordingly:" + ], + "metadata": { + "id": "Ssk8G7HB5VJV" + } + }, + { + "cell_type": "code", + "source": [ + "# Create a Bell pair circuit using the OpenSquirrel circuit builder.\n", + "my_circuit_from_builder = opensquirrel.CircuitBuilder(number_of_qubits=2).h(opensquirrel.squirrel_ir.Qubit(0)).cnot(opensquirrel.squirrel_ir.Qubit(0), opensquirrel.squirrel_ir.Qubit(1)).to_circuit()\n", + "\n", + "my_circuit_from_builder" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "nAS_UZv55bO5", + "outputId": "fb0b95de-bb29-41be-99b6-aaf5278b83c6" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "version 3.0\n", + "\n", + "qubit[2] q\n", + "\n", + "h q[0]\n", + "cnot q[0], q[1]" + ] + }, + "metadata": {}, + "execution_count": 4 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "At this point, the code becomes more straightforward if we make some _imports_ beforehand:" + ], + "metadata": { + "id": "19gBtDM25wsr" + } + }, + { + "cell_type": "code", + "source": [ + "import opensquirrel as os\n", + "from opensquirrel.squirrel_ir import Qubit, Int, Float\n", + "\n", + "my_circuit_from_builder_with_imports = os.CircuitBuilder(number_of_qubits=2).ry(Qubit(0), Float(0.23)).cnot(Qubit(0), Qubit(1)).to_circuit()\n", + "my_circuit_from_builder_with_imports" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_TZ0JF6152ri", + "outputId": "11d6521b-f936-4f6f-c106-e472a845a647" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "version 3.0\n", + "\n", + "qubit[2] q\n", + "\n", + "ry q[0], 0.23\n", + "cnot q[0], q[1]" + ] + }, + "metadata": {}, + "execution_count": 5 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "> __Note__: https://github.com/QuTech-Delft/OpenSquirrel/issues/87" + ], + "metadata": { + "id": "4It53rG68D9g" + } + }, + { + "cell_type": "markdown", + "source": [ + "You can naturally use the functionalities available in Python to create your circuit:" + ], + "metadata": { + "id": "Po7uNS2h6td6" + } + }, + { + "cell_type": "code", + "source": [ + "builder = os.CircuitBuilder(number_of_qubits=10)\n", + "for i in range(0, 10, 2):\n", + " builder.h(Qubit(i))\n", + "\n", + "builder.to_circuit()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "8OJM5wML6xX1", + "outputId": "5b39060a-0e42-458a-e178-1a15dacc8213" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "version 3.0\n", + "\n", + "qubit[10] q\n", + "\n", + "h q[0]\n", + "h q[2]\n", + "h q[4]\n", + "h q[6]\n", + "h q[8]" + ] + }, + "metadata": {}, + "execution_count": 6 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "For instance, you can generate a quantum fourier transform (QFT) circuit as follows:" + ], + "metadata": { + "id": "_hzJOEkk7KXa" + } + }, + { + "cell_type": "code", + "source": [ + "number_of_qubits = 5\n", + "qft = os.CircuitBuilder(number_of_qubits=number_of_qubits)\n", + "for i in range(number_of_qubits):\n", + " qft.h(Qubit(i))\n", + " for c in range(i + 1, number_of_qubits):\n", + " qft.crk(Qubit(c), Qubit(i), Int(c-i+1))\n", + "\n", + " # FIXME: this is not yet supported, see https://github.com/QuTech-Delft/OpenSquirrel/issues/82\n", + " # qft.crk(control=Qubit(c), target=Qubit(i), k=Int(c-i+1))\n", + "\n", + "qft.to_circuit()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Pr8C34bj7RPI", + "outputId": "bfbf7152-4964-4aef-d41f-3095a9645e83" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "version 3.0\n", + "\n", + "qubit[5] q\n", + "\n", + "h q[0]\n", + "crk q[1], q[0], 2\n", + "crk q[2], q[0], 3\n", + "crk q[3], q[0], 4\n", + "crk q[4], q[0], 5\n", + "h q[1]\n", + "crk q[2], q[1], 2\n", + "crk q[3], q[1], 3\n", + "crk q[4], q[1], 4\n", + "h q[2]\n", + "crk q[3], q[2], 2\n", + "crk q[4], q[2], 3\n", + "h q[3]\n", + "crk q[4], q[3], 2\n", + "h q[4]" + ] + }, + "metadata": {}, + "execution_count": 7 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Strong types" + ], + "metadata": { + "id": "EpIsNqaj9GKr" + } + }, + { + "cell_type": "markdown", + "source": [ + "As you can see, gates need to be passed _strong types_. For instance, you cannot do:" + ], + "metadata": { + "id": "VOoDWUzJ84HE" + } + }, + { + "cell_type": "code", + "source": [ + "try:\n", + " os.CircuitBuilder(number_of_qubits=2).cnot(Qubit(0), Int(3))\n", + "except Exception as e:\n", + " print(e)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "AAx99nBT882r", + "outputId": "6f40dee0-a42a-43a1-e0e1-dd36f82f17f3" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Wrong argument type for gate `cnot`, got but expected \n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "The same goes for string-based circuits in cQASM 3.0:" + ], + "metadata": { + "id": "BBkBWcXi9KNI" + } + }, + { + "cell_type": "code", + "source": [ + "try:\n", + " os.Circuit.from_string(\"\"\"\n", + " version 3.0\n", + " qubit[2] q\n", + "\n", + " cnot q[0], 3\n", + " \"\"\")\n", + "except Exception as e:\n", + " print(e)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "65gyfSMC9NzU", + "outputId": "14446085-0ba7-46f8-8de3-ca677b2a794c" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Argument #1 passed to gate `cnot` is of type but should be \n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "By default OpenSquirrel does not use LibQASM (the cQASM parser library), but will do so soon. You can enable this, which changes the error message:" + ], + "metadata": { + "id": "70BczmiH9XJz" + } + }, + { + "cell_type": "code", + "source": [ + "try:\n", + " os.Circuit.from_string(\"\"\"\n", + " version 3.0\n", + " qubit[2] q\n", + "\n", + " cnot q[0], 3\n", + " \"\"\", use_libqasm=True)\n", + "except Exception as e:\n", + " print(e)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9o-jgu7s9dBm", + "outputId": "45860ffd-b407-4341-e235-a2561477783a" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Parsing error: Error at :5:5..9: failed to resolve overload for cnot with argument pack (qubit, int)\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Turning a circuit object into a string\n", + "\n", + "As you have seen in the examples above, you can turn a `Circuit` object into a cQASM 3.0 string by simply using the `str` or `__repr__` methods. We are aiming to support export to more languages, _e.g._, OpenQASM 3.0 string, and frameworks, _e.g._, a Qiskit quantum circuit, in the future." + ], + "metadata": { + "id": "XZitS5zG9rZl" + } + }, + { + "cell_type": "markdown", + "source": [ + "# Modifying a Circuit object" + ], + "metadata": { + "id": "oUHrlzmF-A7U" + } + }, + { + "cell_type": "markdown", + "source": [ + "# Merging gates\n", + "\n", + "OpenSquirrel can merge consecutive quantum gates. For now, this is only supported for single-qubit gates. The resulting gate is labeled as an \"anonymous gate\". Those gates have no name, so you get a placeholder when you try to print them." + ], + "metadata": { + "id": "O__7dQl39mLN" + } + }, + { + "cell_type": "code", + "source": [ + "import math\n", + "\n", + "builder = os.CircuitBuilder(number_of_qubits=1)\n", + "for i in range(16):\n", + " builder.rx(Qubit(0), Float(math.pi / 16))\n", + "\n", + "circuit = builder.to_circuit()\n", + "\n", + "# single qubit gates fusion\n", + "circuit.merge_single_qubit_gates()\n", + "circuit" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "n-gjYvDs-Mkk", + "outputId": "9405bc6e-f311-42b2-f123-8819d7392188" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "version 3.0\n", + "\n", + "qubit[1] q\n", + "\n", + "" + ] + }, + "metadata": {}, + "execution_count": 11 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "You can inspect what the gate has become:" + ], + "metadata": { + "id": "sB29oZckHlI7" + } + }, + { + "cell_type": "code", + "source": [ + "circuit.squirrel_ir.statements[0]" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JH2M0jWdHoLW", + "outputId": "a4671b9c-0a70-4f6e-9362-8ca3bddd7349" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "BlochSphereRotation(Qubit[0], axis=[1. 0. 0.], angle=3.141592653589795, phase=0.0)" + ] + }, + "metadata": {}, + "execution_count": 12 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "In the above example, OpenSquirrel has merged all of the X-rotations together. Yet, for now, it does not recognize it anymore as being an X-rotation; we may want to implement this at a late stage. The issue is that the gate set is not fixed, since you can define your own gates and add them to the set." + ], + "metadata": { + "id": "PUzfod3wHwcu" + } + }, + { + "cell_type": "markdown", + "source": [ + "## Defining your own quantum gates\n", + "\n", + "OpenSquirrel accepts any new gate and requires the semantic of each gate. Creating new gates is done using Python functions, decorators, and one of the following gate semantic classes: `BlochSphereRotation`, `ControlledGate`, or `MatrixGate`.\n", + "\n", + "- The `BlochSphereRotation` class is for every single qubit gate. It accepts a qubit, an axis, an angle, and a phase as arguments. Below is shown how the X gate is defined in the default gate set of OpenSquirrel:\n", + "\n", + "```python\n", + "@named_gate\n", + "def x(q: Qubit) -> Gate:\n", + " return BlochSphereRotation(qubit=q, axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)\n", + "```\n", + "\n", + "Notice the `@named_gate` decorator. This _tells_ OpenSquirrel that the function defines a gate and that it should, therefore, have all the nice properties OpenSquirrel expects of it. When you define a gate as such, it also creates a gate in the accompanying cQASM 3.0 parser taking the same arguments as the Python function.\n", + "\n", + "- The `ControlledGate` class is for multiple qubit gates that comprise controlled operations. For instance, the CNOT gate is defined as follows:\n", + "\n", + "```python\n", + "@named_gate\n", + "def cnot(control: Qubit, target: Qubit) -> Gate:\n", + " return ControlledGate(control, x(target))\n", + "```\n", + "\n", + "- The `MatrixGate` class is for multiple qubit gates that are not controlled operations, and are defined in the generic form of a matrix:\n", + "\n", + "```python\n", + "@named_gate\n", + "def swap(q1: Qubit, q2: Qubit) -> Gate:\n", + " return MatrixGate(\n", + " np.array(\n", + " [\n", + " [1, 0, 0, 0],\n", + " [0, 0, 1, 0],\n", + " [0, 1, 0, 0],\n", + " [0, 0, 0, 1],\n", + " ]\n", + " ),\n", + " [q1, q2],\n", + " )\n", + "```" + ], + "metadata": { + "id": "IZWKGM6CIA_3" + } + }, + { + "cell_type": "markdown", + "source": [ + "Once you have defined your new quantum gates, you can pass them as a custom `gate_set` argument to the `Circuit` object. Here is how to add, _e.g._, the Sycamore gate (labeled as `syc`) to OpenSquirrel's default gate set:" + ], + "metadata": { + "id": "RbHgbA4fK-Gz" + } + }, + { + "cell_type": "code", + "source": [ + "import numpy as np\n", + "import cmath\n", + "from opensquirrel.squirrel_ir import named_gate\n", + "\n", + "@named_gate\n", + "def syc(q1: Qubit, q2: Qubit):\n", + " return opensquirrel.squirrel_ir.MatrixGate(matrix=np.array(\n", + " [[1, 0, 0, 0],\n", + " [0, 0, -1j, 0],\n", + " [0, -1j, 0, 0],\n", + " [0, 0, 0, cmath.rect(1, - math.pi / 6)]]), operands=[q1, q2])\n", + "\n", + "my_extended_gate_set = os.default_gates.default_gate_set.copy()\n", + "my_extended_gate_set.append(syc)\n", + "\n", + "my_sycamore_circuit = os.Circuit.from_string(\"\"\"\n", + "version 3.0\n", + "qubit[3] q\n", + "\n", + "h q[1]\n", + "syc q[1], q[2]\n", + "cnot q[0], q[1]\n", + "\"\"\", gate_set=my_extended_gate_set)\n", + "\n", + "my_sycamore_circuit.test_get_circuit_matrix()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "V4P_8wbNLMOs", + "outputId": "5254cc4f-25bd-463a-fb3d-7a692c6e7037" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "array([[ 7.07106781e-01+1.79345371e-17j, 0.00000000e+00+0.00000000e+00j,\n", + " 7.07106781e-01-4.32978028e-17j, 0.00000000e+00+0.00000000e+00j,\n", + " 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j,\n", + " 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j],\n", + " [ 0.00000000e+00+0.00000000e+00j, 1.55305211e-33+4.32978028e-17j,\n", + " 0.00000000e+00+0.00000000e+00j, 5.30245156e-33+4.32978028e-17j,\n", + " 0.00000000e+00+0.00000000e+00j, -2.53632657e-17-7.07106781e-01j,\n", + " 0.00000000e+00+0.00000000e+00j, -8.65956056e-17-7.07106781e-01j],\n", + " [ 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j,\n", + " 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j,\n", + " 1.79345371e-17-7.07106781e-01j, 0.00000000e+00+0.00000000e+00j,\n", + " -4.32978028e-17-7.07106781e-01j, 0.00000000e+00+0.00000000e+00j],\n", + " [ 0.00000000e+00+0.00000000e+00j, 7.07106781e-01-2.53632657e-17j,\n", + " 0.00000000e+00+0.00000000e+00j, 7.07106781e-01-8.65956056e-17j,\n", + " 0.00000000e+00+0.00000000e+00j, 4.32978028e-17-1.55305211e-33j,\n", + " 0.00000000e+00+0.00000000e+00j, 4.32978028e-17-5.30245156e-33j],\n", + " [-4.32978028e-17-7.07106781e-01j, 0.00000000e+00+0.00000000e+00j,\n", + " 1.04530143e-16+7.07106781e-01j, 0.00000000e+00+0.00000000e+00j,\n", + " 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j,\n", + " 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j],\n", + " [ 0.00000000e+00+0.00000000e+00j, 4.32978028e-17-5.30245156e-33j,\n", + " 0.00000000e+00+0.00000000e+00j, -4.32978028e-17+9.05185102e-33j,\n", + " 0.00000000e+00+0.00000000e+00j, 6.12372436e-01-3.53553391e-01j,\n", + " 0.00000000e+00+0.00000000e+00j, -6.12372436e-01+3.53553391e-01j],\n", + " [ 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j,\n", + " 0.00000000e+00+0.00000000e+00j, 0.00000000e+00+0.00000000e+00j,\n", + " 6.12372436e-01-3.53553391e-01j, 0.00000000e+00+0.00000000e+00j,\n", + " -6.12372436e-01+3.53553391e-01j, 0.00000000e+00+0.00000000e+00j],\n", + " [ 0.00000000e+00+0.00000000e+00j, -8.65956056e-17-7.07106781e-01j,\n", + " 0.00000000e+00+0.00000000e+00j, 1.47827946e-16+7.07106781e-01j,\n", + " 0.00000000e+00+0.00000000e+00j, 2.16489014e-17+3.74969972e-17j,\n", + " 0.00000000e+00+0.00000000e+00j, -2.16489014e-17-3.74969972e-17j]])" + ] + }, + "metadata": {}, + "execution_count": 13 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "Notice that we used `test_get_circuit_matrix` here to obtain the unitary matrix corresponding to the Circuit object." + ], + "metadata": { + "id": "wQD16hfJMnNG" + } + }, + { + "cell_type": "markdown", + "source": [ + "## Gate decompositions\n", + "\n", + "OpenSquirrel can decompose quantum gates in the Circuit object given a custom decomposition. The first kind of decomposition is when you want to replace a given gate, like the `cnot` gate, with a fixed list of gates. It is commonly known that `cnot` can be decomposed as H-CZ-H. This decomposition is demonstrated below using a _Python lambda function_ which shares the same arguments as the gate that is decomposed:" + ], + "metadata": { + "id": "E0jS8Nb0JVj3" + } + }, + { + "cell_type": "code", + "source": [ + "from opensquirrel.default_gates import cnot, h, cz\n", + "\n", + "circuit = os.Circuit.from_string(\"\"\"\n", + "version 3.0\n", + "qubit[3] q\n", + "\n", + "x q[0:2] // Note how the SGMQ notation is expanded in the OpenSquirrel Circuit object.\n", + "cnot q[0], q[1]\n", + "ry q[2], 6.78\n", + "\"\"\")\n", + "\n", + "circuit.replace(cnot,\n", + " lambda control, target:\n", + " [\n", + " h(target),\n", + " cz(control, target),\n", + " h(target),\n", + " ]\n", + " )\n", + "circuit" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "P7KolwXzJwq7", + "outputId": "c583da3f-8135-4074-ab9d-e5476a84590a" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "version 3.0\n", + "\n", + "qubit[3] q\n", + "\n", + "x q[0]\n", + "x q[1]\n", + "x q[2]\n", + "h q[1]\n", + "cz q[0], q[1]\n", + "h q[1]\n", + "ry q[2], 6.78" + ] + }, + "metadata": {}, + "execution_count": 14 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "OpenSquirrel will check whether the provided decomposition is correct. For instance, an exception is thrown if we forget the final hadamard gate in our custom-made decomposition:" + ], + "metadata": { + "id": "NallB8_hKTp3" + } + }, + { + "cell_type": "code", + "source": [ + "circuit = os.Circuit.from_string(\"\"\"\n", + "version 3.0\n", + "qubit[3] q\n", + "\n", + "x q[0:2]\n", + "cnot q[0], q[1]\n", + "ry q[2], 6.78\n", + "\"\"\")\n", + "\n", + "try:\n", + " circuit.replace(cnot,\n", + " lambda control, target:\n", + " [\n", + " h(target),\n", + " cz(control, target),\n", + " ]\n", + " )\n", + "except Exception as e:\n", + " print(e)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "eEbj3aGhKbOn", + "outputId": "33537ff4-502e-44c1-b8ef-f7535735255f" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Replacement for gate cnot does not preserve the quantum state\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "On top of decompositions of a single gate, OpenSquirrel can decompose gates __based on their semantics__, regardless of name. To give an example, let us decompose an arbitrary single qubit gate into a product of axis rotations Z-Y-Z.\n", + "\n", + "First, we need to figure out mathmatics behind this decomposition. Let us use quaternions and Sympy for this, it will make it a lot easier.\n", + "\n", + "A 3D rotation of angle $\\alpha$ about the (normalized) axis $n=\\left(n_x, n_y, n_z \\right)$ can be represented by the quaternion $q = \\cos\\left(\\alpha/2\\right) + \\sin\\left(\\alpha/2\\right) \\left( n_x i + n_y j + n_z k \\right)$.\n", + "\n", + "Since composition of rotations is equivalent of the product of their quaternions, we have to find angles $\\theta_1$, $\\theta_2$ and $\\theta_3$ such that\n", + "\n", + "$$\n", + "q =\n", + "\\left[ \\cos\\left(\\frac{\\theta_1}{2}\\right) + k \\sin\\left(\\frac{\\theta_1}{2}\\right) \\right]\n", + "\\left[ \\cos\\left(\\frac{\\theta_2}{2}\\right) + j \\sin\\left(\\frac{\\theta_2}{2}\\right) \\right]\n", + "\\left[ \\cos\\left(\\frac{\\theta_3}{2}\\right) + k \\sin\\left(\\frac{\\theta_3}{2}\\right) \\right]\\ .\n", + "$$\n", + "\n", + "Let us expand this last term with Sympy:" + ], + "metadata": { + "id": "QPsM_6FvNa-M" + } + }, + { + "cell_type": "code", + "source": [ + "import sympy as sp\n", + "\n", + "theta1, theta2, theta3 = sp.symbols(\"theta_1 theta_2 theta_3\")\n", + "\n", + "z1 = sp.algebras.Quaternion.from_axis_angle((0, 0, 1), theta1)\n", + "y = sp.algebras.Quaternion.from_axis_angle((0, 1, 0), theta2)\n", + "z2 = sp.algebras.Quaternion.from_axis_angle((0, 0, 1), theta3)\n", + "\n", + "rhs = sp.trigsimp(sp.expand(z1 * y * z2))\n", + "rhs" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 58 + }, + "id": "HBDxPUktV4Hh", + "outputId": "f45f7581-90d2-4011-8f69-a9b538232818" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "cos(theta_2/2)*cos((theta_1 + theta_3)/2) + (-sin(theta_2/2)*sin((theta_1 - theta_3)/2))*i + sin(theta_2/2)*cos((theta_1 - theta_3)/2)*j + sin((theta_1 + theta_3)/2)*cos(theta_2/2)*k" + ], + "text/latex": "$\\displaystyle \\cos{\\left(\\frac{\\theta_{2}}{2} \\right)} \\cos{\\left(\\frac{\\theta_{1} + \\theta_{3}}{2} \\right)} + - \\sin{\\left(\\frac{\\theta_{2}}{2} \\right)} \\sin{\\left(\\frac{\\theta_{1} - \\theta_{3}}{2} \\right)} i + \\sin{\\left(\\frac{\\theta_{2}}{2} \\right)} \\cos{\\left(\\frac{\\theta_{1} - \\theta_{3}}{2} \\right)} j + \\sin{\\left(\\frac{\\theta_{1} + \\theta_{3}}{2} \\right)} \\cos{\\left(\\frac{\\theta_{2}}{2} \\right)} k$" + }, + "metadata": {}, + "execution_count": 16 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "Let us change variables and define $p\\equiv\\theta_1 + \\theta_3$ and $m\\equiv\\theta_1 - \\theta_3$." + ], + "metadata": { + "id": "OKso2MAIQ4wD" + } + }, + { + "cell_type": "code", + "source": [ + "p, m = sp.symbols(\"p m\")\n", + "\n", + "rhs_simplified = rhs.subs({\n", + " theta1 + theta3: p,\n", + " theta1 - theta3: m\n", + "})\n", + "\n", + "rhs_simplified" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 58 + }, + "id": "trzm7KB-IbJZ", + "outputId": "1fd23699-f820-4447-97ed-b6f95e255901" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "cos(p/2)*cos(theta_2/2) + (-sin(m/2)*sin(theta_2/2))*i + sin(theta_2/2)*cos(m/2)*j + sin(p/2)*cos(theta_2/2)*k" + ], + "text/latex": "$\\displaystyle \\cos{\\left(\\frac{p}{2} \\right)} \\cos{\\left(\\frac{\\theta_{2}}{2} \\right)} + - \\sin{\\left(\\frac{m}{2} \\right)} \\sin{\\left(\\frac{\\theta_{2}}{2} \\right)} i + \\sin{\\left(\\frac{\\theta_{2}}{2} \\right)} \\cos{\\left(\\frac{m}{2} \\right)} j + \\sin{\\left(\\frac{p}{2} \\right)} \\cos{\\left(\\frac{\\theta_{2}}{2} \\right)} k$" + }, + "metadata": {}, + "execution_count": 17 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "The original rotation's quaternion $q$ can be defined in Sympy accordingly:" + ], + "metadata": { + "id": "F5la6u2D9VBw" + } + }, + { + "cell_type": "code", + "source": [ + "alpha, nx, ny, nz = sp.symbols(\"alpha n_x n_y n_z\")\n", + "\n", + "q = sp.algebras.Quaternion.from_axis_angle((nx, ny, nz), alpha).subs({\n", + " nx**2 + ny**2 + nz**2: 1 # We assume the axis is normalized.\n", + "})\n", + "q" + ], + "metadata": { + "id": "c7uAHXP8YQYl", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 48 + }, + "outputId": "ca03e7e8-98aa-4fce-b13a-93170e655fb6" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "cos(alpha/2) + n_x*sin(alpha/2)*i + n_y*sin(alpha/2)*j + n_z*sin(alpha/2)*k" + ], + "text/latex": "$\\displaystyle \\cos{\\left(\\frac{\\alpha}{2} \\right)} + n_{x} \\sin{\\left(\\frac{\\alpha}{2} \\right)} i + n_{y} \\sin{\\left(\\frac{\\alpha}{2} \\right)} j + n_{z} \\sin{\\left(\\frac{\\alpha}{2} \\right)} k$" + }, + "metadata": {}, + "execution_count": 18 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "We get the following system of equations, where the unknowns are $p$, $m$, and $\\theta_2$:" + ], + "metadata": { + "id": "XjcQcczO28_a" + } + }, + { + "cell_type": "code", + "source": [ + "from IPython.display import display, Math\n", + "\n", + "display(\n", + " sp.Eq(rhs_simplified.a, q.a),\n", + " sp.Eq(rhs_simplified.b, q.b),\n", + " sp.Eq(rhs_simplified.c, q.c),\n", + " sp.Eq(rhs_simplified.d, q.d)\n", + " )\n" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 180 + }, + "id": "NIPpcbgG2FFc", + "outputId": "b00a9ad2-4391-4bcb-b6ac-96c74807852f" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "Eq(cos(p/2)*cos(theta_2/2), cos(alpha/2))" + ], + "text/latex": "$\\displaystyle \\cos{\\left(\\frac{p}{2} \\right)} \\cos{\\left(\\frac{\\theta_{2}}{2} \\right)} = \\cos{\\left(\\frac{\\alpha}{2} \\right)}$" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "Eq(-sin(m/2)*sin(theta_2/2), n_x*sin(alpha/2))" + ], + "text/latex": "$\\displaystyle - \\sin{\\left(\\frac{m}{2} \\right)} \\sin{\\left(\\frac{\\theta_{2}}{2} \\right)} = n_{x} \\sin{\\left(\\frac{\\alpha}{2} \\right)}$" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "Eq(sin(theta_2/2)*cos(m/2), n_y*sin(alpha/2))" + ], + "text/latex": "$\\displaystyle \\sin{\\left(\\frac{\\theta_{2}}{2} \\right)} \\cos{\\left(\\frac{m}{2} \\right)} = n_{y} \\sin{\\left(\\frac{\\alpha}{2} \\right)}$" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "Eq(sin(p/2)*cos(theta_2/2), n_z*sin(alpha/2))" + ], + "text/latex": "$\\displaystyle \\sin{\\left(\\frac{p}{2} \\right)} \\cos{\\left(\\frac{\\theta_{2}}{2} \\right)} = n_{z} \\sin{\\left(\\frac{\\alpha}{2} \\right)}$" + }, + "metadata": {} + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "This system can be solved by Sympy, but we obtain a rather ugly solution after a lot of computation time:" + ], + "metadata": { + "id": "aghJPoCB9hjY" + } + }, + { + "cell_type": "code", + "source": [ + "# sp.solve([q.a - rhs.a, q.b - rhs.b, q.c - rhs.c, q.d - rhs.d], theta1, theta2, theta3) # Using this we find a horrific-looking expression after quite some computation time..." + ], + "metadata": { + "id": "Vdb1iFW29mDL" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "Instead, assume $\\sin(p/2) \\neq 0$, then we can substitute in the first equation $\\cos\\left(\\theta_2/2\\right)$ with its value computed from the last equation. We get:" + ], + "metadata": { + "id": "V-3bhn-o3mnJ" + } + }, + { + "cell_type": "code", + "source": [ + "sp.trigsimp(sp.Eq(rhs_simplified.a, q.a).subs(sp.cos(theta2 / 2), nz * sp.sin(alpha / 2) / sp.sin(p / 2)))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 62 + }, + "id": "5a7du4SZ-eek", + "outputId": "608b4974-fffb-4bd8-fd13-56a597fbc0ef" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "Eq(n_z*sin(alpha/2)/tan(p/2), cos(alpha/2))" + ], + "text/latex": "$\\displaystyle \\frac{n_{z} \\sin{\\left(\\frac{\\alpha}{2} \\right)}}{\\tan{\\left(\\frac{p}{2} \\right)}} = \\cos{\\left(\\frac{\\alpha}{2} \\right)}$" + }, + "metadata": {}, + "execution_count": 21 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "Therefore\n", + "$$\n", + "p = \\theta_1 + \\theta_3 = 2 \\arctan \\left[n_z \\tan\n", + "\\left(\n", + "\\frac{\\alpha}{2} \\right)\\right]\n", + "$$" + ], + "metadata": { + "id": "kWWrouTT5z7_" + } + }, + { + "cell_type": "markdown", + "source": [ + "We can then deduce\n", + "$$\n", + "\\begin{array}{rl}\n", + "\\theta_2 & = 2 \\arccos \\left[ \\cos \\left(\\frac{\\alpha}{2}\\right) \\cos^{-1}\\left(\\frac{p}{2}\\right) \\right] \\\\\n", + "&= 2 \\arccos \\left[ \\cos\\left(\\frac{\\alpha}{2}\\right) \\sqrt{1 + n_z^2 \\tan^2 \\left(\n", + " \\frac{\\alpha}{2} \\right) } \\right] \\\\\n", + "\\end{array}\n", + "$$" + ], + "metadata": { + "id": "FbFJJtNSPgYX" + } + }, + { + "cell_type": "markdown", + "source": [ + "Using the third equation, we can finally deduce the value of $m$:\n", + "$$\n", + "m=\\theta_1 - \\theta_3 = 2\\arccos\\left[\\frac{ n_y \\sin\\left(\\frac{\\alpha}{2}\\right) } {\\sin\\left(\\frac{\\theta_2}{2}\\right)}\\right]\n", + "$$" + ], + "metadata": { + "id": "8xYQQeyjRcUd" + } + }, + { + "cell_type": "markdown", + "source": [ + "Let us put this into code..." + ], + "metadata": { + "id": "f3TqRkKTArZ1" + } + }, + { + "cell_type": "code", + "source": [ + "from typing import Tuple\n", + "\n", + "ATOL = 0.0001\n", + "\n", + "def theta123(alpha: float, axis: Tuple[float, float, float]):\n", + " \"\"\"\n", + " Gives the angles used in the Z-Y-Z decomposition of the Bloch sphere rotation\n", + " caracterized by a rotation around `axis` of angle `alpha`.\n", + "\n", + " Parameters:\n", + " alpha: angle of the Bloch sphere rotation\n", + " axis: _normalized_ axis of the Bloch sphere rotation\n", + "\n", + " Returns:\n", + " a triple (theta1, theta2, theta3) corresponding to the decomposition of the\n", + " arbitrary Bloch sphere rotation into U = rz(theta1) ry(theta2) rz(theta3)\n", + " \"\"\"\n", + "\n", + " # FIXME: there might (will) be edge cases where this crashes.\n", + "\n", + " nx, ny, nz = axis\n", + "\n", + " assert abs(nx**2 + ny**2 + nz**2 - 1) < ATOL, \"Axis needs to be normalized\"\n", + "\n", + " ta2 = math.tan(alpha / 2)\n", + "\n", + " theta2 = 2 * math.acos(math.cos(alpha / 2) * math.sqrt(1 + (nz * ta2) ** 2))\n", + "\n", + " p = 2 * math.atan(nz * ta2)\n", + "\n", + " m = 2 * math.acos(ny * math.sin(alpha / 2) / math.sin(theta2 / 2))\n", + "\n", + " theta1 = (p + m) / 2\n", + "\n", + " theta3 = p - theta1\n", + "\n", + " return (theta1, theta2, theta3)" + ], + "metadata": { + "id": "w_WCrbsgUIQx" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "Once we have our angles, we can implement the OpenSquirrel decomposition. This is done with a Python function (defined below) that takes an arbitrary `opensquirrel.squirrel_ir.Gate` object, and returns a list of gates. This function is applied internally to all gates of the circuit. Since 2-qubit gates should be left as-is, there is an `isinstance` check, to skip those.\n", + "\n", + "Also note that the axis of a `BlochSphereRotation` in OpenSquirrel is always normalized internally, and the `angle` should always be in the range $[-\\pi, \\pi]$.\n", + "\n", + "Here is what our final Z-Y-Z decomposition looks like:" + ], + "metadata": { + "id": "8Hq40VH_ITXw" + } + }, + { + "cell_type": "code", + "source": [ + "from opensquirrel.squirrel_ir import Gate, BlochSphereRotation\n", + "from opensquirrel.default_gates import rz, ry\n", + "\n", + "def zyz_decomposer(g: Gate):\n", + " if not isinstance(g, BlochSphereRotation):\n", + " return [g] # Do nothing.\n", + "\n", + " theta1, theta2, theta3 = theta123(g.angle, g.axis)\n", + "\n", + " z1 = rz(g.qubit, Float(theta1))\n", + " y = ry(g.qubit, Float(theta2))\n", + " z2 = rz(g.qubit, Float(theta3))\n", + "\n", + " # Note: written like this, the decomposition doesn't preserve the global phase, which is fine\n", + " # since the global phase is a physically irrelevant artifact of the mathematical\n", + " # model we use to describe the quantum system.\n", + "\n", + " # Should we want to preserve it, we would need to use a raw BlochSphereRotation, which would then\n", + " # be an anonymous gate in the resulting decomposed circuit:\n", + " # z2 = BlochSphereRotation(qubit=g.qubit, angle=theta3, axis=(0, 0, 1), phase = g.phase)\n", + "\n", + " return [z1, y, z2]" + ], + "metadata": { + "id": "PRdKQosJIoSB" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "Once we defined the decomposition function, we can apply it using the `opensquirrel.Circuit.decompose(decomposer=...)` method. The decomposition of every gate is checked, to see if it preserves the circuit semantics (_i.e._, the unitary matrix), so we can sleep on both ears knowing that our circuit/quantum state remains the same." + ], + "metadata": { + "id": "pzWUmE6wJ5PF" + } + }, + { + "cell_type": "code", + "source": [ + "circuit_to_decompose = os.Circuit.from_string(\"\"\"\n", + "version 3.0\n", + "\n", + "qubit[3] q\n", + "\n", + "h q[0]\n", + "\"\"\")\n", + "\n", + "circuit_to_decompose.merge_single_qubit_gates()\n", + "circuit_to_decompose.decompose(decomposer=zyz_decomposer)\n", + "circuit_to_decompose" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "HsyvBbAvKJJ0", + "outputId": "9738a81f-d149-41f1-abfb-deff29cbcb51" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "version 3.0\n", + "\n", + "qubit[3] q\n", + "\n", + "rz q[0], 3.1415927\n", + "ry q[0], 1.5707963\n", + "rz q[0], 0.0" + ] + }, + "metadata": {}, + "execution_count": 24 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "We get the expected result for the hadamard gate: $H = Y^{\\frac{1}{2}} Z$, one of the canonical decompositions of the Hadamard gate as described in the [Quantum Inspire knowledge base](https://www.quantum-inspire.com/kbase/hadamard/)." + ], + "metadata": { + "id": "NrDwe3WCne_3" + } + }, + { + "cell_type": "code", + "source": [ + "theta123(math.pi, (1/math.sqrt(2), 0, 1/math.sqrt(2)))" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "M9z9g6BMoNJA", + "outputId": "978544f7-4306-48d7-adce-b91c048ee13d" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "(3.141592653589793, 1.5707963267948966, 0.0)" + ] + }, + "metadata": {}, + "execution_count": 52 + } + ] + }, + { + "cell_type": "code", + "source": [ + "theta2" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "kmx4S_cep2nb", + "outputId": "b6290be3-178e-406e-b33b-3276012240c3" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "1.5707963267948966" + ] + }, + "metadata": {}, + "execution_count": 47 + } + ] + }, + { + "cell_type": "code", + "source": [ + "ny * math.sin(alpha / 2) / math.sin(theta2 / 2)" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Xtw7wzuWo7s0", + "outputId": "a06da422-4388-4ee2-e105-8a0fbd5c2d30" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "0.0" + ] + }, + "metadata": {}, + "execution_count": 51 + } + ] + }, + { + "cell_type": "code", + "source": [ + "theta2 = 2 * math.acos(math.cos(alpha / 2) * math.sqrt(1 + (nz * ta2) ** 2))\n", + "theta2" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5Qkm3C0Bo4S-", + "outputId": "279215aa-d77e-4257-fc34-c1a7e04f3490" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "1.5707963267948966" + ] + }, + "metadata": {}, + "execution_count": 31 + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "What happens when the gate set doesn't include `rz` and `ry`?" + ], + "metadata": { + "id": "cwHKdNPw3Ijd" + } + } + ] +} diff --git a/mkdocs.yaml b/mkdocs.yaml index 6862e7eb..dae0e75d 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -10,9 +10,15 @@ plugins: scripts: - scripts/gen_reference_page.py - mkdocstrings + - mkdocs-jupyter + +markdown_extensions: + - pymdownx.superfences + - pymdownx.tasklist + - pymdownx.tabbed nav: - OpenSquirrel: index.md - - Tutorials: tutorials.md + - Tutorial: tutorial.ipynb - How-To Guides: how-to-guides.md - Reference: reference.md diff --git a/opensquirrel/circuit.py b/opensquirrel/circuit.py index 4633ba1c..346fcd43 100644 --- a/opensquirrel/circuit.py +++ b/opensquirrel/circuit.py @@ -34,6 +34,7 @@ class Circuit: rz q[0], 1.5707963 x90 q[0] + """ def __init__(self, squirrel_ir: SquirrelIR): @@ -65,10 +66,7 @@ def from_string( use_libqasm: if True, use libqasm instead of build-in ANTLR parser. Note: those two separate implementations may diverge and libqasm should be taken as reference. - Returns: - A Circuit object corresponding to the input string. Throws on parsing errors. """ - if use_libqasm: libqasm_ir_creator = LibqasmIRCreator(gate_set=gate_set, gate_aliases=gate_aliases) return Circuit(libqasm_ir_creator.squirrel_ir_from_string(cqasm3_string)) diff --git a/docs/explanation.md b/opensquirrel/export/__init__.py similarity index 100% rename from docs/explanation.md rename to opensquirrel/export/__init__.py diff --git a/poetry.lock b/poetry.lock index 235341e9..808165ad 100644 --- a/poetry.lock +++ b/poetry.lock @@ -167,16 +167,26 @@ pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] [[package]] -name = "backcall" -version = "0.2.0" -description = "Specifications for callback functions passed in to an API" +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" optional = false -python-versions = "*" +python-versions = ">=3.6.0" files = [ - {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, - {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, ] +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + [[package]] name = "black" version = "24.2.0" @@ -223,6 +233,24 @@ d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "bleach" +version = "6.1.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, + {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, +] + +[package.dependencies] +six = ">=1.9.0" +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.3)"] + [[package]] name = "broadbean" version = "0.11.0" @@ -647,43 +675,43 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "42.0.3" +version = "42.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:de5086cd475d67113ccb6f9fae6d8fe3ac54a4f9238fd08bfdb07b03d791ff0a"}, - {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:935cca25d35dda9e7bd46a24831dfd255307c55a07ff38fd1a92119cffc34857"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20100c22b298c9eaebe4f0b9032ea97186ac2555f426c3e70670f2517989543b"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eb6368d5327d6455f20327fb6159b97538820355ec00f8cc9464d617caecead"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39d5c93e95bcbc4c06313fc6a500cee414ee39b616b55320c1904760ad686938"}, - {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d96ea47ce6d0055d5b97e761d37b4e84195485cb5a38401be341fabf23bc32a"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d1998e545081da0ab276bcb4b33cce85f775adb86a516e8f55b3dac87f469548"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93fbee08c48e63d5d1b39ab56fd3fdd02e6c2431c3da0f4edaf54954744c718f"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90147dad8c22d64b2ff7331f8d4cddfdc3ee93e4879796f837bdbb2a0b141e0c"}, - {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4dcab7c25e48fc09a73c3e463d09ac902a932a0f8d0c568238b3696d06bf377b"}, - {file = "cryptography-42.0.3-cp37-abi3-win32.whl", hash = "sha256:1e935c2900fb53d31f491c0de04f41110351377be19d83d908c1fd502ae8daa5"}, - {file = "cryptography-42.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:762f3771ae40e111d78d77cbe9c1035e886ac04a234d3ee0856bf4ecb3749d54"}, - {file = "cryptography-42.0.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3ec384058b642f7fb7e7bff9664030011ed1af8f852540c76a1317a9dd0d20"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35772a6cffd1f59b85cb670f12faba05513446f80352fe811689b4e439b5d89e"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04859aa7f12c2b5f7e22d25198ddd537391f1695df7057c8700f71f26f47a129"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c3d1f5a1d403a8e640fa0887e9f7087331abb3f33b0f2207d2cc7f213e4a864c"}, - {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df34312149b495d9d03492ce97471234fd9037aa5ba217c2a6ea890e9166f151"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:de4ae486041878dc46e571a4c70ba337ed5233a1344c14a0790c4c4be4bbb8b4"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0fab2a5c479b360e5e0ea9f654bcebb535e3aa1e493a715b13244f4e07ea8eec"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25b09b73db78facdfd7dd0fa77a3f19e94896197c86e9f6dc16bce7b37a96504"}, - {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d5cf11bc7f0b71fb71af26af396c83dfd3f6eed56d4b6ef95d57867bf1e4ba65"}, - {file = "cryptography-42.0.3-cp39-abi3-win32.whl", hash = "sha256:0fea01527d4fb22ffe38cd98951c9044400f6eff4788cf52ae116e27d30a1ba3"}, - {file = "cryptography-42.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:2619487f37da18d6826e27854a7f9d4d013c51eafb066c80d09c63cf24505306"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ead69ba488f806fe1b1b4050febafdbf206b81fa476126f3e16110c818bac396"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:20180da1b508f4aefc101cebc14c57043a02b355d1a652b6e8e537967f1e1b46"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fbf0f3f0fac7c089308bd771d2c6c7b7d53ae909dce1db52d8e921f6c19bb3a"}, - {file = "cryptography-42.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c23f03cfd7d9826cdcbad7850de67e18b4654179e01fe9bc623d37c2638eb4ef"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db0480ffbfb1193ac4e1e88239f31314fe4c6cdcf9c0b8712b55414afbf80db4"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:6c25e1e9c2ce682d01fc5e2dde6598f7313027343bd14f4049b82ad0402e52cd"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9541c69c62d7446539f2c1c06d7046aef822940d248fa4b8962ff0302862cc1f"}, - {file = "cryptography-42.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b797099d221df7cce5ff2a1d272761d1554ddf9a987d3e11f6459b38cd300fd"}, - {file = "cryptography-42.0.3.tar.gz", hash = "sha256:069d2ce9be5526a44093a0991c450fe9906cdf069e0e7cd67d9dee49a62b9ebe"}, + {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449"}, + {file = "cryptography-42.0.4-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b"}, + {file = "cryptography-42.0.4-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824"}, + {file = "cryptography-42.0.4-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b"}, + {file = "cryptography-42.0.4-cp37-abi3-win32.whl", hash = "sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925"}, + {file = "cryptography-42.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923"}, + {file = "cryptography-42.0.4-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9"}, + {file = "cryptography-42.0.4-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929"}, + {file = "cryptography-42.0.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0"}, + {file = "cryptography-42.0.4-cp39-abi3-win32.whl", hash = "sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129"}, + {file = "cryptography-42.0.4-cp39-abi3-win_amd64.whl", hash = "sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20"}, + {file = "cryptography-42.0.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b"}, + {file = "cryptography-42.0.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660"}, + {file = "cryptography-42.0.4.tar.gz", hash = "sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb"}, ] [package.dependencies] @@ -789,6 +817,17 @@ ordered-set = ">=4.0.2,<4.2.0" cli = ["click (==8.1.3)", "pyyaml (==6.0.1)"] optimize = ["orjson"] +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "dill" version = "0.3.8" @@ -929,12 +968,13 @@ woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] [[package]] name = "future" -version = "0.18.3" +version = "1.0.0" description = "Clean single-source support for Python 3 and 2" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ - {file = "future-0.18.3.tar.gz", hash = "sha256:34a17436ed1e96697a86f9de3d15a3b0be01d8bc8de9c1dffd59fb8234ed5307"}, + {file = "future-1.0.0-py3-none-any.whl", hash = "sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216"}, + {file = "future-1.0.0.tar.gz", hash = "sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05"}, ] [[package]] @@ -978,13 +1018,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-auth" -version = "2.28.0" +version = "2.28.1" description = "Google Authentication Library" optional = false python-versions = ">=3.7" files = [ - {file = "google-auth-2.28.0.tar.gz", hash = "sha256:3cfc1b6e4e64797584fb53fc9bd0b7afa9b7c0dba2004fa7dcc9349e58cc3195"}, - {file = "google_auth-2.28.0-py2.py3-none-any.whl", hash = "sha256:7634d29dcd1e101f5226a23cbc4a0c6cda6394253bf80e281d9c5c6797869c53"}, + {file = "google-auth-2.28.1.tar.gz", hash = "sha256:34fc3046c257cedcf1622fc4b31fc2be7923d9b4d44973d481125ecc50d83885"}, + {file = "google_auth-2.28.1-py2.py3-none-any.whl", hash = "sha256:25141e2d7a14bfcba945f5e9827f98092716e99482562f15306e5b026e21aa72"}, ] [package.dependencies] @@ -1202,42 +1242,40 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio [[package]] name = "ipython" -version = "8.12.3" +version = "8.18.1" description = "IPython: Productive Interactive Computing" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "ipython-8.12.3-py3-none-any.whl", hash = "sha256:b0340d46a933d27c657b211a329d0be23793c36595acf9e6ef4164bc01a1804c"}, - {file = "ipython-8.12.3.tar.gz", hash = "sha256:3910c4b54543c2ad73d06579aa771041b7d5707b033bd488669b4cf544e3b363"}, + {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, + {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, ] [package.dependencies] -appnope = {version = "*", markers = "sys_platform == \"darwin\""} -backcall = "*" colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -pickleshare = "*" -prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" +prompt-toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" stack-data = "*" traitlets = ">=5" typing-extensions = {version = "*", markers = "python_version < \"3.10\""} [package.extras] -all = ["black", "curio", "docrepr", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.21)", "pandas", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] black = ["black"] -doc = ["docrepr", "ipykernel", "matplotlib", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] +test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] [[package]] name = "ipywidgets" @@ -1323,9 +1361,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} jsonschema-specifications = ">=2023.03.6" -pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} referencing = ">=0.28.4" rpds-py = ">=0.7.1" @@ -1345,7 +1381,6 @@ files = [ ] [package.dependencies] -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} referencing = ">=0.31.0" [[package]] @@ -1391,6 +1426,17 @@ traitlets = ">=5.3" docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +description = "Pygments theme using JupyterLab CSS variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, +] + [[package]] name = "jupyterlab-widgets" version = "3.0.10" @@ -1402,6 +1448,35 @@ files = [ {file = "jupyterlab_widgets-3.0.10.tar.gz", hash = "sha256:04f2ac04976727e4f9d0fa91cdc2f1ab860f965e504c29dbd6a65c882c9d04c0"}, ] +[[package]] +name = "jupytext" +version = "1.16.1" +description = "Jupyter notebooks as Markdown documents, Julia, Python or R scripts" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupytext-1.16.1-py3-none-any.whl", hash = "sha256:796ec4f68ada663569e5d38d4ef03738a01284bfe21c943c485bc36433898bd0"}, + {file = "jupytext-1.16.1.tar.gz", hash = "sha256:68c7b68685e870e80e60fda8286fbd6269e9c74dc1df4316df6fe46eabc94c99"}, +] + +[package.dependencies] +markdown-it-py = ">=1.0" +mdit-py-plugins = "*" +nbformat = "*" +packaging = "*" +pyyaml = "*" +toml = "*" + +[package.extras] +dev = ["jupytext[test-cov,test-external]"] +docs = ["myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] +test = ["pytest", "pytest-randomly", "pytest-xdist"] +test-cov = ["jupytext[test-integration]", "pytest-cov (>=2.6.1)"] +test-external = ["autopep8", "black", "flake8", "gitpython", "isort", "jupyter-fs (<0.4.0)", "jupytext[test-integration]", "pre-commit", "sphinx-gallery (<0.8)"] +test-functional = ["jupytext[test]"] +test-integration = ["ipykernel", "jupyter-server (!=2.11)", "jupytext[test-functional]", "nbconvert"] +test-ui = ["calysto-bash"] + [[package]] name = "kiwisolver" version = "1.4.5" @@ -1812,6 +1887,25 @@ files = [ [package.dependencies] traitlets = "*" +[[package]] +name = "mdit-py-plugins" +version = "0.4.0" +description = "Collection of plugins for markdown-it-py" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"}, + {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"}, +] + +[package.dependencies] +markdown-it-py = ">=1.0.0,<4.0.0" + +[package.extras] +code-style = ["pre-commit"] +rtd = ["myst-parser", "sphinx-book-theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + [[package]] name = "mdurl" version = "0.1.2" @@ -1851,6 +1945,17 @@ wirerope = ">=0.4.7" doc = ["sphinx"] test = ["functools32 (>=3.2.3-2)", "pytest (>=4.6.7)", "pytest-cov (>=2.6.1)"] +[[package]] +name = "mistune" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, +] + [[package]] name = "mkdocs" version = "1.5.3" @@ -1911,6 +2016,25 @@ files = [ [package.dependencies] mkdocs = ">=1.0.3" +[[package]] +name = "mkdocs-jupyter" +version = "0.24.6" +description = "Use Jupyter in mkdocs websites" +optional = false +python-versions = ">=3.9" +files = [ + {file = "mkdocs_jupyter-0.24.6-py3-none-any.whl", hash = "sha256:56fb7ad796f2414a4143d54a966b805caf315c32413e97f85591623fa87dceca"}, + {file = "mkdocs_jupyter-0.24.6.tar.gz", hash = "sha256:89fcbe8a9523864d5416de1a60711640b6bc2972279d2adf46ed2776c2d9ff7c"}, +] + +[package.dependencies] +ipykernel = ">6.0.0,<7.0.0" +jupytext = ">1.13.8,<2" +mkdocs = ">=1.4.0,<2" +mkdocs-material = ">9.0.0" +nbconvert = ">=7.2.9,<8" +pygments = ">2.12.0" + [[package]] name = "mkdocs-material" version = "9.5.10" @@ -1997,22 +2121,22 @@ mkdocstrings = ">=0.20" [[package]] name = "msal" -version = "1.26.0" +version = "1.27.0" description = "The Microsoft Authentication Library (MSAL) for Python library enables your app to access the Microsoft Cloud by supporting authentication of users with Microsoft Azure Active Directory accounts (AAD) and Microsoft Accounts (MSA) using industry standard OAuth2 and OpenID Connect." optional = false python-versions = ">=2.7" files = [ - {file = "msal-1.26.0-py2.py3-none-any.whl", hash = "sha256:be77ba6a8f49c9ff598bbcdc5dfcf1c9842f3044300109af738e8c3e371065b5"}, - {file = "msal-1.26.0.tar.gz", hash = "sha256:224756079fe338be838737682b49f8ebc20a87c1c5eeaf590daae4532b83de15"}, + {file = "msal-1.27.0-py2.py3-none-any.whl", hash = "sha256:572d07149b83e7343a85a3bcef8e581167b4ac76befcbbb6eef0c0e19643cdc0"}, + {file = "msal-1.27.0.tar.gz", hash = "sha256:3109503c038ba6b307152b0e8d34f98113f2e7a78986e28d0baf5b5303afda52"}, ] [package.dependencies] -cryptography = ">=0.6,<44" +cryptography = ">=0.6,<45" PyJWT = {version = ">=1.0.0,<3", extras = ["crypto"]} requests = ">=2.0.0,<3" [package.extras] -broker = ["pymsalruntime (>=0.13.2,<0.14)"] +broker = ["pymsalruntime (>=0.13.2,<0.15)"] [[package]] name = "msal-extensions" @@ -2091,6 +2215,87 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "nbclient" +version = "0.9.0" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "nbclient-0.9.0-py3-none-any.whl", hash = "sha256:a3a1ddfb34d4a9d17fc744d655962714a866639acd30130e9be84191cd97cd15"}, + {file = "nbclient-0.9.0.tar.gz", hash = "sha256:4b28c207877cf33ef3a9838cdc7a54c5ceff981194a82eac59d558f05487295e"}, +] + +[package.dependencies] +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +nbformat = ">=5.1" +traitlets = ">=5.4" + +[package.extras] +dev = ["pre-commit"] +docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] + +[[package]] +name = "nbconvert" +version = "7.16.1" +description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbconvert-7.16.1-py3-none-any.whl", hash = "sha256:3188727dffadfdc9c6a1c7250729063d7bc78b355ad7aa023138afa030d1cd07"}, + {file = "nbconvert-7.16.1.tar.gz", hash = "sha256:e79e6a074f49ba3ed29428ed86487bf51509d9aab613bd8522ac08f6d28fd7fd"}, +] + +[package.dependencies] +beautifulsoup4 = "*" +bleach = "!=5.0.0" +defusedxml = "*" +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<4" +nbclient = ">=0.5.0" +nbformat = ">=5.7" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +tinycss2 = "*" +traitlets = ">=5.1" + +[package.extras] +all = ["nbconvert[docs,qtpdf,serve,test,webpdf]"] +docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] +qtpdf = ["nbconvert[qtpng]"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest"] +webpdf = ["playwright"] + +[[package]] +name = "nbformat" +version = "5.9.2" +description = "The Jupyter Notebook format" +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbformat-5.9.2-py3-none-any.whl", hash = "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9"}, + {file = "nbformat-5.9.2.tar.gz", hash = "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192"}, +] + +[package.dependencies] +fastjsonschema = "*" +jsonschema = ">=2.6" +jupyter-core = "*" +traitlets = ">=5.1" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["pep440", "pre-commit", "pytest", "testpath"] + [[package]] name = "nest-asyncio" version = "1.6.0" @@ -2406,6 +2611,17 @@ sql-other = ["SQLAlchemy (>=1.4.16)"] test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.6.3)"] +[[package]] +name = "pandocfilters" +version = "1.5.1" +description = "Utilities for writing pandoc filters in python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, + {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, +] + [[package]] name = "parso" version = "0.8.3" @@ -2461,17 +2677,6 @@ files = [ [package.dependencies] ptyprocess = ">=0.5" -[[package]] -name = "pickleshare" -version = "0.7.5" -description = "Tiny 'shelve'-like database with concurrency support" -optional = false -python-versions = "*" -files = [ - {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, - {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, -] - [[package]] name = "pillow" version = "10.2.0" @@ -2557,17 +2762,6 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa typing = ["typing-extensions"] xmp = ["defusedxml"] -[[package]] -name = "pkgutil-resolve-name" -version = "1.3.10" -description = "Resolve a name to an object." -optional = false -python-versions = ">=3.6" -files = [ - {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, - {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, -] - [[package]] name = "platformdirs" version = "4.2.0" @@ -3149,6 +3343,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3438,13 +3633,13 @@ test = ["pytest", "pytest-mock"] [[package]] name = "quantify-scheduler" -version = "0.18.0" +version = "0.18.1" description = "Quantify-scheduler is a Python package for writing quantum programs featuring a hybrid gate-pulse control model with explicit timing control." optional = false python-versions = "<3.10,>=3.8" files = [ - {file = "quantify-scheduler-0.18.0.tar.gz", hash = "sha256:abe59400cba445cefb1eded93a88832ae396232ca00b7292fab2dd7506023aa1"}, - {file = "quantify_scheduler-0.18.0-py3-none-any.whl", hash = "sha256:20c76974ce4a11697e3a415e755a1b6c182f81c8ff54d0de82992fe00acf0eba"}, + {file = "quantify-scheduler-0.18.1.tar.gz", hash = "sha256:9570fd200359841a1cd709a4a6316c96a730329b19c6f6e5860034a864dff2ad"}, + {file = "quantify_scheduler-0.18.1-py3-none-any.whl", hash = "sha256:a61f6baf1a82f46d22d47b3fe022947e940f315fac36f4faaed1467951c415fc"}, ] [package.dependencies] @@ -3465,7 +3660,6 @@ qcodes = ">=0.32.0" quantify-core = ">=0.7.1" rich = {version = "*", extras = ["jupyter"]} scipy = "*" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} xxhash = "*" zhinst = "21.8.20515" zhinst-qcodes = "0.1.4" @@ -3473,7 +3667,7 @@ zhinst-toolkit = "0.1.5" [package.extras] dev = ["black", "coverage", "pre-commit", "pre-commit-hooks", "prospector", "pyright (!=1.1.309)", "pytest-cov", "pytest-xdist", "quantify-scheduler[docs,test]", "ruff", "sphinx-autobuild"] -docs = ["astroid (<3.0)", "hvplot", "jupyter-sphinx (>=0.4.0)", "jupytext", "myst-nb", "pydata-sphinx-theme", "pylint", "rich[jupyter]", "scanpydoc", "sphinx", "sphinx-autoapi", "sphinx-autodoc-typehints", "sphinx-design", "sphinx-jsonschema", "sphinx-togglebutton", "sphinxcontrib-bibtex"] +docs = ["astroid (<3.0)", "hvplot", "jupyter-sphinx (>=0.4.0)", "jupytext", "myst-nb", "pydata-sphinx-theme", "pylint", "rich[jupyter]", "scanpydoc (<0.12)", "sphinx", "sphinx-autoapi", "sphinx-autodoc-typehints", "sphinx-design", "sphinx-jsonschema", "sphinx-togglebutton", "sphinxcontrib-bibtex"] test = ["pytest", "pytest-mock"] [[package]] @@ -3937,6 +4131,17 @@ files = [ {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, ] +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + [[package]] name = "spirack" version = "0.2.4" @@ -3999,6 +4204,35 @@ files = [ [package.extras] doc = ["reno", "sphinx", "tornado (>=4.5)"] +[[package]] +name = "tinycss2" +version = "1.2.1" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, + {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["flake8", "isort", "pytest"] + +[[package]] +name = "toml" +version = "0.10.2" +description = "Python Library for Tom's Obvious, Minimal Language" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, +] + [[package]] name = "tomli" version = "2.0.1" @@ -4218,6 +4452,17 @@ files = [ {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, ] +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + [[package]] name = "websockets" version = "12.0" @@ -4630,4 +4875,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "c5fd139f6c8fd042fb14b443e8219153953176a49bbceb41ddeee280112ef695" +content-hash = "bc1c5db66c8fc46f3c6e62a2838165bd23c72051993fda5538a2a9064b874da9" diff --git a/pyproject.toml b/pyproject.toml index bc4b2074..d2bedfcb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,10 +37,6 @@ numpy = [ { version = "1.24", python = "<3.9" }, { version = "^1.26", python = "^3.9" }, ] -mkdocs = {extras = ["python"], version = "^1.5.3"} -mkdocstrings = {extras = ["python"], version = "^0.24.0"} -mkdocs_gen_files = {extras = ["python"], version = "^0.5.0"} -mkdocs-material = "^9.4.12" libqasm = "0.5.2" pyqt5-qt5=[ # This package is a transitive dependency of quantify-scheduler. @@ -59,6 +55,12 @@ quantify-scheduler=[ black = ">=23.11,<25.0" coverage = {extras = ["toml"], version = "^7.3.2"} isort = "^5.11.4" +mkdocs = {extras = ["python"], version = "^1.5.3"} +mkdocstrings = {extras = ["python"], version = "^0.24.0"} +mkdocs_gen_files = {extras = ["python"], version = "^0.5.0"} +mkdocs-material = "^9.4.12" +mkdocs-jupyter = {version = "0.24.6", python = ">=3.9,<4.0"} +pymdown-extensions = "^10.7" pytest = {extras = ["toml"], version = ">=7.4.3,<9.0.0"} pytest-cov = "^4.1.0" mypy = "^1.7.0"