Skip to content

Commit

Permalink
🚸 Python Bindings for NA State Preparation (#556)
Browse files Browse the repository at this point in the history
## Description

This PR aims to provide python bindings for the state preparation for
neutral atoms part of qmap.

## Checklist:

<!---
This checklist serves as a reminder of a couple of things that ensure
your pull request will be merged swiftly.
-->

- [x] The pull request only contains commits that are related to it.
- [x] I have added appropriate tests and documentation.
- [x] I have made sure that all CI jobs on GitHub pass.
- [x] The pull request introduces no new warnings and follows the
project's style guidelines.
  • Loading branch information
ystade authored Nov 18, 2024
2 parents f131dc4 + e7abb4b commit 716b21b
Show file tree
Hide file tree
Showing 22 changed files with 702 additions and 70 deletions.
75 changes: 25 additions & 50 deletions docs/DevelopmentGuide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -179,27 +179,23 @@ Furthermore, they provide a command to automatically format your code according
Working on the Python module
############################

`Pybind11 <https://pybind11.readthedocs.io/>`_ is used for providing bindings of the C++ core library to Python.
`Pybind11 <https://pybind11.readthedocs.io/en/stable/>`_ is used for providing bindings of the C++ core library to Python.
This allows to keep the performance critical parts of the code in C++ while providing a convenient interface for Python users.
All of the bindings code as well as the Python module itself is contained in the :code:`mqt/qmap` directory.
All of the bindings code is contained in the :code:`src/python` directory.
The Python package itself lives in the :code:`src/mqt/qmap` directory.

Building the Python module
--------------------------

The recommended way of building the Python module is to perform an editable install using `pip <https://pip.pypa.io/en/stable/>`_.
It is usually most efficient to install the build dependencies in your environment once and use the following command that avoids a costly creation of a new virtual environment at every compilation:

.. code-block:: console
(venv) $ pip install --editable .[dev]
(venv) $ pip install 'scikit-build-core[pyproject]' setuptools_scm pybind11
(venv) $ pip install --no-build-isolation -ve ".[dev]"
The :code:`--editable` flag ensures that changes in the Python code are instantly available without re-running the command.
The :code:`[dev]` extra makes sure that all dependencies for running the Python tests and building the documentation are available.

.. note::
When using the :code:`zsh` shell it might be necessary to add double quotes around the :code:`.[dev]` part of the command.

.. warning::
Do not forget to run the above command again after any changes to the C++ core library or bindings to make the changes available in the Python module.
You may optionally add :code:`-Ceditable.rebuild=true` to auto-rebuild when the package is imported.
Otherwise, you need to re-run the above after editing C++ files.

Running Python Tests
--------------------
Expand All @@ -210,15 +206,9 @@ A :code:`nox` session is provided to conveniently run the Python tests.

.. code-block:: console
(venv) $ nox -rs tests
(venv) $ nox -s tests
This installs all dependencies for running the tests in an isolated environment, builds the Python package, and then runs the tests.
The :code:`-r` flag ensures that the environment is reused for subsequent runs.
To speed up subsequent runs, the installation step can be skipped by adding the :code:`skip-install` flag.

.. code-block:: console
(venv) $ nox -rs tests -- skip-install

.. note::
If you don't want to use :code:`nox`, you can also run the tests directly using :code:`pytest`.
Expand All @@ -233,36 +223,33 @@ Python Code Formatting and Linting
The Python code is formatted and linted using a collection of `pre-commit hooks <https://pre-commit.com/>`_.
This collection includes:

- `black <https://black.readthedocs.io/en/stable/>`_ -- a code formatter that automatically formats Python code according to the `PEP 8 style guide <https://www.python.org/dev/peps/pep-0008/>`_
- `flake8 <https://flake8.pycqa.org/en/latest/>`_ -- a linter that checks for common mistakes in Python code
- `isort <https://pycqa.github.io/isort/>`_ -- a tool that automatically sorts Python imports according to the `PEP 8 style guide <https://www.python.org/dev/peps/pep-0008/>`_
- `mypy <http://mypy-lang.org/>`_ -- a static type checker for Python code
- `pyupgrade <https://github.com/asottile/pyupgrade>`_ -- a tool that automatically upgrades Python syntax to a newer version
- `ruff <https://docs.astral.sh/ruff/>`_ -- an extremely fast Python linter and formatter, written in Rust.
- `mypy <https://mypy-lang.org/>`_ -- a static type checker for Python code

There are two ways of using these hooks:

- You can install the hooks manually by running :code:`pre-commit install` in the project root directory.
- You can install the hooks manually by running

.. code-block:: console
(venv) $ pre-commit install
in the project root directory.
This will install the hooks in the :code:`.git/hooks` directory of the repository.
The hooks will then be executed automatically when committing changes.

- You can use the :code:`nox` session :code:`lint` to run the hooks manually.

.. code-block:: console
(venv) $ nox -rs lint
(venv) $ nox -s lint
.. note::
If you don't want to use :code:`nox`, you can also run the hooks directly using :code:`pre-commit`.

.. code-block:: console
(venv) $ pre-commit run --all-files
In addition to the pre-commit hooks, the Python code is also type checked by `mypy <http://mypy-lang.org/>`_.
This is done by the :code:`nox` session :code:`mypy`.

.. code-block:: console
(venv) $ nox -rs mypy
(venv) $ pre-commit run --all-files
Working on the Documentation
############################
Expand All @@ -273,31 +260,19 @@ You can build the documentation using the :code:`nox` session :code:`docs`.

.. code-block:: console
(venv) $ nox -rs docs
(venv) $ nox -s docs
.. note::
In order to properly build the jupyter notebooks in the documentation, you need to have :code:`pandoc` installed. See `the pandoc documentation <https://pandoc.org/installing.html>`_ for installation instructions.

This will install all dependencies for building the documentation in an isolated environment, build the Python package, and then build the documentation.
The session also provides a convenient option to automatically serve the docs on a local web server. Running

.. code-block:: console
(venv) $ nox -rs docs -- serve
will start a local web server on port 8000 and provide a link to open the documentation in your browser.

To build the documentation without (re-)installing the Python package, you can use the :code:`skip-install` flag.

.. code-block:: console
(venv) $ nox -rs docs -- skip-install
Additionally, the session will automatically serve the docs on a local web server.

.. note::
If you don't want to use :code:`nox`, you can also build the documentation directly using :code:`sphinx-build`.

.. code-block:: console
(venv) $ sphinx-build -b html docs/source docs/build
(venv) $ sphinx-build -b html docs/ docs/_build
The docs can then be found in the :code:`docs/build` directory.
The docs can then be found in the :code:`docs/_build` directory.
150 changes: 150 additions & 0 deletions docs/NAStatePrep.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<style>.widget-subarea{display:none;} /*hide widgets as they do not work with sphinx*/</style>\n",
"\n",
"# Neutral Atom Logical State Preparation\n",
"\n",
"All quantum computers are prone to errors.\n",
"This is the motivation of employing error correction during a quantum computation.\n",
"To this end, a (logical) qubit on the algorithmic level is encoded into a shared and highly entangled state of multiple physical qubits.\n",
"Before the actual computation can start, those physical qubits need to be prepared in a state that represents the logical zero state.\n",
"\n",
"For that, we provide tool that takes a state preparation circuit and generates an optimal sequence of operations tailored to the zoned neutral atom architecture.\n",
"Thereby, the circuit consists of one initial layer of Hadamard gates on all qubits that initialize the physical qubits in the plus state.\n",
"Those are followed by a set of entangling (CZ) gates that generate a so-called graph state.\n",
"The final logical state is achieved by applying additional Hadamard gates on selected qubits.\n",
"\n",
"Below we demonstrate how the optimal schedule can be retrieved for the Steane-code, the smallest 2D color code.\n",
"First, we create the state preparation circuit for the Steane-code as a `qiskit.QuantumCircuit`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from qiskit import QuantumCircuit\n",
"\n",
"qc = QuantumCircuit(7)\n",
"qc.h(range(7))\n",
"qc.cz(0, 3)\n",
"qc.cz(0, 4)\n",
"qc.cz(1, 2)\n",
"qc.cz(1, 5)\n",
"qc.cz(1, 6)\n",
"qc.cz(2, 3)\n",
"qc.cz(2, 4)\n",
"qc.cz(3, 5)\n",
"qc.cz(4, 6)\n",
"qc.h(0)\n",
"qc.h(2)\n",
"qc.h(5)\n",
"qc.h(6)\n",
"\n",
"qc.draw(output=\"mpl\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We solve the problem of optimal state preparation with an SMT solver (Z3).\n",
"Therefore, we encode the problem into an SMT-model.\n",
"To construct the SMT model, the solver takes the entangling operations (CZ) as a list of qubit pairs."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from mqt.qmap.na import get_ops_for_solver\n",
"\n",
"ops = get_ops_for_solver(qc, \"z\", 1) # We extract the 'Z' gates with '1' control, i.e., CZ gates\n",
"ops"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, we are ready to initialize the solver and to generate the optimal sequence of operations.\n",
"The parameters of the solver describe an architecture with two storage zones with each two rows, one zone above the entangling zone and one below.\n",
"The entangling zone itself consists of three rows and the architecture model has three columns.\n",
"Within each interaction site, atoms can be offset by two sites in every direction.\n",
"The considered architecture offers two AOD columns and three AOD rows.\n",
"\n",
"We instruct the solver to generate a sequence consisting of four stages.\n",
"Thereby, we do not fix the number of transfer stages.\n",
"The last two boolean arguments, specify that the solver needs not to maintain the order of operations and must shield idling qubits in the storage zone.\n",
"For further details on the employed abstraction of the 2D plane in the solver, please refer to the corresponding article :cite:labelpar:`stadeOptimalStatePreparation2024`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from mqt.qmap.na import NAStatePreparationSolver\n",
"\n",
"solver = NAStatePreparationSolver(3, 7, 2, 3, 2, 2, 2, 2, 2, 4)\n",
"result = solver.solve(ops, 7, 4, None, False, True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To inspect the result, it can be exported to the human-readable YAML format by invoking the method `result.yaml()`\n",
"In this example, we take another approach and generate code from the result.\n",
"For that, we call the function `generate_code` with the respective arguments."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from mqt.qmap.na import generate_code\n",
"\n",
"code = generate_code(qc, result)\n",
"print(code)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For further details, please refer to the [reference documentation](library/NAStatePrep.rst)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
33 changes: 31 additions & 2 deletions docs/Publications.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,42 @@ Publications

*QMAP* is academic software. Thus, many of its built-in algorithms have been published as scientific papers.
See :cite:labelpar:`wille2023qmap` for a general overview of *QMAP* and its features.
If you want to cite this article, please use the following BibTeX entry:

.. code-block:: bibtex
@inproceedings{qmap,
title = {{QMAP: A Quantum Circuit Mapping Tool}},
booktitle = {International Symp. on Physical Design},
author = {Wille, Robert and Burgholzer, Lukas},
year = {2023}
}
*QMAP* is part of the Munich Quantum Toolkit, which is described in :cite:labelpar:`willeMQTHandbookSummary2024`.
If you want cite the Munich Quantum Toolkit, please use the following BibTeX entry:

.. code-block:: bibtex
@inproceedings{mqt,
title = {The {{MQT}} Handbook: {{A}} Summary of Design Automation Tools and Software for Quantum Computing},
shorttitle = {{The MQT Handbook}},
booktitle = {IEEE International Conference on Quantum Software (QSW)},
author = {Wille, Robert and Berent, Lucas and Forster, Tobias and Kunasaikaran, Jagatheesan and Mato, Kevin and Peham, Tom and Quetschlich, Nils and Rovara, Damian and Sander, Aaron and Schmid, Ludwig and Schoenberger, Daniel and Stade, Yannick and Burgholzer, Lukas},
date = {2024},
doi = {10.1109/QSW62656.2024.00013},
eprint = {2405.17543},
eprinttype = {arxiv},
addendum = {A live version of this document is available at \url{https://mqt.readthedocs.io}}
}
If you use *QMAP* in your work, we would appreciate if you cited

- :cite:labelpar:`zulehnerEfficientMethodologyMapping2019` when using the heuristic mapper,
- :cite:labelpar:`willeMappingQuantumCircuits2019` when using the exact mapper,
- :cite:labelpar:`peham2023DepthOptimalSynthesis` when using the Clifford circuit synthesis approach, and
- :cite:labelpar:`schmid2024HybridCircuitMapping` when using the hybrid mapper for neutral atom quantum computers.
- :cite:labelpar:`peham2023DepthOptimalSynthesis` when using the Clifford circuit synthesis approach,
- :cite:labelpar:`schmid2024HybridCircuitMapping` when using the hybrid mapper for neutral atom quantum computers,
- :cite:labelpar:`stadeAbstractModelEfficient2024` when using the neutral atom logical array compiler (NALAC), and
- :cite:labelpar:`stadeOptimalStatePreparation2024` when using the optimal state preparation for neutral atoms (NASP).

Furthermore, if you use any of the particular algorithms such as

Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ We appreciate any feedback and contributions to the project. If you want to cont
Installation
Mapping
Synthesis
NAStatePrep
Publications

.. toctree::
Expand Down
1 change: 1 addition & 0 deletions docs/library/Library.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ Library
Synthesis
SynthesisResults
Visualization
NAStatePrep
23 changes: 23 additions & 0 deletions docs/library/NAStatePrep.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Neutral Atom Logical State Preparation
======================================

This module provides functionality to generate an optimal operation sequence for zoned neutral atom architectures.
The input must be a circuit of single-qubit gates, followed by a set of entangling gates (CZ) and finally single-qubit gates on selected qubits.
Those circuits arise in the realm of error correction when the initial logical state must be prepared.

The process is divided into three steps:
1. Extract a list of qubit pairs from the circuit that represents the entangling gates with :code:`get_ops_for_solver`

.. currentmodule:: mqt.qmap.na
.. autofunction:: get_ops_for_solver

2. Supply the list of entangling operations to the solver and generate the optimal operation sequence with the :code:`NAStatePreparationSolver`.
For further details on the employed abstraction of the 2D plane in the solver, please refer to the corresponding article :cite:labelpar:`stadeOptimalStatePreparation2024`.

.. currentmodule:: mqt.qmap.na
.. autoclass:: NAStatePreparationSolver

3. Generate code from the solver's result with :code:`generate_code`

.. currentmodule:: mqt.qmap.na
.. autofunction:: generate_code
Loading

0 comments on commit 716b21b

Please sign in to comment.