{ "cells": [ { "cell_type": "markdown", "id": "5f2681ba", "metadata": {}, "source": [ "# Explicit noise: what the model changes and what it assumes\n", "\n", "**Level:** Undergraduate · **Book connections:** P16, P20, P21, F22\n", "\n", "After this notebook you can:\n", "\n", "- Separate quantum channel noise, measurement readout errors and finite shots.\n", "- Predict amplitude damping analytically before simulation.\n", "- Check a density matrix and document the assumptions of a noise model.\n", "\n", "Run cells from top to bottom in the pinned environment described in `README.md`. All default execution is local. Exact amplitudes are simulator information; a QPU supplies sampled outcomes." ] }, { "cell_type": "code", "execution_count": null, "id": "dd3f2e37", "metadata": {}, "outputs": [], "source": [ "from importlib.metadata import version\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from IPython.display import display\n", "from qiskit import QuantumCircuit\n", "from qiskit.quantum_info import Statevector\n", "\n", "EXPECTED = {\"qiskit\": \"2.6.1\", \"qiskit-aer\": \"0.18.2\", \"qiskit-ibm-runtime\": \"0.51.0\"}\n", "for package, expected in EXPECTED.items():\n", " actual = version(package)\n", " assert actual == expected, f\"Use the supplied environment: {package}={actual}, expected {expected}\"\n", "print(\"Verified package versions:\", EXPECTED)\n", "plt.rcParams.update({\"figure.figsize\": (8, 3.5), \"font.size\": 11, \"axes.spines.top\": False,\n", " \"axes.spines.right\": False, \"axes.prop_cycle\": plt.cycler(color=[\"#006DAE\", \"#00A6B2\", \"#9E4A78\"])})\n", "SEED = 20261106\n", "\n", "def draw(circuit):\n", " \"\"\"Render a real circuit; each wire is a qubit, time runs left to right.\"\"\"\n", " fig = circuit.draw(output=\"mpl\", fold=90, style=\"iqp\")\n", " display(fig)\n", " plt.close(fig)\n", "\n", "def book_label(qiskit_label):\n", " \"\"\"For a single register, show q0 first as in the book.\"\"\"\n", " return qiskit_label[::-1]" ] }, { "cell_type": "markdown", "id": "12552a49", "metadata": {}, "source": [ "**Read the wires and bit strings carefully.** Qiskit draws `q0` on the top wire, but a\n", "standard statevector basis label or measured single-register count key is written\n", "`q(n−1)…q1q0`: `q0` has integer weight $2^0$. The book often writes `q0` first.\n", "These notebooks keep native Qiskit labels in calculations and use `book_label`\n", "only for an explicitly labelled display. Reversing a label changes the display;\n", "it does not apply a SWAP gate. All count examples here use one classical register\n", "with measurement `qj → cj`; do not reverse arbitrary multi-register strings." ] }, { "cell_type": "markdown", "id": "47c69e83", "metadata": {}, "source": [ "## 1. A simple, stated physical assumption\n", "\n", "We model one excited qubit relaxing during one interval. The probability of\n", "losing its excitation is $\\gamma=0.20$. For an ideal $|1\\rangle$ input,\n", "\n", "$$\\rho_{\\text{out}}=\\gamma|0\\rangle\\langle0|+(1-\\gamma)|1\\rangle\\langle1|\n", " =\\begin{pmatrix}\\gamma&0\\\\0&1-\\gamma\\end{pmatrix}.$$\n", "\n", "This parameter is illustrative. If a simple exponential relaxation model\n", "applies, $\\gamma=1-e^{-t/T_1}$. No hardware calibration is inferred here.\n", "We attach damping to exactly one identity instruction, representing that\n", "interval; we run it directly so an optimizer cannot delete the instruction." ] }, { "cell_type": "code", "execution_count": null, "id": "54607459", "metadata": {}, "outputs": [], "source": [ "from qiskit_aer import AerSimulator\n", "from qiskit_aer.noise import NoiseModel, amplitude_damping_error, ReadoutError\n", "from qiskit.quantum_info import DensityMatrix, Pauli\n", "gamma = .20\n", "quantum_noise = NoiseModel()\n", "quantum_noise.add_quantum_error(amplitude_damping_error(gamma), [\"id\"], [0])\n", "preparation = QuantumCircuit(1)\n", "preparation.x(0)\n", "preparation.id(0)\n", "draw(preparation)\n", "inspect = preparation.copy()\n", "inspect.save_density_matrix()\n", "simulator = AerSimulator(method=\"density_matrix\", noise_model=quantum_noise, seed_simulator=SEED)\n", "rho = DensityMatrix(simulator.run(inspect).result().data(0)[\"density_matrix\"])\n", "expected_rho = np.diag([gamma, 1-gamma])\n", "np.testing.assert_allclose(rho.data, expected_rho, atol=1e-12)\n", "np.testing.assert_allclose(np.trace(rho.data), 1, atol=1e-12)\n", "assert np.linalg.eigvalsh(rho.data).min() >= -1e-12\n", "print(\"Density matrix:\", rho.data)\n", "print(\"Purity:\", rho.purity())\n", "bloch = np.array([rho.expectation_value(Pauli(p)).real for p in [\"X\", \"Y\", \"Z\"]])\n", "print(\"Bloch vector:\", bloch, \"length:\", np.linalg.norm(bloch))\n", "assert np.linalg.norm(bloch) < 1 # This output is mixed; pure single-qubit states have length 1." ] }, { "cell_type": "markdown", "id": "50790176", "metadata": {}, "source": [ "## 2. Readout is another stage\n", "\n", "Add an asymmetric readout model: a true 0 is reported as 1 with probability\n", "0.03, and a true 1 is reported as 0 with probability 0.07. Rows of the matrix\n", "below are the true value, columns are the reported value. Then\n", "\n", "$$P(\\text{reported }1)=\\gamma(0.03)+(1-\\gamma)(0.93)=0.75.$$\n", "\n", "The density matrix describes the quantum state before readout. A readout\n", "error changes reported outcomes, rather than applying a unitary gate." ] }, { "cell_type": "code", "execution_count": null, "id": "00dd28aa", "metadata": {}, "outputs": [], "source": [ "combined_noise = NoiseModel()\n", "combined_noise.add_quantum_error(amplitude_damping_error(gamma), [\"id\"], [0])\n", "combined_noise.add_readout_error(ReadoutError([[.97, .03], [.07, .93]]), [0])\n", "measured = preparation.copy()\n", "measured.measure_all()\n", "shots = 8192\n", "noisy_simulator = AerSimulator(method=\"density_matrix\", noise_model=combined_noise, seed_simulator=SEED)\n", "counts = noisy_simulator.run(measured, shots=shots).result().get_counts()\n", "reported_one = counts.get(\"1\", 0)/shots\n", "predicted_one = gamma*.03 + (1-gamma)*.93\n", "delta = .001\n", "tolerance = np.sqrt(np.log(2/delta)/(2*shots))\n", "assert abs(reported_one-predicted_one) <= tolerance\n", "print(\"Counts:\", counts)\n", "print(\"Analytic P(reported 1):\", predicted_one, \"sample estimate:\", reported_one)\n", "plt.bar([\"Ideal state\", \"After damping\", \"Predicted readout\", \"Sampled readout\"],\n", " [1, 1-gamma, predicted_one, reported_one])\n", "plt.ylim(0, 1.05)\n", "plt.ylabel(\"Probability or estimated frequency of 1\")\n", "plt.xticks(rotation=12)\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "e47536f4", "metadata": {}, "source": [ "## Checkpoint and practice\n", "\n", "If shots rise from 8192 to 32768, does readout bias disappear?\n", "**No:** sampling uncertainty shrinks; the modeled physical/readout bias remains.\n", "A different model may include coherent errors, leakage, crosstalk, correlated\n", "noise or drift. This independent single-qubit model makes no claim to capture them.\n", "\n", "1. Set $\\gamma=0$ and predict the reported-one probability before rerunning.\n", "2. Prepare $|+\\rangle$ and inspect off-diagonal density-matrix entries. Compare\n", " amplitude damping with phase damping.\n", "3. Record the circuit, channel placement, parameters, seed, shots and package\n", " versions with any result you share.\n", "\n", "**Takeaway:** explain the noise model as carefully as the algorithm." ] }, { "cell_type": "markdown", "id": "7644685b", "metadata": {}, "source": [ "## Sources\n", "\n", "- [Qiskit Aer: AerSimulator](https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.AerSimulator)\n", "- [Qiskit Aer: building noise models](https://qiskit.github.io/qiskit-aer/tutorials/3_building_noise_models.html)\n", "- [Qiskit Aer: amplitude damping API](https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.amplitude_damping_error.html)" ] } ], "metadata": { "kernelspec": { "display_name": "Quantum book (pinned Python)", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.13.2" }, "quantum_book": { "chapters": [ "P16", "P20", "P21", "F22" ], "expected_packages": { "qiskit": "2.6.1", "qiskit-aer": "0.18.2", "qiskit-ibm-runtime": "0.51.0" }, "level": "Undergraduate", "network_on_default_run": false, "verified_release_date": "2026-11-06" } }, "nbformat": 4, "nbformat_minor": 5 }