Skip to content

Cm/cosmetic fixes to notebooks #429

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

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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

Large diffs are not rendered by default.

661 changes: 660 additions & 1 deletion docs/examples/algorithms_and_protocols/entanglement_swapping.ipynb

Large diffs are not rendered by default.

Large diffs are not rendered by default.

12 changes: 7 additions & 5 deletions docs/examples/algorithms_and_protocols/phase_estimation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@
"source": [
"from pytket.circuit import QControlBox, DiagonalBox\n",
"\n",
"\n",
"def build_phase_estimation_circuit(\n",
" n_measurement_qubits: int, state_prep: CircBox, unitary: CircBox | DiagonalBox\n",
") -> Circuit:\n",
Expand Down Expand Up @@ -350,7 +351,7 @@
"from pytket.circuit import DiagonalBox\n",
"import numpy as np\n",
"\n",
"u_diagonal = np.array([1, 1, np.e**(1j * np.pi/4), np.e**(1j * np.pi/8)])\n",
"u_diagonal = np.array([1, 1, np.e ** (1j * np.pi / 4), np.e ** (1j * np.pi / 8)])\n",
"d_box = DiagonalBox(u_diagonal)"
]
},
Expand All @@ -368,9 +369,8 @@
"outputs": [],
"source": [
"qpe_circ_trivial = build_phase_estimation_circuit(\n",
" n_measurement_qubits=4,\n",
" state_prep=prep_box, \n",
" unitary=d_box)"
" n_measurement_qubits=4, state_prep=prep_box, unitary=d_box\n",
")"
]
},
{
Expand Down Expand Up @@ -451,6 +451,7 @@
"from pytket.backends.backendresult import BackendResult\n",
"import matplotlib.pyplot as plt\n",
"\n",
"\n",
"def plot_qpe_results(\n",
" sim_result: BackendResult,\n",
" n_strings: int = 4,\n",
Expand All @@ -469,7 +470,7 @@
"\n",
" if dark_mode:\n",
" plt.style.use(\"dark_background\")\n",
" \n",
"\n",
" fig = plt.figure()\n",
" ax = fig.add_axes((0, 0, 0.4, 0.5))\n",
" color_list = [\"orange\"] * (len(x_axis_values))\n",
Expand Down Expand Up @@ -527,6 +528,7 @@
"source": [
"from pytket.backends.backendresult import BackendResult\n",
"\n",
"\n",
"def single_phase_from_backendresult(result: BackendResult) -> float:\n",
" # Extract most common measurement outcome\n",
" basis_state = result.get_counts().most_common()[0][0]\n",
Expand Down
1,100 changes: 1,099 additions & 1 deletion docs/examples/algorithms_and_protocols/ucc_vqe.ipynb

Large diffs are not rendered by default.

625 changes: 624 additions & 1 deletion docs/examples/backends/comparing_simulators.ipynb

Large diffs are not rendered by default.

1,111 changes: 1,110 additions & 1 deletion docs/examples/backends/creating_backends.ipynb

Large diffs are not rendered by default.

232 changes: 231 additions & 1 deletion docs/examples/backends/qiskit_integration.ipynb
Original file line number Diff line number Diff line change
@@ -1 +1,231 @@
{"cells":[{"cell_type":"markdown","metadata":{},"source":["# Integrating `pytket` into Qiskit software"]},{"cell_type":"markdown","metadata":{},"source":["**Download this notebook - {nb-download}`qiskit_integration.ipynb`**"]},{"cell_type":"markdown","metadata":{},"source":["In this tutorial, we will focus on:\n","- Using `pytket` for compilation or providing devices/simulators within Qiskit workflows;\n","- Adapting Qiskit code to use `pytket` directly."]},{"cell_type":"markdown","metadata":{},"source":["See the [pytket-qiskit docs](inv:pytket-qiskit:std:doc#index) for more information."]},{"cell_type":"markdown","metadata":{},"source":["This example assumes some familiarity with the Qiskit algorithms library. We have chosen a small variational quantum eigensolver (VQE) for our example, but the same principles apply to a wide range of quantum algorithms.\n","\n","To run this example, you will need `pytket-qiskit`, as well as the separate `qiskit-optimization` package. You will also need IBMQ credentials stored on your local machine.\n","\n","Qiskit has risen to prominence as the most popular platform for the development of quantum software, providing an open source, full-stack solution with a large feature list and extensive examples from the developers and community. For many researchers who have already invested in building a large codebase built on top of Qiskit, the idea of switching entirely to a new platform can look like a time-sink and may require reversion to take advantage of the new tools that get regularly added to Qiskit.\n","\n","The interoperability provided by [pytket-qiskit](inv:pytket-qiskit:std:doc#index) allows Qiskit users to start taking advantage of some of the unique features of [pytket](inv:pytket:std:doc#index) without having to completely rewrite their software."]},{"cell_type":"markdown","metadata":{},"source":["Let's take as an example an ansatz for computing the ground-state energy of a hydrogen molecule."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["from qiskit.quantum_info import SparsePauliOp\n","\n","H2_op = SparsePauliOp.from_list(\n"," [\n"," (\"II\", -1.052373245772859),\n"," (\"IZ\", 0.39793742484318045),\n"," (\"ZI\", -0.39793742484318045),\n"," (\"ZZ\", -0.01128010425623538),\n"," (\"XX\", 0.18093119978423156),\n"," ]\n",")"]},{"cell_type":"markdown","metadata":{},"source":["First let's use qiskit's NumPyEigensolver to compute the exact answer:"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["from qiskit.algorithms.eigensolvers import NumPyEigensolver\n","\n","es = NumPyEigensolver(k=1)\n","exact_result = es.compute_eigenvalues(H2_op).eigenvalues[0].real\n","print(\"Exact result:\", exact_result)"]},{"cell_type":"markdown","metadata":{},"source":["The following function will attempt to find an approximation to this using VQE, given a qiskit BackendEstimator on which to run circuits:"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["from qiskit.algorithms.minimum_eigensolvers.vqe import VQE\n","from qiskit.algorithms.optimizers import SPSA\n","from qiskit.circuit.library import EfficientSU2\n","\n","def vqe_solve(op, maxiter, qestimator):\n"," optimizer = SPSA(maxiter=maxiter)\n"," ansatz = EfficientSU2(op.num_qubits, entanglement=\"linear\")\n"," vqe = VQE(estimator=qestimator, ansatz=ansatz, optimizer=optimizer)\n"," return vqe.compute_minimum_eigenvalue(op).eigenvalue"]},{"cell_type":"markdown","metadata":{},"source":["We will run this on a pytket {py:class}`~pytket.extensions.qiskit.IBMQEmulatorBackend`. This is a noisy simulator whose characteristics match those of the real device, in this case \"ibmq_belem\" (a 5-qubit machine). The characteristics are retrieved from the device when the backend is constructed, so we must first load our IBM account. Circuits will be compiled to match the connectivity of the device and simulated using a basic noise model [constructed from the device parameters](https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.NoiseModel.html)."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["from pytket.extensions.qiskit import IBMQEmulatorBackend\n","\n","b_emu = IBMQEmulatorBackend(\"ibm_kyiv\", instance=\"ibm-q/open/main\")"]},{"cell_type":"markdown","metadata":{},"source":["Most qiskit algorithms require a qiskit `primitive` as input; this in turn is constructed from a `qiskit.providers.Backend`. The [TketBackend](inv:#*.TketBackend) class wraps a pytket backend as a `qiskit.providers.Backend`."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["from pytket.extensions.qiskit.tket_backend import TketBackend\n","from qiskit.primitives import BackendEstimator\n","\n","qis_backend = TketBackend(b_emu)\n","qestimator = BackendEstimator(qis_backend, options={\"shots\": 8192})"]},{"cell_type":"markdown","metadata":{},"source":["Note that we could have used any other pytket shots backend instead of `b_emu` here. The `pytket` extension modules provide an interface to a wide variety of devices and simulators from different quantum software platforms.<br>\n","<br>\n","We can now run the VQE algorithm. In this example we use only 50 iterations, but greater accuracy may be achieved by increasing this number:"]},{"cell_type":"markdown","metadata":{},"source":["#print(\"VQE result:\", vqe_solve(H2_op, 50, qestimator))"]},{"cell_type":"markdown","metadata":{},"source":["Another way to improve the accuracy of results is to apply optimisations to the circuit in an attempt to reduce the overall noise. When we construct our qiskit backend, we can pass in a pytket compilation pass as an additional parameter. There is a wide range of options here; we recommend the device-specific default compilation pass, provided by each tket backend. This pass will ensure that all the hardware constraints of the device are met. We can enable tket's most aggressive optimisation level by setting the parameter `optimisation_level=2`."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["qis_backend2 = TketBackend(b_emu, b_emu.default_compilation_pass(optimisation_level=2))\n","qestimator2 = BackendEstimator(qis_backend2, options={\"shots\": 8192})"]},{"cell_type":"markdown","metadata":{},"source":["Let's run the optimisation again:"]},{"cell_type":"markdown","metadata":{},"source":["#print(\"VQE result (with optimisation):\", vqe_solve(H2_op, 50, qestimator2))"]},{"cell_type":"markdown","metadata":{},"source":["These are small two-qubit circuits, so the improvement may be small, but with larger, more complex circuits, the reduction in noise from compilation will make a greater difference and allow VQE experiments to converge with fewer iterations."]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.4"}},"nbformat":4,"nbformat_minor":2}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Integrating `pytket` into Qiskit software"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Download this notebook - {nb-download}`qiskit_integration.ipynb`**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this tutorial, we will focus on:\n",
"- Using `pytket` for compilation or providing devices/simulators within Qiskit workflows;\n",
"- Adapting Qiskit code to use `pytket` directly."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"See the [pytket-qiskit docs](inv:pytket-qiskit:std:doc#index) for more information."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This example assumes some familiarity with the Qiskit algorithms library. We have chosen a small variational quantum eigensolver (VQE) for our example, but the same principles apply to a wide range of quantum algorithms.\n",
"\n",
"To run this example, you will need `pytket-qiskit`, as well as the separate `qiskit-optimization` package. You will also need IBMQ credentials stored on your local machine.\n",
"\n",
"Qiskit has risen to prominence as the most popular platform for the development of quantum software, providing an open source, full-stack solution with a large feature list and extensive examples from the developers and community. For many researchers who have already invested in building a large codebase built on top of Qiskit, the idea of switching entirely to a new platform can look like a time-sink and may require reversion to take advantage of the new tools that get regularly added to Qiskit.\n",
"\n",
"The interoperability provided by [pytket-qiskit](inv:pytket-qiskit:std:doc#index) allows Qiskit users to start taking advantage of some of the unique features of [pytket](inv:pytket:std:doc#index) without having to completely rewrite their software."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's take as an example an ansatz for computing the ground-state energy of a hydrogen molecule."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from qiskit.quantum_info import SparsePauliOp\n",
"\n",
"H2_op = SparsePauliOp.from_list(\n",
" [\n",
" (\"II\", -1.052373245772859),\n",
" (\"IZ\", 0.39793742484318045),\n",
" (\"ZI\", -0.39793742484318045),\n",
" (\"ZZ\", -0.01128010425623538),\n",
" (\"XX\", 0.18093119978423156),\n",
" ]\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First let's use qiskit's NumPyEigensolver to compute the exact answer:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from qiskit.algorithms.eigensolvers import NumPyEigensolver\n",
"\n",
"es = NumPyEigensolver(k=1)\n",
"exact_result = es.compute_eigenvalues(H2_op).eigenvalues[0].real\n",
"print(\"Exact result:\", exact_result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The following function will attempt to find an approximation to this using VQE, given a qiskit BackendEstimator on which to run circuits:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from qiskit.algorithms.minimum_eigensolvers.vqe import VQE\n",
"from qiskit.algorithms.optimizers import SPSA\n",
"from qiskit.circuit.library import EfficientSU2\n",
"\n",
"\n",
"def vqe_solve(op, maxiter, qestimator):\n",
" optimizer = SPSA(maxiter=maxiter)\n",
" ansatz = EfficientSU2(op.num_qubits, entanglement=\"linear\")\n",
" vqe = VQE(estimator=qestimator, ansatz=ansatz, optimizer=optimizer)\n",
" return vqe.compute_minimum_eigenvalue(op).eigenvalue"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We will run this on a pytket {py:class}`~pytket.extensions.qiskit.IBMQEmulatorBackend`. This is a noisy simulator whose characteristics match those of the real device, in this case \"ibmq_belem\" (a 5-qubit machine). The characteristics are retrieved from the device when the backend is constructed, so we must first load our IBM account. Circuits will be compiled to match the connectivity of the device and simulated using a basic noise model [constructed from the device parameters](https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.NoiseModel.html)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pytket.extensions.qiskit import IBMQEmulatorBackend\n",
"\n",
"b_emu = IBMQEmulatorBackend(\"ibm_kyiv\", instance=\"ibm-q/open/main\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Most qiskit algorithms require a qiskit `primitive` as input; this in turn is constructed from a `qiskit.providers.Backend`. The [TketBackend](inv:#*.TketBackend) class wraps a pytket backend as a `qiskit.providers.Backend`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from pytket.extensions.qiskit.tket_backend import TketBackend\n",
"from qiskit.primitives import BackendEstimator\n",
"\n",
"qis_backend = TketBackend(b_emu)\n",
"qestimator = BackendEstimator(qis_backend, options={\"shots\": 8192})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that we could have used any other pytket shots backend instead of `b_emu` here. The `pytket` extension modules provide an interface to a wide variety of devices and simulators from different quantum software platforms.<br>\n",
"<br>\n",
"We can now run the VQE algorithm. In this example we use only 50 iterations, but greater accuracy may be achieved by increasing this number:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#print(\"VQE result:\", vqe_solve(H2_op, 50, qestimator))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another way to improve the accuracy of results is to apply optimisations to the circuit in an attempt to reduce the overall noise. When we construct our qiskit backend, we can pass in a pytket compilation pass as an additional parameter. There is a wide range of options here; we recommend the device-specific default compilation pass, provided by each tket backend. This pass will ensure that all the hardware constraints of the device are met. We can enable tket's most aggressive optimisation level by setting the parameter `optimisation_level=2`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"qis_backend2 = TketBackend(b_emu, b_emu.default_compilation_pass(optimisation_level=2))\n",
"qestimator2 = BackendEstimator(qis_backend2, options={\"shots\": 8192})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's run the optimisation again:"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#print(\"VQE result (with optimisation):\", vqe_solve(H2_op, 50, qestimator2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These are small two-qubit circuits, so the improvement may be small, but with larger, more complex circuits, the reduction in noise from compilation will make a greater difference and allow VQE experiments to converge with fewer iterations."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
751 changes: 750 additions & 1 deletion docs/examples/circuit_compilation/compilation_example.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"from pytket.circuit import Circuit\n",
"from random import random, randrange, seed\n",
"\n",
"\n",
"def random_sparse_ansatz(n_qubits, n_layers, p, rng_seed=None):\n",
" seed(rng_seed)\n",
" circ = Circuit(n_qubits)\n",
Expand Down
1,223 changes: 1,222 additions & 1 deletion docs/examples/circuit_compilation/mapping_example.ipynb

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/examples/creating_backends_exercise.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pytket.circuit import OpType, Qubit, Bit, UnitID
from pytket.circuit import Qubit, Bit, UnitID
from pytket.pauli import Pauli, QubitPauliString

from binarytree import Node
Expand Down
7 changes: 4 additions & 3 deletions docs/examples/oxfordQIS.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@

from pytket.circuit import Circuit, PauliExpBox, Pauli
from pytket.predicates import CompilationUnit
from pytket.passes import DecomposeBoxes, PauliSimp, SequencePass
from pytket.passes import DecomposeBoxes
from pytket.utils import expectation_from_counts
from pytket.extensions.qiskit import AerBackend, AerStateBackend
from pytket.extensions.qiskit import AerBackend

from sympy import Symbol
from scipy.optimize import minimize
from openfermion import QubitOperator, FermionOperator, jordan_wigner
from openfermion import QubitOperator, FermionOperator


# Generate a parametric ansatz
def h2_JW_sto3g_ansatz():
Expand Down