From c9d62f6268fa8512175351da614facee2ac594ea Mon Sep 17 00:00:00 2001 From: Megan <42215983+mlk621@users.noreply.github.com> Date: Tue, 13 Dec 2022 13:46:53 -0600 Subject: [PATCH 01/17] add example compiling for QTM hardware without querying the API --- examples/Quantinuum_compile_without_api.ipynb | 1 + examples/maintained-notebooks.txt | 1 + .../python/Quantinuum_compile_without_api.py | 48 +++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 examples/Quantinuum_compile_without_api.ipynb create mode 100644 examples/python/Quantinuum_compile_without_api.py diff --git a/examples/Quantinuum_compile_without_api.ipynb b/examples/Quantinuum_compile_without_api.ipynb new file mode 100644 index 00000000..6b5d84b9 --- /dev/null +++ b/examples/Quantinuum_compile_without_api.ipynb @@ -0,0 +1 @@ +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# Compiling for Quantinuum Hardware without Querying Quantinuum API"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains an example of how to investigate circuits compiled for Quantinuum hardware without logging in or submitting to Quantinuum hardware. This may be useful if it is desired to explore circuit compilation in depth before submitting."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Circuit Preparation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create your circuit."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, OpType\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Set up Backend"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up a `QuantinuumBackend` object. The difference is the `machine_debug` option uses the default `pytket-quantinuum` options such as pytket's version of the Quantinuum native gate set rather than querying the Quantinuum API for this information."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine, machine_debug=True)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Investigate Native Gate Set"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Users can view the hard-coded native gate set for the Quantinuum backend using the following command."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import pytket.extensions.quantinuum.backends.quantinuum as qtm"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(qtm._GATE_SET)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["It's possible that the hardcoded verion is not up to date with the latest native gate set as described in the [System Model H1 Product Data Sheet](https://www.quantinuum.com/hardware/h1). In this case, the Rzz gate, which is the `ZZPhase` gate in pytket, is missing. This can be added by running the following command."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qtm._GATE_SET.add(OpType.ZZPhase)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Circuits can now be compiled with the `get_compiled_circuit` function without querying the Quantinuum API."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=2)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file diff --git a/examples/maintained-notebooks.txt b/examples/maintained-notebooks.txt index a65e00cf..c8e2b516 100644 --- a/examples/maintained-notebooks.txt +++ b/examples/maintained-notebooks.txt @@ -2,3 +2,4 @@ Quantinuum_circuit_submissions Quantinuum_emulator Quantinuum_mid-circuit_measurement Quantinuum_arbitrary_zz +Quantinuum_compile_without_api diff --git a/examples/python/Quantinuum_compile_without_api.py b/examples/python/Quantinuum_compile_without_api.py new file mode 100644 index 00000000..1a4e162b --- /dev/null +++ b/examples/python/Quantinuum_compile_without_api.py @@ -0,0 +1,48 @@ +# # Compiling for Quantinuum Hardware without Querying Quantinuum API + +# This notebook contains an example of how to investigate circuits compiled for Quantinuum hardware without logging in or submitting to Quantinuum hardware. This may be useful if it is desired to explore circuit compilation in depth before submitting. + +# ## Circuit Preparation + +# Create your circuit. + +from pytket.circuit import Circuit, OpType +from pytket.circuit.display import render_circuit_jupyter + +circuit = Circuit(2, name="Bell Test") +circuit.H(0) +circuit.CX(0, 1) +circuit.measure_all() + +render_circuit_jupyter(circuit) + +# ## Set up Backend + +# Set up a `QuantinuumBackend` object. The difference is the `machine_debug` option uses the default `pytket-quantinuum` options such as pytket's version of the Quantinuum native gate set rather than querying the Quantinuum API for this information. + +from pytket.extensions.quantinuum import QuantinuumBackend + +machine = "H1-1E" +backend = QuantinuumBackend(device_name=machine, machine_debug=True) + +# ## Investigate Native Gate Set + +# Users can view the hard-coded native gate set for the Quantinuum backend using the following command. + +import pytket.extensions.quantinuum.backends.quantinuum as qtm + +print(qtm._GATE_SET) + +# It's possible that the hardcoded verion is not up to date with the latest native gate set as described in the [System Model H1 Product Data Sheet](https://www.quantinuum.com/hardware/h1). In this case, the Rzz gate, which is the `ZZPhase` gate in pytket, is missing. This can be added by running the following command. + +qtm._GATE_SET.add(OpType.ZZPhase) + +# ### Circuit Compilation + +# Circuits can now be compiled with the `get_compiled_circuit` function without querying the Quantinuum API. + +compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=2) + +render_circuit_jupyter(compiled_circuit) + +#
© 2022 by Quantinuum. All Rights Reserved.
From 4d2f0c5453ff468c4bdd246fc912c0a1d20ef8d2 Mon Sep 17 00:00:00 2001 From: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:09:58 +0000 Subject: [PATCH 02/17] Support Python {3.9, 3.10, 3.11} (#97) --- .github/workflows/build_and_test.yml | 24 +++++++++---------- .github/workflows/check-examples.yml | 2 +- .github/workflows/docs.yml | 7 +++--- README.md | 2 +- docs/changelog.rst | 4 ++++ docs/intro.txt | 2 +- examples/Quantinuum_circuit_submissions.ipynb | 2 +- .../python/Quantinuum_circuit_submissions.py | 2 +- mypy.ini | 2 +- setup.py | 6 ++--- 10 files changed, 28 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index ffc21baf..14bf9456 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -34,40 +34,40 @@ jobs: with: fetch-depth: '0' - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/* - - name: Set up Python 3.8 + - name: Set up Python 3.9 if: github.event_name == 'push' || github.event_name == 'schedule' uses: actions/setup-python@v4 with: - python-version: '3.8' - - name: Build and test (3.8) + python-version: '3.9' + - name: Build and test (3.9) if: github.event_name == 'push' || github.event_name == 'schedule' shell: bash run: | ./.github/workflows/build-test nomypy - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: '3.9' - - name: Build and test including remote checks (3.9) mypy + python-version: '3.10' + - name: Build and test including remote checks (3.10) mypy shell: bash if: (matrix.os == 'macos-12') && (github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || github.event_name == 'release' || github.event_name == 'schedule' ) run: | ./.github/workflows/build-test mypy env: PYTKET_RUN_REMOTE_TESTS: 1 - - name: Build and test including remote checks (3.9) nomypy + - name: Build and test including remote checks (3.10) nomypy if: (matrix.os != 'macos-12') && (github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || github.event_name == 'release' || github.event_name == 'schedule') shell: bash run: | ./.github/workflows/build-test nomypy env: PYTKET_RUN_REMOTE_TESTS: 1 - - name: Set up Python 3.10 + - name: Set up Python 3.11 if: github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'schedule' uses: actions/setup-python@v4 with: - python-version: '3.10' - - name: Build and test (3.10) + python-version: '3.11' + - name: Build and test (3.11) if: github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'schedule' shell: bash run: | @@ -118,10 +118,10 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: '0' - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.10' - name: Download all wheels uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/check-examples.yml b/.github/workflows/check-examples.yml index c613a778..a13f0b25 100644 --- a/.github/workflows/check-examples.yml +++ b/.github/workflows/check-examples.yml @@ -39,7 +39,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - python-version: ['3.8', '3.9', '3.10'] + python-version: ['3.9', '3.10', '3.11'] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e5445f92..c07131d7 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -13,15 +13,14 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: 3.10 - name: Upgrade pip and install wheel run: pip install --upgrade pip wheel - name: Install pytket quantinuum - run: | - pip install . + run: pip install . - name: Install docs dependencies run: | pip install -r .github/workflows/docs/requirements.txt diff --git a/README.md b/README.md index c12c658d..1adcc312 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ be executed on Quantinuum's quantum devices. ## Getting started -`pytket-quantinuum` is available for Python 3.8, 3.9 and 3.10, on Linux, MacOS +`pytket-quantinuum` is available for Python 3.9, 3.10 and 3.11, on Linux, MacOS and Windows. To install, run: ```pip install pytket-quantinuum``` diff --git a/docs/changelog.rst b/docs/changelog.rst index 98c7c828..626480ee 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,10 @@ Changelog ~~~~~~~~~ +Unreleased +---------- + +* Drop support for Python 3.8; add support for 3.11. 0.12.0 (December 2022) ---------------------- diff --git a/docs/intro.txt b/docs/intro.txt index 42ff8ced..85dfd2de 100644 --- a/docs/intro.txt +++ b/docs/intro.txt @@ -4,7 +4,7 @@ pytket-quantinuum ``pytket-quantinuum`` is an extension to ``pytket`` that allows ``pytket`` circuits to be executed on Quantinuum's quantum devices. -``pytket-quantinuum`` is available for Python 3.8, 3.9 and 3.10, on Linux, MacOS +``pytket-quantinuum`` is available for Python 3.9, 3.10 and 3.11, on Linux, MacOS and Windows. To install, run: :: diff --git a/examples/Quantinuum_circuit_submissions.ipynb b/examples/Quantinuum_circuit_submissions.ipynb index 45f219dd..9bc224db 100644 --- a/examples/Quantinuum_circuit_submissions.ipynb +++ b/examples/Quantinuum_circuit_submissions.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Quantinuum Circuit Submissions via pytket"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains basic circuit submission examples to Quantinuum quantum hardware via `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [What is TKET?](#tket)
\n", "* [Step by Step](#step-by-step)
\n", " * [Circuit Preparation](#circuit-preparation)
\n", " * [Select Device](#select-device)
\n", " * [Circuit Compilation](#circuit-compilation)
\n", " * [Circuit Cost](#circuit-cost)
\n", " * [Run the Circuit](#run-circuit)
\n", " * [Retrieve Results](#retrieve-results)
\n", " * [Save Results](#save-results)
\n", " * [Analyze Results](#analyze-results)
\n", " * [Cancel Jobs](#cancel-jobs)
\n", "* [Additional Features](#additional-features)
\n", " * [Extended Circuit Compilation](#circuit-compilation-extended)
\n", " * [Batch Submission](#batch-submission)
\n", " * [Parametrized Circuits](#parametrized-circuits)
\n", " * [Conditional Gates](#conditional-gates)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## What is TKET? "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The TKET framework (pronounced \"ticket\") is a software platform for the development and execution of gate-level quantum computation, providing state-of-the-art performance in circuit compilation. It was created and is maintained by Quantinuum. The toolset is designed to extract the most out of the available NISQ devices of today and is platform-agnostic."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In python, the `pytket` packages is available for python 3.8+. The `pytket` and `pytket-quantinuum` packages are included as part of the installation instructions on the user portal."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information on TKET, see the following links:
\n", "- [TKET manual](https://cqcl.github.io/pytket/manual/manual_intro.html)
\n", "- [TKET overview and demo video](https://www.youtube.com/watch?v=yXKSpvgAtrk)
\n", "- [Introduction to Quantum Compilation with TKET](https://github.com/CalMacCQ/tket_blog/blob/main/blog1_intro_to_qc.ipynb)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook covers how to use `pytket` in conjunction with `pytket-quantinuum` to submit to Quantinuum devices. The quantum compilation step is demonstrated, but for a full overview of quantum compilation with TKET, the last link above is recommended."]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the links below for the `pytket` and `pytket-quantinuum` documentation:
\n", "- [pytket](https://cqcl.github.io/tket/pytket/api/index.html)
\n", "- [pytket-quantinuum](https://cqcl.github.io/pytket-quantinuum/api/index.html)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Step by Step "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Preparation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create your circuit via the pytket python library. For details on getting started with `pytket`, see pytket's [Getting Started](https://cqcl.github.io/tket/pytket/api/getting_started.html) page."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note**: `pytket` renders circuits in ZX-calculus notation. This can be toggled on and off by pressing the top left button in the circuit display."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, fresh_symbol\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up Bell Test"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Select Device "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Select a machine and login to the Quantinuum API using your credentials. See the *Quantinuum Systems User Guide* in the *Examples* tab on the *Quantinuum User Portal* for information and target names for each of the H-Series systems available."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Users need to login once per session. In the notebook, a dialogue box will ask for credentials. If running a script, users be prompted at the shell. You can also [save your email in the pytket config](https://cqcl.github.io/pytket-extensions/api/quantinuum/api.html#pytket.extensions.quantinuum.backends.config.set_quantinuum_config)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The device status can be checked using `device_state`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", QuantinuumBackend.device_state(device_name=machine))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Available devices can be viewed using the `available_devices` function. Additional information is returned, here just the device names are pulled in."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["[x.device_name for x in QuantinuumBackend.available_devices()]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Circuits submitted to Quantinuum H-Series quantum computers and emulators are automatically run through TKET compilation passes for H-Series hardware. This enables circuits to be automatically optimized for H-Series systems and run more efficiently."]}, {"cell_type": "markdown", "metadata": {}, "source": ["More information on the specific compilation passes applied can be found on the `pytket-quantinuum` documentation, specifically the [Default Compilation](https://cqcl.github.io/pytket-quantinuum/api/index.html#default-compilation) section. In the H-Series software stack, the optimization level applied is set with the `tket-opt-level` parameter. **The default compilation setting for circuits submited to H-Series sytems is optimization level 2.** More information is found in the *Quantinuum Application Programming Interface (API) Specification*."]}, {"cell_type": "markdown", "metadata": {}, "source": ["When using `pytket` before submitting to hardware, the `get_compiled_circuit` function performs the same compilation passes run after submission to Quantinuum systems. The advantage of using the function before submitting to H-Series hardware is to see exactly what circuit optimizations will be performed when submitted to hardware and determine if a different optimization level is desired. The `optimisation_level` parameter in the `get_compiled_circuit` function corresponds directly to the the level of optimisation after submitting to the H-Series systems and to the `tket-opt-level` parameter in the H-Series API. The default compilation for the `get_compiled_circuit` function is optimization level 2, the same as when submitting to the H-Series directly."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Since the TKET compilation passes have been integrated into the H-Series stack, performing circuit optimizations is redundant before submitting to hardware, unless the user would like to see the optimizations applied before submitting. Given this, users may take 1 of 3 approaches when submitting jobs:
\n", "1. Use `optimisation_level=0` when running `get_compiled_circuit`, then submit the circuit using `process_circuits` knowing that the corresponding optimization level actually run will be 2.
\n", "2. Use the `get_compiled_circuit` function with the desired optimization level to observe the transformed circuit before submitting and then specify `tket-opt-level=None` in the `process_circuits` function when submitting, in order for the optimizations to be applied as desired.
\n", "3. If the user desires to have no optimizations applied, use `optimisation_level=0` in `get_compiled_circuit` and `tket-opt-level=None` in `process_circuits`. This should be specified in both functions."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In this example, option 1 is illustrated, using `get_compiled_circuit` just to rebase the circuit and leaving the optimizations to be done in the H-Series stack."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=0)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Cost "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Before running on Quantinuum systems, it is good practice to check how many HQCs a job will cost, in order to plan usage. In `pytket` this can be done using the `cost` function of the `QuantinuumBackend`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that in this case because an emulator is used, the specific syntax checker the emulator uses is specified. This is an optional parameter not needed if you are using a quantum computer target."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Run the Circuit "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now the circuit can be run on Quantinuum systems."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note:** As described above, the TKET compilation optimization level 2 will be applied since no `tket-opt-level` is specified."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The status of a submitted job can be viewed at any time, indicating if a job is in the queue or completed. Additional information is also provided, such as queue position, start times, completion time, and circuit cost in H-Series Quantum Credits (HQCs)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Retrieve Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a job's status returns completed, results can be returned using the `get_result` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Save Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["It is recommended that users save job results as soon as jobs are completed due to the Quantinuum data retention policy."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import json"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Results can be loaded to their original format using `BackendResult.from_dict`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.backends.backendresult import BackendResult"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_example.json\") as file:\n", " data = json.load(file)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = BackendResult.from_dict(data)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Analyze Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["There are multiple options for analyzing results with pytket. A few examples are highlighted here. More can be seen at [Interpreting Results](https://cqcl.github.io/pytket/manual/manual_backend.html#interpreting-results)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)\n", "print(result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from bit to position in the measured state"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.bit_readout)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from qubit to position in the measured state"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.qubit_readout)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from qubits to the bits to which their measurement values were written"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.qubit_to_bit_map)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Canceling jobs "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Jobs that have been submitted can also be cancelled if needed."]}, {"cell_type": "markdown", "metadata": {}, "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)
\n", "backend.cancel(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Additional Features "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section covers additional features available in `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [Extended Circuit Compilation](#circuit-compilation-extended)
\n", "* [Batch Submission](#batch-submission)
\n", "* [Parametrized Circuits](#parametrized-circuits)
\n", "* [Conditional Gates](#conditional-gates)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Extended Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section leverages the discussion in the [Circuit Compilation](#circuit-compilation) section to illsutrate how to turn TKET compilations on or off in the `process_circuit` function, specifically for options 2 and 3."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For option 2 as described in [Circuit Compilation](#circuit-compilation), suppose a user explores the results of TKET compilation passes on a circuit and finds that `optimisation_level=1` is desirable. The submission below specifies this in the `get_compiled_circuit` function with optimization level 1. Because the circuit is optimized beforehand, the TKET optimization in the H-Series stack should be turned off. The value `tket-opt-level:None` turns off TKET optimization in the H-Series stack."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, options={\"tket-opt-level\": None}\n", ")\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["For option 3 as described in [Circuit Compilation](#circuit-compilation), suppose a user wants to turn off all optimizations in the stack, even simple single-qubit combinations done by the H-Series compiler. This can be done by setting `optimisation_level=0` in `get_compiled_circuit` and setting `tket-opt-level:None` in the `process_circuits` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=0)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, options={\"tket-opt-level\": None}\n", ")\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Batch Submission "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The batch feature on Quantinuum systems gives users the ability to create \"ad-hoc\" reservations. Circuits submitted together in a batch will run at one time. The benefit to users is that once a batch hits the front of the queue, jobs in a batch will run uninterrupted until they are completed."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a batch is submitted, jobs can continue to be added to the batch, ending either when the user signifies the end of a batch or after 1 minute of inactivity."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Batches cannot exceed the maximum limit of 500 H-System Quantum Credits (HQCs) total. If the total HQCs for jobs in a batch hit this limit or a smaller limit set by the user, those jobs *will not be cancelled*. Instead, they will continue to run as regular jobs in the queue instead of as a batch."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Currently only the quantum computer and emulator targets support the batching feature. Batching is not supported on the syntax checkers."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information on using this feature in `pytket`, see [Batch Submission](https://cqcl.github.io/pytket-quantinuum/api/index.html#batching)."]}, {"cell_type": "markdown", "metadata": {}, "source": ["To start a batch, use the `start_batch` function, specifying the `max_batch_cost` in HQCs to enforce."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "n_shots = 100\n", "max_batch_cost = 100"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["backend = QuantinuumBackend(device_name=machine)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["batch1 = backend.start_batch(\n", " max_batch_cost=max_batch_cost, circuit=compiled_circuit, n_shots=n_shots\n", ")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Additional jobs can be added to the batch using the `add_to_batch` function. The end of a batch can optionally be specified with the `batch_end` flag."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["batch2 = backend.add_to_batch(batch1, compiled_circuit, n_shots=n_shots)\n", "batch3 = backend.add_to_batch(batch1, compiled_circuit, n_shots=n_shots, batch_end=True)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The status for the batch jobs can be checked once submitted."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle_list = [batch1, batch2, batch3]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status_list = [backend.circuit_status(h) for h in handle_list]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status_list"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Results for batch submissions can be returned using `get_results` (note the plural)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_results(handle_list)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Parametrized Circuits "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Parametrized circuits are common in variational algorithms. Pytket supports parameters within circuits via symbols. For more information, see [Symbolic Circuits](https://cqcl.github.io/pytket/manual/manual_circuit.html?highlight=paramet#symbolic-circuits)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import fresh_symbol"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up parametrized circuit"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["a = fresh_symbol(\"a\")\n", "circuit = Circuit(3, name=\"Parametrized Circuit\")\n", "circuit.X(0)\n", "circuit.CX(0, 1).CX(1, 2)\n", "circuit.Rz(a, 2)\n", "circuit.CX(1, 2).CX(0, 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note the substitution of an actual value to the `a` variable below."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create a version of the circuit that utilizes a specific value for the variable a"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["simulation_circuit = circuit.copy()\n", "simulation_circuit.measure_all()\n", "simulation_circuit.symbol_substitution({a: -0.09})"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Compile the circuit: this includes optimizing the gates and resynthesizing the circuit to Quantinuum's native gate set"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(simulation_circuit)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Conditional Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Pytket supports conditional gates. This may be for implementing error correction or reducing noise. This capability is well-supported by Quantinuum hardware, which supports mid-circuit measurement and qubit reuse. See [Conditional Gates](https://cqcl.github.io/pytket/manual/manual_circuit.html#conditional-gates) for more information on pytket's implementation. The following example demonstrates the quantum teleportation protocol."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, if_bit"]}, {"cell_type": "markdown", "metadata": {}, "source": ["create a circuit and add quantum and classical registers"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ = Circuit(name=\"Conditional Gates Example\")\n", "qreg = circ.add_q_register(\"q\", 3)\n", "creg = circ.add_c_register(\"b\", 2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["prepare q[0] to be in the state |->, which we wish to teleport to q[2]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.X(qreg[0]).H(qreg[0])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["prepare a Bell state on qubits q[1] and q[2]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.H(qreg[1])\n", "circ.CX(qreg[1], qreg[2])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["construct the teleportation protocol"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.CX(qreg[0], qreg[1])\n", "circ.H(qreg[0])\n", "circ.Measure(qreg[0], creg[0])\n", "circ.Measure(qreg[1], creg[1])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if (creg[1] == 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.X(qreg[2], condition=if_bit(creg[1]))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if (creg[0] == 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.Z(qreg[2], condition=if_bit(creg[0]))"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circ)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can utilise pytket's [Assertion](https://cqcl.github.io/pytket/manual/manual_assertion.html#assertion) feature to verify the successful teleportation of the state $| - \\rangle$."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import ProjectorAssertionBox\n", "import numpy as np"]}, {"cell_type": "markdown", "metadata": {}, "source": ["|-><-|"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["proj = np.array([[0.5, -0.5], [-0.5, 0.5]])\n", "circ.add_assertion(ProjectorAssertionBox(proj), [qreg[2]], name=\"debug\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circ)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "n_shots = 100\n", "backend = QuantinuumBackend(device_name=machine)\n", "compiled_circuit = backend.get_compiled_circuit(circ)\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "status"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The `get_debug_info` function returns the success rate of the state assertion averaged across shots. Note that the failed shots are caused by the simulated device errors"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result.get_debug_info()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Quantinuum Circuit Submissions via pytket"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains basic circuit submission examples to Quantinuum quantum hardware via `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [What is TKET?](#tket)
\n", "* [Step by Step](#step-by-step)
\n", " * [Circuit Preparation](#circuit-preparation)
\n", " * [Select Device](#select-device)
\n", " * [Circuit Compilation](#circuit-compilation)
\n", " * [Circuit Cost](#circuit-cost)
\n", " * [Run the Circuit](#run-circuit)
\n", " * [Retrieve Results](#retrieve-results)
\n", " * [Save Results](#save-results)
\n", " * [Analyze Results](#analyze-results)
\n", " * [Cancel Jobs](#cancel-jobs)
\n", "* [Additional Features](#additional-features)
\n", " * [Extended Circuit Compilation](#circuit-compilation-extended)
\n", " * [Batch Submission](#batch-submission)
\n", " * [Parametrized Circuits](#parametrized-circuits)
\n", " * [Conditional Gates](#conditional-gates)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## What is TKET? "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The TKET framework (pronounced \"ticket\") is a software platform for the development and execution of gate-level quantum computation, providing state-of-the-art performance in circuit compilation. It was created and is maintained by Quantinuum. The toolset is designed to extract the most out of the available NISQ devices of today and is platform-agnostic."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In python, the `pytket` packages is available for python 3.9+. The `pytket` and `pytket-quantinuum` packages are included as part of the installation instructions on the user portal."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information on TKET, see the following links:
\n", "- [TKET manual](https://cqcl.github.io/pytket/manual/manual_intro.html)
\n", "- [TKET overview and demo video](https://www.youtube.com/watch?v=yXKSpvgAtrk)
\n", "- [Introduction to Quantum Compilation with TKET](https://github.com/CalMacCQ/tket_blog/blob/main/blog1_intro_to_qc.ipynb)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook covers how to use `pytket` in conjunction with `pytket-quantinuum` to submit to Quantinuum devices. The quantum compilation step is demonstrated, but for a full overview of quantum compilation with TKET, the last link above is recommended."]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the links below for the `pytket` and `pytket-quantinuum` documentation:
\n", "- [pytket](https://cqcl.github.io/tket/pytket/api/index.html)
\n", "- [pytket-quantinuum](https://cqcl.github.io/pytket-quantinuum/api/index.html)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Step by Step "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Preparation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create your circuit via the pytket python library. For details on getting started with `pytket`, see pytket's [Getting Started](https://cqcl.github.io/tket/pytket/api/getting_started.html) page."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note**: `pytket` renders circuits in ZX-calculus notation. This can be toggled on and off by pressing the top left button in the circuit display."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, fresh_symbol\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up Bell Test"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Select Device "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Select a machine and login to the Quantinuum API using your credentials. See the *Quantinuum Systems User Guide* in the *Examples* tab on the *Quantinuum User Portal* for information and target names for each of the H-Series systems available."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Users need to login once per session. In the notebook, a dialogue box will ask for credentials. If running a script, users be prompted at the shell. You can also [save your email in the pytket config](https://cqcl.github.io/pytket-extensions/api/quantinuum/api.html#pytket.extensions.quantinuum.backends.config.set_quantinuum_config)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The device status can be checked using `device_state`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", QuantinuumBackend.device_state(device_name=machine))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Available devices can be viewed using the `available_devices` function. Additional information is returned, here just the device names are pulled in."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["[x.device_name for x in QuantinuumBackend.available_devices()]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Circuits submitted to Quantinuum H-Series quantum computers and emulators are automatically run through TKET compilation passes for H-Series hardware. This enables circuits to be automatically optimized for H-Series systems and run more efficiently."]}, {"cell_type": "markdown", "metadata": {}, "source": ["More information on the specific compilation passes applied can be found on the `pytket-quantinuum` documentation, specifically the [Default Compilation](https://cqcl.github.io/pytket-quantinuum/api/index.html#default-compilation) section. In the H-Series software stack, the optimization level applied is set with the `tket-opt-level` parameter. **The default compilation setting for circuits submited to H-Series sytems is optimization level 2.** More information is found in the *Quantinuum Application Programming Interface (API) Specification*."]}, {"cell_type": "markdown", "metadata": {}, "source": ["When using `pytket` before submitting to hardware, the `get_compiled_circuit` function performs the same compilation passes run after submission to Quantinuum systems. The advantage of using the function before submitting to H-Series hardware is to see exactly what circuit optimizations will be performed when submitted to hardware and determine if a different optimization level is desired. The `optimisation_level` parameter in the `get_compiled_circuit` function corresponds directly to the the level of optimisation after submitting to the H-Series systems and to the `tket-opt-level` parameter in the H-Series API. The default compilation for the `get_compiled_circuit` function is optimization level 2, the same as when submitting to the H-Series directly."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Since the TKET compilation passes have been integrated into the H-Series stack, performing circuit optimizations is redundant before submitting to hardware, unless the user would like to see the optimizations applied before submitting. Given this, users may take 1 of 3 approaches when submitting jobs:
\n", "1. Use `optimisation_level=0` when running `get_compiled_circuit`, then submit the circuit using `process_circuits` knowing that the corresponding optimization level actually run will be 2.
\n", "2. Use the `get_compiled_circuit` function with the desired optimization level to observe the transformed circuit before submitting and then specify `tket-opt-level=None` in the `process_circuits` function when submitting, in order for the optimizations to be applied as desired.
\n", "3. If the user desires to have no optimizations applied, use `optimisation_level=0` in `get_compiled_circuit` and `tket-opt-level=None` in `process_circuits`. This should be specified in both functions."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In this example, option 1 is illustrated, using `get_compiled_circuit` just to rebase the circuit and leaving the optimizations to be done in the H-Series stack."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=0)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Cost "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Before running on Quantinuum systems, it is good practice to check how many HQCs a job will cost, in order to plan usage. In `pytket` this can be done using the `cost` function of the `QuantinuumBackend`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that in this case because an emulator is used, the specific syntax checker the emulator uses is specified. This is an optional parameter not needed if you are using a quantum computer target."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Run the Circuit "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now the circuit can be run on Quantinuum systems."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note:** As described above, the TKET compilation optimization level 2 will be applied since no `tket-opt-level` is specified."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The status of a submitted job can be viewed at any time, indicating if a job is in the queue or completed. Additional information is also provided, such as queue position, start times, completion time, and circuit cost in H-Series Quantum Credits (HQCs)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Retrieve Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a job's status returns completed, results can be returned using the `get_result` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Save Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["It is recommended that users save job results as soon as jobs are completed due to the Quantinuum data retention policy."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import json"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Results can be loaded to their original format using `BackendResult.from_dict`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.backends.backendresult import BackendResult"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_example.json\") as file:\n", " data = json.load(file)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = BackendResult.from_dict(data)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Analyze Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["There are multiple options for analyzing results with pytket. A few examples are highlighted here. More can be seen at [Interpreting Results](https://cqcl.github.io/pytket/manual/manual_backend.html#interpreting-results)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)\n", "print(result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from bit to position in the measured state"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.bit_readout)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from qubit to position in the measured state"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.qubit_readout)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from qubits to the bits to which their measurement values were written"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.qubit_to_bit_map)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Canceling jobs "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Jobs that have been submitted can also be cancelled if needed."]}, {"cell_type": "markdown", "metadata": {}, "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)
\n", "backend.cancel(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Additional Features "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section covers additional features available in `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [Extended Circuit Compilation](#circuit-compilation-extended)
\n", "* [Batch Submission](#batch-submission)
\n", "* [Parametrized Circuits](#parametrized-circuits)
\n", "* [Conditional Gates](#conditional-gates)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Extended Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section leverages the discussion in the [Circuit Compilation](#circuit-compilation) section to illsutrate how to turn TKET compilations on or off in the `process_circuit` function, specifically for options 2 and 3."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For option 2 as described in [Circuit Compilation](#circuit-compilation), suppose a user explores the results of TKET compilation passes on a circuit and finds that `optimisation_level=1` is desirable. The submission below specifies this in the `get_compiled_circuit` function with optimization level 1. Because the circuit is optimized beforehand, the TKET optimization in the H-Series stack should be turned off. The value `tket-opt-level:None` turns off TKET optimization in the H-Series stack."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, options={\"tket-opt-level\": None}\n", ")\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["For option 3 as described in [Circuit Compilation](#circuit-compilation), suppose a user wants to turn off all optimizations in the stack, even simple single-qubit combinations done by the H-Series compiler. This can be done by setting `optimisation_level=0` in `get_compiled_circuit` and setting `tket-opt-level:None` in the `process_circuits` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=0)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, options={\"tket-opt-level\": None}\n", ")\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Batch Submission "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The batch feature on Quantinuum systems gives users the ability to create \"ad-hoc\" reservations. Circuits submitted together in a batch will run at one time. The benefit to users is that once a batch hits the front of the queue, jobs in a batch will run uninterrupted until they are completed."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a batch is submitted, jobs can continue to be added to the batch, ending either when the user signifies the end of a batch or after 1 minute of inactivity."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Batches cannot exceed the maximum limit of 500 H-System Quantum Credits (HQCs) total. If the total HQCs for jobs in a batch hit this limit or a smaller limit set by the user, those jobs *will not be cancelled*. Instead, they will continue to run as regular jobs in the queue instead of as a batch."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Currently only the quantum computer and emulator targets support the batching feature. Batching is not supported on the syntax checkers."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information on using this feature in `pytket`, see [Batch Submission](https://cqcl.github.io/pytket-quantinuum/api/index.html#batching)."]}, {"cell_type": "markdown", "metadata": {}, "source": ["To start a batch, use the `start_batch` function, specifying the `max_batch_cost` in HQCs to enforce."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "n_shots = 100\n", "max_batch_cost = 100"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["backend = QuantinuumBackend(device_name=machine)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["batch1 = backend.start_batch(\n", " max_batch_cost=max_batch_cost, circuit=compiled_circuit, n_shots=n_shots\n", ")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Additional jobs can be added to the batch using the `add_to_batch` function. The end of a batch can optionally be specified with the `batch_end` flag."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["batch2 = backend.add_to_batch(batch1, compiled_circuit, n_shots=n_shots)\n", "batch3 = backend.add_to_batch(batch1, compiled_circuit, n_shots=n_shots, batch_end=True)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The status for the batch jobs can be checked once submitted."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle_list = [batch1, batch2, batch3]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status_list = [backend.circuit_status(h) for h in handle_list]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status_list"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Results for batch submissions can be returned using `get_results` (note the plural)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_results(handle_list)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Parametrized Circuits "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Parametrized circuits are common in variational algorithms. Pytket supports parameters within circuits via symbols. For more information, see [Symbolic Circuits](https://cqcl.github.io/pytket/manual/manual_circuit.html?highlight=paramet#symbolic-circuits)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import fresh_symbol"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up parametrized circuit"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["a = fresh_symbol(\"a\")\n", "circuit = Circuit(3, name=\"Parametrized Circuit\")\n", "circuit.X(0)\n", "circuit.CX(0, 1).CX(1, 2)\n", "circuit.Rz(a, 2)\n", "circuit.CX(1, 2).CX(0, 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note the substitution of an actual value to the `a` variable below."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create a version of the circuit that utilizes a specific value for the variable a"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["simulation_circuit = circuit.copy()\n", "simulation_circuit.measure_all()\n", "simulation_circuit.symbol_substitution({a: -0.09})"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Compile the circuit: this includes optimizing the gates and resynthesizing the circuit to Quantinuum's native gate set"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(simulation_circuit)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Conditional Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Pytket supports conditional gates. This may be for implementing error correction or reducing noise. This capability is well-supported by Quantinuum hardware, which supports mid-circuit measurement and qubit reuse. See [Conditional Gates](https://cqcl.github.io/pytket/manual/manual_circuit.html#conditional-gates) for more information on pytket's implementation. The following example demonstrates the quantum teleportation protocol."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, if_bit"]}, {"cell_type": "markdown", "metadata": {}, "source": ["create a circuit and add quantum and classical registers"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ = Circuit(name=\"Conditional Gates Example\")\n", "qreg = circ.add_q_register(\"q\", 3)\n", "creg = circ.add_c_register(\"b\", 2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["prepare q[0] to be in the state |->, which we wish to teleport to q[2]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.X(qreg[0]).H(qreg[0])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["prepare a Bell state on qubits q[1] and q[2]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.H(qreg[1])\n", "circ.CX(qreg[1], qreg[2])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["construct the teleportation protocol"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.CX(qreg[0], qreg[1])\n", "circ.H(qreg[0])\n", "circ.Measure(qreg[0], creg[0])\n", "circ.Measure(qreg[1], creg[1])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if (creg[1] == 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.X(qreg[2], condition=if_bit(creg[1]))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if (creg[0] == 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.Z(qreg[2], condition=if_bit(creg[0]))"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circ)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can utilise pytket's [Assertion](https://cqcl.github.io/pytket/manual/manual_assertion.html#assertion) feature to verify the successful teleportation of the state $| - \\rangle$."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import ProjectorAssertionBox\n", "import numpy as np"]}, {"cell_type": "markdown", "metadata": {}, "source": ["|-><-|"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["proj = np.array([[0.5, -0.5], [-0.5, 0.5]])\n", "circ.add_assertion(ProjectorAssertionBox(proj), [qreg[2]], name=\"debug\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circ)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "n_shots = 100\n", "backend = QuantinuumBackend(device_name=machine)\n", "compiled_circuit = backend.get_compiled_circuit(circ)\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "status"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The `get_debug_info` function returns the success rate of the state assertion averaged across shots. Note that the failed shots are caused by the simulated device errors"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result.get_debug_info()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file diff --git a/examples/python/Quantinuum_circuit_submissions.py b/examples/python/Quantinuum_circuit_submissions.py index 7c05d31d..374e8cd7 100644 --- a/examples/python/Quantinuum_circuit_submissions.py +++ b/examples/python/Quantinuum_circuit_submissions.py @@ -23,7 +23,7 @@ # The TKET framework (pronounced "ticket") is a software platform for the development and execution of gate-level quantum computation, providing state-of-the-art performance in circuit compilation. It was created and is maintained by Quantinuum. The toolset is designed to extract the most out of the available NISQ devices of today and is platform-agnostic. -# In python, the `pytket` packages is available for python 3.8+. The `pytket` and `pytket-quantinuum` packages are included as part of the installation instructions on the user portal. +# In python, the `pytket` packages is available for python 3.9+. The `pytket` and `pytket-quantinuum` packages are included as part of the installation instructions on the user portal. # For more information on TKET, see the following links: # - [TKET manual](https://cqcl.github.io/pytket/manual/manual_intro.html) diff --git a/mypy.ini b/mypy.ini index 6da039b7..1dfad53a 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,5 +1,5 @@ [mypy] -python_version = 3.8 +python_version = 3.9 warn_unused_configs = True disallow_untyped_decorators = False diff --git a/setup.py b/setup.py index 44ada3c1..c0e20468 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ version=metadata["__extension_version__"], author="TKET development team", author_email="tket-support@cambridgequantum.com", - python_requires=">=3.8", + python_requires=">=3.9", project_urls={ "Documentation": "https://cqcl.github.io/pytket-quantinuum/api/index.html", "Source": "https://github.com/CQCL/pytket-quantinuum", @@ -43,7 +43,7 @@ packages=find_namespace_packages(include=["pytket.*"]), include_package_data=True, install_requires=[ - "pytket ~= 1.10", + "pytket == 1.11.0rc0", "requests >= 2.2", "types-requests", "websockets >= 7.0", @@ -53,9 +53,9 @@ ], classifiers=[ "Environment :: Console", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "License :: OSI Approved :: Apache Software License", "Operating System :: MacOS :: MacOS X", "Operating System :: POSIX :: Linux", From 43aced5e0aa700059e71ec492120211ff68dec08 Mon Sep 17 00:00:00 2001 From: Yao Tang Date: Wed, 4 Jan 2023 17:43:48 +0000 Subject: [PATCH 03/17] Add script to generate notebooks --- examples/README.md | 35 ++++++----------------------------- examples/check-examples | 7 ++++--- examples/gen-nb | 23 +++++++++++++++++++++++ 3 files changed, 33 insertions(+), 32 deletions(-) create mode 100755 examples/gen-nb diff --git a/examples/README.md b/examples/README.md index 94def474..9a29c8b2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,44 +2,21 @@ Here resides the example notebooks of the `pytket-quantinuum` extension. The `*.ipynb` notebooks are generated from the scripts in `examples/python` -using the [p2j](https://github.com/remykarem/python2jupyter) tool. - +using the `gen-nb` script. The script uses [p2j](https://github.com/remykarem/python2jupyter) tool to generate the notebooks with a Quantinuum logo added to the top. +Notice that the `sed` tool behaves differently on macOS, one can use `gsed` instead of `sed`. ## How to modify the notebooks Any change should be done to the corresponding `.py` file in `examples/python`. For example, in order to modify the `examples/Quantinuum_emulator.ipynb` notebook, you need to change the `examples/python/Quantinuum_emulator.py`. After that, you can update the -actual notebook by running the `p2j` command (still using the same example): +actual notebook by running the `gen-nb` script. -```bash -p2j -o -t examples/Quantinuum_emulator.ipynb examples/python/Quantinuum_emulator.py -``` ## Adding new notebooks To add a new notebook: 1. Create a python file in the `examples/python` folder with the source code for the new notebook. -2. Run the `p2j` command above to create the notebook -3. Add the notebook name to the `maintained-notebooks.txt` file. - - -## Embedding the quantinuum logo - -Please note that if you generate the notebooks from the python files, they will not contain -the quantinuum logo observed at the top of the notebooks. The markdown to embed the logo -is located in the `logo_header_markdown.md` file. So, you need to copy the content -of that file and put it at the top of the python script if you want the notebook to -include the logo. - -You can append it by running: -```bash -logo=`cat logo_header_markdown.md` -sed -i "1i${logo}" python/ -``` - -:warning: Beware that when committing your changes to the repo, you must check-in the *updated notebook -including the logo header*, but check-in the *updated `` without the -markdown cell for the logo*. This is because the `check-examples` script used in the CI, already -appends the logo to the python scripts before generating a temporary notebook, and then this -notebook is compared against the one that already exists. +2. Add the notebook name to the `maintained-notebooks.txt` file. +3. Run the `gen-nb` script to generate the notebook. +4. Commit both the python file and the generated notebook. diff --git a/examples/check-examples b/examples/check-examples index 16678a12..b5301f62 100755 --- a/examples/check-examples +++ b/examples/check-examples @@ -2,12 +2,13 @@ set -e -for file in $(ls python/*py | xargs -n 1 basename) +for name in `cat maintained-notebooks.txt` do echo "============================================================" - echo "Checking: ${file}" + echo "Checking: ${name}" echo "============================================================" - name=`basename $file .py` + file="${name}.py" + echo $file # Save copy of original python file cp python/${file} python/${name}-original.py diff --git a/examples/gen-nb b/examples/gen-nb new file mode 100755 index 00000000..16d40eec --- /dev/null +++ b/examples/gen-nb @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e + +for name in `cat maintained-notebooks.txt` +do + echo "============================================================" + echo "Generating: ${name}.ipynb" + echo "============================================================" + file=${name}.py + + # Save copy of original python file + cp python/${file} python/${name}-original.py + # Append embedded quantinuum logo markup to the beginning of the python file + logo=`cat logo_header_markdown.md` + sed -i "1i${logo}" python/${file} + # Generate the script + p2j -o -t ${name}.ipynb python/${file} + # Remove modified python script + rm python/${file} + # Restore original + mv python/${name}-original.py python/${file} +done From d9057230d813c1282557f9c5f8404ae8450aff95 Mon Sep 17 00:00:00 2001 From: Yao Tang Date: Thu, 5 Jan 2023 10:34:10 +0000 Subject: [PATCH 04/17] Remove maintained-notebooks --- examples/README.md | 7 +++---- examples/check-examples | 11 +++++------ examples/gen-nb | 8 ++++---- examples/maintained-notebooks.txt | 4 ---- 4 files changed, 12 insertions(+), 18 deletions(-) delete mode 100644 examples/maintained-notebooks.txt diff --git a/examples/README.md b/examples/README.md index 9a29c8b2..6d52f82b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -16,7 +16,6 @@ actual notebook by running the `gen-nb` script. ## Adding new notebooks To add a new notebook: -1. Create a python file in the `examples/python` folder with the source code for the new notebook. -2. Add the notebook name to the `maintained-notebooks.txt` file. -3. Run the `gen-nb` script to generate the notebook. -4. Commit both the python file and the generated notebook. +1. Create a python file in the `examples/python` folder with the source code for the new notebook. +2. Run the `gen-nb` script to generate the notebook. +3. Commit both the python file and the generated notebook. diff --git a/examples/check-examples b/examples/check-examples index b5301f62..8ea01b6b 100755 --- a/examples/check-examples +++ b/examples/check-examples @@ -2,20 +2,19 @@ set -e -for name in `cat maintained-notebooks.txt` +for file in $(ls python/*py | xargs -n 1 basename) do echo "============================================================" - echo "Checking: ${name}" + echo "Checking: ${file}" echo "============================================================" - file="${name}.py" - echo $file + name=`basename $file .py` # Save copy of original python file cp python/${file} python/${name}-original.py # Append embedded quantinuum logo markup to the beginning of the python file logo=`cat logo_header_markdown.md` - sed -i "1i${logo}" python/${file} + gsed -i "1i${logo}" python/${file} # Check that notebook is generated from script p2j -o -t ${name}-gen.ipynb python/${file} @@ -29,5 +28,5 @@ do mv python/${name}-original.py python/${file} # Run script - ./answer_input_prompts ${file} $PYTKET_REMOTE_QUANTINUUM_USERNAME $PYTKET_REMOTE_QUANTINUUM_PASSWORD + # ./answer_input_prompts ${file} $PYTKET_REMOTE_QUANTINUUM_USERNAME $PYTKET_REMOTE_QUANTINUUM_PASSWORD done diff --git a/examples/gen-nb b/examples/gen-nb index 16d40eec..272dec6d 100755 --- a/examples/gen-nb +++ b/examples/gen-nb @@ -2,18 +2,18 @@ set -e -for name in `cat maintained-notebooks.txt` +for file in $(ls python/*py | xargs -n 1 basename) do echo "============================================================" - echo "Generating: ${name}.ipynb" + echo "Checking: ${file}" echo "============================================================" - file=${name}.py + name=`basename $file .py` # Save copy of original python file cp python/${file} python/${name}-original.py # Append embedded quantinuum logo markup to the beginning of the python file logo=`cat logo_header_markdown.md` - sed -i "1i${logo}" python/${file} + gsed -i "1i${logo}" python/${file} # Generate the script p2j -o -t ${name}.ipynb python/${file} # Remove modified python script diff --git a/examples/maintained-notebooks.txt b/examples/maintained-notebooks.txt deleted file mode 100644 index a65e00cf..00000000 --- a/examples/maintained-notebooks.txt +++ /dev/null @@ -1,4 +0,0 @@ -Quantinuum_circuit_submissions -Quantinuum_emulator -Quantinuum_mid-circuit_measurement -Quantinuum_arbitrary_zz From 180c060f78e7f9d4e39b6317462bafa60b4a3664 Mon Sep 17 00:00:00 2001 From: Yao Tang Date: Thu, 5 Jan 2023 10:42:37 +0000 Subject: [PATCH 05/17] change gsed back to sed --- examples/check-examples | 2 +- examples/gen-nb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/check-examples b/examples/check-examples index 8ea01b6b..db90f851 100755 --- a/examples/check-examples +++ b/examples/check-examples @@ -14,7 +14,7 @@ do # Append embedded quantinuum logo markup to the beginning of the python file logo=`cat logo_header_markdown.md` - gsed -i "1i${logo}" python/${file} + sed -i "1i${logo}" python/${file} # Check that notebook is generated from script p2j -o -t ${name}-gen.ipynb python/${file} diff --git a/examples/gen-nb b/examples/gen-nb index 272dec6d..c03cfc55 100755 --- a/examples/gen-nb +++ b/examples/gen-nb @@ -13,7 +13,7 @@ do cp python/${file} python/${name}-original.py # Append embedded quantinuum logo markup to the beginning of the python file logo=`cat logo_header_markdown.md` - gsed -i "1i${logo}" python/${file} + sed -i "1i${logo}" python/${file} # Generate the script p2j -o -t ${name}.ipynb python/${file} # Remove modified python script From 207de2ad2bb1ecd9b570298bdebfda3b15bd28c5 Mon Sep 17 00:00:00 2001 From: Yao Tang Date: Thu, 5 Jan 2023 10:43:05 +0000 Subject: [PATCH 06/17] uncomment notebook check --- examples/check-examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/check-examples b/examples/check-examples index db90f851..16678a12 100755 --- a/examples/check-examples +++ b/examples/check-examples @@ -28,5 +28,5 @@ do mv python/${name}-original.py python/${file} # Run script - # ./answer_input_prompts ${file} $PYTKET_REMOTE_QUANTINUUM_USERNAME $PYTKET_REMOTE_QUANTINUUM_PASSWORD + ./answer_input_prompts ${file} $PYTKET_REMOTE_QUANTINUUM_USERNAME $PYTKET_REMOTE_QUANTINUUM_PASSWORD done From 731e81c3ea132baacb0c3dd6f73e5d9022a7f539 Mon Sep 17 00:00:00 2001 From: Yao Tang Date: Thu, 5 Jan 2023 11:53:33 +0000 Subject: [PATCH 07/17] Generate notebook using gen-nb script --- examples/Quantinuum_compile_without_api.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Quantinuum_compile_without_api.ipynb b/examples/Quantinuum_compile_without_api.ipynb index 6b5d84b9..9ffa0806 100644 --- a/examples/Quantinuum_compile_without_api.ipynb +++ b/examples/Quantinuum_compile_without_api.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["# Compiling for Quantinuum Hardware without Querying Quantinuum API"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains an example of how to investigate circuits compiled for Quantinuum hardware without logging in or submitting to Quantinuum hardware. This may be useful if it is desired to explore circuit compilation in depth before submitting."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Circuit Preparation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create your circuit."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, OpType\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Set up Backend"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up a `QuantinuumBackend` object. The difference is the `machine_debug` option uses the default `pytket-quantinuum` options such as pytket's version of the Quantinuum native gate set rather than querying the Quantinuum API for this information."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine, machine_debug=True)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Investigate Native Gate Set"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Users can view the hard-coded native gate set for the Quantinuum backend using the following command."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import pytket.extensions.quantinuum.backends.quantinuum as qtm"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(qtm._GATE_SET)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["It's possible that the hardcoded verion is not up to date with the latest native gate set as described in the [System Model H1 Product Data Sheet](https://www.quantinuum.com/hardware/h1). In this case, the Rzz gate, which is the `ZZPhase` gate in pytket, is missing. This can be added by running the following command."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qtm._GATE_SET.add(OpType.ZZPhase)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Circuits can now be compiled with the `get_compiled_circuit` function without querying the Quantinuum API."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=2)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Compiling for Quantinuum Hardware without Querying Quantinuum API"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains an example of how to investigate circuits compiled for Quantinuum hardware without logging in or submitting to Quantinuum hardware. This may be useful if it is desired to explore circuit compilation in depth before submitting."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Circuit Preparation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create your circuit."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, OpType\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Set up Backend"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up a `QuantinuumBackend` object. The difference is the `machine_debug` option uses the default `pytket-quantinuum` options such as pytket's version of the Quantinuum native gate set rather than querying the Quantinuum API for this information."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine, machine_debug=True)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Investigate Native Gate Set"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Users can view the hard-coded native gate set for the Quantinuum backend using the following command."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import pytket.extensions.quantinuum.backends.quantinuum as qtm"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(qtm._GATE_SET)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["It's possible that the hardcoded verion is not up to date with the latest native gate set as described in the [System Model H1 Product Data Sheet](https://www.quantinuum.com/hardware/h1). In this case, the Rzz gate, which is the `ZZPhase` gate in pytket, is missing. This can be added by running the following command."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qtm._GATE_SET.add(OpType.ZZPhase)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Circuits can now be compiled with the `get_compiled_circuit` function without querying the Quantinuum API."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=2)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file From 2e35caa43cf6634972716a0498ab48916c3a3275 Mon Sep 17 00:00:00 2001 From: Yao Tang Date: Thu, 5 Jan 2023 15:32:26 +0000 Subject: [PATCH 08/17] update expect script --- examples/answer_input_prompts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/examples/answer_input_prompts b/examples/answer_input_prompts index 6bba7d34..fb1e5012 100755 --- a/examples/answer_input_prompts +++ b/examples/answer_input_prompts @@ -11,10 +11,14 @@ set QUANTINUUM_PASSWORD [lindex $argv 2] spawn python python/$PYTHON_FILE -expect "*Quantinuum email*" -send "$QUANTINUUM_EMAIL\n" - -expect "*Quantinuum password*" -send "$QUANTINUUM_PASSWORD\n" - -expect eof +expect { + "*Quantinuum email*" { + send "$QUANTINUUM_EMAIL\n" + exp_continue + } + "*Quantinuum password*" { + send "$QUANTINUUM_PASSWORD\n" + exp_continue + } + eof +} From 61a570a4c7809476ae198e71a23ac68b8484bae8 Mon Sep 17 00:00:00 2001 From: cqc-melf <70640934+cqc-melf@users.noreply.github.com> Date: Fri, 6 Jan 2023 08:32:54 +0000 Subject: [PATCH 09/17] update copyright to 2023 (#101) * update copyright to 2023 * update notebook --- examples/Quantinuum_arbitrary_zz.ipynb | 2 +- examples/Quantinuum_circuit_submissions.ipynb | 2 +- examples/Quantinuum_emulator.ipynb | 2 +- examples/Quantinuum_mid-circuit_measurement.ipynb | 2 +- examples/python/Quantinuum_arbitrary_zz.py | 2 +- examples/python/Quantinuum_circuit_submissions.py | 2 +- examples/python/Quantinuum_emulator.py | 2 +- examples/python/Quantinuum_mid-circuit_measurement.py | 2 +- pytket/extensions/quantinuum/__init__.py | 2 +- pytket/extensions/quantinuum/backends/__init__.py | 2 +- pytket/extensions/quantinuum/backends/api_wrappers.py | 2 +- pytket/extensions/quantinuum/backends/config.py | 2 +- pytket/extensions/quantinuum/backends/credential_storage.py | 2 +- pytket/extensions/quantinuum/backends/federated_login.py | 2 +- pytket/extensions/quantinuum/backends/quantinuum.py | 2 +- setup.py | 2 +- tests/api1_test.py | 2 +- tests/api_test.py | 2 +- tests/backend_test.py | 2 +- tests/conftest.py | 2 +- tests/convert_test.py | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/examples/Quantinuum_arbitrary_zz.ipynb b/examples/Quantinuum_arbitrary_zz.ipynb index 0a83c999..66dfc552 100644 --- a/examples/Quantinuum_arbitrary_zz.ipynb +++ b/examples/Quantinuum_arbitrary_zz.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Arbitrary Angle ZZ Gates via pytket"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains a comparison of circuits with and without use of Quantinuum's native arbitrary-angle ZZ gate in `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [Arbitrary Angle ZZ Gates](#arb-zz)
\n", "* [Quantum Fourier Transform](#qft)
\n", "* [QFT with Fixed Angle Gates](#qft-fixed)
\n", "* [QFT with Arbitrary Angle ZZ Gates](#qft-arb-zz)
\n", "* [Compare Results](#compare)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Arbitrary Angle ZZ Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Quantinuum System Model H1's native gate set includes arbitrary angle ZZ gates. This is beneficial for reducing the 2-qubit gate count for many quantum algorithms and gate sequences."]}, {"cell_type": "markdown", "metadata": {}, "source": ["$RZZ(\\theta) = e^{-i\\frac{\\theta}{2}\\hat{Z} \\otimes \\hat{Z}}= e^{-i \\frac{\\theta}{2}} \\begin{bmatrix} 1 & 0 & 0 & 0\\\\ 0 & e^{-i\\theta} & 0 & 0\\\\ 0 & 0 & e^{-i\\theta} & 0\\\\ 0 & 0 & 0 & 1 \\end{bmatrix}$
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that $RZZ(\\frac{\\pi}{2}) = ZZ()$."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Quantum circuits that use the gate sequence CNOT, RZ, CNOT can be replaced with the arbitrary angle ZZ gate, shown below. This enables a lower number of 2-qubit gates in a quantum circuit, improving performance by decreasing gate errors."]}, {"cell_type": "markdown", "metadata": {}, "source": ["
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["

\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook demonstrates the Quantum Fourier Transform (QFT) with and without the $RZZ$ gate."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Quantum Fourier Transform "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The Quantum Fourier Transform (QFT) is an algorithm that serves as a sub-routine in multiple quantum algorithms, including Shor's factoring algorithm. Below are two functions, written in `pytket`, that work together to implement the QFT."]}, {"cell_type": "markdown", "metadata": {}, "source": ["The `QFT` function can be used to create the QFT. It takes the following arguments:
\n", "- `n`: number of qubits to use in the QFT circuit
\n", "- `arbZZ`: specify whether to use the arbitrary-angle ZZ gate or not, `True`/`False`, default: `False`
\n", "- `approx`: if set to integer `k`, then controlled rotations by angles less than $\\frac{\\pi}{2}^{k}$ do not occur"]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note:** In many presentations of the QFT, the circuit includes a round of SWAP gates at the end of the circuit that reverses the order of the qubits. The QFT circuits in this tutorial do not include this final SWAP step."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note:** In `pytket` the $RZZ$ gate is implemented with the $ZZPhase$ circuit function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "from pytket import Circuit\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def control_phase(circ, theta, q0, q1, arbZZ=False):\n", " \"\"\"circuit gadget for performing controlled-[1 0;0 e^i theta]\n", " Inputs:\n", " circ: pytket Circuit object\n", " theta: Z rotation angle (in units of pi)\n", " q0: control qubit\n", " q1: target qubit\n", " arbZZ (bool): enables arbitrary angle RZZ gate\n", " \"\"\"\n", " if arbZZ == False:\n", " # decompose into CNOTs\n", " circ.Rz(theta / 2, q1)\n", " circ.CX(q0, q1)\n", " circ.Rz(-theta / 2, q1)\n", " circ.CX(q0, q1)\n", " circ.Rz(theta / 2, q0)\n", " elif arbZZ == True:\n", " circ.Rz(theta / 2, q0)\n", " circ.Rz(theta / 2, q1)\n", " if theta > 0:\n", " circ.X(q0)\n", " circ.ZZPhase(theta / 2, q0, q1)\n", " circ.X(q0)\n", " elif theta <= 0:\n", " circ.ZZPhase(-theta / 2, q0, q1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def QFT(n, **kwargs):\n", " \"\"\"\n", " Function to implement the Quantum Fourier Transform\n", " n : number of qubits\n", " approx: if set to integer k, then sets that largest\n", " value of pi/2**k occuring in controlled rotation\n", " returns circ: pytket Circuit object\n", " \"\"\"\n\n", " # optional keyword arguments\n", " arbZZ = kwargs.get(\"arbZZ\", False)\n", " approx = kwargs.get(\"approx\", None)\n\n", " # initialize\n", " circ_name = \"QFT-arbZZ\" if arbZZ else \"QFT-fixed\"\n", " circ = Circuit(n, n, name=circ_name)\n", " for j in range(n - 1):\n", " q = n - 1 - j\n", " circ.H(q)\n", " for i in range(j + 1):\n", " if approx == None or approx >= j + 1 - i:\n", " control_phase(\n", " circ, 1 / (2 ** (j + 1 - i)), q - 1, n - 1 - i, arbZZ=arbZZ\n", " )\n", " circ.H(0)\n", " return circ"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## QFT with Fixed Angle Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["First, create the circuit with fixed-angle gates."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note**: `pytket` renders circuits in ZX-calculus notation. This can be toggled on and off by pressing the top left button."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_qubits = 12"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fixed = QFT(n_qubits, arbZZ=False)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(qft_fixed)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## QFT with Arbitrary Angle ZZ Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Second, create the circuit with arbitrary-angle ZZ gates."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_arbZZ = QFT(n_qubits, arbZZ=True)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(qft_arbZZ)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Compare Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now we compare the results of the QFT circuits with and without use of the arbitrary-angle ZZ gates on hardware."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### State Fidelity"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The QFT circuit applied to the computational basis state $|x\\rangle$ creates the state"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\\begin{align}
\n", "QFT|x\\rangle&=\\frac{1}{\\sqrt{d}}\\sum_{y=0}^{d-1} e^{2\\pi i x y/d} |y\\rangle\\\\
\n", "&= \\bigotimes_{j=0}^{n-1}\\frac{1}{\\sqrt{2}}\\sum_{y_j=0}^1e^{2\\pi i x y_j/d}|y_j\\rangle\\\\
\n", "&= \\bigotimes_{j=0}^{n-1}\\frac{1}{\\sqrt{2}}\\big(|0\\rangle+e^{2\\pi i x/d}|1\\rangle\\big)
\n", "\\end{align}"]}, {"cell_type": "markdown", "metadata": {}, "source": ["where $d=2^n$. Note that this state is unentangled. Therefore the state fidelity can be measured by applying only single-qubit gates to map the state back to the computational basis. In the example circuits above, the initial state $|x\\rangle=|0\\rangle$, and so the output state is"]}, {"cell_type": "markdown", "metadata": {}, "source": ["$$\\bigotimes_{j=0}^{n-1}\\frac{1}{\\sqrt{2}}\\big(|0\\rangle + |1\\rangle\\big) = |+\\rangle^{\\otimes n}$$"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The state fidelity can then be measured by applying a Hadamard gate to each qubit and recording the probability of measuring $|0\\rangle$."]}, {"cell_type": "markdown", "metadata": {}, "source": ["We define a function to measure all qubits in the Hadamard basis and append this circuit to the QFT circuits:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def meas_Had_basis(orig_circ, n_qubits):\n", " circ = orig_circ.copy()\n", " for j in range(n_qubits):\n", " circ.H(j)\n", " circ.add_barrier(range(n_qubits))\n", " circ.measure_all()\n", " return circ"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed = meas_Had_basis(qft_fixed, n_qubits)\n", "render_circuit_jupyter(qft_fid_fixed)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_arbZZ = meas_Had_basis(qft_arbZZ, n_qubits)\n", "render_circuit_jupyter(qft_fid_arbZZ)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Select Device"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Login to the Quantinuum API using your credentials and check the device status."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-2E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Compile the circuits to the Quantinuum backend."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled = backend.get_compiled_circuit(\n", " qft_fid_fixed, optimisation_level=1\n", ")\n", "render_circuit_jupyter(qft_fid_fixed_compiled)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_arbZZ_compiled = backend.get_compiled_circuit(\n", " qft_fid_arbZZ, optimisation_level=1\n", ")\n", "render_circuit_jupyter(qft_fid_arbZZ_compiled)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Depth"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that the circuit depth for the fixed-angle vs. arbitrary angle is less. The difference increases as more qubits are used."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(\"Circuit Depth for fixed-angle QFT:\", qft_fixed.depth())\n", "print(\"Circuit Depth for arbitrary-angle QFT:\", qft_arbZZ.depth())\n", "print(\"Difference:\", qft_fixed.depth() - qft_arbZZ.depth())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Check Circuit Cost"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Check the cost in HQC's for each circuit. See that the Arbitrary angle ZZ QFT uses fewer HQCs, which is a plus."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that in this case because an emulator is used, the specific syntax checker the emulator uses is specified. This is an optional parameter not needed if you are using a quantum computer target."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 1000\n", "print(\n", " \"Fixed angle QFT:\",\n", " backend.cost(qft_fid_fixed_compiled, n_shots=n_shots, syntax_checker=\"H1-2SC\"),\n", ")\n", "print(\n", " \"Arbitrary angle ZZ QFT:\",\n", " backend.cost(qft_fid_arbZZ_compiled, n_shots=n_shots, syntax_checker=\"H1-2SC\"),\n", ")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Run the Circuit"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now run the circuits on Quantinuum systems. First compiling the circuits to the backend, then submitting to the device."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_handle = backend.process_circuit(\n", " qft_fid_fixed_compiled, n_shots=n_shots\n", ")\n", "qft_fid_arbZZ_compiled_handle = backend.process_circuit(\n", " qft_fid_arbZZ_compiled, n_shots=n_shots\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_status = backend.circuit_status(qft_fid_fixed_compiled_handle)\n", "print(qft_fid_fixed_compiled_status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_arbZZ_compiled_status = backend.circuit_status(qft_fid_arbZZ_compiled_handle)\n", "print(qft_fid_arbZZ_compiled_status)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Retrieve Results"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_result = backend.get_result(qft_fid_fixed_compiled_handle)\n", "qft_fid_arbZZ_compiled_result = backend.get_result(qft_fid_arbZZ_compiled_handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Analyze Results"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Here the distribution of bitstrings is retrieved to inspect."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_distro = qft_fid_fixed_compiled_result.get_distribution()\n", "qft_fid_arbZZ_compiled_distro = qft_fid_arbZZ_compiled_result.get_distribution()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["For the QFT with the appended measurement in the Hadamard basis, we expect the QFT to return all 0's in the result bitstring. Investigating the results for both the fixed and arbitrary ZZ versions of QFT, we see this is the bitstring with the highest frequency. This is good, this is what is desired."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_distro"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_arbZZ_compiled_distro"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Comparing the results between the fixed and arbitrary ZZ versions we see that the fidelity is higher using the arbitrary ZZ gate."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(\n", " \"Fixed angle QFT:\",\n", " qft_fid_fixed_compiled_distro[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)],\n", ")\n", "print(\n", " \"Arbitrary Angle ZZ QFT:\",\n", " qft_fid_arbZZ_compiled_distro[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)],\n", ")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Arbitrary Angle ZZ Gates via pytket"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains a comparison of circuits with and without use of Quantinuum's native arbitrary-angle ZZ gate in `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [Arbitrary Angle ZZ Gates](#arb-zz)
\n", "* [Quantum Fourier Transform](#qft)
\n", "* [QFT with Fixed Angle Gates](#qft-fixed)
\n", "* [QFT with Arbitrary Angle ZZ Gates](#qft-arb-zz)
\n", "* [Compare Results](#compare)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Arbitrary Angle ZZ Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Quantinuum System Model H1's native gate set includes arbitrary angle ZZ gates. This is beneficial for reducing the 2-qubit gate count for many quantum algorithms and gate sequences."]}, {"cell_type": "markdown", "metadata": {}, "source": ["$RZZ(\\theta) = e^{-i\\frac{\\theta}{2}\\hat{Z} \\otimes \\hat{Z}}= e^{-i \\frac{\\theta}{2}} \\begin{bmatrix} 1 & 0 & 0 & 0\\\\ 0 & e^{-i\\theta} & 0 & 0\\\\ 0 & 0 & e^{-i\\theta} & 0\\\\ 0 & 0 & 0 & 1 \\end{bmatrix}$
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that $RZZ(\\frac{\\pi}{2}) = ZZ()$."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Quantum circuits that use the gate sequence CNOT, RZ, CNOT can be replaced with the arbitrary angle ZZ gate, shown below. This enables a lower number of 2-qubit gates in a quantum circuit, improving performance by decreasing gate errors."]}, {"cell_type": "markdown", "metadata": {}, "source": ["
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["

\n", "
\n", "
"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook demonstrates the Quantum Fourier Transform (QFT) with and without the $RZZ$ gate."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Quantum Fourier Transform "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The Quantum Fourier Transform (QFT) is an algorithm that serves as a sub-routine in multiple quantum algorithms, including Shor's factoring algorithm. Below are two functions, written in `pytket`, that work together to implement the QFT."]}, {"cell_type": "markdown", "metadata": {}, "source": ["The `QFT` function can be used to create the QFT. It takes the following arguments:
\n", "- `n`: number of qubits to use in the QFT circuit
\n", "- `arbZZ`: specify whether to use the arbitrary-angle ZZ gate or not, `True`/`False`, default: `False`
\n", "- `approx`: if set to integer `k`, then controlled rotations by angles less than $\\frac{\\pi}{2}^{k}$ do not occur"]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note:** In many presentations of the QFT, the circuit includes a round of SWAP gates at the end of the circuit that reverses the order of the qubits. The QFT circuits in this tutorial do not include this final SWAP step."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note:** In `pytket` the $RZZ$ gate is implemented with the $ZZPhase$ circuit function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import numpy as np\n", "from pytket import Circuit\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def control_phase(circ, theta, q0, q1, arbZZ=False):\n", " \"\"\"circuit gadget for performing controlled-[1 0;0 e^i theta]\n", " Inputs:\n", " circ: pytket Circuit object\n", " theta: Z rotation angle (in units of pi)\n", " q0: control qubit\n", " q1: target qubit\n", " arbZZ (bool): enables arbitrary angle RZZ gate\n", " \"\"\"\n", " if arbZZ == False:\n", " # decompose into CNOTs\n", " circ.Rz(theta / 2, q1)\n", " circ.CX(q0, q1)\n", " circ.Rz(-theta / 2, q1)\n", " circ.CX(q0, q1)\n", " circ.Rz(theta / 2, q0)\n", " elif arbZZ == True:\n", " circ.Rz(theta / 2, q0)\n", " circ.Rz(theta / 2, q1)\n", " if theta > 0:\n", " circ.X(q0)\n", " circ.ZZPhase(theta / 2, q0, q1)\n", " circ.X(q0)\n", " elif theta <= 0:\n", " circ.ZZPhase(-theta / 2, q0, q1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def QFT(n, **kwargs):\n", " \"\"\"\n", " Function to implement the Quantum Fourier Transform\n", " n : number of qubits\n", " approx: if set to integer k, then sets that largest\n", " value of pi/2**k occuring in controlled rotation\n", " returns circ: pytket Circuit object\n", " \"\"\"\n\n", " # optional keyword arguments\n", " arbZZ = kwargs.get(\"arbZZ\", False)\n", " approx = kwargs.get(\"approx\", None)\n\n", " # initialize\n", " circ_name = \"QFT-arbZZ\" if arbZZ else \"QFT-fixed\"\n", " circ = Circuit(n, n, name=circ_name)\n", " for j in range(n - 1):\n", " q = n - 1 - j\n", " circ.H(q)\n", " for i in range(j + 1):\n", " if approx == None or approx >= j + 1 - i:\n", " control_phase(\n", " circ, 1 / (2 ** (j + 1 - i)), q - 1, n - 1 - i, arbZZ=arbZZ\n", " )\n", " circ.H(0)\n", " return circ"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## QFT with Fixed Angle Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["First, create the circuit with fixed-angle gates."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note**: `pytket` renders circuits in ZX-calculus notation. This can be toggled on and off by pressing the top left button."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_qubits = 12"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fixed = QFT(n_qubits, arbZZ=False)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(qft_fixed)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## QFT with Arbitrary Angle ZZ Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Second, create the circuit with arbitrary-angle ZZ gates."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_arbZZ = QFT(n_qubits, arbZZ=True)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(qft_arbZZ)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Compare Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now we compare the results of the QFT circuits with and without use of the arbitrary-angle ZZ gates on hardware."]}, {"cell_type": "markdown", "metadata": {}, "source": ["### State Fidelity"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The QFT circuit applied to the computational basis state $|x\\rangle$ creates the state"]}, {"cell_type": "markdown", "metadata": {}, "source": ["\\begin{align}
\n", "QFT|x\\rangle&=\\frac{1}{\\sqrt{d}}\\sum_{y=0}^{d-1} e^{2\\pi i x y/d} |y\\rangle\\\\
\n", "&= \\bigotimes_{j=0}^{n-1}\\frac{1}{\\sqrt{2}}\\sum_{y_j=0}^1e^{2\\pi i x y_j/d}|y_j\\rangle\\\\
\n", "&= \\bigotimes_{j=0}^{n-1}\\frac{1}{\\sqrt{2}}\\big(|0\\rangle+e^{2\\pi i x/d}|1\\rangle\\big)
\n", "\\end{align}"]}, {"cell_type": "markdown", "metadata": {}, "source": ["where $d=2^n$. Note that this state is unentangled. Therefore the state fidelity can be measured by applying only single-qubit gates to map the state back to the computational basis. In the example circuits above, the initial state $|x\\rangle=|0\\rangle$, and so the output state is"]}, {"cell_type": "markdown", "metadata": {}, "source": ["$$\\bigotimes_{j=0}^{n-1}\\frac{1}{\\sqrt{2}}\\big(|0\\rangle + |1\\rangle\\big) = |+\\rangle^{\\otimes n}$$"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The state fidelity can then be measured by applying a Hadamard gate to each qubit and recording the probability of measuring $|0\\rangle$."]}, {"cell_type": "markdown", "metadata": {}, "source": ["We define a function to measure all qubits in the Hadamard basis and append this circuit to the QFT circuits:"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def meas_Had_basis(orig_circ, n_qubits):\n", " circ = orig_circ.copy()\n", " for j in range(n_qubits):\n", " circ.H(j)\n", " circ.add_barrier(range(n_qubits))\n", " circ.measure_all()\n", " return circ"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed = meas_Had_basis(qft_fixed, n_qubits)\n", "render_circuit_jupyter(qft_fid_fixed)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_arbZZ = meas_Had_basis(qft_arbZZ, n_qubits)\n", "render_circuit_jupyter(qft_fid_arbZZ)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Select Device"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Login to the Quantinuum API using your credentials and check the device status."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-2E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Compile the circuits to the Quantinuum backend."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled = backend.get_compiled_circuit(\n", " qft_fid_fixed, optimisation_level=1\n", ")\n", "render_circuit_jupyter(qft_fid_fixed_compiled)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_arbZZ_compiled = backend.get_compiled_circuit(\n", " qft_fid_arbZZ, optimisation_level=1\n", ")\n", "render_circuit_jupyter(qft_fid_arbZZ_compiled)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Depth"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that the circuit depth for the fixed-angle vs. arbitrary angle is less. The difference increases as more qubits are used."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(\"Circuit Depth for fixed-angle QFT:\", qft_fixed.depth())\n", "print(\"Circuit Depth for arbitrary-angle QFT:\", qft_arbZZ.depth())\n", "print(\"Difference:\", qft_fixed.depth() - qft_arbZZ.depth())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Check Circuit Cost"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Check the cost in HQC's for each circuit. See that the Arbitrary angle ZZ QFT uses fewer HQCs, which is a plus."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that in this case because an emulator is used, the specific syntax checker the emulator uses is specified. This is an optional parameter not needed if you are using a quantum computer target."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 1000\n", "print(\n", " \"Fixed angle QFT:\",\n", " backend.cost(qft_fid_fixed_compiled, n_shots=n_shots, syntax_checker=\"H1-2SC\"),\n", ")\n", "print(\n", " \"Arbitrary angle ZZ QFT:\",\n", " backend.cost(qft_fid_arbZZ_compiled, n_shots=n_shots, syntax_checker=\"H1-2SC\"),\n", ")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Run the Circuit"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now run the circuits on Quantinuum systems. First compiling the circuits to the backend, then submitting to the device."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_handle = backend.process_circuit(\n", " qft_fid_fixed_compiled, n_shots=n_shots\n", ")\n", "qft_fid_arbZZ_compiled_handle = backend.process_circuit(\n", " qft_fid_arbZZ_compiled, n_shots=n_shots\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_status = backend.circuit_status(qft_fid_fixed_compiled_handle)\n", "print(qft_fid_fixed_compiled_status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_arbZZ_compiled_status = backend.circuit_status(qft_fid_arbZZ_compiled_handle)\n", "print(qft_fid_arbZZ_compiled_status)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Retrieve Results"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_result = backend.get_result(qft_fid_fixed_compiled_handle)\n", "qft_fid_arbZZ_compiled_result = backend.get_result(qft_fid_arbZZ_compiled_handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Analyze Results"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Here the distribution of bitstrings is retrieved to inspect."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_distro = qft_fid_fixed_compiled_result.get_distribution()\n", "qft_fid_arbZZ_compiled_distro = qft_fid_arbZZ_compiled_result.get_distribution()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["For the QFT with the appended measurement in the Hadamard basis, we expect the QFT to return all 0's in the result bitstring. Investigating the results for both the fixed and arbitrary ZZ versions of QFT, we see this is the bitstring with the highest frequency. This is good, this is what is desired."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_fixed_compiled_distro"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["qft_fid_arbZZ_compiled_distro"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Comparing the results between the fixed and arbitrary ZZ versions we see that the fidelity is higher using the arbitrary ZZ gate."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(\n", " \"Fixed angle QFT:\",\n", " qft_fid_fixed_compiled_distro[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)],\n", ")\n", "print(\n", " \"Arbitrary Angle ZZ QFT:\",\n", " qft_fid_arbZZ_compiled_distro[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)],\n", ")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2023 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file diff --git a/examples/Quantinuum_circuit_submissions.ipynb b/examples/Quantinuum_circuit_submissions.ipynb index 9bc224db..50d1e9b7 100644 --- a/examples/Quantinuum_circuit_submissions.ipynb +++ b/examples/Quantinuum_circuit_submissions.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Quantinuum Circuit Submissions via pytket"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains basic circuit submission examples to Quantinuum quantum hardware via `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [What is TKET?](#tket)
\n", "* [Step by Step](#step-by-step)
\n", " * [Circuit Preparation](#circuit-preparation)
\n", " * [Select Device](#select-device)
\n", " * [Circuit Compilation](#circuit-compilation)
\n", " * [Circuit Cost](#circuit-cost)
\n", " * [Run the Circuit](#run-circuit)
\n", " * [Retrieve Results](#retrieve-results)
\n", " * [Save Results](#save-results)
\n", " * [Analyze Results](#analyze-results)
\n", " * [Cancel Jobs](#cancel-jobs)
\n", "* [Additional Features](#additional-features)
\n", " * [Extended Circuit Compilation](#circuit-compilation-extended)
\n", " * [Batch Submission](#batch-submission)
\n", " * [Parametrized Circuits](#parametrized-circuits)
\n", " * [Conditional Gates](#conditional-gates)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## What is TKET? "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The TKET framework (pronounced \"ticket\") is a software platform for the development and execution of gate-level quantum computation, providing state-of-the-art performance in circuit compilation. It was created and is maintained by Quantinuum. The toolset is designed to extract the most out of the available NISQ devices of today and is platform-agnostic."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In python, the `pytket` packages is available for python 3.9+. The `pytket` and `pytket-quantinuum` packages are included as part of the installation instructions on the user portal."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information on TKET, see the following links:
\n", "- [TKET manual](https://cqcl.github.io/pytket/manual/manual_intro.html)
\n", "- [TKET overview and demo video](https://www.youtube.com/watch?v=yXKSpvgAtrk)
\n", "- [Introduction to Quantum Compilation with TKET](https://github.com/CalMacCQ/tket_blog/blob/main/blog1_intro_to_qc.ipynb)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook covers how to use `pytket` in conjunction with `pytket-quantinuum` to submit to Quantinuum devices. The quantum compilation step is demonstrated, but for a full overview of quantum compilation with TKET, the last link above is recommended."]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the links below for the `pytket` and `pytket-quantinuum` documentation:
\n", "- [pytket](https://cqcl.github.io/tket/pytket/api/index.html)
\n", "- [pytket-quantinuum](https://cqcl.github.io/pytket-quantinuum/api/index.html)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Step by Step "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Preparation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create your circuit via the pytket python library. For details on getting started with `pytket`, see pytket's [Getting Started](https://cqcl.github.io/tket/pytket/api/getting_started.html) page."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note**: `pytket` renders circuits in ZX-calculus notation. This can be toggled on and off by pressing the top left button in the circuit display."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, fresh_symbol\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up Bell Test"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Select Device "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Select a machine and login to the Quantinuum API using your credentials. See the *Quantinuum Systems User Guide* in the *Examples* tab on the *Quantinuum User Portal* for information and target names for each of the H-Series systems available."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Users need to login once per session. In the notebook, a dialogue box will ask for credentials. If running a script, users be prompted at the shell. You can also [save your email in the pytket config](https://cqcl.github.io/pytket-extensions/api/quantinuum/api.html#pytket.extensions.quantinuum.backends.config.set_quantinuum_config)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The device status can be checked using `device_state`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", QuantinuumBackend.device_state(device_name=machine))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Available devices can be viewed using the `available_devices` function. Additional information is returned, here just the device names are pulled in."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["[x.device_name for x in QuantinuumBackend.available_devices()]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Circuits submitted to Quantinuum H-Series quantum computers and emulators are automatically run through TKET compilation passes for H-Series hardware. This enables circuits to be automatically optimized for H-Series systems and run more efficiently."]}, {"cell_type": "markdown", "metadata": {}, "source": ["More information on the specific compilation passes applied can be found on the `pytket-quantinuum` documentation, specifically the [Default Compilation](https://cqcl.github.io/pytket-quantinuum/api/index.html#default-compilation) section. In the H-Series software stack, the optimization level applied is set with the `tket-opt-level` parameter. **The default compilation setting for circuits submited to H-Series sytems is optimization level 2.** More information is found in the *Quantinuum Application Programming Interface (API) Specification*."]}, {"cell_type": "markdown", "metadata": {}, "source": ["When using `pytket` before submitting to hardware, the `get_compiled_circuit` function performs the same compilation passes run after submission to Quantinuum systems. The advantage of using the function before submitting to H-Series hardware is to see exactly what circuit optimizations will be performed when submitted to hardware and determine if a different optimization level is desired. The `optimisation_level` parameter in the `get_compiled_circuit` function corresponds directly to the the level of optimisation after submitting to the H-Series systems and to the `tket-opt-level` parameter in the H-Series API. The default compilation for the `get_compiled_circuit` function is optimization level 2, the same as when submitting to the H-Series directly."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Since the TKET compilation passes have been integrated into the H-Series stack, performing circuit optimizations is redundant before submitting to hardware, unless the user would like to see the optimizations applied before submitting. Given this, users may take 1 of 3 approaches when submitting jobs:
\n", "1. Use `optimisation_level=0` when running `get_compiled_circuit`, then submit the circuit using `process_circuits` knowing that the corresponding optimization level actually run will be 2.
\n", "2. Use the `get_compiled_circuit` function with the desired optimization level to observe the transformed circuit before submitting and then specify `tket-opt-level=None` in the `process_circuits` function when submitting, in order for the optimizations to be applied as desired.
\n", "3. If the user desires to have no optimizations applied, use `optimisation_level=0` in `get_compiled_circuit` and `tket-opt-level=None` in `process_circuits`. This should be specified in both functions."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In this example, option 1 is illustrated, using `get_compiled_circuit` just to rebase the circuit and leaving the optimizations to be done in the H-Series stack."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=0)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Cost "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Before running on Quantinuum systems, it is good practice to check how many HQCs a job will cost, in order to plan usage. In `pytket` this can be done using the `cost` function of the `QuantinuumBackend`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that in this case because an emulator is used, the specific syntax checker the emulator uses is specified. This is an optional parameter not needed if you are using a quantum computer target."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Run the Circuit "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now the circuit can be run on Quantinuum systems."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note:** As described above, the TKET compilation optimization level 2 will be applied since no `tket-opt-level` is specified."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The status of a submitted job can be viewed at any time, indicating if a job is in the queue or completed. Additional information is also provided, such as queue position, start times, completion time, and circuit cost in H-Series Quantum Credits (HQCs)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Retrieve Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a job's status returns completed, results can be returned using the `get_result` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Save Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["It is recommended that users save job results as soon as jobs are completed due to the Quantinuum data retention policy."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import json"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Results can be loaded to their original format using `BackendResult.from_dict`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.backends.backendresult import BackendResult"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_example.json\") as file:\n", " data = json.load(file)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = BackendResult.from_dict(data)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Analyze Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["There are multiple options for analyzing results with pytket. A few examples are highlighted here. More can be seen at [Interpreting Results](https://cqcl.github.io/pytket/manual/manual_backend.html#interpreting-results)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)\n", "print(result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from bit to position in the measured state"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.bit_readout)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from qubit to position in the measured state"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.qubit_readout)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from qubits to the bits to which their measurement values were written"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.qubit_to_bit_map)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Canceling jobs "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Jobs that have been submitted can also be cancelled if needed."]}, {"cell_type": "markdown", "metadata": {}, "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)
\n", "backend.cancel(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Additional Features "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section covers additional features available in `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [Extended Circuit Compilation](#circuit-compilation-extended)
\n", "* [Batch Submission](#batch-submission)
\n", "* [Parametrized Circuits](#parametrized-circuits)
\n", "* [Conditional Gates](#conditional-gates)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Extended Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section leverages the discussion in the [Circuit Compilation](#circuit-compilation) section to illsutrate how to turn TKET compilations on or off in the `process_circuit` function, specifically for options 2 and 3."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For option 2 as described in [Circuit Compilation](#circuit-compilation), suppose a user explores the results of TKET compilation passes on a circuit and finds that `optimisation_level=1` is desirable. The submission below specifies this in the `get_compiled_circuit` function with optimization level 1. Because the circuit is optimized beforehand, the TKET optimization in the H-Series stack should be turned off. The value `tket-opt-level:None` turns off TKET optimization in the H-Series stack."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, options={\"tket-opt-level\": None}\n", ")\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["For option 3 as described in [Circuit Compilation](#circuit-compilation), suppose a user wants to turn off all optimizations in the stack, even simple single-qubit combinations done by the H-Series compiler. This can be done by setting `optimisation_level=0` in `get_compiled_circuit` and setting `tket-opt-level:None` in the `process_circuits` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=0)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, options={\"tket-opt-level\": None}\n", ")\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Batch Submission "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The batch feature on Quantinuum systems gives users the ability to create \"ad-hoc\" reservations. Circuits submitted together in a batch will run at one time. The benefit to users is that once a batch hits the front of the queue, jobs in a batch will run uninterrupted until they are completed."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a batch is submitted, jobs can continue to be added to the batch, ending either when the user signifies the end of a batch or after 1 minute of inactivity."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Batches cannot exceed the maximum limit of 500 H-System Quantum Credits (HQCs) total. If the total HQCs for jobs in a batch hit this limit or a smaller limit set by the user, those jobs *will not be cancelled*. Instead, they will continue to run as regular jobs in the queue instead of as a batch."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Currently only the quantum computer and emulator targets support the batching feature. Batching is not supported on the syntax checkers."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information on using this feature in `pytket`, see [Batch Submission](https://cqcl.github.io/pytket-quantinuum/api/index.html#batching)."]}, {"cell_type": "markdown", "metadata": {}, "source": ["To start a batch, use the `start_batch` function, specifying the `max_batch_cost` in HQCs to enforce."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "n_shots = 100\n", "max_batch_cost = 100"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["backend = QuantinuumBackend(device_name=machine)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["batch1 = backend.start_batch(\n", " max_batch_cost=max_batch_cost, circuit=compiled_circuit, n_shots=n_shots\n", ")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Additional jobs can be added to the batch using the `add_to_batch` function. The end of a batch can optionally be specified with the `batch_end` flag."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["batch2 = backend.add_to_batch(batch1, compiled_circuit, n_shots=n_shots)\n", "batch3 = backend.add_to_batch(batch1, compiled_circuit, n_shots=n_shots, batch_end=True)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The status for the batch jobs can be checked once submitted."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle_list = [batch1, batch2, batch3]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status_list = [backend.circuit_status(h) for h in handle_list]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status_list"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Results for batch submissions can be returned using `get_results` (note the plural)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_results(handle_list)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Parametrized Circuits "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Parametrized circuits are common in variational algorithms. Pytket supports parameters within circuits via symbols. For more information, see [Symbolic Circuits](https://cqcl.github.io/pytket/manual/manual_circuit.html?highlight=paramet#symbolic-circuits)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import fresh_symbol"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up parametrized circuit"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["a = fresh_symbol(\"a\")\n", "circuit = Circuit(3, name=\"Parametrized Circuit\")\n", "circuit.X(0)\n", "circuit.CX(0, 1).CX(1, 2)\n", "circuit.Rz(a, 2)\n", "circuit.CX(1, 2).CX(0, 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note the substitution of an actual value to the `a` variable below."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create a version of the circuit that utilizes a specific value for the variable a"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["simulation_circuit = circuit.copy()\n", "simulation_circuit.measure_all()\n", "simulation_circuit.symbol_substitution({a: -0.09})"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Compile the circuit: this includes optimizing the gates and resynthesizing the circuit to Quantinuum's native gate set"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(simulation_circuit)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Conditional Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Pytket supports conditional gates. This may be for implementing error correction or reducing noise. This capability is well-supported by Quantinuum hardware, which supports mid-circuit measurement and qubit reuse. See [Conditional Gates](https://cqcl.github.io/pytket/manual/manual_circuit.html#conditional-gates) for more information on pytket's implementation. The following example demonstrates the quantum teleportation protocol."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, if_bit"]}, {"cell_type": "markdown", "metadata": {}, "source": ["create a circuit and add quantum and classical registers"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ = Circuit(name=\"Conditional Gates Example\")\n", "qreg = circ.add_q_register(\"q\", 3)\n", "creg = circ.add_c_register(\"b\", 2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["prepare q[0] to be in the state |->, which we wish to teleport to q[2]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.X(qreg[0]).H(qreg[0])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["prepare a Bell state on qubits q[1] and q[2]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.H(qreg[1])\n", "circ.CX(qreg[1], qreg[2])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["construct the teleportation protocol"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.CX(qreg[0], qreg[1])\n", "circ.H(qreg[0])\n", "circ.Measure(qreg[0], creg[0])\n", "circ.Measure(qreg[1], creg[1])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if (creg[1] == 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.X(qreg[2], condition=if_bit(creg[1]))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if (creg[0] == 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.Z(qreg[2], condition=if_bit(creg[0]))"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circ)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can utilise pytket's [Assertion](https://cqcl.github.io/pytket/manual/manual_assertion.html#assertion) feature to verify the successful teleportation of the state $| - \\rangle$."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import ProjectorAssertionBox\n", "import numpy as np"]}, {"cell_type": "markdown", "metadata": {}, "source": ["|-><-|"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["proj = np.array([[0.5, -0.5], [-0.5, 0.5]])\n", "circ.add_assertion(ProjectorAssertionBox(proj), [qreg[2]], name=\"debug\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circ)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "n_shots = 100\n", "backend = QuantinuumBackend(device_name=machine)\n", "compiled_circuit = backend.get_compiled_circuit(circ)\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "status"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The `get_debug_info` function returns the success rate of the state assertion averaged across shots. Note that the failed shots are caused by the simulated device errors"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result.get_debug_info()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Quantinuum Circuit Submissions via pytket"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains basic circuit submission examples to Quantinuum quantum hardware via `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [What is TKET?](#tket)
\n", "* [Step by Step](#step-by-step)
\n", " * [Circuit Preparation](#circuit-preparation)
\n", " * [Select Device](#select-device)
\n", " * [Circuit Compilation](#circuit-compilation)
\n", " * [Circuit Cost](#circuit-cost)
\n", " * [Run the Circuit](#run-circuit)
\n", " * [Retrieve Results](#retrieve-results)
\n", " * [Save Results](#save-results)
\n", " * [Analyze Results](#analyze-results)
\n", " * [Cancel Jobs](#cancel-jobs)
\n", "* [Additional Features](#additional-features)
\n", " * [Extended Circuit Compilation](#circuit-compilation-extended)
\n", " * [Batch Submission](#batch-submission)
\n", " * [Parametrized Circuits](#parametrized-circuits)
\n", " * [Conditional Gates](#conditional-gates)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## What is TKET? "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The TKET framework (pronounced \"ticket\") is a software platform for the development and execution of gate-level quantum computation, providing state-of-the-art performance in circuit compilation. It was created and is maintained by Quantinuum. The toolset is designed to extract the most out of the available NISQ devices of today and is platform-agnostic."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In python, the `pytket` packages is available for python 3.9+. The `pytket` and `pytket-quantinuum` packages are included as part of the installation instructions on the user portal."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information on TKET, see the following links:
\n", "- [TKET manual](https://cqcl.github.io/pytket/manual/manual_intro.html)
\n", "- [TKET overview and demo video](https://www.youtube.com/watch?v=yXKSpvgAtrk)
\n", "- [Introduction to Quantum Compilation with TKET](https://github.com/CalMacCQ/tket_blog/blob/main/blog1_intro_to_qc.ipynb)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook covers how to use `pytket` in conjunction with `pytket-quantinuum` to submit to Quantinuum devices. The quantum compilation step is demonstrated, but for a full overview of quantum compilation with TKET, the last link above is recommended."]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the links below for the `pytket` and `pytket-quantinuum` documentation:
\n", "- [pytket](https://cqcl.github.io/tket/pytket/api/index.html)
\n", "- [pytket-quantinuum](https://cqcl.github.io/pytket-quantinuum/api/index.html)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Step by Step "]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Preparation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create your circuit via the pytket python library. For details on getting started with `pytket`, see pytket's [Getting Started](https://cqcl.github.io/tket/pytket/api/getting_started.html) page."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note**: `pytket` renders circuits in ZX-calculus notation. This can be toggled on and off by pressing the top left button in the circuit display."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, fresh_symbol\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up Bell Test"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Select Device "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Select a machine and login to the Quantinuum API using your credentials. See the *Quantinuum Systems User Guide* in the *Examples* tab on the *Quantinuum User Portal* for information and target names for each of the H-Series systems available."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Users need to login once per session. In the notebook, a dialogue box will ask for credentials. If running a script, users be prompted at the shell. You can also [save your email in the pytket config](https://cqcl.github.io/pytket-extensions/api/quantinuum/api.html#pytket.extensions.quantinuum.backends.config.set_quantinuum_config)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The device status can be checked using `device_state`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", QuantinuumBackend.device_state(device_name=machine))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Available devices can be viewed using the `available_devices` function. Additional information is returned, here just the device names are pulled in."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["[x.device_name for x in QuantinuumBackend.available_devices()]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Circuits submitted to Quantinuum H-Series quantum computers and emulators are automatically run through TKET compilation passes for H-Series hardware. This enables circuits to be automatically optimized for H-Series systems and run more efficiently."]}, {"cell_type": "markdown", "metadata": {}, "source": ["More information on the specific compilation passes applied can be found on the `pytket-quantinuum` documentation, specifically the [Default Compilation](https://cqcl.github.io/pytket-quantinuum/api/index.html#default-compilation) section. In the H-Series software stack, the optimization level applied is set with the `tket-opt-level` parameter. **The default compilation setting for circuits submited to H-Series sytems is optimization level 2.** More information is found in the *Quantinuum Application Programming Interface (API) Specification*."]}, {"cell_type": "markdown", "metadata": {}, "source": ["When using `pytket` before submitting to hardware, the `get_compiled_circuit` function performs the same compilation passes run after submission to Quantinuum systems. The advantage of using the function before submitting to H-Series hardware is to see exactly what circuit optimizations will be performed when submitted to hardware and determine if a different optimization level is desired. The `optimisation_level` parameter in the `get_compiled_circuit` function corresponds directly to the the level of optimisation after submitting to the H-Series systems and to the `tket-opt-level` parameter in the H-Series API. The default compilation for the `get_compiled_circuit` function is optimization level 2, the same as when submitting to the H-Series directly."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Since the TKET compilation passes have been integrated into the H-Series stack, performing circuit optimizations is redundant before submitting to hardware, unless the user would like to see the optimizations applied before submitting. Given this, users may take 1 of 3 approaches when submitting jobs:
\n", "1. Use `optimisation_level=0` when running `get_compiled_circuit`, then submit the circuit using `process_circuits` knowing that the corresponding optimization level actually run will be 2.
\n", "2. Use the `get_compiled_circuit` function with the desired optimization level to observe the transformed circuit before submitting and then specify `tket-opt-level=None` in the `process_circuits` function when submitting, in order for the optimizations to be applied as desired.
\n", "3. If the user desires to have no optimizations applied, use `optimisation_level=0` in `get_compiled_circuit` and `tket-opt-level=None` in `process_circuits`. This should be specified in both functions."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In this example, option 1 is illustrated, using `get_compiled_circuit` just to rebase the circuit and leaving the optimizations to be done in the H-Series stack."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=0)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Cost "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Before running on Quantinuum systems, it is good practice to check how many HQCs a job will cost, in order to plan usage. In `pytket` this can be done using the `cost` function of the `QuantinuumBackend`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note that in this case because an emulator is used, the specific syntax checker the emulator uses is specified. This is an optional parameter not needed if you are using a quantum computer target."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Run the Circuit "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now the circuit can be run on Quantinuum systems."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note:** As described above, the TKET compilation optimization level 2 will be applied since no `tket-opt-level` is specified."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The status of a submitted job can be viewed at any time, indicating if a job is in the queue or completed. Additional information is also provided, such as queue position, start times, completion time, and circuit cost in H-Series Quantum Credits (HQCs)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Retrieve Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a job's status returns completed, results can be returned using the `get_result` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Save Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["It is recommended that users save job results as soon as jobs are completed due to the Quantinuum data retention policy."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import json"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Results can be loaded to their original format using `BackendResult.from_dict`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.backends.backendresult import BackendResult"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_example.json\") as file:\n", " data = json.load(file)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = BackendResult.from_dict(data)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Analyze Results "]}, {"cell_type": "markdown", "metadata": {}, "source": ["There are multiple options for analyzing results with pytket. A few examples are highlighted here. More can be seen at [Interpreting Results](https://cqcl.github.io/pytket/manual/manual_backend.html#interpreting-results)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)\n", "print(result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from bit to position in the measured state"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.bit_readout)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from qubit to position in the measured state"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.qubit_readout)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Map from qubits to the bits to which their measurement values were written"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(compiled_circuit.qubit_to_bit_map)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Canceling jobs "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Jobs that have been submitted can also be cancelled if needed."]}, {"cell_type": "markdown", "metadata": {}, "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)
\n", "backend.cancel(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Additional Features "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section covers additional features available in `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [Extended Circuit Compilation](#circuit-compilation-extended)
\n", "* [Batch Submission](#batch-submission)
\n", "* [Parametrized Circuits](#parametrized-circuits)
\n", "* [Conditional Gates](#conditional-gates)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Extended Circuit Compilation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section leverages the discussion in the [Circuit Compilation](#circuit-compilation) section to illsutrate how to turn TKET compilations on or off in the `process_circuit` function, specifically for options 2 and 3."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For option 2 as described in [Circuit Compilation](#circuit-compilation), suppose a user explores the results of TKET compilation passes on a circuit and finds that `optimisation_level=1` is desirable. The submission below specifies this in the `get_compiled_circuit` function with optimization level 1. Because the circuit is optimized beforehand, the TKET optimization in the H-Series stack should be turned off. The value `tket-opt-level:None` turns off TKET optimization in the H-Series stack."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, options={\"tket-opt-level\": None}\n", ")\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["For option 3 as described in [Circuit Compilation](#circuit-compilation), suppose a user wants to turn off all optimizations in the stack, even simple single-qubit combinations done by the H-Series compiler. This can be done by setting `optimisation_level=0` in `get_compiled_circuit` and setting `tket-opt-level:None` in the `process_circuits` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=0)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, options={\"tket-opt-level\": None}\n", ")\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Batch Submission "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The batch feature on Quantinuum systems gives users the ability to create \"ad-hoc\" reservations. Circuits submitted together in a batch will run at one time. The benefit to users is that once a batch hits the front of the queue, jobs in a batch will run uninterrupted until they are completed."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a batch is submitted, jobs can continue to be added to the batch, ending either when the user signifies the end of a batch or after 1 minute of inactivity."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Batches cannot exceed the maximum limit of 500 H-System Quantum Credits (HQCs) total. If the total HQCs for jobs in a batch hit this limit or a smaller limit set by the user, those jobs *will not be cancelled*. Instead, they will continue to run as regular jobs in the queue instead of as a batch."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Currently only the quantum computer and emulator targets support the batching feature. Batching is not supported on the syntax checkers."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information on using this feature in `pytket`, see [Batch Submission](https://cqcl.github.io/pytket-quantinuum/api/index.html#batching)."]}, {"cell_type": "markdown", "metadata": {}, "source": ["To start a batch, use the `start_batch` function, specifying the `max_batch_cost` in HQCs to enforce."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "n_shots = 100\n", "max_batch_cost = 100"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["backend = QuantinuumBackend(device_name=machine)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["batch1 = backend.start_batch(\n", " max_batch_cost=max_batch_cost, circuit=compiled_circuit, n_shots=n_shots\n", ")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Additional jobs can be added to the batch using the `add_to_batch` function. The end of a batch can optionally be specified with the `batch_end` flag."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["batch2 = backend.add_to_batch(batch1, compiled_circuit, n_shots=n_shots)\n", "batch3 = backend.add_to_batch(batch1, compiled_circuit, n_shots=n_shots, batch_end=True)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The status for the batch jobs can be checked once submitted."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle_list = [batch1, batch2, batch3]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status_list = [backend.circuit_status(h) for h in handle_list]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status_list"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Results for batch submissions can be returned using `get_results` (note the plural)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_results(handle_list)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Parametrized Circuits "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Parametrized circuits are common in variational algorithms. Pytket supports parameters within circuits via symbols. For more information, see [Symbolic Circuits](https://cqcl.github.io/pytket/manual/manual_circuit.html?highlight=paramet#symbolic-circuits)."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import fresh_symbol"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up parametrized circuit"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["a = fresh_symbol(\"a\")\n", "circuit = Circuit(3, name=\"Parametrized Circuit\")\n", "circuit.X(0)\n", "circuit.CX(0, 1).CX(1, 2)\n", "circuit.Rz(a, 2)\n", "circuit.CX(1, 2).CX(0, 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Note the substitution of an actual value to the `a` variable below."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Create a version of the circuit that utilizes a specific value for the variable a"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["simulation_circuit = circuit.copy()\n", "simulation_circuit.measure_all()\n", "simulation_circuit.symbol_substitution({a: -0.09})"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Compile the circuit: this includes optimizing the gates and resynthesizing the circuit to Quantinuum's native gate set"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(simulation_circuit)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Conditional Gates "]}, {"cell_type": "markdown", "metadata": {}, "source": ["Pytket supports conditional gates. This may be for implementing error correction or reducing noise. This capability is well-supported by Quantinuum hardware, which supports mid-circuit measurement and qubit reuse. See [Conditional Gates](https://cqcl.github.io/pytket/manual/manual_circuit.html#conditional-gates) for more information on pytket's implementation. The following example demonstrates the quantum teleportation protocol."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, if_bit"]}, {"cell_type": "markdown", "metadata": {}, "source": ["create a circuit and add quantum and classical registers"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ = Circuit(name=\"Conditional Gates Example\")\n", "qreg = circ.add_q_register(\"q\", 3)\n", "creg = circ.add_c_register(\"b\", 2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["prepare q[0] to be in the state |->, which we wish to teleport to q[2]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.X(qreg[0]).H(qreg[0])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["prepare a Bell state on qubits q[1] and q[2]"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.H(qreg[1])\n", "circ.CX(qreg[1], qreg[2])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["construct the teleportation protocol"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.CX(qreg[0], qreg[1])\n", "circ.H(qreg[0])\n", "circ.Measure(qreg[0], creg[0])\n", "circ.Measure(qreg[1], creg[1])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if (creg[1] == 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.X(qreg[2], condition=if_bit(creg[1]))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if (creg[0] == 1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circ.Z(qreg[2], condition=if_bit(creg[0]))"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circ)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We can utilise pytket's [Assertion](https://cqcl.github.io/pytket/manual/manual_assertion.html#assertion) feature to verify the successful teleportation of the state $| - \\rangle$."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import ProjectorAssertionBox\n", "import numpy as np"]}, {"cell_type": "markdown", "metadata": {}, "source": ["|-><-|"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["proj = np.array([[0.5, -0.5], [-0.5, 0.5]])\n", "circ.add_assertion(ProjectorAssertionBox(proj), [qreg[2]], name=\"debug\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circ)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "n_shots = 100\n", "backend = QuantinuumBackend(device_name=machine)\n", "compiled_circuit = backend.get_compiled_circuit(circ)\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "status"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The `get_debug_info` function returns the success rate of the state assertion averaged across shots. Note that the failed shots are caused by the simulated device errors"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result.get_debug_info()"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2023 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file diff --git a/examples/Quantinuum_emulator.ipynb b/examples/Quantinuum_emulator.ipynb index 097c646d..ada9bd7a 100644 --- a/examples/Quantinuum_emulator.ipynb +++ b/examples/Quantinuum_emulator.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Submitting to Quantinuum Emulators via pytket"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains examples for running quantum circuits on Quantinuum's emulators via `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["An emulator can be used to get an idea of what a quantum device will output for our quantum circuit. This enables circuit debugging and optimization before running on a physical machine. Emulators differ from simulators in that they model the physical and noise model of the device whereas simulators may model noise parameters, but not physical parameters. The Quantinuum emulators run on a physical noise model of the Quantinuum H-Series devices. There are various noise/error parameters modeled. For detailed information on the noise model, see the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or at [Quantinuum H-series](https://www.quantinuum.com/products/h1)."]}, {"cell_type": "markdown", "metadata": {}, "source": ["There are a few options for using the emulator:"]}, {"cell_type": "markdown", "metadata": {}, "source": ["1. **Basic Usage:** Use the emulator as provided, which represents both the physical operations in the device as well as the noise. This the most common and simplest way to use the emulator.
\n", "2. **Noiseless Emulation:** Use the emulator without the physical noise model applied. The physical device operations are represented, but all errors are set to 0.
\n", "3. **Noise Parameters (*advanced option*):** Experiment with the noise parameters in the emulator. There is no guarantee that results achieved changing these parameters will represent outputs from the actual quantum computer represented.
\n", "4. **Stabilizer Emulator:** Use of the emulator for circuits involving only Clifford operations."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information, see the *Quantinuum System Model H1 Emulator Product Data Sheet*, *Quantinuum Systems User Guide*, and *Quantinuum Application Programming Interface (API)* on the Quantinuum User Portal for detailed information on each of the emulators available and workflow information including job submission, queueing, and the full list of options available."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Emulator Usage:**
\n", "* [Basic Usage](#basic-usage)
\n", "* [Noiseless Emulation](#no-noise)
\n", "* [Noise Parameters (*advanced*)](#noise)
\n", "* [Stabilizer Emulator](#stabilizer)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Emulator Usage"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Basic Usage "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section covers usage of the emulator which represents a physical and noise model of the device being used. For example, if using the `H1-1E` target, this emulates the H1-1 quantum computer."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Here the circuit is created via the pytket python library. For details on getting started with `pytket`, see pytket's [Getting Started](https://cqcl.github.io/tket/pytket/api/getting_started.html) page."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up Bell Test"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Select the emulation device. See the *Quantinuum Systems User Guide* in the *Examples* tab on the *Quantinuum User Portal* for information and target names for each of the emulators available."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", backend.device_state(device_name=machine))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Compile the circuit to the Quantinuum backend with `get_compiled_circuit`. See the `pytket` [User Manual](https://cqcl.github.io/pytket/manual/index.html) for more information on all the options that are available."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Check the circuit HQC cost before running on the emulator."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Run the circuit on the emulator chosen."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Check the job status."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a job's status returns completed, return results with the `get_result` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["It is recommended to save job results as soon as jobs are completed due to the Quantinuum data retention policy."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import json"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_emulator_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The result output is just like that of a quantum device. The simulation by default runs with noise."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)\n", "print(result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Noiseless Emulation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The Quantinuum emulators may be run with or without the physical device's noise model. The default is the emulator runs with the physical noise model turned on. The physical noise model can be turned off by setting `noisy_simulation=False`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "no_error_model_handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, noisy_simulation=False\n", ")\n", "print(no_error_model_handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["no_error_model_status = backend.circuit_status(no_error_model_handle)\n", "print(no_error_model_status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["no_error_model_result = backend.get_result(no_error_model_handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["no_error_model_result"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_emulator_noiseless_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["no_error_model_result = backend.get_result(no_error_model_handle)\n", "print(no_error_model_result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(no_error_model_result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Noise Parameters "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The emulator runs with default error parameters that represent a noise environment similar to the physical devices. The `error-params` option can be used to override these error parameters and do finer-grain tweaks of the error model. For detailed information on the noise model, see the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) or the *Quantinuum Application Programming Interface (API)* on the user portal."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In this section, examples are given for experimenting with the noise and error parameters of the emulators. These are advanced options and not recommended to start with when doing initial experiments. As mentioned above, there is no guarantee that results achieved changing these parameters will represent outputs from the actual quantum computer represented."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note**: All the noise parameters are used together any time a simulation is run. If only some of the parameters are specified, the rest of the parameters are used at their default settings. The parameters to override are specified with the `options` parameter."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [Physical Noise](#physical-noise)
\n", "* [Dephasing Noise](#dephasing-noise)
\n", "* [Arbitrary Angle Noise Scaling](#arbitrary-angle-noise)
\n", "* [Scaling](#scaling)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Physical Noise "]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) for information on these parameters."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"p1\": 4e-5,\n", " \"p2\": 3e-3,\n", " \"p_meas\": 3e-3,\n", " \"p_init\": 4e-5,\n", " \"p_crosstalk_meas\": 1e-5,\n", " \"p_crosstalk_init\": 3e-5,\n", " \"p1_emission\": 6e-6,\n", " \"p2_emission\": 2e-4,\n", " }\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Dephasing Noise "]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) for information on these parameters."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"coherent_dephasing_rate\": 0.2,\n", " \"incoherent_dephasing_rate\": 0.3,\n", " \"coherent_dephasing\": False, # False => run the incoherent noise model\n", " \"transport_dephasing\": False, # False => turn off transport dephasing error\n", " \"idle_dephasing\": False, # False => turn off idel dephasing error\n", " },\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Arbitrary Angle Noise Scaling "]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) for information on these parameters."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"przz_a\": 1.09,\n", " \"przz_b\": 0.051,\n", " \"przz_c\": 1.365,\n", " \"przz_d\": 0.035,\n", " },\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Scaling "]}, {"cell_type": "markdown", "metadata": {}, "source": ["All the error rates can be scaled linearly using the `scale` parameter. See the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) for more information."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"scale\": 0.1, # scale error rates linearly by 0.1\n", " },\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Other aspects of the noise model can scale specific error rates in the error model, which are modeled here."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"p1_scale\": 0.1,\n", " \"p2_scale\": 0.1,\n", " \"meas_scale\": 0.1,\n", " \"init_scale\": 0.1,\n", " \"memory_scale\": 0.1,\n", " \"emission_scale\": 0.1,\n", " \"crosstalk_scale\": 0.1,\n", " \"leakage_scale\": 0.1,\n", " },\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Stabilizer Emulator "]}, {"cell_type": "markdown", "metadata": {}, "source": ["By default, emulations are run using a state-vector emulator, which simulates any quantum operation. However, if the quantum operations are all Clifford gates, it can be faster for complex circuits to use the `stabilizer` emulator. The stabilizer emulator is requested in the setup of the `QuantinuumBackend` with the `simulator` input option. This only applies to Quantinuum emulators."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\""]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_backend = QuantinuumBackend(device_name=machine, simulator=\"stabilizer\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", stabilizer_backend.device_state(device_name=machine))\n", "print(\"Simulation type:\", stabilizer_backend.simulator_type)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "stabilizer_handle = stabilizer_backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots\n", ")\n", "print(stabilizer_handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_status = stabilizer_backend.circuit_status(stabilizer_handle)\n", "print(stabilizer_status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_result = stabilizer_backend.get_result(stabilizer_handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_result"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_emulator_stabilizer_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_result = stabilizer_backend.get_result(stabilizer_handle)\n", "print(stabilizer_result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(stabilizer_result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Noiseless Stabilizer"]}, {"cell_type": "markdown", "metadata": {}, "source": ["A noiseless stabilizer simulation can be specified via options in the `process_circuit` function with the following options:"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- `simulator`: choose to run with a `stabilizer` simulator or `state-vector` (default is `state-vector`)
\n", "- `error-model`: whether to run with or without the physical device noise model on or off. The default is `True`, which means the physical noise model is turned on. If set to `False`, the physical noise model is turned off, performing noiseless simulation."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"simulator\": \"stabilizer\",\n", " \"error-model\": False,\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Submitting to Quantinuum Emulators via pytket"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains examples for running quantum circuits on Quantinuum's emulators via `pytket`."]}, {"cell_type": "markdown", "metadata": {}, "source": ["An emulator can be used to get an idea of what a quantum device will output for our quantum circuit. This enables circuit debugging and optimization before running on a physical machine. Emulators differ from simulators in that they model the physical and noise model of the device whereas simulators may model noise parameters, but not physical parameters. The Quantinuum emulators run on a physical noise model of the Quantinuum H-Series devices. There are various noise/error parameters modeled. For detailed information on the noise model, see the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or at [Quantinuum H-series](https://www.quantinuum.com/products/h1)."]}, {"cell_type": "markdown", "metadata": {}, "source": ["There are a few options for using the emulator:"]}, {"cell_type": "markdown", "metadata": {}, "source": ["1. **Basic Usage:** Use the emulator as provided, which represents both the physical operations in the device as well as the noise. This the most common and simplest way to use the emulator.
\n", "2. **Noiseless Emulation:** Use the emulator without the physical noise model applied. The physical device operations are represented, but all errors are set to 0.
\n", "3. **Noise Parameters (*advanced option*):** Experiment with the noise parameters in the emulator. There is no guarantee that results achieved changing these parameters will represent outputs from the actual quantum computer represented.
\n", "4. **Stabilizer Emulator:** Use of the emulator for circuits involving only Clifford operations."]}, {"cell_type": "markdown", "metadata": {}, "source": ["For more information, see the *Quantinuum System Model H1 Emulator Product Data Sheet*, *Quantinuum Systems User Guide*, and *Quantinuum Application Programming Interface (API)* on the Quantinuum User Portal for detailed information on each of the emulators available and workflow information including job submission, queueing, and the full list of options available."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Emulator Usage:**
\n", "* [Basic Usage](#basic-usage)
\n", "* [Noiseless Emulation](#no-noise)
\n", "* [Noise Parameters (*advanced*)](#noise)
\n", "* [Stabilizer Emulator](#stabilizer)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Emulator Usage"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Basic Usage "]}, {"cell_type": "markdown", "metadata": {}, "source": ["This section covers usage of the emulator which represents a physical and noise model of the device being used. For example, if using the `H1-1E` target, this emulates the H1-1 quantum computer."]}, {"cell_type": "markdown", "metadata": {}, "source": ["Here the circuit is created via the pytket python library. For details on getting started with `pytket`, see pytket's [Getting Started](https://cqcl.github.io/tket/pytket/api/getting_started.html) page."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up Bell Test"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(2, name=\"Bell Test\")\n", "circuit.H(0)\n", "circuit.CX(0, 1)\n", "circuit.measure_all()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Select the emulation device. See the *Quantinuum Systems User Guide* in the *Examples* tab on the *Quantinuum User Portal* for information and target names for each of the emulators available."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", backend.device_state(device_name=machine))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Compile the circuit to the Quantinuum backend with `get_compiled_circuit`. See the `pytket` [User Manual](https://cqcl.github.io/pytket/manual/index.html) for more information on all the options that are available."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=1)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Check the circuit HQC cost before running on the emulator."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "backend.cost(compiled_circuit, n_shots=n_shots, syntax_checker=\"H1-1SC\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Run the circuit on the emulator chosen."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)\n", "print(handle)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Check the job status."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Once a job's status returns completed, return results with the `get_result` function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result"]}, {"cell_type": "markdown", "metadata": {}, "source": ["It is recommended to save job results as soon as jobs are completed due to the Quantinuum data retention policy."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import json"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_emulator_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The result output is just like that of a quantum device. The simulation by default runs with noise."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)\n", "print(result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Noiseless Emulation "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The Quantinuum emulators may be run with or without the physical device's noise model. The default is the emulator runs with the physical noise model turned on. The physical noise model can be turned off by setting `noisy_simulation=False`."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "no_error_model_handle = backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots, noisy_simulation=False\n", ")\n", "print(no_error_model_handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["no_error_model_status = backend.circuit_status(no_error_model_handle)\n", "print(no_error_model_status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["no_error_model_result = backend.get_result(no_error_model_handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["no_error_model_result"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_emulator_noiseless_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["no_error_model_result = backend.get_result(no_error_model_handle)\n", "print(no_error_model_result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(no_error_model_result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Noise Parameters "]}, {"cell_type": "markdown", "metadata": {}, "source": ["The emulator runs with default error parameters that represent a noise environment similar to the physical devices. The `error-params` option can be used to override these error parameters and do finer-grain tweaks of the error model. For detailed information on the noise model, see the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) or the *Quantinuum Application Programming Interface (API)* on the user portal."]}, {"cell_type": "markdown", "metadata": {}, "source": ["In this section, examples are given for experimenting with the noise and error parameters of the emulators. These are advanced options and not recommended to start with when doing initial experiments. As mentioned above, there is no guarantee that results achieved changing these parameters will represent outputs from the actual quantum computer represented."]}, {"cell_type": "markdown", "metadata": {}, "source": ["**Note**: All the noise parameters are used together any time a simulation is run. If only some of the parameters are specified, the rest of the parameters are used at their default settings. The parameters to override are specified with the `options` parameter."]}, {"cell_type": "markdown", "metadata": {}, "source": ["* [Physical Noise](#physical-noise)
\n", "* [Dephasing Noise](#dephasing-noise)
\n", "* [Arbitrary Angle Noise Scaling](#arbitrary-angle-noise)
\n", "* [Scaling](#scaling)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Physical Noise "]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) for information on these parameters."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"p1\": 4e-5,\n", " \"p2\": 3e-3,\n", " \"p_meas\": 3e-3,\n", " \"p_init\": 4e-5,\n", " \"p_crosstalk_meas\": 1e-5,\n", " \"p_crosstalk_init\": 3e-5,\n", " \"p1_emission\": 6e-6,\n", " \"p2_emission\": 2e-4,\n", " }\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Dephasing Noise "]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) for information on these parameters."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"coherent_dephasing_rate\": 0.2,\n", " \"incoherent_dephasing_rate\": 0.3,\n", " \"coherent_dephasing\": False, # False => run the incoherent noise model\n", " \"transport_dephasing\": False, # False => turn off transport dephasing error\n", " \"idle_dephasing\": False, # False => turn off idel dephasing error\n", " },\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Arbitrary Angle Noise Scaling "]}, {"cell_type": "markdown", "metadata": {}, "source": ["See the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) for information on these parameters."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"przz_a\": 1.09,\n", " \"przz_b\": 0.051,\n", " \"przz_c\": 1.365,\n", " \"przz_d\": 0.035,\n", " },\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Scaling "]}, {"cell_type": "markdown", "metadata": {}, "source": ["All the error rates can be scaled linearly using the `scale` parameter. See the *Quantinuum System Model H1 Emulator Product Data Sheet* on the user portal or [Quantinuum H-Series page](https://www.quantinuum.com/hardware/h1) for more information."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"scale\": 0.1, # scale error rates linearly by 0.1\n", " },\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Other aspects of the noise model can scale specific error rates in the error model, which are modeled here."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"error-params\": {\n", " \"p1_scale\": 0.1,\n", " \"p2_scale\": 0.1,\n", " \"meas_scale\": 0.1,\n", " \"init_scale\": 0.1,\n", " \"memory_scale\": 0.1,\n", " \"emission_scale\": 0.1,\n", " \"crosstalk_scale\": 0.1,\n", " \"leakage_scale\": 0.1,\n", " },\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Stabilizer Emulator "]}, {"cell_type": "markdown", "metadata": {}, "source": ["By default, emulations are run using a state-vector emulator, which simulates any quantum operation. However, if the quantum operations are all Clifford gates, it can be faster for complex circuits to use the `stabilizer` emulator. The stabilizer emulator is requested in the setup of the `QuantinuumBackend` with the `simulator` input option. This only applies to Quantinuum emulators."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-1E\""]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_backend = QuantinuumBackend(device_name=machine, simulator=\"stabilizer\")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", stabilizer_backend.device_state(device_name=machine))\n", "print(\"Simulation type:\", stabilizer_backend.simulator_type)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "stabilizer_handle = stabilizer_backend.process_circuit(\n", " compiled_circuit, n_shots=n_shots\n", ")\n", "print(stabilizer_handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_status = stabilizer_backend.circuit_status(stabilizer_handle)\n", "print(stabilizer_status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_result = stabilizer_backend.get_result(stabilizer_handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_result"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["with open(\"pytket_emulator_stabilizer_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["stabilizer_result = stabilizer_backend.get_result(stabilizer_handle)\n", "print(stabilizer_result.get_distribution())"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(stabilizer_result.get_counts())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["#### Noiseless Stabilizer"]}, {"cell_type": "markdown", "metadata": {}, "source": ["A noiseless stabilizer simulation can be specified via options in the `process_circuit` function with the following options:"]}, {"cell_type": "markdown", "metadata": {}, "source": ["- `simulator`: choose to run with a `stabilizer` simulator or `state-vector` (default is `state-vector`)
\n", "- `error-model`: whether to run with or without the physical device noise model on or off. The default is `True`, which means the physical noise model is turned on. If set to `False`, the physical noise model is turned off, performing noiseless simulation."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["handle = backend.process_circuit(\n", " compiled_circuit,\n", " n_shots=100,\n", " request_options={\n", " \"options\": {\n", " \"simulator\": \"stabilizer\",\n", " \"error-model\": False,\n", " }\n", " },\n", ")"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(result.get_distribution())"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2023 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file diff --git a/examples/Quantinuum_mid-circuit_measurement.ipynb b/examples/Quantinuum_mid-circuit_measurement.ipynb index 4bdc219b..d98768e4 100644 --- a/examples/Quantinuum_mid-circuit_measurement.ipynb +++ b/examples/Quantinuum_mid-circuit_measurement.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Mid-Circuit Measurement"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains an example using mid-circuit measurement using the Quantinuum machines."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Repetition Code Circuit"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The use of mid-circuit measurement is straightforward, note the use of `measure` and `reset` on the ancilla qubits. This example also utlizes conditional logic available with Quantinuum devices as well as Registers and IDs available in `pytket`. See [Classical and conditional operations](https://cqcl.github.io/pytket/manual/manual_circuit.html#classical-and-conditional-operations) and [Registers and IDs](https://cqcl.github.io/pytket/manual/manual_circuit.html#registers-and-ids) for additional examples."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, Qubit, Bit, OpType, reg_eq\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up Repetition Code with mid-circuit measurement and corrections:
\n", "`2 1 0 = data: data qubits`
\n", "`*----*----*`
\n", "` ZZ ZZ`
\n", "` 1 0 = syndromes`
\n", "` 0 0 = ancillas`"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up circuit object"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(name=\"Repetition Code\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Add qubit register, the data qubits"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["data = circuit.add_q_register(\"data\", 3)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Add qubit register, the ancilla qubit"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["ancilla = circuit.add_q_register(\"anc\", 1)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Add classical registers for the syndromes"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["syndrome = circuit.add_c_register(\"syndrome\", 2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Add classical registers for the output"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["output = circuit.add_c_register(\"output\", 3)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Prepare the logical state. Qubits always start in $| 0 \\rangle$ and logical $ | 0 \\rangle == | 000 \\rangle$. So we already start in logical $| 0 \\rangle$.

\n", "Syndrome Extraction"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.add_gate(OpType.Reset, ancilla)\n", "circuit.CX(data[0], ancilla[0])\n", "circuit.CX(data[1], ancilla[0])\n", "circuit.Measure(ancilla[0], syndrome[0])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Syndrome Extraction"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.add_gate(OpType.Reset, ancilla)\n", "circuit.CX(data[1], ancilla[0])\n", "circuit.CX(data[2], ancilla[0])\n", "circuit.Measure(ancilla[0], syndrome[1])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Correction: if(syndromes==1) -> 01 -> check 0 bad -> X on qubit 0"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.X(data[0], condition=reg_eq(syndrome, 1))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if(syndromes==2) -> 10 -> check 1 bad -> X on qubit 2"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.X(data[2], condition=reg_eq(syndrome, 2))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if(syndromes==3) -> 11 -> check 1 and 2 bad -> X on qubit 1"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.X(data[1], condition=reg_eq(syndrome, 3))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Measure out data qubits"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.Measure(data[0], output[0])\n", "circuit.Measure(data[1], output[1])\n", "circuit.Measure(data[2], output[2])"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Select Device"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Login to the Quantinuum API using your credentials and check the device status."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-2E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", QuantinuumBackend.device_state(device_name=machine))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation"]}, {"cell_type": "markdown", "metadata": {}, "source": ["`pytket` includes many features for optimizing circuits. This includes reducing the number of gates where possible and resynthesizing circuits for a quantum computer's native gate set. See the `pytket` [User Manual](https://cqcl.github.io/pytket/manual/index.html) for more information on all the options that are available.

\n", "Here the circuit is compiled with `get_compiled_circuit`, which includes optimizing the gates and resynthesizing the circuit to Quantinuum's native gate set. The `optimisation_level` sets the level of optimization to perform during compilation, check pytket documentation for more details."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=1)\n", "render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Submit and Run the Circuit"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)\n", "print(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import json"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)\n", "with open(\"pytket_mcmr_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Analyze Results"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We will now take the raw results and apply a majority vote to determine how many times we got 0 vs 1.
\n", "First, define a majority vote function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def majority(result):\n", " \"\"\"Returns whether the output should be considered a 0 or 1.\"\"\"\n", " if result.count(0) > result.count(1):\n", " return 0\n", " elif result.count(0) < result.count(1):\n", " return 1\n", " else:\n", " raise Exception(\"count(0) should not equal count(1)\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now process the output"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result_output_cnts = result.get_counts([output[i] for i in range(output.size)])\n", "result_output_cnts"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["zeros = 0 # Counts the shots with majority zeros\n", "ones = 0 # Counts the shots with majority ones\n", "for out in result_output_cnts:\n", " m = majority(out)\n", " if m == 0:\n", " zeros += result_output_cnts[out]\n", " else:\n", " ones += result_output_cnts[out]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["A logical zero was initialized, so our error rate should be number of ones / total number of shots: `ones/shots`"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["p = ones / n_shots\n", "print(f\"The error-rate is: p = {p}\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2022 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "metadata": {}, "source": ["![Quantinuum_logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIIAAABLCAMAAACLOq%2BzAAACx1BMVEUAAAAAAP%2BAgIBVqqqAgIBmmZmAgKptkpKAgJ9xjo6AgJl0i6JqgJV2iZ1tgJJ3iJlwgJ94h5ZxgJx5hpRzgJl5hp50gJdvhZt1gJVwhZl2gJ12gJtyhJV3gJlzhJx4gJd0g5txgJZ1g5lxgJx1g5hygJp2g5ZzgJl2g5tzgJh3gpp0gJdxgpl0gJtygph1gJpygpd1gJlzgpt2gJhzgpp2gJd0gplygJt0gphygJp1gpdzgJl1gptzgJh1gpp2gZl0gJtygZh0gJpzgZh1gJlzgZp1gJhzgZp1gJh0gZl0gZhygJp0gZhzgJl0gZpzgJh1gZpzgJh1gZl0gJp1gZh0gJp0gJlzgZp0gJhzgZp1gJhzgZl1gJp0gZh1gJp0gZhzgJl0gZpzgJlzgJh1gZlzgJp1gZl1gZh0gJl0gJlzgZl0gJhzgZl1gJp0gZl1gJl0gZh1gJl0gZpzgJl0gZlzgJh0gZlzgJp0gZl0gJl1gJh1gJpzgJl0gJhzgJl0gJpzgJl0gJl1gJl0gJp1gJl0gJl1gJhzgJp0gJlzgJl0gJh0gJl1gJp0gJl1gJl0gJh1gJl0gJpzgJl0gJlzgJh0gJl0gJp0gJl0gJl1gJh0gJl1gJp0gJlzgJl0gJh0gJl0gJp0gJl0gJl0gJh1gJl0gJpzgJh0gJl0gJl0gJl1gJp0gJl1gJl0gJhzgJl0gJl0gJl0gJh0gJl0gJp0gJl0gJl1gJh0gJlzgJp0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJlzgJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl1gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJl0gJn%2F%2F%2F%2Bc0JCdAAAA63RSTlMAAQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRocHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9BQkNERUZHSElKS01OT1BRUlNUVVZXWFpbXF1eX2BhYmNkZWZoaWprbW5wcXJzdHV2d3h5ent8fX5%2FgIGDhYaHiImKjI2Oj5CSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq%2Bws7a3ubq7vL2%2BwMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbY2drb3N3e3%2BDh4uPk5ebn6Orr7O3u7%2FHy8%2FT19vf4%2Bfr7%2FP3%2B7Jw5zgAAAAFiS0dE7CG5sxsAAAVfSURBVBgZ7cGNV9X1AcfxNxcwnhRRaVCsKGszI%2BbDcs3KlDKldAmhGywz0ZyJOqLUHrBraVoKJD5E%2BBDaarXS2tZ0jmkqKjlLKR9SA6EFCNzPP7Hv7%2F7QmMm9nM754jkdXi9%2BsNCxL7x9uLb266qKZx%2BI5Ar4yYsn9J2GNyd46F6e%2BfW6RFWmh2404ANdxq6f022uOajL%2BvYPIXSPyN3qTFkY1vUBytW5tyOwLHE%2BjFMg73iwKqpyCCEHFFAhVpXsgfEKzJeBRWO1CDYpiK%2FisCbsU91N%2BDkFU4Q1WVIkqWrX%2BvGTv04Ih96Dp246o47aUrBlpxogR351z8XzHc%2F4j9TBGiz5lVQD82W0Lo7lErfv0EWN8dixTDoICyTV3Mn3heY36YK52LFf%2BgLypH%2FHcVlDT6vddqxI8EnfQLb29qMTg0%2FJ1RSNDQ%2FJiGJEVTydGlQv1%2F3YMEdGGp4BBJAt1xPYsFTGYoLYIL8l2LBZRhVBJDXJ8TI2%2FEmOewhilRwrsGGDHO8QxI1yvIgNa%2BQ3hiCqZCzChmXyq76KwBbLmIsN0%2BQqIbAHZEzGhmFql0dAKTKSsCGiRa622QQSI6kGO7bpgqWhBNAgrcSOabroX7fRuQ8%2Fqx6JHX2bdNH55ddxJZSrg5aNE6Lpdre06v80bnvVW5DfbnZuR6OxZKW6qhxL%2Btaoi97Altub1TWvY81jPnXJeuzJV5esw6LHW9UFa7Ep%2FayCK8Wqaz9QUKux7OFjCqIE28If2aeAiukGtxX%2B47w6VUT3iBg8Mdc1K%2F8S99GjR48ePXr06PHjkzRjycIxHhyR0%2BNwxOT0wxH64G%2F74xrzaDR%2B9%2F4SeDDzghDwZCZh3PdoJH7jhgLXZobhiH84Aph4E36TBgGpmem0S52eDuFLz8vYPwRjiMbj%2BJlycGRLr%2BKq1N964zi0HqjXBTEQockYB7UtGsexImCSYnHMVCJQl4cjwrcAWCaNxy%2F2tE4SskXb74i%2B5omGhhRgpDJwpGgGRtjhszuarsNvd5t2xmJ8XgYMHZ2WdqQuLS1tWBhEaQrGoTb9tTfGVyXAJF2NI0%2BJQF0Bjr5aACz31X%2FaC8cSfXOWDK0LwfjFt7tC4E49gmOEpmFMVW5KSyl%2Be%2F68QJX9gFPluHafwBWj32FUbynUjljg3GrgIf0UR74SgbrncAzQ08CKs7M0DyO56d2t9Ww%2FFYPfUxoOqZqN435lAeGf7fVQ0jIQx97NzNG%2BBKjbiKvyGK4%2BysE4vJYC7Y6H5lJgggbheF6JwJmXcFyvfOCVk6H7ziUAFa23ljdzeg2uFM2CG7QQxxSNA6ZrEiS3lOPYvwHm6EgyjZtx7TqCq69%2Bj3FkNTyp6iSP1gLpugvHMiUCp9bjSFEesPILRqkM7tFrlLbS8Bqu6%2FVHCP36n6EYmxv7QK9jenxKVu6J1sEYB8qAuTpxq68C18fVuOI0FePzYqBANalaDyRrHUbvmuO9gA%2FPxGE8rVFA0VHY4rsr7EBDAkUtHNiJK10ZwHy9lUD0cnmBmWq3FeNQGUaBarUV1%2FYqXP01DeNoMcYi1aoMY5MKI0neoRyMe31%2Fv5FeeS0fhQAlR2Fg8755WgirmnlWo%2FCLHRgKeFZIdY16Ixyu%2BrJy%2BDBHqW8IUF2G4xnpLVzvfYIrXtMxaopxPC%2BVY8T8ReePy1eI38xmX81%2FtedqjNVHgZfV9mUUrGok%2FvjpsXQ0svj90jSMG7zD8Yt%2BZiwwLwu%2FXG82rqzHcMV4R2AU%2FAa%2FGd7JOEImvv7e8mG0u3nJuxuzw3Fk5AP9vd7RwMQCGPQfHayoKClZ6R3FlRJV8MnJ2trG2trZXBH%2FA2RBOeTINIkQAAAAAElFTkSuQmCC)
\n", "# Mid-Circuit Measurement"]}, {"cell_type": "markdown", "metadata": {}, "source": ["This notebook contains an example using mid-circuit measurement using the Quantinuum machines."]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Repetition Code Circuit"]}, {"cell_type": "markdown", "metadata": {}, "source": ["The use of mid-circuit measurement is straightforward, note the use of `measure` and `reset` on the ancilla qubits. This example also utlizes conditional logic available with Quantinuum devices as well as Registers and IDs available in `pytket`. See [Classical and conditional operations](https://cqcl.github.io/pytket/manual/manual_circuit.html#classical-and-conditional-operations) and [Registers and IDs](https://cqcl.github.io/pytket/manual/manual_circuit.html#registers-and-ids) for additional examples."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.circuit import Circuit, Qubit, Bit, OpType, reg_eq\n", "from pytket.circuit.display import render_circuit_jupyter"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up Repetition Code with mid-circuit measurement and corrections:
\n", "`2 1 0 = data: data qubits`
\n", "`*----*----*`
\n", "` ZZ ZZ`
\n", "` 1 0 = syndromes`
\n", "` 0 0 = ancillas`"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Set up circuit object"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit = Circuit(name=\"Repetition Code\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Add qubit register, the data qubits"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["data = circuit.add_q_register(\"data\", 3)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Add qubit register, the ancilla qubit"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["ancilla = circuit.add_q_register(\"anc\", 1)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Add classical registers for the syndromes"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["syndrome = circuit.add_c_register(\"syndrome\", 2)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Add classical registers for the output"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["output = circuit.add_c_register(\"output\", 3)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Prepare the logical state. Qubits always start in $| 0 \\rangle$ and logical $ | 0 \\rangle == | 000 \\rangle$. So we already start in logical $| 0 \\rangle$.

\n", "Syndrome Extraction"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.add_gate(OpType.Reset, ancilla)\n", "circuit.CX(data[0], ancilla[0])\n", "circuit.CX(data[1], ancilla[0])\n", "circuit.Measure(ancilla[0], syndrome[0])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Syndrome Extraction"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.add_gate(OpType.Reset, ancilla)\n", "circuit.CX(data[1], ancilla[0])\n", "circuit.CX(data[2], ancilla[0])\n", "circuit.Measure(ancilla[0], syndrome[1])"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Correction: if(syndromes==1) -> 01 -> check 0 bad -> X on qubit 0"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.X(data[0], condition=reg_eq(syndrome, 1))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if(syndromes==2) -> 10 -> check 1 bad -> X on qubit 2"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.X(data[2], condition=reg_eq(syndrome, 2))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["if(syndromes==3) -> 11 -> check 1 and 2 bad -> X on qubit 1"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.X(data[1], condition=reg_eq(syndrome, 3))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Measure out data qubits"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["circuit.Measure(data[0], output[0])\n", "circuit.Measure(data[1], output[1])\n", "circuit.Measure(data[2], output[2])"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["render_circuit_jupyter(circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Select Device"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Login to the Quantinuum API using your credentials and check the device status."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["from pytket.extensions.quantinuum import QuantinuumBackend"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["machine = \"H1-2E\"\n", "backend = QuantinuumBackend(device_name=machine)\n", "backend.login()"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["print(machine, \"status:\", QuantinuumBackend.device_state(device_name=machine))"]}, {"cell_type": "markdown", "metadata": {}, "source": ["### Circuit Compilation"]}, {"cell_type": "markdown", "metadata": {}, "source": ["`pytket` includes many features for optimizing circuits. This includes reducing the number of gates where possible and resynthesizing circuits for a quantum computer's native gate set. See the `pytket` [User Manual](https://cqcl.github.io/pytket/manual/index.html) for more information on all the options that are available.

\n", "Here the circuit is compiled with `get_compiled_circuit`, which includes optimizing the gates and resynthesizing the circuit to Quantinuum's native gate set. The `optimisation_level` sets the level of optimization to perform during compilation, check pytket documentation for more details."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["compiled_circuit = backend.get_compiled_circuit(circuit, optimisation_level=1)\n", "render_circuit_jupyter(compiled_circuit)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Submit and Run the Circuit"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["n_shots = 100\n", "handle = backend.process_circuit(compiled_circuit, n_shots=n_shots)\n", "print(handle)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["status = backend.circuit_status(handle)\n", "print(status)"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["import json"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result = backend.get_result(handle)\n", "with open(\"pytket_mcmr_example.json\", \"w\") as file:\n", " json.dump(result.to_dict(), file)"]}, {"cell_type": "markdown", "metadata": {}, "source": ["## Analyze Results"]}, {"cell_type": "markdown", "metadata": {}, "source": ["We will now take the raw results and apply a majority vote to determine how many times we got 0 vs 1.
\n", "First, define a majority vote function."]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["def majority(result):\n", " \"\"\"Returns whether the output should be considered a 0 or 1.\"\"\"\n", " if result.count(0) > result.count(1):\n", " return 0\n", " elif result.count(0) < result.count(1):\n", " return 1\n", " else:\n", " raise Exception(\"count(0) should not equal count(1)\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["Now process the output"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["result_output_cnts = result.get_counts([output[i] for i in range(output.size)])\n", "result_output_cnts"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["zeros = 0 # Counts the shots with majority zeros\n", "ones = 0 # Counts the shots with majority ones\n", "for out in result_output_cnts:\n", " m = majority(out)\n", " if m == 0:\n", " zeros += result_output_cnts[out]\n", " else:\n", " ones += result_output_cnts[out]"]}, {"cell_type": "markdown", "metadata": {}, "source": ["A logical zero was initialized, so our error rate should be number of ones / total number of shots: `ones/shots`"]}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": ["p = ones / n_shots\n", "print(f\"The error-rate is: p = {p}\")"]}, {"cell_type": "markdown", "metadata": {}, "source": ["
© 2023 by Quantinuum. All Rights Reserved.
"]}], "metadata": {"kernelspec": {"display_name": "Python 3", "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.6.4"}}, "nbformat": 4, "nbformat_minor": 2} \ No newline at end of file diff --git a/examples/python/Quantinuum_arbitrary_zz.py b/examples/python/Quantinuum_arbitrary_zz.py index 052d5b03..9365472c 100644 --- a/examples/python/Quantinuum_arbitrary_zz.py +++ b/examples/python/Quantinuum_arbitrary_zz.py @@ -261,4 +261,4 @@ def meas_Had_basis(orig_circ, n_qubits): qft_fid_arbZZ_compiled_distro[(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)], ) -#
© 2022 by Quantinuum. All Rights Reserved.
+#
© 2023 by Quantinuum. All Rights Reserved.
diff --git a/examples/python/Quantinuum_circuit_submissions.py b/examples/python/Quantinuum_circuit_submissions.py index 374e8cd7..13ad5408 100644 --- a/examples/python/Quantinuum_circuit_submissions.py +++ b/examples/python/Quantinuum_circuit_submissions.py @@ -344,4 +344,4 @@ result.get_debug_info() -#
© 2022 by Quantinuum. All Rights Reserved.
+#
© 2023 by Quantinuum. All Rights Reserved.
diff --git a/examples/python/Quantinuum_emulator.py b/examples/python/Quantinuum_emulator.py index ee49b684..33c5d8dc 100644 --- a/examples/python/Quantinuum_emulator.py +++ b/examples/python/Quantinuum_emulator.py @@ -300,4 +300,4 @@ print(result.get_distribution()) -#
© 2022 by Quantinuum. All Rights Reserved.
+#
© 2023 by Quantinuum. All Rights Reserved.
diff --git a/examples/python/Quantinuum_mid-circuit_measurement.py b/examples/python/Quantinuum_mid-circuit_measurement.py index 43521cc9..a3525055 100644 --- a/examples/python/Quantinuum_mid-circuit_measurement.py +++ b/examples/python/Quantinuum_mid-circuit_measurement.py @@ -130,4 +130,4 @@ def majority(result): p = ones / n_shots print(f"The error-rate is: p = {p}") -#
© 2022 by Quantinuum. All Rights Reserved.
+#
© 2023 by Quantinuum. All Rights Reserved.
diff --git a/pytket/extensions/quantinuum/__init__.py b/pytket/extensions/quantinuum/__init__.py index e583d89d..acd118f4 100644 --- a/pytket/extensions/quantinuum/__init__.py +++ b/pytket/extensions/quantinuum/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/quantinuum/backends/__init__.py b/pytket/extensions/quantinuum/backends/__init__.py index 512576e1..6d285bef 100644 --- a/pytket/extensions/quantinuum/backends/__init__.py +++ b/pytket/extensions/quantinuum/backends/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/quantinuum/backends/api_wrappers.py b/pytket/extensions/quantinuum/backends/api_wrappers.py index 058aac45..c82f04a2 100644 --- a/pytket/extensions/quantinuum/backends/api_wrappers.py +++ b/pytket/extensions/quantinuum/backends/api_wrappers.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/quantinuum/backends/config.py b/pytket/extensions/quantinuum/backends/config.py index 0bb01799..37392d4f 100644 --- a/pytket/extensions/quantinuum/backends/config.py +++ b/pytket/extensions/quantinuum/backends/config.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/quantinuum/backends/credential_storage.py b/pytket/extensions/quantinuum/backends/credential_storage.py index ae6f7bfd..5e2a6924 100644 --- a/pytket/extensions/quantinuum/backends/credential_storage.py +++ b/pytket/extensions/quantinuum/backends/credential_storage.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/quantinuum/backends/federated_login.py b/pytket/extensions/quantinuum/backends/federated_login.py index 0db23d21..14ae80d7 100644 --- a/pytket/extensions/quantinuum/backends/federated_login.py +++ b/pytket/extensions/quantinuum/backends/federated_login.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/quantinuum/backends/quantinuum.py b/pytket/extensions/quantinuum/backends/quantinuum.py index 9e74f5ad..5fc6ee66 100644 --- a/pytket/extensions/quantinuum/backends/quantinuum.py +++ b/pytket/extensions/quantinuum/backends/quantinuum.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/setup.py b/setup.py index c0e20468..e7703c03 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/api1_test.py b/tests/api1_test.py index 24161cc1..bfaa86e8 100644 --- a/tests/api1_test.py +++ b/tests/api1_test.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/api_test.py b/tests/api_test.py index 1848bb45..d73dcd34 100644 --- a/tests/api_test.py +++ b/tests/api_test.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/backend_test.py b/tests/backend_test.py index 528bf63f..8ac7a520 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/conftest.py b/tests/conftest.py index 97911075..4303aca6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/convert_test.py b/tests/convert_test.py index 1a114d9c..f7fe5fbb 100644 --- a/tests/convert_test.py +++ b/tests/convert_test.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From dcbd0388aeb8d3221b25cff5ca2c946e0314ab27 Mon Sep 17 00:00:00 2001 From: Yao Tang Date: Fri, 6 Jan 2023 12:46:32 +0000 Subject: [PATCH 10/17] use asyncio.run if running in worker threads --- docs/changelog.rst | 1 + pytket/extensions/quantinuum/backends/api_wrappers.py | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 626480ee..08af97c8 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Unreleased ---------- * Drop support for Python 3.8; add support for 3.11. +* The backend now works in threads other than the main. 0.12.0 (December 2022) ---------------------- diff --git a/pytket/extensions/quantinuum/backends/api_wrappers.py b/pytket/extensions/quantinuum/backends/api_wrappers.py index c82f04a2..2deac6a6 100644 --- a/pytket/extensions/quantinuum/backends/api_wrappers.py +++ b/pytket/extensions/quantinuum/backends/api_wrappers.py @@ -372,7 +372,13 @@ def retrieve_job( if "websocket" in jr: # wait for job completion using websocket - jr = asyncio.get_event_loop().run_until_complete(self._wait_results(job_id)) + try: + loop = asyncio.get_event_loop() + jr = loop.run_until_complete(self._wait_results(job_id)) + except RuntimeError: + # no event loop in thread, call asyncio.run to use a new loop + jr = asyncio.run(self._wait_results(job_id)) + else: # poll for job completion jr = self._poll_results(job_id) From 23dabc1b190d5a99440a5b5fc51f237967fc9503 Mon Sep 17 00:00:00 2001 From: cqc-melf <70640934+cqc-melf@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:28:52 +0000 Subject: [PATCH 11/17] fix python version in docs build (#103) --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c07131d7..f2d4a8d6 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: 3.10 + python-version: '3.10' - name: Upgrade pip and install wheel run: pip install --upgrade pip wheel - name: Install pytket quantinuum From 2e32622c38aad9a0e493a89c3622dac87711d838 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 17 Jan 2023 19:56:35 +0000 Subject: [PATCH 12/17] Docs/update docs (#104) * update .gitignore * Update logo name * Use sphinx-copybutton * use borland pygments * update build-docs * update css colour to grey --- .../{Quantinuum_logo2.png => Quantinuum_logo.png} | Bin .github/workflows/docs/build-docs | 4 ++-- .github/workflows/docs/conf.py | 5 +++-- .github/workflows/docs/requirements.txt | 1 + .gitignore | 1 + docs/_static/custom.css | 2 +- 6 files changed, 8 insertions(+), 5 deletions(-) rename .github/workflows/docs/{Quantinuum_logo2.png => Quantinuum_logo.png} (100%) diff --git a/.github/workflows/docs/Quantinuum_logo2.png b/.github/workflows/docs/Quantinuum_logo.png similarity index 100% rename from .github/workflows/docs/Quantinuum_logo2.png rename to .github/workflows/docs/Quantinuum_logo.png diff --git a/.github/workflows/docs/build-docs b/.github/workflows/docs/build-docs index 9d5f4282..a4554661 100755 --- a/.github/workflows/docs/build-docs +++ b/.github/workflows/docs/build-docs @@ -40,9 +40,9 @@ def build_module_docs(): mod_docs = MODULES_DIR / "docs" mod_build = mod_docs / "build" conf_copy = mod_docs / "conf.py" - logo_copy = mod_docs / "Quantinuum_logo2.png" + logo_copy = mod_docs / "Quantinuum_logo.png" shutil.copy(DOCS_DIR / "conf.py", conf_copy) - shutil.copy(DOCS_DIR / "Quantinuum_logo2.png", logo_copy) + shutil.copy(DOCS_DIR / "Quantinuum_logo.png", logo_copy) remove_dir(mod_build) index_rst = mod_docs / "index.rst" with open(mod_docs / "intro.txt", "r") as f: diff --git a/.github/workflows/docs/conf.py b/.github/workflows/docs/conf.py index 8ffb57bf..a7bb7ac2 100644 --- a/.github/workflows/docs/conf.py +++ b/.github/workflows/docs/conf.py @@ -10,9 +10,10 @@ "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.mathjax", + "sphinx_copybutton", ] -pygments_style = "pastie" +pygments_style = "borland" html_theme = "sphinx_book_theme" @@ -26,7 +27,7 @@ html_css_files = ["custom.css"] -html_logo = "Quantinuum_logo2.png" +html_logo = "Quantinuum_logo.png" # -- Extension configuration ------------------------------------------------- diff --git a/.github/workflows/docs/requirements.txt b/.github/workflows/docs/requirements.txt index 382fc378..31e91260 100644 --- a/.github/workflows/docs/requirements.txt +++ b/.github/workflows/docs/requirements.txt @@ -1,2 +1,3 @@ sphinx ~= 4.3.2 sphinx_book_theme +sphinx-copybutton diff --git a/.gitignore b/.gitignore index b3ca666d..051b7715 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ build dist *.pyc +.venv .vscode .mypy_cache .hypothesis diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 6552cb58..732d595d 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -32,7 +32,7 @@ a:visited, .sig-param, .std.std-ref, a { - color: #2563EB; + color: #544d4d; } :root { From 329eb4b1960a25b410ddfd645ad3da05e93df1ec Mon Sep 17 00:00:00 2001 From: melf Date: Wed, 18 Jan 2023 10:10:33 +0000 Subject: [PATCH 13/17] update version --- _metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_metadata.py b/_metadata.py index eaf20aef..0d252387 100644 --- a/_metadata.py +++ b/_metadata.py @@ -1,2 +1,2 @@ -__extension_version__ = "0.12.0" +__extension_version__ = "0.13.0" __extension_name__ = "pytket-quantinuum" From e5d0e31dc3f550df439132d037e609056f04b828 Mon Sep 17 00:00:00 2001 From: melf Date: Wed, 18 Jan 2023 10:10:51 +0000 Subject: [PATCH 14/17] update changelog --- docs/changelog.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 08af97c8..9dcdb285 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,8 +1,8 @@ Changelog ~~~~~~~~~ -Unreleased ----------- +0.13.0 (January 2022) +--------------------- * Drop support for Python 3.8; add support for 3.11. * The backend now works in threads other than the main. From 952f1491c1ffe1e39fe34a3435883d5f8ca3c6a1 Mon Sep 17 00:00:00 2001 From: melf Date: Wed, 18 Jan 2023 10:11:15 +0000 Subject: [PATCH 15/17] update pytket version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e7703c03..2437ada2 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ packages=find_namespace_packages(include=["pytket.*"]), include_package_data=True, install_requires=[ - "pytket == 1.11.0rc0", + "pytket ~= 1.11", "requests >= 2.2", "types-requests", "websockets >= 7.0", From 5e94579e5fdf6804aa6c03e17abc4d4a69cd8d47 Mon Sep 17 00:00:00 2001 From: melf Date: Wed, 18 Jan 2023 10:12:33 +0000 Subject: [PATCH 16/17] update pytket version in changelog --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 9dcdb285..bbdb2d9e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,6 +6,7 @@ Changelog * Drop support for Python 3.8; add support for 3.11. * The backend now works in threads other than the main. +* Updated pytket version requirement to 1.11. 0.12.0 (December 2022) ---------------------- From 25fbe077eed728261887a5d9c4b2b8019d0a2991 Mon Sep 17 00:00:00 2001 From: cqc-melf <70640934+cqc-melf@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:21:40 +0000 Subject: [PATCH 17/17] update changelog to 2023 --- docs/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index bbdb2d9e..4d713981 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,7 +1,7 @@ Changelog ~~~~~~~~~ -0.13.0 (January 2022) +0.13.0 (January 2023) --------------------- * Drop support for Python 3.8; add support for 3.11.