Skip to content

DDSIM version of Sampler primitive #300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 74 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
1409e27
Backends now support parametrized circuits
andresbar98 Sep 12, 2023
d511592
Merge branch 'cda-tum:main' into qiskit_primitives
andresbar98 Sep 13, 2023
b041d87
Simplify code for handling parametrized gates
andresbar98 Sep 13, 2023
7fa297f
Added tests for parametrized gates
andresbar98 Sep 13, 2023
274a1d2
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 13, 2023
b2bab59
Fixed typing errors and improved test coverage
andresbar98 Sep 14, 2023
7f83216
Simulated circuits are now a backend's attribute
andresbar98 Sep 17, 2023
b778302
Solved minor issues/Redefined _bind_parameters method
andresbar98 Sep 22, 2023
c022213
Simplified loops/Added verifiers to _bind_parameters() method
andresbar98 Sep 25, 2023
997e855
Update src/mqt/ddsim/qasmsimulator.py
andresbar98 Sep 26, 2023
56fb712
Update src/mqt/ddsim/qasmsimulator.py
andresbar98 Sep 26, 2023
bca90fc
Update src/mqt/ddsim/qasmsimulator.py
andresbar98 Sep 26, 2023
e5bdab1
Simplified tests/Improved syntax
andresbar98 Sep 26, 2023
7f7b4e4
🏷️ proper typing
burgholzer Sep 27, 2023
57b49b9
♻️ refactor parameter assignment logic
burgholzer Sep 27, 2023
6fa93f7
✅ adjust tests
burgholzer Sep 27, 2023
9f69586
Merge branch 'qiskit_primitives'
andresbar98 Sep 28, 2023
26f45ef
First DDSIM version of Sampler
andresbar98 Sep 28, 2023
8a9d1bb
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 28, 2023
00683b3
Fixed small errors
andresbar98 Sep 29, 2023
a239550
Sampler now depends exclusively on QasmSimulatorBackend
andresbar98 Sep 30, 2023
40b1f30
First test for DDSIM sampler
andresbar98 Sep 30, 2023
513802d
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 30, 2023
2774b0c
Raise qiskit-terra minimum version
andresbar98 Sep 30, 2023
8c2f48c
Merge branch 'DDSIM_Sampler' of https://github.com/andresbar98/mqt-dd…
andresbar98 Sep 30, 2023
f037db8
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 30, 2023
3920aa7
Change Qiskit-terra version
andresbar98 Oct 1, 2023
6892df7
Adjust class definition to minimum version
andresbar98 Oct 7, 2023
698ef16
Improved test coverage
andresbar98 Oct 7, 2023
1b6970e
Improved test coverage
andresbar98 Oct 7, 2023
dd09d36
API Documentation + Demo for DDSIMSampler
andresbar98 Oct 14, 2023
630396f
🎨 pre-commit fixes
pre-commit-ci[bot] Oct 14, 2023
4090e79
Fixed errors in demo notebook
andresbar98 Oct 14, 2023
988fc7f
Merge branch 'cda-tum:main' into DDSIM_Sampler
andresbar98 Oct 14, 2023
0a6bd2c
Merge branch 'cda-tum:main' into DDSIM_Sampler
andresbar98 Oct 18, 2023
ebbb1b9
retrigger checks
andresbar98 Oct 19, 2023
dfbf44a
Fix indicators
andresbar98 Oct 23, 2023
bfa13f7
Simplified Sampler's features
andresbar98 Oct 23, 2023
5a4faf0
Adapt python notebook documentation
andresbar98 Oct 23, 2023
961bedb
🎨 pre-commit fixes
pre-commit-ci[bot] Oct 23, 2023
6a27036
Merge branch 'main' into DDSIM_Sampler
burgholzer Oct 24, 2023
559580f
Expanded python notebook documentation
andresbar98 Oct 26, 2023
c0b576a
Improved Sampler's functionality/Better typing
andresbar98 Oct 27, 2023
591d2da
Linked documentation
andresbar98 Oct 27, 2023
5a83045
🎨 pre-commit fixes
pre-commit-ci[bot] Oct 27, 2023
e5ab232
Improved test methods and coverage
andresbar98 Oct 29, 2023
4e8d855
Notebook documentation more organized
andresbar98 Oct 29, 2023
1218a38
🎨 pre-commit fixes
pre-commit-ci[bot] Nov 4, 2023
dc973f4
Raised minimum version/Better typing
andresbar98 Nov 4, 2023
64608e1
Merge branch 'cda-tum:main' into DDSIM_Sampler
andresbar98 Nov 4, 2023
bf45f11
Merge branch 'cda-tum:main' into DDSIM_Sampler
andresbar98 Nov 10, 2023
3b0ef40
🎨 pre-commit fixes
pre-commit-ci[bot] Nov 10, 2023
277c571
Missing annotations
andresbar98 Nov 10, 2023
bdc7a91
Merge branch 'cda-tum:main' into DDSIM_Sampler
andresbar98 Nov 17, 2023
5276dd0
Update minimum version in pyproject.toml
andresbar98 Nov 17, 2023
497e912
Improved typing
andresbar98 Nov 17, 2023
319c5f9
Remove transpilation from Sampler
andresbar98 Nov 17, 2023
ed8734b
Increase tolerance
andresbar98 Nov 17, 2023
722bcce
Merge branch 'cda-tum:main' into DDSIM_Sampler
andresbar98 Nov 28, 2023
3b094f6
Better typing
andresbar98 Nov 28, 2023
bae1854
Update test/python/test_sampler.py
burgholzer Nov 28, 2023
bf373a5
Better typing and test performance
andresbar98 Nov 28, 2023
6e84635
Better typing
andresbar98 Nov 29, 2023
28ecf45
Bump the submodules group with 3 updates (#324)
dependabot[bot] Dec 1, 2023
f99904f
⬆️🪝 update pre-commit hooks (#325)
pre-commit-ci[bot] Dec 4, 2023
43435af
✏️ slight fine-tuning
burgholzer Dec 5, 2023
3aaaff9
🚚 move primitives to their own folder
burgholzer Dec 5, 2023
9c4eca9
⏪ revert unnecessary change
burgholzer Dec 5, 2023
217abd8
🏷️ slighlty better typing
burgholzer Dec 5, 2023
86a8358
📝 fix docstrings
burgholzer Dec 5, 2023
56d403e
⚡ slight performance improvement
burgholzer Dec 5, 2023
0aa2261
🏷️ proper typing in tests
burgholzer Dec 5, 2023
83cd8af
🎨 pre-commit fixes
pre-commit-ci[bot] Dec 5, 2023
cf53c9e
Merge branch 'main' into DDSIM_Sampler
burgholzer Dec 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 287 additions & 0 deletions docs/source/Primitives.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "b6aae00d",
"metadata": {},
"source": [
"# Qiskit Primitives\n",
"\n",
"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. \n",
"\n",
"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.\n",
"\n",
"The two currently available primitives are the `Sampler` and the `Estimator`. The first one computes quasi-probability distributions from circuit measurements, while the second one calculates and interprets expectation values of quantum operators that are required for many near-term quantum algorithms.\n",
"\n",
"DDSIM provides its own version of these Qiskit Primitives:\n",
"\n",
"- `Sampler` leverages the default circuit simulator based on decision diagrams, while preserving the methods and functionality of the original Qiskit's sampler.\n",
"\n",
"- `Estimator` is currently in development and will be available soon.\n"
]
},
{
"cell_type": "markdown",
"id": "cc4eac78",
"metadata": {},
"source": [
"## Sampler"
]
},
{
"cell_type": "markdown",
"id": "4a898f0c",
"metadata": {},
"source": [
"The `Sampler` takes a list of `QuantumCircuit` objects and simulates them using the `QasmSimulatorBackend` from MQT DDSIM. It then computes the quasi-probability distributions of the circuits in the list and encapsulates the results, along with the job's metadata, within a `SamplerResult` object. \n",
"\n",
"Furthermore, it also handles compilation and parameter binding when working with parametrized circuits.\n",
"\n",
"Here we show an example on how to use this submodule:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bef3547c",
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from qiskit import QuantumCircuit\n",
"from qiskit.circuit import Parameter\n",
"\n",
"from mqt.ddsim.primitives import Sampler\n",
"\n",
"# Parametrized circuit to create an X-gate\n",
"theta_a = Parameter(\"theta_a\")\n",
"circ = QuantumCircuit(1)\n",
"circ.ry(theta_a, 0)\n",
"circ.measure_all()\n",
"\n",
"# Show circuit\n",
"circ.draw(\"mpl\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b3a673ed",
"metadata": {},
"outputs": [],
"source": [
"# Initialize sampler\n",
"sampler = Sampler()"
]
},
{
"cell_type": "markdown",
"id": "b7578f41",
"metadata": {},
"source": [
"The first argument in the `run` method is the circuit to simulate. The second argument contains the parameter values, if needed. The number of shots can be set as an additional argument. If not, the default value is 1024."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ed6c0970",
"metadata": {},
"outputs": [],
"source": [
"job = sampler.run(circ, np.pi, shots=int(1e4))\n",
"result = job.result()"
]
},
{
"cell_type": "markdown",
"id": "563cd527",
"metadata": {},
"source": [
"The `result()` method of the job returns a `SamplerResult` object, which includes both the quasi-probability distribution and job metadata."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4820227f",
"metadata": {},
"outputs": [],
"source": [
"print(f\">>> {result}\")\n",
"print(f\" > Quasi-probability distribution: {result.quasi_dists[0]}\")"
]
},
{
"cell_type": "markdown",
"id": "e74223d5",
"metadata": {},
"source": [
"It is also possible to simulate multiple circuits in one job:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "03a3e980",
"metadata": {},
"outputs": [],
"source": [
"# Create a second circuit\n",
"circ_2 = QuantumCircuit(1)\n",
"circ_2.measure_all()\n",
"circ_2.draw(\"mpl\")"
]
},
{
"cell_type": "markdown",
"id": "fc067206",
"metadata": {},
"source": [
"In this case, both the circuits and the parameter values must be entered as a `Sequence`."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4f0b78a6",
"metadata": {},
"outputs": [],
"source": [
"job = sampler.run((circ, circ_2), [[np.pi], []], shots=int(1e4))\n",
"result = job.result()\n",
"\n",
"print(f\">>> {result}\")\n",
"print(f\" > Quasi-probability distribution for circuit 1: {result.quasi_dists[0]}\")\n",
"print(f\" > Quasi-probability distribution for circuit 2: {result.quasi_dists[1]}\")"
]
},
{
"cell_type": "markdown",
"id": "a598052e",
"metadata": {},
"source": [
"Now let's use the `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\". \n",
"\n",
"A similar implementation of Grover's algorithm using Qiskit's sampler can be found here: https://qiskit.org/ecosystem/ibm-runtime/tutorials/grover_with_sampler.html"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "55d65e6c",
"metadata": {},
"outputs": [],
"source": [
"# Built-in modules\n",
"import math\n",
"\n",
"# Imports from Qiskit\n",
"from qiskit.circuit.library import MCMT, GroverOperator, ZGate\n",
"from qiskit.visualization import plot_distribution\n",
"\n",
"\n",
"# Define an oracle circuit that marks the input states, which are represented as a list of bitstrings\n",
"def grover_oracle(marked_states: list) -> QuantumCircuit:\n",
" if not isinstance(marked_states, list):\n",
" marked_states = [marked_states]\n",
" # Compute the number of qubits in circuit\n",
" num_qubits = len(marked_states[0])\n",
"\n",
" qc = QuantumCircuit(num_qubits)\n",
" # Mark each target state in the input list\n",
" for target in marked_states:\n",
" # Flip target bit-string to match Qiskit bit-ordering\n",
" rev_target = target[::-1]\n",
" # Find the indices of all the '0' elements in bit-string\n",
" zero_inds = [ind for ind in range(num_qubits) if rev_target.startswith(\"0\", ind)]\n",
" # Add a multi-controlled Z-gate with pre- and post-applied X-gates (open-controls)\n",
" # where the target bit-string has a '0' entry\n",
" qc.x(zero_inds)\n",
" qc.compose(MCMT(ZGate(), num_qubits - 1, 1), inplace=True)\n",
" qc.x(zero_inds)\n",
" return qc\n",
"\n",
"\n",
"# Enter the states to be marked\n",
"marked_states = [\"0110\", \"1010\"]\n",
"oracle = grover_oracle(marked_states)\n",
"oracle.draw(\"mpl\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "957644d9",
"metadata": {},
"outputs": [],
"source": [
"# Build circuit that amplifies the marked states by the oracle\n",
"\n",
"grover_op = GroverOperator(oracle)\n",
"grover_op.decompose().draw(\"mpl\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a4b3cc9b",
"metadata": {},
"outputs": [],
"source": [
"# Compute the optimal number of repetitions of the GroverOperator to amplify the probabilities of the marked states\n",
"optimal_num_iterations = math.floor(math.pi / 4 * math.sqrt(2**grover_op.num_qubits / len(marked_states)))\n",
"\n",
"\n",
"# Build the full Grover circuit\n",
"qc = QuantumCircuit(grover_op.num_qubits)\n",
"# Create even superposition of all basis states\n",
"qc.h(range(grover_op.num_qubits))\n",
"# Apply Grover operator the optimal number of times\n",
"qc.compose(grover_op.power(optimal_num_iterations), inplace=True)\n",
"# Measure all qubits\n",
"qc.measure_all()\n",
"qc.draw(\"mpl\")"
]
},
{
"cell_type": "markdown",
"id": "b58fce88",
"metadata": {},
"source": [
"After having built the circuit, use the `Sampler` to get the probability distribution."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "da2de10a",
"metadata": {},
"outputs": [],
"source": [
"dist = sampler.run(qc, shots=int(1e4)).result().quasi_dists[0]\n",
"plot_distribution(dist.binary_probabilities())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "venv"
},
"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": 5
}
8 changes: 8 additions & 0 deletions docs/source/api/ddsim.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ ddsim.unitarysimulator module
:undoc-members:
:show-inheritance:

ddsim.primitives module
-----------------------

.. automodule:: mqt.ddsim.primitives
:members:
:undoc-members:
:show-inheritance:

Module contents
---------------

Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ We appreciate any feedback and contributions to the project. If you want to cont
Quickstart
Simulators
Usage
Primitives
FAQ
Publications

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ classifiers = [
]
requires-python = ">=3.8"
dependencies = [
"qiskit-terra>=0.20.0"
"qiskit-terra>=0.22.1"
]
dynamic = ["version"]

Expand Down
7 changes: 7 additions & 0 deletions src/mqt/ddsim/primitives/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Module for Qiskit Primitives."""

from __future__ import annotations

from .sampler import Sampler

__all__ = ["Sampler"]
Loading