@@ -80,10 +131,11 @@ To support this endeavor, please consider:
## Getting Started
-MQT DDSIM bundled with the provider and backends for Qiskit is available via [PyPI](https://pypi.org/project/mqt.ddsim/).
+MQT DDSIM bundled with the provider and backends for Qiskit is available via
+[PyPI](https://pypi.org/project/mqt.ddsim/).
```console
-(venv) $ pip install mqt.ddsim
+uv pip install mqt.ddsim
```
The following code gives an example on the usage:
@@ -106,14 +158,18 @@ counts = job.result().get_counts(circ)
print(counts)
```
-**Detailed documentation and examples are available at [ReadTheDocs](https://mqt.readthedocs.io/projects/ddsim).**
+**Detailed documentation and examples are available at
+[ReadTheDocs](https://mqt.readthedocs.io/projects/ddsim).**
## System Requirements and Building
-Building the project requires a C++ compiler with support for C++20 and CMake 3.24 or newer.
-For details on how to build the project, please refer to the [documentation](https://mqt.readthedocs.io/projects/ddsim).
-Building (and running) is continuously tested under Linux, macOS, and Windows using the [latest available system versions for GitHub Actions](https://github.com/actions/runner-images).
-MQT DDSIM is compatible with all [officially supported Python versions](https://devguide.python.org/versions/).
+Building the project requires a C++ compiler with support for C++20 and CMake
+3.24 or newer. For details on how to build the project, please refer to the
+[documentation](https://mqt.readthedocs.io/projects/ddsim). Building (and
+running) is continuously tested under Linux, macOS, and Windows using the
+[latest available system versions for GitHub Actions](https://github.com/actions/runner-images).
+MQT DDSIM is compatible with all
+[officially supported Python versions](https://devguide.python.org/versions/).
## Cite This
@@ -121,7 +177,8 @@ Please cite the work that best fits your use case.
### MQT DDSIM (the tool)
-When citing the software itself or results produced with it, cite the original DD simulation paper:
+When citing the software itself or results produced with it, cite the original
+DD simulation paper:
```bibtex
@article{zulehner2019advanced,
@@ -156,37 +213,50 @@ When discussing the overall MQT project or its ecosystem, cite the MQT Handbook:
### Peer-Reviewed Research
-When citing the underlying methods and research, please reference the most relevant peer-reviewed publications from the list below:
+When citing the underlying methods and research, please reference the most
+relevant peer-reviewed publications from the list below:
[[1]](https://www.cda.cit.tum.de/files/eda/2018_tcad_advanced_simulation_quantum_computation.pdf)
-A. Zulehner and R. Wille. Advanced Simulation of Quantum Computations.
-_IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems (TCAD)_, 2019.
+A. Zulehner and R. Wille. Advanced Simulation of Quantum Computations. _IEEE
+Transactions on Computer-Aided Design of Integrated Circuits and Systems
+(TCAD)_, 2019.
[[2]](https://www.cda.cit.tum.de/files/eda/2020_dac_weak_simulation_quantum_computation.pdf)
-S. Hillmich, I. L. Markov, and R. Wille. Just Like the Real Thing: Fast Weak Simulation of Quantum Computation.
-In _Design Automation Conference (DAC)_, 2020.
+S. Hillmich, I. L. Markov, and R. Wille. Just Like the Real Thing: Fast Weak
+Simulation of Quantum Computation. In _Design Automation Conference (DAC)_,
+2020.
[[3]](https://www.cda.cit.tum.de/files/eda/2021_date_approximations_dd_baed_quantum_circuit_simulation.pdf)
-S. Hillmich, R. Kueng, I. L. Markov, and R. Wille. As Accurate as Needed, as Efficient as Possible: Approximations in DD-based Quantum Circuit Simulation.
-In _Design, Automation and Test in Europe (DATE)_, 2021.
+S. Hillmich, R. Kueng, I. L. Markov, and R. Wille. As Accurate as Needed, as
+Efficient as Possible: Approximations in DD-based Quantum Circuit Simulation. In
+_Design, Automation and Test in Europe (DATE)_, 2021.
[[4]](https://www.cda.cit.tum.de/files/eda/2021_qce_hybrid_schrodinger_feynman_simulation_with_decision_diagrams.pdf)
-L. Burgholzer, H. Bauer, and R. Wille. Hybrid Schrödinger–Feynman Simulation of Quantum Circuits with Decision Diagrams.
-In _IEEE International Conference on Quantum Computing and Engineering (QCE)_, 2021.
+L. Burgholzer, H. Bauer, and R. Wille. Hybrid Schrödinger–Feynman Simulation of
+Quantum Circuits with Decision Diagrams. In
+_IEEE International Conference on Quantum Computing and Engineering (QCE)_,
+2021.
[[5]](https://www.cda.cit.tum.de/files/eda/2022_date_exploiting_arbitrary_paths_simulation_quantum_circuits_decision_diagrams.pdf)
-L. Burgholzer, A. Ploier, and R. Wille. Exploiting Arbitrary Paths for the Simulation of Quantum Circuits with Decision Diagrams.
-In _Design, Automation and Test in Europe (DATE)_, 2022.
+L. Burgholzer, A. Ploier, and R. Wille. Exploiting Arbitrary Paths for the
+Simulation of Quantum Circuits with Decision Diagrams. In
+_Design, Automation and Test in Europe (DATE)_, 2022.
[[6]](https://www.cda.cit.tum.de/files/eda/2022_tcad_noise-aware_quantum_circuit_simulation_with_decision_diagrams.pdf)
-T. Grurl, J. FuĂź, and R. Wille. Noise-aware Quantum Circuit Simulation with Decision Diagrams.
-_IEEE Transactions on Computer-Aided Design of Integrated Circuits and Systems (TCAD)_, 2022.
+T. Grurl, J. FuĂź, and R. Wille. Noise-aware Quantum Circuit Simulation with
+Decision Diagrams. _IEEE Transactions on Computer-Aided Design of Integrated
+Circuits and Systems (TCAD)_, 2022.
---
## Acknowledgements
-The Munich Quantum Toolkit has been supported by the European Research Council (ERC) under the European Union's Horizon 2020 research and innovation program (grant agreement No. 101001318), the Bavarian State Ministry for Science and Arts through the Distinguished Professorship Program, as well as the Munich Quantum Valley, which is supported by the Bavarian state government with funds from the Hightech Agenda Bayern Plus.
+The Munich Quantum Toolkit has been supported by the European Research Council
+(ERC) under the European Union's Horizon 2020 research and innovation program
+(grant agreement No. 101001318), the Bavarian State Ministry for Science and
+Arts through the Distinguished Professorship Program, as well as the Munich
+Quantum Valley, which is supported by the Bavarian state government with funds
+from the Hightech Agenda Bayern Plus.
diff --git a/UPGRADING.md b/UPGRADING.md
index 5e97d4188..2e6bb8a1a 100644
--- a/UPGRADING.md
+++ b/UPGRADING.md
@@ -1,17 +1,22 @@
# Upgrade Guide
-This document describes breaking changes and how to upgrade. For a complete list of changes including minor and patch releases, please refer to the [changelog](CHANGELOG.md).
+This document describes breaking changes and how to upgrade. For a complete list
+of changes including minor and patch releases, please refer to the
+[changelog](CHANGELOG.md).
## [Unreleased]
-This release updates the minimum required `mqt-core` version to 3.7.0 as well as the `nanobind` version to 2.13.0.
+This release updates the minimum required `mqt-core` version to 3.7.0 as well as
+the `nanobind` version to 2.13.0.
### CMake presets
-[CMake presets] have been added to provide a standardized and reproducible way to configure builds across different platforms.
-These presets are also used in our CI.
+[CMake presets] have been added to provide a standardized and reproducible way
+to configure builds across different platforms. These presets are also used in
+our CI.
-On Unix systems, the `debug`, `release`, and `coverage` presets can be used to configure, build, and test MQT DDSIM.
+On Unix systems, the `debug`, `release`, and `coverage` presets can be used to
+configure, build, and test MQT DDSIM.
```console
cmake --preset release
@@ -19,13 +24,15 @@ cmake --build --preset release
ctest --preset release
```
-Additionally, the `lint` preset can be used to configure and build MQT DDSIM in preparation for a `clang-tidy` run.
+Additionally, the `lint` preset can be used to configure and build MQT DDSIM in
+preparation for a `clang-tidy` run.
If you are on Windows, use the `debug-windows` and `release-windows` presets.
## [2.3.0]
-This release updates the minimum required `mqt-core` version to 3.6.0 as well as the `nanobind` version to 2.12.0.
+This release updates the minimum required `mqt-core` version to 3.6.0 as well as
+the `nanobind` version to 2.12.0.
## [2.2.0]
@@ -33,15 +40,16 @@ This release updates the minimum required `mqt-core` version to 3.6.0 as well as
This release contains two changes to the distributed wheels.
-First, we have removed all wheels for Python 3.13t.
-Free-threading Python was introduced as an experimental feature in Python 3.13.
-It became stable in Python 3.14.
+First, we have removed all wheels for Python 3.13t. Free-threading Python was
+introduced as an experimental feature in Python 3.13. It became stable in Python
+3.14.
-Second, for Python 3.12+, we are now providing Stable ABI wheels instead of separate version-specific wheels.
-This was enabled by migrating our Python bindings from `pybind11` to `nanobind`.
+Second, for Python 3.12+, we are now providing Stable ABI wheels instead of
+separate version-specific wheels. This was enabled by migrating our Python
+bindings from `pybind11` to `nanobind`.
-Both of these changes were made in the interest of conserving PyPI space and reducing CI/CD build times.
-The full list of wheels now reads:
+Both of these changes were made in the interest of conserving PyPI space and
+reducing CI/CD build times. The full list of wheels now reads:
- 3.10
- 3.11
@@ -52,62 +60,78 @@ The full list of wheels now reads:
### End of support for Python 3.9
-Starting with this release, MQT DDSIM no longer supports Python 3.9.
-This is in line with the scheduled end of life of the version.
-As a result, MQT DDSIM is no longer tested under Python 3.9 and no longer ships Python 3.9 wheels.
+Starting with this release, MQT DDSIM no longer supports Python 3.9. This is in
+line with the scheduled end of life of the version. As a result, MQT DDSIM is no
+longer tested under Python 3.9 and no longer ships Python 3.9 wheels.
## [2.0.0]
-This major release introduces several breaking changes, including the removal of deprecated features.
-The following paragraphs describe the most important changes and how to adapt your code accordingly.
-We intend to provide a more comprehensive migration guide for future releases.
-
-The major change in this major release is the move to the MQT Core Python package.
-This move allows us to make `qiskit` a fully optional dependency and entirely rely on the MQT Core IR for representing circuits.
-Additionally, the `mqt-core` Python package now ships all its C++ libraries as shared libraries so that these need not be fetched or built as part of the build process.
-This was tricky to achieve cross-platform, and you can find some more backstory in the corresponding PR [#336].
-The problem was simplified by the latest `pybind11` release (`v3`) that greatly increased binary compatibility.
-It is not necessary to build MQT Core from source, and a simple `uv sync` is enough to successfully run `pytest`.
-We expect the MQT Core integration to mature over the next few releases.
-If you encounter any issues, please let us know.
+This major release introduces several breaking changes, including the removal of
+deprecated features. The following paragraphs describe the most important
+changes and how to adapt your code accordingly. We intend to provide a more
+comprehensive migration guide for future releases.
+
+The major change in this major release is the move to the MQT Core Python
+package. This move allows us to make `qiskit` a fully optional dependency and
+entirely rely on the MQT Core IR for representing circuits. Additionally, the
+`mqt-core` Python package now ships all its C++ libraries as shared libraries so
+that these need not be fetched or built as part of the build process. This was
+tricky to achieve cross-platform, and you can find some more backstory in the
+corresponding PR [#336]. The problem was simplified by the latest `pybind11`
+release (`v3`) that greatly increased binary compatibility. It is not necessary
+to build MQT Core from source, and a simple `uv sync` is enough to successfully
+run `pytest`. We expect the MQT Core integration to mature over the next few
+releases. If you encounter any issues, please let us know.
Support for the tensor network strategy in the path simulator has been removed.
-If you still depend on that method, please use the last version of MQT DDSIM that supports them, which is `1.24.0`.
+If you still depend on that method, please use the last version of MQT DDSIM
+that supports them, which is `1.24.0`.
-MQT Core itself dropped support for several parsers in `v3.0.0`, including the `.real`, `.qc`, `.tfc`, and `GRCS` parsers.
-The `.real` parser lives on as part of the [MQT SyReC] project. All others have been removed without replacement.
+MQT Core itself dropped support for several parsers in `v3.0.0`, including the
+`.real`, `.qc`, `.tfc`, and `GRCS` parsers. The `.real` parser lives on as part
+of the [MQT SyReC] project. All others have been removed without replacement.
Consequently, these input formats are no longer supported in MQT DDSIM.
-MQT DDSIM has moved to the [munich-quantum-toolkit](https://github.com/munich-quantum-toolkit) GitHub organization under https://github.com/munich-quantum-toolkit/ddsim.
-While most links should be automatically redirected, please update any links in your code to point to the new location.
-All links in the documentation have been updated accordingly.
+MQT DDSIM has moved to the
+[munich-quantum-toolkit](https://github.com/munich-quantum-toolkit) GitHub
+organization under . While most
+links should be automatically redirected, please update any links in your code
+to point to the new location. All links in the documentation have been updated
+accordingly.
-MQT DDSIM now requires CMake 3.24 or higher.
-Most modern operating systems should have this version available in their package manager.
-Alternatively, CMake can be conveniently installed from PyPI using the [`cmake`](https://pypi.org/project/cmake/) package.
+MQT DDSIM now requires CMake 3.24 or higher. Most modern operating systems
+should have this version available in their package manager. Alternatively,
+CMake can be conveniently installed from PyPI using the
+[`cmake`](https://pypi.org/project/cmake/) package.
-MQT DDSIM now supports Qiskit 2.0.
-As a result, the return values of the `Estimator` and `Sampler` have been changed to align with Qiskit's implementations.
+MQT DDSIM now supports Qiskit 2.0. As a result, the return values of the
+`Estimator` and `Sampler` have been changed to align with Qiskit's
+implementations.
-To developers of MQT DDSIM, it is worth mentioning that all Python code (except tests) has been moved to the top-level `python` directory.
-Furthermore, the C++ code for the Python bindings has been moved to the top-level `bindings` directory.
+To developers of MQT DDSIM, it is worth mentioning that all Python code (except
+tests) has been moved to the top-level `python` directory. Furthermore, the C++
+code for the Python bindings has been moved to the top-level `bindings`
+directory.
-Furthermore, many Python modules and classes have been renamed.
-In particular,
+Furthermore, many Python modules and classes have been renamed. In particular,
- `HybridCircuitSimulator` has been renamed to `HybridSimulator`,
- `HybridMode` has been renamed to `HybridSimulatorMode`,
- `PathCircuitSimulator` has been renamed to `PathSimulator`, and
- `ConstructionMode` has been renamed to `UnitarySimulatorMode`.
-- Some of the Qiskit backends have been renammed.
- For the new names, see `DDSIMProvider.get_backend()`.
+- Some of the Qiskit backends have been renammed. For the new names, see
+ `DDSIMProvider.get_backend()`.
-The `UnitarySimulatorMode`, `HybridSimulatorMode`, and `PathSimulatorMode` enums are now exposed via `pybind11`'s new `py::native_enum`, which makes them compatible with Python's `enum.Enum` class (PEP 435).
-As a result, the enums can no longer be initialized using a string.
-Instead of `PathSimulatorMode("sequential")` or `"sequential"`, use `PathSimulatorMode.sequential`.
+The `UnitarySimulatorMode`, `HybridSimulatorMode`, and `PathSimulatorMode` enums
+are now exposed via `pybind11`'s new `py::native_enum`, which makes them
+compatible with Python's `enum.Enum` class (PEP 435). As a result, the enums can
+no longer be initialized using a string. Instead of
+`PathSimulatorMode("sequential")` or `"sequential"`, use
+`PathSimulatorMode.sequential`.
Finally, the minimum required C++ version has been raised from C++17 to C++20.
-The default compilers of our test systems support all relevant features of the standard.
+The default compilers of our test systems support all relevant features of the
+standard.
diff --git a/docs/conf.py b/docs/conf.py
index 10391336f..ee60cb831 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -114,10 +114,6 @@
# -- Options for {MyST}NB ----------------------------------------------------
nb_execution_mode = "cache"
-nb_mime_priority_overrides = [
- # builder name, mime type, priority
- ("latex", "image/svg+xml", 15),
-]
nb_execution_raise_on_error = True
@@ -210,68 +206,3 @@ def format_url(self, _e: Entry) -> HRef: # noqa: PLR6301
},
],
}
-
-# -- Options for LaTeX output ------------------------------------------------
-
-numfig = True
-numfig_secnum_depth = 0
-
-sd_fontawesome_latex = True
-image_converter_args = ["-density", "300"]
-latex_engine = "pdflatex"
-latex_documents = [
- (
- master_doc,
- "mqt_ddsim.tex",
- r"MQT DDSIM\\{\Large A quantum circuit simulator based on decision diagrams}",
- r"""Chair for Design Automation\\ Technical University of Munich, Germany\\
- \href{mailto:quantum.cda@xcit.tum.de}{quantum.cda@xcit.tum.de}\\
- Munich Quantum Software Company GmbH\\Garching near Munich, Germany""",
- "howto",
- False,
- ),
-]
-latex_logo = "_static/mqt_dark.png"
-latex_elements = {
- "papersize": "letterpaper",
- "releasename": "Version",
- "printindex": r"\footnotesize\raggedright\printindex",
- "tableofcontents": "",
- "sphinxsetup": "iconpackage=fontawesome",
- "extrapackages": r"\usepackage{qrcode,graphicx,calc,amsthm,etoolbox,flushend,mathtools}",
- "preamble": r"""
-\patchcmd{\thebibliography}{\addcontentsline{toc}{section}{\refname}}{}{}{}
-\DeclarePairedDelimiter\abs{\lvert}{\rvert}
-\DeclarePairedDelimiter\mket{\lvert}{\rangle}
-\DeclarePairedDelimiter\mbra{\langle}{\rvert}
-\DeclareUnicodeCharacter{03C0}{$\pi$}
-\DeclareUnicodeCharacter{2728}{\faicon{star}}
-\DeclareUnicodeCharacter{1F6B8}{\faicon{user-plus}}
-\DeclareUnicodeCharacter{1F4DD}{\faicon{book}}
-\DeclareUnicodeCharacter{1F69A}{\faicon{truck}}
-\DeclareUnicodeCharacter{267B}{\faicon{recycle}}
-\DeclareUnicodeCharacter{2B06}{\faicon{arrow-up}}
-\DeclareUnicodeCharacter{1F4C4}{\faicon{file-alt}}
-\DeclareUnicodeCharacter{1F525}{\faicon{fire}}
-\DeclareUnicodeCharacter{1F41B}{\faicon{bug}}
-\DeclareUnicodeCharacter{1F4DA}{\faicon{book-open}}
-\DeclareUnicodeCharacter{1F4E6}{\faicon{archive}}
-\DeclareUnicodeCharacter{23EA}{\faicon{angle-double-left}}
-\DeclareUnicodeCharacter{FE0F}{}
-
-\newcommand*{\ket}[1]{\ensuremath{\mket{\mkern1mu#1}}}
-\newcommand*{\bra}[1]{\ensuremath{\mbra{\mkern1mu#1}}}
-\newtheorem{example}{Example}
-\clubpenalty=10000
-\widowpenalty=10000
-\interlinepenalty 10000
-\def\subparagraph{} % because IEEE classes don't define this, but titlesec assumes it's present
-""",
- "extraclassoptions": r"journal, onecolumn",
- "fvset": r"\fvset{fontsize=\small}",
- "figure_align": "htb",
-}
-latex_domain_indices = False
-latex_docclass = {
- "howto": "IEEEtran",
-}
diff --git a/docs/contributing.md b/docs/contributing.md
index 56dc7bb3d..0621dc563 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -3,12 +3,11 @@
# Contributing
-Thank you for your interest in contributing to MQT DDSIM! This document
-outlines the development guidelines and how to contribute.
+Thank you for your interest in contributing to MQT DDSIM! This document outlines
+the development guidelines and how to contribute.
-We use GitHub to
-[host code](https://github.com/munich-quantum-toolkit/ddsim), to
-[track issues and feature requests][issues], as well as accept
+We use GitHub to [host code](https://github.com/munich-quantum-toolkit/ddsim),
+to [track issues and feature requests][issues], as well as accept
[pull requests](https://github.com/munich-quantum-toolkit/ddsim/pulls). See
for a general introduction
to working with GitHub and contributing to projects.
@@ -73,9 +72,9 @@ Contributions that do not comply with these guidelines or violate our
- Focus on a single feature or bug at a time and only touch relevant files.
Split multiple features into separate contributions.
- Add tests for new features to ensure they work as intended.
-- Document new features.
- For user-facing changes, add a changelog entry; for breaking changes, update the
- upgrade guide. For details, see {ref}`maintaining-changelog-upgrade-guide`.
+- Document new features. For user-facing changes, add a changelog entry; for
+ breaking changes, update the upgrade guide. For details, see
+ {ref}`maintaining-changelog-upgrade-guide`.
- Add tests for bug fixes to demonstrate the fix.
- Document your code thoroughly and ensure it is readable.
- Keep your code clean by removing debug statements, leftover comments, and
@@ -99,9 +98,9 @@ any AI-assisted contribution. In short:
your PR description.
If you use an agent, it will automatically read the provided {code}`AGENTS.md`,
-which contains context and instructions to help the agent work on MQT DDSIM.
-For Claude Code, create a symlink with {code}`ln -s AGENTS.md CLAUDE.md` so
-Claude picks up the same file.
+which contains context and instructions to help the agent work on MQT DDSIM. For
+Claude Code, create a symlink with {code}`ln -s AGENTS.md CLAUDE.md` so Claude
+picks up the same file.
### Pull Request Workflow
@@ -304,11 +303,11 @@ If you want to disable configuring and building the C++ tests, you can pass
:::
Our CI pipeline on GitHub also collects code coverage information and uploads it
-to [Codecov](https://codecov.io/gh/munich-quantum-toolkit/ddsim). Our goal is
-to have new contributions at least maintain the current code coverage level,
-while striving for covering as much of the code as possible. Try to write
-meaningful tests that actually test the correctness of the code and not just
-exercise the code paths.
+to [Codecov](https://codecov.io/gh/munich-quantum-toolkit/ddsim). Our goal is to
+have new contributions at least maintain the current code coverage level, while
+striving for covering as much of the code as possible. Try to write meaningful
+tests that actually test the correctness of the code and not just exercise the
+code paths.
If you want to enable coverage locally, you can use the `coverage` preset:
@@ -407,21 +406,20 @@ in the {code}`bindings` directory.
:::{tip}
-To build only the Python bindings, pass
-{code}`-DBUILD_MQT_DDSIM_BINDINGS=ON` to the CMake configure step.
-CMake will then try to find Python and the necessary dependencies
-({code}`nanobind`) on your system and configure the respective targets. In
-[CLion][clion], you can enable an option to pass the current Python interpreter
-to CMake. Go to {code}`Preferences` -> {code}`Build, Execution, Deployment` ->
-{code}`CMake` -> {code}`Python Integration` and check the box
+To build only the Python bindings, pass {code}`-DBUILD_MQT_DDSIM_BINDINGS=ON` to
+the CMake configure step. CMake will then try to find Python and the necessary
+dependencies ({code}`nanobind`) on your system and configure the respective
+targets. In [CLion][clion], you can enable an option to pass the current Python
+interpreter to CMake. Go to {code}`Preferences` ->
+{code}`Build, Execution, Deployment` -> {code}`CMake` ->
+{code}`Python Integration` and check the box
{code}`Pass Python Interpreter to CMake`. Alternatively, you can pass
{code}`-DPython_ROOT_DIR=` to the configure step to point CMake
to a specific Python installation.
:::
-The Python package itself lives in the {code}`python/mqt/ddsim`
-directory.
+The Python package itself lives in the {code}`python/mqt/ddsim` directory.
The package lives in the {code}`src/mqt/ddsim` directory.
@@ -443,9 +441,9 @@ These are explained in more detail in the following sections.
## Running the Python Tests
The Python code is tested by unit tests using the
-[{code}`pytest`](https://docs.pytest.org/en/latest/) framework.
-The corresponding test files can be found in the {code}`test/python` directory.
-A {code}`nox` session is provided to conveniently run the Python tests.
+[{code}`pytest`](https://docs.pytest.org/en/latest/) framework. The
+corresponding test files can be found in the {code}`test/python` directory. A
+{code}`nox` session is provided to conveniently run the Python tests.
```console
nox -s tests
@@ -532,11 +530,11 @@ what it does and how to use it. {code}`ruff` will check for missing docstrings
and will explicitly warn you if you forget to add one.
We heavily rely on [type hints](https://docs.python.org/3/library/typing.html)
-to document the expected types of function arguments and return values.
-For the compiled parts of the code base, we provide type hints in the form of
-stub files in the {code}`python/mqt/ddsim` directory. These stub files
-are auto-generated. Do not edit them directly. Instead, you can use the
-{code}`nox` session {code}`stubs` to regenerate them automatically.
+to document the expected types of function arguments and return values. For the
+compiled parts of the code base, we provide type hints in the form of stub files
+in the {code}`python/mqt/ddsim` directory. These stub files are auto-generated.
+Do not edit them directly. Instead, you can use the {code}`nox` session
+{code}`stubs` to regenerate them automatically.
```console
nox -s stubs
@@ -665,8 +663,8 @@ implications of recent changes.
## Releasing a New Version
-When it is time to release a new version of MQT DDSIM, create a PR that
-prepares the release. This PR should:
+When it is time to release a new version of MQT DDSIM, create a PR that prepares
+the release. This PR should:
- add new version titles in both the changelog and the upgrade guide,
- add the release date to the changelog entry for the new version,
@@ -682,24 +680,22 @@ prepares the release. This PR should:
reference to it in the changelog.
Before merging the PR preparing the release, check the GitHub release draft
-generated by the Release Drafter for unlabelled PRs.
-Unlabelled PRs would appear at the top of the release draft below the main
-heading.
-If you missed updating labels before merging, you can still update them and
-re-run the Release Drafter afterward.
-Furthermore, check whether the version number in the release draft is correct.
-The version number in the release draft is dictated by the presence of certain
-labels on the PRs involved in a release. By default, a patch release will be
-created. If any PR has the {code}`minor` or {code}`major` label, a minor or
-major release will be created, respectively.
+generated by the Release Drafter for unlabelled PRs. Unlabelled PRs would appear
+at the top of the release draft below the main heading. If you missed updating
+labels before merging, you can still update them and re-run the Release Drafter
+afterward. Furthermore, check whether the version number in the release draft is
+correct. The version number in the release draft is dictated by the presence of
+certain labels on the PRs involved in a release. By default, a patch release
+will be created. If any PR has the {code}`minor` or {code}`major` label, a minor
+or major release will be created, respectively.
:::{note}
Sometimes, Dependabot or Renovate will tag a PR updating a dependency with a
{code}`minor` or {code}`major` label because the dependency update itself is a
minor or major release. This does not mean that the dependency update itself is
-a breaking change for MQT DDSIM. If you are sure that the dependency update
-does not introduce any breaking changes for MQT DDSIM, you can remove the
+a breaking change for MQT DDSIM. If you are sure that the dependency update does
+not introduce any breaking changes for MQT DDSIM, you can remove the
{code}`minor` or {code}`major` label from the PR. This will ensure that the
respective PR does not influence the type of an upcoming release.
diff --git a/docs/index.md b/docs/index.md
index 3c96295d7..72b8da3a7 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,26 +1,19 @@
# MQT DDSIM - A quantum circuit simulator based on Decision Diagrams
-```{raw} latex
-\begin{abstract}
-```
-
-MQT DDSIM is an open-source C++20 and Python library for classical quantum circuit simulation developed as part of the _{doc}`Munich Quantum Toolkit (MQT) `_.
-
-This documentation provides a comprehensive guide to the MQT DDSIM library, including {doc}`installation instructions `, a {doc}`quickstart guide `, and detailed {doc}`API documentation `.
-The source code of MQT DDSIM is publicly available on GitHub at [munich-quantum-toolkit/ddsim](https://github.com/munich-quantum-toolkit/ddsim), while pre-built binaries are available via [PyPI](https://pypi.org/project/mqt.ddsim/) for all major operating systems and all modern Python versions.
-MQT DDSIM is fully compatible with Qiskit 1.0 and above.
-
-````{only} latex
-```{note}
-A live version of this document is available at [mqt.readthedocs.io/projects/ddsim](https://mqt.readthedocs.io/projects/ddsim).
-```
-````
-
-```{raw} latex
-\end{abstract}
-
-\sphinxtableofcontents
-```
+MQT DDSIM is an open-source C++20 and Python library for classical quantum
+circuit simulation developed as part of the
+_{doc}`Munich Quantum Toolkit (MQT) `_.
+
+This documentation provides a comprehensive guide to the MQT DDSIM library,
+including {doc}`installation instructions `, a
+{doc}`quickstart guide `, and detailed
+{doc}`API documentation `. The source code of MQT DDSIM is
+publicly available on GitHub at
+[munich-quantum-toolkit/ddsim](https://github.com/munich-quantum-toolkit/ddsim),
+while pre-built binaries are available via
+[PyPI](https://pypi.org/project/mqt.ddsim/) for all major operating systems and
+all modern Python versions. MQT DDSIM is fully compatible with Qiskit 1.0 and
+above.
```{toctree}
:hidden:
@@ -41,7 +34,6 @@ CHANGELOG
UPGRADING
```
-````{only} not latex
```{toctree}
:maxdepth: 2
:titlesonly:
@@ -53,7 +45,6 @@ ai_usage
tooling
support
```
-````
```{toctree}
:caption: Python API Reference
@@ -70,11 +61,15 @@ api/mqt/ddsim/index
api/cpp/filelist
```
-```{only} html
## Contributors and Supporters
-The _[Munich Quantum Toolkit (MQT)](https://mqt.readthedocs.io)_ is developed by the [Chair for Design Automation](https://www.cda.cit.tum.de/) at the [Technical University of Munich](https://www.tum.de/) and supported by [MQSC](https://mq.sc).
-Among others, it is part of the [Munich Quantum Software Stack (MQSS)](https://www.munich-quantum-valley.de/research/research-areas/mqss) ecosystem, which is being developed as part of the [Munich Quantum Valley (MQV)](https://www.munich-quantum-valley.de) initiative.
+The _[Munich Quantum Toolkit (MQT)](https://mqt.readthedocs.io)_ is developed by
+the [Chair for Design Automation](https://www.cda.cit.tum.de/) at the
+[Technical University of Munich](https://www.tum.de/) and supported by
+[MQSC](https://mq.sc). Among others, it is part of the
+[Munich Quantum Software Stack (MQSS)](https://www.munich-quantum-valley.de/research/research-areas/mqss)
+ecosystem, which is being developed as part of the
+[Munich Quantum Valley (MQV)](https://www.munich-quantum-valley.de) initiative.
@@ -93,18 +88,21 @@ Thank you to all the contributors who have helped make MQT DDSIM a reality!
-The MQT will remain free, open-source, and permissively licensed—now and in the future.
-We are firmly committed to keeping it open and actively maintained for the quantum computing community.
+The MQT will remain free, open-source, and permissively licensed—now and in the
+future. We are firmly committed to keeping it open and actively maintained for
+the quantum computing community.
To support this endeavor, please consider:
-- Starring and sharing our repositories: [https://github.com/munich-quantum-toolkit](https://github.com/munich-quantum-toolkit)
-- Contributing code, documentation, tests, or examples via issues and pull requests
+- Starring and sharing our repositories:
+ [https://github.com/munich-quantum-toolkit](https://github.com/munich-quantum-toolkit)
+- Contributing code, documentation, tests, or examples via issues and pull
+ requests
- Citing the MQT in your publications (see {doc}`References
`)
- Using the MQT in research and teaching, and sharing feedback and use cases
-- Sponsoring us on GitHub: [https://github.com/sponsors/munich-quantum-toolkit](https://github.com/sponsors/munich-quantum-toolkit)
+- Sponsoring us on GitHub:
+ [https://github.com/sponsors/munich-quantum-toolkit](https://github.com/sponsors/munich-quantum-toolkit)
-```
diff --git a/docs/installation.md b/docs/installation.md
index c8f92f07a..6e2b5d5ce 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -4,9 +4,8 @@
# Installation
MQT DDSIM is primarily developed as a C++20 library with Python bindings. The
-Python package is available on
-[PyPI](https://pypi.org/project/mqt.ddsim/) and can be installed on all
-major operating systems with all
+Python package is available on [PyPI](https://pypi.org/project/mqt.ddsim/) and
+can be installed on all major operating systems with all
[officially supported Python versions](https://devguide.python.org/versions/).
:::::{tip}
@@ -66,6 +65,7 @@ python -m pip install mqt.ddsim
:::
::::
+
In most cases, no compilation is required; a platform-specific prebuilt wheel is
downloaded and installed.
@@ -111,8 +111,8 @@ and [CMake](https://cmake.org/) 3.24 or newer.
## Integrating MQT DDSIM into Your Project
-To use the MQT DDSIM Python package in your project, add it as a dependency
-in your {code}`pyproject.toml` or {code}`setup.py`. This ensures the package is
+To use the MQT DDSIM Python package in your project, add it as a dependency in
+your {code}`pyproject.toml` or {code}`setup.py`. This ensures the package is
installed when your project is installed.
::::{tab-set}
diff --git a/docs/primitives.md b/docs/primitives.md
index 996426785..f63487a86 100644
--- a/docs/primitives.md
+++ b/docs/primitives.md
@@ -13,13 +13,27 @@ mystnb:
# Qiskit Primitives
-The existing Qiskit interface to backends (`backend.run()`) was originally designed to accept a list of circuits and return counts for every job. Over time, it became clear that users have diverse purposes for quantum computing, and therefore the ways in which they define the requirements for their computing jobs are expanding.
-
-To address this issue, Qiskit introduced the `qiskit.primitives` module in version 0.35.0 (Qiskit Terra 0.20.0) to provide a simplified way for end users to compute outputs of interest from a QuantumCircuit and to use backends. Qiskit's primitives provide methods that make it easier to build modular algorithms and other higher-order programs. Rather than simply returning counts, they return more immediately meaningful information.
-
-The two currently available primitives are the `Sampler` and the `Estimator`. The first one simulates a circuit and returns the measurement counts, while the second one calculates and interprets expectation values of quantum operators that are required for many near-term quantum algorithms.
-
-DDSIM provides its own version of these Qiskit primitives that leverage the default circuit simulator based on decision diagrams, while preserving the methods and functionality of the original Qiskit primitives.
+The existing Qiskit interface to backends (`backend.run()`) was originally
+designed to accept a list of circuits and return counts for every job. Over
+time, it became clear that users have diverse purposes for quantum computing,
+and therefore the ways in which they define the requirements for their computing
+jobs are expanding.
+
+To address this issue, Qiskit introduced the `qiskit.primitives` module in
+version 0.35.0 (Qiskit Terra 0.20.0) to provide a simplified way for end users
+to compute outputs of interest from a QuantumCircuit and to use backends.
+Qiskit's primitives provide methods that make it easier to build modular
+algorithms and other higher-order programs. Rather than simply returning counts,
+they return more immediately meaningful information.
+
+The two currently available primitives are the `Sampler` and the `Estimator`.
+The first one simulates a circuit and returns the measurement counts, while the
+second one calculates and interprets expectation values of quantum operators
+that are required for many near-term quantum algorithms.
+
+DDSIM provides its own version of these Qiskit primitives that leverage the
+default circuit simulator based on decision diagrams, while preserving the
+methods and functionality of the original Qiskit primitives.
+++
@@ -27,9 +41,15 @@ DDSIM provides its own version of these Qiskit primitives that leverage the defa
+++
-The [`Sampler`](#mqt.ddsim.primitives.sampler.Sampler) implements the Qiskit [`BaseSamplerV2`](#qiskit.*.BaseSamplerV2) interface. It takes a list of `QuantumCircuit` objects and simulates them using the `CircuitSimulator` from MQT DDSIM, returning the measurement counts. The results are encapsulated within a [`PrimitiveResult`](#qiskit.*.PrimitiveResult) object that also contains the job's metadata.
+The {py:class}`~mqt.ddsim.primitives.sampler.Sampler` implements the Qiskit
+{py:class}`~qiskit.*.BaseSamplerV2` interface. It takes a list of
+`QuantumCircuit` objects and simulates them using the `CircuitSimulator` from
+MQT DDSIM, returning the measurement counts. The results are encapsulated within
+a {py:class}`~qiskit.*.PrimitiveResult` object that also contains the job's
+metadata.
-Furthermore, the [`Sampler`](#mqt.ddsim.primitives.sampler.Sampler) also handles compilation and parameter binding when working with parametrized circuits.
+Furthermore, the {py:class}`~mqt.ddsim.primitives.sampler.Sampler` also handles
+compilation and parameter binding when working with parametrized circuits.
Here, we show an example on how to use this submodule:
@@ -55,7 +75,13 @@ circ.draw("mpl")
sampler = Sampler()
```
-The `run()` method accepts an iterable of PUB-like objects, where PUB stands for primitive unified bloc. In the example below, the PUB comprises the circuit and an array of parameter values, where the latter is optional. For more information, see Qiskit's [`StatevectorSampler.run()`](#qiskit.*.StatevectorSampler.run). The number of shots can be set as an additional argument. If not set, the default value is 1024.
+The `run()` method accepts an iterable of PUB-like objects, where PUB stands for
+primitive unified bloc. In the example below, the PUB comprises the circuit and
+an array of parameter values, where the latter is optional. For more
+information, see Qiskit's
+{py:meth}`StatevectorSampler.run() `. The
+number of shots can be set as an additional argument. If not set, the default
+value is 1024.
```{code-cell} ipython3
pubs = [(circ, [np.pi])]
@@ -64,7 +90,9 @@ job = sampler.run(pubs, shots=shots)
result = job.result()
```
-The `result()` method of the job returns a [`PrimitiveResult`](#qiskit.*.PrimitiveResult) object. This object contains a [`SamplerPubResult`](#qiskit.*.SamplerPubResult), which, in turn, contains the measurement counts. It furthermore contains job metadata.
+The `result()` method of the job returns a {py:class}`~qiskit.*.PrimitiveResult`
+object. This object contains a {py:class}`~qiskit.*.SamplerPubResult`, which, in
+turn, contains the measurement counts. It furthermore contains job metadata.
```{code-cell} ipython3
counts = result[0].data["meas"].get_counts()
@@ -96,9 +124,13 @@ print(f" > Counts for circuit 1: {counts_1}")
print(f" > Counts for circuit 2: {counts_2}")
```
-Now, let us use the [`Sampler`](#mqt.ddsim.primitives.sampler.Sampler) on a more complex circuit. For this example, we will test Grover's algorithm on a 4-qubit circuit where the marked states in the binary representation are "0110" and "1010".
+Now, let us use the {py:class}`~mqt.ddsim.primitives.sampler.Sampler` on a more
+complex circuit. For this example, we will test Grover's algorithm on a 4-qubit
+circuit where the marked states in the binary representation are "0110" and
+"1010".
-A similar implementation of Grover's algorithm using Qiskit's sampler can be found here:
+A similar implementation of Grover's algorithm using Qiskit's sampler can be
+found here:
```{code-cell} ipython3
# Built-in imports
@@ -156,7 +188,8 @@ qc.measure_all()
qc.draw("mpl")
```
-After having built the circuit, use the [`Sampler`](#mqt.ddsim.primitives.sampler.Sampler) to get the measurement counts.
+After having built the circuit, use the
+{py:class}`~mqt.ddsim.primitives.sampler.Sampler` to get the measurement counts.
```{code-cell} ipython3
result = sampler.run([qc], shots=int(1e4)).result()
@@ -168,17 +201,26 @@ plot_distribution(counts)
+++
-The [`Estimator`](#mqt.ddsim.primitives.estimator.Estimator) calculates the expectation value of an observable with respect to a certain quantum state (described by a quantum circuit). It implements the Qiskit [`BaseEstimatorV2`](#qiskit.*.BaseEstimatorV2) interface. However, in contrast to Qiskit's estimator, the DDSIM version exactly computes the expectation value using its simulator based on decision diagrams instead of sampling.
+The {py:class}`~mqt.ddsim.primitives.estimator.Estimator` calculates the
+expectation value of an observable with respect to a certain quantum state
+(described by a quantum circuit). It implements the Qiskit
+{py:class}`~qiskit.*.BaseEstimatorV2` interface. However, in contrast to
+Qiskit's estimator, the DDSIM version exactly computes the expectation value
+using its simulator based on decision diagrams instead of sampling.
-The [`Estimator`](#mqt.ddsim.primitives.estimator.Estimator) also handles parameter binding when dealing with parametrized circuits.
+The {py:class}`~mqt.ddsim.primitives.estimator.Estimator` also handles parameter
+binding when dealing with parametrized circuits.
Here, we show an example on how to use it:
+++
-First, we build the observable and the quantum state. The observable is given as a [`SparsePauliOp`](#qiskit.*.SparsePauliOp) object, while the quantum state is described by a `QuantumCircuit`.
+First, we build the observable and the quantum state. The observable is given as
+a {py:class}`~qiskit.*.SparsePauliOp` object, while the quantum state is
+described by a `QuantumCircuit`.
-In this example, our observable is the Pauli matrix $\sigma_{x}$ and the quantum state is $\frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)$.
+In this example, our observable is the Pauli matrix $\sigma_{x}$ and the quantum
+state is $\frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)$.
```{code-cell} ipython3
import numpy as np
@@ -205,7 +247,14 @@ circ.draw("mpl")
estimator = Estimator()
```
-The next step involves running the estimation using the `run()` method. Just like the `run()` method of the [`Sampler`](#mqt.ddsim.primitives.estimator.Sampler), it accepts an iterable of PUB-like objects. In the example below, the `QuantumCircuit` object representing the quantum state and an array of [`SparsePauliOp`](#qiskit.*.SparsePauliOp) objects representing the observable. If the circuit is parametrized, we would also pass an array of parameters. For more information, see Qiskit's [`StatevectorEstimator.run()`](#qiskit.*.StatevectorEstimator.run).
+The next step involves running the estimation using the `run()` method. Just
+like the `run()` method of the
+{py:class}`~mqt.ddsim.primitives.estimator.Sampler`, it accepts an iterable of
+PUB-like objects. In the example below, the `QuantumCircuit` object representing
+the quantum state and an array of {py:class}`~qiskit.*.SparsePauliOp` objects
+representing the observable. If the circuit is parametrized, we would also pass
+an array of parameters. For more information, see Qiskit's
+{py:meth}`StatevectorEstimator.run() `.
```{code-cell} ipython3
# Enter observable and circuit as a sequence
@@ -213,7 +262,9 @@ job = estimator.run([(circ, [pauli_x])])
result = job.result()
```
-The `result()` method of the job returns a [`PrimitiveResult`](#qiskit.*.PrimitiveResult) object. This object contains a [`PubResult`](#qiskit.*.PubResult), which, in turn, contains the computed expectation values.
+The `result()` method of the job returns a {py:class}`~qiskit.*.PrimitiveResult`
+object. This object contains a {py:class}`~qiskit.*.PubResult`, which, in turn,
+contains the computed expectation values.
```{code-cell} ipython3
expectation_values = result[0].data["evs"]
@@ -222,7 +273,12 @@ print(f">>> {result}")
print(f" > Expectation values: {expectation_values}")
```
-Now we explore how the [`Estimator`](#mqt.ddsim.primitives.estimator.Estimator) works with multiple circuits and observables. For this example, we will calculate the expectation value of $\sigma_{x}$ and $\sigma_{y}$ with respect to the quantum state $|1\rangle$. Since our observable list has a length of 2, we need to enter two copies of the `QuantumCircuit` object representing $|1\rangle$ as a sequence:
+Now we explore how the {py:class}`~mqt.ddsim.primitives.estimator.Estimator`
+works with multiple circuits and observables. For this example, we will
+calculate the expectation value of $\sigma_{x}$ and $\sigma_{y}$ with respect to
+the quantum state $|1\rangle$. Since our observable list has a length of 2, we
+need to enter two copies of the `QuantumCircuit` object representing $|1\rangle$
+as a sequence:
```{code-cell} ipython3
# Build quantum state
@@ -249,11 +305,15 @@ print(f">>> {result}")
print(f" > Expectation values: {expectation_values}")
```
-The first and second entries of the list of values are the expectation value of $\sigma_{x}$ and $\sigma_{y}$, respectively.
+The first and second entries of the list of values are the expectation value of
+$\sigma_{x}$ and $\sigma_{y}$, respectively.
+++
-Let us now calculate the expectation values of $\sigma_{x}$ with respect to $\frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)$ and $\frac{1}{\sqrt{2}}(|0\rangle - |1\rangle)$. For this example we will use parametrized circuits to build the quantum state.
+Let us now calculate the expectation values of $\sigma_{x}$ with respect to
+$\frac{1}{\sqrt{2}}(|0\rangle + |1\rangle)$ and
+$\frac{1}{\sqrt{2}}(|0\rangle - |1\rangle)$. For this example we will use
+parametrized circuits to build the quantum state.
```{code-cell} ipython3
theta = Parameter("theta")
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 9348bb972..26e58b32a 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -39,4 +39,5 @@ counts = job.result().get_counts(circ)
print(counts)
```
-Check out the {doc}`reference documentation ` for more information.
+Check out the {doc}`reference documentation ` for more
+information.
diff --git a/docs/references.md b/docs/references.md
index 5e9e4619a..757d35c8b 100644
--- a/docs/references.md
+++ b/docs/references.md
@@ -1,16 +1,10 @@
-```{raw} latex
-\begingroup
-\renewcommand\section[1]{\endgroup}
-\phantomsection
-```
-
-````{only} html
# References
-*MQT DDSIM* has a strong foundation in peer‑reviewed research.
-Many of its built‑in algorithms are based on methods published in scientific journals and conferences.
-For an overview of *MQT DDSIM* and its features, see {cite:p}`zulehner2019advanced`.
-If you want to cite this article, please use the following BibTeX entry:
+*MQT DDSIM* has a strong foundation in peer‑reviewed research. Many of its
+built‑in algorithms are based on methods published in scientific journals and
+conferences. For an overview of *MQT DDSIM* and its features, see
+{cite:p}`zulehner2019advanced`. If you want to cite this article, please use the
+following BibTeX entry:
```bibtex
@article{zulehner2019advanced,
@@ -25,8 +19,9 @@ If you want to cite this article, please use the following BibTeX entry:
}
```
-*MQT DDSIM* is part of the Munich Quantum Toolkit, which is described in {cite:p}`mqt`.
-If you want to cite the Munich Quantum Toolkit, please use the following BibTeX entry:
+*MQT DDSIM* is part of the Munich Quantum Toolkit, which is described in
+{cite:p}`mqt`. If you want to cite the Munich Quantum Toolkit, please use the
+following BibTeX entry:
```bibtex
@inproceedings{mqt,
@@ -43,7 +38,6 @@ If you want to cite the Munich Quantum Toolkit, please use the following BibTeX
```
A full list of references is given below.
-````
```{bibliography}
diff --git a/docs/simulators.md b/docs/simulators.md
index b2be6aee0..8fd23e38b 100644
--- a/docs/simulators.md
+++ b/docs/simulators.md
@@ -1,10 +1,12 @@
# Simulators
-DDSIM offers different kinds of simulators to use. The following documentation gives an overview of the different simulator
-followed by brief demonstrations of the usage in Python and as standalone executable.
+DDSIM offers different kinds of simulators to use. The following documentation
+gives an overview of the different simulator followed by brief demonstrations of
+the usage in Python and as standalone executable.
-All simulators immediately, or with steps in between, inherit from the abstract {cpp:class}`Simulator` class that provides
-basic functionality used by multiple actual simulators.
+All simulators immediately, or with steps in between, inherit from the abstract
+{cpp:class}`Simulator` class that provides basic functionality used by multiple
+actual simulators.
```{toctree}
:maxdepth: 4
diff --git a/docs/simulators/CircuitSimulator.md b/docs/simulators/CircuitSimulator.md
index f5481f9ee..6e5211dee 100644
--- a/docs/simulators/CircuitSimulator.md
+++ b/docs/simulators/CircuitSimulator.md
@@ -13,18 +13,25 @@ mystnb:
# Circuit Simulator
-The _Circuit Simulator_ is a Schrödinger-style simulator based on decision diagrams (DDs) as a data structure that can be used to:
-
-- obtain the full state vector of the quantum circuit ("strong simulation") as originally proposed in {cite:p}`zulehner2019advanced`
-- sample from the output distribution of a quantum circuit ("weak simulation") as originally proposed in {cite:p}`DBLP:conf/dac/HillmichMW20`
-
-To this end, it starts off with the decision diagram representation of the initial state (generally, $|0\dots 0\rangle$) and then applies the gates of the circuit one by one.
-The DD representation of the state vector is updated in each step.
-The simulator can handle (almost) arbitrary quantum circuits, including those with mid-circuit measurements and resets.
-For circuits with no non-unitary operations (except for measurements at the end of the circuit) the simulation is only done once.
-In that case, the requested number of samples is subsequently drawn from the final decision diagram, resulting in fast runtime.
-
-For the purpose of this demonstration, we will use the following simple QASM circuit, which we save as `bell.qasm` in the current working directory:
+The _Circuit Simulator_ is a Schrödinger-style simulator based on decision
+diagrams (DDs) as a data structure that can be used to:
+
+- obtain the full state vector of the quantum circuit ("strong simulation") as
+ originally proposed in {cite:p}`zulehner2019advanced`
+- sample from the output distribution of a quantum circuit ("weak simulation")
+ as originally proposed in {cite:p}`DBLP:conf/dac/HillmichMW20`
+
+To this end, it starts off with the decision diagram representation of the
+initial state (generally, $|0\dots 0\rangle$) and then applies the gates of the
+circuit one by one. The DD representation of the state vector is updated in each
+step. The simulator can handle (almost) arbitrary quantum circuits, including
+those with mid-circuit measurements and resets. For circuits with no non-unitary
+operations (except for measurements at the end of the circuit) the simulation is
+only done once. In that case, the requested number of samples is subsequently
+drawn from the final decision diagram, resulting in fast runtime.
+
+For the purpose of this demonstration, we will use the following simple QASM
+circuit, which we save as `bell.qasm` in the current working directory:
```{code-cell} ipython3
from pathlib import Path
@@ -48,7 +55,8 @@ This circuit creates a Bell state and measures the qubits.
## Simulating a simple circuit
-Using the `CircuitSimulator` to simulate the circuit from the QASM file `bell.qasm` is straightforward.
+Using the `CircuitSimulator` to simulate the circuit from the QASM file
+`bell.qasm` is straightforward.
```{code-cell} ipython3
from mqt.core import load
@@ -66,9 +74,11 @@ result = sim.simulate(shots=1024)
print(result)
```
-As expected, the output distribution is approximately 50% for the states $|00\rangle$ and $|11\rangle$ each.
+As expected, the output distribution is approximately 50% for the states
+$|00\rangle$ and $|11\rangle$ each.
-If we would like to obtain the full state vector of the quantum circuit, we can query it after the simulation as follows:
+If we would like to obtain the full state vector of the quantum circuit, we can
+query it after the simulation as follows:
```{code-cell} ipython3
import numpy as np
@@ -82,12 +92,18 @@ sv = np.array(vec, copy=False)
print(sv)
```
-Note that getting the full state vector is only feasible for small circuits, as the memory and time requirements grow exponentially with the number of qubits.
-However, due to the nature of decision diagrams, the simulator can generally sample from the output distribution of much larger circuits than can be fully represented in memory.
+Note that getting the full state vector is only feasible for small circuits, as
+the memory and time requirements grow exponentially with the number of qubits.
+However, due to the nature of decision diagrams, the simulator can generally
+sample from the output distribution of much larger circuits than can be fully
+represented in memory.
-If you want to inspect the final decision diagram, you can get a Graphviz representation of it.
-For that, make sure that you have Graphviz installed and that the `graphviz` Python package is available.
-Then, you can call the `export_dd_to_graphviz_str` method on the simulator to obtain a Graphviz representation of the decision diagram. The following shows the default configuration options for the export.
+If you want to inspect the final decision diagram, you can get a Graphviz
+representation of it. For that, make sure that you have Graphviz installed and
+that the `graphviz` Python package is available. Then, you can call the
+`export_dd_to_graphviz_str` method on the simulator to obtain a Graphviz
+representation of the decision diagram. The following shows the default
+configuration options for the export.
```{code-cell} ipython3
import graphviz
@@ -104,8 +120,9 @@ Path(filename).unlink()
## Using Qiskit `QuantumCircuit` objects as input
-The `CircuitSimulator` can also be directly used with Qiskit's `QuantumCircuit` objects, which can be more convenient for some users.
-The above computation can be done as follows:
+The `CircuitSimulator` can also be directly used with Qiskit's `QuantumCircuit`
+objects, which can be more convenient for some users. The above computation can
+be done as follows:
```{code-cell} ipython3
from qiskit import QuantumCircuit
@@ -129,9 +146,12 @@ print(result)
## Simulating a circuit with mid-circuit measurements
-The `CircuitSimulator` can also handle circuits with mid-circuit measurements and resets. The following shows an example of Iterative Quantum Phase Estimation (IQPE) with a mid-circuit measurement.
-The circuit tries to iteratively estimate the phase of a unitary $U=p(3\pi/8)$ with 3-bit precision.
-We seek $\theta=3/16=0.0011_2$, which is not exactly representable using 3 bits, so the best we can expect is high probabilities for $0.c_2 c_1 c_0 = 001$ and $010$.
+The `CircuitSimulator` can also handle circuits with mid-circuit measurements
+and resets. The following shows an example of Iterative Quantum Phase Estimation
+(IQPE) with a mid-circuit measurement. The circuit tries to iteratively estimate
+the phase of a unitary $U=p(3\pi/8)$ with 3-bit precision. We seek
+$\theta=3/16=0.0011_2$, which is not exactly representable using 3 bits, so the
+best we can expect is high probabilities for $0.c_2 c_1 c_0 = 001$ and $010$.
```{code-cell} ipython3
import locale
@@ -212,10 +232,13 @@ Path(filename).unlink()
## Usage as a Qiskit backend
-The `CircuitSimulator` can also be easily used as a backend for Qiskit.
-To this end, the `CircuitSimulator` class is wrapped to implement the `BackendV2` interface of Qiskit, which allows using it as a drop-in replacement for any other Qiskit backend, such as the `AerSimulator`.
+The `CircuitSimulator` can also be easily used as a backend for Qiskit. To this
+end, the `CircuitSimulator` class is wrapped to implement the `BackendV2`
+interface of Qiskit, which allows using it as a drop-in replacement for any
+other Qiskit backend, such as the `AerSimulator`.
-All of the backends available from mqt-ddsim are available from the `DDSIMProvider` class, which can be used to obtain a backend instance.
+All of the backends available from mqt-ddsim are available from the
+`DDSIMProvider` class, which can be used to obtain a backend instance.
```{code-cell} ipython3
from mqt.ddsim import DDSIMProvider
@@ -223,7 +246,9 @@ from mqt.ddsim import DDSIMProvider
provider = DDSIMProvider()
```
-The `CircuitSimulator` is offered as two separate backends, the `qasm_simulator` and the `statevector_simulator`, which perform weak and strong simulation, respectively.
+The `CircuitSimulator` is offered as two separate backends, the `qasm_simulator`
+and the `statevector_simulator`, which perform weak and strong simulation,
+respectively.
Let's first create a simple quantum circuit again
@@ -253,7 +278,8 @@ result = job.result()
print(result.get_counts())
```
-Again, we can also use the `statevector_simulator` backend to obtain the full state vector of the quantum circuit.
+Again, we can also use the `statevector_simulator` backend to obtain the full
+state vector of the quantum circuit.
```{code-cell} ipython3
# get the backend
@@ -269,7 +295,9 @@ print(result.get_statevector())
## Usage as standalone C++ executable
-To build the standalone C++ simulator executable, build the `ddsim_simple` (the name stuck due to historical reasons ;) ) CMake target and run the resulting executable with options according to your needs.
+To build the standalone C++ simulator executable, build the `ddsim_simple` (the
+name stuck due to historical reasons;)) CMake target and run the resulting
+executable with options according to your needs.
```console
$ ./ddsim_simple --help
diff --git a/docs/simulators/HybridSchrodingerFeynman.md b/docs/simulators/HybridSchrodingerFeynman.md
index 264b13027..418feecc4 100644
--- a/docs/simulators/HybridSchrodingerFeynman.md
+++ b/docs/simulators/HybridSchrodingerFeynman.md
@@ -13,24 +13,35 @@ mystnb:
# Hybrid Schrödinger-Feynman Simulator
-Hybrid Schrödinger-Feynman approaches strive to use all the available memory and processing units in order to efficiently simulate quantum circuits which would
+Hybrid Schrödinger-Feynman approaches strive to use all the available memory and
+processing units in order to efficiently simulate quantum circuits which would
1. run into memory bottlenecks using Schrödinger-style simulation, or
2. take exceedingly long using Feynman-style path summation,
eventually trading-off the respective memory and runtime requirements.
-DDSIM offers such a simulator based on decision diagrams as proposed in {cite:p}`DBLP:conf/qce/BurgholzerBW21`.
+DDSIM offers such a simulator based on decision diagrams as proposed in
+{cite:p}`DBLP:conf/qce/BurgholzerBW21`.
-It currently assumes that no non-unitary operations (besides measurements at the end of the circuit) are present in the circuit.
-Furthermore it always measures all qubits at the end of the circuit in the order they were defined.
+It currently assumes that no non-unitary operations (besides measurements at the
+end of the circuit) are present in the circuit. Furthermore it always measures
+all qubits at the end of the circuit in the order they were defined.
-The backend provides two different modes that can be set using the `mode` option:
+The backend provides two different modes that can be set using the `mode`
+option:
-- `dd`: all computations are conducted on decision diagrams and the requested number of shots are sampled from the final decision diagram
-- `amplitude`: all individual paths in the hybrid simulation scheme are simulated using decision diagrams, while subsequent computations (addition of all results) is conducted using arrays. This requires more memory but can lead to significantly better runtime performance in many cases. The requested shots are sampled from the final statevector array.
+- `dd`: all computations are conducted on decision diagrams and the requested
+ number of shots are sampled from the final decision diagram
+- `amplitude`: all individual paths in the hybrid simulation scheme are
+ simulated using decision diagrams, while subsequent computations (addition of
+ all results) is conducted using arrays. This requires more memory but can lead
+ to significantly better runtime performance in many cases. The requested shots
+ are sampled from the final statevector array.
-The number of threads to use can be set using the `nthreads` option. Note that the number of threads may be reduced when using the `amplitude` mode in order to fit the computation in the available memory.
+The number of threads to use can be set using the `nthreads` option. Note that
+the number of threads may be reduced when using the `amplitude` mode in order to
+fit the computation in the available memory.
```{code-cell} ipython3
from qiskit import QuantumCircuit
@@ -61,9 +72,13 @@ result = job.result()
print(result.get_counts())
```
-Similar to the circuit simulator, there is also a statevector simulator available. The statevector simulator can be used to obtain the full statevector of the quantum circuit at the end of the simulation.
+Similar to the circuit simulator, there is also a statevector simulator
+available. The statevector simulator can be used to obtain the full statevector
+of the quantum circuit at the end of the simulation.
-Note that `shots` has to be set to `0` when using the `amplitude` mode as the statevector array is modified in-place for sampling and, hence, the state vector is no longer available afterwards.
+Note that `shots` has to be set to `0` when using the `amplitude` mode as the
+statevector array is modified in-place for sampling and, hence, the state vector
+is no longer available afterwards.
```{code-cell} ipython3
from mqt.ddsim import DDSIMProvider
diff --git a/docs/simulators/NoiseAwareSimulator.md b/docs/simulators/NoiseAwareSimulator.md
index 4da62f90f..549c534fd 100644
--- a/docs/simulators/NoiseAwareSimulator.md
+++ b/docs/simulators/NoiseAwareSimulator.md
@@ -1,23 +1,26 @@
# Noise-aware Simulator
-The tool also supports noise-aware quantum circuit simulation, based on a stochastic approach. It currently supports
-global decoherence and gate error noise effects. A detailed summary of the simulator is presented
-in {cite:p}`grurl2022`. Note that the simulator currently does not support simulating the integrated
-algorithms.
+The tool also supports noise-aware quantum circuit simulation, based on a
+stochastic approach. It currently supports global decoherence and gate error
+noise effects. A detailed summary of the simulator is presented in
+{cite:p}`grurl2022`. Note that the simulator currently does not support
+simulating the integrated algorithms.
## Usage in Python
:::{note}
-The noise-aware simulators are exposed to Python, but are currently lacking documentation. Any contributions are welcome!
+The noise-aware simulators are exposed to Python, but are currently lacking
+documentation. Any contributions are welcome!
:::
## Usage as Standalone Executable
-Building the simulator requires {code}`Threads::Threads`. It can be built by executing
+Building the simulator requires {code}`Threads::Threads`. It can be built by
+executing
```console
-$ cmake -DCMAKE_BUILD_TYPE=Release -S . -B build
-$ cmake --build build --config Release --target ddsim_noise_aware
+cmake -DCMAKE_BUILD_TYPE=Release -S . -B build
+cmake --build build --config Release --target ddsim_noise_aware
```
The simulator provides a help function which is called in the following way:
@@ -44,7 +47,9 @@ $ ./build/apps/ddsim_noise_aware --help
--shots arg Specify the number of shots that shall be generated (default: 0)
```
-An example run of the stochastic simulator, with 1000 samples, amplitude damping, phase flip, and depolarization error enabled (each with a probability of 0.1% whenever a gate is applied) looks like this:
+An example run of the stochastic simulator, with 1000 samples, amplitude
+damping, phase flip, and depolarization error enabled (each with a probability
+of 0.1% whenever a gate is applied) looks like this:
```console
$./build/apps/ddsim_noise_aware ./build/apps/ddsim_noise_aware --noise_effects APD --noise_prob 0.001 --shots 1000 --simulate_file adder_n4.qasm --pm --ps
@@ -84,7 +89,9 @@ An example run of the stochastic simulator, with 1000 samples, amplitude damping
}
```
-The deterministic simulator is run when the flag "--use_density_matrix_simulator" is set. The same run from above, using the deterministic simulator would look like this:
+The deterministic simulator is run when the flag
+"--use_density_matrix_simulator" is set. The same run from above, using the
+deterministic simulator would look like this:
```console
$ ./build/apps/ddsim_noise_aware --noise_effects APD --noise_prob 0.001 --shots 1000 --simulate_file adder_n4.qasm --pm --ps --use_density_matrix_simulator
diff --git a/docs/simulators/SimulationPathFramework.md b/docs/simulators/SimulationPathFramework.md
index ad812d6d3..fbb3131e0 100644
--- a/docs/simulators/SimulationPathFramework.md
+++ b/docs/simulators/SimulationPathFramework.md
@@ -13,28 +13,42 @@ mystnb:
# Simulation Path Framework
-DDSIM also provides a framework for exploiting arbitrary simulation paths (using the [taskflow](https://github.com/taskflow/taskflow) library) based on the methods proposed in {cite:p}`burgholzer2022simulation`.
+DDSIM also provides a framework for exploiting arbitrary simulation paths (using
+the [taskflow](https://github.com/taskflow/taskflow) library) based on the
+methods proposed in {cite:p}`burgholzer2022simulation`.
```{note}
-As of mqt-ddsim v2.0.0, the Cotengra-based workflow for translating circuits to tensor networks and deriving contraction strategies has been removed. If you want to check out the respective code, please checkout prior versions of mqt-ddsim.
+As of mqt-ddsim v2.0.0, the Cotengra-based workflow for translating circuits to
+tensor networks and deriving contraction strategies has been removed. If you
+want to check out the respective code, please checkout prior versions of
+mqt-ddsim.
```
-A _simulation path_ describes the order in which the individual MxV or MxM multiplications are conducted during the simulation of a quantum circuit.
-It can be described as a list of tuples that identify the individual states/operations to be multiplied.
-The initial state is always assigned `ID 0`, while the i-th operation is assigned `ID i`.
-The result of a multiplication is assigned the next highest, unused ID, e.g., in a circuit with `|G|` gates the result of the first multiplication is assigned `ID |G|+1`.
+A _simulation path_ describes the order in which the individual MxV or MxM
+multiplications are conducted during the simulation of a quantum circuit. It can
+be described as a list of tuples that identify the individual states/operations
+to be multiplied. The initial state is always assigned `ID 0`, while the i-th
+operation is assigned `ID i`. The result of a multiplication is assigned the
+next highest, unused ID, e.g., in a circuit with `|G|` gates the result of the
+first multiplication is assigned `ID |G|+1`.
The framework comes with several pre-defined simulation path strategies:
-- `sequential` (_default_): simulate the circuit sequentially from left to right using only MxV multiplications
-- `pairwise_recursive`: recursively group pairs of states and operations to form a binary tree of MxV/MxM multiplications
-- `bracket`: group certain number of operations according to a given `bracket_size`
-- `alternating`: start the simulation in the middle of the circuit and alternate between applications of gates "from the left" and "from the right" (useful for equivalence checking).
+- `sequential` (_default_): simulate the circuit sequentially from left to right
+ using only MxV multiplications
+- `pairwise_recursive`: recursively group pairs of states and operations to form
+ a binary tree of MxV/MxM multiplications
+- `bracket`: group certain number of operations according to a given
+ `bracket_size`
+- `alternating`: start the simulation in the middle of the circuit and alternate
+ between applications of gates "from the left" and "from the right" (useful for
+ equivalence checking).
## Simulating a simple circuit
-This example shall serve as a showcase on how to use the simulation path framework (via Python).
-First, create the circuit to be simulated using qiskit, e.g., in this case a three-qubit GHZ state:
+This example shall serve as a showcase on how to use the simulation path
+framework (via Python). First, create the circuit to be simulated using qiskit,
+e.g., in this case a three-qubit GHZ state:
```{code-cell} ipython3
from qiskit import QuantumCircuit
@@ -48,8 +62,11 @@ circ.cx(0, 2) # corresponds to ID 3
circ.draw(output="mpl", style="iqp")
```
-Then, obtain the simulation path framework qiskit backend. You can choose between the `path_qasm_simulator` and the `path_statevector_simulator`.
-The first just yields a dictionary with the counts of the measurements, while the latter also provides the complete statevector (which, depending on the amount of qubits, might not fit in the available memory).
+Then, obtain the simulation path framework qiskit backend. You can choose
+between the `path_qasm_simulator` and the `path_statevector_simulator`. The
+first just yields a dictionary with the counts of the measurements, while the
+latter also provides the complete statevector (which, depending on the amount of
+qubits, might not fit in the available memory).
```{code-cell} ipython3
from mqt.ddsim import DDSIMProvider
@@ -58,16 +75,20 @@ provider = DDSIMProvider()
backend = provider.get_backend("path_qasm_simulator")
```
-Per default, the backend uses the `sequential` strategy. For this particular example, this means:
+Per default, the backend uses the `sequential` strategy. For this particular
+example, this means:
- first, the Hadamard operation is applied to the initial state (`[0, 1] -> 4`)
- then, the first CNOT is applied (`[4, 2] -> 5`)
- finally, the last CNOT is applied (`[5, 3] -> 6`)
-The corresponding simulation path is thus described by `[[0, 1], [4, 2], [5, 3]]` and the final state is the one with `ID 6`.
+The corresponding simulation path is thus described by
+`[[0, 1], [4, 2], [5, 3]]` and the final state is the one with `ID 6`.
-The simulation is started by calling the `run` method on the backend, which takes several optional configuration parameters (such as the simulation path strategy).
-For a complete list of configuration options see [here](#configuration).
+The simulation is started by calling the `run` method on the backend, which
+takes several optional configuration parameters (such as the simulation path
+strategy). For a complete list of configuration options, see
+{ref}`configuration`.
```{code-cell} ipython3
job = backend.run(circ)
@@ -75,11 +96,17 @@ result = job.result()
print(result.get_counts())
```
+(configuration)=
+
## Configuration
-The framework can be configured using multiple options (which can be passed to the `backend.run()` method):
+The framework can be configured using multiple options (which can be passed to
+the `backend.run()` method):
-- `mode`: the simulation path mode to use (`sequential`, `pairwise_recursive`, `bracket`, `alternating`))
+- `mode`: the simulation path mode to use (`sequential`, `pairwise_recursive`,
+ `bracket`, `alternating`))
- `bracket_size`: the bracket size used for the `bracket` mode (default: `2`)
-- `alternating_start`: the id of the operation to start with in the `alternating` mode (default: `0`)
-- `seed`: the random seed used for the simulator (default `0`, i.e., no particular seed).
+- `alternating_start`: the id of the operation to start with in the
+ `alternating` mode (default: `0`)
+- `seed`: the random seed used for the simulator (default `0`, i.e., no
+ particular seed).
diff --git a/docs/simulators/UnitarySimulator.md b/docs/simulators/UnitarySimulator.md
index 460a95beb..0e4d2419e 100644
--- a/docs/simulators/UnitarySimulator.md
+++ b/docs/simulators/UnitarySimulator.md
@@ -13,22 +13,34 @@ mystnb:
# Unitary Simulator
-The _Unitary Simulator_ uses the same underlying techniques as the _Circuit Simulator_, but instead of computing the final state vector, it computes the unitary matrix that represents the (functionality of the) quantum circuit.
-Specifically, given a quantum circuit $G=g_0g_1\ldots g_{|G|-1}$, the unitary simulator computes the matrix $U=U_{{|G|-1}}\ldots U_{1}U_{0}$, where $U_g$ is the unitary matrix that represents the functionality of the gate $g$.
-
-To this end, it starts off with the decision diagram representation of the identity $I$ (which is maximally compact as a decision diagram) and then applies the gates of the circuit one by one.
-The DD representation of the unitary is updated in each step.
-The final result is a decision diagram that represents the unitary matrix $U$.
-Note that, by definition, this simulator can only handle circuits composed of unitary operations.
-
-In general, the unitary matrix for an $n$-qubit circuit is a $2^n \times 2^n$ matrix.
-The decision diagram representation of such a matrix can be exponentially more compact than the full matrix representation.
-Hence, as the other simulators, the unitary simulator can take advantage of the decision diagram representation to efficiently compute a representation of the functionality of the quantum circuit, even in cases where the full matrix representation would be infeasible due to its exponential size.
+The _Unitary Simulator_ uses the same underlying techniques as the
+_Circuit Simulator_, but instead of computing the final state vector, it
+computes the unitary matrix that represents the (functionality of the) quantum
+circuit. Specifically, given a quantum circuit $G=g_0g_1\ldots g_{|G|-1}$, the
+unitary simulator computes the matrix $U=U_{{|G|-1}}\ldots U_{1}U_{0}$, where
+$U_g$ is the unitary matrix that represents the functionality of the gate $g$.
+
+To this end, it starts off with the decision diagram representation of the
+identity $I$ (which is maximally compact as a decision diagram) and then applies
+the gates of the circuit one by one. The DD representation of the unitary is
+updated in each step. The final result is a decision diagram that represents the
+unitary matrix $U$. Note that, by definition, this simulator can only handle
+circuits composed of unitary operations.
+
+In general, the unitary matrix for an $n$-qubit circuit is a $2^n \times 2^n$
+matrix. The decision diagram representation of such a matrix can be
+exponentially more compact than the full matrix representation. Hence, as the
+other simulators, the unitary simulator can take advantage of the decision
+diagram representation to efficiently compute a representation of the
+functionality of the quantum circuit, even in cases where the full matrix
+representation would be infeasible due to its exponential size.
## Computing a simple unitary
-Let us start by computing the unitary matrix of a simple quantum circuit. Out of convenience, the following will use the `QuantumCircuit` class from Qiskit to define the circuit.
-However, the unitary simulator generally accepts the same input types as all other simulators (e.g., OpenQASM).
+Let us start by computing the unitary matrix of a simple quantum circuit. Out of
+convenience, the following will use the `QuantumCircuit` class from Qiskit to
+define the circuit. However, the unitary simulator generally accepts the same
+input types as all other simulators (e.g., OpenQASM).
```{code-cell} ipython3
from qiskit import QuantumCircuit
@@ -71,7 +83,8 @@ print(unitary)
## Examples
-The following examples demonstrate a couple of different aspects about the unitary simulator.
+The following examples demonstrate a couple of different aspects about the
+unitary simulator.
### Multiple qubits and qubit ordering
@@ -155,7 +168,8 @@ unitary
### Multi-controlled quantum operations
-The following shows an example of how efficiently decision diagrams can represent multi-controlled quantum operations.
+The following shows an example of how efficiently decision diagrams can
+represent multi-controlled quantum operations.
```{code-cell} ipython3
from qiskit import QuantumCircuit
@@ -243,7 +257,10 @@ unitary
### Decision diagrams are not always compact
-The following example aims to demonstrate that decision diagrams are not a holy grail to constructing unitaries for circuits. In the worst case, they are still exponentially large. At that point, a plain array representation most likely becomes more performant.
+The following example aims to demonstrate that decision diagrams are not a holy
+grail to constructing unitaries for circuits. In the worst case, they are still
+exponentially large. At that point, a plain array representation most likely
+becomes more performant.
```{code-cell} ipython3
import numpy as np
@@ -292,7 +309,8 @@ unitary
## Usage as a Qiskit backend
-Similar to the circuit simulator, the unitary simulator can be conveniently used via a Qiskit backend.
+Similar to the circuit simulator, the unitary simulator can be conveniently used
+via a Qiskit backend.
```{code-cell} ipython3
from qiskit import QuantumCircuit
@@ -317,8 +335,11 @@ result = job.result()
print(result.get_unitary(qc))
```
-Note that this only gives access to the final unitary and not the underlying decision diagram representing the unitary. As a consequence, this approach is inherently limited by the amount of memory available on your system.
-If you need access to the underlying decision diagram and/or do not need the final unitary matrix, consider using the standalone `UnitarySimulator` as described above.
+Note that this only gives access to the final unitary and not the underlying
+decision diagram representing the unitary. As a consequence, this approach is
+inherently limited by the amount of memory available on your system. If you need
+access to the underlying decision diagram and/or do not need the final unitary
+matrix, consider using the standalone `UnitarySimulator` as described above.
## Alternative construction sequence
@@ -330,7 +351,9 @@ As a result, the straight-forward, sequential application of gates may not alway
The unitary simulator also supports an alternative construction sequence, which recursively groups gates and applies them in a tree-like fashion as described in :cite:p:`burgholzer2021efficient`.
```
-Using the alternative construction sequence is as simple as setting `mode="recursive"` when creating the simulator or passing the `mode` argument to the `backend.run` method when using the Qiskit backend.
+Using the alternative construction sequence is as simple as setting
+`mode="recursive"` when creating the simulator or passing the `mode` argument to
+the `backend.run` method when using the Qiskit backend.
```{code-cell} ipython3
import graphviz
diff --git a/docs/tooling.md b/docs/tooling.md
index 99cd0e7a1..97dc5e991 100644
--- a/docs/tooling.md
+++ b/docs/tooling.md
@@ -3,9 +3,9 @@
# Tooling
-This page summarizes the main tools, software, and standards used in MQT
-DDSIM. It serves as a quick reference for new contributors and users who want
-to understand the project's ecosystem.
+This page summarizes the main tools, software, and standards used in MQT DDSIM.
+It serves as a quick reference for new contributors and users who want to
+understand the project's ecosystem.
## C++
diff --git a/scripts/README.md b/scripts/README.md
index 05b6bf535..9484883f5 100644
--- a/scripts/README.md
+++ b/scripts/README.md
@@ -1,6 +1,8 @@
# Scripts for MQT DDSIM
-The scripts in this folder should help to replicate the results we published in papers.
-However, please note that these scripts assume a certain behavior of the simulator that may (and in fact very likely) change in the future.
+The scripts in this folder should help to replicate the results we published in
+papers. However, please note that these scripts assume a certain behavior of the
+simulator that may (and in fact very likely) change in the future.
-A good idea to get started is to check out the last commit where a particular script has been changed and run it from there.
+A good idea to get started is to check out the last commit where a particular
+script has been changed and run it from there.