introduction_cn.ipynb 10.6 KB
Notebook
Newer Older
Q
Quleaf 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 变分量子线性求解器\n",
    "*Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. All Rights Reserved.*\n",
    "## 背景介绍\n",
    "\n",
    "线性方程组是数学中一个基本但非常有用的工具。 一个例子是,在经济学中,可以使用线性方程对经济进行建模。 此外,它还为非线性的大型系统提供了简单的估计。 因此求解线性方程组是一项重要的任务。\n",
    "\n",
    "变分量子线性求解器(Variational quantum linear solver, VQLS)是一种求解线性方程组的变分量子算法,采用了经典-量子混合的方案,可以在近期的含噪中等规模量子计算机上运行。具体来说,对于一个矩阵 $A$ 和一个向量 $\\boldsymbol{b}$,我们的目标是找到一个向量 $\\boldsymbol{x}$ 使得 $A \\boldsymbol{x} = \\boldsymbol{b}$. 使用 VQLS 算法可以得到一个与 $\\boldsymbol{x}$ 成比例的量子态,即一个归一化的向量 $|x\\rangle = \\frac{\\boldsymbol{x}}{\\lVert \\boldsymbol{x} \\rVert_2}$。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 模型原理\n",
    "\n",
    "量子场景的线性方程求解问题和通常的设定略有不同,因为量子计算需要将酉算子应用到量子态上。对于输入的矩阵 $A$,我们需要将其分解成酉算子的线性组合 $A = \\sum_n c_n A_n$,其中每个 $A_n$ 都是酉算子,可以在量子线路上运行。对于输入的向量 $\\boldsymbol{b}$,我们需要假设它是一个能够被某个酉算子 $U$ 制备的量子态 $|b\\rangle$,即 $U|0\\rangle = |b\\rangle$。我们可以用下面这张图来概括 VQLS 算法的整体架构:\n",
    "\n",
    "![VQLS](vqls.png)\n",
    "\n",
    "可以看到,VQLS 算法是一种混合优化算法,可以分为经典和量子两部分,需要在量子计算机上准备参数化量子电路 $V(\\alpha)$ 并计算损失函数 $C(\\alpha)$,然后在经典计算机上对参数 $\\alpha$ 进行优化从而最小化损失函数,直到损失低于某个阈值,最后输出目标量子态 $|x\\rangle$。其中参数化电路 $V(\\alpha)$ 可以生成一个量子态 $|\\psi(\\alpha)\\rangle$,电路 $F(A)$ 可以计算 $A|\\psi(\\alpha)\\rangle$ 与 $|b\\rangle$ 的近似程度,即损失函数 $C(\\alpha)$。当量子态 $A|\\psi(\\alpha)\\rangle$ 与 $|b\\rangle$ 足够接近时,这就意味着量子态 $|\\psi(\\alpha)\\rangle$ 与目标态 $|x\\rangle$ 足够接近,我们可以输出量子态 $|\\psi(\\alpha)\\rangle$ 作为目标态 $|x\\rangle$ 的近似。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 量桨实现\n",
    "\n",
    "我们使用量桨中的 `Circuit` 类结合飞桨优化器来实现 VQLS 算法,其中量子部分中参数化量子电路 $V(\\alpha)$ 为 `Circuit` 中内置的 `complex_entangled_layer` 模板,损失函数计算电路 $F(A)$ 由 Hadamard Test 或 Hadamard-Overlap Test 组成,主要使用了量桨中的 `oracle` 量子门来实现控制 $A_n$ 门,在经典优化部分中我们使用 Adam 优化器来最小化损失函数。\n",
    "\n",
    "用户可以使用 toml 文件指定算法的输入,矩阵 $A$ 和向量 $\\boldsymbol{b}$,分别以 `.npy` 文件形式存储。用户可以使用以下代码,通过改变$n$的值随机生成一个 $n\\times n$ 的矩阵 $A$ 以及向量 $\\boldsymbol{b}$。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "这是一个随机生成的A:\n",
      "[[4.1702199e+00+7.203245j   1.1437482e-03+3.0233257j\n",
      "  1.4675589e+00+0.9233859j  1.8626021e+00+3.4556072j\n",
      "  3.9676747e+00+5.3881674j ]\n",
      " [2.0445225e+00+8.781175j   2.7387592e-01+6.704675j\n",
      "  4.1730480e+00+5.5868983j  1.4038694e+00+1.9810148j\n",
      "  8.0074453e+00+9.682616j  ]\n",
      " [8.7638912e+00+8.946067j   8.5044211e-01+0.39054784j\n",
      "  1.6983042e+00+8.781425j   9.8346835e-01+4.2110763j\n",
      "  9.5788956e+00+5.3316526j ]\n",
      " [6.8650093e+00+8.346256j   1.8288277e-01+7.5014434j\n",
      "  9.8886108e+00+7.4816566j  2.8044400e+00+7.892793j\n",
      "  1.0322601e+00+4.4789352j ]\n",
      " [2.8777535e+00+1.3002857j  1.9366957e-01+6.7883554j\n",
      "  2.1162813e+00+2.6554666j  4.9157314e+00+0.5336254j\n",
      "  5.7411761e+00+1.4672858j ]]\n",
      "这是一个随机生成的b:\n",
      "[4.191945 +6.852195j  3.1342418+6.9232264j 6.9187713+3.1551564j\n",
      " 9.085955 +2.9361415j 5.8930554+6.9975834j]\n"
     ]
    }
   ],
   "source": [
    "n = 5\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "\n",
    "np.random.seed(1)\n",
    "A = np.zeros([n, n], dtype=\"complex64\")\n",
    "b = np.zeros(n, dtype=\"complex64\")\n",
    "for i in range(n):\n",
    "    for j in range(n):\n",
    "        x = np.random.rand() * 10\n",
    "        y = np.random.rand() * 10\n",
    "        A[i][j] = complex(x, y)\n",
    "    x = np.random.rand() * 10\n",
    "    y = np.random.rand() * 10\n",
    "    b[i] = complex(x, y)\n",
    "np.save(\"./A.npy\", A)\n",
    "np.save(\"./b.npy\", b)\n",
    "print(\"这是一个随机生成的A:\")\n",
    "print(A)\n",
    "print(\"这是一个随机生成的b:\")\n",
    "print(b)\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "用户可以在 toml 文件中指定 VQLS 算法的参数 `depth`,`iterations`,`LR` 以及 `gamma`,分别对应参数化量子电路 $V(\\alpha)$ 的层数,优化器的迭代次数,优化器的学习率,和损失函数的阈值。在命令行输入 `python vqls.py --config config.toml` 即可完成线性方程组求解。这里我们给出一个在线演示的例子,首先定义配置文件的内容如下,用户可以自行更改 `test_toml` 中的参数:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_toml = r\"\"\"\n",
    "# 存储矩阵A的.npy文件的路径。\n",
    "A_dir = './A.npy'\n",
    "# 存储向量b的.npy文件的路径。\n",
    "b_dir = './b.npy'\n",
    "# 参数化量子电路的层数。\n",
    "depth = 4\n",
    "# 优化器迭代次数。\n",
    "iterations = 200\n",
    "# 优化器的学习率。\n",
    "LR = 0.1\n",
    "# 损失函数的阈值。默认为0。\n",
    "gamma = 0\n",
    "\"\"\""
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "运行 VQLS 算法如下:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\Users\\yuzhan01\\Miniconda3\\envs\\pq_model\\lib\\site-packages\\paddle\\tensor\\creation.py:125: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. \n",
      "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
      "  if data.dtype == np.object:\n",
      " 88%|████████▊ | 176/200 [02:04<00:16,  1.42it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Threshold value gamma reached, ending optimization\n",
      "这是求解Ax=b的x: [ 1.3475237 -0.7860472j   0.22970617-0.88826376j -0.35111237-0.31225887j\n",
      "  0.07606918+1.2138402j  -0.729564  +0.48393282j]\n",
      "实际b的值: [4.191945 +6.852195j  3.1342418+6.9232264j 6.9187713+3.1551564j\n",
      " 9.085955 +2.9361415j 5.8930554+6.9975834j]\n",
      "算法得到的Ax的值: [4.185339 +6.8523855j 3.1297188+6.923625j  6.924285 +3.1467872j\n",
      " 9.092921 +2.932943j  5.8879805+6.999589j ]\n",
      "相对误差:  0.0008446976\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "import argparse\n",
    "import os\n",
    "import warnings\n",
    "\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "os.environ[\"PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION\"] = \"python\"\n",
    "\n",
    "import toml\n",
    "import numpy as np\n",
    "import paddle\n",
    "from paddle_quantum.data_analysis.vqls import compute\n",
    "\n",
    "paddle.seed(0)\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    config = toml.loads(test_toml)\n",
    "    A_dir = config.pop(\"A_dir\")\n",
    "    A = np.load(A_dir)\n",
    "    b_dir = config.pop(\"b_dir\")\n",
    "    b = np.load(b_dir)\n",
    "    result = compute(A, b, **config)\n",
    "\n",
    "    print(\"求解 Ax=b 的x:\", result)\n",
    "    print(\"实际 b 的值:\", b)\n",
    "    print(\"算法得到的 Ax 的值:\", np.matmul(A, result))\n",
    "    relative_error = np.linalg.norm(b - np.matmul(A, result)) / np.linalg.norm(b)\n",
    "    print(\"相对误差: \", relative_error)\n",
    "    np.save(\"./answer.npy\", result)\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 引用信息\n",
    "\n",
    "```\n",
    "@misc{bravo-prieto2020variational,\n",
    "  title = {Variational {{Quantum Linear Solver}}},\n",
    "  author = {{Bravo-Prieto}, Carlos and LaRose, Ryan and Cerezo, M. and Subasi, Yigit and Cincio, Lukasz and Coles, Patrick J.},\n",
    "  year = {2020},\n",
    "  month = jun,\n",
    "  number = {arXiv:1909.05820},\n",
    "  eprint = {1909.05820},\n",
    "  eprinttype = {arxiv},\n",
    "  doi = {10.48550/arXiv.1909.05820}\n",
    "}\n",
    "```\n",
    "\n",
    "## 参考文献\n",
    "\n",
    "[1] “Variational Quantum Linear Solver: A Hybrid Algorithm for Linear Systems.” Carlos Bravo-Prieto, Ryan LaRose, Marco Cerezo, Yigit Subasi, Lukasz Cincio, Patrick J. Coles. arXiv:1909.05820, 2019."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pq-dev",
   "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.8.15 (default, Nov 10 2022, 13:17:42) \n[Clang 14.0.6 ]"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "5fea01cac43c34394d065c23bb8c1e536fdb97a765a18633fd0c4eb359001810"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}