{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "551a668e",
   "metadata": {},
   "source": [
    "# Quantum information and quantum computing - Problem set 10\n",
    "\n",
    "### _Problem 2_ : Noise channels in Qiskit\n",
    "\n",
    "In this exercise we will learn how to implement a noise channel in Qiskit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0789485b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# First, import all the useful methods\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt   \n",
    "import math\n",
    "\n",
    "\n",
    "from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister\n",
    "from qiskit_aer import QasmSimulator\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2c34636",
   "metadata": {},
   "source": [
    "----\n",
    "#### Save density matrices "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7c8a0ffc",
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit.quantum_info import DensityMatrix\n",
    "## To visualize density matrices\n",
    "from qiskit.visualization import plot_state_city"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dba3fc68",
   "metadata": {},
   "outputs": [],
   "source": [
    "## Initialise the circuit in the bell state\n",
    "circ = QuantumCircuit(2)\n",
    "circ.h(0)\n",
    "circ.cx(0,1)\n",
    "circ.save_density_matrix()\n",
    "\n",
    "circ.draw(\"mpl\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0db2daf3",
   "metadata": {},
   "outputs": [],
   "source": [
    "simulator = QasmSimulator(method='density_matrix')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5eb9672",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Perform a noise simulation\n",
    "result = simulator.run(circ).result()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "01c6f11e",
   "metadata": {},
   "outputs": [],
   "source": [
    "rho = result.data()[\"density_matrix\"]\n",
    "rho.draw('latex', prefix='\\\\rho = ')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d49aa0a",
   "metadata": {},
   "source": [
    "We can use `plot_state_city` to plot the real and the imaginary part of the density matrix we obtained."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "47b918bb",
   "metadata": {},
   "outputs": [],
   "source": [
    "plot_state_city(rho.data, title='Density Matrix')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61f45c11",
   "metadata": {},
   "source": [
    "----\n",
    "\n",
    "#### Create a noise model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d53901ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "import qiskit_aer.noise as noise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0f8889eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "noise_model = noise.NoiseModel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "88ee9df4",
   "metadata": {},
   "source": [
    "You can add different types of noise by going to [this link](https://qiskit.org/documentation/tutorials/simulators/3_building_noise_models.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "04dbe0e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Error probabilities, we magnify the error probabilities \n",
    "\n",
    "prob_1 = 0.01  # 1-qubit gate\n",
    "prob_2 = 0.5   # 2-qubit gate\n",
    "\n",
    "# Depolarizing quantum errors, define yourself other types \n",
    "error_1 = noise.depolarizing_error(prob_1, 1)\n",
    "error_2 = noise.depolarizing_error(prob_2, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2bf386d1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Add errors to noise model\n",
    "noise_model.add_all_qubit_quantum_error(error_1, ['u1', 'u2', 'u3'])\n",
    "noise_model.add_all_qubit_quantum_error(error_2, ['cx'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28377301",
   "metadata": {},
   "outputs": [],
   "source": [
    "# use the noise model in your simulator\n",
    "noise_simulator = QasmSimulator(method='density_matrix',\n",
    "                        noise_model=noise_model)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2cade467",
   "metadata": {},
   "source": [
    "---\n",
    "#### Apply the noise model to your circuit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6cc6c3ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "### Your code here"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d84eafc3",
   "metadata": {},
   "source": [
    "----\n",
    "#### Quantum State Tomography"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c5b07381",
   "metadata": {},
   "outputs": [],
   "source": [
    "#!pip install qiskit_experiments"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "841afdca",
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_experiments.library import StateTomography"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f229e90",
   "metadata": {},
   "outputs": [],
   "source": [
    "tomography  = StateTomography(##your circuit here\n",
    "                             )\n",
    "exp         = tomography.run(## simulator here ,\n",
    "                            ## shots=5000\n",
    "                             )\n",
    "exp_analysis = exp.analysis_results()[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f95a2cb8",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "jupytext": {
   "formats": "ipynb,md"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
