mirror of https://github.com/Qiskit/qiskit-aer.git
391 lines
12 KiB
Plaintext
Executable File
391 lines
12 KiB
Plaintext
Executable File
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Noise Transformation"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Introduction\n",
|
|
"\n",
|
|
"This notebook shows how to use the Qiskit Aer utility functions `approximate_quantum_error` and `approximate_noise_model` to transform quantum noise channels into a different, more suitable, noise channel.\n",
|
|
"\n",
|
|
"Our guiding example is Clifford simulation. A Clifford simulator can efficiently simulate quantum computations which include gates only from a limited, non-universal set of gates (the Clifford gates). Not all quantum noises can be added to such simulations; hence, we aim to find a \"close\" noise channel which can be simulated in a Clifford simulator.\n",
|
|
"\n",
|
|
"We begin by importing the transformation functions from the Aer provider utilities"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-19T17:13:36.658036Z",
|
|
"start_time": "2019-08-19T17:13:34.394912Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"from qiskit_aer.utils import approximate_quantum_error, approximate_noise_model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The name \"approximate\" suggests that these functions generate the closest (in the Hilbert-Schmidt metric) error possible to the given one.\n",
|
|
"\n",
|
|
"We demonstrate the approximation using several standard error channels defined in Qiskit."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-19T17:13:36.676647Z",
|
|
"start_time": "2019-08-19T17:13:36.672883Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import numpy as np\n",
|
|
"\n",
|
|
"# Import Aer QuantumError functions that will be used\n",
|
|
"from qiskit_aer.noise import amplitude_damping_error, reset_error, pauli_error\n",
|
|
"\n",
|
|
"from qiskit.quantum_info import Kraus"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Overview\n",
|
|
"\n",
|
|
"A 1-qubit quantum channel is a function $\\mathcal{C}:\\mathbb{C}^{2\\times2}\\to\\mathbb{C}^{2\\times2}$ mapping density operators to density operators (to ensure the image is a density operator $\\mathcal{C}$ is required to be completely positive and trace preserving, **CPTP**).\n",
|
|
"\n",
|
|
"Given quantum channels $\\mathcal{E}_{1},\\dots,\\mathcal{E}_{r}$, and probabilities $p_1, p_2, \\dots, p_r$ such that $0\\le p_i \\le 1$ and $p_1+\\dots +p_r = 1$, a new quantum channel $\\mathcal{C}_\\mathcal{E}$ can be constructed such that $\\mathcal{C}_\\mathcal{E}(\\rho)$ has the effect of choosing the channel $\\mathcal{E}_i$ with probability $p_i$ and applying it to $\\rho$.\n",
|
|
"\n",
|
|
"The noise transformation function solves the following optimization problem: Given a channel $\\mathcal{C}$ (\"goal\") and a list of channels $\\mathcal{E}_{1},\\dots,\\mathcal{E}_{r}$, find the probabilities $p_1, p_2, \\dots, p_r$ minimizing $D(\\mathcal{C}, \\mathcal{C}_\\mathcal{E})$ according to some distance metric $D$ (the Hilbert-Schmidt metric is currently used).\n",
|
|
"\n",
|
|
"To ensure the approximation is honest, in the sense that the approximate error channel serves as an \"upper bound\" for the actual error channel, we add the additional honesty constraint:\n",
|
|
"\n",
|
|
"$$\\text{F}(I,\\mathcal{C})\\ge F(I,\\mathcal{C}_\\mathcal{E})$$\n",
|
|
"\n",
|
|
"Where $\\text{F}$ is a fidelity measure and $I$ is the identity channel."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Example: Approximating amplitude damping noise with reset noise.\n",
|
|
"\n",
|
|
"**Amplitude damping** noise is described by a single parameter $0\\le \\gamma \\le 1$ and given by the Kraus operators:\n",
|
|
"\n",
|
|
"$$\\left(\\begin{array}{cc}\n",
|
|
"1 & 0\\\\\n",
|
|
"0 & \\sqrt{1-\\gamma}\n",
|
|
"\\end{array}\\right),\\left(\\begin{array}{cc}\n",
|
|
"0 & \\sqrt{\\gamma}\\\\\n",
|
|
"0 & 0\n",
|
|
"\\end{array}\\right)$$\n",
|
|
"\n",
|
|
"**Reset** error is described by probabilities $0\\le p, q\\le 1$ such that $p+q\\le 1$ and given by the Kraus operators:\n",
|
|
"\n",
|
|
"$$\\left(\\begin{array}{cc}\n",
|
|
"\\sqrt{p} & 0\\\\\n",
|
|
"0 & 0\n",
|
|
"\\end{array}\\right),\\left(\\begin{array}{cc}\n",
|
|
"0 & \\sqrt{p}\\\\\n",
|
|
"0 & 0\n",
|
|
"\\end{array}\\right),\\left(\\begin{array}{cc}\n",
|
|
"0 & 0\\\\\n",
|
|
"\\sqrt{q} & 0\n",
|
|
"\\end{array}\\right),\\left(\\begin{array}{cc}\n",
|
|
"0 & 0\\\\\n",
|
|
"0 & \\sqrt{q}\n",
|
|
"\\end{array}\\right)$$\n",
|
|
"\n",
|
|
"This can be thought of as \"resetting\" the quantum state of the affected qubit to $\\left|0\\right\\rangle$ with probability $p$, to $\\left|1\\right\\rangle$ with probability $q$, and do nothing with probability $1-(p+q)$.\n",
|
|
"\n",
|
|
"It is not too difficult to determine analytically the best values of $p,q$ to approximate a $\\gamma$ amplitude damping channel, see the details __[here](https://arxiv.org/abs/1207.0046)__. The best approximation is:\n",
|
|
"\n",
|
|
"$$p=\\frac{1}{2}\\left(1+\\gamma-\\sqrt{1-\\gamma}\\right), q=0$$"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-19T17:13:36.791986Z",
|
|
"start_time": "2019-08-19T17:13:36.704432Z"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"gamma = 0.23\n",
|
|
"error = amplitude_damping_error(gamma)\n",
|
|
"results = approximate_quantum_error(error, operator_string=\"reset\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"We only needed the above code to perform the actual approximation. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-19T17:13:36.812282Z",
|
|
"start_time": "2019-08-19T17:13:36.805559Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"QuantumError on 1 qubits. Noise circuits:\n",
|
|
" P(0) = 0.8237482193044617, Circuit = \n",
|
|
" ┌───┐\n",
|
|
"q: ┤ I ├\n",
|
|
" └───┘\n",
|
|
" P(1) = 0.17625178069553835, Circuit = \n",
|
|
" \n",
|
|
"q: ─|0>─\n",
|
|
" \n",
|
|
" P(2) = 2.158685879252966e-23, Circuit = \n",
|
|
" ┌───┐\n",
|
|
"q: ─|0>─┤ X ├\n",
|
|
" └───┘\n",
|
|
"\n",
|
|
"Expected results:\n",
|
|
"P(0) = 0.8237482193696062\n",
|
|
"P(1) = 0.17625178063039387\n",
|
|
"P(2) = 0\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(results)\n",
|
|
"\n",
|
|
"p = (1 + gamma - np.sqrt(1 - gamma)) / 2\n",
|
|
"q = 0\n",
|
|
"\n",
|
|
"print(\"\")\n",
|
|
"print(\"Expected results:\")\n",
|
|
"print(\"P(0) = {}\".format(1-(p+q)))\n",
|
|
"print(\"P(1) = {}\".format(p))\n",
|
|
"print(\"P(2) = {}\".format(q))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"We got the results predicted analytically.\n",
|
|
"\n",
|
|
"## Different input types\n",
|
|
"\n",
|
|
"The approximation function is given two inputs: The error channel to approximate, and a set of error channels that can be used in constructing the approximation.\n",
|
|
"\n",
|
|
"The **error channel** to approximate can be given as any input that can be converted to the `QuantumError` object. \n",
|
|
"\n",
|
|
"As an example, we explicitly construct the Kraus matrices of amplitude damping and pass to the same approximation function as before:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-19T17:13:37.367331Z",
|
|
"start_time": "2019-08-19T17:13:37.325594Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"QuantumError on 1 qubits. Noise circuits:\n",
|
|
" P(0) = 0.8237482193044623, Circuit = \n",
|
|
" ┌───┐\n",
|
|
"q: ┤ I ├\n",
|
|
" └───┘\n",
|
|
" P(1) = 0.1762517806955376, Circuit = \n",
|
|
" \n",
|
|
"q: ─|0>─\n",
|
|
" \n",
|
|
" P(2) = 6.463899246563026e-23, Circuit = \n",
|
|
" ┌───┐\n",
|
|
"q: ─|0>─┤ X ├\n",
|
|
" └───┘\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"gamma = 0.23\n",
|
|
"K0 = np.array([[1,0],[0,np.sqrt(1-gamma)]])\n",
|
|
"K1 = np.array([[0,np.sqrt(gamma)],[0,0]])\n",
|
|
"results = approximate_quantum_error(Kraus([K0, K1]), operator_string=\"reset\")\n",
|
|
"print(results)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The **error operators** that are used to construct the approximating channel can be either given as a list, a dictionary or a string indicating hard-coded channels. \n",
|
|
"\n",
|
|
"Any channel can be either a list of Kraus operators, or 'QuantumError' objects.\n",
|
|
"\n",
|
|
"The identity channel does not need to be passed directly; it is always implicitly used.\n",
|
|
"\n",
|
|
"As an example, we approximate amplitude damping using an explicit Kraus representation for reset noises:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-19T17:13:38.083970Z",
|
|
"start_time": "2019-08-19T17:13:38.046909Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"QuantumError on 1 qubits. Noise circuits:\n",
|
|
" P(0) = 0.8237482193044617, Circuit = \n",
|
|
" ┌───┐\n",
|
|
"q: ┤ I ├\n",
|
|
" └───┘\n",
|
|
" P(1) = 0.17625178069553835, Circuit = \n",
|
|
" ┌───────┐\n",
|
|
"q: ┤ kraus ├\n",
|
|
" └───────┘\n",
|
|
" P(2) = 2.158685879252966e-23, Circuit = \n",
|
|
" ┌───────┐\n",
|
|
"q: ┤ kraus ├\n",
|
|
" └───────┘\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"reset_to_0 = Kraus([np.array([[1,0],[0,0]]), np.array([[0,1],[0,0]])])\n",
|
|
"reset_to_1 = Kraus([np.array([[0,0],[1,0]]), np.array([[0,0],[0,1]])])\n",
|
|
"reset_kraus = [reset_to_0, reset_to_1]\n",
|
|
"\n",
|
|
"gamma = 0.23\n",
|
|
"error = amplitude_damping_error(gamma)\n",
|
|
"results = approximate_quantum_error(error, operator_list=reset_kraus)\n",
|
|
"print(results)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Note the difference in the output channel: The probabilities are the same, but the input Kraus operators were converted to general Kraus channels, which cannot be used in a Clifford simulator. Hence, it is always better to pass a `QuantumError` object instead of the Kraus matrices, when possible."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {
|
|
"ExecuteTime": {
|
|
"end_time": "2019-08-19T17:13:57.085790Z",
|
|
"start_time": "2019-08-19T17:13:57.077225Z"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"'1.1.0'"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"import qiskit\n",
|
|
"qiskit.__version__"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"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.3"
|
|
},
|
|
"varInspector": {
|
|
"cols": {
|
|
"lenName": 16,
|
|
"lenType": 16,
|
|
"lenVar": 40
|
|
},
|
|
"kernels_config": {
|
|
"python": {
|
|
"delete_cmd_postfix": "",
|
|
"delete_cmd_prefix": "del ",
|
|
"library": "var_list.py",
|
|
"varRefreshCmd": "print(var_dic_list())"
|
|
},
|
|
"r": {
|
|
"delete_cmd_postfix": ") ",
|
|
"delete_cmd_prefix": "rm(",
|
|
"library": "var_list.r",
|
|
"varRefreshCmd": "cat(var_dic_list()) "
|
|
}
|
|
},
|
|
"types_to_exclude": [
|
|
"module",
|
|
"function",
|
|
"builtin_function_or_method",
|
|
"instance",
|
|
"_Feature"
|
|
],
|
|
"window_display": false
|
|
},
|
|
"vscode": {
|
|
"interpreter": {
|
|
"hash": "f8729fd834348017bca17aea688b306f536a675180840f7307eb909fff39c285"
|
|
}
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|